summaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>1999-05-03 07:29:11 +0000
committerRichard Henderson <rth@redhat.com>1999-05-03 07:29:11 +0000
commit252b5132c753830d5fd56823373aed85f2a0db63 (patch)
tree1af963bfd8d3e55167b81def4207f175eaff3a56 /gas
19990502 sourceware import
Diffstat (limited to 'gas')
-rw-r--r--gas/CONTRIBUTORS111
-rw-r--r--gas/COPYING340
-rw-r--r--gas/ChangeLog3170
-rw-r--r--gas/ChangeLog-929513110
-rw-r--r--gas/ChangeLog-96975960
-rw-r--r--gas/Makefile.am1695
-rw-r--r--gas/Makefile.in2488
-rw-r--r--gas/NEWS287
-rw-r--r--gas/README274
-rw-r--r--gas/README-vms248
-rw-r--r--gas/acinclude.m456
-rw-r--r--gas/aclocal.m4822
-rw-r--r--gas/app.c1255
-rw-r--r--gas/as.c1010
-rw-r--r--gas/as.h645
-rw-r--r--gas/asintl.h44
-rw-r--r--gas/atof-generic.c636
-rw-r--r--gas/bignum-copy.c80
-rw-r--r--gas/bignum.h52
-rw-r--r--gas/bit_fix.h51
-rw-r--r--gas/cgen.c663
-rw-r--r--gas/cgen.h94
-rw-r--r--gas/cond.c461
-rw-r--r--gas/config-gas.com186
-rw-r--r--gas/config.in273
-rw-r--r--gas/config/aout_gnu.h455
-rw-r--r--gas/config/atof-ieee.c696
-rw-r--r--gas/config/atof-tahoe.c431
-rw-r--r--gas/config/atof-vax.c517
-rw-r--r--gas/config/e-i386coff.c17
-rw-r--r--gas/config/e-i386elf.c17
-rw-r--r--gas/config/e-mipsecoff.c37
-rw-r--r--gas/config/e-mipself.c37
-rw-r--r--gas/config/go32.cfg93
-rw-r--r--gas/config/itbl-mips.h47
-rw-r--r--gas/config/m68k-parse.h283
-rw-r--r--gas/config/m68k-parse.y1061
-rw-r--r--gas/config/m88k-opcode.h559
-rw-r--r--gas/config/obj-aout.c629
-rw-r--r--gas/config/obj-aout.h239
-rw-r--r--gas/config/obj-bout.c348
-rw-r--r--gas/config/obj-bout.h316
-rw-r--r--gas/config/obj-coff.c4482
-rw-r--r--gas/config/obj-coff.h841
-rw-r--r--gas/config/obj-ecoff.c309
-rw-r--r--gas/config/obj-ecoff.h67
-rw-r--r--gas/config/obj-elf.c1764
-rw-r--r--gas/config/obj-elf.h194
-rw-r--r--gas/config/obj-evax.c83
-rw-r--r--gas/config/obj-evax.h95
-rw-r--r--gas/config/obj-generic.c41
-rw-r--r--gas/config/obj-generic.h80
-rw-r--r--gas/config/obj-hp300.c52
-rw-r--r--gas/config/obj-hp300.h71
-rw-r--r--gas/config/obj-ieee.c627
-rw-r--r--gas/config/obj-ieee.h50
-rw-r--r--gas/config/obj-multi.c4
-rw-r--r--gas/config/obj-multi.h50
-rw-r--r--gas/config/obj-som.c307
-rw-r--r--gas/config/obj-som.h73
-rw-r--r--gas/config/obj-vms.c5549
-rw-r--r--gas/config/obj-vms.h552
-rw-r--r--gas/config/tc-a29k.c1296
-rw-r--r--gas/config/tc-a29k.h54
-rw-r--r--gas/config/tc-alpha.c4762
-rw-r--r--gas/config/tc-alpha.h104
-rw-r--r--gas/config/tc-arc.c1481
-rw-r--r--gas/config/tc-arc.h71
-rw-r--r--gas/config/tc-arm.c6857
-rw-r--r--gas/config/tc-arm.h204
-rw-r--r--gas/config/tc-d10v.c1636
-rw-r--r--gas/config/tc-d10v.h62
-rw-r--r--gas/config/tc-d30v.c2218
-rw-r--r--gas/config/tc-d30v.h59
-rw-r--r--gas/config/tc-fr30.c664
-rw-r--r--gas/config/tc-fr30.h81
-rw-r--r--gas/config/tc-generic.c0
-rw-r--r--gas/config/tc-generic.h39
-rw-r--r--gas/config/tc-h8300.c1595
-rw-r--r--gas/config/tc-h8300.h58
-rw-r--r--gas/config/tc-h8500.c1633
-rw-r--r--gas/config/tc-h8500.h57
-rw-r--r--gas/config/tc-hppa.c6716
-rw-r--r--gas/config/tc-hppa.h162
-rw-r--r--gas/config/tc-i386.c4475
-rw-r--r--gas/config/tc-i386.h471
-rw-r--r--gas/config/tc-i860.c1263
-rw-r--r--gas/config/tc-i860.h39
-rw-r--r--gas/config/tc-i960.c3231
-rw-r--r--gas/config/tc-i960.h171
-rw-r--r--gas/config/tc-m32r.c1300
-rw-r--r--gas/config/tc-m32r.h102
-rw-r--r--gas/config/tc-m68851.h304
-rw-r--r--gas/config/tc-m68k.c7009
-rw-r--r--gas/config/tc-m68k.h216
-rw-r--r--gas/config/tc-m88k.c1452
-rw-r--r--gas/config/tc-m88k.h108
-rw-r--r--gas/config/tc-mcore.c2183
-rw-r--r--gas/config/tc-mcore.h119
-rw-r--r--gas/config/tc-mips.c11783
-rw-r--r--gas/config/tc-mips.h153
-rw-r--r--gas/config/tc-mn10200.c1414
-rw-r--r--gas/config/tc-mn10200.h51
-rw-r--r--gas/config/tc-mn10300.c1649
-rw-r--r--gas/config/tc-mn10300.h50
-rw-r--r--gas/config/tc-ns32k.c2328
-rw-r--r--gas/config/tc-ns32k.h155
-rw-r--r--gas/config/tc-ppc.c5003
-rw-r--r--gas/config/tc-ppc.h276
-rw-r--r--gas/config/tc-sh.c2425
-rw-r--r--gas/config/tc-sh.h152
-rw-r--r--gas/config/tc-sparc.c3551
-rw-r--r--gas/config/tc-sparc.h164
-rw-r--r--gas/config/tc-tahoe.c2027
-rw-r--r--gas/config/tc-tahoe.h43
-rw-r--r--gas/config/tc-tic30.c1887
-rw-r--r--gas/config/tc-tic30.h55
-rw-r--r--gas/config/tc-tic80.c1061
-rw-r--r--gas/config/tc-tic80.h63
-rw-r--r--gas/config/tc-v850.c2478
-rw-r--r--gas/config/tc-v850.h85
-rw-r--r--gas/config/tc-vax.c3242
-rw-r--r--gas/config/tc-vax.h45
-rw-r--r--gas/config/tc-w65.c1219
-rw-r--r--gas/config/tc-w65.h61
-rw-r--r--gas/config/tc-z8k.c1589
-rw-r--r--gas/config/tc-z8k.h54
-rw-r--r--gas/config/te-386bsd.h31
-rw-r--r--gas/config/te-aux.h17
-rw-r--r--gas/config/te-delt88.h13
-rw-r--r--gas/config/te-delta.h14
-rw-r--r--gas/config/te-dpx2.h12
-rw-r--r--gas/config/te-dynix.h7
-rw-r--r--gas/config/te-epoc-pe.h8
-rw-r--r--gas/config/te-generic.h22
-rw-r--r--gas/config/te-go32.h16
-rw-r--r--gas/config/te-hp300.h25
-rw-r--r--gas/config/te-hppa.h26
-rw-r--r--gas/config/te-i386aix.h29
-rw-r--r--gas/config/te-ic960.h38
-rw-r--r--gas/config/te-linux.h4
-rw-r--r--gas/config/te-lnews.h5
-rw-r--r--gas/config/te-lynx.h7
-rw-r--r--gas/config/te-mach.h2
-rw-r--r--gas/config/te-macos.h11
-rw-r--r--gas/config/te-multi.h22
-rw-r--r--gas/config/te-nbsd.h23
-rw-r--r--gas/config/te-nbsd532.h19
-rw-r--r--gas/config/te-pc532mach.h19
-rw-r--r--gas/config/te-pe.h7
-rw-r--r--gas/config/te-ppcnw.h31
-rw-r--r--gas/config/te-psos.h22
-rw-r--r--gas/config/te-riscix.h6
-rw-r--r--gas/config/te-sparcaout.h21
-rw-r--r--gas/config/te-sun3.h48
-rw-r--r--gas/config/te-svr4.h4
-rw-r--r--gas/config/te-sysv32.h6
-rw-r--r--gas/config/vax-inst.h77
-rw-r--r--gas/config/vms-a-conf.h129
-rw-r--r--gas/config/vms-conf.h179
-rwxr-xr-xgas/configure5750
-rw-r--r--gas/configure.bat57
-rw-r--r--gas/configure.in766
-rw-r--r--gas/debug.c104
-rw-r--r--gas/dep-in.sed45
-rw-r--r--gas/depend.c208
-rw-r--r--gas/doc/Makefile.am49
-rw-r--r--gas/doc/Makefile.in438
-rw-r--r--gas/doc/all.texi72
-rw-r--r--gas/doc/as.1302
-rw-r--r--gas/doc/as.texinfo5322
-rw-r--r--gas/doc/c-a29k.texi182
-rw-r--r--gas/doc/c-arm.texi207
-rw-r--r--gas/doc/c-d10v.texi250
-rw-r--r--gas/doc/c-d30v.texi292
-rw-r--r--gas/doc/c-h8300.texi342
-rw-r--r--gas/doc/c-h8500.texi272
-rw-r--r--gas/doc/c-hppa.texi263
-rw-r--r--gas/doc/c-i386.texi518
-rw-r--r--gas/doc/c-i960.texi298
-rw-r--r--gas/doc/c-m32r.texi13
-rw-r--r--gas/doc/c-m68k.texi503
-rw-r--r--gas/doc/c-mips.texi257
-rw-r--r--gas/doc/c-ns32k.texi30
-rw-r--r--gas/doc/c-sh.texi272
-rw-r--r--gas/doc/c-sparc.texi179
-rw-r--r--gas/doc/c-v850.texi363
-rw-r--r--gas/doc/c-vax.texi357
-rw-r--r--gas/doc/c-z8k.texi380
-rw-r--r--gas/doc/gasp.texi1086
-rw-r--r--gas/doc/h8.texi26
-rw-r--r--gas/doc/internals.texi1557
-rw-r--r--gas/ecoff.c5308
-rw-r--r--gas/ecoff.h110
-rw-r--r--gas/ehopt.c469
-rw-r--r--gas/emul-target.h43
-rw-r--r--gas/emul.h23
-rw-r--r--gas/expr.c1859
-rw-r--r--gas/expr.h162
-rw-r--r--gas/flonum-copy.c73
-rw-r--r--gas/flonum-konst.c209
-rw-r--r--gas/flonum-mult.c200
-rw-r--r--gas/flonum.h110
-rw-r--r--gas/frags.c359
-rw-r--r--gas/frags.h158
-rw-r--r--gas/gasp.c3745
-rw-r--r--gas/gdbinit.in39
-rw-r--r--gas/hash.c1028
-rw-r--r--gas/hash.h45
-rw-r--r--gas/input-file.c248
-rw-r--r--gas/input-file.h68
-rw-r--r--gas/input-scrub.c521
-rw-r--r--gas/itbl-lex.l114
-rw-r--r--gas/itbl-ops.c921
-rw-r--r--gas/itbl-ops.h109
-rw-r--r--gas/itbl-parse.y459
-rw-r--r--gas/link.cmd10
-rw-r--r--gas/listing.c1420
-rw-r--r--gas/listing.h67
-rw-r--r--gas/literal.c95
-rw-r--r--gas/mac-as.r42
-rw-r--r--gas/macro.c1259
-rw-r--r--gas/macro.h53
-rw-r--r--gas/makefile.vms124
-rw-r--r--gas/messages.c541
-rw-r--r--gas/mpw-config.in115
-rw-r--r--gas/mpw-make.sed100
-rw-r--r--gas/obj.h81
-rw-r--r--gas/output-file.c156
-rw-r--r--gas/output-file.h25
-rw-r--r--gas/po/Make-in251
-rw-r--r--gas/po/POTFILES.in193
-rw-r--r--gas/po/gas.pot3853
-rw-r--r--gas/read.c5054
-rw-r--r--gas/read.h166
-rw-r--r--gas/sb.c289
-rw-r--r--gas/sb.h99
-rw-r--r--gas/stabs.c632
-rw-r--r--gas/stamp-h.in1
-rw-r--r--gas/struc-symbol.h166
-rw-r--r--gas/subsegs.c618
-rw-r--r--gas/subsegs.h159
-rw-r--r--gas/symbols.c1785
-rw-r--r--gas/symbols.h90
-rw-r--r--gas/tc.h112
-rw-r--r--gas/testsuite/ChangeLog2333
-rw-r--r--gas/testsuite/config/default.exp46
-rw-r--r--gas/testsuite/gas/all/align.d12
-rw-r--r--gas/testsuite/gas/all/align.s61
-rw-r--r--gas/testsuite/gas/all/cofftag.d25
-rw-r--r--gas/testsuite/gas/all/cofftag.s57
-rw-r--r--gas/testsuite/gas/all/comment.s3
-rw-r--r--gas/testsuite/gas/all/cond.d20
-rw-r--r--gas/testsuite/gas/all/cond.s18
-rw-r--r--gas/testsuite/gas/all/diff1.s5
-rw-r--r--gas/testsuite/gas/all/float.s4
-rw-r--r--gas/testsuite/gas/all/gas.exp145
-rw-r--r--gas/testsuite/gas/all/itbl20
-rw-r--r--gas/testsuite/gas/all/itbl-test.c129
-rw-r--r--gas/testsuite/gas/all/itbl.s13
-rw-r--r--gas/testsuite/gas/all/p1480.s3
-rw-r--r--gas/testsuite/gas/all/p2425.s6
-rw-r--r--gas/testsuite/gas/all/struct.d8
-rw-r--r--gas/testsuite/gas/all/struct.s10
-rw-r--r--gas/testsuite/gas/all/x930509.s3
-rw-r--r--gas/testsuite/gas/alpha/fp.d7
-rw-r--r--gas/testsuite/gas/alpha/fp.exp15
-rw-r--r--gas/testsuite/gas/alpha/fp.s14
-rw-r--r--gas/testsuite/gas/arc/alias.d68
-rw-r--r--gas/testsuite/gas/arc/alias.s76
-rw-r--r--gas/testsuite/gas/arc/arc.exp114
-rw-r--r--gas/testsuite/gas/arc/branch.d45
-rw-r--r--gas/testsuite/gas/arc/branch.s47
-rw-r--r--gas/testsuite/gas/arc/flag.d29
-rw-r--r--gas/testsuite/gas/arc/flag.s27
-rw-r--r--gas/testsuite/gas/arc/insn3.d44
-rw-r--r--gas/testsuite/gas/arc/insn3.s52
-rw-r--r--gas/testsuite/gas/arc/j.d75
-rw-r--r--gas/testsuite/gas/arc/j.s45
-rw-r--r--gas/testsuite/gas/arc/ld.d30
-rw-r--r--gas/testsuite/gas/arc/ld.s24
-rw-r--r--gas/testsuite/gas/arc/math.d78
-rw-r--r--gas/testsuite/gas/arc/math.s89
-rw-r--r--gas/testsuite/gas/arc/sshift.d44
-rw-r--r--gas/testsuite/gas/arc/sshift.s52
-rw-r--r--gas/testsuite/gas/arc/st.d25
-rw-r--r--gas/testsuite/gas/arc/st.s19
-rw-r--r--gas/testsuite/gas/arc/warn.exp13
-rw-r--r--gas/testsuite/gas/arc/warn.s14
-rw-r--r--gas/testsuite/gas/arm/arch4t.s21
-rw-r--r--gas/testsuite/gas/arm/arm.exp34
-rw-r--r--gas/testsuite/gas/arm/arm3.s6
-rw-r--r--gas/testsuite/gas/arm/arm6.s12
-rw-r--r--gas/testsuite/gas/arm/arm7dm.s12
-rw-r--r--gas/testsuite/gas/arm/arm7t.d68
-rw-r--r--gas/testsuite/gas/arm/arm7t.s79
-rw-r--r--gas/testsuite/gas/arm/copro.s24
-rw-r--r--gas/testsuite/gas/arm/float.s162
-rw-r--r--gas/testsuite/gas/arm/immed.s11
-rw-r--r--gas/testsuite/gas/arm/inst.d168
-rw-r--r--gas/testsuite/gas/arm/inst.s189
-rw-r--r--gas/testsuite/gas/arm/le-fpconst.d8
-rw-r--r--gas/testsuite/gas/arm/le-fpconst.s8
-rw-r--r--gas/testsuite/gas/arm/thumb.s193
-rw-r--r--gas/testsuite/gas/d30v/align.d17
-rw-r--r--gas/testsuite/gas/d30v/align.s28
-rw-r--r--gas/testsuite/gas/d30v/array.d31
-rw-r--r--gas/testsuite/gas/d30v/array.s15
-rw-r--r--gas/testsuite/gas/d30v/bittest.d20
-rw-r--r--gas/testsuite/gas/d30v/bittest.l56
-rw-r--r--gas/testsuite/gas/d30v/bittest.s28
-rw-r--r--gas/testsuite/gas/d30v/d30.exp35
-rw-r--r--gas/testsuite/gas/d30v/guard-debug.d25
-rw-r--r--gas/testsuite/gas/d30v/guard-debug.s17
-rw-r--r--gas/testsuite/gas/d30v/guard.d17
-rw-r--r--gas/testsuite/gas/d30v/guard.s24
-rw-r--r--gas/testsuite/gas/d30v/inst.d256
-rw-r--r--gas/testsuite/gas/d30v/inst.s504
-rw-r--r--gas/testsuite/gas/d30v/label-debug.d24
-rw-r--r--gas/testsuite/gas/d30v/label-debug.s11
-rw-r--r--gas/testsuite/gas/d30v/label.d16
-rw-r--r--gas/testsuite/gas/d30v/label.s11
-rw-r--r--gas/testsuite/gas/d30v/mul.d20
-rw-r--r--gas/testsuite/gas/d30v/mul.s19
-rw-r--r--gas/testsuite/gas/d30v/opt.d89
-rw-r--r--gas/testsuite/gas/d30v/opt.s216
-rw-r--r--gas/testsuite/gas/d30v/reloc.d93
-rw-r--r--gas/testsuite/gas/d30v/reloc.s68
-rw-r--r--gas/testsuite/gas/d30v/serial.l46
-rw-r--r--gas/testsuite/gas/d30v/serial.s14
-rw-r--r--gas/testsuite/gas/d30v/serial2.l138
-rw-r--r--gas/testsuite/gas/d30v/serial2.s29
-rw-r--r--gas/testsuite/gas/d30v/serial2O.l99
-rw-r--r--gas/testsuite/gas/d30v/serial2O.s29
-rw-r--r--gas/testsuite/gas/d30v/warn_oddreg.l40
-rw-r--r--gas/testsuite/gas/d30v/warn_oddreg.s12
-rw-r--r--gas/testsuite/gas/fr30/allinsn.d440
-rw-r--r--gas/testsuite/gas/fr30/allinsn.exp5
-rw-r--r--gas/testsuite/gas/fr30/allinsn.s434
-rw-r--r--gas/testsuite/gas/fr30/fr30.exp5
-rw-r--r--gas/testsuite/gas/h8300/addsub.s16
-rw-r--r--gas/testsuite/gas/h8300/addsubh.s25
-rw-r--r--gas/testsuite/gas/h8300/addsubs.s25
-rw-r--r--gas/testsuite/gas/h8300/bitops1.s18
-rw-r--r--gas/testsuite/gas/h8300/bitops1h.s19
-rw-r--r--gas/testsuite/gas/h8300/bitops1s.s29
-rw-r--r--gas/testsuite/gas/h8300/bitops2.s15
-rw-r--r--gas/testsuite/gas/h8300/bitops2h.s16
-rw-r--r--gas/testsuite/gas/h8300/bitops2s.s23
-rw-r--r--gas/testsuite/gas/h8300/bitops3.s15
-rw-r--r--gas/testsuite/gas/h8300/bitops3h.s16
-rw-r--r--gas/testsuite/gas/h8300/bitops3s.s24
-rw-r--r--gas/testsuite/gas/h8300/bitops4.s18
-rw-r--r--gas/testsuite/gas/h8300/bitops4h.s19
-rw-r--r--gas/testsuite/gas/h8300/bitops4s.s29
-rw-r--r--gas/testsuite/gas/h8300/branch.s10
-rw-r--r--gas/testsuite/gas/h8300/branchh.s12
-rw-r--r--gas/testsuite/gas/h8300/branchs.s12
-rw-r--r--gas/testsuite/gas/h8300/cbranch.s23
-rw-r--r--gas/testsuite/gas/h8300/cbranchh.s44
-rw-r--r--gas/testsuite/gas/h8300/cbranchs.s44
-rw-r--r--gas/testsuite/gas/h8300/cmpsi2.s28
-rw-r--r--gas/testsuite/gas/h8300/compare.s6
-rw-r--r--gas/testsuite/gas/h8300/compareh.s10
-rw-r--r--gas/testsuite/gas/h8300/compares.s10
-rw-r--r--gas/testsuite/gas/h8300/decimal.s5
-rw-r--r--gas/testsuite/gas/h8300/decimalh.s6
-rw-r--r--gas/testsuite/gas/h8300/decimals.s6
-rw-r--r--gas/testsuite/gas/h8300/divmul.s5
-rw-r--r--gas/testsuite/gas/h8300/divmulh.s12
-rw-r--r--gas/testsuite/gas/h8300/divmuls.s12
-rw-r--r--gas/testsuite/gas/h8300/extendh.s8
-rw-r--r--gas/testsuite/gas/h8300/extends.s8
-rw-r--r--gas/testsuite/gas/h8300/ffxx1.d23
-rw-r--r--gas/testsuite/gas/h8300/ffxx1.s20
-rw-r--r--gas/testsuite/gas/h8300/h8300.exp2183
-rw-r--r--gas/testsuite/gas/h8300/incdec.s5
-rw-r--r--gas/testsuite/gas/h8300/incdech.s14
-rw-r--r--gas/testsuite/gas/h8300/incdecs.s14
-rw-r--r--gas/testsuite/gas/h8300/logical.s14
-rw-r--r--gas/testsuite/gas/h8300/logicalh.s31
-rw-r--r--gas/testsuite/gas/h8300/logicals.s34
-rw-r--r--gas/testsuite/gas/h8300/macs.s11
-rw-r--r--gas/testsuite/gas/h8300/misc.s13
-rw-r--r--gas/testsuite/gas/h8300/misch.s27
-rw-r--r--gas/testsuite/gas/h8300/miscs.s41
-rw-r--r--gas/testsuite/gas/h8300/mov32bug.s4
-rw-r--r--gas/testsuite/gas/h8300/movb.s15
-rw-r--r--gas/testsuite/gas/h8300/movbh.s20
-rw-r--r--gas/testsuite/gas/h8300/movbs.s20
-rw-r--r--gas/testsuite/gas/h8300/movlh.s18
-rw-r--r--gas/testsuite/gas/h8300/movls.s18
-rw-r--r--gas/testsuite/gas/h8300/movw.s13
-rw-r--r--gas/testsuite/gas/h8300/movwh.s18
-rw-r--r--gas/testsuite/gas/h8300/movws.s18
-rw-r--r--gas/testsuite/gas/h8300/multiples.s10
-rw-r--r--gas/testsuite/gas/h8300/pushpop.s5
-rw-r--r--gas/testsuite/gas/h8300/pushpoph.s8
-rw-r--r--gas/testsuite/gas/h8300/pushpops.s8
-rw-r--r--gas/testsuite/gas/h8300/rotsh.s11
-rw-r--r--gas/testsuite/gas/h8300/rotshh.s27
-rw-r--r--gas/testsuite/gas/h8300/rotshs.s51
-rw-r--r--gas/testsuite/gas/hppa/README34
-rw-r--r--gas/testsuite/gas/hppa/basic/add.s100
-rw-r--r--gas/testsuite/gas/hppa/basic/addi.s83
-rw-r--r--gas/testsuite/gas/hppa/basic/basic.exp2262
-rw-r--r--gas/testsuite/gas/hppa/basic/branch.s227
-rw-r--r--gas/testsuite/gas/hppa/basic/comclr.s50
-rw-r--r--gas/testsuite/gas/hppa/basic/copr.s19
-rw-r--r--gas/testsuite/gas/hppa/basic/coprmem.s55
-rw-r--r--gas/testsuite/gas/hppa/basic/dcor.s41
-rw-r--r--gas/testsuite/gas/hppa/basic/deposit.s88
-rw-r--r--gas/testsuite/gas/hppa/basic/ds.s32
-rw-r--r--gas/testsuite/gas/hppa/basic/extract.s51
-rw-r--r--gas/testsuite/gas/hppa/basic/fmem.s52
-rw-r--r--gas/testsuite/gas/hppa/basic/fmemLRbug.s76
-rw-r--r--gas/testsuite/gas/hppa/basic/fp_comp.s81
-rw-r--r--gas/testsuite/gas/hppa/basic/fp_conv.s92
-rw-r--r--gas/testsuite/gas/hppa/basic/fp_fcmp.s114
-rw-r--r--gas/testsuite/gas/hppa/basic/fp_misc.s18
-rw-r--r--gas/testsuite/gas/hppa/basic/imem.s93
-rw-r--r--gas/testsuite/gas/hppa/basic/immed.s21
-rw-r--r--gas/testsuite/gas/hppa/basic/logical.s60
-rw-r--r--gas/testsuite/gas/hppa/basic/purge.s35
-rw-r--r--gas/testsuite/gas/hppa/basic/sh1add.s67
-rw-r--r--gas/testsuite/gas/hppa/basic/sh2add.s67
-rw-r--r--gas/testsuite/gas/hppa/basic/sh3add.s67
-rw-r--r--gas/testsuite/gas/hppa/basic/shift.s34
-rw-r--r--gas/testsuite/gas/hppa/basic/special.s15
-rw-r--r--gas/testsuite/gas/hppa/basic/spop.s34
-rw-r--r--gas/testsuite/gas/hppa/basic/sub.s117
-rw-r--r--gas/testsuite/gas/hppa/basic/subi.s49
-rw-r--r--gas/testsuite/gas/hppa/basic/system.s46
-rw-r--r--gas/testsuite/gas/hppa/basic/unit.s55
-rw-r--r--gas/testsuite/gas/hppa/basic/weird.s870
-rw-r--r--gas/testsuite/gas/hppa/parse/align1.s41
-rw-r--r--gas/testsuite/gas/hppa/parse/align2.s15
-rw-r--r--gas/testsuite/gas/hppa/parse/appbug.s1
-rw-r--r--gas/testsuite/gas/hppa/parse/badfmpyadd.s33
-rw-r--r--gas/testsuite/gas/hppa/parse/block1.s18
-rw-r--r--gas/testsuite/gas/hppa/parse/block2.s15
-rw-r--r--gas/testsuite/gas/hppa/parse/calldatabug.s189
-rw-r--r--gas/testsuite/gas/hppa/parse/callinfobug.s8
-rw-r--r--gas/testsuite/gas/hppa/parse/defbug.s18
-rw-r--r--gas/testsuite/gas/hppa/parse/entrybug.s24
-rw-r--r--gas/testsuite/gas/hppa/parse/exportbug.s14
-rw-r--r--gas/testsuite/gas/hppa/parse/exprbug.s39
-rw-r--r--gas/testsuite/gas/hppa/parse/fixup7bug.s6192
-rw-r--r--gas/testsuite/gas/hppa/parse/global.s15
-rw-r--r--gas/testsuite/gas/hppa/parse/labelbug.s35
-rw-r--r--gas/testsuite/gas/hppa/parse/linesepbug.s20
-rw-r--r--gas/testsuite/gas/hppa/parse/lselbug.s18
-rw-r--r--gas/testsuite/gas/hppa/parse/nosubspace.s21
-rw-r--r--gas/testsuite/gas/hppa/parse/parse.exp222
-rw-r--r--gas/testsuite/gas/hppa/parse/procbug.s16
-rw-r--r--gas/testsuite/gas/hppa/parse/regpopbug.s17
-rw-r--r--gas/testsuite/gas/hppa/parse/spacebug.s3
-rw-r--r--gas/testsuite/gas/hppa/parse/ssbug.s10
-rw-r--r--gas/testsuite/gas/hppa/parse/stdreg.s27
-rw-r--r--gas/testsuite/gas/hppa/parse/stringer.s19
-rw-r--r--gas/testsuite/gas/hppa/parse/undefbug.s14
-rw-r--r--gas/testsuite/gas/hppa/parse/versionbug.s9
-rw-r--r--gas/testsuite/gas/hppa/parse/xmpyubug.s17
-rw-r--r--gas/testsuite/gas/hppa/reloc/applybug.s130
-rw-r--r--gas/testsuite/gas/hppa/reloc/blebug.s16
-rw-r--r--gas/testsuite/gas/hppa/reloc/blebug2.s14
-rw-r--r--gas/testsuite/gas/hppa/reloc/blebug3.s14
-rw-r--r--gas/testsuite/gas/hppa/reloc/exitbug.s19
-rw-r--r--gas/testsuite/gas/hppa/reloc/fixupbug.s19
-rw-r--r--gas/testsuite/gas/hppa/reloc/funcrelocbug.s186
-rw-r--r--gas/testsuite/gas/hppa/reloc/labelopbug.s37
-rw-r--r--gas/testsuite/gas/hppa/reloc/longcall.s40
-rw-r--r--gas/testsuite/gas/hppa/reloc/picreloc.s13
-rw-r--r--gas/testsuite/gas/hppa/reloc/plabelbug.s47
-rw-r--r--gas/testsuite/gas/hppa/reloc/r_no_reloc.s45
-rw-r--r--gas/testsuite/gas/hppa/reloc/reduce.s48
-rw-r--r--gas/testsuite/gas/hppa/reloc/reduce2.s80
-rw-r--r--gas/testsuite/gas/hppa/reloc/reduce3.s51
-rw-r--r--gas/testsuite/gas/hppa/reloc/reloc.exp679
-rw-r--r--gas/testsuite/gas/hppa/reloc/roundmode.s23
-rw-r--r--gas/testsuite/gas/hppa/reloc/selectorbug.s28
-rw-r--r--gas/testsuite/gas/hppa/unsorted/align3.s20
-rw-r--r--gas/testsuite/gas/hppa/unsorted/align4.s4
-rw-r--r--gas/testsuite/gas/hppa/unsorted/brlenbug.s3502
-rw-r--r--gas/testsuite/gas/hppa/unsorted/common.s8
-rw-r--r--gas/testsuite/gas/hppa/unsorted/fragbug.s3
-rw-r--r--gas/testsuite/gas/hppa/unsorted/globalbug.s16
-rw-r--r--gas/testsuite/gas/hppa/unsorted/importbug.s42
-rw-r--r--gas/testsuite/gas/hppa/unsorted/labeldiffs.s40
-rw-r--r--gas/testsuite/gas/hppa/unsorted/locallabel.s15
-rw-r--r--gas/testsuite/gas/hppa/unsorted/ss_align.s12
-rw-r--r--gas/testsuite/gas/hppa/unsorted/unsorted.exp258
-rw-r--r--gas/testsuite/gas/i386/amd.d37
-rw-r--r--gas/testsuite/gas/i386/amd.s33
-rw-r--r--gas/testsuite/gas/i386/float.l81
-rw-r--r--gas/testsuite/gas/i386/float.s68
-rw-r--r--gas/testsuite/gas/i386/general.l205
-rw-r--r--gas/testsuite/gas/i386/general.s152
-rw-r--r--gas/testsuite/gas/i386/i386.exp34
-rw-r--r--gas/testsuite/gas/i386/inval.l98
-rw-r--r--gas/testsuite/gas/i386/inval.s48
-rw-r--r--gas/testsuite/gas/i386/modrm.l1984
-rw-r--r--gas/testsuite/gas/i386/modrm.s1671
-rw-r--r--gas/testsuite/gas/i386/opcode.d574
-rw-r--r--gas/testsuite/gas/i386/opcode.s567
-rw-r--r--gas/testsuite/gas/i386/prefix.d15
-rw-r--r--gas/testsuite/gas/i386/prefix.s11
-rw-r--r--gas/testsuite/gas/i386/reloc.d15
-rw-r--r--gas/testsuite/gas/i386/reloc.s8
-rw-r--r--gas/testsuite/gas/i386/white.l21
-rw-r--r--gas/testsuite/gas/i386/white.s18
-rw-r--r--gas/testsuite/gas/ieee-fp/x930509a.exp25
-rw-r--r--gas/testsuite/gas/ieee-fp/x930509a.s5
-rw-r--r--gas/testsuite/gas/m32r/allinsn.d374
-rw-r--r--gas/testsuite/gas/m32r/allinsn.exp5
-rw-r--r--gas/testsuite/gas/m32r/allinsn.s501
-rw-r--r--gas/testsuite/gas/m32r/fslot.d31
-rw-r--r--gas/testsuite/gas/m32r/fslot.s27
-rw-r--r--gas/testsuite/gas/m32r/high-1.d19
-rw-r--r--gas/testsuite/gas/m32r/high-1.s14
-rw-r--r--gas/testsuite/gas/m32r/m32r.exp8
-rw-r--r--gas/testsuite/gas/m32r/outofrange.s145
-rw-r--r--gas/testsuite/gas/m32r/relax-1.d18
-rw-r--r--gas/testsuite/gas/m32r/relax-1.s17
-rw-r--r--gas/testsuite/gas/m32r/uppercase.d26
-rw-r--r--gas/testsuite/gas/m32r/uppercase.s14
-rw-r--r--gas/testsuite/gas/m68k-coff/gas.exp15
-rw-r--r--gas/testsuite/gas/m68k-coff/p2389.s19
-rw-r--r--gas/testsuite/gas/m68k-coff/p2389a.s3
-rw-r--r--gas/testsuite/gas/m68k-coff/p2430.s6
-rw-r--r--gas/testsuite/gas/m68k-coff/p2430a.s4
-rw-r--r--gas/testsuite/gas/m68k-coff/t1.s36
-rw-r--r--gas/testsuite/gas/m68k/all.exp39
-rw-r--r--gas/testsuite/gas/m68k/bitfield.d28
-rw-r--r--gas/testsuite/gas/m68k/bitfield.s24
-rw-r--r--gas/testsuite/gas/m68k/cas.d20
-rw-r--r--gas/testsuite/gas/m68k/cas.s16
-rw-r--r--gas/testsuite/gas/m68k/disperr.s16
-rw-r--r--gas/testsuite/gas/m68k/fmoveml.d60
-rw-r--r--gas/testsuite/gas/m68k/fmoveml.s58
-rw-r--r--gas/testsuite/gas/m68k/link.d17
-rw-r--r--gas/testsuite/gas/m68k/link.s13
-rw-r--r--gas/testsuite/gas/m68k/op68000.d195
-rw-r--r--gas/testsuite/gas/m68k/operands.d242
-rw-r--r--gas/testsuite/gas/m68k/operands.s272
-rw-r--r--gas/testsuite/gas/m68k/p2410.s15
-rw-r--r--gas/testsuite/gas/m68k/p2663.s16
-rw-r--r--gas/testsuite/gas/m68k/pcrel.d88
-rw-r--r--gas/testsuite/gas/m68k/pcrel.s59
-rw-r--r--gas/testsuite/gas/m68k/pic1.s5
-rw-r--r--gas/testsuite/gas/m68k/t2.d8
-rw-r--r--gas/testsuite/gas/m68k/t2.s6
-rw-r--r--gas/testsuite/gas/m88k/init.d11
-rw-r--r--gas/testsuite/gas/m88k/init.s5
-rw-r--r--gas/testsuite/gas/m88k/m88k.exp10
-rw-r--r--gas/testsuite/gas/macros/err.s5
-rw-r--r--gas/testsuite/gas/macros/irp.d13
-rw-r--r--gas/testsuite/gas/macros/irp.s8
-rw-r--r--gas/testsuite/gas/macros/macros.exp22
-rw-r--r--gas/testsuite/gas/macros/rept.d10
-rw-r--r--gas/testsuite/gas/macros/rept.s3
-rw-r--r--gas/testsuite/gas/macros/semi.d8
-rw-r--r--gas/testsuite/gas/macros/semi.s14
-rw-r--r--gas/testsuite/gas/macros/test1.d5
-rw-r--r--gas/testsuite/gas/macros/test1.s7
-rw-r--r--gas/testsuite/gas/macros/test2.d10
-rw-r--r--gas/testsuite/gas/macros/test2.s9
-rw-r--r--gas/testsuite/gas/macros/test3.d8
-rw-r--r--gas/testsuite/gas/macros/test3.s7
-rw-r--r--gas/testsuite/gas/mcore/allinsn.d400
-rw-r--r--gas/testsuite/gas/mcore/allinsn.exp5
-rw-r--r--gas/testsuite/gas/mcore/allinsn.s146
-rw-r--r--gas/testsuite/gas/mips/abs.d15
-rw-r--r--gas/testsuite/gas/mips/abs.s5
-rw-r--r--gas/testsuite/gas/mips/add.d20
-rw-r--r--gas/testsuite/gas/mips/add.s16
-rw-r--r--gas/testsuite/gas/mips/and.d34
-rw-r--r--gas/testsuite/gas/mips/and.s28
-rw-r--r--gas/testsuite/gas/mips/beq.d40
-rw-r--r--gas/testsuite/gas/mips/beq.s28
-rw-r--r--gas/testsuite/gas/mips/bge.d53
-rw-r--r--gas/testsuite/gas/mips/bge.s31
-rw-r--r--gas/testsuite/gas/mips/bgeu.d47
-rw-r--r--gas/testsuite/gas/mips/bgeu.s27
-rw-r--r--gas/testsuite/gas/mips/blt.d53
-rw-r--r--gas/testsuite/gas/mips/blt.s31
-rw-r--r--gas/testsuite/gas/mips/bltu.d47
-rw-r--r--gas/testsuite/gas/mips/bltu.s27
-rw-r--r--gas/testsuite/gas/mips/break20.d18
-rw-r--r--gas/testsuite/gas/mips/break20.s17
-rw-r--r--gas/testsuite/gas/mips/delay.d20
-rw-r--r--gas/testsuite/gas/mips/delay.s8
-rw-r--r--gas/testsuite/gas/mips/div-ilocks.d110
-rw-r--r--gas/testsuite/gas/mips/div.d125
-rw-r--r--gas/testsuite/gas/mips/div.s41
-rw-r--r--gas/testsuite/gas/mips/dli.d115
-rw-r--r--gas/testsuite/gas/mips/dli.s67
-rw-r--r--gas/testsuite/gas/mips/elf_e_flags.c24
-rw-r--r--gas/testsuite/gas/mips/elf_e_flags.s43
-rw-r--r--gas/testsuite/gas/mips/elf_e_flags1.d26
-rw-r--r--gas/testsuite/gas/mips/elf_e_flags2.d26
-rw-r--r--gas/testsuite/gas/mips/elf_e_flags3.d26
-rw-r--r--gas/testsuite/gas/mips/elf_e_flags4.d26
-rw-r--r--gas/testsuite/gas/mips/itbl19
-rw-r--r--gas/testsuite/gas/mips/itbl.s18
-rw-r--r--gas/testsuite/gas/mips/jal-empic.d26
-rw-r--r--gas/testsuite/gas/mips/jal-svr4pic.d39
-rw-r--r--gas/testsuite/gas/mips/jal-svr4pic.s20
-rw-r--r--gas/testsuite/gas/mips/jal-xgot.d42
-rw-r--r--gas/testsuite/gas/mips/jal.d24
-rw-r--r--gas/testsuite/gas/mips/jal.s11
-rw-r--r--gas/testsuite/gas/mips/la-empic.d105
-rw-r--r--gas/testsuite/gas/mips/la-empic.s57
-rw-r--r--gas/testsuite/gas/mips/la-svr4pic.d474
-rw-r--r--gas/testsuite/gas/mips/la-xgot.d618
-rw-r--r--gas/testsuite/gas/mips/la.d384
-rw-r--r--gas/testsuite/gas/mips/la.s114
-rw-r--r--gas/testsuite/gas/mips/lb-empic.d102
-rw-r--r--gas/testsuite/gas/mips/lb-pic.s55
-rw-r--r--gas/testsuite/gas/mips/lb-svr4pic.d182
-rw-r--r--gas/testsuite/gas/mips/lb-xgot-ilocks.d214
-rw-r--r--gas/testsuite/gas/mips/lb-xgot.d242
-rw-r--r--gas/testsuite/gas/mips/lb.d395
-rw-r--r--gas/testsuite/gas/mips/lb.s125
-rw-r--r--gas/testsuite/gas/mips/ld-empic.d186
-rw-r--r--gas/testsuite/gas/mips/ld-ilocks-addr32.d632
-rw-r--r--gas/testsuite/gas/mips/ld-ilocks.d631
-rw-r--r--gas/testsuite/gas/mips/ld-pic.s60
-rw-r--r--gas/testsuite/gas/mips/ld-svr4pic.d225
-rw-r--r--gas/testsuite/gas/mips/ld-xgot.d273
-rw-r--r--gas/testsuite/gas/mips/ld.d639
-rw-r--r--gas/testsuite/gas/mips/ld.s144
-rw-r--r--gas/testsuite/gas/mips/li.d16
-rw-r--r--gas/testsuite/gas/mips/li.s12
-rw-r--r--gas/testsuite/gas/mips/lif-empic.d24
-rw-r--r--gas/testsuite/gas/mips/lif-svr4pic.d30
-rw-r--r--gas/testsuite/gas/mips/lif-xgot.d30
-rw-r--r--gas/testsuite/gas/mips/lifloat.d23
-rw-r--r--gas/testsuite/gas/mips/lifloat.s24
-rw-r--r--gas/testsuite/gas/mips/lineno.d97
-rw-r--r--gas/testsuite/gas/mips/lineno.s60
-rw-r--r--gas/testsuite/gas/mips/mips.exp102
-rw-r--r--gas/testsuite/gas/mips/mips16.d683
-rw-r--r--gas/testsuite/gas/mips/mips16.s258
-rw-r--r--gas/testsuite/gas/mips/mips4.d51
-rw-r--r--gas/testsuite/gas/mips/mips4.s52
-rw-r--r--gas/testsuite/gas/mips/mips4010.d23
-rw-r--r--gas/testsuite/gas/mips/mips4010.s20
-rw-r--r--gas/testsuite/gas/mips/mips4100.d15
-rw-r--r--gas/testsuite/gas/mips/mips4100.s10
-rw-r--r--gas/testsuite/gas/mips/mips4650.d14
-rw-r--r--gas/testsuite/gas/mips/mips4650.s8
-rw-r--r--gas/testsuite/gas/mips/mul-ilocks.d81
-rw-r--r--gas/testsuite/gas/mips/mul.d92
-rw-r--r--gas/testsuite/gas/mips/mul.s27
-rw-r--r--gas/testsuite/gas/mips/nodelay.d19
-rw-r--r--gas/testsuite/gas/mips/rol.d37
-rw-r--r--gas/testsuite/gas/mips/rol.s12
-rw-r--r--gas/testsuite/gas/mips/sb.d396
-rw-r--r--gas/testsuite/gas/mips/sb.s124
-rw-r--r--gas/testsuite/gas/mips/sync.d10
-rw-r--r--gas/testsuite/gas/mips/sync.s5
-rw-r--r--gas/testsuite/gas/mips/trap20.d20
-rw-r--r--gas/testsuite/gas/mips/trap20.s18
-rw-r--r--gas/testsuite/gas/mips/trunc.d29
-rw-r--r--gas/testsuite/gas/mips/trunc.s6
-rw-r--r--gas/testsuite/gas/mips/uld.d270
-rw-r--r--gas/testsuite/gas/mips/uld.s66
-rw-r--r--gas/testsuite/gas/mips/ulh-empic.d91
-rw-r--r--gas/testsuite/gas/mips/ulh-pic.s36
-rw-r--r--gas/testsuite/gas/mips/ulh-svr4pic.d124
-rw-r--r--gas/testsuite/gas/mips/ulh-xgot.d154
-rw-r--r--gas/testsuite/gas/mips/ulh.d374
-rw-r--r--gas/testsuite/gas/mips/ulh.s69
-rw-r--r--gas/testsuite/gas/mips/ulw.d270
-rw-r--r--gas/testsuite/gas/mips/ulw.s66
-rw-r--r--gas/testsuite/gas/mips/usd.d270
-rw-r--r--gas/testsuite/gas/mips/usd.s66
-rw-r--r--gas/testsuite/gas/mips/ush.d455
-rw-r--r--gas/testsuite/gas/mips/ush.s65
-rw-r--r--gas/testsuite/gas/mips/usw.d270
-rw-r--r--gas/testsuite/gas/mips/usw.s66
-rw-r--r--gas/testsuite/gas/mn10200/add.s13
-rw-r--r--gas/testsuite/gas/mn10200/basic.exp836
-rw-r--r--gas/testsuite/gas/mn10200/bcc.s17
-rw-r--r--gas/testsuite/gas/mn10200/bccx.s16
-rw-r--r--gas/testsuite/gas/mn10200/bit.s5
-rw-r--r--gas/testsuite/gas/mn10200/cmp.s10
-rw-r--r--gas/testsuite/gas/mn10200/ext.s7
-rw-r--r--gas/testsuite/gas/mn10200/logical.s12
-rw-r--r--gas/testsuite/gas/mn10200/mov1.s13
-rw-r--r--gas/testsuite/gas/mn10200/mov2.s10
-rw-r--r--gas/testsuite/gas/mn10200/mov3.s11
-rw-r--r--gas/testsuite/gas/mn10200/mov4.s9
-rw-r--r--gas/testsuite/gas/mn10200/movb.s13
-rw-r--r--gas/testsuite/gas/mn10200/movbu.s8
-rw-r--r--gas/testsuite/gas/mn10200/movx.s7
-rw-r--r--gas/testsuite/gas/mn10200/muldiv.s4
-rw-r--r--gas/testsuite/gas/mn10200/other.s10
-rw-r--r--gas/testsuite/gas/mn10200/shift.s5
-rw-r--r--gas/testsuite/gas/mn10200/sub.s10
-rw-r--r--gas/testsuite/gas/mn10300/add.s15
-rw-r--r--gas/testsuite/gas/mn10300/basic.exp986
-rw-r--r--gas/testsuite/gas/mn10300/bcc.s17
-rw-r--r--gas/testsuite/gas/mn10300/bit.s12
-rw-r--r--gas/testsuite/gas/mn10300/cmp.s11
-rw-r--r--gas/testsuite/gas/mn10300/ext.s7
-rw-r--r--gas/testsuite/gas/mn10300/extend.s15
-rw-r--r--gas/testsuite/gas/mn10300/logical.s15
-rw-r--r--gas/testsuite/gas/mn10300/loop.s15
-rw-r--r--gas/testsuite/gas/mn10300/mov1.s17
-rw-r--r--gas/testsuite/gas/mn10300/mov2.s16
-rw-r--r--gas/testsuite/gas/mn10300/mov3.s16
-rw-r--r--gas/testsuite/gas/mn10300/mov4.s13
-rw-r--r--gas/testsuite/gas/mn10300/movbu.s21
-rw-r--r--gas/testsuite/gas/mn10300/movhu.s21
-rw-r--r--gas/testsuite/gas/mn10300/movm.s5
-rw-r--r--gas/testsuite/gas/mn10300/muldiv.s5
-rw-r--r--gas/testsuite/gas/mn10300/other.s20
-rw-r--r--gas/testsuite/gas/mn10300/shift.s10
-rw-r--r--gas/testsuite/gas/mn10300/sub.s8
-rw-r--r--gas/testsuite/gas/mn10300/udf.s129
-rw-r--r--gas/testsuite/gas/mri/char.d9
-rw-r--r--gas/testsuite/gas/mri/char.s6
-rw-r--r--gas/testsuite/gas/mri/comment.d9
-rw-r--r--gas/testsuite/gas/mri/comment.s13
-rw-r--r--gas/testsuite/gas/mri/common.d8
-rw-r--r--gas/testsuite/gas/mri/common.s11
-rw-r--r--gas/testsuite/gas/mri/constants.d20
-rw-r--r--gas/testsuite/gas/mri/constants.s31
-rw-r--r--gas/testsuite/gas/mri/empty.s9
-rw-r--r--gas/testsuite/gas/mri/equ.d7
-rw-r--r--gas/testsuite/gas/mri/equ.s3
-rw-r--r--gas/testsuite/gas/mri/expr.d11
-rw-r--r--gas/testsuite/gas/mri/expr.s7
-rw-r--r--gas/testsuite/gas/mri/float.d10
-rw-r--r--gas/testsuite/gas/mri/float.s7
-rw-r--r--gas/testsuite/gas/mri/for.d30
-rw-r--r--gas/testsuite/gas/mri/for.s22
-rw-r--r--gas/testsuite/gas/mri/if.d25
-rw-r--r--gas/testsuite/gas/mri/if.s17
-rw-r--r--gas/testsuite/gas/mri/immconst.d22
-rw-r--r--gas/testsuite/gas/mri/label.d8
-rw-r--r--gas/testsuite/gas/mri/label.s5
-rw-r--r--gas/testsuite/gas/mri/moveml.d27
-rw-r--r--gas/testsuite/gas/mri/moveml.s17
-rw-r--r--gas/testsuite/gas/mri/mri.exp28
-rw-r--r--gas/testsuite/gas/mri/repeat.d16
-rw-r--r--gas/testsuite/gas/mri/repeat.s14
-rw-r--r--gas/testsuite/gas/mri/semi.d9
-rw-r--r--gas/testsuite/gas/mri/semi.s14
-rw-r--r--gas/testsuite/gas/mri/while.d18
-rw-r--r--gas/testsuite/gas/mri/while.s14
-rw-r--r--gas/testsuite/gas/ppc/astest.d74
-rw-r--r--gas/testsuite/gas/ppc/astest.s52
-rw-r--r--gas/testsuite/gas/ppc/astest2.d75
-rw-r--r--gas/testsuite/gas/ppc/astest2.s52
-rw-r--r--gas/testsuite/gas/ppc/ppc.exp21
-rw-r--r--gas/testsuite/gas/ppc/simpshft.d27
-rw-r--r--gas/testsuite/gas/ppc/simpshft.s110
-rw-r--r--gas/testsuite/gas/sh/basic.exp86
-rw-r--r--gas/testsuite/gas/sh/fp.s44
-rw-r--r--gas/testsuite/gas/sparc-solaris/addend.exp36
-rw-r--r--gas/testsuite/gas/sparc-solaris/addend.s11
-rw-r--r--gas/testsuite/gas/sparc-solaris/gas.exp10
-rw-r--r--gas/testsuite/gas/sparc-solaris/sol-cc.s81
-rw-r--r--gas/testsuite/gas/sparc-solaris/sol-gcc.s66
-rw-r--r--gas/testsuite/gas/sparc/asi.d35
-rw-r--r--gas/testsuite/gas/sparc/asi.s28
-rw-r--r--gas/testsuite/gas/sparc/membar.d19
-rw-r--r--gas/testsuite/gas/sparc/membar.s12
-rw-r--r--gas/testsuite/gas/sparc/mism-1.s22
-rw-r--r--gas/testsuite/gas/sparc/mismatch.exp20
-rw-r--r--gas/testsuite/gas/sparc/prefetch.d19
-rw-r--r--gas/testsuite/gas/sparc/prefetch.s11
-rw-r--r--gas/testsuite/gas/sparc/rdpr.d26
-rw-r--r--gas/testsuite/gas/sparc/rdpr.s19
-rw-r--r--gas/testsuite/gas/sparc/reloc64.d76
-rw-r--r--gas/testsuite/gas/sparc/reloc64.s48
-rw-r--r--gas/testsuite/gas/sparc/set64.d88
-rw-r--r--gas/testsuite/gas/sparc/set64.s43
-rw-r--r--gas/testsuite/gas/sparc/sparc.exp27
-rw-r--r--gas/testsuite/gas/sparc/splet-2.d23
-rw-r--r--gas/testsuite/gas/sparc/splet-2.s21
-rw-r--r--gas/testsuite/gas/sparc/splet.d195
-rw-r--r--gas/testsuite/gas/sparc/splet.s211
-rw-r--r--gas/testsuite/gas/sparc/synth.d11
-rw-r--r--gas/testsuite/gas/sparc/synth.s7
-rw-r--r--gas/testsuite/gas/sparc/synth64.d19
-rw-r--r--gas/testsuite/gas/sparc/synth64.s16
-rw-r--r--gas/testsuite/gas/sparc/wrpr.d24
-rw-r--r--gas/testsuite/gas/sparc/wrpr.s17
-rw-r--r--gas/testsuite/gas/sun4/addend.d13
-rw-r--r--gas/testsuite/gas/sun4/addend.exp7
-rw-r--r--gas/testsuite/gas/sun4/addend.s11
-rw-r--r--gas/testsuite/gas/template96
-rw-r--r--gas/testsuite/gas/tic80/add.d22
-rw-r--r--gas/testsuite/gas/tic80/add.lst34
-rw-r--r--gas/testsuite/gas/tic80/add.s19
-rw-r--r--gas/testsuite/gas/tic80/align.d19
-rw-r--r--gas/testsuite/gas/tic80/align.lst47
-rw-r--r--gas/testsuite/gas/tic80/align.s37
-rw-r--r--gas/testsuite/gas/tic80/bitnum.d82
-rw-r--r--gas/testsuite/gas/tic80/bitnum.lst97
-rw-r--r--gas/testsuite/gas/tic80/bitnum.s85
-rw-r--r--gas/testsuite/gas/tic80/ccode.d32
-rw-r--r--gas/testsuite/gas/tic80/ccode.lst37
-rw-r--r--gas/testsuite/gas/tic80/ccode.s30
-rw-r--r--gas/testsuite/gas/tic80/cregops.d68
-rw-r--r--gas/testsuite/gas/tic80/cregops.lst76
-rw-r--r--gas/testsuite/gas/tic80/cregops.s64
-rw-r--r--gas/testsuite/gas/tic80/endmask.d41
-rw-r--r--gas/testsuite/gas/tic80/endmask.lst45
-rw-r--r--gas/testsuite/gas/tic80/endmask.s38
-rw-r--r--gas/testsuite/gas/tic80/float.d40
-rw-r--r--gas/testsuite/gas/tic80/float.lst76
-rw-r--r--gas/testsuite/gas/tic80/float.s32
-rw-r--r--gas/testsuite/gas/tic80/regops.d188
-rw-r--r--gas/testsuite/gas/tic80/regops.lst264
-rw-r--r--gas/testsuite/gas/tic80/regops.s237
-rw-r--r--gas/testsuite/gas/tic80/regops2.d68
-rw-r--r--gas/testsuite/gas/tic80/regops2.lst96
-rw-r--r--gas/testsuite/gas/tic80/regops2.s60
-rw-r--r--gas/testsuite/gas/tic80/regops3.d28
-rw-r--r--gas/testsuite/gas/tic80/regops3.lst27
-rw-r--r--gas/testsuite/gas/tic80/regops3.s20
-rw-r--r--gas/testsuite/gas/tic80/regops4.d28
-rw-r--r--gas/testsuite/gas/tic80/regops4.lst27
-rw-r--r--gas/testsuite/gas/tic80/regops4.s20
-rw-r--r--gas/testsuite/gas/tic80/relocs1.c28
-rw-r--r--gas/testsuite/gas/tic80/relocs1.d56
-rw-r--r--gas/testsuite/gas/tic80/relocs1.lst80
-rw-r--r--gas/testsuite/gas/tic80/relocs1.s66
-rw-r--r--gas/testsuite/gas/tic80/relocs1b.d12
-rw-r--r--gas/testsuite/gas/tic80/relocs2.c41
-rw-r--r--gas/testsuite/gas/tic80/relocs2.d37
-rw-r--r--gas/testsuite/gas/tic80/relocs2.lst112
-rw-r--r--gas/testsuite/gas/tic80/relocs2.s72
-rw-r--r--gas/testsuite/gas/tic80/relocs2b.d38
-rw-r--r--gas/testsuite/gas/tic80/tic80.exp21
-rw-r--r--gas/testsuite/gas/v850/arith.s24
-rw-r--r--gas/testsuite/gas/v850/basic.exp438
-rw-r--r--gas/testsuite/gas/v850/bit.s8
-rw-r--r--gas/testsuite/gas/v850/branch.s24
-rw-r--r--gas/testsuite/gas/v850/compare.s28
-rw-r--r--gas/testsuite/gas/v850/fepsw.s2
-rw-r--r--gas/testsuite/gas/v850/hilo.s5
-rw-r--r--gas/testsuite/gas/v850/hilo2.s4
-rw-r--r--gas/testsuite/gas/v850/jumps.s8
-rw-r--r--gas/testsuite/gas/v850/logical.s11
-rw-r--r--gas/testsuite/gas/v850/mem.s16
-rw-r--r--gas/testsuite/gas/v850/misc.s13
-rw-r--r--gas/testsuite/gas/v850/move.s8
-rw-r--r--gas/testsuite/gas/v850/range.s2
-rw-r--r--gas/testsuite/gas/v850/reloc.s7
-rw-r--r--gas/testsuite/gas/vax/quad.exp23
-rw-r--r--gas/testsuite/gas/vax/quad.s2
-rw-r--r--gas/testsuite/gas/vtable/entry0.d10
-rw-r--r--gas/testsuite/gas/vtable/entry0.s2
-rw-r--r--gas/testsuite/gas/vtable/entry1.d10
-rw-r--r--gas/testsuite/gas/vtable/entry1.s2
-rw-r--r--gas/testsuite/gas/vtable/inherit0.d10
-rw-r--r--gas/testsuite/gas/vtable/inherit0.s13
-rw-r--r--gas/testsuite/gas/vtable/inherit1.l6
-rw-r--r--gas/testsuite/gas/vtable/inherit1.s1
-rw-r--r--gas/testsuite/gas/vtable/vtable.exp39
-rw-r--r--gas/testsuite/gasp/INC1.H3
-rw-r--r--gas/testsuite/gasp/INC2.H2
-rw-r--r--gas/testsuite/gasp/assign.asm13
-rw-r--r--gas/testsuite/gasp/assign.err1
-rw-r--r--gas/testsuite/gasp/assign.out22
-rw-r--r--gas/testsuite/gasp/condass.asm129
-rw-r--r--gas/testsuite/gasp/condass.err0
-rw-r--r--gas/testsuite/gasp/condass.out155
-rw-r--r--gas/testsuite/gasp/crash.asm22
-rw-r--r--gas/testsuite/gasp/crash.err1
-rw-r--r--gas/testsuite/gasp/crash.out3059
-rw-r--r--gas/testsuite/gasp/crash1.asm13
-rw-r--r--gas/testsuite/gasp/crash1.err0
-rw-r--r--gas/testsuite/gasp/crash1.out24
-rw-r--r--gas/testsuite/gasp/crash2.asm41
-rw-r--r--gas/testsuite/gasp/crash2.err0
-rw-r--r--gas/testsuite/gasp/crash2.out69
-rw-r--r--gas/testsuite/gasp/data.asm23
-rw-r--r--gas/testsuite/gasp/data.err0
-rw-r--r--gas/testsuite/gasp/data.out45
-rw-r--r--gas/testsuite/gasp/exp.asm80
-rw-r--r--gas/testsuite/gasp/exp.err7
-rw-r--r--gas/testsuite/gasp/exp.out124
-rw-r--r--gas/testsuite/gasp/gasp.exp40
-rw-r--r--gas/testsuite/gasp/include.asm4
-rw-r--r--gas/testsuite/gasp/include.err0
-rw-r--r--gas/testsuite/gasp/include.out15
-rw-r--r--gas/testsuite/gasp/listing.asm15
-rw-r--r--gas/testsuite/gasp/listing.err0
-rw-r--r--gas/testsuite/gasp/listing.out28
-rw-r--r--gas/testsuite/gasp/macro.asm102
-rw-r--r--gas/testsuite/gasp/macro.err0
-rw-r--r--gas/testsuite/gasp/macro.out382
-rw-r--r--gas/testsuite/gasp/mdouble.asm47
-rw-r--r--gas/testsuite/gasp/mdouble.err0
-rw-r--r--gas/testsuite/gasp/mdouble.out68
-rw-r--r--gas/testsuite/gasp/mri/embed.asm5
-rw-r--r--gas/testsuite/gasp/mri/embed.out9
-rw-r--r--gas/testsuite/gasp/mri/exists.asm10
-rw-r--r--gas/testsuite/gasp/mri/exists.out24
-rw-r--r--gas/testsuite/gasp/mri/irp.asm4
-rw-r--r--gas/testsuite/gasp/mri/irp.out8
-rw-r--r--gas/testsuite/gasp/mri/irpc.asm3
-rw-r--r--gas/testsuite/gasp/mri/irpc.out8
-rw-r--r--gas/testsuite/gasp/mri/macro.asm8
-rw-r--r--gas/testsuite/gasp/mri/macro.out18
-rw-r--r--gas/testsuite/gasp/mri/narg.asm9
-rw-r--r--gas/testsuite/gasp/mri/narg.out38
-rw-r--r--gas/testsuite/gasp/mri/rept.asm3
-rw-r--r--gas/testsuite/gasp/mri/rept.out16
-rw-r--r--gas/testsuite/gasp/pl1.asm20
-rw-r--r--gas/testsuite/gasp/pl1.err1
-rw-r--r--gas/testsuite/gasp/pl1.out49
-rw-r--r--gas/testsuite/gasp/pl2.asm28
-rw-r--r--gas/testsuite/gasp/pl2.err0
-rw-r--r--gas/testsuite/gasp/pl2.out51
-rw-r--r--gas/testsuite/gasp/pl3.asm30
-rw-r--r--gas/testsuite/gasp/pl3.err0
-rw-r--r--gas/testsuite/gasp/pl3.out86
-rw-r--r--gas/testsuite/gasp/pl4.asm10
-rw-r--r--gas/testsuite/gasp/pl4.err0
-rw-r--r--gas/testsuite/gasp/pl4.out16
-rw-r--r--gas/testsuite/gasp/pl5.asm15
-rw-r--r--gas/testsuite/gasp/pl5.err0
-rw-r--r--gas/testsuite/gasp/pl5.out32
-rw-r--r--gas/testsuite/gasp/pl6.asm21
-rw-r--r--gas/testsuite/gasp/pl6.err0
-rw-r--r--gas/testsuite/gasp/pl6.out54
-rw-r--r--gas/testsuite/gasp/pl7.asm12
-rw-r--r--gas/testsuite/gasp/pl7.err1
-rw-r--r--gas/testsuite/gasp/pl7.out26
-rw-r--r--gas/testsuite/gasp/pl8.asm18
-rw-r--r--gas/testsuite/gasp/pl8.err0
-rw-r--r--gas/testsuite/gasp/pl8.out33
-rw-r--r--gas/testsuite/gasp/pr7583.asm3
-rw-r--r--gas/testsuite/gasp/pr7583.err0
-rw-r--r--gas/testsuite/gasp/pr7583.out5
-rw-r--r--gas/testsuite/gasp/reg.asm9
-rw-r--r--gas/testsuite/gasp/reg.err0
-rw-r--r--gas/testsuite/gasp/reg.out15
-rw-r--r--gas/testsuite/gasp/rep.asm13
-rw-r--r--gas/testsuite/gasp/rep.err0
-rw-r--r--gas/testsuite/gasp/rep.out391
-rw-r--r--gas/testsuite/gasp/repeat.asm14
-rw-r--r--gas/testsuite/gasp/repeat.err0
-rw-r--r--gas/testsuite/gasp/repeat.out211
-rw-r--r--gas/testsuite/gasp/reperr.asm2
-rw-r--r--gas/testsuite/gasp/reperr.err1
-rw-r--r--gas/testsuite/gasp/reperr.out5
-rw-r--r--gas/testsuite/gasp/reperr1.asm3
-rw-r--r--gas/testsuite/gasp/reperr1.err1
-rw-r--r--gas/testsuite/gasp/reperr1.out5
-rw-r--r--gas/testsuite/gasp/reperr2.asm6
-rw-r--r--gas/testsuite/gasp/reperr2.err1
-rw-r--r--gas/testsuite/gasp/reperr2.out14
-rw-r--r--gas/testsuite/gasp/reperr3.asm21
-rw-r--r--gas/testsuite/gasp/reperr3.err6
-rw-r--r--gas/testsuite/gasp/reperr3.out2035
-rw-r--r--gas/testsuite/gasp/sdata.asm24
-rw-r--r--gas/testsuite/gasp/sdata.err3
-rw-r--r--gas/testsuite/gasp/sdata.out59
-rw-r--r--gas/testsuite/gasp/sfunc.asm26
-rw-r--r--gas/testsuite/gasp/sfunc.err0
-rw-r--r--gas/testsuite/gasp/sfunc.out49
-rw-r--r--gas/testsuite/gasp/t1.asm3
-rw-r--r--gas/testsuite/gasp/t1.err0
-rw-r--r--gas/testsuite/gasp/t1.out5
-rw-r--r--gas/testsuite/gasp/t2.asm8
-rw-r--r--gas/testsuite/gasp/t2.err0
-rw-r--r--gas/testsuite/gasp/t2.out13
-rw-r--r--gas/testsuite/gasp/t3.asm12
-rw-r--r--gas/testsuite/gasp/t3.err1
-rw-r--r--gas/testsuite/gasp/t3.out25
-rw-r--r--gas/testsuite/gasp/while.asm18
-rw-r--r--gas/testsuite/gasp/while.err0
-rw-r--r--gas/testsuite/gasp/while.out388
-rwxr-xr-xgas/testsuite/lib/doboth19
-rwxr-xr-xgas/testsuite/lib/doobjcmp88
-rwxr-xr-xgas/testsuite/lib/dostriptest14
-rwxr-xr-xgas/testsuite/lib/dotest43
-rwxr-xr-xgas/testsuite/lib/dounsreloc8
-rwxr-xr-xgas/testsuite/lib/dounssym8
-rw-r--r--gas/testsuite/lib/gas-defs.exp574
-rw-r--r--gas/testsuite/lib/gas-dg.exp53
-rwxr-xr-xgas/testsuite/lib/run2
-rw-r--r--gas/vmsconf.sh128
-rw-r--r--gas/write.c2884
-rw-r--r--gas/write.h208
994 files changed, 276712 insertions, 0 deletions
diff --git a/gas/CONTRIBUTORS b/gas/CONTRIBUTORS
new file mode 100644
index 0000000000..b3fd03eb1b
--- /dev/null
+++ b/gas/CONTRIBUTORS
@@ -0,0 +1,111 @@
+(This file is under construction.) -*- text -*-
+
+If you've contributed to gas and your name isn't listed here, it is
+not meant as a slight. I just don't know about it. Email me,
+raeburn@cygnus.com and I'll correct the situation.
+
+This file will eventually be deleted: The general info will go into
+the documentation, and info on specific files will go into an AUTHORS
+file, as requested by the FSF.
+
+++++++++++++++++
+
+Dean Elsner wrote the original gas for vax. [more details?]
+
+Jay Fenlason maintained gas for a while, adding support for
+gdb-specific debug information and the 68k series machines, most of
+the preprocessing pass, and extensive changes in messages.c,
+input-file.c, write.c.
+
+K. Richard Pixley maintained gas for a while, adding various
+enhancements and many bug fixes, including merging support for several
+processors, breaking gas up to handle multiple object file format
+backends (including heavy rewrite, testing, an integration of the coff
+and b.out backends), adding configuration including heavy testing and
+verification of cross assemblers and file splits and renaming,
+converted gas to strictly ansi C including full prototypes, added
+support for m680[34]0 & cpu32, considerable work on i960 including a
+coff port (including considerable amounts of reverse engineering), a
+sparc opcode file rewrite, decstation, rs6000, and hp300hpux host
+ports, updated "know" assertions and made them work, much other
+reorganization, cleanup, and lint.
+
+Ken Raeburn currently maintains gas, and wrote the high-level BFD
+interface code to replace most of the code in format-specific I/O
+modules.
+
+The original Vax-VMS support was contributed by David L. Kashtan.
+Eric Youngdale and Pat Rankin have done much work with it since.
+
+The Intel 80386 machine description was written by Eliot Dresselhaus.
+
+Minh Tran-Le at IntelliCorp contributed some AIX 386 support.
+
+The Motorola 88k machine description was contributed by Devon Bowen of
+Buffalo University and Torbjorn Granlund of the Swedish Institute of
+Computer Science.
+
+Keith Knowles at the Open Software Foundation wrote the original MIPS
+back end (tc-mips.c, tc-mips.h), and contributed Rose format support
+that hasn't been merged in yet. Ralph Campbell worked with the MIPS
+code to support a.out format.
+
+Support for the Zilog Z8k and Hitachi H8/300, H8/500 and SH processors
+(tc-z8k, tc-h8300, tc-h8500, tc-sh), and IEEE 695 object file format
+(obj-ieee), was written by Steve Chamberlain of Cygnus Solutions.
+Steve also modified the COFF back end (obj-coffbfd) to use BFD for
+some low-level operations, for use with the Hitachi, 29k and Zilog
+targets.
+
+John Gilmore built the AMD 29000 support, added .include support, and
+simplified the configuration of which versions accept which
+pseudo-ops. He updated the 68k machine description so that Motorola's
+opcodes always produced fixed-size instructions (e.g. jsr), while
+synthetic instructions remained shrinkable (jbsr). John fixed many
+bugs, including true tested cross-compilation support, and one bug in
+relaxation that took a week and required the proverbial one-bit fix.
+
+Ian Lance Taylor of Cygnus Solutions merged the Motorola and MIT
+syntaxes for the 68k, completed support for some COFF targets (68k,
+i386 SVR3, and SCO Unix), wrote the ECOFF support based on Michael
+Meissner's mips-tfile program, wrote the PowerPC and RS/6000 support,
+and made a few other minor patches. He handled the binutils releases
+for versions 2.7 through 2.9.
+
+David Edelsohn contributed fixes for the PowerPC and AIX support.
+
+Steve Chamberlain made gas able to generate listings.
+
+Support for the HP9000/300 was contributed by Glenn Engel of HP.
+
+Support for ELF format files has been worked on by Mark Eichin of
+Cygnus Solutions (original, incomplete implementation), Pete
+Hoogenboom at the University of Utah (HPPA mainly), Michael Meissner
+of the Open Software Foundation (i386 mainly), and Ken Raeburn of
+Cygnus Solutions (sparc, initial 64-bit support).
+
+Several engineers at Cygnus Solutions have also provided many small
+bug fixes and configuration enhancements.
+
+The initial Alpha support was contributed by Carnegie-Mellon
+University. Additional work was done by Ken Raeburn of Cygnus
+Solutions. Richard Henderson then rewrote much of the Alpha support.
+
+Ian Dall updated the support code for the National Semiconductor 32000
+series, and added support for Mach 3 and NetBSD running on the PC532.
+
+Klaus Kaempf ported the assembler and the binutils to openVMS/Alpha.
+
+Steve Haworth contributed the support for the Texas Instruction c30
+(tms320c30).
+
+H.J. Lu has contributed many patches and much testing.
+
+Alan Modra reworked much of the i386 backend, improving the error
+checking, updating the code, and improving the 16 bit support, using
+patches from the work of Martynas Kunigelis and H.J. Lu.
+
+Many others have contributed large or small bugfixes and enhancements. If
+you've contributed significant work and are not mentioned on this list, and
+want to be, let us know. Some of the history has been lost; we aren't
+intentionally leaving anyone out.
diff --git a/gas/COPYING b/gas/COPYING
new file mode 100644
index 0000000000..60549be514
--- /dev/null
+++ b/gas/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/gas/ChangeLog b/gas/ChangeLog
new file mode 100644
index 0000000000..852b6c7787
--- /dev/null
+++ b/gas/ChangeLog
@@ -0,0 +1,3170 @@
+1999-04-30 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-mcore.c (mcore_s_section): Dump literals before
+ changing section.
+
+1999-04-29 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-mcore.c (md_apply_fix3): Insert reloc addend into insn
+ for COFF/PE port.
+
+Mon Apr 26 12:34:37 1999 Doug Evans <devans@canuck.cygnus.com>
+
+ * config/tc-fr30.h (TC_FIX_TYPE): Delete, cgen fields moved to write.h.
+ (TC_INIT_FIX_DATA): Delete.
+ * config/tc-m32r.h (TC_FIX_TYPE): Delete, cgen fields moved to write.h.
+ (TC_INIT_FIX_DATA): Delete.
+ * write.h (struct fix): New member fx_cgen, ifdef USING_CGEN.
+ * write.c (fix_new_internal): Initialize fx_cgen member.
+ * cgen.c (gas_cgen_record_fixup,gas_cgen_record_fixup_exp): Update.
+ (gas_cgen_md_apply_fix3): Update.
+ * config/tc-m32r.c (md_cgen_lookup_reloc): Update.
+ (md_cgen_record_fixup_exp): Update.
+ (FX_OPINFO_R_TYPE): Update.
+
+ * frags.c (frag_var,frag_variant): Initialize fr_cgen here.
+ * config/tc-fr30.h (TC_FRAG_INIT): Delete.
+ * config/tc-m32r.h (TC_FRAG_INIT): Delete.
+ * frags.h (struct frag): Make opindex, opinfo ints.
+
+ * config/tc-fr30.c (FX_OPINFO_R_TYPE): Delete, unused.
+
+1999-04-26 Tom Tromey <tromey@cygnus.com>
+
+ * aclocal.m4, configure: Updated for new version of libtool.
+
+1999-04-22 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-mcore.c (md_apply_fix3): Renamed function from
+ md_apply_fix.
+ (md_apply_fix3): Do not fix up absolute relocations against
+ symbolic values.
+
+ * config/tc-mcore.h (MD_APPLY_FIX3): Define.
+
+1999-04-20 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-mcore.c (md_pseudo_table): Add intercepts for section
+ changes and data-in-text directives.
+ (mcore_cons): New function: intercept cons() operations.
+ (mcore_float_cons): New function: intercept float_cons()
+ operations.
+ (mcore_stringer): New function: intercept stringer() operations.
+
+1999-04-18 Ian Lance Taylor <ian@zembu.com>
+
+ * obj.h (struct format_ops): Change generate_asm_lineno field to
+ take no parameters.
+ * config/obj-ecoff.h (OBJ_GENERATE_ASM_LINENO): Don't define.
+
+ * config/tc-alpha.c (find_opcode_match): Add default case to
+ switch.
+ (find_macro_match): Likewise.
+ (load_expression): Parenthesize && within ||.
+
+ * config/tc-alpha.h (TC_RELOC_RTSYM_LOC_FIXUP): Define.
+
+1999-04-17 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-mcore.c (md_pseudo_table): Add overrides for .bss
+ .text .data .section pseudo ops.
+ (mcore_s_section): New function. Dump lits before changing secs.
+ (mcore_s_text): New function. Dump lits before changing secs.
+ (mcore_s_data): New function. Dump lits before changing secs.
+
+1999-04-16 Gavin Romig-Koch <gavin@cygnus.com>
+
+ * config/tc-mips.c (mips_32bitmode): New.
+ (md_begin): Set mips_32bitmode if needed.
+ (mips_elf_final_processing): Don't set EF_MIPS_ARCH.
+ Set EF_MIPS_32BITMODE.
+
+Fri Apr 16 12:26:39 1999 Bob Manson <manson@charmed.cygnus.com>
+
+ * config/obj-coff.c (c_section_symbol): Fix typo in previous
+ change.
+
+1999-04-16 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-mcore.h (LOCAL_LABELS_FB): Define to 1.
+
+Thu Apr 15 16:52:09 1999 Jeffrey A Law (law@cygnus.com)
+
+ * tc-hppa.c (pa_get_absolute_exression): Try to handle "5 %r3"
+ expressions correctly.
+
+
+1999-04-15 Gavin Romig-Koch <gavin@cygnus.com>
+
+ * config/tc-mips.c (mips_elf_final_processing): Set EF_MIPS_ARCH.
+
+Mon Apr 12 23:45:07 1999 Jeffrey A Law (law@cygnus.com)
+
+ * tc-hppa.c (pa_ip, case '3'): New case for PA2.0 fmpyfadd
+ and fmpynfadd instructions.
+
+1999-04-11 Richard Henderson <rth@cygnus.com>
+
+ * as.h (environ): Declare it, if needed.
+ * as.c (dump_statistics): Don't declare environ.
+ * configure.in (environ): Detect declaration.
+ * configure, config.in: Rebuild
+
+ * config/tc-i386.c (i386_immediate): Accept @GOT relocations.
+ (i386_displacement): Allocate enough space for replacement buffer.
+ Clean up replacement buffer initialization.
+
+1999-04-11 Bob Manson <manson@charmed.cygnus.com>:
+
+ * subsegs.c (section_symbol): Don't create a new symbol if one
+ already exists; instead, use the existing one, but set its segment
+ and frag data if it hasn't already been defined.
+ * config/obj-coff.c (c_section_symbol): Likewise.
+
+Sat Apr 10 20:10:02 1999 Richard Henderson <rth@cygnus.com>
+
+ * tc-alpha.c (load_expression): Call as_bad instead of abort.
+
+1999-04-08 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-mcore.c: New File: Support routines for MCore
+ assembler.
+ * config/tc-mcore.h: New File: Definitions for MCore assembler.
+ * config/obj-coff.c: Add support for mcore-pe target.
+
+ * Makefile.am: Add support for MCore targets.
+ * Makefile.in: Regenerate.
+ * configure.in: Add support for MCore targets.
+ * configure: Regenerate.
+
+ * doc/all.texi: Set MCORE.
+ * doc/as.texinfo: Document MCore specific command line options.
+
+ * write.h: Prevent multiple inclusion.
+
+1999-04-06 Ian Lance Taylor <ian@zembu.com>
+
+ * asintl.h (LC_MESSAGES): Never define.
+ * as.c (main): Don't pass LC_MESSAGES to setlocale if the system
+ does not define it.
+ * gasp.c (main): Don't pass LC_MESSAGES to setlocale if the system
+ does not define it.
+
+ * Makefile.am (m68k-parse.c): If configuring in the source
+ directory, copy m68k-parse.y into the local directory before
+ running ylwrap, to remove spurious differences when generating
+ snapshots.
+ * Makefile.in: Rebuild.
+
+ * config/tc-sparc.h (md_do_align): Just allocate the number of
+ bytes necessary, rather than always allocating 1024.
+
+1999-04-04 Ian Lance Taylor <ian@zembu.com>
+
+ * listing.c (listing_newline): Add cast to avoid warning.
+ * read.c (generate_lineno_debug): Add cases to switch. Reindent.
+ * config/tc-i386.c (i386_scale): Add return value.
+ (build_displacement_string): Remove unused local temp_disp2.
+ (i386_intel_memory_operand): Add parentheses to avoid warning.
+ (i386_intel_operand): Remove unused local end_of_operand_string.
+ (i386_operand): Remove unused local operand_modifier.
+ (i386_operand): Add parens to avoid warning.
+
+1999-04-04 Don Bowman <don@pixsci.com>
+
+ * configure.in: Add mips*-*-vxworks* target; have it define
+ MIPS_STABS_ELF.
+ * configure, config.in: Rebuild.
+
+1999-03-31 Nick Clifton <nickc@cygnus.com>
+
+ * configure.in (emulations): Add support for arm-epoc-pe.
+ * configure: Regenerate.
+ * config/te-epoc-pe.h: New file. Define macros specific to
+ arm-epoc-pe target.
+ * config/tc-arm.h: Select epoc-pe-arm target format if configured
+ for arm-epoc-pe target.
+
+Mon Mar 29 10:15:40 CST 1999 Catherine Moore <clm@cygnus.com>
+
+ * tc-mips.c (md_apply_fix): Adjust value for linkonce sections.
+
+Wed Mar 24 14:11:10 1999 Jeffrey A Law (law@cygnus.com)
+
+ * tc-hppa.c (pa_parse_nonneg_cmpsub_cmpltr): Clean up code to
+ detect ",n" without a condition.
+ (pa_parse_neg_cmpsub_cmpltr): Likewise.
+
+
+Tue Mar 23 11:28:23 1999 Jeffrey A Law (law@cygnus.com)
+
+ * tc-hppa.c (pa_ip, case '~'): The condition for a branch on bit
+ instruction is encoded with one bit.
+
+
+1999-03-23 Ian Lance Taylor <ian@zembu.com>
+
+ * doc/internals.texi (CPU backend): Mention that
+ line_separator_chars should not include newline. From thi
+ <ttn@mingle.glug.org>.
+
+1999-03-22 Doug Evans <devans@casey.cygnus.com>
+
+ * config/tc-fr30.c (md_begin): Update call to fr30_cgen_cpu_open.
+ * config/tc-m32r.c (md_begin): Update call to m32r_cgen_cpu_open.
+
+Sun Mar 21 18:08:18 1999 Richard Henderson <rth@cygnus.com>
+
+ * tc-alpha.c (md_assemble): Allow '6' in an opcode.
+
+Thu Mar 18 10:55:30 1999 Jeffrey A Law (law@cygnus.com)
+
+ * tc-hppa.c (pa_ip, case 'a'): Do not call pa_parse_..._cmpsub_cmpltr.
+
+
+Thu Mar 18 02:30:07 1999 Jeffrey A Law (law@cygnus.com)
+
+ * tc-hppa.c (pa_ip, case 'd'): Do not allow ",n".
+
+1999-03-15 Martin Hunt <hunt@cygnus.com>
+
+ * app.c (do_scrub_begin): Change '-' back to a symbol char
+ so we can use multiple opcodes on a line again.
+
+ * config/tc-d30v.c: By default, warn if a symbol has
+ the same name as a register. Plus some minor
+ updates from the branch.
+
+1999-03-13 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-d30v.c (md_apply_fix3): Handle BFD_RELOC_8,
+ BFD_RELOC_16 and BFD_RELOC_64.
+
+1999-03-12 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
+
+ * expr.c (expr): Add missing else.
+
+1999-03-12 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-arm.c (md_apply_fix3): Improve error message.
+
+1999-03-11 Doug Evans <devans@casey.cygnus.com>
+
+ * Makefile.am (CPU_TYPES): Add fr30.
+ (cgen.o): Add $(CGEN_CPU_PREFIX)-desc.h dependency.
+ (fr30,m32r dependencies): Update.
+ * Makefile.in: Rebuild.
+
+ * cgen.c (gas_cgen_record_fixup): Update use of operand->type.
+ (gas_cgen_record_fixup_exp): Ditto.
+ (gas_cgen_finish_insn): Call cgen_operand_lookup_by_num.
+ (gas_cgen_md_apply_fix3): Ditto. Update call to set_vma_operand.
+ * config/tc-fr30.c (md_begin): Update call to fr30_cgen_cpu_open.
+ (md_cgen_lookup_reloc): Update use of operand->type.
+ * config/tc-m32r.c (md_begin): Update call to fr30_cgen_cpu_open.
+ (md_convert_frag): Call cgen_operand_lookup_by_num.
+ (md_cgen_lookup_reloc): Update use of operand->type.
+ (m32r_cgen_record_fixup_exp): Ditto.
+
+1999-03-09 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * config/tc-mips.c (md_show_usage): Fix message.
+
+1999-03-03 Nick Clifton <nickc@cygnus.com>
+
+ * doc/c-arm.texi (ARM Syntax): Document new command line switches
+ and LDR reg,=<expr> instruction.
+
+ * config/tc-arm.c: Add support for -mcpu=arm810, -mcpu=arm9 and
+ -mcpu=arm9tdmi.
+
+Fri Feb 19 09:36:30 1999 Ian Lance Taylor <ian@cygnus.com>
+
+ * doc/c-arm.texi (ARM-Chars): Fix typo in use of '@'.
+
+1999-02-17 Nick Clifton <nickc@cygnus.com>
+
+ This patch was created by: Scott Bambrough
+ <scottb@corelcomputer.com>
+
+ * app.c:
+ Special cased '@' character. The '@' character is used as the
+ ARM assembler comment character, as a special character
+ and in ELF .symver pseudo-op's, and as a special character in
+ .type and .section pseudo-ops.
+ (symver_pseudo): New static variable.
+ (symver_state): New static variable.
+ (struct app_save): Add field 'symver_state'.
+ (app_push): Save global symver_state int struct app_save.
+ (app_pop): Restore global symver_state from struct app_save.
+ (do_scrub_chars): Special case handling of '@' character in
+ .symver pseudo-ops.
+
+ * configure.in: Modified to recognize armv* uname syntax from ARM
+ Linux kernel.
+ * configure: Regenerated.
+
+ * config/obj-elf.c (obj_elf_section): Allow '%' as well as '@' as
+ a prefix to the section's type.
+ (obj_elf_type): Allow '%' as well as '@' and '#' as prefixes to
+ the type's typename.
+
+ * config/tc-arm.h: Add support for PIC generation:
+ (pic_code): New boolean.
+ (obj_relocate_extern): Define.
+ (TC_RELOC_RTSYM_LOC_FIXUP): Define
+ (TC_CONS_FIX_NEW): Define.
+ (tc_fix_adjustable): Define.
+ (GLOBAL_OFFSET_TABLE_NAME): Define.
+
+ * config/tc-arm.c: Add support for PIC generation:
+ (line_seperator_chars): Allow ';' as a seperator for Linux.
+ (is_immediate_prefix): New macro.
+ (arm_parse_reloc): New function.
+ (s_arm_elf_cons): New function.
+ (do_branch): Special case for BFD_RELOC_ARM_PLT32.
+ (md_undefined_symbol): Special case handling for the Global Offset
+ Table's symbol.
+ (md_apply_fix3): Handle PIC relocs.
+ (tc_gen_reloc): Handle PIC relocs.
+ (md_parse_option): Add support for '-k' command line switch to
+ enable PIC generation.
+ (cons_fix_new_arm): New function.
+ (s_arm_elf_cons): New function.
+
+Tue Feb 16 16:31:53 1999 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Add comments for uses of AC_DEFINE.
+ * acinclude.m4: Likewise.
+ * acconfig.h: Remove.
+ * aclocal.m4: Rebuild.
+ * configure: Rebuild.
+ * Makefile.in: Rebuild.
+ * config.in: Rebuild.
+
+1999-02-15 Jim Lemke <jlemke@cygnus.com>
+
+ * config/tc-mips.c (mips_ip: case 'o'): Fix assertion failure for
+ non-constant offset from a base register.
+
+1999-02-14 Ken Raeburn <raeburn@raeburn.org>
+
+ * config/tc-alpha.c (md_show_usage): Put \ before newline in
+ strings always.
+
+Sat Feb 13 14:10:10 1999 Richard Henderson <rth@cygnus.com>
+
+ * config/tc-alpha.c (cpu_types): Enable EV6 PALcode with -m21264.
+ (emit_insn): Look for pc-relative and no-overflow specifiers on
+ internal relocation types.
+
+1999-02-13 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * doc/c-mips.texi (MIPS Opts): Updated list of -mNNNN and
+ -mcpu=NNNN flags.
+
+ * config/tc-mips.c: Remove all the mips_NNNN variables; just use
+ mips_cpu instead.
+ (mips_4650, mips_4010, mips_4100): Variables removed.
+ (hilo_interlocks, gpr_interlocks, append_insn, macro_build, macro,
+ macro2, mips16_macro, mips_ip): Test mips_cpu, not the mips_NNNN
+ variables.
+ (md_begin): Don't bother initializing the mips_NNNN variables;
+ mips_cpu is set, and that's good enough now.
+ (md_parse_option): Have the -mNNNN options set mips_cpu instead of
+ the mips_NNNN variable. The -no-mNNNN flags are now no-ops.
+ (show): New function, to handle wrapping in the CPU lists.
+ (md_show_usage): Update lists of -mcpu and -mNNNN switches.
+
+Sat Feb 13 00:17:26 1999 Richard Henderson <rth@cygnus.com>
+
+ * config/tc-i386.c (i386_intel_operand): Ignore `SHORT' rather
+ than treat as an immediate specifier.
+
+Thu Feb 11 16:18:31 1999 Richard Henderson <rth@cygnus.com>
+
+ * config/tc-i386.c: Prototype many functions.
+ (set_intel_syntax): Accept `prefix'/`noprefix' specifiers.
+ (i386_immediate): Remove unused second argument.
+ (i386_intel_operand): Fix i386_is_reg typo.
+ (i386_operand): Use allow_naked_reg.
+ (output_invalid): Make operand int for K&R.
+
+Thu Feb 11 11:21:02 1999 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.am (EXTRA_as_new_SOURCES): Uncomment--fixed by automake
+ patch.
+ * Makefile.in: Rebuild.
+
+1999-02-09 Doug Evans <devans@casey.cygnus.com>
+
+ * Makefile.am (DISTCLEANFILES): Change cgen-opc.h to cgen-desc.h.
+ (cgen.o): Ditto.
+ (EXTRA_as_new_SOURCES): Comment out.
+ (.tcdep): <arch>-opc.h renamed to <arch>-desc.h.
+ * Makefile.in: Rebuild.
+ * doc/Makefile.in: Rebuild.
+ * configure.in: Require autoconf 2.13. Redo using_cgen handling.
+ Delete call to AM_CYGWIN32. Replace AM_EXEEXT with AC_EXEEXT.
+ (AC_OUTPUT): <arch>-opc.h renamed to <arch>-desc.h.
+ * configure: Rebuild.
+ * aclocal.m4: Rebuild.
+ * config.in: Rebuild.
+ * cgen.c: Include cgen-desc.h, not cgen-opc.h.
+ (*): CGEN_OPCODE_DESC renamed to CGEN_CPU_DESC.
+ (gas_cgen_cpu_desc): Renamed from gas_cgen_opcode_desc.
+ CGEN_INSN_ATTR renamed to CGEN_INSN_ATTR_VALUE.
+ CGEN_OPERAND_ATTR renamed to CGEN_OPERAND_ATTR_VALUE.
+ (gas_cgen_record_fixup): Remove unnecessary != 0 test.
+ (gas_cgen_record_fixup_exp): Ditto.
+ (gas_cgen_finish_insn): Ditto. Refer to operand table via cpu
+ descriptor, not global variable.
+ (gas_cgen_md_apply_fix3): Refer to operand_table via cpu
+ descriptor, not global variable. Refer to insert_operand handler
+ via cpu descriptor, not global function.
+ * cgen.h (*): CGEN_OPCODE_DESC renamed to CGEN_CPU_DESC.
+ * config/tc-fr30.c: Include opcodes/fr30-desc.h.
+ (*): gas_cgen_opcode_desc renamed to gas_cgen_cpu_desc.
+ CGEN_INSN_ATTR renamed to CGEN_INSN_ATTR_VALUE.
+ Update call to CGEN_OPERAND_TYPE,CGEN_INSN_OPERANDS.
+ * config/tc-m32r.c: Ditto.
+ (assemble_two_insns): Update calls to cgen_lookup_get_insn_operands.
+ (md_assemble): Ditto.
+ (md_convert_frag): Update call to CGEN_OPERAND_ENTRY.
+
+1999-02-09 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-arm.c (md_apply_fix3): Fix handling of label1 - label2
+ relocations for ELF targets.
+
+1999-02-08 Nick Clifton <nickc@cygnus.com>
+
+ * configure.in: Add support for StrongARM target.
+ * configure: Regenerate.
+
+1999-02-05 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-arm.h: Tidy OBJ_ELF and OBJ_COFF definitions.
+
+ * config/tc-arm.c (md_apply_fix3): Fix BFD_RELOC_ARM_PCREL_BRANCH
+ for COFF ports.
+
+Wed Feb 3 11:35:47 1999 Richard Henderson <rth@cygnus.com>
+
+ * config/tc-alpha.c (md_show_usage): Document pca56 and ev6 options.
+
+Mon Feb 1 20:37:30 1999 Catherine Moore <clm@cygnus.com>
+
+ * config/tc-i386.h (LONG_DOUBLE_MNEM_SUFFIX): Define.
+ (INTEL_DWORD_MNEM_SUFFIX): Define.
+ (BYTE_PTR): Define.
+ (WORD_PTR): Define.
+ (DWORD_PTR): Define.
+ (XWORD_PTR): Define.
+ (SHORT): Define.
+ (OFFSET_FLAT): Define.
+ (FLAT): Define.
+ (NONE_FOUND): Define.
+ (No_dSuf): Define.
+ (No_xSuf): Define.
+ * config/tc-i386.c (set_intel_syntax): New routine.
+ (intel_syntax): Declare.
+ (allow_naked_reg): Declare.
+ (md_pseudo_table): Support .intel_syntax and .att_syntax.
+ (intel_float_operand): New routine.
+ (md_assemble): Handle INTEL_DWORD_MNEM_SUFFIX.
+ Handle brackets as well as parens. Call i386_intel_operand for
+ intel syntax. Reverse operands if appropriate. Handle new
+ suffixes. Handle movzx and movsx.
+ (i386_is_reg): New routine.
+ (i386_immediate): New routine.
+ (i386_scale): New routine.
+ (i386_displacement): New routine.
+ (i386_operand_modifier): New routine.
+ (build_displacement_string): New routine.
+ (i386_parse_seg): New routine.
+ (i386_intel_memory_operand): New routine.
+ (i386_intel_operand): New routine.
+ (i386_operand): Call i386_displacement, i386_immediate,
+ i386_scale, etc. instead of handling inline.
+ (parse_register): Handle registers without prefix.
+
+Mon Feb 1 12:24:58 1999 Catherine Moore <clm@cygnus.com>
+
+ * configure: Regenerate.
+ * configure.in (arm-*-oabi): New.
+ (thumb-*-oabi): New.
+ * config/tc-arm.c (target_oabi): Declare.
+ (md_apply_fix3): Support REL relocs.
+ (md_parse_option): Handle -oabi.
+ (elf32_arm_target_format): New routine.
+ (md_longopts): Add OPTION_OABI.
+ * config/tc-arm.h: Redefine TARGET_FORMAT.
+
+
+1999-01-28 Nick Clifton <nickc@cygnus.com>
+
+ * write.c (write_relocs): Handle out of range error.
+
+ * config/tc-fr30.c (fr30_fix_adjustable): New function.
+ (fr30_force_relocation): Default to 0.
+
+ * config/tc-fr30.h (obj_fix_adjustable): Define.
+ (TC_FORCE_RELOCATION): Define.
+
+ * cgen.c (gas_cgen_md_apply_fix3): Do not apply fixes to VTABLE
+ relocs.
+
+1999-01-16 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-d30v.c (write_2_short): Do not generate a sequential
+ merge of two instructions if the left instruciton kills the right.
+
+1999-01-11 Doug Evans <devans@casey.cygnus.com>
+
+ * Makefile.in: Regenerate.
+ * configure.in: Redo test for using cgen.
+ * configure: Regenerate.
+
+1999-01-09 Nick Clifton <nickc@cygnus.com>
+
+ * config/obj-coff.h (obj_adjust_symtab): Prevent accidental
+ redefinition of this macro.
+
+Tue Jan 5 21:58:03 1999 Doug Evans <devans@canuck.cygnus.com>
+
+ * config/tc-mips.c (mips_frob_file): Disable "Unmatched %hi reloc"
+ warning.
+
+1998-12-29 Gavin Romig-Koch <gavin@cygnus.com>
+
+ * config/tc-mips.c (append_insn): For mips16, insert a nop between
+ a read of HI or LO and an immediatly following branch.
+
+1998-12-29 Gavin Romig-Koch <gavin@cygnus.com>
+
+ * config/tc-mips.c (md_begin): Another correction to the setting of
+ mips_eabi64.
+
+1998-12-23 Gavin Romig-Koch <gavin@cygnus.com>
+
+ * config/tc-mips.c (md_begin): Correct type-o in setting of mips_eabi64.
+
+1998-12-21 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-m32r.c (md_assemble): Emit a NOP after a relaxable 16
+ bit insn when optimizing, so that parallelised instructions will
+ start on a 32 bit boundary.
+
+1998-12-19 Gavin Romig-Koch <gavin@cygnus.com>
+
+ * config/tc-mips.c (mips_eabi64): New.
+ (md_begin): Set mips_eabi64.
+ (mips_elf_final_processing): Use it.
+
+1998-12-18 Gavin Romig-Koch <gavin@cygnus.com>
+
+ * config/tc-mips.c (mips_elf_final_processing):
+ Correct setting of ABI in e_flags.
+
+Wed Dec 16 16:17:22 1998 Dave Brolley <brolley@cygnus.com>
+
+ * config/tc-fr30.c (md_assemble): Warn about invalid instructions in delay slots.
+
+1998-12-16 Gavin Romig-Koch <gavin@cygnus.com>
+
+ * config/tc-mips.c (md_begin,md_parse_option): Handle vr4111.
+
+1998-12-15 Doug Evans <devans@casey.cygnus.com>
+
+ * cgen.c (gas_cgen_md_apply_fix3): Mark as an error, rather than a
+ warning, values that don't fit in the field.
+
+1998-12-15 Gavin Romig-Koch <gavin@cygnus.com>
+
+ * config/tc-mips.c (mips_abi_string): New.
+ (md_parse_option,md_longopts): Add mabi.
+ (mips_elf_final_processing): Set e_flags based on mabi flag.
+
+1998-12-15 Gavin Romig-Koch <gavin@cygnus.com>
+
+ * config/tc-mips.c (md_parse_option): Handle vr4111.
+
+98-12-11 Ken Raeburn <raeburn@cygnus.com>
+
+ * config/tc-h8300.c (build_bytes): Change message given if the
+ instruction requires H8/300H mode and we're not in Hmode, to
+ suggest that it may be the operand modes that are the problem, not
+ necessarily the opcode.
+
+1998-12-10 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-fr30.c: Add line separator character.
+
+Tue Dec 8 19:51:50 1998 Mark Klein <mklein@dis.com>
+
+ * configure.in (hppa-*-mpeix*): New target.
+ * config/obj-som.h (obj_som_compiler): Declare.
+ * config/obj-som.c (compiler_seen): New static variable.
+ (obj_som_compiler): New function.
+ * config/tc-hppa.c: Update tc_data uses for change to bfd/som.h.
+ (md_pseudo_table): Add "compiler" if OBJ_SOM.
+ (pa_type_args): Set hppa_priv_level.
+ (pa_compiler): New static function if OBJ_SOM.
+ * configure: Rebuild.
+
+Tue Dec 8 15:00:50 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.c (output_leb128): Don't mark as inline.
+
+1998-12-08 Andrew MacLeod <amacleod@cygnus.com>
+
+ * config/tc-ppc.c (ppc_vbyte): Prototype and new function for
+ AIX .vbyte unaligned data support.
+ (md_pseudo_table): Add 'vbyte' to list of valid pseudos.
+ (ppc_elf_validate_fix): Add eh_frame to list of ELF relocatable
+ sections.
+
+1998-12-07 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-d30v.c (md_assemble, do_assemble): Improve erroneous
+ input handling.
+
+Mon Dec 7 09:48:34 1998 Catherine Moore <clm@cygnus.com>
+
+ * config/tc-arm.c (elf32_arm_force_relocation): Check for
+ BFD_RELOC_ARM_PCREL_BRANCH.
+
+Sun Dec 6 12:46:36 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Define TARGET_BYTES_{BIG,LITTLE}_ENDIAN after
+ checking the target type.
+ (mips-dec-bsd*): Set endian to little.
+ * configure: Rebuild.
+
+ COFF weak symbol support, based on patches from Mark Elbrecht
+ <snowball3@usa.net>:
+ * config/obj-coff.h (S_IS_WEAK): Define if not BFD_ASSEMBLER.
+ * config/obj-coff.c (obj_coff_weak): New static function.
+ (obj_coff_endef) [both versions]: Handle weak symbols.
+ (coff_frob_symbol): Likewise.
+ (yank_symbols): Likewise.
+ (obj_pseudo_table): Add "weak".
+
+ * configure.in (m68k-*-gnu*): New target. From Aymeric Vincent
+ <aymeric.vincent@emi.u-bordeaux.fr>.
+ * aclocal.m4: Rebuild with current tools.
+ * configure: Rebuild.
+
+ * config/tc-alpha.c (emit_ldgp): Give an error message rather than
+ an assertion failure for a case we can't handle when OBJ_ECOFF.
+
+ * expr.c (operator): And with 0xff to avoid problems with signed
+ char.
+
+1998-12-03 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-fr30.c (md_cgen_lookup_reloc): Generate
+ BFD_RELOC_FR30_48 instead of BFD_RELOC_FR30_32.
+
+1998-12-02 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-fr30.c (md_cgen_lookup_reloc): Enable relocs for
+ LDI:20 insn.
+
+Thu Nov 26 11:23:48 1998 Dave Brolley <brolley@cygnus.com>
+
+ * config/tc-fr30.c (md_pcrel_from_section): Restore previous calculation
+ of pcrel point.
+
+Tue Nov 24 17:21:52 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-fr30.c (md_pcrel_from_section): Fix calculation of
+ pcrel point.
+
+Tue Nov 24 14:54:38 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-d10v.c (md_assemble): Make static 'etype' have file
+ scope.
+ (d10v_cleanup): Only generate previous insn if a multiline insn is
+ not pending.
+
+Fri Nov 20 11:41:13 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-fr30.c (md_cgen_lookup_reloc): Add support for
+ FR30_OPERAND_I32.
+
+Thu Nov 19 15:01:29 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-arm.c (md_parse_option): Add support for -marm7xxx and
+ -marm6xxx command line switches.
+
+1998-11-18 Doug Evans <devans@casey.cygnus.com>
+
+ * Makefile.am (DEP): Use $(srcdir)/../mkdep.
+ (itbl-ops.o): Delete duplicate dependencies.
+ Rebuild dependencies.
+ Add fr30 dependencies.
+ * Makefile.in: Rebuild.
+
+Tue Nov 17 13:42:42 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-fr30.c (md_cgen_lookup_reloc): Updated to match latest
+ opcode list.
+ * listing.c: Ignore line terminator characters found inside
+ strings.
+
+Thu Nov 12 19:21:24 1998 Dave Brolley <brolley@cygnus.com>
+
+ * po/gas.pot: Regenerated.
+
+Thu Nov 12 10:54:16 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-fr30.c (fr30_is_colon_insn): New name for
+ fr30_is_label_start(). Also checks for delay slot insns.
+
+ * config/tc-fr30.c (fr30_is_label_start): New function: Handle
+ FR30 instructions which contain a colon in the mnemonic.
+
+ * config/tc-fr30.h (TC_START_LABEL): Define this macro.
+
+Wed Nov 11 09:58:21 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-fr30.c: Removed currently superflous code.
+
+Tue Nov 10 13:13:05 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-fr30.h: New file.
+ * config/tc-fr30.c: Tweaking so that it will compile.
+
+Tue Nov 10 14:41:33 1998 Catherine Moore <clm@cygnus.com>
+
+ * config/tc-d10v.h (obj_fix_adjustable): Define.
+ (TC_FORCE_RELOCATION): Define.
+ (d10v_force_relocation): Declare.
+ * config/tc-d10v.c (tc_gen_reloc): Handle Vtable relocs.
+ (md_apply_fix3): Handle Vtable relocs.
+ (d10v_fix_adjustable): New.
+ (d10v_force_relocation): New.
+
+Mon Nov 9 14:25:06 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-d30v.c: Change default behaviour to ignore potential
+ conflicts between register name and symbol names.
+
+Wed Nov 4 18:42:00 1998 Dave Brolley <brolley@cygnus.com>
+
+ * configure.in: Add fr30-*-*.
+ * config/tc-fr30.c: New file.
+ * Makefile.in: Regenerated.
+ * config.in: Regenerated.
+ * configure: Regenerated.
+ * doc/Makefile.in: Regenerated.
+ * po/gas.pot: Regenerated.
+
+Mon Nov 2 20:54:16 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * config/tc-m32r.c (assemble_two_insns): Ensure both insns
+ are 16 bit insns.
+
+Mon Nov 2 20:10:18 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
+
+ * app.c (do_scrub_begin): Set characters above 127 to be symbol
+ characters.
+ (do_scrub_chars): Add some casts to unsigned char to avoid
+ unwanted sign extension.
+ * read.c (lex_type): Set characters about 127 to be symbol
+ characters.
+ * config/tc-i386.c (md_begin): Set identifier_chars and
+ operand_chars for values above 127.
+
+Mon Nov 2 15:05:33 1998 Geoffrey Noer <noer@cygnus.com>
+
+ * configure.in: detect cygwin* instead of cygwin32*
+ * configure: regenerate
+
+Tue Oct 27 13:18:40 1998 Nick Clifton <nickc@cygnus.com>
+
+ * listing.c: Add support for producing a listing from piped
+ input.
+
+Tue Oct 27 08:56:44 1998 Gavin Romig-Koch <gavin@cygnus.com>
+
+ * config/tc-mips.c (hilo_interlocks): Remove mips_3900.
+ (append_insn): Account for the tx39's multiply behavior.
+
+1998-10-26 Michael Meissner <meissner@cygnus.com>
+
+ * config/tc-m32r.c (assemble_two_insns): Rename assemble_two_insns
+ from assemble_parallel_insns. Add support for '->' to indicate
+ explicitly serializing the instructions.
+ (md_assemble): Ditto.
+
+Sat Oct 24 15:12:19 1998 Catherine Moore <clm@cygnus.com>
+
+ * config/tc-sh.c (sh_fix_adjustable): Adjust EXTERN and
+ WEAK handling.
+
+Thu Oct 22 12:41:33 1998 Catherine Moore <clm@cygnus.com>
+
+ * cgen.c (gas_cgen_md_apply_fix3): Revert last change.
+
+Thu Oct 22 10:03:15 1998 Ron Unrau <runrau@cygnus.com>
+
+ * config/tc-mips.c : support frame and regmask/fregmask when
+ MIPS_STABS_ELF is specified.
+
+Wed Oct 21 11;34:51 1998 Catherine Moore <clm@cygnus.com>
+
+ * config/tc-sh.c (sh_fix_adjustable): Only include if OBJ_ELF.
+ (md_apply_fix): Don't return 1 for VTABLE relocs.
+ * config/tc-sh.h (obj_fix_adjustable): Define only if OBJ_ELF.
+
+Tue Oct 20 11:18:28 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * doc/c-i386.texi: Replace occurences of "opcode" with
+ "instruction mnemonic", "instruction", or "mnemonic" when
+ referring to the name of an instruction. Use "opcode" when
+ referring to the sequence of machine bytes.
+
+ * config/tc-i386.c (opcode_chars): Rename to mnemonic_chars.
+ (is_opcode_char): Rename to is_mnemonic_char.
+ (md_assemble and i386_operand): Correct error messages from
+ "opcode" to "instruction mnemonic"
+ Rename throughout opcode[] -> mnemonic[], opp -> mnem_p,
+ MAX_OPCODE_SIZE -> MAX_MNEM_SIZE,
+ DWORD_OPCODE_SUFFIX -> DWORD_MNEM_SUFFIX,
+ WORD_OPCODE_SUFFIX -> WORD_MNEM_SUFFIX,
+ BYTE_OPCODE_SUFFIX -> BYTE_MNEM_SUFFIX,
+ SHORT_OPCODE_SUFFIX -> SHORT_MNEM_SUFFIX
+ LONG_OPCODE_SUFFIX -> LONG_MNEM_SUFFIX
+
+ * config/tc-i386.h (*_MNEM_SUFFIX): Rename from *_OPCODE_SUFFIX.
+
+ * config/tc-i386.c (i386_operand): Check for garbage after
+ register name.
+
+Tue Oct 20 10:49:42 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-i386.c (md_apply_fix3): Change handling of PCREL reloc
+ for BFD_ASSEMBLER to only change value when COFF if TE_PE.
+
+Mon Oct 19 20:20:42 1998 Catherine Moore <clm@cygnus.com>
+
+ * config/tc-sh.h (obj_fix_adjustable): Define.
+ * config/tc-sh.c (sh_force_relocation): Handle VT relocs.
+ (md_apply_fix): Likewise.
+ (tc_gen_reloc): Likewise.
+ (sh_fix_adjustable): New.
+
+Mon Oct 19 12:35:43 1998 Doug Evans <devans@seba.cygnus.com>
+
+ * cgen.c (gas_cgen_finish_insn): Update handling of CGEN_INT_INSN_P.
+ * cgen.h (gas_cgen_finish_insn): Update prototype.
+ * config/tc-m32r.c (m32r_insn): CGEN_INT_INSN -> CGEN_INT_INSN_P.
+ cgen_insn_t -> CGEN_INSN_INT.
+ (make_parallel): Update handling of CGEN_INT_INSN_P.
+ (assemble_parallel_insn): Ditto.
+ (target_make_parallel): New function.
+ (md_assemble): Use it.
+
+Mon Oct 19 13:16:12 1998 Catherine Moore <clm@cygnus.com>
+
+ * config/tc-m32r.c (m32r_force_relocation): Fix typo.
+
+Sun Oct 18 18:48:57 1998 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-sh.c (md_assemble): Make sure the entire opcode is
+ converted into lower case.
+
+Fri Oct 16 13:36:34 CDT Catherine Moore <clm@cygnus.com>
+
+ * cgen.c (gas_cgen_md_apply_fix3): Handle VTABLE relocs.
+ (gas_cgen_tc_gen_reloc): Likewise.
+ * config/tc-m32r.h (obj_fix_adjustable): Define.
+ * config/tc-m32r.c (m32r_fix_adjustable): New.
+ (m32r_force_relocation): Handle VTABLE relocs.
+
+Wed Oct 14 11:33:38 1998 Nick Clifton <nickc@cygnus.com>
+
+ * doc/c-arm.texi (ARM Directives): Document .ltorn directive.
+
+Mon Oct 12 11:07:21 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-m32r.c (assemble_parallel_insn): Convert second opcode
+ to lower case before parsing.
+
+ * config/tc-d30v.c (parallel_ok): Ignore conflicts when explicitly
+ parallel insns modift buts in the PSW as a side effect.
+
+Thu Oct 8 10:18:33 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-d30v.c (find_format): Test for missing flag and
+ control registers.
+
+ (md_apply_fix3): Fix error messages to avoid
+ assumption about presence of a symbol.
+
+ (parallel_ok): Disallow parallel instructions that both modify the
+ same flag register.
+
+ (find_format): Generate a warning if an odd numbered register is
+ used as the first register in a mutli-register instruction.
+
+Wed Oct 7 14:09:14 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-d30v.c (md_apply_fix3): Do not assume that bad
+ relocations are always associated with a symbol.
+
+Tue Oct 6 09:31:15 1998 Catherine Moore <clm@cygnus.com>
+
+ * tc-sparc.h (TC_FORCE_RELOCATION): Define.
+ (elf32_sparc_force_relocation): Declare.
+ * tc-sparc.c (md_apply_fix3): Handle vtable relocs.
+ (tc_gen_reloc): Handle vtable relocs.
+ (elf32_sparc_force_relocation): New.
+
+Mon Oct 5 09:25:32 1998 Catherine Moore <clm@cygnsu.com>
+
+ * symbols.c (S_IS_FUNCTION): New.
+ * config/tc-v850.h (obj_fix_adjustable): Define.
+ (TC_FORCE_RELOCATION): Define.
+ (v850_force_relocation): Declare.
+ * config/tc-v850.c (tc_gen_reloc): Use offset instead
+ of fx_addnumber for VTABLE reloc addends.
+ (md_apply_fix3): Handle VTABLE relocs.
+ (v850_fix_adjustable): New.
+ (v850_force_relocation): New.
+
+Mon Oct 5 00:48:52 1998 Jeffrey A Law (law@cygnus.com)
+
+ * tc-hppa.c (fp_operand_format): Add some additional formats.
+ (pa_ip): Do not automatically promote into pa2.0 mode.
+ (pa_level): Handle ".level 2.0".
+
+Sun Oct 4 20:57:43 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * config/tc-i386.c (md_assemble): Handle AMD_3DNOW_OPCODE.
+ * config/tc-i386.h (template.extension_opcode): Change to
+ unsigned int to allow full range of 8-bit opcode suffixes.
+ (None): Redefine as 0xffff.
+
+ From Jeff B Epler <jepler@usgs.gov>
+ * doc/c-i386.texi (i386-SIMD): New section.
+
+Thu Oct 1 15:37:54 1998 Richard Henderson <rth@cygnus.com>
+
+ * read.c (discard_rest_of_line): New function.
+ * read.h: Declare it.
+ * config/tc-alpha.c (s_alpha_mask, s_alpha_frame): Use it.
+
+Thu Oct 1 10:33:53 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-d10v.c (find_symbol_matching_register): New function.
+ (find_opcode): Cope with the case where a register name matches
+ a symbol name.
+
+Wed Sep 30 10:52:32 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c (md_pcrel_from): Rename to
+ v850_pcrel_from_section.
+ (v850_pcrel_from_section): Do not resolves symbols in other
+ sections.
+
+ * config/tc-v850.h (MD_PCREL_FROM_SECTION): Define.
+
+Mon Sep 28 11:01:20 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-d10v.c (find_opcode): Generate an error if a register
+ is supplied for an operand that should not be a register.
+
+Fri Sep 25 10:04:21 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-d30v.c (write_2_short): But do allow delayed branch
+ instructions to have another instruction in the right bin.
+
+Thu Sep 24 09:28:34 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-d30v.c (write_2_short): Do not allow instructions in
+ the right container if the left container holds a branch
+ instruction.
+
+Wed Sep 23 10:54:29 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-d30v.c (reg_name_search): Only warn if a name matches
+ both a register name and symbol name.
+ (find_format): Allow correct parsing of MVTSYS and MVFSYS insns.
+
+Tue Sep 22 17:49:16 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-d30v.c (write_2_short): Implement EITHER_BUT_PREFER_MU
+ execution unit class.
+
+ (reg_name_search): If a name matches a register and a symbol,
+ prefer the register.
+ (find_format): Disallow flag registers when a general purpose
+ register is required.
+ If a number is required, but a register has been given, check to
+ see if a symbol with the same name as the register exists, and if
+ so, use that symbol.
+
+Tue Sep 22 16:40:52 1998 Jim Wilson <wilson@cygnus.com>
+
+ * config/obj-elf.h (ECOFF_DEBUGGING): Add missing parens.
+
+Tue Sep 22 15:44:21 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-d30v.c (find_format): Do not accept flag registers as
+ general purpose registers.
+ (find_format): If an immediate value is expected at a given place
+ in a format, but a register name has been provided instead, check
+ to see if that register name matches the name of a predefined
+ symbol and if it does, then use the symbol instead.
+ (reg_name_search): If a register name matches a symbol name,
+ prefer the register name to the symbol name.
+
+Mon Sep 21 10:42:57 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-m32r.c (m32r_do_align): After inserting NOPs, reset
+ the previous insn to empty.
+
+1998-09-20 Michael Meissner <meissner@cygnus.com>
+
+ * config/tc-ppc.c (md_apply_fix3): Do not break string into two
+ pieces, forcing the use of an ANSI compiler.
+
+Sun Sep 20 00:58:12 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * config/tc-m68k.h (TC_FORCE_RELOCATION): New macro. Force vtable
+ relocs.
+ * config/tc-m68k.c (md_apply_fix_2): Do nothing for vtable relocs.
+
+Tue Sep 15 08:51:07 1998 Catherine Moore <clm@cygnus.com>
+
+ * config/obj-elf.c (obj_elf_vtable_inherit): Handle arm
+ assembler syntax.
+ (obj_elf_vtable_entry): Likewise.
+ * config/tc-arm.h: Define TC_FORCE_RELOCATION for OBJ_ELF.
+ * config/tc-arm.c (md_apply_fix3): Handle VTABLE relocations.
+ (tc_gen_reloc): Likewise.
+ (arm_fix_adjustable): Likewise.
+ (elf32_arm_force_relocation): New.
+ (armelf_frob_symbol): Remove coff-style symbol support.
+
+Wed Sep 9 11:27:16 1998 Richard Henderson <rth@cygnus.com>
+
+ * config/tc-i386.c (i386_operand): Fix typo in last patch.
+
+Tue Sep 8 18:10:01 1998 Catherine Moore <clm@cygnus.com>
+
+ * config/tc-arm.c (arm_adjust_symtab): Move #ifdef
+ OBJ_COFF so that routine is defined for a.out format.
+
+Tue Sep 8 15:56:19 1998 Richard Henderson <rth@cygnus.com>
+
+ * config/tc-i386.c (i386_operand): Detect non-segment registers
+ used as segment prefixes.
+
+Sat Sep 5 19:00:38 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * ehopt.c (check_eh_frame): Check the size of the FDE, and don't
+ optimize across FDE boundaries.
+
+ * config/obj-coff.c (obj_coff_section): Preserve any link once
+ flags when setting the section flags.
+
+Fri Sep 4 17:07:14 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-arm.h (obj_adjust_symtab): Fixed typo.
+ * config/tc-arm.c (armelf_adjust_symtab): Reformatted.
+
+Fri Sep 4 13:57:43 1998 Jakub Jelinek <jj@sunsite.ms.mff.cuni.cz>
+
+ * config/tc-sparc.c (in_signed_range): Sign extend 32-bit words
+ to the host width.
+
+Wed Sep 2 11:31:14 1998 Richard Henderson <rth@cygnus.com>
+
+ * frags.c (frag_grow): Include the size of the frag struct in the
+ obstack chunk size.
+
+ * subsegs.c (subseg_set_rest): Adjust the seginfo frchain start
+ if the new subseg comes before the old.
+
+Tue Sep 1 15:01:33 1998 Jakub Jelinek <jj@sunsite.ms.mff.cuni.cz>
+
+ * config/tc-sparc.c (sparc_ip): Allow all digits in an instruction
+ to handle edge8 and edge16.
+
+Mon Aug 31 09:51:14 1998 Richard Henderson <rth@cygnus.com>
+
+ * config/obj-elf.c (obj_elf_vtable_inherit): Print error message
+ before we clobber the symbol involved.
+
+Mon Aug 31 10:58:06 1998 Catherine Moore <clm@cygnus.com>
+
+ * config/tc-arm.c: Remove OBJ_ELF definitions for
+ S_GET_STORAGE_CLASS and S_SET_STORAGE_CLASS. Only
+ use arm_adjust_symtab for OBJ_COFF.
+ (armelf_adjust_symtab): New Routine.
+ * config/tc-arm.h: Define obj_adjust_symtab to
+ armelf_adjust_symtab for OBJ_ELF.
+
+Sat Aug 29 22:18:51 1998 Richard Henderson <rth@cygnus.com>
+
+ * configure.in: Make all i386-elf targets use bfd_gas.
+ * config/tc-i386.c (tc_i386_force_relocation): New.
+ (tc_i386_fix_adjustable): Don't fix vtable relocs.
+ (md_apply_fix3): Likewise.
+ (tc_gen_reloc): Handle them.
+ * config/tc-i386.h (TC_FORCE_RELOCATION): Always define, calling
+ tc_i386_force_relocation.
+
+Mon Aug 24 13:40:21 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-arm.c (md_show_usage): Improve formatting of --help output.
+
+Fri Aug 21 18:43:48 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-d30v.c (md_assemble): Copy previous opcode over
+ current opcode after writing the first insturction of a reverse
+ sequential pair.
+
+Fri Aug 21 07:30:35 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * read.h (generate_lineno_debug): Add prototype.
+ * read.c (generate_lineno_debug): Make non-static.
+
+Thu Aug 20 23:17:04 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * config/tc-i386.c (md_assemble): Only warn for address/data size
+ prefixes.
+
+Thu Aug 20 14:45:08 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-arm.c (arm_fix_adjustable): Do not adjust relocations
+ against Thumb function names, as the linker needs this information.
+
+1998-08-20 Vladimir N. Makarov <vmakarov@cygnus.com>
+
+ * expr.c (operand): Check also that there is no advance in operand
+ after atof_generic in order to decide "is it label 0f or floating
+ point number?".
+
+Wed Aug 19 09:30:16 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-m32r.c: Replace double dash prefix to M32R specific
+ command line options with a single dash.
+ * doc/c-m32r.texi: Replace double dash prefix with a single dash.
+
+Tue Aug 18 11:59:43 1998 Catherine Moore <clm@cygnus.com>
+
+ * tc-arm.h: Define obj_fix_adjustable for OBJ_ELF.
+ * tc-arm.c (arm_fix_adjustable): New routine.
+
+1998-08-13 Vladimir N. Makarov <vmakarov@cygnus.com>
+
+ * read.c (s_align, s_comm, s_mri_common, s_fail, s_globl, s_space,
+ s_float_space, s_struct, cons_worker): Move ignore_rest_of_line or
+ demand_empty_rest_of_line before mri_comment_end.
+ (equals): Check garbage after expression before
+ mri_comment_end in MRI mode.
+
+Thu Aug 13 15:08:42 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (macro): Correct M_SGE_I/M_SGEUI_I case for a
+ small immediate constant to use the constant itself rather than
+ always using 1.
+
+Wed Aug 12 18:47:38 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-hppa.c (pa_enter): Call as_bad rather than abort.
+ (pa_leave): Likewise.
+
+Wed Aug 12 13:25:03 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * config/tc-i386.c (md_assemble): Emit a warning for stand-alone
+ prefixes.
+ (i386_operand): Fix an error message.
+
+Tue Aug 11 14:44:32 1998 Nick Clifton <nickc@cygnus.com>
+
+ * doc/c-arm.texi (ARM Directives): Document .req directive.
+
+ * config/tc-arm.c (reg_required_here): Display erroneous string if
+ the register name could not be decoded.
+ Do not set inst.instruction if the sift is -1.
+
+Mon Aug 10 15:39:56 1998 Richard Henderson <rth@cygnus.com>
+
+ * config/tc-alpha.c (tc_gen_reloc): Bias WEAK symbols just as
+ we do for EXTERN.
+
+Mon Aug 10 15:06:18 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-d30v.c (d30v_align): Always perform alignment request,
+ even if it is belived to be unnecessary.
+
+Mon Aug 10 17:48:09 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ config/tc-i386.c (i386_operand): Size immediate constants by
+ suffix (erroneously removed as part of July 7 change).
+
+Sun Aug 9 20:45:32 1998 Catherine Moore <clm@cygnus.com>
+
+ * config/obj-elf.h: Check for redefinition of obj_frob_symbol.
+ * config/tc-arm.c: Define S_GET_STORAGE_CLASS and S_SET_STORAGE_CLASS.
+ (armelf_frob_symbol): New Routine.
+ * config/tc-arm.h: Define obj_frob_symbol if OBJ_ELF.
+
+Sat Aug 8 15:21:28 1998 Richard Henderson <rth@cygnus.com>
+
+ * config/tc-alpha.c (alpha_fix_adjustable): Don't adjust weak syms.
+
+Wed Aug 5 15:54:14 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-arm.c (md_begin): Set BFD private flags depending upon
+ command line switches passed to assembler.
+
+Mon Aug 3 14:02:52 1998 Doug Evans <devans@seba.cygnus.com>
+
+ * cgen.h (GAS_CGEN_MAX_FIXUPS): GAS_ prepended, all uses updated.
+ (gas_cgen_opcode_desc): Declare.
+ (gas_cgen_parse_operand): Declare.
+ (*): Prepend gas_ to gas specific fns to denote them as such.
+ All uses updated.
+ * cgen.c (gas_cgen_opcode_desc): New global
+ (gas_cgen_init_parse): Renamed from cgen_asm_init_parse.
+ (queue_fixup): Renamed from cgen_queue_fixup.
+ (*): Prepend gas_ to gas specific fns to denote them as such.
+ All uses updated.
+ (gas_cgen_md_apply_fix3): Update call to insert_operand.
+ (gas_cgen_finish_insn): Renamed from cgen_asm_finish_insn.
+ * config/tc-m32r.c (md_begin): Remove use of CGEN_SYM.
+ Open opcode table and initialize it.
+ (make_parallel): Use gas_cgen_opcode_desc.
+ (assemble_parallel_insn): Ditto. Remove use of CGEN_SYM.
+ (md_assemble): Ditto.
+
+Sat Aug 1 19:27:30 1998 Richard Henderson <rth@cygnus.com>
+
+ * as.h (debug_info_type): Add entries for unspecified and dwarf*.
+ * ecoff.c (ecoff_generate_asm_lineno): Take no arguments; call
+ as_where ourselves. Provide a stub for !ECOFF_DEBUGGING.
+ * ecoff.h: Move ECOFF_DEBUGGING protection inside GAS_ECOFF_H.
+ Move ecoff_generate_asm_lineno outside ECOFF_DEBUGGING protection.
+ * read.c (generate_lineno_debug): Tidy ECOFF bits. Use
+ DEBUG_UNSPECIFIED rather than DEBUG_NONE for initial test.
+ * config/obj-elf.h (ECOFF_DEBUGGING) [TC_ALPHA]: Define to a variable.
+ (SEPARATE_STAB_SECTIONS): Conditionalize on value of ECOFF_DEBUGGING.
+ (INIT_STAB_SECTION): Likewise.
+ (OBJ_PROCESS_STAB): Likewise.
+
+ * config/tc-alpha.c (md_longopts): New options -mdebug/-no-mdebug.
+ (md_parse_option): Watch for them.
+ (alpha_cur_ent_sym, alpha_flag_mdebug): New variables.
+ (md_begin): Kill neverdef code.
+ (s_alpha_ent, s_alpha_end, s_alpha_mask, s_alpha_frame): New.
+ (s_alpha_prologue): Watch alpha_cur_ent_sym.
+ (s_alpha_coff_wrapper): New.
+ (md_pseudo_table): Trap all ECOFF pseudos.
+
+Fri Jul 31 16:45:54 1998 Ron Unrau <runrau@cygnus.com>
+
+ Start of changes to remove mdebug section from mips*-elf
+ Based on MIPS_STAB_ELF definition
+ * acconfig.h: undef if not configured
+ * config.in: undef if not configured
+ * config/mips-elf.h: only set ECOFF debugging if not stabs-in-elf
+ * config/tc-mips.c (s_ent): set BSF_FUNCTION
+ * stabs.c (s_stab_generic): flush frag
+
+Fri Jul 31 16:14:45 1998 Catherine Moore <clm@cygnus.com>
+
+ * configure.in: (arm-*-elf): Handle.
+ (thumb-*-elf): Handle.
+ * configure: Regenerate.
+ * read.c (stringer): Fix typo in comment.
+ * write.c (fixup_segment): Don't add symbol value to addend if
+ TC_ARM and OBJ_ELF.
+ * config/tc-arm.c (md_section_align): Don't align dwarf debug
+ sections.
+ (tc_gen_reloc): Always set the reloc addend to fixp->fx_offset
+ for OBJ_ELF.
+
+Thu Jul 30 21:38:43 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * config/tc-d30v.c ({cur,prev}_left_kills_right_p): New variables.
+ (write_2_short): Emit warning if new flag is set.
+ (do_assemble): Set flags if left instruction is one of special
+ "right-instruction-killer" type.
+
+Tue Jun 28 18:12:28 1998 Stan Cox <scox@cygnus.com>
+
+ * config/tc-sparc.c (md_number_to_chars, cons_fix_new_sparc):
+ Always output words in debug_info section as big endian.
+ (sparc_target_format): Choose correct bfd target.
+ (md_apply_fix3): Rename BFD_RELOC_SPARC_32LE to BFD_RELOC_SPARC_REV32.
+
+Tue Jul 28 11:01:21 1998 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10300.c (md_assemble): Fix "errmsg" initialization
+ to work with internationalization code. Issue an error when two
+ operands match that are not allowed to match.
+
+Mon Jul 27 16:25:58 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * configure.in (install_tooldir): Allow target to specify whether
+ it wants to be installed in $(tooldir)/bin.
+ * configure: Regenerate.
+ * Makefile.am (install-exec-local): Set install-exec-tooldir
+ dependency via configure.
+ * Makefile.in: Regenerate.
+
+Fri Jul 24 19:58:59 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * Makefile.am (install-exec-local): Split into two ...
+ (install-exec-bindir,install-exec-tooldir): New rules.
+ * Makefile.in: Regenerate.
+
+Fri Jul 24 16:31:49 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.am (install-exec-local): Don't remove the file before
+ checking whether $(bindir) == $(tooldir)/bin. From Maciej
+ W. Rozycki <macro@ds2.pg.gda.pl>.
+ * Makefile.in: Rebuild.
+
+Fri Jul 24 09:13:46 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * cgen.c: Include libiberty.h.
+ (cgen_md_apply_fix3): Update call to md_cgen_lookup_reloc.
+ (cgen_tc_gen_reloc): Use xmalloc, not bfd_alloc.
+ * cgen.h (cgen_md_apply_fix3,cgen_tc_gen_reloc): Declare.
+ (md_cgen_lookup_reloc)): Declare.
+ (md_cgen_record_fixup_exp): Declare.
+ * config/tc-m32r.h (md_pcrel_from_section): Declare.
+ (m32r_relax_frag): Declare.
+ (cgen_md_apply_fix3): Decls moved to cgen.h.
+ (cgen_record_fixup_exp,cgen_tc_gen_reloc): Ditto.
+ (m32r_cgen_record_fixup_exp): Delete decl.
+ * config/tc-m32r.c (m32r_cpu_desc): #if 0 out.
+ (assemble_nop): Delete.
+ (expand_debug_syms): Delete unused `exp'.
+ (md_cgen_lookup_reloc): Renamed from CGEN_SYM (lookup_reloc).
+ Add default case for -Wall.
+ (m32r_cgen_record_fixup_exp): Add default case for -Wall.
+ (md_atof): Delete unused wordP.
+
+Thu Jul 23 13:19:50 1998 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10300.c (md_assemble): Make sure "errmsg" has a non-NULL
+ value.
+
+Wed Jul 22 14:36:56 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * doc/as.texinfo: Add documentation for .end, .exitm, .fail,
+ .ifc, .ifeqs, .ifge, .ifgt, .ifle, .iflt, .ifnc, .ifne, .ifnes,
+ .print, .purgem, and .struct. Remove documentation for
+ .app-file.
+
+Tue Jul 21 16:50:52 1998 Doug Evans <devans@seba.cygnus.com>
+
+ * cgen.c (cgen_md_apply_fix3): set_operand renamed to set_vma_operand.
+ Update call to insert_operand.
+
+Fri Jul 17 11:42:20 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-m32r.c (ms_show_usage): Formatting changes.
+
+Wed Jul 15 15:38:28 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-i386.c (md_assemble): Don't get confused by trailing
+ whitespace after a prefix operator.
+
+Tue Jul 14 15:32:56 1998 Richard Henderson <rth@cygnus.com>
+
+ * configure.in (i386-*-beos{pe,elf,}*): Recognize.
+
+Tue Jul 14 12:33:44 1998 Chris Torek <torek@bsdi.com>
+
+ * config/tc-sparc.c (log2): New static function.
+ (s_reserve): Use log2 to convert alignment before calling
+ record_alignment.
+ (s_common): Use log2 to convert alignment before calling
+ record_alignment and frag_align.
+ (sparc_cons_align): Use log2.
+
+Tue Jul 14 11:58:40 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sparc.c (s_reserve): Set symbol size if OBJ_ELF.
+ (s_common): Likewise.
+
+ * config/tc-sparc.c (sparc_handle_align): Reindent a bit. Correct
+ initialization of waddr.
+ (sparc_elf_final_processing): Add default case to switch.
+
+Tue Jul 14 11:00:16 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * doc/c-i386.texi: Fix a typo. Use the term 80-bit real rather
+ than temporary real.
+
+Mon Jul 13 13:55:42 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * write.c (subsegs_finish): Don't align the segments if there were
+ any errors.
+
+ * config/obj-coff.c (c_symbol_merge): Correct number of bytes when
+ copying aux information.
+
+ * expr.c (make_expr_symbol): Catch attempts to turn an O_big
+ expression into a symbol.
+
+Mon Jul 13 13:29:04 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * config/tc-i386.c (mode_from_disp_size): Change arg and return
+ type to unsigned int.
+ (md_assemble): Change type used to store offsets from unsigned
+ long to long.
+ (i386_operand): Switch error check to only call RESTORE_END_STRING
+ once after parse_register.
+
+Fri Jul 10 16:00:04 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c (md_show_usage): Changed format to match that
+ of gcc, ld, etc.
+
+ * as.c (show_usage): Changed format to match that of gcc, ld, etc.
+
+Thu Jul 9 12:09:57 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * config/tc-m68k.c (tc_m68k_fix_adjustable): Don't adjust vtable
+ relocs.
+ (md_apply_fix_2): Force the symbol of the vtable reloc to be
+ weak.
+
+Thu Jul 9 11:31:54 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * doc/Makefile.am (MAINTAINERCLEANFILES): Define.
+ * doc/Makefile.in: Rebuild.
+
+Wed Jul 8 12:18:56 1998 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mips.c (mips_ip, case 'i' and 'j'): Mask off high bits
+ for %lo expressions.
+ (mips_ip, case 'u'): Move range check after code to mask
+ off bits in %hi/%lo expressions. Mask off high bits for
+ %lo expressions.
+
+Tue Jul 7 17:57:38 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * doc/Makefile.am (gasver.texi): New target.
+ (as.info, as.dvi): Depends upon gasver.texi.
+ * doc/as.texinfo: Include gasver.texi. Mention version number on
+ title page and in top node.
+ * doc/Makefile.in: Rebuild.
+
+Tue Jul 7 11:42:16 1998 Richard Henderson <rth@cygnus.com>
+
+ * listing.c (listing_listing): For EDICT_LIST, skip all lines up to
+ but not including the line containing the edict.
+ * listing.h (LISTING_EOF): New.
+ * input-scrub.c (input_scrub_next_buffer): Call it.
+
+Tue Jul 7 13:00:37 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * config/tc-i386.c (i386_operand): Don't set the size of an
+ immediate address based solely on the suffix and the mode.
+
+ * config/tc-i386.c (md_assemble): Add assertion to make sure
+ overlap2 does not set Imm.
+
+ * config/tc-i386.c (space_chars): Remove. The scrubber converts
+ sequences of whitespace to a single space.
+ (is_space_chars): Just compare with space.
+ (md_begin): Don't initialize space_chars.
+ (md_assemble): Just skip a single whitespace character.
+ (i386_operand): Rewrite base-index parsing to use new
+ parse_register, and to skip white space. Skip white space in a
+ number of other places too. Don't give error message if
+ parse_register fails.
+ (parse_register): Change reg_string parameter to be non-const.
+ Add end_op parameter. Skip white space after the `%', and return
+ end of register string. Give error message here rather than
+ caller.
+
+Fri Jul 3 15:34:34 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ Based on patch from Matt Semersky <matts@scd.hp.com>:
+ * expr.c (op_encoding): Make const.
+ (expr_set_precedence): New function.
+ (expr_begin): Don't set operator rankings, just call
+ expr_set_precedence.
+ * expr.h (expr_set_precedence): Declare.
+ * read.c (s_mri): Call expr_set_precedence.
+
+Thu Jul 2 16:24:58 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * doc/as.texinfo (Statements): Remove paragraph discussing
+ continuing lines with a backslash. This hasn't worked for years,
+ if it ever did.
+
+Thu Jul 2 14:06:22 1998 Klaus Kaempf <kkaempf@rmi.de>
+
+ * obj-vms.c: Add C++ support with ctors/dtors sections. Add weak
+ symbol definitions.
+ (Ctors_Symbols, Dtors_Symbols): New symbol chains.
+ (ps_CTORS, ps_DTORS): New section types.
+ (vms_fixup_xtors_section): New function
+ (Ctors_Psect, Dtors_Psect): Define.
+ (IS_GXX_XTOR): Define
+ (global_symbol_directory): Change check of gxx_bug_fixed to 0.
+ Filter static constructors/destructors and add to
+ Ctors_Symbols/Dtors_Symbols chain.
+ (vms_write_object_file): Write Ctors_Symbols/Dtors_Symbols to
+ appropriate section.
+
+ * tc-alpha.h (TARGET_FORMAT): Rename "evax-alpha" to "vms-alpha".
+ * makefile.vms: Merge vax/vms support.
+
+Wed Jul 1 20:06:20 1998 Richard Henderson <rth@cygnus.com>
+
+ * config/obj-elf.c (obj_elf_vtable_inherit, obj_elf_vtable_entry): New.
+ (elf_pseudo_table): Add them.
+ * config/tc-mips.c (mips_force_relocation): Force vtable relocs.
+ (md_apply_fix): Accept them.
+ (mips_fix_adjustable): Don't adjust them.
+ (tc_gen_reloc): Mung BFD_RELOC_VTABLE_ENTRY for Rel.
+ * config/tc-ppc.c (md_apply_fix3): Accept vtable relocs.
+ * config/tc-ppc.h (TC_FORCE_RELOCATION_SECTION): Force vtable relocs.
+ (tc_fix_adjustable): Don't adjust them.
+
+Wed Jul 1 16:35:32 1998 Doug Evans <devans@seba.cygnus.com>
+
+ * Makefile.am (CGEN_CPU_PREFIX): New variable.
+ (cgen.o): Use it.
+ * Makefile.in: Regenerate.
+ * configure.in: AC_SUBST cgen_cpu_prefix.
+ * configure: Regenerate.
+
+Wed Jul 1 21:38:56 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * config/tc-sh (COND_JUMP_DELAY, COND12_DELAY_LENGTH): Define.
+ Changed all users of COND12_DELAY.
+
+Fri Jun 26 11:21:11 1998 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10300.c (set_arch_mach): New function.
+ (md_pseudo_table): Add pseudo-ops to set the current machine type.
+ (md_begin): Default to mn10300 mode.
+ (md_assemble): Only accept instructions for the core mn10300
+ chip and the active machine type.
+
+Wed Jun 24 19:06:04 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * subsegs.h (segment_info_type): Give the struct a name.
+ * config/tc-h8300.h (tc_reloc_mangle): Add prototype.
+ * config/tc-h8500.h (tc_reloc_mangle): Declare.
+ * config/tc-sh.h (sh_coff_reloc_mangle): Add prototype.
+ * config/tc-w65.h (tc_reloc_mangle): Declare.
+ * config/tc-z8k.h (tc_reloc_mangle): Declare.
+
+Wed Jun 24 13:45:00 1998 Catherine Moore <clm@cygnus.com>
+
+ * config/tc-v850.c (v850_comm): Restore old section
+ after common processing.
+
+Wed Jun 24 11:50:54 1998 Klaus Kaempf <kkaempf@progis.de>
+
+ * config/obj-vms.c (Create_VMS_Object_File): Force binary file.
+
+Tue Jun 23 17:47:31 1998 Jim Wilson <wilson@cygnus.com>
+
+ * config/tc-h8300.c (do_a_fix_imm, build_bytes): Replace cast to
+ char with code that explicitly sign-extends.
+
+Tue Jun 23 13:54:57 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c (md_begin): Restore text section as the current
+ section after creating call table sections.
+ * config/obj-coff.h (SYM_AUXINFO): New macro to conceal ugly
+ code.
+
+ * config/obj-coff.c (c_symbol_merge): Replace complex expresion
+ with call to macro SYM_AUXINFO.
+
+Tue Jun 23 15:09:27 1998 Mike Stump <mrs@wrs.com>
+
+ * Makefile.am (install-exec-local): Don't let EXEEXT interfere
+ with the program transform name.
+ * Makefile.in: Rebuild.
+
+Mon Jun 22 19:52:42 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.c (c_symbol_merge): Fix copying of auxiliary
+ information.
+
+Mon Jun 22 15:18:58 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-i386.c (i386_operand): Be prepared for a space between
+ the open parenthesis and the start of the register operand,
+ because of the June 16 change.
+
+Sun Jun 21 21:27:03 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sh.c (md_apply_fix): Handle weak symbols correctly if
+ BFD_ASSEMBLER.
+
+Sun Jun 21 12:26:36 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-d30v.c (d30v_align): Always perform alignment request,
+ even if it is belived to be unnecessary.
+
+Fri Jun 19 13:57:06 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * write.c (adjust_reloc_syms): Never adjust relocs against weak
+ symbols.
+ * config/tc-mips.c (md_apply_fix): Adjust accordingly.
+
+Fri Jun 19 09:50:17 1998 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10300.c (mn10300_insert_operand): Do not hardcode the
+ shift amount for a repeated operand. The shift amount for the
+ repeated copy comes from the size of the operand.
+
+Fri Jun 19 00:44:19 1998 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-h8300.c (get_operand): Fix typos in ldm/stm support.
+
+Wed Jun 17 13:07:05 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (md_show_usage): Fix -mipsN usage.
+
+Tue Jun 16 13:06:21 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * app.c (do_scrub_begin): If tc_symbol_chars is defined, treat all
+ characters in it as LEX_IS_SYMBOL_COMPONENT.
+ * config/tc-i386.h (tc_symbol_chars): Define.
+ (extra_symbol_chars): Declare.
+ * config/tc-i386.c (extra_symbol_chars): Define.
+ (comment_chars): Don't use '/' as comment start if TE_LINUX.
+ (line_comment_chars): Set to '/' if TE_LINUX.
+ * doc/c-i386.texi (i386-prefixes): Update.
+ * doc/internals.texi (CPU backend): Document tc_symbol_chars.
+
+Fri Jun 12 13:36:54 1998 Tom Tromey <tromey@cygnus.com>
+
+ * po/Make-in (all-yes): If maintainer mode, depend on .pot file.
+ ($(PACKAGE).pot): Unconditionally depend on POTFILES.
+
+1998-06-12 Vladimir N. Makarov <vmakarov@cygnus.com>
+
+ * config/tc-d10v.c (md_apply_fix3): Checking displacement
+ constraint in instructions REP & REPI.
+
+Thu Jun 11 08:56:46 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-d30v.c (md_apply_fix3): Catch BFD_RELOC_8,
+ BFD_RELOC_16, BFD_RELOC_64 and issue appropriate error messages.
+
+ (check_range): If the operand is shifted, then shift the number
+ before checking its range.
+
+ * write.c (adjust_reloc_syms): Add more checks for NULL pointers.
+
+ * config/tc-v850.c (v850_comm): Set SEC_COMMON bit on special
+ common sections.
+
+Wed Jun 10 17:26:35 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c (v850_comm): Create special sections as needed.
+
+1998-06-10 Vladimir N. Makarov <vmakarov@cygnus.com>
+
+ * config/tc-d10v.c (write_2_short): Addition of swapping
+ instructions for sequential and reverse sequential order when
+ given order is not possible.
+
+Tue Jun 9 13:52:53 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.am: Rebuild dependencies.
+ (DEP_INCLUDES): Fix reference to intl build directory.
+ * Makefile.in: Rebuild.
+
+Tue Jun 9 12:20:05 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * doc/c-i386.texi: Update 16 bit documentation.
+
+ * config/tc-i386.h: Change Data16 to Size16, Data32 to Size32,
+ IgnoreDataSize to IgnoreSize as they are used for address size as
+ well as data size.
+ * config/tc-i386.c: Likewise. Add code to reject addr32/data32 in
+ 32-bit mode, similarly addr16/data16 and variants.
+
+Mon Jun 8 18:32:01 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-d30v.c (md_assemble): Fix handling of reverse
+ sequential word multiply instructions.
+
+ (do_assemble): Add extra command line argument, to allow mul32
+ attribute to be preserved across parallel insns.
+ (md_assemble): Insert NOPs between explicitly parallel insns which
+ contain an 32 bit multiply and a 16 multiply.
+
+Mon Jun 8 12:20:30 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * config/tc-i386.c: REPNE renamed to REPNE_PREFIX_OPCODE, and
+ likewise for REPE.
+
+ * config/tc-i386.c (reloc): Add braces.
+
+ * config/tc-i386.c (struct _i386_insn): Rename bi to sib to be
+ consistent with Intel naming.
+ * config/tc-i386.h (base_index_byte): Rename to sib_byte. Don't
+ use bitfields in sib_byte.
+ (modrm_byte): Don't use bitfields here either.
+
+ * config/tc-i386.c (current_templates): Add const.
+ (parse_register): Add const to return, param, and char *s.
+ (i386_operand): Add const to reg_entry *r.
+ * config/tc-i386.h (templates): Add const to start, end.
+
+ Inspired by code for 16 bit gas support from Martynas Kunigelis
+ <martynas@nm3.ktu.lt>:
+ * config/tc-i386.c (md_assemble): Add full support for 16 bit
+ modrm, and Jump, JumpByte, JumpDword, JumpInterSegment insns.
+ (uses_mem_addrmode): Remove.
+ (md_estimate_size_before_relax): Add support here too.
+ (md_relax_table): Rewrite interface to md_relax for 16 bit
+ support.
+ (BYTE, WORD, DWORD, UNKNOWN_SIZE): Remove.
+ (opcode_suffix_to_type): Remove.
+ (CODE16, SMALL, SMALL16, BIG, BIG16): Define.
+ (SIZE_FROM_RELAX_STATE): Modify to suit above.
+ (md_convert_frag): Likewise.
+ (i386_operand): Add support for 16 bit base/index regs,
+ immediates, and displacements. Remove some unnecessary casts, and
+ localise end_of_operand_string, displacement_string_start,
+ displacement_string_end variables. Add GCC_ASM_O_HACK.
+ * config/tc-i386.h (NO_BASE_REGISTER_16): Define.
+
+ * config/tc-i386.c (prefix_hash): Remove.
+ (md_begin): Rewrite without obstacks. Remove prefix hash table
+ handling. Rewrite lexical table handling.
+ (i386_print_statistics): Don't print prefix statistics.
+ (md_assemble): Rewrite instruction parser so that line is not
+ converted to lower case. Don't do a hash_find for prefixes,
+ instead recognise them via opcode modifier.
+ (expecting_operand, paren_not_balanced): Localise variables.
+ * config/tc-i386.h (IsPrefix): Define.
+ (prefix_entry): Remove.
+
+ * config/tc-i386.h (PREFIX_SEPERATOR): Don't define.
+ * config/tc-i386.c (PREFIX_SEPARATOR): Define here instead, using
+ '\\' in case where comment_chars contains '/'.
+
+ * config/tc-i386.c (MATCH): Ensure given operand and template
+ match for JumpAbsolute. Makes e.g. `ljmp table(%ebx)' invalid;
+ you must write `ljmp *table(%ebx)'.
+
+ From H.J. Lu <hjl@gnu.org>:
+ * config/tc-i386.c (BFD_RELOC_16, BFD_RELOC_16_PCREL): Define
+ as 0 ifndef BFD_ASSEMBLER.
+ (md_assemble): Allow immediate operands without suffix or
+ other reg operand to default in size to the current code size.
+
+Mon Jun 8 09:45:00 1998 Catherine Moore <clm@cygnus.com>
+
+ * config/tc-v850.c (md_begin): Restore creation of
+ .call_table_text and .call_table_data sections.
+
+Sat Jun 6 00:02:41 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-d30v.c (md_assemble): Set execution type to unknown
+ after emitting a word of noops.
+
+Fri Jun 5 23:27:04 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * config/tc-i386.c (mode_from_disp_size): Disp16 is mode 2.
+ (i386_operand): Simplify checks for valid base/index combinations.
+ Disallow `in 4(%dx),%al'.
+
+ * config/tc-i386.c (struct _i386_insn): Make regs, base_reg, and
+ index_reg const.
+ (add_prefix): Change parameter from char to int.
+
+ * config/tc-i386.h (Ugh): Define opcode modifier.
+ * config/tc-i386.c (md_assemble): Print warnings for Ugh insns.
+
+ * config/tc-i386.c (md_assemble): Rewrite MATCH and
+ CONSISTENT_REGISTER_MATCH macros to check register types more
+ thoroughly. Check for illegal suffix/operand combinations
+ when matching insns with operands. Handle new `s' suffix, and
+ associated FloatMF opcode modifier for float insns with memory
+ operands.
+ * config/tc-i386.h (FloatMF): Define new opcode modifier.
+ (No_sSuf, No_bSuf, No_wSuf, No_lSuf): Likewise.
+ (SHORT_OPCODE_SUFFIX, LONG_OPCODE_SUFFIX): Define.
+ * config/tc-i386.c: Rename WORD_PREFIX_OPCODE to
+ DATA_PREFIX_OPCODE throughout.
+
+ * config/tc-i386.c (REGISTER_WARNINGS): Define.
+ (md_assemble): Rewrite suffix/register operand checking code to be
+ more thorough. Remove Abs8,16,32. Change occurrences of Mem to
+ AnyMem, the better to grep.
+ (pi): Remove Abs.
+ (i386_operand): Don't set Mem bits in i.types[this_operand] when
+ given a memory operand. Don't set Abs bits either.
+ (type_names): Remove Mem*, Abs*.
+ * config/tc-i386.h (Mem8, Mem16, Mem32, Abs8, Abs16, Abs32): Don't
+ define opcode_modifiers as these cases are handled by Disp8,
+ Disp16, Disp32 and suffix checks.
+ (COMES_IN_BOTH_DIRECTIONS): Remove.
+ (FloatR): Define. It's OK to share the bit with ReverseRegRegmem.
+
+ * config/tc-i386.c (md_assemble): Don't emit operand size prefix
+ if IgnoreDataSize modifier given. Remove ShortformW modifier
+ test. Add test for ShortForm in W base_opcode modification.
+ Merge Seg2ShortForm and Seg3ShortForm code.
+ * config/tc-i386.h (ShortFormW): Remove.
+ (IgnoreDataSize): Define.
+
+Fri Jun 5 10:50:53 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-d30v.c (md_assemble): Store previous segment state
+ with previous instruction.
+
+Wed Jun 3 18:21:56 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * config/tc-i386.c (SCALE1_WHEN_NO_INDEX): Define.
+ (ebp, esp): Remove static variables.
+ (MATCH): Remove test for InOutPortReg.
+ (i386_operand): Properly handle InOutPortReg here instead.
+ Disallows `inb (%dx,2)', `inb %es:(%dx)' and `mov (%dx),%ax'
+ (md_assemble): Simplify and correct modrm and sib generation.
+ (i386_operand): Add warning for scale without index.
+ Rewrite checks for valid base/index combinations.
+
+ * config/tc-i386.c (END_STRING_AND_SAVE): Protect arguments of
+ macros and enclose in do while(0).
+ (RESTORE_END_STRING): Likewise.
+ (md_assemble): Add one to printed operand number so we start
+ from 1 not 0. Add some more gettext invocations.
+ (i386_operand): Fix `%%s' -> `%%%s'. Inc printed operand
+ number here too.
+
+ * config/tc-i386.h (WAIT_PREFIX, LOCKREP_PREFIX, ADDR_PREFIX,
+ DATA_PREFIX, SEG_PREFIX): Define.
+ * config/tc-i386.c (struct _i386_insn): Remove wait_prefix field.
+ (check_prefix): Remove function.
+ (add_prefix): New function. Add prefix to i.prefix as well as
+ doing checks.
+ (md_assemble): Changes for add_prefix. Remove hack for wait
+ prefix, instead always output prefixes in fixed order. Test
+ for jcxz/loop when selecting between word & dword operations,
+ and add address size prefix rather than operand size prefix.
+ Remove operand -> address size hack when emitting jcxz/loop.
+ (i386_operand): Remove O_Absent check as it's done in expr.
+
+Wed Jun 3 15:09:10 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Recognize m5200 as a cpu_type of m68k.
+ * aclocal.m4: Rebuild with current libtool.
+ * configure: Rebuild.
+
+Wed Jun 3 14:11:59 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * config/tc-m68k.c (md_estimate_size_before_relax): Add more calls
+ to relaxable_symbol to prevent references to external symbol from
+ being relaxed.
+
+Wed Jun 3 14:10:36 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (relaxable_symbol): If TARGET_OS is "elf", all
+ symbols are relaxable.
+
+Wed Jun 3 09:16:00 1998 Catherine Moore <clm@cygnus.com>
+
+ * config/tc-v850.c (md_begin): Don't create special
+ sections by default.
+
+Tue Jun 2 14:52:56 1998 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mips.c (macro): For div and udiv, close the
+ reorder block as soon as possible.
+
+Tue Jun 2 15:36:13 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ From Matt Semersky <matts@scd.hp.com>:
+ * macro.c (macro_mri_mode): New function.
+ * macro.h (macro_mri_mode): Declare.
+ * read.c (s_mri): Call macro_mri_mode when switching in and out of
+ MRI mode.
+
+Tue Jun 2 13:32:22 1998 Klaus Kaempf <kkaempf@progis.de>
+
+ * config/tc-alpha.c (s_alpha_comm): Allow alignment parameter in
+ OBJ_EVAX case.
+
+ * config/tc-alpha.c (s_alpha_comm): Defer restoring character
+ until after xstrdup in OBJ_EVAX case.
+
+Tue Jun 2 13:11:13 1998 Pat Rankin <rankin@eql.caltech.edu>
+
+ * config/tc-vax.c (md_create_short_jump): Fix off by two bug in
+ offset calculation. Also, use VAX_BRW from vax-inst.h instead
+ of hardcoded magic number.
+ (md_create_long_jump): Use VAX_JMP and VAX_ABSOLUTE_MODE macros.
+
+Tue Jun 2 09:25:34 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * read.c (do_s_func): New function.
+ (s_func): Call it.
+ * read.h (do_s_func): Add prototype.
+
+Mon Jun 1 12:47:30 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * config/tc-m32r.c (m32r_do_align): Only fill code sections with
+ nops if fill pattern not specified.
+
+Mon Jun 1 14:08:35 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ From Andrew Crabtree <andrewc@typhoon.rose.hp.com>:
+ * config/te-go32.h (TE_GO32): Define.
+ * config/tc-i386.h (LOCAL_LABEL): Don't define if TE_GO32.
+
+Sun May 31 15:43:06 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ Implement .func/.endfunc pseudo-ops.
+ * read.h (stabs_generate_asm_func,stabs_generate_asm_endfunc): Declare.
+ (s_func): Declare.
+ * read.c (potable): Add .func,.endfunc.
+ (s_func): New function.
+ * stabs.c (stabs_generate_asm_func,stabs_generate_asm_endfunc): New
+ functions.
+ (in_doc_func_p,current_function_label): New static globals.
+ (stabs_generate_asm_lineno): Emit function relative stabs if in .func.
+
+Fri May 29 18:13:12 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-a29k.h (WORKING_DOT_WORD): Define.
+ * config/tc-alpha.h (WORKING_DOT_WORD): Define.
+ * config/tc-arm.h (WORKING_DOT_WORD): Define.
+ * config/tc-h8300.h (WORKING_DOT_WORD): Define.
+ * config/tc-h8500.h (WORKING_DOT_WORD): Define.
+ * config/tc-hppa.h (WORKING_DOT_WORD): Define.
+ * config/tc-i860.h (WORKING_DOT_WORD): Define.
+ * config/tc-i960.h (WORKING_DOT_WORD): Define.
+ * config/tc-tic30.h (WORKING_DOT_WORD): Define.
+ * config/tc-w65.h (WORKING_DOT_WORD): Define.
+ * config/tc-z8k.h (WORKING_DOT_WORD): Define.
+ * config/tc-a29k.c: Don't define md_short_jump_size,
+ md_long_jump_size, md_create_short_jump or md_create_long_jump.
+ * config/tc-alpha.c: Likewise.
+ * config/tc-alpha.h: Likewise.
+ * config/tc-arm.c: Likewise.
+ * config/tc-h8300.c: Likewise.
+ * config/tc-h8500.c: Likewise.
+ * config/tc-hppa.c: Likewise.
+ * config/tc-i860.c: Likewise.
+ * config/tc-i960.c: Likewise.
+ * config/tc-ppc.c: Likewise.
+ * config/tc-sh.c: Likewise.
+ * config/tc-sparc.h: Likewise.
+ * config/tc-tic30.c: Likewise.
+ * config/tc-w65.c: Likewise.
+ * config/tc-z8k.c: Likewise.
+
+Fri May 29 16:03:26 1998 Pat Rankin <rankin@eql.caltech.edu>
+
+ * config/tc-vax.c (_): Delete this macro used for placeholder
+ values in vax_operand_width_size; it conflicts with the _() macro
+ used for internationalization.
+
+Fri May 29 13:46:07 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * symbols.c (symbol_find_base): Fix case insensitive symbol name
+ code. From Chris Moller <moller@bops.com>.
+
+ Based on patch from Klaus Kaempf <kkaempf@progis.de>:
+ * struc-symbol.h (struct broken_word): Add seg and subseg fields.
+ * read.c (emit_expr): Initialize seg and subseg fields of a new
+ broken word.
+ * write.c (write_object_file): Switch to the appropriate segment
+ and subsegment when processing a broken word.
+
+ * config/tc-m68k.c (mri_assemble): New static function.
+ (build_mri_control_operand): Call mri_assemble rather than
+ md_assemble.
+ (s_mri_else, s_mri_break, s_mri_next, s_mri_for): Likewise.
+ (s_mri_endf, s_mri_endw): Likewise.
+
+Wed May 27 11:16:25 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.c (s_org): Call md_flush_pending_output if it is defined.
+
+ * config/tc-sparc.c (md_show_usage): Add \n\ to new string.
+
+Tue May 26 19:27:52 1998 Stan Cox <scox@equinox.cygnus.com>
+
+ * config/tc-sparc.c (OPTION_LITTLE_ENDIAN_DATA): New.
+ (md_parse_option): Add for same.
+ (sparc_md_end): Set bfd_mach_sparc_sparclite_le.
+ (md_apply_fix3, tc_gen_reloc): Allow BFD_RELOC_SPARC_32LE.
+ (cons_fix_new_sparc): Added to create BFD_RELOC_SPARC_32LE.
+
+ * config/tc-sparc.h (cons_fix_new_sparc): Added.
+
+Thu May 21 15:02:41 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-arm.c (find_real_start): Relax definition of local
+ labels.
+
+Tue May 19 16:59:44 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-d30v.c (d30v_align): Apply address adjustment to all
+ symbols at the given address, not just the last one specified.
+
+Tue May 19 08:25:19 1998 Catherine Moore <clm@cygnus.com>
+
+ * config/tc-sparc.c (sparc_handle_align): Use number_to_chars_bigendian
+ or number_to_chars_littleendian to write data.
+
+Mon May 18 17:09:30 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c (md_assemble): Remove artificially created
+ register name symbols.
+
+Mon May 18 13:47:06 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * write.c (fixup_segment): Change "segment" to "section" in
+ error message.
+
+Mon May 18 16:55:40 1998 Michael Meissner <meissner@cygnus.com>
+
+ * write.c (fixup_segment): Change sym1-sym2 message again.
+
+Mon May 18 09:31:43 1998 Michael Meissner <meissner@cygnus.com>
+
+ * write.c (fixup_segment): Improve error message for sym1-sym2
+ errors when sym1 is in a different segment from sym2.
+
+Wed May 13 10:16:37 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * config/tc-m32r.c (warn_unmatched_high): New static local.
+ (OPTION_WARN_PARALLEL): Rename from OPTION_WARN.
+ (OPTION_NO_WARN_PARALLEL): Rename from OPTION_NO_WARN.
+ (md_longopts): Recognize --{no-,}warn-unmatched-high.
+ (md_parse_option): Likewise.
+ (md_show_usage): Likewise.
+ (m32r_frob_file): Likewise.
+
+ * read.c (generate_file_debug,generate_lineno_debug): New functions.
+ (read_a_source_file): Call them.
+ * read.h (stabs_generate_asm_file): Declare.
+ * stabs.c (stabs_generate_asm_file): New function.
+ (generate_asm_file): New function.
+ (stabs_generate_asm_lineno): Move file name handling into
+ generate_asm_file.
+
+Tue May 12 12:03:44 1998 Richard Henderson <rth@cygnus.com>
+
+ * config/tc-d30v.c (cur_mul32_p, prev_mul32_p): Make static.
+ (d30v_current_align, d30v_current_align_seg): New variables.
+ (d30v_last_label): New variable.
+ (d30v_align, s_d30v_align, s_d30v_text): New functions.
+ (s_d30v_data, s_d30v_section): Likewise.
+ (md_pseudo_table): Call them.
+ (md_begin): Initialize d30v_current_align_seg.
+ (md_assemble): Call d30v_align when needed by known current alignment.
+ (d30v_frob_label, d30v_cons_align): New functions.
+ * config/tc-d30v.h (md_do_align): Remove.
+ (tc_frob_label): Call d30v_frob_label.
+ (md_cons_align): New.
+
+ * config/tc-d30v.c (find_format): Convert complex expressions to
+ expression symbols before processing. Clean up code formatting.
+
+Sun May 10 22:35:02 1998 Jeffrey A Law (law@cygnus.com)
+
+ * po/Make-in (install-info): New target.
+
+Thu May 7 15:49:07 1998 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10200.c (md_assemble): Handle "bra" just like "jmp"
+ instructions.
+ * config/tc-mn10300.c (md_assemble): Likewise.
+
+Thu May 7 11:47:22 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * Makefile.am: Update with `make dep-am'.
+ (HFILES): Add cgen.h.
+ (cgen.o): Depend on cgen.h.
+ * Makefile.in: Regenerate.
+
+ * cgen.c (cgen_md_apply_fix3): Don't pass newline to as_warn_where.
+
+Thu May 7 13:20:56 1998 Anders Blomdell <anders.blomdell@control.lth.se>
+
+ * gasp.c (grab_label): Permit a label to be a preprocessor
+ variable by permitting a label to start with a backslash.
+
+Thu May 7 12:50:33 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * config/tc-mips.c (validate_mips_insn): Removed hack
+ for previously inaccessible bitfields in some INSN_TRAP
+ instructions.
+
+Thu May 7 11:13:00 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * config/tc-d30v.c (do_assemble): Abort with error message
+ if opcode operands do not match.
+
+Thu May 7 09:36:06 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * config/tc-mips.c (macro_build, validate_mips_insn): Implement
+ 'q' operand format for 20-bit "break"/"sdbbp" instructions.
+ (mips_ip): Truncate overflowed "break" 'c' operand. Implement
+ similar new 'q' operand.
+
+Thu May 7 07:47:14 1998 Michael Meissner <meissner@cygnus.com>
+
+ * cgen.c (cgen_asm_finish_insn): Fix typo.
+
+Thu May 7 02:19:14 1998 Doug Evans <devans@charmed.cygnus.com>
+
+ * cgen.h: New file.
+ * cgen.c: Include it.
+ (MAX_FIXUPS): Renamed to CGEN_MAX_FIXUPS.
+ (cgen_asm_finish_insn): Result is now void. New arg `result'.
+ All callers updated.
+ * config/tc-m32r.c: Include cgen.h.
+ (m23r_insn): New members num_fixups,fixups.
+
+Wed May 6 16:29:19 1998 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-hppa.c (md_apply_fix): Slightly rework some code
+ to avoid compiler warning.
+
+Wed May 6 15:26:34 1998 Klaus Kaempf <kkaempf@progis.de>
+
+ * makefile.vms: Run dec c with /nodebug. Pass CC value when
+ calling make.
+
+ * makefile.vms (OBJS): Add ehopt.obj
+
+Wed May 6 15:11:12 1998 Klaus Kaempf <kkaempf@progis.de>
+
+ * doc/c-vax.texi: Correct and extend vax/vms documentation.
+
+Wed May 6 11:51:51 1998 Richard Henderson <rth@cygnus.com>
+
+ * config/tc-d30v.c (do_assemble): Accept a new parameter requesting
+ a short format insn.
+ (md_assemble): Set it for explicitly packed insns.
+
+Tue May 5 13:23:13 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/obj-coff.c (c_symbol_merge): Do not take address of
+ native fields when performing the memcpy.
+
+Tue May 5 13:10:41 1998 Gavin Koch <gavin@cygnus.com>
+
+ * config/tc-mips.c (macro,macro2): Implement
+ M_DMULO_I, M_MULO_I, M_DMULOU_I, and M_MULOU_I.
+
+Mon May 4 17:49:14 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * config/tc-m68k.h (TC_RELOC_RTSYM_LOC_FIXUP): Changed to keep
+ relocations against globally visible symbols.
+ * config/tc-m68k.c (relaxable_symbol): New macro.
+ (m68k_ip, md_estimate_size_before_relax): Use it.
+ (tc_m68k_fix_adjustable): Also handle weak symbols.
+
+Mon May 4 16:12:23 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-i386.h (TC_RELOC_RTSYM_LOC_FIXUP): Keep relocs for all
+ references to externally visible symbols.
+ * config/tc-i386.c (md_apply_fix3): When OBJ_ELF, don't add the
+ values in twice for a PC relative reloc if the symbol is
+ externally defined.
+
+ * config/tc-sparc.h (tc_fix_adjustable) [OBJ_AOUT]: When PIC,
+ don't adjust a PC relative reloc against an externally visible
+ symbol.
+ * config/tc-sparc.c (md_apply_fix3): When generating a.out PIC,
+ for a PC relative fixup against an externally visible defined
+ symbol, arrange to store object file and addend values as though
+ the symbol were not defined.
+ (tc_gen_reloc): Likewise.
+
+Thu Apr 30 13:09:39 1998 Fred Fish <fnf@ninemoons.com>
+
+ * read.c (sizeof_leb128): Referenced externally by write.c so
+ don't inline.
+
+Wed Apr 29 15:45:57 1998 Michael Meissner <meissner@cygnus.com>
+
+ * config/tc-m32r.c ({,expand_}debug_sym): New functions to record
+ and expand a 'debug' symbol associated with the next instruction
+ that does not cause a short instruction to be filled with a NOP.
+ (md_pseudo_table): Add support for .debugsym.
+ (assemble_parallel_insn): Add calls to expand_debug_sym as
+ appropriate.
+ (md_assemble): Ditto.
+
+Tue Apr 28 19:16:26 1998 Tom Tromey <tromey@cygnus.com>
+
+ * as.c (main): Conditionally call setlocale.
+ * gasp.c (main): Likewise.
+ * asintl.h: Include <locale.h> if HAVE_LOCALE_H.
+ (LC_MESSAGES): Now can be defined even when ENABLE_NLS.
+
+Tue Apr 28 18:33:23 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * config/tc-d30v.c (md_show_usage): Correct gettext typo.
+
+Tue Apr 28 12:16:30 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-hppa.c: Change all calls to bzero to use memset.
+ (pa_ip): Add cast to avoid warning.
+ (tc_gen_reloc, md_apply_fix): Likewise.
+ (pa_find_space_by_number): Likewise.
+ (hppa_force_relocation): Likewise.
+ (pa_block): Change i to unsigned int.
+ * config/obj-som.h (obj_som_copyright): Declare.
+
+Tue Apr 28 11:35:56 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * ecoff.c (ecoff_build_lineno): Do not use dummy first_lineno
+ for line numbers for assembly source.
+
+Mon Apr 27 15:58:46 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Change version number to 2.9.4
+ * configure: Rebuild.
+
+Mon Apr 27 12:07:33 1998 Doug Evans <devans@seba.cygnus.com>
+
+ * cgen.c (cgen_asm_finish_insn): New arg relax_p. All callers updated.
+
+Mon Apr 27 15:16:12 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * ecoff.h: Change symbolS in function declaration to struct
+ symbol.
+
+Sun Apr 26 13:44:22 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sh.c (parse_reg): Add casts to avoid warnings.
+ (md_convert_frag): Fix i18n typo.
+
+Sat Apr 25 20:12:02 1998 Richard Henderson <rth@cygnus.com>
+
+ * ecoff.c (ecoff_get_cur_proc_sym): New function.
+ * ecoff.h: Protoype it.
+ * config/tc-alpha.c [ELF] (s_alpha_prologue): New function.
+ [EVAX] (s_alpha_prologue): Delete.
+ (md_pseudo_table): Update.
+
+Sat Apr 25 14:00:52 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-i960.c (md_assemble): Change bp_error_msg from static
+ array to local pointer.
+ (get_args, parse_expr): Add casts to avoid warnings.
+
+Fri Apr 24 12:47:42 1998 Philippe De Muyter <phdm@macqel.be>
+
+ * read.c (s_set): Cast xmalloc return value to fragS *.
+ * config/tc-m68k.c (m68k_ip): Function made static to match
+ previous forward declaration.
+ (insert_reg, init_regtable, md_convert_frag_1): Likewise.
+
+Fri Apr 24 09:26:46 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c: Add internationalisation macros to error
+ strings.
+
+ * config/tc-m32r.c (can_make_parallel): Add internationalisation
+ macros to error strings.
+
+Thu Apr 23 19:23:23 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-ppc.c (ppc_fix_adjustable): Correct test of whether a
+ reloc is in the TOC csect.
+ (md_apply_fix3): Correct gettext typo.
+
+Thu Apr 23 14:58:31 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-arm.c (find_real_start): Ignore symbols starting with
+ .L - they are local labels and the branches are not really
+ function calls but rather far jumps.
+
+Wed Apr 22 15:57:21 1998 Tom Tromey <tromey@cygnus.com>
+
+ * po/Make-in (MKINSTALLDIRS): Don't look in $(top_srcdir).
+
+Wed Apr 22 14:52:36 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-i386.c (md_assemble): Print operand number rather than
+ using ordinal_names.
+ (i386_operand): Likewise.
+
+Tue Apr 21 22:34:25 1998 Tom Tromey <tromey@scribbles.cygnus.com>
+
+ * Makefile.am (INTLLIBS): Define to work around apparent automake
+ bug.
+ All Makefiles: Regenerated.
+
+ * Many files: Added gettext invocations around user-visible
+ strings.
+ * acconfig.h (ENABLE_NLS, HAVE_CATGETS, HAVE_GETTEXT, HAVE_STPCPY,
+ HAVE_LC_MESSAGES): Define.
+ * dep-in.sed: Added asintl.h.
+ * po/Make-in: New file.
+ * gasp.c (main): Call setlocale, bindtextdomain, and textdomain.
+ Include "asintl.h".
+ * read.c (Z_): Renamed from `_'.
+ * Makefile.am (SUBDIRS): Added po.
+ (POTFILES): new macro.
+ (po/POTFILES.in): New target.
+ ($(OBJS)): Added asintl.h.
+ (HFILES): Likewise.
+ (INCLUDES): Added -DLOCALEDIR, -I$(top_srcdir)/../intl.
+ (as_new_LDADD): Added $(INTLLIBS).
+ (as_new_DEPENDENCIES): Added $(INTLDEPS).
+ (gasp_new_LDADD): Added $(INTLLIBS).
+ (gasp_new_DEPENDENCIES): New macro.
+ * configure, aclocal.m4: Rebuilt.
+ * configure.in: Call CY_GNU_GETTEXT. Generate po/Makefile.in and
+ po/Makefile.
+ (ALL_LINGUAS): Define.
+ * macro.c: Include "asintl.h".
+ * as.c (main): Call setlocale, bindtextdomain, and textdomain.
+ * as.h: Include "asintl.h".
+ * config/tc-i386.c (ordinal_names): Removed.
+ (md_assemble): Changed error text to avoid ordinal_names.
+ (i386_operand): Likewise.
+ (reloc): Added as_bad to avoid i18n problems.
+ (tc_gen_reloc): Likewise.
+ * config/tc-arm.c (bad_args): Now a #define.
+ (bad_pc): Likewise.
+ * config/obj-vms.c (VMS_stab_parse): Changed type of
+ `long_const_msg'.
+ (global_symbol_directory): Unified strings to avoid i18n
+ problems.
+ * config/tc-m68k.c (get_reloc_code): Added some as_bad calls to
+ avoid i18n problems.
+ * config/tc-ns32k.c (reloc): Added as_bad to avoid i18n problems.
+ * config/tc-ppc.c (md_apply_fix3): Added as_bad_where to avoid
+ i18n problems.
+ * config/tc-sh.c (md_convert_frag): Added as_bad to avoid i18n
+ problems.
+ * config/tc-v850.c (md_assemble): Changed C++ comment into C
+ comment.
+ * config/tc-vax.c (md_assemble): Added as_warn to avoid i18n
+ problems.
+ * as.c (print_version_id): Added an fprintf to avoid i18n
+ problems.
+ * cond.c (cond_finish_check): Added as_bad call to avoid i18n
+ problems.
+ * expr.c (expr): Added as_warn call to avoid i18n problems.
+ * messages.c (as_assert): Changed code to avoid i18n problems.
+ (as_abort): Likewise.
+ * read.c (pseudo_set): Added as_bad call to avoid i18n problems.
+ (s_space): Likewise.
+ * po/Make-in, po/POTFILES.in, po/gas.pot: New files.
+
+Tue Apr 21 17:01:22 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * config/tc-i386.c (check_prefix): New static function, split out
+ from md_assemble.
+ (struct _i386_insn): Add wait_prefix field.
+ (md_assemble): Remove wait_prefix local variable. Use
+ check_prefix when adding a prefix.
+
+ * config/tc-i386.c (current_templates): New static variable.
+ (md_assemble): Remove current_templates local variable.
+ (md_assemble, i386_operand): Improve error and warning messages in
+ many places. Add RESTORE_END_STRING in many places before error
+ return. Clarify some comments.
+
+ * config/tc-i386.c (struct _i386_insn): Change seg field to a two
+ element array.
+ (md_assemble): Parse string instruction operands, looking for
+ segment override prefixes. Check for invalid segment prefixes on
+ string instruction.
+ (i386_operand): i.seg[] and max mem_operand changes for string
+ insns.
+ * config/tc-i386.h (EsSeg): Define.
+
+ * config/tc-i386.h (regKludge): Define.
+ (iclrKludge, imulKludge): Don't define.
+ * config/tc-i386.c (md_assemble): Merge imulKludge and iclrKludge
+ code. Move ReverseRegRegmem fudges into Modrm case. Reorder
+ opcode_modifier checks to look for more common cases first. Add
+ default_seg for IsString case.
+
+Tue Apr 21 16:18:12 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Call AM_PROG_LEX rather than AC_PROG_LEX and
+ AC_DECL_YYTEXT.
+ * configure: Rebuild with new automake and libtool.
+ * aclocal.m4, Makefile.in: Likewise.
+
+ * doc/Makefile.am (as.dvi): New target.
+ * doc/Makefile.in: Rebuild.
+
+Sat Apr 18 01:21:04 1998 Stan Cox <scox@cygnus.com>
+
+ * configure.in: Added sparc86x support.
+
+ * configure: Rebuild.
+
+ * config/tc-sparc.c (lookup_arch): Added arch_type to struct
+ sparc_arch.
+ (md_parse_option): Warn if -EL is not supported for this architecture.
+
+ * config/tc-sparc.h (SPARC_BIENDIAN) Always define.
+
+Sat Apr 18 01:19:01 1998 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mips.c (mips_ip): Note when we use get match on
+ the full instruction name.
+
+Wed Apr 15 15:17:27 1998 Richard Henderson <rth@cygnus.com>
+
+ * symbols.c (resolve_symbol_value) [O_symbol]: Also store the symbol
+ back into the expression to handle add/sub simplification correctly.
+
+Wed Apr 15 07:06:04 1998 Catherine Moore <clm@cygnus.com>
+
+ * config/tc-mips.c (hilo_interlocks): Remove 4300.
+
+Mon Apr 13 16:51:04 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-arm.c (do_msr): Support undocumented 'msr cpsr_flg,
+ #<n>' instruction.
+
+Thu Apr 9 10:29:42 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * symbols.c (max_indent_level): New global.
+ (print_symbol_value_1): Use it.
+ * expr.h (expr_build_dot): Declare.
+ * expr.c (expr_build_dot): New function.
+
+Wed Apr 8 16:16:11 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * symbols.c (print_binary): New function.
+ (print_expr_1): Call it.
+
+Mon Apr 6 12:06:39 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * config/tc-m68k.c (m68k_ip, case "#B"): Install the offset of the
+ operand in the opcode.
+
+Fri Apr 3 11:58:19 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * config/tc-i386.h: Reorder operand flags and opcode modifier
+ flags for clarity. Remove unused definitions: Unknown,
+ ImmUnknown, DispUnknown, NoModrm.
+ * config/tc-i386.c (type_names): Add missing Debug type.
+ (md_assemble): Better duplicate prefix checking. Quicker string
+ instruction check via new opcode_modifier flag.
+
+Fri Apr 3 11:44:34 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * doc/as.texinfo (Invoking): Clarify -Wa example.
+
+Fri Apr 3 09:12:23 1998 Gavin Koch <gavin@cetus.cygnus.com>
+
+ * config/tc-mips.c (mips_pseudo_table): Add weakext entry.
+ (s_mips_weakext): Define.
+ * ecoff.c (ecoff_directive_weakext): Don't define if defined(TC_MIPS).
+ * config/obj-ecoff.c (obj_pseudo_table): Don't add weakext if
+ defined(TC_MIPS).
+
+Thu Apr 2 22:42:02 1998 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10200.c (tc_gen_reloc): The difference of two symbols
+ is an error if the value can not be computed at assembly time.
+ * config/tc-mn10300.c (tc_gen-reloc): Likewise.
+
+Thu Apr 2 16:36:47 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * gasp.c (main): Set next field of new include_path structure to
+ NULL. From Avery Pennarun <averyp@gdc.ca>.
+
+ * read.c (s_mri_sect): Call as_bad rather than abort for an
+ unsupported MRI target.
+
+Wed Apr 1 11:08:27 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-arm.c (arm_validate_fix): New function. Determine if
+ the destination of a branch instruction should be altered.
+ (find_real_start): New function: Locate the real, Thumb coded
+ start of a Thumb function.
+ (do_t_branch23): Alter the destination of branches to Thumb
+ functions.
+
+ * config/tc-arm.h: Define TC_VALIDATE_FIX.
+
+Tue Mar 31 13:27:33 1998 Dean M. Deaver <deaver@amt.tay1.dec.com>
+
+ * config/tc-arm.c (decode_shift): Handle addressing mode 2 w/rrx
+ also.
+
+Wed Apr 1 13:13:20 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * doc/as.texinfo: Use @itemx for a secondary item in a table.
+ * doc/c-hppa.texi: Likewise.
+
+Tue Mar 31 17:52:40 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.am: Rebuild dependencies.
+ * Makefile.in: Rebuild.
+
+ * Makefile.am (DEP_INCLUDES): New variable.
+ (.dep1): Change to work when srcdir is not an absolute path.
+ (.tcdep, .objdep, .dep2, dep.sed): Likewise.
+ * Makefile.in: Rebuild.
+
+Mon Mar 30 12:46:48 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-i386.h, config/tc-i386.c: Revert March 24
+ LinearAddress patch.
+
+ * configure.in: Set version to 2.9.1.
+ * configure: Rebuild.
+
+ * Branched binutils 2.9.
+
+Mon Mar 30 11:22:08 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * config/tc-i386.h (FWait): Define.
+ * config/tc-i386.c (md_assemble): Emit fwait prefix before any
+ other prefixes. Check FWait flag in opcode table to see which
+ instructions require an fwait prefix.
+
+Mon Mar 30 10:12:00 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * stabs.c (get_stab_string_offset): Always create a stab string
+ section.
+
+Sat Mar 28 22:28:02 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ Fix some gcc -Wall warnings:
+ * atof-generic.c (atof_generic): Add casts to avoid warnings.
+ * ehopt.c (eh_frame_code_alignment): Likewise.
+ * expr.c (integer_constant, operand): Likewise.
+ * frags.c (frag_align): Likewise.
+ * gasp.c (level_0, change_base, doinstr): Likewise.
+ * hash.c (hash_ask): Likewise.
+ * listing.c (listing_page, calc_hex, print_lines): Likewise.
+ (debugging_pseudo): Likewise.
+ * macro.c (define_macro, check_macro): Likewise.
+ * read.c (read_a_source_file, s_align, s_float_space): Likewise.
+ (ignore_rest_of_line, float_cons): Likewise.
+ * symbols.c (decode_local_label_name): Likewise.
+ * write.c (record_alignment, cvs_frag_to_fill): Likewise.
+ (fixup_segment, number_to_chars_bigendian): Likewise.
+ (number_to_chars_littleendian): Likewise.
+ * config/atof-ieee.c (gen_to_words): Likewise.
+ * config/tc-sparc.c (md_begin, md_assemble): Likewise.
+ (sparc_ip, parse_keyword_arg, s_common): Likewise.
+ * read.c (output_big_sleb128): Initialize locals to avoid
+ warnings.
+ (output_big_uleb128, equals): Likewise.
+ * atof-generic.c (atof_generic): Change number_of_digits_* locals
+ to unsigned int. Change zeros to unsigned int.
+ * cond.c (s_if): Add return to default case.
+ * frags.c (frag_now_fix): Change return type to addressT.
+ * frags.h (frag_now_fix): Update declaration.
+ * listing.c (file_info_struct): Change linenum to unsigned int.
+ (struct list_info_struct): Change hll_line to unsigned int.
+ (print_source): Update format string.
+ * read.c (emit_expr): Change scan to unsigned int, and don't
+ bother to initialize it.
+ * symbols.c (dollar_label_count): Change to unsigned long.
+ * write.c (adjust_reloc_syms): Remove unused label reduce_fixup.
+ * config/tc-sparc.c (sparc_memory_model): Only define if OBJ_ELF.
+ * config/tc-sparc.c (tc_gen_reloc): Add return to default case.
+
+Fri Mar 27 12:46:47 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (m68k_ip): Check legal addressing modes for
+ mcf5200 just as we do for m68000.
+ (m68k_init_after_args): Likewise.
+ (md_estimate_size_before_relax): Likewise.
+
+Fri Mar 27 10:30:01 1998 Catherine Moore <clm@cygnus.com>
+
+ * config/tc-v850.c (md_assemble): Store relocation addend in
+ fixup instead of instruction.
+
+Thu Mar 26 23:07:18 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * config/tc-i386.c (md_assemble): Swap template arguments to
+ CONSISTENT_REGISTER_MATCH macro in reverse direction test.
+ This macro is currently symmetric, so passing them the wrong
+ way didn't cause any problem, but may if the macro is changed
+ in the future.
+ After copying template to i.tm, use i.tm. rather than t-> to
+ access fields, and make t a const*
+ Move i.tm.operand_types[] swap to immediately after the copy.
+
+Wed Mar 25 13:44:18 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * expr.h (expr_build_uconstant): Add prototype.
+ (expr_build_unary,expr_build_binary): Add prototypes.
+ * expr.c (expr_build_uconstant): New function.
+ (expr_build_unary,expr_build_binary): New functions.
+
+Wed Mar 25 13:10:42 1998 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
+
+ * gasp.c (IS*): Cast argument to unsigned char, not unsigned int.
+ * macro.c (macro_expand_body): Increase buffer size.
+ * messages.c (as_warn): Likewise.
+ (as_warn_where, as_bad, as_bad_where): Likewise.
+
+Wed Mar 25 12:59:07 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ Based on patch from H.J. Lu <hjl@gnu.org>:
+ * Makefile.am (DISTSTUFF): New variable.
+ (diststuff): New target.
+ * Makefile.in: Rebuild.
+
+Tue Mar 24 16:51:29 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-m32r.h (md_cleanup, md_elf_section_change_hook): Call
+ m32r_elf_section_change_hook.
+
+ * config/tc-m32r.c (m32r_elf_section_change_hook): New function to
+ emit a nop if a section ends with a 16 bit instruction.
+
+Tue Mar 24 19:48:09 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.c (obj_coff_bss): Compile unconditionally. Call
+ s_lcomm rather than obj_coff_lcomm.
+ (obj_pseudo_table): Compile .bss pseudo-op unconditionally.
+
+Tue Mar 24 18:30:58 1998 H.J. Lu <hjl@gnu.org>
+
+ * config/tc-i386.h (LinearAddress): Define.
+ * config/tc-i386.c (md_assemble): If LinearAddress is set for the
+ instruction, don't use a default segment.
+
+Mon Mar 23 18:53:40 1998 Joel Sherrill <joel@OARcorp.com>
+
+ * configure.in: (sh*-*-rtems*): Switched from ELF to COFF.
+ * configure: Rebuild.
+
+Fri Mar 20 19:15:44 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * aclocal.m4, configure: Rebuild with libtool 1.2.
+
+Thu Mar 19 16:03:12 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-arm.c (md_apply_fix3): fix code to test the range of
+ PC relative branches. Patch courtesy of Jonathan Walton.
+
+
+Wed Mar 18 09:29:51 1998 Nick Clifton <nickc@cygnus.com>
+
+ * configure.in (emulations): Add thumb-pe target.
+
+ * configure (emulations): Add thumb-pe target.
+
+1998-03-17 Ken Raeburn <raeburn@cygnus.com>
+
+ * itbl-lex.l (yywrap): Don't define if already defined as a
+ macro.
+
+Fri Mar 13 16:31:38 1998 Tom Tromey <tromey@cygnus.com>
+
+ * depend.c (quote_string_for_make): New function.
+ (wrap_output): Use it.
+
+Thu Mar 12 18:28:22 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/obj-elf.c (obj_elf_section): Set bss flag in seg_info
+ structure if type is SHT_NOBITS. [Bug fix courtesy of rth]
+
+Sat Feb 28 17:28:55 1998 Richard Henderson <rth@cygnus.com>
+
+ * config/tc-alpha.c (md_shortopts, md_longopts, md_parse_option):
+ Recognize -GN and -relax.
+ (md_begin): Initialize gp size from -G switch.
+ (alpha_force_relocation): Always force if -relax.
+ (alpha_align): Take a new argument that will specify when to
+ emit an R_ALPHA_ALIGN relocation (though we don't do that now).
+ Change all callers. Emit nop alignment padding as nop+unop pair.
+
+Sat Feb 28 17:06:22 1998 Richard Henderson <rth@cygnus.com>
+
+ * config/obj-elf.c [TC_ALPHA]: Include <elf/alpha.h>.
+ * config/tc-alpha.h (ELF_TC_SPECIAL_SECTIONS): New.
+
+Thu Feb 26 15:49:04 1998 Michael Meissner <meissner@cygnus.com>
+
+ * config/tc-d30v.c (write_2_short): Delayed jsr instructions don't
+ require padding to the next long word boundary.
+
+Mon Feb 23 11:29:06 1998 Doug Evans <devans@seba.cygnus.com>
+
+ * cgen.c: #include symcat.h.
+ * config/tc-m32r.c: Likewise.
+
+Mon Feb 23 10:27:40 1998 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mips.c (mips_ip, case 'P'): Make 'P' arguments be
+ absolute expressions instead of '$' prefixed register names.
+
+Sat Feb 21 22:36:52 1998 Richard Henderson <rth@cygnus.com>
+
+ * read.c (s_set): Record file and line info for symbols when -as.
+ (pseudo_set): Don't overwrite that dummy fragment.
+
+Fri Feb 20 15:03:13 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-ppc.c (md_pseudo_table): Add "section".
+ (ppc_named_section): New static function.
+
+Thu Feb 19 22:25:42 1998 Richard Henderson <rth@cygnus.com>
+
+ * tc-ppc.c (ppc_biei): Cache the last symbol we inserted
+ so we don't have to scan the entire list.
+
+Tue Feb 17 17:02:15 1998 Fred Fish <fnf@cygnus.com>
+
+ * config/tc-d30v.c (parallel_ok): For the explicitly parallel
+ case, allow the parallel instructions to modify the same flag
+ bits.
+
+Thu Feb 19 16:08:15 1998 Richard Henderson <rth@cygnus.com>
+
+ * listing.c (list_symbol_table): Categorize symbols by
+ undefined_section rather than sy_frag->line == NULL.
+
+Wed Feb 18 23:39:46 1998 Richard Henderson <rth@cygnus.com>
+
+ * Makefile.am (install-exec-local): Install properly when ln
+ fails or tooldir == prefix.
+
+Tue Feb 17 18:58:51 1998 Doug Evans <devans@seba.cygnus.com>
+
+ * cgen.c (cgen_md_apply_fix3): Delete call to validate_operand.
+ Test result of insert_operand for error.
+
+Fri Feb 13 16:41:42 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.am (AUTOMAKE_OPTIONS): Add cygnus.
+ * configure, Makefile.in, aclocal.m4: Rebuild with automake 1.2e.
+ * doc/Makefile.am (AUTOMAKE_OPTIONS): Define.
+ * doc/Makefile.in: Rebuild.
+
+Fri Feb 13 00:47:44 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (macro_build): Handle operand type 'C'.
+ (macro): Fix handling of M_COP[0-3].
+
+Thu Feb 12 14:06:59 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ Based on patches from Ross Harvey <ross@teraflop.com>:
+ * macro.c (ISSEP): Only treat '<' and '>' as separator characters
+ if macro_alternate or macro_mri.
+ (getstring): Remove support for byte constants between < and >.
+ (get_any_string): '<' only starts a string if macro_alternate or
+ macro_mri.
+ (macro_expand_body): Permit keyword parameters following
+ positional parameters.
+
+ NetBSD patches from Gordon W. Ross <gwr@mc.com>:
+ * configure.in (alpha*-*-netbsd*): New target.
+ * config/te-nbsd.h (LOCAL_LABELS_FB): Define.
+ * configure: Rebuild.
+
+ * as.h (flag_warn_suppress_instructionswap): Move from here...
+ * config/tc-d10v.c (flag_warn_suppress_instructionswap): ...to
+ here, and make static.
+
+ * ehopt.c (eh_frame_code_alignment): Only use seg_info if
+ BFD_ASSEMBLER or MANY_SEGMENTS.
+
+ * as.c (show_usage): Update bug-gnu-utils address.
+ * gasp.c (show_usage): Likewise.
+ * doc/as.texinfo (Bug Reporting): Likewise.
+
+Wed Feb 11 23:26:28 1998 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mips.c (load_address): Don't use mips III or mips IV
+ insns regardless of the size of a pointer if we're in mips I or
+ MIPS II mode.
+ (macro, macro2, s_cprestore, s_cpadd): Likewise.
+
+Thu Feb 12 03:41:00 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+Fix rac to accept only a0:
+ * tc-d10v.c (parallel_ok, find_opcode):
+ Split OPERAND_ACC into OPERAND_ACC0 and OPERAND_ACC1.
+ Introduce OPERAND_GPR.
+
+Wed Feb 11 16:28:13 1998 Richard Henderson <rth@cygnus.com>
+
+ * read.c (s_fill): Handle non-constant repeat counts by creating
+ an rs_space fragment.
+
+Tue Feb 10 18:31:31 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-i386.c (i386_operand): Change error added Jan 2 1998
+ from as_bad to as_warn.
+
+Tue Feb 10 18:04:00 1998 Jim Lemke <jlemke@cygnus.com>
+
+ * as.c: (perform_an_assembly_pass): Use [TEXT|DATA|BSS]_SECTION_NAME
+ * as.h: Define default values of [TEXT|DATA|BSS]_SECTION_NAME
+ * config/obj-elf.c (elf_begin): Use [TEXT|DATA|BSS]_SECTION_NAME
+
+Tue Feb 10 17:58:18 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * ehopt.c (eh_frame_code_alignment): If not BFD_ASSEMBLER, use
+ seg_fix_rotP rather than fix_root from seg_info.
+
+Tue Feb 10 15:32:22 1998 Ian Carmichael <iancarm@cygnus.com>
+
+ * expr.c: Add support for 0x1_2_3_4 bignums.
+
+Tue Feb 10 14:43:40 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Change -linux* to -linux-gnu*.
+ * configure: Rebuild.
+
+ * app.c (do_scrub_begin): Treat \r as whitespace.
+
+Mon Feb 9 14:16:11 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.am: Update dependencies.
+ * Makefile.in: Rebuild.
+
+Sat Feb 7 15:33:51 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure, aclocal.m4: Rebuild with new libtool.
+
+Fri Feb 6 16:08:30 1998 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mips.c (md_begin): If mips_cpu is set, then use it as
+ the argument to bfd_set_arch_mach.
+ (load_address): Use bfd_arch_bits_per_address to determine the
+ bit size of an address instead of looking at the isa level.
+ (macro, macro2, s_cprestore, s_cpadd): Likewise.
+
+Fri Feb 6 14:44:34 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c (md_parse_option): Add -mv850any command line option.
+
+Thu Feb 5 12:39:08 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * ehopt.c: New file.
+ * as.h (enum _relax_state): Add rs_cfa.
+ (check_eh_frame, eh_frame_estimate_size_before_relax): Declare.
+ (eh_frame_relax_frag, eh_frame_convert_frag): Declare.
+ * read.c (emit_expr): Call check_eh_frame.
+ * write.c (cvt_frag_to_fill): Handle rs_cfa.
+ (relax_segment): Likewise.
+ * Makefile.am: Rebuild dependencies.
+ (GAS_CFILES): Add ehopt.c.
+ (GENERIC_OBJS): Add ehopt.o.
+ * doc/internals.texi (Frags): Document rs_cfa.
+
+ * as.c (show_usage): Mention --traditional-format.
+ (parse_args): Accept --traditional-format.
+ * as.h (flag_traditional_format): Declare.
+ * output-file.c (output_file_create): If flag_traditional_format,
+ set BFD_TRADITIONAL_FORMAT on stdoutput.
+ * doc/as.texinfo, doc/as.1: Document --traditional-format.
+
+ * config/tc-mips.c (append_insn): Make sure that if we have a
+ fixup for an unmatched %hi reloc, it does not associated with a
+ variant frag.
+
+ * configure, Makefile.in, aclocal.m4: Rebuild with new libtool.
+ * doc/Makefile.in: Likewise.
+
+Wed Feb 4 15:41:54 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-m32r.c (check_for_side_effects): New function.
+ (can_make_parallel): Add checks for instruction side effects
+ clashing with the other instruction.
+ (assemble_parallel_insn): Improve warning messages. Return error
+ message from non-swapped instruction order.
+
+Wed Feb 4 20:00:26 1998 James G. Smith <jsmith@teknema.demon.co.uk>
+
+ * config/tc-arm.c: Rename arm_after_pass_hook() to arm_cleanup().
+
+ * config/tc-arm.h: Replace md_after_pass_hook definition with a
+ md_cleanup definition. This moves the forced literal output to
+ the end of the source pass, and avoids macro's inserting literals
+ into the code immediately after the macro expansion.
+
+Wed Feb 4 13:17:19 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sparc.h (tc_fix_adjustable) [OBJ_ELF]: A reloc against
+ a gas internal symbol is adjustable.
+ * config/tc-ppc.h (tc_fix_adjustable): Likewise.
+
+ * as.h: If gcc version greater than 2.6, use `__format__' and
+ `__printf__' in function attributes, rather than `format' and
+ `printf'.
+
+Mon Feb 2 18:38:18 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sparc.c: Only include elf/sparc.h if OBJ_ELF.
+
+Mon Feb 2 18:30:34 1998 Steve Haworth <steve@pm.cse.rmit.EDU.AU>
+
+ Add tms320c30 support:
+ * config/tc-tic30.h: New file.
+ * config/tc-tic30.c: New file.
+ * config/obj-coff.h: If TC_TIC30, include coff/tic30.h and define
+ TARGET_FORMAT as "coff-tic30".
+ * configure.in (tic30-*-*aout*, tic30-*-*coff*): New targets.
+ * Makefile.am: Rebuild dependencies.
+ (CPU_TYPES): Add tic30.
+ (CPU_OBJ_VALID): tic30-aout is valid.
+ (TARGET_CPU_CFILES): Add config/tc-tic30.c.
+ (TARGET_CPU_HFILES): Add config/tc-tic30.h.
+ * configure, Makefile.in: Rebuild.
+
+Mon Feb 2 10:20:37 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c (md_assemble): Improvements to error messages.
+
+Mon Feb 2 12:39:05 1998 Geoff Keating <geoffk@ozemail.com.au>
+
+ * config/tc-ppc.c (md_apply_fix3): Change BFD_RELOC_HI16 and
+ BFD_RELOC_HI16_S to store the high bits of any value.
+
+ * config/tc-ppc.h (tc_fix_adjustable): Undo change of Fri Jun 27.
+ (TC_RELOC_RTSYM_LOC_FIXUP): Don't let the
+ assembler calculate relocations to any external symbol at all.
+ * config/tc-ppc.c (md_apply_fix3) [OBJ_ELF]: Correct bugs
+ involving generation of pc-relative relocs.
+ (md_pcrel_from_section) [OBJ_ELF]: The job this code used to do
+ has been moved to md_apply_fix3.
+
+ * config/tc-ppc.c (md_apply_fix3): Fix test for too-far branch.
+ (ppc_elf_suffix): Warn about 'identifier+constant@got' syntax,
+ which actually means (the address of identifier's GOT entry) +
+ constant, which is not particularly useful.
+
+Fri Jan 30 11:02:35 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * read.h (include_dirs): Declare.
+ (include_dir_count,include_dir_maxlen): Declare.
+
+Fri Jan 30 11:47:02 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Correct check for shared opcodes library.
+ * configure: Rebuild.
+
+ * listing.c (buffer_line): If we can't open the file, set at_end.
+ (listing_print): Remove unused local variable fi.
+
+ * config/m68k-parse.y (reglistpair): Handle register list in
+ either order.
+
+ * config/vms-conf.h: Don't undef VERSION.
+
+Thu Jan 29 14:42:44 1998 Pat Rankin <rankin@eql.caltech.edu>
+
+ * Makefile.am (CONFIG_OBJS): New variable, containing part of old
+ OBJS variable.
+ (GENERIC_OBJS): New variable, with the rest of the old OBJS
+ variable.
+ (OBJS): Now just $(CONFIG_OBJS) and $(GENERIC_OBJS).
+ ($(srcdir)/make-gas.com): Rename from make-gas.com.
+ (stamp-mk.com): Replace $(OBJS) with $(GENERIC_OBJS).
+ (EXTRA_DIST): Define.
+ * vmsconf.sh: Handle {targ-cpu, obj-format, atof-targ} modules
+ explicitly rather than via the list of object files.
+ (gcc-as.opt): New file created when make-gas.com is run.
+ * config-gas.com: Create {targ-cpu.h, obj-format.h, targ-env.h,
+ itbl-cpu.h} to #include appropriate file rather than copying that
+ file.
+ * config/vms-conf.h: Synchronize with current config.in.
+ * Makefile.in: Rebuild.
+
+Thu Jan 29 18:48:19 1998 Bill Moyer <billm@cygnus.com>
+
+ * config/tc-d30v.c (do_assemble): Added flag_explicitly_parallel.
+ (parallel_ok): Relaxed parallel subinstruction dependency check.
+
+Wed Jan 28 14:35:00 1998 Bill Moyer <billm@cygnus.com>
+
+ * as.h (flag_warn_suppress_instructionswap): added new flag.
+ * tc-d10v.c (md_parse_option,md_longopts): added "--nowarnswap"
+ command line argument.
+ * tc-d10v.c (write_2_short): emit "Swapping instructions"
+ warning only if flag_warn_suppress_instructionswap is false.
+
+Wed Jan 28 16:41:19 1998 J.J. van der Heijden <J.J.vanderHeijden@student.utwente.nl>
+
+ * configure.in (i386-*-mingw32*): New target.
+ * configure: Rebuild.
+
+Wed Jan 28 14:51:18 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * symbols.c (resolve_symbol_value): Don't set the segment if it
+ hasn't changed, and this is OBJ_AOUT without BFD_ASSEMBLER.
+
+ * config/obj-aout.h (S_IS_LOCAL): Correct typo--pass argument to
+ S_GET_SEGMENT.
+
+Wed Jan 28 13:54:50 1998 Pat Rankin <rankin@eql.caltech.edu>
+
+ as.h (unlink): Reverse 13-Feb-97 change; use of unlink vs remove
+ depends upon HAVE_{UNLINK,REMOVE} values rather than host
+ compiler.
+
+Wed Jan 28 13:48:08 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.h (RESOLVE_SYMBOL_REDEFINITION): Define.
+
+Wed Jan 28 09:52:00 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c (v850_insert_operand): Display instruction when
+ an error is encountered.
+
+Tue Jan 27 13:32:01 1998 Robert Lipe <robertl@dgii.com>
+
+ * configure.in (i386-*-sco3.2v5*): Defaults to ELF now.
+ (i386-*-sco3.2v5*coff): New target.
+ (i386-*-sco3.2*): New target.
+ * configure: Rebuild.
+
+Tue Jan 27 11:06:52 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c: Tidy error message production.
+
+Tue Jan 27 12:24:32 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-arm.c (md_apply_fix3): Add new variable newimm to hold
+ validate_immediate return value in the right type for comparisons
+ to FAIL.
+
+Tue Jan 27 06:51:59 1998 Richard Henderson <rth@cygnus.com>
+
+ * listing.c (MAX_BYTES): Use listing variables not constants.
+ (data_buffer): No longer an array, but a pointer.
+ (calc_hex): sizeof(data_buffer) -> MAX_BYTES.
+ (listing_listing): Allocate data_buffer.
+
+Tue Jan 27 06:38:35 1998 Richard Henderson <rth@cygnus.com>
+
+ * as.c (parse_args): Add --listing-lhs-width, --listing-lhs-width2,
+ --listing-rhs-width, --listing-cont-lines.
+ (show_usage): Update.
+ * listing.c (listing_lhs_width, listing_lhs_width_second): New vars.
+ (listing_lhs_cont_lines, listing_rhs_width): New vars.
+ (print_lines): Use the variables instead of the constants.
+ (listing_listing): Likewise.
+ * listing.h: Declare the new vars.
+
+Tue Jan 27 05:32:05 1998 Richard Henderson <rth@cygnus.com>
+
+ * as.c (parse_args): Add --keep-locals alias for -L.
+ Add --strip-local-absolute.
+ (show_usage): Update.
+ * as.h (flag_strip_local_absolute): New flag.
+ * symbols.c (S_IS_LOCAL): Use it.
+ * config/obj-aout.h (S_IS_LOCAL): Likewise.
+ * config/obj-bout.h (S_IS_LOCAL): Likewise.
+ * config/obj-coff.h (S_IS_LOCAL): Likewise.
+
+Mon Jan 26 13:07:41 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-m32r.c: Detect if explicitly parallel instructions
+ might have an io conflict and issue a warning message.
+
+Thu Jan 22 17:51:44 1998 Nick Clifton <nickc@cygnus.com>
+
+ * cgen.c (cgen_save_fixups, cgen_restore_fixups,
+ cgen_swap_fixups): Functions to save, restore and swap the fixup
+ chain with a backup copy.
+ (cgen_asm_finish_insn): Returns address of constructed insn.
+
+Wed Jan 21 16:49:10 1998 Richard Henderson <rth@cygnus.com>
+
+ * listing.c (file_info_struct): Remove FILE, add POS.
+ (last_open_file_info, last_open_file): New; a one entry FILE* cache.
+ (file_info): Don't open the file.
+ (buffer_line): Check for the file in the last_open cache, updating
+ as necessary.
+ (print_source): Don't reference file_info->file.
+ (listing_listing): Likewise.
+ (listing_print): Close the file in the cache, if any.
+
+Fri Jan 16 14:51:48 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.c (dwarf_file_string): New file static variable.
+ (emit_expr): Look for constant sequence that leads up to a file
+ name in DWARF debugging output.
+ (stringer): Use dwarf_file_string to decide whether to accept a
+ string as a file name.
+
+Fri Jan 16 11:30:37 1998 Richard Henderson <rth@cygnus.com>
+
+ * tc-m68k.c (m68k_ip): Remove absl->reglst MRI hack.
+ (crack_operand): Add reg->reglst MRI hack.
+ (r_seg): Put reglst symbols in reg_section.
+ (m68k_frob_symbol): Frob reglst symbols into absolute_section.
+
+Thu Jan 15 14:19:01 1998 Richard Henderson <rth@cygnus.com>
+
+ * tc-sh.c (get_specific): Handle SGR & DBR.
+
+Thu Jan 15 13:46:48 1998 Richard Henderson <rth@cygnus.com>
+
+ * tc-h8300.c (parse_reg): Take the length of the symbol into
+ account when attempting to match a register name.
+ * tc-h8500.c (parse_reg): Likewise.
+
+Wed Jan 14 17:52:33 1998 Nick Clifton <nickc@cygnus.com>
+
+ * cgen.c: Formatting changes to improve readability.
+
+Wed Jan 14 15:41:41 1998 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mips.c (macro): Rework division code to avoid unfilled
+ delay slot.
+
+Wed Jan 14 18:04:20 1998 Michael Meissner <meissner@cygnus.com>
+
+ Based on a patch from Jim Wilson
+ * config/tc-d30v.c (do_assemble): Remove non-ansi default case.
+ (tc_gen_reloc): Handle cross section PC relative relocs
+ correctly.
+
+Wed Jan 14 15:02:19 1998 Doug Evans <devans@seba.cygnus.com>
+
+ * config/tc-mips.c (mips_ip): Don't test pinfo flags if INSN_MACRO.
+
+Mon Jan 12 13:04:57 1998 Doug Evans <devans@seba.cygnus.com>
+
+ * cgen.c: #include setjmp.h. Clean up pass over `struct foo' usage.
+ (expr_jmp_buf): New static local.
+ (cgen_parse_operand): Allow use of longjmp in parsing to handle errors.
+ (cgen_md_operand): New function.
+ * tc-m32r.c: Clean up pass over `struct foo' usage.
+ (md_estimate_size_before_relax): Use CGEN_INSN_MNEMONIC.
+
+Tue Jan 6 15:36:02 1998 Richard Henderson <rth@cygnus.com>
+
+ * symbols.c (S_SET_SEGMENT): Don't set the segment for section syms.
+ (S_IS_EXTERNAL, S_IS_LOCAL): Correct parenthetication.
+
+Fri Jan 2 16:08:54 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-i386.c (i386_operand): Give an error if there are
+ unrecognized characters after an expression.
+
+For older changes see ChangeLog-9697
diff --git a/gas/ChangeLog-9295 b/gas/ChangeLog-9295
new file mode 100644
index 0000000000..7ea48e6a9c
--- /dev/null
+++ b/gas/ChangeLog-9295
@@ -0,0 +1,13110 @@
+Sat Dec 30 23:42:51 1995 Jeffrey A Law (law@cygnus.com)
+
+ * ecoff.c (ecoff_stab): Simplify. Correctly handle sym + offset
+ addresses for static variables.
+
+Thu Dec 21 12:54:32 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (mapping): Make @got give a real GOT relocation,
+ and xgot give the old toc16 relocation.
+ (md_apply_fix3): Support all GOT relocations.
+
+Wed Dec 20 14:57:17 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (load_address): Correctly handle a constant in
+ SVR4_PIC case. From Richard Kenner <kenner@vlsi1.ultra.nyu.edu>.
+
+Fri Dec 15 14:25:07 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * config/tc-sh.c (parse_reg): Recognize SH3 registers.
+ (get_specific): Handle A_SSR, A_SPC and A_REG_B.
+ (build_Mbytes): Handle REG_B.
+
+Fri Dec 15 16:07:25 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * ecoff.c (ecoff_build_aux): Use new bfd_big_endian macro.
+
+Fri Dec 15 12:11:48 1995 Raymond Jou <rjou@mexican.cygnus.com>
+
+ * mpw-make.sed: If linking, edit ALL_CFLAGS to CFLAGS.
+
+Thu Dec 14 15:09:52 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.c (write_object_file): Set the s_align field to
+ the number of bytes, rather than to the power of 2.
+
+Tue Dec 12 12:19:37 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (DISTCLEAN_HERE): New variable.
+ (distclean): Use it.
+ (maintainer-clean): Depend upon clean-here rather than clean,
+ distclean, and clean-info. Run make maintainer-clean in doc.
+ Remove files listed in DISTCLEAN_HERE.
+ * doc/Makefile.in (maintainer-clean realclean): Split out from
+ distclean. Depend upon clean-info and distclean.
+
+Mon Dec 11 16:23:51 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mac-as.r: Fix copyright and version strings.
+ (cfrg): Use PROG_NAME instead of literal name.
+
+Mon Dec 11 14:14:08 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.c (read_a_source_file): If tc_unrecognized_line is defined,
+ call it.
+ * config/tc-a29k.h (tc_unrecognized_line): Define.
+ * config/tc-a29k.c (a29k_unrecognized_line): New function.
+ (md_operand): Handle a29k style local dollar labels.
+
+Wed Dec 6 17:52:52 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-multi.h: If OBJ_MAYBE_ELF, define OBJ_SYMFIELD_TYPE.
+
+Tue Dec 5 13:26:34 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * read.c (s_fill): If md_flush_pending_output is defined, call
+ it.
+
+Mon Dec 4 15:10:53 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * config/obj-coff.c (size_section, fill_section, fixup_mdeps):
+ Treat rs_align_code like rs_align.
+
+Sun Dec 3 16:46:54 1995 Richard Earnshaw (rearnsha@armltd.co.uk)
+
+ * config/tc-arm.c (cp_address_required_here): Set pre_inc when
+ converting an absolute address into a PC-relative one.
+
+Fri Dec 1 11:57:56 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-config.in: Don't always use te-generic.h for emulation.
+ (powerpc-apple-macos): Use emulation te-macos.h.
+ * mpw-make.sed (install, install-only): Edit in Mac-specific
+ install procedure.
+
+Fri Dec 1 10:59:25 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Improve message about unsupported ELF targets.
+ * configure: Rebuild.
+
+ * config/tc-m88k.c (m88k_do_align): Correct check for whether fill
+ pattern is zero. From Manfred Hollstein.
+
+Thu Nov 30 13:25:49 1995 Kim Knuttila <krk@cygnus.com>
+
+ * config/tc-ppc.c (ppc_pe_section): To get the alignment right for
+ the various idata sections, we check the name on the .section pseudo.
+
+Thu Nov 30 11:23:42 1995 Manfred Hollstein KS/EF4A 60/1F/110 #40283 <manfred@lts.sel.alcatel.de>
+
+ * config/obj-coff.c (fixup_segment): If TC_M88K is defined, do not
+ add section's paddr to add_number; compatibility to native as and
+ ld forbids.
+
+Wed Nov 29 23:14:27 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * configure.in: Treat m68k-sysv4 like m68k-elf, not m68k-sysv3.
+
+ * hash.c (struct hash_entry): Moved here...
+ * hash.h (struct hash_entry): ...from here.
+
+ * config/obj-elf.c (elf_frob_symbol): Don't free and clear sy_obj
+ if it's already known to be null.
+
+Wed Nov 29 13:00:20 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (md_apply_fix3): Don't adjust the value for 32
+ bit relocs converted to PC relative relocs. This turned out to
+ add the offset from the beginning of .text twice.
+
+Tue Nov 28 10:42:36 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * stabs.c (s_stab_generic): In 's' case, free string from
+ obstack.
+
+ * config/obj-elf.h (ELF_TARGET_SYMBOL_FIELDS): Remove unused field
+ sy_name_offset.
+ * config/obj-multi.h (ELF_TARGET_SYMBOL_FIELDS) [OBJ_MAYBE_ELF]:
+ Ditto.
+
+ * subsegs.h (segment_info_type): Make bitfields unsigned.
+
+ * expr.h (struct expressionS): Make X_op and X_unsigned bitfields,
+ and move them together. On most systems this will reduce the
+ structure size by one word.
+ (operatorT): Define O_max.
+ * expr.c (expr_begin): Verify that X_op is wide enough to hold
+ O_max.
+
+ * read.c (pop_insert): Print error returned by hash table
+ insertion code.
+
+ * as.c (dump_statistics): Split out from main; dump some hash
+ table stats and target-specific stats.
+ (start_time): No longer automatic to main.
+ (main): Set file-level start_time and call dump_statistics at
+ exit. Exit by calling xexit.
+ (show_usage): Make --statistics description less specific.
+ * subsegs.c (subsegs_print_statistics): New function.
+ * write.c (write_print_statistics): New function.
+ (n_fixups): New static variable.
+ (fix_new_internal): Increment it.
+ * read.c (read_print_statistics): New function.
+ * read.h (read_print_statistics): Declare.
+ * symbol.c (symbol_print_statistics): New function.
+ * symbol.h (symbol_print_statistics): Declare.
+ * hash.c (hash_print_statistics): New function.
+ * hash.h (hash_print_statistics): Declare.
+ * config/tc-i386.c (i386_print_statistics): New function.
+ * config/tc-i386.h (i386_print_statistics): Declare.
+ (tc_print_statistics): New macro.
+ * messages.c (as_fatal, as_assert, as_abort): Use xexit, not
+ exit.
+
+ * hash.c (DELETED): Rewrite to use a valid but unique address.
+ (START_POWER): Reduce to 10.
+ (enum stat_enum): New enumerator, replacing STAT_* index macros.
+ Add new values for counting strcmp calls.
+ (GROW_FACTOR): New macro.
+ (hash_grow): Use GROW_FACTOR. Rewrite for quick returns instead
+ of nesting blocks.
+ (FULL_VALUE): New macro. Use 1/4 of table size instead of 1/2.
+ (hash_new): Use FULL_VALUE.
+ (struct hash_control): Definition moved here.
+ (hash_code): Don't mask to low bits.
+ (hash_ask): Mask returned hash code here. Check hash value before
+ calling strcmp; count strcmp calls.
+ * hash.h (struct hash_control): Declare, don't define, here.
+ (HASH_STATLENGTH): Deleted.
+ (struct hash_entry): Add field for hash code.
+ (hash_say, hash_apply): Don't declare.
+
+ * hash.c (destroy): Return void.
+ (applicatee): Ditto.
+ (main): Fix declarations.
+ (hash_apply): Return void. Argument `function' returns void. Put
+ inside "#ifdef TEST".
+ (hash_say): Define only if TEST is defined.
+ * hash.h (hash_apply, hash_say): Declarations deleted.
+
+Mon Nov 27 13:18:25 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure: Rebuild with autoconf 2.7.
+
+Tue Nov 21 18:39:01 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * aclocal.m4 (AC_PROG_CC): Remove local definition.
+ * configure: Rebuild with autoconf 2.6.
+
+Mon Nov 20 17:26:00 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-ppc.c (ppc_debug_name_section_size): Remove.
+ (ppc_stabx): Don't increment ppc_debug_name_section_size.
+ (ppc_bc): Likewise.
+ (ppc_frob_file): Remove.
+ * config/tc-ppc.h (tc_frob_file): Don't define.
+ (ppc_frob_file): Don't declare.
+
+Mon Nov 20 13:37:05 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * Makefile.in (TARG_CPU_DEP_alpha): Mention alpha-opcode.h.
+ * config/alpha-opcode.h: Include one-operand variants of jmp and
+ jsr.
+
+ * config/te-delt88.h: Renamed from te-delta88.h, to avoid conflict
+ with te-delta.h in 8.3 file systems.
+ * configure.in: Adjusted.
+
+Thu Nov 16 12:49:38 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (s_err): Remove; just use the one in read.c.
+
+ * config/m68k-parse.y (yylex): In MRI mode, '@' can start an octal
+ number.
+ * expr.c (operand): Handle MRI suffixes after unadorned 0.
+
+Thu Nov 16 00:21:44 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ Version 2.6 released.
+ * Makefile.in (VERSION): Updated to 2.6.
+
+ * config/obj-coff.c (write_object_file): Change use of md_do_align
+ to pass a pointer rather than a fill value, to match other uses.
+
+Wed Nov 15 03:52:00 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * config/tc-ns32k.h (TC_FIX_TYPE): Add missing semicolon.
+
+ * as.c (main): Move md_end call to just after call to
+ perform_an_assembly_pass. Delete cpu-specific code here.
+ * config/tc-i960.h (md_end): New macro, calls brtab_emit.
+ * config/tc-arm.c (md_end): Unused function deleted.
+ * config/tc-ns32k.c (md_end): Ditto.
+
+ * config/tc-i386.c (i386_align_code): New function, moved here
+ from HANDLE_ALIGN macro.
+ * config/tc-i386.h (HANDLE_ALIGN): Call it.
+
+ Mon Jul 31 14:53:19 1995 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * config/tc-i386.h (md_do_align): cast fill and 0x90 to char
+ before comparing
+
+ Mon May 1 10:91:49 1995 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * config/tc-i386.h (md_do_align): Make ".align n,0x90" generate
+ multi-byte nops to avoid changing gcc. The necessary gcc change
+ might break old assemblers.
+
+ Sat Apr 22 20:53:05 1995 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * config/tc-i386.h (md_do_align, HANDLE_ALIGN): Add macros to
+ generate optimal multi-byte nop instructions for ".align n"
+ ".align n,0x90", and aligns requiring more than 15 bytes of
+ padding still generate multiple 0x90's as before.
+
+Mon Nov 13 17:40:21 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (s_mri_until): Call pop_mri_control.
+
+Mon Nov 13 20:39:06 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * configure.in (ppc-*-macos*, ppc-*-mpw*): New configurations.
+ * configure: Update.
+ * mpw-make.sed: Reorder commands to make sed happier.
+ * config/te-macos.h: New file.
+ * config/tc-ppc.h (TARGET_FORMAT): Set correctly for PowerMac.
+
+Sun Nov 12 21:14:56 1995 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-hppa.c (pa_ip): Fix off-by-2 bug in length check for
+ conditional branches.
+ (md_apply_fix): Likewise.
+
+Thu Nov 9 16:14:01 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-a29k.c (md_apply_fix): Warn if an attempt is made to
+ generate a reloc which the linker will not handle correctly. Fix
+ overflow checking--R_IREL is 18 bits, not 17.
+
+Wed Nov 8 19:59:36 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.c (fixup_segment): Don't subtract md_pcrel_from
+ from a PC relative reloc if TC_A29K.
+
+ * config/tc-a29k.c (line_separator_chars): Restore '@'. Existing
+ code depends upon it.
+
+ * config/tc-a29k.c (md_operand): Handle $float, $double, and
+ $extend. Based on code from Eric Freudenthal
+ <freudenthal@nyu.edu>.
+ * config/tc-a29k.h (LEX_DOLLAR): Define.
+ * read.c (LEX_DOLLAR): Define if not defined.
+ (lex_type): Use LEX_DOLLAR.
+
+Wed Nov 8 16:38:14 1995 Eric Freudenthal <freudenthal@nyu.edu>
+
+ * configure.in (a29k-nyu-sym1): New target, just like other a29k
+ targets.
+
+Wed Nov 8 11:38:48 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.c (c_dot_file_symbol): Cast xmalloc return.
+
+Tue Nov 7 09:14:35 1995 Kim Knuttila <krk@cygnus.com>
+
+ * config/tc-ppc.c (md_apply_fix3): Added BFD_RELOC_RVA. Currently
+ used only by "dlltool.c".
+
+Mon Nov 6 18:51:26 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-alpha.c: Undefine inline if not __GNUC__.
+ (md_pseudo_table): Don't define "extern".
+
+Sat Nov 4 00:51:21 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-ppc.c (ppc_biei): Force symbol into text_section.
+
+ * config/tc-ppc.c (md_show_usage): Put backslash at end of line.
+
+Fri Nov 3 13:02:59 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * macro.c (macro_expand_body): Don't warn about == with a
+ nonexistent parameter, in case it is in a comment field.
+
+ * as.c (main): On TC_A29K, call macro_init with macro_alternate
+ set to 1.
+ * macro.c (get_any_string): Don't keep quotes if macro_strip_at is
+ set, even if macro_alternate is set.
+ (get_apost_token): If macro_strip_at, only skip kind if it is '@'.
+ (sub_actual): If macro_strip_at, and kind is '@', don't look up
+ the token unless it ended in '@'.
+ * config/tc-a29k.c (line_separator_chars): Remove '@'.
+ * doc/c-a29k.texi: Document macro usage on A29K.
+
+Thu Nov 2 23:07:57 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (m68k_ip): Handle new 'W' place, meaning a
+ signed word.
+ (install_operand): Likewise.
+
+ * config/obj-elf.c (ecoff_debug_pseudo_table): Add "extern".
+
+Wed Nov 1 15:17:02 1995 Manfred Hollstein KS/EF4A 60/1F/110 #40283 <manfred@lts.sel.alcatel.de>
+
+ * configure.in (m88k-motorola-sysv*): New target.
+ * configure: Rebuild.
+ * config/te-delta88.h: New file.
+ * config/obj-coff.c (write_object_file): Use md_do_align if it is
+ defined.
+ * config/tc-m88k.h (SUB_SEGMENT_ALIGN): Define.
+ (md_do_align): Define.
+ * config/tc-m88k.c: Include "subsegs.h".
+ (m88k_do_align): New function.
+
+ * config/te-delta.h (STRIP_UNDERSCORE): Don't define.
+ (COFF_NOLOAD_PROBLEM): Define.
+ (LOCAL_LABELS_DOLLAR, LOCAL_LABELS_FB): Define.
+
+Wed Nov 1 16:07:43 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * config/tc-i386.c (md_assemble): For a jump instruction with
+ non-constant target, require 7 available bytes in the current
+ frag, not 6.
+
+Tue Oct 31 15:37:16 1995 Fred Fish <fnf@rtl.cygnus.com>
+
+ * config/obj-elf.h: Include bfd/elf-bfd.h rather than
+ bfd/libelf.h.
+
+Tue Oct 31 16:34:28 1995 David Mosberger-Tang <davidm@azstarnet.com>
+
+ * configure.in (alpha-*-linux*): Use ecoff.
+ * configure: Rebuild.
+ * ecoff.c (ecoff_directive_extern): New function.
+ (ecoff_directive_weakext): New function.
+ (ecoff_build_symbols): Handle weak symbols.
+ (ecoff_setup_ext): Likewise.
+ (ecoff_frob_symbol): Warn about weak common symbols.
+ * ecoff.h (ecoff_directive_extern): Declare.
+ (ecoff_directive_weakext): Declare.
+ * symbols.c (S_IS_WEAK): New function.
+ * symbols.h (S_IS_WEAK): Declare.
+ * config/obj-ecoff.c (obj_pseudo_table): Add "extern" and
+ "weakext".
+ * config/tc-mips.c (mips_pseudo_table): Remove "extern".
+ (s_extern): Remove.
+
+Tue Oct 31 13:29:08 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-ppc.c (ppc_lglobl): Do the right thing.
+
+ * config/tc-ppc.c (ppc_bb): Call SF_SET_PROCESS.
+ (ppc_eb): Likewise. Set the storage class to C_BLOCK, not C_FCN.
+ (ppc_frob_symbol): Don't change C_BLOCK symbols to C_HIDEXT.
+ * config/obj-coff.c (coff_frob_symbol): Don't call
+ SA_SET_SYM_ENDNDX with the current symbol; call it with the next
+ one. If OBJ_XCOFF, try to figure out whether the symbol is going
+ to be dropped.
+
+ * config/tc-ppc.c (md_pseudo_table): Add "bc" and "ec".
+ (ppc_stab_symbol): New static variable.
+ (ppc_change_csect): Check that ppc_toc_csect is not NULL.
+ (ppc_stabx): Set ppc_stab_symbol around call to symbol_make. Set
+ sy_tc.real_name to the stab string.
+ (ppc_bc, ppc_ec): New static functions.
+ (ppc_canonicalize_symbol_name): If ppc_stab_symbol is set, don't
+ do anything.
+ (ppc_symbol_new_hook): If ppc_stab_symbol is set, don't look for a
+ suffix.
+ (ppc_frob_symbol): Set BSF_NOT_AT_END for symbols with csect aux
+ entries.
+
+ * input-scrub.c (input_scrub_push): Reset sb_index.
+
+Mon Oct 30 17:52:46 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * listing.c (listing_newline): Don't create a frag in the absolute
+ section.
+
+Sat Oct 28 01:02:05 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-ppc.c (md_pseudo_table): Add "data" and "text".
+ (ppc_csect): Move most of the code to ppc_change_csect, and call
+ it.
+ (ppc_change_csect): New static function, taken from ppc_csect.
+ (ppc_section): New static function.
+ (ppc_saw_abs): New static varable.
+ (ppc_frob_symbol): Create aux entry for absolute symbols. Warn if
+ a symbol has no csect.
+ (ppc_adjust_symtab): New function.
+ * config/tc-ppc.h (tc_adjust_symtab): Define if OBJ_XCOFF.
+ (ppc_adjust_symtab): Declare if OBJ_XCOFF.
+
+ * write.c (write_object_file): If tc_adjust_symtab is defined,
+ call it just before the call to obj_adjust_symtab.
+
+ * symbols.c (symbol_find_or_make): Change name to be const.
+ * symbols.h (symbol_find_or_make): Update declaration.
+
+Thu Oct 26 19:18:27 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * doc/as.texinfo (Align): Mention SH.
+ * doc/c-m68k.texi (M68K-Directives, .even): Describe behavior, not
+ .align value.
+ * doc/c-z8k.texi (Z8000 Directives, global): Fix minor typo.
+ (Z8000 Directives, even): Don't give numeric align value, instead
+ explain behavior.
+
+Thu Oct 26 11:45:03 1995 Richard Earnshaw (rearnsha@armltd.co.uk)
+
+ * tc-arm.c (do_ldst): Assemble ldr/str r0, [r1] as a pre-increment
+ instruction.
+
+Wed Oct 25 11:59:24 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * Makefile.in (diststuff): Also make info.
+ (maintainer-clean realclean): Also make clean-info.
+
+Tue Oct 24 15:21:33 1995 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-hppa.c (md_pseudo_table): Add new ".nsubspa" opcode.
+ (pa_subspace): For ".nsubspa", always create a new subspace
+ with the given attributes, even if one already exists with the
+ same name.
+
+Tue Oct 24 14:50:38 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.h (TC_FORCE_RELOCATION_SECTION): Rename from
+ TC_FORCE_RELOCATION, taking an additional section argument. If
+ the section of the target symbol is not the same as the current
+ section, always force the relocation to be used.
+ (MD_PCREL_FROM_SECTION): New macro to call md_pcrel_from_section.
+
+ * config/tc-ppc.c (md_pcrel_from_section): Rename from the
+ md_pcrel_from function, taking an additional section argument.
+ Invoke TC_FORCE_RELOCATION_SECTION instead of TC_FORCE_RELOCATION.
+
+ * write.c (TC_FORCE_RELOCATION_SECTION): Define in terms of the
+ older TC_FORCE_RELOCATION if not defined.
+ (MD_PCREL_FROM_SECTION): If not defined, invoke md_pcrel_from.
+ (fixup_segment): Use MD_PCREL_FROM_SECTION instead of
+ md_pcrel_from, and TC_FORCE_RELOCATION_SECTION instead of
+ TC_FORCE_RELOCATION.
+
+Mon Oct 23 16:20:04 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * input-scrub.c (as_where): Set name to null pointer if we don't
+ have a file name.
+ * messages.c (identify): Only print filename if non-null.
+ (as_show_where): Ditto, for line number too.
+ (as_warn_internal, as_bad_internal): Ditto.
+
+ * input-file.c (input_file_open): If the input file can't be
+ opened, consider it an error.
+
+Mon Oct 23 11:15:44 1995 James G. Smith <jsmith@pasanda.cygnus.co.uk>
+
+ * config/tc-mips.c: Added mips_4100 control, and support for
+ accepting the 4100 as a MIPS architecture variant (md_begin,
+ macro_build, mips_ip, md_parse_option). Adding suitable
+ command-line OPTIONs, and updating the help text (md_show_usage).
+
+Wed Oct 18 13:20:32 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * subsegs.c (subseg_begin): Only set absolute_frchain.fix_* when
+ BFD_ASSEMBLER is defined.
+
+ * Use one active frag and one obstack per frag chain:
+ * frags.c (frags): Variable deleted.
+ (frag_alloc): New function.
+ (frag_grow, frag_more, frag_variant, frag_now_fix,
+ frag_append_1_char): Refer to frchain_now->frch_obstack instead of
+ frags variable.
+ (frag_new): Ditto. Verify that frch_last and frag_now match on
+ entry and exit, and that old frag_now has non-zero type. Replace
+ "know" uses with "assert". Use frag_alloc instead of mucking with
+ obstack alignment.
+ * frags.h (frags): Declaration deleted.
+ * subsegs.h (struct frchain): Add new field frch_frag_now.
+ * subsegs.c (frchains, dummy_frag, absolute_frchain): New static
+ variables.
+ (subsegs_begin): Initialize frchains obstack. Under gcc, don't
+ give it any stricter alignment than frchainS structures need. Do
+ not initialize frags obstack. Set frag_now to point to
+ dummy_obstack. Initialize absolute_frchain.
+ (subseg_set_rest): Save and restore frag_now in frch_frag_now
+ field of frchainS. Don't create new frags on section switch, and
+ use frag_alloc when creating a new frag chain. For absolute
+ section, set frchain_now to absolute_frchain. Verify that
+ frch_last and frag_now match on entry and exit. Initialize
+ per-chain obstack, and under gcc, set required alignment to that
+ needed by fragS structure.
+
+ * write.c (chain_frchains_together_1): Verify fr_type is nonzero.
+
+ * stabs.c (get_stab_string_offset): Only copy input string if a
+ fresh copy is needed, not if the section already exists.
+ (s_stab_generic): Cache stab section name to bypass lookups, since
+ usually it will match. Could be made faster still by changing the
+ memory allocation rules.
+ (s_xstab): Cache section name to bypass repeated string
+ allocation.
+
+ * frags.c (frag_new): Deleted register declarations.
+
+ * listing.c (frag_now): Don't declare.
+
+ * as.c (chunksize): New variable.
+ (debug_memory): New variable.
+ (main): If debug_memory is set, reduce chunksize and
+ _bfd_chunksize.
+ * as.h (chunksize): Declare it.
+ * read.c (read_begin): Use it.
+
+ * config/tc-alpha.c (md_shortopts): Include 'g'.
+ (md_parse_option): Ignore it.
+
+ * Makefile.in (distclean): Remove Makefile and config.status from
+ testsuite directory.
+ (clean-here): Don't delete testsuite. Instead, delete only the
+ files within it that would be generated by running tests.
+
+ * config/tc-hppa.c (hppa_elf_mark_end_of_function): Call
+ frag_now_fix instead of accessing obstack info directly.
+ * config/tc-arm.c (s_ltorg): Ditto.
+ (md_assemble): Ditto.
+
+ * config/tc-i386.c (md_assemble): Call frag_grow instead of
+ obstack_room.
+
+Wed Oct 18 12:22:59 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * stabs.c (aout_process_stab): Insert debug symbol into symbol
+ chain after parsing value expression, if any, to avoid separating
+ continued .stabs lines.
+
+Mon Oct 16 10:56:41 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (mips_elf_pseudo_table): Remove.
+ (mips_pop_insert): Don't call pop_insert on mips_elf_pseudo_table.
+
+Mon Oct 16 07:07:37 1995 Michael Meissner <meissner@wogglebug.tiac.net>
+
+ * config/tc-ppc.c (md_begin): Use new flags PPC_OPCODE_COMMON for
+ -mcom support and PPC_OPCODE_ANY for -many.
+ (md_parse_option): Ditto.
+ (ppc_arch): Ditto.
+ (md_begin): For duplicate instructions, print all duplicates
+ before aborting.
+
+Sun Oct 15 22:06:14 1995 Michael Meissner <meissner@cygnus.com>
+
+ * config/tc-ppc.c (md_parse_option): Support for -mcom to turn on
+ common mode operation.
+ (md_show_usage): Add -mcom to usage message.
+
+Fri Oct 13 13:32:45 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * expr.c (op_rank): Add O_symbol_rva.
+ * expr.h (operatorT): Add O_symbol_rva.
+ * read.c (cons_worker): Set O_symbol_rva when necessary.
+ * write.c (fix_new_exp): Understand O_symbol_rva.
+
+Tue Oct 10 11:34:14 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c: Correct s_cons arguments. From Michael
+ Joosten <joost@ori.cadlab.de>.
+
+Mon Oct 9 19:59:53 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-ppc.c (ppc_macro): Make count unsigned.
+ (ppc_biei): Set segment to now_seg and value to coff_n_line_nos.
+ (ppc_frob_symbol): Handle C_BINCL and C_EINCL symbols by setting
+ the fix_line field.
+ * config/obj-coff.c (coff_n_line_nos): Rename from n_line_nos, and
+ make non-static. Change all users.
+ * config/obj-coff.h (coff_n_line_nos): Declare.
+
+Fri Oct 6 16:24:27 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ Mon Sep 25 22:49:32 1995 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * configure.in (AC_ARG_WITH(bfd-assembler)): Fix help message.
+
+ * config/obj-elf.c (obj_elf_common): Convert specified byte
+ alignment to power of two. Set size of local bss symbol.
+
+ * config/tc-m68k.c (tc_gen_reloc): Fix typo in variable name.
+
+Fri Oct 6 15:22:25 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * sb.c, macro.c: Decide whether to include <string.h> or
+ <strings.h> just as as.h does.
+
+Fri Oct 6 09:55:33 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * Makefile.in (site.exp): Fix setting of $srcdir.
+
+ * config/tc-arm.c (md_atof): Fix little-endian output.
+ * config/tc-arm.h (ARM_BI_ENDIAN): Move definition so defined for
+ all coff targets.
+
+Thu Oct 5 20:17:30 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * doc/as.texinfo: Split out the NS32k family documentation,
+ despite its being commented out for now.
+ * doc/c-ns32k.texi: New file.
+
+ * sb.c, macro.c: Include string.h.
+
+ * Makefile.in (comparison): Only check *.o; we don't care if
+ timestamps inserted by the native linker differ.
+
+ * config/tc-alpha.c (alpha_align): Only fill with a no-op pattern
+ if alignment stricter than 4 bytes is requested; in that case,
+ align to a 4-byte boundary first.
+
+ Thu Sep 28 19:35:27 1995 Pat Rankin <rankin@eql.caltech.edu>
+
+ * config/obj-vms.c (VMS_RSYM_Parse): eliminate "might be used
+ uninitialized" warning for `Max_Source_Offset'.
+
+Wed Oct 4 16:17:02 1995 Kim Knuttila <krk@cygnus.com>
+
+ * config/tc-ppc.c (parse_toc_entry): New function to parse [toc]
+ qualifiers and detect errors if present.
+ (md_assemble): Add call to parse_toc_entry. Also added some support
+ for the [tocv] qualifier.
+ (ppc_pe_tocd): New function to support data in the toc section.
+
+Wed Oct 4 14:03:39 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-ppc.c (ppc_frob_symbol): Don't create an aux entry for
+ an absolute symbol.
+
+Tue Oct 3 12:18:19 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (isword): Accept all values from -65536 to
+ +65535, so ~VAL will not be rejected.
+
+ * cond.c (s_endif): Call demand_empty_rest_of_line. In MRI mode,
+ skip characters after the pseudo-op.
+ (s_else): Likewise.
+ * read.c (get_line_sb): Don't look past buffer_limit.
+ (s_include): In MRI mode, skip characters after the file name.
+
+Mon Oct 2 16:15:27 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/m68k-parse.y (m68k_reg_parse): In MRI mode, permit
+ periods in register names.
+
+Sat Sep 30 23:03:31 1995 Jeff Law (law@hurl.cygnus.com)
+
+ * config/tc-hppa.c (hppa_fix_adjustable): DP relative relocs
+ are not adjustable in SOM to avoid confusing the optimizing
+ linker.
+
+Fri Sep 29 15:18:08 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ Add some support for i960 MRI compatibility mode.
+ * config/tc-i960.c (md_pseudo_table): Add endian.
+ (get_args): Don't discard a space between alphanumeric characters.
+ (get_cdisp): Change text_section to now_seg.
+ (s_endian): New static function.
+ * config/tc-i960.h (MRI_MODE_NEEDS_PSEUDO_DOT): Define.
+ * expr.h (operatorT): Add O_logical_not, O_logical_and, and
+ O_logical_or.
+ * expr.c (operand): Treat '!' as logical not operator. If
+ TC_I960, in MRI mode permit `sizeof secname' and `startof
+ secname'.
+ (op_rank): Bump values by 2 to make room for && and ||. Add
+ entries for !, &&, and ||.
+ (expr_begin): Only do MRI changes if TC_M68K.
+ (operator): Recognize || and &&.
+ (expr): Handle new operatorT values.
+ * symbols.c (resolve_symbol_value): Handle new operatorT values.
+ (print_expr_1): Likewise.
+ * read.c (potable): Add debug, err, irep, irepc, print, purgem,
+ and rep.
+ (read_a_source_file): Handle MRI_MODE_NEEDS_PSEUDO_DOT.
+ (mri_comment_field): Only handle weird comments if TC_M68K.
+ (s_err): New function.
+ (s_org): Only punt in MRI mode if TC_M68K.
+ (s_mri_sect): Write TC_I960 version.
+ (s_print, s_purgem): New functions.
+ * read.h (s_err, s_print, s_purgem): Declare.
+ * cond.c (s_ifeqs): Implement.
+ (ignore_input): Handle MRI_MODE_NEEDS_PSEUDO_DOT.
+ * macro.c (macro_strip_at): New static variable.
+ (macro_init): Add strip_at parameter.
+ (do_formals): If macro_strip_at, change NARG to $NARG.
+ (define_macro): Skip a comma after the macro name.
+ (get_apost_token): Skip character if macro_strip_at, even if
+ macro_mri.
+ (macro_expand_body): If macro_strip_at, don't recognize parameters
+ in strings unless they are preceded by an '@'. If macro_strip_at,
+ pass '@' as strip character to sub_actual. If macro_strip_at,
+ strip '@' characters.
+ (macro_expand): If macro_strip_at, change NARG to $NARG.
+ (delete_macro): New function.
+ (expand_irp): Skip leading and trailing '"' characters if irpc.
+ * macro.h (macro_init): Mention new strip_at parameter.
+ (delete_macro): Declare.
+ * as.c (main): If TC_I960, pass flag_mri to macro_init as
+ strip_at; otherwise, pass 0.
+ * gasp.c (process_pseudo_op): Pass 0 to macro_init as strip_at.
+ (main): Likewise.
+ * doc/as.texinfo: Document i960 MRI mode.
+
+ * as.c (show_usage): Mention --defsym.
+
+Thu Sep 28 19:25:04 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-config.in: Translate "powerpc" into "ppc", remove gen of
+ VERSION, move gen of "conf" here from makefile.
+ * mpw-make.sed: New file, sed commands to translate Unix makefile
+ into MPW syntax.
+ * mpw-make.in: Remove.
+ * mac-as.r: New file, Mac resource file.
+ * as.h (inline): Don't decide about defining if __MWERKS__,
+ remove redundant conditional and definition.
+
+ * stabs.c (s_stab_generic): Fix syntax for OBJ_PROCESS_STAB.
+
+Thu Sep 28 15:43:15 1995 Kim Knuttila <krk@nellie>
+
+ * config/tc-ppc.c (md_apply_fix3): Removed some TE_PE specific
+ manipulations, since I can't prove they're needed.
+ (md_begin): Removed init_regtable, insert_reg, and the call points.
+ (register_name): New function. Parses a register name, if appropriate.
+ (md_assemble): Added call to register_name to handle symbolic names.
+ (ppc_pe_section): Removed all duplicate IMAGE defines, and include
+ coff/pe.h instead.
+
+Thu Sep 28 12:09:19 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-ppc.h (tc_fix_adjustable): Define.
+ (ppc_pe_fix_adjustable): Declare.
+ * config/tc-ppc.c (ppc_pe_fix_adjustable): New function.
+
+Thu Sep 28 01:11:58 1995 Doug Evans <dje@deneb.cygnus.com>
+
+ * config/tc-arm.h (TARGET_FORMAT): Define for arm-coff.
+
+Wed Sep 27 12:53:58 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * symbols.c (S_IS_LOCAL): All symbols in reg_section are local.
+
+ * config/tc-ppc.h (OBJ_XCOFF): Define if OBJ_COFF and not TE_PE.
+ Change OBJ_COFF checks to check OBJ_XCOFF instead.
+ (TARGET_FORMAT): Fully parenthesize.
+ (LEX_QM): Define if TE_PE.
+ * config/tc-ppc.c: Replace OBJ_COFF by OBJ_XCOFF throughout.
+ Remove checks of TE_PE within #ifdef OBJ_XCOFF sections.
+ (init_regtable): Make i unsigned.
+ (ppc_set_current_section): Rename from setCurrentSection. Change
+ all callers.
+ (ppc_arch): Return after as_fatal to avoid gcc warning.
+ (md_assemble): Only declare reloc if OBJ_ELF. Add default to
+ switch on fixups[i].reloc to avoid gcc warning.
+ (IMAGE_SGN_LNK_OTHER): Fix nested comment.
+ (ppc_pe_function): Don't call ppc_canonicalize_symbol_name.
+ (ppc_frob_symbol): Remove TE_PE section checks.
+ (md_estimate_size_before_relax): Return after abort to avoid gcc
+ warning.
+ (md_apply_fix3): Add BFD_RELOC_16_GOT_PCREL to switch.
+ * read.c (LEX_QM): Define as 0 if not defined.
+ (lex_type): Use LEX_QM for '?'.
+
+ * configure.in: No need to check whether ${cpu_type} is powerpc;
+ it never will be.
+ * configure: Rebuild.
+
+Wed Sep 27 11:33:38 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (md_apply_fix3): Remove Sep 26 changes to this
+ function, keeping other Sep. 26 changes.
+
+Wed Sep 27 10:29:13 1995 Kim Knuttila <krk@nellie>
+
+ * configure (emulations): Added support for ppcle-*-[pe|winnt]
+ (target_frag): Removed an extraneous PPC definition.
+ * configure.in (emulations): Same
+ * config/tc-ppc.h:
+ * config/tc-ppc.c (md_pseudo_table): Base support for new or altered
+ pseudo ops - <previous, pdata, ydata, reldata, rdata, ualong, znop,
+ section, comm, function> There will be more.
+ (pre_defined_registers): Predefined reg table to name registers, etc
+ (md_begin): Setup reg table initialization
+ (md_assemble): Initial [toc]x(rtoc) support
+ (ppc_frob_label): Removed some xcoff specific processing from TE_PE
+ (ppc_frob_symbol): Removed some xcoff specific processing from TE_PE
+ Added support for more predefined sections
+ (ppc_frob_section): Removed some xcoff specific processing from TE_PE
+ (ppc_fix_adjustable): Removed from TE_PE mainline
+ (md_apply_fix3): For TE_PE toc entries, we don't need to mess
+ with fx_addnumber. Removed for the time being.
+ (lots): Put back missing assignments to ppc_current_csect.
+
+Tue Sep 26 14:57:59 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (ppc_elf_suffix): Support all of the V.4
+ relocations.
+ (ppc_elf_cons): Remove restriction that @ suffixes must be done
+ with .long. Add error if relocation does not fit in the number of
+ bytes provided.
+ (md_assemble): For absolute branches, map PC relative relocations
+ back into an equivalent absolute relocation.
+ (md_pcrel_from): If TC_FORCE_RELOCATION is true, relocation offset
+ is 0, not segment start.
+ (md_apply_fix3): Don't bother writing addend into the instruction,
+ since it is ignored, given that we use RELA relocations for ELF.
+
+ * config/tc-ppc.h (TC_FORCE_RELOCATION): Define to force all
+ branch prediction relocations to always be emitted.
+
+Mon Sep 25 16:08:43 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (ppc_elf_suffix): Lower case reloc before
+ testing.
+ (md_assemble): Be more robust in terms of relocations.
+ (md_apply_fix3): Allow 14 bit relocs to be emitted for external
+ symbols in addition to 26 bit relocs. Properly insert 26/14 bit
+ reloc value fields into the instruction stream.
+
+Mon Sep 25 00:23:16 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-arm.c (md_atof): Output little endian constants in
+ little endian mode.
+
+ * config/obj-coff.c (obj_coff_section): Pass &type, not type,
+ s_mri_sect.
+
+ * configure.in: Fix typo: fmt-elf to fmt=elf.
+
+Fri Sep 22 16:34:46 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (ppc_elf_suffix): Rewrite to use a table of
+ strings and relocations they represent. Add @br{,n}taken for
+ branch taken/not taken support.
+ (md_apply_fix3): Add BFD_RELOC_PPC_B16_BR{,N}TAKEN support.
+
+Thu Sep 21 21:10:17 1995 Michael Meissner <meissner@cygnus.com>
+
+ * config/tc-ppc.c (md_parse_option): -mrelocatable-lib now only
+ sets EF_PPC_RELOCATABLE_LIB and not also EF_PPC_RELOCATABLE.
+
+Thu Sep 21 16:30:56 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * subsegs.c (subseg_set): Permit SEG_ABSOLUTE in know expression.
+ * expr.c (expr): Account for new operatorT values in know
+ expression.
+
+ * write.c (fixup_segment): Clear fixp->fx_subsy if the relocation
+ is fully resolved.
+
+Thu Sep 21 14:11:49 1995 Michael Meissner <meissner@cygnus.com>
+
+ * config/tc-ppc.c (ppc_flags): New variable to hold the flag bits
+ to set in the ELF header.
+ (md_parse_option): Add support for -mrelocatable-lib. Make both
+ -mrelocatable and -mrelocatable-lib set ppc_flags.
+ (md_begin): Set ELF flags with ppc_flags.
+
+Wed Sep 20 13:01:52 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (maintainer-clean): New target, synonym for
+ realclean. Add GNU standard maintainer-clean echos.
+ * doc/Makefile.in (maintainer-clean): New target, synonym for
+ realclean.
+
+Tue Sep 19 11:31:31 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (m68k_ip): Reject immediate operands for '%'.
+
+ * config/tc-m68k.c (m68k_ip): Reject immediate operands for '|'.
+ Replace 'P' with '0', '1', and '2'.
+
+ * config/tc-m68k.c (parse_mri_control_operand): Change leftstop
+ and rightstop to not be const.
+ (parse_mri_control_expression): Likewise.
+ (build_mri_control_operand): Likewise. Use m68k_ip_op to examine
+ the operand, not m68k_reg_parse.
+ (s_mri_if): In MRI mode, stop at the first '*'.
+ (s_mri_while): Likewise.
+ (s_mri_else): In MRI mode, ignore trailing characters.
+ (s_mri_endi, s_mri_break, s_mri_next, s_mri_for): Likewise.
+ (s_mri_endf, s_mri_repeat, s_mri_until, s_mri_endw): Likewise.
+ * config/m68k-parse.y: Revert yesterday's change.
+ * config/m68k-parse.h: Revert yesterday's change.
+
+Mon Sep 18 15:22:28 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (parse_mri_control_operand): Change leftstart
+ and rightstart to not be const.
+ (parse_mri_control_expression): Likewise.
+ (build_mri_control_operand): Likewise. If the left side of the
+ comparison is a register, and the right side is not, swap the two
+ sides.
+ * config/m68k-parse.y (m68k_reg_parse): Make globally visible.
+ * config/m68k-parse.h (m68k_reg_parse): Declare.
+
+ * read.c (mri_comment_field): New function.
+ (mri_comment_end): New function.
+ (s_align_bytes): Use mri_comment_field.
+ (s_align_ptwo, s_comm, s_mri_common, s_fail, s_globl): Likewise.
+ (s_float_space, s_struct): Likewise.
+ (s_space): Use mri_comment_field rather than doing it by hand.
+ (cons_worker, equals): Likewise.
+ (s_end): Ignore comments starting with '*' or '!'.
+ * read.h (mri_comment_field): Declare.
+ (mri_comment_end): Declare.
+ * cond.c (s_if): Use mri_comment_field.
+ * config/tc-m68k.c (s_chip, s_reg): Likewise.
+
+ * write.c (fixup_segment): Handle ABS-sym in -sym case rather than
+ sym-sym case.
+ * config/obj-coff.c (fixup_segment): Likewise. Permit negative
+ symbols if TC_M68K.
+ * config/tc-m68k.c (tc_coff_fix2rtype): If fx_tcbit is set, return
+ R_RELLONG_NEG.
+ (tc_gen_reloc): If fx_tcbit is set, abort.
+ (md_apply_fix_2): For a negative reloc, move fx_subsy to fx_addsy,
+ and set fx_tcbit.
+
+ * config/tc-m68k.c (s_reg): Ignore comment field in MRI mode.
+
+Mon Sep 18 14:44:04 1995 Arne H. Juul <arnej@pvv.unit.no>
+
+ * configure.in (mips-dec-netbsd*): New target.
+ * configure: Rebuild.
+
+Sun Sep 17 22:17:43 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Set endian to little for mips-*-ultrix*.
+ * configure: Rebuild.
+
+Fri Sep 15 13:16:55 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * expr.c (current_location): New static function. Handle magic
+ symbol `.'; in absolute section, return a constant.
+ (operand): Call current_location for '.' and '$', instead of doing
+ it inline. In MRI mode, call current_location for '*'.
+
+Fri Sep 15 21:39:29 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-m68k.c: Change some "CONST" references to "const".
+
+Fri Sep 15 17:27:41 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ Tue Sep 12 17:08:23 1995 Pat Rankin <rankin@eql.caltech.edu>
+
+ * config/obj-vms.c (VMS_stab_parse): simplify first loop;
+ use S_GET_NAME/modify/S_SET_NAME sequence instead of abusing
+ S_GET_NAME when updating symbol name.
+ (local_symbols_DST): first prefix/postfix typo from July 21st.
+ [plus comment reformatting --kr]
+
+Wed Sep 13 12:33:03 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (EXPECT): New variable.
+ (CHECKFLAGS): Remove.
+ (site.exp): New target.
+ (check): Rewrite to invoke runtest directly, rather than recurring
+ down into testsuite.
+ (clean-here): Remove testsuite directory.
+ (clean, distclean): Don't recur into testsuite.
+ * configure.in: Don't call AC_CONFIG_SUBDIRS(testsuite).
+ * configure: Rebuild.
+
+ * write.c (relax_and_size_seg): Change to the segment we are
+ relaxing, in case md_convert_frag, called by cvt_frag_to_fill,
+ wants to call fix_new.
+ * config/tc-m68k.c (m68k_ip): Permit PC relative code if the
+ segment of the symbol is the current segment, not just in
+ text_section.
+ (md_convert_frag_1): Don't call subseg_change.
+ (md_estimate_size_before_relax): Likewise.
+
+Tue Sep 12 10:36:40 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/tc-arm.c (md_atof): Fix debugging printf, and leave it
+ out by default.
+
+Mon Sep 11 11:39:11 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * doc/configure.in: Remove unused file.
+
+ * app.c (do_scrub_chars): Grab all available spaces at start of
+ line before preserving a single space. Remove state == 0 test
+ which will never succeed.
+ * macro.c (macro_expand_body): Delete local variables from the
+ formal hash table.
+ (macro_expand): In MRI mode, stop when whitespace is seen in the
+ argument list.
+
+ * sb.c: Include "libiberty.h".
+ * macro.c: Likewise. Also include <stdlib.h> if it exists.
+
+Fri Sep 8 00:27:46 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * app.c (do_scrub_chars): In MRI mode, keep a space before a
+ possible comment character.
+ * config/tc-m68k.c (m68k_ip): In MRI mode, ignore anything after
+ an instruction which takes no operands.
+
+ * Makefile.in (install): Don't install gasp in $(tooldir).
+
+ * config/tc-mips.c (macro): Handle a non zero base register for
+ M_U{L,S}{D,W,H}_A.
+
+ * gasp.c (show_usage): Put program_name argument in first fprintf,
+ not second.
+
+Thu Sep 7 12:33:58 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * expr.c (operand): Handle 08 and 09 in MRI mode.
+ * macro.c (ISSEP): Remove duplicated `"' character.
+ (get_any_string): Copy some characters for which ISSEP is true:
+ ';', '>', '(', ')'. Otherwise we can get in an infinite loop.
+ * read.c (s_space): In MRI mode, the expressions stop at the first
+ unquoted space.
+ (cons_worker): In MRI mode, restore the terminating character at
+ the end of the function.
+
+ * read.c (cons_worker): Don't use #elif; old compilers don't
+ support it.
+
+Wed Sep 6 21:13:06 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * app.c (do_scrub_chars): In MRI mode, silently end quoted strings
+ at newline characters. In MRI mode, always keep spaces in the
+ operands field. In MRI mode, treat a line comment character as a
+ regular comment character following a space.
+ * cond.c (ignore_input): Use strncasecmp rather than strncmp when
+ looking for special pseudo-ops.
+ * read.c (cons_worker): In MRI mode, the expressions stop at the
+ first unquoted space.
+ (equals): Likewise.
+
+Wed Sep 6 15:03:53 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * config/tc-sh.c (get_operands): Read third arg if it exists.
+ Otherwise, clear it.
+ (get_specific, case F_FR0): Add.
+
+Wed Sep 6 15:03:53 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * config/tc-sh.c (get_specific): Delete arg_to_test.
+ (md_assemble): Increase operand array from 2 to 3.
+
+Tue Sep 5 16:47:36 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * config/tc-mips.c: Remove CYGNUS LOCAL comments.
+ (md_begin): Use 0/1 instead of TRUE/FALSE.
+ (md_show_usage): Break up long format string for the benefit
+ of lame compilers.
+ * config/tc-m68k.c (md_show_usage): Ditto.
+ * gasp.c (show_usage): Ditto.
+ * macro.c (check_macro): Cast result of hash_find.
+
+Tue Sep 5 14:46:38 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * configure.in: When testing for a free() declaration in system
+ header files, cast the address to a function pointer, not to an
+ integer.
+
+ * write.c (fix_new_internal): Call TC_INIT_FIX_DATA if TC_FIX_TYPE
+ is defined. Don't initialize fx_bsr. Verify that fx_size field
+ is wide enough to hold stored value.
+ * write.h (struct fix): Change tc_fix_data to type TC_FIX_TYPE if
+ that is defined, otherwise omit it. Delete fx_bsr. Change
+ fx_size to unsigned char.
+ * config/tc-i960.h (TC_FIX_TYPE, fx_bsr, TC_INIT_FIX_DATA): New
+ macros.
+ * config/tc-ns32k.h (TC_FIX_TYPE, fx_bsr, TC_INIT_FIX_DATA): New
+ macros.
+ * config/tc-hppa.h (TC_FIX_TYPE): Define as PTR.
+
+ * config/tc-i860.c (md_apply_fix): Delete code for checking
+ fx_im_disp, and for handling non-zero values, since it never gets
+ set after being initialized to zero.
+
+ * write.h (struct fix): Make fx_im_disp always 2 bits, since the
+ only tc-* files actually using it need that much.
+
+ NS32K changes from Ian Dall:
+ * configure.in: Treat ns32k-pc532-ux* like ns32k-pc532-mach*, and
+ ns32k-pc532-lites* like ns32k-pc532-netbsd*.
+ * config/tc-ns32k.h (LOCAL_LABELS_FB): Define to 1.
+
+Fri Sep 1 17:02:15 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * write.c (fixup_segment): Get TC_FORCE_RELOCATION up the
+ right way!
+
+Fri Sep 1 08:20:19 1995 James G. Smith <jsmith@beauty.cygnus.com>
+
+ * config/tc-mips.c (md_parse_option, md_begin, md_show_usage):
+ Add support for "-mcpu=vr4300" as processor identifier.
+
+Thu Aug 31 16:41:06 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * write.c (fixup_segment): Remove change of 29th.
+ * config/tc-{i386,arm}.h (TC_FORCE_RELOCATION): Keep RVA relocs.
+
+Tue Aug 29 19:42:58 1995 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * config/tc-m68k.c (m68k_ip) [case POST/PRE/BASE]: Fix typo when
+ looking at outer displacement. Don't set the postindex bit if the
+ index suppress bit is set (for memory indirect addressing mode).
+
+Thu Aug 31 06:49:37 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/tc-arm.c (tc_gen_reloc): Delete duplicated code.
+
+Wed Aug 30 23:51:57 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * app.c (do_scrub_chars): Free saved_input when the from buffer
+ exactly fills the to buffer.
+
+Wed Aug 30 13:46:39 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/tc-sparc.c (parse_keyword_arg, parse_const_expr_arg): New fns.
+ (sparc_ip): Call them for asi, membar, and prefetch parsing.
+
+Tue Aug 29 15:45:37 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/tc-sparc.c (membar_masks): Deleted.
+ (sparc_ip): Clean up ASI and membar support.
+
+Tue Aug 29 13:20:27 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * read.c (potable): Rva is new entry.
+ (cons_worker): New, split from cons. Handles rva.
+ (cons, s_rva): Call cons_worker.
+ * read.h (s_rva): New declaration.
+ * write.c (fixup_segment): Don't throw away rva relocs.
+ * config/tc-arm.c (md_apply_fix, tc_gen_reloc): Handle RVA.
+ * config/tc-i386.c (tc_coff_fix2type): Handle RVA.
+ * config/tc-i386.h (TC_COUNT_RELOC): Remember RVAs.
+ (TC_RVA_RELOC): New definition.
+
+Sun Aug 27 17:41:05 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/tc-arm.c (do_swi): Allow optional leading '#'.
+
+Sat Aug 26 17:24:20 1995 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/tc-m68k.c (comment_chars): If TE_DELTA is defined,
+ include '#'.
+ * config/tc-m68k.h (NO_PSEUDO_DOT): Define if TE_DELTA is
+ defined.
+
+ * config/te-delta.h: Include obj-format.h.
+ * config/te-sco386.h: Likewise.
+ * config/te-sysv32.h: Likewise.
+
+ * app.c (scrub_file): Remove.
+ (scrub_from_file, scrub_to_file): Remove.
+ (scrub_string, scrub_last_string): Remove.
+ (scrub_from_string, scrub_to_string): Remove.
+ (saved_input, saved_input_len): New static variables.
+ (struct app_saved): Remove scrub_string, scrub_last_string, and
+ scrub_file fields. Add saved_input and saved_input_len fields.
+ (app_push): Adjust saved fields for changes in struct app_save.
+ Initialize state and saved_input.
+ (app_pop): Adjust saved fields for changes in struct app_save.
+ (do_scrub_chars): Rename from do_scrub_next_char and rewrite to
+ process a buffer at a time rather than a character at a time.
+ (main, as_warn): Remove obsolete testing code.
+ * as.h (do_scrub_next_char): Don't declare.
+ (do_scrub_chars): Declare.
+ (scrub_from_file, scrub_from_string): Don't declare.
+ (scrub_to_file, scrub_to_string): Don't declare.
+ * input-file.c (input_file_get): New static function.
+ (input_file_give_next_buffer): Call do_scrub_chars rather than
+ do_scrub_next_char.
+ * read.c (scrub_string, scrub_string_end): New static variables.
+ (scrub_from_string): New static function.
+ (read_a_source_file): Call do_scrub_chars rather than
+ do_scrub_next_char.
+
+Thu Aug 24 18:50:19 1995 Ian Lance Taylor (ian@cygnus.com)
+
+ * gasp.c (as_abort): New function.
+ * sb.c (sb_build): Revert yesterday's patch.
+
+ * Makefile.in (gasp.new): Depend upon ../libiberty/libiberty.a.
+ Just link against libiberty, not against $(LIBS).
+
+Wed Aug 23 15:18:20 1995 Ian Lance Taylor (ian@cygnus.com)
+
+ * sb.c (sb_build): Undefine abort before calling it, since gasp
+ does not provide as_abort.
+
+Wed Aug 23 10:40:41 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (set_target_endian): New static to say whether
+ we've initialized target_big_endian or not.
+ (md_parse_option): Set set_target_endian if we set the variable
+ target_big_endian.
+ (md_begin): Only set target_big_endian if !set_target_endian.
+
+Tue Aug 22 03:00:33 1995 Ken Raeburn <raeburn@kr-laptop.cygnus.com>
+
+ Sat Aug 19 18:08:16 1995 Pat Rankin <rankin@eql.caltech.edu>
+
+ * config/obj-vms.h (DST_S_C_SRC_SETREC_W, DST_S_C_SRC_DEFLINES_B):
+ New macros.
+ * config/obj-vms.c (VMS_TBT_Line_PC_Correlation,
+ VMS_TBT_Source_Lines): Make traceback info be robust enough to
+ handle huge source files.
+ (VMS_TBT_Source_File): Reorganize the native- vs cross-assembly
+ support so that actual object file output is clearer.
+ (VMS_TBT_Source_File: Fab, Nam, Date_Xab, File_Header_Xab):
+ Replace static variables with automatic ones.
+
+ Sat Aug 12 20:18:15 1995 Pat Rankin <rankin@eql.caltech.edu>
+
+ * config/obj-vms.c (Module_Name): new file scope variable.
+ (VMS_TBT_Module_Begin): use it instead of local variable.
+ (Write_VMS_MHD_Records): ditto; assign its value here.
+ (Write_VMS_EOM_Record): second argument has type valueT.
+ (VMS_Initialized_Data_Size): simplify search loop; return
+ type is offsetT; second argument is unsigned.
+
+ Sat Jun 17 19:05:25 1995 Pat Rankin (rankin@eql.caltech.edu)
+
+ * messages.c (as_perror): Use xstrerror instead of strerror.
+
+Mon Aug 21 13:57:20 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * as.c (parse_args): Accept --defsym SYM=VALUE.
+ * doc/as.texinfo, doc/as.1: Document --defsym.
+
+ * read.c (read_a_source_file): In MRI mode, don't end the
+ statement inside a quotation.
+ (s_space): Don't warn about a zero repeat count in MRI mode.
+ * config/tc-m68k.c (crack_operand): In MRI mode, don't count
+ parentheses inside quotes.
+ (md_assemble): In MRI mode, anything after the operands field is a
+ comment.
+ (parse_mri_control_operand): Adjust start and stop to remove
+ spaces.
+ (s_mri_for): Likewise.
+
+ * cond.c (s_ifdef): Restore the character after the symbol name,
+ in case it is a newline.
+ (s_if): If ignoring the current tree, don't try to parse the
+ expression.
+
+ * app.c (do_scrub_next_char): If LEX_IS_STRINGQUOTE or
+ LEX_IS_ONECHAR_QUOTE is seen in state 10, preserve one space.
+
+ * doc/as.texinfo: Document irp, irpc, macro, and rept. MRI mode
+ now supports macros, ifc, ifnc, irp, irpc, rept, and endr, without
+ using gasp.
+
+ Add support for macros.
+ * as.c: Include sb.h and macro.h.
+ (max_macro_next): New global variable.
+ (main): Call macro_init.
+ (macro_expr): New static function.
+ * as.h (max_macro_nest): Declare.
+ * read.c (line_label): Rename from mri_line_label. Change all
+ uses.
+ (potable): Add exitm, irp, irpc, macro, mexit, rept.
+ (read_a_source_file): Always clear line_label at the start of a
+ line, not just when flag_mri or LABELS_WITHOUT_COLONS. Fix
+ MRI/LABELS_WITHOUT_COLONS handling. In MRI mode, permit label:
+ equ val. Set line_label when calling colon. In MRI mode, a
+ leading '.' does not imply a pseudo-op. Check for macro expansion
+ before calling md_assemble.
+ (s_irp): New function.
+ (get_line_sb): New static function.
+ (s_macro): New function.
+ (s_mexit): New function.
+ (s_rept): New function.
+ * read.h (line_label): Rename from mri_line_label.
+ (s_irp, s_rept): Declare.
+ (s_macro, s_mexit): Declare.
+ * input-scrub.c: Include sb.h.
+ (sb_index, from_sb): New static variables.
+ (macro_nest): New static variable.
+ (struct input_save): Add sb_index and from_sb fields. Change
+ next_saved_file field to be struct input_save *.
+ (next_saved_file): Changed to be struct input_save *.
+ (input_scrub_push): Change to return type struct input_save *.
+ Save sb_index and from_sb.
+ (input_scrub_pop): Change parameter type to struct input_save *.
+ Restore sb_index and from_sb.
+ (input_scrub_include_sb): New function.
+ (input_scrub_next_buffer): Handle reading from from_sb.
+ (bump_line_counters): Only increment lines if not using from_sb.
+ * config/tc-m68k.c (opt_table): Add nest.
+ (opt_nest): New static function.
+ * gasp.c: Include sb.h and macro.h. Move all sb related functions
+ and definitions to sb.h and sb.c. Move all macro related
+ functions and definitions to macro.h and macro.c.
+ * sb.h, sb.c: New files, extracted from gasp.c.
+ * macro.h, macro.c: Likewise.
+ * Makefile.in (OBJS): Add sb.o and macro.o
+ (GASPOBJS): Define.
+ (gasp.new): Depend upon $(GASPOBJS). Use $(GASPOBJS) to link.
+ (TARG_CPU_DEP_m68k): Depend upon subsegs.h.
+ (gasp.o): Depend upon sb.h and macro.h.
+ (sb.o): New target.
+ (macro.o): New target.
+ (as.o): Depend upon sb.h and macro.h.
+ (input-scrub.o): Depend upon sb.h.
+ (read.o): Depend upon sb.h and macro.h.
+
+ * cond.c (get_mri_string): New static function.
+ (s_ifc): New function.
+ * read.c (potable): Add ifc and ifnc.
+ * read.h (s_ifc): Declare.
+
+ * app.c (do_scrub_begin): In MRI mode, set lex of ' to
+ LEX_IS_STRINGQUOTE.
+
+Mon Aug 21 13:41:33 1995 Michael Meissner <meissner@cygnus.com>
+
+ * config/tc-ppc.c (md_assemble): Allow @HA, @L, and @H suffixes on
+ constant expressions.
+
+Sun Aug 20 15:54:37 1995 Jim Wilson <wilson@cygnus.com>
+
+ * config/tc-arm.c (md_reloc_size): Add const to declaration.
+
+Fri Aug 18 10:58:09 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.c (s_include): In MRI mode, don't expect quotes around the
+ file name.
+ * listing.c (listing_title): Don't require the title to be quoted.
+
+ * gasp.c (include_print_where_line): Always subtract 1 from
+ linecount before printing it.
+ (process_file): In MRI mode, lines beginning with '*' or '!' are
+ comments.
+ (do_reg): In MRI mode, don't require parentheses.
+ (do_include): In MRI mode, don't requires quotes. If the file can
+ not be found in the include path, try opening it in the current
+ directory. Print the file name correctly in the error message.
+ (chartype_init): In MRI mode, set FIRSTBIT for '.'.
+ (main): Set comment_char to ';' when entering MRI mode.
+
+ * config/tc-m68k.c: Include subsegs.h.
+ (m68k_ip): Pass 64 rather than -1 to add_Fix in 'B' 'B' case.
+ (md_pcrel_from): If fx_pcrel_adjust is 64, use -1 instead.
+
+ * config/tc-sparc.h (tc_fix_adjustable): For OBJ_AOUT case, adjust
+ BFD_RELOC_16 and BFD_RELOC_32 relocs.
+
+Wed Aug 16 14:48:44 1995 Ken Raeburn <raeburn@kr-laptop.cygnus.com>
+
+ * as.h (alloca): Use void* declaration on HP/UX.
+
+Wed Aug 16 12:49:17 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sparc.c (tc_gen_reloc): If PIC, only change PCREL_S2
+ to WPLT30 for an undefined or external symbol. Don't consider
+ PC10 or PC22 to be a PC relative reloc when choosing between
+ fx_addnumber and fx_offset.
+
+ * config/tc-z8k.c (md_number_to_chars): Don't do it here, call
+ number_to_chars_bigendian.
+ * config/tc-z8k.h (TARGET_BYTES_BIG_ENDIAN): Define.
+
+ * expr.c (operand): Add support for .startof. and .sizeof. by
+ using magic symbol names which the linker will recognize
+ specially.
+ * doc/as.texinfo: Take out note that .startof. and .sizeof. are
+ not supported.
+
+Tue Aug 15 15:08:49 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (md_pseudo_table): Add MRI structured control
+ directives: if, if.b, if.w, if.l, else, else.s, else.l, endi,
+ break, break.s, break.l, next, next.s, next.l, for, for.b, for.w,
+ for.l, endf, repeat, until, until.b, until.w, until.l, while,
+ while.b, while.w, while.l, endw.
+ (enum mri_control_type): Define.
+ (struct mri_control_info): Define.
+ (mri_control_stack): New static variable.
+ (mri_control_index): New static variable.
+ (mri_control_label): New static function.
+ (push_mri_control, pop_mri_control): New static functions.
+ (parse_mri_condition): New static function.
+ (parse_mri_control_operand): New static function.
+ (swap_mri_condition, reverse_mri_condition): New static functions.
+ (build_mri_control_operand): New static function.
+ (parse_mri_control_expression): New static function.
+ (s_mri_if, s_mri_else, s_mri_endi): New static functions.
+ (s_mri_break, s_mri_next): New static functions.
+ (s_mri_for, s_mri_endf): New static functions.
+ (s_mri_repeat, s_mri_until): New static functions.
+ (s_mri_while, s_mri_endw): New static functions.
+ * gasp.c (mrikinfo): Remove IF.
+ * expr.c (get_symbol_end): Accept \001 as part of a name.
+
+ * symbols.c (colon): Change parameter to const char *.
+ * symbols.h (colon): Update declaration.
+
+Mon Aug 14 20:51:56 1995 Ken Raeburn <raeburn@kr-laptop.cygnus.com>
+
+ * write.c (write_contents): Always do it the BFD_FAST_SECTION_FILL
+ way. Reformat and reindent that code to GNU standards.
+ (BFD_FAST_SECTION_FILL): Don't define.
+
+Mon Aug 14 14:08:07 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (md_apply_fix): Don't try to apply BEGIN_BRTAB
+ or END_BRTAB fixups.
+
+Mon Aug 14 15:45:07 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * gasp.c (do_align, get_any_string): Mark as static.
+ (do_assigna, do_assignc, new_file): Likewise.
+
+ * config/tc-m68k.c (s_reg): Rename local op to rop to avoid
+ confusion with macro op.
+
+ * gasp.c (strip_comments): Comment out; it's not used.
+ (do_end): Add parameter. In MRI mode, print it out.
+ (do_irp): New static function.
+ (sub_actual): Change parameter m to formal_hash, changing type
+ from macro_entryh * to hash_table *.
+ (macro_expand_body): New static function, broken out of
+ macro_expand.
+ (macro_expand): Call macro_expand_body.
+ (K_*): Fully parenthesize.
+ (K_IRP, K_IRPC): Define.
+ (mrikinfo): Add IRP and IRPC.
+ (process_pseudo_op): In MRI mode, print out END pseudo-op. Pass
+ line to do_end. Handle K_IRP and K_IRPC.
+
+ * config/tc-m68k.c (s_opt): Reset *input_line_pointer even if we
+ don't do anything with the option.
+
+Sun Aug 13 17:03:58 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * frags.c (frag_align): Handle absolute_section.
+ * write.c (record_alignment): Likewise.
+
+ * config/tc-mips.c (macro_build): Skip insns with an inappropriate
+ ISA level.
+
+Sun Aug 13 00:35:02 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (md_pseudo_table): Add entries for
+ "begin_brtab" and "end_brtab" pseudo-ops.
+ (pa_brtab): New function.
+ (tc_gen_reloc, SOM version): Handle R_BEGIN_BRTAB and R_END_BRTAB.
+ (hppa_force_relocation): Force relocations for BRTAB fixups
+ when OBJ_SOM is defined.
+
+Fri Aug 11 20:34:05 1995 Ken Raeburn <raeburn@kr-laptop.cygnus.com>
+
+ * Makefile.in (TE_OBJS): Add empty definition.
+
+Fri Aug 11 19:16:08 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * gasp.c (change_base): Don't treat ' specially in MRI mode.
+ (process_file): Don't warn about missing END in MRI mode.
+ (do_if): New static function.
+ (get_mri_string, do_ifc): New static functions.
+ (buffer_and_nest): Treat MRI mode like alternate syntax mode.
+ (do_aendr): Change error message in MRI mode.
+ (do_arepeat): Use REPT/ENDR in MRI mode.
+ (do_formals): In MRI mode, add special NARG formal.
+ (macro_expand): Various changes for MRI mode: permit a qualifier
+ on the macro name; set special NARG formal; permit unnamed
+ positional arguments; use && to concatenate named parameters;
+ permit \d to specify an unnamed parameter; permit named parameters
+ to not start with \; use == to see if a parameter exists.
+ (getstring): In MRI mode, allow <> to quote a string.
+ (K_IFEQ, K_IFNE, K_IFLT, K_IFLE, K_IFGE, K_IFGT): Define.
+ (K_IFC, K_IFNC): Define.
+ (struct keyword): Name structure used in kinfo array.
+ (mrikinfo): New static array.
+ (process_pseudo_op): Don't require leading '.' in MRI mode.
+ Handle new MRI pseudo-op definitions.
+ (add_keyword): New static function, broken out of process_init.
+ (process_init): Use add_keyword. In MRI mode, add mrikinfo table.
+ (long_options): Add "mri".
+ (show_usage): Mention -M/--mri.
+ (main): Call process_init after processing arguments. Handle -M.
+ * doc/gasp.texi: Document -M/--mri.
+
+ * gasp.c: Include ansidecl.h. Make all local functions static.
+ Add prototypes for all static functions.
+ (mri): New global variable.
+ (sb_add_char): Change parameter c from char to int.
+ (sb_add_string): Make parameter s into a const pointer.
+ (sb_add_buffer): Likewise.
+ (checkconst): Change parameter op from char to int.
+ (exp_get_abs): Make parameter emsg into a const pointer.
+ (do_res): Change parameter type from char to int.
+ (buffer_and_nest): Make parameters from and to into const
+ pointers.
+ (do_sdata): Change parameter type from char to int.
+ (new_file): Make parameter name into a const pointer.
+ (do_define): Make parameter string into a const pointer.
+
+ * config/tc-h8300.c (md_number_to_chars): Don't do it here, call
+ number_to_chars_bigendian.
+ * config/tc-h8300.h (TARGET_BYTES_BIG_ENDIAN): Define.
+
+Fri Aug 11 13:23:56 1995 Michael Meissner <meissner@cygnus.com>
+
+ * write.h (struct fix): Add new field fx_no_overflow.
+
+ * write.c (fixup_segment): If fx_no_overflow is non-zero, don't
+ complain if the addend is too large.
+
+ * config/tc-ppc.c (md_assemble): Set fx_no_overflow if the half
+ word relocations BFD_RELOC_{LO16,HI16,HI16_S}.
+
+Thu Aug 10 20:56:38 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * read.c (s_mri_sect) [BFD_ASSEMBLER]: Fix typos in choosing and
+ setting section flags.
+
+Thu Aug 10 00:38:11 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * doc/as.texinfo: Add documentation for MRI compatibility mode.
+ * doc/as.1: Likewise.
+
+ * config/tc-m68k.c (m68k_ip): When recognizing '#', use isbyte and
+ iword rather than expr8 and expr16. When recognizing 'M', use
+ issbyte rather than expr8. When recognizing 'Q' and 't', just
+ check for O_constant rather than using expr8.
+ * config/m68k-parse.h (expr8, expr16): Don't define.
+ * Makefile.in (m68k-parse.o): Depend upon m68k-parse.h, not
+ m68k-parse.y.
+
+ * read.c (potable): Add spc, ttl, xcom, xref.
+ (s_mri_sect): New function.
+ * read.h (s_mri_sect): Declare.
+ * config/obj-coff.c (obj_coff_section) (both versions): In MRI
+ mode, call s_mri_sect.
+ (obj_pseudo_table): Add sect.s and section.s. Move sect outside
+ of ifndef BFD_ASSEMBLER.
+ * config/obj-elf.c (elf_pseudo_table): Add section.s, sect,
+ sect.s.
+ (obj_elf_section): In MRI mode, call s_mri_sect.
+ * config/tc-m68k.c (md_pseudo_table): Add restore, save.
+ (struct save_opts): Define.
+ (save_stack): New static variable.
+ (s_save, s_restore): New static functions.
+
+ * read.c (s_set): Remove unused local ptr.
+ (hex_float): Check target_big_endian.
+ (equals): Remove unused local p.
+
+ * config/tc-a29k.h (TARGET_BYTES_BIG_ENDIAN): Define.
+ * config/tc-h8500.h (TARGET_BYTES_BIG_ENDIAN): Define.
+ * config/tc-hppa.h (TARGET_BYTES_BIG_ENDIAN): Define.
+ * config/tc-i860.h (TARGET_BYTES_BIG_ENDIAN): Define.
+ * config/tc-m68k.h (TARGET_BYTES_BIG_ENDIAN): Define.
+ * config/tc-m88k.h (TARGET_BYTES_BIG_ENDIAN): Define.
+ * config/tc-tahoe.h (TARGET_BYTES_BIG_ENDIAN): Define.
+ * config/tc-sh.c (little): Set target_big_endian.
+ (md_begin): Likewise.
+ (md_parse_option): Likewise.
+ (build_relax): Check target_big_endian rather than shl.
+ (build_Mytes, md_atof): Likewise.
+ (md_convert_frag, md_apply_fix): Likewise.
+ (md_number_to_chars): Likewise.
+
+Wed Aug 9 10:51:48 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (m68k_abspcadd): New static variable.
+ (m68k_quick): New static variable.
+ (m68k_rel32): New static variable.
+ (md_pseudo_table): Add opt and reg.
+ (m68k_ip): Permit absolute symbols in 'l'/'L' recognition. Check
+ m68k_quick in 'M' and 'Q' recognition. Check m68k_abspcadd in
+ DISP handling. Check m68k_rel32 in BASE/POST/PRE handling.
+ (md_begin): In MRI mode, initialize m68k_abspcadd and m68k_rel32.
+ In MRI mode, change unsized branch aliases to be variable sized.
+ (struct opt_action): Define.
+ (opt_table): Define.
+ (s_opt): New static function.
+ (skip_to_comma): New static function.
+ (opt_chip): New static function.
+ (opt_list): New static function.
+ (opt_list_symbols): New static function.
+ (s_reg): New static function.
+ * as.h (flag_keep_locals): Change from unsigned char to int.
+ (flag_no_warnings): Likewise.
+
+ * read.c (mri_line_label): Make non-static.
+ (potable): Add nopage, page, plen.
+ (s_org): Error if in MRI mode.
+ * read.h (mri_line_label): Declare.
+ * listing.c (listing_nopage): New function.
+ * listing.h (listing_nopage): Declare.
+
+ * symbols.c (symbol_begin): Set sy_frag of abs_symbol to
+ &zero_address_frag.
+
+ * write.c (adjust_reloc_syms): Check that symbol is not NULL
+ before checking sy_mri_common.
+ (fixup_segment): Likewise.
+ * config/obj-coff.c (fixup_segment): Likewise.
+
+ * read.c (abs_section_offset): New global variable.
+ (potable): Add offset, struct.
+ (do_org): New static function; handle changing the origin in the
+ absolute section.
+ (s_org): Use do_org.
+ (s_set): Likewise.
+ (equals): Likewise.
+ (s_space): In absolute_section, just increase abs_section_offset.
+ (s_struct): New function.
+ (emit_expr): Handle absolute_section specially.
+ * read.h (abs_section_offset): Declare.
+ (s_struct): Declare.
+ * frags.c (frag_more): Warn if in absolute_section.
+ (frag_now_fix): In absolute_section, return abs_section_offset.
+ * subsegs.c (subseg_change): If switching to absolute_section,
+ just set now_seg and now_subseg.
+ (subseg_set_rest): Special handling when switching to or from
+ absolute_section.
+
+ * config/tc-m68k.c (m68k_float_copnum): New static variable.
+ (md_pseudo_table): Add fopt and mask2.
+ (m68k_ip): Use m68k_float_copnum, not COPNUM, when setting
+ coprocessor register to use. In case 'I' when checking operands,
+ correct coprocessor register numbers. In case 'I' when setting
+ operands, don't add 1.
+ (s_fopt): New static function.
+ * config/m68k-parse.h (COPNUM): Don't define.
+
+ * read.c (potable): Add ifeq, ifge, ifgt, ifle, iflt, ifne.
+ Change if to pass O_ne to s_if.
+ (read_a_source_file): Don't define an label without a colon if
+ ignore_input returns true.
+ * cond.c (s_if): Treat argument as an operatorT describing how to
+ compare the argument against zero.
+ (ignore_input): Don't require an initial dot in MRI mode, or if
+ NO_PSEUDO_DOT is defined.
+
+ * read.c (potable): Add dcb, dcb.b, dcb.d, dcb.l, dcb.s, dcb.w,
+ dcb.x, ds.d, ds.p, ds.s, ds.x, elsec, endc, fail, format, llen,
+ noformat.
+ (read_a_source_file): If pseudo-op handler is s_end, quit
+ immediately.
+ (s_end): New function.
+ (s_fail): New function.
+ (s_float_space): New function.
+ (hex_float): New static function.
+ (float_cons): Use hex_float.
+ * read.h (s_fail): Declare.
+ (s_float_space): Declare.
+ * cond.c (s_end): Remove.
+ * listing.c (listing_psize): Treat argument as indicating whether
+ a height is expected.
+
+ * read.c (mri_pending_align): New static variable.
+ (read_a_source_file): Handle mri_pending_align.
+ (cons): Set mri_pending_align if appropriate.
+
+ * configure.in: Move random special target handling before
+ possible break.
+ * configure: Rebuild.
+
+Tue Aug 8 23:41:25 1995 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * configure.in: Consistently use ${target_cpu_type} rather than
+ ${cpu_type} after the loop.
+ * configure: Rebuild.
+ * Makefile.in (targ-cpu.o): Use @target_cpu_type@ rather than
+ @cpu_type@.
+
+Tue Aug 8 17:27:17 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * expr.h (operatorT): Remove comma after last enumerator value.
+
+ * config/obj-vms.c: Some whitespace cleanup from Pat Rankin.
+
+ * as.h (alloca): If __STDC__, declare void* instead of char*.
+
+ Wed Aug 2 18:54:37 1995 Pat Rankin <rankin@eql.caltech.edu>
+
+ * config/obj-vms.c (Flush_VMS_Object_Record_Buffer,
+ Close_VMS_Object_File): Reorganize the `#if !VMS' cross-assmebler
+ support code.
+ (Close_VMS_Object_File): Call Set_VMS_Object_File_Record to flush
+ output buffer--just in case--before closing the file.
+
+Tue Aug 8 13:07:05 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (archs): Add 68ec000, 68hc000, 68hc001,
+ 68ec020, 68ec030, 68ec040, and 68330.
+ (md_pseudo_table): Add chip and comline.
+ (m68k_init_after_args): Use strcasecmp when comparing default_cpu
+ against architectures.
+ (mri_chip, s_chip): New static functions.
+
+ * struc-symbol.h (struct symbol): Add sy_mri_common bit.
+ * read.h (mri_comon_symbol): Declare.
+ (s_mri_common): Declare.
+ * read.c (mri_line_label): New static variable.
+ (mri_common_symbol): New global variable.
+ (potable): Add "common" and "common.s".
+ (read_a_source_file): In MRI mode, set mri_line_label for a label
+ at the start of a line.
+ (s_mri_common): New function.
+ (s_space): Handle mri_common_symbol.
+ * symbols.c (colon): Change return value from void to symbolS *,
+ and return new symbol. If mri_common_symbol is set, attach the
+ new symbol to it.
+ (resolve_symbol_value): Handle an sy_mri_common symbol.
+ * symbols.h (colon): Change return value in declaration.
+ * subsegs.c (subseg_set_rest): Clear mri_common_symbol.
+ (subseg_set (both versions)): Likewise.
+ * frags.c (frag_more): Warn if mri_common_symbol is not NULL.
+ * write.c (adjust_reloc_syms): Skip sy_mri_common symbols.
+ (write_object_file): Discard sy_mri_common symbols.
+ (fixup_segment): Change relocations against sy_mri_common symbols
+ to be against the common symbol itself.
+ * config/obj-coff.c (yank_symbols): Discard sy_mri_common symbols.
+ (fixup_segment): Change relocations against sy_mri_common symbols
+ to be against the common symbol itself.
+ * config/obj-aout.c (obj_crawl_symbol_chain): Discard
+ sy_mri_common symbols.
+
+ * doc/c-m68k.texi: Add documentation for CPU specific options, and
+ for Motorola syntax.
+
+ * config/m68k-parse.y (motorola_operand): For (%pc), set mode to
+ DISP, not BASE.
+
+Tue Aug 8 02:31:38 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * write.c (relax_align): Add extra padding for linkrelax only if
+ LINKER_RELAXING_SHRINKS_ONLY is defined.
+ * config/tc-i960.h (LINKER_RELAXING_SHRINKS_ONLY): Define it.
+ * doc/internals.texi (Relaxation): Write up some stuff on linker
+ relaxing and LINKER_RELAXING_SHRINKS_ONLY.
+
+Mon Aug 7 17:18:10 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/m68k-parse.y: New file: bison grammar for m68k operands,
+ including support for Motorola syntax.
+ * config/m68k-parse.h: New file; definitions shared between
+ m68k-parse.y and tc-m68k.c.
+ * config/tc-m68k.c: Include m68k-parse.h.
+ (enum operand_type): Move to m68k-parse.h, where it is named
+ m68k_operand_type. Rename all uses. Rearrange somewhat. Add
+ FPREG. Rename AOFF to DISP. Rename AINDX to BASE. Rename APODX
+ to POST. Rename APRDX to PRE. Remove AMIND. Rename MSCR to
+ CONTROL. Remove DINDR.
+ (struct m68k_exp): Move to m68k-parse.h. Remove e_beg, e_end and
+ e_seg fields. Rename e_exp to exp. Rename e_siz to size, and
+ change type to enum m68k_size. Change all uses.
+ (enum _register): Move to m68k-parse.h, where it is named
+ m68k_register. Rename all uses. Add ZDATA0-7 and ZADDR0-7.
+ (struct m68k_op): Move to m68k-parse.h. Change all fields.
+ (seg): Don't define.
+ (add_exp): Remove.
+ (FAIL, OK): Remove.
+ (m68k_reg_parse): Move to m68k-parse.y, and rewrite.
+ (SKIP_WHITE, SKIP_W): Remove.
+ (try_moto_index, try_index): Remove.
+ (m68k_ip_op): Move to m68k-parse.y, and rewrite to use grammar.
+ (main): Remove obsolete test function.
+ (m68k_ip): Extensive changes to use new grammar.
+ (get_regs): Remove.
+ (crack_operand): m68k_ip_op now returns 0 on success.
+ (init_table): Add ssp, zd0-7 and za0-7.
+ (md_assemble): Make er const. Correct loop over operands when
+ looking for error message.
+ (md_begin): Set alt_notend_table for '(' and '@'.
+ (get_num): Expression is already parsed. Don't set seg.
+ * configure.in: If cpu_type is m68k, put m68k-parse.o in
+ extra-objects.
+ * configure: Rebuild.
+ * Makefile.in (DISTSTUFF): Add m68k-parse.c.
+ (BISON): Use ../bison/bison if it exists.
+ (BISONFLAGS): Define as empty.
+ (TARG_CPU_DEP_m68k): Depend upon $(srcdir)/config/m68k-parse.h.
+ (m68k-parse.c, m68k-parse.o): New targets.
+
+Mon Aug 7 02:54:20 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-sh.c (parse_reg): Handle new FP registers.
+ (get_specific): Handle new operand types.
+
+Fri Aug 4 12:29:21 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * expr.c (op_encoding): Make non-const. Don't set '"' to
+ O_bit_not.
+ (expr_begin): Set op_encoding['"'] in MRI mode.
+
+Wed Aug 2 18:39:43 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c: Remove BREAK_UP_BIG_DECL stuff.
+ (struct m68k_incant): Change m_operands field to be const.
+ (struct m68k_it): Change args field to be const.
+ (m68k_ip): Change local variable s to be const.
+ (opcode_ptr): Remove.
+ (md_begin): Use m68k_numopcodes, not numopcodes. Use
+ m68k_opcodes, not removed opcode_ptr. Use m68k_numaliases, not
+ numaliases.
+
+Tue Aug 1 17:35:26 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (init_table): Add "control", "status", "iaddr",
+ "sfcr", and "dfcr" as synonyms for existing entries.
+ (md_begin): In MRI mode, force flag_reg_prefix_optional to 1.
+ (md_parse_option): Removed unused locals i and arch. Change type
+ of arch (another one) to unsigned long.
+ (tc_coff_sizemachdep): Add return after abort to avoid warning.
+
+ Initial support for MRI style labels and expressions.
+ * as.h (flag_mri): Declare/define.
+ * as.c (show_usage): Mention -M and its synonym --mri.
+ (parse_args): Add 'M' to std_shortopts. Add "mri" to
+ std_longopts. Set flag_mri if -M is seen.
+ (main): Call parse_args before input_scrub_begin. Call
+ expr_begin.
+ * app.c (do_scrub_begin): Don't set lex for '"' or '\'' in MRI
+ mode. Do set lex for ';', '*', and '!' in MRI mode.
+ (do_scrub_next_char): Remove MRI ifdef in LEX_IS_WHITESPACE case.
+ In MRI mode, keep spaces between labels and colons. Remove MRI
+ ifndef around LEX_IS_ONECHAR_QUOTE case. In MRI mode, don't use
+ '!' or '*' as comment characters even if they are in
+ comment_chars.
+ * read.h (lex_type): No longer const.
+ * read.c: Include libiberty.h.
+ (lex_type): No longer const.
+ (read_begin): In MRI mode, set lex_type of '?' to 3.
+ (potable): Add dc, dc.b, dc.d, dc.l, dc.s, dc.w, dc.x, ds, ds.b,
+ ds.l, ds.w, and xdef.
+ (read_a_source_file): Change LABELS_WITHOUT_COLON ifdef to check
+ for MRI mode at runtime rather than compile time. Handle the EQU
+ pseudo-op in MRI mode. Remove bogus MRI ifdef around done_pseudo.
+ Change NO_PSEUDO_DOT ifdef to also take effect for MRI mode at
+ runtime.
+ (cons): In MRI mode, always call parse_mri_cons rather than
+ TC_PARSE_CONS_EXPRESSION.
+ (parse_mri_cons): Always compile, not just when MRI is defined.
+ Call TC_PARSE_CONS_EXPRESSION, not expression, when the input is
+ not a string constant. Handle A and E modifiers.
+ (float_cons): Accept :xxxx, where the x's are hex digits.
+ * expr.h (operatorT): Add O_eq, O_ne, O_lt, O_le, O_ge, O_gt.
+ (expr_begin): Declare.
+ * expr.c (integer_constant): In MRI mode, if the base was not
+ specified, look for a suffix on the number to set the base.
+ (mri_char_constant): New static function.
+ (operand): Remove MRI ifdef. In MRI mode, do various things: Pass
+ 0 as the base when calling integer_constant if there was no
+ prefix. Check for a hex constant suffix if when a leading '0' is
+ seen. Don't accept 0x or 0b as a prefix. Check for E'chars' and
+ A'chars'. Handle MRI character constants. Treat '"' as the
+ unary bitwise not operator. Treat $ as the program counter, or as
+ the prefix for a hex constant. Treat % as the prefix for a binary
+ constant and @ as the prefix for an octal constant. Treat : as
+ the prefix for a hex constant.
+ (op_encoding): Set '"' to O_bit_not, '<' to O_lt, and '>' to O_gt.
+ (op_rank): No longer const. Change rank values.
+ (expr_begin): New function.
+ (operator): New static function.
+ (expr): Use operator. Don't bother to mention the operator in
+ warnings. Remove bogus #if 0 code. Handle new operatorT values.
+ * atof-generic.c (atof_generic): In MRI mode, accept underscores
+ around the exponent in floating point numbers.
+ * symbols.h (symbols_case_sensitive): Declare.
+ * symbols.c (symbols_case_sensitive): New global variable.
+ (symbol_create): Check symbols_case_sensitive.
+ (symbol_find_base): Likewise.
+ (resolve_symbol_value): Handle new operatorT values.
+ (print_expr_1): Likewise.
+ (S_IS_LOCAL): In MRI mode, names beginning with two '?' characters
+ are local.
+
+Tue Aug 1 11:35:18 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * tc-sh.c (md_convert_frag): Make some error messages more
+ explict.
+
+Mon Jul 31 21:40:47 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ Sat Jul 29 18:55:23 1995 Pat Rankin <rankin@eql.caltech.edu>
+
+ * config/obj-vms.c (COPY_SHORT, COPY_LONG, PUT_SHORT, PUT_LONG):
+ Make expansion be safe for use in expressions.
+ (PUT_COUNTED_STRING): Bracket expansion with `do {...} while (0)'
+ rather than just `{...}'.
+
+Mon Jul 31 18:19:26 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * gasp.c (main): Parse -I option.
+ (do_include): Look through include list.
+ * gasp.c (change_base): Don't modify numbers in strings.
+
+Mon Jul 31 12:16:21 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-ppc.h (SUB_SEGMENT_ALIGN): Define. From Niclas
+ Andersson <nican@ida.liu.se>.
+
+Thu Jul 27 20:47:12 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * config/obj-coff.c (fixup_segment): Don't do further pcrel
+ processing after converting difference of two symbols in the
+ same segment. From Jim Wilson.
+
+ * configure.in (i386-*-linuxoldld): Add as synonym for
+ i386-*-linux*aout*. From Fred Fish.
+ * configure: Regenerated.
+
+Thu Jul 27 16:14:56 1995 Pat Rankin <rankin@eql.caltech.edu>
+
+ * config/obj-vms.c (enum ps_type {ps_TEXT,ps_DATA,ps_COMMON,
+ ps_CONST}): New constants.
+ (VMS_Psect_Spec): Use them instead of literal strings.
+ (vms_write_object_file, global_symbol_directory): Adjust callers.
+
+Wed Jul 26 18:31:35 1995 Pat Rankin <rankin@eql.caltech.edu>
+
+ * config/obj-vms.c (const_flag): Change from char to unsigned char.
+ * config/obj-vms.h (const_flag): Ditto.
+ (struct nlist): Replace union n_un and n_un.{n_name,n_next,n_strx}
+ fields with just n_name; delete field n_value; change n_other from
+ char to unsigned char and n_desc from short to int; insert explicit
+ padding for alignment.
+
+Mon Jul 24 20:06:17 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * subsegs.h (struct seg_info_trash): Make bitfield types valid.
+
+ * config/obj-coff.c (fixup_segment): Local add_number should not
+ be declared register since its address is taken for
+ MD_APPLY_FIX3.
+
+ Fri Jul 21 15:28:18 1995 Pat Rankin <rankin@eql.caltech.edu>
+
+ Split huge vms_write_object_file routine into managable pieces.
+
+ * config/obj-vms.c (vms_fixup_text_section, synthesize_data_segment,
+ vms_fixup_data_section, global_symbol_directory, local_symbols_DST,
+ vms_build_DST): New routines.
+ (vms_write_object_file): Call them.
+ (struct vms_obj_state): New file scope variable used by the above.
+
+Mon Jul 24 14:10:24 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sh.c (md_pseudo_table): Add "uses".
+ (s_uses): New static function.
+ (sh_coff_frob_file): New function.
+ (md_convert_frag): Call subseg_change before calling fix_new.
+ (sh_handle_align): New function.
+ (SWITCH_TABLE): Define.
+ (sh_force_relocation): New function.
+ (md_apply_fix): Handle R_SH_USES, R_SH_COUNT and R_SH_ALIGN.
+ (sh_coff_reloc_mangle): Likewise. Also handle switch table
+ entries.
+ * config/tc-sh.h (HANDLE_ALIGN): Define.
+ (sh_handle_align): Declare.
+ (TC_FORCE_RELOCATION): Define.
+ (sh_force_relocation): Declare.
+ (TC_COUNT_RELOC): Simplify; rely on TC_FORCE_RELOCATION instead.
+ (tc_frob_file): Define.
+ (sh_coff_frob_file): Declare.
+ * config/obj-coff.c (write_object_file): Call tc_frob_file if it
+ is defined.
+ (fixup_mdeps): Call HANDLE_ALIGN if it is defined.
+ (TC_FORCE_RELOCATION): Define if not defined.
+ (fixup_segment): Use TC_FORCE_RELOCATION to decide whether to
+ clear the symbol fields of fixP.
+
+Fri Jul 21 22:38:00 1995 Michael Meissner <meissner@cygnus.com>
+
+ * config/tc-ppc.c (ppc_elf_suffix): Add support for R_PPC_SDAREL
+ relocation.
+ (md_apply_fix3): Ditto.
+
+Thu Jul 20 13:00:56 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * config/tc-m68k.c (md_convert_frag): Rename argument seg to sec,
+ since seg is a macro name in this file.
+
+ * configure.in (arm-*-riscix*): Don't set emulation.
+
+Wed Jul 19 16:08:29 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/obj-coff.h (TE_PE): Delete.
+ * config/tc-arm.h (BYTE_ORDER): Delete.
+ (TARGET_FORMAT): Provide value for OBJ_COFF and TE_PE.
+ (ARM_BI_ENDIAN): Define if OBJ_COFF and TE_PE.
+ * config/tc-arm.c (byte_order): Delete.
+ (md_number_to_chars): Reference target_big_endian, not byte_order.
+ (md_chars_to_number): Likewise.
+ (md_longopts): Add -EB/-EL if ARM_BI_ENDIAN.
+ (md_parse_options): Recognize -EB/-EL.
+ (md_show_usage): List -EB/-EL.
+
+Wed Jul 19 11:49:25 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * gasp.c (process_assigns): Use toupper before comparing against
+ upper case letter.
+ (whatcond): Likewise.
+
+ * config/tc-sh.c (sh_relax): Rename from relax, and make global.
+ Renamed all uses.
+ (insert): Pass a size of 2, not 4.
+ (build_relax): Remove unused len variable.
+ (md_show_usage): Mention -little option.
+ (md_convert_frag): Add segT argument. Rewrite to generate relocs
+ rather than to generate complete instructions here.
+ (md_apply_fix): Adjust and clarify R_SH_PCRELIMM8BY4 case for
+ changes in insert and md_pcrel_from. Add cases for R_SH_PCDISP
+ and R_SH_PCDISP8BY2.
+ (md_pcrel_from): Don't subtract 1, add 2.
+ (tc_coff_fix2rtype): Remove.
+ (sh_coff_reloc_mangle): New function.
+ * config/tc-sh.h (TC_COFF_FIX2RTYPE): Just return fx_r_type.
+ (sh_relax): Declare.
+ (TC_COUNT_RELOC): If relaxing, count PC relative relocs.
+ (TC_RELOC_MANGLE): Define.
+ (sh_coff_reloc_mangle): Declare.
+ (tc_coff_sizemachdep): Declare.
+ * tc.h (md_convert_frag): Add segT parameter to non BFD_ASSEMBLER
+ declaration.
+ * write.c (cvt_frag_to_fill): Add sec argument to non
+ BFD_ASSEMBLER version. Pass it to md_convert_frag.
+ (write_object_file): Pass SEG_TEXT to cvs_frag_to_fill.
+ * config/obj-coff.c (do_relocs_for): Pass segment info to
+ TC_RELOC_MANGLE.
+ (fixup_mdeps): Pass segment type to md_convert_frag.
+ * config/tc-a29k.c (md_convert_frag): Add segT argument.
+ * config/tc-h8300.c (md_convert_frag): Likewise.
+ * config/tc-h8500.c (md_convert_frag): Likewise.
+ * config/tc-i386.c (md_convert_frag): Likewise.
+ * config/tc-i860.c (md_convert_frag): Likewise.
+ * config/tc-i960.c (md_convert_frag): Likewise.
+ * config/tc-m68k.c (md_convert_frag): Likewise.
+ * config/tc-m88k.h (md_convert_frag): Likewise.
+ * config/tc-ns32k.c (md_convert_frag): Likewise.
+ * config/tc-tahoe.c (md_convert_frag): Likewise.
+ * config/tc-vax.c (md_convert_frag): Likewise.
+ * config/tc-w65.c (md_convert_frag): Likewise.
+ * config/tc-z8k.c (md_convert_frag): Likewise.
+ * config/tc-h8300.h (TC_RELOC_MANGLE): Add segment argument.
+ * config/tc-h8500.h (TC_RELOC_MANGLE): Likewise.
+ * config/tc-w65.h (TC_RELOC_MANGLE): Likewise.
+ * config/tc-z8k.h (TC_RELOC_MANGLE): Likewise.
+
+Mon Jul 17 15:02:54 1995 Pat Rankin <rankin@eql.caltech.edu>
+
+ * config/obj-vms.c (Current_Routine, Text_Psect): Delete as file
+ scope variables.
+ (Define_Routine, Define_Local_Symbols): Take Current_Routine and
+ Text_Psect as arguments.
+ (VMS_DBG_Define_Routine): Delete.
+ (VMS_TBT_Block_End): Change `Size' argument from int to valueT.
+ (vms_write_object_file: text and data fixup loops): Difference
+ of two symbols has type offsetT rather than int; convert with
+ md_number_to_chars before passing to VMS_Store_Immediate_Data.
+ (vms_write_object_file: debug symbol loop): Call Define_Routine
+ instead of VMS_DBG_Define_Routine.
+
+Sat Jul 15 00:01:35 1995 Michael Meissner <meissner@cygnus.com>
+
+ * config/tc-ppc.c (ppc_elf_suffix): Add @fixup so that the
+ compiler can mark which relocs not to complain about with
+ -mrelocatable.
+ (ppc_elf_validate_fix): Add .fixup to sections not to complain
+ about, and also don't complain for BFD_RELOC_CTOR relocations in
+ writable non-code segments.
+ (md_apply_fix): Treat BFD_RELOC_CTOR just like BFD_RELOC_32.
+
+Fri Jul 14 19:54:28 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ Add support for SPARC SunOS PIC:
+ * config/tc-sparc.h (sparc_pic_code): Always declare, not just
+ when OBJ_ELF.
+ (TC_RELOC_RTSYM_LOC_FIXUP): Define when OBJ_AOUT.
+ (tc_fix_adjustable): New definition for OBJ_AOUT.
+ * config/tc-sparc.c (sparc_pic_code): Always define, not just when
+ OBJ_ELF.
+ (md_apply_fix): Adjust reloc addend for OBJ_AOUT and PIC. In
+ BFD_RELOC_32_PCREL_S2 case, don't increment val for an external
+ symbol when PIC.
+ (tc_gen_reloc): Generate different PIC relocs when OBJ_AOUT, as
+ well as when OBJ_ELF.
+ (md_shortopts): If OBJ_AOUT, include `k'.
+ (md_parse_option): If OBJ_AOUT, handle 'k'.
+ (md_show_usage): Mention -k if OBJ_AOUT, and -KPIC if OBJ_ELF.
+ (md_pcrel_from): Don't add in size for an external symbol when
+ PIC.
+
+Thu Jul 13 21:16:43 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.h (UNDEFINED_DIFFERENCE_OK): Define for SOM.
+ * write.c (adjust_reloc_syms): Set sy_used_in_reloc for both
+ symbols in a fixup where a defined symbol is subtracted from an
+ undefined symbol (when UNDEFINED_DIFFERENCE_OK is defined).
+ (fixup_segment): Do nothing for the difference of two symbols if
+ UNDEFINED_DIFFERENCE_OK is defined.
+
+Wed Jul 12 23:33:40 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.c (fixup_segment): Support MD_APPLY_FIX3.
+
+Wed Jul 12 01:12:12 1995 Ken Raeburn <raeburn@kr-pc.cygnus.com>
+
+ * write.c (fix_new): Use int, not short int, for argument type.
+ (fix_new_exp): Ditto.
+
+ * configure.in (arm-*-riscix*): Don't set emulations.
+
+ * config/tc-mips.c (NO_ECOFF_DEBUGGING): Define if ECOFF_DEBUGGING
+ wasn't previously defined.
+ (s_extern): Don't set ecoff_extern_size if NO_ECOFF_DEBUGGING.
+ (nopic_need_relax): Don't check it if NO_ECOFF_DEBUGGING.
+ (macro_build) [!USE_STDARG]: Don't use variadic prototype.
+ (mips_local_label) [NO_ECOFF_DEBUGGING]: Don't preserve potential
+ ECOFF debugging symbols.
+
+ * emul.h (struct emulation): Use unsigned, not unsigned char, for
+ bitfields.
+ * obj.h (struct format_ops): Likewise.
+
+ * config/tc-arm.c (symbol_make_empty) [BFD_ASSEMBLER]: Set
+ udata.p, not udata.
+
+Tue Jul 11 14:30:19 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * doc/c-mips.texi: Document -m4010 and -mno-4010.
+
+Tue Jul 11 14:28:55 1995 Jeff Spiegel <jeffs@lsil.com>
+
+ * config/tc-mips.c (mips_4010): New static variable.
+ (interlocks): New static variable.
+ (md_begin): Check for a cpu of "r4010". Set mips_4010 correctly.
+ If mips_4650 or mips_4010, set interlocks.
+ (append_insn): Check interlocks, not mips_4650.
+ (mips_emit_delays): Likewise.
+ (mips_ip): Only permit INSN_4010 instructions if mips_4010.
+ (md_longopts): Add "m4010" and "no-m4010".
+ (md_parse_option): Accept -mcpu=r4010. Handle -m4010 and
+ -no-m4010.
+ (md_show_usage): Document -m4010 and -no-m4010.
+
+Tue Jul 11 13:22:50 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * ecoff.c (struct efdr): Add new field fake.
+ (init_file): Initialize fake.
+ (add_file): Add new parameter fake. Change all callers.
+ (ecoff_build_debug): Don't warn about a missing .end for a fake
+ file.
+
+Mon Jul 10 16:01:31 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * doc/as.texinfo: Split out most cpu chapters...
+ * doc/c-*.texi: ...to here.
+
+ * read.c (po_hash): Now static.
+
+Mon Jul 10 13:47:22 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ Based on patches from H.J. Lu <hjl@nynexst.com>:
+ * config/tc-i386.c (md_apply_fix3): Rename from md_apply_fix1.
+ Accept pointer to value and segment. Fix OBJ_ELF PCREL case to
+ handle global defined symbols correctly.
+ (md_apply_fix): Remove both versions.
+ * config/tc-i386.h (MD_APPLY_FIX3): Define.
+
+ * configure.in: When switching on ${cpu}, use ${cpu}, not
+ $[target_cpu}, in default case.
+ * configure: Rebuild.
+
+Sat Jul 8 13:27:55 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * write.c (fixup_segment): Call resolve_symbol_value on
+ sub_symbolP, in case it isn't in the symbol table.
+
+Fri Jul 7 11:17:27 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.c (s_lcomm): For .lcomm 1, set align to 0, not 1.
+
+ * config/obj-coff.c (coff_frob_symbol): If SF_GET_FUNCTION, set
+ BSF_FUNCTION.
+ (symbol_globalP, symbol_global_lastP): New global variables.
+ (yank_symbols): Sort defined global symbols to the end, just
+ before the undefined symbols.
+ (glue_symbols): Add two arguments, and use them instead of
+ referring directly to global variables.
+ (crawl_symbols): Call glue_symbols twice, once for defined globals
+ and once for undefined. Add corresponding know calls.
+
+ * app.c (do_scrub_next_char): Always accept \v. Don't make it
+ conditional on BACKSLASH_V.
+ * read.c (next_char_of_string): Likewise.
+ * config/obj-bout.h (BACKSLASH_V): Don't define.
+ * config/tc-mips.h (BACKSLASH_V): Don't define.
+
+ Add SPARC ELF PIC support.
+ * write.c (fixup_segment): Pass fixP to TC_RELOC_RTSYM_LOC_FIXUP,
+ not fixP->fx_r_type.
+ * config/tc-sparc.c (sparc_pic_code): New global variable.
+ (md_apply_fix): If generating PIC, adjust fx_addnumber for any non
+ PC relative reloc.
+ (tc_gen_reloc): If generating PIC, adjust various reloc types.
+ Remove fx_pcrel assert, since it is no longer true.
+ (md_parse_option): Handle -K PIC.
+ * config/tc-sparc.h (sparc_pic_code): Declare if OBJ_ELF.
+ (TC_RELOC_RTSYM_LOC_FIXUP): Define if OBJ_ELF.
+ (tc_fix_adjustable): Don't adjust PC relative relocs if PIC.
+ * config/tc-i386.h (TC_RELOC_RTSYM_LOC_FIXUP): Take a fixp, not a
+ reloc type.
+
+ * Makefile.in (Makefile): Add dependency on conf.in, so that conf
+ is rebuilt when conf.in changes.
+
+Thu Jul 6 16:49:38 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * All files: Updated FSF address.
+
+Thu Jul 6 16:30:34 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * ecoff.c (add_file): Don't collapse multiple .file commands into
+ a single file structure.
+ (ecoff_build_lineno): Set ilineBase to sum of previous file's
+ ilineBase and cline.
+
+Thu Jul 6 12:54:27 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ Patches from Jerry Blakely <gerry_blakley@wellfleet.com>:
+ * as.c (listing_filename): New static variable.
+ (show_usage): Mention -a=file.
+ (parse_args): Support = option of -a to set name of listing file.
+ (main): Pass listing_filename to listing_print.
+ * listing.c (list_file): New static variable.
+ (various): Replace printf with fprintf to list_file.
+ (listing_print): If name argument is not NULL, open it as
+ list_file.
+ * doc/as.texinfo, doc/as.1: Document -a=file.
+
+ * config/tc-sparc.c (s_reserve): Don't permit redefinition, even
+ if the symbol was already in bss_section. Fix warning message.
+
+ * listing.c (struct file_info_struct): Rename end_pending field to
+ at_end.
+ (file_info): Initialize at_end, not end_pending.
+ (buffer_line): If at_end set, just return immediately. Don't
+ worry about end_pending cases. Set at_end when EOF is read.
+ (print_source): Check at_end, not end_pending.
+ (listing_listing): Likewise.
+
+ * config/tc-alpha.h (alpha_do_align): Don't declare.
+ (md_do_align): Don't define.
+ (tc_frob_label): Define.
+ (alpha_define_label): Declare.
+ (md_flush_pending_output): Define.
+ (alpha_flush_pending_output): Declare.
+ * config/tc-alpha.c (insn_label): New static variable.
+ (auto_align): New static variable.
+ (md_pseudo_table): Add cases for .text, .data, .align, .byte,
+ .hword, .int, .long, .octa, .quad, .short, .word, .double, .float,
+ and .single. Change .t_floating, .s_floating, .f_floating,
+ .g_floating, and .d_floating to use s_alpha_float_cons rather than
+ float_cons.
+ (s_alpha_text, s_alpha_data): New static functions.
+ (s_rdata, s_sdata): Clear insn_label and set auto_align.
+ (s_gprel32): If auto_align, align. Clear insn_label.
+ (emit_insn): Clear insn_label.
+ (s_alpha_align): New static function.
+ (alpha_align): Make static. Take label argument.
+ (alpha_flush_pending_output): New static function.
+ (s_alpha_cons, s_alpha_float_cons): New static functions.
+ (alpha_define_label): New function.
+
+Wed Jul 5 22:49:31 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * conf.in: Regenerate with autoreconf.
+
+ Mon Jul 3 19:47:53 1995 Pat Rankin (rankin@eql.caltech.edu)
+
+ * config/obj-vms.h (vms_resolve_symbol_redef): Use full prototype.
+ (vms_check_for_special_label, tc_frob_label): Move them to group
+ with other prototypes.
+ [WANT_VMS_OBJ_DEFS]: Only define the many OBJ_x, DBG_x, and DST_x
+ macros when this is defined.
+ * config/obj-vms.c: Fully prototype all local functions.
+ [symbolS, fragS]: Use consistently instead of their struct tags.
+ [WANT_VMS_OBJ_DEFS]: Define this.
+ (s_const): Make definition correctly match actual usage.
+ (VMS_stab_parse): Make `expected_type' arg be int rather than char.
+ (get_VMS_time_on_unix): Define as `static void'.
+ (hash_string): Make definition match actual usage; argument is
+ `char const *' rather than `unsigned char *'.
+ (VMS_Case_Hack_Symbol, VMS_Modify_Psect_Attributes, VMS_Psect_Spec,
+ VMS_Global_Symbol_Spec): Declare string args as `const char *'.
+ [IS_GXX_VTABLE]: New macro.
+ (vms_write_object_file: GSD loop): Use it.
+ (vms_write_object_file: data segment): Reorganize `fill' loop.
+
+Wed Jul 5 12:01:49 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sparc.c (md_shortopts): Add "K:" if OBJ_ELF.
+ (md_parse_option): If OBJ_ELF, check for -K. Die if -K PIC, since
+ PIC code is not currently supported.
+
+ * as.c (parse_args): Change std_shortopts to be an array rather
+ than a constant string. Only include 'K' if WORKING_DOT_WORD is
+ not defined. Only check for 'K' in that case as well.
+ * as.h (flag_warn_displacement): Only declare if WORKING_DOT_WORD
+ is not defined.
+
+ * conf.in: Add undef of HAVE_SBRK.
+
+ * config/obj-coff.c (obj_coff_line): Call listing_source_line, in
+ both BFD_ASSEMBLER and non BFD_ASSEMBLER versions of the function.
+
+ * symbols.c (S_SET_EXTERNAL): Warn if symbol is weak.
+ (S_CLEAR_EXTERNAL): Likewise.
+ (S_SET_WEAK): Warn if symbol is global.
+
+ * config/obj-aout.c (obj_aout_frob_symbol): Warn about an attempt
+ to put an undefined symbol into a set.
+
+ * Makefile.in: Remove @configure_input@; it's not needed in
+ files named Makefile.
+
+ * config/tc-m88k.c (md_pseudo_table): Add ".set" so that the
+ explicit pseudo-op works, while continuing to treat "set" as an
+ instruction.
+
+ * ecoff.c (ecoff_debugging_seen): New global variable.
+ (ecoff_directive_def): Set ecoff_debugging_seen.
+ (ecoff_stab): Likewise.
+ * ecoff.h: Make idempotent.
+ (ecoff_debugging_seen): Declare.
+ * config/tc-mips.c: Include ecoff.h.
+ (mips_debug): New static variable.
+ (s_stringer, s_mips_space): Remove unneeded declarations.
+ (md_parse_option): In case 'g', set mips_debug to debugging level.
+ (mips_local_label): New function.
+ * tc-mips.h (LOCAL_LABEL): Call mips_local_label.
+ (mips_local_label): Declare.
+
+Wed Jul 5 00:59:22 1995 Fred Fish (fnf@cygnus.com)
+
+ * as.c (main): Only use sbrk when HAVE_SBRK defined.
+ * configure.in: Add test for sbrk.
+ * configure: Regenerate using autoconf 2.4.
+
+Mon Jul 3 15:58:16 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.h (MAX_RELOC_EXPANSION): Bump to 6.
+ * config/tc-hppa.c (tc_gen_reloc, SOM version): Handle
+ relocations for the difference of two (possibly external)
+ symbols.
+ (hppa_fix_adjustable): For SOM, reject reductions involving
+ the difference of two symbols.
+ (hppa_force_relocation): Force relocations for expressions
+ involving the difference of two symbols.
+
+Mon Jul 3 14:22:59 1995 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * configure[.in] (i386-*-win32): New host and target.
+
+Thu Jun 29 17:25:43 1995 Steve Chamberlain <sac@slash.cygnus.com>
+
+ Support for long filenames non-bfd coff.
+ * config/obj-coff.c (filename_list_head, filename_list_tail): New.
+ (yank_symbols): Notice and record filenames which are too long.
+ (w_strings): Write out filename strings.
+ (c_dot_file_symbols): Put long filenames onto list.
+
+Wed Jun 28 17:33:13 1995 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * config/obj-coff.c (fixup_segment): PE doesn't use
+ the strange common symbol format that other 386s formats
+ do.
+ * config/tc-i386.c (md_begin): If LEX_AT defined then
+ '@' is in the set of identifiers.
+ (i386_operand): If LEX_AT, then don't look for @goto stuff.
+ * config/te-pe.h: Define LEX_AT.
+
+Wed Jun 28 17:49:59 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * doc/as.texinfo (H8/500 Floating Point): Indicate that IEEE FP
+ numbers are for the standard emulation code.
+ (SH Floating Point): Ditto.
+ (Overview): Describe new --emulation option for MIPS.
+ * doc/*.m4: Deleted.
+
+Thu Jun 22 19:26:25 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ Sun May 7 11:53:41 MDT 1995 Bryan Ford <baford@cs.utah.edu>
+
+ * configure.in: Added i386-*-moss* target.
+
+Thu Jun 22 14:41:23 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * write.c (write_object_file): Cast decode_local_label_name
+ argument to char * to avoid warning.
+
+Wed Jun 21 18:07:59 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ Changes from Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>:
+ * config/tc-m68k.c (insword): Increment the frag offsets.
+ (struct m68k_it): Add reloc[].pcrel_fix field to hold pc-rel
+ fixup.
+ (add_fix): Accept additional parameter, the pc-rel fixup. All
+ callers changed. Fix offset address if width == 'b'.
+ (m68k_ip) [case AINDX]: Allow explicit size spec. Don't make the
+ outer displacement pc-relative.
+ (md_pcrel_from): Make it relative to the first extension word of
+ the operand.
+ (opcode_ptr): Make it a macro if DO_BREAK_UP_BIG_DECL is
+ undefined.
+ (md_convert_frag_1): Don't reference fragP->fr_opcode[2..].
+ (md_estimate_size_before_relax) [case TAB (FBRANCH, SZ_UNDEF)]:
+ Turn on long bit.
+ (m68k_ip) [case 'C']: Don't set set long bit, set it in the opcode
+ table.
+ (md_estimate_size_before_relax) [case TAB (PCINDEX, SZ_UNDEF)]:
+ Variable part increases by four, not six.
+ * write.c (fixup_segment) [TC_M68K]: Don't do further pcrel
+ processing after converting difference of two symbols in the
+ same segment.
+
+ * write.c (fixup_segment): Don't conditionalize the pcrel fix on
+ TC_M68K.
+
+ * config/tc-sparc.c (sparc_ip, case 'A'): If ASI is not a "#"
+ value, don't shift it an extra time.
+
+Wed Jun 21 14:18:37 1995 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * gasp.c (do_print, do_form, buffer_and_nest): Use case insensitive
+ string compares.
+
+Tue Jun 20 14:55:02 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/obj-coff.c (write_object_file): Cast time() argument to
+ time_t *.
+
+Tue Jun 20 12:00:53 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (pa_build_unwind_subspace): Fix typo in last
+ change.
+
+Mon Jun 19 15:27:17 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (pa_build_unwind_subspace): Zero out memory
+ from frag_more calls.
+
+Thu Jun 15 16:53:37 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * config/obj-coff.c: Don't use "bfd/" when including libbfd.h
+ and libcoff.h.
+ (fill_section): Call PROGRESS.
+ * Makefile.in (INCLUDES): Add bfd srcdir.
+
+ * mpw-config.in: Add bfd_gas flag and set for each config.
+ (i386-unknown-go32, m68k-unknown-coff): Recognize.
+ * mpw-make.in (HACK_O_RAMA, OBJ_COFF_OMIT_TIMESTAMP): Add to
+ config.h.
+
+Thu Jun 15 10:04:26 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/tc-arm.h (LOCAL_LABEL): Prepend '.' if not OBJ_AOUT.
+ (FAKE_LABEL_NAME): Likewise.
+
+Mon Jun 12 22:25:39 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (pa_ip): Check for invalid register in single
+ precision fmpyadd and fmpysub instructions.
+
+Thu Jun 8 19:33:02 1995 Pat Rankin (rankin@eql.caltech.edu)
+
+ * config/obj-vms.c (myname): Delete all references.
+ (VMS_stab_parse, Write_VMS_MHD_Records, VMS_Case_Hack_Symbol):
+ Replace printf calls with as_tsktsk.
+ (PUT_LONG, PUT_SHORT): Use COPY_LONG, COPY_SHORT.
+ (VMS_Store_Immediate_Data): Move second buffer capacity check
+ below bottom of loop; first check at top suffices for loop itself.
+ (find_file): Remove redundant pointer checks in first two loops;
+ replace third loop with pointer to last list element determined
+ in first loop.
+
+Tue Jun 6 13:53:06 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/tc-sparc.c (sparc_ip): Handle defined absolute symbols as
+ ASI values.
+
+ * config/obj-vms.c (vms_write_object_file, case N_DATA): Use
+ strcmp against FAKE_LABEL_NAME instead of checking third
+ character. (Suggested by Pat Rankin.)
+
+Mon Jun 5 20:10:46 1995 Pat Rankin (rankin@eql.caltech.edu)
+
+ Add support for N_ABS and N_ABS|N_EXT type symbols.
+
+ * config/obj-vms.h (LSY_S_M_{DEF,REL}, ENV_S_M_{DEF,NESTED}):
+ New macros for local symbols (from <lsydef.h> and <envdef.h>).
+ * config/obj-vms.c (Current_Environment): New file-scope variable.
+ (VMS_Local_Environment_Setup): New routine.
+ (GBLSYM_LCL): New macro.
+ (VMS_Global_Symbol_Spec): Handle local symbols too.
+ (VMS_Psect_Spec): Set GLOBALVALUE_BIT for absolute symbols.
+ (VMS_Emit_Globalvalues): Handle local and global absolute symbols.
+ (VMS_Store_PIC_Symbol_Reference): Ditto.
+ (vms_write_object_file: GSD symbol loop): Ditto.
+
+Mon Jun 5 16:10:40 1995 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * config/tc-arm.h (LOCAL_LABELS_FB): Define.
+
+Mon Jun 5 02:17:58 1995 Ken Raeburn <raeburn@kr-laptop.cygnus.com>
+
+ * configure.in (i386-*-gnu*): Always use GNU ELF config.
+
+Wed May 31 17:49:18 1995 Pat Rankin (rankin@eql.caltech.edu)
+
+ * config/obj-vms.c (obj_crawl_symbol_chain): Update *symbolPP
+ in `else' clause when removing a symbol. Also, revise comments
+ to match the code.
+ (vms_write_object_file (GSD symbol loop, case N_DATA)): Never
+ output symbol definitions for local numeric labels.
+
+Tue May 30 18:29:10 1995 Richard Earnshaw (rearnsha@armltd.co.uk)
+
+ * configure.in (architecture variants, cases armeb and arm*): Remove
+ spaces round assignment to endian.
+
+Tue May 30 12:31:31 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * write.c (write_object_file): Check for undefined local dollar
+ and fb labels.
+
+ * symbols.c (decode_local_label_name): Extract instance number
+ from the correct location.
+
+Sat May 27 21:28:49 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * config/te-dpx2.h: Include obj-format.h.
+ (COFF_MAGIC): Renamed from FILE_HEADER_MAGIC.
+
+Wed May 24 13:45:32 1995 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * configure, configure.in, config/obj-coff.c, config/obj-coff.h:
+ Add support for ARM pe
+
+Tue May 23 17:00:32 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/tc-sparc.c (tc_gen_reloc): Handle BFD_RELOC_SPARC_WDISP16
+ and BFD_RELOC_SPARC_WDISP19.
+
+Tue May 23 19:18:33 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * as.c (parse_args) [! USE_EMULATIONS]: Always print an error
+ message.
+
+ * doc/internals.texi: Document obj_app_file and
+ TARGET_BYTES_BIG_ENDIAN.
+
+Mon May 22 20:03:23 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * ecoff.c (ecoff_stab): Add extra leading argument, for 4 May
+ change.
+ * ecoff.h (ecoff_stab): Fix declaration.
+ * obj.h (format_ops.process_stab): Include prototype.
+ * config/obj-elf.h (OBJ_PROCESS_STAB): Pass through seg argument.
+ * config/obj-ecoff.h (OBJ_PROCESS_STAB): Ditto.
+
+ * config/e-mipself.c (mipself): New emulation mode, doesn't change
+ endianness from configured default.
+ * config/e-mipsecoff.c (mipsecoff): Ditto.
+ * configure.in (mips ecoff/elf targets): Include them.
+ * as.c (mipself, mipsecoff): Declare.
+
+ * as.c (emulation_name): New variable.
+ (select_emulation_mode): Set emulation_name. Don't change argv.
+ (parse_args): Handle --emulation; complain if the supplied name
+ isn't what select_emulation_name came up with.
+
+Sun May 21 21:36:17 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c: Reverse changes from Dec. 19th which
+ changed the way unwinds were built for ELF. Rely on relocation
+ symbol reductions to avoid placing the end of function marker
+ symbols into the object file's symbol table.
+
+Sat May 20 12:31:36 1995 Ken Raeburn <raeburn@kr-laptop.cygnus.com>
+
+ Added improved VMS support from Pat Rankin:
+
+ Fri 19 May 16:51:40 1995 Pat Rankin (rankin@eql.caltech.edu)
+
+ * config/obj-vms.h (AOUT_STABS): Define.
+
+ * config/obj-vms.c (fpush, rpush): New routines.
+ (push): Replaced by the above.
+ (find_symbol): Slight reorganization to expose tail recursion.
+
+ Fri Mar 17 18:40:36 1995 Pat Rankin (rankin@eql.caltech.edu)
+
+ * Makefile.in (VMS_OTHER_OBJS): delete this.
+ * vmsconf.sh (make-gas.com): build ../libiberty/liberty.olb
+ first if necessary; link gas against it.
+
+Fri May 19 16:37:39 1995 Richard Earnshaw (rearnsha@armltd.co.uk)
+
+ * gasp.c (istrue): Correctly test for string inequality.
+
+Thu May 18 04:25:11 1995 Ken Raeburn <raeburn@kr-laptop.cygnus.com>
+
+ Wed May 10 14:28:16 1995 Richard Earnshaw (rearnsha@armltd.co.uk)
+
+ * config/tc-arm.c (CP_T_{Pre,UD,WB}): Define, bits in co-processor
+ instructions.
+ ([ls]fm_flags): Correct error in bitmasks.
+ (cp_address_required_here): Delete second parameter, FLAGS. All
+ callers changed. Remove all dead code referring to FLAGS. If
+ address is just "[Reg]" then convert into a PRE-INCREMENT UP format.
+ (do_fp_ldmstm): Handle full-descending and empty-ascending stack
+ formats explicitly.
+
+ * config/tc-arm.c (internalError): Define.
+ (ARM_{1,2,250,3,6,7,7DM,ANY,2UP,ALL,3UP,6UP,LONGMUL}): Define processor
+ variants.
+ (FPU_{CORE,FPA10,FPA11,NONE,ALL,MEMMULTI}): Define floating point
+ variants.
+ ({CPU,FPU}_DEFAULT): Define.
+ (cpu_variant): New variable.
+ (asm_flg): Change more_flags to flag_bits.
+ Add prototypes for new functions.
+ (FLAG_{S,P,B,T,ED,FD,FA,EA,IB,IA,DB,DA,L}): Delete.
+ (s_flag[], ldst_flags[], byte_flag[], cmp_flags[], ldm_flags[],
+ stm_flags[], lfm_flags[], sfm_flags[], round_flags[], except_flags[],
+ cplong_flag[]): New variables.
+ (asm_opcode, insns[]): New format, add version support.
+ (arm_flg_hsh): Delete.
+ (do_mul, do_mla): Remove "Warning" from warning messages.
+ (do_arit): Simplify.
+ (do_swap): Make error message more appropriate.
+ (md_begin): Build hash tables starting at first entry in tables.
+ (md_number_to_chars): Cope with big/little-endian selection.
+ (md_chars_to_number): New function.
+ (md_apply_fix): Rewrite to make endian independent.
+ (tc_gen_reloc): Better error messages.
+ (md_assemble): Reject opcodes forbidden by the currently selected cpu
+ variant. Rewrite handling code for instruction flags.
+ (md_shortopts): Add option "m:".
+ (md_parse_option): Get the desired cpu/fpu variant.
+
+ From: David Taylor (dtaylor@armltd.co.uk)
+ * configure.in (architecture variants): Check for "armeb" and "arm*",
+ set endianness accordingly.
+ * read.c (read_a_source_file): New hooks md_start_line_hook and
+ md_after_pass_hook.
+ * config/arm-{big,lit}.mt: New files
+ * config/tc-arm.h ({LITTLE,BIG}_ENDIAN, BYTE_ORDER): Define.
+ (TARGET_FORMAT): Select depending on endianness and emulation and
+ object format.
+ (md_after_pass_hook, md_start_line_hook): Define.
+ * config/tc-arm.c: Include subsegs.h, symbols.h and listing.h.
+ (shift[]): Add uppper case equivalents.
+ (CP_T_[XY], TRANS_BIT): Define.
+ (conds[]): Delete initial NULL entry, add "lo" entry as synonym for
+ "cc".
+ (LONGEST_FLAG, flags[]): Delete.
+ (arm_psr): New structure.
+ (psrs[]): New variable.
+ (PSR_ALL): Define.
+ (LONGEST_INST): Bump to 5.
+ (LITERAL_MASK, COND_MASK, OPCODE_MASK, DATA_OP_SHIFT): Define.
+ (OPCODE_{AND,EOR,SUB,RSB,ADD,ADC,SBC,RSC,TST,TEQ,CMP,CMN,ORR,MOV,BIC,
+ MVN}): Define.
+ (insns[]): Add smull, umull, smlal, umlal, ldfm, stfm, msr and mrs
+ instructions. Add nop and adr pseudo ops.
+ (reg_table): Add APCS register name variants.
+ (arm_psr_hsh): New hash table.
+ (md_pseudo_table): Add "ltorg", "pool", "extend", "ldouble" and
+ "packed".
+ (MAX_LITERAL_POOL_SIZE): Define.
+ (struct literalS): New structure.
+ (literals, next_literal_pool_place, lit_pool_num, current_poolP): New
+ variables.
+ (add_to_lit_pool, symbol_locate, symbol_make_empty): New functions.
+ (validate_immediate): Return FAIL on failure.
+ (s_ltorg): New function.
+ (psr_required_here, psrf_required_here): New functions.
+ (cp_address_required_here): New parameter, flag, all callers changed.
+ If flag is non-zero, restrict the legal addressing modes.
+ (do_nop, do_mrs, do_msr, do_mull): New functions.
+ (negate_data_op): New function.
+ (data_op2): accept #x,y meaning x rotated right by y, but only when
+ suitable constants. If immediate is not legal, try changing the
+ opcode.
+ (do_adr): New function.
+ (do_ldst): accept "ldr reg, =expr". Put expr in the pool if it can't
+ be done as an immediate.
+ (do_fp_ldst): Use CP_T_[XY], not immediate values.
+ (do_fp_ldmstm): New function.
+ (arm_psr_parse): New function.
+ (output_inst): Use INSN_SIZE in call to md_number_to_chars.
+ (md_assemble): Add hack so that "Label instruction" causes alignment of
+ the label.
+ (arm_after_pass_hook, arm_start_line_hook, arm_frob_symbol): New
+ functions.
+
+Wed May 17 05:25:16 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (md_show_usage): Add \'s at end of lines in
+ strings for non-GCC compilers.
+
+Tue May 16 19:36:00 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/obj-ecoff.c (ecoff_pop_insert): New function.
+ (ecoff_format_ops): Use it.
+ (obj_ecoff_frob_symbol): Now static.
+
+Wed May 17 00:59:12 1995 Andrew Cagney - aka Noid <cagney@highland.com.au>
+
+ * config/tc-ppc.c (md_begin): Was assuming that an instruction was
+ bigendian and hence 16bit relocs withing instructions would
+ ALWAYS be at addresses i+2-i+3. In LE mode it is i+0-i+1.
+
+Tue May 16 16:29:58 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/obj-multi.h (obj_frob_symbol, obj_frob_file, S_GET_SIZE,
+ S_SET_SIZE, S_GET_ALIGN, S_SET_ALIGN, obj_copy_symbol_attributes,
+ OBJ_PROCESS_STAB): New macros.
+ * config/tc-mips.c: Protect against redefining them also when
+ including obj-elf.h. Test only OBJ_ELF for including elf/mips.h.
+ (mips_init_after_args): New function. Set byte_order here.
+ (md_parse_option): Not here.
+ (byte_order): Don't bother initializing.
+ * config/tc-mips.h (mips_init_after_args): Declare.
+ (tc_init_after_args): New macro.
+
+ * read.c (s_lcomm): Do ELF/ECOFF test at run time, not compile
+ time.
+
+Fri May 12 14:17:47 1995 Steve Chamberlain <sac@slash.cygnus.com>
+
+ Initial support for PE object files.
+ * configure.in, configure (i386-*-pe, i386-*-*nt): Add.
+ * config/obj-coff.c (fixup_segment): Cope with PE wierdness.
+ * config/obj-coff.h (TE_PE): New target format.
+
+Thu May 11 14:58:21 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/obj-elf.c (NEED_ECOFF_DEBUG): Define if ECOFF_DEBUGGING
+ was defined by header files. Test in preprocessor conditionals
+ instead of ECOFF_DEBUGGING.
+ (ecoff_debug_pseudo_table): Make empty if NEED_ECOFF_DEBUG is not
+ defined.
+ (obj_read_begin_hook, obj_symbol_new_hook, elf_frob_symbol,
+ elf_frob_file): Only call ecoff routines if NEED_ECOFF_DEBUG is
+ defined.
+ (elf_ecoff_set_ext, elf_get_extr, elf_set_index): Define only if
+ NEED_ECOFF_DEBUG is defined.
+ (elf_format_ops): Reference elf_ecoff_set_ext only if
+ NEED_ECOFF_DEBUG.
+
+Wed May 10 18:09:12 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * Makefile.in (OBJS): Include @extra_objects@.
+ (obj-elf.o, obj-ecoff.o, e-mipself.o, e-mipsecoff.o): New rules
+ for building these independently.
+ * emul-target.h, config/e-mipself.c, config/e-mipsecoff.c: New
+ files.
+
+ * acconfig.h (DEFAULT_EMULATION, EMULATIONS, USE_EMULATIONS,
+ OBJ_MAYBE_*, I386COFF, M68KCOFF, M88KCOFF): New macros.
+ * aclocal.m4 (GAS_UNIQ): New macro.
+
+ * as.c (emulations, n_emulations) [USE_EMULATIONS]: New variable.
+ (select_emulation_mode, default_emul_bfd_name, common_emul_init)
+ [USE_EMULATIONS]: New functions.
+ (main) [USE_EMULATIONS]: Call select_emulation_mode before other
+ initialization.
+ * emul.h: New file.
+ * as.h [USE_EMULATIONS]: Include it.
+
+ * configure.in: Handle enable-targets option. Iterate over target
+ list, building up a list of object file formats and emulation
+ configurations. (Only supports emulations for MIPS CPU so far.)
+ If multiple formats are needed, set obj_format to multi and add
+ format config files to extra_files. If emulation modes are
+ needed, add the relevant files to extra_files.
+
+ * configure.in: Define I386COFF, M68KCOFF, M88KCOFF for those
+ configurations.
+
+ * ecoff.c (ecoff_generate_asm_lineno): Filename argument now
+ points to const.
+ * ecoff.h (ecoff_generate_asm_lineno): Updated declaration.
+
+ * obj.h (obj_read_begin_hook): Don't declare function if it's
+ already a macro.
+
+ * read.c (s_space, cons, stringer): If md_flush_pending_output is
+ defined, call it on entry.
+ * config/obj-elf.c (obj_elf_section): If md_flush_pending_output
+ is defined, call it on entry. If md_elf_section_change_hook is
+ defined, call it before returning normally.
+
+ * read.h (target_big_endian): Declare.
+
+ * obj.h (struct format_ops): Added new function pointer fields
+ ecoff_set_ext, read_begin_hook, symbol_new_hook.
+ (ecoff_format_ops, elf_format_ops): Declare.
+ * config/obj-elf.c (elf_s_get_size, elf_s_set_size,
+ elf_s_get_align, elf_s_set_align, elf_copy_symbol_attributes,
+ elf_sec_sym_ok_for_reloc): New functions.
+ (elf_format_ops): New variable.
+ (elf_frob_symbol): Now takes additional int* argument.
+ * config/obj-elf.h (elf_frob_symbol): Update declaration.
+ (elf_pop_insert): Declare.
+ (obj_pop_insert): Define to call elf_pop_insert.
+ * config/obj-ecoff.c (ecoff_sec_sym_ok_for_reloc,
+ obj_ecoff_frob_symbol): New functions.
+ (ecoff_format_ops): New variable.
+
+ * config/te-generic.h: If OBJ_HEADER is defined, use it as the
+ filename to include in place of obj-format.h.
+ * config/te-multi.h: New file, copied from te-generic.h.
+ * config/obj-elf.c (OBJ_HEADER): Define it to "obj-elf.h".
+ * config/obj-ecoff.c (OBJ_HEADER): Define it to "obj-ecoff.h".
+
+ * config/obj-elf.c (ECOFF_DEBUGGING): Default to 0.
+ (obj_read_begin_hook, obj_symbol_new_hook, elf_frob_symbol,
+ elf_frob_file): Test it at run time.
+ (obj_ecoff_set_ext, elf_get_extr, elf_set_index): Define
+ unconditionally.
+ (elf_pseudo_table): Renamed from obj_pseudo_table, now static.
+ (ecoff_debug_pseudo_table): Split off into separate table. Define
+ it unconditionally.
+ (elf_pop_insert): New function.
+ * config/obj-elf.h (elf_pop_insert): Declare.
+ (obj_pop_insert): New macro.
+ (obj_ecoff_set_ext) [!OBJ_MAYBE_ELF]: Define to elf_ecoff_set_ext.
+ * config/obj-ecoff.h (obj_ecoff_set_ext): Define to ecoff_set_ext.
+
+ * config/tc-mips.h: Protect against multiple inclusions.
+ (mips_pop_insert): Declare.
+ (md_pop_insert): Call it.
+
+ * config/tc-mips.c: If OBJ_MAYBE_ELF is defined, include
+ obj-elf.h, but preserve OUTPUT_FLAVOR and protect some other
+ macros from redefinition.
+ (ECOFF_DEBUGGING): Default to 0. All references changed to
+ run-time tests or made unconditional.
+ (s_stringer, s_mips_space, s_elf_section): Deleted.
+ (md_pseudo_table): Don't refer to them. Split table into three
+ sections, for MIPS, non-ECOFF_DEBUGGING, and ELF.
+ (mips_pop_insert): New function.
+ (mips_flush_pending_output): New function.
+ (mips_enable_auto_align): New function.
+ * config/tc-mips.h (mips_pop_insert): Declare.
+ (md_pop_insert): New macro.
+ (mips_flush_pending_output): Declare.
+ (md_flush_pending_output): New macro.
+ (mips_enable_auto_align): Declare.
+ (md_elf_section_change_hook): New macro, calls
+ mips_enable_auto_align.
+
+Tue May 9 17:07:41 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure.in: Add little endian PowerPC support.
+ * configure: Rebuild with autoconf.
+ * config/ppc-big.mt: New file for big endian PowerPC systems.
+ * config/ppc-lit.mt: New file for little endian PowerPC systems.
+
+ * config/tc-ppc.h (target_big_endian): Declare.
+ (TARGET_FORMAT): Deal with little and big endian ELF variants.
+ (TARGET_BYTES_BIG_ENDIAN): Define as 1, not empty.
+
+ * config/tc-ppc.c (ppc_big_endian): Delete variable, use
+ target_big_endian instead.
+ (md_parse_option): Parse -mlittle and -mlittle-endian to use
+ little endian support. Parse -mbig and -mbig-endian to use big
+ endian support.
+ (md_show_usage): Update to reflect current switches.
+ (ppc_set_cpu): Recognize powerpcle as little endian PowerPC. Use
+ as_fatal, not abort if unknown machine.
+
+Tue May 9 10:58:41 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (md_apply_fix): Cast *valp to an integer when
+ comparing against signed values.
+ (hppa_force_relocation): Make "distance" an integer.
+
+Tue May 9 00:47:03 1995 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * obj.h (struct format_ops) [BFD_ASSEMBLER]: New type.
+ (this_format) [BFD_ASSEMBLER]: Declare new variable, if not
+ already defined as a macro.
+
+Mon May 8 21:44:13 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * subsegs.h (seg_info): Provide dummy version for
+ non-BFD_ASSEMBLER, non-MANY_SEGMENTS configuration. It should
+ never get invoked, but this is easier than conditionalizing some
+ of the uses.
+ (struct seg_info_trash): Dummy type used by above to make code
+ compile.
+
+Fri May 5 14:47:13 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/obj-coff.h (SEPARATE_STAB_SECTIONS): Define to 1, not
+ empty.
+ * config/obj-elf.h (SEPARATE_STAB_SECTIONS): Ditto.
+ * config/obj-som.h (SEPARATE_STAB_SECTIONS): Ditto.
+
+Thu May 4 19:26:55 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * stabs.c (get_stab_string_offset): Always define. If
+ SEPARATE_STAB_SECTIONS isn't set, abort.
+ (SEPARATE_STAB_SECTIONS): Default to zero.
+ (aout_process_stab): New function, split out from s_stab_generic.
+ (OBJ_PROCESS_STAB) [AOUT_STABS]: Define to call aout_process_stab,
+ if not already defined.
+ (s_stab_generic): Test SEPARATE_STAB_SECTIONS at run time. If
+ it's not set, and OBJ_PROCESS_STAB isn't defined, abort. Always
+ pass six arguments to OBJ_PROCESS_STAB.
+ * read.h (get_stab_string_offset): Declare unconditionally.
+ * config/obj-aout.h (AOUT_STABS): Define.
+ * config/obj-bout.h (AOUT_STABS): Define.
+ * config/obj-ecoff.h (OBJ_PROCESS_STAB): Add new first argument,
+ ignored.
+ * config/obj-elf.h (OBJ_PROCESS_STAB) [ECOFF_DEBUGGING]: Ditto.
+
+ * config/obj-ecoff.h (ECOFF_DEBUGGING): Define to 1, not empty.
+ * config/obj-elf.h (ECOFF_DEBUGGING): Ditto. Test value, not
+ whether it's defined.
+
+Wed May 3 21:38:20 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * as.h (LOCAL_LABELS_DOLLAR, LOCAL_LABELS_FB): If not already
+ defined, define them to zero.
+ * config/tc-*.h, config/te-*.h: If defining them, define them to
+ be 1 instead of empty.
+ * expr.c (integer_constant, operand): Test them at run time
+ instead of compile time.
+ * read.c (read_a_source_file): Ditto.
+ * symbols.c (colon): Ditto.
+ (dollar_*, define_dollar_label, fb_*): Define unconditionally.
+ * symbols.h (dollar_*, define_dollar_label, fb_*): Declare
+ unconditionally.
+
+Wed May 3 13:08:53 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (md_apply_fix): Do nothing for an out of range
+ PC relative call since those only occur in cases where the linker
+ can fix them up.
+ (hppa_force_relocation): Force relocations for out of range PC
+ relative calls.
+
+Tue May 2 16:34:47 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * configure (hppa*-*-lites*): Handle just like hppa*-*-*elf*.
+ * configure.in: Likewise.
+
+Tue May 2 11:22:00 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * read.c (pop_insert): New function.
+ (pop_override_ok, pop_table_name): New variables.
+ (md_pop_insert, obj_pop_insert): New macros.
+ (pobegin): Use them.
+
+ * config/tc-mips.c: Use USE_STDARG and USE_VARARGS instead of
+ NO_STDARG &c.
+
+ * read.c (target_big_endian): If TARGET_BYTES_BIG_ENDIAN is
+ defined, initialize to 1.
+ * config/tc-mips.c (mips_target_format): Changed to a function,
+ checking flavor and byte order at run time.
+ (md_parse_option, cases OPTION_EB and OPTION_EL): Set
+ target_big_endian here.
+ (md_begin): Not here.
+ * config/tc-mips.h (mips_target_format): Adjust declaration.
+ (TARGET_FORMAT): Call mips_target_format.
+
+ * config/tc-mips.h (USE_GLOBAL_POINTER_OPT): Define in terms of
+ OUTPUT_FLAVOR.
+ * config/tc-mips.c (g_switch_value, g_switch_seen): Define
+ unconditionally.
+ (md_begin, mips_ip, md_parse_option, s_change_sec, s_option,
+ s_abicalls, nopic_need_relax): Check USE_GLOBAL_POINTER_OPT at run
+ time, instead of compiling conditionally on GPOPT.
+ (GPOPT): Don't define.
+ (md_shortopts): Always include -G.
+ (RDATA_SECTION_NAME): Select at run time.
+ (md_begin): Test for ELF format at run time instead of compile time.
+ (mips_ip, s_change_sec): Ditto.
+ (md_parse_option, cases OPTION_CALL_SHARED and OPTION_NON_SHARED):
+ Ditto.
+ (OPTION_CALL_SHARED, OPTION_NON_SHARED, mips_regmask_frag): Define
+ unconditionally.
+
+Tue May 2 00:17:04 1995 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * Makefile.in (TARG_CPU_DEP_*): New variables.
+ (targ-cpu.o): Depend on one, selected by autoconf substitution,
+ instead of TARG_CPU_DEPENDENTS.
+ * configure.in: Substitute $cpu_type, $obj_format, $atof, and
+ $emulation into Makefile.in.
+ * config/h8300.mt: Deleted.
+ * config/h8500.mt: Deleted.
+ * config/i386coff.mt (TARG_CPU_DEPENDENTS): Deleted.
+ * config/m68k.mt: Deleted.
+ * config/m68kcoff.mt (TARG_CPU_DEPENDENTS): Deleted.
+ * config/m88kcoff.mt (TARG_CPU_DEPENDENTS): Deleted.
+ * config/mips-big.mt (TARG_CPU_DEPENDENTS): Deleted.
+ * config/mips-lit.mt (TARG_CPU_DEPENDENTS): Deleted.
+ * config/sh.mt: Deleted.
+ * config/w65.mt: Deleted.
+ * config/z8k.mt: Deleted.
+
+ * config/te-dpx2.h (dpx2): Deleted unused macro.
+ * config/te-generic.h (TE_GENERIC): Ditto.
+ * config/te-go32.h (TE_GO32): Ditto.
+ * config/te-hp300.h (TE_HP300): Ditto.
+ * config/te-hppa.h (PA, _TE_PA_H): Ditto.
+ * config/te-ic960.h (TE_IC960): Ditto.
+ * config/te-nbsd532.h (TE_NETBSD532): Ditto.
+ * config/te-pc532mach.h (TE_PC532MACH): Ditto.
+ * config/te-ppcnw.h (TE_PPCNW): Ditto.
+ * config/te-sco386.h (scounix): Ditto.
+
+Mon May 1 15:59:56 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * read.c (s_app_file): If obj_app_file is defined, call it with
+ string as argument. Don't call c_dot_file_symbol or
+ elf_file_symbol.
+ * config/obj-coff.h (obj_app_file): Define as c_dot_file_symbol.
+ * config/obj-elf.h (obj_app_file): Define as elf_file_symbol.
+
+ * as.h (OUTPUT_FLAVOR): Don't define here.
+ * config/obj-aout.h (OUTPUT_FLAVOR) [BFD_ASSEMBLER]: Define.
+ * config/obj-bout.h (OUTPUT_FLAVOR): Define.
+ * config/obj-coff.h (OUTPUT_FLAVOR) [BFD_ASSEMBLER]: Define.
+ * config/obj-ecoff.h (OUTPUT_FLAVOR): Define.
+ * config/obj-elf.h (OUTPUT_FLAVOR): Define.
+
+Thu Apr 27 20:07:33 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * Makefile.in (RUNTEST): Use one in srcdir if present.
+ (RUNTESTFLAGS): Define.
+
+Wed Apr 26 15:54:10 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ Support for more portable alignment handling in assembly code,
+ based on patches from Bryan Ford <baford@schirf.cs.utah.edu>:
+ * read.c (potable): Added balign and p2align, for aligning by
+ bytes or powers of two independent of what ".align" does for a
+ given target.
+ * doc/as.texinfo: Document them.
+
+Tue Apr 25 11:12:04 1995 Rob Savoye <rob@thepub.cygnus.com>
+
+ * configure, configure.in: Look for m68k-*-vxworks* rather than
+ just m68k-wrs-vxworks so gas can be configured for
+ m68k-vxworks5.1.
+
+Fri Apr 21 15:19:06 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/tc-sh.c (md_apply_fix): If fx_r_type is zero, handle
+ fx_size of 1, and abort on unrecognized sizes.
+
+ * config/tc-m68k.c (m68k_ip): Fix bug in last change regarding
+ non-isvar case.
+
+Sun Apr 16 01:52:52 1995 Ken Raeburn <raeburn@kr-laptop.cygnus.com>
+
+ * config/tc-m68k.h (md_relax_table, TC_GENERIC_RELAX_TABLE):
+ Missed this one in 11 Apr changes.
+
+ * config/tc-i386.h (TC_GENERIC_RELAX_TABLE): Fix typo.
+
+Thu Apr 13 18:18:08 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/tc-sh.c (md_convert_frag): Instead of aborting on large
+ displacements, print an error message. Don't invoke the code that
+ followed the abort call until it's been verified.
+
+ * config/tc-m68k.c (md_show_usage): Add 68060 to list. Split cpu
+ list into three lines.
+
+Thu Apr 13 14:34:36 1995 Torbjorn Granlund <tege@adder.cygnus.com>
+
+ * tc-m68k.c (m68k_init_after_args): Test for m68360.
+ (md_parse_option): Likewise.
+ (md_show_usage): Mention m68360.
+ * tc-m68k.h (TARGET_WORD_SIZE): Define.
+ (TARGET_ARCH): Define.
+
+ * expr.c (integer_constant): If TARGET_WORD_SIZE is defined,
+ sign-extend appropriately.
+
+Thu Apr 13 11:20:17 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (ppc_elf_validate_fix): Properly use PARAMS to
+ hide prototype from non-ANSI compilers, and don't use ANSI syntax
+ for arguments.
+
+Wed Apr 12 12:20:19 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-config.in (TDEFINES): Put empty definition into
+ makefile fragment.
+ * mpw-make.in (xmalloc.c.o): Remove.
+ (as.new): Depend on Version.r.
+ (Version.r): Generate from version info.
+
+ * mpw-make.in: Delete references to hex-value.c.
+
+ * mpw-config.in: Add mapping from configs to object file formats,
+ get VERSION from Makefile.in and add to mk.tmp.
+ (mips-idt-ecoff) [TDEFINES]: Add TARGET_BYTES_BIG_ENDIAN.
+ * mpw-make.in (VERSION, gC): Don't define.
+ (ALL_CFLAGS): Remove -d flags.
+ (config.h): Remove definition of MPW, add HAVE_STDARG_H,
+ BFD_ASSEMBLER.
+
+ * mpw-make.in (ALL_CFLAGS): Add definition of HAVE_STDARG_H,
+ include of ::libiberty:.
+ (config.h): Ifdef contents on GAS_VERSION.
+
+ * mpw-make.in (as.c): Compile with C not gC.
+ (config-stamp): Touch correctly.
+ (install-only): New target.
+ (install): Depend on all and install-only.
+
+ * mpw-config.in: Parse target and use to generate forward includes
+ to tc-, obj-, and atof- files, use te-generic.h for emulation.
+ * mpw-make.in (VERSION): Define.
+ (as.c): Compile with GCC.
+ (TARG_OBJECTS, CLIBS): Define.
+ (as.new): Use LDFLAGS, TARG_OBJECTS, CLIBS and EXTRALIBS in link
+ command.
+ (config.h, config-stamp): Build.
+
+ * mpw-make.in (C, CFLAGS): Removed definitions.
+ (ALL_CFLAGS): Define.
+ Set default rule to use {CC} instead of {C}.
+
+ * mpw-make.in (install): Moved here from mpw-build.in.
+ * mpw-build.in: Removed, functionality in mpw-make.in
+
+ * mpw-make.in (CFLAGS): Add more include paths.
+
+ * mpw-config.in (varargs.h, sys/*.h): Don't create when
+ configuring.
+ * mpw-make.in (CFLAGS): Add -w flag.
+
+ * mpw-make.in: Replace 8-bit chars with their names.
+
+ * mpw-config.in: New file, MPW version of configure.in.
+ * mpw-make.in: New file, MPW version of Makefile.in.
+
+Tue Apr 11 01:42:36 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * configure.in: Require at least autoconf 2.3, because earlier
+ versions lose on some AIX versions.
+ * configure: Regenerated.
+
+ * configure.in: Add m68k-*-elf.
+ * config/tc-m68k.c (comment_chars) [OBJ_ELF]: Include '#'.
+ (md_pseudo_table) [OBJ_ELF]: Ignore "swbeg".
+ (md_begin): Set alt_notend_table['&'], so svr4-style immediate
+ operands are accepted.
+ (md_apply_fix): Argument VALP should point to valueT.
+ (md_convert_frag): Argument SEC should be type segT.
+ (md_shortopts) [OBJ_ELF]: Accept 'Q' with an argument.
+ (md_parse_option): Ignore it.
+ (md_convert_frag_1): Add in frag address for the symbol in the
+ displacement calculation.
+ * config/tc-m68k.h (TARGET_FORMAT) [OBJ_ELF]: Use "elf32-m68k".
+ (TARGET_ARCH): Define.
+ (REGISTER_PREFIX_OPTIONAL) [OBJ_ELF]: Default to 0.
+ (LOCAL_LABEL, FAKE_LABEL_NAME, REGISTER_PREFIX_OPTIONAL): Handle
+ these the same way for OBJ_ELF as for M68KCOFF.
+
+ * gdbinit.in: Add breakpoint in as_abort.
+
+ * write.c (cvt_frag_to_fill): If offset is less than zero,
+ complain about it specifically, instead of reporting an assertion
+ failure.
+ (relax_segment): Complain about .org backwards, then ignore it.
+ Do generic rs_machine_dependent relaxation only if
+ TC_GENERIC_RELAX_TABLE is defined, and use its value for the base
+ of the table.
+ * tc.h (md_relax_table): Delete declaration.
+ * as.h (struct relax_type): Add forward declaration for type.
+ * config/tc-a29k.c: Deleted md_relax_table.
+ * config/tc-{alpha,arm,h8300,hppa,i860,m88k,mips,ppc,sparc,z8k}.c:
+ Ditto.
+ * config/tc-{h8500,i386,i960,ns32k,sh,tahoe,vax,w65}.h: Declare
+ md_relax_table here, and define TC_GENERIC_RELAX_TABLE to expand
+ to md_relax_table.
+ * config/tc-h8500.c (md_relax_table): No longer const.
+ * config/tc-w65.c (md_relax_table): Ditto.
+ * config/tc-sparc.c (md_short_jump_size, md_long_jump_size):
+ Deleted.
+ * doc/internals.texi: Describe TC_GENERIC_RELAX_TABLE and
+ WORKING_DOT_WORD. Mention md_*_jump_size (but description needs
+ to be fleshed out later). Note m68k PCINDEX mode has been checked
+ in.
+
+Mon Apr 10 15:57:42 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/tc-mips.c (nopic_need_relax): New static function, split
+ out from md_estimate_size_before_relax.
+ (md_estimate_size_before_relax): Call it.
+ (load_address, macro): In NO_PIC branches, if nopic_need_relax
+ returns nonzero, don't attempt GP optimization.
+
+ * config/tc-m68k.c (PCINDEX): New macro.
+ (md_relax_table): No longer const. Add PCINDEX entries.
+ (m68k_ip): For AINDX with simple symbol operand, generate a
+ PCINDEX frag if PC is used, or do normal non-AINDX processing for
+ address register.
+ (m68k_init_after_args): If cpu is 68000 or 68010, fix
+ md_relax_table to prevent relaxation of PCINDEX/BYTE mode to
+ SHORT, since they don't support that mode.
+ (md_convert_frag_1, case PCLEA/LONG): Add 4 to offset, not 2. Add
+ support for new PCINDEX modes.
+ (md_estimate_size_before_relax): Process PCINDEX/SZ_UNDEF mode.
+
+ * config/tc-m68k.c (md_convert_frag_1, case PCLEA/SHORT): Add 2 to
+ offset.
+ (m68k_ip, case most punctuation/AOFF): If using PC, call add_frag
+ using PCLEA.
+
+ * config/tc-m68k.c: Don't explicitly include config.h. Deleted a
+ bunch of "#if 0" code and useless comments.
+ (struct m68k_cpu): New type.
+ (archs, n_archs): New variables, with single list of name/enum
+ mapping and aliases.
+ (m68k_ip): Delete the table here.
+ (m68k_init_after_args): Use the new table here instead of
+ open-coding it.
+ (md_parse_option, case 'm'): Ditto.
+
+ * doc/Makefile.in (Makefile): Fix rule for running config.status.
+ (internals.dvi, internals.ps, internals.ps4): New targets, not
+ built by default.
+
+ * doc/internals.texi: Add loud disclaimer. Refill to 79 columns,
+ specify fill-column in local-variables section. Change
+ subheadings to subsections so they can be cross-referenced.
+ Describe broken words, frags, frag chains, generic relaxation,
+ relax table, m68k relaxation, m68k addressing modes, test suite
+ code. Add a few words about various file formats.
+
+ * doc/as.texinfo (m68k): Recommend using `%' with registers as the
+ normal case, instead of the exceptional case.
+
+Thu Mar 30 14:38:47 1995 H.J. Lu (hjl@nynexst.com)
+
+ * configure.in: Change linux to default to elf. Using
+ i[345]86-*-linuxaout will defaults to a.out.
+ * configure: Rebuild.
+
+Wed Mar 29 17:16:30 1995 Torbjorn Granlund <tege@adder.cygnus.com>
+
+ * config/tc-m68k.c (md_apply_fix_2): Cast negative offsets to offsetT
+ (for hosting on 64 bit machines).
+
+Tue Mar 21 16:53:27 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (md_show_usage): Mention -mips4 and -m4650.
+
+Fri Mar 17 16:47:13 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * write.c (write_object_file): Add PROGRESS macros.
+
+Fri Mar 17 12:40:34 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (pa_comm): Make sure to always reset the frag
+ and section for common symbols.
+
+Thu Mar 16 17:26:18 1995 Michael Meissner <meissner@cygnus.com>
+
+ * config/tc-ppc.c (ppc_elf_validate_fix): Allow non PC relative
+ pointers in the .ctors and .dtors section also when using the
+ -mrelocatable option.
+ (md_parse_option): Support -m403 as a PowerPC computer.
+ (md_show_usage): Ditto.
+
+Wed Mar 15 14:45:42 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * ecoff.c (ecoff_build_debug): The cur_scope field of a fil_ptr
+ may be NULL when given strange input. Don't core dump.
+
+Tue Mar 14 21:36:34 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (load_register): Don't use addiu for dli of an
+ unsigned seemingly negative number. Don't bother shifting a zero
+ value.
+ (mips_ip): For case 'j', if there are more alternatives, and the
+ ISA level is at least 3, don't accept an unsigned seemingly
+ negative number.
+
+Tue Mar 14 19:16:43 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * read.c (s_app_line): Fix last patch to deal with a line number
+ of 1.
+
+Tue Mar 14 17:00:57 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (ppc_elf_validate_fix): Use as_warn_where, not
+ as_bad_where to give a warning instead of an error.
+
+Mon Mar 13 17:03:46 1995 Pat Rankin (rankin@eql.caltech.edu)
+
+ * config/tc-vax.c (md_assemble): issue a warning if a constant
+ is used as an operand where an immediate value is not allowed.
+
+Fri Mar 10 19:21:19 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/obj-coff.c: Redo my 10 Jan change, but get it right this
+ time. :-)
+ (fixup_segment): If linkrelax is set, just return.
+ (write_object_file): Don't treat h8300 and z8k specially with
+ regard to fixups.
+ * config/tc-h8300.c (md_begin): Set linkrelax.
+ * config/tc-z8k.c (md_begin): Ditto.
+
+Thu Mar 9 18:01:37 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.c (coff_header_append): Check return value of
+ bfd_coff_swap_scnhdr_out.
+
+Thu Mar 9 13:51:30 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ Delete this patch, it breaks the h8300 assembler.
+ Tue Jan 10 13:34:14 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+ * config/obj-coff.c (write_object_file): Don't treat h8300 and z8k
+ specially with regard to fixups.
+
+Thu Mar 9 12:28:18 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (mrelocatable): Change type to boolean.
+ (md_begin): Set the EF_PPC_RELOCATABLE if -mrelocatable.
+
+Wed Mar 8 15:39:39 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (md_begin): Check for a cpu string of r8000 or
+ r10000. If mips_isa is 4, set the machine number to 8000.
+ (append_insn): If mips_isa is at least 4, don't generate nops for
+ coprocessor delays. Check INSN_READ_FPR_R when setting
+ mips_cprmask[1].
+ (mips_emit_delays): If mips_isa is at least 4, don't generate nops
+ for coprocessor delays.
+ (mips_ip): Check for INSN_ISA4 instructions. Handle new argument
+ types 'h', 'R', 'N', and 'M'.
+ (md_longopts): Accept "mips4".
+ (md_parse_option): Handle -mips4, and -mcpu=10000 and -mcpu=8000.
+ (s_mipsset): Permit .set mips4.
+
+Wed Mar 8 09:36:05 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (ppc_elf_validate_fix): Allow .stab sections to
+ have non PC relative relocations with -mrelocatable.
+
+Wed Mar 8 02:57:53 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/tc-m68k.c (opcode_ptr): Return pointer to const.
+ (md_begin): Make hash table errors fatal. Process opcode aliases
+ after main opcode table.
+ (md_apply_fix_2, case 4): Recode setting of lower_limit to avoid
+ gcc warning.
+
+Tue Mar 7 16:07:10 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * doc/as.texinfo: Add documentation for SPARC V9, from Doug Evans
+ <dje@cygnus.com>.
+
+Mon Mar 6 09:58:34 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c: Change all occurences of pa-89 with pa-11 to
+ be consistent with current naming conventions.
+ (md_begin): Set a default architecture and machine type.
+ (pa_ip): If the current instruction specifies a newer machine type
+ than the current machine type, then update the current machine
+ type.
+ (need_pa11_opcode): Likewise.
+
+Sun Mar 5 19:38:09 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (pa_ip, case 'z'): Don't lose argument
+ relocation bits for absolute calls.
+
+Fri Mar 3 17:41:50 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/tc-h8300.* (md_operand): Change empty function to empty
+ macro.
+
+ * config/tc-h8300.c (build_bytes): Make H8/300-H warning message
+ clearer.
+
+ * write.c (write_contents): If bfd_set_section_contents fails,
+ print a message and exit, instead of aborting.
+
+Fri Mar 3 16:26:19 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * tc.h (md_apply_fix3): If MD_APPLY_FIX3 is defined, declare
+ md_apply_fix3.
+
+ * write.c (fixup_segment): If MD_APPLY_FIX3 is defined, call
+ md_apply_fix3 with the normal 2 arguments and the current segment
+ pointer instead of md_apply_fix.
+
+ * config/tc-ppc.h (MD_APPLY_FIX3): Define.
+
+ * config/tc-ppc.c (ppc_elf_validate_fix): Warn if -mrelocatable
+ and a non PC relative relocation that isn't in the .got2 segment
+ was performed.
+ (md_apply_fix3): Rename from md_apply_fix and take segment pointer
+ as third argument. If ELF object format, call ppc_elf_validate_fix
+ for normal relocations.
+ (md_parse_option): If ELF object format, recognize the
+ -mrelocatable switch.
+
+Thu Mar 2 16:34:44 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-i386.h (AOUT_MACHTYPE): Define as 100, not 0.
+
+Tue Feb 28 18:29:27 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/tc-arm.c, config/tc-arm.h (md_operand): Replaced empty
+ function in .c file with empty macro in .h file.
+ * config/tc-h8500.*, config/tc-hppa.*, config/tc-i386.*,
+ config/tc-i860.*, config/tc-i960.*, config/tc-ns32k.*,
+ config/tc-ppc.*, config/tc-sh.*, config/tc-sparc.*,
+ config/tc-tahoe.*, config/tc-vax.*, config/tc-w65.*,
+ config/tc-z8k.*: Ditto.
+ * config/tc-m68k.*: Ditto.
+
+ * config/tc-m68k.c (mote_pseudo_table): Removed dots from opcode
+ names.
+
+ * read.c (s_app_line): Ignore non-positive line numbers.
+
+Tue Feb 28 15:34:14 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-i386.c (tc_i386_fix_adjustable): Don't adjust PLT or
+ GOT relocs either.
+
+Mon Feb 27 13:03:41 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * configure.in: add a29k-*-vxworks configuration.
+
+Fri Feb 24 14:41:15 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (load_register): Take dbl argument to determine
+ handling of signed 32 bit values in 64 bit modes. Change all
+ callers.
+ (macro): Handle M_DLI and M_DLA_AB.
+
+Wed Feb 22 23:10:56 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (md_apply_fix): Don't subtract the value of the
+ add symbol if it's a common symbol (the value of a common symbol
+ is its size, not a value in the traditional sense).
+
+Wed Feb 22 21:12:28 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (append_insn): If listing_prev_line is called,
+ call frag_grow to make sure there is still room for a variant.
+
+Fri Feb 17 14:50:08 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (md_pseudo_table): Add 2byte, 4byte and 8byte
+ if OBJ_ELF. From gary@Intrepid.COM (Gary Funck).
+
+ * config/obj-elf.c (elf_frob_symbol): Warn if a symbol is both
+ weak and common.
+ * config/obj-aout.c (obj_aout_frob_symbol): Likewise.
+
+Fri Feb 17 12:43:47 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (md_pseudo_table): Don't redefine byte under
+ ELF.
+ (ppc_elf_cons): Don't support @pcrel any more, since DIFF_EXPR_OK
+ allows the normal expressions to generate it.
+ (md_apply_fix): Convert BFD_RELOC_32 with pcrel bit set into
+ BFD_RELOC_32_PCREL. Abort if either BFD_RELOC_16 or BFD_RELOC_8
+ need PC relative relocations.
+
+ * config/tc-ppc.h (DIFF_EXPR_OK): Define to allow PC relative
+ expressions to be handled.
+
+Thu Feb 16 14:30:13 1995 Doug Evans <dje@cygnus.com>
+
+ * expr.c (operand): Move md_operand handling to default case
+ (so it works).
+
+Wed Feb 15 16:08:47 1995 Jason Molenda <crash@cygnus.com>
+
+ * config/tc-h8500.c (tc_coff_symbol_emit_hook): Add ignored
+ parameter, to match prototype.
+
+Wed Feb 15 15:07:00 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (md_pseudo_table): If ELF, go to ppc_elf_cons
+ instead of cons.
+ (md_show_usage): Show all of the PowerPc options.
+ (ppc_elf_suffix): New function to recognize ELF suffixes that
+ specify a relocation, such as @GOT.
+ (ppc_elf_cons): Replacement for the standard cons function that
+ knows about the ELF suffixes.
+ (ppc_fixup): Add reloc field to hold non-standard relocation.
+ (md_assemble): Handle ELF suffixes like @GOT.
+ (md_create_short_jump): Dummy in case WORKING_DOT_WORD is not
+ defined.
+ (md_create_long_jump): Ditto.
+ (md_short_jump_size): Ditto.
+ (md_long_jump_size): Ditto.
+ (md_apply_fix): Handle BFD_RELOC_32_PCREL, BFD_RELOC_LO16,
+ BFD_RELOC_HI16, BFD_RELOC_HI16_S, BFD_RELOC_PPC_TOC16, and
+ BFD_RELOC_16 relocations. If relocation can not be found, print
+ the decimal value of the relocation.
+
+Wed Feb 15 11:46:02 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (md_apply_fix): Accept BFD_RELOC_16, for
+ DWARF. From gary@Intrepid.COM (Gary Funck).
+
+ * config/tc-mips.c (macro): Handle M_U{L,S}D[_A] (unaligned double
+ loads and stores).
+
+ * config/tc-i386.c (tc_i386_fix_adjustable): Do adjust global
+ symbols if OBJ_AOUT.
+
+ * config/tc-mips.c (macro): Don't use the target register as a
+ base register when building the address for M_L{W,D}{L,R}_AB.
+
+Mon Feb 13 14:44:32 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (KT0, KT1): Define.
+ (mips_ip): Recognize $kt0 and $kt1 as register names.
+
+ * config/tc-sparc.h (tc_fix_adjustable): Define if OBJ_ELF.
+ * config/tc-sparc.c (md_apply_fix): If OBJ_ELF, subtract out the
+ value of a defined symbol; the value was added in by
+ fixup_segment. This was previously corrected, if the reloc was
+ changed to be against a section symbol, in tc_gen_reloc.
+
+Fri Feb 10 14:04:04 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-i386.c (tc_i386_fix_adjustable): Use S_IS_EXTERN
+ rather than !S_IS_LOCAL.
+
+Thu Feb 9 18:16:34 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-i386.c (md_assemble): Adjust conditions for changing
+ BFD_RELOC_32 to BFD_RELOC_386_GOTPC to handle a switch in frags.
+ Patch originally from Rob Ryan <robr@cmu.edu>.
+
+ * config/tc-i386.c: Include subsegs.h.
+ (tc_i386_fix_adjustable): Declare return value.
+ (i386_operand): Don't use an assignment directly as a condition.
+
+Thu Feb 9 10:37:13 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (md_apply_fix): In some cases subtract the
+ value of the add symbol from valp. Offsets braindamage in the
+ "machine independent" fixup_segment.
+
+Wed Feb 8 18:51:23 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * messages.c (as_abort): New function.
+ * as.h (as_abort): Declare it.
+ (abort): New macro.
+
+ Thu Jan 19 18:10:05 1995 Pat Rankin (rankin@eql.caltech.edu)
+
+ * config/vms-conf.h (HAVE_UNISTD_H): define it unconditionally.
+ * config-gas.com: test for availability of <unistd.h>; create a
+ rudimentary one if necessary.
+
+Tue Feb 7 13:34:46 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure.in: Add powerpc-*-eabi support, which is the same as
+ powerpc-*-elf.
+ (configure): Rebuild with autoconf.
+
+Mon Feb 6 03:37:00 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ Changes from Bryan Ford <baford@schirf.cs.utah.edu> for i386
+ 16-bit and msdos support:
+ * config/tc-i386.c (flag_16bit_code): New variable.
+ (set_16bit_code_flag): New function.
+ (md_pseudo_table): Added entries "code16" and "code32".
+ (md_assemble): Ensure that correct data-size prefixes get emitted,
+ based on the current mode. Ensure that 32-bit addressing will
+ always be done. Move segment-prefix handling code. (Why?) Use
+ 16-bit jumps for 16-bit code, 32-bit jumps for 32-bit code.
+ * config/tc-i386.h (MAX_PREFIXES): Bump to 5.
+ (Data16, Data32): Define.
+ * doc/as.texinfo (i386-16bit): New node.
+ * configure.in (i386-*-msdos*): New target, using a.out format.
+ * configure: Regenerated.
+
+Thu Feb 2 15:21:24 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/tc-m68k.c (cpu32_control_regs): New macro.
+ (m68k_init_after_args): Use it, for cpu32 processors.
+
+ Tue Jan 31 17:20:45 1995 Pat Rankin (rankin@eql.caltech.edu)
+
+ * config/obj-vms.c (vms_tir_stack_psect): new routine;
+ (VMS_Set_Data, VMS_Set_Psect, VMS_Store_PIC_Symbol_Reference,
+ VMS_TBT_Routine_Begin, VMS_TBT_Line_PC_Correlation): use it;
+ (VMS_Global_Symbol_Spec, VMS_Procedure_Entry_Pt): treat
+ Psect_Number as `unsigned'.
+
+ Thu Jan 26 17:06:28 1995 Pat Rankin (rankin@eql.caltech.edu)
+
+ * config/obj-vms.c: performance tuning.
+ (VMS_Symbol_type_list): convert from single list head to small
+ array of list heads;
+ (SYMTYP_HASH): new macro for accessing VMS_Symbol_type_list[];
+ (find_symbol, setup_basic_type, VMS_typedef_parse): use it;
+ (VMS_RSYM_Parse): move S_GET_VALUE() inside switch to avoid
+ calling it for uninteresting cases.
+
+Wed Feb 1 23:52:45 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (md_apply_fix): Go ahead and call
+ hppa_field_adjust to get a new value for R_DATA_ONE_SYMBOL
+ relocations in SOM.
+ (hppa_fix_adjustable): Refine somewhat.
+
+Fri Jan 27 21:29:53 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.h (NO_STRING_ESCAPES): Don't define if we are
+ using ELF.
+
+Thu Jan 26 19:03:42 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/tc-h8300.c (get_specific): Add parens around | inside &.
+ (skip_colonthing): Set L_8 if ":8" is specified.
+
+Thu Jan 26 18:38:01 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-ppc.c (md_begin): Permit mfdec to be duplicated on the
+ 601. Check that the error return from hash_insert is "exists".
+
+Thu Jan 26 11:35:33 1995 Michael Meissner <meissner@cygnus.com>
+
+ * configure: Add support for configuring powerpc-*-eabi.
+
+ * config/tc-ppc.c (GOT_symbol): Define if object format is ELF.
+
+ * config/tc-ppc.h (GLOBAL_OFFSET_TABLE_NAME): Define if object
+ format is ELF and not defined to be "_GLOBAL_OFFSET_TABLE_".
+
+Wed Jan 25 16:23:13 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * tc-sh.c (little): Add argument IGNORE to avoid compiler warnings.
+ (md_pseudo_table): Add space for consistent formatting.
+ (COND8_RANGE, COND12_RANGE): Delete unused macros.
+ (COND8_F, COND8_M, COND12_F, COND12_M, UNCOND12_F, UNCOND12_M):
+ Correct minimum and maximum branch offsets. Add comments explaining
+ why these numbers are correct.
+
+Wed Jan 25 15:32:09 1995 David Edelsohn <edelsohn@mhpcc.edu>
+
+ * config/tc-ppc.c (md_parse_option): Accept mpwr2 as a synonym for
+ mpwrx; mppc32, m603, and m604 as synonyms for mppc; and mppc64 and
+ m620 for PowerPC64 mode.
+ (ppc_symbol_new_hook): Add T0 as synonym for TC0 suffix.
+
+Tue Jan 24 16:44:23 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/tc-vax.c (vip): Introduce new ptr-to-const local variable
+ for scanning operand string.
+
+ Sat Jan 21 17:50:38 1995 Pat Rankin (rankin@eql.caltech.edu)
+
+ * config/vax-inst.h (struct vop, fields `vop_warn', `vop_error'):
+ make them pointers to const char;
+ (struct vit, field `vit_error'): ditto.
+ * config/atof-vax.c (md_atof): rename local `littlenum_pointer'
+ to `littlenumP' to avoid shadowing file scope variable.
+ * config/tc-vax.c (vip_begin, vip_op_defaults, vip_op_1): make
+ string arguments be pointers to const char;
+ (vip): make `alloperr' const char *;
+ (vip_op): make `err' and `wrn' const char *; rename `access' to
+ `access_mode' to avoid shadowing library function.
+ * config/obj-vms.c (`symbol_name'): make it const char *;
+ (get_struct_name): cast one use of `symbol_name' to char *
+ [caller guarantees that it won't modify the pointer's target];
+ (PUT_COUNTED_STRING): use pointer to const char;
+ (VMS_typedef_parse): make `pnt2' const char *;
+ (Write_VMS_MHD_Records): make `cp' const char *;
+ (VMS_Modify_Psect_Attributes, array `Attributes'): make const,
+ and make field `Name' pointer to const char;
+
+ * as.h (`seg_name[]' declaration): pointers to const char;
+ (struct _pseudo_type, field `poc_name'): pointer to const char.
+ * subsegs.c (`seg_name[]' definition): ditto;
+ * hash.c (hash_ask): rename argument `access' to `access_type'
+ to avoid shadowing library function.
+ * write.c (variable `the_object_file'): move from file scope
+ to block scope within write_object_file(); free it after use;
+ (fixup_segment): conditionally exclude it for OBJ_VMS.
+ (cvt_frag_to_fill): rename argument `headers' to `headersP'
+ to avoid shadowing file scope variable.
+
+Mon Jan 23 21:42:39 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (pa_ip, case 'D'): Fix typo which caused
+ miscompilation of "diag" instructions.
+
+Mon Jan 23 15:51:41 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * configure: Regenerated.
+
+ * config/tc-mips.c: Include libiberty.h.
+
+Mon Jan 23 14:07:58 1995 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * config/tc-sh.h (tc_init_after_args): Don't define.
+ * config/tc-sh.c (md_begin): Remove unused variable table.
+ (md_assemble): Remove unused variable p.
+ (md_convert_frag): Cast fr_address to unsigned long for printf.
+ (md_apply_fix): Use as_warn_where rather than as_warn.
+ (sh_init_after_args): Remove empty function.
+
+ * configure.in (i386-*-gnu*elf*): New target.
+
+Sat Jan 21 19:02:23 1995 Ian Lance Taylor <ian@tweedledumb.cygnus.com>
+
+ * hash.c (hash_ask): If we find the slot after wrapping around,
+ break out of the loop. Fixes bug in Jan 18 change.
+
+Fri Jan 20 17:07:31 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * hash.c (hash_code): Undo last change.
+
+Thu Jan 19 14:49:47 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/tc-alpha.c (alpha_ip): Initialize local variables to keep
+ gcc quiet.
+ (gpdisp_hi16_howto): Don't use "const" with reloc_howto_type.
+ (in_range_signed): Add parens around subtraction inside shift.
+ * gasp.c (do_data): Initialize local variable "opname".
+ (istrue): Provide a default case to set "res" and keep "gcc -Wall"
+ quiet.
+ * write.c (write_contents): Deleted unused variable.
+ (print_symbol_value_1): Declare.
+ * hash.c (hash_ask): Delete disabled non-strcmp version of the
+ code, and automatic variables used only in those sections.
+ * write.c (chain_frchains_together_1): Only define local variable
+ "prev_fix" if BFD_ASSEMBLER.
+ * flonum-konst.c (dummy1): Return void.
+ * config/tc-vax.c (md_assemble): Remove two comparisons of
+ unsigned numbers versus zero.
+ * as.h (bcopy): If neither memcpy nor bcopy is defined as a macro,
+ define to use memcpy.
+
+ * config/tc-alpha.c, config/alpha-opcode.h: Revert 2 June changes.
+ Turns out we never got the assignment done after all.
+
+ Cleanup of VAX and VMS code, from Pat Rankin:
+ * config/obj-vms.c: Changed exported function names to lower case.
+ (Changed call sites in write.c.) Declare VMS system function
+ names used, conditional on actually being on VMS. Changed many
+ functions that returned no useful value to now be declared to
+ return void. Removed many unused variables. Supply missing
+ return statements or values. Supply `default' case in switch
+ statements. Ensure local variables get initialized.
+ * config/tc-vax.c: Minor changes to silence "gcc -Wall".
+ * config/obj-vms.h, config/tc-vax.h: Added some missing
+ declarations.
+
+Wed Jan 18 13:49:26 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * atof-generic.c (flonum_print) [TRACE]: New function.
+ (atof_generic) [TRACE]: Print multiplier before multiplication,
+ and print multiplication result before and after copy.
+
+ * flonum-mult.c (flonum_multip): Avoid sign extension problems
+ around multiplication operation.
+
+ * atof-generic.c (ASSUME_DECIMAL_MARK_IS_DOT): Define.
+ (atof_generic) [ASSUME_DECIMAL_MARK_IS_DOT]: Check for '.'
+ explicitly instead of calling strchr.
+
+ * config/tc-sparc.c (sparc_ip): When scanning successive opcode
+ table entries, check names for pointer equality before doing
+ string comparisons.
+
+ * hash.c (hash_ask): Call strcmp instead of expanding it inline.
+ (hash_code): Replaced with a version from bfd.
+
+ * config/obj-coff.c (write_object_file): If COFF_FLAGS isn't
+ defined, default it to zero.
+
+Wed Jan 18 12:16:07 1995 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * write.c (fix_new_internal): Clear fx_bsr on those targets which
+ use it.
+
+ * expr.c (operand): Parenthesize && within ||.
+ * listing.c (listing_newline): Likewise.
+ (list_symbol_table): Use %lu to print sizeof.
+ * symbols.c: Comment out unused function indent.
+ (print_symbol_value_1): Cast pointer to unsigned long for printf.
+ * config/obj-coff.c (do_relocs_for): Only declare symbol_ptr if it
+ will be used.
+ * config/tc-h8300.c (md_begin): Remove unused variable reg.
+ (get_operand): Declare type of parameter direction. Remove unused
+ variable size.
+ (get_specific): Fix comment to avoid nested comments.
+ (check_operand): Cast X_add_number to unsigned long for printf.
+ (build_bytes): Remove unused local variables output_ptr, part, and
+ high.
+ (build_bytes): Cast X_add_number to unsigned long for printf.
+ (clever_message): Remove unused variable scan.
+ (md_assemble): Remove unused variable i.
+ (tc_coff_sizemachdep): Remove unused function.
+ * tc-h8300.h (tc_reloc_mangle): Declare.
+
+Tue Jan 17 10:58:06 1995 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * config/tc-mips.c (mips_4650): New static variable.
+ (md_begin): Handle a cpu string of "4650". If mips_4650 was not
+ initialized, set it to 0.
+ (append_insn): Don't insert nops around HI and LO on a 4650.
+ (mips_emit_delays): Likewise.
+ (mips_ip): Use INSN_ISA mask to check ISA of instruction. Check
+ for INSN_4650.
+ (md_longopts): Add m4650 and no-m4650.
+ (md_parse_option): Handle mips-cpu=4650. Handle -m4650 and
+ -no-m4650.
+ * doc/as.texinfo: Document new MIPS options.
+
+Sat Jan 14 23:48:13 1995 Steve Chamberlain <sac@jonny>
+
+ * config/tc-w65.c, config/tc-w65.h, config/w65.mt: Newfiles.
+ * config/obj-coff.h: Cope with w65.
+ * configure, configure.in: Recognize w65.
+
+Thu Jan 12 17:56:24 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * app.c (do_scrub_next_char) [__GNUC__ && __OPTIMIZE__]: If `get'
+ function is scrub_from_file, call scrub_from_file directly, and
+ get gcc's inlining capability into the act.
+
+ * Makefile.in (VMS_OTHER_OBJS): Add ../libiberty/hex.o.
+ (OBJS): Delete hex-value.o.
+ (REAL_SOURCES): Delete hex-value.c.
+ (hex-value.o): Delete dependencies.
+ * hex-value.c: Deleted.
+ * as.c (main): Call hex_init.
+ * expr.c, config/tc-mips.c: Include libiberty.h. Replace
+ hex_value array references with hex_* macros.
+
+Wed Jan 11 17:51:38 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/tc-h8300.h (COFF_FLAGS): Don't define.
+ * config/tc-h8500.h (COFF_FLAGS), config/tc-sh.h (COFF_FLAGS),
+ config/tc-z8k.h (COFF_FLAGS): Ditto.
+
+ * config/obj-coff.c (KEEP_RELOC_INFO): Make sure it's always
+ defined.
+
+ * config/tc-m68k.c (m68k_ip, cases AOFF and AINDEX): Don't
+ generate 68020 addressing modes for a 68000 processor.
+ (md_estimate_size_before_relax, cases PCREL and PCLEA): Ditto.
+
+Tue Jan 10 13:34:14 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/obj-coff.c (write_object_file): Don't treat h8300 and z8k
+ specially with regard to fixups.
+
+Mon Jan 9 16:22:28 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/tc-mips.c (RELAX_RELOC1, RELAX_RELOC2): Cast values to
+ bfd_vma before subtracting.
+
+ * config/obj-coff.c (size_section): Handle rs_space like rs_fill,
+ but make sure fr_symbol is null.
+ (fill_section): Ditto.
+
+Sun Jan 8 16:14:19 1995 Ian Lance Taylor <ian@tweedledumb.cygnus.com>
+
+ * config/tc-mips.c (mips_ip): Fix handling of floating point
+ values when GPOPT is not defined.
+
+Fri Jan 6 16:59:41 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * gasp.c: Include string.h. Put config.h before other includes.
+
+ * config/tc-alpha.c (alpha_ip): Delay calls to emit_add64 until
+ after any remaining operands are also known to match.
+
+Fri Dec 30 18:21:41 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * listing.c (list_symbol_table): Build a format string based on
+ the size of the value to be printed, as long as "unsigned long" is
+ at least as wide, after handling the special case of 4-byte
+ values.
+
+ * Makefile.in (dependencies): Make $(OBJS) depend on as.h and
+ everything it includes. Delete those files from per-file
+ dependencies.
+
+ * as.h (relax_substateT): Now defined to be unsigned int.
+ (relax_stateT): Separate typedef from enum definition.
+ (enum _relax_state): Reordered for better punctuation. Added new
+ values rs_align_code and rs_space.
+ (lineno, struct lineno_struct): Unused, deleted.
+
+ * as.h: No longer include assert.h.
+ (as_assert): Declare.
+ (assert): New definition, calls as_assert longer needed.
+ (__PRETTY_FUNCTION__): Provide default for older versions of gcc.
+ * messages.c (as_assert): New function.
+ * gdbinit.in: Put a breakpoint there.
+
+ * read.c (s_space): Rewrite to handle general expressions.
+ Generate rs_space frags for non-constant values.
+ * write.c (cvt_frag_to_fill): Treat rs_align_code and rs_space
+ like rs_align and rs_org. Verify that fr_offset is non-negative,
+ and force frag type to rs_fill only after assertion checks.
+ (relax_segment): Treat rs_align_code like rs_align. Treat
+ rs_space like rs_org in the first switch; in the second, force the
+ operand to a constant, and use it for the growth size.
+
+Wed Dec 28 20:57:37 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (pa_subspace): For sections with the ZERO
+ attribute, set the "bss" field in the appropriate seginfo structure.
+
+Wed Dec 28 15:01:01 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * subsegs.h: Include obstack.h.
+
+Tue Dec 27 18:16:04 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * as.h (struct frag): Enable align* components now.
+
+Tue Dec 20 14:56:31 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * frags.c (frag_init): Call obstack_begin on `frags'.
+ * subsegs.c (subsegs_begin): Don't do it here.
+ * as.c (main): Call frag_init before subsegs_begin.
+
+ * frags.c (frag_append_1_char): New function.
+ * frags.h (frag_append_1_char): Declare it.
+ (FRAG_APPEND_1_CHAR): Call it. Old definition is commented out
+ for now.
+
+ * as.h (struct frag): Added (but commented out) new fields for
+ tracking current alignment.
+ (frag_now_fix): Changed macro to function declaration.
+ * frags.c (frag_now_fix): Define function here.
+ (frag_new): Use it instead of accessing `frags' directly.
+ * frags.h (frags): Change comment to indicate it shouldn't be
+ accessed directly.
+ * subsegs.h (struct frchain): New field frch_obstack, intended to
+ eventually replace global `frags' obstack.
+ * subsegs.c (subseg_set_rest): Use frag_now_fix instead of
+ accessing `frags' directly. Initialize fields of new frchainS
+ explicitly instead of with memset.
+ * config/obj-coff.c (obj_coff_ln) [!BFD_ASSEMBLER]: Use
+ frag_now_fix.
+ * config/tc-mips.c (s_loc), config/obj-vms.c
+ (vms_resolve_symbol_redef), symbols.c (colon): Likewise.
+
+ * config/tc-m68k.c (md_apply_fix_2): Use offsetT and addressT
+ instead of long and unsigned long.
+ (md_apply_fix): Cast value before passing it.
+
+ * config/obj-aout.h, config/obj-coff.c, config/obj-elf.h,
+ config/obj-som.h, config/tc-h8500.c, config/tc-hppa.c,
+ config/tc-hppa.h, config/tc-sh.c, config/tc-z8k.c: Don't rely on
+ use of ".." when including header files.
+
+ * config/obj-coff.c (fixup_segment): Reformat condition in an `if'
+ statement.
+
+ * Makefile.in (SUBDIR_INCLUDES): Deleted.
+
+Tue Dec 20 13:40:36 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * config/obj-coff.h: Include bfd/libcoff.h, not libcoff.h.
+
+Mon Dec 19 16:53:36 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * config/tc-mips.c (load_register): Rewrite to handle O_big 64 bit
+ constants.
+ (mips_ip): Accept O_big constants in case 'I'. Change case
+ 'i'/'j' to treat an O_big constant as an out of range value.
+
+Mon Dec 19 14:15:07 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (pa_subspace): Make sure SEC_HAS_CONTENTS is
+ clear for a section with the "ZERO" attribute.
+
+ * Reduce useless symbols for ELF in an attempt to make smaller
+ objects and speed up the linker.
+ * config/tc-hppa.c (struct call_info): Replace end_symbol field
+ with a size field.
+ (hppa_elf_mark_end_function): Delete unneeded function.
+ (pa_build_unwind_subspace): For the 2nd unwind relocation, use
+ the function symbol + function size instead of a special symbol
+ for the end of the function.
+ (process_exit): Compute the function size here. Don't call
+ hppa_elf_mark_end_of_function anymore.
+ (pa_procend): Likewise.
+ (hppa_fix_adjustable): Only reject 32bit relocations for SOM.
+ (elf_hppa_final_processing): Simplify.
+
+Mon Dec 19 13:49:07 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * configure.in: Recognize mips-sony-bsd and mips-dec-bsd, but
+ reject other vendors until we can be sure we're consistent with
+ bfd.
+
+ * config/obj-vms.c (Create_VMS_Object_File): Instead of formatting
+ a buffer to pass to `error', just call `as_fatal' directly.
+ (VMS_Psect_Spec): Ditto.
+ (VMS_TBT_Module_Begin, VMS_TBT_Source_File, gen1,
+ VMS_typedef_parse, VMS_LSYM_Parse, VMS_Emit_Globalvalues): Call
+ as_tsktsk instead of printf.
+ (VMS_TBT_Module_Begin, VMS_TBT_Line_PC_Correlation,
+ VMS_TBT_Source_File, VMS_TBT_Source_Lines,
+ VMS_Store_Repeated_Data, VMS_Check_For_Main): Use explicit
+ integers rather than sizeof expressions using basic integer types,
+ in case host and target aren't the same. Use memcpy or COPY_*
+ macros instead of possibly unaligned word or longword assignment.
+
+ * config/obj-vms.h (OBJ_SYMFIELD_TYPE): New macro.
+ * config/obj-vms.c (VMS_Store_PIC_Symbol_Reference,
+ VMS_Check_For_Main, VMS_write_object_file): Use sy_obj instead of
+ forcing sy_number to hold a pointer.
+
+Fri Dec 16 14:40:16 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/tc-sh.c (md_begin): Don't fill in md_relax_table here.
+ (md_relax_table): Use static initialization.
+
+ * config/tc-h8300.c (parse_exp, get_operands, clever_message,
+ md_assemble, tc_crawl_symbol_chain, md_undefined_symbol,
+ tc_headers_hook, md_operand, md_number_to_chars): Don't use DEFUN.
+
+ * Makefile.in (CHECKFLAGS): Don't pass AS_FOR_TARGET,
+ CC_FOR_TARGET, OBJDUMP_FOR_TARGET, NM_FOR_TARGET; they're not
+ used.
+ (AS_FOR_TARGET, CC_FOR_TARGET, OBJDUMP, OBJDUMP_FOR_TARGET, NM,
+ NM_FOR_TARGET): Don't define.
+ (VMS_OTHER_OBJS): Add xmalloc.o and xexit.o from libiberty.
+ (tooldir): Use exec_prefix, not libdir.
+
+Fri Dec 16 11:07:10 1994 Stan Shebs <shebs@andros.cygnus.com>
+
+ * config/obj-coff.h: Include libcoff.h, not ../bfd/libcoff.h.
+
+ * as.h: Include progress.h.
+ * as.c (main): Call START_PROGRESS and END_PROGRESS.
+ (main, perform_an_assembly_pass): Call PROGRESS.
+
+Fri Dec 16 00:46:08 1994 Ian Lance Taylor <ian@tweedledumb.cygnus.com>
+
+ * write.c (adjust_reloc_syms): Use bfd_is_und_section and
+ bfd_is_abs_section rather than comparing against &bfd_und_section
+ and &bfd_abs_section.
+
+Thu Dec 15 15:27:14 1994 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * config/tc-sh.c (md_begin): Use a local variable when
+ initializing md_relax_table to avoid errors about modifying a
+ const data structure.
+
+Tue Dec 13 15:42:27 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * config/tc-ppc.c (tc_gen_reloc): Remove OBJ_ELF hack which
+ appears to no longer be needed.
+
+Tue Dec 13 08:04:15 1994 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (macro_build): Accept BFD_RELOC_PCREL* without
+ requiring that the X_op_symbol be in the text_section.
+ (macro): Change the test for a legel expression difference to
+ correspond to changes in pseudo_set in read.c.
+
+Fri Dec 9 21:04:17 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * write.c (write_relocs) [RELOC_EXPANSION_POSSIBLE]: Use
+ bfd_install_relocation.
+
+ * ecoff.c (ecoff_set_gp_prolog_size): If there is no current
+ routine, just return.
+
+ * config/tc-alpha.c (alpha_ip, case 'B', subcase 'c'): Use opcode
+ value from pattern instead of assuming jsr.
+ * config/alpha-opcode.h (jmp): Add a "1,Bc" form.
+
+Thu Dec 8 17:48:25 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * Makefile.in (NM_FOR_TARGET): Use ../binutils/nm.new, not just
+ plain nm.
+
+ * configure.in (ns32k-pc532-mach*): Select correct emulation.
+ (mips-sony-bsd*): Use ecoff.
+ (mips-*-gnu*): New target, using aout format, from Roland McGrath.
+ * configure: Regenerated.
+
+Tue Nov 29 13:58:10 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ Use libiberty version of xmalloc:
+ * Makefile.in (REAL_SOURCES): Delete xmalloc.c.
+ (OBJS): Delete xmalloc.o.
+ (xmalloc.o): Delete dependencies.
+ * as.c (main): Call xmalloc_set_program_name once program name is
+ known.
+
+ * config/tc-alpha.c (in_range_signed, in_range_unsigned): New
+ routines, split from in_range.
+ (in_range): Deleted. All calls changed to in_range_*signed.
+ (create_lita_section): Macro deleted. Single use expanded in
+ place.
+ (alpha_ip): Handle `t' and `8' operand types.
+ (md_apply_fix): Handle BFD_RELOC_12_PCREL. Print name of
+ unhandled relocation types.
+ * config/alpha-opcode.h: Added HALT and DRAINA. Disabled MOVI,
+ since it doesn't work, and isn't supported by the native
+ assembler.
+
+ * input-scrub.c: Change wording of a comment to avoid interference
+ with Cygnus source-control tools.
+
+ * as.h (errno) [NEED_DECLARATION_ERRNO]: Declare.
+
+ * config/tc-m68k.c (init_table): List buscr and pcr control
+ registers.
+ (m68k_ip, case 'J'): Handle them.
+
+ Delete signal handler code. It's been disabled since March 1993
+ without complaints.
+ * as.c: Don't include signal.h.
+ (got_sig): Unused function deleted, declaration deleted.
+ (SIGTY): Macro deleted.
+ (main): Deleted disabled code for establishing signal handler.
+
+Mon Nov 28 11:37:35 1994 Doug Evans <dje@canuck.cygnus.com>
+
+ * app.c (do_scrub_next_char): Insert missing newline at end of file
+ like warning says we do.
+
+Mon Nov 28 00:11:15 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.h (pa_check_eof): Declare new extern function.
+ (tc_frob_file): Define to call pa_check_eof.
+
+ * config/tc-hppa.c (pa_check_current_space_and_subspace): New
+ function to verify the current space and subspace are reasonable.
+ Call for the appropriate pseudo-ops and before instruction parsing.
+ (pa_check_eof): New function to verify enter/exit and proc/procend
+ pairs match at EOF.
+ (pa_code): Simplify.
+
+ * config/obj-som.c: Delete #if 0 code.
+
+Wed Nov 23 19:36:09 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * config/obj-coff.h (TARGET_FORMAT): Select between coff-shl and
+ coff-sh.
+ * config/sh.mh (TARG_CPU_DEPENDENTS): Get it right.
+ * config/tc-sh.c (little): New function.
+ (md_parse_option): Notice new option.
+ (build_relax, build_Mytes, md_atof, md_convert_frag, md_apply_fix):
+ Cope with little endian data.
+ * config/tc-sh.h (COFF_MAGIC, LISTING_HEADER): Endian dependent.
+
+Wed Nov 23 10:54:38 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (tc_gen_reloc, ELF variant): Revert last
+ change. The real bug was in bfd/elfcode.h and has been fixed.
+
+Tue Nov 22 23:31:20 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (tc_gen_reloc, ELF variant): Add section->vma
+ to the relocation's offset.
+
+Tue Nov 22 14:37:58 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * Makefile.in (INSTALL_XFORM): Fix typo.
+
+Tue Nov 22 10:23:25 1994 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * config/tc-alpha.c (s_alpha_set): Ignore the .set (no)move and
+ .set (no)volatile directives.
+
+Tue Nov 15 21:44:13 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (pa_subspace): Make sure to always reset
+ current_subspace.
+ (pa_text, pa_data): Likewise.
+
+ * config/tc-hppa.c (pa_align): New function. Aligns the current
+ offset within the current subspace along with updating the
+ alignment of the subspace itself.
+ (pa_subspace): Default alignment to one byte rathern than zero
+ bytes to avoid setting alignment to log2(0).
+ (md_pseudo_table): Use pa_alignment for .align.
+
+Tue Nov 15 15:24:45 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * messages.c (as_fatal): Always put a space after "fatal error:"
+ when printing message.
+
+Tue Nov 15 11:10:43 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.h (obj_frob_symbol): Delete.
+ (tc_frob_symbol): Make definition conditional on OBJ_SOM or
+ OBJ_ELF. For ELF subtract out symbol->section->vma for non common
+ symbols.
+
+Wed Nov 9 14:53:03 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/te-delta.h: New file, derived from te-sysv32.h.
+
+Wed Nov 9 11:52:44 1994 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/tc-ppc.c (ppc_bf): Always set coff_line_base.
+
+Mon Nov 7 01:58:49 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * Makefile.in (VERSION): Bump to 2.5.3.
+
+ * configure.in: Compare generic cpu name against "sparc", not
+ "sparc*", since sparc variants should be changed to "sparc".
+ * configure: Regenerated with autoconf 2.1.
+
+ * config/tc-a29k.c (octal, toHex): Variables deleted.
+ (isoctal): Macro deleted.
+ (md_begin): Don't initialize them.
+ (machine_ip, case 'P'/'A'): For absolute operand, generate an
+ error message if it's out of range.
+ (md_apply_fix, case RELOC_JUMPTARG): Check range for PC-relative
+ jumps.
+ (md_apply_fix): Delete code inside "#if 0".
+
+Thu Nov 3 20:20:40 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/go32.mh: Unused file deleted.
+
+ * read.c (get_absolute_expression): Indicate that the error may
+ merely be that the expression can't currently be reduced.
+
+Thu Nov 3 16:09:59 1994 J.T. Conklin (jtc@rtl.cygnus.com)
+
+ * config/tc-m68k.h (TARGET_FORMAT): If TE_NetBSD define as
+ "a.out-m68k-netbsd".
+ * config/tc-sparc.h (TARGET_FORMAT): If TE_NetBSD define as
+ "a.out-sparc-netbsd".
+
+ * config/te-nbsd.h: New file, NetBSD target emulation
+ * config/te-netbsd.h: Removed.
+ * configure.in (i[345]86-*-netbsd*,m68*-*-netbsd*,sparc*-*-netbsd*):
+ Set bfd_gas. Use nbsd emulation.
+
+Thu Nov 3 17:44:47 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ Changes from net 2.5.2 release branch:
+
+ * configure.in: Put AC_DEFINE(sparcv9) on its own line, so that
+ the shell variable settings associated with it are permanent. For
+ CPUs requiring bfd_gas=yes, select it based on CPU only, not
+ individual target names. Handle m68k-hp-hpux*, not just -hpux.
+
+ * config/tc-z8k.c (tc_coff_symbol_emit_hook): Add dummy argument
+ to match prototype in obj-coff.h.
+
+ * configure.in: Skip tests for defining WANT_FOPEN_BIN and
+ IBM_COMPILER_SUX.
+ * acconfig.h: Deleted them.
+ * configure, conf.in: Rebuild with autoconf 2.0.
+ * config/go32.cfg, config/vms-conf.h: Updated.
+
+ * config/tc-m68k.c (md_apply_fix_2, md_convert_frag_1): Always use
+ IBM_COMPILER_SUX version of code, with comments indicating why.
+
+ * listing.c (file_info): Use text mode when opening file for read.
+ Use "r" directly, no macro.
+ * input-file.c (input_file_open): Don't use FOPEN_RT, just use
+ "r".
+ * read.c (s_include): Ditto.
+ * output-file.c (output_file_create): Try both "wb" and "w", don't
+ bother with FOPEN_* macros.
+ * as.h: Don't include fopen-*.h.
+
+ * config/alpha-opcode.h: Make "ret" with no operands equivalent to
+ "ret zero,(ra)", to match OSF1 and to be consistent with both
+ one-operand forms.
+
+ Patches from DJ Delorie:
+ * as.h (alloca): undef alloca before defining it just in case
+ * config/go32.cfg: new file for autoconf values
+ * config/te-go32.h: new file
+ * configure.bat: new for autoconf
+
+ * config/tc-i386.c (md_assemble): Fix typo in GOTPC check; had =
+ for ==.
+
+ * configure.in: If target_frag doesn't exist, use /dev/null.
+
+ * as.c (parse_args): For non-VMS systems, re-add `v' to
+ std_shortopts. Add "verbose" to list of long options.
+
+ * write.c (adjust_reloc_syms): When generating an absolute section
+ symbol as a placeholder, don't mark it as used in a relocation
+ entry, here.
+
+ * Makefile.in (comparison): Compare using makefile code from gcc,
+ stripped down to discard subdir stuff and adapted to give a
+ non-zero exit status if either file differs.
+
+Thu Nov 3 15:43:02 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * config/tc-mips.c (load_address): Fix RELAX_ENCODE arguments for
+ NO_PIC case.
+
+Tue Nov 1 16:10:59 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * config/tc-mips.c (s_change_sec): If not GPOPT, don't permit
+ switching to the readonly data section.
+
+ * ecoff.c (ecoff_directive_type): Fix warning message.
+
+Sun Oct 30 00:57:35 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (pa_proc): Delete disabled code to put each
+ proc in its own subspace, we're not going to use it.
+
+Tue Oct 25 14:44:33 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * config/tc-mips.c (macro): Ensure that mips2 case of M_LI_DD in
+ .rdata does not become a variant frag.
+
+ * config/tc-mips.c (mips_cpu): Initialize to -1.
+ (md_begin): Don't mips_cpu if it was already set.
+ (md_parse_option): For -mipsN, don't set mips_cpu if it was
+ already set. For -mcpu=, just set mips_cpu, not mips_isa.
+
+Fri Oct 21 20:42:29 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * config/tc-mips.c (md_pseudo_table): If OBJ_ELF, handle .section.
+ (s_elf_section): New static function.
+ * ecoff.c (ecoff_build_symbols): Don't abort if we don't recognize
+ the section when setting the storage class; default to sc_Data.
+
+Thu Oct 20 00:43:38 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (md_apply_fix): Set new_val to 8 for all
+ fixups to branch instructions (not just pc-relative ones) which
+ will generate SOM relocations.
+
+Wed Oct 19 13:41:56 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * config/tc-a29k.c: Include ctype.h with angle brackets.
+ (define_some_regs): Add new special register names defined on the
+ 29040.
+ (parse_operand): Add argument opt. If non-zero, don't warn about
+ a missing operand.
+ (machine_ip): If handling argument type 'I', pass opt as non-zero
+ to parse_operand. Handle new optional operand type 'I'.
+ (md_undefined_symbol): Handle special register names (srNN).
+
+Tue Oct 18 00:45:24 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * write.c (renumber_sections): New static BFD_ASSEMBLER function.
+ (write_object_file): Call it after removing gas created sections.
+
+Mon Oct 17 18:06:05 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * symbols.c (symbol_create): Use udata.p, not just udata.
+ * config/obj-elf.c (obj_ecoff_set_ext): Likewise.
+ (elf_get_extr): Likewise.
+
+ * read.c (read_a_source_file): The second argument to as_where is
+ unsigned int *, not int *.
+
+Mon Oct 17 02:26:32 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c: Eliminate all uses of fx_addnumber.
+ (tc_gen_reloc): Simplify. It's no longer necessary to set a
+ reloc's addend field to zero for function symbols.
+ (md_apply_fix): Simplify. For fixups which will require a SOM
+ reloc, just clear out the necessary bits in the output file.
+
+Fri Oct 14 19:06:46 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * Makefile.in (BISON): Use bison -y, not bison.
+
+Thu Oct 13 19:22:54 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * Makefile.in (VERSION): Updated to 2.5.
+ (clean-here): Delete stamp-mk.com.
+ (distclean): Delete .gdbinit.
+ * Version 2.5 released.
+
+Wed Oct 12 20:30:51 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/te-nbsd532.h: Renamed from te-netbsd532.h.
+ * configure.in, configure: Adjusted.
+
+Wed Oct 12 16:33:38 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * config/cplus-dem.c: Removed. It isn't used. Even if it was,
+ it's better to use the one in libiberty.
+
+Wed Oct 12 18:48:39 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * symbols.c (resolve_symbol_value, case O_symbol): Undo last
+ change; it breaks the rs6000 support, and doesn't seem to be
+ needed.
+
+Wed Oct 12 11:56:50 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * config/tc-i386.h,te-netbsd532.h (TARGET_FORMAT): Changed to
+ a.out-<arch>-netbsd to match corresponding changes in BFD.
+
+Wed Oct 12 11:06:11 1994 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/tc-ppc.c (ppc_fix_adjustable): Resolve symbol values
+ rather than explicitly adding the frag address.
+ * config/obj-coff.c (coff_frob_symbol): Add a zero entry to mark
+ the end of the line numbers; this replaces the zero entry which
+ used to be added by coff_add_linesym, removed Oct 7.
+ (coff_adjust_section_syms): Ignore sections with no seginfo.
+
+Wed Oct 12 01:41:37 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * Makefile.in (bootstrap, bootstrap2, bootstrap3): Create a
+ "stage" symlink to the appropriate stage* directory, and use it
+ instead in the -B options.
+ (comparison): Revert yesterday's change.
+
+Tue Oct 11 16:48:11 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/tc-sparc.c (tc_gen_reloc): For non-a.out relocations, if
+ pc-relative, use fx_offset only, ignore address of relocation.
+
+Tue Oct 11 15:24:00 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * config/tc-mips.c (mips_ip): Don't use S_IS_LOCAL when checking
+ for an embedded PIC switch expression, since the definition of
+ S_IS_LOCAL was changed.
+
+Tue Oct 11 15:05:11 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * Makefile.in (comparison): When comparing as.new or gasp.new, try
+ running the binary through sed to avoid differences due to
+ "stage1" or "stage2" having been written into the binary.
+
+Sat Oct 8 01:48:04 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ ELF symbol size handling, based on code from Eric Youngdale:
+ * config/obj-elf.h (OBJ_SYMFIELD_TYPE): New macro. Adds an
+ expression pointer to the symbol structure, used for `size'
+ expressions that couldn't be reduced to constants when initially
+ processed.
+ (elf_frob_symbol): Declare.
+ (obj_frob_symbol): Call elf_frob_symbol always, rather than
+ ecoff_frob_symbol only if ECOFF_DEBUGGING defined.
+ * config/obj-elf.c (obj_symbol_new_hook): Deleted unused code.
+ Clear sy_obj field.
+ (obj_elf_size): Deleted unused code. If size is non-reducible
+ expression, allocate some storage for the sy_obj field and copy
+ the expression.
+ (elf_frob_symbol): New function. Computes sizes, calls
+ ecoff_frob_symbol if appropriate.
+
+ * write.c (fixup_segment): For i386 elf and coff (for now), don't
+ add in value of symbol from another defined section of the file.
+
+Fri Oct 7 17:54:02 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/tc-m88k.h (TC_KEEP_FX_OFFSET): Define.
+ * config/obj-coff.c (do_relocs_for): Test only TC_KEEP_FX_OFFSET,
+ rather than both it and TC_M88K.
+ (coff_adjust_section_syms): New function.
+ (coff_frob_section): For non-empty sections, create aux entry for
+ the section symbol, indicating the size.
+ (n_line_nos): New variable.
+ (add_lineno): Increment it.
+ (coff_add_linesym): Increment n_line_nos, don't call add_lineno.
+ (coff_frob_file): New function; map coff_adjust_section_syms over
+ sections.
+ (obj_coff_line): Only reset line_base for .bf symbols.
+ * config/obj-coff.h (coff_adjust_section_syms, coff_frob_file):
+ Declare.
+ (obj_frob_file): New macro.
+
+ * config/obj-coff.h (OBJ_COPY_SYMBOL_ATTRIBUTES): Renamed from
+ obj_frob_forward_symbol, and rewritten for new parameter list.
+
+ Mon Oct 3 21:02:38 1994 Pat Rankin (rankin@eql.caltech.edu)
+
+ * config/obj-vms.h (S_IS_LOCAL): fix obsolete flagseen[] reference.
+
+Wed Oct 5 11:49:26 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * config/obj-ecoff.c (obj_pseudo_table): Accept .esize and .etype
+ as synonyms for .size and .type.
+
+Wed Oct 5 00:08:10 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/obj-coff.c (coff_frob_section): Remove assert about
+ section alignment.
+ * config/tc-sparc.c (md_section_align): Use section alignment, not
+ xvec align_power_min field.
+
+Fri Sep 30 19:05:20 1994 Pat Rankin (rankin@eql.caltech.edu)
+
+ * vmsconf.sh (make-gas.com): handle DCL verification to enable
+ sensible feedback to the user while gas is being built.
+
+Fri Sep 30 16:23:31 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * Makefile.in (DISTSTUFF): New variable, listing only make-gas.com
+ for now.
+ (diststuff): New target; builds DISTSTUFF.
+ (realclean): Separate target, depend on clean and distclean, then
+ delete DISTSTUFF.
+ * make-gas.com: Deleted.
+
+ * config/tc-i386.c (i386_validate_fix) [BFD_ASSEMBLER]: New
+ function. Converts reloc for "foo-GOT" to BFD_RELOC_386_GOTOFF
+ reloc for "foo".
+ (i386_operand): Don't look up section symbol for
+ undefined_section.
+ (reloc): Always permit return of 8- and 16-bit relocation types.
+ Add a space after "pc-relative" in the error message.
+ (tc_i386_fix_adjustable) [BFD_ASSEMBLER]: Reject
+ BFD_RELOC_386_GOTOFF relocs.
+ (i386_operand): For any GOTOFF reloc, convert it to a BFD_RELOC_32
+ with a "foo-GOT" value.
+ * config/tc-i386.h (i386_validate_fix): Declare it.
+ (TC_VALIDATE_FIX): New macro -- call it.
+ (NOP_OPCODE): Cast to `char' to avoid compiler warnings.
+
+ * as.h: If __STDC__ is not defined and varargs.h is available, use
+ it rather than stdarg.h.
+
+ * write.h (struct fix): Added new bitfield fx_plt, for fixups
+ referring to PLT entries.
+ * write.c (fix_new_internal): Initialize fx_plt to zero.
+ (adjust_reloc_syms): Re-fetch `sym' after top of reduction loop.
+ Don't adjust fx_offset by frag address, since S_GET_VALUE now
+ includes the frag address.
+ (fixup_segment): Changed local var PCREL to type int, added PLT.
+ If PC-relative fixup refers to a PLT entry for a symbol in the
+ current section, don't reduce it.
+
+ * write.c (adjust_reloc_syms): Exit loop through a label. If
+ DEBUG5 is defined, print out each fixup before and after
+ processing.
+ (fixup_segment): If DEBUG5 is defined, print out each fixup before
+ and after processing.
+ (print_fixup): Added prototype. Show address on first line. Show
+ fx_offset and fx_subsy. [!BFD_ASSEMBLER]: Only show fx_r_type if
+ NEED_FX_R_TYPE is defined.
+
+ * symbols.c (print_symbol_value_1): Check S_IS_LOCAL, S_IS_EXTERN,
+ S_IS_DEBUG, S_IS_DEFINED also.
+
+Thu Sep 29 18:57:06 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * Makefile.in (all): Depend on .gdbinit.
+ (.gdbinit): Rebuild from gdbinit.in by running config.status.
+
+ * gdbinit.in: Define new function "pf". Fix doc on "pe" and "ps".
+
+ * write.c (print_fixup): Print source location on first line.
+ Show fx_r_type and fx_addsy fields.
+
+Wed Sep 28 14:56:39 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * configure.in: Set bfd_gas for all sparc targets in one place,
+ instead of separately for each. Correctly handle user-supplied
+ "--enable-bfd-gas" option.
+
+ * gdbinit.in: Move "break abort" to end, in case gdb complains.
+
+ * as.h (PRINTF_WHERE_LIKE, PRINT_LIKE) [USE_STDARG, !__GNUC__]:
+ Use PARAMS macro.
+
+ * symbols.c (resolve_symbol_value, case O_symbol): Don't do any
+ processing if add_symbol is undefined or in expr_section.
+ (resolve_symbol_value, case O_add): For symbol plus
+ constant-valued symbol, convert to O_symbol and re-reduce.
+ (S_GET_VALUE): If symbol needs resolving, resolve it.
+ (indent_level): No longer static.
+ (print_symbol_value_1): Don't print frag address if it matches
+ zero_address_frag. Don't print "resolving" if already resolved.
+ Print segment name. Don't call print_expr_1 on an undefined
+ symbol.
+ (print_expr_1): Fix whitespace before printing X_add_number.
+
+ * expr.c (make_expr_symbol): No longer static. Use symbol_create,
+ not symbol_new, for symbols holding expression values.
+ * expr.h (make_expr_symbol): Move declaration here.
+ * write.c (fix_new_exp): Handle O_add by creating an
+ expression-valued symbol, and calling fix_new_exp recursively.
+ (adjust_reloc_syms): If a fixup's symbol value is a sum of an
+ undefined symbol and a constant, fold the constant into the fixup,
+ and refer to the undefined symbol directly. Then process the
+ fixup again from scratch.
+ (write_object_file): Before calling adjust_reloc_syms, make a pass
+ through the symbol list trying to resolve values.
+
+ * write.c (print_fixup): New routine, for debugging.
+ (write_relocs): Call bfd_install_relocation. Deleted various
+ hacks for working around problems with bfd_perform_relocation.
+
+ * Makefile.in (VERSION): Update to 2.4.90.
+
+Wed Sep 28 11:50:40 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * Makefile.in (gasp.o): Depends upon config.h.
+
+ * config/tc-mips.c: Include subsegs.h.
+ (md_apply_fix): If an unconditional b or bal overflows, and we are
+ not assembling PIC code, replace it with a j or jal.
+
+ * config/tc-mips.c (md_apply_fix): Correct branch overflow test.
+ Use as_bad_where and as_warn_where rather than as_bad and as_warn.
+
+Mon Sep 26 17:15:59 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * write.c (write_relocs): Add file name and line number to
+ as_fatal calls. Handle bfd_reloc_overflow case specifically when
+ RELOC_EXPANSION_POSSIBLE.
+
+Fri Sep 23 16:11:28 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * as.h (USE_STDARG, USE_VARARGS): Define one or neither of these
+ here. Use them for deciding which PRINTF*LIKE macro definitions
+ to use.
+ * messages.c: Use them, instead of NO_STDARG, NO_VARARGS.
+ [!USE_STDARG && !USE_VARARGS] (va_alist, va_dcl, ...): Provide
+ default definitions matching what we were doing before.
+ (as_tsktsk): Remove the non-stdarg, non-varargs version, and
+ always use the varargs form if not using stdarg. It's safe to
+ always use vfprintf, because libiberty will provide it if the
+ native system doesn't. Also, always make format be const.
+ (as_warn, as_warn_where, as_bad, as_bad_where, as_fatal): Ditto.
+
+Fri Sep 23 14:42:34 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * config/tc-mips.c (load_register): Always use addiu when adding a
+ constant to $zero--no need to use daddiu.
+ (macro): Hack the -mips3 overflow tests to not fail when offsetT
+ is only 32 bits.
+
+ * symbols.h (copy_symbol_attributes): Declare.
+
+Thu Sep 22 21:58:24 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * listing.c: Bugfixes based in part on patches from Paul
+ Kranenburg.
+ (listing_newline): Check filename as well as line number when
+ deciding whether to record it.
+ (list_symbol_table) [S_IS_REGISTER]: Check that S_IS_REGISTER is
+ false (if defined) as well as checking for reg_section.
+ (listing_listing): Iterate fetching lines while line number is too
+ low, and we haven't run off the end of the input file.
+
+ * config/vms-conf.h: Changed HAVE_DELETE to HAVE_REMOVE.
+
+Thu Sep 22 13:39:10 1994 Kung Hsu (kung@x1.cygnus.com)
+
+ * ecoff.c (ecoff_generate_asm_lineno): check if
+ current_stabs_filename is NULL before strcmp.
+ * read.c (read_a_source_file): fix a bug in generate_asm_lineno
+ checking.
+
+Wed Sep 21 18:17:35 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * config/ho-*.h: Now-unused files deleted.
+
+ * symbols.c (copy_symbol_attributes): New function. Copies BFD
+ symbol flags and calls OBJ_COPY_SYMBOL_ATTRIBUTES.
+ (resolve_symbol_value, case O_symbol): Call it, if X_add_number is
+ zero. Don't call obj_frob_forward_symbol.
+ * read.c (pseudo_set): Call copy_symbol_attributes, but only if
+ X_add_number is zero.
+ * config/obj-elf.h (obj_frob_forward_symbol): Deleted.
+
+ * config/tc-i960.c: Lots of whitespace, comment reformatting,
+ using GNU indent.
+ (strchr): Don't declare.
+ [BFD_ASSEMBLER]: Don't compile md_convert_frag,
+ md_estimate_size_before_relax, md_ri_to_chars,
+ md_create_short_jump, md_create_long_jump.
+ (brtab_emit): Use data_section, not SEG_DATA.
+
+ Mon Sep 19 17:14:44 1994 Pat Rankin (rankin@eql.caltech.edu)
+
+ * config/vms-conf.h: new file, manually derived from conf.in.
+ * config-gas.com: use it, and eliminate obsolete "host.h".
+
+Wed Sep 21 11:11:30 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * config/tc-ppc.c (ppc_current_block): New static variable.
+ (ppc_stabx): Set sy_tc.within of a C_STSYM symbol to
+ ppc_current_block. Don't move around any stab symbol, just those
+ for common symbols.
+ (ppc_bs): Set ppc_current_block.
+ (ppc_es): Clear ppc_current_block.
+ (ppc_frob_symbol): Set the value of a C_STSYM symbol to the offset
+ from the csect of the enclosing block.
+
+ * config/tc-mips.c (insns_since_cache_access): Remove.
+ (append_insn): Remove setting of insns_since_cache_access, and
+ special 4600 handling; it turns out not to be required.
+
+Tue Sep 20 16:13:18 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * config/tc-mips.c (md_shortopts): Remove E.
+ (md_longopts): Add EB and EL.
+ (md_parse_option): Handle -EB and -EL as separate options, rather
+ than as a single -E option with an argument.
+
+Mon Sep 19 12:42:05 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (hppa_fix_adjustable): Reject reductions
+ involving global symbols too.
+
+Mon Sep 19 12:12:46 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * as.h: Test NEED_DECLARATION_*, not NEED_*_DECLARATION.
+
+ * configure.in: Test for remove, not delete. Fix cross-assembler
+ test.
+ * as.h: Test HAVE_REMOVE, not HAVE_DELETE; define unlink to
+ remove, not delete.
+
+ * read.c (pseudo_set, case O_symbol): If
+ OBJ_COPY_SYMBOL_ATTRIBUTES is defined, invoke it.
+ [BFD_ASSEMBLER]: Copy BSF_FUNCTION setting too.
+ * config/obj-elf.h (OBJ_COPY_SYMBOL_ATTRIBUTES): Define.
+
+ Wed Aug 10 19:15:30 1994 Pat Rankin (rankin@eql.caltech.edu)
+
+ * config/obj-vms.h (DSG_S_C_UBITU, DST_K_VFLAGS_DSC, DST_K_TS_ATOM,
+ many others): new macros; values obtained from "DSTRECRDS.SDL".
+ * config/obj-vms.h (various): use them.
+ (USE_BITSTRING_DESCRIPTOR): new macro, for selecting bitfield
+ representation (only enum bitfields can avoid being bitstrings).
+ (bitfield_suffix, setup_basic_type): new routines.
+ (VMS_typedef_parse): use them. Now recognize bitfields of all
+ integral types, not just type `int'. Caveat: the representation
+ used for bitfields still does not work for objects placed in
+ registers, and gcc's optimizer sometimes puts small structs there.
+
+ Tue Jun 14 17:31:44 1994 Pat Rankin (rankin@eql.caltech.edu)
+
+ * read.c (s_text) [#if OBJ_VMS]: clear the IN_DEFAULT_SECTION
+ bit from const_flag.
+ * config/obj-vms.h (IN_DEFAULT_SECTION): define this macro.
+ (tc_frob_label): define this to call vms_check_for_special_label,
+ and declare the latter.
+ * config/obj-vms.c (vax_g_doubles): declare this file-scope
+ variable.
+ (const_flag): initialize to IN_DEFAULT_SECTION instead of 0.
+ (vms_check_for_special_label): new routine (tc_frob_label).
+ (VMS_TBT_Routine_End): don't bother checking for `gcc_compiled.'
+ and `gcc2_compiled.' labels; they won't reach here any more.
+ (VMS_typedef_parse) [case 'r']: for types `double' and `complex
+ double', use `vax_g_doubles' flag to select type of double.
+ (VMS_write_object_file) [traceback setup]: don't pass symbols
+ with the IN_DEFAULT_SECTION attribute to the TBT_Routine_Begin
+ and TBT_Routine_End functions.
+
+ Mon Jun 6 20:52:20 1994 Pat Rankin (rankin@eql.caltech.edu)
+
+ * config/obj-vms.c (VMS_TBT_Routine_End): cache the result of
+ S_GET_VALUE() to avoid many repeated function calls.
+ (VMS_Check_For_Main) [#if HACK_DEC_C_STARTUP]: capitalize
+ _C$MAIN_ARGS in advance, in case -h3 (leave symbol name as-is)
+ gets requested. [All the HACK_DEC_C_STARTUP code appears to
+ be obsolete; gcc does it automatically for vms target. It's
+ also misnamed, because it is for the "VAX C" run-time library,
+ not the newer "DEC C" one which has much different startup code.]
+ {various}: use `S_SET_xxx(symbol,new_value)' rather than
+ `S_GET_xxx(symbol) = new_value'.
+
+Mon Sep 19 12:05:03 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * config/obj-coff.c (c_dot_file_symbol): Use bfd_abs_section_ptr,
+ not &bfd_abs_section.
+
+Thu Sep 15 18:36:34 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * expr.c (clean_up_expression): Use addressT, not bfd_vma.
+
+Tue Sep 13 20:05:47 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * expr.c (expr): Don't reduce the difference of two symbols in the
+ same frag if the symbols are not in normal sections.
+
+ * config/obj-som.h (S_SET_OTHER, S_SET_TYPE): Delete a.out crud.
+ (S_SET_DESC, S_GET_OTHER, S_GET_TYPE, S_GET_DESC): Likewise.
+ (obj_attach_unwind_info): Do not define. Not needed anymore.
+ * config/tc-hppa.c: Delete whitespace at EOL.
+ (struct hppa_fix_struct): Delete fx_unwind field and all references.
+ (fix_new_hppa): Last arg is now a pointer to an int. Do not
+ call obj_attach_unwind_info anymore. For SOM R_ENTRY and R_EXIT
+ fixups, store 32bits of unwind information in the fx_addnumber
+ field of the fixup.
+ (md_assemble, pa_entry, process_exit, pa_procend): For SOM R_ENTRY
+ and R_EXIT fixups, pass a NULL pointer to fix_new_hppa, and a
+ pointer to 32 bits of unwind info.
+ (tc_gen_reloc): For SOM R_ENTRY and R_EXIT fixups, set the symbol
+ pointer to the dummy symbol; set the addend field to fx_addnumber.
+ (pa_comm, pa_equ, pa_type_args, pa_import): Use bfd_XXX_section_ptr
+ rather than &bfd_XXX_section.
+
+Tue Sep 13 21:15:36 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config/tc-i386.c (md_apply_fix_1): For GOTPC relocs, decrement
+ value by one; discard adjustments previously being made. From
+ Eric Youngdale.
+
+ VMS- and Vax-related changes from Pat Rankin:
+ * Makefile.in (VMS_OTHER_OBJS): add concat, getopt, and getopt1.
+ * vmsconf.sh: no longer have make-gas.com echo text about needing
+ to modify the gcc-vms driver when intending to use with gcc 1.x.
+ * as.c (parse_options): suppress 'v' from std_short_options and
+ eliminate VMS-specific conditional initialization;
+ [default case]: check for '-v' if md_parse_options doesn't recognize
+ an option;
+ [default case, #if VMS]: check for filename argument when '-v' seen;
+ [case 'v']: delete.
+ * config/tc-vax.c (md_assemble): don't rely on `this_add_number'
+ for O_big literal operands (double floats and long long ints);
+ [VMS, md_shortopts]: add second colon after 'v';
+ (md_parse_options) [VMS, case 'v']: check for argument, so
+ caller can handle `-v' w/o arg.
+
+Tue Sep 13 16:45:08 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * config/obj-coff.c (do_relocs_for): If TC_KEEP_FX_OFFSET
+ is defined, put the tx_offset into the r_offset.
+ * config/tc-sh.c (line_comment_chars): Add #
+ (tc_reloc_mangle): Deleted.
+ * config/tc-sh.h (TC_KEEP_FX_OFFSET): Define.
+ (TC_RELOC_MANGLE): Delete.
+
+Tue Sep 13 16:20:36 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * flonum-konst.c: Change preprocessor tests of HO_VMS to just VMS.
+ * hex-value.c: Ditto.
+ * config/obj-vms.c: Ditto.
+
+ * config/tc-sparc.c (sparc_ip): Replace as_bad/exit sequence with
+ a call to as_fatal.
+ * config/tc-i860.c (i860_ip): Ditto.
+ * config/tc-hppa.c (pa_ip): Ditto.
+ * config/tc-alpha.c (alpha_ip): Ditto.
+ * as.c (parse_args): Ditto.
+
+ * config/tc-mips.c (mips_ip): Replace as_warn/exit sequence with a
+ call to as_fatal.
+
+ * write.c (write_contents): Use EXIT_FAILURE.
+ * output-file.c (output_file_create, output_file_close,
+ output_file_create, output_file_close): Ditto.
+ * messages.c (as_fatal): Ditto.
+ * config/obj-som.c (obj_som_version, obj_som_copyright): Ditto.
+ * config/obj-ieee.c (write_object_file): Ditto.
+ * config/obj-coff.c (write_object_file): Ditto.
+ * config/tc-vax.c (main): Use EXIT_SUCCESS.
+ * config/tc-m68k.c (main): Ditto.
+
+ * hash.c (main): Pass a value to exit().
+
+ * as.h (EXIT_SUCCESS, EXIT_FAILURE): Moved here.
+ * as.c: ...from here.
+ (parse_args): Use them always.
+ (main): Use exit rather than return.
+
+ * Makefile.in (*_FOR_TARGET, INSTALL_XFORM, install, uninstall):
+ Rewrite handling of program_transform_name.
+
+ * configure.in: Test for functions unlink and delete.
+ * as.h: If unlink isn't available but delete is, define unlink to
+ be delete.
+
+ Update for autoconf 1.118:
+ * gdbinit.in: New file, created from old .gdbinit.
+ * .gdbinit: Deleted.
+ * aclocal.m4 (GAS_GDBINIT): Deleted.
+ * configure.in: Don't use it. Instead, generate .gdbinit from
+ gdbinit.in. Don't substitute cpu_type, obj_format, emulation,
+ atof. Switched order of AC_LINK_FILES arguments. Use AC_PREREQ
+ to ensure that older versions of autoconf aren't used.
+ * Makefile.in: Added @configure_input@ line.
+ (configure): Deleted rule.
+
+Tue Sep 13 12:08:20 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * config/obj-coff.c (fixup_segment): After handling the difference
+ of two symbols from the same segment, set fx_subsy to NULL, to
+ satisfy existing TC_COUNT_RELOC macros.
+
+Tue Sep 13 01:47:08 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * aclocal.m4 (GAS_GDBINIT): New macro.
+ * configure.in: Use it.
+ * configure: Regenerated.
+
+Mon Sep 12 20:56:38 1994 Ken Raeburn (raeburn@kr-laptop.cygnus.com)
+
+ * .gdbinit (pe, ps): Define new commands.
+ * symbols.c (indent_level): New static variable.
+ (indent, print_expr_1, print_symbol_value_1, print_symbol_value,
+ print_expr): New functions.
+
+ * Makefile.in (config-stamp): Add a "this file generated by make"
+ message to config.h.
+
+ PIC implementation for i386-linux, based on code from Eric
+ Youngdale and Paul Kranenburg, with some work of my own:
+
+ * write.c (fixup_segment): Test TC_RELOC_RTSYM_LOC_FIXUP on fixup
+ before processing same-section pcrel relocations.
+ (TC_RELOC_RTSYM_LOC_FIXUP): Default to 1.
+
+ * expr.c (make_expr_symbol): If operator is O_symbol and
+ X_add_number is zero, just return the symbol. If operator is
+ O_constant, resolve the symbol's value before returning.
+ (operand): Permit use of "[]" for grouping.
+ (clean_up_expression): For difference of two symbols in the same
+ frag, add the difference of their offsets into X_add_number.
+ (expr): Reduce difference of two symbols in same frag to their
+ difference.
+
+ * config/tc-i386.c (TC_RELOC): New macro.
+ (struct _i386_insn): New field disp_reloc.
+ (GOT_symbol): New variable.
+ (operand_special_chars): Added square-brackets and at-sign.
+ (reloc) [BFD_ASSEMBLER]: Added new argument OTHER; if it is not
+ NO_RELOC, just return it.
+ (reloc) [! BFD_ASSEMBLER]: Add third argument to dummy macro.
+ (BFD_RELOC_386_PLT32, _GOT32, _GOTOFF) [! BFD_ASSEMBLER]: More
+ dummy macros.
+ (tc_i386_fix_adjustable): New function. Returns zero if symbol in
+ fixup is not local, to prevent relocations against externals from
+ being dropped.
+ (md_assemble): Initialize disp_reloc field to NO_RELOC. Pass
+ disp_reloc field to reloc() function, and use TC_RELOC to generate
+ value to pass to fix_new_exp.
+ (md_assemble): Change 32-bit reloc against GOT_symbol into a GOTPC
+ reloc.
+ (i386_operand): Initialize disp_reloc field to NO_RELOC. Handle
+ @GOTOFF, @PLT, @GOT operands. For GOTOFF relocations with local
+ symbols, force generation of the section symbol.
+ (md_estimate_size_before_relax): If GOT_symbol exists, decide
+ we're generating PIC code, and convert relocations against
+ undefined symbols from PCREL to PLT32.
+ (md_apply_fix_1) [OBJ_ELF]: Fix up values for dynamic-linking
+ relocs.
+ (md_undefined_symbol): Notice GLOBAL_OFFSET_TABLE_NAME and set
+ and return GOT_symbol if it matches.
+ (F, MAP): Move macro definitions outside function.
+ (tc_gen_reloc): Only switch on size and pcrel if code wasn't
+ already supplied as PLT32. GOT32, GOTOFF, or GOTPC. Convert
+ BFD_RELOC_32 using GOT_symbol into GOTPC.
+ * config/tc-i386.h (TC_RELOC, tc_fix_adjustable,
+ TC_RELOC_GLOBAL_OFFSET_TABLE, TC_RELOC_RTSYM_LOC_FIXUP): New
+ macros.
+ (NEED_FX_R_TYPE): Define.
+ (LOCAL_LABEL): Accept ".X" prefix too.
+ (GLOBAL_OFFSET_TABLE_NAME): Default to "_GLOBAL_OFFSET_TABLE_".
+
+Mon Sep 12 17:51:39 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * config/obj-elf.c (obj_elf_type): Rewrite to accept syntax
+ reportedly to be used on Irix 6.
+
+ * config/tc-mips.c (md_pseudo_table): Handle .globl and .global.
+ (s_mips_globl): New static function; needed for Irix 5 support.
+ * ecoff.c (ecoff_build_symbols): If BSF_FUNCTION is set for an
+ external symbol with no type, set the type to st_Proc rather than
+ st_Global. Don't set the index of an external st_Proc or
+ st_StaticProc symbol unless it is also a local symbol.
+
+ * read.c (read_a_source_file): The second argument to as_where is
+ unsigned int *, not int *.
+
+Thu Sep 8 17:18:24 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * config/obj-ecoff.h : Change names to OBJ_GENERATE_ASM_LINENO,
+ and generate_asm_lineno.
+ * config/obj-elf.h : ditto.
+ * read.h : ditto.
+ * read.c (read_a_source_file): if no file when inst is read, set
+ generate_asm_lineno to true.
+ * ecoff.h : change name to generate_asm_lineno and add function
+ ecoff_no_current_file.
+ * ecoff.c : change name to generate_asm_lineno.
+ * ecoff.c (ecoff_generate_asm_lineno) : new function, to generate
+ ecoff style line for asm file.
+
+Thu Sep 8 19:43:49 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * config/obj-coff.c (size_section): Do an fprintf to stderr rather
+ than a printf.
+ (fixup_segment): Use as_bad_where rather than as_bad.
+
+Wed Sep 7 17:21:12 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * config/tc-{h8300,sh}.[ch] (tc_coff_symbol_emit): Function doing
+ nothing becomes macro doing nothing.
+
+Wed Sep 7 19:10:09 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * Makefile.in (Makefile): Depend on config.status.
+ (config.status): Run config.status from . instead of srcdir.
+
+ * config/tc-i386.c (tc_gen_reloc): Use bfd_get_reloc_code_name to
+ display the name of the relocation type that couldn't be handled.
+ * config/tc-sparc.c (tc_gen_reloc): Likewise.
+ * config/tc-alpha.c (tc_gen_reloc): Likewise. Deleted abort call
+ after call to as_fatal.
+
+ * configure.in (i386-*-linux*): Don't set bfd_gas.
+
+ * Makefile.in (CC_FOR_TARGET, NM_FOR_TARGET, OBJDUMP_FOR_TARGET,
+ install, uninstall): Don't use "brokensed" hack any more, the new
+ autoconf code should never let program_transform_name be empty.
+
+ Update for autoconf beta 1.112:
+ * aclocal.m4 (GAS_CHECK_DECL_NEEDED, GAS_WORKING_ASSERT): New
+ macros.
+ * configure.in: Use them. Use AC_ARG_PROGRAM (now provided by
+ autoconf) instead of my hacked-up AC_PROGRAM_TRANSFORM_NAME. Move
+ test for CROSS_COMPILE just before AC_FUNC_ALLOCA, and emit a
+ message to try to ease confusion about autoconf's
+ "cross-compiling" message.
+ * acconfig.h (NEED_DECLARATION_MALLOC, NEED_DECLARATION_FREE,
+ NEED_DECLARATION_ERRNO): Renamed from NEED_*_DECLARATION.
+ * configure, conf.in: Regenerated.
+
+Wed Sep 7 12:49:55 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * configure.in: Check ${host} and ${target} rather than
+ ${host_canon} and ${target_canon}.
+ * configure: Likewise.
+
+Tue Sep 6 11:42:38 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * config/tc-mips.c (mips_cpu): New static variable.
+ (insns_since_cache_access): New static variable.
+ (md_begin): Set mips_cpu as well as mips_isa.
+ (append_insn): If mips_cpu is 4600, require four nop instructions
+ between an instruction which accesses the cache and certain CACHE
+ instructions. Keep track of the number of instructions seen since
+ an instruction which accesses the cache.
+ (md_parse_option): Set mips_cpu as well as mips_isa.
+
+Mon Sep 5 07:09:00 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * doc/Makefile.in (VPATH): Define using @srcdir@.
+ (prefix, program_transform_name, exec_prefix): Use autoconf style
+ @-substitutions.
+
+Sun Sep 04 17:58:10 1994 Richard Earnshaw (rwe@pegasus.esprit.ec.org)
+
+ * config/ho-riscix.h, config/tc-arm.c, config/tc-arm.h: New files
+ * configure.in: Recognize the arm.
+
+Fri Sep 2 16:05:50 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * ecoff.c (add_file): Don't try to generate line numbers if the
+ symbol table has been frozen.
+
+Thu Sep 1 19:48:01 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * aclocal.m4 (AC_PROG_CC): Use AC_DEFUN, and omit AC_PROVIDE.
+
+ * configure.in: Handle user-specified bfd-assembler option with
+ separate variable from preferred configuration, until the two are
+ resolved. Indicate bfd_gas=preferred for linux a.out. Use
+ AC_PROGRAM_TRANSFORM_NAME, for which a patch has been sent to djm.
+ * Makefile.in (target_alias, program_transform_name): Define,
+ using autoconf @-substitutions.
+
+Wed Aug 31 17:43:06 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * atof-generic.c: Deleted alloca handling here.
+
+ * Makefile.in (prefix, exec_prefix): Use @-subtitutions.
+
+ * aclocal.m4 (AC_OUTPUT_LINKS): Deleted redefinition, since
+ autoconf 1.109 has this fixed.
+ * configure.in: Don't change quote characters around AC_MSG_ERROR
+ invocation. Don't use AC_HEADER_STDC, since it requires running a
+ program. Cache NEED_*_DECLARATION values.
+ * configure, conf.in: Regenerated with a modified autoconf 1.109.
+
+ * as.h (volatile): Don't test or define here; not needed.
+ (alloca): Replace alloca-conf.h inclusion with code recommended in
+ autoconf documentation. Include config.h first.
+
+Wed Aug 31 11:20:48 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * config/obj-coff.h (S_IS_DEFINED): Absolute symbols are defined
+ also.
+
+ * configure.in, configure: Initialize bfd_gas to no.
+
+Tue Aug 30 19:31:14 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * as.h: Include alloca-conf.h from "libiberty", not
+ "../libiberty".
+
+Mon Aug 29 16:11:30 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * config/tc-ppc.c (md_apply_fix): Don't generate a reloc when a
+ symbol is used as an offset into a CSECT that is not a TOC. These
+ types of loads are generated by gcc -mminimal-toc.
+
+Sun Aug 28 13:22:52 1994 Ken Raeburn (raeburn@rtl.cygnus.com)
+
+ * as.h (flag_*): Added comments describing meanings of some of
+ these variables.
+ (struct frag): Add some comments about the ns32k-specific fields
+ and why they're here.
+ (SIZEOF_STRUCT_FRAG): Cast addresses to char*, not int.
+ (flag_print_statistics): Declare.
+
+ * as.c (parse_args): Set flag_print_statistics instead of
+ statistics_flag. Options array is now const. Added new option
+ "dump-config"; if specified, print TARGET_ALIAS, TARGET_CANONICAL,
+ TARGET_CPU, TARGET_OBJ_FORMAT, and TARGET_FORMAT, if defined.
+ (main): Change test to check flag_print_statistics.
+ (statistics_flag): Deleted.
+
+ * frags.c (frag_variant): Removed PCREL_ADJUST and BSR arguments.
+ Always initialize them to zero.
+ * frags.h (frag_variant): Fixed prototype.
+ * config/tc-i960.c (get_cdisp): Don't pass the extra zero args.
+ * config/tc-ns32k.c (convert_iif): Don't pass the arguments; cache
+ the value of frag_now and fill in the fields later.
+
+ * Makefile.in (distclean, realclean): Remove new
+ configure-generated files.
+
+Sat Aug 27 20:26:12 1994 Ken Raeburn (raeburn@kr-laptop.cygnus.com)
+
+ Conversion to autoconf:
+ * acconfig.h, aclocal.m4: New files.
+ * configure.in: Rewritten (except for some target-specific code)
+ for autoconf.
+ * conf.in, configure: New files, generated from the above.
+ * Makefile.in: Changed magic sequence indicating insertion of
+ makefile fragments.
+ (VPATH, srcdir, CC, LIBS, OBJS dependencies): Use @-substitutions
+ from configure.
+ (LINKED_HEADERS): Deleted a.out.gnu.h, a.out.h, and host.h.
+ (config.status, configure): Rewrite rules.
+ (config-stamp): Depend on conf. Skip variables that configure is
+ now substituting itself.
+ (*.o dependencies): Deleted host.h.
+ (distclean, realclean): Don't delete host.h.
+ * as.c: Don't include stdio.h, string.h, sys/types.h. Include
+ signal.h after as.h.
+ * as.h: Include alloca-conf.h first. Include ctype.h, string.h,
+ strings.h, stdlib.h, unistd.h, sys/types.h, fopen-bin.h,
+ fopen-same.h, as suggested by autoconf test results.
+ [BROKEN_ASSERT]: Don't include assert.h.
+ (strdup): Declare.
+ (volatile, const): Define if not __STDC__ and not already defined.
+ (malloc, realloc) [NEED_MALLOC_DECLARATION]: Declare.
+ (free) [NEED_FREE_DECLARATION]: Declare.
+ * gasp.c: Include config.h, stdlib.h (if HAVE_STDLIB_H). Don't
+ include host.h.
+ (malloc) [NEED_MALLOC_DECLARATION]: Declare.
+ * messages.c: Include as.h first. Include errno.h only if
+ HAVE_ERRNO_H. If HAVE_VARARGS_H and not __STDC__, undefine
+ HAVE_STDARG_H. Set NO_STDARG and NO_VARARGS as appropriate.
+ * doc/Makefile.in (srcdir, INSTALL, INSTALL_PROGRAM,
+ INSTALL_DATA): Use autoconf @-substitutions.
+
+ * input-file.c: Don't include assert.h here, 'cause as.h already
+ includes it.
+
+ * config/tc-alpha.c: Added various prototypes for static
+ functions.
+ (in_range): New function, tests whether a value can fit in an
+ N-bit field.
+ (build_mem, build_operate_n): New functions for constructing
+ opcode values.
+ (emit_sll_n, emit_ldah_num, emit_addq_r, emit_lda_n): New
+ functions for emitting single instructions, no longer requiring a
+ recursive call to md_assemble.
+ (emit_add64): New function for expanding a REG:=REG+CONST
+ operation into one or more instructions, to handle wide constants.
+ (clear_insn): New variable.
+ (md_begin): Fill it in with zeros and BFD_RELOC_NONE values.
+ (alpha_ip): Use it to initialize local variable insns.
+ (alpha_ip, label "immediate" and cases 'P', 'G'): Use emit_add64
+ for calculations.
+
+Fri Aug 26 14:46:15 1994 Ken Raeburn (raeburn@kr-laptop.cygnus.com)
+
+ * subsegs.c (section_symbol): Reverse still-wrong test of
+ EMIT_SECTION_SYMBOLS.
+
+ * write.c (BFD_FAST_SECTION_FILL): Always define.
+ (write_contents): If fill_size is 1, use memset instead of looping
+ calling memcpy.
+
+Wed Aug 24 12:46:08 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * config/tc-mips.h (LOCAL_LABEL): Define as 0, for compatibility
+ with native MIPS assembler.
+ * configure.in (mips-*-irix*): Don't set emulation.
+ * config/te-irix.h: Remove.
+
+ * ecoff.c (ecoff_symbol_new_hook): Don't add a new file if we
+ haven't seen any input files yet.
+ * config/tc-alpha.c (md_begin): Just call symbol_create, rather
+ than calling symbol_new and then removing the symbol from the
+ list.
+
+ * as.c (main): Move a inside the #if 0 block which uses it.
+ * ecoff.c (current_stabs_filename): Make const.
+ * frags.h (frag_align_pattern): Declare.
+ * gasp.c (new_file): Cast isp to long, and use %ld to print it.
+ * config/tc-alpha.h (md_operand): Add cast to void.
+ (alpha_do_align): Declare argument types.
+ (tc_get_register): Declare.
+ (alpha_frob_ecoff_data): Declare.
+ * config/tc-alpha.c: Include <ctype.h>.
+ (s_mask): Don't declare; does not exist.
+ (line_comment_chars): Remove /* from descriptive comment.
+ (tc_get_register): Remove unused local reg.
+ (tc_gen_reloc): Don't bother to compare unsigned to zero.
+ (s_base): Correct warning to actually print register number.
+ (md_begin): Remove unused locals retval, lose, and i.
+ (alpha_fix_adjustable): Move default case inside switch to avoid
+ warning.
+ (load_symbol_address): Remove unused locals reloc_addr, p, sym,
+ and addend.
+ (emit_byte_manip_r): Declare types for all arguments.
+ (emit_extract_r, emit_insert_r, emit_mask_r): Likewise.
+ (emit_sign_extend, emit_bis_r, s_proc): Likewise.
+ (alpha_ip): Use sprint_value to print offsetT value. Remove
+ unused local size. Remove unused label get_macro.
+ (alpha_do_align): Make fill const.
+ (md_apply_fix): Remove unused label check_zov.
+
+ * configure.in: Recognize i586 as a synonym for i[34]86.
+
+Tue Aug 23 12:32:14 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * config/obj-coff.c (c_line_new): Change line_number argument from
+ unsigned short to int so that the type in the prototype matches
+ the promoted type in the definition.
+ (stack_delete): Comment out; not used.
+ * config/obj-coff.h (tc_coff_symbol_emit_hook): Declare if not
+ BFD_ASSEMBLER, not if BFD_ASSEMBLER. Declare argument type.
+ * config/tc-m68k.h (tc_coff_sizemachdep): Declare.
+ * config/tc-m68k.c (tc_coff_symbol_emit_hook): Add ignored
+ argument.
+
+Tue Aug 16 01:48:20 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/config/tc-hppa.c (pa_comm): Undo last change. Set sy_frag for
+ the common symbol to the zero address frag (the correct fix).
+
+Tue Aug 16 01:48:20 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/config/tc-hppa.c (pa_comm): Undo last change. Set sy_frag for
+ the common symbol to the zero address frag (the correct fix).
+
+ * config/tc-hppa.c (pa_comm): Set sy_resolved for the common
+ symbol.
+
+Fri Aug 12 17:51:48 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * config/tc-mips.c (md_begin): Drop "el" from the end of
+ TARGET_CPU. Check for mips64orion.
+
+Tue Aug 9 19:43:45 1994 Stu Grossman (grossman@cygnus.com)
+
+ * configure.in: Recognize ppc-*-netware.
+ * config/te-ppcnw.h: New file to support Power-PC/Netware
+ configurations. Currently, it just enables the use of backslash
+ escapes in string directives.
+
+Tue Aug 9 11:12:13 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * config/tc-ppc.c (ppc_stabx): Call expression directly, rather
+ than via pseudo_set. If expression is a symbol, move stab symbol
+ to just after symbol from expression.
+
+ * ecoff.c (ecoff_build_procs): Don't force adr of first fdr to be
+ zero. Undoes change of June 4, 1993.
+
+ * config/tc-mips.c (md_parse_option): Accept -mcpu=4400, 4600, and
+ orion.
+
+Mon Aug 8 16:28:08 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * as.h: Remove FOPEN_WB patch of Aug 6.
+ * configure.in: Configure for ho-go32 correctly.
+ * config/ho-go32.h: Fix copyright.
+
+Mon Aug 8 11:59:51 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/config/tc-hppa.c (md_pseudo_table): Delete redundant
+ upper-case versions of the pseudo-ops.
+
+Mon Aug 8 13:42:16 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * config/tc-sparc.c (md_apply_fix): If we are going to generate a
+ non PC relative reloc, don't put the addend in the object file.
+
+Sat Aug 6 01:15:02 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * as.h: If FOPEN_WB is not defined, do the right thing in a go32
+ environment.
+
+Mon Jul 11 11:34:52 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * config/tc-h8300.c (pint): New function for handling varying
+ size of int pseudo op.
+ * doc/as.texinfo: Fix typo describing .h8300h pseduop.
+
+Mon Aug 1 02:40:43 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (create_new_space): Initialize sd_subspaces
+ field in the space chain.
+
+ * config/tc-hppa.c (tc_gen_reloc): Cast return value from
+ hppa_gen_reloc_type.
+
+Thu Jul 28 15:45:37 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config/tc-sparc.c (sparc_ip): Check more carefully for
+ conflicting architectures.
+ (md_parse_option) [NO_V9]: Complain if v9 was selected.
+ (md_show_usage): Derive architecture list in usage message from
+ architecture_pname array.
+ (cypress): Macro deleted.
+ (op_hash): Don't initialize.
+ (s_common): Use bfd_und_section_ptr instead of bfd_und_section.
+
+ * config/tc-sparc.c (BSR): New function.
+ (sparc_ip): Use it for right-shift operations of 32 bits or more.
+
+ * config/tc-sparc.c (sparc_ip): Implement new operand type 'x'.
+
+Tue Jul 26 18:21:24 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config/obj-coff.h: Moved common includes and TARGET_FORMAT
+ definitions together.
+ (WORKING_DOT_WORD, WARN_SIGNED_OVERFLOW_WORD,
+ OBJ_COFF_OMIT_OPTIONAL_HEADER, BFD_HEADERS, BFD) [!BFD_ASSEMBLER]:
+ Moved these definitions to the start of the file, before the
+ includes.
+ (SYMBOLS_NEED_BACKPOINTERS, OBJ_COFF_MAX_AUXENTRIES): Always
+ define these.
+ (S_GET_ZEROES): Deleted.
+ (S_SET_ZEROES): Moved to obj-coff.c.
+
+ * config/obj-coff.c (obj_coff_* psuedo-op fns): Deleted
+ forward declarations.
+ (obj_pseudo_table): Moved to one version end of file,
+ conditionalized internally.
+ (stack typedef, stack_init, stack_delete, stack_push, stack_pop,
+ tag_hash, tag_init, tag_insert, tag_find, tag_find_or_make): Moved
+ to one combined version at top of file, unconditional. Deleted
+ forward declarations.
+ (s_get_name): Moved one copy of declarations to start of file.
+ (def_symbol_in_progress): Ditto. Don't initialize.
+ (S_SET_ZEROES): Moved here from obj-coff.h.
+ (write_object_file): If TC_COFF_SET_MACHINE is defined, call it on
+ the file headers.
+
+ * config/obj-coff.c (seg_info_off_by_4): Now const and static.
+ (SEG_INFO_FROM_SEG_NUMBER): Unused macro deleted.
+ (previous_file_symbol, def_symbol_in_progress, symbol_externP,
+ symbol_extern_lastP, last_functionP) [!BFD_ASSEMBLER]: Don't
+ bother explicitly initializing to zero value.
+
+ * config/obj-coff.c (fixup_segment) [TC_I960]: Use SF_GET_BALNAME
+ and SF_GET_CALLNAME instead of the TC_S_IS_ versions.
+
+ * config/tc-i960.h (TC_COFF_SET_MACHINE): New macro. Calls
+ tc_headers_hook.
+
+ * config/tc-i960.c (targ_has_iclass): Use I_CX | I_CX2 where I_CX
+ was used previously.
+ (tc_headers_hook): If I_CX2 is found, set flags to F_I960CA.
+
+ * config/tc-i960.c (po_hash): Declaration deleted.
+ (next_object_file_charP): Ditto.
+ (regnames, aregs, coj): Now const.
+ (parse_memop): Static array def_scale now const.
+ (md_begin): Cast away const when passing hash routines addresses
+ of values in regnames or aregs.
+ (md_longopts): Added "link-relax" and "no-relax" hyphenated forms.
+ Continue to accept one-word forms.
+ (struct tabentry, arch_tab): Moved to top level from inside
+ md_parse_option. Now const.
+ (md_show_usage): Use arch_tab to generate usage message. Print
+ hyphenated forms of relax options.
+
+ * config/tc-i960.h (DEFINE_I960_AOUT, TC_S_IS_*, TC_S_*_SYSPROC,
+ TC_S_FORCE_TO_*): Moved from here...
+ * config/tc-i960.c: ... to here. Changed DEFINE_I960_AOUT stuff
+ to test OBJ_AOUT and OBJ_BOUT directly.
+
+ * config/tc-i960.h (CTRL, COBR, COJ, REG, MEM*, FBRA, CALLJ,
+ M1-M3, REG_OPC, R_*, SFR, LIT, FP, OP, R, RS, RL, RSL, F,
+ {R,F}{,L}{2,4}, M, SFR_OK, LIT_OK, FP_OK, REG_ALIGN, MEMOP, I_*):
+ Macros deleted.
+
+ * config/tc-i960.c (ARCH_JX): Define.
+ (arch_tab): Include JX.
+ (targ_has_sfr, targ_has_iclass): Handle JX.
+ (tc_headers_hook): Set flags to F_I960JX for i960JX.
+
+Fri Jul 15 15:36:51 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * subsegs.c (section_symbol): Had last change backwards.
+
+Thu Jul 14 13:21:06 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config/atof-ns32k.c: Deleted.
+
+ * config/obj-aout.c (obj_aout_frob_symbol): Use
+ bfd_ind_section_ptr and bfd_und_section_ptr.
+
+ * subsegs.c (subseg_set_rest): Compare segT values directly,
+ without casting to int first.
+
+ * config/tc-ns32k.c (md_begin): Return value from hash_insert
+ should be pointer to const. Don't call exit explicitly after
+ calling as_fatal; it won't return.
+ (convert_iif): Make local variable j be pointer to bit_fixS, since
+ that's how it's used.
+ (encode_operand, case 'b'): Ignore sprintf return value. Don't try
+ converting freeptr to int and back.
+
+ Merged in NS32K support update from Ian Dall (dall@hfrd.dsto.gov.au):
+
+ * config/te-pc532mach.h: New file. pc532-mach target emulation.
+
+ * config/te-netbsd532.h: New file. Netbsd532 target emulation.
+
+ * config/tc-ns32k.h: Add definition of NOP_OPCODE.
+
+ * config/tc-ns32k.h: Add prototype for fix_new_ns32k_exp.
+
+ * config/tc-ns32k.h: Add BFD_ASSEMBLER support.
+
+ * config/tc-ns32k.c (tc_gen_reloc): New function for BFD_ASSEMBLER.
+
+ * config/tc-ns32k.c (fix_new_ns32k_exp): Get reloc type
+ differently for BFD_ASSEMBLER.
+
+ * config/tc-ns32k.c (md_estimate_size_before_relax): Get reloc
+ type differently for BFD_ASSEMBLER.
+
+ * config/tc-ns32k.c (md_create_long_jump): Size of opcode is one
+ not 2.
+
+ * config/tc-ns32k.c (md_convert_frag): Code for the BFD_ASSEMBLER
+ case. Also use smart md_pcrel_adjust function.
+
+ * config/tc-ns32k.c (md_apply_fix): Code for the BFD_ASSEMBLER
+ case. Also use smart md_fix_pcrel_adjust function.
+
+ * config/tc-ns32k.c (md_fix_pcrel_adjust): New function which can
+ find offset from opcode to operand even if in another frag
+ and in the presence of relaxing.
+
+ * config/tc-ns32k.c (md_pcrel_adjust): New function which can
+ find offset from opcode to operand even if in another frag
+ and in the presence of relaxing.
+
+ * config/tc-ns32k.c (md_number_to_disp): Check ranges properly.
+
+ * config/tc-ns32k.c (md_atof): use atof_ieee instead of special
+ atof_ns32k.
+
+ * config/tc-ns32k.c (reloc): New (static) function for
+ BFD_ASSEMBLER.
+
+ * config/tc-ns32k.c (convert_iif): More correct pc relative code.
+ md_relax must be able to find opcode address even if in another frag.
+
+ * config/tc-ns32k.c: More extensive comments.
+
+ * config/tc-ns32k.c (encode_operand): Support new operand classes I
+ and Z. Drop Q.
+
+ * config/tc-ns32k.c (fix_new_ns32k_exp): new function and
+ corresponding prototype.
+
+ * config/tc-ns32k.c: make 32532 default machine instead of 32032.
+
+ * config/tc-ns32k.c: include opcode/ns32k.h after as.h
+
+ * aout_gnu.h: r_disp needs to be 2 bits for TC_NS32K
+
+ * write.h: fx_im_disp needs to be 2 bits big for TC_NS32K
+
+ * write.c (relax_segment): Use TC_PCREL_ADJUST macro (if defined)
+ instead of adding pcrel_adjust.
+
+ * write.c (write_object_file): Adjust to_addr for the
+ BROKEN_DOT_WORD feature for the BFD_ASSEMBLER case.
+
+ * write.c (write_object_file): Use TC_CONS_FIX_NEW if it is defined.
+
+ * write.c (write_contents): Add code (currently if
+ BFD_FAST_SECTION_FILL is defined) to make large fills a lot faster.
+
+ * configure.in: Remove ns32k from special FP list. All the ns32k
+ series use ieee float.
+
+ * configure.in: Add ns32k-pc532-mach and ns32k-pc532-netbsd targets
+
+ * as.h: include expr.h before targ-env.h. Some target dependent file
+ want to use expr structures.
+
+Wed Jul 13 14:49:05 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * config/tc-m68k.c (m68k_ip): Change rp to be a const pointer.
+ (md_parse_option): Clear cpu field of current_architecture before
+ setting a new cpu type. Clear no_68881 for m68881 or m68882.
+ Clear no_68851 for m68851.
+
+Tue Jul 12 21:27:05 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config/ho-sysv.h (realloc): Declare.
+
+ * symbols.c (symbol_create): New function, most of the guts of the
+ old symbol_new function.
+ (symbol_new): Now just checks symbol_table_frozen, calls
+ symbol_create, and enters the symbol into the symbol table.
+ * subsegs.c (section_symbol): If EMIT_SECTION_SYMBOLS is not true,
+ and the symbol table is frozen, call symbol_create instead of
+ symbol_new.
+ * symbols.h (symbol_create, symbol_table_frozen): Declare.
+
+ * symbols.c (symbol_clear_list_pointers): Always a function now.
+ * struc-symbol.h (symbol_clear_list_pointers): Deleted macro
+ version.
+
+ * symbols.c (debug_verify_symchain): New macro, defined to be
+ verify_symbol_chain or a cast to void, depending on DEBUG_SYMS.
+ (many functions): Invoke debug_verify_symchain unconditionally.
+
+Tue Jul 12 12:06:42 1994 Kung Hsu (kung@x1.cygnus.com)
+
+ * config/obj-ecoff.h: change calling interface of
+ OBJ_GENERATE_ASM_LINE_STAB.
+ * config/obj-elf.h: ditto.
+ * read.c (read_a_source_file): ditto.
+ * ecoff.h: change calling interface of
+ ecoff_generate_asm_line_stab.
+ * ecoff.c (add_file): record of filename to handle case of include
+ files, also change default built-in type from int to void for
+ asm file.
+ * ecoff.c (ecoff_generate_asm_line_stab): handle case of include
+ files.
+
+Mon Jul 11 17:20:23 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * config/tc-mips.c (macro): In case M_LA_AB, SVR4_PIC, large
+ constant, and case ldd_std, set mips_optimize to 2 temporarily to
+ avoid inserting an unexpected nop instruction.
+
+Sat Jul 9 00:05:12 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ecoff.c (ecoff_build_lineno): Handle count correctly for last
+ line number.
+
+Fri Jul 8 15:22:07 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * gasp.c (process_pseudo_op): Pass right args to do do_aif.
+ (get_any_string): New arg 'pretend_quote'.
+ (get_and_process, do_formals, macro_expand, do_sdata,
+ process_pseudo_op): Use new arg.
+
+Fri Jul 8 12:23:44 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * config/obj-ecoff.h: define macro OBJ_GENERATE_ASM_LINE_STAB.
+ * config/obj-elf.h: ditto.
+ * read.c (read_a_source_file): generate line stabs for asm file.
+ * read.h: add extern generate_asm_line_stab.
+ * ecoff.h : add prototype for ecoff_generate_asm_line_stab().
+ * ecoff.c (add_file): if there's no filename provided, set switch
+ to generate line stabs for .s file.
+ * ecoff.c (add_procedure): add stabs symbol for .ent directive.
+ * ecoff.c (generate_ecoff_stab): creates an artificial stabs.
+ * ecoff.c (generate_asm_line_stab): generate a artifitial label
+ for each line and generate a stabn for the line.
+
+Thu Jul 7 17:04:03 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * gasp.c (get_any_string): Cope with getting a string with an
+ alternate base specifier.
+ (do_aif, do_aelse): Only enable output if expression is true and previous
+ level was on.
+ (chartype_init): Add BASEBIT chartype.
+ (process_pseudo_op): Notice nesteed AIFs.
+
+Thu Jul 7 12:30:22 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * h8300.c (do_a_fix_imm): Code for 2 bit reloc type using in trapa
+ insn. (fix pr 5165, 5174)
+
+Thu Jul 7 11:31:32 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (R_DLT_REL): If it isn't defined, then define
+ to an appropriate value to avoid losing on old hpux systems.
+
+ * config/tc-hppa.c (hppa_fix_adjustable): Reject reductions for
+ symbols in DLT relative relocs.
+ (tc_gen_reloc): Zero out the addend field for DLT relative relocs.
+
+Wed Jul 6 01:07:54 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-ppc.c (ppc_tc): If not OBJ_COFF, force TOC entry to
+ align to a four byte boundary.
+
+Tue Jul 5 15:42:09 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config/tc-alpha.c (load_expression): Handle 32-bit addends.
+ (gpdisp_hi16_howto): Now points to const.
+ (load_insn_table, alpha_ip): Fix uses of const.
+
+ * doc/internals.texi: Updates to COFF description. Added "@end
+ defmac" as needed, and some extra heading and "@bye" so it'll
+ format as a separate document.
+
+Tue Jul 5 13:54:00 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * config/obj-elf.h (S_GET_ALIGN, S_SET_ALIGN): Define.
+ * config/obj-elf.c (obj_elf_common): Set alignment of common
+ symbol.
+ * config/tc-sparc.c (s_common): If OBJ_ELF, set alignment of
+ common symbol.
+
+Mon Jul 4 18:29:43 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (is_complex): New macro.
+ (cons_fix_new_hppa): "Handle" complex expressions.
+
+Fri Jul 1 00:48:12 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/obj-coff.c (write_object_file): Set s_align field from
+ section_alignment array.
+
+Thu Jun 30 15:05:28 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * write.c (write_object_file): Use bfd_com_section_ptr.
+ * as.h (absolute_section, undefined_section): Use new BFD macros
+ bfd_abs_section_ptr and bfd_und_section_ptr.
+
+Thu Jun 30 14:36:37 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * config/tc-mips.c (macro): For M_LI_SS, decide how to handle it
+ based on contents of imm_expr and offset_expr, rather than
+ mips_pic. For M_LI_DD, decide how to handle it based on segment
+ name of offset_expr, rather than mips_pic.
+ (mips_ip): If g_switch_value < 4, use immediate values for 'l'.
+ If g_switch_value < 8, use .rdata rather than .lit for 'L'.
+
+Wed Jun 29 17:30:46 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * as.c (show_usage): Break long string into shorter ones.
+ (parse_args): Add -v, prints version id and continues.
+ * config/tc-mips.c (md_show_usage): Break long string.
+
+Mon Jun 27 09:47:16 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * config/tc-i386.c (md_parse_option): Handle "-V" and "-Q" if
+ OBJ_ELF is defined.
+
+Sun Jun 26 16:30:48 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * as.c (main) [HOST_SPECIAL_INIT]: New hook, for host-specific
+ initialization.
+
+Wed Jun 22 00:24:55 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.h (obj_frob_symbol): Define for OBJ_ELF.
+ More gas/bfd lossage exposed by the new linker code.
+
+Tue Jun 21 11:32:18 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * subsegs.c (subseg_change): Clear seginfo after allocating it.
+ (subseg_get): Pass actual size of seginfo to memset.
+
+ * subsegs.c (abs_seg_info, und_seg_info): Define if BFD_ASSEMBLER.
+ (subseg_change): Store seg_info for bfd_abs_section_ptr in
+ abs_seg_info, and store seg_info for bfd_und_section_ptr in
+ und_seg_info.
+ (subseg_get): Likewise. Also, don't set output_section if it is
+ already set.
+ (seg_info): Define as function.
+ * subsegs.h (seg_info): Declare as function rather than defining
+ as macro.
+ * write.c (relax_and_size_seg): Call seg_info rather than
+ bfd_get_section_userdata.
+
+Mon Jun 20 16:30:54 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * configure.in (ppc-*-elf*): New target, like -sysv4*.
+
+ * expr.c (operand): If "0f" is followed by '\0', don't do eol
+ checks.
+
+Mon Jun 20 15:17:43 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * ecoff.c (ecoff_build_aux): Call swap_tir_out and swap_rndx_out
+ via backend pointer, not directly.
+
+Fri Jun 17 18:05:06 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * Makefile.in (config-stamp): Make sure there is at least one
+ element in the for loop.
+
+Fri Jun 17 11:01:04 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c: Misc trivial changes to make gcc -Wall happy.
+
+ * config/tc-hppa.h (elf_hppa_final_processing): Declare.
+
+Wed Jun 15 20:44:46 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * as.c (parse_args): Cast xmalloc return value.
+
+ * Makefile.in (config-stamp): If $(defs) contains multiple words,
+ emit a #define line for each.
+ * configure.in: For sparc64 target, use sparc cpu files and add
+ sparcv9 to extra_defs. No longer treat sparc64-*-aout* specially.
+
+ * config/tc-sparc.c (membar_masks): Now static and const.
+ (md_show_usage) [!NO_V9]: Add -Av9 to usage message.
+ (current_architecture) [sparcv9]: Initialize to v9.
+ (md_begin) [sparcv9]: Don't bother changing it unconditionally
+ here.
+ (s_reserve): Don't pass unexpected argument to as_bad with
+ bad-segment message.
+
+ * as.h (bfd_alloc_by_size_t) [BFD_ASSEMBLER]: Declare.
+
+ * config/atof-ieee.c (int_to_gen): Commented out unused routine.
+
+ * config/tc-vax.c (md_assemble): Removed check of operand section.
+
+ Fri Jun 3 17:25:08 1994 Pat Rankin (rankin@eql.caltech.edu)
+
+ * config/obj-vms.h (DBG_S_C_COMPLX4, DBG_S_C_COMPLX8): define
+ these new VMS symbol-type macros for `complex float' and
+ `complex double' support. Their values come from the existing
+ DSC$K_DTYPE_FC and DSC$K_DTYPE_DC macros in <descrip.h>.
+ (DBG_S_C_REAL8_G, DBG_S_C_COMPLX8_G): G_float versions of
+ REAL8 and COMPLX8; not used yet, because gcc outputs the same
+ .stabs for `double' regardless of whether `-mg' is used.
+ * config/obj-vms.c (VMS_typedef_parse) [case 'r']: add entries
+ for gcc2's predefined types "complex float", "complex double",
+ and "complex long double" (identical to complex double).
+
+Wed Jun 15 12:32:55 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/obj-coff.c (coff_frob_symbol): Use C_STAT for the .text
+ section symbol, not C_LABEL.
+
+ * config/tc-mips.c (mips_ip): Permit a modifier in 'o' case, and
+ permit non constant expressions in 'u' case. Lets ``lui
+ $8,%hi(foo); lw $8,%lo(foo)($8)'' work correctly.
+
+Mon Jun 13 12:08:52 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/obj-aout.c (obj_aout_frob_symbol): Warn about an attempt
+ to put a common symbol in a set.
+
+Sat Jun 11 16:41:21 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ Add weak symbols as an extension to a.out.
+ * read.c (pseudo_set): Only preserve external bit for OBJ_AOUT and
+ OBJ_BOUT if not BFD_ASSEMBLER.
+ * config/aout_gnu.h (N_WEAKU, N_WEAKA, N_WEAKT, N_WEAKD, N_WEAKB):
+ Define as in ../include/aout/aout64.h.
+ * config/obj-aout.h (OBJ_SYMFIELD_TYPE): If not BFD_ASSEMBLER,
+ define as char.
+ (S_GET_WEAK, S_SET_WEAK): Define if not BFD_ASSEMBLER.
+ * config/obj-aout.c (obj_pseudo_table): Add "weak".
+ (obj_emit_symbols): Adjust type of weak symbols.
+ (obj_aout_weak): New static function.
+
+Fri Jun 10 13:48:49 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/obj-elf.c (obj_elf_section): Don't set any flags based on
+ the type of a special section.
+
+ * config/ho-sunos.h: Include <stdlib.h>. Don't declare malloc,
+ realloc, free, or atol.
+
+Wed Jun 8 06:28:37 1994 Bill Cox (bill@cygnus.com)
+
+ * Makefile.in (check): Delete as.new dependency, so that
+ regression test doesn't trigger an assembler build.
+
+Tue Jun 7 13:33:18 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * Makefile.in (mostlyclean, realclean): New targets.
+ * doc/Makefile.in, testsuite/Makefile.in: Likewise.
+
+Mon Jun 6 13:10:54 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (RDATA_SECTION_NAME): Define.
+ (macro): Correct M_LI_SS SVR4_PIC/EMBEDDED_PIC case. After M_LI_D
+ or M_L_DOB or label dob, force a new frag to avoid getting
+ confused in tc_gen_reloc.
+ (mips_ip): Use RDATA_SECTION_NAME, not .rdata.
+ (s_change_sec): Likewise.
+
+Fri Jun 3 23:35:36 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * read.c (emit_expr): Use memset to zero out memory, rather than
+ going through md_number_to_chars. This permits handling symbolic
+ arguments when the size is larger than sizeof (valueT), if
+ TC_CONS_FIX_NEW is prepared to handle the case (as it is on MIPS).
+
+Fri Jun 3 12:50:13 1994 David J. MacKenzie (djm@rtl.cygnus.com)
+
+ * as.c (show_usage), config/tc-alpha.c (md_show_usage),
+ config/tc-mips.c (md_show_usage): Fix up messages.
+
+ * as.h: Replace flagseen with separate variables.
+ * as.c (parse_args): Set them. Don't accept -1 option, or -v
+ explicitly (it's a synonym for --version).
+ * as.c, input-scrub.c, messages.c, read.c, symbols.c, write.c,
+ config/obj-aout.c, config/obj-aout.h, config/obj-bout.c,
+ config/obj-bout.h, config/obj-coff.c, config/obj-coff.h,
+ config/obj-vms.c, config/tc-hppa.c, config/tc-i386.c,
+ config/tc-i960.c, config/tc-m68k.c, config/tc-mips.c,
+ config/tc-vax.c: Use the new flag variables instead of flagseen.
+ * config/tc-vax.c [OBJ_VMS]: Recognize -+, -1, -v, and document in
+ usage.
+
+ * as.c (show_usage): Remove target specific messages;
+ instead, call md_show_usage.
+ (parse_args): Use getopt_long_only. Take pointers to argc and
+ argv.
+ (main): Pass parse_args pointers.
+ * as.h: Remove 3 variables that are redundant with flagseen.
+ * as.c, messages.c: Change their users to use flagseen.
+ Define getopt stuff.
+ * tc.h: Update md_parse_option decl. Add md_show_usage decl.
+ * config/tc-*.c: Add md_shortopts, md_longopts,
+ md_longopts_size, md_show_usage. Change calling convention for
+ md_parse_option. Remove md_parse_long_option.
+ * config/tc-ns32k.c: Rename `struct option' to `struct ns32k_option'.
+ * config/tc-i386.h: Don't define md_parse_option.
+
+Thu Jun 2 13:54:46 1994 David J. Mackenzie (djm@rtl.cygnus.com)
+
+ * as.c (show_usage): New function.
+ (parse_args): Code moved from main.
+ Recognize --help and --version.
+ * config/tc-ns32k.h: Define TC_NS32K.
+ * doc/as.texinfo: Document all of the target-independent command
+ line options.
+
+Thu Jun 2 12:07:25 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * gasp.c (hash_new_table): Clear newly allocated table.
+
+ * config/tc-m68k.c (enum _register): Add 68060 control registers
+ BUSCR and PCR.
+ (last_movec_reg): New macro.
+ (m68000_control_regs, m68010_control_regs, m68020_control_regs,
+ m68040_control_regs, m68060_control_regs): New arrays.
+ (control_regs): New pointer.
+ (m68k_ip): Use control_regs instead of testing CPU every time.
+ Use last_movec_reg too. In error messages, handle 68060, and
+ print 68060 for mfloat, too.
+ (m68k_init_after_args): Handle "68060". Use m68040up for making
+ m68851 choice. Set control_regs.
+ (md_parse_option): Handle "68060".
+ * configure.in: Setting cpu_type, recognize m68060 too.
+
+ * config/obj-coff.c (fixup_segment) [!BFD_ASSEMBLER]
+ [DIFF_EXPR_OK]: Do conversion to pc-relative for difference, even
+ if pcrel is already set.
+
+ * read.c (potable): Add this_gcc_requires_the_gnu_assembler in all
+ lower-case, in case we're ignoring case of opcodes in the input
+ file.
+
+ * doc/as.texinfo (.section): Document as unavailable for a.out
+ type formats.
+
+ * config/tc-alpha.c (machine): New variable.
+ (load_insn): New macro.
+ (load_insn_table): New function.
+ (md_begin): Call load_insn_table, once for basic instructions and
+ once for appropriate PAL instruction table.
+ (md_parse_option): Set `machine' based on -m##### arguments.
+ * config/alpha-opcode.h (alpha_pal21064_opcodes): Split out from
+ alpha_opcodes.
+ (alpha_pal21164_opcodes): New table.
+ (NUM21064OPCODES, NUM21164OPCODES): New macros.
+
+ * configure.in (target i386-*-netbsd0.8): Use 386bsd emulation.
+
+ * doc/Makefile.in (install-info-gasp): Use $$dir when installing
+ file.
+
+Wed Jun 1 10:48:19 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (mips_ip): Force floating point values to be
+ aligned correctly.
+
+Fri May 27 10:05:53 1994 Ken Raeburn (raeburn@cygnus.com)
+
+ Merged in changes from gas-2.3 net release:
+
+ * Makefile.in (VERSION): Updated to cygnus-2.3.1.
+
+ * config/obj-vms.c: Replaced unchecked uses of malloc with
+ xmalloc.
+
+ * listing.c (list_symbol_table): Only test BFD64, not
+ BFD_ASSEMBLER too.
+
+ * config/obj-coff.c (fixup_segment) [BFD_ASSEMBLER]
+ [DIFF_EXPR_OK]: Don't check pcrel, just convert it.
+
+ * config/obj-vms.c: Removed lots of extra semicolons after
+ compound statements.
+ (strchr): Don't declare here.
+
+ * config/ho-vax.h (realloc): Declare.
+
+ * config/ho-vms.h (strchr, strdup): Declare.
+
+ * config/tc-sparc.c (md_parse_option) [OBJ_ELF]: Accept and ignore
+ option `-q'.
+
+ Wed May 18 20:50:35 1994 Pat Rankin (rankin@eql.caltech.edu)
+
+ * config/obj-vms.h (DBG_S_C_SQUAD, DBG_S_C_UQUAD): define these
+ new VMS symbol-type macros; signed and unsigned quadword integers,
+ for `long long' support. Their values come from the existing
+ DSC$K_DTYPE_QU and DSC$K_DTYPE_Q macros in <descrip.h>. The
+ VMS debugger now recognizes `long long' variables correctly.
+ * config/obj-vms.c (VMS_typedef_parse) [case 'r']: add entries
+ for gcc2's predefined types "long double" (same as double, as
+ per gcc's current state), "long long int", "long long unsigned
+ int", and final `otherwise' case (to avoid uninitialized type
+ and size fields). [caveat: predefined types "complex int",
+ "complex float", "complex double", and "complex long double" are
+ still missing.]
+
+ * config/ho-vms.h (EXIT_FAILURE): define as 0x10000002 instead
+ of 0, because the latter indicates success rather than failure
+ when passed to `exit' or return from `main' compiled by gcc2.
+
+ * config/obj-vms.c (array_suffix, generate_suffix): replace two
+ hardcoded `0xa3's with macro DBG_S_C_ADVANCED_TYPE from obj-vms.h.
+ (VMS_typedef_parse): eliminate redundant if-then-else when
+ allocating new symbol entry and linking it to VMS_Symbol_type_list.
+
+ Tue May 17 20:47:31 1994 Pat Rankin (rankin@eql.caltech.edu)
+
+ * config/obj-vms.c (Write_VMS_MHD_Records): don't try to interpret
+ the contents of the GAS_VERSION string when falling back to it for
+ language processor identification.
+
+ * make-gas.com, vmsconf.sh (ENVIRON): fix misspelling of
+ `psect_attr' in linker options.
+
+ Wed May 11 22:32:00 1994 DJ Delorie (dj@ctron.com)
+
+ * configure.bat: update to latest makefile.in
+ * config/te-go32.h: [new] go32's environment
+
+Fri May 20 17:59:34 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * as.h: Don't declare parameters for strstr.
+
+Thu May 19 15:40:13 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-sparc.c (md_section_align): Don't change the size if
+ OBJ_ELF.
+
+Wed May 18 13:08:07 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * Makefile.in (install): Redirect ln output to /dev/null. If ln
+ fails on gasp, install gasp.new, not gasp.
+
+Wed May 18 09:16:36 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (pa_ip): Use R_HPPA_ABS_CALL, not R_HPPA for
+ absolute calls.
+
+Tue May 17 12:50:46 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (pa_parse_fp_cmp_cond): Report an error
+ on a partial completer match.
+
+Mon May 16 12:03:49 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c: Change .hppa_unwind to .PARISC.unwind
+ throughout code.
+ (is_complex): Delete definition and support for complex relocation
+ types.
+ (tc_gen_reloc): Delete special unwind crud for ELF. Simplify and
+ rewrite ELF code based on 94-02-02 PA ELF draft spec.
+ (pa_build_unwind_subspace): Use standard PARISC_DIR32 relocs for
+ the unwind descriptors.
+
+Fri May 6 14:13:15 1994 Steve Chamberlain (sac@cygnus.com)
+
+ * config/go32.mh: New makefile fragment for go32 crossing.
+ * configure.in (host==go32): Use new fragment.
+
+Fri May 6 14:35:58 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * gasp.c: Include libiberty.h.
+ (main): Remove unused variable i.
+
+ * config/tc-ppc.c (md_begin): When using -many, permit comparison
+ instructions to appear multiple times in the opcode table.
+
+Thu May 5 19:14:43 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * Makefile.in (VERSION): Update to 2.2.90.
+
+ * symbols.c (symbol_new) [BFD_ASSEMBLER]: Don't permit additions
+ to the symbol table if it's already been set in the output bfd.
+ (symbol_begin) [! EMIT_SECTION_SYMBOLS] [RELOC_REQUIRES_SYMBOL]:
+ Don't use bfd_abs_section.symbol for gas absolute symbol.
+
+ * doc/Makefile.in (distclean, clean-dvi, clean-info): Delete gasp
+ files too.
+
+Thu May 5 18:12:51 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (mips_emit_delays): Make call to
+ mips_no_prev_insn unconditional.
+
+Thu May 5 17:25:38 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config/obj-coff*.*: Merged coffbfd versions into coff versions,
+ with a single "#ifdef BFD_ASSEMBLER" controlling most of it for
+ now. Deleted obj-coffbfd.* files.
+ * configure.in: Always use obj-coff.* for COFF targets.
+
+Wed May 4 13:34:11 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config/te-dpx2.h (TARGET_FORMAT, REGISTER_PREFIX_OPTIONAL):
+ Define.
+ * configure.in (m68k-bull-sysv3*): Enable.
+
+ * config/coff_gnu.h: Deleted.
+
+Wed May 4 11:29:17 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-m68k.h (TARGET_FORMAT): If not TE_SUN3, define as
+ "a.out-zero.big".
+
+ * config/obj-coffbfd.c (fixup_segment): Make common symbol and PC
+ relative adjustments when TE_LYNX is defined as well as when
+ TC_I386 is defined.
+
+Wed May 4 02:29:21 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * as.h (strstr): Restore declaration.
+ (subseg_get) [BFD_ASSEMBLER]: Declare.
+
+ * write.c (write_object_file): If obj_adjust_symtab is defined,
+ invoke it. Then call set_symtab, and finally invoke *_frob_file
+ hooks.
+ * config/obj-coff.c (coff_adjust_symtab): Renamed from
+ coff_frob_file.
+ * config/obj-coff.h (coff_adjust_symtab): Changed declaration
+ accordingly.
+ (obj_adjust_symtab): Macro also changed.
+
+ * configure.in (i386-*-gnu*): New target, handled like i386-mach.
+
+Tue May 3 21:04:16 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config/obj-coff.h (TARGET_FORMAT) [TC_I960]: Select little
+ endian version.
+
+ * config/obj-coffbfd.h (TARGET_FORMAT) [TC_I960]: Ditto.
+
+ * config/obj-coff.c (coff_frob_section): Round up the size of
+ every section to a multiple of the alignment, so that BFD doesn't
+ surprise us.
+
+ Eliminate many simple differences between the two COFF back ends:
+
+ * config/obj-coffbfd.c: Removed all uses of DEFUN and DEFUN_VOID.
+ Made minor stylistic changes, deleted some register declarations.
+ (stack_top): Deleted.
+ (symbol_to_chars): Use absolute_section and reg_section instead of
+ the corresponding SEG_* symbols.
+ (obj_coff_endef, tag_find_or_make, fixup_segment): Likewise.
+ (stack typedef, stack_init, stack_delete, stack_push, stack_pop):
+ Moved to just after pseudo-op table. All functions now static.
+ (stack_delete): Removed declaration.
+ (tag_init, tag_insert, tag_find_or_make, tag_find): Moved to just
+ after stack functions.
+ * config/obj-coffbfd.h: Reordered some declarations and macros.
+ (stack_init, stack_delete, stack_push, stack_pop): Don't declare.
+ (stack typedef): Deleted.
+ (SYMBOLS_NEED_BACKPOINTERS): Always undef then define; don't test.
+ (SYM_AUXENT): New macro.
+ (SA_GET_*, SA_SET_*): Define in terms of SYM_AUXENT when feasible.
+ (SF_GET_*, SF_SET_*): Define in terms of SF_GET when feasible.
+ (SA_GET_SYM_TAGNDX, SA_GET_SYM_ENDNDX, SA_SET_SYM_TAGNDX,
+ SA_SET_SYM_ENDNDX, object_headers typedef, data_section_header,
+ text_section_header): Delete non-BFD_HEADERS versions, since we
+ always define that symbol now.
+
+ * config/obj-coff.c (stack_top): Deleted.
+ (obj_coff_endef, obj_coff_dim, obj_coff_line, obj_coff_size,
+ obj_coff_scl, obj_coff_tag, obj_coff_type, obj_coff_val): Change
+ argument name from "ignored" to "ignore".
+ (obj_coff_val): Use frag_now_fix.
+ (obj_pseudo_table): Removed IGNORE_DEBUG version, since it doesn't
+ get used.
+ (stack typedef, stack_init, stack_delete, stack_push, stack_pop):
+ Moved to just after pseudo-op table. All functions now static.
+ (tag_init, tag_insert, tag_find_or_make, tag_find): Moved to just
+ after stack functions.
+ * config/obj-coff.h: Reordered some declarations and macros.
+ Protected against multiple inclusions.
+ (stack_init, stack_delete, stack_push, stack_pop): Don't declare.
+ (stack typedef): Deleted.
+ (SYMBOLS_NEED_BACKPOINTERS): Always undef then define; don't test.
+ (stdoutput): Deleted declaration.
+ (TARGET_FORMAT) [TC_I386]: Don't define if already defined.
+
+Mon May 2 17:09:24 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * subsegs.h (segment_info_type): Use fix_tail field even if
+ BFD_ASSEMBLER.
+ * subsegs.c (subseg_change): Initialize fix_tail field.
+ (subseg_get): Likewise.
+ * write.c (frags_chained): New static variable.
+ (fix_new_internal): If frags_chained is set, use fix_root and
+ fix_tail from seg_info (now_seg), rather than frchain_now.
+ (chain_frchains_together_1): Set fix_tail field.
+ (chain_frchains_together): Set frags_chained.
+
+Thu Apr 28 01:39:15 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * config/tc-mips.c (s_option): Only refer to g_switch_* variables
+ if GPOPT is defined.
+ (s_abicalls): Ditto.
+ (md_apply_fix): Cast char* to unsigned char* to avoid pointer
+ mismatch.
+
+Wed Apr 27 11:06:32 1994 Steve Chamberlain (sac@cygnus.com)
+
+ * configure.in (i386-*-go32): Uses coff now.
+ * gasp.c (main): Now takes -D on command line.
+ (show_usage): Describe new options.
+
+Tue Apr 26 17:10:30 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * listing.c (list_symbol_table): Print "NO DEFINED SYMBOLS" and
+ "NO UNDEFINED SYMBOLS" if there aren't any, instead of displaying
+ the header with an empty list.
+
+ * config/obj-coffbfd.c (fill_section): Check COFF_NOLOAD_PROBLEM
+ also before setting STYP_NOLOAD for .bss section.
+
+ * config/tc-m68k.c (flag_reg_prefix_optional): New variable.
+ Initialized to value of REGISTER_PREFIX_OPTIONAL, if defined, or
+ zero.
+ (m68k_reg_parse): If flag_reg_prefix_optional is set, permit
+ register prefix to be absent.
+ (m68k_ip_op): Accept `&' also for immediate constants.
+ (insert_reg): Don't bother with (two!?) sanity checks of the
+ symbol table when inserting each register.
+ (m68k_parse_long_option): New function. Set
+ flag_reg_prefix_optional if "register-prefix-optional" is passed.
+ * config/tc-m68k.h (REGISTER_PREFIX): Always define if not already
+ defined.
+ (OPTIONAL_REGISTER_PREFIX): Don't define.
+ (REGISTER_PREFIX_OPTIONAL): If not already defined, define as zero
+ or one depending on M68KCOFF.
+
+ Some changes to help Apollo support, from troy@cbme.unsw.edu.au:
+ * config/tc-m68k.c (DATA, ADDR, SP, FPREG, COPNUM, BAD, BAC):
+ Define as macros instead of enumerators, since the Apollo compiler
+ can't handle "enumVal1, enumVal2 = enumVal1" when defining an enum
+ type.
+ (make_pcrel_absolute) [NO_PCREL_RELOCS]: New function.
+ (tc_coff_fix2rtype) [NO_PCREL_RELOCS]: Generate only R_RELBYTE,
+ R_DIR16, and R_DIR32 relocs.
+ * config/tc-m68k.h [TE_APOLLO] (COFF_MAGIC, COFF_AOUTHDR_MAGIC):
+ Use Apollo versions.
+ [TE_APOLLO] (OBJ_COFF_OMIT_OPTIONAL_HEADER): Undefine. That is,
+ do include the optional header for Apollo target.
+ (COFF_MAGIC): Don't define as MC68MAGIC if it's already defined.
+
+ * config/tc-m68k.h [TE_DELTA] (LEX_PCT): Define as 1, so that `%'
+ can be used within a label name.
+
+ * config/tc-m68k.h (m68k_init_after_args): Declare.
+ (tc_init_after_args): Define as m68k_init_after_args.
+ * config/tc-m68k.c (m68k_init_after_args): New function,
+ containing one-shot code from md_assemble. Added warning for
+ combination of 68040 and 68851.
+ (md_assemble): Startup-time code deleted.
+
+Mon Apr 25 16:19:17 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * doc/Makefile.in (clean, distclean): Remove asconfig.texi.
+
+Sun Apr 24 00:13:08 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (pa_ip): 13 bit immediate constant (for break
+ instruction) is unsigned.
+
+Fri Apr 22 17:58:22 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/obj-ecoff.c (ecoff_frob_file): Use bfd_ecoff_set_gp_value
+ and bfd_ecoff_set_regmasks to set the GP value and the register
+ masks, rather than using the now obsolete fake .reginfo section.
+
+Fri Apr 22 15:17:06 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * listing.c (list_symbol_table): Don't print register symbols as
+ undefined.
+
+ * config/obj-coff.c (obj_symbol_new_hook): Don't need to strip
+ underscores, since symbol_new will already have done it.
+ * config/obj-coffbfd.c (obj_symbol_new_hook): Ditto.
+
+ * as.c (main): If tc_init_after_args is defined, invoke it after
+ all arguments have been processed.
+
+ Some changes to help Apollo support, from troy@cbme.unsw.edu.au:
+ * as.c (perform_an_assembly_pass) [TE_APOLLO]: Create .wtext
+ section instead of .text. Call create_target_segments.
+ * read.c (demand_copy_string): No longer static.
+
+Thu Apr 21 15:50:04 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (append_insn): Permit branches to be switched
+ with the preceding instruction even if .set nobopt has been seen.
+ .set nobopt actually controls whether to bring up an instruction
+ from the branch target, which gas does not currently support.
+
+Wed Apr 20 18:46:14 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config/obj-coff.h, config/obj-coff.c: Deleted all code used only
+ when BFD_ASSEMBLER is not defined, and all conditionals relating
+ to such code. No such targets remain.
+
+ Fixes for stabs-in-coff:
+ * config/obj-coff.c: Include subsegs.h.
+ (coff_frob_section): New function.
+ (obj_coff_init_stab_section): New function.
+ * config/obj-coff.h (obj_coff_init_stab_section,
+ coff_frob_section): Declare.
+ (obj_frob_section): New macro; uses coff_frob_section.
+ (INIT_STAB_SECTION): New macro; uses obj_coff_init_stab_section.
+
+ * config/tc-sparc.c (md_section_align): Always round up to
+ multiple of alignment power specified in bfd target vector.
+
+ * gasp.c: Include ctype.h.
+
+Mon Apr 18 21:08:01 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * doc/Makefile.in, doc/as.texinfo: Renamed asdoc-config.texi to
+ asconfig.texi.
+
+ * doc/Makefile.in (install-info-as, install-info-gasp): Get file
+ names from source directory without pathname.
+
+ * config/obj-vms.c (VMS_write_object_file): While looking for
+ register mask, skip empty fill frags caused by enabling listing
+ output.
+
+ * config/ho-sysv.h: Include string.h.
+
+ * doc/internals.texi: New (well, recently added) file. Just added
+ info on as_warn and friends.
+
+Mon Apr 18 14:28:22 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (pa_parse_space_stmt): Use the built-in
+ defaults for defined, private, and spnum fields for the
+ $TEXT$ and $PRIVATE$ spaces. Do not clobber spnum. Do
+ not reset the segment if just updating a space.
+ (pa_spaces_begin): Set BFD section flags for all built-in
+ subspaces.
+
+Fri Apr 15 10:51:51 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ecoff.c (first_proc_ptr): New static variable.
+ (add_procedure): Set first_proc_ptr if it hasn't been set.
+ (ecoff_build_lineno): If the first procedure does not start at
+ address zero, insert a dummy line to compensate.
+
+ * Makefile.in (bootstrap, bootstrap2, bootstrap3): Make gasp.new
+ as well as as.new.
+
+Thu Apr 14 15:12:36 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * expr.c (operand): Try to parse "0f" and "0b" sequences as
+ floating point and binary numbers respectively; if it doesn't
+ work, treat them as local labels.
+
+ * Makefile.in: Make $(OBJS) depend on $(ALL_OBJ_DEPS).
+ * configure.in: Set ALL_OBJ_DEPS in output Makefile.
+
+ Based on suggestions from <BAILEY@hmivax.humgen.upenn.edu>
+ (Charles Bailey):
+ * vmsconf.sh: In generated file, get ".obj" suffix right, build
+ source files from other directories into objects in the current
+ directory, and specify PSECT attributes explicitly to linker.
+ Also added missing label.
+ * Makefile.in (stamp-mk.com): Reference new variable
+ VMS_OTHER_OBJS for list of non-local object files, instead of
+ listing them here.
+ (VMS_OTHER_OBJS): New variable, added more libiberty files.
+ * make-gas.com: Regenerated.
+
+ * config/ho-vms.h (unlink): Define as delete.
+
+ * config-gas.com: Fix quoting on TARGET_CANONICAL definition.
+ Delete files before creating them.
+
+Thu Apr 14 13:34:24 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * Makefile.in (de-stage1, de-stage2, de-stage3): Use rm -f.
+
+ * config/tc-mips.h (DIFF_EXPR_OK): Define.
+ * config/tc-mips.c (macro_build): Permit BFD_RELOC_PCREL_LO16 for
+ certain cases of 'i', 'j' and 'o'. Change 'u' to take an
+ argument, the reloc type.
+ (load_register): Pass reloc type to macro_build for 'u'.
+ (macro): Likewise. For M_LA_AB permit a difference expression
+ when generating embedded PIC code between an arbitrary symbol and
+ a symbol in the .text section.
+ (mips_force_relocation): Force BFD_RELOC_PCREL_HI16_S and
+ BFD_RELOC_PCREL_LO16 to be emitted.
+ (md_apply_fix): Check that most relocs are not PC relative.
+ Handle BFD_RELOC_PCREL_HI16_S and BFD_RELOC_PCREL_LO16.
+ (tc_gen_reloc): Change #error to as_fatal. Handle
+ BFD_RELOC_PCREL_LO16 and BFD_RELOC_PCREL_HI16_S.
+
+Tue Apr 12 18:25:13 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * subsegs.c (subsegs_begin): Call memset with args in the correct
+ order.
+ (subseg_get): Clear newly allocated seginfo, set its pointer slots
+ to NULL instead of 0.
+
+Mon Apr 11 09:00:57 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (pa_procend): Handle case where label was
+ defined after the .proc directive.
+
+ * config/tc-hppa.c (pa_procend): Give an error if we encounter a
+ procend for a procedure without a name.
+
+Thu Apr 7 14:28:30 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (macro): Pass NULL for expression argument to
+ macro_build for nori case.
+ (SWITCH_TABLE): Define.
+ (mips_force_relocation): Force a relocation for a switch table
+ entry.
+ (md_apply_fix): Write switch table entry value into file.
+ (tc_gen_reloc): Use BFD_RELOC_GPREL32 for a switch table entry,
+ and set the addend to the difference between the reloc address and
+ the subtrahend.
+
+Thu Apr 7 10:38:18 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.h (elf_tc_symbol): Delete. No longer used.
+ (elf_tc_make_sections): Likewise.
+ (hppa_tc_make_sections, hppa_tc_symbol): Delete extern decls.
+
+ * config/tc-hppa.c (hppa_tc_make_sections): Delete function.
+ (hppa_tc_symbol): Likewise.
+
+ * config/obj-elf.c (elf_frob_file): Delete elf_tc_symbol and
+ elf_tc_make_sections stuff. It was there to support PA braindamage
+ which has been fixed, and in the case of elf_tc_make_sections is
+ redundant with elf_tc_final_processing.
+
+Wed Apr 6 20:48:30 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * configure.in (hppa*-*-*elf*): Don't require "-hp-" for the
+ manufacturer.
+
+Tue Apr 5 15:48:03 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (mips_ip): For case 'o', when generating
+ embedded PIC code, accept the difference between two local symbols
+ as being constant.
+ (mips_force_relocation): Only force a reloc to be generated for a
+ PC relative fixup.
+ (md_apply_fix): For BFD_RELOC_32 and BFD_RELOC_LO16, put the fixup
+ value into the file if the fixup will not generate a reloc.
+
+Tue Apr 5 11:14:14 1994 Ken Raeburn (raeburn@rtl.cygnus.com)
+
+ * config/tc-sparc.c (s_reserve): If section passed isn't bss,
+ don't spew remainder of input file in error message.
+ (tc_gen_reloc): If bfd_reloc_type_lookup returns null, print error
+ message with reloc type and try to process remainder of file.
+
+ * doc/Makefile.in (install-info-as, install-info-gasp): New
+ targets, now explicitly checking $(srcdir) for info files.
+ (install-info): Depend on both of them; do nothing more.
+
+Mon Apr 4 17:06:04 1994 Jeffrey A. Law (law@cygnus.com)
+
+ * config/tc-hppa.c (tc_gen_reloc): Fix thinko in ELF version.
+
+Mon Apr 4 12:39:23 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-ppc.c (ppc_insert_operand): Check PPC_OPERAND_SIGNED
+ flag rather than signedp field. Only permit extended range if
+ PPC_OPERAND_SIGNOPT flag is set and assembling in 32 bit mode.
+ Based on patch from David Edelsohn (edelsohn@npac.syr.edu).
+
+ * config/tc-ppc.c (ppc_size): New static variable.
+ (ppc_arch): Check for PPC_OPCODE_PPC before PPC_OPCODE_POWER.
+ (md_begin): If an instruction has a size specific flag set, only
+ add it if we are assembling that size.
+
+Thu Mar 31 16:51:16 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-sparc.c (tc_gen_reloc): Add a gruesome hack to get
+ cross section PC relative relocs right for COFF and ELF.
+
+Mon Mar 28 14:38:23 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config/obj-coff.h (SEPARATE_STAB_SECTIONS): Always define.
+ (OBJ_PROCESS_STAB): Don't define.
+
+Mon Mar 28 12:40:25 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/obj-aout.c (obj_aout_frob_symbols): Don't let BFD clobber
+ the type of symbol set symbols which happen to be in the absolute
+ or undefined section.
+
+Mon Mar 28 12:35:00 1994 David Edelsohn (edelsohn@npac.syr.edu)
+
+ * config/tc-ppc.c (md_parse_option): Add -mpwrx (POWER/2 aka
+ RIOS2), -mpwr (POWER aka RIOS1), -mppc (PowerPC aka MPC603/604),
+ and -many (all architectures).
+
+Sun Mar 27 14:04:19 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (tc_gen_reloc): Set addend for relocation
+ involving a function symbol which is not a plabel to zero.
+ (md_apply_fix): Never pass a function symbol to field_adjust.
+
+Fri Mar 25 17:35:49 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/obj-aout.c (obj_aout_frob_symbol): If N_EXT is set for an
+ N_INDR symbol, set BSF_EXPORT and clear BSF_LOCAL.
+
+ * config/tc-mips.c (append_insn): If EMBEDDED_PIC, don't swap a
+ branch with an instruction that uses $at, in case the branch is
+ later expanded.
+ (macro): If EMBEDDED_PIC, case M_JAL_A may use $at.
+ (md_pcrel_from): If not OBJ_AOUT, return 4 for an undefined symbol
+ to make it pcrel_offset.
+ (tc_gen_reloc): If not OBJ_AOUT, set the reloc addend to
+ reloc->address; another gruesome hack to get gas reloc handling to
+ do the right thing.
+
+Thu Mar 24 21:29:29 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config/tc-alpha.c (alpha_ip): Only set GP prolog size if using
+ PV register.
+ (T12): New macro.
+ (emit_insn): New function.
+ (md_assemble): Call it.
+ (alpha_force_relocation): Handle BFD_RELOC_26, for call_pal
+ instructions.
+ (lituse_pending): New variable. Set by anything that generates a
+ LITERAL reloc, cleared by anything that generates a LITUSE reloc,
+ tested by code that might want to emit a LITUSE reloc.
+ (emit_unaligned_io): New function. Currently calls md_assemble,
+ but it should eventually be converted to generate the insn itself
+ and call emit_insn directly.
+ (emit_load_unal, emit_store_unal, emit_byte_manip_r,
+ emit_extract_r, emit_insert_r, emit_mask_r, emit_sign_extend,
+ emit_bis_r): Likewise.
+ (alpha_ip, case 'I'): Handle with BFD_RELOC_23.
+ (alpha_ip, label get_macro): Don't emit the final instruction if
+ the opcode is zero.
+ (alpha_ip, case 'B', subcase 'd'): New case, for subword and
+ unaligned memory access macros.
+ (md_apply_fix): Handle BFD_RELOC_26. Generate an error message if
+ the value can't be resolved.
+
+Wed Mar 23 16:06:08 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (md_parse_option): For -membedded-pic, force
+ the -G value to 0x7fffffff. For SVR4 PIC options, don't call
+ bfd_set_gp_size here, it's done in md_begin. Don't permit -G with
+ -membedded-pic.
+ (mips_force_relocation): New function.
+ (md_apply_fix): Set fixP->fx_done appropriately.
+ (s_change_sec): For EMBEDDED_PIC, change .data and .rdata to
+ .sdata.
+ * config/tc-mips.h (TC_FORCE_RELOCATION): Define.
+ (mips_force_relocation): Declare.
+ (TC_HANDLE_FX_DONE): Define.
+
+Tue Mar 22 13:58:37 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (enum mips_pic_level): New enum.
+ (mips_pic): Change from int to enum mips_pic_level. Change all
+ uses (0 becomes NO_PIC, 2 becomes SVR4_PIC).
+ (load_address): Handle EMBEDDED_PIC.
+ (macro): Handle EMBEDDED_PIC in all PIC cases.
+ (md_parse_option): Accept -membedded-pic to use EMBEDDED_PIC. If
+ OBJ_ELF, accept -KPIC and -call_shared to use SVR4_PIC and accept
+ -non_shared to use NO_PIC (this is how the Irix 5 assembler
+ works). Do not permit -G with SVR4_PIC.
+ (s_abicalls): Warn if -G was used, and force -G 0.
+ (tc_gen_reloc): Set reloc->addend to 0 for a PC relative reloc for
+ anything but a.out, not just for ELF. For ECOFF, don't generate a
+ BFD_RELOC_16_PCREL_S2 reloc unless using EMBEDDED_PIC.
+
+ * config/obj-ecoff.h (obj_sec_sym_ok_for_reloc): Define to be 1.
+
+Sun Mar 20 16:31:55 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (create_new_space): Use ints, not chars as
+ parameters to avoid losing when compiling with HP CC.
+ (create_new_subspace, update_subspace, fix_new_hppa): Likewise.
+
+Sun Mar 20 14:43:14 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * Makefile.in (config-stamp): If `defs' is defined, emit a
+ preprocessor directive to create a macro named by this value into
+ config.new; don't explicitly go for BFD_ASSEMBLER.
+ * configure.in: Define `defs', not `BFDDEF'. Set it to
+ MANY_SEGMENTS for any obj-coffbfd target.
+ * config/obj-coffbfd.h (BFD_HEADERS, BFD): Define.
+ * config/i386coff.mt (TDEFINES): Don't define BFD, MANY_SEGMENTS,
+ or BFD_HEADERS.
+ (LOCAL_LOADLIBES): Deleted.
+ * config/m68kcoff.mt (TDEFINES): Don't define those macros.
+ * config/m88kcoff.mt (TDEFINES): Ditto.
+ * config/ebmon29k.mt: Deleted.
+ * config/h8300hds.mt: Deleted.
+ * config/ic960coff.mt: Deleted.
+ * config/sparc.mt: Deleted.
+ * config/h8300.mt (LOCAL_LOADLIBES, TDEFINES): Deleted.
+ * config/h8500.mt (LOCAL_LOADLIBES, TDEFINES): Deleted.
+ * config/sh.mt (LOCAL_LOADLIBES, TDEFINES): Deleted.
+ * config/z8k.mt (LOCAL_LOADLIBES): Deleted.
+ (TDEFINES): Don't define the coffbfd macros.
+
+ * Makefile.in: Insert makefile fragments before OBJS definition.
+ (OBJS): Add $(TE_OBJS).
+
+ * config/obj-coff.c (obj_pseudo_table): Supply "section"
+ unconditionally.
+
+ * write.c (set_symtab): Define only if BFD_ASSEMBLER.
+
+Sun Mar 20 12:06:05 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * Makefile.in (STAGESTUFF): Add gasp.new.
+
+Fri Mar 18 20:09:16 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * write.c (symbol_table_frozen): New variable, to be set after
+ bfd_set_symtab is called.
+ (dump_section_relocs): Note whether a symbol is a section symbol
+ or not.
+ (adjust_reloc_syms): For now, always supply an absolute symbol for
+ fixups without symbols but not yet `done'. Use section_symbol to
+ get the symbol, instead of going directly for abs_symbol.
+ (write_relocs) [DEBUG4]: Abort if any symbol referred to by a
+ reloc is not a section symbol and is not in the symbol table.
+ (set_symtab): New function, broken out from write_object_file.
+ Counts symbol table instead of relying on an earlier count.
+ (write_object_file): Call set_symtab, but do it after potentially
+ invoking the *_frob_file macros. Don't bother counting symbols.
+ Call symbol_remove, instead of expanding it in place. Moved the
+ conditionalized `object_file_size' declaration down to
+ conditionalized block where it's used. When using the absolute
+ symbol for a fixup without a symbol, set sy_used_in_reloc.
+ (write_object_file) [BFD_ASSEMBLER]: Call section_symbol to get
+ the correct symbol for the absolute section.
+
+ * subsegs.c (section_symbol): Use symbol_new instead of
+ symbol_make, since we may want it to go into the symbol table.
+ Make the new symbol have internal linkage. If
+ obj_sec_sym_ok_for_reloc says it's okay, use the BFD section
+ symbol with the newly created GAS symbol.
+ (obj_sec_sym_ok_for_reloc): Default to always returning 0.
+ * config/obj-aout.h (obj_sec_sym_ok_for_reloc) [BFD_ASSEMBLER]:
+ New macro.
+ * config/obj-elf.h (obj_sec_sym_ok_for_reloc): New macro.
+
+ * config/tc-sparc.c: Include subsegs.h.
+ (in_signed_range): New function.
+ (sparc_ip): Use it.
+ (sparc_ip, case 'i'): Use BFD_RELOC_SPARC13, not _BASE13.
+ (sparc_ip, label "immediate"): Reject constants for pcrel
+ instructions only if the relocation type indicates a "call"
+ instruction and the offset is within range of a "jmpl %g0". If
+ it's not in range, use the absolute section symbol plus an offset.
+ (md_apply_fix): Use in_signed_range. Combined _SPARC13 and
+ _BASE13 cases.
+ (tc_gen_reloc): Permit BFD_RELOC_SPARC13.
+
+ * config/ic960coff.mt (TDEFINES): Fixed typo (MANY_SECTIONS, not
+ MANY_SEGMENTS).
+
+ * configure.in: Eliminated all targets using obj-coff but not
+ defining BFD_ASSEMBLER; I think all such targets that are
+ supported will be matched by real CPU-OS combinations earlier in
+ the case statement.
+ (targets *-*-coff*, *-sysv*, *-*-sco*, *-*-sysv32): Deleted. Made
+ some comments about the dpx2 configuration, but left it disabled,
+ since it couldn't be reached before.
+ (target a29k-amd-ebmonold): Deleted.
+
+Thu Mar 17 13:36:09 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (pa_import): Correctly handle importing of an
+ already defined symbol.
+
+Wed Mar 16 17:11:37 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (mips_ip): Only accept overly large values for
+ the 'j' operand if there are no further alternatives for this
+ instruction.
+
+ * config/obj-coffbfd.c (adjust_stab_section): Initialize
+ stabstrseg to SEG_UNKNOWN, not -1. After loop, check whether it
+ is not SEG_UNKNOWN rather than checking whether it is >= 0.
+
+ * config/tc-mips.c (mips_align): Take new argument, label, and use
+ it instead of global insn_label.
+ (s_align, s_cons, s_float_cons, s_gpword): Save insn_label before
+ call to mips_emit_delay and pass it to mips_align.
+
+Wed Mar 16 11:54:12 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (pa_equ): Handle both .reg and .equ correctly.
+
+ * config/tc-hppa.c (pa_callinfo): Accept "millicode" as an
+ argument to a .callinfo directive. Don't loop forever on errors.
+
+ * config/tc-hppa.c (pa_equ): Use pa_parse_number so that we can
+ use pre-defined registers as arguments.
+
+Mon Mar 14 14:29:45 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * write.c (write_object_file): Check both S_IS_LOCAL and
+ S_IS_EXTERNAL when deciding whether to discard a symbol.
+
+ * config-gas.com: Scan Makefile.in, not version.c, for current
+ version number. Delete all versions of temp files when finished
+ with them. Create config.h.
+
+ * config/obj-vms.c (VMS_Initialized_Data_Size): Cache symbol
+ values to reduce number of lookups with S_GET_VALUE. Skip debug
+ symbols to avoid "a really nasty bug". (From Holger Teutsch,
+ holger@botbso.rhein-main.de.)
+ (VMS_write_object_file): For "__vt.*" symbols, set S_GET_OTHER
+ field. (Also from Holger Teutsch.) Watch for a would-be register
+ mask that spans frags.
+
+ * config/obj-coffbfd.c (obj_coff_line): Set symbol lnno field with
+ this_base, not line_base. (Patch from Andreas Arens,
+ ari@obelix.av.rwth-aachen.de.)
+
+ * config/obj-aout.c (obj_crawl_symbol_chain): Retain symbols that
+ look local if they're exported or undefined. Used to be done for
+ i960 only.
+
+ * read.c (s_lcomm, s_comm): Print symbol name being redefined.
+ Get it from the looked-up symbol, instead of using the string from
+ the input stream, which is no longer null-terminated.
+ (LEX_PCT): New macro, defaults to 0.
+ (lex_type): Use it for `%'.
+
+ * config/tc-vax.c (md_parse_option): Handle `-h#' option for VMS.
+ (vip_op): Now static, and returns void. Callers changed. Added
+ forward decl.
+ (vip): Ditto. Call as_fatal directly if a program bug is
+ detected.
+ (op_hash): Let default initialization suffice.
+
+ * Makefile.in (literal.o): Provide dependencies.
+
+ * configure.in: Set new makefile variable OPCODES_LIB.
+ * Makefile.in (LIBS): Use it.
+
+ * Makefile.in (make-gas.com, stamp-mk.com): New targets.
+ * vmsconf.sh: New file.
+ * make-gas.com: Regenerated from new script.
+
+ * configure.in (sparc*-*-lynxos*): Handle any version number
+ suffix after "lynxos". Set emulation to lynx.
+
+Mon Mar 14 11:30:49 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * config/obj-coff.c (obj_coff_section): Delete declaration.
+
+Fri Mar 11 22:25:44 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-ppc.c (md_pcrel_from): Return 0 for undefined ELF
+ symbols.
+ (ppc_is_toc_sym): Change .toc to .got.
+ (md_apply_fix): Change handling of ELF relocs.
+ (tc_gen_reloc): Likewise.
+
+Fri Mar 11 17:42:20 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config/obj-vms.c (Close_VMS_Object_File): Add comment pointing
+ out some code that doesn't belong in this file.
+
+ * config/obj-vms.h: Include aout/stab_gnu.h.
+ (N_GSYM, ..., N_LENG): Deleted.
+ (NO_RELOC): Undefine before defining as part of enum reloc_type.
+
+ * config/tc-alpha.c: Add comment questioning need for all the
+ characters in FLT_CHARS.
+
+ * as.c (main) [OBJ_VMS]: Don't call output_file_close.
+
+ * config/obj-ecoff.c (ecoff_frob_file): Set strict order for
+ sections with recognized names, before computing VMA values.
+
+Fri Mar 11 17:56:23 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (mips_ip): Accept numbers between 0x8000 and
+ 0xffff for 'j' to be compatible with MIPS assembler. These
+ numbers are actually treated as negative.
+
+Thu Mar 10 13:36:29 1994 Doug Evans (dje@canuck.cygnus.com)
+
+ * config/tc-sparc.h (LOCAL_LABEL): Local labels are .Lfoo.
+
+Tue Mar 8 21:17:12 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config/obj-coff.c: Minor formatting/stylistic changes, plus:
+ (obj_coff_section): Declare.
+ (obj_pseudo_table): Make it available only if MANY_SECTIONS.
+ (obj_symbol_to_chars) [CROSS_COMPILE]: Some attemps to make this
+ work. It still doesn't. It now fails to compile, instead of
+ silently compiling to do nothing.
+ * config/obj-coff.h (SEPARATE_STAB_SECTIONS): Define only if
+ MANY_SECTIONS.
+ (OBJ_PROCESS_STAB) [! MANY_SECTIONS]: New macro, just emits
+ warning.
+
+ Handle Alpha load-immediate-FP pseudo-instructions:
+ * config/alpha-opcode.h (ldif, ldig, ldis, ldit): New patterns.
+ * config/tc-alpha.c (lit8_sec, lit4_sec, lit8_sym, lit4_sym): New
+ variables.
+ (create_literal_section): New function.
+ (create_lita_section): Now a macro.
+ (get_lit8_offset, get_lit4_offset): New functions.
+ (maybe_set_gp): New function.
+ (select_gp_value): Call it.
+ (load_expression): Preserve addend if symbol is a section symbol.
+ (alpha_ip): Handle new operand type `F' for floating-point
+ constants; store them in .lit{4,8} sections.
+ (alpha_ip, case 'G'): Emit LITUSE relocations for symbol exprs.
+
+ * config/tc-i386.c (smallest_imm_type): Never return Imm1.
+
+Tue Mar 8 14:18:15 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * config/obj-coffbfd.c (w_strings): Only copy strings out if
+ their symbols are going to be written.
+
+Tue Mar 8 11:49:27 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * messages.c (as_perror): Declare arguments const.
+ * as.h (as_perror): Change declaration.
+
+Mon Mar 7 16:08:25 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (load_address): When calling frag_grow, allow
+ for the (up to) two nops which may be inserted by append_insn if
+ mips_optimize is 0.
+ (macro): Likewise.
+
+Thu Mar 3 11:37:55 1994 Doug Evans (dje@canuck.cygnus.com)
+
+ * config/atof-ieee.c (make_invalid_floating_point_number):
+ Add cast to avoid warning from gcc.
+
+Wed Mar 2 10:31:01 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c: Add a few casts to make HP C compiler happy.
+
+ * config/obj-som.c (obj_som_version, obj_som_copyright): Be
+ prepared
+ to handle an error from bfd_som_attach_aux_hdr.
+
+ * config/tc-hppa.h: Wrap ELF specific decls inside an ifdef.
+
+Mon Feb 28 15:03:26 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config/tc-alpha.c (md_atof): Omit warning about FP values.
+ (line_comment_chars): Add ! to list.
+ (md_apply_fix): Do process 32- and 64-bit relocations.
+
+ * config/obj-coffbfd.c (obj_coff_lcomm): Put "#if 0" around the
+ unused parts (most of the function).
+ (obj_coff_init_stab_section): Cast alloca result.
+
+ * configure.in (i960-*-coff, i960-*-vxworks5.*): Use coffbfd, and
+ gas_target ic960coff.
+ * config/ic960coff.mt: New file.
+ * config/obj-coffbfd.h [TC_I960]: Include coff/i960.h.
+ (TARGET_FORMAT) [TC_I960]: Use coff-Intel-little.
+ * config/te-ic960.h (CROSS_COMPILE): Don't undef this. We'll
+ always build little-endian object files.
+ * config/tc-i960.c (md_reloc_size): Don't define at all if BFD or
+ BFD_ASSEMBLER is defined.
+ (mem_fmt): Since COFF doesn't handle callx relocations yet, treat
+ them like normal 32-bit relocations.
+ (md_apply_fix): For callx relocations, store zero.
+ (tc_bout_fix_to_chars): Store symbol index for all callx
+ relocations, regardless of link-relax setting.
+ (tc_coff_fix2rtype, tc_coff_sizemachdep): New functions.
+ (i960_handle_align) [! OBJ_BOUT]: If link-relax option is
+ selected, print an error message and clear it.
+ * config/tc-i960.h (BFD_ARCH, COFF_FLAGS, COFF_MAGIC,
+ TC_COUNT_RELOC, TC_COFF_FIX2RTYPE, TC_COFF_SIZEMACHDEP,
+ tc_fix_adjustable): New macros.
+ (tc_coff_fix2rtype, tc_coff_sizemachdep): Declare.
+
+Fri Feb 25 20:56:57 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (hppa_tc_symbol): Call PA ELF BFD version.
+ (hppa_tc_make_sections): Likewise.
+ (pa_build_symextn_section): Delete unused function.
+ (hppa_tc_make_symextn_section): Likewise.
+ (pa_export): Delete call to pa_build_symextn_section.
+
+ * config/tc-hppa.h (hppa_tc_symbol): Add extern decl.
+ (elf_hppa_final_processing): Delete extern decl.
+ (hppa_tc_symbol): Delete extern decl.
+
+Fri Feb 25 13:15:31 1994 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/obj-coffbfd.c (fill_section): Correct test for whether to
+ fill a section (from Minh Tran-Le <TRANLE@intellicorp.com>).
+
+Thu Feb 24 11:30:26 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * configure.in: Don't require version number for i386-*-mach.
+
+ * read.c (potable): Added ".this_GCC_requires_the_GNU_assembler",
+ which is ignored by gas, but will cause other assemblers to choke.
+ Intended for use by gcc ports that require gas instead of native
+ assemblers.
+
+Thu Feb 24 07:10:31 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/ho-hppaosf.h: Fix braino in test for ANSI-C.
+
+Wed Feb 23 16:51:43 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * write.c (write_contents): Give the user a reasonable error
+ message rather than "assertion failed" if bfd_set_section_contents
+ fails.
+
+Tue Feb 22 10:07:32 1994 Ken Raeburn (raeburn@rtl.cygnus.com)
+
+ * config/ho-mach3.h: New file.
+
+Mon Feb 21 11:41:18 1994 Ian Lance Taylor (ian@cygnus.com)
+
+ * ecoff.c (ecoff_build_debug): Don't set hdr->magic here. It is
+ now set in bfd/ecofflink.c:ecoff_write_symhdr.
+
+ * config/obj-coffbfd.c (write_object_file): use bfd_get_error (),
+ not bfd_error.
+ * config/obj-elf.c (elf_frob_file): Likewise.
+
+ * read.c (s_lcomm): Use an alignment power of 3 for 8 byte .lcomm
+ variables.
+
+ * config/ho-hpux.h (BROKEN_ASSERT): Define if not __GNUC__.
+
+ * read.c (read_a_source_file): Use correct arguments to memcpy
+ (broken 19 Jul 1993). From kjd@pescadero.stanford.edu (Kenneth
+ Duda).
+
+Sun Feb 20 18:01:54 1994 Ian Lance Taylor (ian@lisa.cygnus.com)
+
+ * config/obj-coff.h (obj_coff_section): Declare.
+ * config/obj-coff.c (obj_pseudo_table): For "section", use
+ obj_coff_section.
+ (obj_coff_section): Rewrite.
+
+Fri Feb 18 14:16:32 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * configure.in (i386-*-mach3*): New target; uses BFD.
+ * config/te-mach.h: New file.
+ * config/obj-aout.c (obj_aout_frob_file): New function.
+ * config/obj-aout.h (obj_aout_frob_file): Declare it.
+ (frob_file): New macro.
+ * config/tc-i386.c (md_apply_fix_1) [TE_Mach]: Don't adjust
+ pcrel32 relocations.
+ * config/tc-i386.h (TARGET_FORMAT) [TE_Mach]: Use a.out-mach3.
+
+ * write.c (write_object_file): Removed register declarations.
+
+Thu Feb 17 16:25:18 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ Some support for PowerPC ELF.
+ * configure.in: If cpu is powerpc*, use ppc.
+ (ppc-*-sysv4*): Use object format elf.
+ * config/tc-ppc.h: Only declare a number of things if OBJ_COFF is
+ defined.
+ (TARGET_ARCH): Make it call ppc_arch.
+ (ppc_arch): Declare.
+ (TARGET_FORMAT): Set based on OBJ_COFF or OBJ_ELF.
+ (NO_STRING_ESCAPES): Define.
+ (LOCAL_LABEL, FAKE_LABEL_NAME): Define for OBJ_ELF.
+ * config/tc-ppc.c: Only define a number of functions of OBJ_COFF
+ is defined.
+ (md_pseudo_table): Most pseudo-ops are OBJ_COFF specific. Added
+ OBJ_COFF specific "bi" and "ei".
+ (md_parse_option): Fix handling of -u. Make -m601 set
+ PPC_OPCODE_601. If OBJ_ELF, accept -V and -Q.
+ (ppc_set_cpu): New function.
+ (ppc_arch): New function.
+ (md_begin): Call ppc_set_cpu.
+ (ppc_insert_operand): For a signed operand accept an unsigned
+ value, for IBM compatibility.
+ (ppc_byte): Don't call stringer for strings; instead, treat two
+ double quotes as a single double quote.
+ (ppc_comm): Set sy_tc.output for a .lcomm symbol.
+ (ppc_biei): New function.
+ (ppc_tc): If not OBJ_COFF, ignore first argument.
+ (ppc_fix_adjustable): Call as_bad_where, not as_bad.
+ (ppc_is_toc_sym): New function.
+ (md_apply_fix): Use ppc_is_toc_sym. Handle BFD_RELOC_16 and
+ BFD_RELOC_8.
+
+Thu Feb 17 09:29:37 1994 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ * messages.c (as_perror) [BFD_ASSEMBLER]: Use bfd_get_error and
+ bfd_set_error and new error names.
+
+Tue Feb 15 20:23:20 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * configure.in: Support i960-vxworks versions > 5.0 as coff.
+ Default is still bout if no version is specified.
+
+ * atof-generic.c (atof_generic): Use switch and strcasecmp instead
+ of large number of compares when looking for inf/nan values.
+
+Fri Feb 11 13:13:27 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (macro): Do unaligned loads and stores
+ correctly when big endian, and give errors on overflow rather than
+ generating incorrect code.
+
+Thu Feb 10 11:24:20 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * as.c: Include libiberty.h.
+
+ * read.c (do_align): Don't define label just_record_alignment
+ unless it might be used.
+
+ * as.c (main): If md_parse_long_option is defined, call it with a
+ long option.
+ * config/tc-mips.h (md_parse_long_option): Define.
+ * config/tc-mips.c (mips_trap): New static variable.
+ (md_begin): Report an error if mips_trap is set at ISA level 1.
+ (macro): If mips_trap, use trap instructions instead of break
+ instructions for overflow and divide by zero detection.
+ (mips_parse_long_option): New function. Support --trap,
+ --no-break, --break and --no-trap.
+ * doc/as.texinfo: Document new options.
+
+ * read.c (potable): Add "zero".
+ * config/tc-i386.c (md_pseudo_table): Remove "zero".
+ * config/tc-m88k.c (md_pseudo_table): Likewise.
+
+Thu Feb 10 01:24:27 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config/tc-sparc.c (sparc_ip): Reject integer values for
+ pc-relative operand fields. This forces "call 0" to become "jmpl
+ %g0,%o7" with no relocations needed.
+
+Wed Feb 9 13:08:32 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * as.h (xmalloc, xrealloc): Declare using PTR rather than char *.
+ * xmalloc.c (xmalloc, xrealloc): Use PTR rather than char *.
+
+ * app.c (do_scrub_next_char): If NO_STRING_ESCAPES is defined,
+ don't treat backslash specially inside strings.
+ * read.c (next_char_of_string): Likewise.
+
+Wed Feb 9 09:42:45 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * config/obj-coffbfd.c (obj_coff_init_stab_section): Use memset
+ instead of memcpy to zero the initial stab symbol, duh.
+ * config/obj-elf.c (obj_elf_init_stab_section): Ditto.
+ * config/obj-som.c (obj_som_init_stab_section): Ditto.
+
+Tue Feb 8 17:25:44 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * write.c (fixup_segment): Use as_bad_where, not as_bad.
+
+ * subsegs.c (subseg_set_rest): Call memset with the arguments in
+ the right order. Explicitly clear fix_root and fix_tail fields.
+
+Tue Feb 8 16:00:25 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config/obj-coff.c (coff_frob_symbol): For abs_symbol, set *punt
+ and do nothing else.
+
+ * symbols.c (symbol_begin): Initialize value of abs_symbol
+ properly.
+
+ * write.c (adjust_reloc_syms): Use abs_symbol instead of calling
+ section_symbol.
+
+ * ecoff.c (ecoff_build_debug): Fix "/*" in comment to silence
+ complaint from "gcc -Wall".
+
+ * configure.in (alpha-*-netware*): New target, like alpha-*-osf*.
+
+ * config/tc-alpha.c (GP_ADJUSTMENT): Move definition to start of
+ file.
+ (tc_gen_reloc): Remove uninitialized variable `code', and code
+ that tried to use it (incorrectly). For LITERAL reloc, set addend
+ to negative of GP value.
+ (load_symbol_address): Don't adjust return value by GP_ADJUSTMENT.
+
+ * write.c (write_relocs): Print some sensible error message if
+ bfd_perform_relocation returns bfd_reloc_overflow.
+
+Mon Feb 7 15:49:24 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * configure.in (hppa*-*elf*): New configuration for PA ELF.
+ (hppa*-*-osf*): Default object format is SOM.
+
+Mon Feb 7 16:07:35 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config/tc-alpha.c (md_atof): Warn that floating-point values
+ might not assemble properly.
+
+ * configure.in (target alpha-*-osf*): Don't set "dev=yes" any
+ more.
+
+ * config/tc-alpha.c (load_expression): Parenthesize operations in
+ range checking, to avoid precedence questions.
+
+ * config/tc-alpha.c (addr32): New static variable.
+ (md_parse_option): Set it for "-32addr".
+ (load_symbol_address): If addr32 is set, use ldl instead of ldq.
+
+ * atof-generic.c (atof_generic): Calculate maximum_useful_digits
+ and more_than_enough_bits_for_digits in integer arithmetic, to
+ eliminate the only sources of dependence on floating point
+ support, which doesn't work yet on the Alpha.
+
+Mon Feb 7 03:56:05 1994 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * ecoff.c (ecoff_build_debug) [TC_ALPHA]: Specify version stamp as
+ 0x30b for Alpha for now, until ".verstamp" is handled.
+
+ * literal.c (add_to_literal_pool): Use seginfo->frchainP, which
+ actually refers to the literal pool section, rather than
+ frchain_now, which refers to whatever section the assembler was
+ in.
+
+ * write.c (fixup_segment): Only do range checking if size of fixup
+ is smaller than word size. Otherwise, we always wind up with
+ zeros.
+
+ * config/tc-alpha.c (md_section_align): Change second argument and
+ return type to valueT, to agree with tc.h.
+ (alpha_do_align): Local static array nop_pattern is now unsigned
+ char, to avoid overflow warnings.
+ * config/tc-alpha.h (md_section_align): Delete declaration.
+
+ * config/obj-ecoff.c (ecoff_frob_file): Ensure that ecoff_data for
+ output bfd is non-null before indirecting through it.
+
+ * config/tc-alpha.c (alpha_frob_ecoff_data): Renamed from
+ alpha_frob_file.
+ * config/tc-alpha.h (tc_frob_file): Macro deleted.
+ * config/obj-ecoff.c (ecoff_frob_file) [TC_ALPHA]: Call
+ alpha_frob_ecoff_data, then fill in optional-header info with gp
+ value and register masks.
+
+Sun Feb 6 16:13:47 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * configure.in (hiux): Fixes from m-kasahr@sramhc.sra.co.JP.
+
+ * config/obj-som.c (obj_som_init_stab_section): Same change
+ as coffbfd and elf below. Zero the initial stab symbol after
+ allocating it.
+
+Sat Feb 5 12:30:32 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * config/obj-coffbfd.c (obj_coff_init_stab_section): Zero the
+ initial stab symbol after allocating it.
+ * config/obj-elf.c (obj_elf_init_stab_section): Ditto.
+
+Sat Feb 5 11:53:31 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (pa_ip): addb[tf] should only accept
+ non-negated condition completers. Add support for addb pseudo-op
+ which accepts both negated and non-negated completers.
+
+Sat Feb 5 00:15:49 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * configure.in (rs6000*): Use cpu_type ppc.
+ (ppc-*-aix*): New target; use coff and force bfd_gas.
+ * config/tc-ppc.h, config/tc-ppc.c: New files for PowerPC/POWER
+ (RS/6000) support. At the moment, only XCOFF is supported.
+
+ * config/obj-coff.c (SA_SET_SYM_ENDNDX): Made non-static.
+ (S_SET_DATA_TYPE): Likewise.
+ (coff_last_function): Renamed from local static last_functionP in
+ coff_frob_symbol and made externally visible.
+ (coff_frob_symbol): New local static set_end; use it to try to
+ avoid calling SA_SET_SYM_ENDNDX on a symbol that will be punted.
+ * config/obj-coff.h (S_SET_DATA_TYPE): Declare.
+ (SA_SET_SYM_ENDNDX): Declare.
+ (coff_last_function): Declare.
+
+ * expr.c (operand): If DOLLAR_DOT is defined, accept `$' as
+ equivalent to `.' to mean the current location.
+
+ * read.c (LEX_BR): If not defined, define as 0.
+ (lex_type): Use LEX_BR as the type of `{',`}',`[',`]'.
+
+ * symbols.c (symbol_new): If tc_canonicalize_symbol_name is
+ defined, call it with preserved_copy_of_name. If
+ tc_symbol_new_hook is defined, call it on the new symbol.
+ (symbol_find_base): If tc_canonicalize_symbol_name is defined,
+ call it on a copy of the name argument.
+
+ * write.c (write_object_file): Simplified usage of obj_frob_symbol
+ and tc_frob_symbol. Always call both if the symbol is going to be
+ output.
+
+ * write.c (relax_segment): Use %ld rather than %d when printing
+ fragP->fr_var, and cast it to long.
+
+ Changed relocs to be based on subsegments (when BFD_ASSEMBLER).
+ * subsegs.h (struct frchain): If BFD_ASSEMBLER, added new fields
+ fix_root and fix_tail.
+ (segment_info_type): If BFD_ASSEMBLER, don't define fix_tail
+ field.
+ * write.c (fix_new_internal): If BFD_ASSEMBLER, set fix_rootP and
+ fix_tailP based on frchain_now, not seg_info (now_seg).
+ (chain_frchains_together_1): Chain the subsegment relocs together.
+ * subsegs.c (subseg_change): Don't clear fix_tail field.
+ (subseg_get): Likewise.
+ * literal.c (add_to_literal_pool): Look through the relocs via
+ frchain_now, not seginfo.
+
+Thu Feb 3 23:07:30 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/obj-ecoff.h (TARGET_SYMBOL_FIELDS): Changed
+ ecoff_undefined to ecoff_extern_size.
+ * config/obj-elf.h (ELF_TARGET_SYMBOL_FIELDS): Likewise.
+ * config/tc-mips.c (s_extern): Set ecoff_extern_size to the
+ external symbol size, rathern than setting the symbol value.
+ (md_estimate_size_before_relax): Check both ecoff_extern_size and
+ symbol value to see if GP referencing can be used.
+ * ecoff.c (ecoff_symbol_new_hook): Clear ecoff_extern_size, not
+ ecoff_undefined.
+ (ecoff_frob_symbol): Don't check ecoff_undefined.
+ (ecoff_build_symbols): Get size of an undefined symbol from
+ sym->ecoff_extern_size, not S_GET_VALUE (sym).
+
+Wed Feb 2 13:55:08 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * Makefile.in: Avoid bug in losing hpux sed.
+
+Wed Feb 2 11:40:11 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (file_mips_isa): New static variable.
+ (md_begin): Set it.
+ (s_mipsset): Add support for .set mipN to set the ISA level.
+
+ * gasp.c (kinfo): Fully bracket initializer.
+
+Tue Feb 1 19:28:12 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * gasp.c (malloc): Don't declare, since host.h or system header
+ files may declare it differently.
+
+ * config/atof-ieee.c (int_to_gen): Now static.
+
+ * config/ho-i386aix.h: Include sys/types.h and stdlib.h, not
+ ho-sysv.h. Based loosely on a patch from Minh Tran-Le.
+
+Tue Feb 1 10:50:17 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * gasp.c: Include host.h.
+
+Tue Feb 1 12:13:01 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (mips_ip): Make an unsupported instruction a
+ warning, not an error.
+
+ * config/obj-coff.c (dot_text_symbol, dot_data_symbol,
+ dot_bss_symbol): Don't define if BFD_ASSEMBLER.
+ (obj_symbol_to_chars): bfd_coff_swap_aux_out now takes more
+ arguments.
+ (coff_line_base): Renamed from line_base. Changed all uses.
+ (coff_add_linesym): Renamed from add_line_sym. Made non-static.
+ Changed all uses.
+ * config/obj-coff.h: If TC_PPC, include coff/rs6000.h.
+ (S_SET_STORAGE_CLASS, S_GET_STORAGE_CLASS): Declare if
+ BFD_ASSEMBLER.
+ (coff_line_base): Declare.
+ (coff_add_linesym): Declare if BFD_ASSEMBLER.
+ * config/obj-coffbfd.c (symbol_to_chars): bfd_coff_swap_aux_out
+ now takes more arguments.
+
+Mon Jan 31 17:55:14 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * as.c (statistics_flag): Renamed from quiet_flag.
+ (main): Get statistics with --statistics instead of -noquiet.
+
+Mon Jan 31 07:19:30 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * Makefile.in: Support for Gnu ASsembler Preprocessor.
+ * gasp.c: New file.
+ * read.c (s_lcomm): Align lcomm data.
+ * config/tc-z8k.c (tc_reloc_mangle): Don't allow subtraction
+ from different sections.
+
+Sun Jan 30 14:58:26 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * write.c (write_object_file): If tc_frob_file is defined, call it
+ just before calling obj_frob_file.
+ * config/tc-alpha.c (alpha_gp_value): Renamed from gp_value
+ (references changed), and made non-static.
+ (getExpression): Return void.
+ (select_gp_value): Abort if gp_value is non-zero. Delete call to
+ non-existent bfd_set_gp_value.
+ (alpha_validate_fix): Function deleted.
+ (alpha_frob_symbol): Function deleted.
+ (alpha_local_label): Function deleted.
+ (alpha_frob_file): Renamed from alpha_end.
+ * config/tc-alpha.h (alpha_frob_symbol, alpha_validate_fix,
+ alpha_local_label, alpha_end): Declarations deleted.
+ (alpha_gp_value, alpha_frob_file): Declare.
+ (tc_frob_symbol, TC_VALIDATE_FIX, md_end): Macros deleted.
+ (LOCAL_LABEL): Move code here from tc-alpha.c:alpha_local_label.
+ (md_convert_frag): Simplified slightly.
+ (tc_frob_file): New macro.
+
+ * read.c (do_align): New function, most of guts of s_align_*
+ functions. Look for md_do_align macro, give it a chance to bypass
+ all but recording of section alignment.
+ (s_align_bytes, s_align_ptwo): Call do_align.
+ (s_lcomm) [TC_ALPHA]: Align object to largest power of two that
+ divides object size.
+
+ * frags.c (frag_align_pattern): New function.
+ (frag_align): Rewrite for clarity.
+
+ * config/tc-vax.c (md_assemble): Handle O_constant expression.
+ (vip_begin): Returns pointer to const char. Cast hash_insert arg
+ to PTR to avoid compiler complaints about const.
+ (md_begin): Local variable errtxt must point to const.
+
+ * configure.in: Handle host vax-*-ultrix* like vax-*-bsd*. Don't
+ bother with *-*-ultrix or *-*-sysv*, except *-*-sysv, since only
+ the last has an existing host support file. Do handle vax-bsd and
+ vax-ultrix targets.
+
+Fri Jan 28 11:26:40 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/obj-coff.c (obj_coff_section_header_append): Do not
+ declare if BFD_ASSEMBLER.
+ (stack_pop): Correct test for stack underflow.
+ (obj_coff_endef, obj_coff_dim, obj_coff_line, obj_coff_size,
+ obj_coff_scl, obj_coff_tag, obj_coff_type, obj_coff_val): Declare
+ type of ignored argument to avoid gcc warning.
+ (align): Removed unused function.
+
+Thu Jan 27 18:14:19 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config/tc-alpha.c, config/tc-alpha.h, config/alpha-opcode.h: New
+ files, based on port of gas-1.38 contributed by CMU, using a.out
+ variant. Updated for gas-2.x and ECOFF. Floating-point constants
+ are still broken, bootstrap testing incomplete.
+
+ * literal.c: Comment changes.
+
+ * listing.c (listing_source_file): Check for null listing_tail
+ before indirecting through it.
+
+ * expr.h (struct expressionS): Added struct tag.
+
+ * as.h: If __GNUC__ and inline are both undefined, define inline
+ away.
+
+ * write.c (cvt_frag_to_fill): Don't assume that fr_var for
+ rs_align or rs_org frags will be 1.
+ (relax_segment): For rs_align, if fr_var is not 1, complain if
+ required padding is not a multiple of the size of the pad pattern.
+ (fixup_segment): Leave gp-relative relocations alone. For pcrel
+ relocations referring to the same segment, clear fx_pcrel when
+ clearing fx_addsy.
+ * as.h: Adjust comments on rs_align.
+
+ * atof-generic.c: Some reformatting.
+ (atof_generic): Be careful when mixing signed/unsigned values of
+ different sizes.
+
+ * write.c, config/obj-{aout,bout,coff*}.c, config/tc-sparc.c:
+ Query the fx_done field instead of fx_addsy to see if the fixup
+ still needs to be applied. Set fx_done and clear fx_addsy both,
+ for now. If TC_HANDLES_FX_DONE isn't defined, assume md_apply_fix
+ will only clear fx_addsy, and set fx_done accordingly after
+ returning.
+ * config/tc-sparc.h (TC_HANDLES_FX_DONE): Define.
+ * config/tc-sparc.c (md_apply_fix): Set fx_done for non-pcrel fix
+ with no fx_addsy.
+
+ * symbols.c (dot_text_symbol, dot_data_symbol, dot_bss_symbol):
+ Deleted.
+ (symbol_begin): Moved to end of file, so function inlining can
+ work better.
+ (fb_label_count, fb_label_max): Default C static initializers are
+ sufficient.
+ * symbols.h (dot_text_symbol, dot_data_symbol, dot_bss_symbol):
+ Declarations deleted.
+ * config/obj-coff.c (dot_text_symbol, dot_data_symbol,
+ dot_bss_symbol): Defined here, static.
+
+ * config/obj-aout.c [BFD_ASSEMBLER]: Undef NO_RELOC before
+ including aout/aout64.h.
+
+ * write.c (write_object_file): If EMIT_SECTION_SYMBOLS is false,
+ don't write out a section symbol even if it's used in a
+ relocation; assume relocations will handle section numbers
+ somehow. Rename "punt_it" label to "punt_it_if_unused" to reflect
+ it's true use.
+ (EMIT_SECTION_SYMBOLS): Default to 1.
+ (adjust_reloc_syms): Don't create a new symbol for an absolute
+ reference; just use the absolute section symbol.
+ (write_relocs): Make printout of reloc values dependent on flag
+ DEBUG3, not DEBUG2.
+ * config/obj-aout.h (EMIT_SECTION_SYMBOLS): Define as 0.
+ * config/obj-ecoff.h (EMIT_SECTION_SYMBOLS): Ditto.
+
+Thu Jan 27 16:43:51 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * read.c (lex_type): No longer make '{' a valid character for
+ symbol names.
+
+ * as.c (main): Print long values using %ld.
+
+ * messages.c (as_warn_internal): New static function.
+ (as_warn, 3 versions): Use as_warn_internal.
+ (as_warn_where, 3 versions): New function.
+ * as.h (as_warn_where): Declare.
+
+Tue Jan 25 18:30:34 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * as.c (quiet_flag): New flag.
+ (main): If -noquiet given, display execution time and memory used.
+
+Tue Jan 25 15:53:11 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * doc/{all.texi,as.texinfo}: Add documentation for HPPA port.
+
+Mon Jan 24 19:18:23 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ecoff.c (ecoff_frob_symbol): New function. Put undefined
+ symbols of known size in the undefined section. Put small common
+ symbols in a .scommon section.
+ * ecoff.h (ecoff_frob_symbol): Declare.
+ * config/obj-ecoff.h (obj_frob_symbol): Define.
+ * config/obj-elf.c (obj_elf_write_symbol_p, obj_elf_write_symbol,
+ obj_elf_frob_symbol): Removed unused functions.
+ * config/obj-elf.h (obj_frob_symbol, obj_write_symbol): Removed
+ unused macros.
+ (obj_elf_frob_symbol, obj_elf_write_symbol): Removed declarations
+ of unused functions.
+ (obj_frob_symbol): Define if ECOFF_DEBUGGING.
+
+ * tc-mips.c (g_switch_seen): New static variable.
+ (md_parse_option): Set g_switch_seen for -G option.
+ (s_option): If creating PIC code, force the GP size to be 0. Warn
+ if -G switch used with a non-zero value.
+
+ * symbols.c (S_IS_COMMON): Use bfd_is_com_section rather than
+ comparing against bfd_com_section.
+
+Mon Jan 24 14:12:25 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * read.c (s_lcomm): Treat Alpha like MIPS in handling of .sbss
+ section.
+
+Thu Jan 20 13:17:58 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * expr.c (operand): For floating point operand with unusual fp
+ char from FLT_CHARS, preserve the character. Patch from Lisa
+ Repka.
+
+Wed Jan 19 23:15:24 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (md_pseudo_table): Add all data allocation
+ pseudo-ops: .hword, .int, .long, .octa, .quad, .short, .single.
+
+Tue Jan 18 15:51:59 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * config/obj-coffbfd.c (obj_coff_endef): For C_EFCN, C_BLOCK and
+ C_FCN assume .val has been set to .
+
+Tue Jan 18 16:19:58 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c: Disable multiple $CODE$ subspace code. It
+ confuses GDB for some unknown reason.
+ * cofnig/obj-som.c: Likewise.
+
+Tue Jan 18 19:05:32 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * literal.c (add_to_literal_pool): Handle duplicates of values
+ already written to literal pool.
+
+Tue Jan 18 17:23:52 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/obj-aout.c (obj_aout_frob_symbol): Try to get symbols
+ with explicitly marked stabs through BFD: if a symbol marked
+ N_UNDF | N_EXT is in the absolute section, move it to the
+ undefined section; move a symbol marked N_INDR into
+ bfd_ind_section and set the BSF_INDIRECT flag; set the
+ BSF_WARNING flag for a symbol makred N_WARNING.
+
+Mon Jan 17 15:40:23 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ecoff.h (ecoff_set_gp_prolog_size): Declare.
+ * ecoff.c (ecoff_set_gp_prolog_size): Return type is void.
+
+Mon Jan 17 00:18:55 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (pa_ip): Explicitly check for comma before 'u'
+ and 'f' template operand.
+
+ * config/tc-hppa.c (pa_ip): Handle 'N', 'O', 'o', '0', '1', 'u',
+ and '2' in copr and sfu instruction templates.
+
+Sun Jan 16 16:44:23 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * as.h (subseg_force_new): Add prototype.
+
+Sat Jan 15 09:20:55 1994 Doug Evans (dje@canuck.cygnus.com)
+
+ * app.c (do_scrub_next_char): Allow lines like " foolab :".
+
+ * read.c (emit_expr): Fix computation of mask.
+ * config/obj-elf.c (obj_elf_section): Fix loop termination test.
+
+Thu Jan 13 16:15:15 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * ecoff.c (ecoff_set_gp_prolog_size): New function.
+ (current_file_idx): New static variable.
+ (add_file): Use and increment current_file_idx instead of indx
+ parameter.
+
+ * struc-symbol.h (struct symbol): Make all bitfields unsigned.
+
+ * config/tc-i960.c (i960_validate_fix): Added argument
+ add_symbolPP. Indirect through it to get "add_symbolP".
+ * config/tc-i960.h (i960_validate_fix): Supply prototype.
+ (TC_VALIDATE_FIX): Pass address of add_symbolP.
+
+ * configure.in (i386-*-netbsd*): New target, using te-netbsd.h.
+ (i386-*-netbsd0.8): New target, like 386bsd.
+
+ * configure.in: Set BFDDEF in Makefile to "define" or "undef".
+ * Makefile.in (config.h): Protect against multiple inclusions.
+ Define or undef BFD_ASSEMBLER as specified by $(BFDDEF).
+ (ALL_CFLAGS): Omit $(BFDDEF).
+ * as.h: Include config.h.
+ (struct symbol): Added forward declaration.
+ (add_to_literal_pool): Fix declaration.
+ * as.c: Don't include config.h.
+
+ * literal.c (add_to_literal_pool): Take symbol and addend as
+ arguments, instead of expression, for now. Fix calculation of
+ offset to return.
+
+ * subsegs.h (segment_info_type) [NEED_LITERAL_POOL]: Add field
+ literal_pool_size.
+
+Thu Jan 13 12:14:21 1994 Jeffrey A. Law (law@snake.cs.utah.edu
+
+ * subsegs.c (subseg_get): Accept new argument "force_new". If
+ set then a new segment is always created. All callers changed.
+ (subseg_force_new): New function. Similar to subseg_new, but
+ always force a new segment to be created.
+
+ * config/obj-som.c (som_frob_file): Call adjust_code_sections
+ for each section.
+ (adjust_code_sections): New function. Adjusts the VMA for all the
+ $CODE$ subspaces.
+
+ * config/tc-hppa.c (md_assemble): Also handle creating a fixup
+ for the unwind descriptors if a function's label follows the
+ .PROC and .ENTRY directives.
+ (pa_entry): Don't set BSF_FUNCTION for the label symbol here; it
+ is done elsewhere. Don't create a fixup for the unwind
+ descriptors if the function's label has not been defined yet.
+ (pa_proc): For SOM, place each procedure within a new $CODE$
+ subspace. Adjust the segment and frag for the associated
+ function label if it exists.
+
+Wed Jan 12 22:05:33 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (hppa_fix_struct): Add new "segment" field.
+ (hppa_fix_new): Initialize segment field.
+ (md_apply_fix): Do nothing for pc-relative fixup which involves
+ crossing a segment boundary.
+ (pa_procend): Undefine the current label after handling .PROC
+ and .PROCEND directives.
+ (dummy_symbol): Make type "symbolS *". Change references as
+ appropriate.
+
+Wed Jan 12 13:29:31 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * read.c (read_a_source_file): Cast array argument to unsigned
+ char.
+ * write.c (adjust_reloc_syms): Remove unused variable symseginfo.
+ (write_object_file): Don't define punt_it if it won't be used.
+ (fixup_segment): Don't define skip if it won't be used.
+
+ * config/tc-mips.h (TARGET_FORMAT): Define as mips_target_format.
+ (mips_target_format): Declare.
+ * config/tc-mips.c (mips_target_format): Define with appropriate
+ default definition.
+ (md_parse_option): If -EL or -EB is used, change byte_order and
+ mips_target_format as appropriate.
+
+Tue Jan 11 21:52:36 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * app.c (do_scrub_next_char): Another attempt to fix bugs
+ dealing with labels without colons (for HPPA and MRI).
+
+Tue Jan 11 17:01:06 1994 Doug Evans (dje@canuck.cygnus.com)
+
+ * config/tc-sparc.c (sparc_ip): Truncate args to %hi/%lo to 32 bits.
+
+ * expr.c (integer_constant): Fix computation of too_many_digits.
+ Variable digit_2 renamed to start. Fix check for whether number
+ will fit in 32 bits.
+ * read.c (emit_expr): Use valueT instead of long.
+
+Tue Jan 11 13:01:20 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/obj-elf.c: If TC_MIPS, include elf/mips.h.
+ (special_sections): Define.
+ (obj_elf_special_section): Get default types and attributes from
+ list of special sections.
+ * config/tc-mips.c (ELF_TC_SPECIAL_SECTIONS): Define.
+
+ * config/obj-ecoff.c (ecoff_frob_file): Force .sdata and .sbss
+ sections to be close together.
+
+ * config/tc-mips.c (macro): Corrected $at warnings in a couple of
+ spots.
+
+ * listing.c (listing_prev_line): New function.
+ * listing.c: Include subsegs.h.
+ (listing_prev_line): New function.
+ (calc_hex): Reset byte_in_frag to zero for each new frag.
+ * config/tc-mips.c (append_insn): Call listing_prev_line after
+ emitting nop instructions.
+ * Makefile.in (listing.o): Depends upon subsegs.h.
+
+Mon Jan 10 09:52:23 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (pa_ip): Put check for missing label on .PROC
+ here. Handle case where label may be defined after the .PROC.
+ (pa_proc): It is not an error if the procedure's label isn't
+ defined before the .PROC directive.
+
+Sun Jan 9 04:43:30 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * config/te-netbsd.h: New file.
+ * config/tc-i386.h (TARGET_FORMAT) [TE_NetBSD]: Use bfd target
+ a.out-netbsd-386 for this configuration.
+
+Fri Jan 7 17:38:28 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ecoff.c (ecoff_stab): Don't clobber the ECOFF symbol information
+ with the associated stabs information.
+ (ecoff_build_symbols): Never set the type of stabs symbols to
+ st_Global. Don't update the symbol index or ifd if the gas symbol
+ is not the same as the ECOFF symbol (which is now the case for
+ stabs symbols).
+
+Fri Jan 7 11:14:07 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * config/tc-mips.c (macro): Add a LOSING_COMPILER ifdef that
+ splits the function.
+ (macro2): New function, if LOSING_COMPILER defined.
+
+Fri Jan 7 09:38:25 1994 Steve Chamberlain (sac@cygnus.com)
+
+ * config/obj-coffbfd.c (fill_section): Don't ever fill past the
+ end of a section. (write_object_file): Temporary fix - setup
+ stdoutput.
+
+Thu Jan 6 18:05:21 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config/tc-sparc.c (tc_gen_reloc): Fix handling of addends in
+ non-pcrel_offset relocations.
+
+Thu Jan 6 01:06:40 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (mips_ip): Warn about using $1 as well as $at
+ without .set noat.
+
+Wed Jan 5 14:22:22 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * literal.c: New file.
+ * Makefile.in (REAL_SOURCES, OBJS): List it.
+
+ * as.h (DEBUG): Don't define.
+ (struct expressionS, struct fix): Declare in case they're used in
+ prototypes.
+ (add_to_literal_pool) [BFD_ASSEMBLER]: Declare.
+
+ * config/tc-mips.h (TARGET_FORMAT) [OBJ_AOUT]: Fix for new names
+ in bfd.
+
+ * subsegs.c (subseg_get): New function. Creates segment if
+ needed, returns pointer, but doesn't change current segment.
+ (subseg_new): Use it.
+
+Tue Jan 4 15:12:43 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * Makefile.in (INCLUDES): Add $(srcdir)/.. to places to search.
+ * config/obj-ecoff.c: Include files as "bfd/" instead of "../bfd/".
+ * app.c, flonum.h, hex-value.c (const): Change #if to be more
+ portable.
+
+Tue Jan 4 22:11:34 1994 Rob Savoye (rob@darkstar.cygnus.com)
+
+ * config/ho-vsta.h, configure.in: Add support for VSTa
+ micro-kernel.
+
+Thu Dec 30 15:27:16 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * write.c (write_relocs): bfd_perform_relocation now takes an
+ additional argument, to return an error string (which we ignore).
+
+Wed Dec 29 14:37:26 1993 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * write.h (struct fix): Field tc_fix_data should be type PTR, not
+ void*, for compatibility with non-ANSI compilers. Added
+ single-bit field "fx_done".
+
+Sun Dec 26 14:31:47 1993 Torbjorn Granlund (tege@adder.cygnus.com)
+
+ * tc-hppa.c (pre_defined_registers): Convert to lower case.
+ Delete spurious register names "%r4L", etc.
+ (selector_table): Sort and convert to lower case.
+ (cons_fix_new_hppa): `reloc_type' => `rel_type'.
+ (pa_ip): Always use strcmp for non-text and strcasecmp for text.
+ (reg_name_search): Rewrite to call strcasecmp only once per
+ iteration.
+ (pa_chk_field_selector): Rewrite to use binary search.
+ (pa_parse_neg_add_cmpltr): Use strcasecmp for completer comparisons.
+ (pa_parse_space_stmt): $TEXT$ and $PRIVATE$ are symbols; use case
+ sensitive comparisons.
+ (pa_parse_space_stmt): Canonicalize strncasecmp arg to lower case.
+ (pa_space): "$text$" => "$TEXT$"; "$private$" => "$PRIVATE$". Use
+ case sensitive comparison for all symbolic names.
+ (pa_subspace): Canonicalize strncasecmp arg to lower case.
+ (pa_subspace_start): Use case sensitive comparison for symbolic names.
+
+Mon Dec 20 10:37:48 1993 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * write.c (adjust_reloc_syms) [RELOC_REQUIRES_SYMBOL]: If no
+ symbol is present (i.e., relocation against absolute), create a
+ phony local symbol, and use it in the reloc.
+ (fixup_segment): When adjusting a reloc with an absolute symbol,
+ have TC_FORCE_RELOCATION control clearing add_symbolP too.
+ * config/tc-sparc.h (RELOC_REQUIRES_SYMBOL): Define, for OBJ_COFF.
+
+ * symbols.c (S_IS_EXTERNAL, S_IS_LOCAL): Don't use both BSF_EXPORT
+ and BSF_GLOBAL, since they're the same.
+
+ * as.c (main): Only invoke md_end if it's defined as a macro.
+ * tc.h (md_end): Don't declare it.
+ * config/tc-*.[ch] (md_end): Deleted, in cases where it doesn't do
+ anything.
+ * config/tc-vax.c (vip_end): Deleted null function.
+ * config/tc-mips.c (md_mips_end): Renamed from md_end.
+ * config/tc-mips.h (md_mips_end): Declare.
+ (md_end): New macro, calls md_mips_end.
+
+ * write.c (write_object_file): Don't close output file.
+ * as.c (main): Close output file (if needed) after calling
+ listing_print, which should be after calling write_object_file,
+ which sets the frag addresses.
+
+ * config/obj-coff.c (obj_coff_dim, obj_coff_endef, obj_coff_line,
+ obj_coff_scl, obj_coff_size, obj_coff_tag, obj_coff_type,
+ obj_coff_val): Add unused int argument to satisfy prototypes; goes
+ with Ian's 10 Sep changes.
+ (S_GET_DATA_TYPE, S_SET_DATA_TYPE, S_GET_STORAGE_CLASS,
+ S_SET_STORAGE_CLASS): Now function instead of macros.
+ (obj_emit_lineno) [BFD_ASSEMBLER]: Deleted.
+ (tag_insert): Local var ERROR_STRING is const. Use "const" not
+ "CONST" for argument NAME. Fixed prototype.
+ (coff_frob_symbol): Removed explicit "#if 1" directive. If
+ S_IS_EXTERNAL, set storage class to C_EXT.
+ (s_get_name): Use "const" not "CONST".
+ * config/obj-coff.h (S_GET_DATA_TYPE, S_SET_DATA_TYPE,
+ S_GET_STORAGE_CLASS, S_SET_STORAGE_CLASS): Deleted.
+ (obj_emit_lineno): Declare only for non-BFD_ASSEMBLER. For
+ BFD_ASSEMBLER, define as macro that aborts.
+ (obj_extra_stuff, tc_headers_hook): Declare only for
+ non-BFD_ASSEMBLER.
+ (coff_frob_symbol): Fix prototype.
+
+Sun Dec 19 00:37:20 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/tc-sparc.c (tc_gen_reloc): Test of pcrel_offset had sense
+ reversed.
+
+Thu Dec 16 21:13:11 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (md_begin): Initialize "dummy_label".
+ (tc_gen_reloc, SOM version): For relocations which have no symbol,
+ set sym_ptr_ptr to dummy_label. Avoids lossage in generic BFD code.
+
+Thu Dec 16 16:07:56 1993 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * read.c (lex_type): No longer make '[' a valid character for
+ symbol names.
+
+ * config/tc-vax.c (tc_aout_fix_to_chars): Local variable
+ NBYTES_R_LENGTH now const.
+
+ * config/obj-*.c, config/tc-*.c: Omit superfluous "return"
+ statements at ends of functions. Don't check for null return from
+ hash_new, since it won't return at all if there's no memory
+ available. Also, check for null return from hash_insert, rather
+ than zero-length string, as success indicator.
+
+ * subsegs.c (section_symbol): New function.
+ * subsegs.h (section_symbol): Declare.
+ * write.c (adjust_reloc_syms): Use it.
+
+Wed Dec 15 15:39:53 1993 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * Makefile.in (RUNTEST): New variable.
+ (CHECKFLAGS): Pass it down.
+
+ * ecoff.c (ecoff_directive_frame): Permit extra trailing operands;
+ unused for now, but supplied by Alpha OSF1 compiler.
+
+ * as.h: Protect against multiple inclusions.
+ (int_to_gen): Don't declare.
+
+ * config/atof-vax.c (atof_vax): NULL is not a valid character
+ constant.
+
+Tue Dec 14 21:38:25 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * configure.in (hppa*-*-osf*): Do not consider this a developmental
+ configuration.
+
+ * config/tc-hppa.c (md_apply_fix): Handle cases where no
+ relocation will be emitted for 32bit formats.
+
+Mon Dec 13 23:33:40 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (md_apply_fix): Do not call hppa_field_adjust
+ for any of the 'T' field selectors.
+
+Sat Dec 11 11:23:12 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * config/tc-h8500.c (build_bytes): Get reloc type right for a
+ %page operation. (md_assemble): Don't modify input_line_pointer.
+ (mdcoff_sizemachdep): New function.
+ * config/tc-h8500.h (TC_COFF_SIZEMACHDEP): New macro.
+ * config/tc-z8k.c (get_operand): Delete bogus check.
+
+Wed Dec 8 16:31:51 1993 Ken Raeburn (raeburn@rtl.cygnus.com)
+
+ * write.c (number_to_chars_*): Delete bogus range check.
+
+ * output-file.c (TARGET_ARCH): No default.
+
+Tue Dec 7 16:02:53 1993 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * config/tc-sh.c (md_convert_frag): Truncate disps before calling
+ md_number_to_chars. (md_assemble): Don't modify
+ input_line_pointer.
+
+Mon Dec 6 11:49:03 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * config/tc-h8300.c (md_assemble): Don't update input_line_pointer.
+
+Mon Dec 6 11:20:02 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/obj-som.[ch] (obj_read_begin_hook): Remove last change.
+ Breaks with the HP compilers.
+
+ * config/tc-hppa.c (struct call_info): Remove fields which were
+ set but never used. Remove all code which sets those fields.
+ (struct subspace_dictionary_chain): Likewise.
+ (struct space_dictionary_chain): Likewise.
+ (pa_desc): Delete useless function. Delete all references.
+ (hppa_tc_make_sections): No need to count the number of symbols for
+ the symbol extension section.
+
+Sun Dec 5 17:05:29 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/obj-som.c (obj_som_version): Pass version string to
+ SOM BFD backend.
+ (obj_som_copyright): New function. Much like obj_som_version.
+
+ * config/tc-hppa.c (obj_copyright): Define as appropriate for
+ SOM and ELF.
+ (pa_copyright): Just a stub now.
+
+ * config/obj-som.c (obj_read_begin_hook): Delete unused function.
+ * config/obj-som.h (obj_read_begin_hook): Provide dummy definition.
+ (TARGET_SYMBOL_FIELDS): Delete. SOM isn't making use of them.
+
+ * config/tc-hppa.c (tc_gen_reloc, SOM version): Handle relocation
+ expansion due to rounding mode selectors. Handle R_[RDSN]_MODE
+ relocations for selecting the current rounding mode.
+
+ * config/tc-hppa.c (evaluate_absolute): Support e_rrsel and
+ e_rlsel field selectors.
+
+Fri Dec 3 18:33:24 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/obj-elf.h: If ECOFF_DEBUGGING, undef
+ SEPARATE_STAB_SECTIONS and INIT_STAB_SECTION, and define
+ OBJ_PROCESS_STAB to call ecoff_stab.
+ * config/obj-elf.c: Don't compile obj_elf_init_stab_section if
+ INIT_STAB_SECTION is not defined.
+
+Fri Dec 3 10:56:40 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (md_apply_fix): Delete old wrapper function.
+ (md_apply_fix_1): Rename to md_apply_fix. Fix argument decls.
+ Fix comments in various places. Always return a value.
+ Avoid dereferencing a NULL fx_addsy.
+ (hppa_force_relocation): Avoid dereferencing a NULL fx_addsy.
+
+ Fri Dec 3 09:47:30 1993 Pete Hoogenboom (hoogen@cs.utah.edu)
+
+ * tc-hppa.c: (tc_gen_reloc): Addend for a plabel relocation should
+ be either 0 or 2 (no static link or static link required). Always
+ assume no static link.
+
+Thu Dec 2 11:52:21 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ * config/tc-sparc.c (tc_gen_reloc): Make adjustment to addend be
+ dependent on howto fields, not on format flavour.
+
+ * struc-symbol.h (struct symbol): New fields sy_obj and sy_tc,
+ defined as types OBJ_SYMFIELD_TYPE and TC_SYMFIELD_TYPE, if those
+ macros are defined.
+ * config/obj-coff.h (TC_SYMFIELD_TYPE, OBJ_SYMFIELD_TYPE): Define.
+ (TARGET_SYMBOL_FIELDS, I960_SYM_FIELDS): Don't define.
+ (sy_tc, sy_obj): Define so that the fields look like they used to,
+ until all references get changed.
+
+ * write.c (fixup_segment): Lots of variables no longer register.
+ Reordered some code for easier reading.
+ * config/obj-coff.c (obj_coff_dim): dim_index no longer register.
+ Deleted superfluous return statement.
+ (obj_coff_line, obj_coff_size, obj_coff_scl, obj_coff_type,
+ obj_coff_val, tag_init, tag_insert): Deleted superfluous return
+ statement.
+ (align, obj_coff_section): Deleted debugging printfs.
+ * config/tc-i386.c (md_assemble): Discard some register decls.
+ Use assignment rather than memcpy to copy template.
+ (op_hash, reg_hash, prefix_hash): Default C initialization of
+ statics is sufficient.
+ * config/tc-sparc.c (print_insn): Array Reloc is now const, and
+ points to const.
+
+ * config/obj-coff.h (TARGET_FORMAT): Only use coff-sparc-lynx if
+ TE_LYNX; use coff-sparc otherwise.
+ [USE_NATIVE_HEADERS]: Delete this code; it isn't used.
+
+ * write.c (fixup_segment): Call TC_VALIDATE_FIX, if defined,
+ before processing a fixup. Call TC_ADJUST_RELOC_COUNT just before
+ returning. Remove some i960-coff-specific code.
+ (TC_ADJUST_RELOC_COUNT): Default to doing nothing.
+ * config/tc-i960.h (TC_ADJUST_RELOC_COUNT) [OBJ_COFF]: Define.
+ (i960_validate_fix): Declare.
+ (TC_VALIDATE_FIX): Define.
+ * config/tc-i960.c (i960_validate_fix): New function.
+
+ * write.c (number_to_chars_littleendian): New function. Write out
+ bytes in little endian order, doing size and range checking.
+ (number_to_chars_bigendian): New function, similar.
+ * write.h: Declare them.
+ * config/tc-*.c (md_number_to_chars): Use them.
+ * config/tc-vax.c (md_apply_fix): Ditto.
+ * config/tc-i386.c (md_apply_fix): Ditto.
+
+ * config/obj-coff.c: Rearranged code for handling line number
+ data.
+ (line_fsym): Renamed from function_lineoff in BFD_ASSEMBLER case,
+ since the usage is different from non-BFD_ASSEMBLER case.
+ (in_function, clear_function, set_function): New macros, to
+ combine some of the functionality implemented in differnet ways in
+ BFD_ASSEMBLER and non-... code. Used in other functions that used
+ to check function_lineoff &c.
+ (obj_emit_lineno): Split into two copies, one for BFD_ASSEMBLER,
+ one for not. Non-BFD_ASSEMBLER version now has temporary variable
+ to contain char* pointer pointed to by char** argument. Always
+ follow CROSS_COMPILE code; easier to read that way.
+ (obj_coff_ln): Don't call add_lineno or c_line_new if appline is
+ set.
+ (obj_coff_endef) [BFD_ASSEMBLER]: Don't do anything special for
+ ".bf", it's been done elsewhere.
+ (coff_frob_symbol): If ilne number data is pending, call
+ add_linesym to flush it.
+ (coff_frob_file): Don't do that here.
+ * config/obj-coff.h (coff_frob_file): Declare.
+ (obj_frob_file): Define, to call it.
+
+ * config/tc-sparc.h (md_create_short_jump, md_create_long_jump,
+ md_estimate_size_before_relax: Define them as macros calling
+ as_fatal.
+ * config/tc-sparc.c: Don't define them as functions.
+
+ * configure.in: Handle target alpha-*-osf*. (No cpu files yet.)
+
+Wed Dec 1 23:37:14 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * Makefile (clean): Depend on clean-here.
+
+Wed Dec 1 11:35:21 1993 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config/ho-go32.h: Include fopen-bin.h.
+ * as.h: If FOPEN_WB isn't defined, include fopen-same.h.
+ * output-file.c (output_file_create): Use FOPEN_WB instead of "w".
+ * input-file.c (input_file_open): Use FOPEN_RT instead of "r".
+ * listing.c (file_info): Use FOPEN_RB instead of "rb".
+ * read.c (s_include): Use FOPEN_RT instead of "r".
+
+ * stabs.c: Include obstack.h.
+
+ * tc.h (md_create_long_jump): Don't declare if it's already
+ defined as a macro.
+ (md_create_short_jump, md_estimate_size_before_relax): Ditto.
+
+ * messages.c (as_perror) [BFD_ASSEMBLER]: Use bfd_errmsg instead
+ of strerror. Clear bfd_error.
+
+ * config/te-lynx.h (LOCAL_LABELS_FB): Define, if not already
+ defined.
+
+Wed Dec 1 10:41:56 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (hppa_elf_mark_end_of_function): New function.
+ (pa_process_exit, pa_procend): Call it for ELF objects.
+
+Wed Dec 1 12:10:41 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (macro): Subtract 8 from offset in non PIC l.d
+ case. See comment. From wilson@cygnus.com: for M_L_DAB, set
+ coproc before doing goto ld.
+
+Tue Nov 30 13:40:30 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * write.c (TC_FORCE_RELOCATION): Provide a default definition.
+ (fixup_segment): Allow the target machine to specify that a
+ relocation must be generated for a particular fixup. Remove
+ #ifndef TC_HPPA hack.
+
+ * config/tc-hppa.h (TC_FORCE_RELOCATION): Define.
+
+ * config/tc-hppa.c (md_apply_fix_1): Never change fx_addsy to
+ be NULL. Only fixup_segment is supposed to do that.
+ (hppa_force_relocation): New function.
+
+Tue Nov 30 11:21:41 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * Makefile.in (stabs.o): Added dependencies.
+
+ * config/obj-ecoff.c (ecoff_frob_file): Don't call bfd_set_symtab.
+
+Sun Nov 28 12:11:40 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * app.c (do_scrub_next_char): Output a TAB before any
+ .app* directive.
+
+ * config/tc-hppa.c (fix_new_hppa): Make sure a sub_symbol
+ exists before trying to peek at its name.
+ (pa_space): Do not call pa_align_subseg. See hppa/unsorted/align3.s
+ for testcase.
+ (pa_align_subseg): Delete unused/unwanted function.
+
+Sat Nov 27 22:49:07 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * read.c (read_a_source_file): Fix test for when to stick a colon
+ on the end of a label. Make code conditional on either MRI or
+ LABELS_WITHOUT_COLONS.
+
+ * app.c (do_scrub_next_char): If a line begins with whitespace, leave
+ the single whitespace character alone. Eat all others.
+
+ * config/tc-hppa.h (LABELS_WITHOUT_COLONS): Define.
+
+Wed Nov 24 01:22:54 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (pa_procend): Do not call process_exit.
+ (exit_processing_complete): Delete unwanted variable and all
+ references.
+
+Wed Nov 24 02:31:38 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ecoff.c (ecoff_setup_ext): Renamed from ecoff_build_ext.
+ Changed to not actually build the external symbol information, as
+ that is now done by the ECOFF back end.
+ (ecoff_build_debug): Changed accordingly.
+ * ecoff.h (obj_ecoff_set_ext): Declare. obj-format.c function
+ called by ecoff_setup_ext.
+ * config/obj-ecoff.c (ecoff_frob_file): If debug_info count is 0,
+ set corresponding pointer to NULL. Don't set raw_size and
+ raw_syments.
+ (obj_ecoff_set_sym_index): Removed.
+ (obj_ecoff_set_ext): New function.
+ * config/obj-ecoff.h (obj_set_sym_index): Don't define.
+ (obj_ecoff_set_sym_index): Don't declare.
+ * config/obj-elf.c (obj_ecoff_set_ext, elf_get_extr,
+ elf_set_index): New functions used for ECOFF_DEBUGGING.
+ (elf_frob_file): Reworked ECOFF debug generation to use
+ new functions in bfd/ecofflink.c.
+
+Sun Nov 21 23:54:52 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (pa_def_subspaces): Only create the unwind
+ subspace for ELF. In the SOM world, the linker is responsible
+ for creating the unwind subspaces.
+
+Fri Nov 19 16:25:09 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/obj-coffbfd.c: Use PARAMS rather than EXFUN.
+ (yank_symbols): Don't call S_SET_EXTERNAL if the storage class is
+ already set. Fixes .def var; .val external_var; .scl 3; .endef.
+ (adjust_stab_section): Make static. Declare return type. Remove
+ unused variables.
+
+ * config/tc-i386.h: Declare tc_coff_fix2rtype and
+ tc_coff_sizemachdep.
+
+Fri Nov 19 04:33:59 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * write.c (write_object_file): Disable obj_check_file_symbols
+ hook; only back end using it wasn't using it correctly.
+ (write_object_file): Always call obj_frob_symbol and
+ tc_frob_symbol; always retain symbol if it's used by a relocation,
+ regardless of what these routines indicate.
+ * config/obj-coff.c (coff_frob_symbol): Renamed from
+ coff_check_file_symbols.
+ * config/obj-coff.h (obj_check_file_symbols): Deleted.
+ (coff_frob_symbol): Declare.
+ (obj_frob_symbol): Call it.
+
+ * config/obj-coff.c (obj_crawl_symbol_chain, obj_emit_strings,
+ obj_pre_write_hook): Don't define for BFD_ASSEMBLER.
+ (c_section_header): Ditto. Delete superfluous return at end of
+ function.
+
+ * config/obj-coff.h [TC_SPARC]: Include coff/sparc.h, and specify
+ coff-sparc-lynx.
+ (SA_GET_SYM_TAGNDX): Use BFD_HEADERS version for BFD_ASSEMBLER
+ too.
+ (c_section_header): Rewrite prototype so that it contains no
+ preprocessing directives. Don't declare it at all if
+ BFD_ASSEMBLER.
+
+ * configure.in (sparc*-*-lynxos): New target, using coff and
+ BFD_ASSEMBLER.
+
+ * stabs.c: New file.
+ * Makefile.in (REAL_SOURCES, OBJS): List it.
+ * read.c (STAB_SECTION_NAME, STAB_STRING_SECTION_NAME,
+ get_stab_string_offset, s_stab_generic, s_stab, s_xstab, s_desc):
+ Moved to new file.
+
+ * config/tc-sparc.c (tc_gen_reloc): Handle coff files like elf
+ files.
+
+Wed Nov 17 17:23:53 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * configure.in (mips-*-irix5*): New target. Use elf and mips-big.
+ * config/obj-elf.c: If ECOFF_DEBUGGING, include ecoff.h.
+ (obj_pseudo_table): If ECOFF_DEBUGGING, define ECOFF
+ pseudo-ops.
+ (obj_read_begin_hook): If ECOFF_DEBUGGING, call
+ ecoff_read_begin_hook.
+ (obj_symbol_new_hook): If ECOFF_DEBUGGING, call
+ ecoff_symbol_new_hook.
+ (obj_elf_init_stab_section): Cast alloca result.
+ (elf_frob_file): If ECOFF_DEBUGGING, finish up ECOFF debugging
+ information and write it out into .mdebug section.
+ * config/obj-elf.h (ELF_TARGET_SYMBOL_FIELDS): New macro.
+ (TARGET_SYMBOL_FIELDS): Use ELF_TARGET_SYMBOL_FIELDS.
+ (ECOFF_DEBUGGING): Define if TC_MIPS.
+ (TARGET_SYMBOL_FIELDS): If ECOFF_DEBUGGING, override to add
+ fields required by ECOFF.
+ * config/tc-mips.c: Check ECOFF_DEBUGGING rather than
+ OBJ_ECOFF in many cases.
+ (mips_any_noreorder): New variable.
+ (mips_cprestore_offset): Initialize to -1.
+ (mips_frame_reg): New variable.
+ (RELAX_ENCODE, RELAX_OLD, RELAX_NEW, RELAX_RELOC1,
+ RELAX_RELOC2, RELAX_RELOC3, RELAX_WARN): New macros.
+ (md_pseudo_table): Handle "gpword" and "cpadd".
+ (md_begin): Initialize ok to false. If OBJ_ELF, set alignment
+ of text, data and bss sections to 4. Set alignment of
+ .reginfo section to 2. If ECOFF_DEBUGGING, create .mdebug
+ section.
+ (ALIGN_ERR, ALIGN_ERR2): Removed unused and useless alignment
+ check.
+ (append_insn, macro_build, macro_build_lui): Take place
+ argument. Changed all callers.
+ (append_insn): If appending a nop, don't emit one.
+ (macro_build): Changed assertion for 'i', 'j', 'o' case.
+ (gp_reference): Removed.
+ (load_address): New function.
+ (macro): If mips_noreorder is used, set mips_any_noreorder.
+ Extensive changes to handle GP and PIC symbols differently.
+ Build both possible code choices using a variant frag, and
+ make a final decision at the end of assembly when all
+ information is known. Added PIC support for all symbol
+ references.
+ (mips_ip): Don't permit anything but a number after $ for a
+ coprocessor register. Don't use .lit4 or .lit8 sections when
+ generating PIC code. If OBJ_ELF, set alignment of .lit4 or
+ .lit8 section to 4.
+ (md_apply_fix): Accept and ignore GOT16 and GPREL32 relocs.
+ (s_change_sec): Set alignment of ELF .rodata or .sdata section
+ to 4.
+ (s_mipsset): If .set noreorder, set mips_any_noreorder.
+ (s_cpload): Ignore .cpload if not generating PIC code. Warn
+ if .cpload is not in noreorder section.
+ (s_cprestore): Ignore .cprestore if not generating PIC code.
+ (s_gpword, s_cpadd): New functions.
+ (tc_get_register): Added frame argument; if true, set
+ mips_frame_reg to return value. Changed all callers.
+ (md_estimate_size_before_relax): Don't error out, but instead
+ determine how much a frag should grow.
+ (tc_gen_reloc): Return multiple relocs if appropriate, as
+ determined by md_estimate_size_before_relax.
+ (md_convert_frag): New function.
+ (mips_elf_final_processing): Set ELF header flags based on
+ mips_any_noreorder and mips_pic.
+ * config/tc-mips.h (RELOC_EXPANSION_POSSIBLE): Define.
+ (MAX_RELOC_EXPANSION): Define to be 3.
+ (md_relax_frag): Define to be 0.
+ (md_convert_frag): Don't define.
+ (tc_get_register): Changed declaration.
+
+ * ecoff.h, ecoff.c: New files pulled out of config/obj-ecoff.c to
+ support generating ECOFF debugging information for MIPS ELF
+ targets. Compiled only if ECOFF_DEBUGGING is defined. Changed
+ handling of external symbols: it now always generates exactly
+ those external symbols that are defined in the global symbol list.
+ * Makefile.in (REAL_SOURCES): Added ecoff.c.
+ (REAL_HEADERS): Added ecoff.h.
+ (OBJS): Added ecoff.o.
+ (ecoff.o): New target.
+ * config/obj-ecoff.c: Almost entirely moved into ecoff.c.
+ Remaining code mostly just calls ecoff.c code.
+ * config/obj-ecoff.h: Define ECOFF_DEBUGGING.
+ (TARGET_SYMBOL_FIELDS): Make ecoff_symbol a pointer to a
+ struct localsym.
+ (obj_read_begin_hook, obj_symbol_new_hook): Define to call
+ functions in ecoff.c.
+ (ecoff_stab): Don't declare (now declared in ecoff.h).
+ (obj_set_sym_index): Define.
+ (obj_ecoff_set_sym_index): Declare.
+
+ * frags.h (frag_grow): Declare.
+ * frags.c (frag_grow): Made non-static.
+
+ * write.c (is_dnrange): Do not define if md_relax_frag is defined.
+ (relax_segment): If md_relax_frag is defined, use it to handle a
+ frag of type rs_machine_dependent rather than looking through
+ md_relax_table.
+
+ * read.c (read_a_source_file): If we find a bad pseudo-op,
+ do a continue to go on to the next line rather than a break.
+ Removed duplicate bad pseudo-op code which was never executed.
+
+ * read.c (s_lcomm): Do not require a comma after the name.
+
+ * subsegs.h (segment_info_type): Changed hadone field to bitfield.
+ Added bss bitfield.
+ * as.c (perform_an_assembly_pass): Set bss flag for bss_section.
+ * read.c (s_lcomm): Set bss flag for .sbss section if used.
+ * write.c (relax_and_size_seg): Don't set SEC_HAS_CONTENTS for a
+ bss section. Set SEC_RELOC if there are any relocations, even for
+ a zero size section.
+
+ * write.c (write_relocs): In RELOC_EXPANSION_POSSIBLE case, base
+ data offset on reloc[0]->address rather than reloc[j]->address, so
+ that multiple relocs can affect different memory locations.
+
+ * write.c (chain_frchains_together, relax_and_size_seg,
+ adjust_reloc_syms, write_relocs): Make third argument PTR, not
+ char *, to match definition of bfd_map_over_sections.
+
+ * app.c (do_scrub_next_char): Don't interpret a comment character
+ as starting a CPP line directive unless it is a '#' and is the
+ very first characters on the line (i.e., do not permit leading
+ whitespace).
+
+ * messages.c (identify): Make file argument non-const, to match
+ callers.
+
+Tue Nov 16 20:38:21 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (pa_ip): Fix thinko in 21bit range check.
+
+Sat Nov 13 18:22:48 1993 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * config/tc-sh.c (md_apply_fix): Cope with IMM16 type too.
+ * config/tc-z8k.c (build_bytes, md_apply_fix): Understand nDISP7
+ relocs.
+
+Fri Nov 12 16:51:47 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.[ch]: Fix assorted trivial indention problems.
+ * config/obj-som.c (obj_som_version): Add missing ';'.
+ (som_frob_file): Delete whitespace at EOL.
+
+Fri Nov 12 15:26:21 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ * Makefile.in (VERSION): Updated following 2.2 release.
+
+Fri Nov 12 14:52:17 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (hppa_fix_struct): Use a real type for the
+ field selector, rather than an int. All uses of field selectors
+ fixed.
+ (tc_gen_reloc): For SOM PLABELs, always set addend to zero for now.
+ (md_apply_fix_1): Do not call hppa_field_adjust for any PLABEL
+ field.
+
+ Thu Nov 11 15:49:08 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (pa_type_args): For .import statements,
+ silently ignore attempt to change the symbol type for a function
+ from ST_ENTRY to ST_CODE on .import.
+
+Wed Nov 10 16:19:13 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * write.h (fixS): Rename fx_callj field to fx_tcbit.
+ * write.c, config/obj-coff.c, config/obj-coffbfd.c,
+ config/tc-i960.c: Corresponding changes.
+
+Tue Nov 9 00:49:01 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * Makefile.in (distclean): Delete config-stamp and config.h
+
+ * config/tc-hppa.c (evaluate_absolute): Avoid relying on
+ ANSI-C features.
+
+ * config/tc-hppa.c (pa_type_args): Renamed from pa_export_args.
+ Accept new argument "is_export". All callers changed. When
+ processing a .export directive for a function, do not allow
+ the user to set the type to "CODE", instead warn and set the
+ type to "ENTRY".
+
+Mon Nov 8 12:05:07 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (mips_ip, printInsn): Handle 'k' (from Ted
+ Lemon <mellon@pepper.ncd.com>).
+ (mips_ip): Permit odd numbered floating point registers if -mips3.
+ (macro): Use BFD_RELOC_MIPS_LITERAL relocation for M_LI_SS.
+
+Mon Nov 8 07:45:01 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * configure.in: Remove h8300h, we have multilib now.
+
+Mon Nov 8 06:09:18 1993 D. V. Henkel-Wallace (gumby@cirdan.cygnus.com)
+
+ * configure.in: Support generic netware as being ELF format.
+ Recognise unixware if the user supplies it.
+
+Sun Nov 7 01:02:08 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * First cut at cleaning up PA instruction parsing.
+ * config/tc-hppa.c (pa_get_absolute_expression): Accept pointer to
+ insn structure as an argument, and a pointer to a string. All
+ callers changed. Always read any field selector here. Call
+ evaluate absolute to get a return value.
+ (evaluate_absolute): Addept pointer to insn structure as its
+ argument. All callers changed.
+ (INSERT_FIELD_AND_CONTINUE): New macro for inserting a bitfield
+ into an instruction and continuing the main pa_ip loop.
+ (CHECK_FIELD): New macro for simple range checking of fields.
+ (pa_ip): Delete unused variables. Use INSERT_FIELD_AND_CONTINUE
+ and CHECK_FIELD. All immediate fields now pass through
+ pa_get_absolute_expression which will also handle field selectors.
+ Delete dead code. Simplify.
+ (md_apply_fix_1): Use CHECK_FIELD to verify any fixes that are
+ applied are in range. Use bfd_put_32 rather than inserting each
+ byte of the fixed instrution into the buffer ourselves.
+
+ * write.c (fixup_segment): Delete {SEG,GLOBAL}_DIFF_ALLOWED code,
+ it was PA specific and is no longer needed (it's now handled
+ within the PA backend).
+ * config/tc-hppa.h (SEG_DIFF_ALLOWED): Delete definition.
+ * config/tc-hppa.c (fix_new_hppa): If the subtract symbol for
+ a fixup is $global$ change it to NULL as $global$ is really only
+ needed long enough to determine the base type of relocation to use.
+
+ * config/tc-hppa.c (create_new_subspace): Initialize subspace_defined.
+
+ * config/tc-hppa.c (pa-ip, case 'z'): Make field selectors work
+ for 'z' operands (target of ble branch).
+
+Sat Nov 6 22:41:57 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c: (update_subspace): Fix type and name of last
+ parameter. All callers fixed.
+ (md_begin, pa_chk_field_selector, pa_entry): Lint.
+
+ * config/tc-hppa.c (cons_fix_new_hppa): Reset field selector
+ to default state after it's been used.
+
+Fri Nov 5 12:08:21 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/obj-som.c (obj_som_init_stab_section): Change
+ space/subspace sort keys for the stab sections so as to avoid
+ bugs in the hp linker and pxdb.
+
+Thu Nov 4 17:00:05 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * write.c (chain_frchains_together): Update pointer to last
+ frag for a segment in the seginfo structure.
+
+Thu Nov 04 09:09:35 1993 Jeffrey Wheat (cassidy@cygnus.com)
+
+ * Makefile.in: Changed RUNTESTFLAGS to RUNTEST_FLAGS
+
+Wed Nov 3 12:16:27 1993 Ken Raeburn (raeburn@rover.cygnus.com)
+
+ * write.c (fixup_segment): Handle conversion of subtraction to
+ pc-relative addressing even if pc-relative flag is already set.
+
+ * config/tc-m68k.c (m68k_ip_op): Use strchr, not index. Don't
+ declare either.
+
+ * doc/Makefile.in (distclean): Delete intermediate files from dvi
+ build, but not the dvi or info files.
+ * Makefile.in (clean-here): New target; cleans up current
+ directory only.
+ (distclean): Use it instead of clean.
+
+ * read.c (s_xstab): Don't use alloca.
+
+ * messages.c (identify): New routine; print message identifying
+ following messages as coming from assembler.
+ (as_show_where, as_bad_internal, as_bad_where): Call it.
+ (as_fatal): Don't need to identify program any more.
+
+Tue Nov 2 18:04:11 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-sparc.c (sparc_ip): Add default case to reloc switch.
+
+ * read.c (s_lcomm): Put small objects in .sbss for MIPS ELF as
+ well as MIPS ECOFF.
+ (get_stab_string_offset): Remove unused variable aligned.
+
+Tue Nov 2 15:07:07 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * tc-hppa.c: Add %dp and %rp as synonyms for %r27 and %r2 in the
+ predefined register table.
+ (pa_parse_number): Handle %rp in common register shortcut code.
+ Consistently set return value to -1 for an error. Clean up error
+ messages and only print them when "print_errors" is true. Handle
+ empty string case like the HP assembler -- assume a value of
+ zero.
+
+ * config/ho-hpux.h: Do not include ho-sysv.h. Instead include
+ standard hpux include files to pick up various function decls.
+
+ * config/ho-hppaosf.h: Delete _IO* macros. They are defined in
+ stdio.h. Delete bogus declaration of free. Get path to
+ alloca-conf.h right.
+
+Tue Nov 2 13:57:30 1993 Ken Raeburn (raeburn@rover.cygnus.com)
+
+ * expr.c (operand): Fix checks for characters following "0b" or
+ "0f".
+
+Mon Nov 1 21:37:04 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/obj-som.h (obj_attach_unwind_info): Define as a hook
+ so GAS can attach unwind descriptor information to a BFD symbol.
+ * config/tc-hppa.c (fix_new_hppa): If necessary attach unwind
+ descriptor information to the BFD symbol.
+ (md_apply_fix): R_HPPA_ENTRY and R_HPPA_EXIT can never be "applied",
+ they are simply markers. Make R_HPPA_UNWIND_* handling OBJ_ELF
+ dependent.
+ (pa_build_unwind_subspace): Whole function is OBJ_ELF dependent.
+ (pa_entry): Build a R_HPPA_ENTRY relocation when configured for SOM.
+ (pa_exit): Likewise, but built a R_HPPA_EXIT relocation. Do not
+ build "end-of-function" symbols for SOM, they are not needed.
+
+ * config/tc-hppa.c (process_exit): Create temporary symbols with
+ correct prefixes so they can be eliminated later.
+
+ * config/tc-hppa.c (call_info struct): Delete unused "frame" field.
+ (pa_callinfo): Insert framesize into the unwind information as
+ soon as it's available.
+ (pa_build_unwind_subspace): Do not insert framesize into the unwind
+ information here.
+
+ * Add support for marker type relocations. These mark areas
+ of interest to the linker. ENTRY/EXIT relocations for SOM are
+ an example of marker relocations.
+ * write.c (write_relocs): Instead of assuming size of a relocation
+ is 4 bytes, pick up the size from relocation itself.
+ (fixup_segment): Do not complain that a value is too small for
+ marker relocations.
+
+ * struc-symbol.h: Add new "sy_used" field to the symbol structure.
+ * expr.c (operand): Set sy_used for any symbol used as an operand.
+ (expr): Likewise for any symbol used in an expression.
+ * config/tc-hppa.h (tc_frob_symbol): Define. Punt imported
+ symbols which are never used and absolute symbols which local scope.
+
+ * config/obj-som.h (obj_frob_file): Define.
+ * config/obj-som.c (obj_som_init_stab_section): Set alignment
+ of stab sections. Make space for the special stab entry.
+ (adjust_stab_sections): Adjust the special entry in the
+ stabs section.
+ (som_frob_file): New function. Simply calls adjust_stab_sections
+ for each section.
+
+Mon Nov 1 17:54:29 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (PIC_CALL_REG, SP, FP): Define.
+ (mips_pic, mips_cprestore_offset): New static variables.
+ (md_pseudo_table): Handle .abicalls, .cpload, and .cprestore.
+ Ignore .bgnb and .endb.
+ (gp_reference): _gp_disp is never addressed off GP.
+ (macro_build): Ignore macros while searching for insn. For cases
+ i, j, and o, accept the reloc type as an argument rather than
+ assuming BFD_RELOC_LO16. Don't try to convert BFD_RELOC_LO16 to
+ BFD_RELOC_MIPS_GPREL. Added new case a.
+ (set_at, load_register, macro): Changed calls to macro_build to
+ pass new argument for i, j and o cases.
+ (macro): Handle M_JAL_1, M_JAL_2 and M_JAL_A. These require
+ special handling when generating SVR4 PIC code.
+ (mips_ip, tc_get_register, s_frame): Use macros FP, SP, GP and AT
+ rather than hard coded constants.
+ (md_apply_fix): Handle BFD_RELOC_MIPS_LITERAL and
+ BFD_RELOC_MIPS_CALL16.
+ (s_option): Set mips_pic based on .option picN.
+ (s_abicalls): New function; set mips_pic to 2.
+ (s_cpload): New function; handle .cpload.
+ (s_cprestore): New function; handle .cprestore.
+
+ * config/obj-ecoff.c (obj_pseudo_table): Add entries for .bgnb,
+ .endb and .verstamp, setting them to s_ignore.
+
+Sun Oct 31 00:36:40 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (subspace_dictionary_chain): Add new ssd_defined
+ field. Define SUBSPACE_DEFINED accessor macro.
+ (pa_subspace): Allow user to override subspace attributes for
+ built-in subspaces. Set ssd_defined at the end of fcn -- that
+ way the attributes can only be changed once. Pass newly allocated
+ name to is_defined_subspace, not a pointer to the input line.
+ Fix typo in space/subspace rework.
+ (is_defined_subspace): Delete unused 2nd arg. All callers changed.
+
+ * config/tc-hppa.c (pa_import): If currently in the text segment
+ and a symbol is imported without type information, set BSF_FUNCTION
+ for the symbol.
+ * write.c (relax_and_size_seg): Correct test to determine if
+ the section's size was rounded up.
+
+ * config/obj-som.h (obj_set_symbol_type): Define a hook so GAS
+ can properly set all the SOM symbol types.
+ * config/tc-hppa.c (pa_symbol_type): New enum to represent the
+ symbol types which can be set from an IMPORT/EXPORT statement.
+ (pa_export_args): Set the pa_symbol_type type based on arguments.
+ If defined, call obj_set_symbol_type to pass this information on
+ to the BFD backend.
+
+ * read.c (get_stab_string_offset): Set SEC_DEBUGGING for any
+ stab section we make.
+ (s_stab_generic): Likewise.
+
+Sat Oct 30 14:26:20 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * Allow backends to override the value of the fake label.
+ * write.h (LOCAL_LABEL): Delete DOT_LABEL_PREFIX code. Instead
+ assume backends will define LOCAL_LABEL if anything other than
+ 'L' is used to denote a local label.
+ (FAKE_LABEL_NAME): New macro. Defines the default name used for
+ the "fake" label.
+ * expr.c (make_expr_symbol): Delete DOT_LABEL_PREFIX code
+ and instead simply use the string defined by FAKE_LABEL_NAME.
+ (operand): Likewise.
+ * read.c (s_stab_generic): Likewise.
+ * config/tc-hppa.h (FAKE_LABEL_NAME): Define as L$0\001 so it's
+ known to be a local label.
+ * config/tc-i386.h (DOT_LABEL_PREFIX): Delete.
+ (LOCAL_LABEL, FAKE_LABEL_NAME): Define.
+ * config/tc-m68k.h (DOT_LABEL_PREFIX): Delete.
+ (LOCAL_LABEL, FAKE_LABEL_NAME): Define.
+ * config/te-sco386.h (DOT_LABEL_PREFIX): Delete.
+ (LOCAL_LABEL, FAKE_LABEL_NAME): Define.
+
+ Rework space/subspace handling in PA code to fully support
+ SOM spaces/subspaces.
+ * config/tc-hppa.c (USE_ALIASES): New object-format dependent define
+ to control the use of space/subspace name aliases.
+ (update_subspace): Accept space chain entry for containing space
+ as a new parameter. All callers changed.
+ (pa_get_label): Use current_space rather than pa_segment_to_space.
+ (pa_define_label): Likewise.
+ (pa_undefine_label): Likewise.
+ (md_begin): Change into the (possibly modified) text_section.
+ (pa_parse_space_stmt): Create a new segment/space if create_flag
+ is true, and the space name is not one of the two predefined spaces.
+ (pa_subspace): Use current_space rather than a lookup via
+ pa_segment_to_space. Reset BFD section flags as required by
+ the .subspace directive. Likewise for the section alignment.
+ Pass the current space to update_subspace and create_new_subspace.
+ (pa_spaces_begin): Only use space/subspace aliases if USE_ALIASES
+ is true. When not using aliases, create a BFD section for each
+ subspace encountered. When not using aliases replace the default
+ text, data, and bss segments with new ones.
+ (create_new_subspace): When not using aliases each subspace has a
+ section/segment and subsegments are not needed, so set the subsegment
+ to zero.
+
+ * config/tc-hppa.c (pa_parse_space_stmt): If needed, call
+ obj_set_section_attributes to pass space attributes to the
+ BFD backend.
+ (create_new_space): Likewise.
+ (create_new_subspace): Likewise for subspace attributes using
+ obj_set_subsection_attributes.
+ (update_subspace): Likewise for subspace attributes using
+ obj_set_subsection_attributes.
+
+ * config/tc-hppa.c (pa_parse_space_stmt): Get segment and sort key
+ for $TEXT$ and $PRIVATE$ from the default space structure.
+
+ * config/tc-hppa.c (pa_export_args): Always set BSF_FUNCTION
+ as appropriate for the given type.
+
+ * config/tc-hppa.c (tc_gen_reloc): Preliminary stab at handling
+ SOM relocations.
+
+ * config/tc-hppa.c (pa_comm): Delete incorrect check for symbol
+ redefinition.
+
+ * config/obj-som.[ch]: New files for SOM support. Note SOM
+ support is not yet complete in GAS or BFD.
+
+ * config/ho-hppabsd.h: Delete IO* macros, they are defined in
+ stdio.h. Delete declaration of free. Include stdlib.h, unistd.h,
+ and string.h.
+
+Fri Oct 29 13:26:12 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * Allow backends to override the section names used for embedded
+ stabs support. Needed for SOM.
+ * read.c (STAB_SECTION_NAME): Default the name of the stab section
+ to ".stab".
+ (STAB_STRING_SECTION_NAME): Likewise for the stab strings section.
+ (get_stab_string_offset): Is now passed the full name for the
+ stab string section rather than a name prefix. All references
+ changed.
+ (s_stab_generic): New argument for the stab string section name.
+ all references changed.
+ (s_xstab): Append "str" to the stab section name to get the
+ stab string section name.
+ * config/obj-coffbfd.c (obj_coff_init_stab_section): Append "str"
+ to stab section name to get the stab string section name. Pass
+ the full name of the stab string section to get_stab_string_offset.
+ * config/obj-elf.c (obj_elf_init_stab_section): Likewise.
+
+ * config/tc-hppa.c (md_begin): Disable "-R" option to fold
+ textand data segments. Warn user "-R" is unsupported on the
+ PA.
+
+Thu Oct 28 12:36:13 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/tc-hppa.c (md_pseudo_table): Default alignment is 8 for
+ .align and .ALIGN directives.
+
+ * config/tc-hppa.c (pa_space): Do not report an error for a .space
+ directive which does not define a "well-known" space and does
+ not include a space number as an argument.
+
+ * config/tc-hppa.c (pa_def_subspaces): Correct initialization of the
+ "defined", "loadable", "code_only" and "space_index" fields.
+ (pa_def_spaces): Correct initialization of the "spnum", "defined",
+ and "private" fields.
+
+ * write.h (struct fix): Add new tc_fix_data field for the various
+ backends to attach machine dependent fixup information to.
+ * write.c (fix_new_internal): Initialize new tc_fix_data field.
+ * config/tc-hppa.c (hppa_fix_struct): Delete unnecessary fix_fixP and
+ fx_next fields.
+ (hppa_find_hppa_fix): Delete unnecessary function. Fix all
+ callers to get HPPA fixup information from the tc_fix_data field
+ in the GAS fixup.
+ (hppa_fix_root): Delete unnecessary variable.
+ (fix_new_hppa): Attach HPPA fixup data to the GAS fixup.
+
+ * config/tc-hppa.c (pa_set_start_symbol); Delete unwanted
+ function. Fix all callers.
+ (subspace_dictionary_chain): Delete unused ssd_start_sym field.
+
+ * config/tc-hppa.c (hppa_fix_adjustable): New function to determine
+ if a particular fixup is adjustable.
+ * config/tc-hppa.h (tc_fix_adjustable): Call hppa_fix_adjustable to
+ perform the real work.
+
+ * config/tc-hppa.h (RELOC_EXPANSION_POSSIBLE): Move definition out
+ of OBJ_XXX conditionals.
+ (MAX_RELOC_EXPANSION): Likewise.
+
+ * config/tc-hppa.c (log2): Renamed from is_power_of_2. Fix all
+ callers. Now returns log2 (N) for positive N which are an exact
+ power of two or -1 for an error.
+
+ * config/tc-hppa.c (pa_callinfo): Range check values provided for
+ ENTRY_GR, ENTRY_FR and ENTRY_SR. Properly adjust vaues before
+ inserting them into the unwind table.
+
+ * config/tc-hppa.c (NEEDS_FIXUP): Delete definition and all references.
+ (hppa_gen_reloc_type): New object format dependent macro.
+ (pa_ip): Delete tons of code which was either OBJ_SOM or OBJ_ELF
+ conditional. The code can (and will) be shared between SOM & ELF
+ formats in the near future.
+ (cons_fix_new_hppa, md_apply_fix_1): Likewise.
+ (pa_build_unwind_subspace, process_exit, pa_exit): Likewise.
+ (tc_gen_reloc): Use hppa_gen_reloc rather than an object format
+ specific call.
+
+ * config/tc-hppa.c (pa_comm): Set the segment for a common symbol
+ to bfd_und_section.
+
+ * config/obj-elf.h (obj_elf_version): Add extern prototype.
+
+ * configure.in (hppa-*-bsd*): New configuration.
+ BFD is always used for GAS generating SOM objects.
+
+ * write.c (adjust_reloc_syms): Set sy_used_in_reloc if an
+ adjustment is rejected by the target machine.
+
+ * config/tc-hppa.c (pa_big_cons): Delete function and its
+ declaration. All callers changed to use pa_cons.
+
+ * write.c (fixup_segment): Fix indention and open/close brace
+ problem.
+
+ From Pete Hoogenboom:
+ * config/tc-hppa.c (md_atof): Return a NULL on success rather than
+ an empty string.
+
+ * config/tc-hppa.c (pa_parse_space_stmt): Advance
+ input_line_poitner when an invalid argument is encountered.
+
+Thu Oct 28 13:09:26 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-a29k.c (md_begin): When opcodes are mashed together in
+ the table, require that the one without bit 0x1000000 set come
+ first. Require further that it be case 'b' or 'P'. The a29k
+ opcode table already meets these constraints.
+ (machine_ip): When handling case 'i' or 'A', make sure that the
+ appropriate opcode really exists by looking at the next entry in
+ the opcode table.
+
+Wed Oct 27 11:48:56 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-m68k.c (m68k_ip): Adjust offsets for PC relative
+ fixups. Add 6 for long 7.3 case, 2 for short 7.2 case.
+
+ * config/obj-ecoff.c (obj_ecoff_ent): Ignore an optional number
+ after a .ent directive.
+
+ * config/tc-mips.c (mips_ip): Handle '>' case (shift amount
+ between 32 and 63 for double shift instruction). Do & 0x1f rather
+ than % 32.
+ (printInsn): Handle '>'.
+
+Tue Oct 26 16:58:36 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-ns32k.c (tc_aout_fix_to_chars): Output the symbol
+ number in the right place. Untested. Probably does not work for
+ cross assembly. From cagney@cs.adelaide.edu.au (Andrew Cagney).
+
+ * config/tc-m68k.c (md_apply_fix_2): Error if a short branch uses
+ an illegal offset of 0 or -1.
+
+ * config/obj-elf.c (obj_elf_init_stab_section): Align .stab
+ section to a longword boundary.
+
+Tue Oct 26 10:24:31 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ * Makefile.in (CHECKFLAGS): Pass down RUNTESTFLAGS.
+
+ From Jeff Law:
+ * config/tc-hppa.c (tc_gen_reloc): ELF32_HPPA_R_ADDEND ->
+ HPPA_R_ADDEND.
+
+Mon Oct 25 14:06:17 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-sparc.c (sparc_ip): Fix up membar argument handling.
+
+Mon Oct 25 11:17:58 1993 Steve Chamberlain (sac@phydeaux.cygnus.com)
+
+ * config/tc-sh.c (build_Mbytes): Write the relocs to the correct
+ address. (md_assemble): Make error handling a bit more graceful.
+ (md_apply_fix): Don't warn on non aligned displacement.
+
+ * config/tc-z8k.c (get_specific, built_bytes): Understand all the
+ aspects of lda.
+
+Mon Oct 25 10:20:31 1993 Ken Raeburn (raeburn@rover.cygnus.com)
+
+ * doc/Makefile.in (install-info): Use "$<*" so VPATH will find
+ as.info* even if they're in $(srcdir) (e.g., for FSF
+ distributions).
+
+ * write.c (write_relocs): For relocs that are pc_relative and
+ pcrel_offset and not partial_inplace, adjust reloc->addend to
+ compensate for a bfd_perform_relocation bug.
+
+ * config/tc-sparc.h: Removed remaining non-BFD_ASSEMBLER code.
+ * config/tc-sparc.c: Ditto.
+ (tc_gen_reloc): Include fx_offset for pcrel fixups.
+
+Sun Oct 24 16:49:00 1993 Jim Wilson (wilson@x1.cygnus.com)
+
+ * tc-mips.c (md_pseudo_table): Add dword pseudo op.
+
+Fri Oct 22 20:40:56 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * messages.c: replaced all variables called Format with 'format',
+ for consistency throughout
+
+ * configure.in: handle mips*- instead of mips, mips*el for little
+ endian configurations
+
+Fri Oct 22 14:45:49 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * input-scrub.c (physical_input_file, logical_input_file,
+ physical_input_line, logical_input_line): Made static.
+ (as_where): Return current file name and line number, don't print
+ them out.
+ * messages.c (as_show_where): New static function. Other
+ functions use it instead of as_where.
+ (as_bad_internal): New static function.
+ (as_bad): Use as_bad_internal.
+ (as_bad_where): New function, like as_bad but taking a file name
+ and line number.
+ * as.h (as_bad_where): Declare.
+ (as_where): Change prototype for new arguments.
+ * write.h (fixS): Added fields fx_file and fx_line.
+ * write.c (fix_new_internal): Save file and line number in fix.
+ (fixup_segment): Use as_bad_where, not as_bad.
+ * input-file.c (f_in, file_name): Made static.
+ * cond.c (struct file_line): Just use file and line fields.
+ (s_else): Use as_where and as_bad_where, not get_file_line and
+ set_file_line.
+ (get_file_line, set_file_line): Removed.
+ * listing.c (listing_newline): Use as_where.
+ * config/obj-coffbfd.c (obj_coff_init_stab_section): Use as_where.
+ * config/obj-ecoff.c (add_file): Use as_where.
+ * config/obj-elf.c (obj_elf_init_stab_section): Use as_where.
+ * config/tc-m68k.c (md_apply_fix_2): Use as_bad_where.
+ * config/tc-mips.c (tc_gen_reloc): Use as_bad_where, not assert.
+
+Thu Oct 21 12:52:01 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ * config/tc-m68k.h: Don't define REGISTER_PREFIX or
+ OPTIONAL_REGISTER_PREFIX if either is already defined.
+
+ * config/tc-m68k.c (m68k_ip): Delete some code in "#if 0".
+
+ * configure.in: Set bfd_gas for all sparc targets. Added facility
+ for keeping or rejecting configurations still under development;
+ default is to assume production environment, and reject configs
+ still being worked on. Mark Elf configurations (except sparc and
+ i386) as developmental. Deleted cases matching some generic names
+ in favor of more specific names. (E.g., when we get Alpha
+ support, we'll still only support VMS for Vax.)
+
+ * config/tc-sparc.h (md_end): New macro.
+ * config/tc-sparc.c (md_end): Function deleted.
+ (BFD_RELOC_*): Delete macros that used to help keep the non-bfd
+ version compiling. All sparc targets will use bfd now.
+ * tc.h (md_end): Don't declare if it's defined as a macro.
+
+ Changes from Jeff Law and Peter Hoogenboom:
+
+ * read.c (next_char_of_string): Limit octal character constants to
+ three digits.
+
+ * config/tc-hppa.h: Major cleanup. Use GNU-style comments. Warn
+ against placing additional object-file dependent code here. Warn
+ against contaminating all of GAS with the internals of tc-hppa.c
+ through inclusion of tc-hppa.h. Delete all forward declarations
+ for functions only used within tc-hppa.c, likewise for structures,
+ variables, and #defines. Try to group OBJ_ELF and OBJ_SOM
+ conditional code in a few small places.
+
+ * config/tc-hppa.c: Major cleanup. Use GNU-style comments. Group
+ structures, global variables, forward declarations together.
+ Reduce (or in some cases eliminate) OBJ_ELF and OBJ_SOM
+ conditional code -- try to group conditional code together
+ into a few places. Make all functions and variables which
+ are only used within tc-hppa.c static. PARAMize all functions.
+ Add comments to functions. Delete unused functions, variables,
+ #defines, etc. Delete unused members within structures. Delete
+ ldil;ble hacks -- it is believed they were installed to work
+ around old gas bugs. Avoid using mixed case for local
+ functions, variables, and structures. Fix formatting problems
+ not found by GNU-indent. Add FIXME notices for things which
+ should be worked on the near future. Delete lots of old
+ useless (1.36 PA-SOM) code.
+
+ * config/tc-hppa.c: (fix_new_hppa): Initialize the fx_r_type
+ field of the fixS structure. Needed to build unwind
+ descriptors correctly.
+
+ * write.c: (fixup_segment): Allow expressions such as
+ sym1-sym2+const as long as sym2 is $global$.
+
+ * write.c (adjust_reloc_syms): Provide a hook so that a target
+ cpu configuration can reject certain relocation reductions.
+ * tc-hppa.h (tc_fix_adjustable): New macro. Only accept relocations
+ which do not involve function symbols.
+
+ * config/tc-hppa.h: Reindent with GNU-indent. Delete references
+ to OBJ_OSFROSE. Fix typos (OBJ_SOME -> OBJ_SOM). Delete unused
+ STAB_FIXUP macro.
+ * config/tc-hppa.c: Likewise.
+
+ * config/tc-hppa.c (md_apply_fix_1): Use elf_symbol_type, instead
+ of elf32_symbol_type.
+ (pa_export_args): Likewise.
+ (elf_hppa_final_processing): Likewise.
+ (pa_desc): Do not call obj_elf_desc. (Is pa_desc even needed
+ anymore?)
+ (hppa_tc_make_sections): Do not declare elf_get_symtab_map any
+ ore.
+
+ * config/tc-hppa.c: (md_section_align): Align all sections to
+ a multiple of the section alignment rather than always a
+ multiple of 8.
+
+ * config/tc-hppa.c (hppa_tc_symbol): If the argument relocation
+ bits are zero (eg they specify no relocations), then do not even
+ bother adding their entries to thesymextn section.
+
+Thu Oct 21 15:44:55 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-sparc.c (md_parse_option): Accept and ignore -sparc
+ option, which is used by the SunOS make default .s.o rule.
+
+Wed Oct 20 12:26:33 1993 Ken Raeburn (raeburn@rover.cygnus.com)
+
+ * config/tc-sparc.c (sparc_ip, label "immediate"): Convert relocs
+ operating on upper 32 bits of immediate constants to lower-half
+ relocs with adjusted constants.
+
+Tue Oct 19 18:13:26 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-m68k.h (AOUT_MACHTYPE): Define to be external variable
+ m68k_aout_machtype.
+ * config/tc-m68k.c (omagic): Remove obsolete and unused variable.
+ (m68k_aout_machtype): New variable, if OBJ_AOUT.
+ (md_assemble): Initialize m68k_aout_machtype based on
+ current_architecture, if OBJ_AOUT.
+ (md_parse_option): Remove obsolete reference to omagic.
+
+Thu Oct 14 16:51:00 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (md_pseudo_table): Ignore .livereg pseudo-op.
+ (s_option): Ignore .option O* and .option pic*.
+ (s_ent): Skip whitespace between symbol and optional digit.
+ (my_getSmallExpression): Handle ($xx) correctly: assume 0($xx).
+
+ * app.c (do_scrub_next_char): Always accept 'x' and 'X' as escape
+ characters in state 6.
+ * read.c (next_char_of_string): Accept \Xh* and \xh* where h* are
+ hexidecimal digits.
+
+ * config/tc-i386.c (md_apply_fix_1): Make cross segment calls work
+ for ELF by hacking around bizarre bfd_perform_relocation behaviour
+ that I don't dare change.
+
+Thu Oct 14 11:33:25 1993 Michael Meissner (meissner@osf.org)
+
+ * config/tc-i386.c: (md_begin): Do not zero static arrays. Don't
+ call strchr for each character to see if it is a special char,
+ instead add a second loop over special_chars. Set alignment
+ of text, data and bss sections to 4.
+ (pi, te, pt, pe, ps): Add declarations so that DEBUG386 can be
+ used again.
+ (reloc): Don't return 8 and 16 bit non-PC relative relocations on
+ ELF, since the ELF object format does not have these type of
+ relocations. Change the abort into as as_bad and return
+ BFD_RELOC_NONE to silence compiler warnings.
+ (md_assemble): Keep track of the instruction size. Allow white
+ space between the $ and the constant for compatibility with older
+ gases and other assemblers.
+ (i386_operand): Skip spaces between $ and expression.
+ (tc_gen_reloc): Don't allow anything but 32 bit relocations on
+ ELF. Convert abort into an as_bad and assert into as_fatal.
+
+Wed Oct 13 16:50:55 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/obj-coffbfd.c (fixup_segment) [DIFF_EXPR_OK]: If
+ sub_symbolP is in the current segment, convert to a PC-relative
+ fixup and discard the symbol.
+
+Wed Oct 13 14:00:02 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/obj-ecoff.c (ecoff_build_symbols): Handle st_End symbol
+ for st_StaticProc just like st_Proc.
+
+ * write.c (relax_and_size_all_segments): Moved #endif for OBJ_BOUT
+ so that OBJ_BOUT doesn't forget to adjust all the fragments in the
+ .bss section.
+
+Tue Oct 12 17:26:15 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c: If OBJ_ELF, include elf/mips.h.
+ (mips_regmask_frag): New static variable, if OBJ_ELF.
+ (md_begin): If OBJ_ELF, create .reginfo section and set
+ mips_regmask_frag to a frag.
+ (mips_elf_final_processing): New function, if OBJ_ELF. Set
+ mips_regmask_frag to register mask information.
+ * config/tc-mips.h (elf_tc_final_processing): New macro, defined
+ if OBJ_ELF.
+
+Tue Oct 12 03:33:26 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * messages.c (as_fatal): Use myname when printing messages.
+
+ * config/tc-i960.c (md_begin): Use null pointer, not empty string,
+ as initial "return" value in case hashing isn't needed.
+
+ * config/tc-a29k.c (md_atof): Return null, not empty string, on
+ success.
+ * config/tc-h8300.c (md_atof), config/tc-h8500.c (md_atof),
+ config/tc-hppa.c (md_atof), config/tc-i860.c (md_atof),
+ config/tc-i960.c (md_atof), config/tc-m88k.c (md_atof),
+ config/tc-ns32k.c (md_atof), config/tc-sh.c (md_atof): Ditto.
+
+Mon Oct 11 16:46:31 1993 Steve Chamberlain (sac@phydeaux.cygnus.com)
+
+ fix for pr 3571
+ * config/tc-h8300.c (get_specific): Special action if 8 bit
+ address seen. (check_operand): Don't complain if truncating top
+ bits of an 8 bit address. (build_bytes): Allow an immediate and
+ an absolute in the same insn.
+
+Mon Oct 11 17:18:51 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * write.c (write_contents): Don't crash if seginfo is NULL.
+
+ * config/obj-ecoff.c (ecoff_frob_file): Write out register masks
+ by modifying .reginfo section, not by directly modifying BFD
+ backend data.
+
+Mon Oct 11 14:11:32 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * config/ho-sunos.h: remove extern time declaration
+
+Mon Oct 11 16:14:43 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * messages.c (as_fatal): Do mention that it's the assembler that
+ got the fatal error.
+
+Fri Oct 8 14:09:35 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (mips_gprmask, mips_cprmask): New variables to
+ hold register masks.
+ (md_begin): Initialize them to zero.
+ (append_insn): Update mips_gprmask and mips_cprmask. Also add
+ register variables pinfo and prev_pinfo.
+ * config/tc-mips.h (mips_gprmask, mips_cprmask): Declare.
+ * config/obj-ecoff.c (ecoff_frob_file): If TC_MIPS, set gprmask
+ and cprmask from mips_gprmask and mips_cprmask.
+
+ * config/tc-mips.h: Define TARGET_FORMAT if OBJ_ELF.
+ * config/tc-mips.c (GPOPT): Define if OBJ_ECOFF or OBJ_ELF.
+ (various): Change all references to GP references to apply if
+ GPOPT, not if OBJ_ECOFF.
+ (s_change_sec): Rearrange somewhat. If OBJ_ELF, use .rodata
+ instead of .rdata. If OBJ_ELF, set section flags for .rodata and
+ .sdata sections.
+ (s_frame, s_loc, s_mask): Comment out entire functions, rather
+ than just body. They're not used anyhow.
+ * configure.in: Set cpu_type to mips for mips*. Accept
+ mips-*-elfl* and mips-*-elf*.
+
+Thu Oct 7 18:36:29 1993 Michael Meissner (meissner@osf.org)
+
+ * config/obj-elf.c (obj_elf_common): Allow the alignment field to
+ not be specified.
+
+Wed Oct 6 13:01:34 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (cons_fix_new_mips): New function. Turn
+ BFD_RELOC_64 into BFD_RELOC_32.
+ * config/tc-mips.h (TC_CONS_FIX_NEW): Define.
+ (cons_fix_new_mips): Declare.
+
+ Changes to let cons handle bignums like general expressions.
+ * expr.h (expressionS): New field X_unsigned.
+ * expr.c (operand): Initialize X_unsigned to 1. Set it to 0 for
+ unary minus case.
+ (expr) Fix typo resultP to right if missing operand. Set
+ X_unsigned to 1 when building new expression.
+ * read.c (potable): Make "octa" and "quad" call cons, not
+ big_cons.
+ (cons): Handle bignums. If given an O_constant (small integer) to
+ fill a big space, turn it into a bignum.
+ (parse_bitfield_cons): Set X_unsigned field.
+ (bignum_low, bignum_limit, bignum_high, grow_bignum, big_cons):
+ Removed.
+ * read.h (big_cons): Remove prototype.
+ * symbols.c (resolve_symbol_value): Don't give a warning if a
+ symbol in expr_section can not be resolved.
+ (S_SET_VALUE): Clear X_unsigned.
+ * write.c (write_object_file): If resolve_symbol_value failed on a
+ symbol we are writing out, give a warning.
+ * config/tc-h8500.c (parse_reglist): Set X_unsigned.
+ * config/tc-hppa.c (md_pseudo_table): Change "octa" and "quad" to
+ call pa_cons, not pa_big_cons.
+ (pa_big_cons): Remove.
+ * config/tc-hppa.h (pa_big_cons): Remove declaration.
+ * config/tc-i960.c (md_pseudo_table): Change "quad" to call cons,
+ not big_cons.
+
+Tue Oct 5 10:53:36 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * doc/as.texinfo (Copying): new node, to handle the recent changes
+ in the texinfo/gpl.texinfo file
+
+Mon Oct 4 17:10:15 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * read.c (big_cons): Handle "0" correctly.
+
+ * config/tc-mips.c (md_begin): Set target_big_endian correctly.
+
+Mon Oct 4 15:37:57 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/tc-m68k.c (m68k_ip): Mode 7.3 operand using PC should
+ have pc-relative fixup.
+ (md_parse_option): Move "-k" case down near "-pic" case.
+
+ * configure.in: Alphabetize list of cpu type alternatives. Enable
+ OS values of "linux*elf*" and "linux*coff*" to select those
+ formats, with linux emulation. Don't bother checking for upper-
+ or mixed-case versions of "ose".
+
+Thu Sep 30 11:05:35 1993 Steve Chamberlain (sac@phydeaux.cygnus.com)
+
+ * config/z8k.c (md_pseudo_table): add "unseg".
+
+Wed Sep 29 16:15:11 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * config/m88k-opcode.h (m88k_opcodes): correct a few mistakes
+ found while extending the dissassembler.
+
+Tue Sep 28 12:02:04 1993 Stan Shebs (shebs@rtl.cygnus.com)
+
+ * configure.in: Split i386 LynxOS out from other coff targets,
+ add a specific Lynx emulation.
+ Add m68k LynxOS target.
+ * config/tc-i386.c: Define specific Lynx target format.
+ * config/tc-m68k.c: Define specific Lynx target format.
+ * config/te-lynx.h: New file.
+
+ * config/obj-coffbfd.h: Don't set TARGET_FORMAT to be
+ "coff-{i386,m68k}" if TARGET_FORMAT already defined.
+ (INIT_STAB_SECTION): Define.
+ * config/obj-coffbfd.c: Include <time.h>.
+ (write_object_file): Look for .stab sections and call
+ adjust_stab_section.
+ (adjust_stab_section): New function, fills in the first symbol
+ of a stab section with number of symbols and string table size.
+ (obj_coff_init_stab_section): New function, creates the initial
+ symbol for a stab section.
+
+Mon Sep 27 15:21:55 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/atof-vax.c (md_atof): Return null on success instead of
+ empty string.
+ * config/atof-tahoe.c (md_atof): Ditto.
+ * read.c (float_cons): Expect a null pointer for success, not an
+ empty string.
+
+ * hash.c (hash_insert, hash_jam, hash_grow): Return null pointer
+ on success, instead of empty string. All callers changed.
+
+ * config/tc-vax.c: Use PARAMS in declarations.
+ (vip_op): Use NULL instead of empty string for success in error
+ and warning fields.
+
+Sun Sep 26 23:45:29 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * expr.c (expr) [DIFF_EXPR_OK]: Permit subtraction of two symbols
+ in different defined segments.
+
+ * write.c (relax_segment): Localize "aim" variable. If
+ DIFF_EXPR_OK, don't impose checks on symbol segment types.
+ (fixup_segment) [DIFF_EXPR_OK]: If sub_symbolP is in the current
+ segment, convert to a PC-relative fixup and discard the symbol.
+
+ * config/tc-m68k.c (flag_want_pic): New variable, mostly ignored.
+ (md_parse_option) [TE_SUN3]: Set it for "-k".
+ (m68k_ip): Generate proper fixup for mode 7.3.
+ * config/tc-m68k.h (DIFF_EXPR_OK): Define.
+
+Sat Sep 25 05:08:19 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/tc-m68k.c (struct m68k_incant, getone, gettwo): Moved
+ earlier in the file.
+ (insop, add_exp): Now defined as functions, for readability.
+ (insop): Now takes two arguments; callers changed.
+
+Fri Sep 24 12:37:59 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * config/tc-m88k.c (get_o6): new function.
+ (get_bf, get_cmp, get_cnd, get_cr, get_fcr, get_imm16, get_reg,
+ get_vec9, getval, get_pcr, calcop, match_name): make static and
+ prototype.
+ (s_file): remove extraneous forward decl.
+ (md_begin): add const to retval decl.
+ (calcop): cope with instructions without arguments. Handle 'o'
+ type argument, the o6 field of the prot insn.
+ (md_estimate_size_before_relax): return a dummy value.
+
+ * config/m88k-opcode.h (m88k_opcodes): comment change; o6 field is
+ in bits 10 through 7. flt.[dxs]s requires an r register in the
+ second argument. New instruction lda.x. New instruction muls
+ (alias for mul).
+
+Fri Sep 24 13:43:30 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * Makefile.in (distclean): Recurse like clean.
+ * doc/Makefile.in (distclean): New target.
+
+ * config/tc-mips.c (md_begin): Set BFD architecture and machine
+ based on MIPS ISA level.
+
+Thu Sep 23 17:58:58 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * as.c (main): "exhausted", not "exhuasted".
+
+ * struc-symbol.h (struct symbol): Add sy_used_in_reloc field.
+ * write.c (adjust_reloc_syms): Set sy_used_in_reloc.
+ (write_object_file): Never strip symbols with sy_used_in_reloc
+ set.
+
+ * config/obj-elf.c (obj_elf_section): Rewrote to handle both
+ Solaris and SVR4 style .section pseudo-ops.
+ (obj_elf_ident): Set SEC_READONLY for .comment section.
+ * config/tc-sparc.c (md_apply_fix): If this is ELF, and we're
+ generating a reloc, don't apply a fix.
+
+Thu Sep 23 13:16:58 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/obj-coffbfd.c (relax_align): Now static.
+
+Mon Sep 20 19:23:35 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * read.c (get_stab_string_offset): Make non-static. Make
+ arguments const. Don't align strings to 4 byte boundaries.
+ * read.h: Declare get_stab_string_offset.
+ * config/obj-elf.c (obj_elf_section): Set SEC_ALLOC as well as
+ SEC_LOAD for progbits section.
+ (obj_elf_init_stab_section): New function.
+ (adjust_stab_sections): Add casts to avoid warnings.
+ * config/obj-elf.h (INIT_STAB_SECTION): Call
+ obj_elf_init_stab_section.
+ (OBJ_PROCESS_STAB): Removed definition.
+
+Fri Sep 17 18:12:34 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/obj-elf.h (S_GET_SIZE): Define.
+ (obj_frob_forward_symbol): Define.
+ * config/tc-i386.c (line_comment_chars): Initialize in all cases.
+
+Thu Sep 16 14:23:08 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * tc.h: Declare tc_gen_reloc differently depending upon
+ RELOC_EXPANSION_POSSIBLE.
+ * config/obj-elf.c (obj_elf_section): Only set flags when first
+ creating the section.
+
+Wed Sep 15 12:15:53 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (append_insn): Don't swap a trap instruction
+ with a branch.
+
+Tue Sep 14 13:31:04 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/obj-elf.c (obj_elf_data, obj_elf_text): New functions;
+ set previous_section and previous_subsection and then call s_data
+ and s_text, respectively.
+ (obj_pseudo_table): Add data and text.
+ (obj_elf_section): Add SEC_LOAD to default initialization of
+ flags. Treat .rodata1 like .rodata. Set SEC_LOAD as well as
+ SEC_ALLOC for "alloc" string. Don't bother trying to find the
+ section; just use subseg_new.
+
+ * read.c (change_to_section): Removed. This is now done by
+ subseg_new.
+ (get_stab_string_offset): Rearranged somewhat. Create the section
+ using subseg_new. Store the string index in seg_info, rather than
+ in a static variable. Force the first string to be empty. Use
+ frag_more rather than FRAG_APPEND_1_CHAR.
+ (s_stab_generic): Rewrote.
+ * subsegs.h (segment_info_type): Added stabu union.
+ * subsegs.c (subseg_new): Initialize stab_string_size to 0.
+ * config/obj-aout.c: Don't include aout/stab_gnu.h.
+ (obj_aout_stab, obj_aout_desc): Removed.
+ (obj_pseudo_table): Removed desc and stabX entries.
+ * config/obj-bout.c: Same changes as config/obj-aout.c.
+ * config/obj-bout.h (S_SET_TYPE): Define.
+ (tc_bout_fix_to_chars): Declare.
+ * config/obj-coff.c (obj_coff_stab): Removed.
+ (obj_pseudo_table): Removed desc and stabX entries.
+ * config/obj-coff.h (SEPARATE_STAB_SECTIONS): Define.
+ * config/obj-coffbfd.c (current_stab_symbol): Removed.
+ * config/obj-coffbfd.h (obj_symbol_type): Removed n_strx, n_type,
+ n_other, n_desc and n_value fields.
+ (S_{S,G}ET_{OFFSET,OTHER,TYPE,DESC}): Removed.
+ (MAKE_STAB_SYMBOL): Removed.
+ * config/obj-ecoff.c (obj_ecoff_stab): Renamed to ecoff_stab.
+ Changed arguments and removed parsing code.
+ (obj_pseudo_table): Removed stabX entries.
+ * config/obj-ecoff.h (ecoff_stab): Declare.
+ (OBJ_PROCESS_STAB): Define.
+ * config/obj-elf.c: Don't include aout/stab_gnu.h.
+ (obj_elf_stab, obj_elf_xstab, obj_elf_desc,
+ elf_stab_symbol_string, elf_stab_symbol, obj_elf_stab_generic):
+ Removed.
+ (obj_pseudo_table): Removed desc, stabX and xstabs entries.
+ (obj_elf_version): Use subseg_new, not bfd_make_section. Don't
+ set SEC_LOAD for .note section.
+ (adjust_stab_sections): Get frag pointer from seg_info, rather
+ than looking through frags.
+ * config/obj-elf.h (S_{S,G}ET_{OTHER,TYPE,DESC}): Removed.
+ (SEPARATE_STAB_SECTIONS, INIT_STAB_SECTION, OBJ_PROCESS_STAB):
+ Define.
+ * config/obj-vms.c (obj_aout_stab): Removed.
+ (obj_pseudo_table): Removed stabX entries.
+ * config/obj-vms.h (S_SET_TYPE): Define.
+
+ * as.h: Declare listing.
+ * read.c: Don't declare listing.
+ (emit_expr): Cast fix_new_exp argument.
+ (parse_bitfield_cons): Correct printf format.
+ * symbols.c (symbol_new): Add cast to avoid warning.
+ * write.h: Declare text_last_frag and data_last_frag.
+ * config/obj-bout.c (obj_bout_line): Added dummy argument.
+ * config/obj-coffbfd.c: Add some casts to avoid warnings.
+ * config/tc-a29k.c: Likewise.
+ * config/tc-i960.c: Likewise. Also fully bracket structure
+ initializations, fix printf formats, and remove unused variables.
+
+Mon Sep 13 16:48:38 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * read.c (s_desc): Only compile and use if S_SET_DESC is defined.
+ * struc-symbol.h: Declare verify_symbol_chain and
+ verify_symbol_chain_2 even if not SYMBOLS_NEED_BACKPOINTERS.
+ * symbols.c (verify_symbol_chain): Removed useless expression.
+ * write.c (headers, the_object_file): Only use if not
+ BFD_ASSEMBLER and not BFD.
+ (fixup_segment, cvs_frag_to_fill): Only use if BFD_ASSEMBLER or
+ not BFD.
+ (merge_data_into_text): Only use if BFD_ASSEMBLER or (not BFD and
+ not OBJ_AOUT).
+ * write.h: Declare relax_segment.
+ * config/obj-coffbfd.c (stack_pop, stack_push, stack_init): Made
+ static.
+ (stack_top): Commented out, since it's not used.
+ Fixed up pseudo-op functions to take an ignored int argument.
+ (size_section): Added default BAD_CASE to switch.
+ Changed bzero calls to memset.
+ * config/obj-coffbfd.h (S_IS_LOCAL): Call strchr on S_GET_NAME
+ (s), not on s itself.
+ * config/tc-a29k.c (s_use): Take ignored int argument. Only
+ define if OBJ_COFF is not defined.
+ * config/tc-i386.c: (fits_in_signed_byte, smallest_imm_type): Make
+ argument signed again.
+ * config/tc-m68k.c (s_bss, s_even, s_proc): Take ignored int
+ argument.
+ (m68k_ip): Fully bracket initialization of archs.
+ Correct several formats for __LINE__ to be %d rather than %s.
+ (init_table): Fully bracket initialization.
+ Cast values larger than 0x7f assigned to fr_opcode to char.
+
+ * subsegs.c: Renamed non-BFD_ASSEMBLER subseg_new to subseg_set.
+ Wrote non-BFD_ASSEMBLER subseg_new. Now subseg_new always takes a
+ section name, and subseg_set always takes a segT. Changed all
+ callers as appropriate.
+ * config/obj-coffbfd.c (change_to_section): Renamed to
+ obj_coff_add_segment. Corrected. Made callers use subseg_new.
+ * config/obj-coffbfd.h (obj_segment_name, obj_add_segment):
+ Define.
+
+Mon Sep 13 13:15:03 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * config/tc-sparc.h (LOCAL_LABEL): Remove test for name[0] == 'L'.
+
+Fri Sep 10 11:22:08 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/obj-elf.h (S_SET_SIZE): Actually set the size.
+
+ Gcc lint.
+ * Added a number of casts to function calls.
+ * app.c (do_scrub_begin), as.c (main), expr.c (integer_constant,
+ operand, expr), read.c (read_begin, HANDLE_CONDITIONAL_ASSEMBLY,
+ read_a_source_file, s_align_bytes, demand_empty_rest_of_line,
+ ignore_rest_of_line, big_cons, is_it_end_of_statement, s_ignore),
+ read.h (is_name_beginner, is_part_of_name), config/obj-elf.c
+ (obj_elf_section), config/tc-i386.c (parse_register),
+ config/tc-sparc.c (isoctal, s_proc): Cast char
+ array indices to unsigned char.
+ * app.c (process_escape): Make static. Add prototype. Change
+ argument from char to int.
+ * as.c: Include output-file.h for prototypes. Comment out unused
+ function got_sig.
+ * Makefile.in (as.o): Depend on output-file.h.
+ * as.h (BAD_CASE): Cast val argument to long, and use %ld.
+ (pseudo_typeS): Add prototype to poc_handler field.
+ (print_version_id): Add prototype.
+ (xmalloc, xrealloc): Change size arguments to unsigned long.
+ (do_scrub_next_char): Add prototypes for function arguments.
+ (had_errors, had_warnings, scrub_from_file): Remove duplicate
+ declarations.
+ * atof-generic.c (atof_generic): Make size variables unsigned.
+ * cond.c (ignore_input): Removed unused local variable ptr.
+ * expr.c (floating_constant, integer_constant): Make static. Add
+ prototypes.
+ * flonum-copy.c (flonum_copy): Make size variables unsigned.
+ * frags.h: Add prototype for frag_init.
+ * hash.h, hash.c: Change hash values from char * to PTR, make hash
+ strings const, make returned error strings const char *. Added
+ prototypes for functions.
+ * input-file.h, input-file.c (input_file_buffer_size): Return
+ unsigned int.
+ * input-scrub.c (buffer_length): Make unsigned.
+ (input_scrub_push, input_scrub_pop): Make static.
+ * listing.c (list_symbol_table): Cast sprintf argument to unsigned
+ long and use %lx. Print name of segment rather than address of
+ structure.
+ (listing_list, listing_title): Change argument to int.
+ (listing_eject, listing_flags, listing_psize): Add int argument.
+ * listing.h: Corresponding declaration changes.
+ * obj.h (obj_emit_symbols): Rename prototype argument to avoid
+ shadowing.
+ * read.h: Change get_absolute_expression prototype to return
+ offsetT. Add prototype for next_char_of_string. Various
+ prototype changes.
+ * read.c: Remove prototype for next_char_of_string.
+ (pobegin): Make errtxt const. Make new_length, tmp_len and num
+ unsigned.
+ (s_abort, s_align_ptwo, s_comm, s_data, s_app_line, s_fill,
+ s_globl, s_lsym, s_org, s_set, s_text, s_desc): Add int argument.
+ Change all callers.
+ (s_comm): Change temp from valueT to offsetT. Cast to long when
+ printing and use %ld (only for error messages anyhow).
+ (s_long, s_int): Remove unused functions.
+ (cons): Change argument to int.
+ (emit_expr): Use %lx when printing longs.
+ (get_absolute_expression): Return offsetT, not long.
+ (get_stab_string_offset): Comment out unless
+ SEPARATE_STAB_SECTIONS.
+ (s_stab_generic): Remove unused offset. Define seg_is_new only
+ if SEPARATE_STAB_SECTIONS. Use toP only in local block.
+ * struc-symbol.h (verify_symbol_chain_2): Add prototype.
+ * symbols.c: Remove nested comment.
+ (symbol_new): Rename value to valu.
+ (colon): Use %ld and cast to long in error message.
+ * symbols.h: Remove duplicate verify_symbol_chain declaration.
+ * tc.h: Remove unused md_emit_relocations declaration.
+ (tc_gen_reloc): Add declaration.
+ * write.c (cvt_frag_to_fill): Change first argument name depending
+ on BFD_ASSEMBLER.
+ (write_relocs): Remove unused offset, frags. Remove tc_gen_reloc
+ declarations. Make n unsigned.
+ (write_contents): Remove unused i, n, relocs, fixp. Rename frags
+ to f to avoid shadowing.
+ (write_object_file): Define fragP only if not BFD_ASSEMBLER or not
+ WORKING_DOT_WORD. Remove unused keep. Only declare punt and
+ punt_it if they will be used. Make i and n unsigned.
+ (fixup_segment): Cast to long and use %ld in error message.
+ * xmalloc.c (xmalloc, xrealloc): Make size argument unsigned.
+ * config/obj-aout.h: Remove nested comment. Add prototype for
+ obj_aout_frob_symbol.
+ (obj_aout_line, obj_aout_desc): Add int argument.
+ * config/obj-ecoff.c: Changed build routines to use an unsigned
+ offset.
+ (add_string): Make len unsigned long.
+ (obj_ecoff_stab): Use %lu in error message.
+ * config/obj-elf.c (obj_elf_common): Comment out unused label
+ allocate_bss.
+ (obj_elf_frob_symbol): Return 0 (currently broken).
+ (obj_elf_desc, obj_elf_version, obj_elf_size, obj_elf_type,
+ obj_elf_ident, obj_elf_weak, obj_elf_local, obj_elf_common,
+ obj_elf_line, obj_elf_previous): Add int argument.
+ (obj_elf_write_symbol_p): Make static.
+ * config/obj-elf.h (obj_elf_write_symbol): Add prototype.
+ * config/tc-hppa.h: Remove declarations of functions declared in
+ read.h.
+ * config/tc-i386.c (ENCODE_RELAX_STATE): Cast to relax_substateT.
+ (s_bss): Add int argument.
+ (fits_in_signed_byte, smallest_imm_type): Make argument unsigned.
+ (dummy): Remove unused function.
+ (md_assemble): Rename local o to op to avoid shadowing.
+ (tc_gen_reloc): Rename local reloc to rel to avoid shadowing.
+ * config/tc-m68k.c (s_data1, s_data2): Add int argument.
+ * config/tc-mips.c (mips_ip, md_apply_fix): Cast to long and use
+ %ld in error messages.
+ * config/tc-sparc.c: Remove duplicate declarations.
+ (getExpression): Rewrite condition to avoid empty conditional
+ body.
+ (s_reg, s_proc, s_reserve, s_common, s_seg, s_xword): Add int
+ argument.
+
+Thu Sep 9 17:10:00 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ Changes from Jeff Law:
+
+ * config/tc-hppa.c (md_assemble): Fix typo.
+ (pa_ip): Delete unused variables and labels. Do not check for
+ unsigned values being < 0, it can't happen.
+ (is_same_frag): Return a value in recursive call case.
+ (pa_callinfo): Delete unused variables and labels.
+ (pa_comm): Likewise.
+ (pa_copyright): Likewise.
+ (pa_export): Likewise.
+ (pa_import): Likewise.
+ (pa_param): Likewise.
+ (pa_space): Likewise.
+ (pa_subspace): Likewise.
+
+Thu Sep 9 15:05:34 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * read.c (get_stab_string_offset, s_stab_generic): If
+ BFD_ASSEMBLER, call subseg_set rather than subseg_new.
+
+Wed Sep 8 15:09:17 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/obj-elf.c (obj_elf_section): Set SEC_LOAD when using
+ default flag values.
+
+Tue Sep 7 10:22:52 1993 Stan Shebs (shebs@rtl.cygnus.com)
+
+ * read.c: (change_to_section): Don't include body if not MANY_SECTIONS.
+
+ * read.c: (s_stab, s_xstab, s_desc): New functions to parse
+ various stab-related directives.
+ * read.h: (s_stab, s_xstab, s_desc): New function prototypes.
+ * write.c: (merge_data_into_text): Fix ifdef tangle.
+ * config/obj-coffbfd.c (current_stab_symbol): Fake symbol
+ for stab reader to use.
+ * config/obj-coffbfdh.h (obj_symbol_type): Added fields for
+ stab reader, macros to access.
+
+Fri Sep 3 16:44:03 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/obj-elf.h (elf_symbol): No longer special-cased on
+ sparcv9, since elf_symbol_type is now independent of size.
+
+ * config/obj-elf.h (elf_symbol): Fixed name of elf_symbol_type.
+
+ * config/tc-hppa.h (struct default_subspace_dict, struct
+ default_space_dict): Field "sort" is now unsigned char.
+
+ * config/tc-hppa.c (pa_def_subspaces, pa_def_spaces): Align
+ columns for easier reading.
+ (bcmp, index): Deleted USG-specific definitions. Should be dealt
+ with in ho-*.h, or in libiberty. Changed mention of index to
+ strchr.
+ (label_symbolP, label_symbol_defined, callinfo_found,
+ within_entry_exit, exit_processing_complete, within_procedure,
+ pa_def_subspaces, pa_def_spaces, pa_pseudo_op_moves_pc,
+ label_symbols_rootP, pa_get_label, pa_label_is_defined,
+ pa_undefine_label): Now static.
+ (movers): Now const, in addition to pointing to const data.
+ * config/tc-hppa.h (label_symbolS_rootP, pa_get_label,
+ pa_label_is_defined, pa_undefine_label, pa_pseudo_op_moves_pc):
+ Delete declarations.
+
+ Merged more changes from Jeff Law and Pete Hoogenboom:
+
+ * config/tc-hppa.c (pa_def_subspaces, pa_def_subspaces): Remove
+ entries for .stab and .stabstr.
+
+ * config/obj-elf.c: (elf_stab_symbol_string): Set the
+ SEC_LOAD attribute for the .stabstr section.
+ (obj_elf_stab_generic): Set the SEC_LOAD attribute for the
+ .stab section.
+ (obj_elf_stab_generic): Change '#if 1' to '#if 0'.
+ (obj_elf_stab_generic): Incorrect byte count on call to
+ md_number_to_chars function.
+
+ * config/tc-hppa.c (hppa_tc_symbol): Static functions need
+ argument relocation bits too.
+
+ * config/tc-hppa.c (pa_stringer): Correctly handle escaping
+ characters which should appear unaltered in the output string (for
+ example an escaped double-quote).
+
+ * config/tc-hppa.c (pa_parse_nonneg_cmpsub_cmpltr): Always
+ initialize name.
+ (pa_parse_neg_cmpsub_cmpltr): Likewise.
+ (pa_parse_nonneg_add_cmpltr): Likewise.
+ (pa_parse_neg_add_cmpltr): Likewise.
+
+ * config/tc-hppa.h (parse_cons_expression_hppa): Remove prototype
+ for now.
+ (cons_fix_new_hppa): Likewise.
+ * config/tc-hppa.c (md_apply_fix): Fix type of valp to match
+ prototype.
+
+ * config/tc-hppa.c: Include libhppa.h.
+
+ * config/tc-hppa.h: Delete extern declarations of functions
+ found in libhppa.h.
+
+ * config/tc-hppa.c (pa_space): Rework to avoid unwanted #ifdef
+ OBJ_ELF conditionals.
+ * config/tc-hppa.h (LOCAL_LABEL): Correctly identify local labels
+ on the PA.
+
+Thu Sep 2 10:43:57 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (macro_build): Accept 'z', and ignore it.
+ (macro): Use "z,s,t" for div instructions to match corresponding
+ change in opcode table.
+ (mips_ip): Added 'z'--must be zero register.
+
+Wed Sep 1 15:56:42 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * write.c (write_relocs) [RELOC_EXPANSION_POSSIBLE]: Declare
+ tc_gen_reloc correctly.
+
+ * configure.in: Use "case" instead of "if" when possible. Rewrote
+ Makefile editing to reduce work done. Treat "hppa*" as "hppa".
+
+Wed Sep 1 12:19:07 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * config/obj-coffbfd.c (obj_coff_section): add 'd' as an alias for
+ section type of data. 'd' seems to be used for m88k.
+
+Wed Aug 25 22:33:22 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (mips_align, s_stringer, s_cons, s_float_cons,
+ s_mips_space): Set insn_label to NULL to avoid changing it at the
+ next .align statement.
+ (append_insn): Don't swap jal with instruction that sets the
+ register that jal sets.
+
+Wed Aug 25 16:15:57 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * configure.in: recognize m88110.
+
+Wed Aug 25 13:37:46 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ Merged changes from Pete Hoogenboom and Jeff Law at Utah:
+ * config/tc-hppa.c (pa_build_unwind_subspace): SEC_ALLOC should
+ not be on for .hppa_unwind.
+ (md_pseudo_table): .PARAM and .param are valid pseudo-ops for GAS.
+ (pa_param): New function to handle .PARAM directives.
+ (pa_ip): Pass "isbranch" argument down to pa_parse_*_compltr
+ functions. Handle '|' for movb; allow movb,n.
+ (pa_parse_nonneg_cmpsub_cmpltr): Delete old useless
+ version. Handle cases where no completer exists for
+ comb,n or addb,n.
+ (pa_parse_neg_cmpsub_cmpltr): Handle cases where no
+ completer exists for comb,n or addb,n. Make logic
+ mirror that of pa_parse_nonneg_cmpsub_cmpltr.
+ (pa_parse_nonneg_add_cmpltr): Likewise.
+ (pa_parse_neg_add_cmpltr): Likewise.
+ * tc-hppa.h (pa_param): Declare.
+
+Tue Aug 24 15:41:35 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/tc-hppa.c (hppa_tc_make_symextn_section): Now static.
+ Added forward declaration.
+
+ Merged changes from Pete Hoogenboom and Jeff Law at Utah:
+
+ * config/obj-elf.c (elf_frob_file): Arguments were incorrect on
+ call to elf_tc_make_sections.
+ (obj_elf_version): A .note section shouldn't have the SEC_ALLOC
+ attribute.
+
+ * config/tc-hppa.c (hppa_tc_make_sections): Add some processing to
+ handle symbol extension sections.
+
+ * config/tc-hppa.c (pa_build_symextn_section): New function to
+ create a symbol extension section.
+ (pa_export_args): Make call to pa_build_symextn_section.
+ (hppa_tc_symbol, hppa_tc_make_sections,
+ hppa_tc_make_symextn_section): New functions.
+ * config/tc-hppa.h: Update elf_tc_symbol and elf_tc_make_sections
+ macros.
+
+ * read.c (emit_expr): Place check for TC_CONS_FIX_NEW in the
+ BFD_ASSEMBLER branch as well.
+
+ * config/tc-hppa.h: If ELF is the target object format, define
+ some ELF- and hppa-specific types and constants.
+
+ * config/tc-hppa.c (getExpression): Fix a typo.
+
+ * read.c (read_a_source_file): Use TC_EQUAL_IN_INSN to determine
+ if a `=' is part of an instruction.
+ (read_a_source_file): Handle case where end-of-line markers are
+ also used within instructions.
+ * config/tc-hppa.h (TC_EQUAL_IN_INSN, TC_EOL_IN_INSN): Define.
+
+ * config/tc-hppa.c (md_apply_fix_1): Keep relocations for
+ out-of-range branches/'calls using "bl" or calls which may need
+ argument relocation stubs. Do not need/keep relocations for
+ conditional branches.
+ (elf_hppa_final_processing): Fix calculation of function size.
+
+ * config/obj-elf.c (obj_elf_version): Mark .note section as
+ READONLY.
+
+ * config/tc-hppa.c (parse_cons_expression_hppa): Pass exp, not the
+ address of exp, to expression.
+ (pa_build_unwind_subspace): Turn SEC_HAS_CONTENTS flag on.
+ (md_apply_fix_1): Delete unwanted comments.
+ (process_exit): Symbols marking the end of a function are always
+ BSF_LOCAL.
+
+ * config/tc-hppa.c: Include elf32-hppa.h from BFD tree.
+ (pa_space): Declare and initialize gdb_section.
+
+ * config/obj-elf.c (elf_frob_file): Change
+ elf_tc_final_processing_hook to elf_tc_final_processing.
+
+ * config/tc-hppa.c (fix_new_hppa): Fix argument list to match
+ argument type declarations.
+ (getExpression): Fix typo.
+ (pa_export_args): Change elf_symbol_type to elf32_symbol_type.
+ (elf_hppa_final_processing): Likewise. Name changed from
+ elf_hppa_final_processing_hook.
+ (start_symbol_root, start_symbol_last): Deleted.
+
+ * config/tc-hppa.h (TC_PARSE_CONS_EXPRESSION): Fix typo.
+
+ * config/tc-hppa.h: Replace "symbolS" with "struct symbol" to
+ avoid changing include ordering.
+
+ * config/tc-hppa.c (pa_ip, case 'y'): Handle just like 't'.
+
+Mon Aug 23 12:47:58 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (set_at): Added unsignedp argument. Use
+ load_register.
+ (set_at_unsigned): Removed; changed callers to use set_at.
+ (load_register): Removed unused ip argument. Changed callers.
+ (append_insn): Don't swap branch and branch likely.
+ (macro_build): Handle 'u'.
+ (load_register): Handle 64 bit constants.
+ (macro): Added M_DABS, removed M_ABSU. Numerous changes to
+ support 64 bit constants.
+ (mips_ip): Use hex constants in range checks for clarity.
+ (md_number_to_chars): Support 8 byte values.
+
+Fri Aug 20 16:50:59 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * config/tc-m88k.h: updated copyrights.
+ (TC_CONS_RELOC): declare to be RELOC_32.
+
+Fri Aug 20 11:16:44 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (mips_isa): New static variable.
+ (md_begin): Initialize mips_isa based on TARGET_CPU. Don't sanity
+ check macros. Set text alignment and GP size here.
+ (md_assemble): Don't set text alignment and GP size here.
+ (append_insn): Don't insert NOPs for load delays if mips_isa >= 2.
+ Use the right mask and shift for WRITE_FPR_T and WRITE_FPR_S. Add
+ a NOP after a branch likely.
+ (mips_emit_delays): Don't insert NOPS for load delays if mips_isa
+ >= 2.
+ (macro): Support r6000 and r4000 macros.
+ (mips_ip): Check insn ISA level against mips_isa before using it.
+ Added 'x' case for ignored register.
+ (md_parse_option): Handle -mipsN and -mcpu=XX.
+
+Fri Aug 20 01:26:52 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/tc-i386.c (md_pseudo_table) [OBJ_ELF]: Handle ".zero".
+
+Thu Aug 19 12:15:18 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/tc-sparc.c (s_local): Function moved and renamed...
+ * config/obj-elf.c (obj_elf_local): ...to here.
+ * config/tc-sparc.c (md_pseudo_table), config/obj-elf.c
+ (obj_pseudo_table): Move handling of ".local".
+
+ * tc.h (md_parse_option): Don't declare if defined as a macro.
+
+ * config/tc-i386.h (NO_RELOC) [BFD_ASSEMBLER]: Define as
+ BFD_RELOC_NONE.
+ (md_parse_option): New macro, converted from function.
+ * config/tc-i386.c (md_parse_option): Function deleted.
+ (comment_chars) [OBJ_ELF]: Include "/".
+ (line_comment_chars) [OBJ_ELF || TE_I386AIX]: Don't include "/".
+ (md_assemble): Cast 0xe9 to char explicitly, to avoid compiler
+ warning.
+ (md_assemble, md_estimate_size_before_relax, md_create_long_jump):
+ Call reloc for fix_new type, or use correct enumerator, instead of
+ always using NO_RELOC.
+ (i386_operand): Change "ifndef I386COFF" to "ifdef OBJ_AOUT" for
+ tests for valid section.
+ (md_convert_frag) [BFD_ASSEMBLER]: Compensate for frag start
+ address.
+ (md_apply_fix_1) [BFD_ASSEMBLER]: For pc-relative reloc with
+ symbol, compensate for location of reloc.
+ (reloc, BFD_RELOC_32, BFD_RELOC_32_PCREL) [!BFD_ASSEMBLER]: Define
+ to return zero.
+
+Wed Aug 18 16:51:29 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/obj-elf.c: Undef NO_RELOC before including aout/aout64.h.
+ (obj_elf_weak): New function.
+ (obj_pseudo_table): Handle ".weak".
+ (obj_elf_section): If section directive includes a string, ignore
+ it for now. Accept "progbits" flag.
+ (obj_elf_type): Accept `@' before flag name.
+
+ * write.c (relax_and_size_seg) [BFD_ASSEMBLER]: Get rid of `if(1)'
+ condition.
+ (fixup_segment) [BFD_ASSEMBLER]: Use bfd_is_com_section, rather
+ than checking for bfd_com_section directly.
+ (fixup_segment): Simplify range check.
+ (fixup_segment) [OBJ_COFF && TC_I960]: Simplify cpp condition
+ test.
+
+ * symbols.h (S_SET_WEAK): Declare.
+ * symbols.c (S_SET_WEAK): New function.
+ (S_SET_EXTERNAL, S_CLEAR_EXTERNAL): Don't bother with BSF_EXPORT,
+ it's not a separate flag any more. Clear BSF_WEAK.
+
+ * read.c (potable): Treat "string" like "asciz".
+
+Wed Aug 18 15:30:29 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (append_insn): Don't swap branch instructions
+ if .set nobopt or .set volatile.
+ (gp_reference): .lit8 and .lit4 are accessed via the GP register.
+ (macro): Added cases M_LI_S, M_LI_SS. Fixed M_LI_D and M_LI_DD.
+ (mips_ip): Added cases 'F', 'L', 'f', 'l' for floating point.
+ * config/obj-ecoff.c: Renamed some variables to avoid shadow
+ warnings.
+
+Mon Aug 16 14:16:02 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * config/obj-coff.h (S_IS_COMMON): add missing backslash
+
+ * configure.in (z8k-*-{coff,sim}): use coffbfd for this target
+
+Thu Aug 12 11:47:58 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (mips_ip): Suggested by
+ davidj@ICSI.Berkeley.EDU (David Johnson): Don't accept symbolic
+ names for 'E' and 'G' argument types (coprocessor registers) and
+ don't warn if $1 is used on the coprocessor.
+ (macro): Handle M_{L,S}WC{0,2,3}_AB correctly.
+
+Mon Aug 9 12:09:14 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * read.c (emit_expr): Use BFD_RELOC_16 for 2-byte values.
+ * config/tc-sparc.c (md_apply_fix, tc_gen_reloc): Handle
+ BFD_RELOC_16.
+ * config/tc-sparc.h (WORKING_DOT_WORD): Define.
+
+Mon Aug 9 13:36:22 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * write.c (merge_data_into_text): Define only if BFD_ASSEMBLER is
+ defined or BFD is not.
+ (relax_and_size_all_segments): Declare local variable fragP.
+
+Fri Aug 6 15:22:53 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/tc-sparc.c (md_apply_fix, case BFD_RELOC_32): Fill in
+ bytes with real values, not zeros.
+
+Fri Aug 6 10:57:59 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * configure.in (mips-*-riscos*, mips-*-sysv*): New (untested)
+ targets, using ecoff and mips-big.
+
+ * config/tc-mips.c (mips_ip): From davidj@ICSI.Berkeley.EDU (David
+ Johnson): Added case for 'C' for coprocessor instruction codes.
+
+Thu Aug 5 13:08:56 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/tc-sparc.c (md_apply_fix, case BFD_RELOC_64): Fill in
+ bytes with real values, not zeros.
+ (md_pseudo_table): Call cons for .uaxword.
+
+ * config/obj-elf.c (obj_pseudo_table): Handle ".8byte".
+
+ * read.c (emit_expr): Use BFD_RELOC_64 for 8-byte expressions.
+
+ * write.c (write_object_file): Test DEBUG_SYMS instead of DEBUG
+ for verifying symbol chain.
+ (merge_data_into_text, relax_and_size_all_segments): New
+ functions, split out from write_object_file.
+
+Tue Aug 3 15:43:55 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/obj-elf.c (obj_elf_stab_generic, in disabled code): If
+ debug section is new, allocate an extra 12 bytes at its start. If
+ ".stabs" type is N_SO, fill in filename symbol field of that first
+ entry. Return early if "goof", to simplify later code slightly.
+ (adjust_stab_sections): New function.
+ (elf_frob_file): Apply adjust_stab_sections to each section.
+
+ * config/obj-elf.c (obj_elf_section, obj_elf_previous): No longer
+ static.
+ * config/obj-elf.h (obj_elf_section, obj_elf_previous): Declare.
+ * config/tc-sparc.c (md_pseudo_table): Call them for "pushsection"
+ and "popsection", and call cons for "uaword" and "uahalf".
+
+ * config/obj-elf.c (obj_elf_version): Use English in error
+ messages.
+
+Tue Aug 3 11:29:06 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/obj-ecoff.c: Updated for BFD ECOFF changes. Now gets the
+ swapping routines and external structure sizes via the
+ ecoff_backend information. No longer includes coff/mips.h.
+
+Mon Aug 2 17:35:48 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/obj-ecoff.c (get_tag): Save tag name in permanent memory
+ and in hash_ptr->string.
+
+ * app.c (do_scrub_next_char): Reset state to 0 after .appline if
+ file name is not seen.
+
+Mon Aug 2 11:51:41 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/tc-sparc.c (md_apply_fix, case BFD_RELOC_64): New case,
+ parallel to BFD_RELOC_32.
+ (tc_gen_reloc): Accept BFD_RELOC_64.
+
+Thu Jul 29 22:21:28 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * write.c: Don't use short int in a prototype.
+
+ * expr.c (operand): Make return value simply depend on contents of
+ returned expression.
+
+Thu Jul 29 18:38:37 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * configure.in: sparc*-aout and sparc*-vxworks are BFD assemblers
+
+Thu Jul 29 18:38:37 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * config/ho-sunos.h: remove some old function decls that conflict
+ w/ ANSI, and which weren't needed anyway
+
+Wed Jul 28 16:34:55 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/obj-elf.h (obj_frob_symbol): Renamed from tc_frob_symbol,
+ and disabled since it breaks Ian's new symbol-value code.
+
+ * expr.c (integer_constant): Accept more digits if BFD64.
+
+Wed Jul 28 11:30:05 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-m68k.c (m68k_ip): If we have a normal constant when we
+ expect a bignum, turn it into a bignum. Output extra zeroes
+ before a short bignum, rather than after.
+
+Tue Jul 27 15:54:27 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * symbols.c (symbol_new): Conditionalize verify_symbol_chain call
+ on DEBUG_SYMS, not DEBUG.
+ (symbol_remove): Likewise.
+ (symbol_insert): Likewise.
+
+Tue Jul 27 08:45:05 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/tc-mips.c (mips_optimize): New static variable.
+ (append_insn): If mips_optimize == 0, always insert NOP
+ instructions. If mips_optimize < 2, don't swap branches.
+ (md_parse_option): If -Ox or -gx, set mips_optimize accordingly.
+
+Mon Jul 26 18:02:43 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * Makefile.in (clean): if testsuite does not exist, then skip it.
+
+Fri Jul 23 14:13:25 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-mips.c (prev_insn_unreordered,
+ prev_prev_insn_unreordered): New static variables.
+ (append_insn): Don't swap branch instruction if
+ prev_prev_insn_unreordered (see comment).
+ (mips_no_prev_insn): Clear the unreordered variables.
+ (s_mipsset): When turning on reordering, set the unreordered
+ variables.
+
+Fri Jul 23 13:09:44 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/obj-elf.c (obj_elf_section): Sections ".init" and ".fini"
+ are also magic, and have special default flag settings.
+ (obj_elf_frob_symbol): Since the return value from this function
+ isn't used, don't bother calling obj_elf_write_symbol_p, since it
+ doesn't accomplish anything else.
+
+ * config/tc-sparc.c (md_section_align): Round up section size only
+ for a.out format.
+
+ * symbols.c: Don't define DEBUG by default.
+
+Thu Jul 22 12:09:41 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * write.c (fix_new_exp): Handle a O_uminus expression.
+
+ * expr.c (expr): Don't let absolute_section override
+ undefined_section for the return value.
+
+ * read.c (read_a_source_file): In NO_PSEUDO_DOT case, if we find a
+ pseudo-op with a poc_handler field of NULL, ignore it and treat it
+ as an instruction instead.
+ * config/tc-m88k.c (md_pseudo_table): Add "set" with a NULL
+ poc_handler field.
+
+ * config/tc-h8500.c (md_begin): Use a local variable when
+ initializing md_relax_table to avoid warnings about modifying a
+ supposedly const data structure.
+
+Thu Jul 22 10:58:51 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * config/obj-aout.c: Only include aout/aout64.h if BFD_ASSEMBLER
+ is defined.
+
+Wed Jul 21 17:32:02 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * configure.in (case ${host}): Map *-*-sysv4* to gas_host=sysv.
+ * configure.in (case ${generic_target}): Add i[34]86-*-sysv4*
+ case to set obj_format=elf. Must go before i386-*-sysv* case that
+ sets obj_format=coffbsd. Add *-*-sysv4* to *-*-elf and
+ *-*-solaris case, and move to before *-sysv* case that wants to
+ set obj_format to coff.
+ * config/tc-i386.c (i386_operand): Change all 'exp.X_op' to
+ 'exp->X_op'.
+ * config/tc-i386.c (md_apply_fix): Fix valp to be 'valueT *' for
+ BFD_ASSEMBLER case.
+
+Wed Jul 21 12:47:51 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/obj-aout.c: Include aout/aout64.h.
+ (obj_aout_frob_symbol): Set BSF_DEBUGGING for a constructor
+ symbol, so that BFD doesn't tamper with the type.
+
+ * read.c (read_a_source_file): If NO_PSEUDO_DOT is defined, look
+ up opcodes as pseudo-ops even if they don't start with '.'.
+ * config/tc-m88k.h (NO_PSEUDO_DOT): Define.
+ * config/tc-m88k.c (md_assemble): Removed special pseudo-op
+ handling.
+ (md_apply_fix): Set fx_offset to the upper 16 bits of the reloc.
+ Output the low 16 bits for RELOC_HI16, not the high 16 bits.
+ * config/obj-coffbfd.c (do_relocs_for): If TC_M88K, set the
+ r_offset field of the reloc to the fixup offset.
+ (fixup_segments): If TC_M88K, don't warn about fixup overflows.
+ * doc/as.texinfo: Minor updates.
+
+Tue Jul 20 19:28:56 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * Extensive changes to permit symbols to contain any expression
+ type and to delay the computation of the expression until the
+ value is actually needed. This permits setting symbols to values
+ calculated based on object code size. Expressions were changed to
+ no longer be in a section, to stop the overloading of segment and
+ expression type that previously occurred.
+
+ * as.c (big_section, pass1_section, diff_section, absent_section):
+ Removed.
+ (expr_section): Added (used for dummy symbols which hold
+ intermediate expression values).
+ (perform_an_assembly_pass): Create expr_section, do not create the
+ sections now removed.
+ * as.h (segT): Removed SEG_ABSENT, SEG_PASS1, SEG_BIG, and
+ SEG_DIFFERENCE. Added SEG_EXPR.
+ (SEG_NORMAL): Corresponding changes.
+ * subsegs.c (seg_name, subsegs_begin): Changed accordingly.
+ * write.c (write_object_file): Ditto.
+ * config/obj-aout.c (seg_N_TYPE): Ditto.
+ * config/obj-bout.c (seg_N_TYPE): Ditto.
+ * config/obj-coff.c (seg_N_TYPE): Ditto.
+ * config/obj-coffbfd.c (seg_N_TYPE): Ditto.
+ * config/obj-vms.c (seg_N_TYPE): Ditto.
+
+ * expr.h (operatorT): Moved in from expr.c, added some values.
+ (expressionS): Added X_op field, removed X_seg field; renamed
+ X_subtract_symbol to X_op_symbol.
+ * expr.c: Extensive changes to assign expression types rather than
+ sections and to simplify the parsing.
+ * write.c (fix_new_internal): New static function.
+ (fix_new): Removed sub_symbol argument.
+ (fix_new_exp): New function, takes expression argument.
+ * write.h: Prototype changes for fix_new and fix_new_exp.
+ * cond.c (s_if): Changed accordingly.
+ * read.c (s_lsym, pseudo_set, emit_expr, parse_bitfield_cons,
+ parse_repeat_cons, get_segmented_expression,
+ get_known_segmented_expression, get_absolute_expression): Ditto.
+ * symbols.c (resolve_symbol_value, S_GET_VALUE, S_SET_VALUE):
+ Ditto.
+ * write.c (write_object_file): Ditto.
+ * config/obj-coff.c (obj_coff_def, obj_coff_val): Ditto.
+ * config/obj-coffbfd.c (obj_coff_def, obj_coff_val,
+ obj_coff_endef, yank_symbols): Ditto.
+ * config/obj-elf.c (obj_elf_stab_generic, obj_elf_size): Ditto.
+ * config/tc-a29k.c (md_assemble, parse_operand, machine_ip,
+ print_insn, md_operand): Ditto.
+ * config/tc-h8300.c (parse_exp, colonmod24, check_operand,
+ do_a_fix_imm, build_bytes): Ditto.
+ * config/tc-h8500.c (parse_exp, skip_colonthing, parse_reglist,
+ get_specific, check, insert, md_convert_frag): Ditto.
+ * config/tc-hppa.c (the_insn, fix_new_hppa, cons_fix_new_hppa,
+ md_assemble, pa_ip, getExpression, getAbsoluteExpression,
+ evaluateAbsolute, pa_build_unwind_subspace, pa_entry,
+ process_exit): Ditto.
+ * config/tc-hppa.h (STAB_FIXUP, is_DP_relative, is_PC_relative,
+ is_complex): Ditto.
+ * config/tc-i386.c (pe, md_assemble, i386_operand,
+ md_estimate_size_before_relax, md_create_long_jump): Ditto.
+ * config/tc-i860.c (md_assemble, getExpression, print_insn):
+ Ditto.
+ * config/tc-i960.c (parse_expr, subs, segs, md_convert_frag,
+ get_cdisp, mem_fmt, parse_ldconst, relax_cobr, s_sysproc,
+ i960_handle_align): Ditto.
+ * config/tc-m68k.c (struct m68k_exp, struct m68k_it, seg, op,
+ subs, add_fix, isvar, m68k_ip, md_assemble, md_convert_frag_1,
+ md_estimate_size_before_relax, md_create_long_jump, get_num):
+ Ditto.
+ * config/tc-m88k.c (md_assemble, get_imm16, get_pcr,
+ md_create_short_jump, md_create_long_jump): Ditto.
+ * config/tc-mips.c (md_assemble, append_insn, gp_reference,
+ macro_build, macro, my_getExpression): Ditto. Also removed
+ get_optional_absolute_expression; just use get_absolute_expression
+ instead.
+ * config/tc-ns32k.c (get_addr_mode, evaluate_expr, convert_iif,
+ fix_new_ns32k, fix_new_ns32k_exp, cons_fix_new_ns32k): Ditto.
+ * config/tc-ns32k.h (fix_new_ns32k prototype): Ditto.
+ * config/tc-sh.c (parse_exp, check, insert, md_convert_frag):
+ Ditto.
+ * config/tc-sparc.c (md_assemble, sparc_ip, getExpression,
+ print_insn): Ditto.
+ * config/tc-tahoe.c (struct top, md_estimate_size_before_relax,
+ tip_op, md_assemble): Ditto.
+ * config/tc-vax.c (seg_of_operand, md_assemble,
+ md_estimate_size_before_relax, md_create_long_jump): Ditto.
+ * config/tc-z8k.c (parse_exp, check_operand, newfix): Ditto.
+
+Tue Jul 20 12:17:16 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * configure.in: i386-lynx is the same as i386-coff
+
+Mon Jul 19 15:21:20 1993 Ken Raeburn (raeburn@rtl.cygnus.com)
+
+ * config/obj-elf.c (obj_elf_previous): New function.
+ (previous_section, previous_subsection): New vars.
+ (obj_elf_section): Save current place in case DWARF code wants us
+ to pop back to it. Handle unquoted section name as well as quoted
+ section name. Don't crash on invalid strings.
+ (obj_pseudo_table): Handle new pseudos "previous", "2byte", and
+ "4byte".
+
+ * config/obj-elf.h: Don't include struc-symbol.h.
+ (obj_elf_frob_symbol): Declare arg as struct symbol *.
+
+ * tc-sparc.h (LOCAL_LABEL) [OBJ_ELF]: Local labels can start with
+ "L" or "_.L_".
+
+ * write.c (write_relocs): New function, split off from
+ write_contents. Use memset instead of bzero.
+ (write_object_file): Apply write_relocs to each section before
+ applying write_contents.
+
+ * read.c (read_begin): Call obstack_begin with values closer to 1K
+ multiples.
+ (read_a_source_file, big_cons, float_cons): Use memcpy instead of
+ bcopy.
+
+Mon Jul 19 14:30:00 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/tc-m68k.c (m68k_ip_op): Don't decrement strend when
+ calculating opP->isiz; this permits the expression size to be
+ determined as well, later on.
+
+ * expr.c (clean_up_expression): Don't cancel the subtraction of
+ undefined symbols.
+
+ * read.c (s_data), config/obj-coffbfd.c (obj_coff_data): If -R,
+ switch to text section rather than data section.
+
+Mon Jul 19 12:35:39 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/tc-m68k.c (m68k_ip, case AINDX): Add 6 to operand
+ expression (to take the pc-rel instruction itself into account)
+ before using the expression, instead of after.
+
+Fri Jul 16 08:56:04 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * read.c (float_cons): Simplified parsing logic. If
+ REPEAT_CONS_EXPRESSIONS is defined, accept a repeat count.
+
+ * symbols.c (colon): Rather than a special case for TC_HPPA,
+ use new macro tc_frob_label.
+ * config/tc-hppa.h (tc_frob_label): Define.
+
+ * config/tc-mips.c: Many changes to support simple assembler
+ optimization.
+ (insn_label, prev_insn, prev_prev_insn, dummy_opcode,
+ prev_insn_valid, prev_insn_frag, prev_insn_where,
+ prev_insn_fixp, prev_insn_is_delay_slot): New static
+ variables.
+ (insn_uses_reg, mips_no_prev_insn, mips_emit_delays,
+ mips_align, s_stringer, s_mips_space): New static functions.
+ (mips_define_label): New global function.
+ (md_pseudo_table): For "ascii", "asciz", "asciiz", call
+ s_stringer. Changed argument to float_cons from 0 or 1 to 'f'
+ or 'd'. For "space" call s_mips_space.
+ (md_begin): Call mips_no_prev_insn.
+ (append_insn): Only insert necessary NOP instructions.
+ (macro): Call mips_emit_delays before setting mips_noreorder.
+ Increment and decrement mips_noreorder rather than using
+ save_reorder_condition. Don't bother to use noreorder in
+ M_L_DOB and M_L_DAB, since append_insn will not insert a NOP.
+ (md_atof): Handle floating point numbers correctly for both
+ big and little endian targets.
+ (s_align, s_cons): Call mips_align rather than frag_align.
+ (s_change_seg, s_cons): Call mips_emit_delays.
+ (s_float_cons): Let float_cons do the work.
+ (s_mipsset): Call mips_emit_delays when setting noreorder.
+ * config/tc-mips.h (tc_frob_label): Define to be
+ mips_define_label.
+
+ * config/obj-ecoff.c (ecoff_build_symbols, ecoff_build_procs,
+ ecoff_frob_files): Consistently use S_GET_VALUE rather than
+ bfd_asymbol_value. Warn if taking difference of symbols in
+ different segments.
+
+Thu Jul 15 11:51:03 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/obj-ecoff.c (ecoff_frob_file): Discard all open scopes,
+ with a warning.
+
+ * config/obj-coffbfd.c (fixup_segment): If TC_M88K, don't adjust
+ by md_pcrel_from if we are relocating against a symbol (we still
+ need md_pcrel_from for a PC relative relocation within the same
+ file).
+ * config/tc-m88k.c (md_pcrel_from): Corrected return value.
+ (omagic): Removed unused variable.
+
+ * Preliminary support for m88k-coff.
+ * configure.in (m88k-*-coff*): New target. Use coffbfd and
+ m88kcoff.
+ * config/m88kcoff.mt: New file.
+ * read.c (lex_type): New macro LEX_AT to set lex type of '@'.
+ (pseudo_set): Handle difference of symbols in different fragments
+ by saving the entire expression as the value of the symbol.
+ * symbols.c (resolve_symbol_value): Resolve difference
+ expressions.
+ * config/obj-coffbfd.c (obj_pseudo_table): If TC_M88K, accept
+ "sdef" as a synonym for "def".
+ * config/obj-coffbfd.h: If TC_M88K, include coff/m88k.h and set
+ TARGET_FORMAT.
+ (S_IS_LOCAL): Any symbol which includes \001 in the name is local.
+ * config/tc-m88k.c, config/tc-m88k.h: Numerous changes to bring
+ m88k port up to date, and to add COFF support.
+
+Wed Jul 14 15:09:32 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * Removed sy_forward and replaced it with an undefined expression
+ as the value of a symbol.
+ * struc-symbol.h (struct symbol): Removed sy_forward field. Added
+ sy_resolved and sy_resolving single bit fields.
+ * symbols.c (symbol_new): Don't initialize sy_forward field.
+ (resolve_symbol_value): New function to adjust symbol value by
+ fragment address, using recursion to resolve forward symbols.
+ * symbols.h: Added prototype for new function.
+ * read.c (pseudo_set): Set symbolP->sy_value to an undefined
+ expression rather than setting symbolP->sy_forward.
+ * write.c (write_object_file): Use resolve_symbol_value on
+ symbols, keeping the common case (the old behaviour) inline.
+ * config/obj-aout.c (obj_aout_frob_symbol): Removed sy_forward
+ handling (subsumed by write.c change).
+ * config/obj-coff.c, config/obj-coffbfd.c (obj_coff_val): Set
+ sy_value rather than sy_forward.
+ * config/obj-coffbfd.c (obj_coff_endef, yank_symbols): Check
+ expression segment rather than sy_forward.
+ (yank_symbols): Use resolve_symbol_value.
+ (crawl_symbols): Removed extra pass over symbols.
+ * config/obj-aout.c, config/obj-bout.c, config/obj-coff.c,
+ config/obj-vms.c (obj_crawl_symbol_chain): Removed extra pass over
+ symbols which handled sy_forward; use resolve_symbol_value
+ instead.
+ * config/obj-coff.h, config/obj-coffbfd.h (obj_frob_forward_symbol):
+ Define.
+ * config/obj-elf.c (obj_elf_stab_generic): Check expression
+ segment rather than sy_forward.
+ * config/obj-vms.c (VMS_Check_For_Main): Don't initialize
+ sy_forward; do initialize sy_resolved and sy_resolving.
+ * config/tc-hppa.h (STAB_FIXUP): Use sy_value, not sy_forward.
+
+ * Changes to keep a full expression as the value of a symbol, not
+ just a longword:
+ * struc-symbol.h: New field sy_value.
+ * as.h: Include expr.h before struc-symbol.h.
+ * expr.h: Use struct symbol rather than symbolS.
+ * symbols.c (S_GET_VALUE, S_SET_VALUE): Rewrote to retrieve value
+ of sy_value field; compile unconditionally, not just if
+ BFD_ASSEMBLER.
+ * symbols.h: Compile S_{SG}ET_VALUE prototypes unconditionally.
+ * write.c (write_object_file): Set BFD symbol value to gas symbol
+ value.
+ * config/obj-aout.h, config/obj-bout.h, config/obj-coff.h,
+ config/obj-coffbfd.h, config/obj-generic.h, config/obj-vms.h
+ (S_GET_VALUE, S_SET_VALUE): Removed macro definitions.
+ * config/obj-ieee.c (S_GET_VALUE, S_SET_VALUE): Removed.
+ * config/obj-coff.h, obj-coffbfd.h: Rewrote several macros to use
+ S_GET_VALUE rather than ost_entry.n_value.
+ * config/obj-aout.c (obj_symbol_to_chars), config/obj-bout.c
+ (obj_symbol_to_chars), config/obj-coff.c (obj_symbol_to_chars),
+ config/obj-coffbfd.c (symbol_to_chars): Get value to write out
+ using S_GET_VALUE--don't assume it is already set.
+ * config/obj-ieee.c (do_symbols): Set BFD symbol value to gas
+ symbol value.
+ * config/obj-vms.c (various): Don't assign directly to
+ S_GET_VALUE; use S_SET_VALUE instead.
+
+Wed Jul 14 09:35:23 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * configure.in: Make sparc64-*-aout* use bfd gas.
+
+ * configure.in: Recognize h8300h.
+
+Tue Jul 13 12:09:44 1993 Steve Chamberlain (sac@phydeaux.cygnus.com)
+
+ * config/tc-h8500.c (line_comment_chars): Add hash.
+ (parse_exp, skip_colonthing, build_bytes): Add support for
+ R_H8500_HIGH16 relocation type.
+
+Mon Jul 12 11:15:34 1993 Ken Raeburn (raeburn@deneb.cygnus.com)
+
+ * config/obj-elf.c (obj_elf_section): Allow `@' to introduce an
+ attribute name. Handle `execinstr' attribute.
+
+Mon Jul 12 07:22:28 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/tc-mips.c (mips_ip): Don't warn on 'i' or 'j' mismatch if
+ there is another alternative for the instruction.
+
+Fri Jul 9 17:31:34 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * doc/as.texinfo: updates for H8/300H
+
+Thu Jul 8 14:41:43 1993 Mark Eichin (eichin@cygnus.com)
+
+ * config/tc-i960.c (md_create_short_jump, md_create_long_jump,
+ md_number_to_chars, md_section_align): Adjusted to use valueT,
+ addressT, to match tc.h.
+
+Thu Jul 8 14:15:05 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/tc-sparc.c (s_common): Revamp to handle both syntaxes,
+ independent of format.
+
+Thu Jul 8 07:25:25 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * config/tc-h8300.h (TC_CONS_RELOC): Use R_RELLONG if h8/300h.
+
+Wed Jul 7 18:11:07 1993 david d `zoo' zuhn (zoo at rtl.cygnus.com)
+
+ * configure.in: define CROSS=-DCROSS_COMPILE if it is a cross
+ build; also recognize h8300-*-coff
+
+Wed Jul 7 10:21:24 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * symbols.c (fb_label_instance, fb_label_instance_inc): Don't dump
+ core just because somebody uses a label before it is defined.
+
+ * config/mips-opcode.h: Moved to opcode/mips.h.
+ * config/tc-mips.c: Include opcode/mips.h rather than
+ mips-opcode.h.
+ (append_insn): An extra NOP is only needed after instructions
+ which set HI or LO, not after instructions which read it.
+ (macro_build, mips_ip): Support new 'E', 'G' and 'B' arguments.
+ (macro): cfc1 and ctc1 now take "t,G" rather than "t,d".
+ * config/tc-mips.h (struct mips_opcode): Don't define.
+ * config/mips-big.mt, config/mips-lit.mt (TARG_CPU_DEPENDENTS):
+ Set to $(srcdir)/../include/opcode/mips.h.
+
+ Get the MIPS assembler up to speed with other gas changes:
+
+ * config/obj-ecoff.c (ecoff_set_vma, ecoff_frob_symbol):
+ Removed; don't change the symbol value.
+ (ecoff_build_symbols, ecoff_build_procs, ecoff_frob_file): Use
+ bfd_asymbol_value rather than S_GET_VALUE to include section
+ vma in symbol value.
+ (ecoff_frob_file): Ignore BSF_SECTION_SYM symbols, since ECOFF
+ doesn't output them. Set the vma of sections.
+ * config/obj-ecoff.h: Don't define obj_frob_symbol.
+ * config/tc-mips.c (tc_gen_reloc): Adjustment by section vma is no
+ longer necessary.
+ (various): use valueT rather than long.
+
+Wed Jul 7 08:33:30 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/tc-sparc.h (ENV64): Define for v9.
+
+ * config/tc-sparc.c (s_xword): For numbers, call big_cons.
+ (sparc_ip, md_apply_fix, tc_gen_reloc): Handle some sparc64
+ relocation types.
+ (md_number_to_chars): Handle 8-byte value.
+
+ * config/obj-elf.h (elf_symbol): For v9, use 64-bit symbol type.
+
+ * as.h (valueT): Typedef moved here.
+ * struc-symbol.h (valueT): ...from here.
+ * write.c (write_object_file): Locals from_addr, to_addr,
+ table_addr are now addressT. Supply prototype for bfd_alloc for
+ now.
+ (fixup_segment): Local add_number is now valueT. Correct some
+ range-checking bugs.
+ (relax_align): Type `int' should be sufficient for the exponent.
+ (fix_new): Argument offset is type offsetT. Locals size and
+ newsize are type valueT.
+ * write.h (struct fix): Fields fx_offset and fx_addnumber are now
+ type valueT.
+ (fix_new): Fix prototype.
+ * symbols.c (symbol_new): Symbol value is type valueT.
+ (S_SET_VALUE, S_GET_VALUE): Likewise.
+ (S_IS_*): Specify int return type explicitly.
+ * symbols.h (symbol_new, S_GET_VALUE, S_SET_VALUE): Fixed
+ prototypes.
+ * read.c (s_comm): Values read are type valueT.
+ * expr.h (expressionS): Field X_add_number is an offsetT.
+ * tc.h (md_create_long_jump, md_create_short_jump,
+ md_section_align): Addresses are now type addressT.
+ (md_number_to_chars, md_apply_fix): Pass value as valueT.
+ * config/tc-i386.c (md_create_short_jump, md_create_long_jump,
+ md_number_to_chars, md_section_align): Adjusted.
+ * config/tc-sparc.c (sparc_ip): Initialize `len' variable to make
+ gcc shut up.
+ (md_create_short_jump, md_create_long_jump, md_number_to_chars,
+ md_section_align): Adjusted.
+
+ * config/tc-sparc.c (s_reserve): Permit use for other than a.out
+ format.
+ (s_common): Handle Solaris-2 version.
+
+ * config/ho-generic.h (free): Returns void if __STDC__.
+
+ * config/obj-elf.h (obj_elf_frob_symbol, elf_frob_file,
+ elf_file_symbol): Declare.
+
+ * expr.c (floating_constant, integer_constant): Now return void.
+
+Thu Jul 1 12:13:43 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * configure.in: Match on sparc*-fujitsu-none rather than
+ sparclite*-fujitsu-none.
+
+Wed Jun 30 11:12:02 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * read.c (cons): Conditionalize parsing of expression. Move
+ putting value into object file into separate function. Separate
+ out MRI and WANT_BITFIELDS cases into separate functions.
+ (emit_expr): New function to write data into object file.
+ Conditionalize on TC_CONS_FIX_NEW and TC_CONS_RELOC rather than on
+ processor types.
+ (parse_bitfield_cons): New function to parse bitfield expressions
+ as used by i960 assemblers. Only compiled if
+ BITFIELD_CONS_EXPRESSIONS is defined.
+ (parse_mri_cons): New function to parse MRI style strings. Only
+ compiled if MRI is defined.
+ (parse_repeat_cons): New function to parse repeat counts. Only
+ compiled if REPEAT_CONS_EXPRESSIONS is defined.
+ * read.h (emit_expr): Added declaration of new function.
+ * config/tc-a29k.h (TC_CONS_RELOC): Define to be RELOC_32.
+ * config/tc-h8300.h (TC_CONS_RELOC): Define to be R_RELWORD.
+ * config/tc-hppa.c (parse_cons_expression_hppa): New function to
+ parse a HPPA expression, rather than special case in cons
+ function.
+ (cons_fix_new_hppa): New function to emit an HPPA fixup, rather
+ than special case in emit_expr function.
+ * config/tc-hppa.h (TC_PARSE_CONS_EXPRESSION, TC_CONS_FIX_NEW):
+ Define to use new functions from tc-hppa.c.
+ * config/tc-i960.h (BITFIELD_CONS_EXPRESSIONS): Define.
+ (WANT_BITFIELDS): Removed; now obsolete.
+ * config/tc-mips.h (REPEAT_CONS_EXPRESSIONS): Define.
+ * config/tc-ns32k.c (cons_fix_new_ns32k): New function to emit an
+ NS32K fixup, rather than special case in emit_expr function.
+ * config/tc-ns32k.h (TC_CONS_FIX_NEW): Define to be
+ cons_fix_new_ns32k. Also use PARAMS rather than checking
+ __STDC__.
+ * config/tc-sparc.h (TC_CONS_RELOC): Define to RELOC_32.
+
+ * write.c (relax_and_size_seg, adjust_reloc_syms, write_contents):
+ Don't core dump if gas has no information about a section.
+
+Wed Jun 30 06:21:27 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/tc-sparc.c (md_begin): If sparcv9 is defined, reset
+ current_architecture to v9 automatically.
+
+ * config/tc-sparc.h (TARGET_FORMAT): Use elf64-sparc for v9.
+
+ * config/tc-sparc64.h, config/tc-sparc64.c: New files.
+ * configure.in: Use sparc64 cpu files for v9, and default to elf
+ format.
+
+ * write.c (relax_and_size_seg): Always fully process a section.
+ Section size is last frag's (vm)address plus its size. If no
+ relocations are present, force SEC_RELOC flag clear.
+ (dump_section_relocs): New debugging routine.
+ (adjust_reloc_syms): New routine, broken out from write_contents.
+ Don't adjust relocs that are already relative to section symbol.
+ Look for obj_fix_adjustable macro to know what else to skip,
+ instead of obj_write_symbol. Look for section symbol stored in
+ section information.
+ (write_object_file): Map adjust_reloc_syms over all sections.
+ (write_contents): Clear SEC_RELOC flag if no relocations are
+ found.
+
+ * as.h (__PTR_TO_INT, __INT_TO_PTR): New versions for Saber, to
+ keep it quiet.
+
+ * write.c (remove_subsegs): Don't define for BFD_ASSEMBLER.
+
+Fri Jun 25 14:42:53 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * Makefile.in (all, dvi, info, install-info, clean-info): do not
+ echo recursion lines.
+ (install-info, clean-info): collapse into the dvi and info rule.
+
+Fri Jun 25 10:47:24 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * config/tc-sparc.c (sparc_ip): Remove support for %d/%q fp regs.
+ All fp regs are now specified as %f.
+ (priv_reg_table): fpq -> fq.
+
+Fri Jun 25 03:43:06 1993 Ken Raeburn (raeburn@poseidon.cygnus.com)
+
+ * as.h (strstr): Disable declaration for now.
+ (fprint_value, sprint_value): Declare.
+
+ * subsegs.c (subseg_new_rest): Use memset to clear new frag.
+ (subseg_new) [BFD_ASSEMBLER]: Initialize all seginfo fields.
+
+ * expr.c (expr_part): Made sanity checks a.out-specific.
+ (expr): Disabled sanity checks.
+
+ * subsegs.h (segment_info_type) [BFD_ASSEMBLER]: Add field for
+ section symbol.
+ * subsegs.c (subseg_change): Initialize section symbol pointer
+ when setting up a new section.
+
+ * symbols.c (symbol_new) [BFD_ASSEMBLER]: Point BFD symbol's udata
+ field back at gas symbol structure.
+
+ * symbols.c (colon): Cast obstack_next_free value to char* before
+ doing arithmetic on it.
+ * subsegs.c (subseg_new_rest): Likewise.
+ * as.h (frag_now_fix): Likewise.
+
+ * config/obj-elf.c (elf_file_symbol): Use subseg_new instead of
+ calling bfd_make_section_old_way directly, and call subseg_set
+ instead of subseg_change. Now returns void.
+ (obj_elf_write_symbol): Only check local symbols for now.
+ (elf_stab_symbol): Now static and void, and disabled until it
+ works completely.
+ (obj_elf_size): For expression values, fail silently for now.
+ (obj_symbol_new_hook): Do nothing.
+
+ * config/tc-sparc.c (tc_gen_reloc): Handle BFD_RELOC_SPARC_WDISP22
+ relocation.
+ (s_local) [OBJ_ELF]: New function.
+ (md_pseudo_table) [OBJ_ELF]: Call it for "local".
+ (s_common): Rearrange to handle Solaris .common pseudo, which may
+ sometimes use bss space instead of common.
+ * config/obj-elf.h (TARGET_SYMBOL_FIELDS): Add new `local' field.
+
+Thu Jun 24 16:33:53 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: set host config to hpux for hppa*-hp-hpux
+
+Thu Jun 24 13:35:06 1993 Ken Raeburn (raeburn@poseidon.cygnus.com)
+
+ * app.c (app_pop, app_push): Fix bug reported by Chris Arthur.
+
+Tue Jun 22 01:04:23 1993 Ken Raeburn (raeburn@poseidon.cygnus.com)
+
+ * subsegs.c (subseg_new): Don't special-case a.out -R flag here.
+ * config/obj-aout.c (s_sect): Do it here.
+
+ * as.h (BAD_CASE): Don't make some lame compilers think we want
+ substitution inside strings.
+
+ * as.c (print_version_id): New function, split off from main.
+ (main): Call it.
+ * config/tc-sparc.c (md_parse_option) [OBJ_ELF]: Print version id
+ for -V. Ignore -Q and -s options for now.
+
+Mon Jun 21 17:37:59 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: make installation & builds work again for crosses
+
+Sun Jun 20 18:18:26 1993 Ken Raeburn (raeburn@poseidon.cygnus.com)
+
+ * listing.c (list_symbol_table): Rewrite to print wide (>32 bits)
+ symbol values correctly.
+
+ * write.c (write_object_file): Deleted unused variables.
+ (fixup_segment): Use sprint_value.
+
+ * messages.c (sprint_value, fprint_value): New routines.
+
+ * config/obj-elf.c (elf_stab_symbol): Now returns void.
+ (obj_elf_stab_generic): Fix typo in logic.
+
+ * Makefile.in (INCLUDES): Look in ../bfd for bfd.h.
+
+ * as.h (addressT, offsetT): New types, using BFD types if
+ available.
+ (relax_addressT, struct frag): Use them.
+ * struc-symbol.h (valueT, struct broken_word): Likewise.
+
+ * as.h (subseg_new) [BFD_ASSEMBLER]: Name argument is const.
+ * subsegs.c (subseg_new) [BFD_ASSEMBLER]: Name argument is const.
+
+Thu Jun 17 16:53:56 1993 david d `zoo' zuhn (zoo@cygnus.com)
+
+ * Makefile.in: canonicalize install.sh; for use within
+ this directory (and subdirs)
+
+Sun Jun 20 02:34:04 1993 Ashley Saulsbury (ans@sics.se)
+
+ * m88k-opcode.h : fixed tiny tiny mistake - xcr was incorrectly
+ specified, should have both S1 and S2 fields identical
+ If only finding the problem was as fast as fixing the bug !!!!
+
+Tue Jun 15 16:01:57 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * write.c (write_contents): Do write out non-loadable sections.
+ Debug sections can fall in this category.
+
+ * read.c (s_app_file): Call elf_file_symbol for ELF files.
+ * config/obj-elf.c (elf_file_symbol): New function.
+
+ * config/obj-elf.c (elf_stab_symbol_string): Renamed from pa_...,
+ added argument to specify section base name.
+ (obj_elf_stab_generic): Renamed from ..._stab. New argument
+ specifies section base name.
+ (obj_elf_stab): New function, calls obj_elf_stab_generic with
+ ".stab" as section base name.
+ (obj_elf_xstab): New function, calls obj_elf_stab_generic.
+ (obj_elf_type): Handle "object". Use bitwise-or to merge in
+ symbol flags rather than simply replacing, so global/local flags
+ are preserved.
+ (obj_elf_ident): Rewrite.
+
+Tue Jun 15 17:03:25 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: remove parentdir support; use INSTALL_XFORM
+
+Wed Jun 9 11:26:07 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/tc-i386.c (md_pseudo_table): .align uses a power of two
+ for any a.out target, not just Linux and 386BSD.
+ * config/tc-i386.h (DOT_LABEL_PREFIX): Do not define for any a.out
+ target.
+
+Mon Jun 7 13:33:19 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/tc-m88k.c: Don't include flonum.h, md.h, m88k.h. They
+ don't exist or duplicate other inclusions.
+
+ * config/tc-vax.h (NO_RELOC): Define.
+
+Mon Jun 7 09:55:03 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * config/tc-sparc.c (sparc_ip): Fix parsing of asi number.
+ Fix error message.
+
+Sat Jun 5 19:32:52 1993 Torbjorn Granlund (tege@nada.kth.se)
+
+ * gas/config/m88k-opcode.h (m88k_opcodes): Add 88110 instructions.
+ * gas/config/tc-m88k.c (get_reg): New arg reg_prefix. Compare first
+ char to reg_prefix instead of to 'r'.
+ (calcop): Change calls to get_reg.
+ (calcop): Handle new case 'x' to set reg_prefix.
+ (calcop): Set reg_prefix to 'r' after each call to get_reg.
+ (cmpslot): Add 88110 conditions.
+
+ * gas/config/m88k-opcode.h: Swap cases for "rot" for consistency.
+
+ * gas/config/tc-m88k.c (get_bf): Always restore input_line_pointer
+ before returning.
+
+ * gas/config/m88k-opcode.h (m88k_opcodes): Make equal mnemonics
+ adjacent; mov.s and mov.d swapped.
+ (m88k_opcodes): Fix typo `r2' -> `2'.
+
+Fri Jun 4 15:59:31 1993 Steve Chamberlain (sac@phydeaux.cygnus.com)
+
+ * config/h8300.c: Support for H8/300-H opcodes.
+
+ * config/obj-coffbfd.c (w_strings): String table length is 4
+ bytes, no matter what the host int size is.
+
+ * configure.in (alpha-*-osf*): New.
+
+Fri Jun 4 07:51:18 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * configure.in (mips-*-ecoffl*): New target; use ecoff and
+ mips-lit.
+ (mips-*-ecoff*): Added trailing '*'.
+
+ * config/obj-ecoff.c (ecoff_build_procs): Force the adr of the
+ first FDR in a file to be zero.
+
+Thu Jun 3 14:09:59 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * Makefile.in (VERSION): Jump to 2.1.4.
+
+ * config/ho-hppabsd.h: New file, from Peter Hoogenboom.
+
+ * config/tc-mips.c (md_assemble): Call bfd_set_gp_size only for
+ ECOFF format.
+
+Tue Jun 1 15:21:57 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/tc-m68k.c (md_assemble): The 68040 cpu doesn't want a
+ separate '851 mmu.
+
+ * config/obj-elf.c, config/obj-elf.h: Update for new type, macro,
+ and routine names. Assuming 32 bits for now.
+
+ * config/obj-elf.c (elf_frob_file): Look for macro
+ elf_tc_final_processing_hook, instead of assuming a function
+ always exists.
+ * config/tc-hppa.c (elf_hppa_final_processing_hook): Renamed from
+ tc_final_processing_hook.
+ * config/tc-hppa.h (elf_tc_final_processing_hook): Use it.
+
+ * config/tc-hppa.h (elf_tc_symbol, elf_tc_make_sections): Macros
+ moved here from obj-elf.h.
+ * config/obj-elf.h: Don't include CPU-specific header files.
+
+Sun May 30 16:49:37 1993 Peter Hoogenboom (hoogen@fast.cs.utah.edu)
+
+ * configure.in: configurations should match on 'hppa*' not 'hppa'.
+
+ * read.c: Add support for HPPA assembly language syntax (denoted
+ with '#ifdef TC_HPPA').
+
+ * symbols.c: Add support for HPPA assembly language syntax (denoted
+ with '#ifdef TC_HPPA').
+
+ * write.c (write_contents): Add support for HPPA-style
+ relocations.
+
+ * config/obj-elf.c: Stab symbols weren't written properly.
+ (obj_elf_version):
+ (obj_elf_desc):
+ (obj_elf_write_symbol):
+ (obj_elf_write_symbol_p):
+ (obj_elf_frob_symbol):
+ (elf_stab_symbol):
+ (elf_frob_file):
+
+ * config/tc-hppa.c: Support for HPPA symbol extension sections.
+ Remove some unused code. Support for HPPA assembly language
+ syntax.
+
+ * app.c:
+
+ * symbols.c:
+
+ * config/obj-elf.h:
+ (obj_write_symbol):
+ (obj_frob_file):
+ (elf_tc_symbol):
+ (elf_tc_make_sections):
+
+ * config/tc-hppa.h:
+
+Sun May 30 21:44:45 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * config/obj-ecoff.c (obj_read_begin_hook, add_file): Assume
+ hash_new will have succeeded if it returns.
+ * config/tc-a29k.c (md_begin): Likewise.
+
+ * config/tc-i386.c (tc_aout_fix_to_chars): Now nbytes_r_length is
+ const.
+ (mode_from_disp_size, opcode_suffic_to_type): Now inline under
+ gcc.
+ (fits_in_{signed,unsigned}_{byte,word}): Likewise.
+
+ * expr.c: Delete register declarations; gcc ignores them anyways.
+
+Fri May 28 19:03:32 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * hash.c (hash_new): Use xmalloc, since many callers don't check
+ for failure.
+
+Thu May 27 13:02:15 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * frags.c (zero_address_frag, bss_address_frag): These are
+ external.
+
+ * tc.h (md_reloc_size): This is const.
+ * config/tc-{a29k,h8300,h8500,i386,i860,i960,m68k,ns32k,z8k}.c
+ (md_reloc_size): Now const.
+
+ * config/aout_gnu.h (enum machine_type, enum reloc_type): Delete
+ trailing commas.
+ * as.h (enum _segT): Ditto.
+
+ * struc-symbol.h (N_TYPE_seg): This should be const.
+
+Thu May 27 11:43:59 1993 Michael Meissner (meissner@osf.org)
+
+ * config/obj-ecoff.c (add_file): Cast file_name to char * in
+ listing_source_file call.
+
+ * config/obj-elf.c (elf_stab_symbol_string): Cast first argument
+ of subseg_new call to eliminate const attribute.
+ (obj_elf_stab): Ditto.
+ (obj_symbol_new_hook): Cast first argument of bzero call to char *.
+
+ * read.c (s_align_bytes): Properly record alignment.
+
+ * expr.c (__): Undefine __ macro before use, since OSF/1 uses it
+ for the prototype/no prototype macro.
+
+ * as.c (got_sig): Don't do return ((SIGTY) 0), SIGTY might well be
+ void.
+
+ * as.h (relax_stateT enum): Delete trailing comma.
+
+Thu May 27 11:07:50 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * app.c (do_scrub_begin): Let line_comment_chars override
+ comment_chars.
+ (do_scrub_next_char): If a line comment character is not at the
+ start of a line, treat it as a comment character if it is one.
+ For a CPP line comment use pseudo-op .appline rather than .line.
+ * input-scrub.c (logical_input_line): Make int rather than
+ unsigned.
+ (input_scrub_push, input_scrub_begin): Initialize
+ logical_input_line to -1 rather than 0.
+ (bump_line_counters): Increment logical_input_line.
+ (new_logical_line): If line_number is -2, decrement
+ logical_input_line.
+ (as_where): Use logical_input_line even if it is 0.
+ * read.h (s_app_file prototype): Now takes an int argument.
+ * read.c (potable): Make .appfile call s_app_file with 1. New
+ .appline pseudo-op calls s_app_line.
+ (s_app_file): If .appfile, call new_logical_line with -2 to
+ account for newline inserted by do_scrub_next_char. If listing,
+ call listing_source_file.
+ (s_app_line): New function to handle fake pseudo-op .appline.
+ * config/obj-coff.c (obj_pseudo_table): Make .appline call
+ obj_coff_ln.
+ (obj_coff_ln): Added argument to indicate whether .appline.
+ * config/obj-coffbfd.c (obj_pseudo_table): Make .appline call
+ obj_coff_ln.
+ (obj_coff_ln): Added argument to indicate whether .appline.
+ * config/tc-mips.c (s_file): Pass argument to s_app_file.
+
+Tue May 25 11:59:07 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/obj-bout.h (S_GET_VALUE): Removed unnecessary cast.
+
+Thu May 20 19:14:24 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/tc-m68k.c (md_apply_fix_2): Straighten out check for
+ invalid values.
+
+Wed May 19 07:33:17 1993 Steve Chamberlain (sac@phydeaux.cygnus.com)
+
+ * config/tc-h5000.c (build_bytes): Understand @rd mode and build
+ relocations correctly.
+
+Mon May 17 15:06:26 1993 Ken Raeburn (raeburn@deneb.cygnus.com)
+
+ * Makefile.in (FLAGS_TO_PASS): Leave out TEXI2DVI for now, because
+ it's wrong.
+
+ * config/tc-m68k.c (md_apply_fix_2): Apply range checks and warn
+ if value is out of range.
+
+ Patch from Minh Tran-Le:
+ * config/tc-i386.c (i386_operand): For in/out port register used
+ as base reg, include InOutPortReg in operand type.
+ (MATCH): Accept overlap value of InOutPortReg.
+
+Mon May 17 09:29:34 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/obj-ecoff.c (add_file, obj_ecoff_loc, obj_ecoff_stab):
+ Add calls to listing routines to produce combined source/assembler
+ listings.
+ (obj_ecoff_stab): Create a file pointer if none used yet.
+ (ecoff_frob_file): Set symcount to correct value.
+
+Fri May 14 06:53:33 1993 Ken Raeburn (raeburn@deneb.cygnus.com)
+
+ * Makefile.in (VERSION): Bump to version 2.1, in preparation for
+ release.
+
+ * config/obj-aout.h (H_GET_HEADER_SIZE, H_SET_SYMBOL_TABLE_SIZE):
+ Define in terms of constants, not C structure sizes.
+
+ * config/tc-rs6000.c, config/tc-rs6000.h: Delete empty files.
+
+Thu May 13 17:01:55 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/obj-aout.c (obj_header_append): Don't define if it's
+ defined as a macro.
+ * config/obj-hp300.h (obj_header_append): Define it as a macro.
+ * config/obj-hp300.c (hp300_header_append): New function.
+
+ * Makefile.in (distclean): Don't bother cleaning up doc files;
+ they aren't going to be in this directory.
+
+Thu May 13 07:51:35 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/obj-ecoff.c (ecoff_build_symbols): Handle absolute
+ symbols.
+
+ * tc.h (TC_COFF_SIZEMACHDEP): Don't define here.
+ * config/tc-sh.h (TC_COFF_SIZEMACHDEP): Define here instead.
+
+Mon May 10 06:01:12 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * config/obj-vms.c (VMS_Symbol_type_list): Don't bother with
+ initialization.
+
+ * configure.in (targets): Treat m68*-*-sysv* like m68k-*-coff.
+
+Wed May 5 14:00:49 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/tc-mips.c (macro): Correct floating point double word
+ loads and stores for big endian target.
+
+Wed May 5 08:39:21 1993 Ken Raeburn (raeburn@deneb.cygnus.com)
+
+ * config/tc-i386.c: Replace SEG_* with *_section, fix up subseg_*
+ calls. Deleted some unused code.
+ * config/obj-coff.c: Likewise.
+
+ ELF support, mostly contributed by Utah:
+ * config/obj-elf.c (obj_elf_section, obj_elf_stab, obj_elf_line,
+ obj_elf_type): Rewrite.
+ (obj_elf_frob_symbol, elf_stab_symbol_string, elf_stab_symbol,
+ obj_elf_desc, obj_elf_version, obj_symbol_new_hook, obj_elf_size):
+ New functions.
+ (obj_elf_ident): Dummy.
+ * config/obj-elf.h (FALSE, TRUE, S_*, tc_frob_symbol,
+ TARGET_SYMBOL_FIELDS): New macros.
+ (gdb_section): New variable decl.
+
+ * config/tc-i386.c (md_atof): Return zero, not empty string, on
+ success.
+
+ BFD_ASSEMBLER conditional changes:
+ * config/obj-coff.c (lineno_rootP, seg_N_TYPE, *_section_header):
+ Don't define these.
+ (SA_SET_SYM_ENDNDX, SA_SET_SYM_TAGNDX): New functions.
+ (fetch_coff_debug_section): Ditto.
+ (obj_coff_endef): Call fetch_coff_debug_section.
+ (struct line_no): New type.
+ (c_symbol_merge): New way for copying aux fields.
+ (c_dot_file_symbol): Put symbol in absolute section, and set flag
+ BSF_DEBUGGING.
+ (function_lineoff): New symbol.
+ (function_lineoff, text_lineno_number, our_lineno_number,
+ lineno_lastP): Don't define.
+ (c_line_new): Don't define.
+ (obj_emit_lineno, obj_coff_endef): Use abort calls as, uh,
+ placeholders, until
+ line-number recording gets implemented.
+ (obj_new_symbol_hook): New code for handling aux fields.
+ (add_lineno, add_linesym): New functions.
+ (obj_coff_ln): Call add_lineno, not c_line_new.
+ (obj_coff_endef): New code for handling symbol names. New lineno
+ code. Look for section name "*DEBUG*" for debugging section.
+ (align, coff_check_file_symbols, obj_coff_section,
+ coff_frob_file): New functions.
+ * config/obj-coff.h: Reordered some includes.
+ (BYTE_ORDERING, FILE_HEADER_MAGIC, seg_N_TYPE, N_TYPE_seg,
+ DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE, AOUTHDR, AOUTHDRSIZE): Don't
+ define these.
+ (TARGET_SYMBOL_FIELDS, I960_SYM_FIELDS): New macros.
+ (SYM_AUXENT): New macro (for non-BFD_ASSEMBLER too) for accessing
+ aux entries. Most SA_* macros now use it unconditionally.
+ (S_*): Use `bsym' field, and access BFD private data.
+ (SF_*): Use `sy_flags' symbol field for most of these.
+ (H_*, object_headers, lineno, lineno_*P, OBJ_EMIT_LINENO): Don't
+ define.
+ (*_section_header): Don't define.
+ * config/tc-i386.c (md_convert_frag, md_apply_fix): Changed
+ interface.
+ (tc_gen_reloc) [I386COFF]: New function.
+ (tc_aout_fix_to_chars, tc_coff_fix2rtype): Don't define.
+ * config/tc-i386.h (TARGET_ARCH, TARGET_BYTES_BIG_ENDIAN): New
+ macros.
+
+ * config/obj-coff.c (stack_init): Don't do assignments inside
+ conditions.
+ (obj_coff_def): Simplified handling of symbol name a bit.
+ (tag_insert): Name argument is now pointer to CONST.
+ (obj_crawl_symbol_chain): Commented out.
+
+ * config/obj-coff.h: Use PARAMS macro in prototypes.
+
+ * write.c (relax_and_size_seg) [BFD_ASSEMBLER]: Don't indirect
+ through frchainP pointer if it is null.
+
+ * configure.in: Warn if BFD mode is explicitly turned off but is
+ required by specified target.
+ (mips ecoff targets): Don't need to set bfd_gas here; it gets
+ taken care of later.
+
+ * config/obj-coffbfd.c (crawl_symbols): Don't clear sy_forward
+ field.
+ (yank_symbols): Merge symbols only if sy_forward is null.
+
+ * config/tc-m68k.h (AOUT_MACHTYPE): Don't define if already
+ defined.
+
+ * tc.h (md_convert_frag) [BFD_ASSEMBLER]: Section arg is not
+ pointer.
+ * config/tc-m68k.c (md_convert_frag) [BFD_ASSEMBLER]: Ditto.
+
+ * config/tc-sparc.h (LOCAL_LABEL) [OBJ_ELF]: Anything starting
+ with "." is a local label.
+
+ * config/te-hppa.h, config/tc-hppa.h, config/tc-hppa.c: New config
+ files.
+
+ * config/te-linux.h, config/te-386bsd.h: New config files.
+ * configure.in (i386-*-linux, i386-*-bsd): Use them.
+ * config/tc-i386.h (TARGET_FORMAT): Select format based on target
+ environment.
+ (DOT_LABEL_PREFIX): Don't define for 386bsd or Linux.
+
+Wed May 5 13:14:01 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/obj-ecoff.c (init_file): Set fMerge to 0 since dbx seems
+ to want it that way.
+ (ecoff_build_symbols): Turn local st_Proc symbols into
+ st_StaticProc symbols. Set index field of external st_Proc and
+ st_staticProc symbols correctly.
+ * config/tc-mips.h (NO_LISTING): Don't define. People might want
+ listings.
+
+Tue May 4 21:22:54 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/obj-hp300.h, config/obj-hp300.c, config/te-hp300.h: New
+ files.
+ * configure.in (m68k-*-hpux): Use them.
+
+ * config/obj-aout.c (obj_pre_write_hook): Use AOUT_VERSION if
+ defined, otherwise zero.
+
+ * config/aout_gnu.h (OMAGIC): Don't define if already defined.
+
+Mon May 3 15:59:32 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * config/tc-sparc.c (sparc_ip): Allow any abs expression as an
+ address space number.
+
+Wed Apr 28 19:11:22 1993 Ken Raeburn (raeburn@deneb.cygnus.com)
+
+ * config/obj-aout.h (TARGET_DEFAULT): Don't default this at all.
+
+ * config/tc-a29k.c: Include ctype.h.
+ (define_some_regs): Added special-purpose registers for 29050.
+
+ * config/tc-i386.c (comment_chars) [TE_I386AIX]: Include "/".
+
+ * config/obj-coffbfd.c (fill_section): Don't set STYP_REG here.
+ (change_to_section): Set it here instead.
+
+Wed Apr 28 13:40:29 1993 Ian Lance Taylor (ian@rtl.cygnus.com)
+
+ * config/obj-ecoff.c (obj_symbol_new_hook): Make up a .file if one
+ hasn't been seen yet.
+ (add_ecoff_symbol): Don't refer to cur_file_ptr if it is NULL.
+
+Mon Apr 26 18:29:05 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * config/tc-sh.ch, config/tc-sh.h: New files supporting Hitachi
+ SH.
+
+Mon Apr 26 12:28:27 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * expr.c (operand): Fix unary plus operator (previously was the
+ same as '~' operator!).
+
+Wed Apr 21 00:20:11 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * write.c (cvt_frag_to_fill): Define even if BFD is defined.
+ (write_object_file): Do define if BFD_ASSEMBLER. Invoke
+ obj_check_file_symbols if defined. Call verify_symbol_chain_2
+ instead of open-coding it. Fix some bugs in patching up symbol
+ chain.
+ (relax_segment): Make some code we "ought to be able to" use for
+ all targets no longer conditionalized on ns32k target; instead, do
+ it always, and if the appropriate conditions fail, abort.
+
+ * symbols.c (DEBUG): Enabled.
+ (symbol_new): Make sure bfd_make_empty_symbol works.
+ (verify_symbol_chain_2): New function; takes one symbol as
+ argument, anywhere in the chain.
+ (dollar_label*): Use default initializers.
+
+ * as.c (perform_an_assembly_pass): Call md_begin here...
+ (main): ...and not here.
+
+ * config/tc-m68k.h (TARGET_FORMAT): Use a.out-sunos-big for a.out.
+ (tc_frob_symbol): New macro: Get rid of symbols in reg_section.
+
+ * config/tc-m68k.c (omagic): Don't define for BFD_ASSEMBLER.
+ (add_fix, add_frag): Now functions instead of macros.
+ (m68k_reg_parse, m68k_ip, md_estimate_size_before_relax, get_num,
+ s_data1, s_data2, s_bss): Use new *_section names, for
+ compatibility with BFD_ASSEMBLER mode; rewrite switch statements
+ to handle non-integral segT.
+ (tc_coff_fix2rtype, tc_aout_fix_to_chars,
+ tc_coff_symbol_emit_hook): Don't define for BFD_ASSEMBLER.
+ (tc_gen_reloc): New routine for BFD_ASSEMBLER.
+ (md_apply_fix, md_apply_fix_2): Renamed old md_apply_fix to
+ md_apply_fix_2; new md_apply_fix definition varies interface
+ depending on BFD_ASSEMBLER.
+ (md_convert_frag, md_convert_frag_1): Likewise. Use new *_section
+ names.
+
+ * config/obj-vms.c: Include config.h.
+ (version_string): Delete declaration.
+ (Write_VMS_MHD_Records): Use GAS_VERSION instead.
+ (vms_resolve_symbol_redef): New function, taken from VMS code in
+ symbols.c.
+ (_doprnt): Deleted.
+ (VMS_Store_Struct, VMS_Def_Struct, VMS_Set_Struct,
+ VMS_TBT_Block_End, get_VMS_time_on_unix, generate_suffix,
+ VMS_Psect_Spec): Fixed to compile under traditional C.
+ * config/obj-vms.h: Use PARAMS macro.
+ (vms_resolve_symbol_redef): Declare.
+ (RESOLVE_SYMBOL_REDEFINITION): New macro.
+ * symbols.c (colon): Remove some VMS-specific code, look for
+ RESOLVE_SYMBOL_REDEFINITION macro instead.
+
+ * config/tc-m68k.c (m68k_ip): Don't try expanding DBcc
+ instructions.
+
+ * config/tc-i386.c: Reordered some functions so inlining might
+ work. Use PARAMS in function declarations.
+ (reloc): New routine.
+ (md_assemble): Rearrange switch statements to work with
+ non-integral segT.
+
+ * struc-symbol.h [BFD_ASSEMBLER]: Undefine
+ SYMBOLS_NEED_BACKPOINTERS before defining it.
+
+ * subsegs.c (subseg_new_rest): Now static.
+
+ * read.c (pseudo_set): Better error message for difference of
+ symbols in different frags.
+
+ * Makefile.in (check): Pass down some new variables, indicating
+ pathname or program name for cc, nm, objdump.
+
+ * as.h (OUTPUT_FLAVOR): New macro.
+ * config/tc-sparc.c (tc_gen_reloc): Use OUTPUT_FLAVOR.
+
+ * configure.in: Initialize bfd_gas properly. Warn that ELF
+ support is incomplete.
+
+Thu Apr 15 22:39:05 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * read.c (float_cons): Accept null pointer return from md_atof.
+ * config/tc-m68k.c (md_atof): Return null for success.
+ * config/tc-sparc.c (md_atof): Ditto.
+
+Thu Apr 15 16:04:39 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * doc/as.texinfo: formatting and comment cleanups; show SPARC
+ alternative options in same style as other machines; simplify some
+ conditional use; include GPL as separate file (from texinfo dir)
+
+ * doc/Makefile.in: (as.info) include directory containing GPL in
+ makeinfo search path
+
+ * doc/h8.texi: new file; conditional settings for GAS manual
+ on Hitachi chips
+
+Tue Apr 13 15:31:40 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * doc/as.texinfo: mention SPARC architecture options.
+
+Fri Apr 9 17:43:11 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ * configure.in: Rearranged whitespace in per-host/per-target
+ sections. Added hooks for dropping in HPPA support (not included
+ yet). Separate out overrides of variables based on target format
+ and bfd-gas selection from actual target-specific commands. Add
+ error message for recognized but unsupported format name.
+
+Fri Apr 9 09:05:47 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/obj-ecoff.h (ecoff_build_lineno): Make ilineMax in
+ symbolic header match cline in FDR; the native linker seems to
+ want that.
+
+Thu Apr 8 15:51:28 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * doc/Makefile.in: as.texinfo is in $(srcdir). Use
+ $(srcdir)/as.texinfo explicitly in several places
+
+Thu Apr 8 15:15:02 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * doc/Makefile.in: update dvi, clean targets for new source
+ file structure
+
+Thu Apr 8 12:52:46 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/ho-decstatn.h: Define BROKEN_ASSERT if not __GNUC__,
+ rather than undefining know.
+ * configure.in: Match ultrix*, not just ultrix.
+
+Wed Apr 7 20:18:10 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * doc/as.texinfo: converted conditional markup to use new
+ Texinfo facilities, avoiding m4.
+
+ * doc/as-all.texinfo, all.m4, pretex.m4: deleted.
+
+ * doc/Makefile.in: recast doc configuration to use a link to an
+ included texinfo file.
+
+ * doc/all.texi: settings for generic form of documentation.
+
+Tue Apr 6 11:56:21 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * read.c (cons): Zero out frag when creating reloc.
+
+Mon Apr 5 09:41:58 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/tc-mips.c (gp_reference): Certain magic symbols can never
+ be referenced off the GP register.
+
+ * app.c (do_scrub_next_char): Handle states 9 and 10 correctly
+ when dealing with characters of type LEX_IS_TWOCHAR_COMMENT_1ST,
+ LEX_IS_STRINGQUOTE, and LEX_IS_ONECHAR_QUOTE.
+
+ * config/te-irix.h: New file; irix needs a different LOCAL_LABEL
+ definition from other MIPS targets.
+ * configure.in (mips-*-irix): Use emulation irix.
+
+Sun Apr 4 15:21:09 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * config/tc-h8500.c: Get relax size of branch instructions right,
+ (get_operand): Parse @sp+ correctly.
+
+Fri Apr 2 15:59:49 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * subsegs.h (segment_info_type) [BFD_ASSEMBLER]: Don't include
+ COFF section header field.
+
+ * configure.in: Print error message if host or target is not
+ supported.
+
+ * configure.in: If with-bfd-assembler, use obj-coff instead of
+ obj-coffbfd.
+
+ * config/ho-generic.h: Include string.h.
+
+Fri Apr 2 08:54:57 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/tc-mips.h (LOCAL_LABEL): Treat any label starting with
+ '$' as local, for any object file format.
+
+ * config/tc-mips.c (macro): Optimizations to branching code and a
+ couple of bug fixes from ralphc@pyrps5.eng.pyramid.com (Ralph
+ Campbell).
+
+ * config/ho-irix.h: New file; if not gcc, define BROKEN_ASSERT.
+ * configure.in (mips-sgi-irix*): Set gas_host to irix.
+
+Wed Mar 31 17:53:54 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * subsegs.c (subseg_new): Set output_section of new section.
+ * as.c (perform_an_assemly_pass): Don't set output_section here.
+ * expr.c (expr_part, expr): Turn off section assertions for ECOFF,
+ since it has additional sections.
+ * read.c (s_lcomm): For MIPS ECOFF, put small objects in .sbss,
+ not bss_section.
+ * config/obj-ecoff.h (TARGET_SYMBOL_FIELDS): Added
+ ecoff_undefined field.
+ * config/obj-ecoff.c (obj_symbol_new_hook): Initialize
+ ecoff_undefined field.
+ (add_file): If using stabs, just output a stabs symbol rather than
+ creating a new fdr.
+ (obj_ecoff_begin, obj_ecoff_bend): Ignore line number by reading
+ it with get_absolute_expression, rather than skipping it by hand.
+ (obj_ecoff_loc): If using stabs, just output a stabs symbol rather
+ than ECOFF line number information.
+ (obj_ecoff_stab): Accept non-zero values for stabs line number.
+ (ecoff_build_symbols): Set ifilesym correctly. Set storage class
+ to small, undefined and/or readonly sections if appropriate.
+ Don't output symbol names containing \001 characters.
+ (ecoff_frob_file): Make sure at least one fdr is output.
+ * config/tc-mips.h: Define TC_MIPS.
+ * config/tc-mips.c (g_switch_value): New static variable.
+ (md_assemble): Set gp size of output BFD.
+ (gp_reference): New function; returns 1 if expression can be
+ accesssed via gp. Always returns 0 if not using ECOFF.
+ (macro_build): Convert BFD_RELOC_LO16 to BFD_RELOC_MIPS_GPREL if
+ possible.
+ (macro): Generate sequences using gp if possible.
+ (md_parse_option): Ignore -EL and -EB. Parse -G.
+ (md_apply_fix): Added BFD_RELOC_MIPS_GPREL to ignored case.
+ (s_change_sec): Handle .rdata and .sdata for ECOFF.
+ (s_extern): Mark symbol as external. Set ecoff_undefined field.
+
+Tue Mar 30 10:11:41 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * output-file.c (output_file_create): Don't call as_perror for
+ filename rejected by application.
+
+ * as.c (main) [BFD_ASSEMBLER]: If errors occur, close and unlink
+ the output file.
+
+ * doc/as.texinfo: Don't use @value in node names for the moment;
+ references don't appear to work right.
+
+ * as.h (const, volatile): Put these definitions back, and use
+ them.
+
+ * doc/as.texinfo: First pass at using new texinfo features --
+ variables, conditional tests. Far from complete.
+
+Mon Mar 29 16:05:40 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * read.c: Temporary hack to handle some 64-bit constants. This
+ should be redone later.
+ (target_big_endian): Declare.
+ (big_cons): If it's set, reverse order of bytes being copied.
+ * config/tc-sparc.c (md_begin): Set target_big_endian.
+
+ * read.c (s_ignore): Delete declaration of is_end_of_line.
+
+ * config/obj-coffbfd.c (yank_symbols): Build list of file symbol
+ forward pointers properly.
+
+Mon Mar 29 13:47:33 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * config/obj-coffbfd.c (do_relocs_for): Fix bug where nrelocs
+ wasn't being stored into scnhdr.
+ * config/obj-coffbfd.h: Add prototype of s_get_segment.
+ * read.c (TC_START_LABEL): Default definition.
+ (read_a_source_file): Use TC_START_LABEL macro to work out
+ if a label has been seen.
+
+Mon Mar 29 12:56:56 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * configure.in: Set BFDDEF and BFDLIB at the top of Makefile, not
+ the bottom (make expands variables in dependencies when the
+ dependencies are read, not when they are used).
+
+ * config/obj-coffbfd.c (fill_section): Don't set NOLOAD bit for
+ a29k .bss section; the mondfe program doesn't like it.
+
+Sun Mar 28 08:12:53 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * config/tc-m68k.c: Use PARAMS macro, and use CONST instead of
+ const.
+ (current_architecture): Don't need initializer.
+
+Fri Mar 26 08:12:48 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * doc/none.m4: Define Z8000.
+ * doc/Makefile.in (as-*.texinfo): Refer to $(srcdir). Remove the
+ texinfo file before recreating it.
+ (TEXI2DVI): Need to set TEXINPUTS if "make as.dvi" is to work in
+ this directory.
+ (srcdir): Delete second, bogus definition.
+ (as.info): Look for as-*.texinfo in current directory rather than
+ in $(srcdir).
+ (as.dvi): Ditto.
+ (dvi): New rule.
+ * doc/configure.in: Create links to all as-*.texinfo files in the
+ source directory, if that's not the current directory.
+
+ * configure.in (per-host): Accept MIPS host with BSD version
+ number.
+ (per-target): Classify i486 as i386. Use generic cpu_type instead
+ of target_cpu in selecting format etc.
+
+ * app.c (do_scrub_next_char): Use .appfile, not .app-file.
+ * read.c (potable): Change .app-file to .appfile.
+
+ * config/ho-decstatn.h: Renamed from ho-decstation.h.
+ * configure.in: Adjusted.
+
+ * config/obj-bfd-sunos.*: Unused; deleted.
+
+ * Makefile.in (version.c, vers-stamp): Deleted.
+ (config.h): Define GAS_VERSION.
+ * as.c (version_string): Deleted declaration.
+ (main): Look for GAS_VERSION instead.
+
+ * doc/as.texinfo: Updated description of -a* (listing) options,
+ and describe how to pass them through from gcc.
+
+ * config/obj-coffbfd.c (do_relocs_for): Don't allocate storage or
+ process relocs if there aren't any relocs to process. Avoids
+ malloc/free bug on SCO too.
+
+ * as.h: Move local include files below system include files, to
+ avoid some redefinition complaints on some systems.
+ (const, volatile): Don't need these conditionally defined if we
+ use CONST and VOLATILE from ansidecl.h.
+ (seg_name): Use CONST, not const.
+
+Fri Mar 26 10:22:04 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/tc-mips.c: Reindented to GNU standards.
+
+Thu Mar 25 08:59:14 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/obj-coffbfd.c (do_relocs_for): Remove a29k special case.
+ (fixup_segment): Add a29k special case; the linker is not prepared
+ to see a segment offset here.
+
+ * app.c (do_scrub_next_char): Added new state, 10, modifying state
+ 9 to only keep a space in between identifier characters.
+
+Wed Mar 24 02:16:22 1993 david d `zoo' zuhn (zoo at poseidon.cygnus.com)
+
+ * Makefile.in: add dvi target; as-$(config).texinfo might live in
+ srcdir, might be in objdir.
+
+ * doc/Makefile.in: dvi depends on as.dvi
+
+Mon Mar 22 23:59:13 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: add installcheck target
+
+Mon Mar 22 16:25:57 1993 Jim Wilson (wilson@sphagnum.cygnus.com)
+
+ * config/tc-sparc.c (sparc_ip): Add support for membar mask names.
+ Add missing colons in prefetch error messages. Add support for
+ ASI names.
+
+Mon Mar 22 10:19:00 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/tc-mips.c (macro): Use $AT for any floating point load.
+
+Sat Mar 20 12:50:51 1993 Ken Raeburn (raeburn@urth.cygnus.com)
+
+ * config/tc-m68k.c (m68k_ip): For operand type 'M', reject
+ bignums, but don't emit error message.
+
+Fri Mar 19 21:02:19 1993 Jim Wilson (wilson@sphagnum.cygnus.com)
+
+ * Makefile.in (targ-cpu.o): Depend on config.h.
+
+Wed Mar 17 16:44:06 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * app.c (do_scrub_next_char): Added new state, 9, to avoid
+ dropping a space immediately following an identifier.
+ * expr.c, write.c: Rewrote assert expressions to not use multiple
+ lines; I don't think that can be done portably.
+ * config/tc-mips.c (macro): Use $AT if target register is zero in
+ load instruction, which it can be for a floating point load.
+
+Mon Mar 15 12:17:28 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * write.c (write_contents): Compute the relocs before writing out
+ the section contents.
+ * config/obj-ecoff.h, config/obj-ecoff.c: Numerous changes to get
+ symbol table and values right.
+ * config/tc-mips.h (LOCAL_LABEL): If OBJ_ECOFF, any label starting
+ with $L is local.
+ * config/tc-mips.c (tc_gen_reloc): If OBJ_ECOFF, adjust the addend
+ by the section vma.
+
+ * config/z8k.mt (TARG_CPU_DEPENDENTS): The relevant file is
+ z8k-opc.h, not z8k.h.
+
+ * config/obj-coffbfd.c (obj_coff_endef): Correct test for .bf
+ symbol.
+
+Fri Mar 12 18:33:36 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: recognize sparc-sun-solaris2* instead of -solaris2
+
+Fri Mar 12 12:00:07 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * expr.c, write.c: Ultrix native 4.2 cc requires assert condition
+ to be on a single line.
+
+Thu Mar 11 17:56:22 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * Makefile.in (config.h): Create file, writing out definitions of
+ target cpu, alias, and canonical name.
+ (ALL_CFLAGS): No longer define TARGET_CPU.
+
+ * Makefile.in (check): Print a message, instead of quitting
+ silently.
+
+ * as.c (main): Don't catch any signals, for now.
+
+ * version.c: Deleted.
+ * Makefile.in: Generate it, putting in only the version number
+ itself.
+ (VERSION): New variable.
+ * as.c: Include config.h.
+ (main): Reformatted version string. Include target alias. Don't
+ print if not requested (i.e., unknown -v argument).
+
+ * as.c (stralloc): Deleted.
+ (main): Call strdup instead.
+
+ * configure.in: Handle all 68300 series chips.
+ * config/tc-m68k.c: Include config.h.
+ (md_assemble): Assume TARGET_CPU is defined. Accept some 68300
+ series cpus as defaults.
+ (md_parse_option): Accept some m68300 series CPUs as defaults.
+
+Wed Mar 10 17:41:16 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * as.c (EXIT_SUCCESS, EXIT_FAILURE): Define to normal values if
+ not already defined.
+ (main, got_sig): Use them.
+ * config/ho-vms.h (EXIT_SUCCESS, EXIT_FAILURE): Reverse default
+ values.
+
+Tue Mar 9 07:40:06 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/obj-ecoff.c, config/obj-ecoff.h: Preliminary ECOFF
+ support.
+
+ * config/tc-mips.h (TARGET_FORMAT): Define based on OBJ_AOUT vs.
+ OBJ_ECOFF as well as TARGET_BYTES_*_ENDIAN.
+ (struct loc, struct proc, struct file): Moved to tc-mips.c within
+ #ifndef OBJ_ECOFF block, since ECOFF uses different versions.
+ * config/tc-mips.c: Rearranged for ECOFF support. Added
+ prototypes for all static functions. Moved existing minimal
+ debugging format support info #ifndef OBJ_ECOFF blocks.
+ (macro_build_lui): Eliminated sign_extend argument, because ECOFF
+ does not support a non sign extended high 16 bits reloc. Adjusted
+ all callers accordingly.
+ (tc_get_register): Renamed from get_register, and made non-static.
+
+ * config/mips-big.mt, config/mips-lit.mt: New files. Define
+ TARGET_BYTES_BIG_ENDIAN and TARGET_BYTES_LITTLE_ENDIAN,
+ respectively.
+ * configure.in (mips-*-bsd*): Use gas_target mips-lit.
+ (mips-*-ultrix*, mips-*-irix*, mips-*-ecoff): New targets, using
+ obj_format ecoff and gas_target mips-lit or mips-big.
+
+Tue Mar 9 07:43:01 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ * version.c: Bump to version 2.0.1.
+
+Tue Mar 9 07:40:06 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * write.c (chain_frchains_together): Check that seg_info (section)
+ is not NULL.
+ (write_object_file): Call obj_frob_file after setting the symbols,
+ not before.
+
+Tue Mar 9 00:00:00 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ * Version 2.0 released.
+
+Mon Mar 8 14:57:10 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/tc-i386.h (TC_COUNT_RELOC): Look for fx_addsy only.
+
+Fri Mar 5 09:05:55 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * read.h: Define stringer here.
+ read.c, config/obj-ieee.c, config/obj-tcm88k.c: Not any of these
+ places.
+
+Thu Mar 4 11:52:23 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * read.c (s_space): Multiply repeat count by mult, not fill.
+
+Thu Mar 4 05:20:42 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ * read.c: Include ctype.h.
+
+Wed Mar 3 10:41:46 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ Patches from Eric Youngdale:
+ * make-gas.com: Find obstack.obj if it's not in the current
+ directory.
+ * read.c (s_ignore): Don't declare is_end_of_line. It's
+ redundant, and triggers a VMS gcc compiler bug.
+
+ * write.c (write_object_file): Macro SUB_SEGMENT_ALIGN now takes
+ current segment as an argument. (Ignored in all cases but VMS.)
+ All callers and definitions changed.
+
+Tue Mar 2 11:56:19 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * listing.c: Cleaned up a bit, added prototypes, made NO_LISTING
+ case compile again.
+
+Tue Mar 2 08:53:34 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ * config/tc-m68k.c (isbyte): Accept all values from -255 to +255,
+ so "~0x80" won't be rejected.
+
+ * config/obj-elf.c: No longer include elf/reloc.h.
+ (obj_elf_section): Set SEC_READONLY and SEC_CODE for text section.
+ (obj_elf_stab, obj_elf_desc): Deleted do-nothing and commented-out
+ routines.
+ (obj_elf_xstab): New routine.
+ (obj_elf_set_size): Call as_warn, not fprintf. Pass desired
+ argument to s_ignore. Put "#if 0" around unused code.
+ (obj_pseudo_table): Use s_ignore instead of do-nothing routines.
+ Call elf_xstabs for .stabs and .xstabs operators.
+
+ * config/tc-sparc.h (TARGET_FORMAT) [OBJ_ELF]: Now "elf32-sparc".
+
+ * write.c (relax_and_size_seg): Set SEC_RELOC only if fixups are
+ present.
+
+ * configure.in: mips-bsd configuration was missing format spec.
+ Should use aout.
+
+ * Makefile.in (Makefile): Depends on configure.in.
+
+ * config/tc-mips.c (append_insn): Don't check for alignment of
+ frag in memory; alignment of instructions in section is a separate
+ matter.
+
+ * config/tc-mips.c (macro_build_lui): Fix some assumptions of ANSI
+ C availability.
+
+ * listing.h: Always provide function declarations, not macros, so
+ pcc won't lose.
+
+Tue Mar 2 00:50:43 1993 John Gilmore (gnu@cygnus.com)
+
+ * CONTRIBUTORS: Update Gilmore entry.
+
+Mon Mar 1 12:03:16 1993 Jim Wilson (wilson@sphagnum.cygnus.com)
+
+ * config/tc-sparc.c (sparc_ip): Correctly assemble prefetch
+ instructions. Accept integer prefetch function numbers.
+
+Wed Feb 24 14:58:19 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/tc-sparc.c (s_xword): Now call big_cons, so large
+ constants are accepted, but symbolic values are not. GCC will not
+ generate the latter currently.
+
+ * frags.c (frag_init): New function.
+ (zero_address_frag, bss_address_frag): Now initialized at run
+ time.
+ * as.c (main): Call frag_init.
+
+Wed Feb 24 10:32:42 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * app.c (do_scrub_next_char): In LEX_IS_LINE_COMMENT_START case:
+ Don't unget ch2 if we didn't get it.
+
+Wed Feb 24 04:14:07 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * doc/Makefile.in (TEXIDIR): Updated for new layout.
+
+ * config/tc-sparc.c (s_common): Add support for ELF version.
+ (tc_gen_reloc) [BFD_ASSEMBLER]: New function.
+ * config/tc-sparc.h (TARGET_ARCH, TARGET_FORMAT) [BFD_ASSEMBLER]:
+ New macros.
+ (md_convert_frag): New macro.
+
+ * config/tc-m68k.c (m68k_ip): For PC-relative addressing of a
+ symbol, fix the offset so "+2" isn't required.
+
+ * config/tc-i960.c (line_comment_chars, line_separator_chars):
+ Define as common/bss.
+ (op_hash, reg_hash, areg_hash, iclasses_seen, br_cnt): Default C
+ initializers are sufficient.
+
+ * config/obj-aout.h [BFD_ASSEMBLER]: Include libaout.h from bfd.
+ (TARGET_FORMAT) [BFD_ASSEMBLER]: Default to "a.out".
+ (S_SET_*, S_GET_*, obj_frob_symbol) [BFD_ASSEMBLER]: New macros.
+ (S_SET_TYPE) [!BFD_ASSEMBLER]: New macro.
+ * config/obj-aout.c: Use PARAMS macro for declarations. Remove
+ "IGNORE_DEBUG" conditional, since both branches are identical.
+ Use S_SET_TYPE, S_GET_TYPE, and S_GET_DESC instead of directly
+ referencing symbol structure members.
+ (obj_aout_frob_symbol) [BFD_ASSEMBLER]: New function.
+
+ * as.h (struct frag): Reordered a couple of fields for better
+ packing.
+
+ * write.c (record_alignment) [BFD_ASSEMBLER]: Record it in the
+ section info.
+ (write_contents) [BFD_ASSEMBLER]: New function.
+ (write_object_file) [BFD_ASSEMBLER]: Always handle -R here. Call
+ fix_new with BFD_RELOC_NONE instead of 0 or NO_RELOC. Call
+ obj_frob_file, obj_frob_symbol, tc_frob_symbol if defined.
+ (fixup_segment): Make sure common-section symbols get treated the
+ same as undefined symbols.
+ (fix_new) [BFD_ASSEMBLER]: Argument r_type is of type
+ bfd_reloc_code_real_type. Use seg_fix_{root,tail}P derived from
+ section info.
+ * write.h (fix_new): Update prototype.
+
+ * tc.h (md_operand, md_convert_frag, tc_headers_hook,
+ md_section_align, md_undefined_symbol): Don't provide prototypes
+ if these are defined as macros.
+ (md_convert_frag) [BFD_ASSEMBLER]: BFD version needs bfd and
+ section passed.
+
+ * symbols.c (symbol_new): Argument NAME is now pointer to const.
+ Simplified STRIP_UNDERSCORE code. Remove assumptions about null
+ pointers in freshly allocated storage. [BFD_ASSEMBLER]: Get new
+ BFD symbol.
+ (colon): Display other/desc fields of redefined symbol only if
+ S_GET_OTHER and S_GET_DESC are defined.
+ (symbol_make): Argument NAME is now pointer to const.
+ (symbol_find, symbol_find_base): Likewise.
+ (S_IS_*, S_GET_*, S_SET_*) [BFD_ASSEMBLER]: New functions.
+ * symbols.h: Fix prototypes for new const arguments. Add
+ prototypes for BFD_ASSEMBLER S_* functions.
+
+ * subsegs.c (subseg_change) [BFD_ASSEMBLER]: BFD version of code
+ for changing to an existing section.
+ (subseg_new_rest) [BFD_ASSEMBLER]: Split off from subseg_new,
+ called by subseg_new and subseg_set.
+ (subseg_new) [BFD_ASSEMBLER]: Rewritten to change to new section,
+ given section name and subseg number.
+ (subseg_set) [BFD_ASSEMBLER]: New function; change to a possibly
+ new section/subsection.
+
+ * read.c: Don't include ctype.h.
+ (cons) [BFD_ASSEMBLER]: For undefined symbols, use BFD_RELOC_32
+ for now; should be machine-dependent.
+
+ * configure.in: Accept *-*-elf and *-*-solaris* as ELF format
+ targets, forcing BFD use.
+
+Wed Feb 17 18:59:03 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/tc-sparc.c: Use PARAMS macro for static function
+ declarations. Use BFD_RELOC_ macros everywhere, with
+ compatibility macros declared for non-BFD mode.
+ (struct sparc_it) [BFD_ASSEMBLER]: Use bfd_reloc_code_real_type
+ instead of enum reloc_type.
+ (emit_sparc_reloc): Commented-out function deleted.
+ (md_convert_frag): Deleted.
+ (tc_aout_pre_write_hook): Don't define for BFD_ASSEMBLER.
+ (md_apply_fix): Changed calling sequence (conditionally) for BFD
+ version.
+ * config/tc-sparc.h (md_convert_frag): New macro.
+
+ * config/obj-aout.c (obj_aout_stab): Refer to undefined_section,
+ not SEG_UNKNOWN. Use S_SET_TYPE, S_GET_TYPE, S_GET_DESC instead
+ of referencing fields directly.
+
+ * write.c (cvt_frag_to_fill): New function; extracted from
+ write_object_file.
+ (write_object_file) [! BFD_ASSEMBLER]: Call it.
+ (relax_and_size_seg) [BFD_ASSEMBLER]: New function; relax section
+ and set its size and flags.
+
+ * struc-symbol.h (struct symbol) [BFD_ASSEMBLER]: Replace some
+ fields with BFD equivalents. Turn on back-pointers, and add
+ target-specific fields at end.
+
+Thu Feb 11 09:20:37 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/obj-coffbfd.c (fill_section): Don't set vaddr here.
+ (write_object_file): Set it here instead, so that fixup_segment
+ can see the correct value.
+
+Mon Feb 8 13:56:17 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * write.c (write_object_file): Check for errors and warnings and
+ bail out before processing contents.
+ (chain_frchains_together_1): New function, does most of the work
+ of remove_subsegs.
+ (chain_frchains_together) [BFD_ASSEMBLER]: New function.
+ (remove_subsegs) [! BFD]: Call it.
+ (write_object_file) [BFD_ASSEMBLER]: Converted to use BFD
+ structures and routines.
+
+ * config/obj-elf.*: New files.
+
+ * config/mips.mt, config/rs6000.mt: Deleted.
+
+ * config/h8300.mt: Don't specify compiler here.
+
+ * config/z8k.mt: The z8k code depends on the z8k opcode table,
+ not the h8300 one.
+ * config/tc-z8k.h: Comment fix.
+
+ * write.c: Reordered some functions for better inlining.
+ (fixup_segment): Linkrelax code is no longer conditional on
+ TC_I960.
+
+Thu Feb 4 12:45:16 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * config/{h8500.mt, tc-h8500.c, tc-h8500.h, obj-coffbfd.c,
+ obj-coffbfd.h}: support for the H8/500
+
+Wed Feb 3 19:28:18 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/obj-vms.h (SUB_SEGMENT_ALIGN): Define VMS version here.
+ * write.c (write_object_file): Not here.
+ (fix_new): Initialize fx_addnumber.
+
+ * listing.c: Don't include target-cpu.h explicitly, since as.h
+ includes it.
+
+Thu Jan 28 00:35:40 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * write.h [BFD_ASSEMBLER]: Don't declare next_object_file_charP,
+ *_fix_root, *_fix_tail, seg_fix_rootP, seg_fix_tailP.
+ (struct fix): Reordered fields for compactness and efficiency.
+ Converted some logical fields to 1-bit fields.
+
+ * config/obj-aout.h: Use PARAMS.
+ [BFD_ASSEMBLER]: Don't define/declare AOUT_MACHTYPE, seg_N_TYPE,
+ N_TYPE_seg, DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE.
+
+ * read.c: Don't include listing.h; as.h includes it. Removed
+ DONTDEF code.
+ [BFD_ASSEMBLER]: Include subsegs.h.
+ (old_buffer, new_broken_words): Default initialization is
+ sufficient.
+
+ * output-file.c [BFD_ASSEMBLER]: Include bfd.h, default TARGET_MACH
+ to 0, define stdoutput.
+ (output_file_create) [BFD_ASSEMBLER]: Call bfd_perror on failure.
+ Call bfd_set_arch_mach.
+ (output_file_close) [BFD_ASSEMBLER]: Call bfd_close, not
+ bfd_close_all_done. Call bfd_perror on failure.
+ (output_file_append) [BFD_ASSEMBLER]: Don't define.
+
+ * config/m68kcoff.mt (LOCAL_LOADLIBES): Delete definition.
+
+ * subsegs.h (segment_info_type): Always define. Omit field scnhdr
+ if not MANY_SEGMENTS. Define new field bfd_section if
+ BFD_ASSEMBLER.
+ (seg_info): New macro.
+
+ * expr.c, input-scrub.c: Use PARAMS macro. Deleted unused
+ variables, and some irrelevant comments.
+
+ * Makefile.in (ALL_CFLAGS): Include $(BFDDEF).
+ (LIBS): Include $(BFDLIB). Don't bother with $(CLIB).
+ * configure.in: Permit --with-bfd-assembler now, with a warning.
+ Variable need_bfd is now a boolean, as is new variable bfd_gas.
+ Set BFDDEF and BFDLIB in Makefile when appropriate.
+
+ * as.c: Removed "#ifdef DONTDEF" and "#ifdef comment" code.
+ (main): Refer to flag_always_generate_output instead of
+ flagseen['Z'].
+
+ * as.c (main) [BFD_ASSEMBLER]: Open output bfd.
+ (*_section) [BFD_ASSEMBLER]: Define them.
+ (perform_an_assembly_pass) [BFD_ASSEMBLER]: Initialize them, and
+ set section flags when appropriate.
+ * as.h (SEG_NORMAL) [BFD_ASSEMBLER]: Require that the specified
+ section is not absolute, undefined, or an assembler internal one.
+ (absolute_section, undefined_section): Always define.
+ * expr.c, read.c, symbols.c: Refer to *_section, not SEG_*; break
+ switch statements into if-else trees.
+ * symbols.c [MANY_SEGMENTS]: Deleted redundant definitions of
+ SEG_BSS and SEG_DATA.
+
+ * as.h (frag_now_fix): New macro.
+ * symbols.c (colon): Use it.
+
+Wed Jan 27 21:43:53 PST 1993 Ralph Campbell (ralphc@pyramid.com)
+
+ * config/tc-mips.c: Added mips support for mips-dec-bsd.
+ * config/tc-mips.h: Added mips support for mips-dec-bsd.
+ * config/ho-mipsbsd.h: Added mips support for mips-dec-bsd.
+ * config/mips-opcode.h: Added mips support for mips-dec-bsd.
+ * configure.in: Added mips support for mips-dec-bsd.
+ * atof-generic.c: Define TRUE and FALSE if not defined.
+
+Thu Jan 21 12:48:19 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * version.c: Bumped version number to 1.93.05.
+
+Wed Jan 20 17:11:53 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/obj-coff.c (obj_emit_relocations): Don't use #elif.
+ (obj_emit_lineno): Don't need return at end of void function.
+ (obj_symbol_new_hook): Ditto.
+
+ * config/tc-m68k.c: Removed some unused code.
+ (tc_aout_fix_to_chars): Array nbytes_r_length is now const.
+
+ * config/tc-m68k.h (TC_COUNT_RELOC): Don't emit reloc if only
+ offset field is set.
+
+Fri Jan 8 05:44:49 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/tc-sparc.c (sparc_ip): For %uhi and %ulo, if not
+ ENV64, emit no reloc.
+ (md_pseudo_table): For ".xword", call s_xword.
+ (s_xword): New function.
+
+ * config/tc-sparc.c (architecture_requested, warn_on_bump,
+ md_relax_table): Use default zero initialization.
+ (s_reserve): Since SEG_E2 is equivalent to SEG_BSS, just use the
+ latter, instead of selecting with preprocessor conditionals.
+
+Thu Jan 7 08:58:21 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: recognise all sparclite variants
+
+Thu Jan 7 05:25:25 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * read.c (s_data) [!BFD_ASSEMBLER]: Fix typo in 4 Jan change --
+ accidentally changed to use subseg_change where it should have
+ been subseg_new.
+
+Tue Jan 5 08:42:16 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * expr.c (operand): If character other than comma or newline is a
+ logical end-of-line character, use the newline case.
+ From Eric Youngdale:
+ (operand): Set X_add_number field for floating-point numbers.
+ (operand): Treat zero byte as end-of-operand.
+
+ * configure.in (per-target): Look for with_bfd_assembler option.
+ For now, only accept "no", until the merge is done.
+
+ Merged changes from Eric Youngdale (youngdale@v6550c.nrl.navy.mil):
+ * as.c, flonum-konst.c, hex-value.c, input-file.c, version.c,
+ config/obj-aout.h, config/obj-vms.c: VMS -> HO_VMS.
+ * read.c: Finish conversion to S_* macros in the VMS only
+ parts of the program. Add "const" modifier to hex_value.
+ * as.c, read.c, symbols.c, write.c: Change "ifdef VMS" to
+ "ifdef OBJ_VMS".
+ * expr.c: Add "const" modifier to hex_value.
+ * symbols.c: Finish conversion to S_* macros in the VMS only
+ parts of the program. Add "const" modifier to
+ md_[long,short]_jump_size. Remove declaration of const_flag
+ (which will be declared in obj-vms.h).
+ * write.c: Add "const" modifier to md_[long,short]_jump_size.
+ Fix arguments to VMS_write_object_file.
+ * config-gas.com: New file. Script for VMS systems to set up the
+ configuration to build gas for VMS, and create config.status.
+ * make-gas.com: Redone to work with new scheme.
+ * obj-vms.c: Patch to fix bug where we were not correctly parsing the
+ stabs directives.
+ * obj-vms.c: Define macros COPY_LONG and COPY_SHORT which
+ will swap bytes if needed on a big endian system. Use throughout
+ as needed.
+ * obj-vms.c (obj_aout_stab): Add code to generate listing file.
+ * obj-vms.c (VMS_typedef_parse): Add alias to correctly handle certain
+ types of malformed stabs. Change parsing algorithm so that we are
+ more certain of having all of the information that we need on hand.
+ * obj-vms.c (final_forward_reference): New function, used to help
+ resolve the data types of as many struct elements as possible
+ when some part of the struct is not fully defined by the compiler.
+ * obj-vms.c (VMS_LSYM_Parse): Correctly handle case of continuation
+ stabs directives.
+ * obj-vms.c (VMS_write_object_file): Define all vtable psects
+ as symbols as well in the object file. Look for external functions
+ that start with "__vt.", and turn them into variables, since the
+ g++ compiler is incapable of doing this.
+ * tc-vax.c: Add '1' option for backward compatibility with older GCC
+ versions.
+ * bignum-copy.c (bignum_copy): Fix bug where we pad with zeroes.
+ * input-scrub.c (as_where): Fix bug where as would crash if we did not
+ have the name of the source file yet.
+ * config/ho-vms.h: define HO_VMS, not HO_VAX.
+
+Mon Jan 4 05:17:26 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ * read.c (s_data): Always use "data_section", since it'll map to
+ SEG_DATA or SEG_E1 if needed.
+ (s_lcomm): Likewise with bss_section.
+ (s_fill): Use memset, not bzero.
+
+Thu Dec 31 04:29:27 1992 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * read.c: Deleted some code under "#ifdef DONTDEF" that was for
+ handling GDB symbol table data.
+
+ * config/obj-aout.h (segment_name): Delete definition.
+ (seg_name): Delete declaration.
+ * config/obj-bout.h (segment_name, seg_name): Ditto.
+ * config/obj-vms.h (segment_name, seg_name): Ditto.
+ * config/obj-coff.h (segment_name): Ditto.
+ * config/obj-coffbfd.h (segment_name): Ditto.
+
+ * Changes for BFD_ASSEMBLER:
+ * obj.h (obj_crawl_symbol_chain): Declare only if not
+ BFD_ASSEMBLER.
+ (obj_header_append, obj_pre_write_hook): Ditto.
+ * as.h (stdoutput): New var, defined only if BFD_ASSEMBLER.
+ (segT) [BFD_ASSEMBLER]: New typedef for "asection *".
+ (segment_name) If BFD_ASSEMBLER, look up BFD section name;
+ otherwise, use seg_name array.
+ (seg_name): Declare only if not BFD_ASSEMBLER.
+ (section_alignment): Declare only if not BFD_ASSEMBLER.
+ (big_section, reg_section, pass1_section, diff_section,
+ absent_section, text_section, data_section, bss_section): If
+ BFD_ASSEMBLER, declare as variables; otherwise, declare as macros,
+ mapping to segT enum values.
+ (tc_aout_fix_to_chars, next_object_file_charP): Force parse errors
+ if these are used or defined, if BFD_ASSEMBLER.
+ (subseg_set, subseg_new) [BFD_ASSEMBLER]: Functionality of old
+ subseg_new split into two functions.
+ (SEG_NORMAL): For BFD_ASSEMBLER, always return true, for now.
+
+ * as.h (volatile): Don't define if already defined.
+ (had_errors, had_warnings): Provide prototypes for ANSI C even if
+ NO_STDARG.
+ (as_bad, as_fatal, as_tsktsk, as_warn): For GNU C version 2,
+ declare with format attribute for -Wformat checking.
+
+Wed Dec 30 10:18:57 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * app.c, config/tc-*.c: Don't include read.h, since it is already
+ included by as.h.
+
+ * These are based on patches from Minh Tran-le
+ <mtranle@paris.intellicorp.com>.
+ * configure.in (i[34]86-ibm-aix*): Accept i486 for host. Use
+ obj_format coffbfd and gas_target i386coff for target.
+ (i[34]86-*-isc*): New host (uses sysv).
+ * config/i386aix.mt: Removed (no longer used).
+ * config/mh-i386aix (RANLIB): Use true rather than /bin/true.
+ (MINUS_G): Removed.
+ (LDFLAGS): Added, defined as -shlib.
+ * config/te-i386aix.h (REVERSE_SORT_RELOCS): Undefine.
+ * config/te-sco386.h (LOCAL_LABEL): Don't define.
+ (DOT_LABEL_PREFIX): Define.
+ * expr.c (operand): If DOT_LABEL_PREFIX, use .L0\001 as a label
+ name rather than L0\001.
+ * read.c (s_lcomm): Make a frag in SEG_BSS rather than using
+ local_bss_counter.
+ * symbols.c, symbols.h (local_bss_counter): Removed.
+ * write.c (write_object_file): bss no longer uses
+ local_bss_counter. Pass correct data and bss size to
+ VMS_write_object_file.
+ * config/obj-vms.c (VMS_write_object_file): Accept bss size as
+ argument, rather than using local_bss_counter.
+ * config/tc-m88k.c (s_bss): Don't use local_bss_counter.
+ * config/tc-sparc.c (s_reserve): Don't use local_bss_counter.
+ * config/obj-coffbfd.c (had_lineno, had_reloc): Removed.
+ (size_section): Restored sanity check.
+ (do_relocs_for): Base section address on s_paddr rather than
+ computing it. Adjust a29k R_IHIHALF special case to account for
+ section paddr (used to require paddr to be zero). If there are no
+ reclos, set s_relptr to 0. Set relocation size in object_headers.
+ (fill_section): Always set s_vaddr here, removing
+ ZERO_BASED_SEGMENTS case. Force s_scnptr for bss to 0. Don't set
+ NOLOAD for i386 .bss, because it confuses the SVR3 native linker.
+ Set STYP_INFO for .comment.
+ (coff_header_append): Use object headers and H_{SET,GET}_* macros.
+ Make aouthdr writing depend on OBJ_COFF_OMIT_OPTIONAL_HEADER.
+ (crawl_symbols): Handle 8 character section name correctly. Use
+ H_{SET,GET}_* macros.
+ (do_linenos_for): Set lineno size in object_headers.
+ (write_object_file): Use H_{SET,GET}_* macros. Don't bother to
+ set s_vaddr here. If string_byte_count remains 4, set it back to
+ 0, and only write strings out if there are some. Call
+ fill_section before do_relocs_for and do_linenos_for.
+ (obj_coff_section): Handle optional quoted second argument giving
+ section characteristics.
+ (obj_coff_bss): Added to handle .bss.
+ (obj_coff_ident): Added to handle .ident (puts string in .comment
+ section).
+ (obj_coff_lcomm): Put common symbols in .bss, not .data.
+ (fixup_mdeps): Change to segment. Call frag_wane after
+ md_convert_frag.
+ (fixup_segment): Explicitly check S_IS_COMMON before making 386
+ adjustment (already happened only for common symbols, but this is
+ clearer).
+ * config/obj-coffbfd.h (OBJ_COFF_OMIT_OPTIONAL_HEADER): Define.
+ * config/tc-i386.c (s_bss): Don't use if I386COFF.
+ (md_pseudo_table): Ignore .optim and .noopt.
+ (tc_coff_sizemachdep): New function.
+ * config/tc-i386.h (REVERSE_SORT_RELOCS): Undef, for SVR3
+ compatibility.
+ (LOCAL_LABEL): Removed definition.
+ (DOT_LABEL_PREFIX): Defined.
+
+Mon Dec 28 10:32:05 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * app.c (app_push): Use memcpy, not bcopy.
+ (do_scrub_next_char): For \", return " not '.
+ (symbol_chars): Now const.
+
+ * expr.c (operand): If not LOCAL_LABELS_FB, don't look for "0f"
+ and "0b". If LOCAL_LABELS_DOLLAR, check for "0$".
+
+ * config/obj-coff.h: Don't use #elif.
+
+ * config/ho-sunos.h: Don't include sys/stdtypes.h; 4.0.3 doesn't
+ have it. (Reported by Noah Friedman, friedman@gnu.ai.mit.edu.)
+
+Wed Dec 16 12:12:33 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * write.c, obj-ieee.c: don't define SUB_SEGMENT_ALIGN if it is
+ already defined.
+
+Tue Dec 15 12:40:11 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * app.c (do_scrub_begin): allow single quote strings if so
+ configured.
+
+ * config/*z8k*: checkpoint
+
+Sun Dec 13 00:04:38 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * read.c (read_a_source_file): avoid calling xmalloc (0).
+
+Sat Dec 12 15:26:34 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * listing.c: Call xmalloc, not malloc; don't declare malloc.
+
+ * Changes to support SCO 3.2v4:
+ * read.c (s_align_bytes, s_align_ptwo): If not SEG_DATA or
+ SEG_BSS, fill with NOP_OPCODE.
+ * config/i386coff.mt: Add opcode/i386.h to TARG_CPU_DEPENDENTS.
+ * config/obj-coffbfd.c (do_relocs_for): Increment addr even if not
+ using ZERO_BASED_SEGMENTS.
+ (fill_section): If ZERO_BASED_SEGMENTS, set segment addresses, but
+ never set segment address for SEG_E2 (.bss) and don't write out
+ SEG_E2 contents. Set .init and .fini sections to STYP_TEXT.
+ (obj_coff_endef): Don't merge labels or symbols awaiting forward
+ definitions, and don't merge tags with non-tags. Check for .bf
+ rather than just checking whether the second character is b and
+ the third character is f.
+ (obj_coff_val): gcc can generate values which we don't handle
+ correctly; discard information for now, since it only affects the
+ debugging information.
+ (tag_find_or_name): Don't insert tags in the symbol table.
+ (yank_symbols): Don't merge labels.
+ (write_object_file): Don't define SUB_SEGMENT_ALIGN if it is
+ already defined. Fill subsegments with NOP_OPCODE, not 0. Don't
+ set segment address if ZERO_BASED_SEGMENTS.
+ (obj_coff_section): Accept and ignore a trailing quoted string, as
+ used in AT&T i386 syntax.
+ (fixup_segment): Take segment as argument. On the i386, adjust PC
+ relative addends by the segment vaddr.
+ * tc-i386.h: Define SUB_SEGMENT_ALIGN.
+ * tc-a29k.h: Define ZERO_BASED_SEGMENTS.
+ * tc-i386.c: (i386_operand): If I386COFF, accept any segment type.
+
+Tue Dec 8 00:06:48 1992 Ken Raeburn (raeburn@rtl.cygnus.com)
+
+ * config/obj-coffbfd.c: Include libcoff.h.
+
+ * version.c: Now version 1.93.
+
+Mon Dec 7 00:39:09 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * config/tc-i386.c (md_pseudo_table): For 386bsd and linux, do
+ power-of-two alignment for .align.
+
+ * as.h: If BROKEN_ASSERT, just redefine `assert' to be trivial,
+ and leave everything else alone.
+
+Fri Dec 4 16:58:42 1992 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * Makefile.in (as.new): Don't bother saving as.old.
+
+ * write.c: Conditionalize on OBJ_VMS, not VMS.
+ (magic_number_for_object_file): Don't define if OBJ_VMS.
+
+ * config/obj-vms.c: Changes for traditional C.
+
+Thu Dec 3 01:24:07 1992 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * config/ho-generic.h (malloc, realloc): Declare.
+
+ * Lots of comment/whitespace changes.
+
+ * write.h (struct fix): Some fields reordered, narrowed.
+
+ * read.c (MASK_CHAR): Define using C types, not magic number.
+
+ * as.c, input-file.c: Deleted some unused code.
+
+ * app.c, as.h: Doc fix.
+
+ * flonum-konst.c, flonum-mult.c: Include ansidecl.h.
+
+ * as.h (xmalloc): Argument is long.
+
+ * xmalloc.c (error): Remove declaration; as.h takes care of it.
+
+ * doc/as.texinfo: Regrouped documentation of some command-line
+ options. Updated options documentation for m68k. Some minor
+ wording/punctuation changes.
+
+Mon Nov 30 11:42:11 1992 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * configure.in: Accept target OS "vms".
+
+ * symbols.c: Merged ANSI and non-ANSI function decls, using
+ PARAMS macro.
+
+ * xmalloc.c: Just include as.h, don't bother trying to figure out
+ other header files.
+
+ * strstr.c, strerror.c: Deleted.
+ * Makefile.in: Deleted references.
+
+ * config/tc-ns32k.c: Don't include header file for string
+ declarations; leave that to ho-*.h.
+
+Fri Nov 27 04:11:36 1992 Ken Raeburn (raeburn at cambridge-laptop.cygnus.com)
+
+ * config/coff_gnu.h [TC_I860]: Guesses for reloc type values,
+ imported from FSF sources.
+
+ * messages.c (strerror): Declare unconditionally.
+
+ * as.h: Delete alloca and register definitions.
+
+ * config/atof-ieee.c (mask): Now const.
+
+ * obstack.c, obstack.h: Deleted.
+
+ * as.h (flag_readonly_data_in_text): New flag.
+ * as.c (main): Set it for -R.
+
+ * as.h (flag_suppress_warnings): New flag.
+ * as.c (main): Set it for -W.
+ * messages.c (as_warn): Check it instead of flagseen['W'].
+
+ * as.h (flag_always_generate_output): New flag.
+ * as.c (main): Set it for -Z.
+
+ * config/tc-sparc.h: Define NEED_FX_R_TYPE.
+ * config/tc-a29k.h: Ditto.
+ * write.h (struct fix): Don't conditionalize fx_r_type field on TC
+ macros.
+
+ * as.h: Merged ANSI and non-ANSI function decls, using PARAMS
+ macro.
+ * bignum.h, expr.h, flonum.h, frags.h, input-file.h, listing.h,
+ obj.h, output-file.h, read.h, struc-symbol.h, symbols.h, tc.h,
+ write.h: Likewise.
+ * read.c: Likewise.
+
+ * xmalloc.c: Conditionalize on HAVE_MALLOC_H, not USG. Fold in
+ xrealloc from xrealloc.c.
+ * xrealloc.c: Deleted.
+ * Makefile.in (REAL_SOURCES, OBJS): Adjusted.
+
+ * configure.in: For host CPU a29k, rs6000, vax, consider using bsd
+ or vms ho- files.
+
+ * config/ho-sysv.h (setbuffer, HO_USG): Deleted.
+
+ * config/atof-ieee.c (atof_ieee): Exponent field isn't a pointer;
+ don't initialize it with NULL.
+
+ * config/ho-vax.h (M_VAX): Deleted; was unused.
+
+ * README-vms, config/ho-vms.h, config/obj-vms.c, config/obj-vms.h:
+ New files imported from FSF version, contributed by Eric Youngdale.
+ * README-vms-dbg, config/vms: Deleted.
+
+ * ChangeLog, config/ChangeLog: Merged.
+
+ * config/*tahoe*, configure.in: Tahoe support brought in from FSF
+ version.
+
+ * input-file.c (input_file_open): Eliminate call to setvbuf.
+ [USG] (setbuffer): Deleted macro.
+
+Mon Nov 23 11:00:16 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * all files: Whitespace changes for GNU indentation style, done by
+ GNU `indent'. Some cleanup still needed, especially of comments.
+
+ * configure.in: No te-386bsd.h file exists; don't try to use it.
+
+ * obj-coff.c (obj_coff_endef): Use as_warn, not fprintf.
+
+ * tc-m68k.c (md_assemble): Don't complain about 68000 with 68881;
+ could be doing emulation.
+
+Thu Nov 19 11:47:19 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ z8000 documentation
+ * doc/Makefile.in, doc/all.m4, doc/as-all.texinfo, doc/as.texinfo:
+ all modified.
+
+Tue Nov 10 09:49:24 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in (as.o, obj-format.o): added dependency on subsegs.h.
+
+ * subsegs.h: add extern to segment_info declaration.
+
+ * read.h: added extern declarations for comment_chars,
+ line_comment_chars, and line_separator_chars.
+ read.c, app.c: removed definitions of comment_chars,
+ line_comment_chars, and line_separator_chars.
+
+ * tc-m68k.c (m68k_reg_parse): If REGISTER_PREFIX isn't defined,
+ still accept (but don't require) OPTIONAL_REGISTER_PREFIX before
+ the register name.
+ (insert_reg): put REGISTER_PREFIX before register names before
+ putting them in the symbol table.
+ * tc-m68k.h (OPTIONAL_REGISTER_PREFIX): Define to be "%", if not
+ M68KCOFF.
+
+ * obj-coffbfd.c (fill_section): set STYP_NOLOAD bit for .bss
+ section.
+
+ * atof-ieee.c, atof-ns32k.c, tc-*.c: made EXP_CHARS, FLT_CHARS,
+ comment_chars, line_comment_chars and line_seperator_chars
+ consistently const, and always initialized them. Included read.h.
+
+Thu Nov 5 17:55:41 1992 Jim Wilson (wilson@sphagnum.cygnus.com)
+
+ * tc-sparc.c (sparc_ip): Add code to flag error if an absolute
+ constant will not fit in an immediate field.
+ (md_apply_fix, RELOC_BASE13 case): Check for relocation overflow.
+
+Wed Nov 4 07:50:46 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * obj-coff.c (callj_table): Delete global variable.
+ (obj_emit_relocations): Define it locally here, and only if
+ TC_I960 is defined.
+
+ * tc-m68k.c (m68k_reg_parse): Underscore is part of a symbol name.
+ (m68k_ip): Don't warn about bignum used as float bit-pattern.
+
+ * obj-coff.c: Replaced ANSI and non-ANSI function declarations
+ with a single set using PARAMS macro.
+
+ * tc-i960.c (tc_bout_fix_to_chars): Bit-field fixups want a length
+ of 2.
+
+ * tc-i960.c: Missed a couple of 0->NO_RELOC conversions.
+
+ * tc-i960.h (N_BALNAME, N_CALLNAME): Define as char-type values,
+ so widening works consistently.
+
+Wed Oct 28 08:52:34 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * version.c: Put conditional "const" before version_string, not
+ before dummy function for VMS. Now version 1.91.03.
+
+ * app.c (do_scrub_next_char): Need double-\ before `000' to show
+ printed rep of null character.
+
+Fri Oct 23 14:40:38 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * obj-coffbfd.c (write_object_file): check return value of
+ bfd_close_all_done.
+
+Tue Oct 20 12:18:08 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * Support for i386-sysv.
+ obj-coffbfd.c (do_relocs_for, write_object_file): set segment
+ addresses to reasonable sizes. New define ZERO_BASED_SEGMENTS can
+ be used to set them all to zero as was done before.
+ (fill_section): segment addresses now set in write_object_file.
+ (fill_section): Don't set STYP_NOLOAD for .bss section.
+ (fixup_segment): 386 uses strange common symbol format.
+ tc-i386.c (tc_coff_fix2rtype): use R_DIR32, not R_RELLONG, for
+ compatibility with SVR3.2 linker.
+ * configure.in: i386-sysv and i386-sco use coffbfd.
+
+ * app.c (do_scrub_next_char): discard whitespace after a label.
+
+Sat Oct 10 12:33:45 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: differentiate between SunOS 4 and Solaris2 for Sun4
+ hosts, use the sysv configuration for solaris2
+
+Mon Oct 5 09:28:57 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ fix i960+non-bfd coff bit rot.
+ * obj-coff.c (c_dot_file_symbol, obj_coff_ln, obj_coff_line):
+ support for C source listings. (obj_coff_endef): look in the right
+ part of the symbol for the symbol name
+
+ * tc-m68k.c (get_num): make it work for all segments, not just the
+ first three.
+
+Mon Oct 5 03:30:36 1992 Mark Eichin (eichin at tweedledumber.cygnus.com)
+
+ * configure.in: recognize i386-*-bsd emulation.
+
+Thu Oct 1 23:05:12 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: use the cpu-vendor-os triple for host and target
+
+Tue Sep 29 12:22:52 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * obj-coffbfd.c (write_object_file): don't fixup for the z8k
+ * tc-z8k.c: lots of bug fixes
+
+Tue Sep 29 10:51:55 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * tc-i960.h, tc-i960.c: avoid the ANSI preprocessor addition
+ #elif, since it is not supported by old compilers.
+ ho-rs6000.h, tc-m68k.c: the native RS/6000 compiler miscompiles a
+ couple of expressions in tc-m68k.c.
+
+Mon Sep 28 21:18:24 1992 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * read.c (cons): If NO_RELOC is defined, use it.
+
+ * tc-i960.c (get_cdisp): Use NO_RELOC, not 0, in call to fix_new.
+
+Fri Sep 25 18:18:52 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * tc-m68k.h: if M68KCOFF, define DOT_LABEL_PREFIX (to require
+ local labels to start with a .) and set REGISTER_PREFIX to %.
+ tc-m68k.c (m68k_reg_parse): accept REGISTER_PREFIX if defined.
+
+Fri Sep 25 17:53:43 1992 John Gilmore (gnu@cygnus.com)
+
+ * messages.c: Comment changes.
+
+Fri Sep 25 14:12:58 1992 Ken Raeburn (raeburn@kyriath.cygnus.com)
+
+ * as.h: Test if __STDC__ is defined only, don't test its value.
+ * messages.c: If __STDC__ is not defined, define NO_STDARG.
+
+Thu Sep 24 12:42:32 1992 Brendan Kehoe (brendan@rtl.cygnus.com)
+
+ * listing.c (debugging_pseudo): Add stabs and stabn as things to
+ ignore.
+
+Tue Sep 22 13:02:07 1992 Sean Eric Fagan (sef@cygnus.com)
+
+ * obj-coffbfd.c (do_relocs_for,fill_section): now allocate all
+ sections starting from zero, rather than making them consecutive.
+ This makes subsequent reloc calculations easier, esp if the object
+ format doesn't understand addends. (obj_coff_lcomm): (maybe temporarily)
+ allocate lcomm in .data rather than in .bss. It seems that some
+ tools can't cope with a non-zero sized bss before linkage.
+
+Tue Sep 22 15:10:51 1992 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * tc-m68k.c: Replace "enum m68k_architecture" with "int"
+ throughout. That enum no longer means what we thought it meant.
+
+ * tc-m68k.c (md_assemble, md_parse_option): Handle new
+ "-mno-688[58]1" options.
+
+ * tc-m68k.c: Added CPU32 support.
+
+Fri Sep 18 08:02:18 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * tc-m68k.c (m68k_ip): An(disp) is not pc relative.
+
+Tue Sep 15 17:25:05 1992 Jim Wilson (wilson@sphagnum.cygnus.com)
+
+ * Makefile.in (as.new): Remove dependence on LOCAL_LOADLIBES.
+ Change LIBDEPS dependence to LIBS.
+
+Tue Sep 15 15:32:02 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in (install): if $(tooldir) exists, install as in
+ $(tooldir)/bin.
+
+Sun Sep 13 20:30:10 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * Added WARN_SIGNED_OVERFLOW_WORD define to give an error if any
+ .word is < -32768 or > 32767. The -J flag causes the error to be
+ ignored. This is to catch over-sized switches generated by gcc on
+ systems which don't support the broken .word hack.
+ as.c (main): permit -J if WARN_SIGNED_OVERFLOW_WORD.
+ write.c (fixup_segment): check for signed .word overflow if
+ WARN_SIGNED_OVERFLOW_WORD.
+
+ * write.c (fixup_segment): fixed missing parens in expression
+ checking for byte or word overflow.
+
+ * obj-coffbfd.h: define WARN_SIGNED_OVERFLOW_WORD.
+ obj-coffbfd.c (fixup_segment): check for signed .word overflow if
+ WARN_SIGNED_OVERFLOW_WORD.
+
+ * obj-coffbfd.c (fixup_segment): fixed missing parens in
+ expression checking for byte or word overflow.
+
+Fri Sep 11 10:21:04 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ Support for i386 coff
+ * obj-coffbfd.h : added stuff
+ * tc-i386.c (tc_coff_fix2rtype): new function
+ * tc-i386.h : new coff defines
+
+Thu Sep 10 09:23:15 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * input-scrub.c (input_scrub_push): call input_file_begin, not
+ input_scrub_begin.
+ messages.c (as_perror): print ": " between the passed in error and
+ the strerror, like perror does.
+
+Wed Sep 9 11:06:25 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in: use gas_target instead of modifying target_cpu.
+ From Steve Chamberlain:
+ Makefile.in: Handle m68*-*-coff*.
+ read.c, read.h: add mult argument to s_space
+
+ * tc-m68k.c (m68k_ip, m68k_ip_op, get_num, try_moto_index): merge
+ Motorola and MIT syntax; gas can now assemble either type of
+ file.
+ tc-m68kmote.c, tc-m68kmote.h: removed now superfluous files.
+ From Steve Chamberlain:
+ m68kcoff.mt: for m68k COFF.
+ obj-coffbfd.c: (fixup_mdeps) added
+ (size_section) removed bad sanity check
+ (fill_section) added rs_machine_dependent case
+ (write_object_file) call fixup_mdeps
+ (fixup_segment) set fx_subsy to 0.
+ obj-coffbfd.h: define WORKING_DOT_WORD (too hard to support) and
+ handle m68k.
+ tc-m68k.c, config/tc-m68k.h: added m68k COFF support and Motorala
+ pseudo ops.
+
+Tue Sep 8 17:10:58 1992 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * Makefile.in (LIBS): Include opcode library.
+
+Fri Sep 4 18:20:56 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * config/tc-m68k.c (get_num, case SEG_BIG): If only small integers
+ including zero are accepted, pass +0.0.
+
+Sun Aug 30 21:24:46 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in: map "as" through program_transform_name when
+ installing.
+
+ * doc/Makefile.in: map "as" through program_transform_name when
+ installing.
+
+Sat Aug 29 12:11:12 1992 Jim Wilson (wilson@sphagnum.cygnus.com)
+
+ * Makefile.in (as.new): Depend on LOCAL_LOADLIBES.
+
+Fri Aug 28 16:25:22 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * obj-bout.h, obj-bout.c (obj_header_append, obj_symbol_to_chars),
+ tc-i960.c (md_ri_to_chars): Always output bout object file in
+ little endian byte order (used to use endianness of host).
+
+Tue Aug 25 15:50:48 1992 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * config/tc-m68k.c (init_table): Now const. Always include 68851
+ data, so that "bc" is available to 68040 cache instructions.
+ Added "tt0", "tt1", and 68ec030 variants.
+ (md_assemble): Complain if 68000 (only) and 68881 are specified.
+ (enum _register): Added TT0, TT1.
+ (m68k_ip, cases '3' and 't'): Handle new operand type codes. Pass
+ line number correctly in "internal error" messages. Don't print
+ architecture-mismatch message for operand errors.
+
+ From Colin Smith (colin@wrs.com):
+ * config/tc-m68k.c (m68k_ip, case '_'): Use addword twice rather
+ than install_operand.
+
+Tue Aug 25 15:13:48 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * listing.c (buffer_line): rewind to the start of include
+ files, they might be included twice.
+
+ * z8k.c, z8k.h, z8k.mt: z8000 support stuff
+
+Mon Aug 24 12:45:43 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in: defined TARGET_CPU for C code so that it can choose
+ one element of a family.
+
+ * tc-m68k.c: use TARGET_CPU to choose default cpu type.
+
+ * te-generic.h: default to LOCAL_LABELS_DOLLAR and LOCAL_LABELS_FB
+ so that we can assemble hand-written libgcc code.
+
+Fri Aug 21 14:38:44 1992 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * messages.c (as_warn): Use fputs, not fprintf, with a buffer that
+ has already been formatted (but may still contain %-characters).
+ (as_bad): Likewise.
+
+Wed Aug 19 11:20:59 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * tc-m68k.c, tc-m68kmote.c: the cas2 instruction is supposed to be
+ written with indirection on the last two operands, which can be
+ either data or address registers. Added a new operand type 'r'
+ which accepts either register type. Added '(' to notend stuff in
+ tc-m68kmote.c to accept (a0):(a2) in cas2 instruction.
+
+Wed Aug 19 09:25:09 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * as.h (enum _relax_state): Start off at one, not zero, to better
+ catch uninitialized-variable errors.
+ (linkrelax): Declare new variable.
+
+ * messages.c (warning_count, error_count): Default initializer is
+ sufficient.
+
+ * write.c: Merged some declarations, using PARMS macro.
+ (text_frag_root, data_frag_root, bss_frag_root, text_last_frag,
+ data_last_frag): No longer static.
+ (write_object_file, case rs_align or rs_org): If HANDLE_ALIGN is
+ defined, call it. Change segments before calling fixup_segment.
+ (relax_align): If linkrelax, provide extra padding.
+
+ * obj-bout.c (obj_emit_relocations): Emit alignment relocs despite
+ their not having symbols associated.
+
+ * tc-i960.c (norelax, instrument_branches): Default initializer is
+ sufficient.
+ (linkrelax): Delete variable definition.
+ (mem_fmt): Call fix_new with NO_RELOC.
+ (tc_bout_fix_to_chars): Handle alignment relocs.
+ (i960_handle_align): New function.
+ * tc-i960.h (linkrelax): Delete declaration.
+ (HANDLE_ALIGN): New macro; calls i960_handle_align.
+ (NEED_FX_R_TYPE, NO_RELOC): New macros.
+
+Tue Aug 18 14:59:21 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * config/sparc.mt: New file. Grab sparc opcode table from bfd
+ library.
+
+Tue Aug 18 14:16:38 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in: always create installation directories. Removed
+ MINUS_G, set CFLAGS to default to -g, added FLAGS_TO_PASS, passed
+ FLAGS_TO_PASS to recursive makes.
+
+ * doc/Makefile.in: always create installation directories.
+
+Mon Aug 17 15:09:56 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * input-scrub.c (input_scrub_pop, input_scrub_push): memcpy was
+ being used with args swapped, causing occasional lossage when
+ refilling buffers after an include file.
+
+Mon Aug 17 13:18:51 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * messages.c (as_tsktsk): Use correct ANSI form for stdarg
+ version. Discard bogus DONTDEF version.
+ (as_warn, as_bad, as_fatal): Likewise.
+
+Fri Aug 14 18:31:14 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * config/tc-m68k.c (m68k_ip): If instruction is invalid for the
+ selected architecture, print a message saying so and listing what
+ processors support it, rather than saying "operands mismatch".
+
+Thu Aug 13 13:53:19 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * as.h [BROKEN_ASSERT]: If defined, turn off all assertion checks.
+
+ * config/ho-rs6000.h (M_RS6000): Don't define it.
+ (free): Declare it.
+ (BROKEN_ASSERT): Define it if not __STDC__.
+
+Tue Aug 11 12:58:14 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * sparc.mt: New file.
+
+Mon Aug 10 14:37:08 1992 Per Bothner (bothner@cygnus.com)
+
+ * tc-m68k.c: ".align N" means align to N-byte boundary *only*
+ if TN_SUN3; otherwise align to 2**N-byte bounary.
+
+Thu Aug 6 12:10:39 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * read.c (s_fill): make the .fill size clamped error a warn and
+ fix bug where 0's were always placed.
+
+ * config/tc-h8300.c: if a :8 is seen after an operand, fill top
+ two bytes of any constant with 0xff:
+
+Wed Aug 5 12:02:40 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * config/tc-m68k.c (md_pseudo_table): fix the .align thing
+ the right way; for just the 68k. Sun 3 .align is nbytes, not ptwo.
+
+Wed Aug 5 01:54:34 1992 John Gilmore (gnu at cygnus.com)
+
+ * tc-m68k.c (try_index): Error if index scaling specified and
+ assembling for an older CPU than a 68020.
+
+Sat Aug 1 19:10:13 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * config/tc-sparc.c (tc_aout_fix_to_chars): If pc-relative, take
+ fx_offset into account.
+
+Fri Jul 31 21:53:28 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * configure.in (mips host): Accept "ultrix" with version number.
+
+ * expr.c (floating_constant): Separate "=-" to avoid confusing
+ ancient or broken compilers.
+
+ * config/tc-m68k.c (m68k_ip): Mismatch error could also indicate
+ processor/opcode mismatch, so reword the error message.
+ (md_assemble): If no CPU has been set (even if FPU/PMMU
+ characteristics have been), default to 68020. Don't need extra
+ quotes around error string.
+
+Fri Jul 31 12:26:34 1992 Jim Wilson (wilson@sphagnum.cygnus.com)
+
+ * read.c (potable): Revert sac's incorrect change made Jul 13.
+ Align really is supposed to be ptwo not nbytes.
+
+Mon Jul 20 02:51:59 1992 D. V. Henkel-Wallace (gumby@cygnus.com)
+
+ * Makefile.in: _Do_ include libiberty. (from sef)
+
+Fri Jul 17 15:15:28 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * expr.c (integer_constant): Handle "0f" and "0b" label references
+ properly.
+
+Thu Jul 16 08:20:17 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * write.c (fixup_segment): if relaxing, don't do anything.
+ * config/obj-bout.[ch] : maintain the a_relaxable file header info
+ * config/tc-i960.c: new option -linkrelax
+
+Mon Jul 13 14:11:36 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * expr.c (expr): allow SEG_BSS in expressions
+ * read.c (potable): align should be nbytes, not ptwo!
+ * write.c (write_object_file): extra glue for new bss attributes
+ (relax_segment): SEG_BSS is ok now
+ * config/tc-m68k.c (m68k_ip_op): can now parse more @( modes
+
+Mon Jul 6 17:09:32 1992 Steve Chamberlain (sac@cygnus.com)
+
+ * obj-coffbfd.c (fill_section): mark .lit sections as STYP_LIT
+
+Mon Jun 1 16:20:22 1992 Michael Tiemann (tiemann@cygnus.com)
+
+ * configure.in: recognize m680x0 as having sun3 emulation mode for
+ vxworks environment.
+
+
+Tue Jun 30 20:25:54 1992 D. V. Henkel-Wallace (gumby@cygnus.com)
+
+ * Makefile.in: Add program_suffix (parallel to program_prefix)
+
+Wed Jun 24 10:57:54 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * app.c (process_escape): new function to handle escapes the right
+ way, (do_scrub_next_char): use new function
+ * cond.c (s_ifdef): do ifdef/ifndef right
+ * read.c (s_fill): make the , expressions optional like the doc
+ says
+ * config/tc-h8300.[ch]: better warnings
+
+Tue Jun 9 07:54:54 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * subsegs.c (subsegs_begin): create bss0_frchainP in the same was
+ as data0_frchainP
+
+ * write.c (write_object_file): various changes to handle data in
+ the BSS segment in much the same was as stuff in the DATA segment.
+
+ * tc-m68k.c (m68kip): Fix typo so that only arch's >=68020 do
+ pcrel data stuff. (md_estimate_size_before_relax): when relaxing a
+ 68010 bxx into a bra+6 jmpxx, put the bytes of the jmp opcode into
+ the right place. (s_bss): Don't put .bss stuff into SEG_DATA, put
+ it into SEG_BSS
+
+Thu Jun 4 11:59:13 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * expr.c(expr): allow SEG_REGISTER in expressions.
+ * read.c(pseudo_set): register expressions can be the source of a
+ set.
+ * subsegs.c (subseg_new): Now -R forces all changes to SEG_DATA to
+ goto SEG_TEXT (if a.out)
+ * write.c (write_object_file): If a.out don't use the old way for
+ -R.
+ * config/obj-a.out (s_sect): complain if the user tries to use a
+ subsegment with a value which might interfere with out -R hackery.
+ * config/tc-m68k.c (m68k_reg_parse): lookup names in symbol table
+ rather than use ugly if tree. (init_regtable): insert register
+ names into symbol table.
+
+Tue Jun 2 16:47:09 1992 Steve Chamberlain (sac@cygnus.com)
+
+ * write.c (write_object_file): keep the fix_tail clean, which
+ fixes a bug in -R where relocations were being lost.
+
+Mon Jun 1 16:20:22 1992 Michael Tiemann (tiemann@cygnus.com)
+
+ * configure.in: recognize m680x0 as having sun3 emulation mode for
+ vxworks environment.
+
+Sun May 31 05:33:00 1992 david d `zoo' zuhn (zoo@cygnus.com)
+
+ * configure.in: recognize m680x0 as an m68k
+
+Thu May 28 11:22:02 1992 Jim Wilson (wilson@sphagnum.cygnus.com)
+
+ * configure.in: Recognize sparclite as a sparc variant.
+
+ * tc-sparc.c: Use new ARCHITECTURES_CONFLICT_P macro. Mention new
+ -Asparclite flag.
+
+Tue May 26 16:47:56 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * config/tc-a29k.c: lint
+ * listing.c, expr.c: patches from Andrew Smith
+
+Thu May 14 17:22:48 1992 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * doc/Makefile.in: use m4 rather than gm4.
+
+Mon May 4 18:56:19 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * obj-coffbfd.c: use is a synonym for section, (do_relocs_for):
+ calc the base of relocs correctly.
+ * tc-a29k.c (parse_operand): allow expressions to be in any section.
+
+Mon Apr 27 13:13:31 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * as.c, write.c: use -K rather than -k for the broken word warning
+ option.
+
+Tue Apr 21 13:35:30 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in: do not print recursion lines.
+
+Wed Apr 15 21:19:31 1992 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * Makefile.in: the tooldir copy of gas goes directly in tooldir.
+
+Tue Apr 14 14:50:22 1992 Ken Raeburn (Raeburn@Cygnus.COM)
+
+ * write.c (write_object_file): For b.out format, round up section
+ start addresses to match required alignment.
+
+Thu Apr 9 05:45:29 1992 Ken Raeburn (Raeburn@Cygnus.COM)
+
+ * Makefile.in (install): Install into $(tooldir)/bin, since that's
+ where gcc looks for it.
+
+Tue Apr 7 15:12:15 1992 Sean Eric Fagan (sef@cygnus.com)
+
+ * Makefile.in: Changed some lines to be less confusing for some
+ makes.
+
+ * input-file.c: Conditionalize on _IOFBF, not VMS.
+
+ * read.c, write.c: Change a series of ifdef/elif to
+ ifdef/else/ifdef etc.
+
+Fri Mar 27 12:21:16 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * symbols.c (fb_label_init): fix sizeof to memset.
+
+Fri Mar 13 15:45:44 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in: install the man page.
+
+ * Makefile.in: pass down MAKEINFO explicitly on info.
+
+ * doc/Makefile.in: use $(MAKEINFO) not makeinfo.
+
+Fri Mar 13 08:03:03 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * flonum-const.c: renamed flonum-konst.c to stop dos name
+ conflict.
+
+Thu Mar 12 04:42:38 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * tc-m68k.h, te-sun3.h: moved LOCAL_LABELS_FB definition from
+ tc-m68k.h to te-sun3.h.
+
+Wed Mar 11 23:32:42 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * configure.in: vxworks68 gets te-sun3.h.
+
+ * expr.c: remove limitation that local_labels_dollar or
+ local_labels_fb must be < 10.
+
+ * symbols.c: remove local_labels_dollar, replace with a function
+ interface for a sparse array. All users adjusted.
+
+ * te-sun3.h: add LOCAL_LABELS_DOLLAR.
+
+Sat Mar 7 00:06:25 1992 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * doc/Makefile.in: commented out line for building as-all.texinfo.
+ This is temporary.
+
+ * doc/as.texinfo, doc/as-all.texinfo: added menu item hooks.
+
+Fri Mar 6 21:57:18 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in: added check target.
+
+Tue Mar 3 15:45:56 1992 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * Makefile.in: added tooldir and program_prefix.
+
+Sun Mar 1 04:43:19 1992 Michael Tiemann (tiemann@cygnus.com)
+
+ * write.{c,h} (fix_new): Make these declarations consistent.
+
+Sat Feb 29 13:59:10 1992 Michael Tiemann (tiemann@cygnus.com)
+
+ * Makefile.in (strerror.o): Add rule so that broken Sun make can
+ work in subdirs.
+
+Wed Feb 26 19:26:28 1992 Steve Chamberlain (sac at thepub.cygnus.com)
+
+ * read.c, obj-coffbfd.c : fix h8300 specific bit rot
+
+ * expr.c (operand): if can't work out what sort of operand it is,
+ then look through FLT_CHARS for a hint.
+
+Wed Feb 26 18:04:40 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in, configure.in: removed traces of namesubdir,
+ -subdirs, $(subdir), $(unsubdir), some rcs triggers. Forced
+ copyrights to '92, changed some from Cygnus to FSF.
+
+ * doc/Makefile.in, doc/configure.in: removed traces of namesubdir,
+ -subdirs, $(subdir), $(unsubdir), some rcs triggers. Forced
+ copyrights to '92, changed some from Cygnus to FSF.
+
+Tue Feb 25 14:17:15 1992 Steve Chamberlain (sac at rtl.cygnus.com)
+
+ * expr.c: If an expression is single comma, then return with
+ SEG_ABSENT rather than an error - since the sparc front end does
+ really strange things with things like fbge,a
+
+ * as.h: include bfd.h if using many sections
+ * expr.c: LOCAL_LABELS_FB had been changed to lower case - so
+ local labels didn't work.
+ * listing.c (list_symbol_table): don't core dump when there's no
+ symbol there.
+ * write.c, write.h: call fix_new with the right number of args on
+ the H8.
+ * config/tc-h8300.[ch] : fix bugs reported by HMSI, and make
+ errors nices
+
+Sat Feb 22 12:26:28 1992 Steve Chamberlain (sac at rtl.cygnus.com)
+
+ * app.c: MRI compatibility - allow single quote to start a string.
+ * as.c: fix typo recently introduced.
+ * as.h : Don't include aout/reloc.h - it's not right for COFF!
+ * expr.c: Much rewriting, to accomodate MRI syntax for
+ expressions. Also easier to read now.
+ * listing.c: Put back defuns
+ * read.c: modified to accept MRI syntax, put back listing pseudo
+ ops so that an assembler built with NO_LISTING ignores list ops
+ rather than pukes.
+ * write.c, write.h: fixs - only keep a reloc type in a fix if the target
+ machine is a SPARC or a 29K.
+ * config/obj-aout.c: added s_sect pseudo op
+ * config/obj-coffbfd.c: lints, set the filehdr flags right and
+ fill in the timestamp.
+ * config/obj-coffbfd.h: Since we don't include aout/reloc.h
+ anymore, define all the relocs which the tc-<x> bit will use so we
+ can translate from them to the coff types.
+ * config/tc-a29k.c: reloc_type isn't ane enum any more
+ * config/tc-m68k.c: Added NO_RELOC definition.
+
+Fri Feb 21 06:21:07 1992 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * Makefile.in: put header files before C source for TAGS; remove
+ references to non-existent syscalls.h.
+
+ * read.c, write.c subsegs.c: back out the .bss changes.
+
+ * obj-aout.c: do not include stab.gnu.h if NO_LISTING.
+
+ * tc-i860.c, a.out.gnu.h: move i860 relocs to a proper place.
+
+ * a.out.h: removed.
+
+Fri Feb 21 01:08:48 1992 Minh Tran-Le (TRANLE@INTELLICORP.COM)
+
+ * symbols.c (local_label_name): symbols now start with ^A.
+
+ * read.c, subsegs.c, write.c obj-coff.c: added handling of
+ `.bss` pseudo op for unitialized data. The new gcc (1.37.9x)
+ generate these sections. .align: will use NOP_OPCODE or 0
+ for padding. This is just for being nice to the
+ disassembler.
+
+ * expr.c (operand): changed to generate local label "\001L0"
+ starting with a ^A so that it is recognized as a local label.
+
+ * as.c (perform_an_assembly_pass): zero bss_fix_root, too.
+
+ * tc-i386.c: tc-i386.c: added handling of the following opcodes:
+ i/o opcodes - inb, inw, outb and outw. string manipulation with
+ att syntax - scmp, slod, smov, ssca, ssto.
+
+ * obj-coff.c: (for aix386) Moved the symbols .text, .data and .bss
+ to just after .file .
+
+ In obj_crawl_symbol_chain() where it tries to put the external
+ symbols apart, with the condition:
+ (!S_IS_DEFINED(symbolP) &&
+ !S_IS_DEBUG(symbolP) &&
+ !SF_GET_STATICS(symbolP))
+ it was moving too many symbols out. So I switch it back to the
+ condition:
+ (S_GET_STORAGE_CLASS(symbolP) == C_EXT && !SF_GET_FUNCTION(symbolP))
+
+ In obj_emit_relocations() added the conditional on KEEP_RELOC_INFO
+ so that we don't use the F_RELFLG which make the linker complain
+ that somebody has stripped the relocation info.
+
+ Also, the AIX ld program require that the relocation table
+ is sorted by r_vaddr like the standard ATT assembler does.
+
+ [he also changed the sizeof(struct ...)'s into the coff
+ style FOOSZ macros. I'm not sure this is right, but I can't
+ remember why. xoxorich.]
+
+Fri Feb 21 01:08:48 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in, configure.in, doc: use the doc. Build it, install
+ it, clean it, etc.
+
+Tue Feb 18 02:21:25 1992 K. Richard Pixley (rich at cygnus.com)
+
+ * read.c: white space and comments only.
+
+ * configure.in: use the new atof-ns32.c for ns32k.
+
+ * write.c: comment change only.
+
+ * tc-m88k.[hc]: pulled in from hack's unfinished work. These
+ aren't yet integrated.
+
+ * tc-i860.[hc]: blew off the dust. Something must still be done
+ about conflicting relocation types.
+
+ * tc-ns32k.c: Replaced previous tc_aout_fix_to_chars stub with the
+ real thing.
+
+ * tc-i960.c, tc-sparc.c: white space and comments only.
+
+ * tc-a29k.h: delete duplicate macro definition.
+
+ * new file atof-ns32k.c copied from hack's last unreleased gas.
+
+Mon Feb 17 07:51:06 1992 K. Richard Pixley (rich at cygnus.com)
+
+ * config/tc-ns32k.c: actually make tc_aout_fix_to_chars work
+ rather than abort.
+
+ * nearly everything. flush ChangeLog, package as gas-1.92.1.
+ ChangeLog's prior to this are sketchy at best. I have logs.
+ They just aren't ChangeLogs.
diff --git a/gas/ChangeLog-9697 b/gas/ChangeLog-9697
new file mode 100644
index 0000000000..dd2af82455
--- /dev/null
+++ b/gas/ChangeLog-9697
@@ -0,0 +1,5960 @@
+Wed Dec 31 12:29:47 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10200.c (md_relax_table): Correct branch ranges.
+
+Mon Dec 22 13:06:05 1997 Joel Sherrill <joel@oarcorp.com>
+
+ * configure.in (i386*-go32-rtems*): Fix to be the same as
+ i[3456]86-go32.
+ * configure: Rebuild.
+
+Mon Dec 22 12:54:07 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (macro): The 4650 doesn't permit M_LDC1_AB,
+ M_SDC1_AB, M_L_DOB, M_L_DAB, M_S_DAB, or M_S_DOB.
+ (mips_ip): Always check for FP_D, not just for instructions that
+ are not part of the regular ISA.
+
+Thu Dec 18 16:49:28 1997 Richard Henderson <rth@cygnus.com>
+
+ * config/tc-d10v.c (build_insn): Make `number' a long for 64-bit hosts.
+
+Thu Dec 18 16:42:57 1997 Richard Henderson <rth@cygnus.com>
+
+ * config/tc-alpha.c (cpu_types): 21164pc/pca56 does not have CIX.
+
+Wed Dec 17 21:23:07 1997 Jeffrey A Law (law@cygnus.com)
+
+ * expr.c (integer_constant 32bit bignum): Mask off bits outside
+ the range we care about.
+
+Wed Dec 17 15:29:03 1997 Michael Meissner <meissner@cygnus.com>
+
+ * config/tc-d30v.c (md_shortopts): Add 'n' and 'N' options.
+ (exec_type_enum): Enumeration giving all of the exec types.
+ (warn_nops): New static variable to give nop warning level.
+ ({cur,prev}_mul32_p): New static variable to keep track of whether
+ the current/previous instruction is a 32-bit multiply.
+ (Optimizing): Make static.
+ (NOP{2,_LEFT,_RIGHT}): Macros for word of nops and left/right
+ nops.
+ (d30v_insert_operand): Delete declaration of unused function.
+ (write_2_short): Make exec_type argument enum, not int.
+ (parallel_ok): Ditto.
+ (check_range): Delete unused variable(s).
+ (build_insn): Ditto.
+ (find_format): Ditto.
+ (md_apply_fix3): Ditto.
+ (md_show_usage): Document -n and -N.
+ (md_parse_option): Parse -n and -N.
+ (write_1_short): If -n, warn about adding a nop. Use
+ NOP_{LEFT,RIGHT}.
+ (write_2_short): Use enumeration values instead of hard coded
+ integers. Reset exec_type for default operations. For explicit
+ parallel operations, call parallel_ok to make sure everything is
+ ok. If writing out a parallel operation, and the previous
+ instruction was a 32-bit multiply, indicate current instruction
+ is.
+ (parallel_ok): Allow add/tx ... to be done in parallel with
+ another add/tx ... assuming the gpr registers don't overlap.
+ (md_assemble): Use exec type enumeration values, not hard coded
+ ints. Check for loads or 16-bit multiplies following in the next
+ cycle after a 32-bit multiply. Add nops if that is the case.
+ (do_assemble): Copy prev_mul32_p to cur_mul32_p, and set
+ cur_mul32_p if current instruction is a 32-bit multiply.
+ (find_format): Change spacing and layout.
+
+Tue Dec 16 16:55:45 1997 Fred Fish <fnf@cygnus.com>
+
+ * config/tc-tic80.c (tic80_relax): New static variable.
+ (md_longopts): Add new OPTION_RELAX and OPTION_NO_RELAX options.
+ (md_parse_option): Handle new relax options.
+ (md_show_usage): Document new relax options.
+ (find_opcode): Don't use short forms of PC relative branches if
+ tic80_relax is set.
+
+Tue Dec 16 15:26:03 1997 Michael Meissner <meissner@cygnus.com>
+
+ * config/tc-d30v.c (parallel_ok): Remove non-register bits from
+ used/set flag fields. Make flag vars unsigned long. Use
+ FLAG_A{0,1} for accumulators. Allow any 2 insns to be done in
+ parallel if they use the same conditional flag with reversed
+ meaning. Allow 2 add/sub insns that set the carry or overflow
+ flags but do not query them to be done in parallel. Don't allow 2
+ word store operations to be done in parallel with ADDppp or
+ SUBppp. Don't allow loads to be done in parallel with 16 bit
+ multiplies.
+
+Tue Dec 16 09:20:43 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-arm.c: Prevent use of interworking support for
+ non-COFF targets.
+
+Mon Dec 15 15:20:32 1997 Nick Clifton <nickc@cygnus.com>
+
+ * doc/all.texi: Add M32R cpu.
+
+ * doc/as.texinfo: Add documentation of m32r processor.
+
+ * doc/c-m32r.texi: New file, documenting m32r specific features.
+
+
+Mon Dec 15 10:32:28 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mips.c (mips_ip): Correctly insert 'P' operands into
+ the instruction.
+
+Fri Dec 12 11:44:20 1997 Fred Fish <fnf@cygnus.com>
+
+ * config/tc-tic80.c (build_insn): Handle instructions that have
+ long (32 bit) PC relative offsets. Fix places that previously
+ misused R_MPPCR for 15 bit offsets to use the new R_MPPCR15W type.
+ (md_apply_fix): Add case to handle long PC relative offsets.
+
+Fri Dec 12 10:35:01 1997 Nick Clifton <nickc@cygnus.com>
+
+ * doc/c-arm.texi (ARM Options): Document support for new ARM
+ processor names.
+
+ * config/tc-arm.c (md_parse_option): Add support for new ARM
+ processor names.
+
+Thu Dec 11 17:46:50 1997 Richard Henderson <rth@cygnus.com>
+
+ * config/tc-m68k.c (m68k_ip): Don't overwrite opcode table data.
+ (insop, m68k_ip): Make `opcode' const so it doesn't happen again.
+
+Fri Dec 5 11:23:59 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c (md_assemble): Fix BFD_RELOC_32 against a
+ symbol + offset.
+
+ * config/tc-v850.h (ELF_TC_SPECIAL_SECTIONS): Use
+ SHT_V850_{S|T|Z}COMMON to mark special common sections.
+
+Tue Dec 2 17:05:13 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c: Brought up to date with the branch.
+
+Mon Dec 1 20:24:18 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * config/tc-sh.c (SWITCH_TABLE_CONS): Handle (fix)->fx_size == 1.
+ (SWITCH_TABLE): Handle BFD_RELOC_8.
+ (md_apply_fix): #ifndef BFD_ASSEMBLER code: Handle fixP->fx_size == 1.
+ (coff_reloc_map): Add BFD_RELOC_8_PCREL entry.
+ (sh_coff_reloc_mangle): SWITCH_TABLE case: Handle BFD_RELOC_8.
+
+Sat Nov 22 16:19:22 1997 Richard Henderson <rth@cygnus.com>
+
+ * tc-alpha.c (range_signed_16, range_signed_32): Work around an
+ apparent bug in gcc's long long support crossing from x86.
+
+Sat Nov 22 14:26:09 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-arm.c: Brought up to date with latest changes on arm
+ branch.
+
+Sat Nov 22 15:50:09 1997 Klaus Kaempf <kkaempf@progis.de>
+
+ * config-gas.com: Get version info from configure.in.
+
+ * makefile.vms: include depend.obj in OBJS.
+
+ * config/tc-alpha.c (s_alpha_section): Remove ".lcomm" handling.
+
+ * config/tc-alpha.c (alpha_basereg_clobbered): Remove variable and
+ all corresponding code.
+
+Thu Nov 20 15:06:08 1997 Richard Earnshaw <rearnsha@arm.com>
+
+ * config/tc-arm.h (TARGET_FORMAT for generic a.out targets): Allow
+ run-time endian selection.
+
+Wed Nov 19 17:44:42 1997 Richard Henderson <rth@cygnus.com>
+
+ * tc-sh.c (parse_reg): Properly quote for fv4.
+
+Wed Nov 19 23:46:18 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * symbols.c (resolve_symbol_value): Add missing breaks in case on
+ symbol value operator.
+
+Tue Nov 18 18:45:14 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * config/tc-d10v.c (parallel_ok, find_opcode):
+ Split OPERAND_FLAG into OPERAND_FFLAG and OPERAND_CFLAG.
+
+Sun Nov 16 10:05:07 1997 Fred Fish <fnf@cygnus.com>
+
+ * config/obj-coff.c (fixup_segment): Cast second arg of
+ md_apply_fix3 call to type "valueT *".
+
+Thu Nov 13 13:53:10 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * configure.in (emulations): Make FreeBSD an aout / i386bsd
+ variant.
+ * configure: Re-generate.
+
+Thu Nov 13 11:07:14 1997 Gavin Koch <gavin@cygnus.com>
+
+ * config/tc-mips.c (macro_build): Use the membership field
+ for INSN_MACRO's.
+ (mips_ip): Same.
+
+Thu Nov 13 02:04:55 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * config/tc-d10v.c (find_opcode): For OPCODE_FAKE, add check for
+ first argument if it's supposed to be a register.
+
+Tue Nov 11 19:25:05 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * app.c (do_scrub_chars): If d10v, re-insert a space before
+ a '#' when in state 10.
+
+Tue Nov 11 13:33:15 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-h8300.c: Include "subsegs.h".
+ (tc_reloc_mangle): Handle references to symbols which are not
+ being output, so that references to `.' work.
+
+Mon Nov 10 13:43:33 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (m68k_ip): Call add_fix when needed for '_'
+ case.
+
+ * macro.c (sub_actual): If we don't find a parameter for an &,
+ just substitute &.
+
+Fri Nov 7 21:29:32 1997 Ken Raeburn <raeburn@cygnus.com>
+
+ * config/tc-mips.c (mips_ip): In default case, call as_bad
+ instead of fprintf, to get "assembler messages:" message output
+ before instead of after.
+
+Fri Nov 7 10:36:22 1997 Doug Evans <devans@canuck.cygnus.com>
+
+ * frags.h: Handle multiple inclusion.
+
+Wed Nov 5 10:51:49 1997 Doug Evans <devans@canuck.cygnus.com>
+
+ Based on a patch from Ian.Dall@dsto.defence.gov.au.
+ * as.h (struct frag, frag support): Moved from here.
+ * frags.h: To here.
+ (struct frag, member tc_frag_data): New member if TC_FRAG_TYPE
+ is defined.
+ (struct frag, member fr_cgen): Renamed from fr_targ.cgen.
+ * cgen.c (cgen_asm_finish_insn): Update.
+ * config/tc-m32r.c (md_estimate_size_before_relax): Update.
+ * config/tc-m32r.h (TC_FRAG_INIT): Renamed from md_init_frag.
+ (md_convert_frag): Ditto.
+ * config/tc-ns32k.h (TC_FRAG_TYPE): Define.
+ (frag_opcode_frag,frag_opcode_offset,frag_bsr): Update.
+ (TC_FRAG_INIT): Update.
+
+Tue Nov 4 16:35:57 1997 Ian Dall <Ian.Dall@dsto.defence.gov.au>
+
+ * write.c (print_fixup): Use TC_FIX_DATA_PRINT (if defined) to
+ print out MD fields of fix.
+ * frags.c (frag_var, frag_variant): Use TC_FRAG_INIT macro (if
+ defined) to initialize MD fields in frag.
+ * as.h (struct frag, ns32k support): Rename ns32k to fr_ns32k.
+ Delete pcrel_adjust. Add fr_opcode_fragP, fr_opcode_offset.
+ * config/tc-ns32k.h: Add comments. Remove obsolete
+ BFD_FAST_SECTION_FILL definition, change prototypes for
+ fix_new_ns32k and fix_new_ns32k_exp to add new arguments
+ opcode_frag and opcode_offset and remove pcrel_adjust.
+ (TC_FIX_TYPE): add opcode_fragP and opcode_offset fields.
+ (TC_FIX_DATA_PRINT): new macro to print out TC_FIX_TYPE.
+ (TC_FRAG_INIT): new macro to initialize machine dependent field in
+ frags.
+ (frag_opcode_frag, frag_opcode_offset, frag_bsr): macros to access
+ MD fields in frag structure.
+ (fix_im_disp, fix_bit_fixP, fix_opcode_frag, fix_opcode_offset,
+ fix_bsr): macros to access MD fields in fix structure.
+ * config/tc-ns32k.c: Avoid overlength lines. Align comments. Don't
+ use struct opcode_location as these fields are now in the frag
+ structure.
+ (convert_iif): Call frag_more as it is needed instead
+ of trying to allocate for the whole insn. Avoid call of frag_more
+ with negative argument.
+ (md_pcrel_adjust, md_fix_pcrel_adjust, md_apply_fix,
+ md_estimate_size_before_relax, md_pcrel_from,
+ tc_aout_fix_to_chars): use accessor macros to get md fields in fix
+ and frag structures.
+ (fix_new_ns32k, fix_new_ns32k_exp): add new arguments opcode_frag and
+ opcode_offset and remove pcrel_adjust.
+ (convert_iif, cons_fix_new_ns32k): call fix_new_ns32k,
+ fix_new_ns32k_exp with changed arguments.
+
+Mon Nov 3 13:30:17 1997 Gavin Koch <gavin@cygnus.com>
+
+ * tc-mips.c (md_begin): Reorganize setting of default values so
+ that mips_cpu depends on TARGET_CPU, and mips_opts.isa depends on
+ mips_cpu.
+ (md_parse_option): Remove all code that sets defaults; md_begin
+ handles all of this now.
+
+Sun Nov 2 14:46:09 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.am (STAGESTUFF): Change bin_PROGRAMS to
+ noinst_PROGRAMS.
+ (bootstrap, bootstrap2, bootstrap3): Likewise.
+ * Makefile.in: Rebuild.
+
+ * config/tc-ppc.c (ppc_fix_adjustable): Don't adjust relocs in the
+ TOC section to be against the csect.
+
+Fri Oct 31 18:19:55 1997 Ken Raeburn <raeburn@cygnus.com>
+
+ * config/tc-mips.c (validate_mips_insn): New function, checks
+ match versus mask bits, and also verifies that all bits to be
+ output are actually specified somewhere.
+ (md_begin): Call it for 32-bit instructions, instead of doing
+ match/mask check here. In case of failure, print a message, but
+ check the rest of the opcode table before exiting.
+
+Thu Oct 30 13:46:20 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-arm.c (md_apply_fix3): Fix thumb ADR pseudo op. Patch
+ from Tony Thompson at ARM: athompso@arm.com
+
+Thu Oct 30 11:11:26 1997 Michael Meissner <meissner@cygnus.com>
+
+ * config/tc-d30v.c (build_insn): Allow odd registers for ld2w and
+ friends.
+
+Fri Oct 24 15:56:47 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-ppc.c (md_assemble): When handling @l, always sign
+ extend if the operand expects a signed value.
+
+ * config/tc-mips.h (LOCAL_LABELS_DOLLAR): Don't define; use
+ default which is to permit dollar labels.
+
+Fri Oct 24 11:19:22 1997 Jakub Jelinek <jj@sunsite.mff.cuni.cz>
+
+ * config/tc-sparc.c (sparc_memory_model): New variable.
+ (md_longopts): Add -TSO/-PSO/-RMO options.
+ (md_parse_options): Handle them.
+ (sparc_elf_final_processing): For 64 ELF, set required
+ memory ordering in e_flags. Default to RMO and let the user
+ override it through command line.
+
+ * config/tc-sparc.h (elf_tc_final_processing): Add.
+
+Wed Oct 22 17:42:12 1997 Richard Henderson <rth@cygnus.com>
+
+ * config/tc-sparc.c (v9a_asr_table): New variable.
+ (sparc_ip): Handle v9a asr's.
+ Patch from David Miller <davem@vger.rutgers.edu>.
+
+Wed Oct 22 17:22:59 1997 Richard Henderson <rth@cygnus.com>
+
+ * config/tc-sparc.h (md_do_align): New macro.
+ * config/tc-sparc.c (sparc_handle_align): Handle rs_align_code.
+ Patch from Jakub Jelinek <jj@sunsite.mff.cuni.cz>.
+
+Wed Oct 22 12:51:18 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sh.c (sh_small): New variable.
+ (OPTION_SMALL): Define.
+ (md_longopts): Add "small".
+ (md_parse_option): Handle OPTION_SMALL.
+ (md_show_usage): Mention -small.
+ * config/tc-sh.h (sh_small): Declare.
+ (SUB_SEGMENT_ALIGN): Handle sh_small.
+ * config/obj-coff.h (TARGET_FORMAT): Check sh_small in TC_SH
+ case.
+
+ * config/tc-mips.c (macro): Correct handling of constant in M_LI_D
+ case in little endian mode.
+
+Tue Oct 21 10:20:11 1997 Doug Evans <devans@canuck.cygnus.com>
+
+ * config/tc-sparc.c (md_apply_fix3, cases ..._H44, ..._HIX22): Leave
+ overflow signalling to linker.
+
+Mon Oct 20 14:54:06 1997 Klaus K"ampf <kkaempf@progis.de>
+
+ * makefile.vms: Fix for dec c.
+
+ * config-gas.com: Give explanation for dec c setup in error
+ message.
+
+ * config/tc-alpha.c (s_alpha_comm): Make .comm symbols separate
+ sections on openvms/alpha.
+
+ * config/obj-evax.c: support .weak pseudo-op
+
+Mon Oct 20 10:13:32 1997 Doug Evans <devans@canuck.cygnus.com>
+
+ * config/tc-sparc.c (default_arch_size): New static local.
+ (struct sparc_arch): Rename arch_size to default_arch_size.
+ New member user_option_p.
+ (sparc_arch_table): Always include v9, v9a. New entry v9-64.
+ (init_default_arch): Check whether default arch is valid.
+ Set default_arch_size in addition to sparc_arch_size.
+ (OPTION_32,OPTION_64): Define.
+ (md_longopts): New entries for -32, -64.
+ (md_parse_option): Handle them.
+ (md_show_usage): Print them. Ensure init_default_arch called.
+ * configure.in (sparc64): Set arch to v9-64.
+ * configure: Regenerated.
+
+Sun Oct 19 13:50:50 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * write.c (subsegs_finish): New function, broken out of
+ write_object_file.
+ (write_object_file): Some code moves into subsegs_finish.
+ * write.c (subsegs_finish): Declare.
+ * as.c (main): Call subsegs_finish.
+
+ * read.c (s_include): Check for error return from
+ demand_copy_string.
+
+Tue Oct 14 20:50:58 1997 Richard Henderson <rth@cygnus.com>
+
+ * read.c (get_line_sb): Accept any eol marker while scanning macros.
+
+Tue Oct 14 19:12:45 1997 Richard Henderson <rth@cygnus.com>
+
+ * config/tc-alpha.h (DIFF_EXPR_OK): Define.
+ * config/tc-i386.h (DIFF_EXPR_OK): Define.
+ * config/tc-alpha.c (md_apply_fix): Notice fx_pcrel and substitute
+ the correct relocation when it exists.
+ * config/tc-i386.c (md_apply_fix3): Likewise.
+
+ * config/tc-ppc.h: Correct typo in comment.
+ * config/tc-v850.h: Likewise.
+
+Fri Oct 10 16:09:35 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * config/tc-d10v.c (parallel_ok): Allow parallel instruction issue
+ when second instruction is writing to first instructions inputs.
+
+Mon Oct 13 15:27:17 1997 Richard Henderson <rth@cygnus.com>
+
+ * ecoff.c (PAGE_SIZE): Double to 8k as a hack to allow some C++
+ templated programs to build with -g.
+
+Fri Oct 10 17:48:29 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c (md_relax_table): Add support for relaxing
+ unconditional branches. This patch is courtesy of Jim Wilson.
+ (md_convert_frag): Fix relaxing of branches. This patch is
+ courtesy of Jim Wilson.
+ (md_assemble): Create different fixups for conditional and
+ unconditional branches. This patch is courtesy of Jim Wilson.
+ (md_estimate_size_before_relax): Estimate size of variable part of
+ fixup based on whether it is for a conditional or an unconditional
+ branch. This patch is courtesy of Jim Wilson.
+ (v850_sdata, v850_tdata, v850_zdata, v850_sbss, v850_tbss,
+ v850_zbss, v850_rosdata, v850_rozdata, v850_bss): Add call to
+ obj_elf_section_change_hook().
+ (v850_comm): New function.
+ (md_pseudo_table): Add new pseudo ops .zcomm, .scomm and .tcomm.
+ (md_begin): Add bss flag to seg_info of bss sections.
+
+ Add support for .scommon, .tcommon and .zcommon sections.
+
+ * config/tc-v850.h (ELF_TC_SPECIAL_SECTIONS): Add .scommon,
+ .zcommon, .tbss, .call_table_data and .call_table_text.
+
+Fri Oct 10 15:01:14 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * configure.in (sparc): Set DEFAULT_ARCH from correct target.
+ * configure: Regenerated.
+
+Fri Oct 10 11:22:45 1997 Martin M. Hunt <hunt@cygnus.com>
+
+ * config/tc-d10v.c: Fixes to make sure the AT_WORD
+ expression is not confused with -1.
+
+Fri Oct 10 11:54:50 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * config/tc-d10v.c (parallel_ok): Flag SP as modified for @-sp
+ operand - OPERAND_ATMINUS.
+
+Fri Oct 10 00:47:44 1997 Michael Meissner <meissner@cygnus.com>
+
+ * config/tc-d10v.c (parallel_ok): Note that auto increment and
+ decrement modify the index register.
+
+Thu Oct 9 15:17:50 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ From Robin Kirkham <Robin.Kirkham@mlb.dmt.csiro.au>:
+ * config/tc-m68k.c (archs): Add 68306, 68307, 68322, 68356, 68334,
+ 68336, 68341, 68349.
+ * doc/c-m68k.texi (M68K-Opts): Add -m68ec000 -m68hc000 -m68hc001
+ -m68306, -m68307, -m68322, -m68356, -m68ec020, -m68ec030,
+ -m68ec040, -m68ec060, -m68330, -m68334, -m68336, -m68341,
+ -m68349.
+
+ * doc/Makefile.am (CPU_DOCS): Define.
+ (as.info): Depend upon $(CPU_DOCS).
+ * doc/Makefile.in: Rebuild.
+
+ * configure.in: Remove AM_PROG_INSTALL; it's called by
+ AM_INIT_AUTOMAKE.
+ * configure: Rebuild.
+
+Thu Oct 9 01:44:36 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * tc-d10v.h (TC_START_LABEL): Don't define.
+ (tc_frob_label): Define.
+
+Thu Oct 9 00:07:23 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * config/tc-d10v.c (write_2_short): Fix bug that wouldn't allow
+ to pair a branch and link with anything but an exe instruction.
+
+Wed Oct 8 16:28:53 1997 Richard Henderson <rth@cygnus.com>
+
+ * config/tc-alpha.c (load_expression): Disable the sym+const .got
+ optimization to reduce the alignment surprises for gcc.
+
+Wed Oct 8 16:11:15 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/obj-coff.h (TC_SPARC): Don't define TARGET_FORMAT.
+ * config/tc-sparc.c (sparc_target_format): Handle coff here.
+ (sparc_ip): Add %hix,%lox.
+ (md_apply_fix3): Call as_bad_where, not as_bad.
+ Add support for BFD_RELOC_SPARC_{HIX22,LOX10}.
+ (tc_gen_reloc): Add support for BFD_RELOC_SPARC_{HIX22,LOX10}.
+
+Wed Oct 8 12:33:32 1997 Richard Henderson <rth@cygnus.com>
+
+ * configure.in: Change alpha-*-* to alpha*-*-*; config.guess now
+ recognizes alphaev5 etc.
+ * configure: Rebuild.
+
+Wed Oct 8 00:04:05 1997 Gavin Koch <gavin@cygnus.com>
+
+ * config/tc-mips.c (md_begin): Replace the TARGET_CPU value
+ of mipsr3900 with mipstx39.
+
+ * config/tc-mips.c (mips_ip): Don't print the 'opcode requires
+ -mipsXX message' if the insn isn't an ISA insn.
+
+Tue Oct 7 12:48:30 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/tc-sparc.h (TARGET_FORMAT support): Moved to tc-sparc.c.
+ Redefine TARGET_FORMAT to call sparc_target_format.
+ * config/tc-sparc.c (in_unsigned_range): New function.
+ (sparc_arch_size): Make static.
+ (sparc_target_format): New function.
+ (sparc_ip): Delete variable immediate_max. Rewrite %hi/etc reloc
+ handling. Add support for %hh,%hm,%lm,%h44,%m44,%l44.
+ (output_insn): Set `fx_no_overflow'.
+ (md_apply_fix3): Handle BFD_RELOC_SPARC_{7,H44,M44,L44}.
+ (tc_gen_reloc): Likewise.
+
+Mon Oct 6 14:04:50 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c (v850_section): Remove.
+
+ * config/obj-elf.c (obj_elf_section): Enhance error message.
+
+Fri Oct 3 15:40:38 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c: Undef OBJ_COPY_SYMBOL_ATTRIBUTES before
+ including obj-elf.h in OBJ_MAYBE_ELF case.
+ (mips_target_format): Return NULL after abort to avoid warning.
+
+ * ecoff.c (generate_ecoff_stab): Remove unused static function.
+
+ * expr.c (operator): Accept ==. From Anders Blomdell
+ <anders.blomdell@control.lth.se>.
+
+ * config/atof-ieee.c (gen_to_words): When generating a denormal
+ number, handle an overflow into the smallest normalized number.
+
+Mon Sep 29 15:24:52 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * as.h, input-scrub.c (new_logical_line): New return value.
+ * read.c (s_app_file): Don't note the same file several times
+ in a row.
+
+Thu Sep 25 13:08:02 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (m68k_ip): Remove ` operand specifier.
+
+Wed Sep 24 16:54:40 1997 Joel Sherrill <joel@oarcorp.com>
+
+ * configure.in (sh*-*-rtems*): New target, like sh-*-elf*.
+ * configure: Rebuild.
+
+Wed Sep 24 11:30:25 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (m68k_ip): Handle q and v operand specifiers.
+
+ * doc/c-i386.texi (i386-Float): Remove incorrect assertion that
+ fn* instructions do not insert implicit fwait. This was changed
+ Jan 29, 1996.
+
+ * config/m68k-parse.y (yylex): Permit an expression to be used for
+ the scale factor.
+
+ * Makefile.am (EXTRA_as_new_SOURCES): Set to config/m68k-parse.y,
+ not m68k-parse.y.
+ * Makefile.in: Rebuild.
+
+ * aclocal.m4: Rebuild with new libtool.
+ * configure: Rebuild.
+
+Tue Sep 23 17:48:09 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * app.c (do_scrub_chars): Clear mri_state at end of .mri
+ pseudo-op.
+
+ * config/tc-mips.c (hilo_interlocks): Change from a static
+ variable to a macro, so that it varies with the variables upon
+ which it depends.
+ (gpr_interlocks, cop_interlocks): Likewise.
+ (md_begin): Don't initialize them.
+
+Fri Sep 19 17:08:41 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10300.c (md_assemble): Use strcasecomp instead
+ of strcmp where appropriate.
+
+Thu Sep 18 14:11:56 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c (md_assemble): Cope with a zero data area
+ relocation with a constant offset.
+ (md_assemble): Produce error message when special data area
+ relocations are used on instructions which do not support them.
+ (md_assemble): Reset processor mask if defined by command line
+ switch.
+
+Thu Sep 18 11:24:01 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/tc-sparc.c: Reorganize file.
+ (parse_keyword_arg): Allow numbers in reg names.
+ (SPECIAL_CASE_NONE): New macro.
+ (md_assemble): Use it.
+ (lookup_arch,init_default_arch): New functions.
+ (default_arch,default_init_p,sparc_arch_table): New static locals.
+ (sparc_arch_size): New static local.
+ (max_architecture): Initialize in init_default_arch.
+ (md_parse_options): Call init_default_arch if necessary.
+ Rewrite -xarch/-A processing.
+ (md_show_usage): Print -A values from sparc_arch_table.
+ (md_begin): Call init_default_arch if necessary.
+ (sparc_md_end): Handle both 32 and 64 bit environments.
+ * config/tc-sparc.h (TARGET_FORMAT): Likewise.
+ * acconfig.h (SPARC_V9,SPARC_ARCH64): Delete.
+ (DEFAULT_ARCH): Add.
+ * config.in: Regenerate.
+ * configure.in (sparc): Default DEFAULT_ARCH based on target cpu.
+ (SPARC_V9,SPARC_ARCH64): Delete.
+ * configure: Regenerate.
+ * config/vms-conf.h (SPARC_V9,SPARC_ARCH64): Delete.
+
+Wed Sep 17 16:54:20 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c (v850_reloc_prefix): Recoded to use CHECK_ ()
+ macro.
+ (handle_tdaoff, handle_zdaoff, handle_sdaoff): New functions.
+
+ * config/tc-v850.c (md_assemble): Corrected typo.
+ * config/tc-v850.c Add new sections: call_table_data and
+ call_table_text.
+ (v850_reloc_prefix): Add support for ctoff() relocation prefix.
+ (handle_ctoff): New Function.
+
+ * doc/c-v850.texi (V850 Opcodes): Document call table relocations.
+
+Tue Sep 16 14:18:22 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c (v850_reloc_prefix): Add support for a 16 bit
+ displacement from the tiny data area pointer.
+
+Mon Sep 15 21:28:09 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-hppa.c (fix_new_hppa): Make declaration match
+ definition.
+
+Mon Sep 15 18:33:06 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c (processor_mask): New variable.
+ (set_machine, md_parse_option): Set processor_mask.
+ (md_assemble): Check that instruction is available to target
+ processor.
+
+ * config/tc-v850.h (TARGET_PROCESSOR): New constant.
+
+Mon Sep 15 11:28:04 1997 Ken Raeburn <raeburn@cygnus.com>
+
+ Merge in work from Martin Hunt:
+
+ * config/tc-d30v.c (build_insn): For mvfsys and mvtsys,
+ CR is 0 for PSWL and PSWH.
+
+ * config/tc-d30v.c (do_assemble): Don't accept
+ illegal condition codes for cmpu instruction.
+
+ * config/tc-d30v.c: Add support for BFD_RELOC_D30V_9_PCREL
+ used in d*i instructions.
+
+ * config/tc-d30v.c (check_size): New function. Check
+ relocations for overflows.
+ (md_pcrel_from_section): Fix relocations between sections.
+ (md_apply_fix3): Use new relocation types for 15 and 21
+ bit relocations in the right container. Needed because
+ the address of the instruction is not eight-byte aligned
+ but the relocations must be.
+
+ * config/tc-d30v.c (md_apply_fix3): Check for overflow.
+ (find_format): If ".s" or ".l" are used, don't try
+ to compute branch sizes.
+
+ * config/tc-d30v.c (do_assemble): Check for ".s" or
+ ".l" extensions to opcode names.
+ (find_format): Generate the correct instructions when
+ ".s" or ".l" are used.
+
+ * config/tc-d30v.c (build_insn): Check for odd registers
+ on instructions that require even registers.
+
+ * config/tc-d30v.h (md_start_line_hook): Define.
+ * config/tc-d30v.c (md_start_line_hook): New hook.
+ Checks the beginning of each line for a ".". If it
+ finds one, assume a pseudo-op and flush any unwritten
+ instructions.
+
+ * config/tc-d30v.c (md_apply_fix3): Fix problem
+ with determining when fixups were done.
+
+ * config/tc-d30v.c (build_insn): Fix bug where the numeric
+ part of a symbol (for example, "foo+8") was being written
+ into the instruction.
+ (md_pseudo_table): Change .word to be 32 bits and add
+ .hword as 16 bits.
+
+ * config/tc-d30v.c (parallel_ok): Check to see if first
+ instruction is a jump.
+
+ * config/tc-d30v.c (parallel_ok): Major code reorganization.
+
+Wed Sep 10 10:07:08 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c (md_assemble): Corrected spelling mistake.
+ * configure.in (emulations): Add v850 emulation.
+
+Tue Sep 9 17:14:33 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * Makefile.am (CPU_TYPES): Add arc.
+ (TARGET_CPU_CFILES): Add tc-arc.c.
+ (TARGET_CPU_HFILES): Add tc-arc.h.
+ (dependencies): Rebuild.
+ * Makefile.in: Rebuild.
+ * configure.in: Recognize arc-*-elf*.
+ * configure: Regenerated.
+ * config/tc-arc.[ch]: New files.
+
+Tue Sep 9 10:19:37 1997 Nick Clifton <nickc@cygnus.com>
+
+ * doc/c-v850.texi (V850 Opcodes): Document hi0() reloc prefix.
+ Correct description of hi() reloc prefix.
+
+ * doc/c-v850.texi (V850 Opcodes): Document new reloc prefix.
+ * config/tc-v850.c (v850_reloc_prefix): Add hilo() reloc prefix.
+ * config/tc-v850.c (md_assemble): Add support for BFD_RELOC_32.
+
+ * doc/c-v850.texi: Document new pseudo ops and command line
+ options.
+
+ * config/tc-v850.c (set_machine): New function.
+ * config/tc-v850.c (.v850): New pseudo op.
+ * config/tc-v850.c (.v850e): New pseudo op.
+ * config/tc-v850.c (.v850ea): New pseudo op.
+
+
+Mon Sep 8 23:08:04 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ Support -alh and -ald for DWARF 1:
+ * listing.c (struct list_info_struct): Add debugging field.
+ (listing_newline): Initialize the debugging field. If ELF, if the
+ section starts with .debug or .line, set the debugging field in
+ the listing structure.
+ (debugging_pseudo): Add list parameter. Change all callers. If
+ the debugging field is set, consider it to be a debugging pseudo.
+ If ELF, skip blank lines between debugging lines.
+ * read.c (emit_expr): If ELF, look for line numbers.
+ (stringer): If ELF, look for file names.
+
+Mon Sep 8 12:33:40 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c (v850_insert_operand): Only test for overflow
+ if there is no insert function.
+
+ * config/tc-v850.h (TARGET_MACHINE): New constant.
+
+ * config/tc-v850.c (v850_insert_operand): Add
+ -mwarn_unsigned_overflow.
+ (md_begin): Set BFD machine number based on machine variable.
+ (md_parse_option): Add -mv850, -mv850e and -mv850ea options.
+
+Mon Sep 8 11:20:46 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * as.h: Don't declare alloca if it is a macro.
+ * macro.c: Likewise.
+
+Sun Sep 7 00:30:19 1997 Richard Henderson <rth@cygnus.com>
+
+ * config/tc-alpha.c (md_parse_option): Move m[] out to top level and
+ rename to cpu_types[].
+ (s_alpha_arch): New function.
+ (md_pseudo_table): Add "arch".
+
+ * config/tc-alpha.c (md_begin): Merge the two loops through the
+ opcode table.
+ (s_alpha_proc): Add initial SKIP_WHITESPACE.
+ (s_alpha_set): Likewise. Use get_symbol_end instead local while loop.
+
+Sat Sep 6 19:38:12 1997 Fred Fish <fnf@cygnus.com>
+
+ * read.h (s_lcomm_bytes): Add prototype (for real this time).
+
+Thu Sep 4 12:10:01 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-elf.c (elf_frob_symbol): Only set BSF_OBJECT for
+ symbols on Irix.
+
+Wed Sep 3 11:21:33 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c: Remove BFD_RELOC_V850_16_PCREL.
+
+Tue Sep 2 18:32:30 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10200.c (md_convert_frag): PC relative instructions arex
+ relative to the next instruction, not the current instruction.
+ (md_assemble): Similarly.
+
+Tue Sep 2 15:58:52 1997 Nick Clifton <nickc@cygnus.com>
+
+ * doc/c-v850.texi: Explanations of offsets in SDA/ZDA areas
+ correcetd.
+
+ * config/tc-v850.c: Add support for SDA/TDA/ZDA sections.
+ (v850_reloc_prefix): Duplicate code eliminated. Add code to
+ recognise special instructions.
+ (md_assemble): Calculation of the size of a fixups corrected.
+
+ * config/tc-v850.h (ELF_TC_SPECIAL_SECTIONS): Add SDA/TDA/ZDA
+ sections.
+
+Tue Sep 2 15:40:56 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * config/tc-v850.c (md_assemble): Use opcode->name instead of
+ opcode->opcode as the sentinal. Zero is a valid opcode.
+
+Tue Aug 26 16:51:14 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * doc/as.texinfo (Machine Dependencies): Add v850 to menu.
+ * doc/c-v850.texi: Change node name to match other chapter nodes.
+
+Tue Aug 26 09:46:22 1997 Nick Clifton <nickc@cygnus.com>
+
+ * doc/c-v850.texi (V850 Opcodes): Correct name for tiny data area
+ pointer.
+
+Tue Aug 26 12:23:25 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * expr.c (integer_constant): If BFD64, don't make a bignum if the
+ number will fit in 64 bits.
+
+ * config/tc-alpha.c (load_expression): Check explicitly for O_big,
+ rather than calling abort.
+
+ * as.h: Don't define alloca if __GNUC__. Just declare it.
+ * macro.c: Copy alloca handling from as.h.
+
+ * config/tc-i386.c (i386_align_code): Correct 16 bit noops. From
+ Gabriel Paubert <paubert@iram.es>.
+
+ * config/tc-i386.c (md_assemble): In JumpByte case, when looking
+ for a WORD_PREFIX_OPCODE, change it to ADDR_PREFIX_OPCODE if this
+ is jcxz or a loop instruction.
+
+Mon Aug 25 16:04:14 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c (pre_defined_registers): Add 'hp' as alias for
+ r2.
+ (md_begin): Set up machine architecture and type.
+
+Mon Aug 25 14:25:48 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * symbols.c (resolve_symbol_value): Store the value back into the
+ symbol expression, to handle add or subtract simplification
+ correctly. Handle O_symbol_rva. Add default case.
+
+ * config/tc-ppc.c (ppc_change_csect): Temporarily lower the
+ chunksize while creating the new subsection.
+ * as.c (chunksize): Initialize to zero.
+ * subsegs.c (subseg_set_rest): Change 5000 to chunksize when
+ calling obstack_begin.
+
+Mon Aug 25 11:21:48 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c (md_assemble): Restore input_line_pointer upon
+ exit.
+
+ * config/tc-v850.c (parse_register_list): Support constant
+ expressions as register lists.
+
+Mon Aug 25 10:19:34 1997 Nick Clifton <nickc@cygnus.com>
+
+ * doc/c-v850.texi: Change the major node to v850 Machine
+ Dependencies.
+
+Fri Aug 22 11:16:14 1997 Nick Clifton <nickc@cygnus.com>
+
+ * doc/as.texinfo: Add inclusion of c-v850.texi
+
+ * doc/c-v850.texi: New file.
+
+ * read.c (is_end_of_line): Make NUL character be considered to be
+ a line terminator.
+
+Fri Aug 22 10:45:33 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c (parse_register_list): Add support for curly
+ brace syntax.
+ (cc_names): Add "e" and "ne" conditions.
+
+Thu Aug 21 11:00:36 1997 Nick Clifton <nickc@cygnus.com>
+
+ * app.c (do_scrub_chars): Support a double dash as starting a
+ comment that extends to end of line.
+
+Thu Aug 21 10:54:27 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c (v850_section, v850_bss, v850_offset): New
+ functions.
+ (md_pseudo_table): New pseudo ops: .bss, .offset, .section
+
+Thu Aug 21 00:59:53 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/tc-m32r.c (md_estimate_size_before_relax): Update recorded
+ insn when changing to a different instruction.
+
+Wed Aug 20 00:45:20 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * tc-sh.c (parse_reg, get_specific, build_Mytes): Add SH4
+ floating point extensions.
+ (parse_reg): parse sgr and dbr.
+
+Tue Aug 19 17:07:34 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c (system_register_name): Support numbers for
+ system register IDs.
+
+Tue Aug 19 08:59:12 1997 Fred Fish <fnf@cygnus.com>
+
+ * read.c (s_lcomm_internal): Renamed from s_lcomm, added arg to
+ flag when alignment is in bytes instead of power of 2, and code to
+ use that flag to convert alignment to bytes.
+ (s_lcomm, s_lcomm_bytes): New helpers that call s_lcomm_internal.
+ * read.h (s_lcomm_bytes): Add prototype.
+ * config/obj-coff.c (write_object_file): If ALIGNMENT_IN_S_FLAGS is
+ defined, write alignment to alignment bits in section header s_flags
+ rather than the s_align field.
+ * config/obj-coff.h (ALIGNMENT_IN_S_FLAGS): Define for TC_TIC80.
+ * config/tc-tic80.c (md_pseudo_table): Use s_lcomm_bytes for bss
+ pseudo, instead of s_lcomm which wants a power of two for alignment.
+
+Mon Aug 18 20:42:23 1997 Richard Henderson <rth@cygnus.com>
+
+ * macro.c (check_macro): use alloca instead of xmalloc to plug leak.
+
+Mon Aug 18 20:33:06 1997 Richard Henderson <rth@cygnus.com>
+
+ * as.c (show_usage): Add -am.
+ * input-scrub.c (input_scrub_include_sb): Don't add leading \n
+ if we've already got one.
+ * listing.c (struct list_info_struct): Add line_contents.
+ (listing_newline): Put unused argument to work: if non-null, save it...
+ (listing_listing): ... and regurgitate during listing instead of line
+ from file.
+ * listing.h (LISTING_MACEXP): New define.
+ (LISTING_NEWLINE): Argument is NULL.
+ * read.c (read_a_source_file): If expanding macros, break up input
+ lines and pass them to listing_newline.
+ * doc/as.texinfo: Document -ac and -am.
+
+ * cond.c (s_ifc): Add missing demand_empty_rest_of_line.
+
+Mon Aug 18 11:26:36 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c (md_apply_fix3): Add support for new 16 bit PC
+ relative reloc.
+
+Mon Aug 18 11:24:21 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c: Remove support_v850e flag and command line
+ option.
+
+ * configure.in (emulations): Add support for v850e target
+
+ * configure (emulations): Add support for v850e target
+
+Mon Aug 18 11:24:21 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c: Remove support_v850ea flag and command line
+ option.
+
+ * configure.in (emulations): Add support for v850ea target
+
+ * configure (emulations): Add support for v850ea target
+
+Fri Aug 15 14:00:13 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.am (check-DEJAGNU): Don't cd into testsuite until after
+ setting EXPECT and TCL_LIBRARY.
+ * Makefile.in: Rebuild.
+
+ * as.h (enum debug_info_type): Define.
+ (debug_type): Declare.
+ * as.c (debug_type): New global variable.
+ (show_usage): Add --gstabs.
+ (parse_args): Handle --gstabs.
+ * read.c (generate_asm_lineno): Remove.
+ (read_a_source_file): Output stabs debugging if appropriate.
+ Change checks of generate_asm_lineno to check debug_type. Only
+ generate ECOFF debugging if ECOFF_DEBUGGING is defined.
+ * read.h (generate_asm_lineno): Don't declare.
+ (stabs_generate_asm_lineno): Declare.
+ * stabs.c (stabs_generate_asm_lineno): New function.
+ * ecoff.c (add_file): Use debug_type, not generate_asm_lineno.
+ Don't turn off debugging.
+ (add_file): Remove old #if 0 code.
+ (ecoff_new_file): Set debug_type, not generate_asm_lineno.
+ (ecoff_directive_end): Don't generate stabs line symbols.
+ (ecoff_generate_asm_lineno): Don't check stabs_seen. Don't set
+ generate_asm_lineno.
+ (line_label_cnt): Remove.
+ (ecoff_generate_asm_line_stab): Remove.
+ * ecoff.h (ecoff_generate_asm_line_stab): Don't declare.
+ * doc/as.texinfo, doc/as.1: Document --gstabs.
+
+Wed Aug 13 18:58:56 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-v850.c (md_assemble, md_show_usage, md_parse_option):
+ Add support for v850ea instructions.
+
+ * config/tc-v850.c (md_assemble, md_show_usage, md_parse_option):
+ Add support for v850e instructions.
+
+ * config/tc-v850.c (md_assemble): Fix error recovery to reload
+ text of entire opcode.
+
+Tue Aug 12 10:27:34 1997 Richard Henderson <rth@cygnus.com>
+
+ * doc/internals.texi: Document rs_leb128.
+
+Tue Aug 12 12:17:03 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (m68k_ip): Give an error message for SIZE_BYTE
+ in ABSL case, rather than calling abort.
+
+Mon Aug 11 21:48:00 1997 Richard Henderson <rth@cygnus.com>
+
+ * as.h (enum _relax_state): Add rs_leb128.
+ * read.c (potable): Add sleb128 and uleb128.
+ (sizeof_*leb128, output_*leb128, emit_leb128_expr, s_leb128): New
+ functions.
+ * read.h: Update prototypes.
+ * symbols.c (resolve_symbol_value): Streamline quite a bit. Return
+ the symbol value, add a second FINALIZE argument that prevents
+ changes from being comitted. Update all callers.
+ * write.c (cvt_frag_to_fill, relax_segment): Handle rs_leb128.
+ * doc/as.texinfo: Document the new pseudos.
+
+Sun Aug 10 14:51:49 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.am (MOSTLYCLEANFILES): Add site.bak, site.exp, stage,
+ stage1, and stage2.
+ (DISTCLEANFILES): Define.
+ * doc/Makefile.am (DISTCLEANFILES): Define.
+ * Makefile.in, doc/Makefile.in: Rebuild.
+
+Wed Aug 6 00:30:30 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Define TARGET_BYTES_BIG_ENDIAN if endian is set.
+ Don't set targ or gas_target. Define SCO_ELF and
+ TARGET_SOLARIS_COMMENT when appropriate. Don't substitute for
+ target_frag.
+ * Makefile.am: Remove @target_frag@.
+ (INCLUDES): Remove $(INTERNAL_CFLAGS), $(CROSS), $(HDEFINES), and
+ $(TDEFINES).
+ (dep-am): Mark as phony.
+ * acconfig.h: Add TARGET_BYTES_BIG_ENDIAN, TARGET_SOLARIS_COMMENT,
+ and SCO_ELF.
+ * config/arm-big.mt, config/arm-lit.mt: Remove.
+ * config/mips-big.mt, config/mips-lit.mt: Remove.
+ * config/ppc-big.mt, config/ppc-lit.mt: Remove.
+ * config/ppc-sol.mt: Remove.
+ * config/i386coff.mt, config/m68kcoff.mt: Remove.
+ * config/m88kcoff.mt: Remove.
+ * config/sco5.mt: Remove.
+ * configure, config.in, Makefile.in: Rebuild.
+
+ * Makefile.am ($(srcdir)/config/m68k-parse.h): New target, to
+ further try to circumvent the .y.h rule.
+ * Makefile.in: Rebuild.
+
+Tue Aug 5 12:32:07 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.am: New file, based on old Makefile.in.
+ * acinclude.m4: New file, from old aclocal.m4.
+ * configure.in: Call AM_INIT_AUTOMAKE and AM_PROG_LIBTOOL. Remove
+ shared library handling; now handled by libtool. Replace
+ AC_CONFIG_HEADER with AM_CONFIG_HEADER. Call AC_PROG_YACC,
+ AC_PROG_LEX, and AC_DECL_YYTEXT. Call AM_MAINTAINER_MODE,
+ AM_CYGWIN32, and AM_EXEEXT. Don't call CY_CYGWIN32 or CY_EXEEXT.
+ * config.in: New file, created by autoheader.
+ * conf.in: Remove.
+ * acconfig.h: Mention PACKAGE, VERSION, and USING_CGEN.
+ * stamp-h.in: New file.
+ * as.c (print_version_id): Change GAS_VERSION to VERSION.
+ (parse_args): Likewise.
+ * config/obj-vms.c: (Write_VMS_MHD_Records): Likewise.
+ * doc/Makefile.am: New file, based on old doc/Makefile.in.
+ * Makefile.in, doc/Makefile.in: Now built with automake.
+ * aclocal.m4: Now built with aclocal.
+ * configure: Rebuild.
+
+ * cond.c (s_else): If not listing false conditionals, turn listing
+ off in the false branch of the else.
+
+Mon Aug 4 11:28:35 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (macro): Fix handling of a double load from a
+ symbol plus an offset.
+
+ * ecoff.c (ecoff_build_symbols): Set fMerge to 0 for an FDR which
+ has an associated external symbol.
+
+Sun Aug 3 23:23:59 1997 Richard Henderson <rth@cygnus.com>
+
+ * config/tc-alpha.c (s_alpha_ucons): New function.
+ (md_pseudo_table): Add unaligned data pseudos for DWARF.
+
+Thu Jul 31 15:13:43 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-v850.c (md_assemble): Ignore the rest of the current
+ line if we encounter an error.
+
+ * config/tc-v850.c (md_assemble): Sign extend constants value
+ for hi and hi0 expressions.
+ (v850_insert_operand): Enable range checking for generic 16bit
+ operands.
+
+Tue Jul 29 14:20:43 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-v850.c (md_assemble): Turn on fx_no_overflow for
+ LO16, HI16 and HI16_S relocs.
+
+Mon Jul 28 18:41:41 1997 Rob Savoye <rob@chinadoll.cygnus.com>
+
+ * configure.in: Use CYGWIN and EXEEXT autoconf macro to look for
+ win32 dependencies.
+ * configure: Regenerated with autoconf 2.12.
+ * Makefile.in: Add $(EXEEXT) to all executables.
+
+Fri Jul 25 10:54:43 1997 Jeffrey A Law (law@cygnus.com)
+
+ * tc-hppa.c (md_apply_fix): Improve warnings for out of range
+ unconditional branches.
+ (hppa_fix_adjustable): Don't adjust anything with a RR% or LR%
+ field selector.
+
+Thu Jul 24 15:21:49 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * tc-sparc.c (md_begin): Cast sparc_opcodes to PTR for hash_insert.
+
+Thu Jul 24 17:51:29 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * macro.c (define_macro): Make sure the index is in range before
+ checking for '('.
+
+Thu Jul 24 12:13:19 1997 Fred Fish <fnf@cygnus.com>
+
+ * config/tc-tic80.c (build_insn): Remove "extended" and replace with
+ "fx" and "fxfrag". Add "ffrag". Change code to initialize and use
+ the right f/ffrag and fx/fxfrag pairs since instruction may be split
+ across frags.
+
+Tue Jul 22 18:38:56 1997 Robert Hoehne <robert.hoehne@Mathematik.TU-Chemnitz.DE>
+
+ * config/te-go32.h (USE_ALIGN_PTWO): Define.
+ * config/tc-i386.c (md_pseudo_table): If USE_ALIGN_PTWO is
+ defined, use s_align_ptwo for .align.
+ * configure.in (i386-*-msdosdjgpp*): New target.
+ (i386-*-go32*): Set em to go32 and targ to coffgo32.
+ * configure: Rebuild.
+
+Tue Jul 22 12:41:40 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/tc-sparc.c (last_opcode): New static local.
+ (md_assemble): Don't issue "FP branch in delay slot" warning if
+ the delay slot has been annulled.
+
+Tue Jul 22 13:25:13 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (md_apply_fix_2): Check for PC relative reloc
+ code if BFD_ASSEMBLER.
+
+Mon Jul 21 08:57:17 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-v850.c (system_registers): Fix ordering of registers.
+
+Tue Jul 15 16:29:54 1997 Fred Fish <fnf@cygnus.com>
+
+ * config/tc-tic80.c (build_insn): Initialize extended word to zero
+ when it will be filled in later by relocation information.
+
+Mon Jul 14 23:10:58 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (macro_build): Restore check of fmt argument.
+ (mips_ip): Fix ISA checks.
+
+Mon Jul 14 19:30:55 1997 Fred Fish <fnf@cygnus.com>
+
+ * config/tc-tic80.c (build_insn): Fix endianness problem with
+ O_big operands.
+
+Sun Jul 13 20:43:46 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (check_absolute_expr): Change warning to
+ error.
+
+Fri Jul 11 10:18:47 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mips.c (macro_build): Refine code to check if an
+ instruction is available on a particular cpu variant.
+ (mips_ip): Likewise.
+
+Mon Jul 7 22:53:08 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-i386.c (tc_i386_fix_adjustable): Change ifndef
+ OBJ_AOUT to ifdef OBJ_ELF.
+ (md_apply_fix3): When mangling 32 bit PC relative reloc for
+ BFD_ASSEMBLER, handle one ELF case for COFF as well, and add a PE
+ case.
+ * write.c (fixup_segment): Change special case for i386-coff to
+ not apply for i386-pe.
+ * config/obj-coff.c (coff_adjust_section_syms): Only count fixups
+ which were not done.
+ (coff_frob_file_after_relocs): Rename from coff_frob_file.
+ (coff_format_ops): Initialize frob_file_after_relocs field rather
+ than frob_file field.
+ * config/obj-coff.h (coff_frob_file): Don't declare.
+ (coff_frob_file_after_relocs): Declare.
+ (obj_frob_file): Don't define.
+ (obj_frob_file_after_relocs): Define.
+ * configure.in: Set bfd_gas to yes for i386-*-cygwin32.
+ * configure: Rebuild.
+
+Wed Jul 2 12:05:00 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.c (fixup_segment): Never subtract section
+ address from PC relative reloc which will be fully resolved.
+
+Tue Jul 1 15:23:07 1997 Jeffrey A Law (law@cygnus.com)
+
+ * ecoff.c (page_type): Renamed from page_t to avoid conflict
+ with hpux10 header files.
+
+Mon Jun 30 12:27:28 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ From Jason Merrill <jason@cygnus.com>:
+ * read.c (do_align): If BFD_ASSEMBLER, only use NOP_OPCODE if
+ SEC_CODE is set.
+ * config/tc-i386.h (md_maybe_text): Define.
+ (md_do_align): Use md_maybe_text.
+
+Fri Jun 27 19:15:27 1997 Michael Meissner <meissner@cygnus.com>
+
+ * config/tc-ppc.h (tc_fix_adjustable): Only check for GOT type
+ relocations, don't check for symbol being external, weak, etc.
+
+Mon Jun 16 19:12:51 1997 Geoff Keating <geoffk@ozemail.com.au>
+
+ * config/tc-ppc.h (tc_fix_adjustable): Don't let the assembler
+ calculate relocations to any external symbol, because we might be
+ linking a shared object and the symbol might be overriden or moved
+ (for instance, moved into a static executable's .bss section).
+ (GLOBAL_OFFSET_TABLE_NAME): Delete. This is an i386 wierdness.
+
+ * config/tc-ppc.h (tc_fix_adjustable): GOT-based relocations can't
+ be calculated by the assembler.
+
+ * config/tc-ppc.c (md_apply_fix3): Handle @plt or @local branch
+ whose destination lies in the same file, by ignoring the @plt or
+ @local and aiming the branch at its destination.
+
+Mon Jun 16 13:59:18 1997 H.J. Lu <hjl@gnu.ai.mit.edu>
+
+ * symbols.c (copy_symbol_attributes): Copy BSF_OBJECT flag.
+ * config/obj-elf.h (OBJ_COPY_SYMBOL_ATTRIBUTES): Copy size
+ expression.
+
+ * config/obj-multi.h (OBJ_COPY_SYMBOL_ATTRIBUTES): Define instead
+ of obj_copy_symbol_attributes.
+
+Mon Jun 16 12:45:56 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-ppc.c (ppc_insert_operand): In 32 bit mode, with a
+ signed operand, sign extend a 32 bit value to the host size.
+
+ * Makefile.in (CFLAGS): Subsitute from configure script. From
+ Jeff Makey <jeff@cts.com>.
+
+ * config/tc-i386.c (i386_operand): Use alloca rather than a fixed
+ buffer size to make a copy of the symbol.
+
+ * Makefile.in (OBJS): Put @extra_objects@ on the same line as
+ macro.o.
+
+Thu Jun 12 12:16:20 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * write.c (write_object_file): In non BFD_ASSEMBLER code, as we
+ step through the frags calling cvt_frag_to_fill, switch to
+ SEG_DATA when we reach data_frag_root.
+
+Tue Jun 10 17:08:34 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10300.c (md_assemble): Allow an empty register
+ list for instructions which use register lists.
+
+Tue Jun 10 11:18:09 1997 H.J. Lu <hjl@gnu.ai.mit.edu>
+
+ * config/tc-arm.c (md_apply_fix3): Make temp unsigned long.
+
+ * config/tc-arm.c (arm_adjust_symtab): Only set storage classes if
+ OBJ_COFF.
+
+ * config/tc-arm.c: Add prototypes for many static functions.
+ (struct asm_opcode ): Add prototypes for parms field.
+ (struct thumb_opcode ): Likewise.
+ (fp_op2): Remove unused flags parameter.
+ (output_inst): Make static.
+ (arm_after_pass_hook): Remove unused ignore parameter.
+ * config/tc-arm.h (arm_after_pass_hook): Declare.
+ (arm_start_line_hook): Declare.
+ (arm_frob_label): Declare.
+
+Mon Jun 9 12:55:45 1997 H.J. Lu <hjl@gnu.ai.mit.edu>
+
+ * depend.c (wrap_output): new prototype.
+
+Mon Jun 9 12:52:44 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sh.c (md_apply_fix): Check for overflow.
+
+ * config/tc-m68k.c (md_section_align): If a.out and BFD, force
+ section size to be aligned.
+
+Fri Jun 6 17:15:55 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sh.h (md_cons_align): Define.
+ (sh_cons_align): Declare.
+ * config/tc-sh.c (md_pseudo_table): Add .uaword and .ualong.
+ (sh_no_align_cons): New static variable.
+ (s_uacons): New static function.
+ (sh_cons_align): New function.
+ (sh_handle_align): Warn about misaligned data.
+ * doc/c-sh.texi: Document .uaword and .ualong.
+
+Thu Jun 5 15:38:17 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * macro.c (macro_expand): In MRI mode, treat single quote as a
+ separator character when checking for a positional argument.
+
+Tue Jun 3 16:15:13 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-arm.c (md_parse_option): Merge in changes from
+ armT-970328-branch.
+
+ * config/tc-arm.h: Merge in changes from armT-970328-branch.
+
+ * configure.in (emulations): Add Thumb architecture support from
+ armT-9703-28-branch.
+
+Mon Jun 2 16:25:07 1997 Nick Clifton <nickc@cygnus.com>
+
+ * doc/all.texi: Add enabling of ARM documentation.
+
+ * doc/as.texinfo: Add ARM documentation from armT-970328-branch.
+
+Mon Jun 2 11:55:12 1997 Gavin Koch <gavin@cygnus.com>
+
+ * config/tc-mips.c: Added r3900 support.
+
+Thu May 29 12:58:26 1997 Ben Pfaff <pfaffben@pilot.msu.edu>
+
+ * as.c: (parse_args) `-t' option requires an argument.
+
+Wed May 28 15:45:07 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-arm.c (md_begin): Change call to
+ coff_arm_bfd_set_private_flags() to a call to
+ bfd_set_private_flags().
+
+Wed May 28 16:17:34 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in: Rebuild dependencies.
+
+ * config/tc-i386.c (tc_gen_reloc): Don't try to convert the type
+ of a BFD_RELOC_RVA reloc.
+
+Wed May 28 10:48:14 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-hppa.c (tc_fix_adjustable): Reject absolute calls/jumps.
+ (hppa_force_relocation): Force a relocation for an absolute
+ call/jump.
+
+Mon May 26 13:24:25 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * doc/as.texinfo: Don't use @value in section names or index
+ entries; it confuses texinfo.tex.
+
+Fri May 23 00:09:35 1997 Tom Tromey <tromey@cygnus.com>
+
+ * doc/as.texinfo: Updated for -MD option.
+ * Makefile.in (CFILES): Added depend.c.
+ (OBJS): Added depend.o.
+ * as.h (start_dependencies, register_dependency,
+ print_dependencies): New declarations.
+ * depend.c: New file.
+ * as.c (parse_args): Added -MD option.
+ (main): Call print_dependencies.
+ (show_usage): Added help for -MD.
+ * read.c (s_app_file): Call register_dependency.
+ (s_include): Call register_dependency when file is found.
+ (read_a_source_file): Call register_dependency.
+
+Wed May 21 17:39:28 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.c (symbol_to_chars): If TE_PE, don't add the
+ section address to the symbol value.
+
+Tue May 20 11:23:31 1997 Gavin Koch <gavin@cygnus.com>
+
+ * config/tc-mips.c (macro_build,mips_ip): Move the INSN_ISA field
+ into the new membership field.
+
+Thu May 15 10:00:53 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-arm.c (md_begin): If no cpu type is specified on the
+ command line then the ARM7 is now chosen by default when setting
+ the BFD machine and architecture.
+
+Wed May 14 09:54:53 1997 Nick Clifton <nickc@cygnus.com>
+
+ * config/tc-arm.c (global variables): Added 'uses_apcs_26' flag to
+ hold APCS selection.
+ (md_begin): Added code to generate flags to be set into the COFF
+ header and the calls to the BFD functions to do this.
+ (md_parse_option, md_show_usage): Added new command line
+ options -mapcs-32, -mapcs-26, -marmv2, -marmv2a, -marmv3,
+ -marmv3m, -marmv4, -marmv4t.
+
+ * tc-arm.h (LOCAL_LABEL): Removed the definition of this macro
+ as it is never used.
+
+Tue May 13 22:26:14 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10200.c (md_convert_frag): Prefix temporary
+ label name with ".".
+ * config/tc-mn10300.c (md_convert_frag): Likewise.
+
+Tue May 13 14:44:39 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (set_at): Check for bignum.
+ (check_absolute_expr, macro, mips16_macro): Likewise.
+
+Tue May 13 10:45:56 1997 Fred Fish <fnf@cygnus.com>
+
+ * config/tc-tic80.c (md_apply_fix): Check PC relative relocations
+ for overflow/underflow, only insert lower 15 bits into instruction.
+
+Mon May 12 13:33:08 1997 H.J. Lu <hjl@gnu.ai.mit.edu>
+
+ * config/tc-i386.c (pi): Check for RegMMX.
+
+Thu May 8 11:10:15 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * expr.c (expr): When subtracting values in the same frag,
+ subtract X_add_number rather than adding it.
+
+Wed May 7 15:39:48 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.c (write_object_file): Just pass NULL to
+ md_do_align, not the address of a char holding NOP_OPCODE.
+
+ * config/tc-mips.c (macro): Handle constants for M_LI_D and
+ M_LI_DD.
+ (mips_ip): For 'F', 'L', 'f', and 'l', generate a constant rather
+ than an address if the floating point value looks sufficiently
+ simple.
+
+Tue May 6 12:18:09 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-i386.c (md_section_align): If a.out and BFD, force
+ section size to be aligned.
+
+Mon May 5 17:16:55 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * cond.c: Include "macro.h".
+ (struct conditional_frame): Add macro_nest field.
+ (initialize_cframe): Initialize macro_nest.
+ (cond_finish_check): Add nest parameter. Change all callers.
+ (cond_exit_macro): New function.
+ * as.h (cond_finish_check): Update declaration.
+ (cond_exit_macro): Declare.
+ * input-scrub.c (macro_nest): Make globally visible.
+ (input_scrub_next_buffer): Call cond_finish_check.
+ * macro.h (macro_nest): Declare.
+ * read.c (s_mexit): Call cond_exit_macro.
+
+ * config/tc-i386.h (RegMMX): Define.
+ * config/tc-i386.c (pi): Check for all register types.
+ (type_names): Add RegMMX.
+ (md_assemble): Handle RegMMX.
+
+Wed Apr 30 12:47:00 1997 Manfred Hollstein <manfred@s-direktnet.de>
+
+ * config/obj-coff.c (c_section_symbol): Clear the LOCAL bit #ifdef
+ TE_DELTA.
+
+Tue Apr 29 20:23:10 1997 Jim Wilson <wilson@cygnus.com>
+
+ * config/tc-mips.c (nopic_need_relax): Add new parameter
+ before_relaxing. Use it when testing ecoff_extern_size.
+ (load_address, macro, md_estimate_size_before_relax): Fix all
+ callers.
+
+Tue Apr 29 19:54:36 1997 Richard Henderson <rth@tamu.edu>
+
+ * config/obj-elf.c (elf_pseudo_table): Add "subsection".
+ (obj_elf_subsection): New static function.
+
+Tue Apr 29 19:52:47 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.c (coff_header_append): Don't reset string_size
+ each time through the loop.
+
+Fri Apr 25 14:17:46 1997 H.J. Lu <hjl@gnu.ai.mit.edu>
+
+ * Makefile.in (DISTSTUFF): Add itbl-parse.h.
+
+Fri Apr 25 12:03:15 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * doc/internals.texi (Porting GAS): Correct documentation for
+ current configure handling of targ-cpu.h, et. al.
+ (CPU backend): Document listing macros.
+
+ * listing.c (data_buffer): Set size based on other listing macros,
+ rather than always using 100.
+ (data_buffer_size): Remove static variable.
+ (calc_hex): Make data_buffer_size a local variable. Don't leave
+ any slop when filling data_buffer.
+
+Mon Apr 21 15:33:19 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * doc/c-mips.texi: Document .set autoextend.
+
+Sat Apr 19 23:09:25 1997 Niklas Hallqvist <niklas@petra.appli.se>
+
+ * configure.in (i386-*-openbsd*, m68k-*-openbsd*,
+ mips-dec-openbsd*, ppc-*-*bsd*, ns32k-pc532-openbsd*,
+ sparc-*-openbsd*): New targets.
+ * configure: Rebuild.
+
+Sat Apr 19 22:52:03 1997 Jim Wilson <wilson@cygnus.com>
+
+ * config/obj-elf.c (elf_frob_symbol): If TC_MIPS, set BSF_OBJECT
+ for all undefined symbols.
+
+Fri Apr 18 13:37:35 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-ppc.c (ppc_fix_adjustable): Handle zero length csects
+ correctly.
+
+Fri Apr 18 11:51:35 1997 Niklas Hallqvist <niklas@appli.se>
+
+ * configure.in (alpha*-*-openbsd*): New target.
+ * configure: Rebuild.
+
+Thu Apr 17 13:59:47 1997 Per Fogelstrom <pefo@openbsd.org>
+
+ * configure.in (mips-*-openbsd*): New target.
+ * configure: Rebuild.
+
+Wed Apr 16 12:31:24 1997 Martin Hunt <hunt@cygnus.com>
+
+ * config/tc-d30v.c (parallel_ok): Fix parallel checking
+ for instructions using conditional execution.
+
+Tue Apr 15 18:11:44 1997 Gavin Koch <gavin@cygnus.com>
+
+ * config/tc-mips.c (insn_uses_reg): Correct test for fpr pairs.
+
+Tue Apr 15 13:04:47 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (srcroot): Remove.
+ (INSTALL): Set to @INSTALL@.
+ (INSTALL_XFORM, INSTALL_XFORM1): Remove.
+ (all, dvi): Don't set srcroot.
+ (install): Depend upon as.new, gasp.new, and installdirs. Use
+ $(program_transform_name) directly, rather than using
+ $(INSTALL_XFORM) and $(INSTALL_XFORM1).
+ (installdirs): New target.
+ * doc/Makefile.in (INSTALL_XFORM1): Remove.
+ (install): Depend upon installdirs. Use $(program_transform_name)
+ directly, rather than using $(INSTALL_XFORM) and
+ $(INSTALL_XFORM1).
+ (installdirs): New target.
+ (install-info-as): Run mkinstalldirs.
+ (install-info-gasp): Likewise.
+
+Mon Apr 14 11:59:08 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (INSTALL): Change install.sh to install-sh.
+
+ * symbols.c (resolve_symbol_value): Check for division by zero.
+
+ From Thomas Graichen <graichen@rzpd.de>:
+ * Makefile.in: Always use $(SHELL) when running move-if-change.
+ * configure.in: Use ${CONFIG_SHELL} when running $ac_config_sub.
+ * configure: Rebuild.
+
+Thu Apr 10 14:40:00 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * cgen.c (cgen_parse_operand): Renamed from cgen_asm_parse_operand.
+ New argument `want'. Update enum cgen_parse_operand_result values.
+ Initialize if CGEN_PARSE_OPERAND_INIT.
+ * config/tc-m32r.c (md_begin): Set cgen_parse_operand_fn.
+ (md_assemble): Call cgen_asm_init_parse.
+ Update call to m32r_cgen_assemble_insn, call as_bad if assembly failed.
+
+Wed Apr 9 11:49:41 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (m68k_ip): Handle #j.
+
+Tue Apr 8 16:37:57 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10300.c (md_convert_frag): Create fixup at the
+ right address for call label:32,regs,imm.
+
+Mon Apr 7 14:58:22 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-hppa.c (pa_subspace_start): If OBJ_ELF, then always return
+ zero.
+ * config/tc-hppa.h (tc_frob_symbol): Don't reset the value of the
+ symbol for OBJ_ELF anymore.
+
+Mon Apr 7 10:54:59 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * Makefile.in: Regenerate dependencies.
+ (TARG_CPU): New variable.
+ (cgen.o): Depend on cgen.h, $(TARG_CPU)-opc.h.
+ (.dep1): Delete creating of cgen-opc.h.
+ (.tcdep): Put proper contents in cgen-opc.h.
+ * configure.in (m32r): Delete setting of extra_files, extra_links.
+ (AC_OUTPUT): Create cgen-opc.h.
+ * configure: Regenerated.
+
+Sat Apr 5 13:19:12 1997 Klaus Kaempf <kkaempf@progis.de>
+
+ * makefile.vms: Update to build gasp.exe.
+
+Fri Apr 4 16:10:02 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * write.c (relax_frag): Make non-static.
+ * write.h (relax_frag): Add prototype for.
+ * config/tc-m32r.h (md_do_align): New arg `max'.
+ * config/tc-m32r.c (m32r_do_align): Likewise.
+ Update calls to frag_align, frag_align_pattern.
+ (fill_insn): Update call to m32r_do_align.
+ (m32r_scomm): Update call to frag_align.
+
+ * config/tc-m32r.[ch]: New files.
+ * cgen.c: New file.
+ * Makefile.in (CPU_TYPES): Add m32r.
+ (TARGET_CPU_CFILES): Add tc-m32r.c.
+ (TARGET_CPU_HFILES): Add tc-m32r.h.
+ (DISTCLEAN_HERE): Add cgen-opc.h.
+ (.dep1,.tcdep): Create empty cgen-opc.h.
+ (cgen.o): Add dependencies.
+ (dependencies): Regenerate.
+ * as.h (struct frag): New member fr_targ.
+ (fr_pcrel_adjust,fr_bsr): Move into union fr_targ.ns32k.
+ * conf.in (USING_CGEN): New macro.
+ * configure.in (m32r-*-*): Add entry for.
+ Add cgen.o to extra_objects.
+ * configure: Regenerate.
+ * frags.c (frag_var): fr_pcrel_adjust renamed to
+ fr_targ.ns32k.pcrel_adjust. fr_bsr renamed to fr_targ.ns32k.bsr.
+ (frag_variant): Likewise.
+ * write.c (relax_frag): Likewise.
+ * config/tc-ns32k.c (*): Likewise.
+
+Fri Apr 4 13:26:10 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-hppa.h (TC_EOL_IN_INSN): Check explicitly for '!',
+ rather than for any end of line character.
+
+ * config/tc-hppa.c (tc_gen_reloc): If hppa_ren_reloc_type fails,
+ call abort (i.e., as_abort) rather than crashing.
+
+ * config/tc-mips.c: Protect uses of STO_MIPS16 with an ifdef of
+ OBJ_ELF, rather than of S_GET_OTHER.
+
+ * Makefile.in (DISTCLEAN_HERE): Add site.exp and site.bak.
+
+Thu Apr 3 13:16:18 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (VERSION): Set to 2.8.1.
+
+ * Branched binutils 2.8.
+
+Wed Apr 2 12:24:10 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * COPYING: Update FSF address.
+
+ * config/tc-mips.c (mips16_macro): Handle M_DMUL and M_MUL.
+
+Tue Apr 1 18:29:47 1997 Jim Wilson <wilson@cygnus.com>
+
+ * config/tc-mips.c (md_begin): Don't set interlocks for 4100.
+
+Tue Apr 1 16:24:28 1997 Klaus Kaempf <kkaempf@progis.de>
+
+ * config-gas.com: Update to handle both vax and alpha.
+ * makefile.vms: Update to use config-gas.
+ * conf-a-gas.com: Remove file.
+
+Tue Apr 1 16:08:21 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in: Remove unnecessary itbl-parse.h, ibtl-parse.c, and
+ itbl-lex.c dependencies. Remove rules for itbl-lex.o,
+ itbl-parse.o, and itbl-ops.o; just use the normal .c.o rule.
+
+Tue Apr 1 11:25:56 1997 Michael Meissner <meissner@cygnus.com>
+
+ * config/tc-tic80.c (line_comment_char): Make '#' start comments
+ at the beginning of a line for compatibility with .S files where
+ cpp leaves the filename transitions beginning with '#'.
+
+Tue Apr 1 00:07:30 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c: Only compile tc_coff_symbol_emit_hook and
+ tc_coff_sizemachdep if OBJ_COFF.
+
+Mon Mar 31 23:53:44 1997 H.J. Lu <hjl@gnu.ai.mit.edu>
+
+ * config/tc-ppc.c (register_name): Declare.
+
+Mon Mar 31 16:31:04 1997 Joel Sherrill <joel@oarcorp.com>
+
+ * configure.in (hppa*-*-rtems*): New target, like hppa-*-*elf*.
+ * configure: Rebuild.
+
+Mon Mar 31 14:15:19 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (mips_pseudo_table): Add "stabn".
+ (mips16_mark_labels): New static function.
+ (append_insn): Call mips16_mark_labels.
+ (mips_emit_delays): Likewise.
+ (s_insn): Likewise. Don't call mips_clear_insn_labels.
+ (s_mips_stab): New static function.
+
+ * configure.in: Use ELF for mips-*-gnu*.
+ * configure: Rebuild.
+
+Mon Mar 31 14:01:40 1997 Philippe De Muyter <phdm@info.ucl.ac.be>
+
+ * config/tc-m68k.h (TARGET_FORMAT): Set to "coff-m68k-sysv" if
+ TE_DELTA.
+
+Fri Mar 28 18:03:19 1997 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * configure.in: Add AC_ARG_ENABLE for commonbfdlib. If it is set,
+ set OPCODES_LIB to empty.
+ * configure: Rebuild.
+
+Fri Mar 28 15:25:24 1997 H.J. Lu <hjl@gnu.ai.mit.edu>
+
+ * configure.in (sparc-*-linux*aout*, sparc-*-linux*): New
+ targets.
+ * configure: Rebuild.
+
+Fri Mar 28 13:08:33 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * itbl-parse.y (yyerror): Make static. Declare.
+
+ From Ralf Baechle <ralf@gnu.ai.mit.edu>:
+ * configure.in: Set emulations for mips-*-linux*-*.
+ * configure: Rebuild.
+
+ * config/tc-mips.c (struct mips_set_options): Define.
+ (mips_opts): New static variable.
+ (mips_isa): Remove. Now a field in mips_opts. Change all
+ references.
+ (mips16, mips16_autoextend, mips_warn_about_macros): Likewise.
+ (mips_noreorder, mips_nomove, mips_noat, mips_nobopt): Likewise.
+ (struct mips_option_stack): Define.
+ (mips_opts_stack): New static variable.
+ (s_mipsset): Add support for .set push and .set pop.
+ * doc/c-mips.texi: Document .set push and .set pop.
+
+ * config/obj-elf.c (obj_elf_section_change_hook): New function.
+ * config/obj-elf.h (obj_elf_section_change_hook): Declare it.
+ * config/tc-mips.c (s_change_sec): Call it if OBJ_ELF.
+
+Thu Mar 27 12:23:56 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * as.c (parse_args): Update copyright date in version message.
+
+ * Makefile.in (clean-here): Remove dependency files.
+
+ * read.c (s_comm): Check S_IS_COMMON as well as S_IS_DEFINED.
+ (s_mri_common): Check S_IS_COMMON unconditionally.
+ * symbols.c (colon): Check S_IS_COMMON as well as S_IS_DEFINED.
+ * config/tc-alpha.c (s_alpha_comm): Likewise.
+ * config/tc-mips.c (nopic_need_relax): Likewise.
+ * config/tc-ppc.c (ppc_elf_lcomm): Likewise.
+ (ppc_pe_comm): Likewise.
+ * config/obj-elf.c (obj_elf_common): Likewise. Set segment of
+ common symbol to bfd_com_section_ptr.
+ * config/tc-sparc.c (s_common): Likewise.
+ (tc_gen_reloc): Likewise.
+
+Thu Mar 27 00:29:46 1997 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d30v.c (md_apply_fix3): Get the relocs right.
+
+Wed Mar 26 13:35:15 1997 H.J. Lu <hjl@lucon.org>
+
+ * config/tc-i386.c (tc_i386_fix_adjustable): Only define if
+ BFD_ASSEMBLER.
+
+Wed Mar 26 11:32:51 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * input-scrub.c (input_scrub_next_buffer): Handle very long input
+ lines correctly.
+
+ * listing.c (print_lines): Add lineno parameter. Change all
+ callers.
+ (listing_listing): Only call calc_hex for the right line.
+ (listing_list): Set the new edict based on the current edict, in
+ order to handle listing commands in macros correctly.
+
+ * config/tc-mips.c (insn_uses_reg): Map register numbers in mips16
+ instructions.
+
+ * cond.c (cond_finish_check): New function.
+ * as.h (cond_finish_check): Declare.
+ * as.c (main): Call cond_finish_check.
+
+Tue Mar 25 14:45:54 1997 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d30v.c (md_assemble): If two instructions
+ are supposed to be assembled in parallel and the first one is
+ long, print an error and stop.
+ (md_apply_fix3): Don't calculate absolute relocs. Just write
+ them out.
+
+Mon Mar 24 12:11:18 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-i386.h (iclrKludge): Define.
+ * config/tc-i386.c (md_assemble): Handle iclrKludge.
+
+ * config/tc-alpha.h (tc_frob_file_before_adjust): Define if
+ OBJ_ECOFF.
+ (alpha_frob_file_before_adjust): Declare if OBJ_ECOFF.
+ * config/tc-alpha.c (alpha_debug): New static variable.
+ (md_parse_option): Set alpha_debug if -g is seen.
+ (alpha_frob_file_before_adjust): New function if OBJ_ECOFF.
+
+Sun Mar 23 18:03:31 1997 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d30v.c (build_insn): Enable range-checking code.
+ (postfix): Stop at space or comma.
+ (md_assemble): Change error message.
+
+Sat Mar 22 13:44:28 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in: Added automatic dependency building.
+ * dep-in.sed: New file.
+
+Fri Mar 21 15:42:37 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-ieee.c (segment_name): Don't define function if this
+ is a macro.
+
+ * config/obj-coff.h (DO_STRIP): Don't define.
+ * config/tc-h8300.h (DO_STRIP): Don't define.
+ * config/tc-h8500.h (DO_STRIP): Don't define.
+ * config/tc-w65.h (DO_STRIP): Don't define.
+ * config/tc-z8k.h (DO_STRIP): Don't define.
+
+ * symbols.c (colon): Call obj_frob_label if it is defined.
+ * config/obj-vms.h (obj_frob_label): Rename from tc_frob_label.
+
+ * configure.in: Don't set files and links. Don't call
+ AC_LINK_FILES. Substitute te_file. Create targ-cpu.h,
+ obj-format.h, targ-env.h, and itbl-cpu.h in AC_OUTPUT.
+ * configure: Rebuild.
+ * Makefile.in (TARG_CPU_C): New variable.
+ (TARG_CPU_O, TARG_CPU_H): New variables.
+ (OBJ_FORMAT_C, OBJ_FORMAT_O, OBJ_FORMAT_H): New variables.
+ (TARG_ENV_H, ATOF_TARG_C, ATOF_TARG_O): New variables.
+ (SOURCES): Rename from REAL_SOURCES. Delete old definition.
+ (LINKED_SOURCES): Remove.
+ (HEADERS): Rename from REAL_HEADERS. Delete old definition.
+ (LINKED_HEADERS): Remove.
+ (OBJS): Use $(TARG_CPU_O), etc., rather than targ-cpu.o, etc.
+ ($(OBJS)): Depend upon $(TARG_ENV_H), etc., rather than
+ targ-cpu.h, etc.
+ ($(TARG_CPU_O), $(OBJ_FORMAT_O) $(ATOF_TARG_O)): New targets.
+ (targ-cpu.o, obj-format.o, atof-targ.o): Remove targets.
+ (itbl-cpu.h): Remove target.
+ (DISTCLEAN_HERE): Remove targ-cpu.c, obj-format.c, atof-targ.c,
+ atof-targ.h.
+
+Thu Mar 20 19:18:58 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * doc/as.texinfo (Symbol Names): Don't use obsolete @ctrl macro.
+
+Thu Mar 20 16:49:14 1997 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * config/tc-m68k.c (mri_chip): Replace calls to get_symbol_end by
+ open coded loop that does not require the name to start with a
+ name beginner.
+
+Thu Mar 20 13:42:01 1997 H.J. Lu <hjl@lucon.org>
+
+ * frags.c (frag_var): Change offset parameter to offsetT.
+ (frag_variant): Likewise.
+ * frags.h (frag_variant, frag_var): Update declarations.
+ * config/tc-m68k.c (struct m68k_it): Change foff field to
+ offsetT.
+ (add_frag): Change off parameter to offsetT.
+ * Several files: Add casts to calls to frag_var.
+
+ * Makefile.in (m68k-parse.c): Depend upon itbl-parse.c, to
+ serialize a parallel make.
+ (itbl-parse.h): Split target out from itbl-parse.c.
+
+Thu Mar 20 12:48:45 1997 Philippe De Muyter <phdm@info.ucl.ac.be>
+
+ * config/m68k-parse.y (motorola_operand): Allow (zdireg,EXPR).
+
+ * config/te-delta.h (COFF_COMMON_ADDEND): Define.
+ * config/obj-coff.c (fixup_segment): Check COFF_COMMON_ADDEND when
+ storing the value of a common symbol.
+
+Wed Mar 19 11:37:57 1997 Philippe De Muyter <phdm@info.ucl.ac.be>
+
+ * config/obj-coff.c (glue_symbols): Unused variable symbolP
+ removed.
+ (crawl_symbols): Do not modify symbol_rootP and symbol_lastP here;
+ that is done by symbol_remove and symbol_insert.
+
+ * config/obj-coff.h (S_IS_LOCAL): Return 0 for a debugging
+ symbol.
+
+Wed Mar 19 11:06:29 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (load_register): In 32 bit mode, when not
+ dealing with a 64 bit number, permit the upper 32 bits to be set
+ even if bit 31 is not set.
+
+Tue Mar 18 23:30:14 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.c (potable): Add "equiv".
+ (s_set): Handle .equiv based on argument.
+ * doc/as.texinfo (Equiv): New node to document .equiv.
+ (Err): New node to document .err.
+
+Tue Mar 18 15:50:13 1997 H.J. Lu <hjl@lucon.org>
+
+ * Many files: Add function prototypes.
+ * as.c (show_usage, parse_args): Make static.
+ * frags.h (frag_alloc): Declare.
+ * subsegs.c (subseg_set_rest): Don't declare frag_alloc.
+ * symbols.c (dollar_label_instance): Change return type to long.
+ * symbols.h (print_symbol_value): Declare.
+ (print_expr, print_expr_1, print_symbol_value_1): Declare.
+ * write.c (fix_new_exp): Don't declare make_expr_symbol.
+ (remove_subsegs, relax_frag): Make static.
+ * config/atof-vax.c (atof_vax_sizeof): Change letter to int.
+ (what_kind_of_float): Likewise.
+ (atof_vax): Make static. Change what_kind to int.
+ (md_atof): Change what_statement_type to int.
+ * config/obj-ecoff.h (obj_ecoff_set_ext): Declare.
+ * config/tc-alpha.c (vax_md_atof): Declare.
+ (md_atof): Don't declare atof_ieee and vax_md_atof.
+ * config/tc-i386.c (set_16bit_code_flag): Make static.
+ * config/tc-i386.h (tc_i386_fix_adjustable): Declare.
+ * config/tc-m68k.c (add_fix): Change width to int.
+ (insert_reg): Change regname to const.
+ (md_atof): Don't declare atof_ieee.
+ (demand_empty_rest_of_line): Don't declare.
+ * config/tc-m88k.c (md_atof): Don't declare atof_ieee.
+ * config/tc-sparc.c (cmp_reg_entry): Change args to const PTR.
+ (parse_keyword_arg): Change lookup_fn to take const arg.
+ (md_atof): Don't declare atof_ieee.
+ * config/tc-sparc.h: Add ifdef for multiple inclusion.
+ (tc_aout_pre_write_hook): Don't declare.
+
+Mon Mar 17 11:21:09 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * as.h (bfd_alloc_by_size_t): Don't declare.
+ * Many files: Use xmalloc rather than bfd_alloc_by_size_t.
+
+Sun Mar 16 13:49:21 1997 Philippe De Muyter <phdm@info.ucl.ac.be>
+
+ * symbols.c (symbol_new): Don't call debug_verify_symchain.
+ (symbol_append): Set sy_next and sy_previous when adding a single
+ symbol to an empty list. Call debug_verify_symchain.
+ (verify_symbol_chain): Use assert, not know.
+
+Sat Mar 15 20:27:12 1997 Fred Fish <fnf@cygnus.com>
+
+ * NEWS: Note BeOS support.
+ * configure.in: (ppc-*-beos): New target, use coff as object format.
+ * configure: Regenerate with autoconf.
+
+Sat Mar 15 19:14:02 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (md_apply_fix): Improve error message for out
+ of range branch.
+
+ * Makefile.in: Add dependencies on obstack.h where needed.
+
+Fri Mar 14 15:33:38 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (md_estimate_size_before_relax): Handle the
+ case of a symbol equated to another symbol when using SVR4_PIC.
+
+ * Makefile.in (TARG_CPU_DEP_sparc): Add opcode/sparc.h.
+
+Thu Mar 13 11:20:51 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.c (read_a_source_file): Call LISTING_NEWLINE before
+ HANDLE_CONDITIONAL_ASSEMBLY when handling an MRI line label.
+
+ * config/obj-elf.c (obj_elf_data): Call md_flush_pending_output
+ and md_elf_section_change_hook if they are defined.
+ (obj_elf_text, obj_elf_previous): Likewise.
+
+Wed Mar 12 11:40:20 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-multi.h (struct elf_obj_sy): Define if
+ OBJ_MAYBE_ELF.
+ (OBJ_SYMFIELD_TYPE): Define as struct elf_obj_sy if
+ OBJ_MAYBE_ELF.
+ * config/obj-elf.h (struct elf_obj_sy): Don't define if
+ OBJ_SYMFIELD_TYPE is defined.
+
+ * doc/as.texinfo (bss): Improve description of .bss section. In
+ ELF or COFF, you are permitted to switch into the section.
+ (Comm): Rewrite description of common symbols.
+ (Lcomm): Mention that some targets permit a third argument.
+
+Tue Mar 11 01:13:31 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-ppc.c (ppc_elf_lcomm): Don't call S_CLEAR_EXTERNAL.
+
+ * symbols.c (colon): Change type of local to int. From Alan Modra
+ <alan@spri.levels.unisa.edu.au>.
+
+ * config/tc-m88k.c (m88k_do_align): Don't use a special nop
+ alignment if a zero fill pattern was explicitly specified.
+ * config/tc-sh.c (sh_do_align): Likewise.
+
+ * read.c (equals): Always permit register names to be redefined.
+
+ * config/tc-mips.c (mips_fix_adjustable): Permit a reloc against a
+ mips16 symbol to be adjusted if a symbol is being subtracted from
+ it.
+
+ From Eric Youngdale <eric@andante.jic.com>:
+ * config/obj-elf.c (obj_elf_symver): Check for duplicate or
+ illegal symbol version names.
+ (elf_frob_symbol): Check for external default versions.
+
+Sun Mar 9 23:49:12 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ From Eric Youngdale <eric@andante.jic.com>:
+ * config/obj-elf.h (struct elf_obj_sy): Define.
+ (OBJ_SYMFIELD_TYPE): Define to elf_obj_sy struct. Change all
+ users.
+ * config/obj-elf.c (obj_elf_symver): Just record the name.
+ (obj_symbol_new_hook): Initialized versioned_name field.
+ (elf_frob_symbol): If there is a versioned_name, either rename the
+ symbol, or add an alias with that name.
+
+Thu Mar 6 13:55:32 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10300.c (md_relax_table): Define.
+ (md_convert_frag): Implement.
+ (md_assemble): Handle relaxable operands/instructions correctly.
+ (md_estimate_size_before_relax): Implement.
+ * config/tc-mn10300.h (TC_GENERIC_RELAX_TABLE): Define.
+
+ * config/tc-mn10200.c (md_relax_table): Fix typos.
+
+ * config/tc-mn10300.c (md_assemble): Don't use any MN10300 specific
+ relocs anymore. Tweak fx_offset for pc-relative relocs.
+
+Wed Mar 5 15:46:16 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * cond.c (s_ifc): Call mri_comment_field and mri_comment_end when
+ in MRI mode.
+
+Tue Mar 4 19:34:21 1997 Fred Fish <fnf@cygnus.com>
+
+ * config/tc-tic80.c (md_pseudo_table): Add "sect" and "section"
+ pseudo-ops.
+ * config/tc-tic80.c (md_begin): Declare external variable
+ coff_flags and insert an F_AR32WR bit into it.
+
+Tue Mar 4 10:01:04 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.c (equals): Add reassign parameter. Change all callers.
+ * read.h (equals): Update declaration.
+
+Sat Mar 1 01:04:04 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (mips16_extended_frag): Don't assume that we
+ can rely on the frag address to determine whether a frag is
+ earlier or later.
+
+Fri Feb 28 14:40:00 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * write.h (LOCAL_LABEL): Only define if not BFD_ASSEMBLER.
+ (S_LOCAL_NAME): Likewise.
+ (FAKE_LABEL_NAME): Define unconditionally.
+ * symbols.c (colon): Call bfd_is_local_label, not LOCAL_LABEL, if
+ BFD_ASSEMBLER.
+ (S_IS_LOCAL): Call bfd_is_local_label_name, not LOCAL_LABEL.
+ * config/tc-*.h: Only define LOCAL_LABEL if not BFD_ASSEMBLER.
+ Don't define FAKE_LABEL_NAME.
+ * config/te-ic960.h: Likewise.
+ * config/tc-mips.h (tc_frob_file_before_adjust): Define.
+ (mips_frob_file_before_adjust): Declare.
+ * config/tc-mips.c (mips_frob_file_before_adjust): New function.
+ (mips_local_label): Remove.
+
+ * config/te-sco386.h: Remove; not used.
+
+Thu Feb 27 15:39:16 1997 Fred Fish <fnf@cygnus.com>
+
+ * config/tc-tic80 (md_pseudo_table): Add align pseudo op to do
+ byte alignment rather than power-of-two alignment that is the
+ GAS default.
+
+Thu Feb 27 13:29:04 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (md_assemble): Handle a reloc width of 'W'.
+
+ * gasp.c (hash_add_to_string_table): Correct misspelling in error
+ message, and add newline.
+ (process_file): Don't process assignments in the label if this is
+ a equ or assign pseudo-op.
+ (process_pseudo_op): Swap first argument to do_assign for K_ASSIGN
+ and K_EQU, to match documentation.
+
+Thu Feb 27 12:00:03 1997 Michael Meissner <meissner@cygnus.com>
+
+ * config/obj-coff.c (obj_coff_section): Add 'r' section attribute
+ to denote read-only data sections.
+
+Thu Feb 27 00:26:33 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-elf.c (obj_elf_common): Set BSF_OBJECT in flags.
+ * config/tc-sparc.c (s_common): Likewise, if BFD_ASSEMBLER.
+
+ * expr.c (operand): Simplify 0b handling. Don't treat 0b as a
+ binary number if the next character is '+' or '-'.
+
+Wed Feb 26 20:47:12 1997 Fred Fish <fnf@cygnus.com>
+
+ * config/tc-tic80.c (FLT_CHARS): Change from "dD" to "fF".
+ (find_opcode): Match operands that can be floats.
+ (build_insn): Handle O_big (float) expressions and build
+ correct opcode.
+
+Wed Feb 26 18:19:00 1997 Stan Shebs <shebs@andros.cygnus.com>
+
+ * configure.in (mips*-*-lnews*): New target, also make empty
+ emulation list for this target.
+ * configure: Update.
+ * tc-mips.c (ECOFF_LITTLE_FORMAT): Define.
+ (mips_target_format): Use.
+ * te-lnews.h: New file.
+
+Wed Feb 26 15:33:46 1997 Fred Fish <fnf@cygnus.com>
+
+ * config/tc-tic80.c (find_opcode, build_insn): Changes to match
+ operands with :m or :s modifiers and generate the right opcodes
+ for them.
+
+Wed Feb 26 11:56:11 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (itbl-parse.c itbl-parse.h): Use $(BISON) and
+ $(BISONFLAGS), not $(YACC) and $(YACCFLAGS).
+
+Tue Feb 25 22:02:23 1997 Philippe De Muyter <phdm@info.ucl.ac.be>
+
+ * config/tc-m68k.c (instring): Useless local declaration of
+ crack_operand removed.
+ * expr.h (expressionS): Changed type of X_op field to operatorT if
+ __GNUC__.
+
+Tue Feb 25 13:17:27 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ Based on patches from Robert Lipe <robertl@dgii.com>:
+ * configure.in: Add i386coff and i386elf to emulation list.
+ * configure: Rebuild.
+ * as.c (i386coff, i386elf): Declare.
+ * obj.h (coff_format_ops): Declare.
+ * config/obj-coff.c (OBJ_HEADER): Define.
+ (coff_obj_symbol_new_hook): Rename from obj_symbol_new_hook.
+ (coff_obj_read_begin_hook): Rename from obj_read_begin_hook.
+ (obj_pseudo_table): Add "version".
+ (coff_pop_insert): New static function.
+ (coff_sec_sym_ok_for_reloc): New static function.
+ (no_func): New static function.
+ (coff_format_ops): New variable.
+ * config/obj-coff.h (coff_obj_symbol_new_hook): Declare.
+ (obj_symbol_new_hook): Define.
+ (coff_obj_read_begin_hook): Declare.
+ (obj_read_begin_hook): Define.
+ * config/tc-i386.h (i386_target_format): Declare.
+ * config/tc-i386.c: Check OBJ_MAYBE_ELF as well as OBJ_ELF; check
+ OUTPUT_FLAVOR when appropriate.
+ (i386_target_format): New function.
+ * Makefile.in (obj-coff.o): New target.
+ (e-i386coff.o, e-i386elf.o): New targets.
+
+ From Stephen Williams <steve@icarus.icarus.com>:
+ * config/tc-i960.h (TC_SYMFIELD_TYPE): Define if OBJ_COFF.
+ (_tc_get_bal_of_call): Don't declare.
+ (tc_get_bal_of_call): Declare as function, don't define as macro.
+ * config/tc-i960.c (tc_set_bal_of_call): If OBJ_COFF, store balP
+ in sy_tc field, not x_balntry field.
+ (tc_get_bal_of_call): Rename from _tc_get_bal_of_call. Change
+ return type to symbolS *. If OBJ_COFF, retrieve value from sy_tc
+ field, not x_balntry field.
+
+ * config/obj-elf.c (obj_elf_section): Permit a .note section to
+ have the SHF_ALLOC attribute.
+
+ * Makefile.in ($(OBJS)): Don't depend upon $(IT_HDRS).
+ (TARG_CPU_DEP_mips): Depend upon $(srcdir)/itbl-ops.h.
+ (itbl-lex.o): Depend upon itbl-parse.h.
+
+ * itbl-parse.y (yyerror): Change return type to int. Change to
+ use old style function declaration.
+
+ * Makefile.in (itbl-lex.o): Remove -Wall.
+ (itbl-parse.o): Likewise.
+
+ * cond.c (s_ifdef): If we should omit conditionals from listings,
+ call listing_list.
+ (s_if, s_ifc, s_endif, s_else, s_ifeqs): Likewise.
+ * listing.c (list_info_struct): Add EDICT_NOLIST_NEXT.
+ (listing_listing): Handle EDICT_NOLIST_NEXT.
+ (listing_list): An argument of 2 means EDICT_NOLIST_NEXT.
+ * listing.h (LISTING_NOCOND): Define.
+ (LISTING_SKIP_COND): Define.
+ * as.c (show_usage): Mention c as a suboption of -a.
+ (parse_args): Handle c as a suboption of -a.
+ * doc/as.texinfo: Document -alc.
+
+Mon Feb 24 23:34:14 1997 Fred Fish <fnf@cygnus.com>
+
+ * config/tc-tic80.c (md_apply_fix): Handle R_ABS type fixups.
+
+Mon Feb 24 18:27:43 1997 Eric Youngdale <eric@andante.jic.com>
+
+ * doc/as.texinfo: Document .symver.
+
+Mon Feb 24 15:19:57 1997 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c: Change pre_defined_registers to
+ d10v_predefined_registers and reg_name_cnt to d10v_reg_name_cnt.
+
+Mon Feb 24 10:40:45 1997 Fred Fish <fnf@cygnus.com>
+
+ * config/obj-coff.c: Fix typo in comment section.
+ * config/tc-tic80.c (md_pseudo_table): Add entry for bss, which takes
+ an additional alignment argument.
+ (find_opcode): Allow O_symbol relocs for any 32 bit field, not just
+ base relative ones.
+ (build_insn): Handle O_symbol relocs for any 32 bit field, not just
+ base relative ones.
+
+Mon Feb 24 02:23:00 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * Makefile.in: Remove dependancies on itbl-cpu.h.
+ * as.c: Define stubs for itbl_parse and itbl_init if HAVE_ITBL_CPU
+ is not defined.
+
+Mon Feb 24 02:03:00 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * itbl-ops.h: Include as.h.
+
+Mon Feb 24 01:04:00 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * as.c: Remove -t option.
+ * configure, configure.in: Move itbl-cpu.h to mips specific configure.
+ * itbl-ops.h: Include itbl-cpu.h only if HAVE_ITBL_CPU is defined.
+ * config/tc-mips.h: Define HAVE_ITBL_CPU.
+
+Sun Feb 23 18:01:00 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * itbl-ops.c: Don't define DEBUG.
+
+Sun Feb 23 17:49:00 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * Makefile.in: Update itbl-test.c to reflect its new location.
+
+Sun Feb 23 15:50:00 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * itbl-ops.c: Add test for itbl_have_entries.
+ * config/tc-mips.c: Remove test for itbl_have_entries.
+ * config/tc-mips.h: Define tc_init_after_args to mips_init_after_args.
+
+Sun Feb 23 18:13:19 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (DISTSTUFF): Remove itbl-parse.y, itbl-lex.l, and
+ itbl-ops.c. Add itbl-parse.c and itbl-lex.c.
+ (LEX, LEXFLAGS): Define.
+ * itbl-ops.c (append_insns_as_macros): Remove bogus ASSERT.
+
+Sat Feb 22 21:25:00 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * itbl-parse.y: Fix indentation mistakes from indent program.
+ * itbl-lex.l: Fix indentation mistakes from indent program.
+ * itbl-ops.h: Add include for ansidecl.h.
+ Add PARAMS around function arguments.
+ Add declaration for itbl_have_entries.
+ * itbl-ops.c: Add PARAMS around function arguments.
+ * Makefile.in: Add itbl build rules.
+ Add dependancies for itbl files to mips target.
+ * as.c: Add itbl support.
+ Add new option "--insttbl" for dynamically extending instruction set.
+ * as.h: Declare insttbl_file_name;
+ the name of file defining extensions to the basic instruction set
+ * configure.in, configure: Add itbl-parse.o, itbl-lex.o, and
+ itbl-ops.o to extra_objects for mips configuration.
+ Add include file link from itbl-cpu.h to
+ config/itbl-${target_cpu_type}.h.
+ * config/tc-mips.c: Allow copz instructions.
+ Add notes for future additions to the itbl support.
+ Add debug macros.
+ (macro): Call itbl_assemble to assemble itbl instructions.
+ See if an unknown register is specified in an itbl entry.
+
+Sat Feb 22 20:53:01 1997 Fred Fish <fnf@cygnus.com>
+ * doc/internals.texi (CPU backend): Fix typo in md_section_align
+ description.
+ * config/tc-tic80.h (NEED_FX_R_TYPE): Define.
+ * config/tc-tic80.c (find_opcode): Add code to support O_symbol
+ operands.
+ (build_insn): Grab a frag early so we can use the address in
+ fixups. Take one's complement of BITNUM values before insertion
+ in opcode. Add code to support O_symbol operands.
+ (md_apply_fix): Replace unimplemented warning with implementation.
+ (md_pcrel_from): Ditto.
+ (tc_coff_fix2rtype): Ditto.
+
+Fri Feb 21 14:34:31 1997 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d30v.c (parallel_ok): New function.
+ * config/tc-d30v.h: Define TARGET_BYTES_BIG_ENDIAN.
+ * config/tc-d10v.c (md_pcrel_from_section): Return 0 if
+ relocation is in different section.
+
+Fri Feb 21 10:08:25 1997 Jim Wilson <wilson@cygnus.com>
+
+ * tc-mips.c (mips_ip): If configured for an embedded ELF system,
+ don't set the section alignment to 2**4.
+
+Fri Feb 21 11:55:03 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (line_comment_chars): Add '*'.
+
+ * app.c (LEX_IS_TWOCHAR_COMMENT_2ND): Don't define.
+ (do_scrub_begin): Don't set lex['*'].
+ (do_scrub_chars): When handling LEX_IS_TWOCHAR_COMMENT_1ST, don't
+ check for LEX_IS_TWOCHAR_COMMENT_2ND. Instead, just check for
+ a literal '*'.
+
+ * configure.in: Set em=svr4 for m68k-*-sysv4*.
+ * configure: Rebuild.
+ * config/te-svr4.h: New file.
+ * config/tc-m68k.c (m68k_comment_chars): Only include `#' if
+ TE_SVR4 or TE_DELTA.
+
+Thu Feb 20 22:24:39 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10200.c (md_convert_frag): Create a fixup for the
+ short conditional branch around a long unconditional branch.
+
+Thu Feb 20 13:56:00 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.c (obj_coff_ln [both versions]): Call
+ new_logical_line.
+
+ * config/tc-arm.c (fix_new_arm): Use make_expr_symbol to handle a
+ complex expression.
+
+ * symbols.c (resolve_symbol_value): If both left and right
+ operands are undefined, warn about both of them.
+
+Wed Feb 19 00:53:28 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ Based on patches from Eric Youngdale <eric@andante.jic.com>:
+ * config/obj-elf.c (elf_pseudo_table): Add "symver".
+ (obj_elf_symver): New static function.
+ * config/obj-elf.h (OBJ_COPY_SYMBOL_ATTRIBUTES): Copy the st_other
+ field.
+
+ * write.c (relax_segment): Make type and printf format agree.
+
+ * read.c (get_line_sb): Don't end the line on a semicolon inside a
+ string.
+
+Tue Feb 18 18:42:51 1997 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d30v.c, config/tc-d30v.h: New files.
+
+ * configure: Rebuilt.
+
+ * configure.in: Add case for d30v.
+
+Sun Feb 16 17:47:29 1997 Fred Fish <fnf@cygnus.com>
+
+ * config/tc-alpha.h (md_operand): Define with a null expansion,
+ like all the other targets.
+ * doc/internals.texi (CPU backend): Add missing word in
+ md_flush_pending_output description. Fix typo in md_convert_frag
+ description.
+ * config/tc-tic80: Minor comment additions/changes.
+
+Fri Feb 14 18:09:59 1997 Philippe De Muyter <phdm@info.ucl.ac.be>
+
+ * config/tc-m68k.c (LOCAL_LABEL): Macro redefined if TE_DELTA.
+ (tc_canonicalize_symbol_name): Macro defined if TE_DELTA.
+ * config/obj-coff.c (obj_coff_def): Use
+ tc_canonicalize_symbol_name if defined.
+ (obj_coff_tag, obj_coff_val): Likewise.
+ * expr.c (operand): Reject '~' as operator if is_name_beginner.
+
+Fri Feb 14 17:24:48 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ Based on notes from Peter Eriksson <peter@ifm.liu.se>. The target
+ does not actually work, though:
+ * configure.in (i386-sequent-bsd*): New target.
+ * configure: Rebuild.
+ * config/tc-dynix.h: New file.
+ * config/tc-i386.h: Define TARGET_FORMAT if TE_DYNIX.
+
+ * read.c (do_align): Add max parameter. Change all callers.
+ Remove useless static variables.
+ (s_align): New static function. Do common portion of
+ s_align_bytes and s_align_ptwo.
+ (s_align_bytes, s_align_ptwo): Just call s_align.
+ * frags.c (frag_align): Add max parameter. Change all callers.
+ (frag_align_pattern): Likewise.
+ * frags.h (frag_align, frag_align_pattern): Update declarations.
+ * write.c (relax_segment): Limit alignment change to fr_subtype.
+ Fix some types to be addressT.
+ * config/obj-coff.c (size_section): Likewise.
+ * config/obj-ieee.c (size_section): Likewise.
+ * config/tc-d10v.h (md_do_align): Add max parameter.
+ * config/tc-i386.h (md_do_align): Likewise.
+ * config/tc-m88k.h (md_do_align): Likewise.
+ * config/tc-m88k.c (m88k_do_align): Likewise.
+ * config/tc-sh.h (md_do_align): Likewise.
+ * config/tc-sh.c (sh_do_align): Likewise.
+ * as.h: Improve comments on rs_align and rs_align_code.
+ * doc/as.texinfo: Document new alignment arguments.
+ * doc/internals.texi (Frags): Document use of fr_subtype field for
+ rs_align and rs_align_code.
+
+Fri Feb 14 15:56:06 1997 Gavin Koch <gavin@cygnus.com>
+
+ * config/tc-mips.c: Changed opcode parsing.
+
+Thu Feb 13 20:02:16 1997 Fred Fish <fnf@cygnus.com>
+
+ * config/{tc-alpha.h, tc-d10v.h, tc-generic.h, tc-i960.h,
+ tc-mn10200.h, tc-mn10300.h, tc-sh.h, tc-vax.h, tc-w65.h}:
+ Add default definition of zero for TARGET_BYTES_BIG_ENDIAN.
+ * config/{tc-arm.h, tc-hppa.h, tc-i386.h, tc-mips.h, tc-ns32k.h,
+ tc-ppc.h, tc-sparc.h}: Move definition of TARGET_BYTES_BIG_ENDIAN
+ to a location consistent with the rest of the target include files.
+ * config/tc-i386.c: Remove misleading comment.
+ * doc/internals.texi (CPU backend): Add description of function
+ md_undefined_symbol.
+ * config/tc-tic80.c: Add code to insert predefined symbols into the
+ symbol table so they can be parsed by the standard expression parser.
+ Remove custom code that use to parse them.
+ * config/tc-tic80.h: Move definition of TARGET_BYTES_BIG_ENDIAN
+ to a location consistent with the rest of the target include files.
+
+Thu Feb 13 21:44:18 1997 Klaus Kaempf <kkaempf@progis.de>
+
+ * as.h: GNU c provides unlink() function.
+
+ Unify section handling on openVMS/Alpha:
+ * config/tc-alpha.c(s_alpha_link): Remove.
+ (s_alpha_section): New function.
+ Remove case-hacking of symbols
+ Add .code_address pseudo-op.
+ (BFD_RELOC_ALPHA_CODEADDR): New relocation.
+ (s_alpha_code_address): New function.
+ (alpha_ctors_section, alpha_dtors_section): New sections for C++
+ static constructors/destructors.
+ Add debug code for crash debugs, to be removed when traceback code
+ is added to object code.
+ (s_alpha_name): New function for .name pseudo-op.
+ (alpha_print_token): New function to print token expressions with
+ alpha specific extensions.
+
+ * makefile.vms: Allow compilation with current gcc snapshot.
+
+Thu Feb 13 16:29:04 1997 Fred Fish <fnf@cygnus.com>
+
+ * doc/Makefile.in (TEXI2DVI): Set to just name of program.
+ (DVIPS): Set to dvips.
+ (ps, as.ps, gasp.ps): New targets.
+ (internals.info, gasp.dvi, internals.dvi): Set both TEXINPUTS
+ and MAKEINFO env variables.
+ (internals.ps): Use DVIPS macro.
+ (clean): Remove core and backup files.
+ (distclean): Remove temporary files from building internals.
+ (clean-dvi): Ditto.
+ * doc/internals.texi (Frags): Fix typo.
+ (GAS processing): Ditto.
+ (CPU backend): Ditto.
+ * ecoff.c (init_file): Use TARGET_BYTES_BIG_ENDIAN value directly.
+ * mpw-config.in: Define TARGET_BYTES_BIG_ENDIAN as 1.
+ * read.c: Remove ugly hack that dealt with config files not
+ correctly defining TARGET_BYTES_BIG_ENDIAN.
+ (target_big_endian): Use TARGET_BYTES_BIG_ENDIAN directly.
+ * config/arm-big.mt: Define TARGET_BYTES_BIG_ENDIAN to 1.
+ * config/arm-lit.mt: Define TARGET_BYTES_BIG_ENDIAN to 0.
+ * config/mips-big.mt: Define TARGET_BYTES_BIG_ENDIAN to 1.
+ * config/mips-lit.mt: Define TARGET_BYTES_BIG_ENDIAN to 0.
+ * config/ppc-lit.mt: Define TARGET_BYTES_BIG_ENDIAN to 1.
+ * config/ppc-sol.mt: Replace TARGET_BYTES_LITTLE_ENDIAN
+ with TARGET_BYTES_BIG_ENDIAN defined to 0.
+ * config/tc-arm.h: Remove use of TARGET_BYTES_LITTLE_ENDIAN
+ and simplify. Test value of TARGET_BYTES_BIG_ENDIAN, not just
+ whether it is defined or not.
+ * config/tc-mips.h: Remove use of TARGET_BYTES_LITTLE_ENDIAN.
+ * config/tc-ppc.h: Remove use of TARGET_BYTES_LITTLE_ENDIAN
+ and simplify. Test value of TARGET_BYTES_BIG_ENDIAN, not just
+ whether it is defined or not.
+ * config/tic80.h (TARGET_FORMAT): Define to coff-tic80.
+ (TARGET_BYTES_BIG_ENDIAN): Define to 0.
+
+Thu Feb 13 14:40:16 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * write.c (write_relocs): Correct text in as_fatal error message,
+ bfd_perform_relocation -> bfd_install_relocation.
+
+Thu Feb 13 14:48:03 1997 Philippe De Muyter <phdm@info.ucl.ac.be>
+
+ * config/tc-m68k.c (LEX_TILDE): Define if TE_DELTA.
+ * read.c (LEX_TILDE): Define if not defined.
+ (lex_type): Use LEX_TILDE.
+ * expr.c (get_symbol_end): Check first char with is_name_beginner,
+ not is_part_of_name.
+
+Thu Feb 13 11:40:58 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sparc.c (md_show_usage): Add missing backslash at end
+ of continued line.
+
+ * config/tc-mips.c (mips16_extended_frag): Correct base address
+ for an extended PC relative instruction.
+ (md_convert_frag): Likewise.
+
+ * config/tc-mips.c (prev_nop_frag): New static variable.
+ (prev_nop_frag_holds): New static variable.
+ (prev_nop_frag_required): New static variable.
+ (prev_nop_frag_since): New static variable.
+ (append_insn): If we aren't reordering, and prev_nop_frag is not
+ NULL, and we don't need any nops, then decrease the size of
+ prev_nop_frag. Don't insert nops because of instructions in
+ noreorder sections. Remember whether the previous instructions
+ where in noreorder sections even when not reordering.
+ (mips_no_prev_insn): Add preserver parameter. Change all
+ callers. Refer prev_nop_frag variables when appropriate.
+ (mips_emit_delays): Set up prev_nop_frag.
+ (s_mipsset): Clear prev_nop_frag if reordering.
+
+Wed Feb 12 14:36:29 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (append_insn): Remove useless code which
+ handled swapping a mips16 jump with a mips16 instruction with a
+ reloc.
+
+ * config/tc-mips.c (md_parse_option): When debugging, set
+ mips_optimize to 1, not 0.
+
+ * config/tc-mips.c (mips16_ip): Handle an extend operand.
+
+ * config/tc-mips.c (my_getExpression): In mips16 mode, if it looks
+ like the expression was based on `.', adjust the value of the
+ symbol.
+
+ * config/tc-mips.c (append_insn): Warn about an attempt to put an
+ extended instruction in a delay slot when not reordering.
+ (md_convert_frag): Warn if an extended instruction appears in a
+ delay slot.
+
+ * config/tc-mips.c (mips_pseudo_table): Add "insn".
+ (s_insn): New static function.
+ * doc/c-mips.texi: Document .insn.
+
+ * config/tc-mips.c (md_begin): Add the general registers to the
+ symbol table.
+ (mips16_ip): First parse the expression, and then see whether it
+ came up with a register, rather than trying to first see whether
+ we are looking at a register.
+
+Tue Feb 11 15:13:39 1997 Fred Fish <fnf@cygnus.com>
+
+ * config/tc-tic80.c: Numerous changes and additions to flesh
+ out functions that were previously just stubs, and fix some
+ problems found using the new TIc80 testsuite cases.
+
+Tue Feb 11 15:52:22 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (mips16_ip): Handle %gprel modifier.
+ (md_apply_fix): Handle BFD_RELOC_MIPS16_GPREL.
+
+ * config/tc-mips.c (append_insn): Output jump instruction as a
+ pair of 2 byte instructions, rather than as a single 4 byte
+ instruction.
+
+Mon Feb 10 22:06:00 1997 Dawn Perchik (dawn@cygnus.com)
+
+ * itbl-ops.c, itbl-lex.l, itbl-parse.y, itbl-ops.h,
+ config/itbl-mips.h: Add copyright message and fix indentation.
+
+Mon Feb 10 18:09:00 1997 Dawn Perchik (dawn@cygnus.com)
+
+ * itbl-ops.c: New file. Add support for dynamically read
+ instruction registers, opcodes and formats. Build internal table
+ for new instructions and provide callbacks for assembler and
+ disassembler.
+ * itbl-lex.l, itbl-parse.y: Lex and yacc parsers for instruction
+ spec table.
+ * itbl-ops.h: New file. Header file for itbl support.
+ * config/itbl-mips.h: New file. Mips specific definitions for
+ itbl support.
+
+Fri Feb 7 09:52:34 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10200.c (md_assemble): If a constant operand won't
+ fit into the constant field of a relaxable operand, then it does
+ not match.
+
+Thu Feb 6 20:08:12 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10200.c (md_estimate_size_before_relax): Treat
+ a jsr target in a different section just like a jsr to
+ an undefined target.
+
+Thu Feb 6 16:52:57 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (mips_fix_adjustable): Don't adjust relocations
+ against any mips16 symbols, not just externally visible ones.
+ (md_apply_fix): Corresponding change.
+
+Wed Feb 5 11:11:06 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (mips16_ip): Accept floating point registers in
+ the operand of the exit instruction.
+
+Tue Feb 4 14:12:39 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * symbols.c (resolve_symbol_value): If we leave an equated symbol
+ as O_symbol, copy over the segment.
+
+Mon Feb 3 12:35:54 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (md_apply_fix): If we aren't adjusting this
+ fixup to be against the section symbol, adjust the value
+ accordingly.
+
+ * symbols.c (resolve_symbol_value): Don't change X_add_number for
+ an equated symbol.
+ * write.c (write_relocs): Avoid looping on equated symbols.
+ Adjust fx_offset by X_add_number for each symbol.
+ * config/obj-coff.c (do_relocs_for): Avoid looping on equated
+ symbols.
+ (fixup_segment): Add a loop to track down equated symbols and
+ adjust fx_offset appropriately.
+
+Fri Jan 31 15:21:02 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10200.c (md_relax_table): Add entries to allow
+ jmp -> bra relaxing.
+ (md_convert_frag): Handle jmp->bra relaxing.
+ (md_assemble): Handle jmp->bra relaxing.
+ (md_estimate_size_before_relax): Likewise.
+
+Fri Jan 31 13:15:05 1997 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * config/tc-i386.c (i386_align_code): Add comments explaining the
+ nop instructions.
+
+Fri Jan 31 10:46:14 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sparc.c (enforce_aligned_data): New static variable.
+ (sparc_cons_align): Don't do anything unless enforce_aligned_data
+ is set.
+ (md_longopts): Add "enforce-aligned-data".
+ (md_show_usage): Mention --enforce-aligned-data.
+ * doc/c-sparc.texi (Sparc-Aligned-Data): New node; document
+ enforce-aligned-data.
+
+ * config/tc-ppc.c (md_pseudo_table): If OBJ_XCOFF, add "long",
+ "word", and "short".
+ (ppc_xcoff_cons): New static function.
+
+ * write.c (relax_segment): Give an error if a .space symbol is
+ common or undefined.
+
+ * read.c (read_a_source_file): Don't handle mri_pending_align if
+ the handler is s_globl or s_ignore.
+
+Thu Jan 30 11:46:59 1997 Fred Fish <fnf@cygnus.com>
+
+ * config/tc-d10v.c (find_opcode): Remove unused variable "numops".
+ * config/tc-tic80.c: Many additions to previous placeholder file.
+ * config/tc-tic80.h: Ditto.
+
+Thu Jan 30 12:28:18 1997 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * config/tc-i386.c (i386_align_code): Improve the nop patterns.
+
+Thu Jan 30 12:08:40 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (mips_fix_adjustable): New function.
+ * config/tc-mips.h (tc_fix_adjustable): Call mips_fix_adjustable.
+ (mips_fix_adjustable): Declare.
+
+ Ideas from Srinivas Addagarla <srinivas@cdotd.ernet.in>:
+ * read.c (read_a_source_file): After doing an mri_pending_align,
+ adjust the line_label if there is one.
+ (s_space): Set mri_pending_align if an odd number of bytes were
+ output.
+
+Wed Jan 29 15:31:12 1997 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.h (md_do_align): Add this hook to call
+ d10v_cleanup() when a ".align" is detected.
+
+ * config/tc-d10v.c (find_opcode): Correctly calculate
+ branch displacement when .aligns are present.
+
+Wed Jan 29 09:42:11 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10200.c (md_relax_table): Define.
+ (md_convert_frag): Implement.
+ (md_assemble): Handle relaxable operands/instructions correctly.
+ (md_estimate_size_before_relax): Implement.
+ * config/tc-mn10200.h (TC_GENERIC_RELAX_TABLE): Define.
+
+Tue Jan 28 15:27:28 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (append_insn): Give an error for jumps to a
+ misaligned address.
+ (md_apply_fix): Make a branch to an odd address an error rather
+ than a warning.
+
+ * config/tc-mips.c (md_convert_frag): If the user explicitly
+ requested an extended opcode, pass warn as true to mips16_immed.
+
+ * config/tc-mips.c (mips16_ip): Handle a missing expression like
+ an explicit 0, so that explicitly extended instructions work
+ correctly.
+
+Mon Jan 27 17:41:20 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * ecoff.c (ecoff_build_symbols): Don't generate a local ECOFF
+ symbol for a common symbol.
+
+Wed Jan 22 10:39:39 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ Patch presumed to have been checked in awhile ago but wasn't.
+ Mon Nov 25 10:45:14 1996 Doug Evans <dje@seba.cygnus.com>
+ * write.c: Delete "ifndef md_relax_frag" around is_dnrange.
+ (relax_segment, case rs_org): Move code inside braces. Move locals
+ target,after inside too.
+ (relax_segment, case rs_machine_dependent): Guts moved to ...
+ (relax_frag): New function.
+ Call md_prepare_relax_scan if defined.
+
+Mon Jan 20 10:56:47 1997 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * config/tc-m68k.c (m68k_ip): Reject pc-relative addresses for the
+ 'p' operand specifier.
+
+Mon Jan 20 10:39:36 1997 J.T. Conklin <jtc@cygnus.com>
+
+ * config/tc-m68k.c (HAVE_LONG_BRANCH): New macro, returns true for
+ m68k family cpus which support long branch addressing modes.
+ (m68k_ip, md_convert_frag_1, md_estimate_size_before_relax,
+ md_create_long_jump): Use it.
+
+Mon Jan 20 12:42:06 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (md_begin): Don't set SEC_ALLOC or SEC_LOAD for
+ the .reginfo or .MIPS.options section if configured for an
+ embedded target.
+
+ * config/tc-mips.c (md_begin): Don't set interlocks for
+ mips_4650.
+
+Wed Jan 15 13:51:50 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.c (read_a_source_file): Make sure the symbol ends with
+ whitespace before checking whether the next character is '='.
+
+Tue Jan 14 15:07:27 1997 Robert Lipe <robertl@dgii.com>
+
+ * config/tc-i386.c (sco_id): Moved from here...
+ * config/obj-elf.c (sco_id): ...to here. Adding the identifier
+ really is an SCO ELF specific thing, not just a SCO x86 specific
+ thing.
+
+Mon Jan 13 22:43:01 1997 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure.in (tic80-*-*): Don't require 'coff'.
+ * configure: Regenerate.
+
+Thu Jan 9 09:08:43 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.c (emit_expr): Check for overflow of a negative value
+ correctly.
+ * write.c (fixup_segment): Likewise.
+ * config/obj-coff.c (fixup_segment): Likewise.
+
+ * config/tc-m68k.c (struct label_line): Define.
+ (labels, current_label): New static variables.
+ (md_assemble): Mark current_label as text, and clear it.
+ (m68k_frob_label): New function.
+ (m68k_flush_pending_output): New function.
+ (m68k_frob_symbol): New function.
+ * config/tc-m68k.h (tc_frob_label): Define.
+ (md_flush_pending_output): Define.
+ (tc_frob_symbol): Don't warn, just call m68k_frob_symbol.
+ (tc_frob_coff_symbol): Likewise.
+
+ * read.c (read_a_source_file): When defining a macro in MRI mode,
+ don't add the symbol to the symbol table.
+
+Tue Jan 7 11:21:42 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10300.c (tc_gen_reloc): Handle sym1-sym2 fixups
+ here since fixup_segment doesn't (linkrelax is set).
+ * config/tc-mn10200.c (tc_gen_reloc): Likewise.
+
+Mon Jan 6 15:19:32 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10200.c (md_assemble): Tweak fx_offset for pc-relative
+ relocs.
+
+Fri Jan 3 16:47:08 1997 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-hppa.c (struct hppa_fix_struct): Tweak fx_r_field's type
+ to avoid warnings with the native HP compiler.
+ (fix_new_hppa): Similarly for the r_type argument.
+ (pa_build_unwind_subspace, hppa_elf_mark_end_of_function): Enclose
+ in an #if OBJ_ELF to keep gcc -Wall quiet.
+ (md_apply_fix): Always initialize "result".
+
+ * config/tc-mn10200.c (md_assemble): Generate relocations.
+
+Fri Jan 3 18:17:23 1997 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * config/tc-m68k.c (s_even): Adjust the alignment of the current
+ section.
+
+Fri Jan 3 17:10:33 1997 Richard Henderson <rth@tamu.edu>
+
+ * config/obj-elf.c (elf_file_symbol): When using ECOFF debugging,
+ pass on the new file hook.
+
+ * config/tc-alpha.c (alpha_fix_adjustable): Not quite the same as
+ !alpha_force_relocation, as local LITERALs can be adjusted to be
+ relative to the section.
+
+Fri Jan 3 12:09:24 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.c (yank_symbols): If tc_frob_coff_symbol is
+ defined, call it.
+ * config/tc-m68k.h (tc_frob_symbol): Check whether text label is
+ aligned to odd boundary.
+ (tc_frob_coff_symbol): Define.
+
+ * doc/as.texinfo (Set): Change parenthesized @xref to @pxref.
+
+ * macro.c (macro_expand_body): In MRI mode, just copy a single &.
+
+ * config/tc-m68k.c (m68k_ip): Call frag_grow before adding a
+ PCINDEX frag. From Ronald F. Guilmette <rfg@monkeys.com>.
+
+ * config/tc-m68k.c (m68k_ip): Accept 'B' as a size for an
+ immediate value.
+ (md_assemble): If the size is 'B', set fx_signed.
+ (md_apply_fix_2): Use fx_signed when checking for overflow.
+
+ * write.h (struct fix): Add fx_signed field.
+ * write.c (fix_new_internal): Initialize fx_no_overflow and
+ fx_signed fields.
+ (fixup_segment): Use fx_signed when checking for overflow.
+ * config/obj-coff.c (fixup_segment): Check fx_no_overflow and
+ fx_signed when checking for overflow.
+
+Thu Jan 2 13:37:29 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * NOTES, NOTES.config: Removed. These are rarely, if ever,
+ updated, and all the useful information is in doc/internals.texi.
+
+ Based on patch from Ronald F. Guilmette <rfg@monkeys.com>:
+ * read.c (read_a_source_file): Check for conditional operators
+ before doing an MRI pending alignment.
+ * config/tc-m68k.h (m68k_conditional_pseudoop): Declare.
+ (tc_conditional_pseudop): Define.
+ * config/tc-m68k.c (m68k_conditional_pseudop): New function.
+ * doc/internals.texi (CPU backend): Describe
+ tc_conditional_pseudoop.
+
+ Based on patch from Ronald F. Guilmette <rfg@monkeys.com>:
+ * config/tc-m68k.c (m68k_rel32_from_cmdline): New static
+ variable.
+ (md_begin): Check m68k_rel32_from_cmdline before setting
+ m68k_rel32.
+ (m68k_mri_mode_change): Likewise.
+ (md_longopts): Add --disp-size-default-16 and
+ --disp-size-default-32.
+ (md_parse_option): Handle new options.
+ (md_show_usage): Mention new options.
+ * doc/c-m68k.texi (M68K-Opts): Document new options.
+
+ Based on patch from Ronald F. Guilmette <rfg@monkeys.com>:
+ * config/tc-m68k.c (m68k_index_width_default): New static
+ variable.
+ (m68k_ip): Use m68k_index_width_default to set the size of a base
+ register whose size was not given.
+ (md_longopts): Add --base-size-default-16 and
+ --base-size-default-32.
+ (md_parse_option): Handle new options.
+ (md_show_usage): Mention new options.
+ * doc/c-m68k.texi (M68K-Opts): Document new options.
+
+ * doc/c-mips.texi: Mention ISA level 4, and the -mips16 option.
+
+ * configure.in: Recognize mips-*-linux* target.
+ * configure: Rebuild.
+
+ * config/tc-mips.c (load_register): Rewrite 64 bit handling to
+ work if valueT is only 32 bits.
+
+ * config/tc-mips.c: Throughout, check target_big_endian rather
+ than byte_order.
+ (byte_order): Remove.
+ (mips_init_after_args): Remove.
+ * config/tc-mips.h (LITTLE_ENDIAN, BIG_ENDIAN): Don't define.
+ (mips_init_after_args): Don't declare.
+ (tc_init_after_args): Don't define.
+
+ * config/tc-mips.h (tc_frob_after_relocs): Define if
+ OBJ_MAYBE_ELF.
+ (mips_elf_final_processing): Likewise.
+ (ELF_TC_SPECIAL_SECTIONS): Likewise.
+
+Tue Dec 31 15:12:35 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-v850.c (md_assemble): If this is sst.{h,w} or
+ sld.{h,w} and the operand is relocatable, adjust the adend by
+ shifting it right one bit.
+
+Tue Dec 31 12:56:41 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.c (read_a_source_file): Check mri_pending_align after
+ checking for a macro. From Ronald F. Guilmette
+ <rfg@monkeys.com>.
+
+ * Makefile.in (ALL_CFLAGS): Add -D_GNU_SOURCE.
+
+ * config/tc-sparc.c (md_apply_fix3): Rename from md_apply_fix, and
+ add segment argument. If OBJ_ELF, treat a relocation against a
+ symbol in a linkonce section like a relocation against an external
+ symbol.
+ * config/tc-sparc.h (MD_APPLY_FIX3): Define.
+
+Mon Dec 30 11:35:40 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (mips16_macro): Add case for M_ABS.
+
+Fri Dec 27 22:51:51 1996 Fred Fish <fnf@cygnus.com>
+
+ * NOTES.config (Implementation): as.h #define's "GAS" not "gas",
+ includes config.h instead of host.h, tc.h instead of tp.h, and
+ targ-env.h instead of target-environment.h.
+ Also, obj-format.h includes targ-cpu.h instead of
+ target-processor.h.
+ * configure.in (case ${generic_target}): Add tic80-*-coff entry.
+ * configure: Rebuild with autoconf.
+ * config/obj-coff.h (coff/tic80.h): Include if TC_TIC80 defined.
+ (TARGET_FORMAT): Define to "coff-tic80".
+ * config/tc-tic80.c: New file for TIc80 support.
+ * config/tc-tic80.h: New file for TIc80 support.
+
+Fri Dec 27 11:42:29 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * doc/as.texinfo (M): Mention explicitly that -M changes macro
+ handling.
+
+Thu Dec 19 12:06:08 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * write.c (adjust_reloc_syms): If the fixup symbol has been
+ equated to an undefined symbol, convert the fixup to being against
+ the target symbol. Remove obsolete code handling a special case
+ for i386 PIC.
+
+Wed Dec 18 22:54:39 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-make.sed: Use NewFolderRecursive for installation.
+
+Wed Dec 18 16:00:42 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c (do_assemble): Correct previous bug fix.
+
+Wed Dec 18 15:27:40 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c (md_assemble): Fix bug which caused
+ second instruction in a line to be case sensitize.
+
+Wed Dec 18 10:08:46 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10200.c (mn10200_insert_operand): Don't
+ range check operands with MN10200_OPERAND_NOCHECK set.
+ (check_operand): Likewise.
+
+Tue Dec 17 10:59:32 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c: Undo part of last Friday's alignment changes.
+ (md_begin): Always align the text section to a four byte
+ boundary.
+ (append_insn): Remove call to record_align.
+
+ * config/tc-mips.c (insn_label): Remove.
+ (struct insn_label_list): Define.
+ (insn_labels, free_insn_labels): New static variables.
+ (mips_clear_insn_labels): New static function.
+ (append_insn): Mark all mips16 text labels, and make them odd.
+ Handle all labels after emitting a nop, not just one. Call
+ mips_clear_insn_labels rather than just clearing insn_label.
+ (mips_emit_delays): Add insns parameter, and use it to decide
+ whether to mark mips16 labels. Handle all labels, not just one.
+ Force mips16 labels to be odd. Change all callers.
+ (mips16_immed): Don't check for an odd branch target.
+ (md_apply_fix): Don't check mips16 mode for a branch reloc.
+ (mips16_extended_frag): Ignore the low bit in a branch target.
+ (md_convert_frag): Likewise.
+ (mips_no_prev_insn): Call mips_clear_insn_labels rather than just
+ clearing insn_label.
+ (mips_align, mips_flush_pending_output, s_cons): Likewise.
+ (s_float_cons, s_gpword): Likewise.
+ (s_align): Use insn_labels rather than insn_label.
+ (s_cons, s_float_cons, s_gpword): Likewise.
+ (mips_frob_file_after_relocs): New function.
+ (mips_define_label): Rewrite to add to insn_labels list.
+ * config/tc-mips.h (tc_frob_file_after_relocs): Define.
+ * ecoff.c (ecoff_build_symbols): If the size of a function comes
+ out odd, increment it.
+
+ * config/tc-mips.c (append_insn): Only update prev_insn when not
+ reordering if place is NULL.
+
+ * config/tc-mips.c (mips16_ip): Check for a missing expression
+ when using the register indirect addressing mode.
+
+Mon Dec 16 10:08:46 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10200.c (mn10200_insert_operand): Don't
+ check 24bit operands for overflow.
+ (check_operand): Likewise.
+
+Mon Dec 16 11:50:40 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * doc/as.texinfo (Section): Document how to use the .section
+ pseudo-op for COFF and ELF.
+
+Sun Dec 15 15:26:37 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * write.c (adjust_reloc_syms): Fix linkonce check for ELF.
+
+Sat Dec 14 22:37:27 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (prev_insn_reloc_type): New static variable.
+ (RELAX_MIPS16_ENCODE): Add dslot and jal_dslot arguments, and
+ store them. Adjust other RELAX_MIPS16 macros.
+ (RELAX_MIPS16_DSLOT): Define.
+ (RELAX_MIPS16_JAL_DSLOT): Define.
+ (append_insn): Pass new arguments to RELAX_MIPS16_ENCODE. Correct
+ handling of whether previous instruction has a fixup. Set
+ prev_insn_reloc_type.
+ (mips_no_prev_insn): Clear prev_insn_reloc_type.
+ (mips16_extended_frag): Use the right base address for a PC
+ relative add or load.
+ (md_convert_frag): Likewise. If a PC relative add or load is
+ used, record the alignment for the section.
+
+Fri Dec 13 13:00:33 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * write.c (adjust_reloc_syms): Don't reduce a reloc against a
+ linkonce section into a reloc against the section symbol.
+
+ * config/tc-mips.c (mips16_macro): Remove nop instructions after
+ branch instructions.
+
+ * config/tc-mips.c (md_begin): If configured for an embedded ELF
+ system, don't set the section alignment to 2**4.
+ (s_change_sec): Likewise.
+ (append_insn): Call record_alignment for the section.
+ (md_section_align): Don't align the section size for an embedded
+ ELF system.
+
+Thu Dec 12 16:40:47 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * write.c (adjust_reloc_syms): Make sure that symbols are
+ resolved; expression symbols may have been skipped.
+ * config/obj-coff.c (fixup_segment): Likewise.
+
+Thu Dec 12 15:18:21 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (ppc_elf_suffix): Move @plt to
+ BFD_RELOC_24_PLT_PCREL relocation.
+ (md_apply_fix3): Support BFD_RELOC_24_PLT_PCREL.
+
+Tue Dec 10 13:51:55 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c (write_2_short): Remove code that called
+ parallel_ok() when the programmer specified parallel instructions.
+
+Tue Dec 10 12:23:19 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10300.c (md_assemble): Update to handle endianness
+ issues correctly.
+
+ * config/tc-mn10200.c (md_assemble): Opcode 0x0 is valid!
+ * config/tc-mn10300.c (md_assemble): Likewise.
+
+Tue Dec 10 11:37:14 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (append_insn): Make sure there is enough room
+ in a frag after a mips16 instruction to switch it with a jump
+ instruction.
+
+ * config/tc-mips.c (mips16_extended_frag): Give an error for an
+ attempt to use a non absolute symbol in an extending frag.
+
+Mon Dec 9 16:48:20 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10200.c: Flesh out assembler support for MN10200.
+ * config/tc-mn10200.h: Likewise.
+
+Mon Dec 9 17:09:42 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * app.c (do_scrub_chars): At the end of a C comment, pass space to
+ UNGET rather than PUT. Set old_state before setting state to -2.
+
+ * config/tc-mips.c (mips16_extended_frag): Avoid an infinite loop
+ when extending because the value is exactly maxtiny + 1.
+
+ * config/tc-mips.c (RELAX_MIPS16_ENCODE): Add small and ext
+ arguments, and store them. Adjust other RELAX_MIPS16 macros.
+ (RELAX_MIPS16_USER_SMALL): Define.
+ (RELAX_MIPS16_USER_EXT): Define.
+ (mips16_small, mips16_ext): New static variables.
+ (append_insn): Pass mips16_small and mips16_ext to
+ RELAX_MIPS16_ENCODE.
+ (mips16_ip): Set mips16_small and mips16_ext.
+ (mips16_immed): Don't check mips16_autoextend.
+ (mips16_extended_frag): Check USER_SMALL and USER_EXT.
+
+ * write.c (write_relocs): Print an error for an out of range
+ fixup, rather than calling abort.
+
+ * as.c (main): Unlink the output file if there are errors while
+ generating the fixups.
+
+Fri Dec 6 18:48:13 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (mips16_extended_frag): Don't call
+ S_GET_VALUE.
+ (md_convert_frag): Call resolve_symbol_value before calling
+ S_GET_VALUE, and don't add in the frag address.
+
+ * config/tc-mips.c (mips16_immed): Add file and line parameters,
+ and use them when reporting errors. Change all callers.
+
+Fri Dec 6 15:36:32 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10300.c: Fix various gcc -Wall warnings.
+ Remove '$' prefixing for registers.
+
+Fri Dec 6 00:55:48 1996 Martin <hunt@cygnus.com>
+
+ * config/tc-d10v.c (md_assemble): Check to see if prev_seg
+ is initialized before using it.
+ (d10v_cleanup): No longer uses its argument, so make it void.
+
+ * config/tc-d10v.h (d10v_cleanup): Change prototype.
+
+Thu Dec 5 11:03:31 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * write.c (fixup_segment): Don't discard the symbol for a PC
+ relative fixup to an absolute symbol.
+
+Wed Dec 4 15:42:41 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c (md_assemble, d10v_cleanup): Fix bug
+ with multiple sections.
+
+Wed Dec 4 13:00:07 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (md_longopts): Rename mips-16 to mips16, and
+ no-mips-16 to no-mips16.
+ (s_mipsset): Accept .set mips16 and .set nomips16.
+
+Wed Dec 4 10:35:33 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (ppc_elf_suffix): Take expressionS pointer
+ argument, and check for +/- constant following the suffix, folding
+ it into the expression.
+ (ppc_elf_cons): Change ppc_elf_suffix calls.
+ (md_assemble): Ditto.
+ (shlib): Replace boolean mrelocatable with enumeration shlib.
+ (md_parse_option): Discriminate between PIC style shared libraries
+ and -mrelocatable.
+ (ppc_elf_validate_fix): Don't report warnings for PIC style shared
+ libraries.
+
+Tue Dec 3 23:18:29 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.h ({tc,ppc}_comment_chars): Define, so that we can
+ change the comment characters.
+
+ * config/tc-ppc.c (comment_chars): Delete in favor of
+ tc_comment_chars.
+ (ppc_{eabi,solaris}_comment_chars): Eabi and Solaris versions of
+ comment chars.
+ (ppc_comment_chars): Select appropriate comment chars by default.
+ (msolaris): New flag for -m{,no-}solaris.
+ (md_parse_option): Recognize -K pic. Add support for
+ -m{,no-}solaris.
+ (md_show_usage): Update.
+ (md_begin): Do not set ELF flags if Solaris.
+ (ppc_elf_suffix): @local sets R_PPC_LOCAL24PC relocation.
+ (md_apply_fix3): Add support for R_PPC_LOCAL24PC.
+
+Mon Dec 2 13:48:57 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * as.c (main): Correct handling of flag_always_generate_output.
+
+Sun Dec 1 21:46:05 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10300.c (tc_gen_reloc): Get the addend from
+ fx_offset, not fx_addnumber.
+
+ * config/tc-mn10300.h (tc_fix_adjustable): Don't do any
+ reloc adjustments.
+
+Sat Nov 30 17:34:48 1996 Eliot Dresselhaus <eliot@wally.edc.com>
+
+ * config/tc-i386.c: Correct misspelling: balenced to balanced.
+
+Wed Nov 27 13:25:39 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (md_section_align): Check for an alignment of
+ 4, not an alignment of 16. Corrects August 7 patch.
+
+Tue Nov 26 10:33:16 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure, conf.in: Rebuild with autoconf 2.12.
+
+ * config/tc-ppc.c (ppc_elf_lcomm): Don't give an error if no
+ alignment is specified.
+
+ Add support for mips16 (16 bit MIPS implementation):
+ * config/tc-mips.c: Extensive additions for mips16 support, not
+ listed here.
+ (RELAX_OLD, RELAX_NEW): Use only 7 bits each.
+ (insn_uses_reg): Change last parameter to an enum.
+ * config/tc-mips.h (LOCAL_LABELS_DOLLAR): Define as 0.
+ (md_relax_frag): Define as mips_relax_frag.
+ (mips_relax_frag): Declare.
+ (struct mips_cl_insn): Add use_extend and extend fields.
+ (tc_fix_adjustable): Define.
+ * config/obj-elf.h (S_GET_OTHER): Define.
+ (S_SET_OTHER): Define.
+
+Mon Nov 25 18:02:29 1996 J.T. Conklin <jtc@beauty.cygnus.com>
+
+ * config/tc-m68k.c (m68k_ip): Implement cases for new <, >, m, n,
+ o and p operand specifiers.
+
+Mon Nov 25 10:45:14 1996 Doug Evans <dje@seba.cygnus.com>
+
+ * write.c: Delete "ifndef md_relax_frag" around is_dnrange.
+ (relax_segment, case rs_org): Move code inside braces. Move locals
+ target,after inside too.
+ (relax_segment, case rs_machine_dependent): Guts moved to ...
+ (relax_frag): New function.
+ Call md_prepare_relax_scan if defined.
+ * config/tc-m68k.h (md_prepare_relax_scan): Renamed from
+ M68K_AIM_KLUDGE.
+
+Mon Nov 25 08:49:36 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10300.c (address_registers): Use '$' as register
+ prefix instead of '%'.
+ (data_registers, other_registers, md_assemble): Likewise.
+
+ * config/tc-mn10300.c (address_registers): Use '%' prefix for regs.
+ (data_registers, other_registers, md_assemble): Likewise.
+
+ * config/tc-mn10300.c (md_assemble): Correctly determine the
+ correct location and type for each relocation.
+ (md_pcrel_from): Simplify.
+
+Fri Nov 22 15:42:26 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sh.c (md_convert_frag): Improve warning when branch is
+ converted into branch around branch.
+
+Thu Nov 21 11:56:11 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10300.h (DIFF_EXPR_OK): Don't define this.
+ (tc_fix_adjustable): Don't adjust relocs against weak symbols or
+ pc-relative relocs.
+ * config/tc-mn10300.c (md_begin): Set linkrelax.
+ (md_assemble): Create fixups as needed.
+ (md_apply_fix3): Gut. It shouldn't ever get called anymore.
+
+Tue Nov 19 17:48:06 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-d10v.c (parallel_ok): When automatically converting
+ serial ops to parallel, do not consider a branch as the first
+ instruction.
+
+Tue Nov 19 13:35:22 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10300.c (md_assemble): Handle MN10300_OPERAND_REG_LIST.
+
+Mon Nov 18 15:26:55 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10300.c (mn10300_insert_operand): Provide prototype
+ via PARAMS.
+ (check_operand): Likewise.
+
+Mon Nov 18 15:22:28 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-d10v.c (parallel_ok): Branch and link instructions
+ modify r13.
+ (write_2_short): Call parallel_ok to check whether two short
+ instructions the user requested execute in parallel, can be
+ executed that way.
+
+Thu Nov 14 11:17:49 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c (write_2_short): Fix bug that wouldn't
+ allow a branch and link in parallel with an exe instruction.
+
+Fri Nov 8 13:55:03 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * doc/c-d10v.texi: Add info on @word modifier.
+
+Wed Nov 6 13:46:07 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10300.c (mn10300_insert_operand): MN10300_OPERAND_SPLIT
+ operands are assumed to be 32bits. Use "bits" field to hold the
+ number of bits in the main instruction word for MN10300_OPERAND_SPLIT.
+ (mn10300_check_operand): MN10300_OPERAND_SPLIT operands are assumed
+ to be 32bits.
+
+ * config/tc-mn10300.c (mn10300_insert_operand): Shift low part
+ of a MN10300_OPERAND_SPLIT operand by operand->shift.
+
+ * config/tc-mn10300.c (mn10300_insert_operand): Handle
+ MN10300_OPERAND_SPLIT.
+
+Tue Nov 5 13:30:40 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10300.c (md_assemble): Insert operands into
+ the extension part of the instruction if necessary.
+ (mn10300_insert_operand): Accept pointer to extension word
+ argument. Make insn a pointer argument too. Return type
+ is now void. All callers changed.
+
+Mon Nov 4 12:53:40 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10300.c (mn10300_insert_operand): Handle
+ repeated register operands.
+
+Fri Nov 1 10:42:49 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * doc/as.texinfo: Added section on reporting bugs.
+
+ * config/tc-alpha.c: Change uses of void * to PTR. Change the
+ alpha_macro emit field to expect a const argument, and change the
+ arg field to be const. Fix some spacing to follow the GNU
+ standard.
+
+Fri Nov 1 10:32:03 1996 Richard Henderson <rth@tamu.edu>
+
+ * config/tc-alpha.c (md_parse_option): Add knowledge of 21164pc
+ (pca56) and 21264 (ev6) cpus.
+ (md_apply_fix): Private relocation types are now negative.
+ (alpha_force_relocation): Likewise.
+ (tc_gen_reloc): Likewise.
+ (emit_insn): Likewise.
+ (emit_ldXu): Do the right thing when the hardware can do byte insns.
+ (emit_stX): Likewise.
+ (emit_sextX): Likewise.
+
+Thu Oct 31 16:33:21 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.c (do_relocs_for): Call resolve_symbol_value on
+ a symbol found in a reloc.
+
+ * symbols.c (resolve_symbol_value): Improve the error message if
+ an undefined symbol is used in an expression.
+
+Wed Oct 30 20:15:35 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * doc/internals.texi: Rewrite, and add a lot of documentation.
+ * doc/Makefile.in (internals.info): New target.
+
+Wed Oct 30 14:55:57 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-v850.h (tc_fix_adjustable): Don't adjust relocs
+ against weak symbols.
+
+Tue Oct 29 12:28:16 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-v850.c (md_assemble): Don't lose for relaxable
+ addresses like .+6.
+
+ * config/tc-v850.c (md_convert_frag): Make sure we insert the
+ fixup at the right address within the frag.
+
+ * config/tc-v850.c (md_convert_frag): Don't set fragP->fr_fix
+ to an absolute value, instead increment it as needed.
+
+ * config/tc-v850.h (TC_GENERIC_RELAX_TABLE): Define.
+ * config/tc-v850.c: Fix some indention problems.
+ (md_relax_table): Define for D9->D99 branch displacement
+ relaxing.
+ (md_convert_frag): Do something useful instead of aborting.
+ (md_estimate_size_before_relax): Likewise.
+ (md_assemble): Note if the matching instruction has a relaxable
+ operand. If it does, allocate frag with frag_var and don't
+ do any fixups.
+
+Mon Oct 28 10:48:40 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.h (md_cleanup): New function. This is needed to
+ write out any buffered instructions when a ".end" is found.
+
+Mon Oct 28 10:43:45 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * read.c (read_a_source_file): New hook md_cleanup().
+
+Fri Oct 25 00:01:00 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * write.c (fix_new_exp): Use make_expr_symbol to build an
+ expression symbol for a complex fixup.
+
+Thu Oct 24 14:31:04 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-v850.c (v850_reloc_prefix): Several disgusting
+ hacks to improve parsing of complex hi, lo, zda, etc
+ expressions.
+ (md_assemble): Don't demand and eat a trailing ')' after finding
+ a v850 relocation prefix. Sign extend the constant in a
+ BFD_RELOC_LO16 expression. Do eat a trailing ')' after a complete
+ operand.
+ (parse_cons_expression_v850): Don't eat a trailing ')' after
+ finding a v850 relocation prefix.
+
+ * config/tc-v850.h (TC_PARSE_CONS_EXPRESSION): Define.
+ (TC_CONS_FIX_NEW): Likewise.
+ * config/tc-v850.c (parse_cons_expression_v850): New function.
+ (cons_fix_new_v850): Likewise.
+
+ * config/tc-v850.h (tc_fix_adjustable): Don't adjust TDA relocs.
+
+Wed Oct 23 18:20:29 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-ppc.c (md_apply_fix3): Give a better warning message
+ for an unknown relocation type.
+
+Wed Oct 23 16:21:28 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-v850.c (md_pseudo_table): Add .word; allocates
+ 4 bytes of space.
+
+Tue Oct 22 22:01:25 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-v850.c (md_assemble): Handle TDAOFF relocs
+ differently for movea & sst/sld insns.
+
+Tue Oct 22 17:09:32 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-d10v.c (parallel_ok): Don't allow illegal combinations
+ of instructions.
+
+Tue Oct 22 11:28:39 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * obj.h (struct format_ops): Add frob_file_after_relocs field.
+ * config/obj-multi.h (obj_frob_file_after_relocs): Define.
+ * config/obj-ecoff.c (ecoff_format_ops): Initialize new
+ frob_file_after_relocs field.
+ * config/obj-elf.c (elf_format_ops): Likewise.
+ * config/tc-mips.c: Undefine obj_frob_file_after_relocs before
+ including obj-elf.h.
+
+Mon Oct 21 11:38:30 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (cons_fix_new_mips): Only treat 8 byte reloc
+ specially if not ELF.
+ (md_apply_fix): Handle BFD_RELOC_64.
+ (tc_gen_reloc): Handle BFD_RELOC_64.
+
+ * config/tc-i386.c (md_apply_fix3): Don't increment value for a PC
+ relative reloc when BFD_ASSEMBLER and OBJ_AOUT (more ugly gas
+ reloc hacking).
+
+ * config/obj-aout.h (S_IS_DEFINE): non BFD_ASSEMBLER version:
+ Don't check S_GET_OTHER.
+
+Fri Oct 18 14:06:26 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (mips_ip): Accept an odd floating point
+ register with l.s or s.s.
+
+ * config/obj-aout.c (obj_pseudo_table): Use obj_aout_type for
+ .type pseudo-op.
+ (obj_aout_type): New static function.
+
+Thu Oct 17 17:55:17 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in ($(OBJS)): Depend upon libiberty.h.
+
+Wed Oct 16 11:28:31 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-v850.c (v850_reloc_prefix): Recognize zdaoff, tdaoff
+ and sdaoff expressions.
+
+ * write.c (fixup_segment): Don't add symbol value to addend if
+ TC_V850 and OBJ_ELF.
+ * config/tc-v850.h (tc_fix_adjustable): Don't adjust any
+ pc-relative fixups.
+
+ * config/tc-v850.c (md_pcrel_from): Undo yesterday's changes.
+ (md_pcrel_from_section): Likewise.
+ * config/tc-v850.h (MD_PCREL_FROM_SECTION): Likewise.
+
+Tue Oct 15 23:19:00 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-v850.c (md_pcrel_from): Delete unused function.
+ (md_pcrel_from_section): New function.
+ * config/tc-v850.h (MD_PCREL_FROM_SECTION): Define.
+
+Mon Oct 14 13:59:12 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (load_register): Add cast to offsetT when using
+ a constant with &~.
+
+Mon Oct 14 11:24:28 1996 Richard Henderson <rth@tamu.edu>
+
+ * config/obj-elf.c (elf_frob_file): Move ECOFF debug processing to ...
+ (elf_frob_file_after_relocs): ... here. New function.
+ * config/obj-elf.h (obj_from_file_after_relocs): New macro.
+ * write.c (write_object_file): Call *frob_after_relocs after the
+ call to write_relocs.
+
+ * config/tc-alpha.c: Use new BFD_RELOC_ALPHA_ELF_LITERAL reloc.
+
+ * config/tc-alpha.c (load_expression): Don't SET_VALUE on the section
+ symbol, as this messes up linking. Instead, expand the recursive call
+ inline and change up the appropriate bits to get the 0x8000 offset
+ in the reloc addend.
+
+Thu Oct 10 17:30:31 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sparc.h (tc_fix_adjustable): Permit the difference of
+ two symbols in the same segment to be adjusted.
+
+ * configure.in: Don't get confused by CPU-VENDOR-linux-gnu.
+ * configure: Rebuild.
+
+Thu Oct 10 17:22:18 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (ppc_insert_operand): Change most warnings into
+ errors.
+ (ppc_elf_validate_fix): Ditto.
+ (md_assemble): Ditto.
+ (ppc_tc): Ditto.
+ (ppc_pe_section): Ditto.
+ (ppc_frob_symbol): Ditto.
+
+Thu Oct 10 12:05:45 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/mn10300.c (md_assemble): Pass an extra shift count
+ to mn10300_insert_operand based on the opcode format.
+ (mn10300_insert_operand): Accept and use extra shift count
+ parameter.
+
+ * config/tc-mn10300.c (md_assemble): Use FMT_* macros for
+ formats rather than hard-coded constants.
+
+ * config/tc-mn10300.c (md_assemble): Format D5 instructions
+ are 7 bytes long. Write out instructions in big-endian format.
+
+Tue Oct 8 14:56:15 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10300.c (md_assemble): Tweak further so
+ that all instructions are parsed correctly.
+
+Tue Oct 8 13:02:21 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * as.h: Include libiberty.h.
+ (xmalloc, xrealloc): Don't declare.
+ * as.c: Don't include libiberty.h.
+ * expr.c, read.c, stabs.c, config/obj-coff.c: Likewise.
+ * config/tc-mips.c: Likewise.
+ * messages.c: Likewise.
+ (xstrerror): Don't declare.
+ * xmalloc.c: Remove.
+
+Mon Oct 7 16:53:23 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10300.h (pre_defined_registers) Remove.
+ (system_registers, cc_names): Likewise.
+ (address_registers, data_registers, other_registers): New register
+ arrays.
+ (register_name, system_register_name, cc_name): Remove.
+ (mn10300_reloc_prefix): Likewise.
+ (data_register_name): New function.
+ (address_register_name, other_register_name): Likewise.
+ (md_assemble): Rough cut at parsing operands. Remove lots of
+ unwanted code.
+ (md_apply_fix3): Disable for now.
+
+Mon Oct 7 11:38:34 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * config/tc-m68k.c (select_control_regs): New function, extracted
+ out of m68k_init_after_args.
+ (m68k_init_after_args): Use it.
+ (mri_chip): Use it here as well to update set of allowed control
+ regs for movec.
+
+Mon Oct 7 11:24:29 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-elf.c (elf_begin): New function.
+ (obj_elf_section): Add the section symbol to the symbol table.
+ * config/obj-elf.h (obj_begin): Define.
+ (elf_begin): Declare.
+ * as.c (perform_an_assembly_pass): Call obj_begin if it is
+ defined.
+
+Fri Oct 4 18:37:32 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.c (fixup_segment): Subtract the section address
+ from a PC relative reloc if TC_M68K.
+
+Thu Oct 3 15:15:30 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sparc.c (md_pseudo_table): Make .uahalf, .uaword, and
+ .uaxword available even if not OBJ_ELF.
+ (md_atof): Remove unused local variable wordP.
+
+Thu Oct 3 00:16:50 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-mn10x00.c, config/tc-mn10x00.h: New files
+ for Matsushita MN10x00 support.
+ * configure.in: Recognize mn10x00-*-*
+ * configure: Rebuilt.
+
+Wed Oct 2 15:54:03 1996 Klaus Kaempf <kkaempf@progis.de>
+
+ * obj-evax.h: move openvms definitions from here to tc-alpha.c.
+ * tc-alpha.c: add support for vms_case_hack like in vax/vms.
+ (load_expression): track clobbering of base reg before jmp/jsr.
+ (s_alpha_file): pass case_hack flags and source filename via
+ symbol table to bfd.
+ * tc-alpha.h (TC_CONS_FIX_NEW): define
+
+Tue Oct 1 16:16:01 1996 Joel Sherrill <joel@oarcorp.com>
+
+ * configure.in (mips-*-rtems*): New target, like mips-*-elf*.
+ * configure: Rebuild.
+
+Tue Oct 1 12:37:48 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.c (s_macro): Warn if a macro has the same name as a
+ pseudo-op.
+ (s_space): In m68k MRI mode, align to a word boundary.
+ * macro.c (define_macro): Add namep parameter. Change all
+ callers.
+ * macro.h (define_macro): Update declaration.
+
+ * as.c (show_usage): Print bug report address.
+ (parse_args): Change version printing to match current GNU
+ standards.
+ * gasp.c (show_usage): Print bug report address.
+ (main): Change version printing to match current GNU standards.
+
+ * config/tc-m68k.c (init_table): Correct access control unit
+ register numbers. From Ken Rose <rose@netcom.com>.
+
+ * config/tc-alpha.c: Add some static function prototypes.
+ (alpha_macros): Move to top of file. Make static.
+ (alpha_num_macros): Move to top of file.
+
+Tue Oct 1 09:36:19 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * tc-v850.h: Define LOCAL_LABEL to recognise _.L_* symbols
+ generated by DWARF.
+
+Sat Sep 28 03:38:08 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * listing.c (list_symbol_table): Remove bogus code in BFD64 case,
+ and just call sprintf_vma.
+
+Thu Sep 26 16:04:11 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * expr.c (expr): Change >>= to >> (fix typo). (From meissner).
+
+Tue Sep 24 19:05:08 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.c (float_cons): Call md_flush_pending_output if it is
+ defined.
+
+Tue Sep 24 12:22:18 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c (md_operand): Created. Allows operands to
+ start with '#'.
+ * config/tc-d10v.h (md_operand): Undefined.
+
+Mon Sep 23 12:13:18 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (add_fix): Treat a width of '3' like 'B'.
+ (md_assemble): A fixup width of '3' means a 1 byte reloc.
+
+Thu Sep 19 12:21:24 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.c (fixup_segment): Don't adjust PC relative
+ reloc for the i960 for a reloc in the same section. This undoes
+ one of the two changes made Aug 19.
+
+Wed Sep 18 12:11:58 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.c (obj_coff_endef): Both versions: Move C_STAT
+ symbols to the position of the debugging information.
+
+Mon Sep 16 11:41:40 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * expr.c (expr): Always use unsigned right shifts for >>.
+
+Thu Sep 12 10:25:45 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * config/tc-arm.c (md_apply_fix3): Update two thumb instruction
+ slots when processing BL fixups.
+
+ * config/tc-arm.c (output_inst): Ensure Thumb BL fixup is marked
+ on the first half of the instruction.
+
+Wed Sep 11 00:09:35 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * ecoff.c (ecoff_stab): Create an expression symbol for a complex
+ stabs expression, rather than giving an error.
+
+ * ecoff.c (ecoff_new_file): Don't do anything if we are still in
+ the same file.
+
+Tue Sep 10 11:45:37 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (append_insn): Fill in the value for a constant
+ jump, rather than creating a reloc.
+
+Mon Sep 9 10:57:42 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (append_insn): Don't swap an instruction which
+ sets a condition code with an instruction which uses a condition
+ code.
+ (mips_ip): In cases 'N' and 'M', look for $fccN rather than an
+ immediate value.
+
+ * config/tc-mips.c (md_begin): Recognize r5000 for cpu.
+ (mips_ip): Give a better error message if the ISA level is wrong.
+ (md_parse_option): Recognize -mcpu=[v][r]5000.
+
+Sat Sep 7 13:25:55 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * config/tc-mips.c (COUNT_TOP_ZEROES): Added macro to count
+ leading zeroes.
+ (load_register): Ensure hi32 bits are not lost during lo32bit
+ processing. Fix shift offset that was overflowing into the next
+ instruction field. Add code to generate shorter sequences for
+ constants with a single contiguous seqeuence of ones.
+
+Fri Sep 6 17:07:12 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c (d10v_dot_word): New function to support
+ "@word" with the word pseudo-op.
+ (md_apply_fix3): Cleanup and changes to support correct sizes
+ for 16 and 18-bit relocs.
+
+Fri Sep 6 16:00:29 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * configure.in (sparc-*-aout): Set `em'.
+ * configure: Regenerated.
+ * config/te-sparcaout.h: New file.
+ * config/tc-sparc.h (TARGET_BYTES_BIG_ENDIAN): Define.
+ Ifdef TE_SPARCOUT define TARGET_FORMAT and SPARC_BIENDIAN.
+ * config/tc-sparc.c (INSN_BIG_ENDIAN): New macro.
+ (SPECIAL_CASE_{SETSW,SETX}): Define.
+ ({NOP,OR,FMOVS,SETHI,SLLX,SRA}_INSN): Define.
+ (md_begin): Delete setting of `target_big_endian'.
+ (output_insn): New function.
+ (md_assemble): Rewrite. Add `setx' support.
+ (sparc_ip): Handle `0' operand char. Recognize setuw, setsw, setx
+ special cases.
+ (md_atof): Add little endian support.
+ (md_number_to_chars): Likewise.
+ (md_apply_fix): Likewise.
+ (md_longopts): Recognize -EL,-EB ifdef SPARC_BIENDIAN.
+ (md_parse_option): Likewise.
+ (md_show_usage): Print -EL, -EB ifdef SPARC_BIENDIAN.
+
+Thu Sep 5 13:40:29 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * ecoff.c (ecoff_new_file): New function.
+ * ecoff.h (ecoff_new_file): Declare.
+ * config/obj-ecoff.h (obj_app_file): Define.
+
+Thu Sep 5 13:39:25 1996 Richard Henderson <rth@tamu.edu>
+
+ * config/tc-alpha.c (load_expression): Bias the .lit8 section
+ symbol by 32k so that our 16-bit signed offset can address the
+ entire chunk. Reported by <matt@lkg.dec.com>.
+
+Wed Sep 4 10:23:20 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (load_register): Remove unused variable tmp.
+
+Wed Sep 4 11:24:29 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * config/tc-mips.c (load_register): Remove unnecessary code that
+ was causing the high 32bits of 64bit constants to be lost.
+
+Tue Sep 3 13:52:56 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c: Added changes to support function
+ pointers and "@word" syntax.
+
+Tue Sep 3 11:57:18 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-v850.c: Remove commented out and #if 0'd code.
+ (v850_reloc_prefix): Provide prototype.
+ (postfix, get_reloc, build_insn): Remove prototypes for nonexistant
+ functions.
+ (md_begin, md_assemble, md_apply_fix3): Remove unused variables.
+ (md_assemble): Add default to case statement.
+
+Sat Aug 31 16:03:00 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-v850.c (md_assemble): Compute size of the instrction
+ from the opcode.
+
+ * config/tc-v850.c (md_apply_fix3): Do simple byte, short and
+ word fixups too.
+
+Fri Aug 30 23:50:08 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-v850.c (md_apply_fix3): Use little endian get/put
+ routines to fetch/store the updated instruction from/to memory.
+ (v850_insert_operand): If the operand has a specialized insert
+ routine, call it.
+
+Fri Aug 30 18:35:26 1996 J.T. Conklin <jtc@hippo.cygnus.com>
+
+ * config/tc-v850.c (reg_name_search): Align calling convention to
+ be like identical function found in tc-ppc.c.
+ (get_reloc): Removed.
+ (v850_reloc_prefix): New function, parse lo(), hi() and hi0().
+ (md_assemble): emit fixups.
+ (md_pcrel_from): renamed from md_pcrel_from_section, emit proper
+ displacement.
+ (md_apply_fix3): handle fixups/relocs.
+ * config/tc-v850.h (MD_PCREL_FROM_SECTION): Removed definition.
+
+Fri Aug 30 18:12:00 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ Add SH ELF support.
+ * configure.in (sh-*-elf*): New target.
+ * config/tc-sh.h (TARGET_ARCH): Define.
+ (WORKING_DOT_WORD): Define.
+ (TC_COFF_FIX2RTYPE): Only define if OBJ_COFF.
+ (BFD_ARCH, COFF_MAGIC, TC_COUNT_RELOC): Likewise.
+ (TC_RELOC_MANGLE, tc_coff_symbol_emit_hook): Likewise.
+ (DO_NOT_STRIP, NEED_FX_R_TYPE, TC_KEEP_FX_OFFSET): Likewise.
+ (TC_COFF_SIZEMACHDEP, tc_frob_file): Likewise.
+ (SUB_SEGMENT_ALIGN): Likewise.
+ (RELOC_32): Don't define.
+ (tc_frob_file_before_adjust): Define if BFD_ASSEMBLER.
+ (target_big_endian): Declare if OBJ_ELF.
+ (TARGET_FORMAT): Define if OBJ_ELF.
+ * config/tc-sh.c: Use BFD reloc codes instead of SH COFF reloc
+ numbers throughout.
+ (tc_crawl_symbol_chain): Only define if OBJ_COFF.
+ (tc_headers_hook, tc_coff_sizemachdep): Likewise.
+ (struct sh_count_relocs): Define.
+ (sh_count_relocs): New static function, broken out of
+ sh_frob_file. Add BFD_ASSEMBLER code.
+ (sh_frob_section): Likewise.
+ (sh_frob_file): Call sh_frob_section.
+ (md_convert_frag): If BFD_ASSEMBLER, change type of headers, and
+ call section_symbol rather than seg_info (seg)->dot.
+ (md_section_align): Add OBJ_ELF version.
+ (SWITCH_TABLE_CONS): Define.
+ (SWITCH_TABLE): Use SWITCH_TABLE_CONS.
+ (md_apply_fix): Change parameter types if BFD_ASSEMBLER. Only
+ handle fx_r_type == 0 if not BFD_ASSEMBLER. Return 0 if
+ BFD_ASSEMBLER.
+ (struct reloc_map): Define if not BFD_ASSEMBLER.
+ (coff_reloc_map): Likewise.
+ (sh_coff_reloc_mangle): Use coff_reloc_map to convert fx_r_type.
+ (tc_gen_reloc): New function if BFD_ASSEMBLER.
+ * write.c (write_relocs): Ifdef out fx_where test which triggers
+ inappropriately for SH ELF.
+ (write_object_file): Call tc_frob_file_before_adjust and
+ obj_frob_file_before_adjust if they are defined.
+
+ * write.c (write_object_file): Use BFD_RELOC_16, not
+ BFD_RELOC_NONE, when calling fix_new_exp for a broken word.
+
+ * read.c (emit_expr): Fix conversion of byte count to BFD reloc
+ code.
+
+Fri Aug 30 14:47:38 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c (find_opcode): Fix problem with calculating
+ branch sizes in across sections.
+
+Fri Aug 30 00:44:13 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-850.c (md_assemble): Handle hi() correctly. Handle
+ hi0() too.
+
+Wed Aug 28 23:11:08 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-v850.c (md_begin): Deal with end of opcode
+ table marker.
+
+Wed Aug 28 19:20:04 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c (find_opcode): Fix a bug which could generate
+ the wrong opcode for cases like st2w where there are many forms
+ of the same instruction.
+
+Tue Aug 27 13:53:22 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * expr.c (operand): If md_parse_name is defined, call it before
+ calling symbol_find_or_make.
+ * config/tc-ppc.h (md_parse_name): Define.
+ (ppc_parse_name): Declare.
+ * config/tc-ppc.c (reg_name_search): Add regs and regcount
+ parameters.
+ (register_name): Update call to reg_name_search.
+ (cr_operand): New static variable.
+ (cr_names): New static const array.
+ (ppc_parse_name): New function.
+ (md_assemble): If PPC_OPERAND_CR is set in the operand flags, set
+ cr_operand before calling expression.
+
+Tue Aug 27 09:05:50 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-hppa.c (tc_gen_reloc): Add new argument to
+ hppa_gen_reloc_type call.
+
+Mon Aug 26 18:24:51 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c: Fixed ".word". Fixed problem with range checking
+ on addresses. Improved error messages.
+ * doc/c-d10v.texi: Added docs for register pairs.
+
+Mon Aug 26 13:39:27 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c (parallel_ok): Fix bug in parallel
+ checking code.
+
+Mon Aug 26 14:38:22 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * ecoff.c (init_file): Initialize fMerge to 1.
+ (add_file): Restore old file merging code, but only merge files if
+ fMerge is set.
+ (ecoff_directive_loc): Clear fMerge field of current file.
+ (ecoff_generate_asm_lineno): Likewise.
+
+Fri Aug 23 11:40:47 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * doc/c-d10v.texi: Fix typo.
+
+Fri Aug 23 10:41:32 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-v850.c (md_assemble): Correct bit masking for
+ hi and lo expressions.
+
+ * config/tc-v850.c (md_assemble): Rough cut at demanding
+ "ep" or "r30" in sst and sld instructions.
+ (md_apply_fix3): Don't abort. Just warn that we don't
+ have relocs yet.
+
+ * config/tc-v850.c (CC_NAME_CNT): Define.
+ (cc_name): New function.
+ (md_assemble): Handle V850_OPERAND_CC correctly.
+
+ * config/tc-v850.c (md_assemble): Don't forget to initialize
+ "insn"!
+
+ * config/tc-v850.c (reg_name_search): Generalize to search
+ any given register table.
+ (register_name): Pass appropriate table and size to reg_name_search.
+ (system_register_name): New function.
+ (SYSREG_NAME_CNT): Define.
+ (md_assemble): Handle operands which are system registers.
+
+ * config/tc-v850.c (md_assemble): If we find a register, but the
+ opcode doesn't want a register, then we don't have a match.
+ (md_assemble): Get size of the instruction from the opcode table.
+
+Thu Aug 22 10:20:30 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Set and substitute HLDENV.
+ * configure: Rebuild.
+ * Makefile.in (HLDENV): New variable.
+ (as.new): Use $(HLDENV).
+
+ * ecoff.c (ecoff_directive_endef): Avoid a division by zero error
+ if an array dimension is not known.
+
+Thu Aug 22 10:50:00 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c: Fix a reloc bug caused by my last change.
+ * doc/c-d10v.texi: Cleanup.
+
+Tue Aug 20 15:15:16 1996 J.T. Conklin <jtc@hippo.cygnus.com>
+
+ * config/tc-v850.c: New file.
+ * config/tc-v850.h: New file.
+ * configure (v850-*-elf): New target.
+ * configure.in (v850-*-elf): New target.
+
+Wed Aug 21 15:50:54 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * doc/c-d10v.texi: New file.
+ * doc/all.texi: Added D10V stuff.
+ * doc/as.texinfo: Added D10V stuff.
+
+Tue Aug 20 14:10:02 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c: All references to defined symbols should
+ now use the optimal instruction. .float and .double now work.
+
+Mon Aug 19 14:41:36 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.c (fixup_segment): Adjust PC relative reloc by
+ section address for the i960 as is done for the i386.
+
+Thu Aug 15 16:37:59 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-config.in: Add wildcards for config matching, add mips-*-*
+ case, forward-include bfd/elf-bfd.h.
+
+Thu Aug 15 13:24:30 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c: Add additional information to the opcode
+ table to help determinine which instructions can be done
+ in parallel.
+
+Thu Aug 15 17:01:31 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * config/tc-arm.c: Major changes to add Thumb support, with lots
+ of change input from <rearnsha@armltd.co.uk>.
+ Reverted to INSN_SIZE macro, rather than insn_size variable.
+ (insns): Added ARM "bx" instruction support.
+ (tinsns): Added Thumb instruction definition structure.
+ (arm_tops_hsh): Added hash structure for Thumb opcodes.
+ (md_pseudo_table): Added ".arm", ".thumb" and ".code" pseudo-ops.
+ (opcode_select,s_arm,s_thumb,s_code): Added.
+ (decode_shift): Allow upper-case RRX.
+ (do_ldst): Simpler halfword support.
+ (do_ldmstm): Improved.
+ (reg_list, do_bx, thumb_reg, thumb_add_sub, thumb_shift,
+ thumb_mov_compare, thumb_load_store, do_t_arit, do_t_add,
+ do_t_asr, do_t_branch, do_t_bx, do_t_compare, do_t_ldmstm,
+ do_t_ldrb, do_t_ldrh, do_t_lds, do_t_lsl, do_t_lsr, do_t_mov,
+ do_t_push_pop, do_t_str, do_t_strb, do_t_strh, do_t_sub, do_t_swi,
+ do_t_adr): Added.
+ (md_apply_fix3): Add support for BFD_RELOC_ARM_THUMB_* relocations.
+ (md_parse_option): Add support for -mthumb.
+ (md_show_usage): Updated to reflect new command line option.
+ (arm_data_in_code, arm_canonicalize_symbol_name): Added.
+ * config/tc-arm.h: Provide TC_FIX_TYPE to allow private ARM
+ fragment information to be held.
+
+Thu Aug 15 16:12:00 1996 Richard Earnshaw (rearnsha@armltd.co.uk)
+
+ * tc-arm.c (md_apply_fix3): Also set fixP->fx_done if fx_addsy is
+ non-null, but is a constant.
+ (fix_new_arm): Call make_expr_symbol to make the expression symbol
+ so that error reporting will work correctly.
+
+Wed Aug 14 10:37:21 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-i386.c (tc_i386_fix_adjustable): Don't adjust relocs
+ against weak symbols.
+
+Tue Aug 13 17:39:24 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-ppc.h (TC_FORCE_RELOCTION): Define if OBJ_XCOFF.
+ (ppc_force_relocation): Declare if OBJ_XCOFF.
+ * config/tc-ppc.c (ppc_force_relocation): New function if
+ OBJ_XCOFF.
+
+Mon Aug 12 16:49:43 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.h (BYTE_ORDER): Don't define. No longer used.
+
+Fri Aug 9 17:48:28 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c: Fix problem with relocs.
+
+Fri Aug 9 14:16:14 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sh.c (sh_do_align): If not BFD_ASSEMBLER, always align
+ with nops if not in data_section or bss_section.
+
+Thu Aug 8 12:32:56 1996 Klaus Kaempf <kkaempf@progis.de>
+
+ Add support for openVMS/Alpha.
+ * as.h (PRINTF_LIKE): Don't define if VMS, for now.
+ * config/obj-evax.c: New file.
+ * config/obj-evax.h: New file.
+ * config/tc-alpha.c: Add support for EVAX format if OBJ_EVAX is
+ defined.
+ * config/tc-alpha.h: Add support for EVAX format if OBJ_EVAX is
+ defined. Add case for bfd_target_evax_flavour.
+ * config/vms-a-conf.h: New file.
+ * conf-a-gas.com: New file.
+ * configure.in: Add target alpha-*-*vms*.
+ * configure: Rebuild.
+ * makefile.vms: New file.
+ * read.c (s_lcomm): Align bss_seg on 8 byte boundary if OBJ_EVAX.
+ Don't call ffs on openVMS/Alpha.
+
+Wed Aug 7 14:19:03 1996 Philippe De Muyter <phdm@info.ucl.ac.be>
+
+ * configure.in: Make GAS_CHECK_DECL_NEEDED include <string.h> or
+ <strings.h> if they exist. Call GAS_CHECK_DECL_NEEDED on strstr
+ and sbrk.
+ * acconfig.h (NEED_DECLARATION_STRSTR): New macro.
+ (NEED_DECLARATION_SBRK): New macro.
+ * configure, conf.in: Rebuild.
+ * as.h: Only include <strings.h> if HAVE_STRINGS_H.
+ (strstr): Declare if NEED_DECLARATION_STRSTR.
+ * as.c: If HAVE_SBRK and NEED_DECLARATION_SBRK, declare sbrk.
+
+Wed Aug 7 11:50:26 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * symbols.c (resolve_symbol_value): Handle addition or subtraction
+ by a constant before entering the main switch. Reject attempts to
+ apply an arithmetic function to non-absolute symbols, except for
+ the special case of subtraction of two symbols in the same
+ section.
+
+ * config/tc-mips.c (md_section_align): Do align if OBJ_ELF, but
+ not to more than a 16 byte boundary.
+
+ * config/tc-i386.c (tc_gen_reloc): Accept all relocs; remove
+ #ifndef OBJ_ELF lines. From Eric Valette <valette@crf.canon.fr>.
+ (tc_gen_reloc): If out of memory call as_fatal rather than
+ assert. If no howto found, call as_bad_where rather than
+ as_fatal. Change the error message slightly. Set howto to a
+ non-NULL value in order to keep going.
+
+Tue Aug 6 12:58:03 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c: Added code to support 32-bit fixups for stabs.
+
+Tue Aug 6 11:15:26 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-h8300.c (get_specific): New operand "size" derived
+ from ".b", ".w" and ".l" extensions. All callers changed. If
+ the base instruction has no operands, then use the size to
+ determine which specific instruction to use.
+
+Mon Aug 5 14:21:10 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-i960.c (mem_fmt): Call parse_expr before emit.
+
+Fri Aug 2 11:23:31 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (md_section_align): Don't change addr if
+ OBJ_ELF.
+
+Thu Aug 1 23:51:52 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-hppa.c: Revert yesterday's changes.
+
+Wed Jul 31 14:46:11 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c: Disable range checking on 16-bit values.
+
+Wed Jul 31 16:27:19 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (m68k_ip): Set ok_arch for every instruction,
+ not just the ones that don't match.
+
+Wed Jul 31 11:45:15 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c: Fixed bugs in short relocs and range checking.
+
+Wed Jul 31 15:41:42 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * config/tc-arm.c: Changed INSN_SIZE to variable insn_size, as
+ pre-cursor to adding Thumb support. Also added cpu_variant flag
+ information to each of the asm_flg structures.
+ (md_parse_option): Updated ARM7 parsing to allow 't' for
+ thumb/halfword support, aswell as 'm' for long multiply.
+ (md_show_usage): Updated help message.
+ (md_assemble): Check that instruction flags are applicated to the
+ current cpu variant.
+ (md_apply_fix3, tc_gen_reloc): Add BFD_RELOC_ARM_OFFSET_IMM8 and
+ BFD_RELOC_ARM_HWLITERAL relocation support for new halfword and
+ signextension instructions.
+ (do_ldst): Generate halfword and signextension variants if
+ mnemonic flags match.
+ (ldst_extend): Do not allow shifts in the offset field of halfword
+ or signextension instructions.
+ (validate_offset_imm): Provide check on halfword and signextension
+ immediate range.
+ (add_to_lit_pool): Merge identical literal pool values.
+
+Tue Jul 30 14:28:23 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-hppa.c (selector_table): Add 'E' selector.
+ (cons_fix_new_hppa): Don't coke on e_esel.
+ (tc_gen_reloc, SOM version): Handle R_COMP2 when used
+ to help generate exception handling tables.
+ (md_apply_fix): Don't try to apply fixups with an e_esel
+ selector.
+ (hppa_fix_adjustable): Fixups with e_esel selectors
+ are not adjustable.
+
+Tue Jul 30 15:51:41 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sparc.c (md_pseudo_table): Add 2byte, 4byte, and 8byte
+ pseudo-ops.
+
+Fri Jul 26 11:43:03 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c: Added lots of error checking. Added hacks
+ to support accumulator shifts.
+
+Fri Jul 26 11:56:08 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * symbols.c (S_SET_EXTERNAL): Let .weak override.
+ (S_CLEAR_EXTERNAL): Likewise.
+ (S_SET_WEAK): Remove error; just let .weak override.
+
+Thu Jul 25 15:22:51 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c (md_assemble): Now handles multiline
+ instructions.
+
+Thu Jul 25 12:03:33 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c: Fix packaging bug. Added range checking.
+ Added kludge for divs instruction. Fixed minor problem with
+ multiple text sections.
+ * config/tc-d10v.h (d10v_cleanup): Change prototype.
+
+Tue Jul 23 10:49:36 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c (md_apply_fix3): Fix all instruction
+ addresses to be right-shifted by 2.
+
+Mon Jul 22 11:32:36 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c: Many changes to get relocs working.
+ (register_name): No longer creates a symbol for register names.
+ (pre_defined_registers): moved to opcodes/d10v-opc.c.
+ (d10v_insert_operand): Now works correctly for either container.
+ * config/tc-d10v.h (d10v_cleanup): Declare.
+
+Mon Jul 22 14:01:33 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (tc_gen_reloc): BFD_RELOC_PCREL_HI16_S and
+ BFD_RELOC_PCREL_LO16 are expected to be PC relative.
+
+Mon Jul 22 12:46:55 1996 Richard Henderson <rth@tamu.edu>
+
+ * tc-alpha.c: Patches to track current minimum alignment to reduce
+ the number of fragments created with frag_align.
+ (alpha_current_align): New static variable.
+ (s_alpha_text): Reset alignment to 0.
+ (s_alpha_data, s_alpha_rdata, s_alpha_sdata): Likewise.
+ (s_alpha_stringer, s_alpha_space): New functions.
+ (s_alpha_cons, alpha_flush_pending_output): Remove functions.
+ (alpha_cons_align): New function to replace both of them.
+ (emit_insn): Only align if alpha_current_align is less than 2;
+ reset alpha_current_align to 2.
+ (s_alpha_gprel32): Likewise.
+ (s_alpha_section): New function. Basically duplicate the other
+ alpha section change hooks. Only define for ELF.
+ (s_alpha_float_cons): Simplify alignment handling.
+ (md_pseudo_table): Only define "rdata" and "sdata" if OBJ_ECOFF.
+ If OBJ_ELF, define "section", "section.s", "sect", and "sect.s".
+ Don't define the s_alpha_cons pseudo-ops. Do define
+ s_alpha_stringer and s_alpha_space pseudo-ops.
+ (alpha_align): Skip if less than current default alignment. Set
+ default alignment.
+ * tc-alpha.h (md_flush_pending_output): Remove.
+ (md_cons_align): Add.
+
+ * tc-alpha.c: Add oodles of function description comments.
+ (md_bignum_to_chars): Remove; there are no callers.
+ (md_show_usage): Mention some more variants.
+
+Thu Jul 18 15:54:54 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ From Andrew Gierth <ANDREWG@microlise.co.uk>:
+ * configure.in (sparc-*-sysv4*): New target.
+ * configure: Rebuild.
+
+ * config/tc-sparc.c (md_pseudo_table): Change uahalf, uaword, and
+ uaxword to use s_uacons.
+ (sparc_no_align_cons): New static variable.
+ (s_uacons): New static function.
+ (sparc_cons_align): If sparc_no_align_cons is set, just clear it
+ and return.
+
+ * config/tc-sparc.c (s_common): Remove unused label allocate_bss.
+
+ * configure.in: Add mips-*-irix6* target. Handle Irix 6 like Irix
+ 5 with regard to shared libraries.
+ * configure: Rebuild.
+
+ * config/tc-m68k.c (m68k_ip): Use the correct length when
+ allocating space for the unsupported architecture error message.
+
+Thu Jul 18 12:57:10 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure.in (d10v-*-*): Allow d10v-*-*, don't require d10v-*-elf*.
+
+Wed Jul 17 14:25:13 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * config/tc-d10v.c: New file.
+ * config/tc-d10v.h: New file.
+ * configure (d10v-*-elf): New target.
+ * configure.in (d10v-*-elf): New target.
+
+Fri Jul 12 20:54:19 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (md_parse_option): Recognize -K PIC.
+
+Wed Jul 10 12:39:08 1996 Richard Henderson <rth@tamu.edu>
+
+ * config/tc-alpha.c (alpha_align): Change fill parameter
+ to a pointer. Take NULL as 0 or nop depending on section. Change
+ all callers.
+ (s_alpha_align): Rename local variables.
+
+ * doc/as.texinfo (.align): Document action of omitted
+ fill parameter.
+
+Wed Jul 10 00:23:30 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-ppc.c (md_apply_fix3): Give a useful error message
+ when an unsupported PC relative reloc is seen, rather than calling
+ abort.
+
+ * app.c (do_scrub_chars): Remove not_cpp_line local variable.
+ Instead, check state when '#' comment is seen.
+
+Mon Jul 8 14:11:49 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (mips_regmask_frag): Only define if OBJ_ELF or
+ OBJ_MAYBE_ELF.
+ (tc_gen_reloc): If fixup was changed to be PC relative, change
+ reloc type accordingly. Use name of reloc in error message.
+
+ * as.h: Don't define const or volatile.
+ * flonum.h: Don't define const.
+
+ * config/tc-m68k.c (tc_gen_reloc): Change the code appropriately
+ if fx_pcrel is set. Correct setting the addend case in the
+ OBJ_ELF case (from Andreas Schwab
+ <schwab@issan.informatik.uni-dortmund.de>).
+ (md_show_usage): Correct -mfc5200 to -m5200.
+
+Fri Jul 5 10:32:58 1996 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * doc/c-m68k.texi: Document -m5200 flag.
+ * doc/as.texinfo: Likewise.
+
+ * config/tc-m68k.c (m68k_ip): The coldfire does not support 8x
+ scale factor.
+
+Fri Jul 5 11:07:24 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * symbols.c (S_SET_EXTERNAL): Change as_warn to as_bad.
+ (S_CLEAR_EXTERNAL, S_SET_WEAK): Likewise.
+
+Thu Jul 4 11:59:46 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (VERSION): Set to cygnus-2.7.1.
+
+ * Released binutils 2.7.
+
+Thu Jul 4 10:11:33 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * config/tc-mips.c (mips_ip): Only perform range check when
+ dealing with O_constant expressions.
+
+Wed Jul 3 15:02:21 1996 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * m68k-parse.h (m68k_register): Add new coldfile control
+ registers.
+
+ * config/tc-m68k.c (mcf5200_control_regs): New variable,
+ array of control registers for the coldfire.
+ (cpu_of_arch): Added mcf5200.
+ (archs): Added mcf5200.
+ (init_table): Add new control registers.
+ (m68k_ip): Added support for new control registers.
+ (m68k_init_after_args): Likewise.
+
+ * config/tc-m68k.c (md_show_usage): Add -m5200 to usage text.
+
+Wed Jul 3 16:05:50 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.h (is_it_end_of_statement): Declare.
+ * read.c (is_it_end_of_statement): Remove declaration.
+
+ * config/tc-ppc.c (ppc_elf_suffix): Correct parenthesization of ||
+ within &&.
+ (md_assemble): Fix handling of @l with an unsigned constant. Add
+ default case to reloc switch.
+
+ * config/tc-i386.h (AOUT_MACHTYPE): Define as 0 if TE_386BSD.
+
+ Based on patches from Tom Quiggle <quiggle@sgi.com>:
+ * ecoff.c (last_lineno): New static variable.
+ (add_procedure): Set last_lineno.
+ (ecoff_directive_loc): Likewise.
+ (ecoff_generate_asm_lineno): Likewise.
+ (ecoff_fix_loc): New function.
+ * ecoff.h (ecoff_fix_loc): Declare.
+ * config/tc-mips.c (append_insn): When inserting nops, and using
+ ECOFF debugging, call ecoff_fix_loc.
+
+Tue Jul 2 23:02:12 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-h8300.c (build_bytes): If an operand type is
+ marked as SRC_IN_DST retrieve it from the "destination" op.
+
+Sat Jun 29 13:38:31 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in (arm-*-riscix*): Set emulation to riscix.
+ * configure: Rebuild.
+ * config/te-riscix.h: New file to define TE_RISCIX.
+
+ * config/tc-sh.h (SUB_SEGMENT_ALIGN): Define.
+
+Fri Jun 28 15:14:31 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (config.status): Just run config.status as other
+ tools do.
+
+Fri Jun 28 11:09:38 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-config.in (TARGET_OS): Add definition to conf.
+
+Thu Jun 27 20:39:40 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * config/tc-mips.c (append_insn): Parenthesize
+ cop_interlocks expressions.
+
+Thu Jun 27 12:18:26 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * listing.c (listing_print): Close the listing file if it is not
+ stdout. Close the other files opened for the listing.
+
+ * config/tc-sparc.h (md_cons_align): Define.
+ (sparc_cons_align): Declare.
+ (HANDLE_ALIGN): Define.
+ (sparc_handle_align): Declare.
+ * config/tc-sparc.c (sparc_cons_align): New function.
+ (sparc_handle_align): New function.
+ * read.c (cons_worker): Call md_cons_align if it is defined.
+
+ * as.h (struct frag): Add fr_file and fr_line fields.
+ * frags.c (frag_new): Set fr_file and fr_line.
+ (frag_var): Likewise.
+ (frag_variant): Likewise.
+
+ * as.h (struct frag): Remove unused align_mask and align_offset
+ fields.
+
+ * listing.c (calc_hex): Offset by fr_fix when examining fr_var.
+ From <uddeborg@carmen.se>.
+
+Wed Jun 26 13:21:34 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in (mips-*-osf*): New target.
+ * configure: Rebuild.
+
+ * config/tc-m68k.c: Add 68ec060 as a synonym for 68060.
+
+Wed Jun 26 16:23:08 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * config/tc-mips.c: Added cop_interlocks, to avoid NOP insertion
+ between co-processor comparisons and branches for the VR4300.
+
+Mon Jun 24 18:02:50 1996 Jason Molenda (crash@godzilla.cygnus.co.jp)
+
+ * Makefile.in (bindir, libdir, datadir, mandir, infodir, includedir,
+ INSTALL_PROGRAM, INSTALL_DATA): Use autoconf-set values.
+ (docdir): Removed.
+ * configure.in (AC_PREREQ): autoconf 2.5 or higher.
+ * doc/Makefile.in (bindir, libdir, datadir, mandir, infodir,
+ includedir): Use autoconf set values.
+ (docdir): Removed.
+
+Mon Jun 24 11:58:14 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * listing.c (listing_eject): Don't do anything if listing is 0.
+ (listing_list): Likewise.
+ (listing_source_line): Likewise.
+ (listing_title): Don't save title if listing is 0.
+ (listing_source_file): Check listing rather than listing_tail.
+
+ * configure.in: On alpha*-*-osf*, link against libbfd.a if not
+ using shared libraries.
+ * configure: Rebuild.
+
+Fri Jun 21 18:22:23 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (mips_ip): In case 'i'/'j', don't require an
+ absolute expression if a relocation type was specified.
+
+Fri Jun 21 17:40:16 1996 Joel Sherrill <joel@merlin.gcs.redstone.army.mil>
+
+ * configure.in: Add support for *-*-rtems* configurations.
+ * configure: Rebuild.
+
+Fri Jun 21 16:01:18 1996 Richard Henderson <rth@tamu.edu>
+
+ * configure.in: Add alpha-*-linuxecoff* target. Use elf for
+ alpha-*-linux* target. Force bfd_gas for alpha-*. Require
+ opcodes library for alpha.
+ * configure: Rebuild with autoconf 2.10.
+ * config/tc-alpha.c: Substantial rewrite to add ELF support and
+ use new opcode table.
+ * config/tc-alpha.h (md_undefined_symbol): Don't define.
+ (LOCAL_LABEL): Define differently if OBJ_ELF.
+ (FAKE_LABEL_NAME): Define if OBJ_ELF.
+ * config/alpha-opcode.h: Remove.
+ * config/obj-elf.h: If TC_ALPHA, define ECOFF_DEBUGGING.
+ * Makefile.in (TARG_CPU_DEP_alpha): Depend upon
+ include/opcode/alpha.h rather than config/alpha-opcode.h.
+
+Thu Jun 20 19:10:28 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-aout.c (obj_emit_relocations): Give an error if the
+ relocation symbol was not resolved.
+ * config/obj-coff.c (do_relocs_for): Likewise.
+
+ * write.c (adjust_reloc_syms): Refetch the symbol section after
+ calling S_GET_VALUE, since it may have changed.
+
+ * expr.c (struct expr_symbol_line): Define.
+ (expr_symbol_lines): New static variable.
+ (make_expr_symbol): Add entry to expr_symbol_lines.
+ (expr_symbol_where): New function.
+ * expr.h: Use extern on function declarations.
+ (expr_symbol_where): Declare.
+ * symbols.c (resolve_symbol_value): Try to use expr_symbol_where
+ rather than printing the meaningless name of an expression
+ symbol.
+
+Thu Jun 20 15:57:41 1996 Ken Raeburn <raeburn@cygnus.com>
+
+ * config/tc-i386.c (md_number_to_chars): Deleted.
+ * config/tc-i386.h (md_number_to_chars): New macro.
+
+ * config/tc-alpha.c (build_operate_n, build_mem): Moved earlier in
+ the file.
+ (load_symbol_address, load_expression): Use build_mem.
+ (build_operate): New function.
+ (emit_addq_r): Use it.
+
+ Wed Mar 13 22:14:14 1996 Pat Rankin <rankin@eql.caltech.edu>
+
+ * symbols.c (colon): #if VMS, use S_SET_OTHER to store `const_flag'.
+
+ Tue Mar 5 14:31:45 1996 Pat Rankin <rankin@eql.caltech.edu>
+
+ * config/tc-vax.h (NOP_OPCODE): Define.
+
+ Sun Feb 4 21:01:03 1996 Pat Rankin <rankin@eql.caltech.edu>
+
+ * config/obj-vms.h (S_IS_COMMON): Define.
+ (S_IS_LOCAL): Check for \002 as well as \001.
+ (LONGWORD_ALIGNMENT): New macro.
+ (SUB_SEGMENT_ALIGN): Use it.
+
+ Fri Jan 26 17:44:09 1996 Pat Rankin <rankin@eql.caltech.edu>
+
+ * config/vms-conf.h: Reconcile with conf.in.
+
+Wed Jun 19 11:31:50 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * write.c (is_dnrange): Only define if TC_GENERIC_RELAX_TABLE is
+ defined.
+
+ * doc/as.texinfo: Document that any number of hex digits can
+ follow \x.
+
+ * as.c (struct defsym_list): Define.
+ (defsyms): New static variable.
+ (parse_args): Just put --defsym arguments on defsyms list, rather
+ than defining them.
+ (main): Define defsyms after output file is created.
+
+ * config/tc-m68k.c (m68k_ip): Reject PRE and POST indexing mode on
+ cpu32. From Eric Norum <Eric.Norum@usask.ca>.
+
+ * config/tc-mips.c (mips_ip): In cases 'I', 'i', and 'j', set
+ insn_error rather than calling check_absolute_expr.
+
+ * as.c (emulation_name): Remove unused static variable.
+ (default_emul_bfd_name): Add return NULL to avoid warning.
+ * ecoff.c (ecoff_stab): Remove unused variables name and
+ name_end.
+ * frags.c (frag_new): Remove unused variable tmp.
+ * hash.c (hash_grow): Parenthesize + within <<.
+ (hash_print_statistics): Use %lu, not %d, to print unsigned
+ long variables.
+ * messages.c: Include "libiberty.h".
+ (fprint_value): Add cast to avoid printf warning.
+ (sprint_value): Likewise.
+ * read.c: Include "ecoff.h".
+ (emit_expr): Add casts to avoid printf warnings.
+ * read.h: Use extern for function declarations.
+ (pop_insert): Declare.
+ * stabs.c: Include "ecoff.h".
+ * subsegs.c (subseg_set_rest): Remove unused variables tmp,
+ former_last_fragP, and new_fragP.
+ * subsegs.h (subsegs_print_statistics): Declare.
+ * symbols.c (debug_verify_symchain): Change macro to discard
+ arguments.
+ * write.c (dump_section_relocs): Likewise.
+ * write.h: Use extern for function declarations.
+ (write_print_statistics): Declare.
+ * config/e-mipsecoff.c (mipsecoff_bfd_name): Return NULL to avoid
+ warning.
+ * config/e-mipself.c (mipself_bfd_name): Likewise.
+ * config/obj-elf.h (elf_ecoff_set_ext): Declare.
+
+ * config/tc-sparc.h (TC_RELOC_RTSYM_LOC_FIXUP): If OBJ_ELF, always
+ emit relocations against external symbols.
+
+ * config/tc-alpha.c (tc_gen_reloc): Output a sensible error
+ message if bfd_reloc_type_lookup fails, rather than calling
+ assert.
+
+ * config/tc-alpha.c (alpha_force_relocation): Add
+ BFD_RELOC_12_PCREL to switch.
+
+Tue Jun 18 20:29:57 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/tc-i386.h (LOCAL_LABEL,FAKE_LABEL_NAME): Use defaults for
+ TE_PE (Lfoo, not .Lfoo).
+
+Tue Jun 18 17:13:33 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.c (s_fill): Don't warn about a zero repeat count.
+
+ * config/tc-mips.c (mips_ip): Don't warn about using AT as a
+ coprocessor register.
+
+ * config/tc-i386.c (md_assemble): When checking the size of a
+ register to set the size of an instruction, do a bitwise and with
+ Reg8 and Reg16 rather than requiring the type to be exactly Reg8
+ or Reg16.
+
+Tue Jun 18 13:19:51 1996 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * config/tc-h8300.c (parse_reg): Tweak error messages.
+ (build_bytes): Likewise.
+ (skip_colonthing): Handle :32 suffix.
+ (get_specific): Promote L_24 to L_32 if it makes a match.
+ Don't always promote L_8 to L_16.
+ (do_a_fix_imm): Clean up L_32 and L_24 handling.
+
+ * config/tc-h8300.c (Smode): New variable.
+ (h8300hmode): Turn off Hmode.
+ (h8300smode): New function. Turn on Smode and Hmode.
+ (md_pseudo_table): New ".h8300s" pseudo-op.
+ (parse_reg): Handle "exr" register.
+ (get_operand): Handle bizarre syntax for "stm.l" and "ldm.l".
+ Handle "mach" and "machl" operands for ldmac.
+ (get_specific): Handle "stm.l" and "ldm.l".
+ (build_bytes): Handle "stm.l" and "ldm.l"; handle MACREG operands.
+ * config/tc-h8300.h (COFF_MAGIC): Handle H8/S magic number.
+ (Smode): Declare.
+
+Mon Jun 17 15:50:53 1996 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * doc/as.texinfo: Reorder chapter of machine dependent options so
+ that it is sorted by chip name.
+
+ * doc/as.texinfo: Use consistant spelling of Vax.
+ * doc/c-vax.texi: Likewise.
+
+Mon Jun 17 11:26:56 1996 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * config/tc-hppa.c (md_pseudo_table): Add ".begin_try" and ".end_try"
+ pseudo ops.
+ (tc_gen_reloc, SOM version): Handle R_BEGIN_TRY and R_END_TRY.
+ (md_apply_fix): Likewise.
+ (pa_try): New function.
+ (hppa_force_relocation): Force relocs for BEGIN_TRY and END_TRY.
+
+Sun Jun 16 22:57:47 1996 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * config/tc-hppa.c (md_pseudo_table): Add ".level" pseudo op.
+ (pa_level): New function.
+
+Fri Jun 14 20:06:44 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * listing.c (listing_newline): Don't do anything if listing is 0.
+
+Thu Jun 13 17:50:54 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * subsegs.c (section_symbol): If symbol_table_frozen is set, call
+ symbol_create, not symbol_new.
+
+Wed Jun 12 14:10:44 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * write.c (adjust_reloc_syms): Don't set sy_used_in_reloc for an
+ absolute symbol unless TC_FORCE_RELOCATION returns true.
+
+ * config/obj-coff.c (previous_file_symbol): Remove BFD_ASSEMBLER
+ version.
+ (c_dot_file_symbol): BFD_ASSEMBLER version: Don't set the value of
+ the symbol to a pointer. Don't set previous_file_symbol.
+ Simplify symbol list rearrangement.
+ (coff_frob_symbol): Don't do anything with C_FILE symbols.
+ (coff_adjust_symtab): Don't check previous_file_symbol.
+
+Mon Jun 10 14:52:29 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (ppc_elf_lcomm): New function for .lcomm
+ directive.
+ (md_pseudo_table): Add ppc_elf_lcomm.
+
+Mon Jun 10 11:45:51 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (m68k_ip): Accept ABSL for 'O', so that `bfextu
+ d0{24:1},d0' works without an immediate prefix on the bit numbers.
+ (md_begin): Add digits to alt_notend_table.
+ (md_parse_option): Make s a const pointer.
+
+ * config/tc-sparc.c (md_pseudo_table): Add "empty".
+ (s_empty): New static function.
+
+ * config/obj-coff.c (struct filename_list): Only define if not
+ BFD_ASSEMBLER.
+ (filename_list_head, filename_list_tail): Likewise.
+ (c_section_symbol): Remove unused BFD_ASSEMBLER version.
+ (obj_coff_endef, BFD_ASSEMBLER version): Don't set the debugging
+ flag for C_MOS, C_MOE, C_MOU, or C_EOS symbols, since they should
+ have a section of N_ABS rather than N_DEBUG. If we do a merge,
+ remove the new symbol from the list.
+ (obj_coff_endef, both versions): Call tag_insert even if there is
+ an old symbol with the same name, if the old symbol does not
+ happen to be a tag.
+ (coff_frob_symbol): Check SF_GET_TAG, C_EOF, and C_FILE outside of
+ the SF_GET_DEBUG condition. Don't call SA_SET_SYM_ENDNDX with a
+ symbol that will be moved to the end of the symbol list.
+ (coff_adjust_section_syms): Always call section_symbol for .text,
+ .data, and .bss.
+ (coff_frob_section): Likewise. Also, remove unused variable
+ strname.
+
+ * config/tc-ns32k.c (convert_iif): Call frag_grow rather than
+ manipulating frags directly.
+ (md_number_to_field): Adjust mem_ptr correctly if ENDIAN is
+ defined.
+
+ * app.c (do_scrub_chars): If '/' is LINE_COMMENT_START, check
+ whether the next character is '*' before checking whether we are
+ at the start of a line. Permit LINE_COMMENT_START to start a
+ comment in state 1 (seen some whitespace) as well, to match the
+ documentation.
+
+ * gasp.c (do_align): Permit a fill value for .align.
+
+Wed Jun 5 17:09:26 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.c (next_char_of_string): Warn if a newline is seen in the
+ middle of a string. Call bump_line_counters when appropriate.
+
+Wed Jun 5 17:08:36 1996 Richard Henderson <rth@tamu.edu>
+
+ * symbols.c (colon): Use LOCAL_LABEL.
+
+Tue Jun 4 10:55:16 1996 Tom Tromey <tromey@csk3.cygnus.com>
+
+ * Makefile.in (install): Don't check to see if tooldir exists.
+ Make $(tooldir) and $(tooldir)/bin.
+
+Tue Jun 4 10:14:53 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/ppc-sol.mt (TDEFINES): Don't turn on -mregnames by
+ default.
+
+Mon Jun 3 11:34:41 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (mips_ip): Don't call as_warn if we are setting
+ insn_error. Don't put the string "ERROR" in insn_error. Set
+ insn_error rather than calling as_warn for an unsupported opcode.
+
+Sat Jun 1 21:51:55 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (md_parse_option): Check for a 64 bit format
+ before permitting -64.
+ * output-file.c (output_file_create): Remove duplicate
+ bfd_perror.
+
+Fri May 31 01:08:06 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (md_begin): If -64, create a .MIPS.options
+ section rather than a .reginfo section.
+ (mips_elf_final_processing): If -64, write out 64 bit RegInfo
+ information.
+
+ * config/tc-mips.c (load_register): If mips_isa < 3, permit a 32
+ bit value with the high bit set.
+
+Thu May 30 19:00:19 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.c (s_lcomm): Set section flags for .sbss section.
+
+ * config/tc-mips.c (mips_64): New static variable.
+ (mips_target_format): If mips_64, return elf64 targets rather than
+ elf32 ones.
+ (md_longopts): Add "32" and "64".
+ (md_parse_option): Handle -32 and -64.
+ (md_show_usage): Mention -32 and -64.
+ (cons_fix_new_mips): If mips_64, don't convert an 8 byte reloc to
+ a 4 byte one.
+
+Thu May 30 10:36:19 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (comment_chars): Make '!' a comment character
+ for Solaris compatibility.
+
+ * stabs.c (s_stab_generic): Under PowerPC Solaris, convert a
+ .stabd with 4 arguments into a .stabn.
+
+Wed May 29 16:43:16 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (macro): When passing X_add_number to
+ macro_build, cast it to int first.
+
+Tue May 28 13:29:39 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-z8k.c (md_apply_fix): Handle fx_r_type of 0, as
+ created by emit_expr.
+
+ * symbols.c (symbol_create): If bfd_make_empty_symbol fails, call
+ as_perror rather than assert.
+
+Fri May 24 18:24:11 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (mips_ip): Mark sections created to hold
+ floating point information as read only.
+
+Fri May 24 12:07:54 1996 David Edelsohn <edelsohn@mhpcc.edu>
+
+ * config/tc-ppc.c (ppc_set_cpu): Change defaults to match AIX.
+
+Thu May 23 17:34:24 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * read.c (potable): Add .skip as a synonym for .space.
+
+ * stabs.c (s_stab_generic): For PowerPC ELF, allow .stabd to take
+ 4 arguments, providing the 4th argument is 0, to allow
+ compatibility with the Solaris assembler.
+
+Thu May 16 15:51:48 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sh.h (struct sh_segment_info_type): Define.
+ (TC_SEGMENT_INFO_TYPE): Define.
+ (sh_frob_label): Declare.
+ (tc_frob_label): Define.
+ (sh_flush_pending_output): Declare.
+ (md_flush_pending_output): Define.
+ * config/tc-sh.c (md_assemble): If relaxing, emit a R_SH_CODE
+ reloc before the instruction if necessary.
+ (sh_frob_label): New function.
+ (sh_flush_pending_output): New function.
+ (sh_coff_frob_file): Ignore ALIGN, CODE, DATA, and LABEL relocs
+ when looking for the reloc for the target of .uses.
+ (md_convert_frag): Fix printf format (%0xlx to 0x%lx).
+ (sh_force_relocation): Force CODE, DATA, and LABEL relocs to be
+ emitted.
+ (md_apply_fix): Ignore CODE, DATA, and LABEL relocs.
+ (sh_coff_reloc_mangle): Force CODE, DATA, and LABEL relocs to use
+ the absolute symbol.
+
+ * subsegs.h (segment_info_type): Add tc_segment_info_data field if
+ TC_SEGMENT_INFO_TYPE is defined.
+
+Wed May 15 12:23:53 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-i386.c (md_assemble): Make sure the opcode suffix
+ matches the register size.
+
+Wed May 15 08:33:37 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/obj-coff.c (count_entries_in_chain): Ignore Fixups with
+ fx_done set.
+ (do_relocs_for): Likewise.
+ (fixup_segment): Don't just quit if linkrelax is set. Try to
+ apply non pc-relative sym1-sym2 fixups, even if linkrelax is
+ nonzero.
+
+Fri May 10 14:16:59 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (ppc_elf_validate_fix): Allow GOT and section
+ relative relocations with -mrelocatable. Also allow unfixed
+ relocs in .ex_shared.
+
+Tue May 7 11:24:10 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.c (yank_symbols): Check that FNAME_OFFSET is
+ non-zero before assuming this is a long file name.
+ (w_strings): Likewise.
+ (c_dot_file_symbol): Set FNAME_OFFSET to 1 for a long file name.
+
+ * config/obj-coff.c (w_strings): Move declaration of i inside
+ #ifdef block which uses it.
+
+Tue May 7 00:49:58 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-h8300.c (do_a_fix_imm): Rename last argument to
+ "relaxmode". Output relocs which identify various relaxing
+ possibilities for mov.[bwl] instructions.
+ (build_bytes): Pass in a relaxing mode to do_a_fix_imm.
+
+Mon May 6 15:26:28 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/tc-arm.h (TC_HANDLES_FX_DONE): Define.
+ (MD_APPLY_FIX3): Define.
+ * config/tc-arm.c (my_get_expression): Only watch for bad segments
+ if OBJ_AOUT.
+ (md_apply_fix3): Renamed from md_apply_fix.
+ If pcrel reloc and symbol is in different section, undo effects
+ of md_pcrel_from.
+
+Sat May 4 12:49:35 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-hppa.c (hppa_fix_adjustable): Don't adjust
+ any reloc with an LR% or RR% field selector for SOM.
+
+Sat May 4 11:26:19 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in: Add subsegs.h to appropriate TARG_CPU_DEP_*
+ variables.
+
+Fri May 3 17:58:31 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.c (coff_frob_symbol): Don't merge a symbol with
+ SF_GET_STATICS set.
+ (yank_symbols): Likewise.
+
+Wed May 1 13:38:17 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * subsegs.h (segment_info_type): If MANY_SEGMENTS and not
+ BFD_ASSEMBLER, add name field.
+ * config/obj-coff.c: Include "libiberty.h".
+ (coff_header_append): Handle long section names.
+ (crawl_symbols): Just use the name field for the symbol name,
+ without worrying about null byte termination.
+ (w_strings): Handle long section names.
+ (write_object_file): Likewise. Also, use the name field, rather
+ than scnhdr.s_name.
+ (obj_coff_add_segment): Permit long section names.
+ (obj_coff_init_stab_section): Use the name field, rather than
+ scnhdr.s_name.
+ (adjust_stab_section): Likewise.
+ * config/te-pe.h (COFF_LONG_SECTION_NAMES): Define.
+
+ * config/tc-i960.c (brtab_emit): Don't set fx_im_disp field.
+ (mem_fmt): Likewise.
+ (md_apply_fix): Don't check fx_im_disp field.
+
+Thu Apr 25 11:39:51 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Add * after sparc*-*-vxworks.
+ * configure: Rebuild.
+
+ * app.c (do_scrub_begin): If tc_comment_chars is not defined,
+ define it to comment_chars. Use tc_comment_chars rather than
+ comment_chars.
+ (do_scrub_chars): Use tc_comment_chars rather than comment_chars.
+ * config/tc-m68k.h (tc_comment_chars): Define.
+ (m68k_comment_chars): Declare.
+ * config/tc-m68k.c (m68k_comment_chars): Rename from
+ comment_chars. Change into a pointer rather than an array.
+ (md_longopts): Add "bitwise-or".
+ (md_parse_option): Handle OPTION_BITWISE_OR.
+ (md_show_usage): Mention --bitwise-or.
+ * doc/c-m68k.texi: Document --bitwise-or.
+
+Wed Apr 24 11:28:38 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (m68k_ip): Prevent attempts to use long offsets
+ in 68000 mode.
+
+ * config/obj-coff.c (obj_coff_section): BFD_ASSEMBLER version:
+ call demand_empty_rest_of_line. Non BFD_ASSEMBLER version:
+ correct handling of input line pointer, and call
+ demand_empty_rest_of_line.
+
+Mon Apr 22 18:02:37 1996 Doug Evans <dje@blues.cygnus.com>
+
+ * config/tc-sparc.c (in_bitfield_range): New static function.
+ (sparc_ip): New cases X,Y. Use SPARC_OPCODE_ARCH_V9_P.
+ (md_apply_fix, cases BFD_RELOC_32_PCREL_S2,
+ BFD_RELOC_SPARC_{WDISP16,WDISP19}): Fix undefined code.
+ (md_apply_fix): New cases BFD_RELOC_SPARC_[56].
+ (tc_gen_reloc): New cases BFD_RELOC_SPARC_[56].
+
+Thu Apr 18 18:58:33 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.c: BFD_ASSEMBLER:
+ (coff_last_bf): New static variable.
+ (coff_frob_symbol): Set endndx of a .bf symbol.
+ Non BFD_ASSEMBLER:
+ (obj_coff_endef): Call SF_SET_PROCESS on a .bf symbol.
+ (last_bfP): New static variable.
+ (yank_symbols): Set endndx of a .bf symbol.
+
+Thu Apr 18 11:53:58 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (md_parse_option): Add support for Solaris's -le
+ and -s options. Add -be for good measure.
+
+Wed Apr 17 12:31:01 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.c (s_space): Support non-constant fill value. Handle fill
+ value correctly for a size other than 1.
+
+Tue Apr 16 15:17:40 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/tc-arm.c (my_get_float_expression): Update call to
+ gen_to_words, X_PRECISION changed from 6 to 5.
+
+Tue Apr 16 10:25:42 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (register_name,reg_name_search): Move register
+ name lookup from PE specific code to all targets. Add support for
+ -mregnames/-mno-regnames to control whether register names are
+ expanded or not.
+ (md_assemble): Call register_name for all platforms.
+ (md_parse_option): Add support for -mregnames/-mno-regnames.
+
+ * configure.in (powerpcle*-*-solaris): Add support.
+ (powerpc*-*-linux): Ditto.
+ * configure: Regenerate.
+
+ * config/ppc-sol.mt: New config file for PowerPC Solaris.
+
+Mon Apr 15 12:26:33 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (mips_frob_file): Permit multiple %hi relocs to
+ be associated with a single %lo reloc.
+
+ * config/tc-mips.c (load_address): Cast X_add_number to valueT
+ before comparing against MAX_GPREL_OFFSET, so that negative
+ numbers are handled correctly.
+ (macro): Likewise.
+
+Thu Apr 11 12:39:02 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sparc.c (last_insn): New static variable.
+ (md_assemble): Warn about putting floating point branches in a
+ delay slot. If architecture is less than v9, insert NOP
+ instructions between floating point instructions and floating
+ point branches. (The SunOS assembler does both these operations.)
+ Save the last instruction opcode.
+ (sparc_ip): Add pinsn parameter. Change caller.
+
+ * config/tc-m68k.c (md_estimate_size_before_relax): Correct check
+ for byte jump to next instruction to skip empty frags.
+
+Wed Apr 10 16:48:12 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-alpha.c (alpha_ip): If we are going to call emit_add64
+ for addq with a 16 bit signed value, just emit a lda instruction
+ instead.
+
+Wed Apr 10 14:34:49 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-h8300.c (do_a_fix_imm): Don't cut off high bits
+ of a 32bit operand.
+
+Mon Apr 8 14:42:53 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Permit --enable-shared to specify a list of
+ directories.
+ * configure: Rebuild.
+
+Fri Apr 5 17:01:35 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-h8300.c (get_specific): Remove some #if 0 code.
+ (build_bytes): Remove all ABSMOV related code; it's unnecessary.
+
+Fri Apr 5 15:13:10 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * config/atof-ieee.c: Fix handling of denormalized extended
+ precision numbers and overflow/underflow detection.
+ (MAX_PRECISION, X_PRECISION, P_PRECISION): Changed from 6 to 5, to
+ not include the 16 bit gap in the m68k extended precision format.
+
+Fri Apr 5 14:29:23 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Add i386-*-freebsdelf* target; from John Polstra
+ <jdp@polstra.com>.
+ * configure: Rebuild.
+
+Fri Apr 5 18:39:28 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * config/tc-mips.c: Allow non-zero offsets from .sdata symbols to
+ be accessed using the $gp register.
+ * config/tc-mips.h (MAX_GPREL_OFFSET): Added.
+
+Wed Apr 3 10:56:14 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/tc-sparc.c (sparc_md_end): Set bfd machine number to
+ bfd_mach_sparc_sparclet if current_architecture is sparclet.
+
+Mon Apr 1 16:55:44 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.c (get_line_sb): Bump line counters based on
+ input_line_pointer[-1], not *input_line_pointer. Don't bother to
+ call LISTING_NEWLINE.
+ (s_macro): Don't call demand_empty_rest_of_line.
+ * app.c (do_scrub_chars): When handling C style comments, unget
+ ch2 rather than ch.
+
+Fri Mar 29 16:15:06 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.h (enum linkonce_type): Define.
+ (s_linkonce): Declare.
+ * read.c (potable): Add "linkonce".
+ (s_linkonce): New function.
+ * subsegs.h (segment_info_type): Add linkonce field to
+ MANY_SEGMENTS && ! BFD_ASSEMBLER section.
+ * config/obj-coff.h (obj_handle_link_once): Define if TE_PE.
+ (obj_coff_pe_handle_link_once): Declare if TE_PE.
+ * config/obj-coff.c: If TE_PE and not BFD_ASSEMBLER, #include
+ "coff/pe.h".
+ (obj_coff_pe_handle_link_once): New function, defined if TE_PE.
+ (c_section_symbol): If TE_PE, set the x_comdat field in the aux
+ entry based on the linkonce field in segment_info.
+ * doc/as.texinfo: Document .linkonce.
+
+Fri Mar 29 11:31:27 1996 J.T. Conklin (jtc@lisa.cygnus.com)
+
+ * doc/as.1: Changed to be recognized by catman -w on Solaris.
+
+Thu Mar 28 15:27:47 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * stabs.c (s_stab_generic): Call the listing functions before
+ doing the rest of the processing, which may involve freeing the
+ string. Pass string, not string + stroff, to OBJ_PROCESS_STAB in
+ SEPARATE_STAB_SECTIONS case.
+
+ * config/tc-hppa.c: Remove nested comment.
+ (tc_gen_reloc): Move label done inside the ifdef in which it is
+ used.
+ (md_apply_fix): Pass pointers to correct types to libhppa.h
+ functions. Always return a value.
+
+ * config/tc-mips.h (tc_frob_file): Define.
+ (mips_frob_file): Declare.
+ * config/tc-mips.c (struct mips_hi_fixup): Define.
+ (mips_hi_fixup_list): New static variable.
+ (imm_unmatched_hi): New static variable.
+ (md_assemble): Clear imm_reloc, imm_unmatched_hi, and
+ offset_reloc. Pass imm_unmatched_hi to append_insn.
+ (append_insn): Add unmatched_hi parameter. If it is set, add the
+ new fixup to mips_hi_fixup_list. Change all callers.
+ (mips_ip): Set imm_unmatched_hi when appropriate.
+ (mips_frob_file): New function.
+
+Thu Mar 28 11:47:59 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * configure.in (sparc-*-solaris2*): Renamed from sparc*-*-solaris2*.
+ * configure: Regenerated.
+
+Tue Mar 26 18:19:12 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * as.c (main): Call bfd_set_error_program_name.
+
+Fri Mar 22 11:13:00 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * as.h (strdup): Don't declare.
+ * stabs.c: Include libiberty.h
+ (get_stab_string_offset): Use xstrdup rather than strdup.
+ (s_stab_generic): Likewise.
+ * as.c (parse_args): Likewise.
+ * read.c (s_mri_sect): Likewise.
+
+ * gasp.c (change_base): Recognize \(...) construct documented to
+ pass through enclosed characters literally through to the output.
+ (process_assigns): Likewise. Also, be more careful to avoid
+ looking past the end of the buffer.
+
+Thu Mar 21 13:18:43 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-i386.c (md_parse_option): If OBJ_ELF, ignore -k for
+ FreeBSD compatibility. From John Polstra <jdp@polstra.com>.
+
+Wed Mar 20 18:13:32 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * doc/as.texinfo, doc/c-i960.texi: Fix typos.
+
+Wed Mar 20 17:05:16 1996 David Mosberger-Tang <davidm@azstarnet.com>
+
+ * config/alpha-opcode.h: Added cvtst instruction.
+
+Mon Mar 18 13:12:46 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * ecoff.c (ecoff_stab): Don't try to make a symbol out of the stab
+ string. Extract the addend from the result of expression.
+
+Fri Mar 15 17:10:43 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * app.c (do_scrub_chars): If whitespace is seen in state 11, and
+ LABELS_WITHOUT_COLONS is not defined, and we are not in m68k MRI
+ mode, change the state to 3 rather than 1.
+
+Thu Mar 14 18:18:25 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.h (C_REGISTER_SECTION): Change from 20 to 50, to
+ correspond to 11 March change.
+
+Thu Mar 14 15:27:10 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-h8300.c (build_bytes, MEMIND case): Generate
+ an R_MEM_INDIRECT reloc rather than R_RELBYTE.
+
+Tue Mar 12 12:21:10 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure: Rebuild with autoconf 2.8.
+
+Mon Mar 11 18:57:12 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/atof-ieee.c (gen_to_words): Improve handling of
+ X_PRECISION numbers. Based on patches from Andreas Schwab
+ <schwab@issan.informatik.uni-dortmund.de>.
+
+Mon Mar 11 09:59:53 1996 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * as.h (SEG_NORMAL, SEG_LIST): Bump segment limit from 10 to 40.
+ (SEG_LAST): New.
+ * subsegs.c (MANY_SEGMENTS): Increase segment limit.
+ * obj-coff.c (seg_N_TYPE, seg_info_off_by_4): Likewise.
+ (do_relocs_for, w_symbols, obj_coff_add_segment, do_linenos_for,
+ crawl_symbols, coff_header_append): Loop to SEG_LAST rather than
+ SEG_E9.
+
+Thu Mar 7 15:17:39 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * config/tc-sparc.c (sparc_ip): Handle operand char 'O' (neg reg).
+
+Thu Mar 7 09:19:15 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-hppa.c (SUBSEG_MILLI): Define.
+ (pa_def_subspaces): Add $MILLICODE$.
+ (pa_spaces_begin): Set section flags for $MILLICODE$.
+
+Wed Mar 6 14:11:30 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-elf.c (obj_elf_section): Only SEC_LOAD if the type is
+ not SHT_NOBITS. Don't tamper with flags based on type if a
+ special section was found (revert Feb 29 change).
+
+ * config/tc-sh.c (sh_do_align): Only align using the nop pattern
+ if aligning to a longword boundary or greater.
+
+Tue Mar 5 15:10:43 1996 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * config/tc-sh.c (sh_do_align): Pass 1 not 2 to frag_align.
+
+Mon Mar 4 20:50:57 1996 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * configure.in (i386-*-cygwin32): Don't use bfd_gas.
+ * configure: Regenerated.
+
+Mon Mar 4 10:13:06 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-hppa.c: Add default definitions for R_N0SEL and
+ R_N1SEL since they're not defined for old versions of hpux.
+
+ * config/tc-hppa.c (tc_gen_reloc): Fix typo in R_COMP2 code.
+ Set "sym_ptr_ptr" and "addend" fields to dummy values for
+ R_N0SEL and R_N1SEL.
+
+Fri Mar 1 10:20:52 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * flonum-konst.c: Add two more constants for 1e+-2048 and
+ 1e+-4096, and correct the other constants.
+
+ * symbols.c (resolve_symbol_value): Handle O_logical_not.
+
+Thu Feb 29 13:58:35 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/obj-elf.c (obj_elf_section): Allow predefined section
+ types to set the nobits type. Avoid a shadowed declaration.
+
+Wed Feb 28 15:38:56 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-hppa.c (hppa_fix_adjustable): For SOM, don't
+ reduce relocs using e_nlrsel field selectors.
+
+ * write.c (fix_new_exp): Don't use #elif. Some compilers
+ don't handle it.
+
+ * config/tc-hppa.c (selector_table): Add "n", "nl", and "nlr" to
+ the selector table.
+ (pa_chk_field_selector): Handle new field selectors for SOM.
+
+Tue Feb 27 14:42:27 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * configure.in (m68k-*-linux*aout*, m68k-*-linux*): New targets.
+ * configure: Rebuild.
+ * config/te-linux.h (LOCAL_LABELS_FB): Define.
+ * config/tc-m68k.h (TARGET_FORMAT) [TE_LINUX]: Define to
+ "a.out-m68k-linux".
+ * config/tc-m68k.c (comment_chars): Don't include '#' if TE_LINUX
+ is defined.
+
+Mon Feb 26 18:58:58 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-make.sed: Update to handle shared library support.
+
+Mon Feb 26 10:34:10 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * config/tc-sparc.c (sparc_ip): Print all architectures that support
+ the insn on mismatch.
+
+Fri Feb 23 21:44:39 1996 Rob Savoye <rob@chinadoll.cygnus.com>
+
+ * configure.in: Add support for a29-coff.
+ * configure: Rebuild.
+
+Thu Feb 22 16:39:43 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sh.c (sh_coff_frob_file): Don't consider the address
+ of the section when looking for the R_SH_USES fixup, because the
+ frag addresses have not yet been adjusted.
+
+ * gdbinit.in: Set a breakpoint on as_warn_where.
+
+ * config/tc-mips.c (macro): Add missing arguments to macro_build
+ omitted in last change. From Jim Wilson <wilson@cygnus.com>.
+
+Wed Feb 21 17:00:32 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-h8300.c (tc_reloc_mangle): Change reloc based on size
+ if it is TC_CONS_RELOC. Set a size of 4 to R_RELLONG.
+
+Wed Feb 21 09:25:39 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * config/tc-sparc.c (sparc_ip): Recognize %asr0 for v8.
+
+Tue Feb 20 21:48:03 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * config/tc-sparc.c (parse_keyword_arg): Accept leading '%'.
+ (sparc_ip): Accept %asr[1..31] for v8 and %asr[%16..31] for v9.
+ Recognize [uU] format args as sparclet cpregs.
+
+Tue Feb 20 22:25:55 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sh.c (sh_handle_align): Don't emit R_SH_ALIGN relocs
+ in bss_section.
+
+Mon Feb 19 14:16:24 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sparc.h (TC_RELOC_RTSYM_LOC_FIXUP): Check S_IS_WEAK as
+ well as S_IS_EXTERNAL.
+ (tc_fix_adjustable): Likewise.
+ * config/tc-sparc.c (md_apply_fix): In OBJ_ELF case, check for
+ S_IS_WEAK as well as S_IS_EXTERNAL when deciding whether to return
+ early.
+ (tc_gen_reloc): Check S_IS_WEAK as wel as S_IS_EXTERNAL when
+ deciding whether to convert BFD_RELOC_32_PCREL_S2 if PIC.
+
+Mon Feb 19 02:15:57 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * config/tc-sparc.c (max_architecture): Change to sparclite for
+ 32 bit arch.
+ (default_compatible): Delete.
+ (sparc_ffs): New function.
+ (md_begin): Only call SPARC_OPCODE_CONFLICT_P once.
+ (sparc_ip): Rewrite architecture match and bump logic.
+
+Sun Feb 18 15:03:50 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Check for 'do not mix' from native linker before
+ trying to use -rpath.
+ * configure: Rebuild.
+
+Fri Feb 16 16:53:31 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.h (SF_ADJ_LNNOPTR): Define (non BFD_ASSEMBLER).
+ (SF_GET_ADJ_LNNOPTR): Define (non BFD_ASSEMBLER).
+ (SF_SET_ADJ_LNNOPTR): Define (non BFD_ASSEMBLER).
+ * config/obj-coff.c (obj_coff_endef): Set ADJ_LNNOPTR when LNNOPTR
+ is set.
+ (w_symbols): If ADJ_LNNOPTR is set, add the section lnnoptr field
+ to the symbol lnnoptr field, to get the correct file offset.
+
+Thu Feb 15 14:48:38 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/obj-elf.c (elf_frob_symbol): On the PowerPC, force all
+ symbols that are not function, file, or section symbols to be
+ object types.
+
+Thu Feb 15 11:20:18 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure: Set and substitute RPATH_ENVVAR.
+ * configure: Rebuild.
+ * Makefile.in (RPATH_ENVVAR): New variable.
+ (check): Use $(RPATH_ENVVAR) rather than LD_LIBRARY_PATH.
+
+ * configure.in: Accept i686. From H.J. Lu <hjl@zoom.com>: i386
+ doesn't need opcodes. If configuring shared, opcodes needs bfd.
+ * configure: Rebuild.
+
+Wed Feb 14 16:33:12 1996 Martin Anantharaman <martin@mail.imech.uni-duisburg.de>
+
+ * read.c (s_mri_sect): Don't return '\0' in type. Set all
+ appropriate flags in BFD section.
+
+ * configure.in (m68k-*-psos*): New target.
+ * configure: Rebuild.
+ * config/te-psos.h: New file.
+ * config/tc-m68k.c (comment_chars): Don't include '#' if TE_PSOS
+ is defined.
+
+Wed Feb 14 13:43:24 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ From Alan Modra <alan@spri.levels.unisa.edu.au>:
+ * configure.in: Remove duplicate setting of cpu_type. Check
+ whether opcodes library is required for on all targets, not just
+ primary one.
+ * configure: Rebuild.
+
+ * config/tc-mips.c (mips_big_got): New static variable.
+ (s_extern): Don't declare.
+ (reg_needs_delay): New static function.
+ (macro_build): Permit GOT/CALL_HI/LO relocs.
+ (macro_build_lui): If place is not NULL, use the number in the
+ expression.
+ (load_address): Handle mips_big_got case.
+ (macro): Handle mips_big_got for M_LA_AB, M_JAL_A, and load and
+ store macros.
+ (OPTION_XGOT): Define.
+ (md_longopts): Add "xgot" if OBJ_ELF.
+ (md_parse_option): Handle -xgot.
+ (md_show_usage): Mention -xgot.
+ (md_apply_fix): Permit GOT/CALL_HI/LO relocs.
+ (tc_gen_reloc): Handle GOT/CALL_HI/LO relocs.
+
+Wed Feb 14 11:22:27 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * config/tc-m68k.c (m68k_ip) [operand kind '#']: When fixing
+ the byte relocation, point it to the low byte of the word.
+
+Tue Feb 13 15:31:18 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Set HDLFLAGS for *-*-hpux with --enable-shared.
+ * configure: Rebuild.
+
+Mon Feb 12 15:53:46 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * configure.in: Recognize any sparc* cpu.
+ * configure: Regenerated.
+
+Mon Feb 12 15:41:21 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.c (potable): Add "mri" and ".mri".
+ (s_mri): New function.
+ * read.h (s_mri): Declare.
+ * app.c (scrub_m68k_mri): New static variable.
+ (mri_pseudo): New static variable.
+ (do_scrub_begin): Add m68k_mri parameter. Use it rather than
+ flag_m68k_mri. Initialize scrub_m68k_mri.
+ (mri_state, mri_last_ch): New static variables.
+ (struct app_save): Add scrub_m68k_mri, mri_state, and mri_last_ch
+ fields.
+ (app_push): Save new fields.
+ (app_pop): Restore new fields.
+ (do_scrub_chars): Check scrub_m68k_mri rather than flag_mri_mri.
+ If TC_M68K, use a trivial state machine to look for occurrences of
+ the .mri pseudo-op, and change the mode appropriately.
+ * as.h (do_scrub_begin): Update prototype.
+ * input-scrub.c (input_scrub_begin): Pass flag_m68k_mri to
+ do_scrub_begin.
+ * config/tc-m68k.c (reg_prefix_optional_seen): New static
+ variable.
+ (m68k_mri_mode_change): New function.
+ (md_parse_option): Set reg_prefix_optional_seen.
+ * config/tc-m68k.h (m68k_mri_mode_change): Declare.
+ (MRI_MODE_CHANGE): Define.
+ * doc/as.texinfo: Document .mri pseudo-op.
+
+ * app.c (do_scrub_chars): In MRI mode, don't treat '#' as a
+ comment character.
+
+Mon Feb 12 15:16:29 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ Support for OBJ_ELF on m68k, mostly inside #ifdef OBJ_ELF:
+ * config/m68k-parse.h (enum pic_relocation): Define.
+ (struct m68k_exp): Add pic_reloc field.
+ * config/tc-m68k.h (TC_RELOC_RTSYM_LOC_FIXUP): Define.
+ (tc_fix_adjustable): Define to call tc_m68k_fix_adjustable.
+ (NO_RELOC): Define to BFD_RELOC_NONE if BFD_ASSEMBLER, to zero
+ otherwise.
+ * config/tc-m68k.c: Delete definition of NO_RELOC.
+ (struct m68k_it): Add pic_reloc field.
+ (add_fix): Copy over pic_reloc field.
+ (md_pseudo_table): Interpret .align parameter as byte count.
+ (mote_pseudo_table): Likewise.
+ (tc_m68k_fix_adjustable): New function.
+ (get_reloc_code): New function.
+ (md_assemble): Use it as last argument to fix_new_exp.
+ (md_apply_fix_2): For a relocation against a symbol don't put the
+ addend into the data.
+ (tc_gen_reloc): Different addend computation for OBJ_ELF.
+ (m68k_ip): Don't relax an operand that requires pic relocation.
+ (md_begin): Align .text, .data and .bss on 4 byte boundary by
+ default.
+ * write.c (fixup_segment): Don't add symbol value to addend if
+ TC_M68K and OBJ_ELF.
+ * config/m68k-parse.y (yylex): Handle @PLTPC, etc.
+ (motorola_operand): Add rule for `(zapc, EXPR)'.
+
+Mon Feb 12 10:07:33 1996 David Mosberger-Tang <davidm@azstarnet.com>
+
+ * ecoff.c (ecoff_directive_weakext): Fixed so that whitespace
+ *really* is permissible before the comma.
+
+Mon Feb 12 00:12:13 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sh.c (sh_do_align): Align to a 2 byte boundary before
+ inserting nop instructions.
+
+Fri Feb 9 10:54:19 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/te-aux.h: Change include of aux.h to aux-coff.h.
+
+Thu Feb 8 20:02:58 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-i960.c (tc_coff_symbol_emit_hook): Correct storage
+ class setting for a CALLNAME symbol in COFF.
+
+ * read.c (potable): Pass negative numbers for new .balign[wl] and
+ .p2align[wl] pseudo-ops.
+ (s_align_bytes): Treat a negative argument as specifying the fill
+ length.
+ (s_align_ptwo): Likewise.
+
+Wed Feb 7 14:12:03 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.c (potable): Add balignw, balignl, p2alignw, and p2alignl.
+ (do_align): Take new len parameter. Change all callers. Pass it
+ to md_do_align.
+ (s_align_bytes): Arg now indicates the length of the fill pattern.
+ (s_align_ptwo): Likewise.
+ * config/obj-coff.c (write_object_file): Pass length to
+ md_do_align.
+ * config/tc-i386.h (md_do_align): Take new len parameter.
+ * config/tc-m88k.h (md_do_align): Likewise.
+ * config/tc-m88k.c (m88k_do_align): Likewise.
+ * config/tc-sh.h (md_do_align): Likewise.
+ * config/tc-sh.c (sh_do_align): Likewise.
+ * doc/as.texinfo: Document new pseudo-ops.
+
+ * config/obj-coff.c (fixup_mdeps): Divide offset by fr_var, as is
+ done in cvt_frag_to_fill.
+
+ * config/tc-sh.h (sh_do_align): Declare.
+ (md_do_align): Define.
+ * config/tc-sh.c (sh_do_align): New function.
+
+ * ecoff.c (ecoff_build_lineno): Don't try to store the address
+ difference if the next address is before the current one.
+
+ * config/tc-m68k.c (struct m68k_cpu): Add alias field.
+ (archs): Initialize new field.
+ (m68k_ip): Don't list alias names when listing CPUs which support
+ an instruction.
+
+ * as.c (main): Call parse_args before read_begin.
+ * app.c (do_scrub_chars): If flag_m68k_mri, don't put a dot in
+ front of generated pseudo-ops.
+ * read.c (potable): Ignore "name".
+ (s_app_file): Permit a single quote after the string, since one
+ may appear in m68k MRI mode.
+
+ * configure.in: Check for --enable-shared. If linking against
+ shared BFD and opcodes, fix library name on SunOS, and try to set
+ -rpath reasonably.
+ * configure: Rebuild.
+
+Tue Feb 6 15:16:17 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * as.h (flag_m68k_mri): Declare.
+ * as.c (parse_args): If TC_M68K, set flag_m68k_mri for -M.
+ * Many files: For MRI syntax that is specific to the m68k MRI
+ assembler, check flag_m68k_mri rather than flag_mri or
+ MRI_MODE_NEEDS_PSEUDO_DOT.
+
+Mon Feb 5 16:29:11 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-i960.c (ARCH_HX): Define.
+ (arch_tab): Add HX.
+ (targ_has_sfr): Handle ARCH_HX.
+ (targ_has_iclass): Handle ARCH_HX.
+ (tc_coff_fix2rtype): Add return 0 to avoid warning.
+ (tc_headers_hook): If the architecture was specified explicitly,
+ use it when setting the flags. Set the extern variable coff_flags
+ rather than headers->filehdr.f_flags, since the latter is set
+ unconditionally in obj-coff.c.
+ (i960_handle_align): Remove unused variable fixp.
+
+ Support for building bfd and opcodes as shared libraries, based on
+ patches from Alan Modra <alan@spri.levels.unisa.edu.au>:
+ * configure.in: Set OPCODES and BFD to search directories.
+ Substitute OPCODES_DEP and BFDDEP. On SunOS, set HLDFLAGS.
+ * configure: Rebuild.
+ * Makefile.in (LDFLAGS, HLDFLAGS): New variables.
+ (LIBDEPS): New variable.
+ (as.new0: Depend upon $(LIBDEPS) rather than $(LIBS). Use
+ $(HLDFLAGS) in link.
+ (check): Set LD_LIBRARY_PATH in the environment.
+
+Fri Feb 2 17:41:53 1996 Michael Meissner <meissner@wogglebug.tiac.net>
+
+ * config/tc-ppc.h (ELF_TC_SPECIAL_SECTIONS): Make .sdata2, .sbss2,
+ .PPC.EMB.sdata0, and .PPC.EMB.sbss0 sections all default to
+ read-only, not read/write.
+
+Fri Feb 2 14:09:25 1996 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * Makefile.in (INSTALL_XFORM): Remove -e.
+
+Fri Feb 2 12:32:15 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * write.c (write_relocs): Use S_IS_DEFINED and S_IS_COMMON rather
+ than comparing S_GET_SEGMENT to undefined_section.
+ (write_object_file): Skip symbols which were equated to an
+ undefined or common symbol.
+ * symbols.c (resolve_symbol_value): Use S_IS_DEFINED and
+ S_IS_COMMON rather than comparing S_GET_SEGMENT to
+ undefined_section.
+ (S_GET_VALUE): Likewise. Avoid recursion problems if S_IS_DEFINED
+ or S_IS_COMMON call S_GET_VALUE.
+ * config/obj-aout.h (S_IS_COMMON): Define if not BFD_ASSEMBLER.
+ * config/obj-aout.c (obj_emit_relocations): If a reloc is equated
+ to an undefined or common symbol, convert the reloc to be against
+ the target symbol.
+ (obj_crawl_symbol_chain): Skip symbols which were equated to an
+ undefined or common symbol.
+ * config/obj-bout.h (S_IS_COMMON): Define if not BFD_ASSEMBLER.
+ * config/obj-bout.c (obj_emit_relocations): If a reloc is equated
+ to an undefined or common symbol, convert the reloc to be against
+ the target symbol.
+ (obj_crawl_symbol_chain): Skip symbols which were equated to an
+ undefined or common symbol.
+ * config/obj-coff.c (do_relocs_for): Use S_IS_DEFINED and
+ S_IS_COMMON rather than comparing S_GET_SEGMENT to
+ undefined_section.
+ (yank_symbols): Skip symbols which were equated to an undefined or
+ common symbol.
+
+Thu Feb 1 15:34:32 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-aout.h (S_IS_LOCAL): Check for \002 as well as \001.
+ * config/obj-bout.h (S_IS_LOCAL): Likewise.
+
+ * configure.in: Make sure we only add m68k-parse.o to
+ ${extra_objects} once, no matter how many m68k targets have been
+ enabled.
+ * configure: Rebuild.
+
+Wed Jan 31 18:31:46 1996 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * configure.in (i386-*-cygwin32, ppc-*-cygwin32): New.
+ * configure: Rebuild.
+
+Wed Jan 31 14:03:17 1996 Richard Henderson <rth@tamu.edu>
+
+ * config/tc-m68k.c (md_pseudo_table): Add "extend" and "ldouble".
+ * doc/c-m68k.texi: Document .extend and .ldouble.
+
+ * configure.in (m68*-apple-aux*): New target.
+ * config/te-aux.h: New file.
+ * config/obj-coff.c (compare_external_relocs): New static function
+ if TE_AUX.
+ (do_relocs_for): Sort relocs if TE_AUX.
+ (fixup_segment): If TE_AUX, store common symbol value in segment.
+ * config/tc-m68k.h (TARGET_FORMAT): Define if TE_AUX.
+
+Wed Jan 31 12:24:58 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.h (S_IS_LOCAL): Check for \002 as well as \001.
+
+ * config/tc-mips.c (s_mips_globl): Set BSF_OBJECT if it is not
+ BSF_FUNCTION.
+ (s_cpload): Set BSF_OBJECT for _gp_disp symbol.
+ * read.c (s_lcomm): If S_SET_SIZE is defined, set the size of the
+ symbol.
+ * ecoff.c (add_procedure): Set the BSF_FUNCTION flag.
+ (ecoff_build_symbols): If S_SET_SIZE is defined, set the size of
+ an undefined symbol and the size of a function symbol.
+ * config/obj-elf.c (elf_frob_symbol): If TC_MIPS, set BSF_OBJECT
+ for all common symbols.
+
+Tue Jan 30 12:35:24 1996 Ken Raeburn <raeburn@cygnus.com>
+
+ * config/tc-i960.c (parse_memop): In MRI mode, don't use implicit
+ scaling of index.
+
+ * expr.c (operand): Accept 0x hex constants in MRI mode if not on
+ m68k.
+
+Mon Jan 29 12:21:30 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-elf.c (obj_elf_type): Set BSF_OBJECT flag for a type
+ of object. From Ronald F. Guilmette <rfg@monkeys.com>.
+
+ * ecoff.c (localsym_t): Add addend field.
+ (add_ecoff_symbol): Add addend argument. Change all callers.
+ (coff_sym_value): Make static.
+ (coff_sym_addend): New static variable.
+ (ecoff_directive_def): Initialize coff_sym_addend.
+ (ecoff_directive_val): Accept symbol + constant.
+ (ecoff_directive_endef): Pass coff_sym_addend to add_ecoff_symbol.
+ (ecoff_build_symbols): Include the addend in the symbol value.
+
+Fri Jan 26 19:28:52 1996 Kim Knuttila <krk@cygnus.com>
+
+ * config/tc-ppc.c (md_assemble): Ignore overflow on
+ BFD_RELOC_16_GOTOFF and BFD_RELOC_PPC_TOC16.
+
+Fri Jan 26 16:14:17 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (md_apply_fix3): SDA21 relocations are now 4
+ bytes in size, so offset appropriately in big endian mode when
+ writing the bottom 2 bytes.
+
+Thu Jan 25 20:26:23 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * config/tc-sparc.c (default_compatible): New static local.
+ (md_begin): Initialize it. Rewrite warn_on_bump handling.
+ (sparc_ip): If no architecture or -bump specified, don't mark as
+ mismatched those in default_compatible.
+
+Thu Jan 25 12:21:53 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ SCO ELF support from Robert Lipe <robertl@arnet.com>:
+ * configure.in (i386-*-sco*elf*): Use fmt elf, targ sco5.
+ * configure: Rebuild.
+ * config/sco5.mt: New file; set TDEFINES to -DSCO_ELF.
+ * config/tc-i386.c (sco_id): New function, if SCO_ELF.
+ * config/tc-i386.h (tc_init_after_args): Define if SCO_ELF.
+ (sco_id): Declare if SCO_ELF.
+
+Thu Jan 25 03:10:53 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * config/tc-sparc.c (initial_architecture,can_bump_v9_p): Deleted.
+ ({max,warn_after}_architecture): New static locals.
+ (md_begin): Replace NUMOPCODES with sparc_num_opcodes.
+ If both architecture and -bump requested, set max_architecture to max.
+ (sparc_md_end): Simplify.
+ (sparc_ip): Replace references to can_bump_v9_p with max_architecture.
+ Rewrite code to bump architecture and check for conflicts.
+ (md_longopts): Recognize -xarch={v8plus,v8plusa} for compatibility
+ with Solaris assembler.
+ (md_parse_option): Likewise. Call sparc_opcode_lookup_arch.
+ (md_show_usage): Update.
+
+Wed Jan 24 22:11:03 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * Makefile.in (RUNTEST): Fix reference to $${srcdir}.
+
+Mon Jan 22 09:21:36 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * config/tc-sparc.h (TARGET_FORMAT): Use #ifdef SPARC_ARCH64 instead of
+ #ifdef sparcv9 when choosing value.
+ (ENV64): Delete.
+ (md_end): Define.
+ (sparc_md_end): Declare.
+ * config/tc-sparc.c (SPARC_V9): Renamed from sparcv9.
+ (initial_architecture): New static local.
+ (can_bump_v9_p): Likewise.
+ (NO_V9): Delete all occurrences.
+ (sparc_md_end): New function.
+ (sparc_ip): New local v9_arg_p. Rework fp reg number test.
+ Don't bump architecture to v9 unless can_bump_v9_p set.
+ (md_parse_option): -A<arch> passed, set can_bump_v9_p accordingly.
+ * configure.in (sparc64 target cpu): Don't set obj_format here.
+ (SPARC_V9): Renamed from sparcv9.
+ (sparc64-*-elf*): Define SPARC_ARCH64.
+ * configure: Regenerated.
+ * acconfig.h (SPARC_V9): Renamed from sparcv9.
+ (SPARC_ARCH64): Add.
+ * conf.in: Regenerated.
+ * config/vmsconf.h: Update.
+
+Mon Jan 22 17:24:47 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * config/tc-mips.c (load_register): Optimise "dli" loads.
+ (md_show_usage): add "-mcpu=vr4100" to help text.
+
+Mon Jan 22 11:53:00 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * symbols.c (resolve_symbol_value): If a symbol is equated to an
+ undefined symbol, preserve the X_op of O_symbol.
+ (S_GET_VALUE): Fix check to permit this case.
+ * write.c (write_relocs): If a reloc is against an undefined
+ symbol equated to another symbol, change the reloc to be against
+ the latter symbol.
+ * config/obj-coff.c (do_relocs_for): Likewise.
+
+ * config/tc-ppc.c (ppc_csect): An unnamed csect is storage class
+ XMC_PR.
+
+Mon Jan 22 10:59:48 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/obj-elf.c (elf/ppc.h): Include elf/ppc.h if target
+ computer is PowerPC.
+
+ * config/tc-ppc.c (md_apply_fix3): Add more embedded relocations.
+
+ * config/tc-ppc.h (ELF_TC_SPECIAL_SECTIONS): Add sections
+ mentioned in the eabi.
+
+Thu Jan 18 17:58:19 1996 Kim Knuttila <krk@cygnus.com>
+
+ * config/tc-ppc.c (ppc_reldata): Changed alignement on reldata_section
+ * config/tc-ppc.c (ppc_pdata): Changed the alignment on pdata_section
+
+Mon Jan 15 17:43:42 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (mapping): Add more relocation suffixes.
+
+Sun Jan 14 21:29:36 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (ppc_elf_validate_fix): Allow .gcc_except_table
+ as a section it is ok to have unadorned -mrelocatable pointers in.
+
+Sat Jan 13 11:09:08 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (ppc_section*): Wrap these functions inside
+ #ifdef OBJ_ELF.
+
+Fri Jan 12 15:32:07 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/obj-elf.c (obj_elf_section): Add hooks so machine
+ dependent section attributes can be handled.
+
+ * config/tc-ppc.h: (md_elf_section_{letter,type,word,flags}): New
+ macros to add support for exclude section flag and ordered section
+ type.
+
+ * config/tc-ppc.c (ppc_elf_section_{letter,type,word,flags}): New
+ functions to add support for exclude section flag and ordered
+ section type.
+
+Fri Jan 12 12:04:00 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * subsegs.c (section_symbol): Don't try to look up the section
+ symbol in the hash table. It should be possible to have a symbol
+ with the same name as a section, but no connection to it.
+
+ * read.c (cons_worker): Only call mri_comment_end from flag_mri.
+ From James Carlson <carlson@xylogics.com>.
+
+ * expr.c (operand): Skip whitespace after a close parenthesis.
+ From James Carlson <carlson@xylogics.com>.
+
+Tue Jan 2 12:43:23 1996 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * config/tc-sh.c (md_apply_fix): Call as_bad_where instead of
+ as_warn_where for relocation overflow.
+ (parse_reg): Accept register name only if next character is
+ not alphanumeric.
+
+For older changes see ChangeLog-9295
diff --git a/gas/Makefile.am b/gas/Makefile.am
new file mode 100644
index 0000000000..688f21ccc6
--- /dev/null
+++ b/gas/Makefile.am
@@ -0,0 +1,1695 @@
+## Process this file with automake to generate Makefile.in
+
+## Work around apparent automake bug.
+INTLLIBS = @INTLLIBS@
+
+AUTOMAKE_OPTIONS = cygnus dejagnu
+
+SUBDIRS = doc po
+
+tooldir = $(exec_prefix)/$(target_alias)
+
+YACC = `if [ -f ../bison/bison ] ; then echo ../bison/bison -y -L../bison/bison ; else echo bison -y ; fi`
+LEX = `if [ -f ../flex/flex ] ; then echo ../flex/flex ; else echo flex ; fi`
+
+DEP = $(srcdir)/../mkdep
+
+TARG_CPU = @target_cpu_type@
+TARG_CPU_C = $(srcdir)/config/tc-@target_cpu_type@.c
+TARG_CPU_O = tc-@target_cpu_type@.o
+TARG_CPU_H = $(srcdir)/config/tc-@target_cpu_type@.h
+OBJ_FORMAT_C = $(srcdir)/config/obj-@obj_format@.c
+OBJ_FORMAT_O = obj-@obj_format@.o
+OBJ_FORMAT_H = $(srcdir)/config/obj-@obj_format@.h
+TARG_ENV_H = $(srcdir)/config/te-@te_file@.h
+ATOF_TARG_C = $(srcdir)/config/atof-@atof@.c
+ATOF_TARG_O = atof-@atof@.o
+
+# use @target_cpu_type@ for refering to configured target name
+IT_HDRS=itbl-parse.h $(srcdir)/itbl-ops.h
+IT_SRCS=itbl-parse.c itbl-lex.c $(srcdir)/itbl-ops.c
+IT_DEPS=$(srcdir)/itbl-parse.y $(srcdir)/itbl-lex.l $(srcdir)/config/itbl-@target_cpu_type@.h
+IT_OBJS=itbl-parse.o itbl-lex.o itbl-ops.o
+
+# CPU types. This is only used for dependency information.
+
+CPU_TYPES = \
+ a29k \
+ alpha \
+ arc \
+ arm \
+ d10v \
+ d30v \
+ fr30 \
+ h8300 \
+ h8500 \
+ hppa \
+ i386 \
+ i860 \
+ i960 \
+ m32r \
+ m68k \
+ m88k \
+ mcore \
+ mips \
+ mn10200 \
+ mn10300 \
+ ns32k \
+ ppc \
+ sh \
+ sparc \
+ tahoe \
+ tic30 \
+ tic80 \
+ vax \
+ w65 \
+ v850 \
+ z8k
+
+# Object format types. This is only used for dependency information.
+# We deliberately omit som, since it does not work as a cross assembler.
+
+OBJ_FORMATS = \
+ aout \
+ bout \
+ coff \
+ ecoff \
+ elf \
+ evax \
+ hp300 \
+ ieee \
+ vms
+
+# This is an sh case which sets valid according to whether the CPU
+# type in the shell variable c and the OS type in the shell variable o
+# are supported. This helps cuts down on the amount of dependency
+# information.
+
+CPU_OBJ_VALID = \
+ valid= ; \
+ case $$o in \
+ aout) \
+ case $$c in \
+ a29k | arm | i386 | i860 | m68k | mips | ns32k | sparc | tahoe | tic30 | vax) \
+ valid=yes ;; \
+ esac ;; \
+ bout) \
+ case $$c in \
+ i960) valid=yes ;; \
+ esac ;; \
+ coff) valid=yes ;; \
+ ecoff) \
+ case $$c in \
+ mips | alpha) valid=yes ;; \
+ esac ;; \
+ elf) valid=yes ;; \
+ evax) \
+ case $$c in \
+ alpha) valid=yes ;; \
+ esac ;; \
+ hp300) \
+ case $$c in \
+ m68k) valid=yes ;; \
+ esac ;; \
+ vms) \
+ case $$c in \
+ vax) valid=yes ;; \
+ esac ;; \
+ esac;
+
+# This is like CPU_OBJ_VALID, for the obj=multi case.
+
+CPU_MULTI_VALID = \
+ valid= ; \
+ case $$c in \
+ i386 | mips) valid=yes ;; \
+ esac;
+
+# Regular source files.
+
+GAS_CFILES = \
+ app.c \
+ as.c \
+ atof-generic.c \
+ bignum-copy.c \
+ cond.c \
+ depend.c \
+ ecoff.c \
+ ehopt.c \
+ expr.c \
+ flonum-copy.c \
+ flonum-konst.c \
+ flonum-mult.c \
+ frags.c \
+ hash.c \
+ input-file.c \
+ input-scrub.c \
+ listing.c \
+ literal.c \
+ macro.c \
+ messages.c \
+ output-file.c \
+ read.c \
+ sb.c \
+ stabs.c \
+ subsegs.c \
+ symbols.c \
+ write.c
+
+CFILES = $(GAS_CFILES) gasp.c itbl-ops.c
+
+HFILES = \
+ as.h \
+ asintl.h \
+ bignum.h \
+ bit_fix.h \
+ cgen.h \
+ ecoff.h \
+ emul-target.h \
+ emul.h \
+ expr.h \
+ flonum.h \
+ frags.h \
+ hash.h \
+ input-file.h \
+ itbl-ops.h \
+ listing.h \
+ macro.h \
+ obj.h \
+ output-file.h \
+ read.h \
+ sb.h \
+ struc-symbol.h \
+ subsegs.h \
+ symbols.h \
+ tc.h \
+ write.h
+
+# CPU files in config.
+
+TARGET_CPU_CFILES = \
+ config/tc-a29k.c \
+ config/tc-alpha.c \
+ config/tc-arc.c \
+ config/tc-arm.c \
+ config/tc-d10v.c \
+ config/tc-d30v.c \
+ config/tc-h8300.c \
+ config/tc-h8500.c \
+ config/tc-hppa.c \
+ config/tc-i386.c \
+ config/tc-i860.c \
+ config/tc-i960.c \
+ config/tc-m32r.c \
+ config/tc-m68k.c \
+ config/tc-m88k.c \
+ config/tc-mcore.c \
+ config/tc-mips.c \
+ config/tc-mn10200.c \
+ config/tc-mn10300.c \
+ config/tc-ns32k.c \
+ config/tc-ppc.c \
+ config/tc-sh.c \
+ config/tc-sparc.c \
+ config/tc-tahoe.c \
+ config/tc-tic30.c \
+ config/tc-tic80.c \
+ config/tc-vax.c \
+ config/tc-w65.c \
+ config/tc-v850.c \
+ config/tc-z8k.c
+
+TARGET_CPU_HFILES = \
+ config/tc-a29k.h \
+ config/tc-alpha.h \
+ config/tc-arc.h \
+ config/tc-arm.h \
+ config/tc-d10v.h \
+ config/tc-d30v.h \
+ config/tc-h8300.h \
+ config/tc-h8500.h \
+ config/tc-hppa.h \
+ config/tc-i386.h \
+ config/tc-i860.h \
+ config/tc-i960.h \
+ config/tc-m32r.h \
+ config/tc-m68k.h \
+ config/tc-m88k.h \
+ config/tc-mcore.h \
+ config/tc-mips.h \
+ config/tc-mn10200.h \
+ config/tc-mn10300.h \
+ config/tc-ns32k.h \
+ config/tc-ppc.h \
+ config/tc-sh.h \
+ config/tc-sparc.h \
+ config/tc-tahoe.h \
+ config/tc-tic30.h \
+ config/tc-tic80.h \
+ config/tc-vax.h \
+ config/tc-w65.h \
+ config/tc-v850.h \
+ config/tc-z8k.h
+
+# OBJ files in config
+
+OBJ_FORMAT_CFILES = \
+ config/obj-aout.c \
+ config/obj-bout.c \
+ config/obj-coff.c \
+ config/obj-ecoff.c \
+ config/obj-elf.c \
+ config/obj-evax.c \
+ config/obj-hp300.c \
+ config/obj-ieee.c \
+ config/obj-som.c \
+ config/obj-vms.c
+
+OBJ_FORMAT_HFILES = \
+ config/obj-aout.h \
+ config/obj-bout.h \
+ config/obj-coff.h \
+ config/obj-ecoff.h \
+ config/obj-elf.h \
+ config/obj-evax.h \
+ config/obj-hp300.h \
+ config/obj-ieee.h \
+ config/obj-som.h \
+ config/obj-vms.h
+
+# Emulation header files in config
+
+TARG_ENV_HFILES = \
+ config/te-386bsd.h \
+ config/te-aux.h \
+ config/te-delta.h \
+ config/te-delt88.h \
+ config/te-dpx2.h \
+ config/te-dynix.h \
+ config/te-generic.h \
+ config/te-go32.h \
+ config/te-hp300.h \
+ config/te-hppa.h \
+ config/te-i386aix.h \
+ config/te-ic960.h \
+ config/te-linux.h \
+ config/te-lnews.h \
+ config/te-lynx.h \
+ config/te-mach.h \
+ config/te-macos.h \
+ config/te-multi.h \
+ config/te-nbsd.h \
+ config/te-nbsd532.h \
+ config/te-pc532mach.h \
+ config/te-pe.h \
+ config/te-ppcnw.h \
+ config/te-psos.h \
+ config/te-riscix.h \
+ config/te-sparcaout.h \
+ config/te-sun3.h \
+ config/te-svr4.h \
+ config/te-sysv32.h
+
+# Multi files in config
+
+MULTI_CFILES = \
+ config/e-i386coff.c \
+ config/e-i386elf.c \
+ config/e-mipsecoff.c \
+ config/e-mipself.c
+
+CONFIG_OBJS = \
+ $(TARG_CPU_O) \
+ $(OBJ_FORMAT_O) \
+ $(ATOF_TARG_O) \
+ $(extra_objects)
+
+GENERIC_OBJS = \
+ app.o \
+ as.o \
+ atof-generic.o \
+ bignum-copy.o \
+ cond.o \
+ depend.o \
+ ehopt.o \
+ expr.o \
+ flonum-konst.o \
+ flonum-copy.o \
+ flonum-mult.o \
+ frags.o \
+ hash.o \
+ input-file.o \
+ input-scrub.o \
+ literal.o \
+ messages.o \
+ output-file.o \
+ read.o \
+ subsegs.o \
+ symbols.o \
+ write.o \
+ listing.o \
+ ecoff.o \
+ stabs.o \
+ sb.o \
+ macro.o
+
+OBJS = $(CONFIG_OBJS) $(GENERIC_OBJS)
+
+POTFILES = $(MULTI_CFILES) $(TARGET_ENV_HFILES) $(OBJ_FORMAT_HFILES) \
+ $(OBJ_FORMAT_CFILES) $(TARGET_CPU_HFILES) $(TARGET_CPU_CFILES) \
+ $(HFILES) $(CFILES) $(GAS_CFILES)
+po/POTFILES.in: @MAINT@ Makefile
+ for file in $(POTFILES); do echo $$file; done | sort > tmp \
+ && mv tmp $(srcdir)/po/POTFILES.in
+
+noinst_PROGRAMS = as-new gasp-new
+noinst_SCRIPTS = .gdbinit
+
+$(srcdir)/make-gas.com: stamp-mk.com
+stamp-mk.com: vmsconf.sh Makefile
+ sh $(srcdir)/vmsconf.sh $(GENERIC_OBJS) > new-make.com
+ $(SHELL) $(srcdir)/../move-if-change new-make.com $(srcdir)/make-gas.com
+ touch stamp-mk.com
+
+EXTRA_DIST = make-gas.com
+
+DISTSTUFF = make-gas.com m68k-parse.c itbl-parse.c itbl-parse.h itbl-lex.c
+diststuff: $(DISTSTUFF) info
+
+DISTCLEANFILES = targ-cpu.h obj-format.h targ-env.h itbl-cpu.h cgen-desc.h
+
+# Now figure out from those variables how to compile and link.
+
+BASEDIR = $(srcdir)/..
+BFDDIR = $(BASEDIR)/bfd
+INCDIR = $(BASEDIR)/include
+
+# This is the variable actually used when we compile.
+# Specify the directories to be searched for header files.
+# Both . and srcdir are used, in that order,
+# so that tm.h and config.h will be found in the compilation
+# subdirectory rather than in the source directory.
+INCLUDES = -D_GNU_SOURCE -I. -I$(srcdir) -I../bfd -I$(srcdir)/config -I$(INCDIR) -I$(srcdir)/.. -I$(BFDDIR) -I$(srcdir)/../intl -I../intl -DLOCALEDIR="\"$(prefix)/share/locale\""
+
+# This should be parallel to INCLUDES, but should replace $(srcdir)
+# with $${srcdir}, and should work in a subdirectory. This is used
+# when building dependencies, because the dependency building is done
+# in a subdirectory.
+DEP_INCLUDES = -D_GNU_SOURCE -I.. -I$${srcdir} -I../../bfd -I$${srcdir}/config -I$${srcdir}/../include -I$${srcdir}/.. -I$${srcdir}/../bfd -I$${srcdir}/../intl -I../../intl -DLOCALEDIR="\"$(prefix)/share/locale\""
+
+# How to link with both our special library facilities
+# and the system's installed libraries.
+
+GASLIBS = @OPCODES_LIB@ @BFDLIB@ ../libiberty/libiberty.a
+
+# Files to be copied away after each stage in building.
+STAGESTUFF = *.o $(noinst_PROGRAMS)
+
+$(OBJS): @ALL_OBJ_DEPS@
+
+as_new_SOURCES = $(GAS_CFILES)
+as_new_LDADD = $(TARG_CPU_O) $(OBJ_FORMAT_O) $(ATOF_TARG_O) \
+ $(extra_objects) $(GASLIBS) $(INTLLIBS)
+as_new_DEPENDENCIES = $(TARG_CPU_O) $(OBJ_FORMAT_O) $(ATOF_TARG_O) \
+ $(extra_objects) $(GASLIBS) $(INTLDEPS)
+
+# Stuff that every object file depends upon. If anything is removed
+# from this list, remove it from dep-in.sed as well.
+$(OBJS): config.h as.h $(TARG_ENV_H) $(OBJ_FORMAT_H) $(TARG_CPU_H) flonum.h \
+ expr.h struc-symbol.h write.h frags.h hash.h read.h symbols.h tc.h \
+ obj.h listing.h bignum.h bit_fix.h $(INCDIR)/libiberty.h asintl.h
+
+gasp_new_SOURCES = gasp.c macro.c sb.c hash.c
+gasp_new_LDADD = ../libiberty/libiberty.a $(INTLLIBS)
+gasp_new_DEPENDENCIES = ../libiberty/libiberty.a $(INTLDEPS)
+
+EXPECT = `if [ -f $${rootme}/../expect/expect ] ; then \
+ echo $${rootme}/../expect/expect ; \
+ else echo expect ; fi`
+
+RUNTEST = `if [ -f $${srcdir}/../dejagnu/runtest ] ; then \
+ echo $${srcdir}/../dejagnu/runtest ; else echo runtest; \
+ fi`
+RUNTESTFLAGS=
+
+check-DEJAGNU: site.exp
+ if [ -d testsuite ]; then \
+ true; \
+ else \
+ mkdir testsuite; \
+ fi
+ rm -f testsuite/site.exp
+ cp site.exp testsuite/site.exp
+ rootme=`pwd`; export rootme; \
+ srcdir=`cd ${srcdir}; pwd` ; export srcdir ; \
+ EXPECT=${EXPECT} ; export EXPECT ; \
+ if [ -f $(top_builddir)/../expect/expect ]; then \
+ TCL_LIBRARY=`cd $(top_srcdir)/../tcl/library && pwd`; \
+ export TCL_LIBRARY; \
+ fi; \
+ runtest=$(RUNTEST); \
+ cd testsuite; \
+ if $(SHELL) -c "$$runtest --version" > /dev/null 2>&1; then \
+ $$runtest --tool $(DEJATOOL) --srcdir $${srcdir}/testsuite \
+ $(RUNTESTFLAGS); \
+ else echo "WARNING: could not find \`runtest'" 1>&2; :;\
+ fi
+
+# The implicit .c.o rule doesn't work for these, perhaps because of
+# the variables, or perhaps because the sources are not on vpath.
+$(TARG_CPU_O): $(TARG_CPU_C) $(TARG_CPU_DEP_@target_cpu_type@)
+ $(COMPILE) -c $(TARG_CPU_C)
+$(ATOF_TARG_O): $(ATOF_TARG_C)
+ $(COMPILE) -c $(ATOF_TARG_C)
+
+# ecoff.c only has full dependencies when ECOFF_DEBUGGING is defined,
+# so the automatic dependency stuff doesn't work.
+ecoff.o : ecoff.c ecoff.h $(INCDIR)/coff/internal.h $(INCDIR)/coff/sym.h \
+ $(INCDIR)/coff/ecoff.h $(INCDIR)/coff/symconst.h \
+ $(INCDIR)/aout/stab_gnu.h
+
+# We need all these explicit rules for the multi stuff. Because of
+# these rules, we don't need one for OBJ_FORMAT_O.
+
+obj-aout.o : $(srcdir)/config/obj-aout.c
+ $(COMPILE) -c $(srcdir)/config/obj-aout.c
+obj-bout.o : $(srcdir)/config/obj-bout.c
+ $(COMPILE) -c $(srcdir)/config/obj-bout.c
+obj-coff.o: $(srcdir)/config/obj-coff.c
+ $(COMPILE) -c $(srcdir)/config/obj-coff.c
+obj-ecoff.o : $(srcdir)/config/obj-ecoff.c
+ $(COMPILE) -c $(srcdir)/config/obj-ecoff.c
+obj-elf.o : $(srcdir)/config/obj-elf.c
+ $(COMPILE) -c $(srcdir)/config/obj-elf.c
+obj-evax.o : $(srcdir)/config/obj-evax.c
+ $(COMPILE) -c $(srcdir)/config/obj-evax.c
+obj-hp300.o : $(srcdir)/config/obj-hp300.c
+ $(COMPILE) -c $(srcdir)/config/obj-hp300.c
+obj-ieee.o : $(srcdir)/config/obj-ieee.c
+ $(COMPILE) -c $(srcdir)/config/obj-ieee.c
+obj-multi.o : $(srcdir)/config/obj-multi.c
+ $(COMPILE) -c $(srcdir)/config/obj-multi.c
+obj-som.o : $(srcdir)/config/obj-som.c
+ $(COMPILE) -c $(srcdir)/config/obj-som.c
+obj-vms.o : $(srcdir)/config/obj-vms.c
+ $(COMPILE) -c $(srcdir)/config/obj-vms.c
+
+e-mipself.o : $(srcdir)/config/e-mipself.c
+ $(COMPILE) -c $(srcdir)/config/e-mipself.c
+e-mipsecoff.o : $(srcdir)/config/e-mipsecoff.c
+ $(COMPILE) -c $(srcdir)/config/e-mipsecoff.c
+e-i386coff.o: $(srcdir)/config/e-i386coff.c
+ $(COMPILE) -c $(srcdir)/config/e-i386coff.c
+e-i386elf.o: $(srcdir)/config/e-i386elf.c
+ $(COMPILE) -c $(srcdir)/config/e-i386elf.c
+
+# The m68k operand parser.
+
+EXTRA_as_new_SOURCES = config/m68k-parse.y
+
+# If m68k-parse.y is in a different directory, then ylwrap will use an
+# absolute path when it invokes yacc, which will cause yacc to put the
+# absolute path into the generated file. That's a pain when it comes
+# to generating snapshots, because it introduces spurious diffs.
+# Since when we make the snapshots $(srcdir) = ".", we check for that
+# case and handle it differently. This means that anybody who
+# configures with $(srcdir) = "." will have to set their path in the
+# debugger if they want to debug m68k-parse.y. This is bad, but on
+# the other hand it's good that people who use the prebuilt
+# m68k-parse.c don't get a spurious absolute path.
+m68k-parse.c: $(srcdir)/config/m68k-parse.y
+ f=$(srcdir)/config/m68k-parse.y; \
+ if [ $$f = "./config/m68k-parse.y" ]; then \
+ ln -s config/m68k-parse.y . > /dev/null 2>/dev/null || \
+ ln config/m68k-parse.y . > /dev/null 2>/dev/null || \
+ cp config/m68k-parse.y . >/dev/null 2>/dev/null; \
+ f=m68k-parse.y; \
+ else true; fi; \
+ $(SHELL) $(YLWRAP) "$(YACC)" $$f y.tab.c m68k-parse.c --; \
+ if [ $$f = "m68k-parse.y" ]; then \
+ rm -f m68k-parse.y; \
+ else true; fi
+m68k-parse.o: m68k-parse.c $(srcdir)/config/m68k-parse.h
+
+# Don't let the .y.h rule clobber m68k-parse.h.
+m68k-parse.h: ; @true
+$(srcdir)/config/m68k-parse.h: ; @true
+
+# The instruction table specification lexical analyzer and parser.
+
+itbl-lex.c: $(srcdir)/itbl-lex.l
+itbl-lex.o: itbl-lex.c itbl-parse.h
+
+itbl-parse.o: itbl-parse.c itbl-parse.h $(srcdir)/itbl-ops.h
+
+itbl-ops.o: $(srcdir)/itbl-ops.c $(srcdir)/itbl-ops.h itbl-parse.h
+
+itbl-parse.c itbl-parse.h: $(srcdir)/itbl-parse.y
+ $(SHELL) $(YLWRAP) "$(YACC)" $(srcdir)/itbl-parse.y y.tab.c itbl-parse.c y.tab.h itbl-parse.h -- -d
+
+# stand-alone itbl assembler & disassembler
+
+EXTRA_PROGRAMS = itbl-test
+itbl_test_SOURCES = itbl-parse.y itbl-lex.l
+itbl_test_LDADD = itbl-test-ops.o itbl-test.o $(GASLIBS) @LEXLIB@
+
+itbl-test-ops.o: $(srcdir)/itbl-ops.c $(srcdir)/itbl-ops.h itbl-parse.h
+ $(COMPILE) -o itbl-test-ops.o -DSTAND_ALONE -c $(srcdir)/itbl-ops.c
+
+itbl-test.o: $(srcdir)/testsuite/gas/all/itbl-test.c $(srcdir)/itbl-ops.h
+ $(COMPILE) -c -DSTAND_ALONE $(srcdir)/testsuite/gas/all/itbl-test.c
+
+# CGEN interface.
+
+CGEN_CPU_PREFIX = @cgen_cpu_prefix@
+
+cgen.o: cgen.c cgen.h cgen-desc.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/cgen.h \
+ $(srcdir)/../opcodes/$(CGEN_CPU_PREFIX)-desc.h \
+ $(srcdir)/../opcodes/$(CGEN_CPU_PREFIX)-opc.h
+
+# Remake the info files.
+
+MOSTLYCLEANFILES = $(STAGESTUFF) core stamp-mk.com \
+ testsuite/*.o testsuite/*.out testsuite/gas.log testsuite/gas.sum \
+ testsuite/site.exp site.bak site.exp stage stage1 stage2
+
+CLEANFILES = dep.sed .tcdep .objdep .dep2 .dep1 .depa .dep .depdir
+
+.PHONY: install-exec-local install-data-local
+.PHONY: install-exec-bindir install-exec-tooldir
+
+install-exec-local: install-exec-bindir @install_tooldir@
+
+install-exec-bindir: $(noinst_PROGRAMS)
+ $(mkinstalldirs) $(bindir)
+ @list='$(noinst_PROGRAMS)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(bindir)/`echo $$p|sed -e 's/$(EXEEXT)$$//' -e 's/-new//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+ $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(bindir)/`echo $$p|sed -e 's/$(EXEEXT)$$//' -e 's/-new//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ else :; fi; \
+ done
+
+install-exec-tooldir: $(noinst_PROGRAMS)
+ $(mkinstalldirs) $(tooldir)/bin
+ n=`echo as | sed '$(transform)'`; \
+ if [ "$(bindir)/$$n$(EXEEXT)" != "$(tooldir)/bin/as$(EXEEXT)" ]; then \
+ rm -f $(tooldir)/bin/as$(EXEEXT); \
+ ln $(bindir)/$$n$(EXEEXT) $(tooldir)/bin/as$(EXEEXT) >/dev/null 2>/dev/null \
+ || $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) as-new$(EXEEXT) $(tooldir)/bin/as$(EXEEXT); \
+ else \
+ true ; \
+ fi
+
+# These exist for maintenance purposes.
+
+.PHONY: bootstrap bootstrap2 bootstrap3 stage1 stage2 stage3 comparison
+
+bootstrap: as-new
+ $(MAKE) stage1
+ rm -f stage && ln -s stage1 stage
+ $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage/ $(CFLAGS)" libdir=$(libdir) ALLOCA= $(noinst_PROGRAMS)
+ $(MAKE) stage2
+ rm -f stage && ln -s stage2 stage
+ $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage/ $(CFLAGS)" libdir=$(libdir) ALLOCA= $(noinst_PROGRAMS)
+ $(MAKE) comparison against=stage2
+
+bootstrap2:
+ rm -f stage && ln -s stage1 stage
+ $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage/ $(CFLAGS)" libdir=$(libdir) ALLOCA= $(noinst_PROGRAMS)
+ $(MAKE) stage2
+ rm -f stage && ln -s stage2 stage
+ $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage/ $(CFLAGS)" libdir=$(libdir) ALLOCA= $(noinst_PROGRAMS)
+ $(MAKE) comparison against=stage2
+
+bootstrap3:
+ rm -f stage && ln -s stage2 stage
+ $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage/ $(CFLAGS)" libdir=$(libdir) ALLOCA= $(noinst_PROGRAMS)
+ $(MAKE) comparison against=stage2
+
+# Copy the object files from a particular stage into a subdirectory.
+stage1:
+ -mkdir stage1
+ -mv $(STAGESTUFF) stage1
+ if [ -f stage1/as-new$(EXEEXT) -a ! -f stage1/as$(EXEEXT) ] ; then (cd stage1 ; ln -s as-new$(EXEEXT) as$(EXEEXT)) ; fi
+
+stage2:
+ -mkdir stage2
+ -mv $(STAGESTUFF) stage2
+ if [ -f stage2/as-new$(EXEEXT) -a ! -f stage2/as$(EXEEXT) ] ; then (cd stage2 ; ln -s as-new$(EXEEXT) as$(EXEEXT)) ; fi
+
+stage3:
+ -mkdir stage3
+ -mv $(STAGESTUFF) stage3
+ if [ -f stage3/as-new$(EXEEXT) -a ! -f stage3/as$(EXEEXT) ] ; then (cd stage3 ; ln -s as-new as$(EXEEXT)) ; fi
+
+against=stage2
+
+# This rule is derived from corresponding code in the Makefile.in for gcc.
+# The "tail +16c" is to bypass headers which may include timestamps or
+# temporary assembly file names.
+comparison:
+ x=0 ; \
+ for file in *.o ; do \
+ tail +16c ./$$file > tmp-foo1; \
+ if tail +16c ${against}/$$file > tmp-foo2 2>/dev/null ; then \
+ if cmp tmp-foo1 tmp-foo2 ; then \
+ true ; \
+ else \
+ echo $$file differs ; \
+ x=1 ; \
+ fi ; \
+ else true; fi ; \
+ done ; \
+ exit $$x
+ -rm -f tmp-foo*
+
+.PHONY: de-stage1 de-stage2 de-stage3
+
+de-stage1:
+ - (cd stage1 ; rm -f as$(EXEEXT) ; mv -f * ..)
+ - rmdir stage1
+
+de-stage2:
+ - (cd stage2 ; rm -f as$(EXEEXT) ; mv -f * ..)
+ - rmdir stage2
+
+de-stage3:
+ - (cd stage3 ; rm -f as$(EXEEXT) ; mv -f * ..)
+ - rmdir stage3
+
+# Automatic dependency computation. This is a real pain, because the
+# dependencies change based on target_cpu_type and obj_format. We
+# currently ignore any dependencies caused by emulation files.
+
+DEP_FILE_DEPS = $(CFILES) $(HFILES) $(TARGET_CPU_CFILES) \
+ $(TARGET_CPU_HFILES) $(OBJ_FORMAT_CFILES) $(OBJ_FORMAT_HFILES)
+
+.dep: dep.sed $(DEP_FILE_DEPS) .tcdep .objdep .dep2
+ rm -f .dep1
+ srcdir=`cd $(srcdir); pwd`; \
+ $(MAKE) DEP=$(DEP) srcdir=$${srcdir} VPATH=$${srcdir} .dep1
+ rm -rf .depdir
+ sed -f dep.sed < .dep1 > .depa
+ sed -f dep.sed < .tcdep >> .depa
+ sed -f dep.sed < .objdep >> .depa
+ sed -f dep.sed < .dep2 >> .depa
+ echo '$$(OBJS): $$(DEP_@target''_cpu_type@_@obj''_format@)' >> .depa
+ echo '$$(TARG_CPU_O): $$(TCDEP_@target''_cpu_type@_@obj''_format@)' >> .depa
+ echo '$$(OBJ_FORMAT_O): $$(OBJDEP_@target''_cpu_type@_@obj''_format@)' >> .depa
+ echo '# IF YOU PUT ANYTHING HERE IT WILL GO AWAY' >> .depa
+ $(SHELL) $(srcdir)/../move-if-change .depa .dep
+
+# This rule needs a mkdep that runs "gcc -MM".
+.dep1: $(CFILES) $(MULTI_CFILES)
+ if [ -d .depdir ]; then true; else mkdir .depdir; fi
+ srcdir=`cd $(srcdir); pwd`; \
+ cd .depdir; \
+ echo '' > targ-cpu.h; \
+ echo '' > obj-format.h; \
+ echo '' > targ-env.h; \
+ echo '' > itbl-cpu.h; \
+ echo '# DO NOT DELETE THIS LINE -- mkdep uses it.' > .dep; \
+ $(DEP) -f .dep -DBFD_ASSEMBLER -I. -I.. -I$${srcdir} -I../../bfd $(DEP_INCLUDES) $?
+ sed -e '/IF YOU PUT ANYTHING/,$$d' < .depdir/.dep > .dep1
+ rm -f .depdir/.dep
+
+# Work out the special dependencies for the tc-*.c files.
+.tcdep: $(TARGET_CPU_CFILES)
+ rm -f .tcdepa
+ if [ -d .depdir ]; then true; else mkdir .depdir; fi
+ srcdir=`cd $(srcdir); pwd`; \
+ cd .depdir; \
+ for c in $(CPU_TYPES); do \
+ for o in $(OBJ_FORMATS); do \
+ $(CPU_OBJ_VALID) \
+ if [ x$${valid} = xyes ]; then \
+ echo '#include "tc-'"$${c}"'.h"' > targ-cpu.h; \
+ echo '#include "obj-'"$${o}"'.h"' > obj-format.h; \
+ echo '#include "te-generic.h"' > targ-env.h; \
+ echo '' > itbl-cpu.h; \
+ echo '#include "opcodes/'"$${c}"'-desc.h"' > cgen-desc.h; \
+ rm -f dummy.c; \
+ cp $${srcdir}/config/tc-$${c}.c dummy.c; \
+ echo '# DO NOT DELETE THIS LINE -- mkdep uses it.' > .dep; \
+ $(DEP) -f .dep -DBFD_ASSEMBLER -I. -I.. -I$${srcdir} -I../../bfd $(DEP_INCLUDES) dummy.c; \
+ sed -e "s/dummy.o: dummy.c/TCDEP_$${c}_$${o} =/" \
+ -e '1,/DO NOT PUT ANYTHING AFTER/d' \
+ -e '/IF YOU PUT ANYTHING/,$$d' \
+ -e '/^$$/d' < .dep >> ../.tcdepa; \
+ rm -f dummy.c; \
+ else true; fi; \
+ done; \
+ done
+ echo 'TCDEP_hppa_som = $$(srcdir)/config/tc-hppa.h subsegs.h \' >> .tcdepa
+ echo ' $$(INCDIR)/obstack.h $$(BFDDIR)/libhppa.h \' >> .tcdepa
+ echo ' $$(INCDIR)/opcode/hppa.h $$(BFDDIR)/som.h' >> .tcdepa
+ # We don't try to handle all multi cases.
+ for c in $(CPU_TYPES); do \
+ $(CPU_MULTI_VALID) \
+ if [ x$${valid} = xyes ]; then \
+ o=ecoff; \
+ $(CPU_OBJ_VALID) \
+ echo 'TCDEP_'"$${c}"'_multi = \' >> .tcdepa; \
+ echo '$$(TCDEP_'"$${c}"'_coff) \' >> .tcdepa; \
+ if [ x$${valid} = xyes ]; then \
+ echo '$$(TCDEP_'"$${c}"'_ecoff) \' >> .tcdepa; \
+ else true; fi; \
+ echo '$$(TCDEP_'"$${c}"'_elf)' >> .tcdepa; \
+ else true; fi; \
+ done
+ mv -f .tcdepa .tcdep
+
+# Work out the special dependencies for the obj-*.c files.
+.objdep: $(OBJ_FORMAT_CFILES)
+ rm -f .objdepa
+ if [ -d .depdir ]; then true; else mkdir .depdir; fi
+ srcdir=`cd $(srcdir); pwd`; \
+ cd .depdir; \
+ for c in $(CPU_TYPES); do \
+ for o in $(OBJ_FORMATS); do \
+ $(CPU_OBJ_VALID) \
+ if [ x$${valid} = xyes ]; then \
+ echo '#include "tc-'"$${c}"'.h"' > targ-cpu.h; \
+ echo '#include "obj-'"$${o}"'.h"' > obj-format.h; \
+ echo '#include "te-generic.h"' > targ-env.h; \
+ echo '' > itbl-cpu.h; \
+ rm -f dummy.c; \
+ cp $${srcdir}/config/obj-$${o}.c dummy.c; \
+ echo '# DO NOT DELETE THIS LINE -- mkdep uses it.' > .dep; \
+ $(DEP) -f .dep -DBFD_ASSEMBLER -I. -I.. -I$${srcdir} -I../../bfd $(DEP_INCLUDES) dummy.c; \
+ sed -e "s/dummy.o: dummy.c/OBJDEP_$${c}_$${o} =/" \
+ -e '1,/DO NOT PUT ANYTHING AFTER/d' \
+ -e '/IF YOU PUT ANYTHING/,$$d' \
+ -e '/^$$/d' < .dep >> ../.objdepa; \
+ rm -f dummy.c; \
+ else true; fi; \
+ done; \
+ done
+ echo 'OBJDEP_hppa_som = $$(srcdir)/config/obj-som.h subsegs.h \' >> .objdepa
+ echo ' $$(INCDIR)/obstack.h $$(BFDDIR)/libhppa.h \' >> .objdepa
+ echo ' $$(BFDDIR)/som.h $$(INCDIR)/aout/stab_gnu.h \' >> .objdepa
+ echo ' $$(INCDIR)/aout/stab.def' >> .objdepa
+ # We don't try to handle all multi cases.
+ for c in $(CPU_TYPES); do \
+ $(CPU_MULTI_VALID) \
+ if [ x$${valid} = xyes ]; then \
+ o=ecoff; \
+ $(CPU_OBJ_VALID) \
+ echo 'OBJDEP_'"$${c}"'_multi = \' >> .objdepa; \
+ echo '$$(OBJDEP_'"$${c}"'_coff) \' >> .objdepa; \
+ if [ x$${valid} = xyes ]; then \
+ echo '$$(OBJDEP_'"$${c}"'_ecoff) \' >> .objdepa; \
+ else true; fi; \
+ echo '$$(OBJDEP_'"$${c}"'_elf)' >> .objdepa; \
+ else true; fi; \
+ done
+ mv -f .objdepa .objdep
+
+# Work out the dependencies for each CPU/OBJ combination.
+# Note that SOM is a special case, because it only works native.
+.dep2: $(TARGET_CPU_HFILES) $(OBJ_FORMAT_HFILES)
+ rm -f .dep2a
+ if [ -d .depdir ]; then true; else mkdir .depdir; fi
+ srcdir=`cd $(srcdir); pwd`; \
+ cd .depdir; \
+ for c in $(CPU_TYPES); do \
+ for o in $(OBJ_FORMATS); do \
+ $(CPU_OBJ_VALID) \
+ if [ x$${valid} = xyes ]; then \
+ echo '#include "tc-'"$${c}"'.h"' > targ-cpu.h; \
+ echo '#include "obj-'"$${o}"'.h"' > dummy.c; \
+ echo '# DO NOT DELETE THIS LINE -- mkdep uses it.' > .dep; \
+ $(DEP) -f .dep -DBFD_ASSEMBLER -I. -I.. -I$${srcdir} -I../../bfd $(DEP_INCLUDES) dummy.c; \
+ sed -e "s/dummy.o: dummy.c/DEP_$${c}_$${o} =/" \
+ -e '1,/DO NOT PUT ANYTHING AFTER/d' \
+ -e '/IF YOU PUT ANYTHING/,$$d' \
+ -e '/^$$/d' < .dep >> ../.dep2a; \
+ else true; fi; \
+ done; \
+ done
+ echo 'DEP_hppa_som = $$(BFDDIR)/som.h' >> .dep2a
+ # We don't try to handle all multi cases.
+ for c in $(CPU_TYPES); do \
+ $(CPU_MULTI_VALID) \
+ if [ x$${valid} = xyes ]; then \
+ o=ecoff; \
+ $(CPU_OBJ_VALID) \
+ echo 'DEP_'"$${c}"'_multi = \' >> .dep2a; \
+ echo '$$(DEP_'"$${c}"'_coff) \' >> .dep2a; \
+ if [ x$${valid} = xyes ]; then \
+ echo '$$(DEP_'"$${c}"'_ecoff) \' >> .dep2a; \
+ else true; fi; \
+ echo '$$(DEP_'"$${c}"'_elf)' >> .dep2a; \
+ else true; fi; \
+ done
+ mv -f .dep2a .dep2
+
+dep.sed: dep-in.sed config.status
+ srcdir=`cd $(srcdir); pwd`; \
+ sed <$(srcdir)/dep-in.sed >dep.sed \
+ -e "s!@INCDIR@!$${srcdir}/../include!" \
+ -e "s!@BFDDIR@!$${srcdir}/../bfd!" \
+ -e "s!@SRCDIR@!$${srcdir}!"
+
+dep: .dep
+ sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < Makefile > tmp-Makefile
+ cat .dep >> tmp-Makefile
+ $(SHELL) $(srcdir)/../move-if-change tmp-Makefile Makefile
+
+dep-in: .dep
+ sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < $(srcdir)/Makefile.in > tmp-Makefile.in
+ cat .dep >> tmp-Makefile.in
+ $(SHELL) $(srcdir)/../move-if-change tmp-Makefile.in $(srcdir)/Makefile.in
+
+dep-am: .dep
+ sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < $(srcdir)/Makefile.am > tmp-Makefile.am
+ cat .dep >> tmp-Makefile.am
+ $(SHELL) $(srcdir)/../move-if-change tmp-Makefile.am $(srcdir)/Makefile.am
+
+.PHONY: dep dep-in dep-am
+
+# DO NOT DELETE THIS LINE -- mkdep uses it.
+# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
+
+app.o: app.c
+as.o: as.c subsegs.h $(INCDIR)/obstack.h output-file.h \
+ sb.h macro.h
+atof-generic.o: atof-generic.c
+bignum-copy.o: bignum-copy.c
+cond.o: cond.c macro.h sb.h $(INCDIR)/obstack.h
+depend.o: depend.c
+ecoff.o: ecoff.c
+ehopt.o: ehopt.c subsegs.h $(INCDIR)/obstack.h $(INCDIR)/elf/dwarf2.h
+expr.o: expr.c $(INCDIR)/obstack.h
+flonum-copy.o: flonum-copy.c
+flonum-konst.o: flonum-konst.c
+flonum-mult.o: flonum-mult.c
+frags.o: frags.c subsegs.h $(INCDIR)/obstack.h
+hash.o: hash.c
+input-file.o: input-file.c input-file.h
+input-scrub.o: input-scrub.c input-file.h sb.h
+listing.o: listing.c input-file.h subsegs.h
+literal.o: literal.c subsegs.h $(INCDIR)/obstack.h
+macro.o: macro.c sb.h macro.h
+messages.o: messages.c
+output-file.o: output-file.c output-file.h
+read.o: read.c subsegs.h $(INCDIR)/obstack.h sb.h macro.h \
+ ecoff.h
+sb.o: sb.c sb.h
+stabs.o: stabs.c $(INCDIR)/obstack.h subsegs.h ecoff.h \
+ $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def
+subsegs.o: subsegs.c subsegs.h $(INCDIR)/obstack.h
+symbols.o: symbols.c $(INCDIR)/obstack.h subsegs.h
+write.o: write.c subsegs.h $(INCDIR)/obstack.h output-file.h
+gasp.o: gasp.c sb.h macro.h
+e-i386coff.o: $(srcdir)/config/e-i386coff.c emul.h \
+ emul-target.h
+e-i386elf.o: $(srcdir)/config/e-i386elf.c emul.h emul-target.h
+e-mipsecoff.o: $(srcdir)/config/e-mipsecoff.c emul.h \
+ emul-target.h
+e-mipself.o: $(srcdir)/config/e-mipself.c emul.h emul-target.h
+
+TCDEP_a29k_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-a29k.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/opcode/a29k.h
+TCDEP_a29k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-a29k.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/a29k.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/opcode/a29k.h
+TCDEP_a29k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-a29k.h $(INCDIR)/opcode/a29k.h
+TCDEP_alpha_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-alpha.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ subsegs.h $(INCDIR)/obstack.h ecoff.h $(INCDIR)/opcode/alpha.h \
+ $(srcdir)/config/atof-vax.c
+TCDEP_alpha_ecoff = $(srcdir)/config/obj-ecoff.h $(srcdir)/config/tc-alpha.h \
+ ecoff.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h \
+ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/alpha.h \
+ $(srcdir)/config/atof-vax.c
+TCDEP_alpha_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-alpha.h subsegs.h \
+ $(INCDIR)/obstack.h ecoff.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h \
+ $(INCDIR)/opcode/alpha.h $(INCDIR)/elf/alpha.h $(INCDIR)/elf/reloc-macros.h \
+ $(srcdir)/config/atof-vax.c
+TCDEP_alpha_evax = $(srcdir)/config/obj-evax.h $(srcdir)/config/tc-alpha.h \
+ subsegs.h $(INCDIR)/obstack.h ecoff.h $(INCDIR)/opcode/alpha.h \
+ $(srcdir)/config/atof-vax.c
+TCDEP_arc_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-arc.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/arc.h \
+ $(INCDIR)/elf/arc.h $(INCDIR)/elf/reloc-macros.h
+TCDEP_arc_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-arc.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/arc.h $(INCDIR)/elf/arc.h \
+ $(INCDIR)/elf/reloc-macros.h
+TCDEP_arm_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-arm.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h
+TCDEP_arm_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-arm.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/arm.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h
+TCDEP_arm_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-arm.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/elf/arm.h $(INCDIR)/elf/reloc-macros.h
+TCDEP_d10v_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-d10v.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/d10v.h \
+ $(INCDIR)/elf/ppc.h $(INCDIR)/elf/reloc-macros.h
+TCDEP_d10v_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-d10v.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/d10v.h $(INCDIR)/elf/ppc.h \
+ $(INCDIR)/elf/reloc-macros.h
+TCDEP_d30v_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-d30v.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/d30v.h
+TCDEP_d30v_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-d30v.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/d30v.h
+TCDEP_fr30_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-fr30.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/symcat.h $(srcdir)/../opcodes/fr30-desc.h \
+ $(INCDIR)/opcode/cgen.h $(srcdir)/../opcodes/fr30-opc.h \
+ cgen.h
+TCDEP_fr30_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-fr30.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/symcat.h $(srcdir)/../opcodes/fr30-desc.h \
+ $(INCDIR)/opcode/cgen.h $(srcdir)/../opcodes/fr30-opc.h \
+ cgen.h
+TCDEP_h8300_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-h8300.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/h8300.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/h8300.h
+TCDEP_h8300_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-h8300.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/h8300.h
+TCDEP_h8500_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-h8500.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/h8500.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h $(srcdir)/../opcodes/h8500-opc.h
+TCDEP_h8500_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-h8500.h subsegs.h \
+ $(INCDIR)/obstack.h $(srcdir)/../opcodes/h8500-opc.h
+TCDEP_hppa_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-hppa.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ subsegs.h $(INCDIR)/obstack.h $(BFDDIR)/libhppa.h $(BFDDIR)/libbfd.h \
+ $(INCDIR)/opcode/hppa.h
+TCDEP_hppa_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-hppa.h $(BFDDIR)/elf32-hppa.h \
+ $(BFDDIR)/libhppa.h $(INCDIR)/elf/hppa.h $(INCDIR)/elf/reloc-macros.h \
+ subsegs.h $(INCDIR)/obstack.h $(BFDDIR)/libbfd.h $(INCDIR)/opcode/hppa.h
+TCDEP_i386_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-i386.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h \
+ $(INCDIR)/opcode/i386.h
+TCDEP_i386_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-i386.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/i386.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/i386.h
+TCDEP_i386_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-i386.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/i386.h
+TCDEP_i860_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-i860.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/opcode/i860.h
+TCDEP_i860_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-i860.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/opcode/i860.h
+TCDEP_i860_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-i860.h $(INCDIR)/opcode/i860.h
+TCDEP_i960_bout = $(srcdir)/config/obj-bout.h $(srcdir)/config/tc-i960.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/i960.h
+TCDEP_i960_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-i960.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/i960.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h $(INCDIR)/opcode/i960.h
+TCDEP_i960_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-i960.h $(INCDIR)/obstack.h \
+ $(INCDIR)/opcode/i960.h
+TCDEP_m32r_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-m32r.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/symcat.h $(srcdir)/../opcodes/m32r-desc.h \
+ $(INCDIR)/opcode/cgen.h $(srcdir)/../opcodes/m32r-opc.h \
+ cgen.h
+TCDEP_m32r_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-m32r.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/symcat.h $(srcdir)/../opcodes/m32r-desc.h \
+ $(INCDIR)/opcode/cgen.h $(srcdir)/../opcodes/m32r-opc.h \
+ cgen.h
+TCDEP_m68k_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-m68k.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h \
+ subsegs.h $(INCDIR)/opcode/m68k.h $(srcdir)/config/m68k-parse.h
+TCDEP_m68k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-m68k.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/m68k.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h $(INCDIR)/opcode/m68k.h \
+ $(srcdir)/config/m68k-parse.h
+TCDEP_m68k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-m68k.h $(INCDIR)/obstack.h \
+ subsegs.h $(INCDIR)/opcode/m68k.h $(srcdir)/config/m68k-parse.h
+TCDEP_m68k_hp300 = $(srcdir)/config/obj-hp300.h $(srcdir)/config/obj-aout.h \
+ $(srcdir)/config/tc-m68k.h $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h $(INCDIR)/opcode/m68k.h \
+ $(srcdir)/config/m68k-parse.h
+TCDEP_m88k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-m88k.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/m88k.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h $(srcdir)/config/m88k-opcode.h
+TCDEP_m88k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-m88k.h subsegs.h \
+ $(INCDIR)/obstack.h $(srcdir)/config/m88k-opcode.h
+TCDEP_mcore_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mcore.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/mcore.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h $(srcdir)/../opcodes/mcore-opc.h
+TCDEP_mcore_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-mcore.h subsegs.h \
+ $(INCDIR)/obstack.h $(srcdir)/../opcodes/mcore-opc.h \
+ $(INCDIR)/elf/mcore.h $(INCDIR)/elf/reloc-macros.h
+TCDEP_mips_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-mips.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h \
+ $(INCDIR)/opcode/mips.h itbl-ops.h ecoff.h $(INCDIR)/coff/sym.h \
+ $(INCDIR)/coff/ecoff.h
+TCDEP_mips_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mips.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/mips.h \
+ itbl-ops.h ecoff.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h
+TCDEP_mips_ecoff = $(srcdir)/config/obj-ecoff.h $(srcdir)/config/tc-mips.h \
+ ecoff.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h \
+ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/mips.h \
+ itbl-ops.h
+TCDEP_mips_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-mips.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/mips.h itbl-ops.h \
+ $(INCDIR)/elf/mips.h $(INCDIR)/elf/reloc-macros.h ecoff.h \
+ $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h
+TCDEP_mn10200_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mn10200.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/mn10200.h
+TCDEP_mn10200_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-mn10200.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/mn10200.h
+TCDEP_mn10300_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mn10300.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/mn10300.h
+TCDEP_mn10300_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-mn10300.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/mn10300.h
+TCDEP_ns32k_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-ns32k.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/opcode/ns32k.h \
+ $(INCDIR)/obstack.h
+TCDEP_ns32k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-ns32k.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/opcode/ns32k.h $(INCDIR)/obstack.h
+TCDEP_ns32k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-ns32k.h $(INCDIR)/opcode/ns32k.h \
+ $(INCDIR)/obstack.h
+TCDEP_ppc_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-ppc.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/rs6000.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/ppc.h
+TCDEP_ppc_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-ppc.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/ppc.h $(INCDIR)/elf/ppc.h \
+ $(INCDIR)/elf/reloc-macros.h
+TCDEP_sh_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-sh.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/sh.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h $(srcdir)/../opcodes/sh-opc.h
+TCDEP_sh_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-sh.h subsegs.h \
+ $(INCDIR)/obstack.h $(srcdir)/../opcodes/sh-opc.h
+TCDEP_sparc_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-sparc.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h \
+ $(INCDIR)/opcode/sparc.h
+TCDEP_sparc_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-sparc.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/sparc.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/sparc.h
+TCDEP_sparc_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-sparc.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/sparc.h $(INCDIR)/elf/sparc.h \
+ $(INCDIR)/elf/reloc-macros.h
+TCDEP_tahoe_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-tahoe.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h \
+ $(INCDIR)/opcode/tahoe.h
+TCDEP_tahoe_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tahoe.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/tahoe.h
+TCDEP_tahoe_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tahoe.h $(INCDIR)/obstack.h \
+ $(INCDIR)/opcode/tahoe.h
+TCDEP_tic30_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-tic30.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/opcode/tic30.h
+TCDEP_tic30_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tic30.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/tic30.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/opcode/tic30.h
+TCDEP_tic30_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tic30.h $(INCDIR)/opcode/tic30.h
+TCDEP_tic80_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tic80.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/tic80.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/opcode/tic80.h
+TCDEP_tic80_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tic80.h $(INCDIR)/opcode/tic80.h
+TCDEP_vax_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-vax.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(srcdir)/config/vax-inst.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/vax.h
+TCDEP_vax_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-vax.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(srcdir)/config/vax-inst.h $(INCDIR)/obstack.h $(INCDIR)/opcode/vax.h
+TCDEP_vax_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-vax.h $(srcdir)/config/vax-inst.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/vax.h
+TCDEP_vax_vms = $(srcdir)/config/obj-vms.h $(srcdir)/config/tc-vax.h \
+ $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def $(srcdir)/config/vax-inst.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/vax.h
+TCDEP_w65_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-w65.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/w65.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h $(srcdir)/../opcodes/w65-opc.h
+TCDEP_w65_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-w65.h subsegs.h \
+ $(INCDIR)/obstack.h $(srcdir)/../opcodes/w65-opc.h
+TCDEP_v850_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-v850.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/v850.h
+TCDEP_v850_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-v850.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/v850.h
+TCDEP_z8k_coff = $(srcdir)/../opcodes/z8k-opc.h $(srcdir)/config/obj-coff.h \
+ $(srcdir)/config/tc-z8k.h $(INCDIR)/coff/internal.h \
+ $(INCDIR)/coff/z8k.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+TCDEP_z8k_elf = $(srcdir)/../opcodes/z8k-opc.h $(srcdir)/config/obj-elf.h \
+ $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
+ $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-z8k.h
+TCDEP_hppa_som = $(srcdir)/config/tc-hppa.h subsegs.h \
+ $(INCDIR)/obstack.h $(BFDDIR)/libhppa.h $(INCDIR)/opcode/hppa.h \
+ $(BFDDIR)/som.h
+TCDEP_i386_multi = $(TCDEP_i386_coff) $(TCDEP_i386_elf)
+TCDEP_mips_multi = $(TCDEP_mips_coff) $(TCDEP_mips_ecoff) \
+ $(TCDEP_mips_elf)
+OBJDEP_a29k_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-a29k.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/obstack.h
+OBJDEP_a29k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-a29k.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/a29k.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+OBJDEP_a29k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-a29k.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_alpha_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-alpha.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+OBJDEP_alpha_ecoff = $(srcdir)/config/obj-ecoff.h $(srcdir)/config/tc-alpha.h \
+ ecoff.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(BFDDIR)/libecoff.h
+OBJDEP_alpha_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-alpha.h subsegs.h \
+ $(INCDIR)/obstack.h ecoff.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h \
+ $(INCDIR)/elf/alpha.h $(INCDIR)/elf/reloc-macros.h \
+ $(INCDIR)/aout/aout64.h
+OBJDEP_alpha_evax = $(srcdir)/config/obj-evax.h $(srcdir)/config/tc-alpha.h
+OBJDEP_arc_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-arc.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+OBJDEP_arc_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-arc.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_arm_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-arm.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/obstack.h
+OBJDEP_arm_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-arm.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/arm.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+OBJDEP_arm_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-arm.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_d10v_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-d10v.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+OBJDEP_d10v_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-d10v.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_d30v_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-d30v.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+OBJDEP_d30v_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-d30v.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_fr30_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-fr30.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+OBJDEP_fr30_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-fr30.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_h8300_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-h8300.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/h8300.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+OBJDEP_h8300_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-h8300.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_h8500_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-h8500.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/h8500.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+OBJDEP_h8500_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-h8500.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_hppa_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-hppa.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+OBJDEP_hppa_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-hppa.h $(BFDDIR)/elf32-hppa.h \
+ $(BFDDIR)/libhppa.h $(INCDIR)/elf/hppa.h $(INCDIR)/elf/reloc-macros.h \
+ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_i386_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-i386.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/obstack.h
+OBJDEP_i386_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-i386.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/i386.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+OBJDEP_i386_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-i386.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_i860_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-i860.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/obstack.h
+OBJDEP_i860_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-i860.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+OBJDEP_i860_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-i860.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_i960_bout = $(srcdir)/config/obj-bout.h $(srcdir)/config/tc-i960.h \
+ $(INCDIR)/obstack.h
+OBJDEP_i960_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-i960.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/i960.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+OBJDEP_i960_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-i960.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_m32r_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-m32r.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+OBJDEP_m32r_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-m32r.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_m68k_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-m68k.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/obstack.h
+OBJDEP_m68k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-m68k.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/m68k.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+OBJDEP_m68k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-m68k.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_m68k_hp300 = $(srcdir)/config/obj-aout.c $(srcdir)/config/obj-hp300.h \
+ $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-m68k.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/obstack.h
+OBJDEP_m88k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-m88k.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/m88k.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+OBJDEP_m88k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-m88k.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_mcore_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mcore.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/mcore.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+OBJDEP_mcore_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-mcore.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_mips_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-mips.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/obstack.h
+OBJDEP_mips_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mips.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+OBJDEP_mips_ecoff = $(srcdir)/config/obj-ecoff.h $(srcdir)/config/tc-mips.h \
+ ecoff.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(BFDDIR)/libecoff.h
+OBJDEP_mips_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-mips.h subsegs.h \
+ $(INCDIR)/obstack.h ecoff.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h \
+ $(INCDIR)/elf/mips.h $(INCDIR)/elf/reloc-macros.h $(INCDIR)/aout/aout64.h
+OBJDEP_mn10200_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mn10200.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+OBJDEP_mn10200_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-mn10200.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_mn10300_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mn10300.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+OBJDEP_mn10300_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-mn10300.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_ns32k_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-ns32k.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/obstack.h
+OBJDEP_ns32k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-ns32k.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+OBJDEP_ns32k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-ns32k.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_ppc_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-ppc.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/rs6000.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+OBJDEP_ppc_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-ppc.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/elf/ppc.h $(INCDIR)/elf/reloc-macros.h \
+ $(INCDIR)/aout/aout64.h
+OBJDEP_sh_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-sh.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/sh.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+OBJDEP_sh_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-sh.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_sparc_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-sparc.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/obstack.h
+OBJDEP_sparc_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-sparc.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/sparc.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+OBJDEP_sparc_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-sparc.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_tahoe_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-tahoe.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/obstack.h
+OBJDEP_tahoe_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tahoe.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+OBJDEP_tahoe_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tahoe.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_tic30_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-tic30.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/obstack.h
+OBJDEP_tic30_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tic30.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/tic30.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+OBJDEP_tic30_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tic30.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_tic80_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tic80.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/tic80.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+OBJDEP_tic80_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tic80.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_vax_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-vax.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/obstack.h
+OBJDEP_vax_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-vax.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+OBJDEP_vax_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-vax.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_vax_vms = $(srcdir)/config/obj-vms.h $(srcdir)/config/tc-vax.h \
+ $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def subsegs.h \
+ $(INCDIR)/obstack.h
+OBJDEP_w65_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-w65.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/w65.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+OBJDEP_w65_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-w65.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_v850_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-v850.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+OBJDEP_v850_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-v850.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_z8k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-z8k.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/z8k.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+OBJDEP_z8k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-z8k.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+OBJDEP_hppa_som = $(srcdir)/config/obj-som.h subsegs.h \
+ $(INCDIR)/obstack.h $(BFDDIR)/libhppa.h $(BFDDIR)/som.h \
+ $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def
+OBJDEP_i386_multi = $(OBJDEP_i386_coff) $(OBJDEP_i386_elf)
+OBJDEP_mips_multi = $(OBJDEP_mips_coff) $(OBJDEP_mips_ecoff) \
+ $(OBJDEP_mips_elf)
+DEP_a29k_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-a29k.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
+DEP_a29k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-a29k.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/a29k.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+DEP_a29k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-a29k.h
+DEP_alpha_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-alpha.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+DEP_alpha_ecoff = $(srcdir)/config/obj-ecoff.h $(srcdir)/config/tc-alpha.h \
+ ecoff.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h
+DEP_alpha_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-alpha.h
+DEP_alpha_evax = $(srcdir)/config/obj-evax.h $(srcdir)/config/tc-alpha.h
+DEP_arc_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-arc.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+DEP_arc_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-arc.h
+DEP_arm_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-arm.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
+DEP_arm_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-arm.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/arm.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+DEP_arm_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-arm.h
+DEP_d10v_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-d10v.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+DEP_d10v_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-d10v.h
+DEP_d30v_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-d30v.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+DEP_d30v_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-d30v.h
+DEP_fr30_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-fr30.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+DEP_fr30_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-fr30.h
+DEP_h8300_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-h8300.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/h8300.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+DEP_h8300_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-h8300.h
+DEP_h8500_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-h8500.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/h8500.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+DEP_h8500_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-h8500.h
+DEP_hppa_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-hppa.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+DEP_hppa_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-hppa.h $(BFDDIR)/elf32-hppa.h \
+ $(BFDDIR)/libhppa.h $(INCDIR)/elf/hppa.h $(INCDIR)/elf/reloc-macros.h
+DEP_i386_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-i386.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
+DEP_i386_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-i386.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/i386.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+DEP_i386_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-i386.h
+DEP_i860_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-i860.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
+DEP_i860_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-i860.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+DEP_i860_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-i860.h
+DEP_i960_bout = $(srcdir)/config/obj-bout.h $(srcdir)/config/tc-i960.h
+DEP_i960_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-i960.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/i960.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+DEP_i960_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-i960.h
+DEP_m32r_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-m32r.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+DEP_m32r_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-m32r.h
+DEP_m68k_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-m68k.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
+DEP_m68k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-m68k.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/m68k.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+DEP_m68k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-m68k.h
+DEP_m68k_hp300 = $(srcdir)/config/obj-hp300.h $(srcdir)/config/obj-aout.h \
+ $(srcdir)/config/tc-m68k.h $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
+DEP_m88k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-m88k.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/m88k.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+DEP_m88k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-m88k.h
+DEP_mcore_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mcore.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/mcore.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+DEP_mcore_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-mcore.h
+DEP_mips_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-mips.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
+DEP_mips_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mips.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+DEP_mips_ecoff = $(srcdir)/config/obj-ecoff.h $(srcdir)/config/tc-mips.h \
+ ecoff.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h
+DEP_mips_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-mips.h
+DEP_mn10200_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mn10200.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+DEP_mn10200_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-mn10200.h
+DEP_mn10300_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mn10300.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+DEP_mn10300_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-mn10300.h
+DEP_ns32k_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-ns32k.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
+DEP_ns32k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-ns32k.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+DEP_ns32k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-ns32k.h
+DEP_ppc_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-ppc.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/rs6000.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+DEP_ppc_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-ppc.h
+DEP_sh_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-sh.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/sh.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+DEP_sh_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-sh.h
+DEP_sparc_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-sparc.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
+DEP_sparc_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-sparc.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/sparc.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+DEP_sparc_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-sparc.h
+DEP_tahoe_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-tahoe.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
+DEP_tahoe_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tahoe.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+DEP_tahoe_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tahoe.h
+DEP_tic30_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-tic30.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
+DEP_tic30_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tic30.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/tic30.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+DEP_tic30_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tic30.h
+DEP_tic80_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tic80.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/tic80.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+DEP_tic80_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tic80.h
+DEP_vax_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-vax.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
+DEP_vax_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-vax.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+DEP_vax_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-vax.h
+DEP_vax_vms = $(srcdir)/config/obj-vms.h $(srcdir)/config/tc-vax.h \
+ $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def
+DEP_w65_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-w65.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/w65.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+DEP_w65_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-w65.h
+DEP_v850_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-v850.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+DEP_v850_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-v850.h
+DEP_z8k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-z8k.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/z8k.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+DEP_z8k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-z8k.h
+DEP_hppa_som = $(BFDDIR)/som.h
+DEP_i386_multi = $(DEP_i386_coff) $(DEP_i386_elf)
+DEP_mips_multi = $(DEP_mips_coff) $(DEP_mips_ecoff) \
+ $(DEP_mips_elf)
+$(OBJS): $(DEP_@target_cpu_type@_@obj_format@)
+$(TARG_CPU_O): $(TCDEP_@target_cpu_type@_@obj_format@)
+$(OBJ_FORMAT_O): $(OBJDEP_@target_cpu_type@_@obj_format@)
+# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
diff --git a/gas/Makefile.in b/gas/Makefile.in
new file mode 100644
index 0000000000..244fff2ef3
--- /dev/null
+++ b/gas/Makefile.in
@@ -0,0 +1,2488 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = .
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_alias = @build_alias@
+build_triplet = @build@
+host_alias = @host_alias@
+host_triplet = @host@
+target_alias = @target_alias@
+target_triplet = @target@
+ALL_OBJ_DEPS = @ALL_OBJ_DEPS@
+AS = @AS@
+BFDLIB = @BFDLIB@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+DATADIRNAME = @DATADIRNAME@
+DLLTOOL = @DLLTOOL@
+EXEEXT = @EXEEXT@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GT_NO = @GT_NO@
+GT_YES = @GT_YES@
+INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@
+INSTOBJEXT = @INSTOBJEXT@
+INTLDEPS = @INTLDEPS@
+INTLOBJS = @INTLOBJS@
+LD = @LD@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+NM = @NM@
+OPCODES_LIB = @OPCODES_LIB@
+PACKAGE = @PACKAGE@
+POFILES = @POFILES@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+atof = @atof@
+cgen_cpu_prefix = @cgen_cpu_prefix@
+extra_objects = @extra_objects@
+install_tooldir = @install_tooldir@
+l = @l@
+obj_format = @obj_format@
+target_cpu_type = @target_cpu_type@
+te_file = @te_file@
+
+INTLLIBS = @INTLLIBS@
+
+AUTOMAKE_OPTIONS = cygnus dejagnu
+
+SUBDIRS = doc po
+
+tooldir = $(exec_prefix)/$(target_alias)
+
+YACC = `if [ -f ../bison/bison ] ; then echo ../bison/bison -y -L../bison/bison ; else echo bison -y ; fi`
+LEX = `if [ -f ../flex/flex ] ; then echo ../flex/flex ; else echo flex ; fi`
+
+DEP = $(srcdir)/../mkdep
+
+TARG_CPU = @target_cpu_type@
+TARG_CPU_C = $(srcdir)/config/tc-@target_cpu_type@.c
+TARG_CPU_O = tc-@target_cpu_type@.o
+TARG_CPU_H = $(srcdir)/config/tc-@target_cpu_type@.h
+OBJ_FORMAT_C = $(srcdir)/config/obj-@obj_format@.c
+OBJ_FORMAT_O = obj-@obj_format@.o
+OBJ_FORMAT_H = $(srcdir)/config/obj-@obj_format@.h
+TARG_ENV_H = $(srcdir)/config/te-@te_file@.h
+ATOF_TARG_C = $(srcdir)/config/atof-@atof@.c
+ATOF_TARG_O = atof-@atof@.o
+
+# use @target_cpu_type@ for refering to configured target name
+IT_HDRS = itbl-parse.h $(srcdir)/itbl-ops.h
+IT_SRCS = itbl-parse.c itbl-lex.c $(srcdir)/itbl-ops.c
+IT_DEPS = $(srcdir)/itbl-parse.y $(srcdir)/itbl-lex.l $(srcdir)/config/itbl-@target_cpu_type@.h
+IT_OBJS = itbl-parse.o itbl-lex.o itbl-ops.o
+
+# CPU types. This is only used for dependency information.
+
+CPU_TYPES = \
+ a29k \
+ alpha \
+ arc \
+ arm \
+ d10v \
+ d30v \
+ fr30 \
+ h8300 \
+ h8500 \
+ hppa \
+ i386 \
+ i860 \
+ i960 \
+ m32r \
+ m68k \
+ m88k \
+ mcore \
+ mips \
+ mn10200 \
+ mn10300 \
+ ns32k \
+ ppc \
+ sh \
+ sparc \
+ tahoe \
+ tic30 \
+ tic80 \
+ vax \
+ w65 \
+ v850 \
+ z8k
+
+
+# Object format types. This is only used for dependency information.
+# We deliberately omit som, since it does not work as a cross assembler.
+
+OBJ_FORMATS = \
+ aout \
+ bout \
+ coff \
+ ecoff \
+ elf \
+ evax \
+ hp300 \
+ ieee \
+ vms
+
+
+# This is an sh case which sets valid according to whether the CPU
+# type in the shell variable c and the OS type in the shell variable o
+# are supported. This helps cuts down on the amount of dependency
+# information.
+
+CPU_OBJ_VALID = \
+ valid= ; \
+ case $$o in \
+ aout) \
+ case $$c in \
+ a29k | arm | i386 | i860 | m68k | mips | ns32k | sparc | tahoe | tic30 | vax) \
+ valid=yes ;; \
+ esac ;; \
+ bout) \
+ case $$c in \
+ i960) valid=yes ;; \
+ esac ;; \
+ coff) valid=yes ;; \
+ ecoff) \
+ case $$c in \
+ mips | alpha) valid=yes ;; \
+ esac ;; \
+ elf) valid=yes ;; \
+ evax) \
+ case $$c in \
+ alpha) valid=yes ;; \
+ esac ;; \
+ hp300) \
+ case $$c in \
+ m68k) valid=yes ;; \
+ esac ;; \
+ vms) \
+ case $$c in \
+ vax) valid=yes ;; \
+ esac ;; \
+ esac;
+
+
+# This is like CPU_OBJ_VALID, for the obj=multi case.
+
+CPU_MULTI_VALID = \
+ valid= ; \
+ case $$c in \
+ i386 | mips) valid=yes ;; \
+ esac;
+
+
+# Regular source files.
+
+GAS_CFILES = \
+ app.c \
+ as.c \
+ atof-generic.c \
+ bignum-copy.c \
+ cond.c \
+ depend.c \
+ ecoff.c \
+ ehopt.c \
+ expr.c \
+ flonum-copy.c \
+ flonum-konst.c \
+ flonum-mult.c \
+ frags.c \
+ hash.c \
+ input-file.c \
+ input-scrub.c \
+ listing.c \
+ literal.c \
+ macro.c \
+ messages.c \
+ output-file.c \
+ read.c \
+ sb.c \
+ stabs.c \
+ subsegs.c \
+ symbols.c \
+ write.c
+
+
+CFILES = $(GAS_CFILES) gasp.c itbl-ops.c
+
+HFILES = \
+ as.h \
+ asintl.h \
+ bignum.h \
+ bit_fix.h \
+ cgen.h \
+ ecoff.h \
+ emul-target.h \
+ emul.h \
+ expr.h \
+ flonum.h \
+ frags.h \
+ hash.h \
+ input-file.h \
+ itbl-ops.h \
+ listing.h \
+ macro.h \
+ obj.h \
+ output-file.h \
+ read.h \
+ sb.h \
+ struc-symbol.h \
+ subsegs.h \
+ symbols.h \
+ tc.h \
+ write.h
+
+
+# CPU files in config.
+
+TARGET_CPU_CFILES = \
+ config/tc-a29k.c \
+ config/tc-alpha.c \
+ config/tc-arc.c \
+ config/tc-arm.c \
+ config/tc-d10v.c \
+ config/tc-d30v.c \
+ config/tc-h8300.c \
+ config/tc-h8500.c \
+ config/tc-hppa.c \
+ config/tc-i386.c \
+ config/tc-i860.c \
+ config/tc-i960.c \
+ config/tc-m32r.c \
+ config/tc-m68k.c \
+ config/tc-m88k.c \
+ config/tc-mcore.c \
+ config/tc-mips.c \
+ config/tc-mn10200.c \
+ config/tc-mn10300.c \
+ config/tc-ns32k.c \
+ config/tc-ppc.c \
+ config/tc-sh.c \
+ config/tc-sparc.c \
+ config/tc-tahoe.c \
+ config/tc-tic30.c \
+ config/tc-tic80.c \
+ config/tc-vax.c \
+ config/tc-w65.c \
+ config/tc-v850.c \
+ config/tc-z8k.c
+
+
+TARGET_CPU_HFILES = \
+ config/tc-a29k.h \
+ config/tc-alpha.h \
+ config/tc-arc.h \
+ config/tc-arm.h \
+ config/tc-d10v.h \
+ config/tc-d30v.h \
+ config/tc-h8300.h \
+ config/tc-h8500.h \
+ config/tc-hppa.h \
+ config/tc-i386.h \
+ config/tc-i860.h \
+ config/tc-i960.h \
+ config/tc-m32r.h \
+ config/tc-m68k.h \
+ config/tc-m88k.h \
+ config/tc-mcore.h \
+ config/tc-mips.h \
+ config/tc-mn10200.h \
+ config/tc-mn10300.h \
+ config/tc-ns32k.h \
+ config/tc-ppc.h \
+ config/tc-sh.h \
+ config/tc-sparc.h \
+ config/tc-tahoe.h \
+ config/tc-tic30.h \
+ config/tc-tic80.h \
+ config/tc-vax.h \
+ config/tc-w65.h \
+ config/tc-v850.h \
+ config/tc-z8k.h
+
+
+# OBJ files in config
+
+OBJ_FORMAT_CFILES = \
+ config/obj-aout.c \
+ config/obj-bout.c \
+ config/obj-coff.c \
+ config/obj-ecoff.c \
+ config/obj-elf.c \
+ config/obj-evax.c \
+ config/obj-hp300.c \
+ config/obj-ieee.c \
+ config/obj-som.c \
+ config/obj-vms.c
+
+
+OBJ_FORMAT_HFILES = \
+ config/obj-aout.h \
+ config/obj-bout.h \
+ config/obj-coff.h \
+ config/obj-ecoff.h \
+ config/obj-elf.h \
+ config/obj-evax.h \
+ config/obj-hp300.h \
+ config/obj-ieee.h \
+ config/obj-som.h \
+ config/obj-vms.h
+
+
+# Emulation header files in config
+
+TARG_ENV_HFILES = \
+ config/te-386bsd.h \
+ config/te-aux.h \
+ config/te-delta.h \
+ config/te-delt88.h \
+ config/te-dpx2.h \
+ config/te-dynix.h \
+ config/te-generic.h \
+ config/te-go32.h \
+ config/te-hp300.h \
+ config/te-hppa.h \
+ config/te-i386aix.h \
+ config/te-ic960.h \
+ config/te-linux.h \
+ config/te-lnews.h \
+ config/te-lynx.h \
+ config/te-mach.h \
+ config/te-macos.h \
+ config/te-multi.h \
+ config/te-nbsd.h \
+ config/te-nbsd532.h \
+ config/te-pc532mach.h \
+ config/te-pe.h \
+ config/te-ppcnw.h \
+ config/te-psos.h \
+ config/te-riscix.h \
+ config/te-sparcaout.h \
+ config/te-sun3.h \
+ config/te-svr4.h \
+ config/te-sysv32.h
+
+
+# Multi files in config
+
+MULTI_CFILES = \
+ config/e-i386coff.c \
+ config/e-i386elf.c \
+ config/e-mipsecoff.c \
+ config/e-mipself.c
+
+
+CONFIG_OBJS = \
+ $(TARG_CPU_O) \
+ $(OBJ_FORMAT_O) \
+ $(ATOF_TARG_O) \
+ $(extra_objects)
+
+
+GENERIC_OBJS = \
+ app.o \
+ as.o \
+ atof-generic.o \
+ bignum-copy.o \
+ cond.o \
+ depend.o \
+ ehopt.o \
+ expr.o \
+ flonum-konst.o \
+ flonum-copy.o \
+ flonum-mult.o \
+ frags.o \
+ hash.o \
+ input-file.o \
+ input-scrub.o \
+ literal.o \
+ messages.o \
+ output-file.o \
+ read.o \
+ subsegs.o \
+ symbols.o \
+ write.o \
+ listing.o \
+ ecoff.o \
+ stabs.o \
+ sb.o \
+ macro.o
+
+
+OBJS = $(CONFIG_OBJS) $(GENERIC_OBJS)
+
+POTFILES = $(MULTI_CFILES) $(TARGET_ENV_HFILES) $(OBJ_FORMAT_HFILES) \
+ $(OBJ_FORMAT_CFILES) $(TARGET_CPU_HFILES) $(TARGET_CPU_CFILES) \
+ $(HFILES) $(CFILES) $(GAS_CFILES)
+
+
+noinst_PROGRAMS = as-new gasp-new
+noinst_SCRIPTS = .gdbinit
+
+EXTRA_DIST = make-gas.com
+
+DISTSTUFF = make-gas.com m68k-parse.c itbl-parse.c itbl-parse.h itbl-lex.c
+
+DISTCLEANFILES = targ-cpu.h obj-format.h targ-env.h itbl-cpu.h cgen-desc.h
+
+# Now figure out from those variables how to compile and link.
+
+BASEDIR = $(srcdir)/..
+BFDDIR = $(BASEDIR)/bfd
+INCDIR = $(BASEDIR)/include
+
+# This is the variable actually used when we compile.
+# Specify the directories to be searched for header files.
+# Both . and srcdir are used, in that order,
+# so that tm.h and config.h will be found in the compilation
+# subdirectory rather than in the source directory.
+INCLUDES = -D_GNU_SOURCE -I. -I$(srcdir) -I../bfd -I$(srcdir)/config -I$(INCDIR) -I$(srcdir)/.. -I$(BFDDIR) -I$(srcdir)/../intl -I../intl -DLOCALEDIR="\"$(prefix)/share/locale\""
+
+# This should be parallel to INCLUDES, but should replace $(srcdir)
+# with $${srcdir}, and should work in a subdirectory. This is used
+# when building dependencies, because the dependency building is done
+# in a subdirectory.
+DEP_INCLUDES = -D_GNU_SOURCE -I.. -I$${srcdir} -I../../bfd -I$${srcdir}/config -I$${srcdir}/../include -I$${srcdir}/.. -I$${srcdir}/../bfd -I$${srcdir}/../intl -I../../intl -DLOCALEDIR="\"$(prefix)/share/locale\""
+
+# How to link with both our special library facilities
+# and the system's installed libraries.
+
+GASLIBS = @OPCODES_LIB@ @BFDLIB@ ../libiberty/libiberty.a
+
+# Files to be copied away after each stage in building.
+STAGESTUFF = *.o $(noinst_PROGRAMS)
+
+as_new_SOURCES = $(GAS_CFILES)
+as_new_LDADD = $(TARG_CPU_O) $(OBJ_FORMAT_O) $(ATOF_TARG_O) \
+ $(extra_objects) $(GASLIBS) $(INTLLIBS)
+
+as_new_DEPENDENCIES = $(TARG_CPU_O) $(OBJ_FORMAT_O) $(ATOF_TARG_O) \
+ $(extra_objects) $(GASLIBS) $(INTLDEPS)
+
+
+gasp_new_SOURCES = gasp.c macro.c sb.c hash.c
+gasp_new_LDADD = ../libiberty/libiberty.a $(INTLLIBS)
+gasp_new_DEPENDENCIES = ../libiberty/libiberty.a $(INTLDEPS)
+
+EXPECT = `if [ -f $${rootme}/../expect/expect ] ; then \
+ echo $${rootme}/../expect/expect ; \
+ else echo expect ; fi`
+
+
+RUNTEST = `if [ -f $${srcdir}/../dejagnu/runtest ] ; then \
+ echo $${srcdir}/../dejagnu/runtest ; else echo runtest; \
+ fi`
+
+RUNTESTFLAGS =
+
+# The m68k operand parser.
+
+EXTRA_as_new_SOURCES = config/m68k-parse.y
+
+# stand-alone itbl assembler & disassembler
+
+EXTRA_PROGRAMS = itbl-test
+itbl_test_SOURCES = itbl-parse.y itbl-lex.l
+itbl_test_LDADD = itbl-test-ops.o itbl-test.o $(GASLIBS) @LEXLIB@
+
+# CGEN interface.
+
+CGEN_CPU_PREFIX = @cgen_cpu_prefix@
+
+# Remake the info files.
+
+MOSTLYCLEANFILES = $(STAGESTUFF) core stamp-mk.com \
+ testsuite/*.o testsuite/*.out testsuite/gas.log testsuite/gas.sum \
+ testsuite/site.exp site.bak site.exp stage stage1 stage2
+
+
+CLEANFILES = dep.sed .tcdep .objdep .dep2 .dep1 .depa .dep .depdir
+
+against = stage2
+
+# Automatic dependency computation. This is a real pain, because the
+# dependencies change based on target_cpu_type and obj_format. We
+# currently ignore any dependencies caused by emulation files.
+
+DEP_FILE_DEPS = $(CFILES) $(HFILES) $(TARGET_CPU_CFILES) \
+ $(TARGET_CPU_HFILES) $(OBJ_FORMAT_CFILES) $(OBJ_FORMAT_HFILES)
+
+
+TCDEP_a29k_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-a29k.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/opcode/a29k.h
+
+TCDEP_a29k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-a29k.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/a29k.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/opcode/a29k.h
+
+TCDEP_a29k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-a29k.h $(INCDIR)/opcode/a29k.h
+
+TCDEP_alpha_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-alpha.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ subsegs.h $(INCDIR)/obstack.h ecoff.h $(INCDIR)/opcode/alpha.h \
+ $(srcdir)/config/atof-vax.c
+
+TCDEP_alpha_ecoff = $(srcdir)/config/obj-ecoff.h $(srcdir)/config/tc-alpha.h \
+ ecoff.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h \
+ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/alpha.h \
+ $(srcdir)/config/atof-vax.c
+
+TCDEP_alpha_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-alpha.h subsegs.h \
+ $(INCDIR)/obstack.h ecoff.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h \
+ $(INCDIR)/opcode/alpha.h $(INCDIR)/elf/alpha.h $(INCDIR)/elf/reloc-macros.h \
+ $(srcdir)/config/atof-vax.c
+
+TCDEP_alpha_evax = $(srcdir)/config/obj-evax.h $(srcdir)/config/tc-alpha.h \
+ subsegs.h $(INCDIR)/obstack.h ecoff.h $(INCDIR)/opcode/alpha.h \
+ $(srcdir)/config/atof-vax.c
+
+TCDEP_arc_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-arc.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/arc.h \
+ $(INCDIR)/elf/arc.h $(INCDIR)/elf/reloc-macros.h
+
+TCDEP_arc_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-arc.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/arc.h $(INCDIR)/elf/arc.h \
+ $(INCDIR)/elf/reloc-macros.h
+
+TCDEP_arm_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-arm.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h
+
+TCDEP_arm_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-arm.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/arm.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h
+
+TCDEP_arm_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-arm.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/elf/arm.h $(INCDIR)/elf/reloc-macros.h
+
+TCDEP_d10v_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-d10v.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/d10v.h \
+ $(INCDIR)/elf/ppc.h $(INCDIR)/elf/reloc-macros.h
+
+TCDEP_d10v_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-d10v.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/d10v.h $(INCDIR)/elf/ppc.h \
+ $(INCDIR)/elf/reloc-macros.h
+
+TCDEP_d30v_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-d30v.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/d30v.h
+
+TCDEP_d30v_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-d30v.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/d30v.h
+
+TCDEP_fr30_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-fr30.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/symcat.h $(srcdir)/../opcodes/fr30-desc.h \
+ $(INCDIR)/opcode/cgen.h $(srcdir)/../opcodes/fr30-opc.h \
+ cgen.h
+
+TCDEP_fr30_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-fr30.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/symcat.h $(srcdir)/../opcodes/fr30-desc.h \
+ $(INCDIR)/opcode/cgen.h $(srcdir)/../opcodes/fr30-opc.h \
+ cgen.h
+
+TCDEP_h8300_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-h8300.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/h8300.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/h8300.h
+
+TCDEP_h8300_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-h8300.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/h8300.h
+
+TCDEP_h8500_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-h8500.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/h8500.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h $(srcdir)/../opcodes/h8500-opc.h
+
+TCDEP_h8500_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-h8500.h subsegs.h \
+ $(INCDIR)/obstack.h $(srcdir)/../opcodes/h8500-opc.h
+
+TCDEP_hppa_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-hppa.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ subsegs.h $(INCDIR)/obstack.h $(BFDDIR)/libhppa.h $(BFDDIR)/libbfd.h \
+ $(INCDIR)/opcode/hppa.h
+
+TCDEP_hppa_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-hppa.h $(BFDDIR)/elf32-hppa.h \
+ $(BFDDIR)/libhppa.h $(INCDIR)/elf/hppa.h $(INCDIR)/elf/reloc-macros.h \
+ subsegs.h $(INCDIR)/obstack.h $(BFDDIR)/libbfd.h $(INCDIR)/opcode/hppa.h
+
+TCDEP_i386_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-i386.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h \
+ $(INCDIR)/opcode/i386.h
+
+TCDEP_i386_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-i386.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/i386.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/i386.h
+
+TCDEP_i386_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-i386.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/i386.h
+
+TCDEP_i860_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-i860.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/opcode/i860.h
+
+TCDEP_i860_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-i860.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/opcode/i860.h
+
+TCDEP_i860_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-i860.h $(INCDIR)/opcode/i860.h
+
+TCDEP_i960_bout = $(srcdir)/config/obj-bout.h $(srcdir)/config/tc-i960.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/i960.h
+
+TCDEP_i960_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-i960.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/i960.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h $(INCDIR)/opcode/i960.h
+
+TCDEP_i960_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-i960.h $(INCDIR)/obstack.h \
+ $(INCDIR)/opcode/i960.h
+
+TCDEP_m32r_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-m32r.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/symcat.h $(srcdir)/../opcodes/m32r-desc.h \
+ $(INCDIR)/opcode/cgen.h $(srcdir)/../opcodes/m32r-opc.h \
+ cgen.h
+
+TCDEP_m32r_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-m32r.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/symcat.h $(srcdir)/../opcodes/m32r-desc.h \
+ $(INCDIR)/opcode/cgen.h $(srcdir)/../opcodes/m32r-opc.h \
+ cgen.h
+
+TCDEP_m68k_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-m68k.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h \
+ subsegs.h $(INCDIR)/opcode/m68k.h $(srcdir)/config/m68k-parse.h
+
+TCDEP_m68k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-m68k.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/m68k.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h $(INCDIR)/opcode/m68k.h \
+ $(srcdir)/config/m68k-parse.h
+
+TCDEP_m68k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-m68k.h $(INCDIR)/obstack.h \
+ subsegs.h $(INCDIR)/opcode/m68k.h $(srcdir)/config/m68k-parse.h
+
+TCDEP_m68k_hp300 = $(srcdir)/config/obj-hp300.h $(srcdir)/config/obj-aout.h \
+ $(srcdir)/config/tc-m68k.h $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h $(INCDIR)/opcode/m68k.h \
+ $(srcdir)/config/m68k-parse.h
+
+TCDEP_m88k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-m88k.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/m88k.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h $(srcdir)/config/m88k-opcode.h
+
+TCDEP_m88k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-m88k.h subsegs.h \
+ $(INCDIR)/obstack.h $(srcdir)/config/m88k-opcode.h
+
+TCDEP_mcore_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mcore.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/mcore.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h $(srcdir)/../opcodes/mcore-opc.h
+
+TCDEP_mcore_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-mcore.h subsegs.h \
+ $(INCDIR)/obstack.h $(srcdir)/../opcodes/mcore-opc.h \
+ $(INCDIR)/elf/mcore.h $(INCDIR)/elf/reloc-macros.h
+
+TCDEP_mips_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-mips.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h \
+ $(INCDIR)/opcode/mips.h itbl-ops.h ecoff.h $(INCDIR)/coff/sym.h \
+ $(INCDIR)/coff/ecoff.h
+
+TCDEP_mips_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mips.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/mips.h \
+ itbl-ops.h ecoff.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h
+
+TCDEP_mips_ecoff = $(srcdir)/config/obj-ecoff.h $(srcdir)/config/tc-mips.h \
+ ecoff.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h \
+ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/mips.h \
+ itbl-ops.h
+
+TCDEP_mips_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-mips.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/mips.h itbl-ops.h \
+ $(INCDIR)/elf/mips.h $(INCDIR)/elf/reloc-macros.h ecoff.h \
+ $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h
+
+TCDEP_mn10200_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mn10200.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/mn10200.h
+
+TCDEP_mn10200_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-mn10200.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/mn10200.h
+
+TCDEP_mn10300_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mn10300.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/mn10300.h
+
+TCDEP_mn10300_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-mn10300.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/mn10300.h
+
+TCDEP_ns32k_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-ns32k.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/opcode/ns32k.h \
+ $(INCDIR)/obstack.h
+
+TCDEP_ns32k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-ns32k.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/opcode/ns32k.h $(INCDIR)/obstack.h
+
+TCDEP_ns32k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-ns32k.h $(INCDIR)/opcode/ns32k.h \
+ $(INCDIR)/obstack.h
+
+TCDEP_ppc_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-ppc.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/rs6000.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/ppc.h
+
+TCDEP_ppc_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-ppc.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/ppc.h $(INCDIR)/elf/ppc.h \
+ $(INCDIR)/elf/reloc-macros.h
+
+TCDEP_sh_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-sh.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/sh.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h $(srcdir)/../opcodes/sh-opc.h
+
+TCDEP_sh_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-sh.h subsegs.h \
+ $(INCDIR)/obstack.h $(srcdir)/../opcodes/sh-opc.h
+
+TCDEP_sparc_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-sparc.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h \
+ $(INCDIR)/opcode/sparc.h
+
+TCDEP_sparc_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-sparc.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/sparc.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/sparc.h
+
+TCDEP_sparc_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-sparc.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/sparc.h $(INCDIR)/elf/sparc.h \
+ $(INCDIR)/elf/reloc-macros.h
+
+TCDEP_tahoe_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-tahoe.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h \
+ $(INCDIR)/opcode/tahoe.h
+
+TCDEP_tahoe_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tahoe.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/tahoe.h
+
+TCDEP_tahoe_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tahoe.h $(INCDIR)/obstack.h \
+ $(INCDIR)/opcode/tahoe.h
+
+TCDEP_tic30_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-tic30.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/opcode/tic30.h
+
+TCDEP_tic30_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tic30.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/tic30.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/opcode/tic30.h
+
+TCDEP_tic30_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tic30.h $(INCDIR)/opcode/tic30.h
+
+TCDEP_tic80_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tic80.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/tic80.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/opcode/tic80.h
+
+TCDEP_tic80_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tic80.h $(INCDIR)/opcode/tic80.h
+
+TCDEP_vax_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-vax.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(srcdir)/config/vax-inst.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/vax.h
+
+TCDEP_vax_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-vax.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(srcdir)/config/vax-inst.h $(INCDIR)/obstack.h $(INCDIR)/opcode/vax.h
+
+TCDEP_vax_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-vax.h $(srcdir)/config/vax-inst.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/vax.h
+
+TCDEP_vax_vms = $(srcdir)/config/obj-vms.h $(srcdir)/config/tc-vax.h \
+ $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def $(srcdir)/config/vax-inst.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/vax.h
+
+TCDEP_w65_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-w65.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/w65.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h $(srcdir)/../opcodes/w65-opc.h
+
+TCDEP_w65_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-w65.h subsegs.h \
+ $(INCDIR)/obstack.h $(srcdir)/../opcodes/w65-opc.h
+
+TCDEP_v850_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-v850.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/opcode/v850.h
+
+TCDEP_v850_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-v850.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/v850.h
+
+TCDEP_z8k_coff = $(srcdir)/../opcodes/z8k-opc.h $(srcdir)/config/obj-coff.h \
+ $(srcdir)/config/tc-z8k.h $(INCDIR)/coff/internal.h \
+ $(INCDIR)/coff/z8k.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+
+TCDEP_z8k_elf = $(srcdir)/../opcodes/z8k-opc.h $(srcdir)/config/obj-elf.h \
+ $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
+ $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-z8k.h
+
+TCDEP_hppa_som = $(srcdir)/config/tc-hppa.h subsegs.h \
+ $(INCDIR)/obstack.h $(BFDDIR)/libhppa.h $(INCDIR)/opcode/hppa.h \
+ $(BFDDIR)/som.h
+
+TCDEP_i386_multi = $(TCDEP_i386_coff) $(TCDEP_i386_elf)
+TCDEP_mips_multi = $(TCDEP_mips_coff) $(TCDEP_mips_ecoff) \
+ $(TCDEP_mips_elf)
+
+OBJDEP_a29k_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-a29k.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/obstack.h
+
+OBJDEP_a29k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-a29k.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/a29k.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_a29k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-a29k.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_alpha_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-alpha.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_alpha_ecoff = $(srcdir)/config/obj-ecoff.h $(srcdir)/config/tc-alpha.h \
+ ecoff.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(BFDDIR)/libecoff.h
+
+OBJDEP_alpha_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-alpha.h subsegs.h \
+ $(INCDIR)/obstack.h ecoff.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h \
+ $(INCDIR)/elf/alpha.h $(INCDIR)/elf/reloc-macros.h \
+ $(INCDIR)/aout/aout64.h
+
+OBJDEP_alpha_evax = $(srcdir)/config/obj-evax.h $(srcdir)/config/tc-alpha.h
+OBJDEP_arc_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-arc.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_arc_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-arc.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_arm_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-arm.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/obstack.h
+
+OBJDEP_arm_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-arm.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/arm.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_arm_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-arm.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_d10v_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-d10v.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_d10v_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-d10v.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_d30v_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-d30v.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_d30v_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-d30v.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_fr30_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-fr30.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_fr30_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-fr30.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_h8300_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-h8300.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/h8300.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_h8300_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-h8300.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_h8500_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-h8500.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/h8500.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_h8500_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-h8500.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_hppa_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-hppa.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_hppa_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-hppa.h $(BFDDIR)/elf32-hppa.h \
+ $(BFDDIR)/libhppa.h $(INCDIR)/elf/hppa.h $(INCDIR)/elf/reloc-macros.h \
+ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_i386_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-i386.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/obstack.h
+
+OBJDEP_i386_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-i386.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/i386.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_i386_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-i386.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_i860_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-i860.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/obstack.h
+
+OBJDEP_i860_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-i860.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_i860_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-i860.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_i960_bout = $(srcdir)/config/obj-bout.h $(srcdir)/config/tc-i960.h \
+ $(INCDIR)/obstack.h
+
+OBJDEP_i960_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-i960.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/i960.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_i960_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-i960.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_m32r_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-m32r.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_m32r_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-m32r.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_m68k_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-m68k.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/obstack.h
+
+OBJDEP_m68k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-m68k.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/m68k.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_m68k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-m68k.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_m68k_hp300 = $(srcdir)/config/obj-aout.c $(srcdir)/config/obj-hp300.h \
+ $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-m68k.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/obstack.h
+
+OBJDEP_m88k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-m88k.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/m88k.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_m88k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-m88k.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_mcore_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mcore.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/mcore.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_mcore_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-mcore.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_mips_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-mips.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/obstack.h
+
+OBJDEP_mips_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mips.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_mips_ecoff = $(srcdir)/config/obj-ecoff.h $(srcdir)/config/tc-mips.h \
+ ecoff.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(BFDDIR)/libecoff.h
+
+OBJDEP_mips_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-mips.h subsegs.h \
+ $(INCDIR)/obstack.h ecoff.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h \
+ $(INCDIR)/elf/mips.h $(INCDIR)/elf/reloc-macros.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_mn10200_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mn10200.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_mn10200_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-mn10200.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_mn10300_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mn10300.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_mn10300_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-mn10300.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_ns32k_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-ns32k.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/obstack.h
+
+OBJDEP_ns32k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-ns32k.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_ns32k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-ns32k.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_ppc_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-ppc.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/rs6000.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_ppc_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-ppc.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/elf/ppc.h $(INCDIR)/elf/reloc-macros.h \
+ $(INCDIR)/aout/aout64.h
+
+OBJDEP_sh_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-sh.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/sh.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_sh_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-sh.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_sparc_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-sparc.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/obstack.h
+
+OBJDEP_sparc_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-sparc.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/sparc.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_sparc_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-sparc.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_tahoe_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-tahoe.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/obstack.h
+
+OBJDEP_tahoe_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tahoe.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_tahoe_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tahoe.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_tic30_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-tic30.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/obstack.h
+
+OBJDEP_tic30_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tic30.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/tic30.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_tic30_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tic30.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_tic80_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tic80.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/tic80.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_tic80_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tic80.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_vax_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-vax.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/obstack.h
+
+OBJDEP_vax_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-vax.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_vax_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-vax.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_vax_vms = $(srcdir)/config/obj-vms.h $(srcdir)/config/tc-vax.h \
+ $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def subsegs.h \
+ $(INCDIR)/obstack.h
+
+OBJDEP_w65_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-w65.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/w65.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_w65_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-w65.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_v850_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-v850.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_v850_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-v850.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_z8k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-z8k.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/z8k.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h subsegs.h
+
+OBJDEP_z8k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-z8k.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/aout/aout64.h
+
+OBJDEP_hppa_som = $(srcdir)/config/obj-som.h subsegs.h \
+ $(INCDIR)/obstack.h $(BFDDIR)/libhppa.h $(BFDDIR)/som.h \
+ $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def
+
+OBJDEP_i386_multi = $(OBJDEP_i386_coff) $(OBJDEP_i386_elf)
+OBJDEP_mips_multi = $(OBJDEP_mips_coff) $(OBJDEP_mips_ecoff) \
+ $(OBJDEP_mips_elf)
+
+DEP_a29k_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-a29k.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
+
+DEP_a29k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-a29k.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/a29k.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+
+DEP_a29k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-a29k.h
+
+DEP_alpha_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-alpha.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+
+DEP_alpha_ecoff = $(srcdir)/config/obj-ecoff.h $(srcdir)/config/tc-alpha.h \
+ ecoff.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h
+
+DEP_alpha_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-alpha.h
+
+DEP_alpha_evax = $(srcdir)/config/obj-evax.h $(srcdir)/config/tc-alpha.h
+DEP_arc_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-arc.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+
+DEP_arc_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-arc.h
+
+DEP_arm_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-arm.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
+
+DEP_arm_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-arm.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/arm.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+
+DEP_arm_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-arm.h
+
+DEP_d10v_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-d10v.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+
+DEP_d10v_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-d10v.h
+
+DEP_d30v_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-d30v.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+
+DEP_d30v_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-d30v.h
+
+DEP_fr30_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-fr30.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+
+DEP_fr30_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-fr30.h
+
+DEP_h8300_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-h8300.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/h8300.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+
+DEP_h8300_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-h8300.h
+
+DEP_h8500_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-h8500.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/h8500.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+
+DEP_h8500_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-h8500.h
+
+DEP_hppa_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-hppa.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+
+DEP_hppa_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-hppa.h $(BFDDIR)/elf32-hppa.h \
+ $(BFDDIR)/libhppa.h $(INCDIR)/elf/hppa.h $(INCDIR)/elf/reloc-macros.h
+
+DEP_i386_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-i386.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
+
+DEP_i386_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-i386.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/i386.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+
+DEP_i386_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-i386.h
+
+DEP_i860_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-i860.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
+
+DEP_i860_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-i860.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+
+DEP_i860_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-i860.h
+
+DEP_i960_bout = $(srcdir)/config/obj-bout.h $(srcdir)/config/tc-i960.h
+DEP_i960_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-i960.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/i960.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+
+DEP_i960_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-i960.h
+
+DEP_m32r_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-m32r.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+
+DEP_m32r_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-m32r.h
+
+DEP_m68k_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-m68k.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
+
+DEP_m68k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-m68k.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/m68k.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+
+DEP_m68k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-m68k.h
+
+DEP_m68k_hp300 = $(srcdir)/config/obj-hp300.h $(srcdir)/config/obj-aout.h \
+ $(srcdir)/config/tc-m68k.h $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
+
+DEP_m88k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-m88k.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/m88k.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+
+DEP_m88k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-m88k.h
+
+DEP_mcore_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mcore.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/mcore.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+
+DEP_mcore_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-mcore.h
+
+DEP_mips_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-mips.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
+
+DEP_mips_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mips.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+
+DEP_mips_ecoff = $(srcdir)/config/obj-ecoff.h $(srcdir)/config/tc-mips.h \
+ ecoff.h $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h
+
+DEP_mips_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-mips.h
+
+DEP_mn10200_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mn10200.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+
+DEP_mn10200_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-mn10200.h
+
+DEP_mn10300_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-mn10300.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+
+DEP_mn10300_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-mn10300.h
+
+DEP_ns32k_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-ns32k.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
+
+DEP_ns32k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-ns32k.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+
+DEP_ns32k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-ns32k.h
+
+DEP_ppc_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-ppc.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/rs6000.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+
+DEP_ppc_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-ppc.h
+
+DEP_sh_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-sh.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/sh.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+
+DEP_sh_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-sh.h
+
+DEP_sparc_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-sparc.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
+
+DEP_sparc_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-sparc.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/sparc.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+
+DEP_sparc_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-sparc.h
+
+DEP_tahoe_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-tahoe.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
+
+DEP_tahoe_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tahoe.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+
+DEP_tahoe_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tahoe.h
+
+DEP_tic30_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-tic30.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
+
+DEP_tic30_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tic30.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/tic30.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+
+DEP_tic30_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tic30.h
+
+DEP_tic80_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tic80.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/tic80.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+
+DEP_tic80_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-tic80.h
+
+DEP_vax_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-vax.h \
+ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h
+
+DEP_vax_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-vax.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+
+DEP_vax_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-vax.h
+
+DEP_vax_vms = $(srcdir)/config/obj-vms.h $(srcdir)/config/tc-vax.h \
+ $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def
+
+DEP_w65_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-w65.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/w65.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+
+DEP_w65_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-w65.h
+
+DEP_v850_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-v850.h \
+ $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+
+DEP_v850_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-v850.h
+
+DEP_z8k_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-z8k.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/z8k.h $(BFDDIR)/libcoff.h \
+ $(INCDIR)/bfdlink.h
+
+DEP_z8k_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-z8k.h
+
+DEP_hppa_som = $(BFDDIR)/som.h
+DEP_i386_multi = $(DEP_i386_coff) $(DEP_i386_elf)
+DEP_mips_multi = $(DEP_mips_coff) $(DEP_mips_ecoff) \
+ $(DEP_mips_elf)
+
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES = .gdbinit
+noinst_PROGRAMS = as-new$(EXEEXT) gasp-new$(EXEEXT)
+PROGRAMS = $(noinst_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I.
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+itbl_test_OBJECTS = itbl-parse.o itbl-lex.o
+itbl_test_DEPENDENCIES = itbl-test-ops.o itbl-test.o \
+../libiberty/libiberty.a
+itbl_test_LDFLAGS =
+as_new_OBJECTS = app.o as.o atof-generic.o bignum-copy.o cond.o \
+depend.o ecoff.o ehopt.o expr.o flonum-copy.o flonum-konst.o \
+flonum-mult.o frags.o hash.o input-file.o input-scrub.o listing.o \
+literal.o macro.o messages.o output-file.o read.o sb.o stabs.o \
+subsegs.o symbols.o write.o
+as_new_LDFLAGS =
+gasp_new_OBJECTS = gasp.o macro.o sb.o hash.o
+gasp_new_LDFLAGS =
+SCRIPTS = $(noinst_SCRIPTS)
+
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LEXLIB = @LEXLIB@
+YLWRAP = $(top_srcdir)/../ylwrap
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON = README ./stamp-h.in COPYING ChangeLog Makefile.am \
+Makefile.in NEWS acinclude.m4 aclocal.m4 config.in config/m68k-parse.c \
+configure configure.in gdbinit.in itbl-lex.c itbl-parse.c
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP_ENV = --best
+SOURCES = $(itbl_test_SOURCES) $(as_new_SOURCES) $(EXTRA_as_new_SOURCES) $(gasp_new_SOURCES)
+OBJECTS = $(itbl_test_OBJECTS) $(as_new_OBJECTS) $(gasp_new_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .l .lo .o .s .y
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --cygnus Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ configure.in acinclude.m4
+ cd $(srcdir) && $(ACLOCAL)
+
+config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+$(srcdir)/configure: @MAINTAINER_MODE_TRUE@$(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
+ cd $(srcdir) && $(AUTOCONF)
+
+config.h: stamp-h
+ @if test ! -f $@; then \
+ rm -f stamp-h; \
+ $(MAKE) stamp-h; \
+ else :; fi
+stamp-h: $(srcdir)/config.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES= CONFIG_HEADERS=config.h:config.in \
+ $(SHELL) ./config.status
+ @echo timestamp > stamp-h 2> /dev/null
+$(srcdir)/config.in: @MAINTAINER_MODE_TRUE@$(srcdir)/stamp-h.in
+ @if test ! -f $@; then \
+ rm -f $(srcdir)/stamp-h.in; \
+ $(MAKE) $(srcdir)/stamp-h.in; \
+ else :; fi
+$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOHEADER)
+ @echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null
+
+mostlyclean-hdr:
+
+clean-hdr:
+
+distclean-hdr:
+ -rm -f config.h
+
+maintainer-clean-hdr:
+.gdbinit: $(top_builddir)/config.status gdbinit.in
+ cd $(top_builddir) && CONFIG_FILES=$@:gdbinit.in CONFIG_HEADERS= $(SHELL) ./config.status
+
+mostlyclean-noinstPROGRAMS:
+
+clean-noinstPROGRAMS:
+ -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+
+distclean-noinstPROGRAMS:
+
+maintainer-clean-noinstPROGRAMS:
+
+.c.o:
+ $(COMPILE) -c $<
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.c.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+itbl-test$(EXEEXT): $(itbl_test_OBJECTS) $(itbl_test_DEPENDENCIES)
+ @rm -f itbl-test$(EXEEXT)
+ $(LINK) $(itbl_test_LDFLAGS) $(itbl_test_OBJECTS) $(itbl_test_LDADD) $(LIBS)
+
+as-new$(EXEEXT): $(as_new_OBJECTS) $(as_new_DEPENDENCIES)
+ @rm -f as-new$(EXEEXT)
+ $(LINK) $(as_new_LDFLAGS) $(as_new_OBJECTS) $(as_new_LDADD) $(LIBS)
+
+gasp-new$(EXEEXT): $(gasp_new_OBJECTS) $(gasp_new_DEPENDENCIES)
+ @rm -f gasp-new$(EXEEXT)
+ $(LINK) $(gasp_new_LDFLAGS) $(gasp_new_OBJECTS) $(gasp_new_LDADD) $(LIBS)
+.l.c:
+ $(LEX) $(AM_LFLAGS) $(LFLAGS) $< && mv $(LEX_OUTPUT_ROOT).c $@
+.y.c:
+ $(SHELL) $(YLWRAP) "$(YACC)" $< y.tab.c $*.c y.tab.h $*.h -- $(AM_YFLAGS) $(YFLAGS)
+config/m68k-parse.h: config/m68k-parse.c
+itbl-parse.h: itbl-parse.c
+
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+
+@SET_MAKE@
+
+all-recursive install-data-recursive install-exec-recursive \
+installdirs-recursive install-recursive uninstall-recursive install-info-recursive \
+check-recursive installcheck-recursive info-recursive dvi-recursive:
+ @set fnord $(MAKEFLAGS); amf=$$2; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+ @set fnord $(MAKEFLAGS); amf=$$2; \
+ dot_seen=no; \
+ rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
+ rev="$$subdir $$rev"; \
+ test "$$subdir" = "." && dot_seen=yes; \
+ done; \
+ test "$$dot_seen" = "no" && rev=". $$rev"; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) config.in $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)config.in$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.in $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ -rm -rf $(distdir)
+ GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz
+ mkdir $(distdir)/=build
+ mkdir $(distdir)/=inst
+ dc_install_base=`cd $(distdir)/=inst && pwd`; \
+ cd $(distdir)/=build \
+ && ../configure --srcdir=.. --prefix=$$dc_install_base \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) dist
+ -rm -rf $(distdir)
+ @banner="$(distdir).tar.gz is ready for distribution"; \
+ dashes=`echo "$$banner" | sed s/./=/g`; \
+ echo "$$dashes"; \
+ echo "$$banner"; \
+ echo "$$dashes"
+dist: distdir
+ -chmod -R a+r $(distdir)
+ GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
+ -rm -rf $(distdir)
+dist-all: distdir
+ -chmod -R a+r $(distdir)
+ GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
+ -rm -rf $(distdir)
+distdir: $(DISTFILES)
+ -rm -rf $(distdir)
+ mkdir $(distdir)
+ -chmod 777 $(distdir)
+ @for file in $(DISTFILES); do \
+ if test -f $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ cp -pr $$/$$file $(distdir)/$$file; \
+ else \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+ for subdir in $(SUBDIRS); do \
+ if test "$$subdir" = .; then :; else \
+ test -d $(distdir)/$$subdir \
+ || mkdir $(distdir)/$$subdir \
+ || exit 1; \
+ chmod 777 $(distdir)/$$subdir; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \
+ || exit 1; \
+ fi; \
+ done
+
+DEJATOOL = $(PACKAGE)
+
+RUNTESTDEFAULTFLAGS = --tool $(DEJATOOL) --srcdir $$srcdir
+site.exp: Makefile
+ @echo 'Making a new site.exp file...'
+ @test ! -f site.bak || rm -f site.bak
+ @echo '## these variables are automatically generated by make ##' > $@-t
+ @echo '# Do not edit here. If you wish to override these values' >> $@-t
+ @echo '# edit the last section' >> $@-t
+ @echo 'set tool $(DEJATOOL)' >> $@-t
+ @echo 'set srcdir $(srcdir)' >> $@-t
+ @echo 'set objdir' `pwd` >> $@-t
+ @echo 'set host_alias $(host_alias)' >> $@-t
+ @echo 'set host_triplet $(host_triplet)' >> $@-t
+ @echo 'set target_alias $(target_alias)' >> $@-t
+ @echo 'set target_triplet $(target_triplet)' >> $@-t
+ @echo 'set build_alias $(build_alias)' >> $@-t
+ @echo 'set build_triplet $(build_triplet)' >> $@-t
+ @echo '## All variables above are generated by configure. Do Not Edit ##' >> $@-t
+ @test ! -f site.exp || sed '1,/^## All variables above are.*##/ d' site.exp >> $@-t
+ @test ! -f site.exp || mv site.exp site.bak
+ @mv $@-t site.exp
+info-am:
+info: info-recursive
+dvi-am:
+dvi: dvi-recursive
+check-am:
+ $(MAKE) $(AM_MAKEFLAGS) check-DEJAGNU
+check: check-recursive
+installcheck-am:
+installcheck: installcheck-recursive
+install-info-am:
+install-info: install-info-recursive
+all-recursive-am: config.h
+ $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+install-exec-am: install-exec-local
+install-exec: install-exec-recursive
+
+install-data-am:
+install-data: install-data-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-recursive
+uninstall-am:
+uninstall: uninstall-recursive
+all-am: Makefile $(PROGRAMS) $(SCRIPTS) config.h
+all-redirect: all-recursive-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs: installdirs-recursive
+installdirs-am:
+
+
+mostlyclean-generic:
+ -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ -test -z "itbl-lexlconfig/m68k-parsehconfig/m68k-parsecitbl-parsehitbl-parsec" || rm -f itbl-lexl config/m68k-parseh config/m68k-parsec itbl-parseh itbl-parsec
+mostlyclean-am: mostlyclean-hdr mostlyclean-noinstPROGRAMS \
+ mostlyclean-compile mostlyclean-libtool \
+ mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-recursive
+
+clean-am: clean-hdr clean-noinstPROGRAMS clean-compile clean-libtool \
+ clean-tags clean-generic mostlyclean-am
+
+clean: clean-recursive
+
+distclean-am: distclean-hdr distclean-noinstPROGRAMS distclean-compile \
+ distclean-libtool distclean-tags distclean-generic \
+ clean-am
+ -rm -f libtool
+
+distclean: distclean-recursive
+ -rm -f config.status
+
+maintainer-clean-am: maintainer-clean-hdr \
+ maintainer-clean-noinstPROGRAMS \
+ maintainer-clean-compile maintainer-clean-libtool \
+ maintainer-clean-tags maintainer-clean-generic \
+ distclean-am
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f config.status
+
+.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \
+mostlyclean-noinstPROGRAMS distclean-noinstPROGRAMS \
+clean-noinstPROGRAMS maintainer-clean-noinstPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool install-data-recursive \
+uninstall-data-recursive install-exec-recursive \
+uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \
+all-recursive check-recursive installcheck-recursive info-recursive \
+dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \
+maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir check-DEJAGNU \
+info-am info dvi-am dvi check check-am installcheck-am installcheck \
+install-info-am install-info all-recursive-am install-exec-local \
+install-exec-am install-exec install-data-am install-data install-am \
+install uninstall-am uninstall all-redirect all-am all installdirs-am \
+installdirs mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+po/POTFILES.in: @MAINT@ Makefile
+ for file in $(POTFILES); do echo $$file; done | sort > tmp \
+ && mv tmp $(srcdir)/po/POTFILES.in
+
+$(srcdir)/make-gas.com: stamp-mk.com
+stamp-mk.com: vmsconf.sh Makefile
+ sh $(srcdir)/vmsconf.sh $(GENERIC_OBJS) > new-make.com
+ $(SHELL) $(srcdir)/../move-if-change new-make.com $(srcdir)/make-gas.com
+ touch stamp-mk.com
+diststuff: $(DISTSTUFF) info
+
+$(OBJS): @ALL_OBJ_DEPS@
+
+# Stuff that every object file depends upon. If anything is removed
+# from this list, remove it from dep-in.sed as well.
+$(OBJS): config.h as.h $(TARG_ENV_H) $(OBJ_FORMAT_H) $(TARG_CPU_H) flonum.h \
+ expr.h struc-symbol.h write.h frags.h hash.h read.h symbols.h tc.h \
+ obj.h listing.h bignum.h bit_fix.h $(INCDIR)/libiberty.h asintl.h
+
+check-DEJAGNU: site.exp
+ if [ -d testsuite ]; then \
+ true; \
+ else \
+ mkdir testsuite; \
+ fi
+ rm -f testsuite/site.exp
+ cp site.exp testsuite/site.exp
+ rootme=`pwd`; export rootme; \
+ srcdir=`cd ${srcdir}; pwd` ; export srcdir ; \
+ EXPECT=${EXPECT} ; export EXPECT ; \
+ if [ -f $(top_builddir)/../expect/expect ]; then \
+ TCL_LIBRARY=`cd $(top_srcdir)/../tcl/library && pwd`; \
+ export TCL_LIBRARY; \
+ fi; \
+ runtest=$(RUNTEST); \
+ cd testsuite; \
+ if $(SHELL) -c "$$runtest --version" > /dev/null 2>&1; then \
+ $$runtest --tool $(DEJATOOL) --srcdir $${srcdir}/testsuite \
+ $(RUNTESTFLAGS); \
+ else echo "WARNING: could not find \`runtest'" 1>&2; :;\
+ fi
+
+# The implicit .c.o rule doesn't work for these, perhaps because of
+# the variables, or perhaps because the sources are not on vpath.
+$(TARG_CPU_O): $(TARG_CPU_C) $(TARG_CPU_DEP_@target_cpu_type@)
+ $(COMPILE) -c $(TARG_CPU_C)
+$(ATOF_TARG_O): $(ATOF_TARG_C)
+ $(COMPILE) -c $(ATOF_TARG_C)
+
+# ecoff.c only has full dependencies when ECOFF_DEBUGGING is defined,
+# so the automatic dependency stuff doesn't work.
+ecoff.o : ecoff.c ecoff.h $(INCDIR)/coff/internal.h $(INCDIR)/coff/sym.h \
+ $(INCDIR)/coff/ecoff.h $(INCDIR)/coff/symconst.h \
+ $(INCDIR)/aout/stab_gnu.h
+
+# We need all these explicit rules for the multi stuff. Because of
+# these rules, we don't need one for OBJ_FORMAT_O.
+
+obj-aout.o : $(srcdir)/config/obj-aout.c
+ $(COMPILE) -c $(srcdir)/config/obj-aout.c
+obj-bout.o : $(srcdir)/config/obj-bout.c
+ $(COMPILE) -c $(srcdir)/config/obj-bout.c
+obj-coff.o: $(srcdir)/config/obj-coff.c
+ $(COMPILE) -c $(srcdir)/config/obj-coff.c
+obj-ecoff.o : $(srcdir)/config/obj-ecoff.c
+ $(COMPILE) -c $(srcdir)/config/obj-ecoff.c
+obj-elf.o : $(srcdir)/config/obj-elf.c
+ $(COMPILE) -c $(srcdir)/config/obj-elf.c
+obj-evax.o : $(srcdir)/config/obj-evax.c
+ $(COMPILE) -c $(srcdir)/config/obj-evax.c
+obj-hp300.o : $(srcdir)/config/obj-hp300.c
+ $(COMPILE) -c $(srcdir)/config/obj-hp300.c
+obj-ieee.o : $(srcdir)/config/obj-ieee.c
+ $(COMPILE) -c $(srcdir)/config/obj-ieee.c
+obj-multi.o : $(srcdir)/config/obj-multi.c
+ $(COMPILE) -c $(srcdir)/config/obj-multi.c
+obj-som.o : $(srcdir)/config/obj-som.c
+ $(COMPILE) -c $(srcdir)/config/obj-som.c
+obj-vms.o : $(srcdir)/config/obj-vms.c
+ $(COMPILE) -c $(srcdir)/config/obj-vms.c
+
+e-mipself.o : $(srcdir)/config/e-mipself.c
+ $(COMPILE) -c $(srcdir)/config/e-mipself.c
+e-mipsecoff.o : $(srcdir)/config/e-mipsecoff.c
+ $(COMPILE) -c $(srcdir)/config/e-mipsecoff.c
+e-i386coff.o: $(srcdir)/config/e-i386coff.c
+ $(COMPILE) -c $(srcdir)/config/e-i386coff.c
+e-i386elf.o: $(srcdir)/config/e-i386elf.c
+ $(COMPILE) -c $(srcdir)/config/e-i386elf.c
+
+# If m68k-parse.y is in a different directory, then ylwrap will use an
+# absolute path when it invokes yacc, which will cause yacc to put the
+# absolute path into the generated file. That's a pain when it comes
+# to generating snapshots, because it introduces spurious diffs.
+# Since when we make the snapshots $(srcdir) = ".", we check for that
+# case and handle it differently. This means that anybody who
+# configures with $(srcdir) = "." will have to set their path in the
+# debugger if they want to debug m68k-parse.y. This is bad, but on
+# the other hand it's good that people who use the prebuilt
+# m68k-parse.c don't get a spurious absolute path.
+m68k-parse.c: $(srcdir)/config/m68k-parse.y
+ f=$(srcdir)/config/m68k-parse.y; \
+ if [ $$f = "./config/m68k-parse.y" ]; then \
+ ln -s config/m68k-parse.y . > /dev/null 2>/dev/null || \
+ ln config/m68k-parse.y . > /dev/null 2>/dev/null || \
+ cp config/m68k-parse.y . >/dev/null 2>/dev/null; \
+ f=m68k-parse.y; \
+ else true; fi; \
+ $(SHELL) $(YLWRAP) "$(YACC)" $$f y.tab.c m68k-parse.c --; \
+ if [ $$f = "m68k-parse.y" ]; then \
+ rm -f m68k-parse.y; \
+ else true; fi
+m68k-parse.o: m68k-parse.c $(srcdir)/config/m68k-parse.h
+
+# Don't let the .y.h rule clobber m68k-parse.h.
+m68k-parse.h: ; @true
+$(srcdir)/config/m68k-parse.h: ; @true
+
+# The instruction table specification lexical analyzer and parser.
+
+itbl-lex.c: $(srcdir)/itbl-lex.l
+itbl-lex.o: itbl-lex.c itbl-parse.h
+
+itbl-parse.o: itbl-parse.c itbl-parse.h $(srcdir)/itbl-ops.h
+
+itbl-ops.o: $(srcdir)/itbl-ops.c $(srcdir)/itbl-ops.h itbl-parse.h
+
+itbl-parse.c itbl-parse.h: $(srcdir)/itbl-parse.y
+ $(SHELL) $(YLWRAP) "$(YACC)" $(srcdir)/itbl-parse.y y.tab.c itbl-parse.c y.tab.h itbl-parse.h -- -d
+
+itbl-test-ops.o: $(srcdir)/itbl-ops.c $(srcdir)/itbl-ops.h itbl-parse.h
+ $(COMPILE) -o itbl-test-ops.o -DSTAND_ALONE -c $(srcdir)/itbl-ops.c
+
+itbl-test.o: $(srcdir)/testsuite/gas/all/itbl-test.c $(srcdir)/itbl-ops.h
+ $(COMPILE) -c -DSTAND_ALONE $(srcdir)/testsuite/gas/all/itbl-test.c
+
+cgen.o: cgen.c cgen.h cgen-desc.h subsegs.h \
+ $(INCDIR)/obstack.h $(INCDIR)/opcode/cgen.h \
+ $(srcdir)/../opcodes/$(CGEN_CPU_PREFIX)-desc.h \
+ $(srcdir)/../opcodes/$(CGEN_CPU_PREFIX)-opc.h
+
+.PHONY: install-exec-local install-data-local
+.PHONY: install-exec-bindir install-exec-tooldir
+
+install-exec-local: install-exec-bindir @install_tooldir@
+
+install-exec-bindir: $(noinst_PROGRAMS)
+ $(mkinstalldirs) $(bindir)
+ @list='$(noinst_PROGRAMS)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(bindir)/`echo $$p|sed -e 's/$(EXEEXT)$$//' -e 's/-new//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+ $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(bindir)/`echo $$p|sed -e 's/$(EXEEXT)$$//' -e 's/-new//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ else :; fi; \
+ done
+
+install-exec-tooldir: $(noinst_PROGRAMS)
+ $(mkinstalldirs) $(tooldir)/bin
+ n=`echo as | sed '$(transform)'`; \
+ if [ "$(bindir)/$$n$(EXEEXT)" != "$(tooldir)/bin/as$(EXEEXT)" ]; then \
+ rm -f $(tooldir)/bin/as$(EXEEXT); \
+ ln $(bindir)/$$n$(EXEEXT) $(tooldir)/bin/as$(EXEEXT) >/dev/null 2>/dev/null \
+ || $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) as-new$(EXEEXT) $(tooldir)/bin/as$(EXEEXT); \
+ else \
+ true ; \
+ fi
+
+# These exist for maintenance purposes.
+
+.PHONY: bootstrap bootstrap2 bootstrap3 stage1 stage2 stage3 comparison
+
+bootstrap: as-new
+ $(MAKE) stage1
+ rm -f stage && ln -s stage1 stage
+ $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage/ $(CFLAGS)" libdir=$(libdir) ALLOCA= $(noinst_PROGRAMS)
+ $(MAKE) stage2
+ rm -f stage && ln -s stage2 stage
+ $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage/ $(CFLAGS)" libdir=$(libdir) ALLOCA= $(noinst_PROGRAMS)
+ $(MAKE) comparison against=stage2
+
+bootstrap2:
+ rm -f stage && ln -s stage1 stage
+ $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage/ $(CFLAGS)" libdir=$(libdir) ALLOCA= $(noinst_PROGRAMS)
+ $(MAKE) stage2
+ rm -f stage && ln -s stage2 stage
+ $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage/ $(CFLAGS)" libdir=$(libdir) ALLOCA= $(noinst_PROGRAMS)
+ $(MAKE) comparison against=stage2
+
+bootstrap3:
+ rm -f stage && ln -s stage2 stage
+ $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage/ $(CFLAGS)" libdir=$(libdir) ALLOCA= $(noinst_PROGRAMS)
+ $(MAKE) comparison against=stage2
+
+# Copy the object files from a particular stage into a subdirectory.
+stage1:
+ -mkdir stage1
+ -mv $(STAGESTUFF) stage1
+ if [ -f stage1/as-new$(EXEEXT) -a ! -f stage1/as$(EXEEXT) ] ; then (cd stage1 ; ln -s as-new$(EXEEXT) as$(EXEEXT)) ; fi
+
+stage2:
+ -mkdir stage2
+ -mv $(STAGESTUFF) stage2
+ if [ -f stage2/as-new$(EXEEXT) -a ! -f stage2/as$(EXEEXT) ] ; then (cd stage2 ; ln -s as-new$(EXEEXT) as$(EXEEXT)) ; fi
+
+stage3:
+ -mkdir stage3
+ -mv $(STAGESTUFF) stage3
+ if [ -f stage3/as-new$(EXEEXT) -a ! -f stage3/as$(EXEEXT) ] ; then (cd stage3 ; ln -s as-new as$(EXEEXT)) ; fi
+
+# This rule is derived from corresponding code in the Makefile.in for gcc.
+# The "tail +16c" is to bypass headers which may include timestamps or
+# temporary assembly file names.
+comparison:
+ x=0 ; \
+ for file in *.o ; do \
+ tail +16c ./$$file > tmp-foo1; \
+ if tail +16c ${against}/$$file > tmp-foo2 2>/dev/null ; then \
+ if cmp tmp-foo1 tmp-foo2 ; then \
+ true ; \
+ else \
+ echo $$file differs ; \
+ x=1 ; \
+ fi ; \
+ else true; fi ; \
+ done ; \
+ exit $$x
+ -rm -f tmp-foo*
+
+.PHONY: de-stage1 de-stage2 de-stage3
+
+de-stage1:
+ - (cd stage1 ; rm -f as$(EXEEXT) ; mv -f * ..)
+ - rmdir stage1
+
+de-stage2:
+ - (cd stage2 ; rm -f as$(EXEEXT) ; mv -f * ..)
+ - rmdir stage2
+
+de-stage3:
+ - (cd stage3 ; rm -f as$(EXEEXT) ; mv -f * ..)
+ - rmdir stage3
+
+.dep: dep.sed $(DEP_FILE_DEPS) .tcdep .objdep .dep2
+ rm -f .dep1
+ srcdir=`cd $(srcdir); pwd`; \
+ $(MAKE) DEP=$(DEP) srcdir=$${srcdir} VPATH=$${srcdir} .dep1
+ rm -rf .depdir
+ sed -f dep.sed < .dep1 > .depa
+ sed -f dep.sed < .tcdep >> .depa
+ sed -f dep.sed < .objdep >> .depa
+ sed -f dep.sed < .dep2 >> .depa
+ echo '$$(OBJS): $$(DEP_@target''_cpu_type@_@obj''_format@)' >> .depa
+ echo '$$(TARG_CPU_O): $$(TCDEP_@target''_cpu_type@_@obj''_format@)' >> .depa
+ echo '$$(OBJ_FORMAT_O): $$(OBJDEP_@target''_cpu_type@_@obj''_format@)' >> .depa
+ echo '# IF YOU PUT ANYTHING HERE IT WILL GO AWAY' >> .depa
+ $(SHELL) $(srcdir)/../move-if-change .depa .dep
+
+# This rule needs a mkdep that runs "gcc -MM".
+.dep1: $(CFILES) $(MULTI_CFILES)
+ if [ -d .depdir ]; then true; else mkdir .depdir; fi
+ srcdir=`cd $(srcdir); pwd`; \
+ cd .depdir; \
+ echo '' > targ-cpu.h; \
+ echo '' > obj-format.h; \
+ echo '' > targ-env.h; \
+ echo '' > itbl-cpu.h; \
+ echo '# DO NOT DELETE THIS LINE -- mkdep uses it.' > .dep; \
+ $(DEP) -f .dep -DBFD_ASSEMBLER -I. -I.. -I$${srcdir} -I../../bfd $(DEP_INCLUDES) $?
+ sed -e '/IF YOU PUT ANYTHING/,$$d' < .depdir/.dep > .dep1
+ rm -f .depdir/.dep
+
+# Work out the special dependencies for the tc-*.c files.
+.tcdep: $(TARGET_CPU_CFILES)
+ rm -f .tcdepa
+ if [ -d .depdir ]; then true; else mkdir .depdir; fi
+ srcdir=`cd $(srcdir); pwd`; \
+ cd .depdir; \
+ for c in $(CPU_TYPES); do \
+ for o in $(OBJ_FORMATS); do \
+ $(CPU_OBJ_VALID) \
+ if [ x$${valid} = xyes ]; then \
+ echo '#include "tc-'"$${c}"'.h"' > targ-cpu.h; \
+ echo '#include "obj-'"$${o}"'.h"' > obj-format.h; \
+ echo '#include "te-generic.h"' > targ-env.h; \
+ echo '' > itbl-cpu.h; \
+ echo '#include "opcodes/'"$${c}"'-desc.h"' > cgen-desc.h; \
+ rm -f dummy.c; \
+ cp $${srcdir}/config/tc-$${c}.c dummy.c; \
+ echo '# DO NOT DELETE THIS LINE -- mkdep uses it.' > .dep; \
+ $(DEP) -f .dep -DBFD_ASSEMBLER -I. -I.. -I$${srcdir} -I../../bfd $(DEP_INCLUDES) dummy.c; \
+ sed -e "s/dummy.o: dummy.c/TCDEP_$${c}_$${o} =/" \
+ -e '1,/DO NOT PUT ANYTHING AFTER/d' \
+ -e '/IF YOU PUT ANYTHING/,$$d' \
+ -e '/^$$/d' < .dep >> ../.tcdepa; \
+ rm -f dummy.c; \
+ else true; fi; \
+ done; \
+ done
+ echo 'TCDEP_hppa_som = $$(srcdir)/config/tc-hppa.h subsegs.h \' >> .tcdepa
+ echo ' $$(INCDIR)/obstack.h $$(BFDDIR)/libhppa.h \' >> .tcdepa
+ echo ' $$(INCDIR)/opcode/hppa.h $$(BFDDIR)/som.h' >> .tcdepa
+ # We don't try to handle all multi cases.
+ for c in $(CPU_TYPES); do \
+ $(CPU_MULTI_VALID) \
+ if [ x$${valid} = xyes ]; then \
+ o=ecoff; \
+ $(CPU_OBJ_VALID) \
+ echo 'TCDEP_'"$${c}"'_multi = \' >> .tcdepa; \
+ echo '$$(TCDEP_'"$${c}"'_coff) \' >> .tcdepa; \
+ if [ x$${valid} = xyes ]; then \
+ echo '$$(TCDEP_'"$${c}"'_ecoff) \' >> .tcdepa; \
+ else true; fi; \
+ echo '$$(TCDEP_'"$${c}"'_elf)' >> .tcdepa; \
+ else true; fi; \
+ done
+ mv -f .tcdepa .tcdep
+
+# Work out the special dependencies for the obj-*.c files.
+.objdep: $(OBJ_FORMAT_CFILES)
+ rm -f .objdepa
+ if [ -d .depdir ]; then true; else mkdir .depdir; fi
+ srcdir=`cd $(srcdir); pwd`; \
+ cd .depdir; \
+ for c in $(CPU_TYPES); do \
+ for o in $(OBJ_FORMATS); do \
+ $(CPU_OBJ_VALID) \
+ if [ x$${valid} = xyes ]; then \
+ echo '#include "tc-'"$${c}"'.h"' > targ-cpu.h; \
+ echo '#include "obj-'"$${o}"'.h"' > obj-format.h; \
+ echo '#include "te-generic.h"' > targ-env.h; \
+ echo '' > itbl-cpu.h; \
+ rm -f dummy.c; \
+ cp $${srcdir}/config/obj-$${o}.c dummy.c; \
+ echo '# DO NOT DELETE THIS LINE -- mkdep uses it.' > .dep; \
+ $(DEP) -f .dep -DBFD_ASSEMBLER -I. -I.. -I$${srcdir} -I../../bfd $(DEP_INCLUDES) dummy.c; \
+ sed -e "s/dummy.o: dummy.c/OBJDEP_$${c}_$${o} =/" \
+ -e '1,/DO NOT PUT ANYTHING AFTER/d' \
+ -e '/IF YOU PUT ANYTHING/,$$d' \
+ -e '/^$$/d' < .dep >> ../.objdepa; \
+ rm -f dummy.c; \
+ else true; fi; \
+ done; \
+ done
+ echo 'OBJDEP_hppa_som = $$(srcdir)/config/obj-som.h subsegs.h \' >> .objdepa
+ echo ' $$(INCDIR)/obstack.h $$(BFDDIR)/libhppa.h \' >> .objdepa
+ echo ' $$(BFDDIR)/som.h $$(INCDIR)/aout/stab_gnu.h \' >> .objdepa
+ echo ' $$(INCDIR)/aout/stab.def' >> .objdepa
+ # We don't try to handle all multi cases.
+ for c in $(CPU_TYPES); do \
+ $(CPU_MULTI_VALID) \
+ if [ x$${valid} = xyes ]; then \
+ o=ecoff; \
+ $(CPU_OBJ_VALID) \
+ echo 'OBJDEP_'"$${c}"'_multi = \' >> .objdepa; \
+ echo '$$(OBJDEP_'"$${c}"'_coff) \' >> .objdepa; \
+ if [ x$${valid} = xyes ]; then \
+ echo '$$(OBJDEP_'"$${c}"'_ecoff) \' >> .objdepa; \
+ else true; fi; \
+ echo '$$(OBJDEP_'"$${c}"'_elf)' >> .objdepa; \
+ else true; fi; \
+ done
+ mv -f .objdepa .objdep
+
+# Work out the dependencies for each CPU/OBJ combination.
+# Note that SOM is a special case, because it only works native.
+.dep2: $(TARGET_CPU_HFILES) $(OBJ_FORMAT_HFILES)
+ rm -f .dep2a
+ if [ -d .depdir ]; then true; else mkdir .depdir; fi
+ srcdir=`cd $(srcdir); pwd`; \
+ cd .depdir; \
+ for c in $(CPU_TYPES); do \
+ for o in $(OBJ_FORMATS); do \
+ $(CPU_OBJ_VALID) \
+ if [ x$${valid} = xyes ]; then \
+ echo '#include "tc-'"$${c}"'.h"' > targ-cpu.h; \
+ echo '#include "obj-'"$${o}"'.h"' > dummy.c; \
+ echo '# DO NOT DELETE THIS LINE -- mkdep uses it.' > .dep; \
+ $(DEP) -f .dep -DBFD_ASSEMBLER -I. -I.. -I$${srcdir} -I../../bfd $(DEP_INCLUDES) dummy.c; \
+ sed -e "s/dummy.o: dummy.c/DEP_$${c}_$${o} =/" \
+ -e '1,/DO NOT PUT ANYTHING AFTER/d' \
+ -e '/IF YOU PUT ANYTHING/,$$d' \
+ -e '/^$$/d' < .dep >> ../.dep2a; \
+ else true; fi; \
+ done; \
+ done
+ echo 'DEP_hppa_som = $$(BFDDIR)/som.h' >> .dep2a
+ # We don't try to handle all multi cases.
+ for c in $(CPU_TYPES); do \
+ $(CPU_MULTI_VALID) \
+ if [ x$${valid} = xyes ]; then \
+ o=ecoff; \
+ $(CPU_OBJ_VALID) \
+ echo 'DEP_'"$${c}"'_multi = \' >> .dep2a; \
+ echo '$$(DEP_'"$${c}"'_coff) \' >> .dep2a; \
+ if [ x$${valid} = xyes ]; then \
+ echo '$$(DEP_'"$${c}"'_ecoff) \' >> .dep2a; \
+ else true; fi; \
+ echo '$$(DEP_'"$${c}"'_elf)' >> .dep2a; \
+ else true; fi; \
+ done
+ mv -f .dep2a .dep2
+
+dep.sed: dep-in.sed config.status
+ srcdir=`cd $(srcdir); pwd`; \
+ sed <$(srcdir)/dep-in.sed >dep.sed \
+ -e "s!@INCDIR@!$${srcdir}/../include!" \
+ -e "s!@BFDDIR@!$${srcdir}/../bfd!" \
+ -e "s!@SRCDIR@!$${srcdir}!"
+
+dep: .dep
+ sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < Makefile > tmp-Makefile
+ cat .dep >> tmp-Makefile
+ $(SHELL) $(srcdir)/../move-if-change tmp-Makefile Makefile
+
+dep-in: .dep
+ sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < $(srcdir)/Makefile.in > tmp-Makefile.in
+ cat .dep >> tmp-Makefile.in
+ $(SHELL) $(srcdir)/../move-if-change tmp-Makefile.in $(srcdir)/Makefile.in
+
+dep-am: .dep
+ sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < $(srcdir)/Makefile.am > tmp-Makefile.am
+ cat .dep >> tmp-Makefile.am
+ $(SHELL) $(srcdir)/../move-if-change tmp-Makefile.am $(srcdir)/Makefile.am
+
+.PHONY: dep dep-in dep-am
+
+# DO NOT DELETE THIS LINE -- mkdep uses it.
+# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
+
+app.o: app.c
+as.o: as.c subsegs.h $(INCDIR)/obstack.h output-file.h \
+ sb.h macro.h
+atof-generic.o: atof-generic.c
+bignum-copy.o: bignum-copy.c
+cond.o: cond.c macro.h sb.h $(INCDIR)/obstack.h
+depend.o: depend.c
+ecoff.o: ecoff.c
+ehopt.o: ehopt.c subsegs.h $(INCDIR)/obstack.h $(INCDIR)/elf/dwarf2.h
+expr.o: expr.c $(INCDIR)/obstack.h
+flonum-copy.o: flonum-copy.c
+flonum-konst.o: flonum-konst.c
+flonum-mult.o: flonum-mult.c
+frags.o: frags.c subsegs.h $(INCDIR)/obstack.h
+hash.o: hash.c
+input-file.o: input-file.c input-file.h
+input-scrub.o: input-scrub.c input-file.h sb.h
+listing.o: listing.c input-file.h subsegs.h
+literal.o: literal.c subsegs.h $(INCDIR)/obstack.h
+macro.o: macro.c sb.h macro.h
+messages.o: messages.c
+output-file.o: output-file.c output-file.h
+read.o: read.c subsegs.h $(INCDIR)/obstack.h sb.h macro.h \
+ ecoff.h
+sb.o: sb.c sb.h
+stabs.o: stabs.c $(INCDIR)/obstack.h subsegs.h ecoff.h \
+ $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def
+subsegs.o: subsegs.c subsegs.h $(INCDIR)/obstack.h
+symbols.o: symbols.c $(INCDIR)/obstack.h subsegs.h
+write.o: write.c subsegs.h $(INCDIR)/obstack.h output-file.h
+gasp.o: gasp.c sb.h macro.h
+e-i386coff.o: $(srcdir)/config/e-i386coff.c emul.h \
+ emul-target.h
+e-i386elf.o: $(srcdir)/config/e-i386elf.c emul.h emul-target.h
+e-mipsecoff.o: $(srcdir)/config/e-mipsecoff.c emul.h \
+ emul-target.h
+e-mipself.o: $(srcdir)/config/e-mipself.c emul.h emul-target.h
+$(OBJS): $(DEP_@target_cpu_type@_@obj_format@)
+$(TARG_CPU_O): $(TCDEP_@target_cpu_type@_@obj_format@)
+$(OBJ_FORMAT_O): $(OBJDEP_@target_cpu_type@_@obj_format@)
+# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/gas/NEWS b/gas/NEWS
new file mode 100644
index 0000000000..0844076352
--- /dev/null
+++ b/gas/NEWS
@@ -0,0 +1,287 @@
+-*- text -*-
+
+Changes in 2.10:
+
+Support for the Motorolla MCore 210 processor added.
+
+A new pseudo-op .intel_syntax has been implemented to allow gas to parse i386 assembly
+programs with intel syntax.
+
+New pseudo-ops .func,.endfunc to aid in debugging user-written assembler code.
+
+Full 16-bit mode support for i386.
+
+Greatly improved instruction operand checking for i386. This change will
+produce errors or warnings on incorrect assembly code that previous versions of
+gas accepted. If you get unexpected messages from code that worked with older
+versions of gas, please double check the code before reporting a bug.
+
+Weak symbol support added for COFF targets.
+
+Mitsubishi D30V support added.
+
+Texas Instruments c80 (tms320c80) support added.
+
+Changes in 2.9:
+
+Texas Instruments c30 (tms320c30) support added.
+
+The assembler now optimizes the exception frame information generated by egcs
+and gcc 2.8. The new --traditional-format option disables this optimization.
+
+Added --gstabs option to generate stabs debugging information.
+
+The -a option takes a new suboption, m (e.g., -alm) to expand macros in a
+listing.
+
+Added -MD option to print dependencies.
+
+Changes in 2.8:
+
+BeOS support added.
+
+MIPS16 support added.
+
+Motorola ColdFire 5200 support added (configure for m68k and use -m5200).
+
+Alpha/VMS support added.
+
+m68k options --base-size-default-16, --base-size-default-32,
+--disp-size-default-16, and --disp-size-default-32 added.
+
+The alignment directives now take an optional third argument, which is the
+maximum number of bytes to skip. If doing the alignment would require skipping
+more than the given number of bytes, the alignment is not done at all.
+
+The ELF assembler has a new pseudo-op, .symver, used for symbol versioning.
+
+The -a option takes a new suboption, c (e.g., -alc), to skip false conditionals
+in listings.
+
+Added new pseudo-op, .equiv; it's like .equ, except that it is an error if the
+symbol is already defined.
+
+Changes in 2.7:
+
+The PowerPC assembler now allows the use of symbolic register names (r0, etc.)
+if -mregnames is used. Symbolic names preceded by a '%' (%r0, etc.) can be
+used any time. PowerPC 860 move to/from SPR instructions have been added.
+
+Alpha Linux (ELF) support added.
+
+PowerPC ELF support added.
+
+m68k Linux (ELF) support added.
+
+i960 Hx/Jx support added.
+
+i386/PowerPC gnu-win32 support added.
+
+SCO ELF support added. For OpenServer 5 targets (i386-unknown-sco3.2v5) the
+default is to build COFF-only support. To get a set of tools that generate ELF
+(they'll understand both COFF and ELF), you must configure with
+target=i386-unknown-sco3.2v5elf.
+
+m88k-motorola-sysv3* support added.
+
+Changes in 2.6:
+
+Gas now directly supports macros, without requiring GASP.
+
+Gas now has an MRI assembler compatibility mode. Use -M or --mri to select MRI
+mode. The pseudo-op ``.mri 1'' will switch into the MRI mode until the ``.mri
+0'' is seen; this can be convenient for inline assembler code.
+
+Added --defsym SYM=VALUE option.
+
+Added -mips4 support to MIPS assembler.
+
+Added PIC support to Solaris and SPARC SunOS 4 assembler.
+
+Changes in 2.4:
+
+Converted this directory to use an autoconf-generated configure script.
+
+ARM support, from Richard Earnshaw.
+
+Updated VMS support, from Pat Rankin, including considerably improved debugging
+support.
+
+Support for the control registers in the 68060.
+
+Handles (ignores) a new directive ".this_GCC_requires_the_GNU_assembler", to
+provide for possible future gcc changes, for targets where gas provides some
+features not available in the native assembler. If the native assembler is
+used, it should become obvious pretty quickly what the problem is.
+
+Usage message is available with "--help".
+
+The GNU Assembler Preprocessor (gasp) is included. (Actually, it was in 2.3
+also, but didn't get into the NEWS file.)
+
+Weak symbol support for a.out.
+
+A bug in the listing code which could cause an infinite loop has been fixed.
+Bugs in listings when generating a COFF object file have also been fixed.
+
+Initial i386-svr4 PIC implementation from Eric Youngdale, based on code by Paul
+Kranenburg.
+
+Improved Alpha support. Immediate constants can have a much larger range now.
+Support for the 21164 has been contributed by Digital.
+
+Updated ns32k (pc532-mach, netbsd532) support from Ian Dall.
+
+Changes in 2.3:
+
+Mach i386 support, by David Mackenzie and Ken Raeburn.
+
+RS/6000 and PowerPC support by Ian Taylor.
+
+VMS command scripts (make-gas.com, config-gas.com) have been worked on a bit,
+based on mail received from various people. The `-h#' option should work again
+too.
+
+HP-PA work, by Jeff Law. Note, for the PA, gas-2.3 has been designed to work
+with gdb-4.12 and gcc-2.6. As gcc-2.6 has not been released yet, a special
+version of gcc-2.5.8 has been patched to work with gas-2.3. You can retrieve
+this special version of gcc-2.5.8 via anonymous ftp from jaguar.cs.utah.edu
+in the "dist" directory.
+
+Vax support in gas fixed for BSD, so it builds and seems to run a couple simple
+tests okay. I haven't put it through extensive testing. (GNU make is
+currently required for BSD 4.3 builds.)
+
+Support for the DEC Alpha, running OSF/1 (ECOFF format). The gas support is
+based on code donated by CMU, which used an a.out-based format. I'm afraid the
+alpha-a.out support is pretty badly mangled, and much of it removed; making it
+work will require rewriting it as BFD support for the format anyways.
+
+Irix 5 support.
+
+The test suites have been fixed up a bit, so that they should work with a
+couple different versions of expect and dejagnu.
+
+Symbols' values are now handled internally as expressions, permitting more
+flexibility in evaluating them in some cases. Some details of relocation
+handling have also changed, and simple constant pool management has been added,
+to make the Alpha port easier.
+
+New option "--statistics" for printing out program run times. This is intended
+to be used with the gcc "-Q" option, which prints out times spent in various
+phases of compilation. (You should be able to get all of them printed out with
+"gcc -Q -Wa,--statistics", I think.)
+
+----------------------------------------------------------------
+
+Changes in 2.2:
+
+RS/6000 AIX and MIPS SGI Irix 5 support has been added.
+
+Configurations that are still in development (and therefore are convenient to
+have listed in configure.in) still get rejected without a minor change to
+gas/Makefile.in, so people not doing development work shouldn't get the
+impression that support for such configurations is actually believed to be
+reliable.
+
+The program name (usually "as") is printed when a fatal error message is
+displayed. This should prevent some confusion about the source of occasional
+messages about "internal errors".
+
+ELF support is falling into place. Support for the 386 should be working.
+Support for SPARC Solaris is in. HPPA support from Utah is being integrated.
+
+Symbol values are maintained as expressions instead of being immediately boiled
+down to add-symbol, sub-symbol, and constant. This permits slightly more
+complex calculations involving symbols whose values are not alreadey known.
+
+DBX-style debugging info ("stabs") is now supported for COFF formats.
+If any stabs directives are seen in the source, GAS will create two new
+sections: a ".stab" and a ".stabstr" section. The format of the .stab
+section is nearly identical to the a.out symbol format, and .stabstr is
+its string table. For this to be useful, you must have configured GCC
+to generate stabs (by defining DBX_DEBUGGING_INFO), and must have a GDB
+that can use the stab sections (4.11 or later).
+
+LynxOS, on i386 and m68k platforms, is now supported. SPARC LynxOS
+support is in progress.
+
+----------------------------------------------------------------
+
+Changes in 2.1:
+
+Several small fixes for i386-aix (PS/2) support from Minh Tran-Le have been
+incorporated, but not well tested yet.
+
+Altered the opcode table split for m68k; it should require less VM to compile
+with gcc now.
+
+Some minor adjustments to add (Convergent Technologies') Miniframe support,
+suggested by Ronald Cole.
+
+HPPA support (running OSF only, not HPUX) has been contributed by Utah. This
+includes improved ELF support, which I've started adapting for SPARC Solaris
+2.x. Integration isn't completely, so it probably won't work.
+
+HP9000/300 support, donated by HP, has been merged in.
+
+Ian Taylor has finished the MIPS ECOFF (Ultrix, Irix) support.
+
+Better error messages for unsupported configurations (e.g., hppa-hpux).
+
+Test suite framework is starting to become reasonable.
+
+----------------------------------------------------------------
+
+Changes in 2.0:
+
+Mostly bug fixes.
+
+Some more merging of BFD and ELF code, but ELF still doesn't work.
+
+----------------------------------------------------------------
+
+Changes in 1.94:
+
+BFD merge is partly done. Adventurous souls may try giving configure the
+"--with-bfd-assembler" option. Currently, ELF format requires it, a.out format
+accepts it; SPARC CPU accepts it. It's the default only for OS "elf" or
+"solaris". (ELF isn't really supported yet. It needs work. I've got some
+code from Utah for HP-PA ELF, and from DG for m88k ELF, but they're not fully
+merged yet.)
+
+The 68K opcode table has been split in half. It should now compile under gcc
+without consuming ridiculous amounts of memory.
+
+A couple data structures have been reduced in size. This should result in
+saving a little bit of space at runtime.
+
+Support for MIPS, from OSF and Ralph Campbell, has been merged in. The OSF
+code provided ROSE format support, which I haven't merged in yet. (I can make
+it available, if anyone wants to try it out.) Ralph's code, for BSD 4.4,
+supports a.out format. We don't have ECOFF support in just yet; it's coming.
+
+Support for the Hitachi H8/500 has been added.
+
+VMS host and target support should be working now, thanks chiefly to Eric
+Youngdale.
+
+----------------------------------------------------------------
+
+Changes in 1.93.01:
+
+For m68k, support for more processors has been added: 68040, CPU32, 68851.
+
+For i386, .align is now power-of-two; was number-of-bytes.
+
+For m68k, "%" is now accepted before register names. For COFF format, which
+doesn't use underscore prefixes for C labels, it is required, so variable "a0"
+can be distinguished from the register.
+
+Last public release was 1.38. Lots of configuration changes since then, lots
+of new CPUs and formats, lots of bugs fixed.
+
+
+Local variables:
+fill-column: 79
+End:
diff --git a/gas/README b/gas/README
new file mode 100644
index 0000000000..4ac27db82f
--- /dev/null
+++ b/gas/README
@@ -0,0 +1,274 @@
+ README for GAS
+
+A number of things have changed since version 1 and the wonderful world of gas
+looks very different. There's still a lot of irrelevant garbage lying around
+that will be cleaned up in time. Documentation is scarce, as are logs of the
+changes made since the last gas release. My apologies, and I'll try to get
+something useful.
+
+Unpacking and Installation - Summary
+====================================
+
+See ../binutils/README.
+
+To build just the assembler, make the target all-gas.
+
+Documentation
+=============
+
+The GAS release includes texinfo source for its manual, which can be processed
+into `info' or `dvi' forms.
+
+The DVI form is suitable for printing or displaying; the commands for doing
+this vary from system to system. On many systems, `lpr -d' will print a DVI
+file. On others, you may need to run a program such as `dvips' to convert the
+DVI file into a form your system can print.
+
+If you wish to build the DVI file, you will need to have TeX installed on your
+system. You can rebuild it by typing:
+
+ cd gas/doc
+ make as.dvi
+
+The Info form is viewable with the GNU Emacs `info' subsystem, or the
+standalone `info' program, available as part of the GNU Texinfo distribution.
+To build the info files, you will need the `makeinfo' program. Type:
+
+ cd gas/doc
+ make info
+
+Specifying names for hosts and targets
+======================================
+
+ The specifications used for hosts and targets in the `configure'
+script are based on a three-part naming scheme, but some short
+predefined aliases are also supported. The full naming scheme encodes
+three pieces of information in the following pattern:
+
+ ARCHITECTURE-VENDOR-OS
+
+ For example, you can use the alias `sun4' as a HOST argument or in a
+`--target=TARGET' option. The equivalent full name is
+`sparc-sun-sunos4'.
+
+ The `configure' script accompanying GAS does not provide any query
+facility to list all supported host and target names or aliases.
+`configure' calls the Bourne shell script `config.sub' to map
+abbreviations to full names; you can read the script, if you wish, or
+you can use it to test your guesses on abbreviations--for example:
+
+ % sh config.sub sun4
+ sparc-sun-sunos411
+ % sh config.sub sun3
+ m68k-sun-sunos411
+ % sh config.sub decstation
+ mips-dec-ultrix42
+ % sh config.sub hp300bsd
+ m68k-hp-bsd
+ % sh config.sub i386v
+ i386-unknown-sysv
+ % sh config.sub i786v
+ Invalid configuration `i786v': machine `i786v' not recognized
+
+
+`configure' options
+===================
+
+ Here is a summary of the `configure' options and arguments that are
+most often useful for building GAS. `configure' also has several other
+options not listed here.
+
+ configure [--help]
+ [--prefix=DIR]
+ [--srcdir=PATH]
+ [--host=HOST]
+ [--target=TARGET]
+ [--with-OPTION]
+ [--enable-OPTION]
+
+You may introduce options with a single `-' rather than `--' if you
+prefer; but you may abbreviate option names if you use `--'.
+
+`--help'
+ Print a summary of the options to `configure', and exit.
+
+`-prefix=DIR'
+ Configure the source to install programs and files under directory
+ `DIR'.
+
+`--srcdir=PATH'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--host=HOST'
+ Configure GAS to run on the specified HOST. Normally the
+ configure script can figure this out automatically.
+
+ There is no convenient way to generate a list of all available
+ hosts.
+
+`--target=TARGET'
+ Configure GAS for cross-assembling programs for the specified
+ TARGET. Without this option, GAS is configured to assemble .o files
+ that run on the same machine (HOST) as GAS itself.
+
+ There is no convenient way to generate a list of all available
+ targets.
+
+`--enable-OPTION'
+ These flags tell the program or library being configured to
+ configure itself differently from the default for the specified
+ host/target combination. See below for a list of `--enable'
+ options recognized in the gas distribution.
+
+`configure' accepts other options, for compatibility with configuring
+other GNU tools recursively; but these are the only options that affect
+GAS or its supporting libraries.
+
+The `--enable' options recognized by software in the gas distribution are:
+
+`--enable-targets=...'
+ This causes one or more specified configurations to be added to those for
+ which BFD support is compiled. Currently gas cannot use any format other
+ than its compiled-in default, so this option is not very useful.
+
+`--enable-bfd-assembler'
+ This causes the assembler to use the new code being merged into it to use
+ BFD data structures internally, and use BFD for writing object files.
+ For most targets, this isn't supported yet. For most targets where it has
+ been done, it's already the default. So generally you won't need to use
+ this option.
+
+Supported platforms
+===================
+
+At this point I believe gas to be ansi only code for most target cpu's. That
+is, there should be relatively few, if any host system dependencies. So
+porting (as a cross-assembler) to hosts not yet supported should be fairly
+easy. Porting to a new target shouldn't be too tough if it's a variant of one
+already supported.
+
+Native assembling should work on:
+
+ sun3
+ sun4
+ 386bsd
+ bsd/386
+ delta (m68k-sysv from Motorola)
+ delta88 (m88k-sysv from Motorola)
+ GNU/linux
+ m68k hpux 8.0 (hpux 7.0 may be a problem)
+ vax bsd, ultrix, vms
+ hp9000s300
+ decstation
+ irix 4
+ irix 5
+ miniframe (m68k-sysv from Convergent Technologies)
+ i386-aix (ps/2)
+ hppa (hpux 4.3bsd, osf1)
+ AIX
+ unixware
+ sco 3.2v4.2
+ sco openserver 5.0 (a.k.a. 3.2v5.0 )
+ sparc solaris
+ ns32k (netbsd, lites)
+
+I believe that gas as a cross-assembler can currently be targetted for
+most of the above hosts, plus
+
+ decstation-bsd (a.out format, to be used in BSD 4.4)
+ ebmon29k
+ go32 (DOS on i386, with DJGPP -- old a.out version)
+ h8/300, h8/500 (Hitachi)
+ i386-aix (ps/2)
+ i960-coff
+ mips ecoff (decstation-ultrix, iris, mips magnum, mips-idt-ecoff)
+ Mitsubishi d10v and d30v
+ nindy960
+ powerpc EABI
+ SH (Hitachi)
+ sco386
+ TI tic30 and tic80
+ vax bsd or ultrix?
+ vms
+ vxworks68k
+ vxworks960
+ z8000 (Zilog)
+
+MIPS ECOFF support has been added, but GAS will not run a C-style
+preprocessor. If you want that, rename your file to have a ".S" suffix, and
+run gcc on it. Or run "gcc -xassembler-with-cpp foo.s".
+
+Support for ELF should work now for sparc, hppa, i386, alpha, m68k,
+MIPS, powerpc.
+
+Support for sequent (ns32k), tahoe, i860, m88k may be suffering from bitrot.
+
+If you try out gas on some host or target not listed above, please let me know
+the results, so I can update the list.
+
+Compiler Support Hacks
+======================
+
+On a few targets, the assembler has been modified to support a feature
+that is potentially useful when assembling compiler output, but which
+may confuse assembly language programmers. If assembler encounters a
+.word pseudo-op of the form symbol1-symbol2 (the difference of two
+symbols), and the difference of those two symbols will not fit in 16
+bits, the assembler will create a branch around a long jump to
+symbol1, and insert this into the output directly before the next
+label: The .word will (instead of containing garbage, or giving an
+error message) contain (the address of the long jump)-symbol2. This
+allows the assembler to assemble jump tables that jump to locations
+very far away into code that works properly. If the next label is
+more than 32K away from the .word, you lose (silently); RMS claims
+this will never happen. If the -K option is given, you will get a
+warning message when this happens.
+
+
+REPORTING BUGS IN GAS
+=====================
+
+Bugs in gas should be reported to bug-gnu-utils@gnu.org. They may be
+cross-posted to bug-gcc if they affect the use of gas with gcc. They
+should not be reported just to bug-gcc, since I don't read that list,
+and therefore wouldn't see them.
+
+If you report a bug in GAS, please remember to include:
+
+A description of exactly what went wrong, and exactly what should have
+happened instead.
+
+The type of machine (VAX, 68020, etc) and operating system (BSD, SunOS, DYNIX,
+VMS, etc) GAS was running on.
+
+The configuration name(s) given to the "configure" script. The
+"config.status" file should have this information.
+
+The options given to GAS at run time.
+
+The actual input file that caused the problem.
+
+It is silly to report a bug in GAS without including an input file for GAS.
+Don't ask us to generate the file just because you made it from files you
+think we have access to.
+
+1. You might be mistaken.
+2. It might take us a lot of time to install things to regenerate that file.
+3. We might get a different file from the one you got, and might not see any
+ bug.
+
+To save us these delays and uncertainties, always send the input file for the
+program that failed. A smaller test case that demonstrates the problem is of
+course preferable, but be sure it is a complete input file, and that it really
+does demonstrate the problem; but if paring it down would cause large delays
+in filing the bug report, don't bother.
+
+If the input file is very large, and you are on the internet, you may want to
+make it avaliable for anonymous FTP instead of mailing it. If you do, include
+instructions for FTP'ing it in your bug report.
+
+If you expect to be contributing a large number of test cases, it would be
+helpful if you would look at the test suite included in the release (based on
+the Deja Gnu testing framework, available from the usual ftp sites) and write
+test cases to fit into that framework. This is certainly not required.
diff --git a/gas/README-vms b/gas/README-vms
new file mode 100644
index 0000000000..796c603b4f
--- /dev/null
+++ b/gas/README-vms
@@ -0,0 +1,248 @@
+ This document explains a couple of things that are specific to VMS.
+There are currently two "chapters", the first deals with cross-assembly
+issues, and the second deals with the VMS debugger and GNU-CC.
+
+
+***********************************************************************
+****************** Notes for Cross Assembly with VMS ******************
+***********************************************************************
+
+ If you wish to build gas on a non-VMS system to cross-assemble,
+you should use:
+
+configure ${hosttype} -target=vms
+
+and then follow the usual procedure. The object files generated on
+Unix will be correct from a binary point of view, but the real trick is
+getting them to the VMS machine. The format of the object file is
+a variable-length record, but each record contains binary data. gas
+writes the records in the same format that VMS would expect,
+namely a two-byte count followed by that number of bytes.
+
+ If you try to copy the file to a VMS system using ftp, the ftp
+protocol will screw up the file by looking for nulls (record terminator for
+unix) and it will insert it's own record terminators at that point. This
+will obviously corrupt the file.
+
+ If you try to transfer the file with ftp in binary mode, the
+file itself will not be corrupt, but VMS will think that the file contains
+fixed-length records of 512 bytes. You can use the public-domain FILE
+utility to change this with a command like:
+
+$FILE foo.o/type=variable
+
+If you do not have this utility available, the following program can be
+used to perform this task:
+
+ #include <fab.h>
+
+ #define RME$C_SETRFM 1
+
+ struct FAB * fab;
+
+ main(int argc, char * argv[]){
+ int i, status;
+ fab = (struct FAB*) malloc(sizeof(struct FAB));
+ *fab = cc$rms_fab; /* initialize FAB*/
+ fab->fab$b_fac = FAB$M_PUT;
+ fab->fab$l_fop |= FAB$M_ESC;
+ fab->fab$l_ctx = RME$C_SETRFM;
+ fab->fab$w_ifi = 0;
+ for(i=1;i<argc;i++){
+ printf("Setting %s to variable length records.\n",argv[i]);
+ fab->fab$l_fna = argv[i];
+ fab->fab$b_fns = strlen(argv[i]);
+ status = sys$open(fab,0,0);
+ if((status & 7) != 1) lib$signal(status);
+ fab->fab$b_rfm = FAB$C_VAR;
+ status = sys$modify(fab,0,0);
+ if((status & 7) != 1) lib$signal(status);
+ status = sys$close(fab,0,0);
+ if((status & 7) != 1) lib$signal(status);
+ };
+ }
+
+ If you have NFS running on the VMS system, what you need to do
+depends upon which NFS software you are running on the VMS system. There
+are a number of different TCP/IP packages for VMS available, and only very
+limited testing has been performed. In the tests that has been done so
+far, the contents of the file will always be correct when transferring the
+file via NFS, but the record attributes may or may not be correct.
+
+ One proprietary TCP/IP/NFS package for VMS is known to
+automatically fix the record attributes of the object file if you NFS mount
+a unix disk from the VMS system, and if the file has a ".obj" extension on
+the unix system. Other TCP/IP packages might do this for you as well, but
+they have not been checked.
+
+No matter what method you use to get the file to the VMS system, it is
+always a good idea to check to make sure that it is the correct type by
+doing a "$dir/full" on the object file. The desired record attributes will
+be "None". Undesirable record attributes will be "Stream-LF" or anything
+else.
+
+Once you get the files on the VMS system, you can check their integrity
+with the "$anal/obj" command. (Naturally at some point you should rename
+the .o files to .obj). As far as the debugger is concerned, the records
+will be correct, but the debugger will not be able to find the source files,
+since it only has the file name, and not the full directory specification.
+You must give the debugger some help by telling it which directories to
+search for the individual files - once you have done this you should be
+able to proceed normally.
+
+ It is a good idea to use names for your files which will be valid
+under VMS, since otherwise you will have no way of getting the debugger to
+find the source file when deugging.
+
+The reason for this is that the object file normally contins specific
+information that the debugger can use to positively identify a file, and if
+you are assembling on a unix system this information simply does not exist
+in a meaningful way. You must help the debugger by using the "SET FILE="
+command to tell the debugger where to look for source files. The debugger
+records will be correct, except that the debugger will not be initially
+able to find the source files. You can use the "SET FILE" command to tell
+the debugger where to look for the source files.
+
+I have only tested this with a SVr4 i486 machine, and everything seems to
+work OK, with the limited testing that I have done. Other machines may
+or may not work. You should read the chapters on cross-compilers in the gcc
+manual before fooling with this. Since gas does not need to do any floating
+point arithmetic, the floating point constants that are generated here should
+be correct - the only concern is with constant folding in the main compiler.
+The range and precision of floats and doubles are similar on the 486 (with
+a builtin 80387) and the VAX, although there is a factor of 2 to 4
+difference in the range. The double, as implemented on the 486, is quite
+similar to the G_FLOAT on the VAX.
+
+***********************************************************************
+****************** Notes for using GNU CC with the VMS debugger********
+***********************************************************************
+
+
+ 1) You should be aware that GNU-C, as with any other decent compiler,
+will do things when optimization is turned on that you may not expect.
+Sometimes intermediate results are not written to variables, if they are only
+used in one place, and sometimes variables that are not used at all will not be
+written to the symbol table. Also, parameters to inline functions are often
+inaccessible. You can see the assembly code equivalent by using KP7 in the
+debugger, and from this you can tell if in fact a variable should have the
+value that you expect. You can find out if a variable lives withing a register
+by doing a 'show symbol/addr'.
+
+ 2) Overly complex data types, such as:
+
+int (*(*(*(*(*(* sarr6)[1])[1])[2])[3])[4])[5];
+
+will not be debugged properly, since the debugging record overflows an internal
+debugger buffer. gcc-as will convert these to *void as far as the debugger
+symbol table is concerned, which will avoid any problems, and the assembler
+will give you a message informing you that this has happened.
+
+ 3) You must, of course, compile and link with /debug. If you link
+without debug, you still get traceback table in the executable, but there is no
+symbol table for variables.
+
+ 4) Included in the patches to VMS.C are fixes to two bugs that are
+unrelated to the changes that I have made. One of these made it impossible to
+debug small programs sometimes, and the other caused the debugger to become
+confused about which routine it was in, and give this incorrect info in
+tracebacks.
+
+ 5) If you are using the GNU-C++ compiler, you should modify the
+compiler driver file GNU_CC:[000000]GCC.COM (or GXX.COM). If you have a
+seperate GXX.COM, then you need to change one line in GXX.COM to:
+$ if f$locate("D",p2) .ne. P2_Length then Debug = " ""-G0"""
+ Notice zero---> ^
+If you are using a GCC.COM that does both C and C++, add the following lines to
+GCC.COM:
+
+$!
+$! Use old style debugging records for VMS
+$!
+$ if (Debug.nes."" ).and. Plus then Debug = " ""-G0"""
+
+after the variables Plus and Debug are set. The reason for this, is that C++
+compiler by default generates debugging records that are more complex,
+with many new syntactical elements that allow for the new features of the
+language. The -G0 switch tells the C++ compiler to use the old style debugging
+records. Until the debugger understands C++ there is not any point to try and
+use the expanded syntax.
+
+ 6) When you have nested scopes, i.e.:
+main(){
+ int i;
+ {int i;
+ {int i;
+};};}
+and you say "EXAM i" the debugger needs to figure out which variable you
+actually want to reference. I have arranged things to define a block to the
+debugger when you use brackets to enter a new scope, so in the example above,
+the variables would be described as:
+TEST\main\i
+TEST\main\$0\i
+TEST\main\$0\$0\i
+At each level, the block name is a number with a dollar sign prefix, the
+numbers start with 0 and count upward. When you say EXAM i, the debugger looks
+at the current PC, and decides which block it is currently in. It works from
+the innermost level outward until it finds a block that has the variable "i"
+defined. You can always specify the scope explicitly.
+
+ 7) With C++, there can be a lot of inline functions, and it would be
+rather restrictive to force the user to debug the program by converting all of
+the inline functions to normal functions. What I have done is to essentially
+"add" (with the debugger) source lines from the include files that contain the
+inline functions. Thus when you step into an inline function it appears as if
+you have called the function, and you can examine variables and so forth.
+There are several *very* important differences, however. First of all, since
+there is no function call involved, you cannot step over the inline function
+call - you always step into it. Secondly, since the same source lines are used
+in many locations, there is a seperate copy of the source for *each* usage.
+Without this, breakpoints do not work, since we must have a 1-to-1 mapping
+between source lines and PC.
+ Since you cannot step over inline function calls, it can be a real pain
+if you are not really interested in what is going on for that function call.
+What I have done is to use the "-D" switch for the assembler to toggle the
+following behavior. With the "-D" switch, all inline functions are included in
+the object file, and you can debug everything. Without the "-D" switch
+(default case with VMS implementation), inline functions are included *only* if
+they did not come from system header files (i.e. from GNU_CC_INCLUDE: or
+GNU_GXX_INCLUDE:). Thus, without the switch the user only debugs his/her own
+inline functions, and not the system ones. (This is especially useful if you do
+a lot of stream I/O in C++). This probably will not provide enough granularity
+for many users, but for now this is still somewhat experimental, and I would
+like to reflect upon it and get some feedback before I go any further.
+Possible solutions include an interactive prompting, a logical name, or a new
+command line option in gcc.c (which is then passed through somehow to the guts
+of the assembler).
+ The inline functions from header files appear after the source code
+for the source file. This has the advantage that the source file itself is
+numbered with the same line numbers that you get with an editor. In addition,
+the entire header file is not included, since the assembler makes a list of
+the min and max source lines that are used, and only includes those lines from
+the first to the last actually used. (It is easy to change it to include the
+whole file).
+
+ 8) When you are debugging C++ objects, the object "this" is refered to
+as "$this". Actually, the compiler writes it as ".this", but the period is
+not good for the debugger, so I have a routine to convert it to a $. (It
+actually converts all periods to $, but only for variables, since this was
+intended to allow us to access "this".
+
+ 9) If you use the asm("...") keyword for global symbols, you will not
+be able to see that symbol with the debugger. The reason is that there are two
+records for the symbol stored in the data structures of the assembler. One
+contains the info such as psect number and offset, and the other one contains
+the information having to do with the data type of the variable. In order to
+debug as symbol, you need to be able to coorelate these records, and the only
+way to do this is by name. The record with the storage attributes will take
+the name used in the asm directive, and the record that specifies the data type
+has the actual variable name, and thus when you use the asm directive to change
+a variable name, the symbol becomes invisible.
+
+ 10) Older versions of the compiler ( GNU-C 1.37.92 and earlier) place
+global constants in the text psect. This is unfortunate, since to the linker
+this appears to be an entry point. I sent a patch to the compiler to RMS,
+which will generate a .const section for these variables, and patched the
+assembler to put these variables into a psect just like that for normal
+variables, except that they are marked NOWRT. static constants are still
+placed in the text psect, since there is no need for any external access.
diff --git a/gas/acinclude.m4 b/gas/acinclude.m4
new file mode 100644
index 0000000000..31a2c1632f
--- /dev/null
+++ b/gas/acinclude.m4
@@ -0,0 +1,56 @@
+dnl GAS_CHECK_DECL_NEEDED(name, typedefname, typedef, headers)
+AC_DEFUN(GAS_CHECK_DECL_NEEDED,[
+AC_MSG_CHECKING(whether declaration is required for $1)
+AC_CACHE_VAL(gas_cv_decl_needed_$1,
+AC_TRY_LINK([$4],
+[
+typedef $3;
+$2 x;
+x = ($2) $1;
+], gas_cv_decl_needed_$1=no, gas_cv_decl_needed_$1=yes))dnl
+AC_MSG_RESULT($gas_cv_decl_needed_$1)
+if test $gas_cv_decl_needed_$1 = yes; then
+ AC_DEFINE([NEED_DECLARATION_]translit($1, [a-z], [A-Z]), 1,
+ [Define if $1 is not declared in system header files.])
+fi
+])dnl
+dnl
+dnl Some non-ANSI preprocessors botch requoting inside strings. That's bad
+dnl enough, but on some of those systems, the assert macro relies on requoting
+dnl working properly!
+dnl GAS_WORKING_ASSERT
+AC_DEFUN(GAS_WORKING_ASSERT,
+[AC_MSG_CHECKING([for working assert macro])
+AC_CACHE_VAL(gas_cv_assert_ok,
+AC_TRY_LINK([#include <assert.h>
+#include <stdio.h>], [
+/* check for requoting problems */
+static int a, b, c, d;
+static char *s;
+assert (!strcmp(s, "foo bar baz quux"));
+/* check for newline handling */
+assert (a == b
+ || c == d);
+], gas_cv_assert_ok=yes, gas_cv_assert_ok=no))dnl
+AC_MSG_RESULT($gas_cv_assert_ok)
+test $gas_cv_assert_ok = yes || AC_DEFINE(BROKEN_ASSERT, 1, [assert broken?])
+])dnl
+dnl
+dnl Since many Bourne shell implementations lack subroutines, use this
+dnl hack to simplify the code in configure.in.
+dnl GAS_UNIQ(listvar)
+AC_DEFUN(GAS_UNIQ,
+[_gas_uniq_list="[$]$1"
+_gas_uniq_newlist=""
+dnl Protect against empty input list.
+for _gas_uniq_i in _gas_uniq_dummy [$]_gas_uniq_list ; do
+ case [$]_gas_uniq_i in
+ _gas_uniq_dummy) ;;
+ *) case " [$]_gas_uniq_newlist " in
+ *" [$]_gas_uniq_i "*) ;;
+ *) _gas_uniq_newlist="[$]_gas_uniq_newlist [$]_gas_uniq_i" ;;
+ esac ;;
+ esac
+done
+$1=[$]_gas_uniq_newlist
+])dnl
diff --git a/gas/aclocal.m4 b/gas/aclocal.m4
new file mode 100644
index 0000000000..1c6d60cb23
--- /dev/null
+++ b/gas/aclocal.m4
@@ -0,0 +1,822 @@
+dnl aclocal.m4 generated automatically by aclocal 1.4
+
+dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+dnl PARTICULAR PURPOSE.
+
+dnl GAS_CHECK_DECL_NEEDED(name, typedefname, typedef, headers)
+AC_DEFUN(GAS_CHECK_DECL_NEEDED,[
+AC_MSG_CHECKING(whether declaration is required for $1)
+AC_CACHE_VAL(gas_cv_decl_needed_$1,
+AC_TRY_LINK([$4],
+[
+typedef $3;
+$2 x;
+x = ($2) $1;
+], gas_cv_decl_needed_$1=no, gas_cv_decl_needed_$1=yes))dnl
+AC_MSG_RESULT($gas_cv_decl_needed_$1)
+if test $gas_cv_decl_needed_$1 = yes; then
+ AC_DEFINE([NEED_DECLARATION_]translit($1, [a-z], [A-Z]), 1,
+ [Define if $1 is not declared in system header files.])
+fi
+])dnl
+dnl
+dnl Some non-ANSI preprocessors botch requoting inside strings. That's bad
+dnl enough, but on some of those systems, the assert macro relies on requoting
+dnl working properly!
+dnl GAS_WORKING_ASSERT
+AC_DEFUN(GAS_WORKING_ASSERT,
+[AC_MSG_CHECKING([for working assert macro])
+AC_CACHE_VAL(gas_cv_assert_ok,
+AC_TRY_LINK([#include <assert.h>
+#include <stdio.h>], [
+/* check for requoting problems */
+static int a, b, c, d;
+static char *s;
+assert (!strcmp(s, "foo bar baz quux"));
+/* check for newline handling */
+assert (a == b
+ || c == d);
+], gas_cv_assert_ok=yes, gas_cv_assert_ok=no))dnl
+AC_MSG_RESULT($gas_cv_assert_ok)
+test $gas_cv_assert_ok = yes || AC_DEFINE(BROKEN_ASSERT, 1, [assert broken?])
+])dnl
+dnl
+dnl Since many Bourne shell implementations lack subroutines, use this
+dnl hack to simplify the code in configure.in.
+dnl GAS_UNIQ(listvar)
+AC_DEFUN(GAS_UNIQ,
+[_gas_uniq_list="[$]$1"
+_gas_uniq_newlist=""
+dnl Protect against empty input list.
+for _gas_uniq_i in _gas_uniq_dummy [$]_gas_uniq_list ; do
+ case [$]_gas_uniq_i in
+ _gas_uniq_dummy) ;;
+ *) case " [$]_gas_uniq_newlist " in
+ *" [$]_gas_uniq_i "*) ;;
+ *) _gas_uniq_newlist="[$]_gas_uniq_newlist [$]_gas_uniq_i" ;;
+ esac ;;
+ esac
+done
+$1=[$]_gas_uniq_newlist
+])dnl
+
+# Do all the work for Automake. This macro actually does too much --
+# some checks are only needed if your package does certain things.
+# But this isn't really a big deal.
+
+# serial 1
+
+dnl Usage:
+dnl AM_INIT_AUTOMAKE(package,version, [no-define])
+
+AC_DEFUN(AM_INIT_AUTOMAKE,
+[AC_REQUIRE([AC_PROG_INSTALL])
+PACKAGE=[$1]
+AC_SUBST(PACKAGE)
+VERSION=[$2]
+AC_SUBST(VERSION)
+dnl test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+fi
+ifelse([$3],,
+AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]))
+AC_REQUIRE([AM_SANITY_CHECK])
+AC_REQUIRE([AC_ARG_PROGRAM])
+dnl FIXME This is truly gross.
+missing_dir=`cd $ac_aux_dir && pwd`
+AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
+AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
+AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
+AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
+AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
+AC_REQUIRE([AC_PROG_MAKE_SET])])
+
+#
+# Check to make sure that the build environment is sane.
+#
+
+AC_DEFUN(AM_SANITY_CHECK,
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
+ if test "[$]*" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftestfile`
+ fi
+ if test "[$]*" != "X $srcdir/configure conftestfile" \
+ && test "[$]*" != "X conftestfile $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+alias in your environment])
+ fi
+
+ test "[$]2" = conftestfile
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+rm -f conftest*
+AC_MSG_RESULT(yes)])
+
+dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
+dnl The program must properly implement --version.
+AC_DEFUN(AM_MISSING_PROG,
+[AC_MSG_CHECKING(for working $2)
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if ($2 --version) < /dev/null > /dev/null 2>&1; then
+ $1=$2
+ AC_MSG_RESULT(found)
+else
+ $1="$3/missing $2"
+ AC_MSG_RESULT(missing)
+fi
+AC_SUBST($1)])
+
+
+# serial 25 AM_PROG_LIBTOOL
+AC_DEFUN(AM_PROG_LIBTOOL,
+[AC_REQUIRE([AM_ENABLE_SHARED])dnl
+AC_REQUIRE([AM_ENABLE_STATIC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([AC_PROG_RANLIB])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AM_PROG_LD])dnl
+AC_REQUIRE([AM_PROG_NM])dnl
+AC_REQUIRE([AC_PROG_LN_S])dnl
+dnl
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+# Check for any special flags to pass to ltconfig.
+libtool_flags=
+test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared"
+test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static"
+test "$silent" = yes && libtool_flags="$libtool_flags --silent"
+test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc"
+test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld"
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case "$host" in
+*-*-irix6*)
+ # Find out which ABI we are using.
+ echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case "`/usr/bin/file conftest.o`" in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ CFLAGS="$CFLAGS -belf"
+ ;;
+
+*-*-cygwin*)
+ AM_SYS_LIBTOOL_CYGWIN
+ ;;
+
+esac
+
+# Actually configure libtool. ac_aux_dir is where install-sh is found.
+CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \
+LD="$LD" NM="$NM" RANLIB="$RANLIB" LN_S="$LN_S" \
+DLLTOOL="$DLLTOOL" AS="$AS" \
+${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \
+$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $host \
+|| AC_MSG_ERROR([libtool configure failed])
+
+# Redirect the config.log output again, so that the ltconfig log is not
+# clobbered by the next message.
+exec 5>>./config.log
+])
+
+# AM_ENABLE_SHARED - implement the --enable-shared flag
+# Usage: AM_ENABLE_SHARED[(DEFAULT)]
+# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to
+# `yes'.
+AC_DEFUN(AM_ENABLE_SHARED,
+[define([AM_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(shared,
+changequote(<<, >>)dnl
+<< --enable-shared[=PKGS] build shared libraries [default=>>AM_ENABLE_SHARED_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_shared=yes ;;
+no) enable_shared=no ;;
+*)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+ for pkg in $enableval; do
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac],
+enable_shared=AM_ENABLE_SHARED_DEFAULT)dnl
+])
+
+# AM_DISABLE_SHARED - set the default shared flag to --disable-shared
+AC_DEFUN(AM_DISABLE_SHARED,
+[AM_ENABLE_SHARED(no)])
+
+# AM_DISABLE_STATIC - set the default static flag to --disable-static
+AC_DEFUN(AM_DISABLE_STATIC,
+[AM_ENABLE_STATIC(no)])
+
+# AM_ENABLE_STATIC - implement the --enable-static flag
+# Usage: AM_ENABLE_STATIC[(DEFAULT)]
+# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to
+# `yes'.
+AC_DEFUN(AM_ENABLE_STATIC,
+[define([AM_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(static,
+changequote(<<, >>)dnl
+<< --enable-static[=PKGS] build static libraries [default=>>AM_ENABLE_STATIC_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_static=yes ;;
+no) enable_static=no ;;
+*)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+ for pkg in $enableval; do
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac],
+enable_static=AM_ENABLE_STATIC_DEFAULT)dnl
+])
+
+
+# AM_PROG_LD - find the path to the GNU or non-GNU linker
+AC_DEFUN(AM_PROG_LD,
+[AC_ARG_WITH(gnu-ld,
+[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]],
+test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
+AC_REQUIRE([AC_PROG_CC])
+ac_prog=ld
+if test "$ac_cv_prog_gcc" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ AC_MSG_CHECKING([for ld used by GCC])
+ ac_prog=`($CC -print-prog-name=ld) 2>&5`
+ case "$ac_prog" in
+ # Accept absolute paths.
+changequote(,)dnl
+ /* | [A-Za-z]:\\*)
+changequote([,])dnl
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ AC_MSG_CHECKING([for GNU ld])
+else
+ AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(ac_cv_path_LD,
+[if test -z "$LD"; then
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog"; then
+ ac_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+ test "$with_gnu_ld" != no && break
+ else
+ test "$with_gnu_ld" != yes && break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+else
+ ac_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$ac_cv_path_LD"
+if test -n "$LD"; then
+ AC_MSG_RESULT($LD)
+else
+ AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_SUBST(LD)
+AM_PROG_LD_GNU
+])
+
+AC_DEFUN(AM_PROG_LD_GNU,
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], ac_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+ ac_cv_prog_gnu_ld=yes
+else
+ ac_cv_prog_gnu_ld=no
+fi])
+])
+
+# AM_PROG_NM - find the path to a BSD-compatible name lister
+AC_DEFUN(AM_PROG_NM,
+[AC_MSG_CHECKING([for BSD-compatible nm])
+AC_CACHE_VAL(ac_cv_path_NM,
+[if test -n "$NM"; then
+ # Let the user override the test.
+ ac_cv_path_NM="$NM"
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in /usr/ucb /usr/ccs/bin $PATH /bin; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/nm; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+ ac_cv_path_NM="$ac_dir/nm -B"
+ elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+ ac_cv_path_NM="$ac_dir/nm -p"
+ else
+ ac_cv_path_NM="$ac_dir/nm"
+ fi
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm
+fi])
+NM="$ac_cv_path_NM"
+AC_MSG_RESULT([$NM])
+AC_SUBST(NM)
+])
+
+# AM_SYS_LIBTOOL_CYGWIN - find tools needed on cygwin
+AC_DEFUN(AM_SYS_LIBTOOL_CYGWIN,
+[AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+AC_CHECK_TOOL(AS, as, false)
+])
+
+# Like AC_CONFIG_HEADER, but automatically create stamp file.
+
+AC_DEFUN(AM_CONFIG_HEADER,
+[AC_PREREQ([2.12])
+AC_CONFIG_HEADER([$1])
+dnl When config.status generates a header, we must update the stamp-h file.
+dnl This file resides in the same directory as the config header
+dnl that is generated. We must strip everything past the first ":",
+dnl and everything past the last "/".
+AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl
+ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>,
+<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>,
+<<am_indx=1
+for am_file in <<$1>>; do
+ case " <<$>>CONFIG_HEADERS " in
+ *" <<$>>am_file "*<<)>>
+ echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx
+ ;;
+ esac
+ am_indx=`expr "<<$>>am_indx" + 1`
+done<<>>dnl>>)
+changequote([,]))])
+
+
+dnl AM_PROG_LEX
+dnl Look for flex, lex or missing, then run AC_PROG_LEX and AC_DECL_YYTEXT
+AC_DEFUN(AM_PROG_LEX,
+[missing_dir=ifelse([$1],,`cd $ac_aux_dir && pwd`,$1)
+AC_CHECK_PROGS(LEX, flex lex, "$missing_dir/missing flex")
+AC_PROG_LEX
+AC_DECL_YYTEXT])
+
+# This file is derived from `gettext.m4'. The difference is that the
+# included macros assume Cygnus-style source and build trees.
+
+# Macro to add for using GNU gettext.
+# Ulrich Drepper <drepper@cygnus.com>, 1995.
+#
+# This file file be copied and used freely without restrictions. It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+# serial 3
+
+AC_DEFUN(CY_WITH_NLS,
+ [AC_MSG_CHECKING([whether NLS is requested])
+ dnl Default is enabled NLS
+ AC_ARG_ENABLE(nls,
+ [ --disable-nls do not use Native Language Support],
+ USE_NLS=$enableval, USE_NLS=yes)
+ AC_MSG_RESULT($USE_NLS)
+ AC_SUBST(USE_NLS)
+
+ USE_INCLUDED_LIBINTL=no
+
+ dnl If we use NLS figure out what method
+ if test "$USE_NLS" = "yes"; then
+ AC_DEFINE(ENABLE_NLS, 1, [Define to 1 if NLS is requested])
+ AC_MSG_CHECKING([whether included gettext is requested])
+ AC_ARG_WITH(included-gettext,
+ [ --with-included-gettext use the GNU gettext library included here],
+ nls_cv_force_use_gnu_gettext=$withval,
+ nls_cv_force_use_gnu_gettext=no)
+ AC_MSG_RESULT($nls_cv_force_use_gnu_gettext)
+
+ nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext"
+ if test "$nls_cv_force_use_gnu_gettext" != "yes"; then
+ dnl User does not insist on using GNU NLS library. Figure out what
+ dnl to use. If gettext or catgets are available (in this order) we
+ dnl use this. Else we have to fall back to GNU NLS library.
+ dnl catgets is only used if permitted by option --with-catgets.
+ nls_cv_header_intl=
+ nls_cv_header_libgt=
+ CATOBJEXT=NONE
+
+ AC_CHECK_HEADER(libintl.h,
+ [AC_CACHE_CHECK([for gettext in libc], gt_cv_func_gettext_libc,
+ [AC_TRY_LINK([#include <libintl.h>], [return (int) gettext ("")],
+ gt_cv_func_gettext_libc=yes, gt_cv_func_gettext_libc=no)])
+
+ if test "$gt_cv_func_gettext_libc" != "yes"; then
+ AC_CHECK_LIB(intl, bindtextdomain,
+ [AC_CACHE_CHECK([for gettext in libintl],
+ gt_cv_func_gettext_libintl,
+ [AC_TRY_LINK([], [return (int) gettext ("")],
+ gt_cv_func_gettext_libintl=yes,
+ gt_cv_func_gettext_libintl=no)])])
+ fi
+
+ if test "$gt_cv_func_gettext_libc" = "yes" \
+ || test "$gt_cv_func_gettext_libintl" = "yes"; then
+ AC_DEFINE(HAVE_GETTEXT, 1,
+ [Define as 1 if you have gettext and don't want to use GNU gettext.])
+ AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl
+ if test "$MSGFMT" != "no"; then
+ AC_CHECK_FUNCS(dcgettext)
+ AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
+ AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
+ AC_TRY_LINK(, [extern int _nl_msg_cat_cntr;
+ return _nl_msg_cat_cntr],
+ [CATOBJEXT=.gmo
+ DATADIRNAME=share],
+ [CATOBJEXT=.mo
+ DATADIRNAME=lib])
+ INSTOBJEXT=.mo
+ fi
+ fi
+ ])
+
+ dnl In the standard gettext, we would now check for catgets.
+ dnl However, we never want to use catgets for our releases.
+
+ if test "$CATOBJEXT" = "NONE"; then
+ dnl Neither gettext nor catgets in included in the C library.
+ dnl Fall back on GNU gettext library.
+ nls_cv_use_gnu_gettext=yes
+ fi
+ fi
+
+ if test "$nls_cv_use_gnu_gettext" = "yes"; then
+ dnl Mark actions used to generate GNU NLS library.
+ INTLOBJS="\$(GETTOBJS)"
+ AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], msgfmt)
+ AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
+ AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
+ AC_SUBST(MSGFMT)
+ USE_INCLUDED_LIBINTL=yes
+ CATOBJEXT=.gmo
+ INSTOBJEXT=.mo
+ DATADIRNAME=share
+ INTLDEPS='$(top_builddir)/../intl/libintl.a'
+ INTLLIBS=$INTLDEPS
+ LIBS=`echo $LIBS | sed -e 's/-lintl//'`
+ nls_cv_header_intl=libintl.h
+ nls_cv_header_libgt=libgettext.h
+ fi
+
+ dnl Test whether we really found GNU xgettext.
+ if test "$XGETTEXT" != ":"; then
+ dnl If it is no GNU xgettext we define it as : so that the
+ dnl Makefiles still can work.
+ if $XGETTEXT --omit-header /dev/null 2> /dev/null; then
+ : ;
+ else
+ AC_MSG_RESULT(
+ [found xgettext programs is not GNU xgettext; ignore it])
+ XGETTEXT=":"
+ fi
+ fi
+
+ # We need to process the po/ directory.
+ POSUB=po
+ else
+ DATADIRNAME=share
+ nls_cv_header_intl=libintl.h
+ nls_cv_header_libgt=libgettext.h
+ fi
+
+ # If this is used in GNU gettext we have to set USE_NLS to `yes'
+ # because some of the sources are only built for this goal.
+ if test "$PACKAGE" = gettext; then
+ USE_NLS=yes
+ USE_INCLUDED_LIBINTL=yes
+ fi
+
+ dnl These rules are solely for the distribution goal. While doing this
+ dnl we only have to keep exactly one list of the available catalogs
+ dnl in configure.in.
+ for lang in $ALL_LINGUAS; do
+ GMOFILES="$GMOFILES $lang.gmo"
+ POFILES="$POFILES $lang.po"
+ done
+
+ dnl Make all variables we use known to autoconf.
+ AC_SUBST(USE_INCLUDED_LIBINTL)
+ AC_SUBST(CATALOGS)
+ AC_SUBST(CATOBJEXT)
+ AC_SUBST(DATADIRNAME)
+ AC_SUBST(GMOFILES)
+ AC_SUBST(INSTOBJEXT)
+ AC_SUBST(INTLDEPS)
+ AC_SUBST(INTLLIBS)
+ AC_SUBST(INTLOBJS)
+ AC_SUBST(POFILES)
+ AC_SUBST(POSUB)
+ ])
+
+AC_DEFUN(CY_GNU_GETTEXT,
+ [AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+ AC_REQUIRE([AC_PROG_CC])dnl
+ AC_REQUIRE([AC_PROG_RANLIB])dnl
+ AC_REQUIRE([AC_ISC_POSIX])dnl
+ AC_REQUIRE([AC_HEADER_STDC])dnl
+ AC_REQUIRE([AC_C_CONST])dnl
+ AC_REQUIRE([AC_C_INLINE])dnl
+ AC_REQUIRE([AC_TYPE_OFF_T])dnl
+ AC_REQUIRE([AC_TYPE_SIZE_T])dnl
+ AC_REQUIRE([AC_FUNC_ALLOCA])dnl
+ AC_REQUIRE([AC_FUNC_MMAP])dnl
+
+ AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h string.h \
+unistd.h values.h sys/param.h])
+ AC_CHECK_FUNCS([getcwd munmap putenv setenv setlocale strchr strcasecmp \
+__argz_count __argz_stringify __argz_next])
+
+ if test "${ac_cv_func_stpcpy+set}" != "set"; then
+ AC_CHECK_FUNCS(stpcpy)
+ fi
+ if test "${ac_cv_func_stpcpy}" = "yes"; then
+ AC_DEFINE(HAVE_STPCPY, 1, [Define if you have the stpcpy function])
+ fi
+
+ AM_LC_MESSAGES
+ CY_WITH_NLS
+
+ if test "x$CATOBJEXT" != "x"; then
+ if test "x$ALL_LINGUAS" = "x"; then
+ LINGUAS=
+ else
+ AC_MSG_CHECKING(for catalogs to be installed)
+ NEW_LINGUAS=
+ for lang in ${LINGUAS=$ALL_LINGUAS}; do
+ case "$ALL_LINGUAS" in
+ *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;;
+ esac
+ done
+ LINGUAS=$NEW_LINGUAS
+ AC_MSG_RESULT($LINGUAS)
+ fi
+
+ dnl Construct list of names of catalog files to be constructed.
+ if test -n "$LINGUAS"; then
+ for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done
+ fi
+ fi
+
+ dnl The reference to <locale.h> in the installed <libintl.h> file
+ dnl must be resolved because we cannot expect the users of this
+ dnl to define HAVE_LOCALE_H.
+ if test $ac_cv_header_locale_h = yes; then
+ INCLUDE_LOCALE_H="#include <locale.h>"
+ else
+ INCLUDE_LOCALE_H="\
+/* The system does not provide the header <locale.h>. Take care yourself. */"
+ fi
+ AC_SUBST(INCLUDE_LOCALE_H)
+
+ dnl Determine which catalog format we have (if any is needed)
+ dnl For now we know about two different formats:
+ dnl Linux libc-5 and the normal X/Open format
+ if test -f $srcdir/po2tbl.sed.in; then
+ if test "$CATOBJEXT" = ".cat"; then
+ AC_CHECK_HEADER(linux/version.h, msgformat=linux, msgformat=xopen)
+
+ dnl Transform the SED scripts while copying because some dumb SEDs
+ dnl cannot handle comments.
+ sed -e '/^#/d' $srcdir/$msgformat-msg.sed > po2msg.sed
+ fi
+ dnl po2tbl.sed is always needed.
+ sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \
+ $srcdir/po2tbl.sed.in > po2tbl.sed
+ fi
+
+ dnl In the intl/Makefile.in we have a special dependency which makes
+ dnl only sense for gettext. We comment this out for non-gettext
+ dnl packages.
+ if test "$PACKAGE" = "gettext"; then
+ GT_NO="#NO#"
+ GT_YES=
+ else
+ GT_NO=
+ GT_YES="#YES#"
+ fi
+ AC_SUBST(GT_NO)
+ AC_SUBST(GT_YES)
+
+ MKINSTALLDIRS="\$(srcdir)/../../mkinstalldirs"
+ AC_SUBST(MKINSTALLDIRS)
+
+ dnl *** For now the libtool support in intl/Makefile is not for real.
+ l=
+ AC_SUBST(l)
+
+ dnl Generate list of files to be processed by xgettext which will
+ dnl be included in po/Makefile. But only do this if the po directory
+ dnl exists in srcdir.
+ if test -d $srcdir/po; then
+ test -d po || mkdir po
+ if test "x$srcdir" != "x."; then
+ if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then
+ posrcprefix="$srcdir/"
+ else
+ posrcprefix="../$srcdir/"
+ fi
+ else
+ posrcprefix="../"
+ fi
+ rm -f po/POTFILES
+ sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \
+ < $srcdir/po/POTFILES.in > po/POTFILES
+ fi
+ ])
+
+# Search path for a program which passes the given test.
+# Ulrich Drepper <drepper@cygnus.com>, 1996.
+#
+# This file file be copied and used freely without restrictions. It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+# serial 1
+
+dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR,
+dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]])
+AC_DEFUN(AM_PATH_PROG_WITH_TEST,
+[# Extract the first word of "$2", so it can be a program name with args.
+set dummy $2; ac_word=[$]2
+AC_MSG_CHECKING([for $ac_word])
+AC_CACHE_VAL(ac_cv_path_$1,
+[case "[$]$1" in
+ /*)
+ ac_cv_path_$1="[$]$1" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in ifelse([$5], , $PATH, [$5]); do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if [$3]; then
+ ac_cv_path_$1="$ac_dir/$ac_word"
+ break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+dnl If no 4th arg is given, leave the cache variable unset,
+dnl so AC_PATH_PROGS will keep looking.
+ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4"
+])dnl
+ ;;
+esac])dnl
+$1="$ac_cv_path_$1"
+if test -n "[$]$1"; then
+ AC_MSG_RESULT([$]$1)
+else
+ AC_MSG_RESULT(no)
+fi
+AC_SUBST($1)dnl
+])
+
+# Check whether LC_MESSAGES is available in <locale.h>.
+# Ulrich Drepper <drepper@cygnus.com>, 1995.
+#
+# This file file be copied and used freely without restrictions. It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+# serial 1
+
+AC_DEFUN(AM_LC_MESSAGES,
+ [if test $ac_cv_header_locale_h = yes; then
+ AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES,
+ [AC_TRY_LINK([#include <locale.h>], [return LC_MESSAGES],
+ am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)])
+ if test $am_cv_val_LC_MESSAGES = yes; then
+ AC_DEFINE(HAVE_LC_MESSAGES, 1,
+ [Define if your locale.h file contains LC_MESSAGES.])
+ fi
+ fi])
+
+# Add --enable-maintainer-mode option to configure.
+# From Jim Meyering
+
+# serial 1
+
+AC_DEFUN(AM_MAINTAINER_MODE,
+[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+ dnl maintainer-mode is disabled by default
+ AC_ARG_ENABLE(maintainer-mode,
+[ --enable-maintainer-mode enable make rules and dependencies not useful
+ (and sometimes confusing) to the casual installer],
+ USE_MAINTAINER_MODE=$enableval,
+ USE_MAINTAINER_MODE=no)
+ AC_MSG_RESULT($USE_MAINTAINER_MODE)
+ AM_CONDITIONAL(MAINTAINER_MODE, test $USE_MAINTAINER_MODE = yes)
+ MAINT=$MAINTAINER_MODE_TRUE
+ AC_SUBST(MAINT)dnl
+]
+)
+
+# Define a conditional.
+
+AC_DEFUN(AM_CONDITIONAL,
+[AC_SUBST($1_TRUE)
+AC_SUBST($1_FALSE)
+if $2; then
+ $1_TRUE=
+ $1_FALSE='#'
+else
+ $1_TRUE='#'
+ $1_FALSE=
+fi])
+
diff --git a/gas/app.c b/gas/app.c
new file mode 100644
index 0000000000..2a8df3ace5
--- /dev/null
+++ b/gas/app.c
@@ -0,0 +1,1255 @@
+/* This is the Assembler Pre-Processor
+ Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 97, 98, 1999
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* Modified by Allen Wirfs-Brock, Instantiations Inc 2/90 */
+/* App, the assembler pre-processor. This pre-processor strips out excess
+ spaces, turns single-quoted characters into a decimal constant, and turns
+ # <number> <filename> <garbage> into a .line <number>\n.file <filename>
+ pair. This needs better error-handling. */
+
+#include <stdio.h>
+#include "as.h" /* For BAD_CASE() only */
+
+#if (__STDC__ != 1)
+#ifndef const
+#define const /* empty */
+#endif
+#endif
+
+/* Whether we are scrubbing in m68k MRI mode. This is different from
+ flag_m68k_mri, because the two flags will be affected by the .mri
+ pseudo-op at different times. */
+static int scrub_m68k_mri;
+
+/* The pseudo-op which switches in and out of MRI mode. See the
+ comment in do_scrub_chars. */
+static const char mri_pseudo[] = ".mri 0";
+
+#if defined TC_ARM && defined OBJ_ELF
+/* The pseudo-op for which we need to special-case `@' characters.
+ See the comment in do_scrub_chars. */
+static const char symver_pseudo[] = ".symver";
+static const char * symver_state;
+#endif
+
+static char lex[256];
+static const char symbol_chars[] =
+"$._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+#define LEX_IS_SYMBOL_COMPONENT 1
+#define LEX_IS_WHITESPACE 2
+#define LEX_IS_LINE_SEPARATOR 3
+#define LEX_IS_COMMENT_START 4
+#define LEX_IS_LINE_COMMENT_START 5
+#define LEX_IS_TWOCHAR_COMMENT_1ST 6
+#define LEX_IS_STRINGQUOTE 8
+#define LEX_IS_COLON 9
+#define LEX_IS_NEWLINE 10
+#define LEX_IS_ONECHAR_QUOTE 11
+#ifdef TC_V850
+#define LEX_IS_DOUBLEDASH_1ST 12
+#endif
+#ifdef TC_M32R
+#define LEX_IS_DOUBLEBAR_1ST 13
+#endif
+#define IS_SYMBOL_COMPONENT(c) (lex[c] == LEX_IS_SYMBOL_COMPONENT)
+#define IS_WHITESPACE(c) (lex[c] == LEX_IS_WHITESPACE)
+#define IS_LINE_SEPARATOR(c) (lex[c] == LEX_IS_LINE_SEPARATOR)
+#define IS_COMMENT(c) (lex[c] == LEX_IS_COMMENT_START)
+#define IS_LINE_COMMENT(c) (lex[c] == LEX_IS_LINE_COMMENT_START)
+#define IS_NEWLINE(c) (lex[c] == LEX_IS_NEWLINE)
+
+static int process_escape PARAMS ((int));
+
+/* FIXME-soon: The entire lexer/parser thingy should be
+ built statically at compile time rather than dynamically
+ each and every time the assembler is run. xoxorich. */
+
+void
+do_scrub_begin (m68k_mri)
+ int m68k_mri;
+{
+ const char *p;
+ int c;
+
+ scrub_m68k_mri = m68k_mri;
+
+ lex[' '] = LEX_IS_WHITESPACE;
+ lex['\t'] = LEX_IS_WHITESPACE;
+ lex['\r'] = LEX_IS_WHITESPACE;
+ lex['\n'] = LEX_IS_NEWLINE;
+ lex[';'] = LEX_IS_LINE_SEPARATOR;
+ lex[':'] = LEX_IS_COLON;
+
+ if (! m68k_mri)
+ {
+ lex['"'] = LEX_IS_STRINGQUOTE;
+
+#ifndef TC_HPPA
+ lex['\''] = LEX_IS_ONECHAR_QUOTE;
+#endif
+
+#ifdef SINGLE_QUOTE_STRINGS
+ lex['\''] = LEX_IS_STRINGQUOTE;
+#endif
+ }
+
+ /* Note: if any other character can be LEX_IS_STRINGQUOTE, the loop
+ in state 5 of do_scrub_chars must be changed. */
+
+ /* Note that these override the previous defaults, e.g. if ';' is a
+ comment char, then it isn't a line separator. */
+ for (p = symbol_chars; *p; ++p)
+ {
+ lex[(unsigned char) *p] = LEX_IS_SYMBOL_COMPONENT;
+ } /* declare symbol characters */
+
+ for (c = 128; c < 256; ++c)
+ lex[c] = LEX_IS_SYMBOL_COMPONENT;
+
+#ifdef tc_symbol_chars
+ /* This macro permits the processor to specify all characters which
+ may appears in an operand. This will prevent the scrubber from
+ discarding meaningful whitespace in certain cases. The i386
+ backend uses this to support prefixes, which can confuse the
+ scrubber as to whether it is parsing operands or opcodes. */
+ for (p = tc_symbol_chars; *p; ++p)
+ lex[(unsigned char) *p] = LEX_IS_SYMBOL_COMPONENT;
+#endif
+
+ /* The m68k backend wants to be able to change comment_chars. */
+#ifndef tc_comment_chars
+#define tc_comment_chars comment_chars
+#endif
+ for (p = tc_comment_chars; *p; p++)
+ {
+ lex[(unsigned char) *p] = LEX_IS_COMMENT_START;
+ } /* declare comment chars */
+
+ for (p = line_comment_chars; *p; p++)
+ {
+ lex[(unsigned char) *p] = LEX_IS_LINE_COMMENT_START;
+ } /* declare line comment chars */
+
+ for (p = line_separator_chars; *p; p++)
+ {
+ lex[(unsigned char) *p] = LEX_IS_LINE_SEPARATOR;
+ } /* declare line separators */
+
+ /* Only allow slash-star comments if slash is not in use.
+ FIXME: This isn't right. We should always permit them. */
+ if (lex['/'] == 0)
+ {
+ lex['/'] = LEX_IS_TWOCHAR_COMMENT_1ST;
+ }
+
+ if (m68k_mri)
+ {
+ lex['\''] = LEX_IS_STRINGQUOTE;
+ lex[';'] = LEX_IS_COMMENT_START;
+ lex['*'] = LEX_IS_LINE_COMMENT_START;
+ /* The MRI documentation says '!' is LEX_IS_COMMENT_START, but
+ then it can't be used in an expression. */
+ lex['!'] = LEX_IS_LINE_COMMENT_START;
+ }
+
+#ifdef TC_V850
+ lex['-'] = LEX_IS_DOUBLEDASH_1ST;
+#endif
+#ifdef TC_M32R
+ lex['|'] = LEX_IS_DOUBLEBAR_1ST;
+#endif
+#ifdef TC_D30V
+ /* must do this is we want VLIW instruction with "->" or "<-" */
+ lex['-'] = LEX_IS_SYMBOL_COMPONENT;
+#endif
+} /* do_scrub_begin() */
+
+/* Saved state of the scrubber */
+static int state;
+static int old_state;
+static char *out_string;
+static char out_buf[20];
+static int add_newlines;
+static char *saved_input;
+static int saved_input_len;
+static const char *mri_state;
+static char mri_last_ch;
+
+/* Data structure for saving the state of app across #include's. Note that
+ app is called asynchronously to the parsing of the .include's, so our
+ state at the time .include is interpreted is completely unrelated.
+ That's why we have to save it all. */
+
+struct app_save
+ {
+ int state;
+ int old_state;
+ char * out_string;
+ char out_buf[sizeof (out_buf)];
+ int add_newlines;
+ char * saved_input;
+ int saved_input_len;
+ int scrub_m68k_mri;
+ const char * mri_state;
+ char mri_last_ch;
+#if defined TC_ARM && defined OBJ_ELF
+ const char * symver_state;
+#endif
+ };
+
+char *
+app_push ()
+{
+ register struct app_save *saved;
+
+ saved = (struct app_save *) xmalloc (sizeof (*saved));
+ saved->state = state;
+ saved->old_state = old_state;
+ saved->out_string = out_string;
+ memcpy (saved->out_buf, out_buf, sizeof (out_buf));
+ saved->add_newlines = add_newlines;
+ saved->saved_input = saved_input;
+ saved->saved_input_len = saved_input_len;
+ saved->scrub_m68k_mri = scrub_m68k_mri;
+ saved->mri_state = mri_state;
+ saved->mri_last_ch = mri_last_ch;
+#if defined TC_ARM && defined OBJ_ELF
+ saved->symver_state = symver_state;
+#endif
+
+ /* do_scrub_begin() is not useful, just wastes time. */
+
+ state = 0;
+ saved_input = NULL;
+
+ return (char *) saved;
+}
+
+void
+app_pop (arg)
+ char *arg;
+{
+ register struct app_save *saved = (struct app_save *) arg;
+
+ /* There is no do_scrub_end (). */
+ state = saved->state;
+ old_state = saved->old_state;
+ out_string = saved->out_string;
+ memcpy (out_buf, saved->out_buf, sizeof (out_buf));
+ add_newlines = saved->add_newlines;
+ saved_input = saved->saved_input;
+ saved_input_len = saved->saved_input_len;
+ scrub_m68k_mri = saved->scrub_m68k_mri;
+ mri_state = saved->mri_state;
+ mri_last_ch = saved->mri_last_ch;
+#if defined TC_ARM && defined OBJ_ELF
+ symver_state = saved->symver_state;
+#endif
+
+ free (arg);
+} /* app_pop() */
+
+/* @@ This assumes that \n &c are the same on host and target. This is not
+ necessarily true. */
+static int
+process_escape (ch)
+ int ch;
+{
+ switch (ch)
+ {
+ case 'b':
+ return '\b';
+ case 'f':
+ return '\f';
+ case 'n':
+ return '\n';
+ case 'r':
+ return '\r';
+ case 't':
+ return '\t';
+ case '\'':
+ return '\'';
+ case '"':
+ return '\"';
+ default:
+ return ch;
+ }
+}
+
+/* This function is called to process input characters. The GET
+ parameter is used to retrieve more input characters. GET should
+ set its parameter to point to a buffer, and return the length of
+ the buffer; it should return 0 at end of file. The scrubbed output
+ characters are put into the buffer starting at TOSTART; the TOSTART
+ buffer is TOLEN bytes in length. The function returns the number
+ of scrubbed characters put into TOSTART. This will be TOLEN unless
+ end of file was seen. This function is arranged as a state
+ machine, and saves its state so that it may return at any point.
+ This is the way the old code used to work. */
+
+int
+do_scrub_chars (get, tostart, tolen)
+ int (*get) PARAMS ((char **));
+ char *tostart;
+ int tolen;
+{
+ char *to = tostart;
+ char *toend = tostart + tolen;
+ char *from;
+ char *fromend;
+ int fromlen;
+ register int ch, ch2 = 0;
+
+ /*State 0: beginning of normal line
+ 1: After first whitespace on line (flush more white)
+ 2: After first non-white (opcode) on line (keep 1white)
+ 3: after second white on line (into operands) (flush white)
+ 4: after putting out a .line, put out digits
+ 5: parsing a string, then go to old-state
+ 6: putting out \ escape in a "d string.
+ 7: After putting out a .appfile, put out string.
+ 8: After putting out a .appfile string, flush until newline.
+ 9: After seeing symbol char in state 3 (keep 1white after symchar)
+ 10: After seeing whitespace in state 9 (keep white before symchar)
+ 11: After seeing a symbol character in state 0 (eg a label definition)
+ -1: output string in out_string and go to the state in old_state
+ -2: flush text until a '*' '/' is seen, then go to state old_state
+#ifdef TC_V850
+ 12: After seeing a dash, looking for a second dash as a start of comment.
+#endif
+#ifdef TC_M32R
+ 13: After seeing a vertical bar, looking for a second vertical bar as a parallel expression seperator.
+#endif
+ */
+
+ /* I added states 9 and 10 because the MIPS ECOFF assembler uses
+ constructs like ``.loc 1 20''. This was turning into ``.loc
+ 120''. States 9 and 10 ensure that a space is never dropped in
+ between characters which could appear in a identifier. Ian
+ Taylor, ian@cygnus.com.
+
+ I added state 11 so that something like "Lfoo add %r25,%r26,%r27" works
+ correctly on the PA (and any other target where colons are optional).
+ Jeff Law, law@cs.utah.edu.
+
+ I added state 13 so that something like "cmp r1, r2 || trap #1" does not
+ get squashed into "cmp r1,r2||trap#1", with the all important space
+ between the 'trap' and the '#1' being eliminated. nickc@cygnus.com */
+
+ /* This macro gets the next input character. */
+
+#define GET() \
+ (from < fromend \
+ ? * (unsigned char *) (from++) \
+ : ((saved_input != NULL \
+ ? (free (saved_input), \
+ saved_input = NULL, \
+ 0) \
+ : 0), \
+ fromlen = (*get) (&from), \
+ fromend = from + fromlen, \
+ (fromlen == 0 \
+ ? EOF \
+ : * (unsigned char *) (from++))))
+
+ /* This macro pushes a character back on the input stream. */
+
+#define UNGET(uch) (*--from = (uch))
+
+ /* This macro puts a character into the output buffer. If this
+ character fills the output buffer, this macro jumps to the label
+ TOFULL. We use this rather ugly approach because we need to
+ handle two different termination conditions: EOF on the input
+ stream, and a full output buffer. It would be simpler if we
+ always read in the entire input stream before processing it, but
+ I don't want to make such a significant change to the assembler's
+ memory usage. */
+
+#define PUT(pch) \
+ do \
+ { \
+ *to++ = (pch); \
+ if (to >= toend) \
+ goto tofull; \
+ } \
+ while (0)
+
+ if (saved_input != NULL)
+ {
+ from = saved_input;
+ fromend = from + saved_input_len;
+ }
+ else
+ {
+ fromlen = (*get) (&from);
+ if (fromlen == 0)
+ return 0;
+ fromend = from + fromlen;
+ }
+
+ while (1)
+ {
+ /* The cases in this switch end with continue, in order to
+ branch back to the top of this while loop and generate the
+ next output character in the appropriate state. */
+ switch (state)
+ {
+ case -1:
+ ch = *out_string++;
+ if (*out_string == '\0')
+ {
+ state = old_state;
+ old_state = 3;
+ }
+ PUT (ch);
+ continue;
+
+ case -2:
+ for (;;)
+ {
+ do
+ {
+ ch = GET ();
+
+ if (ch == EOF)
+ {
+ as_warn (_("end of file in comment"));
+ goto fromeof;
+ }
+
+ if (ch == '\n')
+ PUT ('\n');
+ }
+ while (ch != '*');
+
+ while ((ch = GET ()) == '*')
+ ;
+
+ if (ch == EOF)
+ {
+ as_warn (_("end of file in comment"));
+ goto fromeof;
+ }
+
+ if (ch == '/')
+ break;
+
+ UNGET (ch);
+ }
+
+ state = old_state;
+ UNGET (' ');
+ continue;
+
+ case 4:
+ ch = GET ();
+ if (ch == EOF)
+ goto fromeof;
+ else if (ch >= '0' && ch <= '9')
+ PUT (ch);
+ else
+ {
+ while (ch != EOF && IS_WHITESPACE (ch))
+ ch = GET ();
+ if (ch == '"')
+ {
+ UNGET (ch);
+ if (scrub_m68k_mri)
+ out_string = "\n\tappfile ";
+ else
+ out_string = "\n\t.appfile ";
+ old_state = 7;
+ state = -1;
+ PUT (*out_string++);
+ }
+ else
+ {
+ while (ch != EOF && ch != '\n')
+ ch = GET ();
+ state = 0;
+ PUT (ch);
+ }
+ }
+ continue;
+
+ case 5:
+ /* We are going to copy everything up to a quote character,
+ with special handling for a backslash. We try to
+ optimize the copying in the simple case without using the
+ GET and PUT macros. */
+ {
+ char *s;
+ int len;
+
+ for (s = from; s < fromend; s++)
+ {
+ ch = *s;
+ /* This condition must be changed if the type of any
+ other character can be LEX_IS_STRINGQUOTE. */
+ if (ch == '\\'
+ || ch == '"'
+ || ch == '\''
+ || ch == '\n')
+ break;
+ }
+ len = s - from;
+ if (len > toend - to)
+ len = toend - to;
+ if (len > 0)
+ {
+ memcpy (to, from, len);
+ to += len;
+ from += len;
+ }
+ }
+
+ ch = GET ();
+ if (ch == EOF)
+ {
+ as_warn (_("end of file in string: inserted '\"'"));
+ state = old_state;
+ UNGET ('\n');
+ PUT ('"');
+ }
+ else if (lex[ch] == LEX_IS_STRINGQUOTE)
+ {
+ state = old_state;
+ PUT (ch);
+ }
+#ifndef NO_STRING_ESCAPES
+ else if (ch == '\\')
+ {
+ state = 6;
+ PUT (ch);
+ }
+#endif
+ else if (scrub_m68k_mri && ch == '\n')
+ {
+ /* Just quietly terminate the string. This permits lines like
+ bne label loop if we haven't reach end yet
+ */
+ state = old_state;
+ UNGET (ch);
+ PUT ('\'');
+ }
+ else
+ {
+ PUT (ch);
+ }
+ continue;
+
+ case 6:
+ state = 5;
+ ch = GET ();
+ switch (ch)
+ {
+ /* Handle strings broken across lines, by turning '\n' into
+ '\\' and 'n'. */
+ case '\n':
+ UNGET ('n');
+ add_newlines++;
+ PUT ('\\');
+ continue;
+
+ case '"':
+ case '\\':
+ case 'b':
+ case 'f':
+ case 'n':
+ case 'r':
+ case 't':
+ case 'v':
+ case 'x':
+ case 'X':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ break;
+#if defined(IGNORE_NONSTANDARD_ESCAPES) | defined(ONLY_STANDARD_ESCAPES)
+ default:
+ as_warn (_("Unknown escape '\\%c' in string: Ignored"), ch);
+ break;
+#else /* ONLY_STANDARD_ESCAPES */
+ default:
+ /* Accept \x as x for any x */
+ break;
+#endif /* ONLY_STANDARD_ESCAPES */
+
+ case EOF:
+ as_warn (_("End of file in string: '\"' inserted"));
+ PUT ('"');
+ continue;
+ }
+ PUT (ch);
+ continue;
+
+ case 7:
+ ch = GET ();
+ state = 5;
+ old_state = 8;
+ if (ch == EOF)
+ goto fromeof;
+ PUT (ch);
+ continue;
+
+ case 8:
+ do
+ ch = GET ();
+ while (ch != '\n' && ch != EOF);
+ if (ch == EOF)
+ goto fromeof;
+ state = 0;
+ PUT (ch);
+ continue;
+ }
+
+ /* OK, we are somewhere in states 0 through 4 or 9 through 11 */
+
+ /* flushchar: */
+ ch = GET ();
+
+ recycle:
+
+#if defined TC_ARM && defined OBJ_ELF
+ /* We need to watch out for .symver directives. See the comment later
+ in this function. */
+ if (symver_state == NULL)
+ {
+ if ((state == 0 || state == 1) && ch == symver_pseudo[0])
+ symver_state = symver_pseudo + 1;
+ }
+ else
+ {
+ /* We advance to the next state if we find the right
+ character. */
+ if (ch != '\0' && (*symver_state == ch))
+ ++symver_state;
+ else if (*symver_state != '\0')
+ /* We did not get the expected character, or we didn't
+ get a valid terminating character after seeing the
+ entire pseudo-op, so we must go back to the beginning. */
+ symver_state = NULL;
+ else
+ {
+ /* We've read the entire pseudo-op. If this is the end
+ of the line, go back to the beginning. */
+ if (IS_NEWLINE (ch))
+ symver_state = NULL;
+ }
+ }
+#endif /* TC_ARM && OBJ_ELF */
+
+#ifdef TC_M68K
+ /* We want to have pseudo-ops which control whether we are in
+ MRI mode or not. Unfortunately, since m68k MRI mode affects
+ the scrubber, that means that we need a special purpose
+ recognizer here. */
+ if (mri_state == NULL)
+ {
+ if ((state == 0 || state == 1)
+ && ch == mri_pseudo[0])
+ mri_state = mri_pseudo + 1;
+ }
+ else
+ {
+ /* We advance to the next state if we find the right
+ character, or if we need a space character and we get any
+ whitespace character, or if we need a '0' and we get a
+ '1' (this is so that we only need one state to handle
+ ``.mri 0'' and ``.mri 1''). */
+ if (ch != '\0'
+ && (*mri_state == ch
+ || (*mri_state == ' '
+ && lex[ch] == LEX_IS_WHITESPACE)
+ || (*mri_state == '0'
+ && ch == '1')))
+ {
+ mri_last_ch = ch;
+ ++mri_state;
+ }
+ else if (*mri_state != '\0'
+ || (lex[ch] != LEX_IS_WHITESPACE
+ && lex[ch] != LEX_IS_NEWLINE))
+ {
+ /* We did not get the expected character, or we didn't
+ get a valid terminating character after seeing the
+ entire pseudo-op, so we must go back to the
+ beginning. */
+ mri_state = NULL;
+ }
+ else
+ {
+ /* We've read the entire pseudo-op. mips_last_ch is
+ either '0' or '1' indicating whether to enter or
+ leave MRI mode. */
+ do_scrub_begin (mri_last_ch == '1');
+ mri_state = NULL;
+
+ /* We continue handling the character as usual. The
+ main gas reader must also handle the .mri pseudo-op
+ to control expression parsing and the like. */
+ }
+ }
+#endif
+
+ if (ch == EOF)
+ {
+ if (state != 0)
+ {
+ as_warn (_("end of file not at end of a line; newline inserted"));
+ state = 0;
+ PUT ('\n');
+ }
+ goto fromeof;
+ }
+
+ switch (lex[ch])
+ {
+ case LEX_IS_WHITESPACE:
+ do
+ {
+ ch = GET ();
+ }
+ while (ch != EOF && IS_WHITESPACE (ch));
+ if (ch == EOF)
+ goto fromeof;
+
+ if (state == 0)
+ {
+ /* Preserve a single whitespace character at the
+ beginning of a line. */
+ state = 1;
+ UNGET (ch);
+ PUT (' ');
+ break;
+ }
+
+ if (IS_COMMENT (ch)
+ || ch == '/'
+ || IS_LINE_SEPARATOR (ch))
+ {
+ if (scrub_m68k_mri)
+ {
+ /* In MRI mode, we keep these spaces. */
+ UNGET (ch);
+ PUT (' ');
+ break;
+ }
+ goto recycle;
+ }
+
+ /* If we're in state 2 or 11, we've seen a non-white
+ character followed by whitespace. If the next character
+ is ':', this is whitespace after a label name which we
+ normally must ignore. In MRI mode, though, spaces are
+ not permitted between the label and the colon. */
+ if ((state == 2 || state == 11)
+ && lex[ch] == LEX_IS_COLON
+ && ! scrub_m68k_mri)
+ {
+ state = 1;
+ PUT (ch);
+ break;
+ }
+
+ switch (state)
+ {
+ case 0:
+ state++;
+ goto recycle; /* Punted leading sp */
+ case 1:
+ /* We can arrive here if we leave a leading whitespace
+ character at the beginning of a line. */
+ goto recycle;
+ case 2:
+ state = 3;
+ if (to + 1 < toend)
+ {
+ /* Optimize common case by skipping UNGET/GET. */
+ PUT (' '); /* Sp after opco */
+ goto recycle;
+ }
+ UNGET (ch);
+ PUT (' ');
+ break;
+ case 3:
+ if (scrub_m68k_mri)
+ {
+ /* In MRI mode, we keep these spaces. */
+ UNGET (ch);
+ PUT (' ');
+ break;
+ }
+ goto recycle; /* Sp in operands */
+ case 9:
+ case 10:
+ if (scrub_m68k_mri)
+ {
+ /* In MRI mode, we keep these spaces. */
+ state = 3;
+ UNGET (ch);
+ PUT (' ');
+ break;
+ }
+ state = 10; /* Sp after symbol char */
+ goto recycle;
+ case 11:
+ if (flag_m68k_mri
+#ifdef LABELS_WITHOUT_COLONS
+ || 1
+#endif
+ )
+ state = 1;
+ else
+ {
+ /* We know that ch is not ':', since we tested that
+ case above. Therefore this is not a label, so it
+ must be the opcode, and we've just seen the
+ whitespace after it. */
+ state = 3;
+ }
+ UNGET (ch);
+ PUT (' '); /* Sp after label definition. */
+ break;
+ default:
+ BAD_CASE (state);
+ }
+ break;
+
+ case LEX_IS_TWOCHAR_COMMENT_1ST:
+ ch2 = GET ();
+ if (ch2 == '*')
+ {
+ for (;;)
+ {
+ do
+ {
+ ch2 = GET ();
+ if (ch2 != EOF && IS_NEWLINE (ch2))
+ add_newlines++;
+ }
+ while (ch2 != EOF && ch2 != '*');
+
+ while (ch2 == '*')
+ ch2 = GET ();
+
+ if (ch2 == EOF || ch2 == '/')
+ break;
+
+ /* This UNGET will ensure that we count newlines
+ correctly. */
+ UNGET (ch2);
+ }
+
+ if (ch2 == EOF)
+ as_warn (_("end of file in multiline comment"));
+
+ ch = ' ';
+ goto recycle;
+ }
+ else
+ {
+ if (ch2 != EOF)
+ UNGET (ch2);
+ if (state == 9 || state == 10)
+ state = 3;
+ PUT (ch);
+ }
+ break;
+
+ case LEX_IS_STRINGQUOTE:
+ if (state == 10)
+ {
+ /* Preserve the whitespace in foo "bar" */
+ UNGET (ch);
+ state = 3;
+ PUT (' ');
+
+ /* PUT didn't jump out. We could just break, but we
+ know what will happen, so optimize a bit. */
+ ch = GET ();
+ old_state = 3;
+ }
+ else if (state == 9)
+ old_state = 3;
+ else
+ old_state = state;
+ state = 5;
+ PUT (ch);
+ break;
+
+#ifndef IEEE_STYLE
+ case LEX_IS_ONECHAR_QUOTE:
+ if (state == 10)
+ {
+ /* Preserve the whitespace in foo 'b' */
+ UNGET (ch);
+ state = 3;
+ PUT (' ');
+ break;
+ }
+ ch = GET ();
+ if (ch == EOF)
+ {
+ as_warn (_("end of file after a one-character quote; \\0 inserted"));
+ ch = 0;
+ }
+ if (ch == '\\')
+ {
+ ch = GET ();
+ if (ch == EOF)
+ {
+ as_warn (_("end of file in escape character"));
+ ch = '\\';
+ }
+ else
+ ch = process_escape (ch);
+ }
+ sprintf (out_buf, "%d", (int) (unsigned char) ch);
+
+ /* None of these 'x constants for us. We want 'x'. */
+ if ((ch = GET ()) != '\'')
+ {
+#ifdef REQUIRE_CHAR_CLOSE_QUOTE
+ as_warn (_("Missing close quote: (assumed)"));
+#else
+ if (ch != EOF)
+ UNGET (ch);
+#endif
+ }
+ if (strlen (out_buf) == 1)
+ {
+ PUT (out_buf[0]);
+ break;
+ }
+ if (state == 9)
+ old_state = 3;
+ else
+ old_state = state;
+ state = -1;
+ out_string = out_buf;
+ PUT (*out_string++);
+ break;
+#endif
+
+ case LEX_IS_COLON:
+ if (state == 9 || state == 10)
+ state = 3;
+ else if (state != 3)
+ state = 1;
+ PUT (ch);
+ break;
+
+ case LEX_IS_NEWLINE:
+ /* Roll out a bunch of newlines from inside comments, etc. */
+ if (add_newlines)
+ {
+ --add_newlines;
+ UNGET (ch);
+ }
+ /* fall thru into... */
+
+ case LEX_IS_LINE_SEPARATOR:
+ state = 0;
+ PUT (ch);
+ break;
+
+#ifdef TC_V850
+ case LEX_IS_DOUBLEDASH_1ST:
+ ch2 = GET();
+ if (ch2 != '-')
+ {
+ UNGET (ch2);
+ goto de_fault;
+ }
+ /* read and skip to end of line */
+ do
+ {
+ ch = GET ();
+ }
+ while (ch != EOF && ch != '\n');
+ if (ch == EOF)
+ {
+ as_warn (_("end of file in comment; newline inserted"));
+ }
+ state = 0;
+ PUT ('\n');
+ break;
+#endif
+#ifdef TC_M32R
+ case LEX_IS_DOUBLEBAR_1ST:
+ ch2 = GET();
+ if (ch2 != '|')
+ {
+ UNGET (ch2);
+ goto de_fault;
+ }
+ /* Reset back to state 1 and pretend that we are parsing a line from
+ just after the first white space. */
+ state = 1;
+ PUT ('|');
+ PUT ('|');
+ break;
+#endif
+ case LEX_IS_LINE_COMMENT_START:
+ /* FIXME-someday: The two character comment stuff was badly
+ thought out. On i386, we want '/' as line comment start
+ AND we want C style comments. hence this hack. The
+ whole lexical process should be reworked. xoxorich. */
+ if (ch == '/')
+ {
+ ch2 = GET ();
+ if (ch2 == '*')
+ {
+ old_state = 3;
+ state = -2;
+ break;
+ }
+ else
+ {
+ UNGET (ch2);
+ }
+ } /* bad hack */
+
+ if (state == 0 || state == 1) /* Only comment at start of line. */
+ {
+ int startch;
+
+ startch = ch;
+
+ do
+ {
+ ch = GET ();
+ }
+ while (ch != EOF && IS_WHITESPACE (ch));
+ if (ch == EOF)
+ {
+ as_warn (_("end of file in comment; newline inserted"));
+ PUT ('\n');
+ break;
+ }
+ if (ch < '0' || ch > '9' || state != 0 || startch != '#')
+ {
+ /* Not a cpp line. */
+ while (ch != EOF && !IS_NEWLINE (ch))
+ ch = GET ();
+ if (ch == EOF)
+ as_warn (_("EOF in Comment: Newline inserted"));
+ state = 0;
+ PUT ('\n');
+ break;
+ }
+ /* Loks like `# 123 "filename"' from cpp. */
+ UNGET (ch);
+ old_state = 4;
+ state = -1;
+ if (scrub_m68k_mri)
+ out_string = "\tappline ";
+ else
+ out_string = "\t.appline ";
+ PUT (*out_string++);
+ break;
+ }
+
+#ifdef TC_D10V
+ /* All insns end in a char for which LEX_IS_SYMBOL_COMPONENT is true.
+ Trap is the only short insn that has a first operand that is
+ neither register nor label.
+ We must prevent exef0f ||trap #1 to degenerate to exef0f ||trap#1 .
+ We can't make '#' LEX_IS_SYMBOL_COMPONENT because it is already
+ LEX_IS_LINE_COMMENT_START. However, it is the only character in
+ line_comment_chars for d10v, hence we can recognize it as such. */
+ /* An alternative approach would be to reset the state to 1 when
+ we see '||', '<'- or '->', but that seems to be overkill. */
+ if (state == 10) PUT (' ');
+#endif
+ /* We have a line comment character which is not at the
+ start of a line. If this is also a normal comment
+ character, fall through. Otherwise treat it as a default
+ character. */
+ if (strchr (tc_comment_chars, ch) == NULL
+ && (! scrub_m68k_mri
+ || (ch != '!' && ch != '*')))
+ goto de_fault;
+ if (scrub_m68k_mri
+ && (ch == '!' || ch == '*' || ch == '#')
+ && state != 1
+ && state != 10)
+ goto de_fault;
+ /* Fall through. */
+ case LEX_IS_COMMENT_START:
+#if defined TC_ARM && defined OBJ_ELF
+ /* On the ARM, `@' is the comment character.
+ Unfortunately this is also a special character in ELF .symver
+ directives (and .type, though we deal with those another way). So
+ we check if this line is such a directive, and treat the character
+ as default if so. This is a hack. */
+ if ((symver_state != NULL) && (*symver_state == 0))
+ goto de_fault;
+#endif
+ do
+ {
+ ch = GET ();
+ }
+ while (ch != EOF && !IS_NEWLINE (ch));
+ if (ch == EOF)
+ as_warn (_("end of file in comment; newline inserted"));
+ state = 0;
+ PUT ('\n');
+ break;
+
+ case LEX_IS_SYMBOL_COMPONENT:
+ if (state == 10)
+ {
+ /* This is a symbol character following another symbol
+ character, with whitespace in between. We skipped
+ the whitespace earlier, so output it now. */
+ UNGET (ch);
+ state = 3;
+ PUT (' ');
+ break;
+ }
+
+ if (state == 3)
+ state = 9;
+
+ /* This is a common case. Quickly copy CH and all the
+ following symbol component or normal characters. */
+ if (to + 1 < toend
+ && mri_state == NULL
+#if defined TC_ARM && defined OBJ_ELF
+ && symver_state == NULL
+#endif
+ )
+ {
+ char *s;
+ int len;
+
+ for (s = from; s < fromend; s++)
+ {
+ int type;
+
+ ch2 = * (unsigned char *) s;
+ type = lex[ch2];
+ if (type != 0
+ && type != LEX_IS_SYMBOL_COMPONENT)
+ break;
+ }
+ if (s > from)
+ {
+ /* Handle the last character normally, for
+ simplicity. */
+ --s;
+ }
+ len = s - from;
+ if (len > (toend - to) - 1)
+ len = (toend - to) - 1;
+ if (len > 0)
+ {
+ PUT (ch);
+ if (len > 8)
+ {
+ memcpy (to, from, len);
+ to += len;
+ from += len;
+ }
+ else
+ {
+ switch (len)
+ {
+ case 8: *to++ = *from++;
+ case 7: *to++ = *from++;
+ case 6: *to++ = *from++;
+ case 5: *to++ = *from++;
+ case 4: *to++ = *from++;
+ case 3: *to++ = *from++;
+ case 2: *to++ = *from++;
+ case 1: *to++ = *from++;
+ }
+ }
+ ch = GET ();
+ }
+ }
+
+ /* Fall through. */
+ default:
+ de_fault:
+ /* Some relatively `normal' character. */
+ if (state == 0)
+ {
+ state = 11; /* Now seeing label definition */
+ }
+ else if (state == 1)
+ {
+ state = 2; /* Ditto */
+ }
+ else if (state == 9)
+ {
+ if (lex[ch] != LEX_IS_SYMBOL_COMPONENT)
+ state = 3;
+ }
+ else if (state == 10)
+ {
+ state = 3;
+ }
+ PUT (ch);
+ break;
+ }
+ }
+
+ /*NOTREACHED*/
+
+ fromeof:
+ /* We have reached the end of the input. */
+ return to - tostart;
+
+ tofull:
+ /* The output buffer is full. Save any input we have not yet
+ processed. */
+ if (fromend > from)
+ {
+ char *save;
+
+ save = (char *) xmalloc (fromend - from);
+ memcpy (save, from, fromend - from);
+ if (saved_input != NULL)
+ free (saved_input);
+ saved_input = save;
+ saved_input_len = fromend - from;
+ }
+ else
+ {
+ if (saved_input != NULL)
+ {
+ free (saved_input);
+ saved_input = NULL;
+ }
+ }
+ return to - tostart;
+}
+
+/* end of app.c */
diff --git a/gas/as.c b/gas/as.c
new file mode 100644
index 0000000000..0cdd357dc7
--- /dev/null
+++ b/gas/as.c
@@ -0,0 +1,1010 @@
+/* as.c - GAS main program.
+ Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 97, 98, 1999
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/*
+ * Main program for AS; a 32-bit assembler of GNU.
+ * Understands command arguments.
+ * Has a few routines that don't fit in other modules because they
+ * are shared.
+ *
+ *
+ * bugs
+ *
+ * : initialisers
+ * Since no-one else says they will support them in future: I
+ * don't support them now.
+ *
+ */
+
+#include "ansidecl.h"
+
+#define COMMON
+
+#include "as.h"
+#include "subsegs.h"
+#include "output-file.h"
+#include "sb.h"
+#include "macro.h"
+
+#ifndef HAVE_ITBL_CPU
+#define itbl_parse(itbl_file) 1
+#define itbl_init()
+#endif
+
+#ifdef HAVE_SBRK
+#ifdef NEED_DECLARATION_SBRK
+extern PTR sbrk ();
+#endif
+#endif
+
+static void show_usage PARAMS ((FILE *));
+static void parse_args PARAMS ((int *, char ***));
+static void dump_statistics PARAMS ((void));
+static void perform_an_assembly_pass PARAMS ((int argc, char **argv));
+static int macro_expr PARAMS ((const char *, int, sb *, int *));
+
+int listing; /* true if a listing is wanted */
+
+static char *listing_filename = NULL; /* Name of listing file. */
+
+/* Type of debugging to generate. */
+
+enum debug_info_type debug_type = DEBUG_NONE;
+
+/* Maximum level of macro nesting. */
+
+int max_macro_nest = 100;
+
+char *myname; /* argv[0] */
+#ifdef BFD_ASSEMBLER
+segT reg_section, expr_section;
+segT text_section, data_section, bss_section;
+#endif
+
+/* The default obstack chunk size. If we set this to zero, the
+ obstack code will use whatever will fit in a 4096 byte block. */
+int chunksize = 0;
+
+/* To monitor memory allocation more effectively, make this non-zero.
+ Then the chunk sizes for gas and bfd will be reduced. */
+int debug_memory = 0;
+
+/* We build a list of defsyms as we read the options, and then define
+ them after we have initialized everything. */
+
+struct defsym_list
+{
+ struct defsym_list *next;
+ char *name;
+ valueT value;
+};
+
+static struct defsym_list *defsyms;
+
+/* Keep a record of the itbl files we read in. */
+
+struct itbl_file_list
+{
+ struct itbl_file_list *next;
+ char *name;
+};
+
+static struct itbl_file_list *itbl_files;
+
+void
+print_version_id ()
+{
+ static int printed;
+ if (printed)
+ return;
+ printed = 1;
+
+#ifdef BFD_ASSEMBLER
+ fprintf (stderr, _("GNU assembler version %s (%s) using BFD version %s"),
+ VERSION, TARGET_ALIAS, BFD_VERSION);
+#else
+ fprintf (stderr, _("GNU assembler version %s (%s)"), VERSION, TARGET_ALIAS);
+#endif
+ fprintf (stderr, "\n");
+}
+
+static void
+show_usage (stream)
+ FILE *stream;
+{
+ fprintf (stream, _("Usage: %s [option...] [asmfile...]\n"), myname);
+
+ fprintf (stream, _("\
+Options:\n\
+ -a[sub-option...] turn on listings\n\
+ Sub-options [default hls]:\n\
+ c omit false conditionals\n\
+ d omit debugging directives\n\
+ h include high-level source\n\
+ l include assembly\n\
+ m include macro expansions\n\
+ n omit forms processing\n\
+ s include symbols\n\
+ =file set listing file name (must be last sub-option)\n"));
+
+ fprintf (stream, _("\
+ -D produce assembler debugging messages\n\
+ --defsym SYM=VAL define symbol SYM to given value\n\
+ -f skip whitespace and comment preprocessing\n\
+ --gstabs generate stabs debugging information\n\
+ --help show this message and exit\n\
+ -I DIR add DIR to search list for .include directives\n\
+ -J don't warn about signed overflow\n\
+ -K warn when differences altered for long displacements\n\
+ -L,--keep-locals keep local symbols (e.g. starting with `L')\n"));
+
+ fprintf (stream, _("\
+ -M,--mri assemble in MRI compatibility mode\n\
+ --MD FILE write dependency information in FILE (default none)\n\
+ -nocpp ignored\n\
+ -o OBJFILE name the object-file output OBJFILE (default a.out)\n\
+ -R fold data section into text section\n\
+ --statistics print various measured statistics from execution\n\
+ --strip-local-absolute strip local absolute symbols\n\
+ --traditional-format Use same format as native assembler when possible\n\
+ --version print assembler version number and exit\n\
+ -W suppress warnings\n\
+ --itbl INSTTBL extend instruction set to include instructions\n\
+ matching the specifications defined in file INSTTBL\n\
+ -w ignored\n\
+ -X ignored\n\
+ -Z generate object file even after errors\n"));
+
+ fprintf (stream, _("\
+ --listing-lhs-width set the width in words of the output data column of\n\
+ the listing\n\
+ --listing-lhs-width2 set the width in words of the continuation lines\n\
+ of the output data column; ignored if smaller than\n\
+ the width of the first line\n\
+ --listing-rhs-width set the max width in characters of the lines from\n\
+ the source file\n\
+ --listing-cont-lines set the maximum number of continuation lines used\n\
+ for the output data column of the listing\n"));
+
+ md_show_usage (stream);
+
+ fprintf (stream, _("\nReport bugs to bug-gnu-utils@gnu.org\n"));
+}
+
+#ifdef USE_EMULATIONS
+#define EMULATION_ENVIRON "AS_EMULATION"
+
+extern struct emulation mipsbelf, mipslelf, mipself;
+extern struct emulation mipsbecoff, mipslecoff, mipsecoff;
+extern struct emulation i386coff, i386elf;
+
+static struct emulation *const emulations[] = { EMULATIONS };
+static const int n_emulations = sizeof (emulations) / sizeof (emulations[0]);
+
+static void select_emulation_mode PARAMS ((int, char **));
+
+static void
+select_emulation_mode (argc, argv)
+ int argc;
+ char **argv;
+{
+ int i;
+ char *p, *em = 0;
+
+ for (i = 1; i < argc; i++)
+ if (!strncmp ("--em", argv[i], 4))
+ break;
+
+ if (i == argc)
+ goto do_default;
+
+ p = strchr (argv[i], '=');
+ if (p)
+ p++;
+ else
+ p = argv[i+1];
+
+ if (!p || !*p)
+ as_fatal (_("missing emulation mode name"));
+ em = p;
+
+ do_default:
+ if (em == 0)
+ em = getenv (EMULATION_ENVIRON);
+ if (em == 0)
+ em = DEFAULT_EMULATION;
+
+ if (em)
+ {
+ for (i = 0; i < n_emulations; i++)
+ if (!strcmp (emulations[i]->name, em))
+ break;
+ if (i == n_emulations)
+ as_fatal (_("unrecognized emulation name `%s'"), em);
+ this_emulation = emulations[i];
+ }
+ else
+ this_emulation = emulations[0];
+
+ this_emulation->init ();
+}
+
+const char *
+default_emul_bfd_name ()
+{
+ abort ();
+ return NULL;
+}
+
+void
+common_emul_init ()
+{
+ this_format = this_emulation->format;
+
+ if (this_emulation->leading_underscore == 2)
+ this_emulation->leading_underscore = this_format->dfl_leading_underscore;
+
+ if (this_emulation->default_endian != 2)
+ target_big_endian = this_emulation->default_endian;
+
+ if (this_emulation->fake_label_name == 0)
+ {
+ if (this_emulation->leading_underscore)
+ this_emulation->fake_label_name = "L0\001";
+ else
+ /* What other parameters should we test? */
+ this_emulation->fake_label_name = ".L0\001";
+ }
+}
+#endif
+
+/*
+ * Since it is easy to do here we interpret the special arg "-"
+ * to mean "use stdin" and we set that argv[] pointing to "".
+ * After we have munged argv[], the only things left are source file
+ * name(s) and ""(s) denoting stdin. These file names are used
+ * (perhaps more than once) later.
+ *
+ * check for new machine-dep cmdline options in
+ * md_parse_option definitions in config/tc-*.c
+ */
+
+static void
+parse_args (pargc, pargv)
+ int *pargc;
+ char ***pargv;
+{
+ int old_argc, new_argc;
+ char **old_argv, **new_argv;
+
+ /* Starting the short option string with '-' is for programs that
+ expect options and other ARGV-elements in any order and that care about
+ the ordering of the two. We describe each non-option ARGV-element
+ as if it were the argument of an option with character code 1. */
+
+ char *shortopts;
+ extern CONST char *md_shortopts;
+ static const char std_shortopts[] =
+ {
+ '-', 'J',
+#ifndef WORKING_DOT_WORD
+ /* -K is not meaningful if .word is not being hacked. */
+ 'K',
+#endif
+ 'L', 'M', 'R', 'W', 'Z', 'f', 'a', ':', ':', 'D', 'I', ':', 'o', ':',
+#ifndef VMS
+ /* -v takes an argument on VMS, so we don't make it a generic
+ option. */
+ 'v',
+#endif
+ 'w', 'X',
+ /* New option for extending instruction set (see also --itbl below) */
+ 't', ':',
+ '\0'
+ };
+ struct option *longopts;
+ extern struct option md_longopts[];
+ extern size_t md_longopts_size;
+ static const struct option std_longopts[] = {
+#define OPTION_HELP (OPTION_STD_BASE)
+ {"help", no_argument, NULL, OPTION_HELP},
+ {"keep-locals", no_argument, NULL, 'L'},
+ {"mri", no_argument, NULL, 'M'},
+#define OPTION_NOCPP (OPTION_STD_BASE + 1)
+ {"nocpp", no_argument, NULL, OPTION_NOCPP},
+#define OPTION_STATISTICS (OPTION_STD_BASE + 2)
+ {"statistics", no_argument, NULL, OPTION_STATISTICS},
+#define OPTION_VERSION (OPTION_STD_BASE + 3)
+ {"version", no_argument, NULL, OPTION_VERSION},
+#define OPTION_DUMPCONFIG (OPTION_STD_BASE + 4)
+ {"dump-config", no_argument, NULL, OPTION_DUMPCONFIG},
+#define OPTION_VERBOSE (OPTION_STD_BASE + 5)
+ {"verbose", no_argument, NULL, OPTION_VERBOSE},
+#define OPTION_EMULATION (OPTION_STD_BASE + 6)
+ {"emulation", required_argument, NULL, OPTION_EMULATION},
+#define OPTION_DEFSYM (OPTION_STD_BASE + 7)
+ {"defsym", required_argument, NULL, OPTION_DEFSYM},
+#define OPTION_INSTTBL (OPTION_STD_BASE + 8)
+ /* New option for extending instruction set (see also -t above).
+ The "-t file" or "--itbl file" option extends the basic set of
+ valid instructions by reading "file", a text file containing a
+ list of instruction formats. The additional opcodes and their
+ formats are added to the built-in set of instructions, and
+ mnemonics for new registers may also be defined. */
+ {"itbl", required_argument, NULL, OPTION_INSTTBL},
+#define OPTION_LISTING_LHS_WIDTH (OPTION_STD_BASE + 9)
+ {"listing-lhs-width", required_argument, NULL, OPTION_LISTING_LHS_WIDTH},
+#define OPTION_LISTING_LHS_WIDTH2 (OPTION_STD_BASE + 10)
+ {"listing-lhs-width", required_argument, NULL, OPTION_LISTING_LHS_WIDTH2},
+#define OPTION_LISTING_RHS_WIDTH (OPTION_STD_BASE + 11)
+ {"listing-rhs-width", required_argument, NULL, OPTION_LISTING_RHS_WIDTH},
+#define OPTION_LISTING_CONT_LINES (OPTION_STD_BASE + 12)
+ {"listing-cont-lines", required_argument, NULL, OPTION_LISTING_CONT_LINES},
+#define OPTION_DEPFILE (OPTION_STD_BASE + 13)
+ {"MD", required_argument, NULL, OPTION_DEPFILE},
+#define OPTION_GSTABS (OPTION_STD_BASE + 14)
+ {"gstabs", no_argument, NULL, OPTION_GSTABS},
+#define OPTION_STRIP_LOCAL_ABSOLUTE (OPTION_STD_BASE + 15)
+ {"strip-local-absolute", no_argument, NULL, OPTION_STRIP_LOCAL_ABSOLUTE},
+#define OPTION_TRADITIONAL_FORMAT (OPTION_STD_BASE + 16)
+ {"traditional-format", no_argument, NULL, OPTION_TRADITIONAL_FORMAT}
+ };
+
+ /* Construct the option lists from the standard list and the
+ target dependent list. */
+ shortopts = concat (std_shortopts, md_shortopts, (char *) NULL);
+ longopts = (struct option *) xmalloc (sizeof (std_longopts) + md_longopts_size);
+ memcpy (longopts, std_longopts, sizeof (std_longopts));
+ memcpy ((char *) longopts + sizeof (std_longopts),
+ md_longopts, md_longopts_size);
+
+ /* Make a local copy of the old argv. */
+ old_argc = *pargc;
+ old_argv = *pargv;
+
+ /* Initialize a new argv that contains no options. */
+ new_argv = (char **) xmalloc (sizeof (char *) * (old_argc + 1));
+ new_argv[0] = old_argv[0];
+ new_argc = 1;
+ new_argv[new_argc] = NULL;
+
+ while (1)
+ {
+ /* getopt_long_only is like getopt_long, but '-' as well as '--' can
+ indicate a long option. */
+ int longind;
+ int optc = getopt_long_only (old_argc, old_argv, shortopts, longopts,
+ &longind);
+
+ if (optc == -1)
+ break;
+
+ switch (optc)
+ {
+ default:
+ /* md_parse_option should return 1 if it recognizes optc,
+ 0 if not. */
+ if (md_parse_option (optc, optarg) != 0)
+ break;
+ /* `-v' isn't included in the general short_opts list, so check for
+ it explicity here before deciding we've gotten a bad argument. */
+ if (optc == 'v')
+ {
+#ifdef VMS
+ /* Telling getopt to treat -v's value as optional can result
+ in it picking up a following filename argument here. The
+ VMS code in md_parse_option can return 0 in that case,
+ but it has no way of pushing the filename argument back. */
+ if (optarg && *optarg)
+ new_argv[new_argc++] = optarg, new_argv[new_argc] = NULL;
+ else
+#else
+ case 'v':
+#endif
+ case OPTION_VERBOSE:
+ print_version_id ();
+ break;
+ }
+ /*FALLTHRU*/
+
+ case '?':
+ exit (EXIT_FAILURE);
+
+ case 1: /* File name. */
+ if (!strcmp (optarg, "-"))
+ optarg = "";
+ new_argv[new_argc++] = optarg;
+ new_argv[new_argc] = NULL;
+ break;
+
+ case OPTION_HELP:
+ show_usage (stdout);
+ exit (EXIT_SUCCESS);
+
+ case OPTION_NOCPP:
+ break;
+
+ case OPTION_STATISTICS:
+ flag_print_statistics = 1;
+ break;
+
+ case OPTION_STRIP_LOCAL_ABSOLUTE:
+ flag_strip_local_absolute = 1;
+ break;
+
+ case OPTION_TRADITIONAL_FORMAT:
+ flag_traditional_format = 1;
+ break;
+
+ case OPTION_VERSION:
+ /* This output is intended to follow the GNU standards document. */
+ printf (_("GNU assembler %s\n"), VERSION);
+ printf (_("Copyright 1997 Free Software Foundation, Inc.\n"));
+ printf (_("\
+This program is free software; you may redistribute it under the terms of\n\
+the GNU General Public License. This program has absolutely no warranty.\n"));
+ printf (_("This assembler was configured for a target of `%s'.\n"),
+ TARGET_ALIAS);
+ exit (EXIT_SUCCESS);
+
+ case OPTION_EMULATION:
+#ifdef USE_EMULATIONS
+ if (strcmp (optarg, this_emulation->name))
+ as_fatal (_("multiple emulation names specified"));
+#else
+ as_fatal (_("emulations not handled in this configuration"));
+#endif
+ break;
+
+ case OPTION_DUMPCONFIG:
+ fprintf (stderr, _("alias = %s\n"), TARGET_ALIAS);
+ fprintf (stderr, _("canonical = %s\n"), TARGET_CANONICAL);
+ fprintf (stderr, _("cpu-type = %s\n"), TARGET_CPU);
+#ifdef TARGET_OBJ_FORMAT
+ fprintf (stderr, _("format = %s\n"), TARGET_OBJ_FORMAT);
+#endif
+#ifdef TARGET_FORMAT
+ fprintf (stderr, _("bfd-target = %s\n"), TARGET_FORMAT);
+#endif
+ exit (EXIT_SUCCESS);
+
+ case OPTION_DEFSYM:
+ {
+ char *s;
+ long i;
+ struct defsym_list *n;
+
+ for (s = optarg; *s != '\0' && *s != '='; s++)
+ ;
+ if (*s == '\0')
+ as_fatal (_("bad defsym; format is --defsym name=value"));
+ *s++ = '\0';
+ i = strtol (s, (char **) NULL, 0);
+ n = (struct defsym_list *) xmalloc (sizeof *n);
+ n->next = defsyms;
+ n->name = optarg;
+ n->value = i;
+ defsyms = n;
+ }
+ break;
+
+ case OPTION_INSTTBL:
+ case 't':
+ {
+ /* optarg is the name of the file containing the instruction
+ formats, opcodes, register names, etc. */
+ struct itbl_file_list *n;
+
+ if (optarg == NULL)
+ {
+ as_warn ( _("No file name following -t option\n") );
+ break;
+ }
+
+ n = (struct itbl_file_list *) xmalloc (sizeof *n);
+ n->next = itbl_files;
+ n->name = optarg;
+ itbl_files = n;
+
+ /* Parse the file and add the new instructions to our internal
+ table. If multiple instruction tables are specified, the
+ information from this table gets appended onto the existing
+ internal table. */
+ itbl_files->name = xstrdup (optarg);
+ if (itbl_parse (itbl_files->name) != 0)
+ {
+ fprintf (stderr, _("Failed to read instruction table %s\n"),
+ itbl_files->name);
+ exit (EXIT_SUCCESS);
+ }
+ }
+ break;
+
+ case OPTION_DEPFILE:
+ start_dependencies (optarg);
+ break;
+
+ case OPTION_GSTABS:
+ debug_type = DEBUG_STABS;
+ break;
+
+ case 'J':
+ flag_signed_overflow_ok = 1;
+ break;
+
+#ifndef WORKING_DOT_WORD
+ case 'K':
+ flag_warn_displacement = 1;
+ break;
+#endif
+
+ case 'L':
+ flag_keep_locals = 1;
+ break;
+
+ case OPTION_LISTING_LHS_WIDTH:
+ listing_lhs_width = atoi(optarg);
+ if (listing_lhs_width_second < listing_lhs_width)
+ listing_lhs_width_second = listing_lhs_width;
+ break;
+ case OPTION_LISTING_LHS_WIDTH2:
+ {
+ int tmp = atoi(optarg);
+ if (tmp > listing_lhs_width)
+ listing_lhs_width_second = tmp;
+ }
+ break;
+ case OPTION_LISTING_RHS_WIDTH:
+ listing_rhs_width = atoi(optarg);
+ break;
+ case OPTION_LISTING_CONT_LINES:
+ listing_lhs_cont_lines = atoi(optarg);
+ break;
+
+ case 'M':
+ flag_mri = 1;
+#ifdef TC_M68K
+ flag_m68k_mri = 1;
+#endif
+ break;
+
+ case 'R':
+ flag_readonly_data_in_text = 1;
+ break;
+
+ case 'W':
+ flag_no_warnings = 1;
+ break;
+
+ case 'Z':
+ flag_always_generate_output = 1;
+ break;
+
+ case 'a':
+ if (optarg)
+ {
+ while (*optarg)
+ {
+ switch (*optarg)
+ {
+ case 'c':
+ listing |= LISTING_NOCOND;
+ break;
+ case 'd':
+ listing |= LISTING_NODEBUG;
+ break;
+ case 'h':
+ listing |= LISTING_HLL;
+ break;
+ case 'l':
+ listing |= LISTING_LISTING;
+ break;
+ case 'm':
+ listing |= LISTING_MACEXP;
+ break;
+ case 'n':
+ listing |= LISTING_NOFORM;
+ break;
+ case 's':
+ listing |= LISTING_SYMBOLS;
+ break;
+ case '=':
+ listing_filename = xstrdup (optarg + 1);
+ optarg += strlen (listing_filename);
+ break;
+ default:
+ as_fatal (_("invalid listing option `%c'"), *optarg);
+ break;
+ }
+ optarg++;
+ }
+ }
+ if (!listing)
+ listing = LISTING_DEFAULT;
+ break;
+
+ case 'D':
+ /* DEBUG is implemented: it debugs different */
+ /* things from other people's assemblers. */
+ flag_debug = 1;
+ break;
+
+ case 'f':
+ flag_no_comments = 1;
+ break;
+
+ case 'I':
+ { /* Include file directory */
+ char *temp = xstrdup (optarg);
+ add_include_dir (temp);
+ break;
+ }
+
+ case 'o':
+ out_file_name = xstrdup (optarg);
+ break;
+
+ case 'w':
+ break;
+
+ case 'X':
+ /* -X means treat warnings as errors */
+ break;
+ }
+ }
+
+ free (shortopts);
+ free (longopts);
+
+ *pargc = new_argc;
+ *pargv = new_argv;
+}
+
+static long start_time;
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int macro_alternate;
+ int macro_strip_at;
+ int keep_it;
+
+ start_time = get_run_time ();
+
+#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
+ setlocale (LC_MESSAGES, "");
+#endif
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+
+ if (debug_memory)
+ {
+#ifdef BFD_ASSEMBLER
+ extern long _bfd_chunksize;
+ _bfd_chunksize = 64;
+#endif
+ chunksize = 64;
+ }
+
+#ifdef HOST_SPECIAL_INIT
+ HOST_SPECIAL_INIT (argc, argv);
+#endif
+
+ myname = argv[0];
+ xmalloc_set_program_name (myname);
+
+ START_PROGRESS (myname, 0);
+
+#ifndef OBJ_DEFAULT_OUTPUT_FILE_NAME
+#define OBJ_DEFAULT_OUTPUT_FILE_NAME "a.out"
+#endif
+
+ out_file_name = OBJ_DEFAULT_OUTPUT_FILE_NAME;
+
+ hex_init ();
+#ifdef BFD_ASSEMBLER
+ bfd_init ();
+ bfd_set_error_program_name (myname);
+#endif
+
+#ifdef USE_EMULATIONS
+ select_emulation_mode (argc, argv);
+#endif
+
+ PROGRESS (1);
+ symbol_begin ();
+ frag_init ();
+ subsegs_begin ();
+ parse_args (&argc, &argv);
+ read_begin ();
+ input_scrub_begin ();
+ expr_begin ();
+
+ if (flag_print_statistics)
+ xatexit (dump_statistics);
+
+ macro_alternate = 0;
+ macro_strip_at = 0;
+#ifdef TC_I960
+ macro_strip_at = flag_mri;
+#endif
+#ifdef TC_A29K
+ /* For compatibility with the AMD 29K family macro assembler
+ specification. */
+ macro_alternate = 1;
+ macro_strip_at = 1;
+#endif
+
+ macro_init (macro_alternate, flag_mri, macro_strip_at, macro_expr);
+
+ PROGRESS (1);
+
+#ifdef BFD_ASSEMBLER
+ output_file_create (out_file_name);
+ assert (stdoutput != 0);
+#endif
+
+#ifdef tc_init_after_args
+ tc_init_after_args ();
+#endif
+
+ itbl_init ();
+
+ /* Now that we have fully initialized, and have created the output
+ file, define any symbols requested by --defsym command line
+ arguments. */
+ while (defsyms != NULL)
+ {
+ symbolS *sym;
+ struct defsym_list *next;
+
+ sym = symbol_new (defsyms->name, absolute_section, defsyms->value,
+ &zero_address_frag);
+ symbol_table_insert (sym);
+ next = defsyms->next;
+ free (defsyms);
+ defsyms = next;
+ }
+
+ PROGRESS (1);
+
+ perform_an_assembly_pass (argc, argv); /* Assemble it. */
+
+ cond_finish_check (-1);
+
+#ifdef md_end
+ md_end ();
+#endif
+
+ if (seen_at_least_1_file ()
+ && (flag_always_generate_output || had_errors () == 0))
+ keep_it = 1;
+ else
+ keep_it = 0;
+
+#if defined (BFD_ASSEMBLER) || !defined (BFD)
+ /* This used to be done at the start of write_object_file in
+ write.c, but that caused problems when doing listings when
+ keep_it was zero. This could probably be moved above md_end, but
+ I didn't want to risk the change. */
+ subsegs_finish ();
+#endif
+
+ if (keep_it)
+ write_object_file ();
+
+#ifndef NO_LISTING
+ listing_print (listing_filename);
+#endif
+
+#ifndef OBJ_VMS /* does its own file handling */
+#ifndef BFD_ASSEMBLER
+ if (keep_it)
+#endif
+ output_file_close (out_file_name);
+#endif
+
+ if (had_errors () > 0 && ! flag_always_generate_output)
+ keep_it = 0;
+
+ if (!keep_it)
+ unlink (out_file_name);
+
+ input_scrub_end ();
+
+ END_PROGRESS (myname);
+
+ /* Use xexit instead of return, because under VMS environments they
+ may not place the same interpretation on the value given. */
+ if (had_errors () > 0)
+ xexit (EXIT_FAILURE);
+
+ /* Only generate dependency file if assembler was successful. */
+ print_dependencies ();
+
+ xexit (EXIT_SUCCESS);
+}
+
+static void
+dump_statistics ()
+{
+#ifdef HAVE_SBRK
+ char *lim = (char *) sbrk (0);
+#endif
+ long run_time = get_run_time () - start_time;
+
+ fprintf (stderr, _("%s: total time in assembly: %ld.%06ld\n"),
+ myname, run_time / 1000000, run_time % 1000000);
+#ifdef HAVE_SBRK
+ fprintf (stderr, _("%s: data size %ld\n"),
+ myname, (long) (lim - (char *) &environ));
+#endif
+
+ subsegs_print_statistics (stderr);
+ write_print_statistics (stderr);
+ symbol_print_statistics (stderr);
+ read_print_statistics (stderr);
+
+#ifdef tc_print_statistics
+ tc_print_statistics (stderr);
+#endif
+#ifdef obj_print_statistics
+ obj_print_statistics (stderr);
+#endif
+}
+
+
+/* perform_an_assembly_pass()
+ *
+ * Here to attempt 1 pass over each input file.
+ * We scan argv[*] looking for filenames or exactly "" which is
+ * shorthand for stdin. Any argv that is NULL is not a file-name.
+ * We set need_pass_2 TRUE if, after this, we still have unresolved
+ * expressions of the form (unknown value)+-(unknown value).
+ *
+ * Note the un*x semantics: there is only 1 logical input file, but it
+ * may be a catenation of many 'physical' input files.
+ */
+static void
+perform_an_assembly_pass (argc, argv)
+ int argc;
+ char **argv;
+{
+ int saw_a_file = 0;
+#ifdef BFD_ASSEMBLER
+ flagword applicable;
+#endif
+
+ need_pass_2 = 0;
+
+#ifndef BFD_ASSEMBLER
+#ifdef MANY_SEGMENTS
+ {
+ unsigned int i;
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ segment_info[i].fix_root = 0;
+ }
+ /* Create the three fixed ones */
+ {
+ segT seg;
+
+#ifdef TE_APOLLO
+ seg = subseg_new (".wtext", 0);
+#else
+ seg = subseg_new (".text", 0);
+#endif
+ assert (seg == SEG_E0);
+ seg = subseg_new (".data", 0);
+ assert (seg == SEG_E1);
+ seg = subseg_new (".bss", 0);
+ assert (seg == SEG_E2);
+#ifdef TE_APOLLO
+ create_target_segments ();
+#endif
+ }
+
+#else /* not MANY_SEGMENTS */
+ text_fix_root = NULL;
+ data_fix_root = NULL;
+ bss_fix_root = NULL;
+#endif /* not MANY_SEGMENTS */
+#else /* BFD_ASSEMBLER */
+ /* Create the standard sections, and those the assembler uses
+ internally. */
+ text_section = subseg_new (TEXT_SECTION_NAME, 0);
+ data_section = subseg_new (DATA_SECTION_NAME, 0);
+ bss_section = subseg_new (BSS_SECTION_NAME, 0);
+ /* @@ FIXME -- we're setting the RELOC flag so that sections are assumed
+ to have relocs, otherwise we don't find out in time. */
+ applicable = bfd_applicable_section_flags (stdoutput);
+ bfd_set_section_flags (stdoutput, text_section,
+ applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC
+ | SEC_CODE | SEC_READONLY));
+ /* @@ FIXME -- SEC_CODE seems to mean code only, rather than code possibly.*/
+ bfd_set_section_flags (stdoutput, data_section,
+ applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC));
+ bfd_set_section_flags (stdoutput, bss_section, applicable & SEC_ALLOC);
+ seg_info (bss_section)->bss = 1;
+ subseg_new (BFD_ABS_SECTION_NAME, 0);
+ subseg_new (BFD_UND_SECTION_NAME, 0);
+ reg_section = subseg_new ("*GAS `reg' section*", 0);
+ expr_section = subseg_new ("*GAS `expr' section*", 0);
+
+#endif /* BFD_ASSEMBLER */
+
+ subseg_set (text_section, 0);
+
+ /* This may add symbol table entries, which requires having an open BFD,
+ and sections already created, in BFD_ASSEMBLER mode. */
+ md_begin ();
+
+#ifdef obj_begin
+ obj_begin ();
+#endif
+
+ argv++; /* skip argv[0] */
+ argc--; /* skip argv[0] */
+ while (argc--)
+ {
+ if (*argv)
+ { /* Is it a file-name argument? */
+ PROGRESS (1);
+ saw_a_file++;
+ /* argv->"" if stdin desired, else->filename */
+ read_a_source_file (*argv);
+ }
+ argv++; /* completed that argv */
+ }
+ if (!saw_a_file)
+ read_a_source_file ("");
+} /* perform_an_assembly_pass() */
+
+/* The interface between the macro code and gas expression handling. */
+
+static int
+macro_expr (emsg, idx, in, val)
+ const char *emsg;
+ int idx;
+ sb *in;
+ int *val;
+{
+ char *hold;
+ expressionS ex;
+
+ sb_terminate (in);
+
+ hold = input_line_pointer;
+ input_line_pointer = in->ptr + idx;
+ expression (&ex);
+ idx = input_line_pointer - in->ptr;
+ input_line_pointer = hold;
+
+ if (ex.X_op != O_constant)
+ as_bad ("%s", emsg);
+
+ *val = (int) ex.X_add_number;
+
+ return idx;
+}
+
+/* end of as.c */
diff --git a/gas/as.h b/gas/as.h
new file mode 100644
index 0000000000..a72dfad28d
--- /dev/null
+++ b/gas/as.h
@@ -0,0 +1,645 @@
+/* as.h - global header file
+ Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 97, 1998
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#ifndef GAS
+#define GAS 1
+/*
+ * I think this stuff is largely out of date. xoxorich.
+ *
+ * CAPITALISED names are #defined.
+ * "lowercaseH" is #defined if "lowercase.h" has been #include-d.
+ * "lowercaseT" is a typedef of "lowercase" objects.
+ * "lowercaseP" is type "pointer to object of type 'lowercase'".
+ * "lowercaseS" is typedef struct ... lowercaseS.
+ *
+ * #define DEBUG to enable all the "know" assertion tests.
+ * #define SUSPECT when debugging hash code.
+ * #define COMMON as "extern" for all modules except one, where you #define
+ * COMMON as "".
+ * If TEST is #defined, then we are testing a module: #define COMMON as "".
+ */
+
+#include "config.h"
+
+/* This is the code recommended in the autoconf documentation, almost
+ verbatim. If it doesn't work for you, let me know, and notify
+ djm@gnu.ai.mit.edu as well. */
+/* Added #undef for DJ Delorie. The right fix is to ensure that as.h
+ is included first, before even any system header files, in all files
+ that use it. KR 1994.11.03 */
+/* Added void* version for STDC case. This is to be compatible with
+ the declaration in bison.simple, used for m68k operand parsing.
+ --KR 1995.08.08 */
+/* Force void* decl for hpux. This is what Bison uses. --KR 1995.08.16 */
+
+/* AIX requires this to be the first thing in the file. */
+#ifdef __GNUC__
+# ifndef alloca
+# ifdef __STDC__
+extern void *alloca ();
+# else
+extern char *alloca ();
+# endif
+# endif
+#else
+# if HAVE_ALLOCA_H
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca /* predefined by HP cc +Olibcalls */
+# if !defined (__STDC__) && !defined (__hpux)
+extern char *alloca ();
+# else
+extern void *alloca ();
+# endif /* __STDC__, __hpux */
+# endif /* alloca */
+# endif /* _AIX */
+# endif /* HAVE_ALLOCA_H */
+#endif
+
+/* Now, tend to the rest of the configuration. */
+
+/* System include files first... */
+#include <stdio.h>
+#include <ctype.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+/* for size_t, pid_t */
+#include <sys/types.h>
+#endif
+
+#include <getopt.h>
+/* The first getopt value for machine-independent long options.
+ 150 isn't special; it's just an arbitrary non-ASCII char value. */
+#define OPTION_STD_BASE 150
+/* The first getopt value for machine-dependent long options.
+ 170 gives the standard options room to grow. */
+#define OPTION_MD_BASE 170
+
+#ifdef DEBUG
+#undef NDEBUG
+#endif
+#if !defined (__GNUC__) || __GNUC_MINOR__ <= 5
+#define __PRETTY_FUNCTION__ ((char*)0)
+#endif
+#if 0
+
+/* Handle lossage with assert.h. */
+#ifndef BROKEN_ASSERT
+#include <assert.h>
+#else /* BROKEN_ASSERT */
+#ifndef NDEBUG
+#define assert(p) ((p) ? 0 : (as_assert (__FILE__, __LINE__, __PRETTY_FUNCTION__), 0))
+#else
+#define assert(p) ((p), 0)
+#endif
+#endif /* BROKEN_ASSERT */
+
+#else
+
+#define assert(P) ((P) ? 0 : (as_assert (__FILE__, __LINE__, __PRETTY_FUNCTION__), 0))
+#undef abort
+#define abort() as_abort (__FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+#endif
+
+
+/* Now GNU header files... */
+#include <ansidecl.h>
+#ifdef BFD_ASSEMBLER
+#include <bfd.h>
+#endif
+#include <libiberty.h>
+
+/* Define the standard progress macros. */
+#include <progress.h>
+
+/* This doesn't get taken care of anywhere. */
+#ifndef __MWERKS__ /* Metrowerks C chokes on the "defined (inline)" */
+#if !defined (__GNUC__) && !defined (inline)
+#define inline
+#endif
+#endif /* !__MWERKS__ */
+
+/* Other stuff from config.h. */
+#ifdef NEED_DECLARATION_STRSTR
+extern char *strstr ();
+#endif
+#ifdef NEED_DECLARATION_MALLOC
+extern PTR malloc ();
+extern PTR realloc ();
+#endif
+#ifdef NEED_DECLARATION_FREE
+extern void free ();
+#endif
+#ifdef NEED_DECLARATION_ERRNO
+extern int errno;
+#endif
+#ifdef NEED_DECLARATION_ENVIRON
+extern char **environ;
+#endif
+
+/* This is needed for VMS. */
+#if ! defined (HAVE_UNLINK) && defined (HAVE_REMOVE)
+#define unlink remove
+#endif
+
+/* Hack to make "gcc -Wall" not complain about obstack macros. */
+#if !defined (memcpy) && !defined (bcopy)
+#define bcopy(src,dest,size) memcpy(dest,src,size)
+#endif
+
+/* Make Saber happier on obstack.h. */
+#ifdef SABER
+#undef __PTR_TO_INT
+#define __PTR_TO_INT(P) ((int)(P))
+#undef __INT_TO_PTR
+#define __INT_TO_PTR(P) ((char *)(P))
+#endif
+
+#ifndef __LINE__
+#define __LINE__ "unknown"
+#endif /* __LINE__ */
+
+#ifndef __FILE__
+#define __FILE__ "unknown"
+#endif /* __FILE__ */
+
+#ifndef FOPEN_WB
+#ifdef GO32
+#include "fopen-bin.h"
+#else
+#include "fopen-same.h"
+#endif
+#endif
+
+#ifndef EXIT_SUCCESS
+#define EXIT_SUCCESS 0
+#define EXIT_FAILURE 1
+#endif
+
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free xfree
+
+#define xfree free
+
+#include "asintl.h"
+
+#define BAD_CASE(val) \
+{ \
+ as_fatal(_("Case value %ld unexpected at line %d of file \"%s\"\n"), \
+ (long) val, __LINE__, __FILE__); \
+ }
+
+#include "flonum.h"
+
+/* These are assembler-wide concepts */
+
+#ifdef BFD_ASSEMBLER
+extern bfd *stdoutput;
+typedef bfd_vma addressT;
+typedef bfd_signed_vma offsetT;
+#else
+typedef unsigned long addressT;
+typedef long offsetT;
+#endif
+
+/* Type of symbol value, etc. For use in prototypes. */
+typedef addressT valueT;
+
+#ifndef COMMON
+#ifdef TEST
+#define COMMON /* declare our COMMONs storage here. */
+#else
+#define COMMON extern /* our commons live elswhere */
+#endif
+#endif
+/* COMMON now defined */
+
+#ifdef DEBUG
+#ifndef know
+#define know(p) assert(p) /* Verify our assumptions! */
+#endif /* not yet defined */
+#else
+#define know(p) /* know() checks are no-op.ed */
+#endif
+
+/* input_scrub.c */
+
+/*
+ * Supplies sanitised buffers to read.c.
+ * Also understands printing line-number part of error messages.
+ */
+
+
+/* subsegs.c Sub-segments. Also, segment(=expression type)s.*/
+
+#ifndef BFD_ASSEMBLER
+
+#ifdef MANY_SEGMENTS
+#include "bfd.h"
+#define N_SEGMENTS 40
+#define SEG_NORMAL(x) ((x) >= SEG_E0 && (x) <= SEG_E39)
+#define SEG_LIST SEG_E0,SEG_E1,SEG_E2,SEG_E3,SEG_E4,SEG_E5,SEG_E6,SEG_E7,SEG_E8,SEG_E9,\
+ SEG_E10,SEG_E11,SEG_E12,SEG_E13,SEG_E14,SEG_E15,SEG_E16,SEG_E17,SEG_E18,SEG_E19,\
+ SEG_E20,SEG_E21,SEG_E22,SEG_E23,SEG_E24,SEG_E25,SEG_E26,SEG_E27,SEG_E28,SEG_E29,\
+ SEG_E30,SEG_E31,SEG_E32,SEG_E33,SEG_E34,SEG_E35,SEG_E36,SEG_E37,SEG_E38,SEG_E39
+#define SEG_TEXT SEG_E0
+#define SEG_DATA SEG_E1
+#define SEG_BSS SEG_E2
+#define SEG_LAST SEG_E39
+#else
+#define N_SEGMENTS 3
+#define SEG_NORMAL(x) ((x) == SEG_TEXT || (x) == SEG_DATA || (x) == SEG_BSS)
+#define SEG_LIST SEG_TEXT,SEG_DATA,SEG_BSS
+#endif
+
+typedef enum _segT
+ {
+ SEG_ABSOLUTE = 0,
+ SEG_LIST,
+ SEG_UNKNOWN,
+ SEG_GOOF, /* Only happens if AS has a logic error. */
+ /* Invented so we don't crash printing */
+ /* error message involving weird segment. */
+ SEG_EXPR, /* Intermediate expression values. */
+ SEG_DEBUG, /* Debug segment */
+ SEG_NTV, /* Transfert vector preload segment */
+ SEG_PTV, /* Transfert vector postload segment */
+ SEG_REGISTER /* Mythical: a register-valued expression */
+ } segT;
+
+#define SEG_MAXIMUM_ORDINAL (SEG_REGISTER)
+#else
+typedef asection *segT;
+#define SEG_NORMAL(SEG) ((SEG) != absolute_section \
+ && (SEG) != undefined_section \
+ && (SEG) != reg_section \
+ && (SEG) != expr_section)
+#endif
+typedef int subsegT;
+
+/* What subseg we are accreting now? */
+COMMON subsegT now_subseg;
+
+/* Segment our instructions emit to. */
+COMMON segT now_seg;
+
+#ifdef BFD_ASSEMBLER
+#define segment_name(SEG) bfd_get_section_name (stdoutput, SEG)
+#else
+extern char const *const seg_name[];
+#define segment_name(SEG) seg_name[(int) (SEG)]
+#endif
+
+#ifndef BFD_ASSEMBLER
+extern int section_alignment[];
+#endif
+
+#ifdef BFD_ASSEMBLER
+extern segT reg_section, expr_section;
+/* Shouldn't these be eliminated someday? */
+extern segT text_section, data_section, bss_section;
+#define absolute_section bfd_abs_section_ptr
+#define undefined_section bfd_und_section_ptr
+#else
+#define reg_section SEG_REGISTER
+#define expr_section SEG_EXPR
+#define text_section SEG_TEXT
+#define data_section SEG_DATA
+#define bss_section SEG_BSS
+#define absolute_section SEG_ABSOLUTE
+#define undefined_section SEG_UNKNOWN
+#endif
+
+/* relax() */
+
+enum _relax_state
+ {
+ /* Variable chars to be repeated fr_offset times.
+ Fr_symbol unused. Used with fr_offset == 0 for a
+ constant length frag. */
+ rs_fill = 1,
+
+ /* Align. The fr_offset field holds the power of 2 to which to
+ align. The fr_var field holds the number of characters in the
+ fill pattern. The fr_subtype field holds the maximum number of
+ bytes to skip when aligning, or 0 if there is no maximum. */
+ rs_align,
+
+ /* Align code. The fr_offset field holds the power of 2 to which
+ to align. This type is only generated by machine specific
+ code, which is normally responsible for handling the fill
+ pattern. The fr_subtype field holds the maximum number of
+ bytes to skip when aligning, or 0 if there is no maximum. */
+ rs_align_code,
+
+ /* Org: Fr_offset, fr_symbol: address. 1 variable char: fill
+ character. */
+ rs_org,
+
+#ifndef WORKING_DOT_WORD
+ /* JF: gunpoint */
+ rs_broken_word,
+#endif
+
+ /* machine-specific relaxable (or similarly alterable) instruction */
+ rs_machine_dependent,
+
+ /* .space directive with expression operand that needs to be computed
+ later. Similar to rs_org, but different.
+ fr_symbol: operand
+ 1 variable char: fill character */
+ rs_space,
+
+ /* A DWARF leb128 value; only ELF uses this. The subtype is 0 for
+ unsigned, 1 for signed. */
+ rs_leb128,
+
+ /* Exception frame information which we may be able to optimize. */
+ rs_cfa
+ };
+
+typedef enum _relax_state relax_stateT;
+
+/* This type is used in prototypes, so it can't be a type that will be
+ widened for argument passing. */
+typedef unsigned int relax_substateT;
+
+/* Enough bits for address, but still an integer type.
+ Could be a problem, cross-assembling for 64-bit machines. */
+typedef addressT relax_addressT;
+
+/* main program "as.c" (command arguments etc) */
+
+COMMON unsigned char flag_no_comments; /* -f */
+COMMON unsigned char flag_debug; /* -D */
+COMMON unsigned char flag_signed_overflow_ok; /* -J */
+#ifndef WORKING_DOT_WORD
+COMMON unsigned char flag_warn_displacement; /* -K */
+#endif
+
+/* True if local symbols should be retained. */
+COMMON int flag_keep_locals; /* -L */
+
+/* True if we are assembling in MRI mode. */
+COMMON int flag_mri;
+
+/* True if we are assembling in m68k MRI mode. */
+COMMON int flag_m68k_mri;
+
+/* Should the data section be made read-only and appended to the text
+ section? */
+COMMON unsigned char flag_readonly_data_in_text; /* -R */
+
+/* True if warnings should be inhibited. */
+COMMON int flag_no_warnings; /* -W */
+
+/* True if we should attempt to generate output even if non-fatal errors
+ are detected. */
+COMMON unsigned char flag_always_generate_output; /* -Z */
+
+/* This is true if the assembler should output time and space usage. */
+COMMON unsigned char flag_print_statistics;
+
+/* True if local absolute symbols are to be stripped. */
+COMMON int flag_strip_local_absolute;
+
+/* True if we should generate a traditional format object file. */
+COMMON int flag_traditional_format;
+
+/* name of emitted object file */
+COMMON char *out_file_name;
+
+/* name of file defining extensions to the basic instruction set */
+COMMON char *insttbl_file_name;
+
+/* TRUE if we need a second pass. */
+COMMON int need_pass_2;
+
+/* TRUE if we should do no relaxing, and
+ leave lots of padding. */
+COMMON int linkrelax;
+
+/* TRUE if we should produce a listing. */
+extern int listing;
+
+/* Type of debugging information we should generate. We currently
+ only support stabs and ECOFF. */
+
+enum debug_info_type
+ {
+ DEBUG_UNSPECIFIED,
+ DEBUG_NONE,
+ DEBUG_STABS,
+ DEBUG_ECOFF,
+ DEBUG_DWARF,
+ DEBUG_DWARF2
+ };
+
+extern enum debug_info_type debug_type;
+
+/* Maximum level of macro nesting. */
+extern int max_macro_nest;
+
+/* Obstack chunk size. Keep large for efficient space use, make small to
+ increase malloc calls for monitoring memory allocation. */
+extern int chunksize;
+
+struct _pseudo_type
+ {
+ /* assembler mnemonic, lower case, no '.' */
+ const char *poc_name;
+ /* Do the work */
+ void (*poc_handler) PARAMS ((int));
+ /* Value to pass to handler */
+ int poc_val;
+ };
+
+typedef struct _pseudo_type pseudo_typeS;
+
+/* Prefer varargs for non-ANSI compiler, since some will barf if the
+ ellipsis definition is used with a no-arguments declaration. */
+#if defined (HAVE_VARARGS_H) && !defined (__STDC__)
+#undef HAVE_STDARG_H
+#endif
+
+#if defined (HAVE_STDARG_H)
+#define USE_STDARG
+#endif
+#if !defined (USE_STDARG) && defined (HAVE_VARARGS_H)
+#define USE_VARARGS
+#endif
+
+#ifdef USE_STDARG
+#if (__GNUC__ >= 2) && !defined(VMS)
+/* for use with -Wformat */
+
+#if __GNUC_MINOR__ < 6
+/* Support for double underscores in attribute names was added in gcc
+ 2.6, so avoid them if we are using an earlier version. */
+#define __printf__ printf
+#define __format__ format
+#endif
+
+#define PRINTF_LIKE(FCN) \
+ void FCN (const char *format, ...) \
+ __attribute__ ((__format__ (__printf__, 1, 2)))
+#define PRINTF_WHERE_LIKE(FCN) \
+ void FCN (char *file, unsigned int line, const char *format, ...) \
+ __attribute__ ((__format__ (__printf__, 3, 4)))
+
+#else /* __GNUC__ < 2 || defined(VMS) */
+
+#define PRINTF_LIKE(FCN) void FCN PARAMS ((const char *format, ...))
+#define PRINTF_WHERE_LIKE(FCN) void FCN PARAMS ((char *file, \
+ unsigned int line, \
+ const char *format, ...))
+
+#endif /* __GNUC__ < 2 || defined(VMS) */
+
+#else /* ! USE_STDARG */
+
+#define PRINTF_LIKE(FCN) void FCN ()
+#define PRINTF_WHERE_LIKE(FCN) void FCN ()
+
+#endif /* ! USE_STDARG */
+
+PRINTF_LIKE (as_bad);
+PRINTF_LIKE (as_fatal);
+PRINTF_LIKE (as_tsktsk);
+PRINTF_LIKE (as_warn);
+PRINTF_WHERE_LIKE (as_bad_where);
+PRINTF_WHERE_LIKE (as_warn_where);
+
+void as_assert PARAMS ((const char *, int, const char *));
+void as_abort PARAMS ((const char *, int, const char *));
+
+void fprint_value PARAMS ((FILE *file, addressT value));
+void sprint_value PARAMS ((char *buf, addressT value));
+
+int had_errors PARAMS ((void));
+int had_warnings PARAMS ((void));
+
+void print_version_id PARAMS ((void));
+char *app_push PARAMS ((void));
+char *atof_ieee PARAMS ((char *str, int what_kind, LITTLENUM_TYPE * words));
+char *input_scrub_include_file PARAMS ((char *filename, char *position));
+char *input_scrub_new_file PARAMS ((char *filename));
+char *input_scrub_next_buffer PARAMS ((char **bufp));
+int do_scrub_chars PARAMS ((int (*get) (char **), char *to, int tolen));
+int gen_to_words PARAMS ((LITTLENUM_TYPE * words, int precision,
+ long exponent_bits));
+int had_err PARAMS ((void));
+int ignore_input PARAMS ((void));
+void cond_finish_check PARAMS ((int));
+void cond_exit_macro PARAMS ((int));
+int seen_at_least_1_file PARAMS ((void));
+void app_pop PARAMS ((char *arg));
+void as_howmuch PARAMS ((FILE * stream));
+void as_perror PARAMS ((const char *gripe, const char *filename));
+void as_where PARAMS ((char **namep, unsigned int *linep));
+void bump_line_counters PARAMS ((void));
+void do_scrub_begin PARAMS ((int));
+void input_scrub_begin PARAMS ((void));
+void input_scrub_close PARAMS ((void));
+void input_scrub_end PARAMS ((void));
+int new_logical_line PARAMS ((char *fname, int line_number));
+void subsegs_begin PARAMS ((void));
+void subseg_change PARAMS ((segT seg, int subseg));
+segT subseg_new PARAMS ((const char *name, subsegT subseg));
+segT subseg_force_new PARAMS ((const char *name, subsegT subseg));
+void subseg_set PARAMS ((segT seg, subsegT subseg));
+#ifdef BFD_ASSEMBLER
+segT subseg_get PARAMS ((const char *, int));
+#endif
+
+void start_dependencies PARAMS ((char *));
+void register_dependency PARAMS ((char *));
+void print_dependencies PARAMS ((void));
+
+struct expressionS;
+struct fix;
+struct symbol;
+struct relax_type;
+typedef struct frag fragS;
+
+#ifdef BFD_ASSEMBLER
+/* literal.c */
+valueT add_to_literal_pool PARAMS ((struct symbol *, valueT, segT, int));
+#endif
+
+int check_eh_frame PARAMS ((struct expressionS *, unsigned int *));
+int eh_frame_estimate_size_before_relax PARAMS ((fragS *));
+int eh_frame_relax_frag PARAMS ((fragS *));
+void eh_frame_convert_frag PARAMS ((fragS *));
+
+#include "expr.h" /* Before targ-*.h */
+
+/* this one starts the chain of target dependant headers */
+#include "targ-env.h"
+
+#include "struc-symbol.h"
+#include "write.h"
+#include "frags.h"
+#include "hash.h"
+#include "read.h"
+#include "symbols.h"
+
+#include "tc.h"
+#include "obj.h"
+
+#ifdef USE_EMULATIONS
+#include "emul.h"
+#endif
+#include "listing.h"
+
+#ifndef LOCAL_LABELS_DOLLAR
+#define LOCAL_LABELS_DOLLAR 0
+#endif
+
+#ifndef LOCAL_LABELS_FB
+#define LOCAL_LABELS_FB 0
+#endif
+
+#ifndef TEXT_SECTION_NAME
+#define TEXT_SECTION_NAME ".text"
+#define DATA_SECTION_NAME ".data"
+#define BSS_SECTION_NAME ".bss"
+#endif
+
+#endif /* GAS */
+
+/* end of as.h */
diff --git a/gas/asintl.h b/gas/asintl.h
new file mode 100644
index 0000000000..b733c85f0f
--- /dev/null
+++ b/gas/asintl.h
@@ -0,0 +1,44 @@
+/* asintl.h - gas-specific header for gettext code.
+ Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+
+ Written by Tom Tromey <tromey@cygnus.com>
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#ifdef HAVE_LOCALE_H
+# include <locale.h>
+#endif
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# define _(String) gettext (String)
+# ifdef gettext_noop
+# define N_(String) gettext_noop (String)
+# else
+# define N_(String) (String)
+# endif
+#else
+/* Stubs that do something close enough. */
+# define textdomain(String) (String)
+# define gettext(String) (String)
+# define dgettext(Domain,Message) (Message)
+# define dcgettext(Domain,Message,Type) (Message)
+# define bindtextdomain(Domain,Directory) (Domain)
+# define _(String) (String)
+# define N_(String) (String)
+#endif
diff --git a/gas/atof-generic.c b/gas/atof-generic.c
new file mode 100644
index 0000000000..316f665a45
--- /dev/null
+++ b/gas/atof-generic.c
@@ -0,0 +1,636 @@
+/* atof_generic.c - turn a string of digits into a Flonum
+ Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 1998
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <ctype.h>
+#include <string.h>
+
+#include "as.h"
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+#ifndef TRUE
+#define TRUE (1)
+#endif
+
+#ifdef TRACE
+static void flonum_print PARAMS ((const FLONUM_TYPE *));
+#endif
+
+#define ASSUME_DECIMAL_MARK_IS_DOT
+
+/***********************************************************************\
+ * *
+ * Given a string of decimal digits , with optional decimal *
+ * mark and optional decimal exponent (place value) of the *
+ * lowest_order decimal digit: produce a floating point *
+ * number. The number is 'generic' floating point: our *
+ * caller will encode it for a specific machine architecture. *
+ * *
+ * Assumptions *
+ * uses base (radix) 2 *
+ * this machine uses 2's complement binary integers *
+ * target flonums use " " " " *
+ * target flonums exponents fit in a long *
+ * *
+ \***********************************************************************/
+
+/*
+
+ Syntax:
+
+ <flonum> ::= <optional-sign> <decimal-number> <optional-exponent>
+ <optional-sign> ::= '+' | '-' | {empty}
+ <decimal-number> ::= <integer>
+ | <integer> <radix-character>
+ | <integer> <radix-character> <integer>
+ | <radix-character> <integer>
+
+ <optional-exponent> ::= {empty}
+ | <exponent-character> <optional-sign> <integer>
+
+ <integer> ::= <digit> | <digit> <integer>
+ <digit> ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
+ <exponent-character> ::= {one character from "string_of_decimal_exponent_marks"}
+ <radix-character> ::= {one character from "string_of_decimal_marks"}
+
+ */
+
+int
+atof_generic (address_of_string_pointer,
+ string_of_decimal_marks,
+ string_of_decimal_exponent_marks,
+ address_of_generic_floating_point_number)
+ /* return pointer to just AFTER number we read. */
+ char **address_of_string_pointer;
+ /* At most one per number. */
+ const char *string_of_decimal_marks;
+ const char *string_of_decimal_exponent_marks;
+ FLONUM_TYPE *address_of_generic_floating_point_number;
+{
+ int return_value; /* 0 means OK. */
+ char *first_digit;
+ unsigned int number_of_digits_before_decimal;
+ unsigned int number_of_digits_after_decimal;
+ long decimal_exponent;
+ unsigned int number_of_digits_available;
+ char digits_sign_char;
+
+ /*
+ * Scan the input string, abstracting (1)digits (2)decimal mark (3) exponent.
+ * It would be simpler to modify the string, but we don't; just to be nice
+ * to caller.
+ * We need to know how many digits we have, so we can allocate space for
+ * the digits' value.
+ */
+
+ char *p;
+ char c;
+ int seen_significant_digit;
+
+#ifdef ASSUME_DECIMAL_MARK_IS_DOT
+ assert (string_of_decimal_marks[0] == '.'
+ && string_of_decimal_marks[1] == 0);
+#define IS_DECIMAL_MARK(c) ((c) == '.')
+#else
+#define IS_DECIMAL_MARK(c) (0 != strchr (string_of_decimal_marks, (c)))
+#endif
+
+ first_digit = *address_of_string_pointer;
+ c = *first_digit;
+
+ if (c == '-' || c == '+')
+ {
+ digits_sign_char = c;
+ first_digit++;
+ }
+ else
+ digits_sign_char = '+';
+
+ switch (first_digit[0])
+ {
+ case 'n':
+ case 'N':
+ if (!strncasecmp ("nan", first_digit, 3))
+ {
+ address_of_generic_floating_point_number->sign = 0;
+ address_of_generic_floating_point_number->exponent = 0;
+ address_of_generic_floating_point_number->leader =
+ address_of_generic_floating_point_number->low;
+ *address_of_string_pointer = first_digit + 3;
+ return 0;
+ }
+ break;
+
+ case 'i':
+ case 'I':
+ if (!strncasecmp ("inf", first_digit, 3))
+ {
+ address_of_generic_floating_point_number->sign =
+ digits_sign_char == '+' ? 'P' : 'N';
+ address_of_generic_floating_point_number->exponent = 0;
+ address_of_generic_floating_point_number->leader =
+ address_of_generic_floating_point_number->low;
+
+ first_digit += 3;
+ if (!strncasecmp ("inity", first_digit, 5))
+ first_digit += 5;
+
+ *address_of_string_pointer = first_digit;
+
+ return 0;
+ }
+ break;
+ }
+
+ number_of_digits_before_decimal = 0;
+ number_of_digits_after_decimal = 0;
+ decimal_exponent = 0;
+ seen_significant_digit = 0;
+ for (p = first_digit;
+ (((c = *p) != '\0')
+ && (!c || !IS_DECIMAL_MARK (c))
+ && (!c || !strchr (string_of_decimal_exponent_marks, c)));
+ p++)
+ {
+ if (isdigit ((unsigned char) c))
+ {
+ if (seen_significant_digit || c > '0')
+ {
+ ++number_of_digits_before_decimal;
+ seen_significant_digit = 1;
+ }
+ else
+ {
+ first_digit++;
+ }
+ }
+ else
+ {
+ break; /* p -> char after pre-decimal digits. */
+ }
+ } /* For each digit before decimal mark. */
+
+#ifndef OLD_FLOAT_READS
+ /* Ignore trailing 0's after the decimal point. The original code here
+ * (ifdef'd out) does not do this, and numbers like
+ * 4.29496729600000000000e+09 (2**31)
+ * come out inexact for some reason related to length of the digit
+ * string.
+ */
+ if (c && IS_DECIMAL_MARK (c))
+ {
+ unsigned int zeros = 0; /* Length of current string of zeros */
+
+ for (p++; (c = *p) && isdigit ((unsigned char) c); p++)
+ {
+ if (c == '0')
+ {
+ zeros++;
+ }
+ else
+ {
+ number_of_digits_after_decimal += 1 + zeros;
+ zeros = 0;
+ }
+ }
+ }
+#else
+ if (c && IS_DECIMAL_MARK (c))
+ {
+ for (p++;
+ (((c = *p) != '\0')
+ && (!c || !strchr (string_of_decimal_exponent_marks, c)));
+ p++)
+ {
+ if (isdigit (c))
+ {
+ /* This may be retracted below. */
+ number_of_digits_after_decimal++;
+
+ if ( /* seen_significant_digit || */ c > '0')
+ {
+ seen_significant_digit = TRUE;
+ }
+ }
+ else
+ {
+ if (!seen_significant_digit)
+ {
+ number_of_digits_after_decimal = 0;
+ }
+ break;
+ }
+ } /* For each digit after decimal mark. */
+ }
+
+ while (number_of_digits_after_decimal
+ && first_digit[number_of_digits_before_decimal
+ + number_of_digits_after_decimal] == '0')
+ --number_of_digits_after_decimal;
+#endif
+
+ if (flag_m68k_mri)
+ {
+ while (c == '_')
+ c = *++p;
+ }
+ if (c && strchr (string_of_decimal_exponent_marks, c))
+ {
+ char digits_exponent_sign_char;
+
+ c = *++p;
+ if (flag_m68k_mri)
+ {
+ while (c == '_')
+ c = *++p;
+ }
+ if (c && strchr ("+-", c))
+ {
+ digits_exponent_sign_char = c;
+ c = *++p;
+ }
+ else
+ {
+ digits_exponent_sign_char = '+';
+ }
+
+ for (; (c); c = *++p)
+ {
+ if (isdigit ((unsigned char) c))
+ {
+ decimal_exponent = decimal_exponent * 10 + c - '0';
+ /*
+ * BUG! If we overflow here, we lose!
+ */
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (digits_exponent_sign_char == '-')
+ {
+ decimal_exponent = -decimal_exponent;
+ }
+ }
+
+ *address_of_string_pointer = p;
+
+
+
+ number_of_digits_available =
+ number_of_digits_before_decimal + number_of_digits_after_decimal;
+ return_value = 0;
+ if (number_of_digits_available == 0)
+ {
+ address_of_generic_floating_point_number->exponent = 0; /* Not strictly necessary */
+ address_of_generic_floating_point_number->leader
+ = -1 + address_of_generic_floating_point_number->low;
+ address_of_generic_floating_point_number->sign = digits_sign_char;
+ /* We have just concocted (+/-)0.0E0 */
+
+ }
+ else
+ {
+ int count; /* Number of useful digits left to scan. */
+
+ LITTLENUM_TYPE *digits_binary_low;
+ unsigned int precision;
+ unsigned int maximum_useful_digits;
+ unsigned int number_of_digits_to_use;
+ unsigned int more_than_enough_bits_for_digits;
+ unsigned int more_than_enough_littlenums_for_digits;
+ unsigned int size_of_digits_in_littlenums;
+ unsigned int size_of_digits_in_chars;
+ FLONUM_TYPE power_of_10_flonum;
+ FLONUM_TYPE digits_flonum;
+
+ precision = (address_of_generic_floating_point_number->high
+ - address_of_generic_floating_point_number->low
+ + 1); /* Number of destination littlenums. */
+
+ /* Includes guard bits (two littlenums worth) */
+#if 0 /* The integer version below is very close, and it doesn't
+ require floating point support (which is currently buggy on
+ the Alpha). */
+ maximum_useful_digits = (((double) (precision - 2))
+ * ((double) (LITTLENUM_NUMBER_OF_BITS))
+ / (LOG_TO_BASE_2_OF_10))
+ + 2; /* 2 :: guard digits. */
+#else
+ maximum_useful_digits = (((precision - 2))
+ * ( (LITTLENUM_NUMBER_OF_BITS))
+ * 1000000 / 3321928)
+ + 2; /* 2 :: guard digits. */
+#endif
+
+ if (number_of_digits_available > maximum_useful_digits)
+ {
+ number_of_digits_to_use = maximum_useful_digits;
+ }
+ else
+ {
+ number_of_digits_to_use = number_of_digits_available;
+ }
+
+ /* Cast these to SIGNED LONG first, otherwise, on systems with
+ LONG wider than INT (such as Alpha OSF/1), unsignedness may
+ cause unexpected results. */
+ decimal_exponent += ((long) number_of_digits_before_decimal
+ - (long) number_of_digits_to_use);
+
+#if 0
+ more_than_enough_bits_for_digits
+ = ((((double) number_of_digits_to_use) * LOG_TO_BASE_2_OF_10) + 1);
+#else
+ more_than_enough_bits_for_digits
+ = (number_of_digits_to_use * 3321928 / 1000000 + 1);
+#endif
+
+ more_than_enough_littlenums_for_digits
+ = (more_than_enough_bits_for_digits
+ / LITTLENUM_NUMBER_OF_BITS)
+ + 2;
+
+ /* Compute (digits) part. In "12.34E56" this is the "1234" part.
+ Arithmetic is exact here. If no digits are supplied then this
+ part is a 0 valued binary integer. Allocate room to build up
+ the binary number as littlenums. We want this memory to
+ disappear when we leave this function. Assume no alignment
+ problems => (room for n objects) == n * (room for 1
+ object). */
+
+ size_of_digits_in_littlenums = more_than_enough_littlenums_for_digits;
+ size_of_digits_in_chars = size_of_digits_in_littlenums
+ * sizeof (LITTLENUM_TYPE);
+
+ digits_binary_low = (LITTLENUM_TYPE *)
+ alloca (size_of_digits_in_chars);
+
+ memset ((char *) digits_binary_low, '\0', size_of_digits_in_chars);
+
+ /* Digits_binary_low[] is allocated and zeroed. */
+
+ /*
+ * Parse the decimal digits as if * digits_low was in the units position.
+ * Emit a binary number into digits_binary_low[].
+ *
+ * Use a large-precision version of:
+ * (((1st-digit) * 10 + 2nd-digit) * 10 + 3rd-digit ...) * 10 + last-digit
+ */
+
+ for (p = first_digit, count = number_of_digits_to_use; count; p++, --count)
+ {
+ c = *p;
+ if (isdigit ((unsigned char) c))
+ {
+ /*
+ * Multiply by 10. Assume can never overflow.
+ * Add this digit to digits_binary_low[].
+ */
+
+ long carry;
+ LITTLENUM_TYPE *littlenum_pointer;
+ LITTLENUM_TYPE *littlenum_limit;
+
+ littlenum_limit = digits_binary_low
+ + more_than_enough_littlenums_for_digits
+ - 1;
+
+ carry = c - '0'; /* char -> binary */
+
+ for (littlenum_pointer = digits_binary_low;
+ littlenum_pointer <= littlenum_limit;
+ littlenum_pointer++)
+ {
+ long work;
+
+ work = carry + 10 * (long) (*littlenum_pointer);
+ *littlenum_pointer = work & LITTLENUM_MASK;
+ carry = work >> LITTLENUM_NUMBER_OF_BITS;
+ }
+
+ if (carry != 0)
+ {
+ /*
+ * We have a GROSS internal error.
+ * This should never happen.
+ */
+ as_fatal (_("failed sanity check."));
+ }
+ }
+ else
+ {
+ ++count; /* '.' doesn't alter digits used count. */
+ }
+ }
+
+
+ /*
+ * Digits_binary_low[] properly encodes the value of the digits.
+ * Forget about any high-order littlenums that are 0.
+ */
+ while (digits_binary_low[size_of_digits_in_littlenums - 1] == 0
+ && size_of_digits_in_littlenums >= 2)
+ size_of_digits_in_littlenums--;
+
+ digits_flonum.low = digits_binary_low;
+ digits_flonum.high = digits_binary_low + size_of_digits_in_littlenums - 1;
+ digits_flonum.leader = digits_flonum.high;
+ digits_flonum.exponent = 0;
+ /*
+ * The value of digits_flonum . sign should not be important.
+ * We have already decided the output's sign.
+ * We trust that the sign won't influence the other parts of the number!
+ * So we give it a value for these reasons:
+ * (1) courtesy to humans reading/debugging
+ * these numbers so they don't get excited about strange values
+ * (2) in future there may be more meaning attached to sign,
+ * and what was
+ * harmless noise may become disruptive, ill-conditioned (or worse)
+ * input.
+ */
+ digits_flonum.sign = '+';
+
+ {
+ /*
+ * Compute the mantssa (& exponent) of the power of 10.
+ * If sucessful, then multiply the power of 10 by the digits
+ * giving return_binary_mantissa and return_binary_exponent.
+ */
+
+ LITTLENUM_TYPE *power_binary_low;
+ int decimal_exponent_is_negative;
+ /* This refers to the "-56" in "12.34E-56". */
+ /* FALSE: decimal_exponent is positive (or 0) */
+ /* TRUE: decimal_exponent is negative */
+ FLONUM_TYPE temporary_flonum;
+ LITTLENUM_TYPE *temporary_binary_low;
+ unsigned int size_of_power_in_littlenums;
+ unsigned int size_of_power_in_chars;
+
+ size_of_power_in_littlenums = precision;
+ /* Precision has a built-in fudge factor so we get a few guard bits. */
+
+ decimal_exponent_is_negative = decimal_exponent < 0;
+ if (decimal_exponent_is_negative)
+ {
+ decimal_exponent = -decimal_exponent;
+ }
+
+ /* From now on: the decimal exponent is > 0. Its sign is separate. */
+
+ size_of_power_in_chars = size_of_power_in_littlenums
+ * sizeof (LITTLENUM_TYPE) + 2;
+
+ power_binary_low = (LITTLENUM_TYPE *) alloca (size_of_power_in_chars);
+ temporary_binary_low = (LITTLENUM_TYPE *) alloca (size_of_power_in_chars);
+ memset ((char *) power_binary_low, '\0', size_of_power_in_chars);
+ *power_binary_low = 1;
+ power_of_10_flonum.exponent = 0;
+ power_of_10_flonum.low = power_binary_low;
+ power_of_10_flonum.leader = power_binary_low;
+ power_of_10_flonum.high = power_binary_low + size_of_power_in_littlenums - 1;
+ power_of_10_flonum.sign = '+';
+ temporary_flonum.low = temporary_binary_low;
+ temporary_flonum.high = temporary_binary_low + size_of_power_in_littlenums - 1;
+ /*
+ * (power) == 1.
+ * Space for temporary_flonum allocated.
+ */
+
+ /*
+ * ...
+ *
+ * WHILE more bits
+ * DO find next bit (with place value)
+ * multiply into power mantissa
+ * OD
+ */
+ {
+ int place_number_limit;
+ /* Any 10^(2^n) whose "n" exceeds this */
+ /* value will fall off the end of */
+ /* flonum_XXXX_powers_of_ten[]. */
+ int place_number;
+ const FLONUM_TYPE *multiplicand; /* -> 10^(2^n) */
+
+ place_number_limit = table_size_of_flonum_powers_of_ten;
+
+ multiplicand = (decimal_exponent_is_negative
+ ? flonum_negative_powers_of_ten
+ : flonum_positive_powers_of_ten);
+
+ for (place_number = 1;/* Place value of this bit of exponent. */
+ decimal_exponent;/* Quit when no more 1 bits in exponent. */
+ decimal_exponent >>= 1, place_number++)
+ {
+ if (decimal_exponent & 1)
+ {
+ if (place_number > place_number_limit)
+ {
+ /* The decimal exponent has a magnitude so great
+ that our tables can't help us fragment it.
+ Although this routine is in error because it
+ can't imagine a number that big, signal an
+ error as if it is the user's fault for
+ presenting such a big number. */
+ return_value = ERROR_EXPONENT_OVERFLOW;
+ /* quit out of loop gracefully */
+ decimal_exponent = 0;
+ }
+ else
+ {
+#ifdef TRACE
+ printf ("before multiply, place_number = %d., power_of_10_flonum:\n",
+ place_number);
+
+ flonum_print (&power_of_10_flonum);
+ (void) putchar ('\n');
+#endif
+#ifdef TRACE
+ printf ("multiplier:\n");
+ flonum_print (multiplicand + place_number);
+ (void) putchar ('\n');
+#endif
+ flonum_multip (multiplicand + place_number,
+ &power_of_10_flonum, &temporary_flonum);
+#ifdef TRACE
+ printf ("after multiply:\n");
+ flonum_print (&temporary_flonum);
+ (void) putchar ('\n');
+#endif
+ flonum_copy (&temporary_flonum, &power_of_10_flonum);
+#ifdef TRACE
+ printf ("after copy:\n");
+ flonum_print (&power_of_10_flonum);
+ (void) putchar ('\n');
+#endif
+ } /* If this bit of decimal_exponent was computable.*/
+ } /* If this bit of decimal_exponent was set. */
+ } /* For each bit of binary representation of exponent */
+#ifdef TRACE
+ printf ("after computing power_of_10_flonum:\n");
+ flonum_print (&power_of_10_flonum);
+ (void) putchar ('\n');
+#endif
+ }
+
+ }
+
+ /*
+ * power_of_10_flonum is power of ten in binary (mantissa) , (exponent).
+ * It may be the number 1, in which case we don't NEED to multiply.
+ *
+ * Multiply (decimal digits) by power_of_10_flonum.
+ */
+
+ flonum_multip (&power_of_10_flonum, &digits_flonum, address_of_generic_floating_point_number);
+ /* Assert sign of the number we made is '+'. */
+ address_of_generic_floating_point_number->sign = digits_sign_char;
+
+ }
+ return return_value;
+}
+
+#ifdef TRACE
+static void
+flonum_print (f)
+ const FLONUM_TYPE *f;
+{
+ LITTLENUM_TYPE *lp;
+ char littlenum_format[10];
+ sprintf (littlenum_format, " %%0%dx", sizeof (LITTLENUM_TYPE) * 2);
+#define print_littlenum(LP) (printf (littlenum_format, LP))
+ printf ("flonum @%p %c e%ld", f, f->sign, f->exponent);
+ if (f->low < f->high)
+ for (lp = f->high; lp >= f->low; lp--)
+ print_littlenum (*lp);
+ else
+ for (lp = f->low; lp <= f->high; lp++)
+ print_littlenum (*lp);
+ printf ("\n");
+ fflush (stdout);
+}
+#endif
+
+/* end of atof_generic.c */
diff --git a/gas/bignum-copy.c b/gas/bignum-copy.c
new file mode 100644
index 0000000000..2bffcbfea4
--- /dev/null
+++ b/gas/bignum-copy.c
@@ -0,0 +1,80 @@
+/* bignum_copy.c - copy a bignum
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "as.h"
+
+/*
+ * bignum_copy ()
+ *
+ * Copy a bignum from in to out.
+ * If the output is shorter than the input, copy lower-order littlenums.
+ * Return 0 or the number of significant littlenums dropped.
+ * Assumes littlenum arrays are densely packed: no unused chars between
+ * the littlenums. Uses memcpy() to move littlenums, and wants to
+ * know length (in chars) of the input bignum.
+ */
+
+/* void */
+int
+bignum_copy (in, in_length, out, out_length)
+ register LITTLENUM_TYPE *in;
+ register int in_length; /* in sizeof(littlenum)s */
+ register LITTLENUM_TYPE *out;
+ register int out_length; /* in sizeof(littlenum)s */
+{
+ int significant_littlenums_dropped;
+
+ if (out_length < in_length)
+ {
+ LITTLENUM_TYPE *p; /* -> most significant (non-zero) input
+ littlenum. */
+
+ memcpy ((void *) out, (void *) in,
+ (unsigned int) out_length << LITTLENUM_SHIFT);
+ for (p = in + in_length - 1; p >= in; --p)
+ {
+ if (*p)
+ break;
+ }
+ significant_littlenums_dropped = p - in - in_length + 1;
+
+ if (significant_littlenums_dropped < 0)
+ {
+ significant_littlenums_dropped = 0;
+ }
+ }
+ else
+ {
+ memcpy ((char *) out, (char *) in,
+ (unsigned int) in_length << LITTLENUM_SHIFT);
+
+ if (out_length > in_length)
+ {
+ memset ((char *) (out + in_length),
+ '\0',
+ (unsigned int) (out_length - in_length) << LITTLENUM_SHIFT);
+ }
+
+ significant_littlenums_dropped = 0;
+ }
+
+ return (significant_littlenums_dropped);
+} /* bignum_copy() */
+
+/* end of bignum-copy.c */
diff --git a/gas/bignum.h b/gas/bignum.h
new file mode 100644
index 0000000000..e3b2f16799
--- /dev/null
+++ b/gas/bignum.h
@@ -0,0 +1,52 @@
+/* bignum.h-arbitrary precision integers
+ Copyright (C) 1987, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/***********************************************************************\
+ * *
+ * Arbitrary-precision integer arithmetic. *
+ * For speed, we work in groups of bits, even though this *
+ * complicates algorithms. *
+ * Each group of bits is called a 'littlenum'. *
+ * A bunch of littlenums representing a (possibly large) *
+ * integer is called a 'bignum'. *
+ * Bignums are >= 0. *
+ * *
+ \***********************************************************************/
+
+#define LITTLENUM_NUMBER_OF_BITS (16)
+#define LITTLENUM_RADIX (1 << LITTLENUM_NUMBER_OF_BITS)
+#define LITTLENUM_MASK (0xFFFF)
+#define LITTLENUM_SHIFT (1)
+#define CHARS_PER_LITTLENUM (1 << LITTLENUM_SHIFT)
+#ifndef BITS_PER_CHAR
+#define BITS_PER_CHAR (8)
+#endif
+
+typedef unsigned short LITTLENUM_TYPE;
+
+/* JF truncated this to get around a problem with GCC */
+#define LOG_TO_BASE_2_OF_10 (3.3219280948873623478703194294893901758651)
+/* WARNING: I haven't checked that the trailing digits are correct! */
+
+/* lengths are in sizeof(littlenum)s */
+
+int bignum_copy PARAMS ((LITTLENUM_TYPE * in, int in_length,
+ LITTLENUM_TYPE * out, int out_length));
+
+/* end of bignum.h */
diff --git a/gas/bit_fix.h b/gas/bit_fix.h
new file mode 100644
index 0000000000..6a729a700c
--- /dev/null
+++ b/gas/bit_fix.h
@@ -0,0 +1,51 @@
+/* write.h
+
+ Copyright (C) 1987, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* The bit_fix was implemented to support machines that need variables
+ to be inserted in bitfields other than 1, 2 and 4 bytes.
+ Furthermore it gives us a possibillity to mask in bits in the symbol
+ when it's fixed in the objectcode and check the symbols limits.
+
+ The or-mask is used to set the huffman bits in displacements for the
+ ns32k port.
+ The acbi, addqi, movqi, cmpqi instruction requires an assembler that
+ can handle bitfields. Ie handle an expression, evaluate it and insert
+ the result in an some bitfield. ( ex: 5 bits in a short field of a opcode)
+ */
+
+#ifndef __bit_fix_h__
+#define __bit_fix_h__
+
+struct bit_fix
+ {
+ int fx_bit_size; /* Length of bitfield */
+ int fx_bit_offset; /* Bit offset to bitfield */
+ long fx_bit_base; /* Where do we apply the bitfix.
+ If this is zero, default is assumed. */
+ long fx_bit_base_adj; /* Adjustment of base */
+ long fx_bit_max; /* Signextended max for bitfield */
+ long fx_bit_min; /* Signextended min for bitfield */
+ long fx_bit_add; /* Or mask, used for huffman prefix */
+ };
+typedef struct bit_fix bit_fixS;
+
+#endif /* __bit_fix_h__ */
+
+/* end of bit_fix.h */
diff --git a/gas/cgen.c b/gas/cgen.c
new file mode 100644
index 0000000000..3d2330e05f
--- /dev/null
+++ b/gas/cgen.c
@@ -0,0 +1,663 @@
+/* GAS interface for targets using CGEN: Cpu tools GENerator.
+ Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GAS 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 more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <setjmp.h>
+#include "ansidecl.h"
+#include "libiberty.h"
+#include "bfd.h"
+#include "symcat.h"
+#include "cgen-desc.h"
+#include "as.h"
+#include "subsegs.h"
+#include "cgen.h"
+
+/* Opcode table descriptor, must be set by md_begin. */
+
+CGEN_CPU_DESC gas_cgen_cpu_desc;
+
+/* Callback to insert a register into the symbol table.
+ A target may choose to let GAS parse the registers.
+ ??? Not currently used. */
+
+void
+cgen_asm_record_register (name, number)
+ char * name;
+ int number;
+{
+ /* Use symbol_create here instead of symbol_new so we don't try to
+ output registers into the object file's symbol table. */
+ symbol_table_insert (symbol_create (name, reg_section,
+ number, & zero_address_frag));
+}
+
+/* We need to keep a list of fixups. We can't simply generate them as
+ we go, because that would require us to first create the frag, and
+ that would screw up references to ``.''.
+
+ This is used by cpu's with simple operands. It keeps knowledge of what
+ an `expressionS' is and what a `fixup' is out of CGEN which for the time
+ being is preferable.
+
+ OPINDEX is the index in the operand table.
+ OPINFO is something the caller chooses to help in reloc determination. */
+
+struct fixup
+{
+ int opindex;
+ int opinfo;
+ expressionS exp;
+};
+
+static struct fixup fixups [GAS_CGEN_MAX_FIXUPS];
+static int num_fixups;
+
+/* Prepare to parse an instruction.
+ ??? May wish to make this static and delete calls in md_assemble. */
+
+void
+gas_cgen_init_parse ()
+{
+ num_fixups = 0;
+}
+
+/* Queue a fixup. */
+
+static void
+queue_fixup (opindex, opinfo, expP)
+ int opindex;
+ expressionS * expP;
+{
+ /* We need to generate a fixup for this expression. */
+ if (num_fixups >= GAS_CGEN_MAX_FIXUPS)
+ as_fatal (_("too many fixups"));
+ fixups[num_fixups].exp = * expP;
+ fixups[num_fixups].opindex = opindex;
+ fixups[num_fixups].opinfo = opinfo;
+ ++ num_fixups;
+}
+
+/* The following three functions allow a backup of the fixup chain to be made,
+ and to have this backup be swapped with the current chain. This allows
+ certain ports, eg the m32r, to swap two instructions and swap their fixups
+ at the same time. */
+/* ??? I think with cgen_asm_finish_insn (or something else) there is no
+ more need for this. */
+
+static struct fixup saved_fixups [GAS_CGEN_MAX_FIXUPS];
+static int saved_num_fixups;
+
+void
+gas_cgen_save_fixups ()
+{
+ saved_num_fixups = num_fixups;
+
+ memcpy (saved_fixups, fixups, sizeof (fixups[0]) * num_fixups);
+
+ num_fixups = 0;
+}
+
+void
+gas_cgen_restore_fixups ()
+{
+ num_fixups = saved_num_fixups;
+
+ memcpy (fixups, saved_fixups, sizeof (fixups[0]) * num_fixups);
+
+ saved_num_fixups = 0;
+}
+
+void
+gas_cgen_swap_fixups ()
+{
+ int tmp;
+ struct fixup tmp_fixup;
+
+ if (num_fixups == 0)
+ {
+ gas_cgen_restore_fixups ();
+ }
+ else if (saved_num_fixups == 0)
+ {
+ gas_cgen_save_fixups ();
+ }
+ else
+ {
+ tmp = saved_num_fixups;
+ saved_num_fixups = num_fixups;
+ num_fixups = tmp;
+
+ for (tmp = GAS_CGEN_MAX_FIXUPS; tmp--;)
+ {
+ tmp_fixup = saved_fixups [tmp];
+ saved_fixups [tmp] = fixups [tmp];
+ fixups [tmp] = tmp_fixup;
+ }
+ }
+}
+
+/* Default routine to record a fixup.
+ This is a cover function to fix_new.
+ It exists because we record INSN with the fixup.
+
+ FRAG and WHERE are their respective arguments to fix_new_exp.
+ LENGTH is in bits.
+ OPINFO is something the caller chooses to help in reloc determination.
+
+ At this point we do not use a bfd_reloc_code_real_type for
+ operands residing in the insn, but instead just use the
+ operand index. This lets us easily handle fixups for any
+ operand type. We pick a BFD reloc type in md_apply_fix. */
+
+fixS *
+gas_cgen_record_fixup (frag, where, insn, length, operand, opinfo, symbol, offset)
+ fragS * frag;
+ int where;
+ const CGEN_INSN * insn;
+ int length;
+ const CGEN_OPERAND * operand;
+ int opinfo;
+ symbolS * symbol;
+ offsetT offset;
+{
+ fixS * fixP;
+
+ /* It may seem strange to use operand->attrs and not insn->attrs here,
+ but it is the operand that has a pc relative relocation. */
+
+ fixP = fix_new (frag, where, length / 8, symbol, offset,
+ CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR),
+ (bfd_reloc_code_real_type)
+ ((int) BFD_RELOC_UNUSED
+ + (int) operand->type));
+ fixP->fx_cgen.insn = insn;
+ fixP->fx_cgen.opinfo = opinfo;
+
+ return fixP;
+}
+
+/* Default routine to record a fixup given an expression.
+ This is a cover function to fix_new_exp.
+ It exists because we record INSN with the fixup.
+
+ FRAG and WHERE are their respective arguments to fix_new_exp.
+ LENGTH is in bits.
+ OPINFO is something the caller chooses to help in reloc determination.
+
+ At this point we do not use a bfd_reloc_code_real_type for
+ operands residing in the insn, but instead just use the
+ operand index. This lets us easily handle fixups for any
+ operand type. We pick a BFD reloc type in md_apply_fix. */
+
+fixS *
+gas_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp)
+ fragS * frag;
+ int where;
+ const CGEN_INSN * insn;
+ int length;
+ const CGEN_OPERAND * operand;
+ int opinfo;
+ expressionS * exp;
+{
+ fixS * fixP;
+
+ /* It may seem strange to use operand->attrs and not insn->attrs here,
+ but it is the operand that has a pc relative relocation. */
+
+ fixP = fix_new_exp (frag, where, length / 8, exp,
+ CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR),
+ (bfd_reloc_code_real_type)
+ ((int) BFD_RELOC_UNUSED
+ + (int) operand->type));
+ fixP->fx_cgen.insn = insn;
+ fixP->fx_cgen.opinfo = opinfo;
+
+ return fixP;
+}
+
+/* Used for communication between the next two procedures. */
+static jmp_buf expr_jmp_buf;
+
+/* Callback for cgen interface. Parse the expression at *STRP.
+ The result is an error message or NULL for success (in which case
+ *STRP is advanced past the parsed text).
+ WANT is an indication of what the caller is looking for.
+ If WANT == CGEN_ASM_PARSE_INIT the caller is beginning to try to match
+ a table entry with the insn, reset the queued fixups counter.
+ An enum cgen_parse_operand_result is stored in RESULTP.
+ OPINDEX is the operand's table entry index.
+ OPINFO is something the caller chooses to help in reloc determination.
+ The resulting value is stored in VALUEP. */
+
+const char *
+gas_cgen_parse_operand (cd, want, strP, opindex, opinfo, resultP, valueP)
+ CGEN_CPU_DESC cd;
+ enum cgen_parse_operand_type want;
+ const char ** strP;
+ int opindex;
+ int opinfo;
+ enum cgen_parse_operand_result * resultP;
+ bfd_vma * valueP;
+{
+#ifdef __STDC__
+ /* These are volatile to survive the setjmp. */
+ char * volatile hold;
+ enum cgen_parse_operand_result * volatile resultP_1;
+#else
+ static char * hold;
+ static enum cgen_parse_operand_result * resultP_1;
+#endif
+ const char * errmsg = NULL;
+ expressionS exp;
+
+ if (want == CGEN_PARSE_OPERAND_INIT)
+ {
+ gas_cgen_init_parse ();
+ return NULL;
+ }
+
+ resultP_1 = resultP;
+ hold = input_line_pointer;
+ input_line_pointer = (char *) * strP;
+
+ /* We rely on md_operand to longjmp back to us.
+ This is done via gas_cgen_md_operand. */
+ if (setjmp (expr_jmp_buf) != 0)
+ {
+ input_line_pointer = (char *) hold;
+ * resultP_1 = CGEN_PARSE_OPERAND_RESULT_ERROR;
+ return "illegal operand";
+ }
+
+ expression (& exp);
+
+ * strP = input_line_pointer;
+ input_line_pointer = hold;
+
+ /* FIXME: Need to check `want'. */
+
+ switch (exp.X_op)
+ {
+ case O_illegal :
+ errmsg = _("illegal operand");
+ * resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
+ break;
+ case O_absent :
+ errmsg = _("missing operand");
+ * resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
+ break;
+ case O_constant :
+ * valueP = exp.X_add_number;
+ * resultP = CGEN_PARSE_OPERAND_RESULT_NUMBER;
+ break;
+ case O_register :
+ * valueP = exp.X_add_number;
+ * resultP = CGEN_PARSE_OPERAND_RESULT_REGISTER;
+ break;
+ default :
+ queue_fixup (opindex, opinfo, & exp);
+ * valueP = 0;
+ * resultP = CGEN_PARSE_OPERAND_RESULT_QUEUED;
+ break;
+ }
+
+ return errmsg;
+}
+
+/* md_operand handler to catch unrecognized expressions and halt the
+ parsing process so the next entry can be tried.
+
+ ??? This could be done differently by adding code to `expression'. */
+
+void
+gas_cgen_md_operand (expressionP)
+ expressionS * expressionP;
+{
+ longjmp (expr_jmp_buf, 1);
+}
+
+/* Finish assembling instruction INSN.
+ BUF contains what we've built up so far.
+ LENGTH is the size of the insn in bits.
+ RELAX_P is non-zero if relaxable insns should be emitted as such.
+ Otherwise they're emitted in non-relaxable forms.
+ The "result" is stored in RESULT if non-NULL. */
+
+void
+gas_cgen_finish_insn (insn, buf, length, relax_p, result)
+ const CGEN_INSN * insn;
+ CGEN_INSN_BYTES_PTR buf;
+ unsigned int length;
+ int relax_p;
+ finished_insnS * result;
+{
+ int i;
+ int relax_operand;
+ char * f;
+ unsigned int byte_len = length / 8;
+
+ /* ??? Target foo issues various warnings here, so one might want to provide
+ a hook here. However, our caller is defined in tc-foo.c so there
+ shouldn't be a need for a hook. */
+
+ /* Write out the instruction.
+ It is important to fetch enough space in one call to `frag_more'.
+ We use (f - frag_now->fr_literal) to compute where we are and we
+ don't want frag_now to change between calls.
+
+ Relaxable instructions: We need to ensure we allocate enough
+ space for the largest insn. */
+
+ if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAX))
+ abort (); /* These currently shouldn't get here. */
+
+ /* Is there a relaxable insn with the relaxable operand needing a fixup? */
+
+ relax_operand = -1;
+ if (relax_p && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXABLE))
+ {
+ /* Scan the fixups for the operand affected by relaxing
+ (i.e. the branch address). */
+
+ for (i = 0; i < num_fixups; ++ i)
+ {
+ if (CGEN_OPERAND_ATTR_VALUE (cgen_operand_lookup_by_num (gas_cgen_cpu_desc, fixups[i].opindex),
+ CGEN_OPERAND_RELAX))
+ {
+ relax_operand = i;
+ break;
+ }
+ }
+ }
+
+ if (relax_operand != -1)
+ {
+ int max_len;
+ fragS * old_frag;
+
+#ifdef TC_CGEN_MAX_RELAX
+ max_len = TC_CGEN_MAX_RELAX (insn, byte_len);
+#else
+ max_len = CGEN_MAX_INSN_SIZE;
+#endif
+ /* Ensure variable part and fixed part are in same fragment. */
+ /* FIXME: Having to do this seems like a hack. */
+ frag_grow (max_len);
+
+ /* Allocate space for the fixed part. */
+ f = frag_more (byte_len);
+
+ /* Create a relaxable fragment for this instruction. */
+ old_frag = frag_now;
+
+ frag_var (rs_machine_dependent,
+ max_len - byte_len /* max chars */,
+ 0 /* variable part already allocated */,
+ /* FIXME: When we machine generate the relax table,
+ machine generate a macro to compute subtype. */
+ 1 /* subtype */,
+ fixups[relax_operand].exp.X_add_symbol,
+ fixups[relax_operand].exp.X_add_number,
+ f);
+
+ /* Record the operand number with the fragment so md_convert_frag
+ can use gas_cgen_md_record_fixup to record the appropriate reloc. */
+ old_frag->fr_cgen.insn = insn;
+ old_frag->fr_cgen.opindex = fixups[relax_operand].opindex;
+ old_frag->fr_cgen.opinfo = fixups[relax_operand].opinfo;
+ if (result)
+ result->frag = old_frag;
+ }
+ else
+ {
+ f = frag_more (byte_len);
+ if (result)
+ result->frag = frag_now;
+ }
+
+ /* If we're recording insns as numbers (rather than a string of bytes),
+ target byte order handling is deferred until now. */
+#if CGEN_INT_INSN_P
+ cgen_put_insn_value (gas_cgen_cpu_desc, f, length, *buf);
+#else
+ memcpy (f, buf, byte_len);
+#endif
+
+ /* Create any fixups. */
+ for (i = 0; i < num_fixups; ++i)
+ {
+ fixS *fixP;
+ const CGEN_OPERAND *operand =
+ cgen_operand_lookup_by_num (gas_cgen_cpu_desc, fixups[i].opindex);
+
+ /* Don't create fixups for these. That's done during relaxation.
+ We don't need to test for CGEN_INSN_RELAX as they can't get here
+ (see above). */
+ if (relax_p
+ && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXABLE)
+ && CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_RELAX))
+ continue;
+
+#ifndef md_cgen_record_fixup_exp
+#define md_cgen_record_fixup_exp gas_cgen_record_fixup_exp
+#endif
+
+ fixP = md_cgen_record_fixup_exp (frag_now, f - frag_now->fr_literal,
+ insn, length, operand,
+ fixups[i].opinfo,
+ & fixups[i].exp);
+ if (result)
+ result->fixups[i] = fixP;
+ }
+
+ if (result)
+ {
+ result->num_fixups = num_fixups;
+ result->addr = f;
+ }
+}
+
+/* Apply a fixup to the object code. This is called for all the
+ fixups we generated by the call to fix_new_exp, above. In the call
+ above we used a reloc code which was the largest legal reloc code
+ plus the operand index. Here we undo that to recover the operand
+ index. At this point all symbol values should be fully resolved,
+ and we attempt to completely resolve the reloc. If we can not do
+ that, we determine the correct reloc code and put it back in the fixup. */
+
+/* FIXME: This function handles some of the fixups and bfd_install_relocation
+ handles the rest. bfd_install_relocation (or some other bfd function)
+ should handle them all. */
+
+int
+gas_cgen_md_apply_fix3 (fixP, valueP, seg)
+ fixS * fixP;
+ valueT * valueP;
+ segT seg;
+{
+ char * where = fixP->fx_frag->fr_literal + fixP->fx_where;
+ valueT value;
+ /* canonical name, since used a lot */
+ CGEN_CPU_DESC cd = gas_cgen_cpu_desc;
+
+ /* FIXME FIXME FIXME: The value we are passed in *valuep includes
+ the symbol values. Since we are using BFD_ASSEMBLER, if we are
+ doing this relocation the code in write.c is going to call
+ bfd_install_relocation, which is also going to use the symbol
+ value. That means that if the reloc is fully resolved we want to
+ use *valuep since bfd_install_relocation is not being used.
+ However, if the reloc is not fully resolved we do not want to use
+ *valuep, and must use fx_offset instead. However, if the reloc
+ is PC relative, we do want to use *valuep since it includes the
+ result of md_pcrel_from. This is confusing. */
+
+ if (fixP->fx_addsy == (symbolS *) NULL)
+ {
+ value = * valueP;
+ fixP->fx_done = 1;
+ }
+ else if (fixP->fx_pcrel)
+ value = * valueP;
+ else
+ {
+ value = fixP->fx_offset;
+ if (fixP->fx_subsy != (symbolS *) NULL)
+ {
+ if (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section)
+ value -= S_GET_VALUE (fixP->fx_subsy);
+ else
+ {
+ /* We don't actually support subtracting a symbol. */
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("expression too complex"));
+ }
+ }
+ }
+
+ if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
+ {
+ int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
+ const CGEN_OPERAND *operand = cgen_operand_lookup_by_num (cd, opindex);
+ const char *errmsg;
+ bfd_reloc_code_real_type reloc_type;
+ CGEN_FIELDS *fields = alloca (CGEN_CPU_SIZEOF_FIELDS (cd));
+ const CGEN_INSN *insn = fixP->fx_cgen.insn;
+
+ /* If the reloc has been fully resolved finish the operand here. */
+ /* FIXME: This duplicates the capabilities of code in BFD. */
+ if (fixP->fx_done
+ /* FIXME: If partial_inplace isn't set bfd_install_relocation won't
+ finish the job. Testing for pcrel is a temporary hack. */
+ || fixP->fx_pcrel)
+ {
+ CGEN_CPU_SET_FIELDS_BITSIZE (cd) (fields, CGEN_INSN_BITSIZE (insn));
+ CGEN_CPU_SET_VMA_OPERAND (cd) (cd, opindex, fields, (bfd_vma) value);
+
+#if CGEN_INT_INSN_P
+ {
+ CGEN_INSN_INT insn_value =
+ cgen_get_insn_value (cd, where, CGEN_INSN_BITSIZE (insn));
+
+ /* ??? 0 is passed for `pc' */
+ errmsg = CGEN_CPU_INSERT_OPERAND (cd) (cd, opindex, fields,
+ &insn_value, (bfd_vma) 0);
+ cgen_put_insn_value (cd, where, CGEN_INSN_BITSIZE (insn),
+ insn_value);
+ }
+#else
+ /* ??? 0 is passed for `pc' */
+ errmsg = CGEN_CPU_INSERT_OPERAND (cd) (cd, opindex, fields, where,
+ (bfd_vma) 0);
+#endif
+ if (errmsg)
+ as_bad_where (fixP->fx_file, fixP->fx_line, "%s", errmsg);
+ }
+
+ if (fixP->fx_done)
+ return 1;
+
+ /* The operand isn't fully resolved. Determine a BFD reloc value
+ based on the operand information and leave it to
+ bfd_install_relocation. Note that this doesn't work when
+ partial_inplace == false. */
+
+ reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
+ if (reloc_type != BFD_RELOC_NONE)
+ {
+ fixP->fx_r_type = reloc_type;
+ }
+ else
+ {
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("unresolved expression that must be resolved"));
+ fixP->fx_done = 1;
+ return 1;
+ }
+ }
+ else if (fixP->fx_done)
+ {
+ /* We're finished with this fixup. Install it because
+ bfd_install_relocation won't be called to do it. */
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_8:
+ md_number_to_chars (where, value, 1);
+ break;
+ case BFD_RELOC_16:
+ md_number_to_chars (where, value, 2);
+ break;
+ case BFD_RELOC_32:
+ md_number_to_chars (where, value, 4);
+ break;
+ /* FIXME: later add support for 64 bits. */
+ default:
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("internal error: can't install fix for reloc type %d (`%s')"),
+ fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type));
+ break;
+ }
+ }
+ else
+ {
+ /* bfd_install_relocation will be called to finish things up. */
+ }
+
+ /* Tuck `value' away for use by tc_gen_reloc.
+ See the comment describing fx_addnumber in write.h.
+ This field is misnamed (or misused :-). */
+ fixP->fx_addnumber = value;
+
+ return 1;
+}
+
+/* Translate internal representation of relocation info to BFD target format.
+
+ FIXME: To what extent can we get all relevant targets to use this? */
+
+arelent *
+gas_cgen_tc_gen_reloc (section, fixP)
+ asection * section;
+ fixS * fixP;
+{
+ arelent * reloc;
+
+ reloc = (arelent *) xmalloc (sizeof (arelent));
+
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
+ if (reloc->howto == (reloc_howto_type *) NULL)
+ {
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("internal error: can't export reloc type %d (`%s')"),
+ fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type));
+ return NULL;
+ }
+
+ assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
+
+ reloc->sym_ptr_ptr = & fixP->fx_addsy->bsym;
+
+ /* Use fx_offset for these cases */
+ if ( fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
+ || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT)
+ reloc->addend = fixP->fx_offset;
+ else
+ reloc->addend = fixP->fx_addnumber;
+
+ reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
+ return reloc;
+}
diff --git a/gas/cgen.h b/gas/cgen.h
new file mode 100644
index 0000000000..2bc1732247
--- /dev/null
+++ b/gas/cgen.h
@@ -0,0 +1,94 @@
+/* GAS cgen support.
+ Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#ifndef GAS_CGEN_H
+#define GAS_CGEN_H
+
+/* Opcode table handle. */
+extern CGEN_CPU_DESC gas_cgen_cpu_desc;
+
+/* Maximum number of fixups in an insn.
+ If you need to change this, allow target to override and do so there. */
+#define GAS_CGEN_MAX_FIXUPS 3
+
+/* Struct defining result of gas_cgen_finish_insn. */
+typedef struct {
+ /* frag containing the insn */
+ fragS * frag;
+ /* Address of insn in frag. */
+ char * addr;
+ /* Number of fixups this insn has. */
+ int num_fixups;
+ /* Array of fixups. */
+ fixS * fixups[GAS_CGEN_MAX_FIXUPS];
+} finished_insnS;
+
+/* Callback for operand parsing.
+ The result is an error message or NULL for success.
+ The parsed value is stored in the bfd_vma *. */
+extern const char * gas_cgen_parse_operand
+ PARAMS ((CGEN_CPU_DESC, enum cgen_parse_operand_type,
+ const char **, int, int, enum cgen_parse_operand_result *,
+ bfd_vma *));
+
+/* Call this from md_assemble to initialize the assembler callback. */
+extern void gas_cgen_init_parse PARAMS ((void));
+
+extern void gas_cgen_save_fixups PARAMS ((void));
+extern void gas_cgen_restore_fixups PARAMS ((void));
+extern void gas_cgen_swap_fixups PARAMS ((void));
+
+/* Add a register to the assembler's hash table.
+ This makes lets GAS parse registers for us.
+ ??? This isn't currently used, but it could be in the future. */
+extern void cgen_asm_record_register PARAMS ((char *, int));
+
+/* After CGEN_SYM (assemble_insn) is done, this is called to
+ output the insn and record any fixups. */
+extern void gas_cgen_finish_insn PARAMS ((const CGEN_INSN *,
+ CGEN_INSN_BYTES_PTR, unsigned int,
+ int, finished_insnS *));
+
+/* Record a fixup. */
+extern fixS * gas_cgen_record_fixup PARAMS ((fragS *, int, const CGEN_INSN *,
+ int, const CGEN_OPERAND *, int,
+ symbolS *, offsetT));
+extern fixS * gas_cgen_record_fixup_exp PARAMS ((fragS *, int, const CGEN_INSN *,
+ int, const CGEN_OPERAND *, int,
+ expressionS *));
+
+/* md_apply_fix3 handler */
+extern int gas_cgen_md_apply_fix3 PARAMS ((fixS *, valueT *, segT));
+
+/* tc_gen_reloc handler */
+extern arelent *gas_cgen_tc_gen_reloc PARAMS ((asection *, fixS *));
+
+/* Target supplied routine to lookup a reloc. */
+extern bfd_reloc_code_real_type
+md_cgen_lookup_reloc PARAMS ((const CGEN_INSN *, const CGEN_OPERAND *,
+ fixS *));
+
+/* Optional target supplied routine to record a fixup for an expression. */
+extern fixS *
+md_cgen_record_fixup_exp PARAMS ((fragS *, int, const CGEN_INSN *, int,
+ const CGEN_OPERAND *, int,
+ expressionS *));
+
+#endif /* GAS_CGEN_H */
diff --git a/gas/cond.c b/gas/cond.c
new file mode 100644
index 0000000000..71a2a8e7d1
--- /dev/null
+++ b/gas/cond.c
@@ -0,0 +1,461 @@
+/* cond.c - conditional assembly pseudo-ops, and .include
+ Copyright (C) 1990, 91, 92, 93, 95, 96, 97, 1998
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include "as.h"
+#include "macro.h"
+
+#include "obstack.h"
+
+/* This is allocated to grow and shrink as .ifdef/.endif pairs are scanned. */
+struct obstack cond_obstack;
+
+struct file_line
+{
+ char *file;
+ unsigned int line;
+};
+
+/* We push one of these structures for each .if, and pop it at the
+ .endif. */
+
+struct conditional_frame
+{
+ /* The source file & line number of the "if". */
+ struct file_line if_file_line;
+ /* The source file & line of the "else". */
+ struct file_line else_file_line;
+ /* The previous conditional. */
+ struct conditional_frame *previous_cframe;
+ /* Have we seen an else yet? */
+ int else_seen;
+ /* Whether we are currently ignoring input. */
+ int ignoring;
+ /* Whether a conditional at a higher level is ignoring input. */
+ int dead_tree;
+ /* Macro nesting level at which this conditional was created. */
+ int macro_nest;
+};
+
+static void initialize_cframe PARAMS ((struct conditional_frame *cframe));
+static char *get_mri_string PARAMS ((int, int *));
+
+static struct conditional_frame *current_cframe = NULL;
+
+void
+s_ifdef (arg)
+ int arg;
+{
+ register char *name; /* points to name of symbol */
+ register struct symbol *symbolP; /* Points to symbol */
+ struct conditional_frame cframe;
+
+ SKIP_WHITESPACE (); /* Leading whitespace is part of operand. */
+ name = input_line_pointer;
+
+ if (!is_name_beginner (*name))
+ {
+ as_bad (_("invalid identifier for \".ifdef\""));
+ obstack_1grow (&cond_obstack, 0);
+ ignore_rest_of_line ();
+ }
+ else
+ {
+ char c;
+
+ c = get_symbol_end ();
+ symbolP = symbol_find (name);
+ *input_line_pointer = c;
+
+ initialize_cframe (&cframe);
+ cframe.ignoring = cframe.dead_tree || !((symbolP != 0) ^ arg);
+ current_cframe = ((struct conditional_frame *)
+ obstack_copy (&cond_obstack, &cframe,
+ sizeof (cframe)));
+
+ if (LISTING_SKIP_COND ()
+ && cframe.ignoring
+ && (cframe.previous_cframe == NULL
+ || ! cframe.previous_cframe->ignoring))
+ listing_list (2);
+
+ demand_empty_rest_of_line ();
+ } /* if a valid identifyer name */
+} /* s_ifdef() */
+
+void
+s_if (arg)
+ int arg;
+{
+ expressionS operand;
+ struct conditional_frame cframe;
+ int t;
+ char *stop = NULL;
+ char stopc;
+
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
+
+ SKIP_WHITESPACE (); /* Leading whitespace is part of operand. */
+
+ if (current_cframe != NULL && current_cframe->ignoring)
+ {
+ operand.X_add_number = 0;
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+ else
+ {
+ expression (&operand);
+ if (operand.X_op != O_constant)
+ as_bad (_("non-constant expression in \".if\" statement"));
+ }
+
+ switch ((operatorT) arg)
+ {
+ case O_eq: t = operand.X_add_number == 0; break;
+ case O_ne: t = operand.X_add_number != 0; break;
+ case O_lt: t = operand.X_add_number < 0; break;
+ case O_le: t = operand.X_add_number <= 0; break;
+ case O_ge: t = operand.X_add_number >= 0; break;
+ case O_gt: t = operand.X_add_number > 0; break;
+ default:
+ abort ();
+ return;
+ }
+
+ /* If the above error is signaled, this will dispatch
+ using an undefined result. No big deal. */
+ initialize_cframe (&cframe);
+ cframe.ignoring = cframe.dead_tree || ! t;
+ current_cframe = ((struct conditional_frame *)
+ obstack_copy (&cond_obstack, &cframe, sizeof (cframe)));
+
+ if (LISTING_SKIP_COND ()
+ && cframe.ignoring
+ && (cframe.previous_cframe == NULL
+ || ! cframe.previous_cframe->ignoring))
+ listing_list (2);
+
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+
+ demand_empty_rest_of_line ();
+} /* s_if() */
+
+/* Get a string for the MRI IFC or IFNC pseudo-ops. */
+
+static char *
+get_mri_string (terminator, len)
+ int terminator;
+ int *len;
+{
+ char *ret;
+ char *s;
+
+ SKIP_WHITESPACE ();
+ s = ret = input_line_pointer;
+ if (*input_line_pointer == '\'')
+ {
+ ++s;
+ ++input_line_pointer;
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ *s++ = *input_line_pointer++;
+ if (s[-1] == '\'')
+ {
+ if (*input_line_pointer != '\'')
+ break;
+ ++input_line_pointer;
+ }
+ }
+ SKIP_WHITESPACE ();
+ }
+ else
+ {
+ while (*input_line_pointer != terminator
+ && ! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ s = input_line_pointer;
+ while (s > ret && (s[-1] == ' ' || s[-1] == '\t'))
+ --s;
+ }
+
+ *len = s - ret;
+ return ret;
+}
+
+/* The MRI IFC and IFNC pseudo-ops. */
+
+void
+s_ifc (arg)
+ int arg;
+{
+ char *stop = NULL;
+ char stopc;
+ char *s1, *s2;
+ int len1, len2;
+ int res;
+ struct conditional_frame cframe;
+
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
+
+ s1 = get_mri_string (',', &len1);
+
+ if (*input_line_pointer != ',')
+ as_bad (_("bad format for ifc or ifnc"));
+ else
+ ++input_line_pointer;
+
+ s2 = get_mri_string (';', &len2);
+
+ res = len1 == len2 && strncmp (s1, s2, len1) == 0;
+
+ initialize_cframe (&cframe);
+ cframe.ignoring = cframe.dead_tree || ! (res ^ arg);
+ current_cframe = ((struct conditional_frame *)
+ obstack_copy (&cond_obstack, &cframe, sizeof (cframe)));
+
+ if (LISTING_SKIP_COND ()
+ && cframe.ignoring
+ && (cframe.previous_cframe == NULL
+ || ! cframe.previous_cframe->ignoring))
+ listing_list (2);
+
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+
+ demand_empty_rest_of_line ();
+}
+
+void
+s_endif (arg)
+ int arg;
+{
+ struct conditional_frame *hold;
+
+ if (current_cframe == NULL)
+ {
+ as_bad (_("\".endif\" without \".if\""));
+ }
+ else
+ {
+ if (LISTING_SKIP_COND ()
+ && current_cframe->ignoring
+ && (current_cframe->previous_cframe == NULL
+ || ! current_cframe->previous_cframe->ignoring))
+ listing_list (1);
+
+ hold = current_cframe;
+ current_cframe = current_cframe->previous_cframe;
+ obstack_free (&cond_obstack, hold);
+ } /* if one pop too many */
+
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
+ demand_empty_rest_of_line ();
+} /* s_endif() */
+
+void
+s_else (arg)
+ int arg;
+{
+ if (current_cframe == NULL)
+ {
+ as_bad (_(".else without matching .if - ignored"));
+
+ }
+ else if (current_cframe->else_seen)
+ {
+ as_bad (_("duplicate \"else\" - ignored"));
+ as_bad_where (current_cframe->else_file_line.file,
+ current_cframe->else_file_line.line,
+ _("here is the previous \"else\""));
+ as_bad_where (current_cframe->if_file_line.file,
+ current_cframe->if_file_line.line,
+ _("here is the previous \"if\""));
+ }
+ else
+ {
+ as_where (&current_cframe->else_file_line.file,
+ &current_cframe->else_file_line.line);
+
+ if (!current_cframe->dead_tree)
+ {
+ current_cframe->ignoring = !current_cframe->ignoring;
+ if (LISTING_SKIP_COND ())
+ {
+ if (! current_cframe->ignoring)
+ listing_list (1);
+ else
+ listing_list (2);
+ }
+ } /* if not a dead tree */
+
+ current_cframe->else_seen = 1;
+ } /* if error else do it */
+
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
+ demand_empty_rest_of_line ();
+} /* s_else() */
+
+void
+s_ifeqs (arg)
+ int arg;
+{
+ char *s1, *s2;
+ int len1, len2;
+ int res;
+ struct conditional_frame cframe;
+
+ s1 = demand_copy_C_string (&len1);
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_(".ifeqs syntax error"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ ++input_line_pointer;
+
+ s2 = demand_copy_C_string (&len2);
+
+ res = len1 == len2 && strncmp (s1, s2, len1) == 0;
+
+ initialize_cframe (&cframe);
+ cframe.ignoring = cframe.dead_tree || ! (res ^ arg);
+ current_cframe = ((struct conditional_frame *)
+ obstack_copy (&cond_obstack, &cframe, sizeof (cframe)));
+
+ if (LISTING_SKIP_COND ()
+ && cframe.ignoring
+ && (cframe.previous_cframe == NULL
+ || ! cframe.previous_cframe->ignoring))
+ listing_list (2);
+
+ demand_empty_rest_of_line ();
+} /* s_ifeqs() */
+
+int
+ignore_input ()
+{
+ char *s;
+
+ s = input_line_pointer;
+
+ if (flag_m68k_mri
+#ifdef NO_PSEUDO_DOT
+ || 1
+#endif
+ )
+ {
+ if (s[-1] != '.')
+ --s;
+ }
+ else
+ {
+ if (s[-1] != '.')
+ return (current_cframe != NULL) && (current_cframe->ignoring);
+ }
+
+ /* We cannot ignore certain pseudo ops. */
+ if (((s[0] == 'i'
+ || s[0] == 'I')
+ && (!strncasecmp (s, "if", 2)
+ || !strncasecmp (s, "ifdef", 5)
+ || !strncasecmp (s, "ifndef", 6)))
+ || ((s[0] == 'e'
+ || s[0] == 'E')
+ && (!strncasecmp (s, "else", 4)
+ || !strncasecmp (s, "endif", 5)
+ || !strncasecmp (s, "endc", 4))))
+ return 0;
+
+ return (current_cframe != NULL) && (current_cframe->ignoring);
+} /* ignore_input() */
+
+static void
+initialize_cframe (cframe)
+ struct conditional_frame *cframe;
+{
+ memset (cframe, 0, sizeof (*cframe));
+ as_where (&cframe->if_file_line.file,
+ &cframe->if_file_line.line);
+ cframe->previous_cframe = current_cframe;
+ cframe->dead_tree = current_cframe != NULL && current_cframe->ignoring;
+ cframe->macro_nest = macro_nest;
+}
+
+/* Give an error if a conditional is unterminated inside a macro or
+ the assembly as a whole. If NEST is non negative, we are being
+ called because of the end of a macro expansion. If NEST is
+ negative, we are being called at the of the input files. */
+
+void
+cond_finish_check (nest)
+ int nest;
+{
+ if (current_cframe != NULL && current_cframe->macro_nest >= nest)
+ {
+ if (nest >= 0)
+ as_bad (_("end of macro inside conditional"));
+ else
+ as_bad (_("end of file inside conditional"));
+ as_bad_where (current_cframe->if_file_line.file,
+ current_cframe->if_file_line.line,
+ _("here is the start of the unterminated conditional"));
+ if (current_cframe->else_seen)
+ as_bad_where (current_cframe->else_file_line.file,
+ current_cframe->else_file_line.line,
+ _("here is the \"else\" of the unterminated conditional"));
+ }
+}
+
+/* This function is called when we exit out of a macro. We assume
+ that any conditionals which began within the macro are correctly
+ nested, and just pop them off the stack. */
+
+void
+cond_exit_macro (nest)
+ int nest;
+{
+ while (current_cframe != NULL && current_cframe->macro_nest >= nest)
+ {
+ struct conditional_frame *hold;
+
+ hold = current_cframe;
+ current_cframe = current_cframe->previous_cframe;
+ obstack_free (&cond_obstack, hold);
+ }
+}
+
+/* end of cond.c */
diff --git a/gas/config-gas.com b/gas/config-gas.com
new file mode 100644
index 0000000000..cf5248af5d
--- /dev/null
+++ b/gas/config-gas.com
@@ -0,0 +1,186 @@
+$!config-gas.com
+$! This file sets things up to build gas on a VMS system to generate object
+$! files for a VMS system. We do not use the configure script, since we
+$! do not have /bin/sh to execute it.
+$!
+$!
+$ gas_host="vms"
+$ arch_indx = 1 + ((f$getsyi("CPU").ge.128).and.1) ! vax==1, alpha==2
+$ arch = f$element(arch_indx,"|","|VAX|Alpha|")
+$ if arch.eqs."VAX"
+$ then
+$ cpu_type="vax"
+$ obj_format="vms"
+$ atof="vax"
+$ else
+$ cpu_type="alpha"
+$ obj_format="evax"
+$ atof="ieee"
+$ endif
+$ emulation="generic"
+$!
+$ DELETE = "delete/noConfirm"
+$ ECHO = "write sys$output"
+$!
+$! Target specific information
+$ call make "targ-cpu.h" "[.config]tc-''cpu_type'.h"
+$ call make "targ-env.h" "[.config]te-''emulation'.h"
+$!
+$! Code to handle the object file format.
+$ call make "obj-format.h" "[.config]obj-''obj_format'.h"
+$!
+$! (not currently used for vax or alpha)
+$ call make "itbl-cpu.h" "[.config]itbl-''cpu_type'.h"
+$!
+$!
+$! Create the file version.opt, which helps identify the executable.
+$!
+$if f$trnlnm("IFILE$").nes."" then close/noLog ifile$
+$search CONFIGURE.IN "AM_INIT_AUTOMAKE"/Exact/Output=config-gas-tmp.tmp
+$open ifile$ config-gas-tmp.tmp
+$read ifile$ line
+$close ifile$
+$DELETE config-gas-tmp.tmp;*
+$! Discard "AM_INIT_AUTOMAKE(gas, " and ")" parts.
+$ijk=f$locate(",",line)+2
+$line=f$extract(ijk,f$length(line)-ijk,line)
+$ijk=f$locate(")",line)
+$line=f$extract(0,ijk,line)
+$!
+$ if f$search("version.opt").nes."" then DELETE version.opt;*
+$copy _NL: version.opt
+$open/Append ifile$ version.opt
+$write ifile$ "identification="+""""+line+""""
+$close ifile$
+$!
+$! Now write config.h.
+$!
+$ if f$search("config.h").nes."" then DELETE config.h;*
+$copy _NL: config.h
+$open/Append ifile$ config.h
+$write ifile$ "/* config.h. Generated by config-gas.com. */
+$write ifile$ "#ifndef VERSION"
+$write ifile$ "#define VERSION """,line,""""
+$write ifile$ "#endif"
+$write ifile$ "/*--*/"
+$if arch .eqs. "VAX"
+$then
+$append [.config]vms-conf.h ifile$:
+$else
+$ append [.config]vms-a-conf.h ifile$:
+$endif
+$close ifile$
+$ECHO "Created config.h."
+$!
+$! Check for, and possibly make, header file <unistd.h>.
+$!
+$ if f$search("tmp-chk-h.*").nes."" then DELETE tmp-chk-h.*;*
+$!can't use simple `#include HDR' with `gcc /Define="HDR=<foo.h>"'
+$!because the 2.6.[0-3] preprocessor handles it wrong (VMS-specific gcc bug)
+$ create tmp-chk-h.c
+int tmp_chk_h; /* guarantee non-empty output */
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_UNIXIO_H
+#include <unixio.h>
+#endif
+#ifdef HAVE_UNIXLIB_H
+#include <unixlib.h>
+#endif
+$ on warning then continue
+$ CHECK = "call tmp_chk_h"
+$ CHECK "HAVE_STDIO_H"
+$ if .not.$status
+$ then type sys$input:
+
+? could not compile <stdio.h>.
+
+ If you're compiling with DEC C or VAX C, create config.status as an
+ empty file and start gnu make again.
+
+ If you're compiling with GNU C, there is some setup problem and
+ gas configuration cannot proceed.
+
+$ DELETE tmp-chk-h.c;*
+$ exit %x002C
+$ endif
+$!
+$ CHECK "HAVE_UNISTD_H"
+$ if .not.$status
+$ then
+$ if f$trnlnm("HFILE$").nes."" then close/noLog hfile$
+$ CHECK "HAVE_UNIXIO_H"
+$ got_unixio = ($status .and. 1)
+$ CHECK "HAVE_UNIXLIB_H"
+$ got_unixlib = ($status .and. 1)
+$ create []unistd.h !with rudimentary contents
+/* <unistd.h> substitute for building gas */
+#ifndef UNISTD_H
+#define UNISTD_H
+
+$ open/Append hfile$ []unistd.h
+$ if got_unixio
+$ then write hfile$ "#include <unixio.h>"
+$ else append sys$input: hfile$:
+/* some of the routines normally prototyped in <unixio.h> */
+extern int creat(), open(), close(), read(), write();
+extern int access(), dup(), dup2(), fstat(), stat();
+extern long lseek();
+$ endif
+$ write hfile$ ""
+$ if got_unixlib
+$ then write hfile$ "#include <unixlib.h>"
+$ else append sys$input: hfile$:
+/* some of the routines normally prototyped in <unixlib.h> */
+extern char *sbrk(), *getcwd(), *cuserid();
+extern int brk(), chdir(), chmod(), chown(), mkdir();
+extern unsigned getuid(), umask();
+$ endif
+$ append sys$input: hfile$:
+
+#endif /*UNISTD_H*/
+$ close hfile$
+$ ECHO "Created ""[]unistd.h""."
+$ endif !gcc '#include <unistd.h>' failed
+$ DELETE tmp-chk-h.c;*
+$
+$tmp_chk_h: subroutine
+$ set noOn
+$ hname = f$edit("<" + (p1 - "HAVE_" - "_H") + ".h>","LOWERCASE")
+$ write sys$output "Checking for ''hname'."
+$ if f$search("tmp-chk-h.obj").nes."" then DELETE tmp-chk-h.obj;*
+$ define/noLog sys$error _NL: !can't use /User_Mode here due to gcc
+$ define/noLog sys$output _NL: ! driver's use of multiple image activation
+$ gcc /Include=([],[-.include]) /Define=("''p1'") tmp-chk-h.c
+$!can't just check $status; gcc 2.6.[0-3] preprocessor doesn't set it correctly
+$ ok = (($status.and.1).and.(f$search("tmp-chk-h.obj").nes."")) .or. %x10000000
+$ deassign sys$error !restore, more or less
+$ deassign sys$output
+$ if ok then DELETE tmp-chk-h.obj;*
+$ exit ok
+$ endsubroutine !tmp_chk_h
+$
+$!
+$! Done
+$!
+$ if f$search("config.status") .nes. "" then DELETE config.status;*
+$ open/write cfile []config.status
+$ write cfile "Links are now set up for use with a "+arch+" running VMS."
+$ close cfile
+$ type []config.status
+$exit
+$!
+$!
+$make: subroutine
+$ if f$search(p1).nes."" then DELETE 'p1';*
+$ create 'p1'
+$ if f$trnlnm("IFILE$").nes."" then close/noLog ifile$
+$ open/Append ifile$ 'p1'
+$ write ifile$ "#include ""''f$string(p2 - "[.config]")'"""
+$ close ifile$
+$ ECHO "Created ''p1' for ''p2'."
+$endsubroutine !make
diff --git a/gas/config.in b/gas/config.in
new file mode 100644
index 0000000000..81f2adac60
--- /dev/null
+++ b/gas/config.in
@@ -0,0 +1,273 @@
+/* config.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if using alloca.c. */
+#undef C_ALLOCA
+
+/* Define to empty if the keyword does not work. */
+#undef const
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+#undef CRAY_STACKSEG_END
+
+/* Define if you have alloca, as a function or macro. */
+#undef HAVE_ALLOCA
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+#undef HAVE_ALLOCA_H
+
+/* Define if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* Define as __inline if that's what the C compiler calls it. */
+#undef inline
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+#undef off_t
+
+/* Define if you need to in order for stat and other things to work. */
+#undef _POSIX_SOURCE
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+#undef size_t
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+#undef STACK_DIRECTION
+
+/* Define if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define if lex declares yytext as a char * by default, not a char[]. */
+#undef YYTEXT_POINTER
+
+/* Define if you have the __argz_count function. */
+#undef HAVE___ARGZ_COUNT
+
+/* Define if you have the __argz_next function. */
+#undef HAVE___ARGZ_NEXT
+
+/* Define if you have the __argz_stringify function. */
+#undef HAVE___ARGZ_STRINGIFY
+
+/* Define if you have the dcgettext function. */
+#undef HAVE_DCGETTEXT
+
+/* Define if you have the getcwd function. */
+#undef HAVE_GETCWD
+
+/* Define if you have the getpagesize function. */
+#undef HAVE_GETPAGESIZE
+
+/* Define if you have the munmap function. */
+#undef HAVE_MUNMAP
+
+/* Define if you have the putenv function. */
+#undef HAVE_PUTENV
+
+/* Define if you have the remove function. */
+#undef HAVE_REMOVE
+
+/* Define if you have the sbrk function. */
+#undef HAVE_SBRK
+
+/* Define if you have the setenv function. */
+#undef HAVE_SETENV
+
+/* Define if you have the setlocale function. */
+#undef HAVE_SETLOCALE
+
+/* Define if you have the stpcpy function. */
+#undef HAVE_STPCPY
+
+/* Define if you have the strcasecmp function. */
+#undef HAVE_STRCASECMP
+
+/* Define if you have the strchr function. */
+#undef HAVE_STRCHR
+
+/* Define if you have the unlink function. */
+#undef HAVE_UNLINK
+
+/* Define if you have the <argz.h> header file. */
+#undef HAVE_ARGZ_H
+
+/* Define if you have the <errno.h> header file. */
+#undef HAVE_ERRNO_H
+
+/* Define if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define if you have the <locale.h> header file. */
+#undef HAVE_LOCALE_H
+
+/* Define if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
+/* Define if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define if you have the <nl_types.h> header file. */
+#undef HAVE_NL_TYPES_H
+
+/* Define if you have the <stdarg.h> header file. */
+#undef HAVE_STDARG_H
+
+/* Define if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define if you have the <values.h> header file. */
+#undef HAVE_VALUES_H
+
+/* Define if you have the <varargs.h> header file. */
+#undef HAVE_VARARGS_H
+
+/* Name of package */
+#undef PACKAGE
+
+/* Version number of package */
+#undef VERSION
+
+/* Define if defaulting to ELF on SCO 5. */
+#undef SCO_ELF
+
+/* Use ELF stabs for MIPS, not ECOFF stabs */
+#undef MIPS_STABS_ELF
+
+/* Define if default target is PowerPC Solaris. */
+#undef TARGET_SOLARIS_COMMENT
+
+/* Define as 1 if big endian. */
+#undef TARGET_BYTES_BIG_ENDIAN
+
+/* Default architecture. */
+#undef DEFAULT_ARCH
+
+/* Using cgen code? */
+#undef USING_CGEN
+
+/* Using i386 COFF? */
+#undef I386COFF
+
+/* Using m68k COFF? */
+#undef M68KCOFF
+
+/* Using m88k COFF? */
+#undef M88KCOFF
+
+/* a.out support? */
+#undef OBJ_MAYBE_AOUT
+
+/* b.out support? */
+#undef OBJ_MAYBE_BOUT
+
+/* COFF support? */
+#undef OBJ_MAYBE_COFF
+
+/* ECOFF support? */
+#undef OBJ_MAYBE_ECOFF
+
+/* ELF support? */
+#undef OBJ_MAYBE_ELF
+
+/* generic support? */
+#undef OBJ_MAYBE_GENERIC
+
+/* HP300 support? */
+#undef OBJ_MAYBE_HP300
+
+/* IEEE support? */
+#undef OBJ_MAYBE_IEEE
+
+/* SOM support? */
+#undef OBJ_MAYBE_SOM
+
+/* VMS support? */
+#undef OBJ_MAYBE_VMS
+
+/* Use emulation support? */
+#undef USE_EMULATIONS
+
+/* Supported emulations. */
+#undef EMULATIONS
+
+/* Default emulation. */
+#undef DEFAULT_EMULATION
+
+/* old COFF support? */
+#undef MANY_SEGMENTS
+
+/* Use BFD interface? */
+#undef BFD_ASSEMBLER
+
+/* Target alias. */
+#undef TARGET_ALIAS
+
+/* Canonical target. */
+#undef TARGET_CANONICAL
+
+/* Target CPU. */
+#undef TARGET_CPU
+
+/* Target vendor. */
+#undef TARGET_VENDOR
+
+/* Target OS. */
+#undef TARGET_OS
+
+/* Define if you have the stpcpy function */
+#undef HAVE_STPCPY
+
+/* Define if your locale.h file contains LC_MESSAGES. */
+#undef HAVE_LC_MESSAGES
+
+/* Define to 1 if NLS is requested */
+#undef ENABLE_NLS
+
+/* Define as 1 if you have gettext and don't want to use GNU gettext. */
+#undef HAVE_GETTEXT
+
+/* Compiling cross-assembler? */
+#undef CROSS_COMPILE
+
+/* assert broken? */
+#undef BROKEN_ASSERT
+
+/* Define if strstr is not declared in system header files. */
+#undef NEED_DECLARATION_STRSTR
+
+/* Define if malloc is not declared in system header files. */
+#undef NEED_DECLARATION_MALLOC
+
+/* Define if free is not declared in system header files. */
+#undef NEED_DECLARATION_FREE
+
+/* Define if sbrk is not declared in system header files. */
+#undef NEED_DECLARATION_SBRK
+
+/* Define if environ is not declared in system header files. */
+#undef NEED_DECLARATION_ENVIRON
+
+/* Define if errno is not declared in system header files. */
+#undef NEED_DECLARATION_ERRNO
+
diff --git a/gas/config/aout_gnu.h b/gas/config/aout_gnu.h
new file mode 100644
index 0000000000..badf9cb21c
--- /dev/null
+++ b/gas/config/aout_gnu.h
@@ -0,0 +1,455 @@
+/* This file is aout_gnu.h
+
+ Copyright (C) 1987-1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef __A_OUT_GNU_H__
+#define __A_OUT_GNU_H__
+
+/* There are two main flavours of a.out, one which uses the standard
+ relocations, and one which uses extended relocations.
+
+ Today, the extended reloc uses are
+ TC_SPARC, TC_A29K
+
+ each must define the enum reloc_type
+
+*/
+
+#define USE_EXTENDED_RELOC (defined(TC_SPARC) || defined(TC_A29K))
+
+#if defined(TC_SPARC) || defined(TC_A29K)
+enum reloc_type
+ {
+ RELOC_8, RELOC_16, RELOC_32,/* simple relocations */
+ RELOC_DISP8, RELOC_DISP16, RELOC_DISP32, /* pc-rel displacement */
+ RELOC_WDISP30, RELOC_WDISP22,
+ RELOC_HI22, RELOC_22,
+ RELOC_13, RELOC_LO10,
+ RELOC_SFA_BASE, RELOC_SFA_OFF13,
+ RELOC_BASE10, RELOC_BASE13, RELOC_BASE22, /* P.I.C. (base-relative) */
+ RELOC_PC10, RELOC_PC22, /* for some sort of pc-rel P.I.C. (?) */
+ RELOC_JMP_TBL, /* P.I.C. jump table */
+ RELOC_SEGOFF16, /* reputedly for shared libraries somehow */
+ RELOC_GLOB_DAT, RELOC_JMP_SLOT, RELOC_RELATIVE,
+ RELOC_10, RELOC_11,
+ RELOC_WDISP2_14,
+ RELOC_WDISP19,
+ RELOC_HHI22,
+ RELOC_HLO10,
+
+ /* 29K relocation types */
+ RELOC_JUMPTARG, RELOC_CONST, RELOC_CONSTH,
+
+ RELOC_WDISP14, RELOC_WDISP21,
+
+ NO_RELOC
+ };
+
+#endif /* TC_SPARC or TC_A29K */
+
+
+#define __GNU_EXEC_MACROS__
+
+#ifndef __STRUCT_EXEC_OVERRIDE__
+
+/* This is the layout on disk of a Unix V7, Berkeley, SunOS, Vax Ultrix
+ "struct exec". Don't assume that on this machine, the "struct exec"
+ will lay out the same sizes or alignments. */
+
+struct exec_bytes
+ {
+ unsigned char a_info[4];
+ unsigned char a_text[4];
+ unsigned char a_data[4];
+ unsigned char a_bss[4];
+ unsigned char a_syms[4];
+ unsigned char a_entry[4];
+ unsigned char a_trsize[4];
+ unsigned char a_drsize[4];
+ };
+
+/* How big the "struct exec" is on disk */
+#define EXEC_BYTES_SIZE (8 * 4)
+
+/* This is the layout in memory of a "struct exec" while we process it. */
+
+struct exec
+{
+ unsigned long a_info; /* Use macros N_MAGIC, etc for access */
+ unsigned a_text; /* length of text, in bytes */
+ unsigned a_data; /* length of data, in bytes */
+ unsigned a_bss; /* length of uninitialized data area for file, in bytes */
+ unsigned a_syms; /* length of symbol table data in file, in bytes */
+ unsigned a_entry; /* start address */
+ unsigned a_trsize; /* length of relocation info for text, in bytes */
+ unsigned a_drsize; /* length of relocation info for data, in bytes */
+};
+
+#endif /* __STRUCT_EXEC_OVERRIDE__ */
+
+/* these go in the N_MACHTYPE field */
+/* These symbols could be defined by code from Suns...punt 'em */
+#undef M_UNKNOWN
+#undef M_68010
+#undef M_68020
+#undef M_SPARC
+enum machine_type
+ {
+ M_UNKNOWN = 0,
+ M_68010 = 1,
+ M_68020 = 2,
+ M_SPARC = 3,
+ /* skip a bunch so we don't run into any of sun's numbers */
+ M_386 = 100,
+ M_29K = 101,
+ M_RS6000 = 102, /* IBM RS/6000 */
+ /* HP/BSD formats */
+ M_HP200 = 200, /* hp200 (68010) BSD binary */
+ M_HP300 = 300, /* hp300 (68020+68881) BSD binary */
+ M_HPUX23 = 0x020C /* hp200/300 HPUX binary */
+ };
+
+#define N_MAGIC(exec) ((exec).a_info & 0xffff)
+#define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff))
+#define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff)
+#define N_SET_INFO(exec, magic, type, flags) \
+ ((exec).a_info = ((magic) & 0xffff) \
+ | (((int)(type) & 0xff) << 16) \
+ | (((flags) & 0xff) << 24))
+#define N_SET_MAGIC(exec, magic) \
+ ((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff)))
+
+#define N_SET_MACHTYPE(exec, machtype) \
+ ((exec).a_info = \
+ ((exec).a_info&0xff00ffff) | ((((int)(machtype))&0xff) << 16))
+
+#define N_SET_FLAGS(exec, flags) \
+ ((exec).a_info = \
+ ((exec).a_info&0x00ffffff) | (((flags) & 0xff) << 24))
+
+/* Code indicating object file or impure executable. */
+#ifndef OMAGIC
+#define OMAGIC 0407
+#endif
+/* Code indicating pure executable. */
+#define NMAGIC 0410
+/* Code indicating demand-paged executable. */
+#define ZMAGIC 0413
+
+/* Virtual Address of text segment from the a.out file. For OMAGIC,
+ (almost always "unlinked .o's" these days), should be zero.
+ For linked files, should reflect reality if we know it. */
+
+#ifndef N_TXTADDR
+#define N_TXTADDR(x) (N_MAGIC(x)==OMAGIC? 0 : TEXT_START_ADDR)
+#endif
+
+#ifndef N_BADMAG
+#define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \
+ && N_MAGIC(x) != NMAGIC \
+ && N_MAGIC(x) != ZMAGIC)
+#endif
+
+/* By default, segment size is constant. But on some machines, it can
+ be a function of the a.out header (e.g. machine type). */
+#ifndef N_SEGSIZE
+#define N_SEGSIZE(x) SEGMENT_SIZE
+#endif
+
+/* This complexity is for encapsulated COFF support */
+#ifndef _N_HDROFF
+#define _N_HDROFF(x) (N_SEGSIZE(x) - sizeof (struct exec))
+#endif
+
+#ifndef N_TXTOFF
+#define N_TXTOFF(x) (N_MAGIC(x) == ZMAGIC ? \
+ _N_HDROFF((x)) + sizeof (struct exec) : \
+ sizeof (struct exec))
+#endif
+
+
+#ifndef N_DATOFF
+#define N_DATOFF(x) ( N_TXTOFF(x) + (x).a_text )
+#endif
+
+#ifndef N_TRELOFF
+#define N_TRELOFF(x) ( N_DATOFF(x) + (x).a_data )
+#endif
+
+#ifndef N_DRELOFF
+#define N_DRELOFF(x) ( N_TRELOFF(x) + (x).a_trsize )
+#endif
+
+#ifndef N_SYMOFF
+#define N_SYMOFF(x) ( N_DRELOFF(x) + (x).a_drsize )
+#endif
+
+#ifndef N_STROFF
+#define N_STROFF(x) ( N_SYMOFF(x) + (x).a_syms )
+#endif
+
+/* Address of text segment in memory after it is loaded. */
+#ifndef N_TXTADDR
+#define N_TXTADDR(x) 0
+#endif
+
+#ifndef N_DATADDR
+#define N_DATADDR(x) \
+ (N_MAGIC(x)==OMAGIC? (N_TXTADDR(x)+(x).a_text) \
+ : (N_SEGSIZE(x) + ((N_TXTADDR(x)+(x).a_text-1) & ~(N_SEGSIZE(x)-1))))
+#endif
+
+/* Address of bss segment in memory after it is loaded. */
+#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data)
+
+struct nlist
+ {
+ union
+ {
+ char *n_name;
+ struct nlist *n_next;
+ long n_strx;
+ }
+ n_un;
+ unsigned char n_type;
+ char n_other;
+ short n_desc;
+ unsigned long n_value;
+ };
+
+#define N_UNDF 0
+#define N_ABS 2
+#define N_TEXT 4
+#define N_DATA 6
+#define N_BSS 8
+#define N_COMM 0x12 /* common (visible in shared lib commons) */
+#define N_FN 0x1F /* File name of a .o file */
+
+/* Note: N_EXT can only usefully be OR-ed with N_UNDF, N_ABS, N_TEXT,
+ N_DATA, or N_BSS. When the low-order bit of other types is set,
+ (e.g. N_WARNING versus N_FN), they are two different types. */
+#define N_EXT 1
+#define N_TYPE 036
+#define N_STAB 0340
+
+/* The following type indicates the definition of a symbol as being
+ an indirect reference to another symbol. The other symbol
+ appears as an undefined reference, immediately following this symbol.
+
+ Indirection is asymmetrical. The other symbol's value will be used
+ to satisfy requests for the indirect symbol, but not vice versa.
+ If the other symbol does not have a definition, libraries will
+ be searched to find a definition. */
+
+#define N_INDR 0xa
+
+/* The following symbols refer to set elements.
+ All the N_SET[ATDB] symbols with the same name form one set.
+ Space is allocated for the set in the text section, and each set
+ element's value is stored into one word of the space.
+ The first word of the space is the length of the set (number of elements).
+
+ The address of the set is made into an N_SETV symbol
+ whose name is the same as the name of the set.
+ This symbol acts like a N_DATA global symbol
+ in that it can satisfy undefined external references. */
+
+/* These appear as input to LD, in a .o file. */
+#define N_SETA 0x14 /* Absolute set element symbol */
+#define N_SETT 0x16 /* Text set element symbol */
+#define N_SETD 0x18 /* Data set element symbol */
+#define N_SETB 0x1A /* Bss set element symbol */
+
+/* This is output from LD. */
+#define N_SETV 0x1C /* Pointer to set vector in data area. */
+
+/* Warning symbol. The text gives a warning message, the next symbol
+ in the table will be undefined. When the symbol is referenced, the
+ message is printed. */
+
+#define N_WARNING 0x1e
+
+/* Weak symbols. These are a GNU extension to the a.out format. The
+ semantics are those of ELF weak symbols. Weak symbols are always
+ externally visible. The N_WEAK? values are squeezed into the
+ available slots. The value of a N_WEAKU symbol is 0. The values
+ of the other types are the definitions. */
+#define N_WEAKU 0x0d /* Weak undefined symbol. */
+#define N_WEAKA 0x0e /* Weak absolute symbol. */
+#define N_WEAKT 0x0f /* Weak text symbol. */
+#define N_WEAKD 0x10 /* Weak data symbol. */
+#define N_WEAKB 0x11 /* Weak bss symbol. */
+
+/* This structure describes a single relocation to be performed.
+ The text-relocation section of the file is a vector of these structures,
+ all of which apply to the text section.
+ Likewise, the data-relocation section applies to the data section. */
+
+/* The following enum and struct were borrowed from SunOS's
+ /usr/include/sun4/a.out.h and extended to handle
+ other machines. It is currently used on SPARC and AMD 29000.
+
+ reloc_ext_bytes is how it looks on disk. reloc_info_extended is
+ how we might process it on a native host. */
+#if USE_EXTENDED_RELOC
+
+struct reloc_ext_bytes
+ {
+ unsigned char r_address[4];
+ unsigned char r_index[3];
+ unsigned char r_bits[1];
+ unsigned char r_addend[4];
+ };
+
+
+#define RELOC_EXT_BITS_EXTERN_BIG 0x80
+#define RELOC_EXT_BITS_EXTERN_LITTLE 0x01
+
+#define RELOC_EXT_BITS_TYPE_BIG 0x1F
+#define RELOC_EXT_BITS_TYPE_SH_BIG 0
+#define RELOC_EXT_BITS_TYPE_LITTLE 0xF8
+#define RELOC_EXT_BITS_TYPE_SH_LITTLE 3
+
+#define RELOC_EXT_SIZE 12 /* Bytes per relocation entry */
+
+struct reloc_info_extended
+{
+ unsigned long r_address;
+ unsigned int r_index:24;
+# define r_symbolnum r_index
+ unsigned r_extern:1;
+ unsigned:2;
+ /* RS/6000 compiler does not support enum bitfield
+ enum reloc_type r_type:5; */
+ enum reloc_type r_type;
+ long int r_addend;
+};
+
+#else
+
+/* The standard, old-fashioned, Berkeley compatible relocation struct */
+
+
+
+#ifdef TC_I860
+/* NOTE: three bits max, see struct reloc_info_i860.r_type */
+enum i860_reloc_type
+ {
+ NO_RELOC = 0, BRADDR, LOW0, LOW1, LOW2, LOW3, LOW4, SPLIT0, SPLIT1, SPLIT2, RELOC_32,
+ };
+
+typedef enum i860_reloc_type reloc_type;
+
+/* NOTE: two bits max, see reloc_info_i860.r_type */
+enum highlow_type
+ {
+ NO_SPEC = 0, PAIR, HIGH, HIGHADJ,
+ };
+
+
+struct reloc_info_i860
+{
+ unsigned long r_address;
+ /*
+ * Using bit fields here is a bad idea because the order is not portable. :-(
+ */
+ unsigned int r_symbolnum:24;
+ unsigned int r_pcrel:1;
+ unsigned int r_extern:1;
+ /* combining the two field simplifies the argument passing in "new_fix()" */
+ /* and is compatible with the existing Sparc #ifdef's */
+ /* r_type: highlow_type - bits 5,4; reloc_type - bits 3-0 */
+ unsigned int r_type:6;
+ long r_addend;
+};
+
+#endif /* TC_I860 */
+
+
+struct reloc_std_bytes
+ {
+ unsigned char r_address[4];
+ unsigned char r_index[3];
+ unsigned char r_bits[1];
+ };
+
+#define RELOC_STD_BITS_PCREL_BIG 0x80
+#define RELOC_STD_BITS_PCREL_LITTLE 0x01
+
+#define RELOC_STD_BITS_LENGTH_BIG 0x60
+#define RELOC_STD_BITS_LENGTH_SH_BIG 5 /* To shift to units place */
+#define RELOC_STD_BITS_LENGTH_LITTLE 0x06
+#define RELOC_STD_BITS_LENGTH_SH_LITTLE 1
+
+#define RELOC_STD_BITS_EXTERN_BIG 0x10
+#define RELOC_STD_BITS_EXTERN_LITTLE 0x08
+
+#define RELOC_STD_BITS_BASEREL_BIG 0x08
+#define RELOC_STD_BITS_BASEREL_LITTLE 0x08
+
+#define RELOC_STD_BITS_JMPTABLE_BIG 0x04
+#define RELOC_STD_BITS_JMPTABLE_LITTLE 0x04
+
+#define RELOC_STD_BITS_RELATIVE_BIG 0x02
+#define RELOC_STD_BITS_RELATIVE_LITTLE 0x02
+
+#define RELOC_STD_SIZE 8 /* Bytes per relocation entry */
+
+#endif /* USE_EXTENDED_RELOC */
+
+#ifndef CUSTOM_RELOC_FORMAT
+struct relocation_info
+{
+ /* Address (within segment) to be relocated. */
+ int r_address;
+ /* The meaning of r_symbolnum depends on r_extern. */
+ unsigned int r_symbolnum:24;
+ /* Nonzero means value is a pc-relative offset
+ and it should be relocated for changes in its own address
+ as well as for changes in the symbol or section specified. */
+ unsigned int r_pcrel:1;
+ /* Length (as exponent of 2) of the field to be relocated.
+ Thus, a value of 2 indicates 1<<2 bytes. */
+ unsigned int r_length:2;
+ /* 1 => relocate with value of symbol.
+ r_symbolnum is the index of the symbol
+ in file's the symbol table.
+ 0 => relocate with the address of a segment.
+ r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS
+ (the N_EXT bit may be set also, but signifies nothing). */
+ unsigned int r_extern:1;
+ /* The next three bits are for SunOS shared libraries, and seem to
+ be undocumented. */
+#ifdef TC_NS32K
+ unsigned int r_bsr:1;
+ unsigned int r_disp:2;
+#else
+ unsigned int r_baserel:1; /* Linkage table relative */
+ unsigned int r_jmptable:1; /* pc-relative to jump table */
+ unsigned int r_relative:1; /* "relative relocation" */
+#endif /* TC_NS32K */
+ /* unused */
+ unsigned int r_pad:1; /* Padding -- set to zero */
+};
+
+#endif /* CUSTOM_RELOC_FORMAT */
+
+#endif /* __A_OUT_GNU_H__ */
+
+/* end of aout_gnu.h */
diff --git a/gas/config/atof-ieee.c b/gas/config/atof-ieee.c
new file mode 100644
index 0000000000..d586e3a85e
--- /dev/null
+++ b/gas/config/atof-ieee.c
@@ -0,0 +1,696 @@
+/* atof_ieee.c - turn a Flonum into an IEEE floating point number
+ Copyright (C) 1987, 92, 93, 94, 95, 96, 97, 1998
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include "as.h"
+
+/* Flonums returned here. */
+extern FLONUM_TYPE generic_floating_point_number;
+
+static int next_bits PARAMS ((int));
+static void unget_bits PARAMS ((int));
+static void make_invalid_floating_point_number PARAMS ((LITTLENUM_TYPE *));
+
+extern const char EXP_CHARS[];
+/* Precision in LittleNums. */
+/* Don't count the gap in the m68k extended precision format. */
+#define MAX_PRECISION (5)
+#define F_PRECISION (2)
+#define D_PRECISION (4)
+#define X_PRECISION (5)
+#define P_PRECISION (5)
+
+/* Length in LittleNums of guard bits. */
+#define GUARD (2)
+
+static const unsigned long mask[] =
+{
+ 0x00000000,
+ 0x00000001,
+ 0x00000003,
+ 0x00000007,
+ 0x0000000f,
+ 0x0000001f,
+ 0x0000003f,
+ 0x0000007f,
+ 0x000000ff,
+ 0x000001ff,
+ 0x000003ff,
+ 0x000007ff,
+ 0x00000fff,
+ 0x00001fff,
+ 0x00003fff,
+ 0x00007fff,
+ 0x0000ffff,
+ 0x0001ffff,
+ 0x0003ffff,
+ 0x0007ffff,
+ 0x000fffff,
+ 0x001fffff,
+ 0x003fffff,
+ 0x007fffff,
+ 0x00ffffff,
+ 0x01ffffff,
+ 0x03ffffff,
+ 0x07ffffff,
+ 0x0fffffff,
+ 0x1fffffff,
+ 0x3fffffff,
+ 0x7fffffff,
+ 0xffffffff,
+};
+
+
+static int bits_left_in_littlenum;
+static int littlenums_left;
+static LITTLENUM_TYPE *littlenum_pointer;
+
+static int
+next_bits (number_of_bits)
+ int number_of_bits;
+{
+ int return_value;
+
+ if (!littlenums_left)
+ return (0);
+ if (number_of_bits >= bits_left_in_littlenum)
+ {
+ return_value = mask[bits_left_in_littlenum] & *littlenum_pointer;
+ number_of_bits -= bits_left_in_littlenum;
+ return_value <<= number_of_bits;
+
+ if (--littlenums_left)
+ {
+ bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS - number_of_bits;
+ --littlenum_pointer;
+ return_value |= (*littlenum_pointer >> bits_left_in_littlenum) & mask[number_of_bits];
+ }
+ }
+ else
+ {
+ bits_left_in_littlenum -= number_of_bits;
+ return_value = mask[number_of_bits] & (*littlenum_pointer >> bits_left_in_littlenum);
+ }
+ return (return_value);
+}
+
+/* Num had better be less than LITTLENUM_NUMBER_OF_BITS */
+static void
+unget_bits (num)
+ int num;
+{
+ if (!littlenums_left)
+ {
+ ++littlenum_pointer;
+ ++littlenums_left;
+ bits_left_in_littlenum = num;
+ }
+ else if (bits_left_in_littlenum + num > LITTLENUM_NUMBER_OF_BITS)
+ {
+ bits_left_in_littlenum = num - (LITTLENUM_NUMBER_OF_BITS - bits_left_in_littlenum);
+ ++littlenum_pointer;
+ ++littlenums_left;
+ }
+ else
+ bits_left_in_littlenum += num;
+}
+
+static void
+make_invalid_floating_point_number (words)
+ LITTLENUM_TYPE *words;
+{
+ as_bad (_("cannot create floating-point number"));
+ words[0] = (LITTLENUM_TYPE) ((unsigned) -1) >> 1; /* Zero the leftmost bit */
+ words[1] = (LITTLENUM_TYPE) -1;
+ words[2] = (LITTLENUM_TYPE) -1;
+ words[3] = (LITTLENUM_TYPE) -1;
+ words[4] = (LITTLENUM_TYPE) -1;
+ words[5] = (LITTLENUM_TYPE) -1;
+}
+
+/************************************************************************\
+ * Warning: this returns 16-bit LITTLENUMs. It is up to the caller *
+ * to figure out any alignment problems and to conspire for the *
+ * bytes/word to be emitted in the right order. Bigendians beware! *
+ * *
+\************************************************************************/
+
+/* Note that atof-ieee always has X and P precisions enabled. it is up
+ to md_atof to filter them out if the target machine does not support
+ them. */
+
+/* Returns pointer past text consumed. */
+char *
+atof_ieee (str, what_kind, words)
+ char *str; /* Text to convert to binary. */
+ char what_kind; /* 'd', 'f', 'g', 'h' */
+ LITTLENUM_TYPE *words; /* Build the binary here. */
+{
+ /* Extra bits for zeroed low-order bits. The 1st MAX_PRECISION are
+ zeroed, the last contain flonum bits. */
+ static LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD];
+ char *return_value;
+ /* Number of 16-bit words in the format. */
+ int precision;
+ long exponent_bits;
+ FLONUM_TYPE save_gen_flonum;
+
+ /* We have to save the generic_floating_point_number because it
+ contains storage allocation about the array of LITTLENUMs where
+ the value is actually stored. We will allocate our own array of
+ littlenums below, but have to restore the global one on exit. */
+ save_gen_flonum = generic_floating_point_number;
+
+ return_value = str;
+ generic_floating_point_number.low = bits + MAX_PRECISION;
+ generic_floating_point_number.high = NULL;
+ generic_floating_point_number.leader = NULL;
+ generic_floating_point_number.exponent = 0;
+ generic_floating_point_number.sign = '\0';
+
+ /* Use more LittleNums than seems necessary: the highest flonum may
+ have 15 leading 0 bits, so could be useless. */
+
+ memset (bits, '\0', sizeof (LITTLENUM_TYPE) * MAX_PRECISION);
+
+ switch (what_kind)
+ {
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ precision = F_PRECISION;
+ exponent_bits = 8;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ precision = D_PRECISION;
+ exponent_bits = 11;
+ break;
+
+ case 'x':
+ case 'X':
+ case 'e':
+ case 'E':
+ precision = X_PRECISION;
+ exponent_bits = 15;
+ break;
+
+ case 'p':
+ case 'P':
+
+ precision = P_PRECISION;
+ exponent_bits = -1;
+ break;
+
+ default:
+ make_invalid_floating_point_number (words);
+ return (NULL);
+ }
+
+ generic_floating_point_number.high
+ = generic_floating_point_number.low + precision - 1 + GUARD;
+
+ if (atof_generic (&return_value, ".", EXP_CHARS,
+ &generic_floating_point_number))
+ {
+ make_invalid_floating_point_number (words);
+ return (NULL);
+ }
+ gen_to_words (words, precision, exponent_bits);
+
+ /* Restore the generic_floating_point_number's storage alloc (and
+ everything else). */
+ generic_floating_point_number = save_gen_flonum;
+
+ return return_value;
+}
+
+/* Turn generic_floating_point_number into a real float/double/extended. */
+int
+gen_to_words (words, precision, exponent_bits)
+ LITTLENUM_TYPE *words;
+ int precision;
+ long exponent_bits;
+{
+ int return_value = 0;
+
+ long exponent_1;
+ long exponent_2;
+ long exponent_3;
+ long exponent_4;
+ int exponent_skippage;
+ LITTLENUM_TYPE word1;
+ LITTLENUM_TYPE *lp;
+ LITTLENUM_TYPE *words_end;
+
+ words_end = words + precision;
+#ifdef TC_M68K
+ if (precision == X_PRECISION)
+ /* On the m68k the extended precision format has a gap of 16 bits
+ between the exponent and the mantissa. */
+ words_end++;
+#endif
+
+ if (generic_floating_point_number.low > generic_floating_point_number.leader)
+ {
+ /* 0.0e0 seen. */
+ if (generic_floating_point_number.sign == '+')
+ words[0] = 0x0000;
+ else
+ words[0] = 0x8000;
+ memset (&words[1], '\0',
+ (words_end - words - 1) * sizeof (LITTLENUM_TYPE));
+ return (return_value);
+ }
+
+ /* NaN: Do the right thing */
+ if (generic_floating_point_number.sign == 0)
+ {
+ if (precision == F_PRECISION)
+ {
+ words[0] = 0x7fff;
+ words[1] = 0xffff;
+ }
+ else if (precision == X_PRECISION)
+ {
+#ifdef TC_M68K
+ words[0] = 0x7fff;
+ words[1] = 0;
+ words[2] = 0xffff;
+ words[3] = 0xffff;
+ words[4] = 0xffff;
+ words[5] = 0xffff;
+#else /* ! TC_M68K */
+#ifdef TC_I386
+ words[0] = 0xffff;
+ words[1] = 0xc000;
+ words[2] = 0;
+ words[3] = 0;
+ words[4] = 0;
+#else /* ! TC_I386 */
+ abort ();
+#endif /* ! TC_I386 */
+#endif /* ! TC_M68K */
+ }
+ else
+ {
+ words[0] = 0x7fff;
+ words[1] = 0xffff;
+ words[2] = 0xffff;
+ words[3] = 0xffff;
+ }
+ return return_value;
+ }
+ else if (generic_floating_point_number.sign == 'P')
+ {
+ /* +INF: Do the right thing */
+ if (precision == F_PRECISION)
+ {
+ words[0] = 0x7f80;
+ words[1] = 0;
+ }
+ else if (precision == X_PRECISION)
+ {
+#ifdef TC_M68K
+ words[0] = 0x7fff;
+ words[1] = 0;
+ words[2] = 0;
+ words[3] = 0;
+ words[4] = 0;
+ words[5] = 0;
+#else /* ! TC_M68K */
+#ifdef TC_I386
+ words[0] = 0x7fff;
+ words[1] = 0x8000;
+ words[2] = 0;
+ words[3] = 0;
+ words[4] = 0;
+#else /* ! TC_I386 */
+ abort ();
+#endif /* ! TC_I386 */
+#endif /* ! TC_M68K */
+ }
+ else
+ {
+ words[0] = 0x7ff0;
+ words[1] = 0;
+ words[2] = 0;
+ words[3] = 0;
+ }
+ return (return_value);
+ }
+ else if (generic_floating_point_number.sign == 'N')
+ {
+ /* Negative INF */
+ if (precision == F_PRECISION)
+ {
+ words[0] = 0xff80;
+ words[1] = 0x0;
+ }
+ else if (precision == X_PRECISION)
+ {
+#ifdef TC_M68K
+ words[0] = 0xffff;
+ words[1] = 0;
+ words[2] = 0;
+ words[3] = 0;
+ words[4] = 0;
+ words[5] = 0;
+#else /* ! TC_M68K */
+#ifdef TC_I386
+ words[0] = 0xffff;
+ words[1] = 0x8000;
+ words[2] = 0;
+ words[3] = 0;
+ words[4] = 0;
+#else /* ! TC_I386 */
+ abort ();
+#endif /* ! TC_I386 */
+#endif /* ! TC_M68K */
+ }
+ else
+ {
+ words[0] = 0xfff0;
+ words[1] = 0x0;
+ words[2] = 0x0;
+ words[3] = 0x0;
+ }
+ return (return_value);
+ }
+ /*
+ * The floating point formats we support have:
+ * Bit 15 is sign bit.
+ * Bits 14:n are excess-whatever exponent.
+ * Bits n-1:0 (if any) are most significant bits of fraction.
+ * Bits 15:0 of the next word(s) are the next most significant bits.
+ *
+ * So we need: number of bits of exponent, number of bits of
+ * mantissa.
+ */
+ bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS;
+ littlenum_pointer = generic_floating_point_number.leader;
+ littlenums_left = (1
+ + generic_floating_point_number.leader
+ - generic_floating_point_number.low);
+ /* Seek (and forget) 1st significant bit */
+ for (exponent_skippage = 0; !next_bits (1); ++exponent_skippage);;
+ exponent_1 = (generic_floating_point_number.exponent
+ + generic_floating_point_number.leader
+ + 1
+ - generic_floating_point_number.low);
+ /* Radix LITTLENUM_RADIX, point just higher than
+ generic_floating_point_number.leader. */
+ exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS;
+ /* Radix 2. */
+ exponent_3 = exponent_2 - exponent_skippage;
+ /* Forget leading zeros, forget 1st bit. */
+ exponent_4 = exponent_3 + ((1 << (exponent_bits - 1)) - 2);
+ /* Offset exponent. */
+
+ lp = words;
+
+ /* Word 1. Sign, exponent and perhaps high bits. */
+ word1 = ((generic_floating_point_number.sign == '+')
+ ? 0
+ : (1 << (LITTLENUM_NUMBER_OF_BITS - 1)));
+
+ /* Assume 2's complement integers. */
+ if (exponent_4 <= 0)
+ {
+ int prec_bits;
+ int num_bits;
+
+ unget_bits (1);
+ num_bits = -exponent_4;
+ prec_bits = LITTLENUM_NUMBER_OF_BITS * precision - (exponent_bits + 1 + num_bits);
+#ifdef TC_I386
+ if (precision == X_PRECISION && exponent_bits == 15)
+ {
+ /* On the i386 a denormalized extended precision float is
+ shifted down by one, effectively decreasing the exponent
+ bias by one. */
+ prec_bits -= 1;
+ num_bits += 1;
+ }
+#endif
+
+ if (num_bits >= LITTLENUM_NUMBER_OF_BITS - exponent_bits)
+ {
+ /* Bigger than one littlenum */
+ num_bits -= (LITTLENUM_NUMBER_OF_BITS - 1) - exponent_bits;
+ *lp++ = word1;
+ if (num_bits + exponent_bits + 1 >= precision * LITTLENUM_NUMBER_OF_BITS)
+ {
+ /* Exponent overflow */
+ make_invalid_floating_point_number (words);
+ return (return_value);
+ }
+#ifdef TC_M68K
+ if (precision == X_PRECISION && exponent_bits == 15)
+ *lp++ = 0;
+#endif
+ while (num_bits >= LITTLENUM_NUMBER_OF_BITS)
+ {
+ num_bits -= LITTLENUM_NUMBER_OF_BITS;
+ *lp++ = 0;
+ }
+ if (num_bits)
+ *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS - (num_bits));
+ }
+ else
+ {
+ if (precision == X_PRECISION && exponent_bits == 15)
+ {
+ *lp++ = word1;
+#ifdef TC_M68K
+ *lp++ = 0;
+#endif
+ *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS - num_bits);
+ }
+ else
+ {
+ word1 |= next_bits ((LITTLENUM_NUMBER_OF_BITS - 1) - (exponent_bits + num_bits));
+ *lp++ = word1;
+ }
+ }
+ while (lp < words_end)
+ *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS);
+
+ /* Round the mantissa up, but don't change the number */
+ if (next_bits (1))
+ {
+ --lp;
+ if (prec_bits > LITTLENUM_NUMBER_OF_BITS)
+ {
+ int n = 0;
+ int tmp_bits;
+
+ n = 0;
+ tmp_bits = prec_bits;
+ while (tmp_bits > LITTLENUM_NUMBER_OF_BITS)
+ {
+ if (lp[n] != (LITTLENUM_TYPE) - 1)
+ break;
+ --n;
+ tmp_bits -= LITTLENUM_NUMBER_OF_BITS;
+ }
+ if (tmp_bits > LITTLENUM_NUMBER_OF_BITS || (lp[n] & mask[tmp_bits]) != mask[tmp_bits])
+ {
+ unsigned long carry;
+
+ for (carry = 1; carry && (lp >= words); lp--)
+ {
+ carry = *lp + carry;
+ *lp = carry;
+ carry >>= LITTLENUM_NUMBER_OF_BITS;
+ }
+ }
+ else
+ {
+ /* This is an overflow of the denormal numbers. We
+ need to forget what we have produced, and instead
+ generate the smallest normalized number. */
+ lp = words;
+ word1 = ((generic_floating_point_number.sign == '+')
+ ? 0
+ : (1 << (LITTLENUM_NUMBER_OF_BITS - 1)));
+ word1 |= (1
+ << ((LITTLENUM_NUMBER_OF_BITS - 1)
+ - exponent_bits));
+ *lp++ = word1;
+ while (lp < words_end)
+ *lp++ = 0;
+ }
+ }
+ else if ((*lp & mask[prec_bits]) != mask[prec_bits])
+ *lp += 1;
+ }
+
+ return return_value;
+ }
+ else if ((unsigned long) exponent_4 >= mask[exponent_bits])
+ {
+ /*
+ * Exponent overflow. Lose immediately.
+ */
+
+ /*
+ * We leave return_value alone: admit we read the
+ * number, but return a floating exception
+ * because we can't encode the number.
+ */
+ make_invalid_floating_point_number (words);
+ return return_value;
+ }
+ else
+ {
+ word1 |= (exponent_4 << ((LITTLENUM_NUMBER_OF_BITS - 1) - exponent_bits))
+ | next_bits ((LITTLENUM_NUMBER_OF_BITS - 1) - exponent_bits);
+ }
+
+ *lp++ = word1;
+
+ /* X_PRECISION is special: on the 68k, it has 16 bits of zero in the
+ middle. Either way, it is then followed by a 1 bit. */
+ if (exponent_bits == 15 && precision == X_PRECISION)
+ {
+#ifdef TC_M68K
+ *lp++ = 0;
+#endif
+ *lp++ = (1 << (LITTLENUM_NUMBER_OF_BITS - 1)
+ | next_bits (LITTLENUM_NUMBER_OF_BITS - 1));
+ }
+
+ /* The rest of the words are just mantissa bits. */
+ while (lp < words_end)
+ *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS);
+
+ if (next_bits (1))
+ {
+ unsigned long carry;
+ /*
+ * Since the NEXT bit is a 1, round UP the mantissa.
+ * The cunning design of these hidden-1 floats permits
+ * us to let the mantissa overflow into the exponent, and
+ * it 'does the right thing'. However, we lose if the
+ * highest-order bit of the lowest-order word flips.
+ * Is that clear?
+ */
+
+ /* #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2)
+ Please allow at least 1 more bit in carry than is in a LITTLENUM.
+ We need that extra bit to hold a carry during a LITTLENUM carry
+ propagation. Another extra bit (kept 0) will assure us that we
+ don't get a sticky sign bit after shifting right, and that
+ permits us to propagate the carry without any masking of bits.
+ #endif */
+ for (carry = 1, lp--; carry && (lp >= words); lp--)
+ {
+ carry = *lp + carry;
+ *lp = carry;
+ carry >>= LITTLENUM_NUMBER_OF_BITS;
+ }
+ if (precision == X_PRECISION && exponent_bits == 15)
+ {
+ /* Extended precision numbers have an explicit integer bit
+ that we may have to restore. */
+ if (lp == words)
+ {
+#ifdef TC_M68K
+ /* On the m68k there is a gap of 16 bits. We must
+ explicitly propagate the carry into the exponent. */
+ words[0] += words[1];
+ words[1] = 0;
+ lp++;
+#endif
+ /* Put back the integer bit. */
+ lp[1] |= 1 << (LITTLENUM_NUMBER_OF_BITS - 1);
+ }
+ }
+ if ((word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1)))
+ {
+ /* We leave return_value alone: admit we read the
+ * number, but return a floating exception
+ * because we can't encode the number.
+ */
+ *words &= ~(1 << (LITTLENUM_NUMBER_OF_BITS - 1));
+ /* make_invalid_floating_point_number (words); */
+ /* return return_value; */
+ }
+ }
+ return (return_value);
+}
+
+#if 0 /* unused */
+/* This routine is a real kludge. Someone really should do it better,
+ but I'm too lazy, and I don't understand this stuff all too well
+ anyway. (JF) */
+static void
+int_to_gen (x)
+ long x;
+{
+ char buf[20];
+ char *bufp;
+
+ sprintf (buf, "%ld", x);
+ bufp = &buf[0];
+ if (atof_generic (&bufp, ".", EXP_CHARS, &generic_floating_point_number))
+ as_bad (_("Error converting number to floating point (Exponent overflow?)"));
+}
+#endif
+
+#ifdef TEST
+char *
+print_gen (gen)
+ FLONUM_TYPE *gen;
+{
+ FLONUM_TYPE f;
+ LITTLENUM_TYPE arr[10];
+ double dv;
+ float fv;
+ static char sbuf[40];
+
+ if (gen)
+ {
+ f = generic_floating_point_number;
+ generic_floating_point_number = *gen;
+ }
+ gen_to_words (&arr[0], 4, 11);
+ memcpy (&dv, &arr[0], sizeof (double));
+ sprintf (sbuf, "%x %x %x %x %.14G ", arr[0], arr[1], arr[2], arr[3], dv);
+ gen_to_words (&arr[0], 2, 8);
+ memcpy (&fv, &arr[0], sizeof (float));
+ sprintf (sbuf + strlen (sbuf), "%x %x %.12g\n", arr[0], arr[1], fv);
+
+ if (gen)
+ {
+ generic_floating_point_number = f;
+ }
+
+ return (sbuf);
+}
+
+#endif
+
+/* end of atof-ieee.c */
diff --git a/gas/config/atof-tahoe.c b/gas/config/atof-tahoe.c
new file mode 100644
index 0000000000..760485c5fd
--- /dev/null
+++ b/gas/config/atof-tahoe.c
@@ -0,0 +1,431 @@
+
+/* atof_tahoe.c - turn a string into a Tahoe floating point number
+ Copyright (C) 1987, 1998 Free Software Foundation, Inc.
+ */
+
+/* This is really a simplified version of atof_vax.c. I glommed it wholesale
+ and then shaved it down. I don't even know how it works. (Don't you find
+ my honesty refreshing? bowen@cs.Buffalo.EDU (Devon E Bowen)
+
+ I don't allow uppercase letters in the precision descrpitors. Ie 'f' and
+ 'd' are allowed but 'F' and 'D' aren't */
+
+#include "as.h"
+
+/* Precision in LittleNums. */
+#define MAX_PRECISION (4)
+#define D_PRECISION (4)
+#define F_PRECISION (2)
+
+/* Precision in chars. */
+#define D_PRECISION_CHARS (8)
+#define F_PRECISION_CHARS (4)
+
+/* Length in LittleNums of guard bits. */
+#define GUARD (2)
+
+static const long int mask[] =
+{
+ 0x00000000,
+ 0x00000001,
+ 0x00000003,
+ 0x00000007,
+ 0x0000000f,
+ 0x0000001f,
+ 0x0000003f,
+ 0x0000007f,
+ 0x000000ff,
+ 0x000001ff,
+ 0x000003ff,
+ 0x000007ff,
+ 0x00000fff,
+ 0x00001fff,
+ 0x00003fff,
+ 0x00007fff,
+ 0x0000ffff,
+ 0x0001ffff,
+ 0x0003ffff,
+ 0x0007ffff,
+ 0x000fffff,
+ 0x001fffff,
+ 0x003fffff,
+ 0x007fffff,
+ 0x00ffffff,
+ 0x01ffffff,
+ 0x03ffffff,
+ 0x07ffffff,
+ 0x0fffffff,
+ 0x1fffffff,
+ 0x3fffffff,
+ 0x7fffffff,
+ 0xffffffff
+};
+
+
+/* Shared between flonum_gen2tahoe and next_bits */
+static int bits_left_in_littlenum;
+static LITTLENUM_TYPE *littlenum_pointer;
+static LITTLENUM_TYPE *littlenum_end;
+
+#if __STDC__ == 1
+
+int flonum_gen2tahoe (int format_letter, FLONUM_TYPE * f, LITTLENUM_TYPE * words);
+
+#else /* not __STDC__ */
+
+int flonum_gen2tahoe ();
+
+#endif /* not __STDC__ */
+
+
+static int
+next_bits (number_of_bits)
+ int number_of_bits;
+{
+ int return_value;
+
+ if (littlenum_pointer < littlenum_end)
+ return 0;
+ if (number_of_bits >= bits_left_in_littlenum)
+ {
+ return_value = mask[bits_left_in_littlenum] & *littlenum_pointer;
+ number_of_bits -= bits_left_in_littlenum;
+ return_value <<= number_of_bits;
+ bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS - number_of_bits;
+ littlenum_pointer--;
+ if (littlenum_pointer >= littlenum_end)
+ return_value |= ((*littlenum_pointer) >> (bits_left_in_littlenum)) &
+ mask[number_of_bits];
+ }
+ else
+ {
+ bits_left_in_littlenum -= number_of_bits;
+ return_value = mask[number_of_bits] &
+ ((*littlenum_pointer) >> bits_left_in_littlenum);
+ }
+ return (return_value);
+}
+
+static void
+make_invalid_floating_point_number (words)
+ LITTLENUM_TYPE *words;
+{
+ *words = 0x8000; /* Floating Reserved Operand Code */
+}
+
+static int /* 0 means letter is OK. */
+what_kind_of_float (letter, precisionP, exponent_bitsP)
+ char letter; /* In: lowercase please. What kind of float? */
+ int *precisionP; /* Number of 16-bit words in the float. */
+ long int *exponent_bitsP; /* Number of exponent bits. */
+{
+ int retval; /* 0: OK. */
+
+ retval = 0;
+ switch (letter)
+ {
+ case 'f':
+ *precisionP = F_PRECISION;
+ *exponent_bitsP = 8;
+ break;
+
+ case 'd':
+ *precisionP = D_PRECISION;
+ *exponent_bitsP = 8;
+ break;
+
+ default:
+ retval = 69;
+ break;
+ }
+ return (retval);
+}
+
+/***********************************************************************\
+* *
+* Warning: this returns 16-bit LITTLENUMs, because that is *
+* what the VAX thinks in. It is up to the caller to figure *
+* out any alignment problems and to conspire for the bytes/word *
+* to be emitted in the right order. Bigendians beware! *
+* *
+\***********************************************************************/
+
+char * /* Return pointer past text consumed. */
+atof_tahoe (str, what_kind, words)
+ char *str; /* Text to convert to binary. */
+ char what_kind; /* 'd', 'f', 'g', 'h' */
+ LITTLENUM_TYPE *words; /* Build the binary here. */
+{
+ FLONUM_TYPE f;
+ LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD];
+ /* Extra bits for zeroed low-order bits. */
+ /* The 1st MAX_PRECISION are zeroed, */
+ /* the last contain flonum bits. */
+ char *return_value;
+ int precision; /* Number of 16-bit words in the format. */
+ long int exponent_bits;
+
+ return_value = str;
+ f.low = bits + MAX_PRECISION;
+ f.high = NULL;
+ f.leader = NULL;
+ f.exponent = NULL;
+ f.sign = '\0';
+
+ if (what_kind_of_float (what_kind, &precision, &exponent_bits))
+ {
+ return_value = NULL; /* We lost. */
+ make_invalid_floating_point_number (words);
+ }
+ if (return_value)
+ {
+ memset (bits, '\0', sizeof (LITTLENUM_TYPE) * MAX_PRECISION);
+
+ /* Use more LittleNums than seems */
+ /* necessary: the highest flonum may have */
+ /* 15 leading 0 bits, so could be useless. */
+ f.high = f.low + precision - 1 + GUARD;
+
+ if (atof_generic (&return_value, ".", "eE", &f))
+ {
+ make_invalid_floating_point_number (words);
+ return_value = NULL; /* we lost */
+ }
+ else
+ {
+ if (flonum_gen2tahoe (what_kind, &f, words))
+ {
+ return_value = NULL;
+ }
+ }
+ }
+ return (return_value);
+}
+
+/*
+ * In: a flonum, a Tahoe floating point format.
+ * Out: a Tahoe floating-point bit pattern.
+ */
+
+int /* 0: OK. */
+flonum_gen2tahoe (format_letter, f, words)
+ char format_letter; /* One of 'd' 'f'. */
+ FLONUM_TYPE *f;
+ LITTLENUM_TYPE *words; /* Deliver answer here. */
+{
+ LITTLENUM_TYPE *lp;
+ int precision;
+ long int exponent_bits;
+ int return_value; /* 0 == OK. */
+
+ return_value = what_kind_of_float (format_letter, &precision, &exponent_bits);
+ if (return_value != 0)
+ {
+ make_invalid_floating_point_number (words);
+ }
+ else
+ {
+ if (f->low > f->leader)
+ {
+ /* 0.0e0 seen. */
+ memset (words, '\0', sizeof (LITTLENUM_TYPE) * precision);
+ }
+ else
+ {
+ long int exponent_1;
+ long int exponent_2;
+ long int exponent_3;
+ long int exponent_4;
+ int exponent_skippage;
+ LITTLENUM_TYPE word1;
+
+ /* JF: Deal with new Nan, +Inf and -Inf codes */
+ if (f->sign != '-' && f->sign != '+')
+ {
+ make_invalid_floating_point_number (words);
+ return return_value;
+ }
+ /*
+ * All tahoe floating_point formats have:
+ * Bit 15 is sign bit.
+ * Bits 14:n are excess-whatever exponent.
+ * Bits n-1:0 (if any) are most significant bits of fraction.
+ * Bits 15:0 of the next word are the next most significant bits.
+ * And so on for each other word.
+ *
+ * So we need: number of bits of exponent, number of bits of
+ * mantissa.
+ */
+
+ bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS;
+ littlenum_pointer = f->leader;
+ littlenum_end = f->low;
+ /* Seek (and forget) 1st significant bit */
+ for (exponent_skippage = 0;
+ !next_bits (1);
+ exponent_skippage++)
+ {
+ }
+ exponent_1 = f->exponent + f->leader + 1 - f->low;
+ /* Radix LITTLENUM_RADIX, point just higher than f -> leader. */
+ exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS;
+ /* Radix 2. */
+ exponent_3 = exponent_2 - exponent_skippage;
+ /* Forget leading zeros, forget 1st bit. */
+ exponent_4 = exponent_3 + (1 << (exponent_bits - 1));
+ /* Offset exponent. */
+
+ if (exponent_4 & ~mask[exponent_bits])
+ {
+ /*
+ * Exponent overflow. Lose immediately.
+ */
+
+ make_invalid_floating_point_number (words);
+
+ /*
+ * We leave return_value alone: admit we read the
+ * number, but return a floating exception
+ * because we can't encode the number.
+ */
+ }
+ else
+ {
+ lp = words;
+
+ /* Word 1. Sign, exponent and perhaps high bits. */
+ /* Assume 2's complement integers. */
+ word1 = ((exponent_4 & mask[exponent_bits]) << (15 - exponent_bits))
+ | ((f->sign == '+') ? 0 : 0x8000)
+ | next_bits (15 - exponent_bits);
+ *lp++ = word1;
+
+ /* The rest of the words are just mantissa bits. */
+ for (; lp < words + precision; lp++)
+ {
+ *lp = next_bits (LITTLENUM_NUMBER_OF_BITS);
+ }
+
+ if (next_bits (1))
+ {
+ /*
+ * Since the NEXT bit is a 1, round UP the mantissa.
+ * The cunning design of these hidden-1 floats permits
+ * us to let the mantissa overflow into the exponent, and
+ * it 'does the right thing'. However, we lose if the
+ * highest-order bit of the lowest-order word flips.
+ * Is that clear?
+ */
+
+ unsigned long int carry;
+
+ /*
+ #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2)
+ Please allow at least 1 more bit in carry than is in a LITTLENUM.
+ We need that extra bit to hold a carry during a LITTLENUM carry
+ propagation. Another extra bit (kept 0) will assure us that we
+ don't get a sticky sign bit after shifting right, and that
+ permits us to propagate the carry without any masking of bits.
+ #endif
+ */
+ for (carry = 1, lp--;
+ carry && (lp >= words);
+ lp--)
+ {
+ carry = *lp + carry;
+ *lp = carry;
+ carry >>= LITTLENUM_NUMBER_OF_BITS;
+ }
+
+ if ((word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1)))
+ {
+ make_invalid_floating_point_number (words);
+ /*
+ * We leave return_value alone: admit we read the
+ * number, but return a floating exception
+ * because we can't encode the number.
+ */
+ }
+ } /* if (we needed to round up) */
+ } /* if (exponent overflow) */
+ } /* if (0.0e0) */
+ } /* if (float_type was OK) */
+ return (return_value);
+}
+
+/*
+ * md_atof()
+ *
+ * In: input_line_pointer -> the 1st character of a floating-point
+ * number.
+ * 1 letter denoting the type of statement that wants a
+ * binary floating point number returned.
+ * Address of where to build floating point literal.
+ * Assumed to be 'big enough'.
+ * Address of where to return size of literal (in chars).
+ *
+ * Out: Input_line_pointer -> of next char after floating number.
+ * Error message, or 0.
+ * Floating point literal.
+ * Number of chars we used for the literal.
+ */
+
+char *
+md_atof (what_statement_type, literalP, sizeP)
+ char what_statement_type;
+ char *literalP;
+ int *sizeP;
+{
+ LITTLENUM_TYPE words[MAX_PRECISION];
+ register char kind_of_float;
+ register int number_of_chars;
+ register LITTLENUM_TYPE *littlenum_pointer;
+
+ switch (what_statement_type)
+ {
+ case 'f': /* .ffloat */
+ case 'd': /* .dfloat */
+ kind_of_float = what_statement_type;
+ break;
+
+ default:
+ kind_of_float = 0;
+ break;
+ };
+
+ if (kind_of_float)
+ {
+ register LITTLENUM_TYPE *limit;
+
+ input_line_pointer = atof_tahoe (input_line_pointer,
+ kind_of_float,
+ words);
+ /*
+ * The atof_tahoe() builds up 16-bit numbers.
+ * Since the assembler may not be running on
+ * a different-endian machine, be very careful about
+ * converting words to chars.
+ */
+ number_of_chars = (kind_of_float == 'f' ? F_PRECISION_CHARS :
+ (kind_of_float == 'd' ? D_PRECISION_CHARS : 0));
+ know (number_of_chars <= MAX_PRECISION * sizeof (LITTLENUM_TYPE));
+ limit = words + (number_of_chars / sizeof (LITTLENUM_TYPE));
+ for (littlenum_pointer = words;
+ littlenum_pointer < limit;
+ littlenum_pointer++)
+ {
+ md_number_to_chars (literalP, *littlenum_pointer,
+ sizeof (LITTLENUM_TYPE));
+ literalP += sizeof (LITTLENUM_TYPE);
+ };
+ }
+ else
+ {
+ number_of_chars = 0;
+ };
+
+ *sizeP = number_of_chars;
+ return kind_of_float ? 0 : _("Bad call to md_atof()");
+}
+
+/* atof_tahoe.c */
diff --git a/gas/config/atof-vax.c b/gas/config/atof-vax.c
new file mode 100644
index 0000000000..45b90a8cc2
--- /dev/null
+++ b/gas/config/atof-vax.c
@@ -0,0 +1,517 @@
+/* atof_vax.c - turn a Flonum into a VAX floating point number
+ Copyright (C) 1987, 1992, 93, 95, 1997, 1998 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include "as.h"
+
+static int atof_vax_sizeof PARAMS ((int));
+static int next_bits PARAMS ((int));
+static void make_invalid_floating_point_number PARAMS ((LITTLENUM_TYPE *));
+static int what_kind_of_float PARAMS ((int, int *, long *));
+static char *atof_vax PARAMS ((char *, int, LITTLENUM_TYPE *));
+
+/* Precision in LittleNums. */
+#define MAX_PRECISION (8)
+#define H_PRECISION (8)
+#define G_PRECISION (4)
+#define D_PRECISION (4)
+#define F_PRECISION (2)
+
+/* Length in LittleNums of guard bits. */
+#define GUARD (2)
+
+int flonum_gen2vax PARAMS ((int format_letter, FLONUM_TYPE * f,
+ LITTLENUM_TYPE * words));
+
+/* Number of chars in flonum type 'letter'. */
+static int
+atof_vax_sizeof (letter)
+ int letter;
+{
+ int return_value;
+
+ /*
+ * Permitting uppercase letters is probably a bad idea.
+ * Please use only lower-cased letters in case the upper-cased
+ * ones become unsupported!
+ */
+ switch (letter)
+ {
+ case 'f':
+ case 'F':
+ return_value = 4;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'g':
+ case 'G':
+ return_value = 8;
+ break;
+
+ case 'h':
+ case 'H':
+ return_value = 16;
+ break;
+
+ default:
+ return_value = 0;
+ break;
+ }
+ return (return_value);
+} /* atof_vax_sizeof */
+
+static const long mask[] =
+{
+ 0x00000000,
+ 0x00000001,
+ 0x00000003,
+ 0x00000007,
+ 0x0000000f,
+ 0x0000001f,
+ 0x0000003f,
+ 0x0000007f,
+ 0x000000ff,
+ 0x000001ff,
+ 0x000003ff,
+ 0x000007ff,
+ 0x00000fff,
+ 0x00001fff,
+ 0x00003fff,
+ 0x00007fff,
+ 0x0000ffff,
+ 0x0001ffff,
+ 0x0003ffff,
+ 0x0007ffff,
+ 0x000fffff,
+ 0x001fffff,
+ 0x003fffff,
+ 0x007fffff,
+ 0x00ffffff,
+ 0x01ffffff,
+ 0x03ffffff,
+ 0x07ffffff,
+ 0x0fffffff,
+ 0x1fffffff,
+ 0x3fffffff,
+ 0x7fffffff,
+ 0xffffffff
+};
+
+
+/* Shared between flonum_gen2vax and next_bits */
+static int bits_left_in_littlenum;
+static LITTLENUM_TYPE *littlenum_pointer;
+static LITTLENUM_TYPE *littlenum_end;
+
+static int
+next_bits (number_of_bits)
+ int number_of_bits;
+{
+ int return_value;
+
+ if (littlenum_pointer < littlenum_end)
+ return 0;
+ if (number_of_bits >= bits_left_in_littlenum)
+ {
+ return_value = mask[bits_left_in_littlenum] & *littlenum_pointer;
+ number_of_bits -= bits_left_in_littlenum;
+ return_value <<= number_of_bits;
+ bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS - number_of_bits;
+ littlenum_pointer--;
+ if (littlenum_pointer >= littlenum_end)
+ return_value |= ((*littlenum_pointer) >> (bits_left_in_littlenum)) & mask[number_of_bits];
+ }
+ else
+ {
+ bits_left_in_littlenum -= number_of_bits;
+ return_value = mask[number_of_bits] & ((*littlenum_pointer) >> bits_left_in_littlenum);
+ }
+ return (return_value);
+}
+
+static void
+make_invalid_floating_point_number (words)
+ LITTLENUM_TYPE *words;
+{
+ *words = 0x8000; /* Floating Reserved Operand Code */
+}
+
+static int /* 0 means letter is OK. */
+what_kind_of_float (letter, precisionP, exponent_bitsP)
+ int letter; /* In: lowercase please. What kind of float? */
+ int *precisionP; /* Number of 16-bit words in the float. */
+ long *exponent_bitsP; /* Number of exponent bits. */
+{
+ int retval; /* 0: OK. */
+
+ retval = 0;
+ switch (letter)
+ {
+ case 'f':
+ *precisionP = F_PRECISION;
+ *exponent_bitsP = 8;
+ break;
+
+ case 'd':
+ *precisionP = D_PRECISION;
+ *exponent_bitsP = 8;
+ break;
+
+ case 'g':
+ *precisionP = G_PRECISION;
+ *exponent_bitsP = 11;
+ break;
+
+ case 'h':
+ *precisionP = H_PRECISION;
+ *exponent_bitsP = 15;
+ break;
+
+ default:
+ retval = 69;
+ break;
+ }
+ return (retval);
+}
+
+/***********************************************************************\
+ * *
+ * Warning: this returns 16-bit LITTLENUMs, because that is *
+ * what the VAX thinks in. It is up to the caller to figure *
+ * out any alignment problems and to conspire for the bytes/word *
+ * to be emitted in the right order. Bigendians beware! *
+ * *
+ \***********************************************************************/
+
+static char * /* Return pointer past text consumed. */
+atof_vax (str, what_kind, words)
+ char *str; /* Text to convert to binary. */
+ int what_kind; /* 'd', 'f', 'g', 'h' */
+ LITTLENUM_TYPE *words; /* Build the binary here. */
+{
+ FLONUM_TYPE f;
+ LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD];
+ /* Extra bits for zeroed low-order bits. */
+ /* The 1st MAX_PRECISION are zeroed, */
+ /* the last contain flonum bits. */
+ char *return_value;
+ int precision; /* Number of 16-bit words in the format. */
+ long exponent_bits;
+
+ return_value = str;
+ f.low = bits + MAX_PRECISION;
+ f.high = NULL;
+ f.leader = NULL;
+ f.exponent = 0;
+ f.sign = '\0';
+
+ if (what_kind_of_float (what_kind, &precision, &exponent_bits))
+ {
+ return_value = NULL; /* We lost. */
+ make_invalid_floating_point_number (words);
+ }
+
+ if (return_value)
+ {
+ memset (bits, '\0', sizeof (LITTLENUM_TYPE) * MAX_PRECISION);
+
+ /* Use more LittleNums than seems */
+ /* necessary: the highest flonum may have */
+ /* 15 leading 0 bits, so could be useless. */
+ f.high = f.low + precision - 1 + GUARD;
+
+ if (atof_generic (&return_value, ".", "eE", &f))
+ {
+ make_invalid_floating_point_number (words);
+ return_value = NULL; /* we lost */
+ }
+ else
+ {
+ if (flonum_gen2vax (what_kind, &f, words))
+ {
+ return_value = NULL;
+ }
+ }
+ }
+ return (return_value);
+} /* atof_vax() */
+
+/*
+ * In: a flonum, a vax floating point format.
+ * Out: a vax floating-point bit pattern.
+ */
+
+int /* 0: OK. */
+flonum_gen2vax (format_letter, f, words)
+ char format_letter; /* One of 'd' 'f' 'g' 'h'. */
+ FLONUM_TYPE *f;
+ LITTLENUM_TYPE *words; /* Deliver answer here. */
+{
+ LITTLENUM_TYPE *lp;
+ int precision;
+ long exponent_bits;
+ int return_value; /* 0 == OK. */
+
+ return_value = what_kind_of_float (format_letter, &precision, &exponent_bits);
+
+ if (return_value != 0)
+ {
+ make_invalid_floating_point_number (words);
+ }
+ else
+ {
+ if (f->low > f->leader)
+ {
+ /* 0.0e0 seen. */
+ memset (words, '\0', sizeof (LITTLENUM_TYPE) * precision);
+ }
+ else
+ {
+ long exponent_1;
+ long exponent_2;
+ long exponent_3;
+ long exponent_4;
+ int exponent_skippage;
+ LITTLENUM_TYPE word1;
+
+ /* JF: Deal with new Nan, +Inf and -Inf codes */
+ if (f->sign != '-' && f->sign != '+')
+ {
+ make_invalid_floating_point_number (words);
+ return return_value;
+ }
+ /*
+ * All vaxen floating_point formats (so far) have:
+ * Bit 15 is sign bit.
+ * Bits 14:n are excess-whatever exponent.
+ * Bits n-1:0 (if any) are most significant bits of fraction.
+ * Bits 15:0 of the next word are the next most significant bits.
+ * And so on for each other word.
+ *
+ * All this to be compatible with a KF11?? (Which is still faster
+ * than lots of vaxen I can think of, but it also has higher
+ * maintenance costs ... sigh).
+ *
+ * So we need: number of bits of exponent, number of bits of
+ * mantissa.
+ */
+
+#ifdef NEVER /******* This zeroing seems redundant - Dean 3may86 **********/
+ /*
+ * No matter how few bits we got back from the atof()
+ * routine, add enough zero littlenums so the rest of the
+ * code won't run out of "significant" bits in the mantissa.
+ */
+ {
+ LITTLENUM_TYPE *ltp;
+ for (ltp = f->leader + 1;
+ ltp <= f->low + precision;
+ ltp++)
+ {
+ *ltp = 0;
+ }
+ }
+#endif
+
+ bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS;
+ littlenum_pointer = f->leader;
+ littlenum_end = f->low;
+ /* Seek (and forget) 1st significant bit */
+ for (exponent_skippage = 0;
+ !next_bits (1);
+ exponent_skippage++);;
+
+ exponent_1 = f->exponent + f->leader + 1 - f->low;
+ /* Radix LITTLENUM_RADIX, point just higher than f->leader. */
+ exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS;
+ /* Radix 2. */
+ exponent_3 = exponent_2 - exponent_skippage;
+ /* Forget leading zeros, forget 1st bit. */
+ exponent_4 = exponent_3 + (1 << (exponent_bits - 1));
+ /* Offset exponent. */
+
+ if (exponent_4 & ~mask[exponent_bits])
+ {
+ /*
+ * Exponent overflow. Lose immediately.
+ */
+
+ make_invalid_floating_point_number (words);
+
+ /*
+ * We leave return_value alone: admit we read the
+ * number, but return a floating exception
+ * because we can't encode the number.
+ */
+ }
+ else
+ {
+ lp = words;
+
+ /* Word 1. Sign, exponent and perhaps high bits. */
+ /* Assume 2's complement integers. */
+ word1 = (((exponent_4 & mask[exponent_bits]) << (15 - exponent_bits))
+ | ((f->sign == '+') ? 0 : 0x8000)
+ | next_bits (15 - exponent_bits));
+ *lp++ = word1;
+
+ /* The rest of the words are just mantissa bits. */
+ for (; lp < words + precision; lp++)
+ {
+ *lp = next_bits (LITTLENUM_NUMBER_OF_BITS);
+ }
+
+ if (next_bits (1))
+ {
+ /*
+ * Since the NEXT bit is a 1, round UP the mantissa.
+ * The cunning design of these hidden-1 floats permits
+ * us to let the mantissa overflow into the exponent, and
+ * it 'does the right thing'. However, we lose if the
+ * highest-order bit of the lowest-order word flips.
+ * Is that clear?
+ */
+
+ unsigned long carry;
+
+ /*
+ #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2)
+ Please allow at least 1 more bit in carry than is in a LITTLENUM.
+ We need that extra bit to hold a carry during a LITTLENUM carry
+ propagation. Another extra bit (kept 0) will assure us that we
+ don't get a sticky sign bit after shifting right, and that
+ permits us to propagate the carry without any masking of bits.
+ #endif
+ */
+ for (carry = 1, lp--;
+ carry && (lp >= words);
+ lp--)
+ {
+ carry = *lp + carry;
+ *lp = carry;
+ carry >>= LITTLENUM_NUMBER_OF_BITS;
+ }
+
+ if ((word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1)))
+ {
+ make_invalid_floating_point_number (words);
+ /*
+ * We leave return_value alone: admit we read the
+ * number, but return a floating exception
+ * because we can't encode the number.
+ */
+ }
+ } /* if (we needed to round up) */
+ } /* if (exponent overflow) */
+ } /* if (0.0e0) */
+ } /* if (float_type was OK) */
+ return (return_value);
+} /* flonum_gen2vax() */
+
+
+/* JF this used to be in vax.c but this looks like a better place for it */
+
+/*
+ * md_atof()
+ *
+ * In: input_line_pointer->the 1st character of a floating-point
+ * number.
+ * 1 letter denoting the type of statement that wants a
+ * binary floating point number returned.
+ * Address of where to build floating point literal.
+ * Assumed to be 'big enough'.
+ * Address of where to return size of literal (in chars).
+ *
+ * Out: Input_line_pointer->of next char after floating number.
+ * Error message, or 0.
+ * Floating point literal.
+ * Number of chars we used for the literal.
+ */
+
+#define MAXIMUM_NUMBER_OF_LITTLENUMS (8) /* For .hfloats. */
+
+char *
+md_atof (what_statement_type, literalP, sizeP)
+ int what_statement_type;
+ char *literalP;
+ int *sizeP;
+{
+ LITTLENUM_TYPE words[MAXIMUM_NUMBER_OF_LITTLENUMS];
+ register char kind_of_float;
+ register int number_of_chars;
+ register LITTLENUM_TYPE *littlenumP;
+
+ switch (what_statement_type)
+ {
+ case 'F': /* .float */
+ case 'f': /* .ffloat */
+ kind_of_float = 'f';
+ break;
+
+ case 'D': /* .double */
+ case 'd': /* .dfloat */
+ kind_of_float = 'd';
+ break;
+
+ case 'g': /* .gfloat */
+ kind_of_float = 'g';
+ break;
+
+ case 'h': /* .hfloat */
+ kind_of_float = 'h';
+ break;
+
+ default:
+ kind_of_float = 0;
+ break;
+ };
+
+ if (kind_of_float)
+ {
+ register LITTLENUM_TYPE *limit;
+
+ input_line_pointer = atof_vax (input_line_pointer,
+ kind_of_float,
+ words);
+ /*
+ * The atof_vax() builds up 16-bit numbers.
+ * Since the assembler may not be running on
+ * a little-endian machine, be very careful about
+ * converting words to chars.
+ */
+ number_of_chars = atof_vax_sizeof (kind_of_float);
+ know (number_of_chars <= MAXIMUM_NUMBER_OF_LITTLENUMS * sizeof (LITTLENUM_TYPE));
+ limit = words + (number_of_chars / sizeof (LITTLENUM_TYPE));
+ for (littlenumP = words; littlenumP < limit; littlenumP++)
+ {
+ md_number_to_chars (literalP, *littlenumP, sizeof (LITTLENUM_TYPE));
+ literalP += sizeof (LITTLENUM_TYPE);
+ };
+ }
+ else
+ {
+ number_of_chars = 0;
+ };
+
+ *sizeP = number_of_chars;
+ return kind_of_float ? 0 : _("Bad call to md_atof()");
+}
+
+/* end of atof-vax.c */
diff --git a/gas/config/e-i386coff.c b/gas/config/e-i386coff.c
new file mode 100644
index 0000000000..afed72886a
--- /dev/null
+++ b/gas/config/e-i386coff.c
@@ -0,0 +1,17 @@
+#include "as.h"
+#include "emul.h"
+
+static const char *
+i386coff_bfd_name ()
+{
+ abort ();
+ return NULL;
+}
+
+#define emul_bfd_name i386coff_bfd_name
+#define emul_format &coff_format_ops
+
+#define emul_name "i386coff"
+#define emul_struct_name i386coff
+#define emul_default_endian 0
+#include "emul-target.h"
diff --git a/gas/config/e-i386elf.c b/gas/config/e-i386elf.c
new file mode 100644
index 0000000000..a16701e811
--- /dev/null
+++ b/gas/config/e-i386elf.c
@@ -0,0 +1,17 @@
+#include "as.h"
+#include "emul.h"
+
+static const char *
+i386elf_bfd_name ()
+{
+ abort ();
+ return NULL;
+}
+
+#define emul_bfd_name i386elf_bfd_name
+#define emul_format &elf_format_ops
+
+#define emul_name "i386elf"
+#define emul_struct_name i386elf
+#define emul_default_endian 0
+#include "emul-target.h"
diff --git a/gas/config/e-mipsecoff.c b/gas/config/e-mipsecoff.c
new file mode 100644
index 0000000000..be2f71b7d4
--- /dev/null
+++ b/gas/config/e-mipsecoff.c
@@ -0,0 +1,37 @@
+#include "as.h"
+#include "emul.h"
+
+static const char *mipsecoff_bfd_name PARAMS ((void));
+
+static const char *
+mipsecoff_bfd_name ()
+{
+ abort ();
+ return NULL;
+}
+
+#define emul_bfd_name mipsecoff_bfd_name
+#define emul_format &ecoff_format_ops
+
+#define emul_name "mipsbecoff"
+#define emul_struct_name mipsbecoff
+#define emul_default_endian 1
+#include "emul-target.h"
+
+#undef emul_name
+#undef emul_struct_name
+#undef emul_default_endian
+
+#define emul_name "mipslecoff"
+#define emul_struct_name mipslecoff
+#define emul_default_endian 0
+#include "emul-target.h"
+
+#undef emul_name
+#undef emul_struct_name
+#undef emul_default_endian
+
+#define emul_name "mipsecoff"
+#define emul_struct_name mipsecoff
+#define emul_default_endian 2
+#include "emul-target.h"
diff --git a/gas/config/e-mipself.c b/gas/config/e-mipself.c
new file mode 100644
index 0000000000..eea72f5165
--- /dev/null
+++ b/gas/config/e-mipself.c
@@ -0,0 +1,37 @@
+#include "as.h"
+#include "emul.h"
+
+static const char *mipself_bfd_name PARAMS ((void));
+
+static const char *
+mipself_bfd_name ()
+{
+ abort ();
+ return NULL;
+}
+
+#define emul_bfd_name mipself_bfd_name
+#define emul_format &elf_format_ops
+
+#define emul_name "mipsbelf"
+#define emul_struct_name mipsbelf
+#define emul_default_endian 1
+#include "emul-target.h"
+
+#undef emul_name
+#undef emul_struct_name
+#undef emul_default_endian
+
+#define emul_name "mipslelf"
+#define emul_struct_name mipslelf
+#define emul_default_endian 0
+#include "emul-target.h"
+
+#undef emul_name
+#undef emul_struct_name
+#undef emul_default_endian
+
+#define emul_name "mipself"
+#define emul_struct_name mipself
+#define emul_default_endian 2
+#include "emul-target.h"
diff --git a/gas/config/go32.cfg b/gas/config/go32.cfg
new file mode 100644
index 0000000000..4059395da8
--- /dev/null
+++ b/gas/config/go32.cfg
@@ -0,0 +1,93 @@
+/* config.h for go32 */
+
+#define I386COFF 1
+
+/* Define if using alloca.c. */
+#undef C_ALLOCA
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+#undef CRAY_STACKSEG_END
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+#undef HAVE_ALLOCA_H
+
+/* Define as __inline if that's what the C compiler calls it. */
+#undef inline
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+#undef STACK_DIRECTION
+
+/* Should gas use high-level BFD interfaces? */
+#undef BFD_ASSEMBLER
+
+/* If we aren't doing cross-assembling, some operations can be optimized,
+ since byte orders and value sizes don't need to be adjusted. */
+#undef CROSS_COMPILE
+
+/* Some gas code wants to know these parameters. */
+#define TARGET_ALIAS "i386"
+#define TARGET_CPU "i386"
+#define TARGET_CANONICAL "i386-i386"
+#define TARGET_OS "djgpp"
+#define TARGET_VENDOR "djgpp"
+
+/* Some operating systems, for example DOS, require the use of "wb" mode when
+ opening a binary file for writing. If only "w" is used, the file will not
+ be correct. However, some other systems reject such a mode. This indicates
+ which ../include/fopen-*.h header file we want to include, so that we can
+ get macros that'll do the right thing for this system. */
+#define WANT_FOPEN_BIN 1
+
+/* Sometimes the system header files don't declare malloc and realloc. */
+#undef NEED_DECLARATION_MALLOC
+
+/* Sometimes the system header files don't declare free. */
+#undef NEED_DECLARATION_FREE
+
+/* Sometimes errno.h doesn't declare errno itself. */
+#undef NEED_DECLARATION_ERRNO
+
+#define MANY_SEGMENTS 1
+
+/* Needed only for sparc configuration */
+#undef sparcv9
+
+/* Define if you have the remove function. */
+#define HAVE_REMOVE 1
+
+/* Define if you have the unlink function. */
+#define HAVE_UNLINK 1
+
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <varargs.h> header file. */
+#undef HAVE_VARARGS_H
diff --git a/gas/config/itbl-mips.h b/gas/config/itbl-mips.h
new file mode 100644
index 0000000000..f6482bd1f7
--- /dev/null
+++ b/gas/config/itbl-mips.h
@@ -0,0 +1,47 @@
+
+/* itbl-mips.h
+
+ Copyright (C) 1997 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* Defines for Mips itbl cop support */
+
+#include "opcode/mips.h"
+
+/* Values for processors will be from 0 to NUMBER_OF_PROCESSORS-1 */
+#define NUMBER_OF_PROCESSORS 4
+#define MAX_BITPOS 31
+
+/* Mips specifics */
+#define MIPS_OPCODE_COP0 (0x21) /* COPz+CO, bits 31-25: 0100zz1 */
+#define MIPS_ENCODE_COP_NUM(z) ((MIPS_OPCODE_COP0|z<<1)<<25)
+#define MIPS_IS_COP_INSN(insn) ((MIPS_OPCODE_COP0&(insn>>25)) \
+ == MIPS_OPCODE_COP0)
+#define MIPS_DECODE_COP_NUM(insn) ((~MIPS_OPCODE_COP0&(insn>>25))>>1)
+#define MIPS_DECODE_COP_COFUN(insn) ((~MIPS_ENCODE_COP_NUM(3))&(insn))
+
+/* definitions required by generic code */
+#define ITBL_IS_INSN(insn) MIPS_IS_COP_INSN(insn)
+#define ITBL_DECODE_PNUM(insn) MIPS_DECODE_COP_NUM(insn)
+#define ITBL_ENCODE_PNUM(pnum) MIPS_ENCODE_COP_NUM(pnum)
+
+#define ITBL_OPCODE_STRUCT mips_opcode
+#define ITBL_OPCODES mips_opcodes
+#define ITBL_NUM_OPCODES NUMOPCODES
+#define ITBL_NUM_MACROS M_NUM_MACROS
diff --git a/gas/config/m68k-parse.h b/gas/config/m68k-parse.h
new file mode 100644
index 0000000000..e13134212e
--- /dev/null
+++ b/gas/config/m68k-parse.h
@@ -0,0 +1,283 @@
+/* m68k-parse.h -- header file for m68k assembler
+ Copyright (C) 1987, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#ifndef M68K_PARSE_H
+#define M68K_PARSE_H
+
+/* This header file defines things which are shared between the
+ operand parser in m68k.y and the m68k assembler proper in
+ tc-m68k.c. */
+
+/* The various m68k registers. */
+
+/* DATA and ADDR have to be contiguous, so that reg-DATA gives
+ 0-7==data reg, 8-15==addr reg for operands that take both types.
+
+ We don't use forms like "ADDR0 = ADDR" here because this file is
+ likely to be used on an Apollo, and the broken Apollo compiler
+ gives an `undefined variable' error if we do that, according to
+ troy@cbme.unsw.edu.au. */
+
+#define DATA DATA0
+#define ADDR ADDR0
+#define SP ADDR7
+#define BAD BAD0
+#define BAC BAC0
+
+enum m68k_register
+{
+ DATA0 = 1, /* 1- 8 == data registers 0-7 */
+ DATA1,
+ DATA2,
+ DATA3,
+ DATA4,
+ DATA5,
+ DATA6,
+ DATA7,
+
+ ADDR0,
+ ADDR1,
+ ADDR2,
+ ADDR3,
+ ADDR4,
+ ADDR5,
+ ADDR6,
+ ADDR7,
+
+ FP0, /* Eight FP registers */
+ FP1,
+ FP2,
+ FP3,
+ FP4,
+ FP5,
+ FP6,
+ FP7,
+
+ COP0, /* Co-processor #0-#7 */
+ COP1,
+ COP2,
+ COP3,
+ COP4,
+ COP5,
+ COP6,
+ COP7,
+
+ PC, /* Program counter */
+ ZPC, /* Hack for Program space, but 0 addressing */
+ SR, /* Status Reg */
+ CCR, /* Condition code Reg */
+
+ /* These have to be grouped together for the movec instruction to work. */
+ USP, /* User Stack Pointer */
+ ISP, /* Interrupt stack pointer */
+ SFC,
+ DFC,
+ CACR,
+ VBR,
+ CAAR,
+ MSP,
+ ITT0,
+ ITT1,
+ DTT0,
+ DTT1,
+ MMUSR,
+ TC,
+ SRP,
+ URP,
+ BUSCR, /* 68060 added these */
+ PCR,
+ ROMBAR, /* mcf5200 added these */
+ RAMBAR0,
+ RAMBAR1,
+ MBAR,
+#define last_movec_reg MBAR
+ /* end of movec ordering constraints */
+
+ FPI,
+ FPS,
+ FPC,
+
+ DRP, /* 68851 or 68030 MMU regs */
+ CRP,
+ CAL,
+ VAL,
+ SCC,
+ AC,
+ BAD0,
+ BAD1,
+ BAD2,
+ BAD3,
+ BAD4,
+ BAD5,
+ BAD6,
+ BAD7,
+ BAC0,
+ BAC1,
+ BAC2,
+ BAC3,
+ BAC4,
+ BAC5,
+ BAC6,
+ BAC7,
+ PSR, /* aka MMUSR on 68030 (but not MMUSR on 68040)
+ and ACUSR on 68ec030 */
+ PCSR,
+
+ IC, /* instruction cache token */
+ DC, /* data cache token */
+ NC, /* no cache token */
+ BC, /* both caches token */
+
+ TT0, /* 68030 access control unit regs */
+ TT1,
+
+ ZDATA0, /* suppressed data registers. */
+ ZDATA1,
+ ZDATA2,
+ ZDATA3,
+ ZDATA4,
+ ZDATA5,
+ ZDATA6,
+ ZDATA7,
+
+ ZADDR0, /* suppressed address registers. */
+ ZADDR1,
+ ZADDR2,
+ ZADDR3,
+ ZADDR4,
+ ZADDR5,
+ ZADDR6,
+ ZADDR7,
+};
+
+/* Size information. */
+
+enum m68k_size
+{
+ /* Unspecified. */
+ SIZE_UNSPEC,
+
+ /* Byte. */
+ SIZE_BYTE,
+
+ /* Word (2 bytes). */
+ SIZE_WORD,
+
+ /* Longword (4 bytes). */
+ SIZE_LONG
+};
+
+/* The structure used to hold information about an index register. */
+
+struct m68k_indexreg
+{
+ /* The index register itself. */
+ enum m68k_register reg;
+
+ /* The size to use. */
+ enum m68k_size size;
+
+ /* The value to scale by. */
+ int scale;
+};
+
+#ifdef OBJ_ELF
+/* The type of a PIC expression. */
+
+enum pic_relocation
+{
+ pic_none, /* not pic */
+ pic_plt_pcrel, /* @PLTPC */
+ pic_got_pcrel, /* @GOTPC */
+ pic_plt_off, /* @PLT */
+ pic_got_off /* @GOT */
+};
+#endif
+
+/* The structure used to hold information about an expression. */
+
+struct m68k_exp
+{
+ /* The size to use. */
+ enum m68k_size size;
+
+#ifdef OBJ_ELF
+ /* The type of pic relocation if any. */
+ enum pic_relocation pic_reloc;
+#endif
+
+ /* The expression itself. */
+ expressionS exp;
+};
+
+/* The operand modes. */
+
+enum m68k_operand_type
+{
+ IMMED = 1,
+ ABSL,
+ DREG,
+ AREG,
+ FPREG,
+ CONTROL,
+ AINDR,
+ AINC,
+ ADEC,
+ DISP,
+ BASE,
+ POST,
+ PRE,
+ REGLST
+};
+
+/* The structure used to hold a parsed operand. */
+
+struct m68k_op
+{
+ /* The type of operand. */
+ enum m68k_operand_type mode;
+
+ /* The main register. */
+ enum m68k_register reg;
+
+ /* The register mask for mode REGLST. */
+ unsigned long mask;
+
+ /* An error message. */
+ const char *error;
+
+ /* The index register. */
+ struct m68k_indexreg index;
+
+ /* The displacement. */
+ struct m68k_exp disp;
+
+ /* The outer displacement. */
+ struct m68k_exp odisp;
+};
+
+#endif /* ! defined (M68K_PARSE_H) */
+
+/* The parsing function. */
+
+extern int m68k_ip_op PARAMS ((char *, struct m68k_op *));
+
+/* Whether register prefixes are optional. */
+extern int flag_reg_prefix_optional;
diff --git a/gas/config/m68k-parse.y b/gas/config/m68k-parse.y
new file mode 100644
index 0000000000..70a4e4fe86
--- /dev/null
+++ b/gas/config/m68k-parse.y
@@ -0,0 +1,1061 @@
+/* m68k.y -- bison grammar for m68k operand parsing
+ Copyright (C) 1995, 96, 1997, 1998 Free Software Foundation, Inc.
+ Written by Ken Raeburn and Ian Lance Taylor, Cygnus Support
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* This file holds a bison grammar to parse m68k operands. The m68k
+ has a complicated operand syntax, and gas supports two main
+ variations of it. Using a grammar is probably overkill, but at
+ least it makes clear exactly what we do support. */
+
+%{
+
+#include "as.h"
+#include "tc-m68k.h"
+#include "m68k-parse.h"
+
+/* Remap normal yacc parser interface names (yyparse, yylex, yyerror,
+ etc), as well as gratuitiously global symbol names If other parser
+ generators (bison, byacc, etc) produce additional global names that
+ conflict at link time, then those parser generators need to be
+ fixed instead of adding those names to this list. */
+
+#define yymaxdepth m68k_maxdepth
+#define yyparse m68k_parse
+#define yylex m68k_lex
+#define yyerror m68k_error
+#define yylval m68k_lval
+#define yychar m68k_char
+#define yydebug m68k_debug
+#define yypact m68k_pact
+#define yyr1 m68k_r1
+#define yyr2 m68k_r2
+#define yydef m68k_def
+#define yychk m68k_chk
+#define yypgo m68k_pgo
+#define yyact m68k_act
+#define yyexca m68k_exca
+#define yyerrflag m68k_errflag
+#define yynerrs m68k_nerrs
+#define yyps m68k_ps
+#define yypv m68k_pv
+#define yys m68k_s
+#define yy_yys m68k_yys
+#define yystate m68k_state
+#define yytmp m68k_tmp
+#define yyv m68k_v
+#define yy_yyv m68k_yyv
+#define yyval m68k_val
+#define yylloc m68k_lloc
+#define yyreds m68k_reds /* With YYDEBUG defined */
+#define yytoks m68k_toks /* With YYDEBUG defined */
+#define yylhs m68k_yylhs
+#define yylen m68k_yylen
+#define yydefred m68k_yydefred
+#define yydgoto m68k_yydgoto
+#define yysindex m68k_yysindex
+#define yyrindex m68k_yyrindex
+#define yygindex m68k_yygindex
+#define yytable m68k_yytable
+#define yycheck m68k_yycheck
+
+#ifndef YYDEBUG
+#define YYDEBUG 1
+#endif
+
+/* Internal functions. */
+
+static enum m68k_register m68k_reg_parse PARAMS ((char **));
+static int yylex PARAMS ((void));
+static void yyerror PARAMS ((const char *));
+
+/* The parser sets fields pointed to by this global variable. */
+static struct m68k_op *op;
+
+%}
+
+%union
+{
+ struct m68k_indexreg indexreg;
+ enum m68k_register reg;
+ struct m68k_exp exp;
+ unsigned long mask;
+ int onereg;
+}
+
+%token <reg> DR AR FPR FPCR LPC ZAR ZDR LZPC CREG
+%token <indexreg> INDEXREG
+%token <exp> EXPR
+
+%type <indexreg> zireg zdireg
+%type <reg> zadr zdr apc zapc zpc optzapc optczapc
+%type <exp> optcexpr optexprc
+%type <mask> reglist ireglist reglistpair
+%type <onereg> reglistreg
+
+%%
+
+/* An operand. */
+
+operand:
+ generic_operand
+ | motorola_operand
+ | mit_operand
+ ;
+
+/* A generic operand. */
+
+generic_operand:
+ DR
+ {
+ op->mode = DREG;
+ op->reg = $1;
+ }
+ | AR
+ {
+ op->mode = AREG;
+ op->reg = $1;
+ }
+ | FPR
+ {
+ op->mode = FPREG;
+ op->reg = $1;
+ }
+ | FPCR
+ {
+ op->mode = CONTROL;
+ op->reg = $1;
+ }
+ | CREG
+ {
+ op->mode = CONTROL;
+ op->reg = $1;
+ }
+ | EXPR
+ {
+ op->mode = ABSL;
+ op->disp = $1;
+ }
+ | '#' EXPR
+ {
+ op->mode = IMMED;
+ op->disp = $2;
+ }
+ | '&' EXPR
+ {
+ op->mode = IMMED;
+ op->disp = $2;
+ }
+ | reglist
+ {
+ op->mode = REGLST;
+ op->mask = $1;
+ }
+ ;
+
+/* An operand in Motorola syntax. This includes MRI syntax as well,
+ which may or may not be different in that it permits commutativity
+ of index and base registers, and permits an offset expression to
+ appear inside or outside of the parentheses. */
+
+motorola_operand:
+ '(' AR ')'
+ {
+ op->mode = AINDR;
+ op->reg = $2;
+ }
+ | '(' AR ')' '+'
+ {
+ op->mode = AINC;
+ op->reg = $2;
+ }
+ | '-' '(' AR ')'
+ {
+ op->mode = ADEC;
+ op->reg = $3;
+ }
+ | '(' EXPR ',' zapc ')'
+ {
+ op->reg = $4;
+ op->disp = $2;
+ if (($4 >= ZADDR0 && $4 <= ZADDR7)
+ || $4 == ZPC)
+ op->mode = BASE;
+ else
+ op->mode = DISP;
+ }
+ | '(' zapc ',' EXPR ')'
+ {
+ op->reg = $2;
+ op->disp = $4;
+ if (($2 >= ZADDR0 && $2 <= ZADDR7)
+ || $2 == ZPC)
+ op->mode = BASE;
+ else
+ op->mode = DISP;
+ }
+ | EXPR '(' zapc ')'
+ {
+ op->reg = $3;
+ op->disp = $1;
+ if (($3 >= ZADDR0 && $3 <= ZADDR7)
+ || $3 == ZPC)
+ op->mode = BASE;
+ else
+ op->mode = DISP;
+ }
+ | '(' LPC ')'
+ {
+ op->mode = DISP;
+ op->reg = $2;
+ }
+ | '(' ZAR ')'
+ {
+ op->mode = BASE;
+ op->reg = $2;
+ }
+ | '(' LZPC ')'
+ {
+ op->mode = BASE;
+ op->reg = $2;
+ }
+ | '(' EXPR ',' zapc ',' zireg ')'
+ {
+ op->mode = BASE;
+ op->reg = $4;
+ op->disp = $2;
+ op->index = $6;
+ }
+ | '(' EXPR ',' zapc ',' zpc ')'
+ {
+ if ($4 == PC || $4 == ZPC)
+ yyerror (_("syntax error"));
+ op->mode = BASE;
+ op->reg = $6;
+ op->disp = $2;
+ op->index.reg = $4;
+ op->index.size = SIZE_UNSPEC;
+ op->index.scale = 1;
+ }
+ | '(' EXPR ',' zdireg optczapc ')'
+ {
+ op->mode = BASE;
+ op->reg = $5;
+ op->disp = $2;
+ op->index = $4;
+ }
+ | '(' zdireg ',' EXPR ')'
+ {
+ op->mode = BASE;
+ op->disp = $4;
+ op->index = $2;
+ }
+ | EXPR '(' zapc ',' zireg ')'
+ {
+ op->mode = BASE;
+ op->reg = $3;
+ op->disp = $1;
+ op->index = $5;
+ }
+ | '(' zapc ',' zireg ')'
+ {
+ op->mode = BASE;
+ op->reg = $2;
+ op->index = $4;
+ }
+ | EXPR '(' zapc ',' zpc ')'
+ {
+ if ($3 == PC || $3 == ZPC)
+ yyerror (_("syntax error"));
+ op->mode = BASE;
+ op->reg = $5;
+ op->disp = $1;
+ op->index.reg = $3;
+ op->index.size = SIZE_UNSPEC;
+ op->index.scale = 1;
+ }
+ | '(' zapc ',' zpc ')'
+ {
+ if ($2 == PC || $2 == ZPC)
+ yyerror (_("syntax error"));
+ op->mode = BASE;
+ op->reg = $4;
+ op->index.reg = $2;
+ op->index.size = SIZE_UNSPEC;
+ op->index.scale = 1;
+ }
+ | EXPR '(' zdireg optczapc ')'
+ {
+ op->mode = BASE;
+ op->reg = $4;
+ op->disp = $1;
+ op->index = $3;
+ }
+ | '(' zdireg optczapc ')'
+ {
+ op->mode = BASE;
+ op->reg = $3;
+ op->index = $2;
+ }
+ | '(' '[' EXPR optczapc ']' ',' zireg optcexpr ')'
+ {
+ op->mode = POST;
+ op->reg = $4;
+ op->disp = $3;
+ op->index = $7;
+ op->odisp = $8;
+ }
+ | '(' '[' EXPR optczapc ']' optcexpr ')'
+ {
+ op->mode = POST;
+ op->reg = $4;
+ op->disp = $3;
+ op->odisp = $6;
+ }
+ | '(' '[' zapc ']' ',' zireg optcexpr ')'
+ {
+ op->mode = POST;
+ op->reg = $3;
+ op->index = $6;
+ op->odisp = $7;
+ }
+ | '(' '[' zapc ']' optcexpr ')'
+ {
+ op->mode = POST;
+ op->reg = $3;
+ op->odisp = $5;
+ }
+ | '(' '[' EXPR ',' zapc ',' zireg ']' optcexpr ')'
+ {
+ op->mode = PRE;
+ op->reg = $5;
+ op->disp = $3;
+ op->index = $7;
+ op->odisp = $9;
+ }
+ | '(' '[' zapc ',' zireg ']' optcexpr ')'
+ {
+ op->mode = PRE;
+ op->reg = $3;
+ op->index = $5;
+ op->odisp = $7;
+ }
+ | '(' '[' EXPR ',' zapc ',' zpc ']' optcexpr ')'
+ {
+ if ($5 == PC || $5 == ZPC)
+ yyerror (_("syntax error"));
+ op->mode = PRE;
+ op->reg = $7;
+ op->disp = $3;
+ op->index.reg = $5;
+ op->index.size = SIZE_UNSPEC;
+ op->index.scale = 1;
+ op->odisp = $9;
+ }
+ | '(' '[' zapc ',' zpc ']' optcexpr ')'
+ {
+ if ($3 == PC || $3 == ZPC)
+ yyerror (_("syntax error"));
+ op->mode = PRE;
+ op->reg = $5;
+ op->index.reg = $3;
+ op->index.size = SIZE_UNSPEC;
+ op->index.scale = 1;
+ op->odisp = $7;
+ }
+ | '(' '[' optexprc zdireg optczapc ']' optcexpr ')'
+ {
+ op->mode = PRE;
+ op->reg = $5;
+ op->disp = $3;
+ op->index = $4;
+ op->odisp = $7;
+ }
+ ;
+
+/* An operand in MIT syntax. */
+
+mit_operand:
+ optzapc '@'
+ {
+ /* We use optzapc to avoid a shift/reduce conflict. */
+ if ($1 < ADDR0 || $1 > ADDR7)
+ yyerror (_("syntax error"));
+ op->mode = AINDR;
+ op->reg = $1;
+ }
+ | optzapc '@' '+'
+ {
+ /* We use optzapc to avoid a shift/reduce conflict. */
+ if ($1 < ADDR0 || $1 > ADDR7)
+ yyerror (_("syntax error"));
+ op->mode = AINC;
+ op->reg = $1;
+ }
+ | optzapc '@' '-'
+ {
+ /* We use optzapc to avoid a shift/reduce conflict. */
+ if ($1 < ADDR0 || $1 > ADDR7)
+ yyerror (_("syntax error"));
+ op->mode = ADEC;
+ op->reg = $1;
+ }
+ | optzapc '@' '(' EXPR ')'
+ {
+ op->reg = $1;
+ op->disp = $4;
+ if (($1 >= ZADDR0 && $1 <= ZADDR7)
+ || $1 == ZPC)
+ op->mode = BASE;
+ else
+ op->mode = DISP;
+ }
+ | optzapc '@' '(' optexprc zireg ')'
+ {
+ op->mode = BASE;
+ op->reg = $1;
+ op->disp = $4;
+ op->index = $5;
+ }
+ | optzapc '@' '(' EXPR ')' '@' '(' optexprc zireg ')'
+ {
+ op->mode = POST;
+ op->reg = $1;
+ op->disp = $4;
+ op->index = $9;
+ op->odisp = $8;
+ }
+ | optzapc '@' '(' EXPR ')' '@' '(' EXPR ')'
+ {
+ op->mode = POST;
+ op->reg = $1;
+ op->disp = $4;
+ op->odisp = $8;
+ }
+ | optzapc '@' '(' optexprc zireg ')' '@' '(' EXPR ')'
+ {
+ op->mode = PRE;
+ op->reg = $1;
+ op->disp = $4;
+ op->index = $5;
+ op->odisp = $9;
+ }
+ ;
+
+/* An index register, possibly suppressed, which need not have a size
+ or scale. */
+
+zireg:
+ INDEXREG
+ | zadr
+ {
+ $$.reg = $1;
+ $$.size = SIZE_UNSPEC;
+ $$.scale = 1;
+ }
+ ;
+
+/* A register which may be an index register, but which may not be an
+ address register. This nonterminal is used to avoid ambiguity when
+ trying to parse something like (0,d5,a6) as compared to (0,a6,d5). */
+
+zdireg:
+ INDEXREG
+ | zdr
+ {
+ $$.reg = $1;
+ $$.size = SIZE_UNSPEC;
+ $$.scale = 1;
+ }
+ ;
+
+/* An address or data register, or a suppressed address or data
+ register. */
+
+zadr:
+ zdr
+ | AR
+ | ZAR
+ ;
+
+/* A data register which may be suppressed. */
+
+zdr:
+ DR
+ | ZDR
+ ;
+
+/* Either an address register or the PC. */
+
+apc:
+ AR
+ | LPC
+ ;
+
+/* Either an address register, or the PC, or a suppressed address
+ register, or a suppressed PC. */
+
+zapc:
+ apc
+ | LZPC
+ | ZAR
+ ;
+
+/* An optional zapc. */
+
+optzapc:
+ /* empty */
+ {
+ $$ = ZADDR0;
+ }
+ | zapc
+ ;
+
+/* The PC, optionally suppressed. */
+
+zpc:
+ LPC
+ | LZPC
+ ;
+
+/* ',' zapc when it may be omitted. */
+
+optczapc:
+ /* empty */
+ {
+ $$ = ZADDR0;
+ }
+ | ',' zapc
+ {
+ $$ = $2;
+ }
+ ;
+
+/* ',' EXPR when it may be omitted. */
+
+optcexpr:
+ /* empty */
+ {
+ $$.exp.X_op = O_absent;
+ $$.size = SIZE_UNSPEC;
+ }
+ | ',' EXPR
+ {
+ $$ = $2;
+ }
+ ;
+
+/* EXPR ',' when it may be omitted. */
+
+optexprc:
+ /* empty */
+ {
+ $$.exp.X_op = O_absent;
+ $$.size = SIZE_UNSPEC;
+ }
+ | EXPR ','
+ {
+ $$ = $1;
+ }
+ ;
+
+/* A register list for the movem instruction. */
+
+reglist:
+ reglistpair
+ | reglistpair '/' ireglist
+ {
+ $$ = $1 | $3;
+ }
+ | reglistreg '/' ireglist
+ {
+ $$ = (1 << $1) | $3;
+ }
+ ;
+
+/* We use ireglist when we know we are looking at a reglist, and we
+ can safely reduce a simple register to reglistreg. If we permitted
+ reglist to reduce to reglistreg, it would be ambiguous whether a
+ plain register were a DREG/AREG/FPREG or a REGLST. */
+
+ireglist:
+ reglistreg
+ {
+ $$ = 1 << $1;
+ }
+ | reglistpair
+ | reglistpair '/' ireglist
+ {
+ $$ = $1 | $3;
+ }
+ | reglistreg '/' ireglist
+ {
+ $$ = (1 << $1) | $3;
+ }
+ ;
+
+reglistpair:
+ reglistreg '-' reglistreg
+ {
+ if ($1 <= $3)
+ $$ = (1 << ($3 + 1)) - 1 - ((1 << $1) - 1);
+ else
+ $$ = (1 << ($1 + 1)) - 1 - ((1 << $3) - 1);
+ }
+ ;
+
+reglistreg:
+ DR
+ {
+ $$ = $1 - DATA0;
+ }
+ | AR
+ {
+ $$ = $1 - ADDR0 + 8;
+ }
+ | FPR
+ {
+ $$ = $1 - FP0 + 16;
+ }
+ | FPCR
+ {
+ if ($1 == FPI)
+ $$ = 24;
+ else if ($1 == FPS)
+ $$ = 25;
+ else
+ $$ = 26;
+ }
+ ;
+
+%%
+
+/* The string to parse is stored here, and modified by yylex. */
+
+static char *str;
+
+/* The original string pointer. */
+
+static char *strorig;
+
+/* If *CCP could be a register, return the register number and advance
+ *CCP. Otherwise don't change *CCP, and return 0. */
+
+static enum m68k_register
+m68k_reg_parse (ccp)
+ register char **ccp;
+{
+ char *start = *ccp;
+ char c;
+ char *p;
+ symbolS *symbolp;
+
+ if (flag_reg_prefix_optional)
+ {
+ if (*start == REGISTER_PREFIX)
+ start++;
+ p = start;
+ }
+ else
+ {
+ if (*start != REGISTER_PREFIX)
+ return 0;
+ p = start + 1;
+ }
+
+ if (! is_name_beginner (*p))
+ return 0;
+
+ p++;
+ while (is_part_of_name (*p) && *p != '.' && *p != ':' && *p != '*')
+ p++;
+
+ c = *p;
+ *p = 0;
+ symbolp = symbol_find (start);
+ *p = c;
+
+ if (symbolp != NULL && S_GET_SEGMENT (symbolp) == reg_section)
+ {
+ *ccp = p;
+ return S_GET_VALUE (symbolp);
+ }
+
+ /* In MRI mode, something like foo.bar can be equated to a register
+ name. */
+ while (flag_mri && c == '.')
+ {
+ ++p;
+ while (is_part_of_name (*p) && *p != '.' && *p != ':' && *p != '*')
+ p++;
+ c = *p;
+ *p = '\0';
+ symbolp = symbol_find (start);
+ *p = c;
+ if (symbolp != NULL && S_GET_SEGMENT (symbolp) == reg_section)
+ {
+ *ccp = p;
+ return S_GET_VALUE (symbolp);
+ }
+ }
+
+ return 0;
+}
+
+/* The lexer. */
+
+static int
+yylex ()
+{
+ enum m68k_register reg;
+ char *s;
+ int parens;
+ int c = 0;
+ int tail = 0;
+ char *hold;
+
+ if (*str == ' ')
+ ++str;
+
+ if (*str == '\0')
+ return 0;
+
+ /* Various special characters are just returned directly. */
+ switch (*str)
+ {
+ case '@':
+ /* In MRI mode, this can be the start of an octal number. */
+ if (flag_mri)
+ {
+ if (isdigit (str[1])
+ || ((str[1] == '+' || str[1] == '-')
+ && isdigit (str[2])))
+ break;
+ }
+ /* Fall through. */
+ case '#':
+ case '&':
+ case ',':
+ case ')':
+ case '/':
+ case '[':
+ case ']':
+ return *str++;
+ case '+':
+ /* It so happens that a '+' can only appear at the end of an
+ operand. If it appears anywhere else, it must be a unary
+ plus on an expression. */
+ if (str[1] == '\0')
+ return *str++;
+ break;
+ case '-':
+ /* A '-' can only appear in -(ar), rn-rn, or ar@-. If it
+ appears anywhere else, it must be a unary minus on an
+ expression. */
+ if (str[1] == '\0')
+ return *str++;
+ s = str + 1;
+ if (*s == '(')
+ ++s;
+ if (m68k_reg_parse (&s) != 0)
+ return *str++;
+ break;
+ case '(':
+ /* A '(' can only appear in `(reg)', `(expr,...', `([', `@(', or
+ `)('. If it appears anywhere else, it must be starting an
+ expression. */
+ if (str[1] == '['
+ || (str > strorig
+ && (str[-1] == '@'
+ || str[-1] == ')')))
+ return *str++;
+ s = str + 1;
+ if (m68k_reg_parse (&s) != 0)
+ return *str++;
+ /* Check for the case of '(expr,...' by scanning ahead. If we
+ find a comma outside of balanced parentheses, we return '('.
+ If we find an unbalanced right parenthesis, then presumably
+ the '(' really starts an expression. */
+ parens = 0;
+ for (s = str + 1; *s != '\0'; s++)
+ {
+ if (*s == '(')
+ ++parens;
+ else if (*s == ')')
+ {
+ if (parens == 0)
+ break;
+ --parens;
+ }
+ else if (*s == ',' && parens == 0)
+ {
+ /* A comma can not normally appear in an expression, so
+ this is a case of '(expr,...'. */
+ return *str++;
+ }
+ }
+ }
+
+ /* See if it's a register. */
+
+ reg = m68k_reg_parse (&str);
+ if (reg != 0)
+ {
+ int ret;
+
+ yylval.reg = reg;
+
+ if (reg >= DATA0 && reg <= DATA7)
+ ret = DR;
+ else if (reg >= ADDR0 && reg <= ADDR7)
+ ret = AR;
+ else if (reg >= FP0 && reg <= FP7)
+ return FPR;
+ else if (reg == FPI
+ || reg == FPS
+ || reg == FPC)
+ return FPCR;
+ else if (reg == PC)
+ return LPC;
+ else if (reg >= ZDATA0 && reg <= ZDATA7)
+ ret = ZDR;
+ else if (reg >= ZADDR0 && reg <= ZADDR7)
+ ret = ZAR;
+ else if (reg == ZPC)
+ return LZPC;
+ else
+ return CREG;
+
+ /* If we get here, we have a data or address register. We
+ must check for a size or scale; if we find one, we must
+ return INDEXREG. */
+
+ s = str;
+
+ if (*s != '.' && *s != ':' && *s != '*')
+ return ret;
+
+ yylval.indexreg.reg = reg;
+
+ if (*s != '.' && *s != ':')
+ yylval.indexreg.size = SIZE_UNSPEC;
+ else
+ {
+ ++s;
+ switch (*s)
+ {
+ case 'w':
+ case 'W':
+ yylval.indexreg.size = SIZE_WORD;
+ ++s;
+ break;
+ case 'l':
+ case 'L':
+ yylval.indexreg.size = SIZE_LONG;
+ ++s;
+ break;
+ default:
+ yyerror (_("illegal size specification"));
+ yylval.indexreg.size = SIZE_UNSPEC;
+ break;
+ }
+ }
+
+ yylval.indexreg.scale = 1;
+
+ if (*s == '*' || *s == ':')
+ {
+ expressionS scale;
+
+ ++s;
+
+ hold = input_line_pointer;
+ input_line_pointer = s;
+ expression (&scale);
+ s = input_line_pointer;
+ input_line_pointer = hold;
+
+ if (scale.X_op != O_constant)
+ yyerror (_("scale specification must resolve to a number"));
+ else
+ {
+ switch (scale.X_add_number)
+ {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ yylval.indexreg.scale = scale.X_add_number;
+ break;
+ default:
+ yyerror (_("invalid scale value"));
+ break;
+ }
+ }
+ }
+
+ str = s;
+
+ return INDEXREG;
+ }
+
+ /* It must be an expression. Before we call expression, we need to
+ look ahead to see if there is a size specification. We must do
+ that first, because otherwise foo.l will be treated as the symbol
+ foo.l, rather than as the symbol foo with a long size
+ specification. The grammar requires that all expressions end at
+ the end of the operand, or with ',', '(', ']', ')'. */
+
+ parens = 0;
+ for (s = str; *s != '\0'; s++)
+ {
+ if (*s == '(')
+ {
+ if (parens == 0
+ && s > str
+ && (s[-1] == ')' || isalnum ((unsigned char) s[-1])))
+ break;
+ ++parens;
+ }
+ else if (*s == ')')
+ {
+ if (parens == 0)
+ break;
+ --parens;
+ }
+ else if (parens == 0
+ && (*s == ',' || *s == ']'))
+ break;
+ }
+
+ yylval.exp.size = SIZE_UNSPEC;
+ if (s <= str + 2
+ || (s[-2] != '.' && s[-2] != ':'))
+ tail = 0;
+ else
+ {
+ switch (s[-1])
+ {
+ case 's':
+ case 'S':
+ case 'b':
+ case 'B':
+ yylval.exp.size = SIZE_BYTE;
+ break;
+ case 'w':
+ case 'W':
+ yylval.exp.size = SIZE_WORD;
+ break;
+ case 'l':
+ case 'L':
+ yylval.exp.size = SIZE_LONG;
+ break;
+ default:
+ break;
+ }
+ if (yylval.exp.size != SIZE_UNSPEC)
+ tail = 2;
+ }
+
+#ifdef OBJ_ELF
+ {
+ /* Look for @PLTPC, etc. */
+ char *cp;
+
+ yylval.exp.pic_reloc = pic_none;
+ cp = s - tail;
+ if (cp - 6 > str && cp[-6] == '@')
+ {
+ if (strncmp (cp - 6, "@PLTPC", 6) == 0)
+ {
+ yylval.exp.pic_reloc = pic_plt_pcrel;
+ tail += 6;
+ }
+ else if (strncmp (cp - 6, "@GOTPC", 6) == 0)
+ {
+ yylval.exp.pic_reloc = pic_got_pcrel;
+ tail += 6;
+ }
+ }
+ else if (cp - 4 > str && cp[-4] == '@')
+ {
+ if (strncmp (cp - 4, "@PLT", 4) == 0)
+ {
+ yylval.exp.pic_reloc = pic_plt_off;
+ tail += 4;
+ }
+ else if (strncmp (cp - 4, "@GOT", 4) == 0)
+ {
+ yylval.exp.pic_reloc = pic_got_off;
+ tail += 4;
+ }
+ }
+ }
+#endif
+
+ if (tail != 0)
+ {
+ c = s[-tail];
+ s[-tail] = 0;
+ }
+
+ hold = input_line_pointer;
+ input_line_pointer = str;
+ expression (&yylval.exp.exp);
+ str = input_line_pointer;
+ input_line_pointer = hold;
+
+ if (tail != 0)
+ {
+ s[-tail] = c;
+ str = s;
+ }
+
+ return EXPR;
+}
+
+/* Parse an m68k operand. This is the only function which is called
+ from outside this file. */
+
+int
+m68k_ip_op (s, oparg)
+ char *s;
+ struct m68k_op *oparg;
+{
+ memset (oparg, 0, sizeof *oparg);
+ oparg->error = NULL;
+ oparg->index.reg = ZDATA0;
+ oparg->index.scale = 1;
+ oparg->disp.exp.X_op = O_absent;
+ oparg->odisp.exp.X_op = O_absent;
+
+ str = strorig = s;
+ op = oparg;
+
+ return yyparse ();
+}
+
+/* The error handler. */
+
+static void
+yyerror (s)
+ const char *s;
+{
+ op->error = s;
+}
diff --git a/gas/config/m88k-opcode.h b/gas/config/m88k-opcode.h
new file mode 100644
index 0000000000..27464bc0fc
--- /dev/null
+++ b/gas/config/m88k-opcode.h
@@ -0,0 +1,559 @@
+/* m88k-opcode.h -- Instruction information for the Motorola 88000
+ Contributed by Devon Bowen of Buffalo University
+ and Torbjorn Granlund of the Swedish Institute of Computer Science.
+ Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GAS 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 more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined(__STDC__) && !defined(const)
+#define const
+#endif
+
+/*
+ Character codes for op_spec field below.
+ Reserved for self-matching: [ ] ,
+
+ d = GRF Destination register (21:5)
+ x = XRF register prefix. Makes next d, 1, or 2, match an extended register.
+ 1 = Source register 1 (16:5)
+ 2 = Source register 2 (0:5)
+ 3 = Both source registers (same value) (0:5 and 16:5)
+ I = IMM16 (0:16)
+ b = bit field spec. (0:10)
+ p = 16 bit pc displ. (0:16)
+ P = 26 bit pc displ. (0:26)
+ B = bb0/bb1 condition (21:5)
+ M = bcnd condition (21:5)
+ f = fcr (5:6)
+ c = cr (5:6)
+ V = VEC9 (0:9)
+ o = O6 field of "prot" insn (10:7)
+ ? = Give warning for this insn/operand combination
+ */
+
+/* instruction descriptor structure */
+
+struct m88k_opcode
+{
+ unsigned int opcode;
+ char *name;
+ char *op_spec;
+};
+
+/* and introducing... the Motorola 88100 and 88110 instruction sets... */
+
+/* By default, include the 88110 instructions. */
+#define MC88110
+
+#if defined (MC88110)
+#define _MC88100(OPCODE,MNEM,OP_SPEC)
+#define _MC88110(OPCODE,MNEM,OP_SPEC) {OPCODE,MNEM,OP_SPEC},
+#else
+#define _MC88100(OPCODE,MNEM,OP_SPEC) {OPCODE,MNEM,OP_SPEC},
+#define _MC88110(OPCODE,MNEM,OP_SPEC)
+#endif
+
+#define _MC88xxx(OPCODE,MNEM,OP_SPEC) {OPCODE,MNEM,OP_SPEC},
+
+/* Equal mnemonics must be adjacent.
+ More specific operand specification must go before more general.
+ For example, "d,1,2" must go before "d,1,I" as a register for s2
+ would otherwise be considered a variable name. */
+
+static struct m88k_opcode m88k_opcodes[] =
+{
+ /* Opcode Mnemonic Opspec */
+
+ _MC88xxx (0xf4007000, "add", "d,1,2")
+ _MC88xxx (0x70000000, "add", "d,1,I")
+ _MC88xxx (0xf4007200, "add.ci", "d,1,2")
+ _MC88xxx (0xf4007300, "add.cio", "d,1,2")
+ _MC88xxx (0xf4007100, "add.co", "d,1,2")
+ _MC88xxx (0xf4006000, "addu", "d,1,2")
+ _MC88xxx (0x60000000, "addu", "d,1,I")
+ _MC88xxx (0xf4006200, "addu.ci", "d,1,2")
+ _MC88xxx (0xf4006300, "addu.cio", "d,1,2")
+ _MC88xxx (0xf4006100, "addu.co", "d,1,2")
+ _MC88xxx (0xf4004000, "and", "d,1,2")
+ _MC88xxx (0x40000000, "and", "d,1,I")
+ _MC88xxx (0xf4004400, "and.c", "d,1,2")
+ _MC88xxx (0x44000000, "and.u", "d,1,I")
+ _MC88xxx (0xd0000000, "bb0", "B,1,p")
+ _MC88xxx (0xd4000000, "bb0.n", "B,1,p")
+ _MC88xxx (0xd8000000, "bb1", "B,1,p")
+ _MC88xxx (0xdc000000, "bb1.n", "B,1,p")
+ _MC88xxx (0xe8000000, "bcnd", "M,1,p")
+ _MC88xxx (0xec000000, "bcnd.n", "M,1,p")
+ _MC88xxx (0xc0000000, "br", "P")
+ _MC88xxx (0xc4000000, "br.n", "P")
+ _MC88xxx (0xc8000000, "bsr", "P")
+ _MC88xxx (0xcc000000, "bsr.n", "P")
+ _MC88xxx (0xf4008000, "clr", "d,1,2")
+ _MC88xxx (0xf0008000, "clr", "d,1,b")
+ _MC88xxx (0xf4007c00, "cmp", "d,1,2")
+ _MC88xxx (0x7c000000, "cmp", "d,1,I")
+ _MC88xxx (0xf4007800, "div", "d,1,2")
+ _MC88xxx (0x78000000, "div", "d,1,I")
+ _MC88xxx (0xf4007800, "divs", "d,1,2")
+ _MC88xxx (0x78000000, "divs", "d,1,I")
+ _MC88110 (0xf4006900, "divu.d", "d,1,2")
+ _MC88xxx (0xf4006800, "divu", "d,1,2")
+ _MC88xxx (0x68000000, "divu", "d,1,I")
+ _MC88xxx (0xf4009000, "ext", "d,1,2")
+ _MC88xxx (0xf0009000, "ext", "d,1,b")
+ _MC88xxx (0xf4009800, "extu", "d,1,2")
+ _MC88xxx (0xf0009800, "extu", "d,1,b")
+ _MC88xxx (0x84002800, "fadd.sss", "d,1,2")
+ _MC88110 (0x8400a800, "fadd.sss", "xd,x1,x2")
+ _MC88xxx (0x84002880, "fadd.ssd", "d,1,2")
+ _MC88110 (0x8400a820, "fadd.ssd", "xd,x1,x2")
+ _MC88110 (0x8400a840, "fadd.ssx", "xd,x1,x2")
+ _MC88xxx (0x84002a00, "fadd.sds", "d,1,2")
+ _MC88110 (0x8400a880, "fadd.sds", "xd,x1,x2")
+ _MC88xxx (0x84002a80, "fadd.sdd", "d,1,2")
+ _MC88110 (0x8400a8a0, "fadd.sdd", "xd,x1,x2")
+ _MC88110 (0x8400a8c0, "fadd.sdx", "xd,x1,x2")
+ _MC88110 (0x8400a900, "fadd.sxs", "xd,x1,x2")
+ _MC88110 (0x8400a920, "fadd.sxd", "xd,x1,x2")
+ _MC88110 (0x8400a940, "fadd.sxx", "xd,x1,x2")
+ _MC88xxx (0x84002820, "fadd.dss", "d,1,2")
+ _MC88110 (0x8400aa00, "fadd.dss", "xd,x1,x2")
+ _MC88xxx (0x840028a0, "fadd.dsd", "d,1,2")
+ _MC88110 (0x8400aa20, "fadd.dsd", "xd,x1,x2")
+ _MC88110 (0x8400aa40, "fadd.dsx", "xd,x1,x2")
+ _MC88xxx (0x84002a20, "fadd.dds", "d,1,2")
+ _MC88110 (0x8400aa80, "fadd.dds", "xd,x1,x2")
+ _MC88xxx (0x84002aa0, "fadd.ddd", "d,1,2")
+ _MC88110 (0x8400aaa0, "fadd.ddd", "xd,x1,x2")
+ _MC88110 (0x8400aac0, "fadd.ddx", "xd,x1,x2")
+ _MC88110 (0x8400ab00, "fadd.dxs", "xd,x1,x2")
+ _MC88110 (0x8400ab20, "fadd.dxd", "xd,x1,x2")
+ _MC88110 (0x8400ab40, "fadd.dxx", "xd,x1,x2")
+ _MC88110 (0x8400ac00, "fadd.xss", "xd,x1,x2")
+ _MC88110 (0x8400ac20, "fadd.xsd", "xd,x1,x2")
+ _MC88110 (0x8400ac40, "fadd.xsx", "xd,x1,x2")
+ _MC88110 (0x8400ac80, "fadd.xds", "xd,x1,x2")
+ _MC88110 (0x8400aca0, "fadd.xdd", "xd,x1,x2")
+ _MC88110 (0x8400acc0, "fadd.xdx", "xd,x1,x2")
+ _MC88110 (0x8400ad00, "fadd.xxs", "xd,x1,x2")
+ _MC88110 (0x8400ad20, "fadd.xxd", "xd,x1,x2")
+ _MC88110 (0x8400ad40, "fadd.xxx", "xd,x1,x2")
+ _MC88xxx (0x84003a80, "fcmp.sdd", "d,1,2")
+ _MC88110 (0x8400ba80, "fcmp.sdd", "d,x1,x2")
+ _MC88xxx (0x84003a00, "fcmp.sds", "d,1,2")
+ _MC88110 (0x8400ba00, "fcmp.sds", "d,x1,x2")
+ _MC88110 (0x8400bb00, "fcmp.sdx", "d,x1,x2")
+ _MC88xxx (0x84003880, "fcmp.ssd", "d,1,2")
+ _MC88110 (0x8400b880, "fcmp.ssd", "d,x1,x2")
+ _MC88xxx (0x84003800, "fcmp.sss", "d,1,2")
+ _MC88110 (0x8400b800, "fcmp.sss", "d,x1,x2")
+ _MC88110 (0x8400b900, "fcmp.ssx", "d,x1,x2")
+ _MC88110 (0x8400bc80, "fcmp.sxd", "d,x1,x2")
+ _MC88110 (0x8400bc00, "fcmp.sxs", "d,x1,x2")
+ _MC88110 (0x8400bd00, "fcmp.sxx", "d,x1,x2")
+ _MC88110 (0x84003aa0, "fcmpu.sdd", "d,1,2")
+ _MC88110 (0x8400baa0, "fcmpu.sdd", "d,x1,x2")
+ _MC88110 (0x84003a20, "fcmpu.sds", "d,1,2")
+ _MC88110 (0x8400ba20, "fcmpu.sds", "d,x1,x2")
+ _MC88110 (0x8400bb20, "fcmpu.sdx", "d,x1,x2")
+ _MC88110 (0x840038a0, "fcmpu.ssd", "d,1,2")
+ _MC88110 (0x8400b8a0, "fcmpu.ssd", "d,x1,x2")
+ _MC88110 (0x84003820, "fcmpu.sss", "d,1,2")
+ _MC88110 (0x8400b820, "fcmpu.sss", "d,x1,x2")
+ _MC88110 (0x8400b920, "fcmpu.ssx", "d,x1,x2")
+ _MC88110 (0x8400bca0, "fcmpu.sxd", "d,x1,x2")
+ _MC88110 (0x8400bc20, "fcmpu.sxs", "d,x1,x2")
+ _MC88110 (0x8400bd20, "fcmpu.sxx", "d,x1,x2")
+ _MC88110 (0x84000880, "fcvt.ds", "d,2")
+ _MC88110 (0x84008880, "fcvt.ds", "xd,x2")
+ _MC88110 (0x840088c0, "fcvt.dx", "xd,x2")
+ _MC88110 (0x84000820, "fcvt.sd", "d,2")
+ _MC88110 (0x84008820, "fcvt.sd", "xd,x2")
+ _MC88110 (0x84008840, "fcvt.sx", "xd,x2")
+ _MC88110 (0x84008920, "fcvt.xd", "xd,x2")
+ _MC88110 (0x84008900, "fcvt.xs", "xd,x2")
+ _MC88xxx (0x84007000, "fdiv.sss", "d,1,2")
+ _MC88110 (0x8400f000, "fdiv.sss", "xd,x1,x2")
+ _MC88xxx (0x84007080, "fdiv.ssd", "d,1,2")
+ _MC88110 (0x8400f020, "fdiv.ssd", "xd,x1,x2")
+ _MC88110 (0x8400f040, "fdiv.ssx", "xd,x1,x2")
+ _MC88xxx (0x84007200, "fdiv.sds", "d,1,2")
+ _MC88110 (0x8400f080, "fdiv.sds", "xd,x1,x2")
+ _MC88xxx (0x84007280, "fdiv.sdd", "d,1,2")
+ _MC88110 (0x8400f0a0, "fdiv.sdd", "xd,x1,x2")
+ _MC88110 (0x8400f0c0, "fdiv.sdx", "xd,x1,x2")
+ _MC88110 (0x8400f100, "fdiv.sxs", "xd,x1,x2")
+ _MC88110 (0x8400f120, "fdiv.sxd", "xd,x1,x2")
+ _MC88110 (0x8400f140, "fdiv.sxx", "xd,x1,x2")
+ _MC88xxx (0x84007020, "fdiv.dss", "d,1,2")
+ _MC88110 (0x8400f200, "fdiv.dss", "xd,x1,x2")
+ _MC88xxx (0x840070a0, "fdiv.dsd", "d,1,2")
+ _MC88110 (0x8400f220, "fdiv.dsd", "xd,x1,x2")
+ _MC88110 (0x8400f240, "fdiv.dsx", "xd,x1,x2")
+ _MC88xxx (0x84007220, "fdiv.dds", "d,1,2")
+ _MC88110 (0x8400f280, "fdiv.dds", "xd,x1,x2")
+ _MC88xxx (0x840072a0, "fdiv.ddd", "d,1,2")
+ _MC88110 (0x8400f2a0, "fdiv.ddd", "xd,x1,x2")
+ _MC88110 (0x8400f2c0, "fdiv.ddx", "xd,x1,x2")
+ _MC88110 (0x8400f300, "fdiv.dxs", "xd,x1,x2")
+ _MC88110 (0x8400f320, "fdiv.dxd", "xd,x1,x2")
+ _MC88110 (0x8400f340, "fdiv.dxx", "xd,x1,x2")
+ _MC88110 (0x8400f400, "fdiv.xss", "xd,x1,x2")
+ _MC88110 (0x8400f420, "fdiv.xsd", "xd,x1,x2")
+ _MC88110 (0x8400f440, "fdiv.xsx", "xd,x1,x2")
+ _MC88110 (0x8400f480, "fdiv.xds", "xd,x1,x2")
+ _MC88110 (0x8400f4a0, "fdiv.xdd", "xd,x1,x2")
+ _MC88110 (0x8400f4c0, "fdiv.xdx", "xd,x1,x2")
+ _MC88110 (0x8400f500, "fdiv.xxs", "xd,x1,x2")
+ _MC88110 (0x8400f520, "fdiv.xxd", "xd,x1,x2")
+ _MC88110 (0x8400f540, "fdiv.xxx", "xd,x1,x2")
+ _MC88xxx (0xf400ec00, "ff0", "d,2")
+ _MC88xxx (0xf400e800, "ff1", "d,2")
+ _MC88xxx (0x80004800, "fldcr", "d,f")
+ _MC88xxx (0x84002020, "flt.ds", "d,2")
+ _MC88110 (0x84002220, "flt.ds", "xd,2")
+ _MC88xxx (0x84002000, "flt.ss", "d,2")
+ _MC88110 (0x84002200, "flt.ss", "xd,2")
+ _MC88110 (0x84002240, "flt.xs", "xd,2")
+ _MC88xxx (0x84000000, "fmul.sss", "d,1,2")
+ _MC88110 (0x84008000, "fmul.sss", "xd,x1,x2")
+ _MC88xxx (0x84000080, "fmul.ssd", "d,1,2")
+ _MC88110 (0x84008020, "fmul.ssd", "xd,x1,x2")
+ _MC88110 (0x84008040, "fmul.ssx", "xd,x1,x2")
+ _MC88xxx (0x84000200, "fmul.sds", "d,1,2")
+ _MC88110 (0x84008080, "fmul.sds", "xd,x1,x2")
+ _MC88xxx (0x84000280, "fmul.sdd", "d,1,2")
+ _MC88110 (0x840080a0, "fmul.sdd", "xd,x1,x2")
+ _MC88110 (0x840080c0, "fmul.sdx", "xd,x1,x2")
+ _MC88110 (0x84008100, "fmul.sxs", "xd,x1,x2")
+ _MC88110 (0x84008120, "fmul.sxd", "xd,x1,x2")
+ _MC88110 (0x84008140, "fmul.sxx", "xd,x1,x2")
+ _MC88xxx (0x84000020, "fmul.dss", "d,1,2")
+ _MC88110 (0x84008200, "fmul.dss", "xd,x1,x2")
+ _MC88xxx (0x840000a0, "fmul.dsd", "d,1,2")
+ _MC88110 (0x84008220, "fmul.dsd", "xd,x1,x2")
+ _MC88110 (0x84008240, "fmul.dsx", "xd,x1,x2")
+ _MC88xxx (0x84000220, "fmul.dds", "d,1,2")
+ _MC88110 (0x84008280, "fmul.dds", "xd,x1,x2")
+ _MC88xxx (0x840002a0, "fmul.ddd", "d,1,2")
+ _MC88110 (0x840082a0, "fmul.ddd", "xd,x1,x2")
+ _MC88110 (0x840082c0, "fmul.ddx", "xd,x1,x2")
+ _MC88110 (0x84008300, "fmul.dxs", "xd,x1,x2")
+ _MC88110 (0x84008320, "fmul.dxd", "xd,x1,x2")
+ _MC88110 (0x84008340, "fmul.dxx", "xd,x1,x2")
+ _MC88110 (0x84008400, "fmul.xss", "xd,x1,x2")
+ _MC88110 (0x84008420, "fmul.xsd", "xd,x1,x2")
+ _MC88110 (0x84008440, "fmul.xsx", "xd,x1,x2")
+ _MC88110 (0x84008480, "fmul.xds", "xd,x1,x2")
+ _MC88110 (0x840084a0, "fmul.xdd", "xd,x1,x2")
+ _MC88110 (0x840084c0, "fmul.xdx", "xd,x1,x2")
+ _MC88110 (0x84008500, "fmul.xxs", "xd,x1,x2")
+ _MC88110 (0x84008520, "fmul.xxd", "xd,x1,x2")
+ _MC88110 (0x84008540, "fmul.xxx", "xd,x1,x2")
+ _MC88110 (0x840078a0, "fsqrt.dd", "d,2")
+ _MC88110 (0x8400f8a0, "fsqrt.dd", "xd,x2")
+ _MC88110 (0x84007880, "fsqrt.ds", "d,2")
+ _MC88110 (0x8400f880, "fsqrt.ds", "xd,x2")
+ _MC88110 (0x8400f8c0, "fsqrt.dx", "xd,x2")
+ _MC88110 (0x84007820, "fsqrt.sd", "d,2")
+ _MC88110 (0x8400f820, "fsqrt.sd", "xd,x2")
+ _MC88110 (0x84007800, "fsqrt.ss", "d,2")
+ _MC88110 (0x8400f800, "fsqrt.ss", "xd,x2")
+ _MC88110 (0x8400f840, "fsqrt.sx", "xd,x2")
+ _MC88110 (0x8400f920, "fsqrt.xd", "xd,x2")
+ _MC88110 (0x8400f900, "fsqrt.xs", "xd,x2")
+ _MC88110 (0x8400f940, "fsqrt.xx", "xd,x2")
+ _MC88xxx (0x80008800, "fstcr", "3,f")
+ _MC88xxx (0x84003000, "fsub.sss", "d,1,2")
+ _MC88110 (0x8400b000, "fsub.sss", "xd,x1,x2")
+ _MC88xxx (0x84003080, "fsub.ssd", "d,1,2")
+ _MC88110 (0x8400b020, "fsub.ssd", "xd,x1,x2")
+ _MC88110 (0x8400b040, "fsub.ssx", "xd,x1,x2")
+ _MC88xxx (0x84003200, "fsub.sds", "d,1,2")
+ _MC88110 (0x8400b080, "fsub.sds", "xd,x1,x2")
+ _MC88xxx (0x84003280, "fsub.sdd", "d,1,2")
+ _MC88110 (0x8400b0a0, "fsub.sdd", "xd,x1,x2")
+ _MC88110 (0x8400b0c0, "fsub.sdx", "xd,x1,x2")
+ _MC88110 (0x8400b100, "fsub.sxs", "xd,x1,x2")
+ _MC88110 (0x8400b120, "fsub.sxd", "xd,x1,x2")
+ _MC88110 (0x8400b140, "fsub.sxx", "xd,x1,x2")
+ _MC88xxx (0x84003020, "fsub.dss", "d,1,2")
+ _MC88110 (0x8400b200, "fsub.dss", "xd,x1,x2")
+ _MC88xxx (0x840030a0, "fsub.dsd", "d,1,2")
+ _MC88110 (0x8400b220, "fsub.dsd", "xd,x1,x2")
+ _MC88110 (0x8400b240, "fsub.dsx", "xd,x1,x2")
+ _MC88xxx (0x84003220, "fsub.dds", "d,1,2")
+ _MC88110 (0x8400b280, "fsub.dds", "xd,x1,x2")
+ _MC88xxx (0x840032a0, "fsub.ddd", "d,1,2")
+ _MC88110 (0x8400b2a0, "fsub.ddd", "xd,x1,x2")
+ _MC88110 (0x8400b2c0, "fsub.ddx", "xd,x1,x2")
+ _MC88110 (0x8400b300, "fsub.dxs", "xd,x1,x2")
+ _MC88110 (0x8400b320, "fsub.dxd", "xd,x1,x2")
+ _MC88110 (0x8400b340, "fsub.dxx", "xd,x1,x2")
+ _MC88110 (0x8400b400, "fsub.xss", "xd,x1,x2")
+ _MC88110 (0x8400b420, "fsub.xsd", "xd,x1,x2")
+ _MC88110 (0x8400b440, "fsub.xsx", "xd,x1,x2")
+ _MC88110 (0x8400b480, "fsub.xds", "xd,x1,x2")
+ _MC88110 (0x8400b4a0, "fsub.xdd", "xd,x1,x2")
+ _MC88110 (0x8400b4c0, "fsub.xdx", "xd,x1,x2")
+ _MC88110 (0x8400b500, "fsub.xxs", "xd,x1,x2")
+ _MC88110 (0x8400b520, "fsub.xxd", "xd,x1,x2")
+ _MC88110 (0x8400b540, "fsub.xxx", "xd,x1,x2")
+ _MC88xxx (0x8000c800, "fxcr", "d,3,f")
+ _MC88xxx (0x8400fc01, "illop1", "")
+ _MC88xxx (0x8400fc02, "illop2", "")
+ _MC88xxx (0x8400fc03, "illop3", "")
+ _MC88xxx (0x84004880, "int.sd", "d,2")
+ _MC88110 (0x8400c880, "int.sd", "d,x2")
+ _MC88xxx (0x84004800, "int.ss", "d,2")
+ _MC88110 (0x8400c800, "int.ss", "d,x2")
+ _MC88110 (0x8400c900, "int.sx", "d,x2")
+ _MC88xxx (0xf400c000, "jmp", "2")
+ _MC88xxx (0xf400c400, "jmp.n", "2")
+ _MC88xxx (0xf400c800, "jsr", "2")
+ _MC88xxx (0xf400cc00, "jsr.n", "2")
+ _MC88xxx (0xf4001400, "ld", "d,1,2")
+ _MC88xxx (0xf4001600, "ld", "d,1[2]")
+ _MC88xxx (0x14000000, "ld", "d,1,I")
+ _MC88110 (0xf0001600, "ld", "xd,1[2]")
+ _MC88110 (0xf0001400, "ld", "xd,1,2")
+ _MC88110 (0x04000000, "ld", "xd,1,I")
+ _MC88xxx (0xf4001e00, "ld.b", "d,1[2]")
+ _MC88xxx (0xf4001c00, "ld.b", "d,1,2")
+ _MC88xxx (0x1c000000, "ld.b", "d,1,I")
+ _MC88xxx (0xf4001d00, "ld.b.usr", "d,1,2")
+ _MC88xxx (0xf4001f00, "ld.b.usr", "d,1[2]")
+ _MC88xxx (0xf4000e00, "ld.bu", "d,1[2]")
+ _MC88xxx (0xf4000c00, "ld.bu", "d,1,2")
+ _MC88xxx (0x0c000000, "ld.bu", "d,1,I")
+ _MC88xxx (0xf4000d00, "ld.bu.usr", "d,1,2")
+ _MC88xxx (0xf4000f00, "ld.bu.usr", "d,1[2]")
+ _MC88xxx (0xf4001200, "ld.d", "d,1[2]")
+ _MC88xxx (0xf4001000, "ld.d", "d,1,2")
+ _MC88xxx (0x10000000, "ld.d", "d,1,I")
+ _MC88110 (0xf0001200, "ld.d", "xd,1[2]")
+ _MC88110 (0xf0001000, "ld.d", "xd,1,2")
+ _MC88110 (0x00000000, "ld.d", "xd,1,I")
+ _MC88xxx (0xf4001100, "ld.d.usr", "d,1,2")
+ _MC88xxx (0xf4001300, "ld.d.usr", "d,1[2]")
+ _MC88110 (0xf0001100, "ld.d.usr", "xd,1,2")
+ _MC88110 (0xf0001300, "ld.d.usr", "xd,1[2]")
+ _MC88xxx (0xf4001a00, "ld.h", "d,1[2]")
+ _MC88xxx (0xf4001800, "ld.h", "d,1,2")
+ _MC88xxx (0x18000000, "ld.h", "d,1,I")
+ _MC88xxx (0xf4001900, "ld.h.usr", "d,1,2")
+ _MC88xxx (0xf4001b00, "ld.h.usr", "d,1[2]")
+ _MC88xxx (0xf4000a00, "ld.hu", "d,1[2]")
+ _MC88xxx (0xf4000800, "ld.hu", "d,1,2")
+ _MC88xxx (0x08000000, "ld.hu", "d,1,I")
+ _MC88xxx (0xf4000900, "ld.hu.usr", "d,1,2")
+ _MC88xxx (0xf4000b00, "ld.hu.usr", "d,1[2]")
+ _MC88xxx (0xf4001500, "ld.usr", "d,1,2")
+ _MC88xxx (0xf4001700, "ld.usr", "d,1[2]")
+ _MC88110 (0xf0001500, "ld.usr", "xd,1,2")
+ _MC88110 (0xf0001700, "ld.usr", "xd,1[2]")
+ _MC88110 (0xf0001a00, "ld.x", "xd,1[2]")
+ _MC88110 (0xf0001800, "ld.x", "xd,1,2")
+ _MC88110 (0x3c000000, "ld.x", "xd,1,I")
+ _MC88110 (0xf0001900, "ld.x.usr", "xd,1,2")
+ _MC88110 (0xf0001b00, "ld.x.usr", "xd,1[2]")
+ _MC88xxx (0xf4003600, "lda", "d,1[2]")
+ _MC88xxx (0xf4006000, "lda", "?d,1,2") /* Output addu */
+ _MC88xxx (0x60000000, "lda", "?d,1,I") /* Output addu */
+ _MC88xxx (0xf4006000, "lda.b", "?d,1[2]") /* Output addu */
+ _MC88xxx (0xf4006000, "lda.b", "?d,1,2") /* Output addu */
+ _MC88xxx (0x60000000, "lda.b", "?d,1,I") /* Output addu */
+ _MC88xxx (0xf4003200, "lda.d", "d,1[2]")
+ _MC88xxx (0xf4006000, "lda.d", "?d,1,2") /* Output addu */
+ _MC88xxx (0x60000000, "lda.d", "?d,1,I") /* Output addu */
+ _MC88110 (0xf4003e00, "lda.x", "d,1[2]")
+ _MC88xxx (0xf4003a00, "lda.h", "d,1[2]")
+ _MC88xxx (0xf4006000, "lda.h", "?d,1,2") /* Output addu */
+ _MC88xxx (0x60000000, "lda.h", "?d,1,I") /* Output addu */
+ _MC88xxx (0x80004000, "ldcr", "d,c")
+ _MC88xxx (0xf400a000, "mak", "d,1,2")
+ _MC88xxx (0xf000a000, "mak", "d,1,b")
+ _MC88xxx (0x48000000, "mask", "d,1,I")
+ _MC88xxx (0x4c000000, "mask.u", "d,1,I")
+ _MC88110 (0x8400c000, "mov.s", "d,x2")
+ _MC88110 (0x84004200, "mov.s", "xd,2")
+ _MC88110 (0x8400c080, "mov.d", "d,x2")
+ _MC88110 (0x84004280, "mov.d", "xd,2")
+ _MC88110 (0x8400c300, "mov", "xd,x2")
+ _MC88xxx (0xf4006c00, "mul", "d,1,2")
+ _MC88xxx (0x6c000000, "mul", "d,1,I")
+ _MC88xxx (0xf4006e00, "muls", "d,1,2")
+ _MC88xxx (0x6c000000, "muls", "d,1,I")
+ _MC88xxx (0xf4006c00, "mulu", "d,1,2") /* synonym for mul */
+ _MC88xxx (0x6c000000, "mulu", "d,1,I") /* synonym for mul */
+ _MC88110 (0xf4006d00, "mulu.d", "d,1,2")
+ _MC88xxx (0x84005080, "nint.sd", "d,2")
+ _MC88110 (0x8400d080, "nint.sd", "d,x2")
+ _MC88xxx (0x84005000, "nint.ss", "d,2")
+ _MC88110 (0x8400d000, "nint.ss", "d,x2")
+ _MC88110 (0x8400d100, "nint.sx", "d,x2")
+ _MC88xxx (0xf4005800, "or", "d,1,2")
+ _MC88xxx (0x58000000, "or", "d,1,I")
+ _MC88xxx (0xf4005c00, "or.c", "d,1,2")
+ _MC88xxx (0x5c000000, "or.u", "d,1,I")
+ _MC88110 (0x88002020, "padd.b", "d,1,2")
+ _MC88110 (0x88002040, "padd.h", "d,1,2")
+ _MC88110 (0x88002060, "padd", "d,1,2")
+ _MC88110 (0x880020a0, "padds.u.b", "d,1,2")
+ _MC88110 (0x880020c0, "padds.u.h", "d,1,2")
+ _MC88110 (0x880020e0, "padds.u", "d,1,2")
+ _MC88110 (0x88002120, "padds.us.b", "d,1,2")
+ _MC88110 (0x88002140, "padds.us.h", "d,1,2")
+ _MC88110 (0x88002160, "padds.us", "d,1,2")
+ _MC88110 (0x880021a0, "padds.s.b", "d,1,2")
+ _MC88110 (0x880021c0, "padds.s.h", "d,1,2")
+ _MC88110 (0x880021e0, "padds.s", "d,1,2")
+ _MC88110 (0x88003860, "pcmp", "d,1,2")
+ _MC88110 (0x88000000, "pmul", "d,1,2")
+ _MC88110 (0x88006420, "ppack.32.b", "d,1,2")
+ _MC88110 (0x88006240, "ppack.16.h", "d,1,2")
+ _MC88110 (0x88006440, "ppack.32.h", "d,1,2")
+ _MC88110 (0x88006160, "ppack.8", "d,1,2")
+ _MC88110 (0x88006260, "ppack.16", "d,1,2")
+ _MC88110 (0x88006460, "ppack.32", "d,1,2")
+ _MC88110 (0x88007800, "prot", "d,1,2")
+ _MC88110 (0x88007000, "prot", "d,1,o")
+ _MC88110 (0x88003020, "psub.b", "d,1,2")
+ _MC88110 (0x88003040, "psub.h", "d,1,2")
+ _MC88110 (0x88003060, "psub", "d,1,2")
+ _MC88110 (0x880030a0, "psubs.u.b", "d,1,2")
+ _MC88110 (0x880030c0, "psubs.u.h", "d,1,2")
+ _MC88110 (0x880030e0, "psubs.u", "d,1,2")
+ _MC88110 (0x88003120, "psubs.us.b", "d,1,2")
+ _MC88110 (0x88003140, "psubs.us.h", "d,1,2")
+ _MC88110 (0x88003160, "psubs.us", "d,1,2")
+ _MC88110 (0x880031a0, "psubs.s.b", "d,1,2")
+ _MC88110 (0x880031c0, "psubs.s.h", "d,1,2")
+ _MC88110 (0x880031e0, "psubs.s", "d,1,2")
+ _MC88110 (0x88006800, "punpk.n", "d,1")
+ _MC88110 (0x88006820, "punpk.b", "d,1")
+ _MC88110 (0x88006840, "punpk.h", "d,1")
+ _MC88xxx (0xf400a800, "rot", "d,1,2")
+ _MC88xxx (0xf000a800, "rot", "d,1,b")
+ _MC88xxx (0xf400fc00, "rte", "")
+ _MC88xxx (0xf4008800, "set", "d,1,2")
+ _MC88xxx (0xf0008800, "set", "d,1,b")
+ _MC88xxx (0xf4002600, "st", "d,1[2]")
+ _MC88xxx (0xf4002400, "st", "d,1,2")
+ _MC88xxx (0x24000000, "st", "d,1,I")
+ _MC88110 (0xf0002600, "st", "xd,1[2]")
+ _MC88110 (0xf0002400, "st", "xd,1,2")
+ _MC88110 (0x34000000, "st", "xd,1,I")
+ _MC88xxx (0xf4002e00, "st.b", "d,1[2]")
+ _MC88xxx (0xf4002c00, "st.b", "d,1,2")
+ _MC88xxx (0x2c000000, "st.b", "d,1,I")
+ _MC88xxx (0xf4002d00, "st.b.usr", "d,1,2")
+ _MC88xxx (0xf4002f00, "st.b.usr", "d,1[2]")
+ _MC88110 (0xf4002d80, "st.b.usr.wt", "d,1,2")
+ _MC88110 (0xf4002f80, "st.b.usr.wt", "d,1[2]")
+ _MC88110 (0xf4002c80, "st.b.wt", "d,1,2")
+ _MC88110 (0xf4002e80, "st.b.wt", "d,1[2]")
+ _MC88xxx (0xf4002200, "st.d", "d,1[2]")
+ _MC88xxx (0xf4002000, "st.d", "d,1,2")
+ _MC88xxx (0x20000000, "st.d", "d,1,I")
+ _MC88110 (0xf0002200, "st.d", "xd,1[2]")
+ _MC88110 (0xf0002000, "st.d", "xd,1,2")
+ _MC88110 (0x30000000, "st.d", "xd,1,I")
+ _MC88xxx (0xf4002100, "st.d.usr", "d,1,2")
+ _MC88xxx (0xf4002300, "st.d.usr", "d,1[2]")
+ _MC88110 (0xf0002100, "st.d.usr", "xd,1,2")
+ _MC88110 (0xf0002300, "st.d.usr", "xd,1[2]")
+ _MC88110 (0xf4002180, "st.d.usr.wt", "d,1,2")
+ _MC88110 (0xf4002380, "st.d.usr.wt", "d,1[2]")
+ _MC88110 (0xf0002180, "st.d.usr.wt", "xd,1,2")
+ _MC88110 (0xf0002380, "st.d.usr.wt", "xd,1[2]")
+ _MC88110 (0xf4002080, "st.d.wt", "d,1,2")
+ _MC88110 (0xf4002280, "st.d.wt", "d,1[2]")
+ _MC88110 (0xf0002080, "st.d.wt", "xd,1,2")
+ _MC88110 (0xf0002280, "st.d.wt", "xd,1[2]")
+ _MC88xxx (0xf4002a00, "st.h", "d,1[2]")
+ _MC88xxx (0xf4002800, "st.h", "d,1,2")
+ _MC88xxx (0x28000000, "st.h", "d,1,I")
+ _MC88xxx (0xf4002900, "st.h.usr", "d,1,2")
+ _MC88xxx (0xf4002b00, "st.h.usr", "d,1[2]")
+ _MC88110 (0xf4002980, "st.h.usr.wt", "d,1,2")
+ _MC88110 (0xf4002b80, "st.h.usr.wt", "d,1[2]")
+ _MC88110 (0xf4002880, "st.h.wt", "d,1,2")
+ _MC88110 (0xf4002a80, "st.h.wt", "d,1[2]")
+ _MC88xxx (0xf4002500, "st.usr", "d,1,2")
+ _MC88xxx (0xf4002700, "st.usr", "d,1[2]")
+ _MC88110 (0xf0002500, "st.usr", "xd,1,2")
+ _MC88110 (0xf0002700, "st.usr", "xd,1[2]")
+ _MC88110 (0xf4002580, "st.usr.wt", "d,1,2")
+ _MC88110 (0xf4002780, "st.usr.wt", "d,1[2]")
+ _MC88110 (0xf0002580, "st.usr.wt", "xd,1,2")
+ _MC88110 (0xf0002780, "st.usr.wt", "xd,1[2]")
+ _MC88110 (0xf4002480, "st.wt", "d,1,2")
+ _MC88110 (0xf4002680, "st.wt", "d,1[2]")
+ _MC88110 (0xf0002480, "st.wt", "xd,1,2")
+ _MC88110 (0xf0002680, "st.wt", "xd,1[2]")
+ _MC88110 (0xf0002a00, "st.x", "xd,1[2]")
+ _MC88110 (0xf0002800, "st.x", "xd,1,2")
+ _MC88110 (0x38000000, "st.x", "xd,1,I")
+ _MC88110 (0xf0002900, "st.x.usr", "xd,1,2")
+ _MC88110 (0xf0002b00, "st.x.usr", "xd,1[2]")
+ _MC88110 (0xf0002980, "st.x.usr.wt", "xd,1,2")
+ _MC88110 (0xf0002b80, "st.x.usr.wt", "xd,1[2]")
+ _MC88110 (0xf0002880, "st.x.wt", "xd,1,2")
+ _MC88110 (0xf0002a80, "st.x.wt", "xd,1[2]")
+ _MC88xxx (0x80008000, "stcr", "3,c")
+ _MC88xxx (0xf4007400, "sub", "d,1,2")
+ _MC88xxx (0x74000000, "sub", "d,1,I")
+ _MC88xxx (0xf4007600, "sub.ci", "d,1,2")
+ _MC88xxx (0xf4007700, "sub.cio", "d,1,2")
+ _MC88xxx (0xf4007500, "sub.co", "d,1,2")
+ _MC88xxx (0xf4006400, "subu", "d,1,2")
+ _MC88xxx (0x64000000, "subu", "d,1,I")
+ _MC88xxx (0xf4006600, "subu.ci", "d,1,2")
+ _MC88xxx (0xf4006700, "subu.cio", "d,1,2")
+ _MC88xxx (0xf4006500, "subu.co", "d,1,2")
+ _MC88xxx (0xf000d000, "tb0", "B,1,V")
+ _MC88xxx (0xf000d800, "tb1", "B,1,V")
+ _MC88xxx (0xf400f800, "tbnd", "1,2")
+ _MC88xxx (0xf8000000, "tbnd", "1,I")
+ _MC88xxx (0xf000e800, "tcnd", "M,1,V")
+ _MC88xxx (0x84005880, "trnc.sd", "d,2")
+ _MC88110 (0x8400d880, "trnc.sd", "d,x2")
+ _MC88xxx (0x84005800, "trnc.ss", "d,2")
+ _MC88110 (0x8400d800, "trnc.ss", "d,x2")
+ _MC88110 (0x8400d900, "trnc.sx", "d,x2")
+ _MC88xxx (0x8000c000, "xcr", "d,3,c")
+ _MC88xxx (0xf4000600, "xmem", "d,1[2]")
+ _MC88xxx (0xf4000400, "xmem", "d,1,2")
+ _MC88100 (0x04000000, "xmem", "?d,1,I")
+ _MC88xxx (0xf4000200, "xmem.bu", "d,1[2]")
+ _MC88xxx (0xf4000000, "xmem.bu", "d,1,2")
+ _MC88100 (0x00000000, "xmem.bu", "?d,1,I")
+ _MC88xxx (0xf4000300, "xmem.bu.usr", "d,1[2]")
+ _MC88xxx (0xf4000100, "xmem.bu.usr", "d,1,2")
+ _MC88100 (0x00000100, "xmem.bu.usr", "?d,1,I")
+ _MC88xxx (0xf4000700, "xmem.usr", "d,1[2]")
+ _MC88xxx (0xf4000500, "xmem.usr", "d,1,2")
+ _MC88100 (0x04000100, "xmem.usr", "?d,1,I")
+ _MC88xxx (0xf4005000, "xor", "d,1,2")
+ _MC88xxx (0x50000000, "xor", "d,1,I")
+ _MC88xxx (0xf4005400, "xor.c", "d,1,2")
+ _MC88xxx (0x54000000, "xor.u", "d,1,I")
+ _MC88xxx (0x00000000, "", 0)
+};
+
+#define NUMOPCODES ((sizeof m88k_opcodes)/(sizeof m88k_opcodes[0]))
diff --git a/gas/config/obj-aout.c b/gas/config/obj-aout.c
new file mode 100644
index 0000000000..b5193475c1
--- /dev/null
+++ b/gas/config/obj-aout.c
@@ -0,0 +1,629 @@
+/* a.out object file format
+ Copyright (C) 1989, 90, 91, 92, 93, 94, 95, 1996
+ Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2,
+or (at your option) any later version.
+
+GAS 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 more details.
+
+You should have received a copy of the GNU General Public
+License along with GAS; see the file COPYING. If not, write
+to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "as.h"
+#ifdef BFD_ASSEMBLER
+#undef NO_RELOC
+#include "aout/aout64.h"
+#endif
+#include "obstack.h"
+
+#ifndef BFD_ASSEMBLER
+/* in: segT out: N_TYPE bits */
+const short seg_N_TYPE[] =
+{
+ N_ABS,
+ N_TEXT,
+ N_DATA,
+ N_BSS,
+ N_UNDF, /* unknown */
+ N_UNDF, /* error */
+ N_UNDF, /* expression */
+ N_UNDF, /* debug */
+ N_UNDF, /* ntv */
+ N_UNDF, /* ptv */
+ N_REGISTER, /* register */
+};
+
+const segT N_TYPE_seg[N_TYPE + 2] =
+{ /* N_TYPE == 0x1E = 32-2 */
+ SEG_UNKNOWN, /* N_UNDF == 0 */
+ SEG_GOOF,
+ SEG_ABSOLUTE, /* N_ABS == 2 */
+ SEG_GOOF,
+ SEG_TEXT, /* N_TEXT == 4 */
+ SEG_GOOF,
+ SEG_DATA, /* N_DATA == 6 */
+ SEG_GOOF,
+ SEG_BSS, /* N_BSS == 8 */
+ SEG_GOOF,
+ SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
+ SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
+ SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
+ SEG_REGISTER, /* dummy N_REGISTER for regs = 30 */
+ SEG_GOOF,
+};
+#endif
+
+static void obj_aout_line PARAMS ((int));
+static void obj_aout_weak PARAMS ((int));
+static void obj_aout_type PARAMS ((int));
+
+const pseudo_typeS obj_pseudo_table[] =
+{
+ {"line", obj_aout_line, 0}, /* source code line number */
+ {"ln", obj_aout_line, 0}, /* coff line number that we use anyway */
+
+ {"weak", obj_aout_weak, 0}, /* mark symbol as weak. */
+
+ {"type", obj_aout_type, 0},
+
+ /* coff debug pseudos (ignored) */
+ {"def", s_ignore, 0},
+ {"dim", s_ignore, 0},
+ {"endef", s_ignore, 0},
+ {"ident", s_ignore, 0},
+ {"line", s_ignore, 0},
+ {"ln", s_ignore, 0},
+ {"scl", s_ignore, 0},
+ {"size", s_ignore, 0},
+ {"tag", s_ignore, 0},
+ {"val", s_ignore, 0},
+ {"version", s_ignore, 0},
+
+ {"optim", s_ignore, 0}, /* For sun386i cc (?) */
+
+ /* other stuff */
+ {"ABORT", s_abort, 0},
+
+ {NULL} /* end sentinel */
+}; /* obj_pseudo_table */
+
+
+#ifdef BFD_ASSEMBLER
+
+void
+obj_aout_frob_symbol (sym, punt)
+ symbolS *sym;
+ int *punt;
+{
+ flagword flags;
+ asection *sec;
+ int desc, type, other;
+
+ flags = sym->bsym->flags;
+ desc = S_GET_DESC (sym);
+ type = S_GET_TYPE (sym);
+ other = S_GET_OTHER (sym);
+ sec = sym->bsym->section;
+
+ /* Only frob simple symbols this way right now. */
+ if (! (type & ~ (N_TYPE | N_EXT)))
+ {
+ if (type == (N_UNDF | N_EXT)
+ && sec == &bfd_abs_section)
+ sym->bsym->section = sec = bfd_und_section_ptr;
+
+ if ((type & N_TYPE) != N_INDR
+ && (type & N_TYPE) != N_SETA
+ && (type & N_TYPE) != N_SETT
+ && (type & N_TYPE) != N_SETD
+ && (type & N_TYPE) != N_SETB
+ && type != N_WARNING
+ && (sec == &bfd_abs_section
+ || sec == &bfd_und_section))
+ return;
+ if (flags & BSF_EXPORT)
+ type |= N_EXT;
+
+ switch (type & N_TYPE)
+ {
+ case N_SETA:
+ case N_SETT:
+ case N_SETD:
+ case N_SETB:
+ /* Set the debugging flag for constructor symbols so that
+ BFD leaves them alone. */
+ sym->bsym->flags |= BSF_DEBUGGING;
+
+ /* You can't put a common symbol in a set. The way a set
+ element works is that the symbol has a definition and a
+ name, and the linker adds the definition to the set of
+ that name. That does not work for a common symbol,
+ because the linker can't tell which common symbol the
+ user means. FIXME: Using as_bad here may be
+ inappropriate, since the user may want to force a
+ particular type without regard to the semantics of sets;
+ on the other hand, we certainly don't want anybody to be
+ mislead into thinking that their code will work. */
+ if (S_IS_COMMON (sym))
+ as_bad (_("Attempt to put a common symbol into set %s"),
+ S_GET_NAME (sym));
+ /* Similarly, you can't put an undefined symbol in a set. */
+ else if (! S_IS_DEFINED (sym))
+ as_bad (_("Attempt to put an undefined symbol into set %s"),
+ S_GET_NAME (sym));
+
+ break;
+ case N_INDR:
+ /* Put indirect symbols in the indirect section. */
+ sym->bsym->section = bfd_ind_section_ptr;
+ sym->bsym->flags |= BSF_INDIRECT;
+ if (type & N_EXT)
+ {
+ sym->bsym->flags |= BSF_EXPORT;
+ sym->bsym->flags &=~ BSF_LOCAL;
+ }
+ break;
+ case N_WARNING:
+ /* Mark warning symbols. */
+ sym->bsym->flags |= BSF_WARNING;
+ break;
+ }
+ }
+ else
+ {
+ sym->bsym->flags |= BSF_DEBUGGING;
+ }
+
+ S_SET_TYPE (sym, type);
+
+ /* Double check weak symbols. */
+ if (sym->bsym->flags & BSF_WEAK)
+ {
+ if (S_IS_COMMON (sym))
+ as_bad (_("Symbol `%s' can not be both weak and common"),
+ S_GET_NAME (sym));
+ }
+}
+
+void
+obj_aout_frob_file ()
+{
+ /* Relocation processing may require knowing the VMAs of the sections.
+ Since writing to a section will cause the BFD back end to compute the
+ VMAs, fake it out here.... */
+ bfd_byte b = 0;
+ boolean x = true;
+ if (bfd_section_size (stdoutput, text_section) != 0)
+ {
+ x = bfd_set_section_contents (stdoutput, text_section, &b, (file_ptr) 0,
+ (bfd_size_type) 1);
+ }
+ else if (bfd_section_size (stdoutput, data_section) != 0)
+ {
+ x = bfd_set_section_contents (stdoutput, data_section, &b, (file_ptr) 0,
+ (bfd_size_type) 1);
+ }
+ assert (x == true);
+}
+
+#else
+
+/* Relocation. */
+
+/*
+ * emit_relocations()
+ *
+ * Crawl along a fixS chain. Emit the segment's relocations.
+ */
+void
+obj_emit_relocations (where, fixP, segment_address_in_file)
+ char **where;
+ fixS *fixP; /* Fixup chain for this segment. */
+ relax_addressT segment_address_in_file;
+{
+ for (; fixP; fixP = fixP->fx_next)
+ if (fixP->fx_done == 0)
+ {
+ symbolS *sym;
+
+ sym = fixP->fx_addsy;
+ while (sym->sy_value.X_op == O_symbol
+ && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
+ sym = sym->sy_value.X_add_symbol;
+ fixP->fx_addsy = sym;
+
+ if (! sym->sy_resolved && ! S_IS_DEFINED (sym))
+ {
+ char *file;
+ unsigned int line;
+
+ if (expr_symbol_where (sym, &file, &line))
+ as_bad_where (file, line, _("unresolved relocation"));
+ else
+ as_bad (_("bad relocation: symbol `%s' not in symbol table"),
+ S_GET_NAME (sym));
+ }
+
+ tc_aout_fix_to_chars (*where, fixP, segment_address_in_file);
+ *where += md_reloc_size;
+ }
+}
+
+#ifndef obj_header_append
+/* Aout file generation & utilities */
+void
+obj_header_append (where, headers)
+ char **where;
+ object_headers *headers;
+{
+ tc_headers_hook (headers);
+
+#ifdef CROSS_COMPILE
+ md_number_to_chars (*where, headers->header.a_info, sizeof (headers->header.a_info));
+ *where += sizeof (headers->header.a_info);
+ md_number_to_chars (*where, headers->header.a_text, sizeof (headers->header.a_text));
+ *where += sizeof (headers->header.a_text);
+ md_number_to_chars (*where, headers->header.a_data, sizeof (headers->header.a_data));
+ *where += sizeof (headers->header.a_data);
+ md_number_to_chars (*where, headers->header.a_bss, sizeof (headers->header.a_bss));
+ *where += sizeof (headers->header.a_bss);
+ md_number_to_chars (*where, headers->header.a_syms, sizeof (headers->header.a_syms));
+ *where += sizeof (headers->header.a_syms);
+ md_number_to_chars (*where, headers->header.a_entry, sizeof (headers->header.a_entry));
+ *where += sizeof (headers->header.a_entry);
+ md_number_to_chars (*where, headers->header.a_trsize, sizeof (headers->header.a_trsize));
+ *where += sizeof (headers->header.a_trsize);
+ md_number_to_chars (*where, headers->header.a_drsize, sizeof (headers->header.a_drsize));
+ *where += sizeof (headers->header.a_drsize);
+
+#else /* CROSS_COMPILE */
+
+ append (where, (char *) &headers->header, sizeof (headers->header));
+#endif /* CROSS_COMPILE */
+
+}
+#endif
+
+void
+obj_symbol_to_chars (where, symbolP)
+ char **where;
+ symbolS *symbolP;
+{
+ md_number_to_chars ((char *) &(S_GET_OFFSET (symbolP)), S_GET_OFFSET (symbolP), sizeof (S_GET_OFFSET (symbolP)));
+ md_number_to_chars ((char *) &(S_GET_DESC (symbolP)), S_GET_DESC (symbolP), sizeof (S_GET_DESC (symbolP)));
+ md_number_to_chars ((char *) &(symbolP->sy_symbol.n_value), S_GET_VALUE (symbolP), sizeof (symbolP->sy_symbol.n_value));
+
+ append (where, (char *) &symbolP->sy_symbol, sizeof (obj_symbol_type));
+}
+
+void
+obj_emit_symbols (where, symbol_rootP)
+ char **where;
+ symbolS *symbol_rootP;
+{
+ symbolS *symbolP;
+
+ /* Emit all symbols left in the symbol chain. */
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
+ {
+ /* Used to save the offset of the name. It is used to point
+ to the string in memory but must be a file offset. */
+ register char *temp;
+
+ temp = S_GET_NAME (symbolP);
+ S_SET_OFFSET (symbolP, symbolP->sy_name_offset);
+
+ /* Any symbol still undefined and is not a dbg symbol is made N_EXT. */
+ if (!S_IS_DEBUG (symbolP) && !S_IS_DEFINED (symbolP))
+ S_SET_EXTERNAL (symbolP);
+
+ /* Adjust the type of a weak symbol. */
+ if (S_GET_WEAK (symbolP))
+ {
+ switch (S_GET_TYPE (symbolP))
+ {
+ case N_UNDF: S_SET_TYPE (symbolP, N_WEAKU); break;
+ case N_ABS: S_SET_TYPE (symbolP, N_WEAKA); break;
+ case N_TEXT: S_SET_TYPE (symbolP, N_WEAKT); break;
+ case N_DATA: S_SET_TYPE (symbolP, N_WEAKD); break;
+ case N_BSS: S_SET_TYPE (symbolP, N_WEAKB); break;
+ default: as_bad (_("%s: bad type for weak symbol"), temp); break;
+ }
+ }
+
+ obj_symbol_to_chars (where, symbolP);
+ S_SET_NAME (symbolP, temp);
+ }
+}
+
+#endif /* ! BFD_ASSEMBLER */
+
+static void
+obj_aout_line (ignore)
+ int ignore;
+{
+ /* Assume delimiter is part of expression.
+ BSD4.2 as fails with delightful bug, so we
+ are not being incompatible here. */
+ new_logical_line ((char *) NULL, (int) (get_absolute_expression ()));
+ demand_empty_rest_of_line ();
+} /* obj_aout_line() */
+
+/* Handle .weak. This is a GNU extension. */
+
+static void
+obj_aout_weak (ignore)
+ int ignore;
+{
+ char *name;
+ int c;
+ symbolS *symbolP;
+
+ do
+ {
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ symbolP = symbol_find_or_make (name);
+ *input_line_pointer = c;
+ SKIP_WHITESPACE ();
+ S_SET_WEAK (symbolP);
+ if (c == ',')
+ {
+ input_line_pointer++;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '\n')
+ c = '\n';
+ }
+ }
+ while (c == ',');
+ demand_empty_rest_of_line ();
+}
+
+/* Handle .type. On {Net,Open}BSD, this is used to set the n_other field,
+ which is then apparently used when doing dynamic linking. Older
+ versions ogas ignored the .type pseudo-op, so we also ignore it if
+ we can't parse it. */
+
+static void
+obj_aout_type (ignore)
+ int ignore;
+{
+ char *name;
+ int c;
+ symbolS *sym;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ sym = symbol_find (name);
+ *input_line_pointer = c;
+ if (sym != NULL)
+ {
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == ',')
+ {
+ ++input_line_pointer;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '@')
+ {
+ ++input_line_pointer;
+ if (strncmp (input_line_pointer, "object", 6) == 0)
+ S_SET_OTHER (sym, 1);
+ else if (strncmp (input_line_pointer, "function", 8) == 0)
+ S_SET_OTHER (sym, 2);
+ }
+ }
+ }
+
+ /* Ignore everything else on the line. */
+ s_ignore (0);
+}
+
+void
+obj_read_begin_hook ()
+{
+}
+
+#ifndef BFD_ASSEMBLER
+
+void
+obj_crawl_symbol_chain (headers)
+ object_headers *headers;
+{
+ symbolS *symbolP;
+ symbolS **symbolPP;
+ int symbol_number = 0;
+
+ tc_crawl_symbol_chain (headers);
+
+ symbolPP = &symbol_rootP; /*->last symbol chain link. */
+ while ((symbolP = *symbolPP) != NULL)
+ {
+ if (symbolP->sy_mri_common)
+ {
+ if (S_IS_EXTERNAL (symbolP))
+ as_bad (_("%s: global symbols not supported in common sections"),
+ S_GET_NAME (symbolP));
+ *symbolPP = symbol_next (symbolP);
+ continue;
+ }
+
+ if (flag_readonly_data_in_text && (S_GET_SEGMENT (symbolP) == SEG_DATA))
+ {
+ S_SET_SEGMENT (symbolP, SEG_TEXT);
+ } /* if pusing data into text */
+
+ resolve_symbol_value (symbolP, 1);
+
+ /* Skip symbols which were equated to undefined or common
+ symbols. */
+ if (symbolP->sy_value.X_op == O_symbol
+ && (! S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP)))
+ {
+ *symbolPP = symbol_next (symbolP);
+ continue;
+ }
+
+ /* OK, here is how we decide which symbols go out into the brave
+ new symtab. Symbols that do are:
+
+ * symbols with no name (stabd's?)
+ * symbols with debug info in their N_TYPE
+
+ Symbols that don't are:
+ * symbols that are registers
+ * symbols with \1 as their 3rd character (numeric labels)
+ * "local labels" as defined by S_LOCAL_NAME(name) if the -L
+ switch was passed to gas.
+
+ All other symbols are output. We complain if a deleted
+ symbol was marked external. */
+
+
+ if (!S_IS_REGISTER (symbolP)
+ && (!S_GET_NAME (symbolP)
+ || S_IS_DEBUG (symbolP)
+ || !S_IS_DEFINED (symbolP)
+ || S_IS_EXTERNAL (symbolP)
+ || (S_GET_NAME (symbolP)[0] != '\001'
+ && (flag_keep_locals || !S_LOCAL_NAME (symbolP)))))
+ {
+ symbolP->sy_number = symbol_number++;
+
+ /* The + 1 after strlen account for the \0 at the
+ end of each string */
+ if (!S_IS_STABD (symbolP))
+ {
+ /* Ordinary case. */
+ symbolP->sy_name_offset = string_byte_count;
+ string_byte_count += strlen (S_GET_NAME (symbolP)) + 1;
+ }
+ else /* .Stabd case. */
+ symbolP->sy_name_offset = 0;
+ symbolPP = &(symbol_next (symbolP));
+ }
+ else
+ {
+ if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP))
+ /* This warning should never get triggered any more.
+ Well, maybe if you're doing twisted things with
+ register names... */
+ {
+ as_bad (_("Local symbol %s never defined."), decode_local_label_name (S_GET_NAME (symbolP)));
+ } /* oops. */
+
+ /* Unhook it from the chain */
+ *symbolPP = symbol_next (symbolP);
+ } /* if this symbol should be in the output */
+ } /* for each symbol */
+
+ H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number);
+}
+
+/*
+ * Find strings by crawling along symbol table chain.
+ */
+
+void
+obj_emit_strings (where)
+ char **where;
+{
+ symbolS *symbolP;
+
+#ifdef CROSS_COMPILE
+ /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
+ md_number_to_chars (*where, string_byte_count, sizeof (string_byte_count));
+ *where += sizeof (string_byte_count);
+#else /* CROSS_COMPILE */
+ append (where, (char *) &string_byte_count, (unsigned long) sizeof (string_byte_count));
+#endif /* CROSS_COMPILE */
+
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
+ {
+ if (S_GET_NAME (symbolP))
+ append (&next_object_file_charP, S_GET_NAME (symbolP),
+ (unsigned long) (strlen (S_GET_NAME (symbolP)) + 1));
+ } /* walk symbol chain */
+}
+
+#ifndef AOUT_VERSION
+#define AOUT_VERSION 0
+#endif
+
+void
+obj_pre_write_hook (headers)
+ object_headers *headers;
+{
+ H_SET_DYNAMIC (headers, 0);
+ H_SET_VERSION (headers, AOUT_VERSION);
+ H_SET_MACHTYPE (headers, AOUT_MACHTYPE);
+ tc_aout_pre_write_hook (headers);
+}
+
+void
+DEFUN_VOID (s_sect)
+{
+ /* Strip out the section name */
+ char *section_name;
+ char *section_name_end;
+ char c;
+
+ unsigned int len;
+ unsigned int exp;
+ char *save;
+
+ section_name = input_line_pointer;
+ c = get_symbol_end ();
+ section_name_end = input_line_pointer;
+
+ len = section_name_end - section_name;
+ input_line_pointer++;
+ save = input_line_pointer;
+
+ SKIP_WHITESPACE ();
+ if (c == ',')
+ {
+ exp = get_absolute_expression ();
+ }
+ else if (*input_line_pointer == ',')
+ {
+ input_line_pointer++;
+ exp = get_absolute_expression ();
+ }
+ else
+ {
+ input_line_pointer = save;
+ exp = 0;
+ }
+ if (exp >= 1000)
+ {
+ as_bad (_("subsegment index too high"));
+ }
+
+ if (strcmp (section_name, ".text") == 0)
+ {
+ subseg_set (SEG_TEXT, (subsegT) exp);
+ }
+
+ if (strcmp (section_name, ".data") == 0)
+ {
+ if (flag_readonly_data_in_text)
+ subseg_set (SEG_TEXT, (subsegT) exp + 1000);
+ else
+ subseg_set (SEG_DATA, (subsegT) exp);
+ }
+
+ *section_name_end = c;
+}
+
+#endif /* ! BFD_ASSEMBLER */
+
+/* end of obj-aout.c */
diff --git a/gas/config/obj-aout.h b/gas/config/obj-aout.h
new file mode 100644
index 0000000000..339070e093
--- /dev/null
+++ b/gas/config/obj-aout.h
@@ -0,0 +1,239 @@
+/* obj-aout.h, a.out object file format for gas, the assembler.
+ Copyright (C) 1989, 90, 91, 92, 93, 94, 95, 96, 1998
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2,
+ or (at your option) any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* Tag to validate a.out object file format processing */
+#define OBJ_AOUT 1
+
+#include "targ-cpu.h"
+
+#ifdef BFD_ASSEMBLER
+
+#include "bfd/libaout.h"
+
+#define OUTPUT_FLAVOR bfd_target_aout_flavour
+
+#else /* ! BFD_ASSEMBLER */
+
+#ifndef VMS
+#include "aout_gnu.h" /* Needed to define struct nlist. Sigh. */
+#else
+#include "a_out.h"
+#endif
+
+#ifndef AOUT_MACHTYPE
+#define AOUT_MACHTYPE 0
+#endif /* AOUT_MACHTYPE */
+
+extern const short seg_N_TYPE[];
+extern const segT N_TYPE_seg[];
+
+#ifndef DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE
+#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (OMAGIC)
+#endif /* DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE */
+
+#endif /* ! BFD_ASSEMBLER */
+
+/* SYMBOL TABLE */
+/* Symbol table entry data type */
+
+typedef struct nlist obj_symbol_type; /* Symbol table entry */
+
+/* Symbol table macros and constants */
+
+#ifdef BFD_ASSEMBLER
+
+#define S_SET_OTHER(S,V) (aout_symbol((S)->bsym)->other = (V))
+#define S_SET_TYPE(S,T) (aout_symbol((S)->bsym)->type = (T))
+#define S_SET_DESC(S,D) (aout_symbol((S)->bsym)->desc = (D))
+#define S_GET_OTHER(S) (aout_symbol((S)->bsym)->other)
+#define S_GET_TYPE(S) (aout_symbol((S)->bsym)->type)
+#define S_GET_DESC(S) (aout_symbol((S)->bsym)->desc)
+
+asection *text_section, *data_section, *bss_section;
+
+#define obj_frob_symbol(S,PUNT) obj_aout_frob_symbol (S, &PUNT)
+#define obj_frob_file() obj_aout_frob_file ()
+extern void obj_aout_frob_symbol PARAMS ((struct symbol *, int *));
+extern void obj_aout_frob_file PARAMS ((void));
+
+#define obj_sec_sym_ok_for_reloc(SEC) (1)
+
+#else
+
+/* We use the sy_obj field to record whether a symbol is weak. */
+#define OBJ_SYMFIELD_TYPE char
+
+/*
+ * Macros to extract information from a symbol table entry.
+ * This syntaxic indirection allows independence regarding a.out or coff.
+ * The argument (s) of all these macros is a pointer to a symbol table entry.
+ */
+
+/* True if the symbol is external */
+#define S_IS_EXTERNAL(s) ((s)->sy_symbol.n_type & N_EXT)
+
+/* True if symbol has been defined, ie is in N_{TEXT,DATA,BSS,ABS} or N_EXT */
+#define S_IS_DEFINED(s) \
+ (S_GET_TYPE (s) != N_UNDF || S_GET_DESC (s) != 0)
+
+#define S_IS_COMMON(s) \
+ (S_GET_TYPE (s) == N_UNDF && S_GET_VALUE (s) != 0)
+
+#define S_IS_REGISTER(s) ((s)->sy_symbol.n_type == N_REGISTER)
+
+/* True if a debug special symbol entry */
+#define S_IS_DEBUG(s) ((s)->sy_symbol.n_type & N_STAB)
+/* True if a symbol is local symbol name */
+#define S_IS_LOCAL(s) \
+ ((S_GET_NAME (s) \
+ && !S_IS_DEBUG (s) \
+ && (strchr (S_GET_NAME (s), '\001') != NULL \
+ || strchr (S_GET_NAME (s), '\002') != NULL \
+ || (S_LOCAL_NAME(s) && !flag_keep_locals))) \
+ || (flag_strip_local_absolute \
+ && ! S_IS_EXTERNAL(s) \
+ && S_GET_SEGMENT (s) == absolute_section))
+/* True if a symbol is not defined in this file */
+#define S_IS_EXTERN(s) ((s)->sy_symbol.n_type & N_EXT)
+/* True if the symbol has been generated because of a .stabd directive */
+#define S_IS_STABD(s) (S_GET_NAME(s) == (char *)0)
+
+/* Accessors */
+/* The name of the symbol */
+#define S_GET_NAME(s) ((s)->sy_symbol.n_un.n_name)
+/* The pointer to the string table */
+#define S_GET_OFFSET(s) ((s)->sy_symbol.n_un.n_strx)
+/* The type of the symbol */
+#define S_GET_TYPE(s) ((s)->sy_symbol.n_type & N_TYPE)
+/* The numeric value of the segment */
+#define S_GET_SEGMENT(s) (N_TYPE_seg[S_GET_TYPE(s)])
+/* The n_other expression value */
+#define S_GET_OTHER(s) ((s)->sy_symbol.n_other)
+/* The n_desc expression value */
+#define S_GET_DESC(s) ((s)->sy_symbol.n_desc)
+/* Whether the symbol is weak. */
+#define S_GET_WEAK(s) ((s)->sy_obj)
+
+/* Modifiers */
+/* Assume that a symbol cannot be simultaneously in more than on segment */
+/* set segment */
+#define S_SET_SEGMENT(s,seg) ((s)->sy_symbol.n_type &= ~N_TYPE,(s)->sy_symbol.n_type|=SEGMENT_TO_SYMBOL_TYPE(seg))
+/* The symbol is external */
+#define S_SET_EXTERNAL(s) ((s)->sy_symbol.n_type |= N_EXT)
+/* The symbol is not external */
+#define S_CLEAR_EXTERNAL(s) ((s)->sy_symbol.n_type &= ~N_EXT)
+/* Set the name of the symbol */
+#define S_SET_NAME(s,v) ((s)->sy_symbol.n_un.n_name = (v))
+/* Set the offset in the string table */
+#define S_SET_OFFSET(s,v) ((s)->sy_symbol.n_un.n_strx = (v))
+/* Set the n_type field */
+#define S_SET_TYPE(s,t) ((s)->sy_symbol.n_type = (t))
+/* Set the n_other expression value */
+#define S_SET_OTHER(s,v) ((s)->sy_symbol.n_other = (v))
+/* Set the n_desc expression value */
+#define S_SET_DESC(s,v) ((s)->sy_symbol.n_desc = (v))
+/* Mark the symbol as weak. This causes n_type to be adjusted when
+ the symbol is written out. */
+#define S_SET_WEAK(s) ((s)->sy_obj = 1)
+
+/* File header macro and type definition */
+
+#define H_GET_FILE_SIZE(h) (H_GET_HEADER_SIZE(h) \
+ + H_GET_TEXT_SIZE(h) \
+ + H_GET_DATA_SIZE(h) \
+ + H_GET_SYMBOL_TABLE_SIZE(h) \
+ + H_GET_TEXT_RELOCATION_SIZE(h) \
+ + H_GET_DATA_RELOCATION_SIZE(h) \
+ + H_GET_STRING_SIZE(h))
+
+#define H_GET_HEADER_SIZE(h) (EXEC_BYTES_SIZE)
+#define H_GET_TEXT_SIZE(h) ((h)->header.a_text)
+#define H_GET_DATA_SIZE(h) ((h)->header.a_data)
+#define H_GET_BSS_SIZE(h) ((h)->header.a_bss)
+#define H_GET_TEXT_RELOCATION_SIZE(h) ((h)->header.a_trsize)
+#define H_GET_DATA_RELOCATION_SIZE(h) ((h)->header.a_drsize)
+#define H_GET_SYMBOL_TABLE_SIZE(h) ((h)->header.a_syms)
+#define H_GET_ENTRY_POINT(h) ((h)->header.a_entry)
+#define H_GET_STRING_SIZE(h) ((h)->string_table_size)
+#define H_GET_LINENO_SIZE(h) (0)
+
+#define H_GET_DYNAMIC(h) ((h)->header.a_info >> 31)
+#define H_GET_VERSION(h) (((h)->header.a_info >> 24) & 0x7f)
+#define H_GET_MACHTYPE(h) (((h)->header.a_info >> 16) & 0xff)
+#define H_GET_MAGIC_NUMBER(h) ((h)->header.a_info & 0xffff)
+
+#define H_SET_DYNAMIC(h,v) ((h)->header.a_info = (((v) << 31) \
+ | (H_GET_VERSION(h) << 24) \
+ | (H_GET_MACHTYPE(h) << 16) \
+ | (H_GET_MAGIC_NUMBER(h))))
+
+#define H_SET_VERSION(h,v) ((h)->header.a_info = ((H_GET_DYNAMIC(h) << 31) \
+ | ((v) << 24) \
+ | (H_GET_MACHTYPE(h) << 16) \
+ | (H_GET_MAGIC_NUMBER(h))))
+
+#define H_SET_MACHTYPE(h,v) ((h)->header.a_info = ((H_GET_DYNAMIC(h) << 31) \
+ | (H_GET_VERSION(h) << 24) \
+ | ((v) << 16) \
+ | (H_GET_MAGIC_NUMBER(h))))
+
+#define H_SET_MAGIC_NUMBER(h,v) ((h)->header.a_info = ((H_GET_DYNAMIC(h) << 31) \
+ | (H_GET_VERSION(h) << 24) \
+ | (H_GET_MACHTYPE(h) << 16) \
+ | ((v))))
+
+#define H_SET_TEXT_SIZE(h,v) ((h)->header.a_text = md_section_align(SEG_TEXT, (v)))
+#define H_SET_DATA_SIZE(h,v) ((h)->header.a_data = md_section_align(SEG_DATA, (v)))
+#define H_SET_BSS_SIZE(h,v) ((h)->header.a_bss = md_section_align(SEG_BSS, (v)))
+
+#define H_SET_RELOCATION_SIZE(h,t,d) (H_SET_TEXT_RELOCATION_SIZE((h),(t)),\
+ H_SET_DATA_RELOCATION_SIZE((h),(d)))
+
+#define H_SET_TEXT_RELOCATION_SIZE(h,v) ((h)->header.a_trsize = (v))
+#define H_SET_DATA_RELOCATION_SIZE(h,v) ((h)->header.a_drsize = (v))
+#define H_SET_SYMBOL_TABLE_SIZE(h,v) ((h)->header.a_syms = (v) * 12)
+
+#define H_SET_ENTRY_POINT(h,v) ((h)->header.a_entry = (v))
+#define H_SET_STRING_SIZE(h,v) ((h)->string_table_size = (v))
+
+typedef struct
+ {
+ struct exec header; /* a.out header */
+ long string_table_size; /* names + '\0' + sizeof(int) */
+ }
+
+object_headers;
+
+/* line numbering stuff. */
+#define OBJ_EMIT_LINENO(a, b, c) {;}
+
+struct fix;
+void tc_aout_fix_to_chars PARAMS ((char *where, struct fix *fixP, relax_addressT segment_address));
+
+#endif
+
+#define obj_symbol_new_hook(s) {;}
+
+#define EMIT_SECTION_SYMBOLS 0
+
+#define AOUT_STABS
+
+/* end of obj-aout.h */
diff --git a/gas/config/obj-bout.c b/gas/config/obj-bout.c
new file mode 100644
index 0000000000..c9b80f5733
--- /dev/null
+++ b/gas/config/obj-bout.c
@@ -0,0 +1,348 @@
+/* b.out object file format
+ Copyright (C) 1989, 90, 91, 92, 93, 94, 95, 1996
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2,
+ or (at your option) any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public
+ License along with GAS; see the file COPYING. If not, write
+ to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "as.h"
+#include "obstack.h"
+const short /* in: segT out: N_TYPE bits */
+ seg_N_TYPE[] =
+{
+ N_ABS,
+ N_TEXT,
+ N_DATA,
+ N_BSS,
+ N_UNDF, /* unknown */
+ N_UNDF, /* error */
+ N_UNDF, /* expression */
+ N_UNDF, /* debug */
+ N_UNDF, /* ntv */
+ N_UNDF, /* ptv */
+ N_REGISTER, /* register */
+};
+
+const segT N_TYPE_seg[N_TYPE + 2] =
+{ /* N_TYPE == 0x1E = 32-2 */
+ SEG_UNKNOWN, /* N_UNDF == 0 */
+ SEG_GOOF,
+ SEG_ABSOLUTE, /* N_ABS == 2 */
+ SEG_GOOF,
+ SEG_TEXT, /* N_TEXT == 4 */
+ SEG_GOOF,
+ SEG_DATA, /* N_DATA == 6 */
+ SEG_GOOF,
+ SEG_BSS, /* N_BSS == 8 */
+ SEG_GOOF,
+ SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
+ SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
+ SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
+ SEG_REGISTER, /* dummy N_REGISTER for regs = 30 */
+ SEG_GOOF,
+};
+
+static void obj_bout_line PARAMS ((int));
+
+const pseudo_typeS obj_pseudo_table[] =
+{
+ {"line", obj_bout_line, 0}, /* source code line number */
+
+/* coff debugging directives. Currently ignored silently */
+ {"def", s_ignore, 0},
+ {"dim", s_ignore, 0},
+ {"endef", s_ignore, 0},
+ {"ln", s_ignore, 0},
+ {"scl", s_ignore, 0},
+ {"size", s_ignore, 0},
+ {"tag", s_ignore, 0},
+ {"type", s_ignore, 0},
+ {"val", s_ignore, 0},
+
+/* other stuff we don't handle */
+ {"ABORT", s_ignore, 0},
+ {"ident", s_ignore, 0},
+
+ {NULL} /* end sentinel */
+}; /* obj_pseudo_table */
+
+/* Relocation. */
+
+/*
+ * emit_relocations()
+ *
+ * Crawl along a fixS chain. Emit the segment's relocations.
+ */
+void
+obj_emit_relocations (where, fixP, segment_address_in_file)
+ char **where;
+ fixS *fixP; /* Fixup chain for this segment. */
+ relax_addressT segment_address_in_file;
+{
+ for (; fixP; fixP = fixP->fx_next)
+ {
+ if (fixP->fx_done == 0
+ || fixP->fx_r_type != NO_RELOC)
+ {
+ symbolS *sym;
+
+ sym = fixP->fx_addsy;
+ while (sym->sy_value.X_op == O_symbol
+ && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
+ sym = sym->sy_value.X_add_symbol;
+ fixP->fx_addsy = sym;
+
+ tc_bout_fix_to_chars (*where, fixP, segment_address_in_file);
+ *where += sizeof (struct relocation_info);
+ } /* if there's a symbol */
+ } /* for each fixup */
+
+} /* emit_relocations() */
+
+/* Aout file generation & utilities */
+
+/* Convert a lvalue to machine dependent data */
+void
+obj_header_append (where, headers)
+ char **where;
+ object_headers *headers;
+{
+ /* Always leave in host byte order */
+
+ headers->header.a_talign = section_alignment[SEG_TEXT];
+
+ if (headers->header.a_talign < 2)
+ {
+ headers->header.a_talign = 2;
+ } /* force to at least 2 */
+
+ headers->header.a_dalign = section_alignment[SEG_DATA];
+ headers->header.a_balign = section_alignment[SEG_BSS];
+
+ headers->header.a_tload = 0;
+ headers->header.a_dload = md_section_align (SEG_DATA, H_GET_TEXT_SIZE (headers));
+
+ headers->header.a_relaxable = linkrelax;
+
+#ifdef CROSS_COMPILE
+ md_number_to_chars (*where, headers->header.a_magic, sizeof (headers->header.a_magic));
+ *where += sizeof (headers->header.a_magic);
+ md_number_to_chars (*where, headers->header.a_text, sizeof (headers->header.a_text));
+ *where += sizeof (headers->header.a_text);
+ md_number_to_chars (*where, headers->header.a_data, sizeof (headers->header.a_data));
+ *where += sizeof (headers->header.a_data);
+ md_number_to_chars (*where, headers->header.a_bss, sizeof (headers->header.a_bss));
+ *where += sizeof (headers->header.a_bss);
+ md_number_to_chars (*where, headers->header.a_syms, sizeof (headers->header.a_syms));
+ *where += sizeof (headers->header.a_syms);
+ md_number_to_chars (*where, headers->header.a_entry, sizeof (headers->header.a_entry));
+ *where += sizeof (headers->header.a_entry);
+ md_number_to_chars (*where, headers->header.a_trsize, sizeof (headers->header.a_trsize));
+ *where += sizeof (headers->header.a_trsize);
+ md_number_to_chars (*where, headers->header.a_drsize, sizeof (headers->header.a_drsize));
+ *where += sizeof (headers->header.a_drsize);
+ md_number_to_chars (*where, headers->header.a_tload, sizeof (headers->header.a_tload));
+ *where += sizeof (headers->header.a_tload);
+ md_number_to_chars (*where, headers->header.a_dload, sizeof (headers->header.a_dload));
+ *where += sizeof (headers->header.a_dload);
+ md_number_to_chars (*where, headers->header.a_talign, sizeof (headers->header.a_talign));
+ *where += sizeof (headers->header.a_talign);
+ md_number_to_chars (*where, headers->header.a_dalign, sizeof (headers->header.a_dalign));
+ *where += sizeof (headers->header.a_dalign);
+ md_number_to_chars (*where, headers->header.a_balign, sizeof (headers->header.a_balign));
+ *where += sizeof (headers->header.a_balign);
+ md_number_to_chars (*where, headers->header.a_relaxable, sizeof (headers->header.a_relaxable));
+ *where += sizeof (headers->header.a_relaxable);
+#else /* ! CROSS_COMPILE */
+ append (where, (char *) &headers->header, sizeof (headers->header));
+#endif /* ! CROSS_COMPILE */
+} /* a_header_append() */
+
+void
+obj_symbol_to_chars (where, symbolP)
+ char **where;
+ symbolS *symbolP;
+{
+ md_number_to_chars ((char *) &(S_GET_OFFSET (symbolP)), S_GET_OFFSET (symbolP), sizeof (S_GET_OFFSET (symbolP)));
+ md_number_to_chars ((char *) &(S_GET_DESC (symbolP)), S_GET_DESC (symbolP), sizeof (S_GET_DESC (symbolP)));
+ md_number_to_chars ((char *) &symbolP->sy_symbol.n_value, S_GET_VALUE (symbolP), sizeof (symbolP->sy_symbol.n_value));
+
+ append (where, (char *) &symbolP->sy_symbol, sizeof (obj_symbol_type));
+} /* obj_symbol_to_chars() */
+
+void
+obj_emit_symbols (where, symbol_rootP)
+ char **where;
+ symbolS *symbol_rootP;
+{
+ symbolS *symbolP;
+
+ /*
+ * Emit all symbols left in the symbol chain.
+ */
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
+ {
+ /* Used to save the offset of the name. It is used to point
+ to the string in memory but must be a file offset. */
+ char *temp;
+
+ temp = S_GET_NAME (symbolP);
+ S_SET_OFFSET (symbolP, symbolP->sy_name_offset);
+
+ /* Any symbol still undefined and is not a dbg symbol is made N_EXT. */
+ if (!S_IS_DEBUG (symbolP) && !S_IS_DEFINED (symbolP))
+ S_SET_EXTERNAL (symbolP);
+
+ obj_symbol_to_chars (where, symbolP);
+ S_SET_NAME (symbolP, temp);
+ }
+} /* emit_symbols() */
+
+void
+obj_symbol_new_hook (symbolP)
+ symbolS *symbolP;
+{
+ S_SET_OTHER (symbolP, 0);
+ S_SET_DESC (symbolP, 0);
+}
+
+static void
+obj_bout_line (ignore)
+ int ignore;
+{
+ /* Assume delimiter is part of expression. */
+ /* BSD4.2 as fails with delightful bug, so we */
+ /* are not being incompatible here. */
+ new_logical_line ((char *) NULL, (int) (get_absolute_expression ()));
+ demand_empty_rest_of_line ();
+} /* obj_bout_line() */
+
+void
+obj_read_begin_hook ()
+{
+}
+
+void
+obj_crawl_symbol_chain (headers)
+ object_headers *headers;
+{
+ symbolS **symbolPP;
+ symbolS *symbolP;
+ int symbol_number = 0;
+
+ tc_crawl_symbol_chain (headers);
+
+ symbolPP = &symbol_rootP; /*->last symbol chain link. */
+ while ((symbolP = *symbolPP) != NULL)
+ {
+ if (flag_readonly_data_in_text && (S_GET_SEGMENT (symbolP) == SEG_DATA))
+ {
+ S_SET_SEGMENT (symbolP, SEG_TEXT);
+ } /* if pusing data into text */
+
+ resolve_symbol_value (symbolP, 1);
+
+ /* Skip symbols which were equated to undefined or common
+ symbols. */
+ if (symbolP->sy_value.X_op == O_symbol
+ && (! S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP)))
+ {
+ *symbolPP = symbol_next (symbolP);
+ continue;
+ }
+
+ /* OK, here is how we decide which symbols go out into the
+ brave new symtab. Symbols that do are:
+
+ * symbols with no name (stabd's?)
+ * symbols with debug info in their N_TYPE
+
+ Symbols that don't are:
+ * symbols that are registers
+ * symbols with \1 as their 3rd character (numeric labels)
+ * "local labels" as defined by S_LOCAL_NAME(name)
+ if the -L switch was passed to gas.
+
+ All other symbols are output. We complain if a deleted
+ symbol was marked external. */
+
+
+ if (1
+ && !S_IS_REGISTER (symbolP)
+ && (!S_GET_NAME (symbolP)
+ || S_IS_DEBUG (symbolP)
+#ifdef TC_I960
+ /* FIXME-SOON this ifdef seems highly dubious to me. xoxorich. */
+ || !S_IS_DEFINED (symbolP)
+ || S_IS_EXTERNAL (symbolP)
+#endif /* TC_I960 */
+ || (S_GET_NAME (symbolP)[0] != '\001' && (flag_keep_locals || !S_LOCAL_NAME (symbolP)))))
+ {
+ symbolP->sy_number = symbol_number++;
+
+ /* The + 1 after strlen account for the \0 at the
+ end of each string */
+ if (!S_IS_STABD (symbolP))
+ {
+ /* Ordinary case. */
+ symbolP->sy_name_offset = string_byte_count;
+ string_byte_count += strlen (S_GET_NAME (symbolP)) + 1;
+ }
+ else /* .Stabd case. */
+ symbolP->sy_name_offset = 0;
+ symbolPP = &(symbol_next (symbolP));
+ }
+ else
+ {
+ if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP))
+ {
+ as_bad (_("Local symbol %s never defined"), S_GET_NAME (symbolP));
+ } /* oops. */
+
+ /* Unhook it from the chain */
+ *symbolPP = symbol_next (symbolP);
+ } /* if this symbol should be in the output */
+ } /* for each symbol */
+
+ H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number);
+}
+
+/*
+ * Find strings by crawling along symbol table chain.
+ */
+
+void
+obj_emit_strings (where)
+ char **where;
+{
+ symbolS *symbolP;
+
+#ifdef CROSS_COMPILE
+ /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
+ md_number_to_chars (*where, string_byte_count, sizeof (string_byte_count));
+ *where += sizeof (string_byte_count);
+#else /* CROSS_COMPILE */
+ append (where, (char *) &string_byte_count, (unsigned long) sizeof (string_byte_count));
+#endif /* CROSS_COMPILE */
+
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
+ {
+ if (S_GET_NAME (symbolP))
+ append (where, S_GET_NAME (symbolP), (unsigned long) (strlen (S_GET_NAME (symbolP)) + 1));
+ } /* walk symbol chain */
+}
+
+/* end of obj-bout.c */
diff --git a/gas/config/obj-bout.h b/gas/config/obj-bout.h
new file mode 100644
index 0000000000..ec539a0cf4
--- /dev/null
+++ b/gas/config/obj-bout.h
@@ -0,0 +1,316 @@
+/* b.out object file format
+ Copyright (C) 1989, 90, 91, 92, 93, 94, 95, 1996
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2,
+ or (at your option) any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public
+ License along with GAS; see the file COPYING. If not, write
+ to the Free Software Foundation, 59 Temple Place - Suite 330, Cambridge, MA
+ 02139, USA. */
+
+/*
+ * This file is a modified version of 'a.out.h'. It is to be used in all GNU
+ * tools modified to support the i80960 b.out format (or tools that operate on
+ * object files created by such tools).
+ *
+ * All i80960 development is done in a CROSS-DEVELOPMENT environment. I.e.,
+ * object code is generated on, and executed under the direction of a symbolic
+ * debugger running on, a host system. We do not want to be subject to the
+ * vagaries of which host it is or whether it supports COFF or a.out format, or
+ * anything else. We DO want to:
+ *
+ * o always generate the same format object files, regardless of host.
+ *
+ * o have an 'a.out' header that we can modify for our own purposes
+ * (the 80960 is typically an embedded processor and may require
+ * enhanced linker support that the normal a.out.h header can't
+ * accommodate).
+ *
+ * As for byte-ordering, the following rules apply:
+ *
+ * o Text and data that is actually downloaded to the target is always
+ * in i80960 (little-endian) order.
+ *
+ * o All other numbers (in the header, symbols, relocation directives)
+ * are in host byte-order: object files CANNOT be lifted from a
+ * little-end host and used on a big-endian (or vice versa) without
+ * modification.
+ * ==> THIS IS NO LONGER TRUE USING BFD. WE CAN GENERATE ANY BYTE ORDER
+ * FOR THE HEADER, AND READ ANY BYTE ORDER. PREFERENCE WOULD BE TO
+ * USE LITTLE-ENDIAN BYTE ORDER THROUGHOUT, REGARDLESS OF HOST. <==
+ *
+ * o The downloader ('comm960') takes care to generate a pseudo-header
+ * with correct (i80960) byte-ordering before shipping text and data
+ * off to the NINDY monitor in the target systems. Symbols and
+ * relocation info are never sent to the target.
+ */
+
+
+#define OBJ_BOUT 1
+
+#define OUTPUT_FLAVOR bfd_target_aout_flavour
+
+#include "targ-cpu.h"
+
+#define OBJ_DEFAULT_OUTPUT_FILE_NAME "b.out"
+
+extern const short seg_N_TYPE[];
+extern const segT N_TYPE_seg[];
+
+#define BMAGIC 0415
+/* We don't accept the following (see N_BADMAG macro).
+ * They're just here so GNU code will compile.
+ */
+#define OMAGIC 0407 /* old impure format */
+#define NMAGIC 0410 /* read-only text */
+#define ZMAGIC 0413 /* demand load format */
+
+#ifndef DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE
+#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (BMAGIC)
+#endif /* DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE */
+
+/* FILE HEADER
+ * All 'lengths' are given as a number of bytes.
+ * All 'alignments' are for relinkable files only; an alignment of
+ * 'n' indicates the corresponding segment must begin at an
+ * address that is a multiple of (2**n).
+ */
+struct exec
+ {
+ /* Standard stuff */
+ unsigned long a_magic; /* Identifies this as a b.out file */
+ unsigned long a_text; /* Length of text */
+ unsigned long a_data; /* Length of data */
+ unsigned long a_bss; /* Length of runtime uninitialized data area */
+ unsigned long a_syms; /* Length of symbol table */
+ unsigned long a_entry; /* Runtime start address */
+ unsigned long a_trsize; /* Length of text relocation info */
+ unsigned long a_drsize; /* Length of data relocation info */
+
+ /* Added for i960 */
+ unsigned long a_tload; /* Text runtime load address */
+ unsigned long a_dload; /* Data runtime load address */
+ unsigned char a_talign; /* Alignment of text segment */
+ unsigned char a_dalign; /* Alignment of data segment */
+ unsigned char a_balign; /* Alignment of bss segment */
+ unsigned char a_relaxable; /* Contains enough info to relax */
+ };
+
+#define N_BADMAG(x) (((x).a_magic)!=BMAGIC)
+#define N_TXTOFF(x) ( sizeof(struct exec) )
+#define N_DATOFF(x) ( N_TXTOFF(x) + (x).a_text )
+#define N_TROFF(x) ( N_DATOFF(x) + (x).a_data )
+#define N_DROFF(x) ( N_TROFF(x) + (x).a_trsize )
+#define N_SYMOFF(x) ( N_DROFF(x) + (x).a_drsize )
+#define N_STROFF(x) ( N_SYMOFF(x) + (x).a_syms )
+
+/* A single entry in the symbol table
+ */
+struct nlist
+ {
+ union
+ {
+ char *n_name;
+ struct nlist *n_next;
+ long n_strx; /* Index into string table */
+ }
+ n_un;
+ unsigned char n_type; /* See below */
+ char n_other; /* Used in i80960 support -- see below */
+ short n_desc;
+ unsigned long n_value;
+ };
+
+typedef struct nlist obj_symbol_type;
+
+/* Legal values of n_type
+ */
+#define N_UNDF 0 /* Undefined symbol */
+#define N_ABS 2 /* Absolute symbol */
+#define N_TEXT 4 /* Text symbol */
+#define N_DATA 6 /* Data symbol */
+#define N_BSS 8 /* BSS symbol */
+#define N_FN 31 /* Filename symbol */
+
+#define N_EXT 1 /* External symbol (OR'd in with one of above) */
+#define N_TYPE 036 /* Mask for all the type bits */
+#define N_STAB 0340 /* Mask for all bits used for SDB entries */
+
+#ifndef CUSTOM_RELOC_FORMAT
+struct relocation_info
+ {
+ int r_address; /* File address of item to be relocated */
+ unsigned
+ r_index:24, /* Index of symbol on which relocation is based*/
+ r_pcrel:1, /* 1 => relocate PC-relative; else absolute
+ * On i960, pc-relative implies 24-bit
+ * address, absolute implies 32-bit.
+ */
+ r_length:2, /* Number of bytes to relocate:
+ * 0 => 1 byte
+ * 1 => 2 bytes
+ * 2 => 4 bytes -- only value used for i960
+ */
+ r_extern:1, r_bsr:1, /* Something for the GNU NS32K assembler */
+ r_disp:1, /* Something for the GNU NS32K assembler */
+ r_callj:1, /* 1 if relocation target is an i960 'callj' */
+ nuthin:1; /* Unused */
+ };
+
+#endif /* CUSTOM_RELOC_FORMAT */
+
+/*
+ * Macros to extract information from a symbol table entry.
+ * This syntaxic indirection allows independence regarding a.out or coff.
+ * The argument (s) of all these macros is a pointer to a symbol table entry.
+ */
+
+/* Predicates */
+/* True if the symbol is external */
+#define S_IS_EXTERNAL(s) ((s)->sy_symbol.n_type & N_EXT)
+
+/* True if symbol has been defined, ie is in N_{TEXT,DATA,BSS,ABS} or N_EXT */
+#define S_IS_DEFINED(s) ((S_GET_TYPE(s) != N_UNDF) || (S_GET_DESC(s) != 0))
+
+#define S_IS_COMMON(s) \
+ (S_GET_TYPE (s) == N_UNDF && S_GET_VALUE (s) != 0)
+
+#define S_IS_REGISTER(s) ((s)->sy_symbol.n_type == N_REGISTER)
+
+/* True if a debug special symbol entry */
+#define S_IS_DEBUG(s) ((s)->sy_symbol.n_type & N_STAB)
+/* True if a symbol is local symbol name */
+#define S_IS_LOCAL(s) \
+ ((S_GET_NAME (s) \
+ && !S_IS_DEBUG (s) \
+ && (strchr (S_GET_NAME (s), '\001') != NULL \
+ || strchr (S_GET_NAME (s), '\002') != NULL \
+ || (S_LOCAL_NAME(s) && !flag_keep_locals))) \
+ || (flag_strip_local_absolute \
+ && !S_IS_EXTERNAL(s) \
+ && S_GET_SEGMENT(s) == absolute_section))
+/* True if a symbol is not defined in this file */
+#define S_IS_EXTERN(s) ((s)->sy_symbol.n_type & N_EXT)
+/* True if the symbol has been generated because of a .stabd directive */
+#define S_IS_STABD(s) (S_GET_NAME(s) == NULL)
+
+/* Accessors */
+/* The name of the symbol */
+#define S_GET_NAME(s) ((s)->sy_symbol.n_un.n_name)
+/* The pointer to the string table */
+#define S_GET_OFFSET(s) ((s)->sy_symbol.n_un.n_strx)
+/* The type of the symbol */
+#define S_GET_TYPE(s) ((s)->sy_symbol.n_type & N_TYPE)
+/* The numeric value of the segment */
+#define S_GET_SEGMENT(s) (N_TYPE_seg[S_GET_TYPE(s)])
+/* The n_other expression value */
+#define S_GET_OTHER(s) ((s)->sy_symbol.n_other)
+/* The n_desc expression value */
+#define S_GET_DESC(s) ((s)->sy_symbol.n_desc)
+
+/* Modifiers */
+/* Assume that a symbol cannot be simultaneously in more than on segment */
+/* set segment */
+#define S_SET_SEGMENT(s,seg) ((s)->sy_symbol.n_type &= ~N_TYPE,(s)->sy_symbol.n_type|=SEGMENT_TO_SYMBOL_TYPE(seg))
+/* The symbol is external */
+#define S_SET_EXTERNAL(s) ((s)->sy_symbol.n_type |= N_EXT)
+/* The symbol is not external */
+#define S_CLEAR_EXTERNAL(s) ((s)->sy_symbol.n_type &= ~N_EXT)
+/* Set the name of the symbol */
+#define S_SET_NAME(s,v) ((s)->sy_symbol.n_un.n_name = (v))
+/* Set the offset in the string table */
+#define S_SET_OFFSET(s,v) ((s)->sy_symbol.n_un.n_strx = (v))
+/* Set the n_other expression value */
+#define S_SET_OTHER(s,v) ((s)->sy_symbol.n_other = (v))
+/* Set the n_desc expression value */
+#define S_SET_DESC(s,v) ((s)->sy_symbol.n_desc = (v))
+/* Set the n_type value */
+#define S_SET_TYPE(s,v) ((s)->sy_symbol.n_type = (v))
+
+/* File header macro and type definition */
+
+#define H_GET_FILE_SIZE(h) (sizeof(struct exec) + \
+ H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \
+ H_GET_SYMBOL_TABLE_SIZE(h) + \
+ H_GET_TEXT_RELOCATION_SIZE(h) + \
+ H_GET_DATA_RELOCATION_SIZE(h) + \
+ (h)->string_table_size)
+
+#define H_GET_HEADER_SIZE(h) (sizeof(struct exec))
+#define H_GET_TEXT_SIZE(h) ((h)->header.a_text)
+#define H_GET_DATA_SIZE(h) ((h)->header.a_data)
+#define H_GET_BSS_SIZE(h) ((h)->header.a_bss)
+#define H_GET_TEXT_RELOCATION_SIZE(h) ((h)->header.a_trsize)
+#define H_GET_DATA_RELOCATION_SIZE(h) ((h)->header.a_drsize)
+#define H_GET_SYMBOL_TABLE_SIZE(h) ((h)->header.a_syms)
+#define H_GET_MAGIC_NUMBER(h) ((h)->header.a_info)
+#define H_GET_ENTRY_POINT(h) ((h)->header.a_entry)
+#define H_GET_STRING_SIZE(h) ((h)->string_table_size)
+#define H_GET_LINENO_SIZE(h) (0)
+
+#ifdef EXEC_MACHINE_TYPE
+#define H_GET_MACHINE_TYPE(h) ((h)->header.a_machtype)
+#endif /* EXEC_MACHINE_TYPE */
+#ifdef EXEC_VERSION
+#define H_GET_VERSION(h) ((h)->header.a_version)
+#endif /* EXEC_VERSION */
+
+#define H_SET_TEXT_SIZE(h,v) ((h)->header.a_text = (v))
+#define H_SET_DATA_SIZE(h,v) ((h)->header.a_data = (v))
+#define H_SET_BSS_SIZE(h,v) ((h)->header.a_bss = (v))
+
+#define H_SET_RELOCATION_SIZE(h,t,d) (H_SET_TEXT_RELOCATION_SIZE((h),(t)),\
+ H_SET_DATA_RELOCATION_SIZE((h),(d)))
+
+#define H_SET_TEXT_RELOCATION_SIZE(h,v) ((h)->header.a_trsize = (v))
+#define H_SET_DATA_RELOCATION_SIZE(h,v) ((h)->header.a_drsize = (v))
+#define H_SET_SYMBOL_TABLE_SIZE(h,v) ((h)->header.a_syms = (v) * \
+ sizeof(struct nlist))
+
+#define H_SET_MAGIC_NUMBER(h,v) ((h)->header.a_magic = (v))
+
+#define H_SET_ENTRY_POINT(h,v) ((h)->header.a_entry = (v))
+#define H_SET_STRING_SIZE(h,v) ((h)->string_table_size = (v))
+#ifdef EXEC_MACHINE_TYPE
+#define H_SET_MACHINE_TYPE(h,v) ((h)->header.a_machtype = (v))
+#endif /* EXEC_MACHINE_TYPE */
+#ifdef EXEC_VERSION
+#define H_SET_VERSION(h,v) ((h)->header.a_version = (v))
+#endif /* EXEC_VERSION */
+
+typedef struct
+ {
+ struct exec header; /* a.out header */
+ long string_table_size; /* names + '\0' + sizeof(int) */
+ }
+
+object_headers;
+
+/* unused hooks. */
+#define OBJ_EMIT_LINENO(a, b, c) {;}
+#define obj_pre_write_hook(a) {;}
+
+#if __STDC__
+struct fix;
+#endif
+extern void tc_aout_fix_to_chars PARAMS ((char *where,
+ struct fix *fixP,
+ relax_addressT segment_address));
+extern void tc_bout_fix_to_chars PARAMS ((char *where,
+ struct fix *fixP,
+ relax_addressT segment_address));
+
+#define AOUT_STABS
+
+/* end of obj-bout.h */
diff --git a/gas/config/obj-coff.c b/gas/config/obj-coff.c
new file mode 100644
index 0000000000..5639fbed96
--- /dev/null
+++ b/gas/config/obj-coff.c
@@ -0,0 +1,4482 @@
+/* coff object file format
+ Copyright (C) 1989, 90, 91, 92, 93, 94, 95, 96, 97, 1998
+ Free Software Foundation, Inc.
+
+ This file is part of GAS.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#define OBJ_HEADER "obj-coff.h"
+
+#include "as.h"
+#include "obstack.h"
+#include "subsegs.h"
+
+/* I think this is probably always correct. */
+#ifndef KEEP_RELOC_INFO
+#define KEEP_RELOC_INFO
+#endif
+
+static void obj_coff_bss PARAMS ((int));
+const char *s_get_name PARAMS ((symbolS * s));
+static symbolS *def_symbol_in_progress;
+
+
+/* stack stuff */
+typedef struct
+ {
+ unsigned long chunk_size;
+ unsigned long element_size;
+ unsigned long size;
+ char *data;
+ unsigned long pointer;
+ }
+stack;
+
+static stack *
+stack_init (chunk_size, element_size)
+ unsigned long chunk_size;
+ unsigned long element_size;
+{
+ stack *st;
+
+ st = (stack *) malloc (sizeof (stack));
+ if (!st)
+ return 0;
+ st->data = malloc (chunk_size);
+ if (!st->data)
+ {
+ free (st);
+ return 0;
+ }
+ st->pointer = 0;
+ st->size = chunk_size;
+ st->chunk_size = chunk_size;
+ st->element_size = element_size;
+ return st;
+}
+
+#if 0
+/* Not currently used. */
+static void
+stack_delete (st)
+ stack *st;
+{
+ free (st->data);
+ free (st);
+}
+#endif
+
+static char *
+stack_push (st, element)
+ stack *st;
+ char *element;
+{
+ if (st->pointer + st->element_size >= st->size)
+ {
+ st->size += st->chunk_size;
+ if ((st->data = xrealloc (st->data, st->size)) == (char *) 0)
+ return (char *) 0;
+ }
+ memcpy (st->data + st->pointer, element, st->element_size);
+ st->pointer += st->element_size;
+ return st->data + st->pointer;
+}
+
+static char *
+stack_pop (st)
+ stack *st;
+{
+ if (st->pointer < st->element_size)
+ {
+ st->pointer = 0;
+ return (char *) 0;
+ }
+ st->pointer -= st->element_size;
+ return st->data + st->pointer;
+}
+
+/*
+ * Maintain a list of the tagnames of the structres.
+ */
+
+static struct hash_control *tag_hash;
+
+static void
+tag_init ()
+{
+ tag_hash = hash_new ();
+}
+
+static void
+tag_insert (name, symbolP)
+ const char *name;
+ symbolS *symbolP;
+{
+ const char *error_string;
+
+ if ((error_string = hash_jam (tag_hash, name, (char *) symbolP)))
+ {
+ as_fatal (_("Inserting \"%s\" into structure table failed: %s"),
+ name, error_string);
+ }
+}
+
+static symbolS *
+tag_find (name)
+ char *name;
+{
+#ifdef STRIP_UNDERSCORE
+ if (*name == '_')
+ name++;
+#endif /* STRIP_UNDERSCORE */
+ return (symbolS *) hash_find (tag_hash, name);
+}
+
+static symbolS *
+tag_find_or_make (name)
+ char *name;
+{
+ symbolS *symbolP;
+
+ if ((symbolP = tag_find (name)) == NULL)
+ {
+ symbolP = symbol_new (name, undefined_section,
+ 0, &zero_address_frag);
+
+ tag_insert (S_GET_NAME (symbolP), symbolP);
+#ifdef BFD_ASSEMBLER
+ symbol_table_insert (symbolP);
+#endif
+ } /* not found */
+
+ return symbolP;
+}
+
+/* We accept the .bss directive to set the section for backward
+ compatibility with earlier versions of gas. */
+
+static void
+obj_coff_bss (ignore)
+ int ignore;
+{
+ if (*input_line_pointer == '\n')
+ subseg_new (".bss", get_absolute_expression ());
+ else
+ s_lcomm (0);
+}
+
+/* Handle .weak. This is a GNU extension. */
+
+static void
+obj_coff_weak (ignore)
+ int ignore;
+{
+ char *name;
+ int c;
+ symbolS *symbolP;
+
+ do
+ {
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ symbolP = symbol_find_or_make (name);
+ *input_line_pointer = c;
+ SKIP_WHITESPACE ();
+
+#ifdef BFD_ASSEMLER
+ S_SET_WEAK (symbolP);
+#endif
+
+#ifdef TE_PE
+ S_SET_STORAGE_CLASS (symbolP, C_NT_WEAK);
+#else
+ S_SET_STORAGE_CLASS (symbolP, C_WEAKEXT);
+#endif
+
+ if (c == ',')
+ {
+ input_line_pointer++;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '\n')
+ c = '\n';
+ }
+ }
+ while (c == ',');
+
+ demand_empty_rest_of_line ();
+}
+
+#ifdef BFD_ASSEMBLER
+
+static void SA_SET_SYM_TAGNDX PARAMS ((symbolS *, symbolS *));
+
+#define GET_FILENAME_STRING(X) \
+((char*)(&((X)->sy_symbol.ost_auxent->x_file.x_n.x_offset))[1])
+
+/* @@ Ick. */
+static segT
+fetch_coff_debug_section ()
+{
+ static segT debug_section;
+ if (!debug_section)
+ {
+ CONST asymbol *s;
+ s = bfd_make_debug_symbol (stdoutput, (char *) 0, 0);
+ assert (s != 0);
+ debug_section = s->section;
+ }
+ return debug_section;
+}
+
+void
+SA_SET_SYM_ENDNDX (sym, val)
+ symbolS *sym;
+ symbolS *val;
+{
+ combined_entry_type *entry, *p;
+
+ entry = &coffsymbol (sym->bsym)->native[1];
+ p = coffsymbol (val->bsym)->native;
+ entry->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p = p;
+ entry->fix_end = 1;
+}
+
+static void
+SA_SET_SYM_TAGNDX (sym, val)
+ symbolS *sym;
+ symbolS *val;
+{
+ combined_entry_type *entry, *p;
+
+ entry = &coffsymbol (sym->bsym)->native[1];
+ p = coffsymbol (val->bsym)->native;
+ entry->u.auxent.x_sym.x_tagndx.p = p;
+ entry->fix_tag = 1;
+}
+
+static int
+S_GET_DATA_TYPE (sym)
+ symbolS *sym;
+{
+ return coffsymbol (sym->bsym)->native->u.syment.n_type;
+}
+
+int
+S_SET_DATA_TYPE (sym, val)
+ symbolS *sym;
+ int val;
+{
+ coffsymbol (sym->bsym)->native->u.syment.n_type = val;
+ return val;
+}
+
+int
+S_GET_STORAGE_CLASS (sym)
+ symbolS *sym;
+{
+ return coffsymbol (sym->bsym)->native->u.syment.n_sclass;
+}
+
+int
+S_SET_STORAGE_CLASS (sym, val)
+ symbolS *sym;
+ int val;
+{
+ coffsymbol (sym->bsym)->native->u.syment.n_sclass = val;
+ return val;
+}
+
+/* Merge a debug symbol containing debug information into a normal symbol. */
+
+void
+c_symbol_merge (debug, normal)
+ symbolS *debug;
+ symbolS *normal;
+{
+ S_SET_DATA_TYPE (normal, S_GET_DATA_TYPE (debug));
+ S_SET_STORAGE_CLASS (normal, S_GET_STORAGE_CLASS (debug));
+
+ if (S_GET_NUMBER_AUXILIARY (debug) > S_GET_NUMBER_AUXILIARY (normal))
+ {
+ /* take the most we have */
+ S_SET_NUMBER_AUXILIARY (normal, S_GET_NUMBER_AUXILIARY (debug));
+ }
+
+ if (S_GET_NUMBER_AUXILIARY (debug) > 0)
+ {
+ /* Move all the auxiliary information. */
+ memcpy (SYM_AUXINFO (normal), SYM_AUXINFO (debug),
+ (S_GET_NUMBER_AUXILIARY (debug)
+ * sizeof (*SYM_AUXINFO (debug))));
+ }
+
+ /* Move the debug flags. */
+ SF_SET_DEBUG_FIELD (normal, SF_GET_DEBUG_FIELD (debug));
+}
+
+void
+c_dot_file_symbol (filename)
+ char *filename;
+{
+ symbolS *symbolP;
+
+ symbolP = symbol_new (filename, bfd_abs_section_ptr, 0, &zero_address_frag);
+
+ S_SET_STORAGE_CLASS (symbolP, C_FILE);
+ S_SET_NUMBER_AUXILIARY (symbolP, 1);
+
+ symbolP->bsym->flags = BSF_DEBUGGING;
+
+#ifndef NO_LISTING
+ {
+ extern int listing;
+ if (listing)
+ {
+ listing_source_file (filename);
+ }
+ }
+#endif
+
+ /* Make sure that the symbol is first on the symbol chain */
+ if (symbol_rootP != symbolP)
+ {
+ symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
+ symbol_insert (symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP);
+ } /* if not first on the list */
+}
+
+/* Line number handling */
+
+struct line_no {
+ struct line_no *next;
+ fragS *frag;
+ alent l;
+};
+
+int coff_line_base;
+
+/* Symbol of last function, which we should hang line#s off of. */
+static symbolS *line_fsym;
+
+#define in_function() (line_fsym != 0)
+#define clear_function() (line_fsym = 0)
+#define set_function(F) (line_fsym = (F), coff_add_linesym (F))
+
+
+void
+coff_obj_symbol_new_hook (symbolP)
+ symbolS *symbolP;
+{
+ long sz = (OBJ_COFF_MAX_AUXENTRIES + 1) * sizeof (combined_entry_type);
+ char * s = (char *) xmalloc (sz);
+
+ memset (s, 0, sz);
+ coffsymbol (symbolP->bsym)->native = (combined_entry_type *) s;
+
+ S_SET_DATA_TYPE (symbolP, T_NULL);
+ S_SET_STORAGE_CLASS (symbolP, 0);
+ S_SET_NUMBER_AUXILIARY (symbolP, 0);
+
+ if (S_IS_STRING (symbolP))
+ SF_SET_STRING (symbolP);
+
+ if (S_IS_LOCAL (symbolP))
+ SF_SET_LOCAL (symbolP);
+}
+
+
+/*
+ * Handle .ln directives.
+ */
+
+static symbolS *current_lineno_sym;
+static struct line_no *line_nos;
+/* @@ Blindly assume all .ln directives will be in the .text section... */
+int coff_n_line_nos;
+
+static void
+add_lineno (frag, offset, num)
+ fragS *frag;
+ int offset;
+ int num;
+{
+ struct line_no *new_line =
+ (struct line_no *) xmalloc (sizeof (struct line_no));
+ if (!current_lineno_sym)
+ {
+ abort ();
+ }
+ new_line->next = line_nos;
+ new_line->frag = frag;
+ new_line->l.line_number = num;
+ new_line->l.u.offset = offset;
+ line_nos = new_line;
+ coff_n_line_nos++;
+}
+
+void
+coff_add_linesym (sym)
+ symbolS *sym;
+{
+ if (line_nos)
+ {
+ coffsymbol (current_lineno_sym->bsym)->lineno = (alent *) line_nos;
+ coff_n_line_nos++;
+ line_nos = 0;
+ }
+ current_lineno_sym = sym;
+}
+
+static void
+obj_coff_ln (appline)
+ int appline;
+{
+ int l;
+
+ if (! appline && def_symbol_in_progress != NULL)
+ {
+ as_warn (_(".ln pseudo-op inside .def/.endef: ignored."));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ l = get_absolute_expression ();
+ if (!appline)
+ {
+ add_lineno (frag_now, frag_now_fix (), l);
+ }
+
+ if (appline)
+ new_logical_line ((char *) NULL, l - 1);
+
+#ifndef NO_LISTING
+ {
+ extern int listing;
+
+ if (listing)
+ {
+ if (! appline)
+ l += coff_line_base - 1;
+ listing_source_line (l);
+ }
+ }
+#endif
+
+ demand_empty_rest_of_line ();
+}
+
+/*
+ * def()
+ *
+ * Handle .def directives.
+ *
+ * One might ask : why can't we symbol_new if the symbol does not
+ * already exist and fill it with debug information. Because of
+ * the C_EFCN special symbol. It would clobber the value of the
+ * function symbol before we have a chance to notice that it is
+ * a C_EFCN. And a second reason is that the code is more clear this
+ * way. (at least I think it is :-).
+ *
+ */
+
+#define SKIP_SEMI_COLON() while (*input_line_pointer++ != ';')
+#define SKIP_WHITESPACES() while (*input_line_pointer == ' ' || \
+ *input_line_pointer == '\t') \
+ input_line_pointer++;
+
+static void
+obj_coff_def (what)
+ int what;
+{
+ char name_end; /* Char after the end of name */
+ char *symbol_name; /* Name of the debug symbol */
+ char *symbol_name_copy; /* Temporary copy of the name */
+ unsigned int symbol_name_length;
+
+ if (def_symbol_in_progress != NULL)
+ {
+ as_warn (_(".def pseudo-op used inside of .def/.endef: ignored."));
+ demand_empty_rest_of_line ();
+ return;
+ } /* if not inside .def/.endef */
+
+ SKIP_WHITESPACES ();
+
+ symbol_name = input_line_pointer;
+#ifdef STRIP_UNDERSCORE
+ if (symbol_name[0] == '_' && symbol_name[1] != 0)
+ symbol_name++;
+#endif /* STRIP_UNDERSCORE */
+
+ name_end = get_symbol_end ();
+ symbol_name_length = strlen (symbol_name);
+ symbol_name_copy = xmalloc (symbol_name_length + 1);
+ strcpy (symbol_name_copy, symbol_name);
+#ifdef tc_canonicalize_symbol_name
+ symbol_name_copy = tc_canonicalize_symbol_name (symbol_name_copy);
+#endif
+
+ /* Initialize the new symbol */
+ def_symbol_in_progress = symbol_make (symbol_name_copy);
+ def_symbol_in_progress->sy_frag = &zero_address_frag;
+ S_SET_VALUE (def_symbol_in_progress, 0);
+
+ if (S_IS_STRING (def_symbol_in_progress))
+ SF_SET_STRING (def_symbol_in_progress);
+
+ *input_line_pointer = name_end;
+
+ demand_empty_rest_of_line ();
+}
+
+unsigned int dim_index;
+
+static void
+obj_coff_endef (ignore)
+ int ignore;
+{
+ symbolS *symbolP;
+
+ /* DIM BUG FIX sac@cygnus.com */
+ dim_index = 0;
+ if (def_symbol_in_progress == NULL)
+ {
+ as_warn (_(".endef pseudo-op used outside of .def/.endef: ignored."));
+ demand_empty_rest_of_line ();
+ return;
+ } /* if not inside .def/.endef */
+
+ /* Set the section number according to storage class. */
+ switch (S_GET_STORAGE_CLASS (def_symbol_in_progress))
+ {
+ case C_STRTAG:
+ case C_ENTAG:
+ case C_UNTAG:
+ SF_SET_TAG (def_symbol_in_progress);
+ /* intentional fallthrough */
+ case C_FILE:
+ case C_TPDEF:
+ SF_SET_DEBUG (def_symbol_in_progress);
+ S_SET_SEGMENT (def_symbol_in_progress, fetch_coff_debug_section ());
+ break;
+
+ case C_EFCN:
+ SF_SET_LOCAL (def_symbol_in_progress); /* Do not emit this symbol. */
+ /* intentional fallthrough */
+ case C_BLOCK:
+ SF_SET_PROCESS (def_symbol_in_progress); /* Will need processing before writing */
+ /* intentional fallthrough */
+ case C_FCN:
+ {
+ CONST char *name;
+ S_SET_SEGMENT (def_symbol_in_progress, text_section);
+
+ name = bfd_asymbol_name (def_symbol_in_progress->bsym);
+ if (name[1] == 'b' && name[2] == 'f')
+ {
+ if (! in_function ())
+ as_warn (_("`%s' symbol without preceding function"), name);
+/* SA_SET_SYM_LNNO (def_symbol_in_progress, 12345);*/
+ /* Will need relocating */
+ SF_SET_PROCESS (def_symbol_in_progress);
+ clear_function ();
+ }
+ }
+ break;
+
+#ifdef C_AUTOARG
+ case C_AUTOARG:
+#endif /* C_AUTOARG */
+ case C_AUTO:
+ case C_REG:
+ case C_ARG:
+ case C_REGPARM:
+ case C_FIELD:
+ SF_SET_DEBUG (def_symbol_in_progress);
+ S_SET_SEGMENT (def_symbol_in_progress, absolute_section);
+ break;
+
+ case C_MOS:
+ case C_MOE:
+ case C_MOU:
+ case C_EOS:
+ S_SET_SEGMENT (def_symbol_in_progress, absolute_section);
+ break;
+
+ case C_EXT:
+ case C_WEAKEXT:
+#ifdef TE_PE
+ case C_NT_WEAK:
+#endif
+ case C_STAT:
+ case C_LABEL:
+ /* Valid but set somewhere else (s_comm, s_lcomm, colon) */
+ break;
+
+ default:
+ case C_USTATIC:
+ case C_EXTDEF:
+ case C_ULABEL:
+ as_warn (_("unexpected storage class %d"),
+ S_GET_STORAGE_CLASS (def_symbol_in_progress));
+ break;
+ } /* switch on storage class */
+
+ /* Now that we have built a debug symbol, try to find if we should
+ merge with an existing symbol or not. If a symbol is C_EFCN or
+ SEG_ABSOLUTE or untagged SEG_DEBUG it never merges. */
+
+ /* Two cases for functions. Either debug followed by definition or
+ definition followed by debug. For definition first, we will
+ merge the debug symbol into the definition. For debug first, the
+ lineno entry MUST point to the definition function or else it
+ will point off into space when obj_crawl_symbol_chain() merges
+ the debug symbol into the real symbol. Therefor, let's presume
+ the debug symbol is a real function reference. */
+
+ /* FIXME-SOON If for some reason the definition label/symbol is
+ never seen, this will probably leave an undefined symbol at link
+ time. */
+
+ if (S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_EFCN
+ || (!strcmp (bfd_get_section_name (stdoutput,
+ S_GET_SEGMENT (def_symbol_in_progress)),
+ "*DEBUG*")
+ && !SF_GET_TAG (def_symbol_in_progress))
+ || S_GET_SEGMENT (def_symbol_in_progress) == absolute_section
+ || (symbolP = symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP)) == NULL)
+ {
+ if (def_symbol_in_progress != symbol_lastP)
+ symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP,
+ &symbol_lastP);
+ }
+ else
+ {
+ /* This symbol already exists, merge the newly created symbol
+ into the old one. This is not mandatory. The linker can
+ handle duplicate symbols correctly. But I guess that it save
+ a *lot* of space if the assembly file defines a lot of
+ symbols. [loic] */
+
+ /* The debug entry (def_symbol_in_progress) is merged into the
+ previous definition. */
+
+ c_symbol_merge (def_symbol_in_progress, symbolP);
+ symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
+
+ def_symbol_in_progress = symbolP;
+
+ if (SF_GET_FUNCTION (def_symbol_in_progress)
+ || SF_GET_TAG (def_symbol_in_progress)
+ || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_STAT)
+ {
+ /* For functions, and tags, and static symbols, the symbol
+ *must* be where the debug symbol appears. Move the
+ existing symbol to the current place. */
+ /* If it already is at the end of the symbol list, do nothing */
+ if (def_symbol_in_progress != symbol_lastP)
+ {
+ symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
+ symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
+ }
+ }
+ }
+
+ if (SF_GET_TAG (def_symbol_in_progress))
+ {
+ symbolS *oldtag;
+
+ oldtag = symbol_find_base (S_GET_NAME (def_symbol_in_progress),
+ DO_NOT_STRIP);
+ if (oldtag == NULL || ! SF_GET_TAG (oldtag))
+ tag_insert (S_GET_NAME (def_symbol_in_progress),
+ def_symbol_in_progress);
+ }
+
+ if (SF_GET_FUNCTION (def_symbol_in_progress))
+ {
+ know (sizeof (def_symbol_in_progress) <= sizeof (long));
+ set_function (def_symbol_in_progress);
+ SF_SET_PROCESS (def_symbol_in_progress);
+
+ if (symbolP == NULL)
+ {
+ /* That is, if this is the first time we've seen the
+ function... */
+ symbol_table_insert (def_symbol_in_progress);
+ } /* definition follows debug */
+ } /* Create the line number entry pointing to the function being defined */
+
+ def_symbol_in_progress = NULL;
+ demand_empty_rest_of_line ();
+}
+
+static void
+obj_coff_dim (ignore)
+ int ignore;
+{
+ int dim_index;
+
+ if (def_symbol_in_progress == NULL)
+ {
+ as_warn (_(".dim pseudo-op used outside of .def/.endef: ignored."));
+ demand_empty_rest_of_line ();
+ return;
+ } /* if not inside .def/.endef */
+
+ S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
+
+ for (dim_index = 0; dim_index < DIMNUM; dim_index++)
+ {
+ SKIP_WHITESPACES ();
+ SA_SET_SYM_DIMEN (def_symbol_in_progress, dim_index,
+ get_absolute_expression ());
+
+ switch (*input_line_pointer)
+ {
+ case ',':
+ input_line_pointer++;
+ break;
+
+ default:
+ as_warn (_("badly formed .dim directive ignored"));
+ /* intentional fallthrough */
+ case '\n':
+ case ';':
+ dim_index = DIMNUM;
+ break;
+ }
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+static void
+obj_coff_line (ignore)
+ int ignore;
+{
+ int this_base;
+
+ if (def_symbol_in_progress == NULL)
+ {
+ /* Probably stabs-style line? */
+ obj_coff_ln (0);
+ return;
+ }
+
+ this_base = get_absolute_expression ();
+ if (!strcmp (".bf", S_GET_NAME (def_symbol_in_progress)))
+ coff_line_base = this_base;
+
+ S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
+ SA_SET_SYM_LNNO (def_symbol_in_progress, coff_line_base);
+
+ demand_empty_rest_of_line ();
+
+#ifndef NO_LISTING
+ if (strcmp (".bf", S_GET_NAME (def_symbol_in_progress)) == 0)
+ {
+ extern int listing;
+
+ if (listing)
+ listing_source_line ((unsigned int) coff_line_base);
+ }
+#endif
+}
+
+static void
+obj_coff_size (ignore)
+ int ignore;
+{
+ if (def_symbol_in_progress == NULL)
+ {
+ as_warn (_(".size pseudo-op used outside of .def/.endef ignored."));
+ demand_empty_rest_of_line ();
+ return;
+ } /* if not inside .def/.endef */
+
+ S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
+ SA_SET_SYM_SIZE (def_symbol_in_progress, get_absolute_expression ());
+ demand_empty_rest_of_line ();
+}
+
+static void
+obj_coff_scl (ignore)
+ int ignore;
+{
+ if (def_symbol_in_progress == NULL)
+ {
+ as_warn (_(".scl pseudo-op used outside of .def/.endef ignored."));
+ demand_empty_rest_of_line ();
+ return;
+ } /* if not inside .def/.endef */
+
+ S_SET_STORAGE_CLASS (def_symbol_in_progress, get_absolute_expression ());
+ demand_empty_rest_of_line ();
+}
+
+static void
+obj_coff_tag (ignore)
+ int ignore;
+{
+ char *symbol_name;
+ char name_end;
+
+ if (def_symbol_in_progress == NULL)
+ {
+ as_warn (_(".tag pseudo-op used outside of .def/.endef ignored."));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
+ symbol_name = input_line_pointer;
+ name_end = get_symbol_end ();
+
+#ifdef tc_canonicalize_symbol_name
+ symbol_name = tc_canonicalize_symbol_name (symbol_name);
+#endif
+
+ /* Assume that the symbol referred to by .tag is always defined.
+ This was a bad assumption. I've added find_or_make. xoxorich. */
+ SA_SET_SYM_TAGNDX (def_symbol_in_progress,
+ tag_find_or_make (symbol_name));
+ if (SA_GET_SYM_TAGNDX (def_symbol_in_progress) == 0L)
+ {
+ as_warn (_("tag not found for .tag %s"), symbol_name);
+ } /* not defined */
+
+ SF_SET_TAGGED (def_symbol_in_progress);
+ *input_line_pointer = name_end;
+
+ demand_empty_rest_of_line ();
+}
+
+static void
+obj_coff_type (ignore)
+ int ignore;
+{
+ if (def_symbol_in_progress == NULL)
+ {
+ as_warn (_(".type pseudo-op used outside of .def/.endef ignored."));
+ demand_empty_rest_of_line ();
+ return;
+ } /* if not inside .def/.endef */
+
+ S_SET_DATA_TYPE (def_symbol_in_progress, get_absolute_expression ());
+
+ if (ISFCN (S_GET_DATA_TYPE (def_symbol_in_progress)) &&
+ S_GET_STORAGE_CLASS (def_symbol_in_progress) != C_TPDEF)
+ {
+ SF_SET_FUNCTION (def_symbol_in_progress);
+ } /* is a function */
+
+ demand_empty_rest_of_line ();
+}
+
+static void
+obj_coff_val (ignore)
+ int ignore;
+{
+ if (def_symbol_in_progress == NULL)
+ {
+ as_warn (_(".val pseudo-op used outside of .def/.endef ignored."));
+ demand_empty_rest_of_line ();
+ return;
+ } /* if not inside .def/.endef */
+
+ if (is_name_beginner (*input_line_pointer))
+ {
+ char *symbol_name = input_line_pointer;
+ char name_end = get_symbol_end ();
+
+#ifdef tc_canonicalize_symbol_name
+ symbol_name = tc_canonicalize_symbol_name (symbol_name);
+#endif
+ if (!strcmp (symbol_name, "."))
+ {
+ def_symbol_in_progress->sy_frag = frag_now;
+ S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ());
+ /* If the .val is != from the .def (e.g. statics) */
+ }
+ else if (strcmp (S_GET_NAME (def_symbol_in_progress), symbol_name))
+ {
+ def_symbol_in_progress->sy_value.X_op = O_symbol;
+ def_symbol_in_progress->sy_value.X_add_symbol =
+ symbol_find_or_make (symbol_name);
+ def_symbol_in_progress->sy_value.X_op_symbol = NULL;
+ def_symbol_in_progress->sy_value.X_add_number = 0;
+
+ /* If the segment is undefined when the forward reference is
+ resolved, then copy the segment id from the forward
+ symbol. */
+ SF_SET_GET_SEGMENT (def_symbol_in_progress);
+ }
+ /* Otherwise, it is the name of a non debug symbol and its value will be calculated later. */
+ *input_line_pointer = name_end;
+ }
+ else
+ {
+ S_SET_VALUE (def_symbol_in_progress, get_absolute_expression ());
+ } /* if symbol based */
+
+ demand_empty_rest_of_line ();
+}
+
+void
+coff_obj_read_begin_hook ()
+{
+ /* These had better be the same. Usually 18 bytes. */
+#ifndef BFD_HEADERS
+ know (sizeof (SYMENT) == sizeof (AUXENT));
+ know (SYMESZ == AUXESZ);
+#endif
+ tag_init ();
+}
+
+
+symbolS *coff_last_function;
+static symbolS *coff_last_bf;
+
+void
+coff_frob_symbol (symp, punt)
+ symbolS *symp;
+ int *punt;
+{
+ static symbolS *last_tagP;
+ static stack *block_stack;
+ static symbolS *set_end;
+ symbolS *next_set_end = NULL;
+
+ if (symp == &abs_symbol)
+ {
+ *punt = 1;
+ return;
+ }
+
+ if (current_lineno_sym)
+ coff_add_linesym ((symbolS *) 0);
+
+ if (!block_stack)
+ block_stack = stack_init (512, sizeof (symbolS*));
+
+ if (S_IS_WEAK (symp))
+ {
+#ifdef TE_PE
+ S_SET_STORAGE_CLASS (symp, C_NT_WEAK);
+#else
+ S_SET_STORAGE_CLASS (symp, C_WEAKEXT);
+#endif
+ }
+
+ if (!S_IS_DEFINED (symp)
+ && !S_IS_WEAK (symp)
+ && S_GET_STORAGE_CLASS (symp) != C_STAT)
+ S_SET_STORAGE_CLASS (symp, C_EXT);
+
+ if (!SF_GET_DEBUG (symp))
+ {
+ symbolS *real;
+ if (!SF_GET_LOCAL (symp)
+ && !SF_GET_STATICS (symp)
+ && (real = symbol_find_base (S_GET_NAME (symp), DO_NOT_STRIP))
+ && real != symp)
+ {
+ c_symbol_merge (symp, real);
+ *punt = 1;
+ }
+ if (!S_IS_DEFINED (symp) && !SF_GET_LOCAL (symp))
+ {
+ assert (S_GET_VALUE (symp) == 0);
+ S_SET_EXTERNAL (symp);
+ }
+ else if (S_GET_STORAGE_CLASS (symp) == C_NULL)
+ {
+ if (S_GET_SEGMENT (symp) == text_section
+ && symp != seg_info (text_section)->sym)
+ S_SET_STORAGE_CLASS (symp, C_LABEL);
+ else
+ S_SET_STORAGE_CLASS (symp, C_STAT);
+ }
+ if (SF_GET_PROCESS (symp))
+ {
+ if (S_GET_STORAGE_CLASS (symp) == C_BLOCK)
+ {
+ if (!strcmp (S_GET_NAME (symp), ".bb"))
+ stack_push (block_stack, (char *) &symp);
+ else
+ {
+ symbolS *begin;
+ begin = *(symbolS **) stack_pop (block_stack);
+ if (begin == 0)
+ as_warn (_("mismatched .eb"));
+ else
+ next_set_end = begin;
+ }
+ }
+ if (coff_last_function == 0 && SF_GET_FUNCTION (symp))
+ {
+ union internal_auxent *auxp;
+ coff_last_function = symp;
+ if (S_GET_NUMBER_AUXILIARY (symp) < 1)
+ S_SET_NUMBER_AUXILIARY (symp, 1);
+ auxp = &coffsymbol (symp->bsym)->native[1].u.auxent;
+ memset (auxp->x_sym.x_fcnary.x_ary.x_dimen, 0,
+ sizeof (auxp->x_sym.x_fcnary.x_ary.x_dimen));
+ }
+ if (S_GET_STORAGE_CLASS (symp) == C_EFCN)
+ {
+ if (coff_last_function == 0)
+ as_fatal (_("C_EFCN symbol out of scope"));
+ SA_SET_SYM_FSIZE (coff_last_function,
+ (long) (S_GET_VALUE (symp)
+ - S_GET_VALUE (coff_last_function)));
+ next_set_end = coff_last_function;
+ coff_last_function = 0;
+ }
+ }
+ if (S_IS_EXTERNAL (symp))
+ S_SET_STORAGE_CLASS (symp, C_EXT);
+ else if (SF_GET_LOCAL (symp))
+ *punt = 1;
+
+ if (SF_GET_FUNCTION (symp))
+ symp->bsym->flags |= BSF_FUNCTION;
+
+ /* more ... */
+ }
+
+ if (SF_GET_TAG (symp))
+ last_tagP = symp;
+ else if (S_GET_STORAGE_CLASS (symp) == C_EOS)
+ next_set_end = last_tagP;
+
+#ifdef OBJ_XCOFF
+ /* This is pretty horrible, but we have to set *punt correctly in
+ order to call SA_SET_SYM_ENDNDX correctly. */
+ if (! symp->sy_used_in_reloc
+ && ((symp->bsym->flags & BSF_SECTION_SYM) != 0
+ || (! S_IS_EXTERNAL (symp)
+ && ! symp->sy_tc.output
+ && S_GET_STORAGE_CLASS (symp) != C_FILE)))
+ *punt = 1;
+#endif
+
+ if (set_end != (symbolS *) NULL
+ && ! *punt
+ && ((symp->bsym->flags & BSF_NOT_AT_END) != 0
+ || (S_IS_DEFINED (symp)
+ && ! S_IS_COMMON (symp)
+ && (! S_IS_EXTERNAL (symp) || SF_GET_FUNCTION (symp)))))
+ {
+ SA_SET_SYM_ENDNDX (set_end, symp);
+ set_end = NULL;
+ }
+
+ if (next_set_end != NULL
+ && ! *punt)
+ set_end = next_set_end;
+
+ if (! *punt
+ && S_GET_STORAGE_CLASS (symp) == C_FCN
+ && strcmp (S_GET_NAME (symp), ".bf") == 0)
+ {
+ if (coff_last_bf != NULL)
+ SA_SET_SYM_ENDNDX (coff_last_bf, symp);
+ coff_last_bf = symp;
+ }
+
+ if (coffsymbol (symp->bsym)->lineno)
+ {
+ int i;
+ struct line_no *lptr;
+ alent *l;
+
+ lptr = (struct line_no *) coffsymbol (symp->bsym)->lineno;
+ for (i = 0; lptr; lptr = lptr->next)
+ i++;
+ lptr = (struct line_no *) coffsymbol (symp->bsym)->lineno;
+
+ /* We need i entries for line numbers, plus 1 for the first
+ entry which BFD will override, plus 1 for the last zero
+ entry (a marker for BFD). */
+ l = (alent *) xmalloc ((i + 2) * sizeof (alent));
+ coffsymbol (symp->bsym)->lineno = l;
+ l[i + 1].line_number = 0;
+ l[i + 1].u.sym = NULL;
+ for (; i > 0; i--)
+ {
+ if (lptr->frag)
+ lptr->l.u.offset += lptr->frag->fr_address;
+ l[i] = lptr->l;
+ lptr = lptr->next;
+ }
+ }
+}
+
+void
+coff_adjust_section_syms (abfd, sec, x)
+ bfd *abfd;
+ asection *sec;
+ PTR x;
+{
+ symbolS *secsym;
+ segment_info_type *seginfo = seg_info (sec);
+ int nlnno, nrelocs = 0;
+
+ /* RS/6000 gas creates a .debug section manually in ppc_frob_file in
+ tc-ppc.c. Do not get confused by it. */
+ if (seginfo == NULL)
+ return;
+
+ if (!strcmp (sec->name, ".text"))
+ nlnno = coff_n_line_nos;
+ else
+ nlnno = 0;
+ {
+ /* @@ Hope that none of the fixups expand to more than one reloc
+ entry... */
+ fixS *fixp = seginfo->fix_root;
+ while (fixp)
+ {
+ if (! fixp->fx_done)
+ nrelocs++;
+ fixp = fixp->fx_next;
+ }
+ }
+ if (bfd_get_section_size_before_reloc (sec) == 0
+ && nrelocs == 0
+ && nlnno == 0
+ && sec != text_section
+ && sec != data_section
+ && sec != bss_section)
+ return;
+ secsym = section_symbol (sec);
+ SA_SET_SCN_NRELOC (secsym, nrelocs);
+ SA_SET_SCN_NLINNO (secsym, nlnno);
+}
+
+void
+coff_frob_file_after_relocs ()
+{
+ bfd_map_over_sections (stdoutput, coff_adjust_section_syms, (char*) 0);
+}
+
+/*
+ * implement the .section pseudo op:
+ * .section name {, "flags"}
+ * ^ ^
+ * | +--- optional flags: 'b' for bss
+ * | 'i' for info
+ * +-- section name 'l' for lib
+ * 'n' for noload
+ * 'o' for over
+ * 'w' for data
+ * 'd' (apparently m88k for data)
+ * 'x' for text
+ * 'r' for read-only data
+ * But if the argument is not a quoted string, treat it as a
+ * subsegment number.
+ */
+
+void
+obj_coff_section (ignore)
+ int ignore;
+{
+ /* Strip out the section name */
+ char *section_name;
+ char c;
+ char *name;
+ unsigned int exp;
+ flagword flags;
+ asection *sec;
+
+ if (flag_mri)
+ {
+ char type;
+
+ s_mri_sect (&type);
+ return;
+ }
+
+ section_name = input_line_pointer;
+ c = get_symbol_end ();
+
+ name = xmalloc (input_line_pointer - section_name + 1);
+ strcpy (name, section_name);
+
+ *input_line_pointer = c;
+
+ SKIP_WHITESPACE ();
+
+ exp = 0;
+ flags = SEC_NO_FLAGS;
+
+ if (*input_line_pointer == ',')
+ {
+ ++input_line_pointer;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != '"')
+ exp = get_absolute_expression ();
+ else
+ {
+ ++input_line_pointer;
+ while (*input_line_pointer != '"'
+ && ! is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ switch (*input_line_pointer)
+ {
+ case 'b': flags |= SEC_ALLOC; flags &=~ SEC_LOAD; break;
+ case 'n': flags &=~ SEC_LOAD; break;
+ case 'd':
+ case 'w': flags &=~ SEC_READONLY; break;
+ case 'x': flags |= SEC_CODE; break;
+ case 'r': flags |= SEC_READONLY; break;
+
+ case 'i': /* STYP_INFO */
+ case 'l': /* STYP_LIB */
+ case 'o': /* STYP_OVER */
+ as_warn (_("unsupported section attribute '%c'"),
+ *input_line_pointer);
+ break;
+
+ default:
+ as_warn(_("unknown section attribute '%c'"),
+ *input_line_pointer);
+ break;
+ }
+ ++input_line_pointer;
+ }
+ if (*input_line_pointer == '"')
+ ++input_line_pointer;
+ }
+ }
+
+ sec = subseg_new (name, (subsegT) exp);
+
+ if (flags != SEC_NO_FLAGS)
+ {
+ flagword oldflags;
+
+ oldflags = bfd_get_section_flags (stdoutput, sec);
+ oldflags &= SEC_LINK_ONCE | SEC_LINK_DUPLICATES;
+ flags |= oldflags;
+
+ if (! bfd_set_section_flags (stdoutput, sec, flags))
+ as_warn (_("error setting flags for \"%s\": %s"),
+ bfd_section_name (stdoutput, sec),
+ bfd_errmsg (bfd_get_error ()));
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+void
+coff_adjust_symtab ()
+{
+ if (symbol_rootP == NULL
+ || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE)
+ c_dot_file_symbol ("fake");
+}
+
+void
+coff_frob_section (sec)
+ segT sec;
+{
+ segT strsec;
+ char *p;
+ fragS *fragp;
+ bfd_vma size, n_entries, mask;
+
+ /* The COFF back end in BFD requires that all section sizes be
+ rounded up to multiples of the corresponding section alignments.
+ Seems kinda silly to me, but that's the way it is. */
+ size = bfd_get_section_size_before_reloc (sec);
+ mask = ((bfd_vma) 1 << (bfd_vma) sec->alignment_power) - 1;
+ if (size & mask)
+ {
+ size = (size + mask) & ~mask;
+ bfd_set_section_size (stdoutput, sec, size);
+ }
+
+ /* If the section size is non-zero, the section symbol needs an aux
+ entry associated with it, indicating the size. We don't know
+ all the values yet; coff_frob_symbol will fill them in later. */
+ if (size != 0
+ || sec == text_section
+ || sec == data_section
+ || sec == bss_section)
+ {
+ symbolS *secsym = section_symbol (sec);
+
+ S_SET_STORAGE_CLASS (secsym, C_STAT);
+ S_SET_NUMBER_AUXILIARY (secsym, 1);
+ SF_SET_STATICS (secsym);
+ SA_SET_SCN_SCNLEN (secsym, size);
+ }
+
+ /* @@ these should be in a "stabs.h" file, or maybe as.h */
+#ifndef STAB_SECTION_NAME
+#define STAB_SECTION_NAME ".stab"
+#endif
+#ifndef STAB_STRING_SECTION_NAME
+#define STAB_STRING_SECTION_NAME ".stabstr"
+#endif
+ if (strcmp (STAB_STRING_SECTION_NAME, sec->name))
+ return;
+
+ strsec = sec;
+ sec = subseg_get (STAB_SECTION_NAME, 0);
+ /* size is already rounded up, since other section will be listed first */
+ size = bfd_get_section_size_before_reloc (strsec);
+
+ n_entries = bfd_get_section_size_before_reloc (sec) / 12 - 1;
+
+ /* Find first non-empty frag. It should be large enough. */
+ fragp = seg_info (sec)->frchainP->frch_root;
+ while (fragp && fragp->fr_fix == 0)
+ fragp = fragp->fr_next;
+ assert (fragp != 0 && fragp->fr_fix >= 12);
+
+ /* Store the values. */
+ p = fragp->fr_literal;
+ bfd_h_put_16 (stdoutput, n_entries, (bfd_byte *) p + 6);
+ bfd_h_put_32 (stdoutput, size, (bfd_byte *) p + 8);
+}
+
+void
+obj_coff_init_stab_section (seg)
+ segT seg;
+{
+ char *file;
+ char *p;
+ char *stabstr_name;
+ unsigned int stroff;
+
+ /* Make space for this first symbol. */
+ p = frag_more (12);
+ /* Zero it out. */
+ memset (p, 0, 12);
+ as_where (&file, (unsigned int *) NULL);
+ stabstr_name = (char *) alloca (strlen (seg->name) + 4);
+ strcpy (stabstr_name, seg->name);
+ strcat (stabstr_name, "str");
+ stroff = get_stab_string_offset (file, stabstr_name);
+ know (stroff == 1);
+ md_number_to_chars (p, stroff, 4);
+}
+
+#ifdef DEBUG
+/* for debugging */
+const char *
+s_get_name (s)
+ symbolS *s;
+{
+ return ((s == NULL) ? "(NULL)" : S_GET_NAME (s));
+}
+
+void
+symbol_dump ()
+{
+ symbolS *symbolP;
+
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
+ {
+ printf(_("0x%lx: \"%s\" type = %ld, class = %d, segment = %d\n"),
+ (unsigned long) symbolP,
+ S_GET_NAME(symbolP),
+ (long) S_GET_DATA_TYPE(symbolP),
+ S_GET_STORAGE_CLASS(symbolP),
+ (int) S_GET_SEGMENT(symbolP));
+ }
+}
+
+#endif /* DEBUG */
+
+#else /* not BFD_ASSEMBLER */
+
+#include "frags.h"
+/* This is needed because we include internal bfd things. */
+#include <time.h>
+
+#include "libbfd.h"
+#include "libcoff.h"
+
+#ifdef TE_PE
+#include "coff/pe.h"
+#endif
+
+/* The NOP_OPCODE is for the alignment fill value. Fill with nop so
+ that we can stick sections together without causing trouble. */
+#ifndef NOP_OPCODE
+#define NOP_OPCODE 0x00
+#endif
+
+/* The zeroes if symbol name is longer than 8 chars */
+#define S_SET_ZEROES(s,v) ((s)->sy_symbol.ost_entry.n_zeroes = (v))
+
+#define MIN(a,b) ((a) < (b)? (a) : (b))
+/* This vector is used to turn an internal segment into a section #
+ suitable for insertion into a coff symbol table
+ */
+
+const short seg_N_TYPE[] =
+{ /* in: segT out: N_TYPE bits */
+ C_ABS_SECTION,
+ 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,
+ C_UNDEF_SECTION, /* SEG_UNKNOWN */
+ C_UNDEF_SECTION, /* SEG_GOOF */
+ C_UNDEF_SECTION, /* SEG_EXPR */
+ C_DEBUG_SECTION, /* SEG_DEBUG */
+ C_NTV_SECTION, /* SEG_NTV */
+ C_PTV_SECTION, /* SEG_PTV */
+ C_REGISTER_SECTION, /* SEG_REGISTER */
+};
+
+int function_lineoff = -1; /* Offset in line#s where the last function
+ started (the odd entry for line #0) */
+
+/* structure used to keep the filenames which
+ are too long around so that we can stick them
+ into the string table */
+struct filename_list
+{
+ char *filename;
+ struct filename_list *next;
+};
+
+static struct filename_list *filename_list_head;
+static struct filename_list *filename_list_tail;
+
+static symbolS *last_line_symbol;
+
+/* Add 4 to the real value to get the index and compensate the
+ negatives. This vector is used by S_GET_SEGMENT to turn a coff
+ section number into a segment number
+*/
+static symbolS *previous_file_symbol;
+void c_symbol_merge ();
+static int line_base;
+
+symbolS *c_section_symbol ();
+bfd *abfd;
+
+static void fixup_segment PARAMS ((segment_info_type *segP,
+ segT this_segment_type));
+
+
+static void fixup_mdeps PARAMS ((fragS *,
+ object_headers *,
+ segT));
+
+
+static void fill_section PARAMS ((bfd * abfd,
+ object_headers *,
+ unsigned long *));
+
+
+static int c_line_new PARAMS ((symbolS * symbol, long paddr,
+ int line_number,
+ fragS * frag));
+
+
+static void w_symbols PARAMS ((bfd * abfd, char *where,
+ symbolS * symbol_rootP));
+
+static void adjust_stab_section PARAMS ((bfd *abfd, segT seg));
+
+static void obj_coff_lcomm PARAMS ((int));
+static void obj_coff_text PARAMS ((int));
+static void obj_coff_data PARAMS ((int));
+static void obj_coff_ident PARAMS ((int));
+void obj_coff_section PARAMS ((int));
+
+/* Section stuff
+
+ We allow more than just the standard 3 sections, infact, we allow
+ 40 sections, (though the usual three have to be there).
+
+ This structure performs the mappings for us:
+*/
+
+
+typedef struct
+{
+ segT seg_t;
+ int i;
+} seg_info_type;
+
+static const seg_info_type seg_info_off_by_4[] =
+{
+ {SEG_PTV, },
+ {SEG_NTV, },
+ {SEG_DEBUG, },
+ {SEG_ABSOLUTE, },
+ {SEG_UNKNOWN, },
+ {SEG_E0}, {SEG_E1}, {SEG_E2}, {SEG_E3}, {SEG_E4},
+ {SEG_E5}, {SEG_E6}, {SEG_E7}, {SEG_E8}, {SEG_E9},
+ {SEG_E10},{SEG_E11},{SEG_E12},{SEG_E13},{SEG_E14},
+ {SEG_E15},{SEG_E16},{SEG_E17},{SEG_E18},{SEG_E19},
+ {SEG_E20},{SEG_E21},{SEG_E22},{SEG_E23},{SEG_E24},
+ {SEG_E25},{SEG_E26},{SEG_E27},{SEG_E28},{SEG_E29},
+ {SEG_E30},{SEG_E31},{SEG_E32},{SEG_E33},{SEG_E34},
+ {SEG_E35},{SEG_E36},{SEG_E37},{SEG_E38},{SEG_E39},
+ {(segT)40},
+ {(segT)41},
+ {(segT)42},
+ {(segT)43},
+ {(segT)44},
+ {(segT)45},
+ {(segT)0},
+ {(segT)0},
+ {(segT)0},
+ {SEG_REGISTER}
+};
+
+
+
+#define SEG_INFO_FROM_SECTION_NUMBER(x) (seg_info_off_by_4[(x)+4])
+
+static relax_addressT
+relax_align (address, alignment)
+ relax_addressT address;
+ long alignment;
+{
+ relax_addressT mask;
+ relax_addressT new_address;
+
+ mask = ~((~0) << alignment);
+ new_address = (address + mask) & (~mask);
+ return (new_address - address);
+}
+
+
+segT
+s_get_segment (x)
+ symbolS * x;
+{
+ return SEG_INFO_FROM_SECTION_NUMBER (x->sy_symbol.ost_entry.n_scnum).seg_t;
+}
+
+/* calculate the size of the frag chain and fill in the section header
+ to contain all of it, also fill in the addr of the sections */
+static unsigned int
+size_section (abfd, idx)
+ bfd * abfd;
+ unsigned int idx;
+{
+
+ unsigned int size = 0;
+ fragS *frag = segment_info[idx].frchainP->frch_root;
+ while (frag)
+ {
+ size = frag->fr_address;
+ if (frag->fr_address != size)
+ {
+ fprintf (stderr, _("Out of step\n"));
+ size = frag->fr_address;
+ }
+
+ switch (frag->fr_type)
+ {
+#ifdef TC_COFF_SIZEMACHDEP
+ case rs_machine_dependent:
+ size += TC_COFF_SIZEMACHDEP (frag);
+ break;
+#endif
+ case rs_space:
+ assert (frag->fr_symbol == 0);
+ case rs_fill:
+ case rs_org:
+ size += frag->fr_fix;
+ size += frag->fr_offset * frag->fr_var;
+ break;
+ case rs_align:
+ case rs_align_code:
+ {
+ addressT off;
+
+ size += frag->fr_fix;
+ off = relax_align (size, frag->fr_offset);
+ if (frag->fr_subtype != 0 && off > frag->fr_subtype)
+ off = 0;
+ size += off;
+ }
+ break;
+ default:
+ BAD_CASE (frag->fr_type);
+ break;
+ }
+ frag = frag->fr_next;
+ }
+ segment_info[idx].scnhdr.s_size = size;
+ return size;
+}
+
+
+static unsigned int
+count_entries_in_chain (idx)
+ unsigned int idx;
+{
+ unsigned int nrelocs;
+ fixS *fixup_ptr;
+
+ /* Count the relocations */
+ fixup_ptr = segment_info[idx].fix_root;
+ nrelocs = 0;
+ while (fixup_ptr != (fixS *) NULL)
+ {
+ if (fixup_ptr->fx_done == 0 && TC_COUNT_RELOC (fixup_ptr))
+ {
+#ifdef TC_A29K
+ if (fixup_ptr->fx_r_type == RELOC_CONSTH)
+ nrelocs += 2;
+ else
+ nrelocs++;
+#else
+ nrelocs++;
+#endif
+ }
+
+ fixup_ptr = fixup_ptr->fx_next;
+ }
+ return nrelocs;
+}
+
+#ifdef TE_AUX
+
+static int compare_external_relocs PARAMS ((const PTR, const PTR));
+
+/* AUX's ld expects relocations to be sorted */
+static int
+compare_external_relocs (x, y)
+ const PTR x;
+ const PTR y;
+{
+ struct external_reloc *a = (struct external_reloc *) x;
+ struct external_reloc *b = (struct external_reloc *) y;
+ bfd_vma aadr = bfd_getb32 (a->r_vaddr);
+ bfd_vma badr = bfd_getb32 (b->r_vaddr);
+ return (aadr < badr ? -1 : badr < aadr ? 1 : 0);
+}
+
+#endif
+
+/* output all the relocations for a section */
+void
+do_relocs_for (abfd, h, file_cursor)
+ bfd * abfd;
+ object_headers * h;
+ unsigned long *file_cursor;
+{
+ unsigned int nrelocs;
+ unsigned int idx;
+ unsigned long reloc_start = *file_cursor;
+
+ for (idx = SEG_E0; idx < SEG_LAST; idx++)
+ {
+ if (segment_info[idx].scnhdr.s_name[0])
+ {
+ struct external_reloc *ext_ptr;
+ struct external_reloc *external_reloc_vec;
+ unsigned int external_reloc_size;
+ unsigned int base = segment_info[idx].scnhdr.s_paddr;
+ fixS *fix_ptr = segment_info[idx].fix_root;
+ nrelocs = count_entries_in_chain (idx);
+
+ if (nrelocs)
+ /* Bypass this stuff if no relocs. This also incidentally
+ avoids a SCO bug, where free(malloc(0)) tends to crash. */
+ {
+ external_reloc_size = nrelocs * RELSZ;
+ external_reloc_vec =
+ (struct external_reloc *) malloc (external_reloc_size);
+
+ ext_ptr = external_reloc_vec;
+
+ /* Fill in the internal coff style reloc struct from the
+ internal fix list. */
+ while (fix_ptr)
+ {
+ struct internal_reloc intr;
+
+ /* Only output some of the relocations */
+ if (fix_ptr->fx_done == 0 && TC_COUNT_RELOC (fix_ptr))
+ {
+#ifdef TC_RELOC_MANGLE
+ TC_RELOC_MANGLE (&segment_info[idx], fix_ptr, &intr,
+ base);
+
+#else
+ symbolS *dot;
+ symbolS *symbol_ptr = fix_ptr->fx_addsy;
+
+ intr.r_type = TC_COFF_FIX2RTYPE (fix_ptr);
+ intr.r_vaddr =
+ base + fix_ptr->fx_frag->fr_address + fix_ptr->fx_where;
+
+#ifdef TC_KEEP_FX_OFFSET
+ intr.r_offset = fix_ptr->fx_offset;
+#else
+ intr.r_offset = 0;
+#endif
+
+ while (symbol_ptr->sy_value.X_op == O_symbol
+ && (! S_IS_DEFINED (symbol_ptr)
+ || S_IS_COMMON (symbol_ptr)))
+ {
+ symbolS *n;
+
+ /* We must avoid looping, as that can occur
+ with a badly written program. */
+ n = symbol_ptr->sy_value.X_add_symbol;
+ if (n == symbol_ptr)
+ break;
+ symbol_ptr = n;
+ }
+
+ /* Turn the segment of the symbol into an offset. */
+ if (symbol_ptr)
+ {
+ resolve_symbol_value (symbol_ptr, 1);
+ if (! symbol_ptr->sy_resolved)
+ {
+ char *file;
+ unsigned int line;
+
+ if (expr_symbol_where (symbol_ptr, &file, &line))
+ as_bad_where (file, line,
+ _("unresolved relocation"));
+ else
+ as_bad (_("bad relocation: symbol `%s' not in symbol table"),
+ S_GET_NAME (symbol_ptr));
+ }
+ dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot;
+ if (dot)
+ {
+ intr.r_symndx = dot->sy_number;
+ }
+ else
+ {
+ intr.r_symndx = symbol_ptr->sy_number;
+ }
+
+ }
+ else
+ {
+ intr.r_symndx = -1;
+ }
+#endif
+
+ (void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr);
+ ext_ptr++;
+
+#if defined(TC_A29K)
+
+ /* The 29k has a special kludge for the high 16 bit
+ reloc. Two relocations are emited, R_IHIHALF,
+ and R_IHCONST. The second one doesn't contain a
+ symbol, but uses the value for offset. */
+
+ if (intr.r_type == R_IHIHALF)
+ {
+ /* now emit the second bit */
+ intr.r_type = R_IHCONST;
+ intr.r_symndx = fix_ptr->fx_addnumber;
+ (void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr);
+ ext_ptr++;
+ }
+#endif
+ }
+
+ fix_ptr = fix_ptr->fx_next;
+ }
+
+#ifdef TE_AUX
+ /* Sort the reloc table */
+ qsort ((PTR) external_reloc_vec, nrelocs,
+ sizeof (struct external_reloc), compare_external_relocs);
+#endif
+
+ /* Write out the reloc table */
+ bfd_write ((PTR) external_reloc_vec, 1, external_reloc_size,
+ abfd);
+ free (external_reloc_vec);
+
+ /* Fill in section header info. */
+ segment_info[idx].scnhdr.s_relptr = *file_cursor;
+ *file_cursor += external_reloc_size;
+ segment_info[idx].scnhdr.s_nreloc = nrelocs;
+ }
+ else
+ {
+ /* No relocs */
+ segment_info[idx].scnhdr.s_relptr = 0;
+ }
+ }
+ }
+ /* Set relocation_size field in file headers */
+ H_SET_RELOCATION_SIZE (h, *file_cursor - reloc_start, 0);
+}
+
+
+/* run through a frag chain and write out the data to go with it, fill
+ in the scnhdrs with the info on the file postions
+*/
+static void
+fill_section (abfd, h, file_cursor)
+ bfd * abfd;
+ object_headers *h;
+ unsigned long *file_cursor;
+{
+
+ unsigned int i;
+ unsigned int paddr = 0;
+
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ {
+ unsigned int offset = 0;
+ struct internal_scnhdr *s = &(segment_info[i].scnhdr);
+
+ PROGRESS (1);
+
+ if (s->s_name[0])
+ {
+ fragS *frag = segment_info[i].frchainP->frch_root;
+ char *buffer;
+
+ if (s->s_size == 0)
+ s->s_scnptr = 0;
+ else
+ {
+ buffer = xmalloc (s->s_size);
+ s->s_scnptr = *file_cursor;
+ }
+ know (s->s_paddr == paddr);
+
+ if (strcmp (s->s_name, ".text") == 0)
+ s->s_flags |= STYP_TEXT;
+ else if (strcmp (s->s_name, ".data") == 0)
+ s->s_flags |= STYP_DATA;
+ else if (strcmp (s->s_name, ".bss") == 0)
+ {
+ s->s_scnptr = 0;
+ s->s_flags |= STYP_BSS;
+
+ /* @@ Should make the i386 and a29k coff targets define
+ COFF_NOLOAD_PROBLEM, and have only one test here. */
+#ifndef TC_I386
+#ifndef TC_A29K
+#ifndef COFF_NOLOAD_PROBLEM
+ /* Apparently the SVR3 linker (and exec syscall) and UDI
+ mondfe progrem are confused by noload sections. */
+ s->s_flags |= STYP_NOLOAD;
+#endif
+#endif
+#endif
+ }
+ else if (strcmp (s->s_name, ".lit") == 0)
+ s->s_flags = STYP_LIT | STYP_TEXT;
+ else if (strcmp (s->s_name, ".init") == 0)
+ s->s_flags |= STYP_TEXT;
+ else if (strcmp (s->s_name, ".fini") == 0)
+ s->s_flags |= STYP_TEXT;
+ else if (strncmp (s->s_name, ".comment", 8) == 0)
+ s->s_flags |= STYP_INFO;
+
+ while (frag)
+ {
+ unsigned int fill_size;
+ switch (frag->fr_type)
+ {
+ case rs_machine_dependent:
+ if (frag->fr_fix)
+ {
+ memcpy (buffer + frag->fr_address,
+ frag->fr_literal,
+ (unsigned int) frag->fr_fix);
+ offset += frag->fr_fix;
+ }
+
+ break;
+ case rs_space:
+ assert (frag->fr_symbol == 0);
+ case rs_fill:
+ case rs_align:
+ case rs_align_code:
+ case rs_org:
+ if (frag->fr_fix)
+ {
+ memcpy (buffer + frag->fr_address,
+ frag->fr_literal,
+ (unsigned int) frag->fr_fix);
+ offset += frag->fr_fix;
+ }
+
+ fill_size = frag->fr_var;
+ if (fill_size && frag->fr_offset > 0)
+ {
+ unsigned int count;
+ unsigned int off = frag->fr_fix;
+ for (count = frag->fr_offset; count; count--)
+ {
+ if (fill_size + frag->fr_address + off <= s->s_size)
+ {
+ memcpy (buffer + frag->fr_address + off,
+ frag->fr_literal + frag->fr_fix,
+ fill_size);
+ off += fill_size;
+ offset += fill_size;
+ }
+ }
+ }
+ break;
+ case rs_broken_word:
+ break;
+ default:
+ abort ();
+ }
+ frag = frag->fr_next;
+ }
+
+ if (s->s_size != 0)
+ {
+ if (s->s_scnptr != 0)
+ {
+ bfd_write (buffer, s->s_size, 1, abfd);
+ *file_cursor += s->s_size;
+ }
+ free (buffer);
+ }
+ paddr += s->s_size;
+ }
+ }
+}
+
+/* Coff file generation & utilities */
+
+static void
+coff_header_append (abfd, h)
+ bfd * abfd;
+ object_headers * h;
+{
+ unsigned int i;
+ char buffer[1000];
+ char buffero[1000];
+#ifdef COFF_LONG_SECTION_NAMES
+ unsigned long string_size = 4;
+#endif
+
+ bfd_seek (abfd, 0, 0);
+
+#ifndef OBJ_COFF_OMIT_OPTIONAL_HEADER
+ H_SET_MAGIC_NUMBER (h, COFF_MAGIC);
+ H_SET_VERSION_STAMP (h, 0);
+ H_SET_ENTRY_POINT (h, 0);
+ H_SET_TEXT_START (h, segment_info[SEG_E0].frchainP->frch_root->fr_address);
+ H_SET_DATA_START (h, segment_info[SEG_E1].frchainP->frch_root->fr_address);
+ H_SET_SIZEOF_OPTIONAL_HEADER (h, bfd_coff_swap_aouthdr_out(abfd, &h->aouthdr,
+ buffero));
+#else /* defined (OBJ_COFF_OMIT_OPTIONAL_HEADER) */
+ H_SET_SIZEOF_OPTIONAL_HEADER (h, 0);
+#endif /* defined (OBJ_COFF_OMIT_OPTIONAL_HEADER) */
+
+ i = bfd_coff_swap_filehdr_out (abfd, &h->filehdr, buffer);
+
+ bfd_write (buffer, i, 1, abfd);
+ bfd_write (buffero, H_GET_SIZEOF_OPTIONAL_HEADER (h), 1, abfd);
+
+ for (i = SEG_E0; i < SEG_LAST; i++)
+ {
+ if (segment_info[i].scnhdr.s_name[0])
+ {
+ unsigned int size;
+
+#ifdef COFF_LONG_SECTION_NAMES
+ /* Support long section names as found in PE. This code
+ must coordinate with that in write_object_file and
+ w_strings. */
+ if (strlen (segment_info[i].name) > SCNNMLEN)
+ {
+ memset (segment_info[i].scnhdr.s_name, 0, SCNNMLEN);
+ sprintf (segment_info[i].scnhdr.s_name, "/%lu", string_size);
+ string_size += strlen (segment_info[i].name) + 1;
+ }
+#endif
+
+ size = bfd_coff_swap_scnhdr_out (abfd,
+ &(segment_info[i].scnhdr),
+ buffer);
+ if (size == 0)
+ as_bad (_("bfd_coff_swap_scnhdr_out failed"));
+ bfd_write (buffer, size, 1, abfd);
+ }
+ }
+}
+
+
+char *
+symbol_to_chars (abfd, where, symbolP)
+ bfd * abfd;
+ char *where;
+ symbolS * symbolP;
+{
+ unsigned int numaux = symbolP->sy_symbol.ost_entry.n_numaux;
+ unsigned int i;
+ valueT val;
+
+ /* Turn any symbols with register attributes into abs symbols */
+ if (S_GET_SEGMENT (symbolP) == reg_section)
+ {
+ S_SET_SEGMENT (symbolP, absolute_section);
+ }
+ /* At the same time, relocate all symbols to their output value */
+
+#ifndef TE_PE
+ val = (segment_info[S_GET_SEGMENT (symbolP)].scnhdr.s_paddr
+ + S_GET_VALUE (symbolP));
+#else
+ val = S_GET_VALUE (symbolP);
+#endif
+
+ S_SET_VALUE (symbolP, val);
+
+ symbolP->sy_symbol.ost_entry.n_value = val;
+
+ where += bfd_coff_swap_sym_out (abfd, &symbolP->sy_symbol.ost_entry,
+ where);
+
+ for (i = 0; i < numaux; i++)
+ {
+ where += bfd_coff_swap_aux_out (abfd,
+ &symbolP->sy_symbol.ost_auxent[i],
+ S_GET_DATA_TYPE (symbolP),
+ S_GET_STORAGE_CLASS (symbolP),
+ i, numaux, where);
+ }
+ return where;
+
+}
+
+void
+coff_obj_symbol_new_hook (symbolP)
+ symbolS *symbolP;
+{
+ char underscore = 0; /* Symbol has leading _ */
+
+ /* Effective symbol */
+ /* Store the pointer in the offset. */
+ S_SET_ZEROES (symbolP, 0L);
+ S_SET_DATA_TYPE (symbolP, T_NULL);
+ S_SET_STORAGE_CLASS (symbolP, 0);
+ S_SET_NUMBER_AUXILIARY (symbolP, 0);
+ /* Additional information */
+ symbolP->sy_symbol.ost_flags = 0;
+ /* Auxiliary entries */
+ memset ((char *) &symbolP->sy_symbol.ost_auxent[0], 0, AUXESZ);
+
+ if (S_IS_STRING (symbolP))
+ SF_SET_STRING (symbolP);
+ if (!underscore && S_IS_LOCAL (symbolP))
+ SF_SET_LOCAL (symbolP);
+}
+
+/*
+ * Handle .ln directives.
+ */
+
+static void
+obj_coff_ln (appline)
+ int appline;
+{
+ int l;
+
+ if (! appline && def_symbol_in_progress != NULL)
+ {
+ as_warn (_(".ln pseudo-op inside .def/.endef: ignored."));
+ demand_empty_rest_of_line ();
+ return;
+ } /* wrong context */
+
+ l = get_absolute_expression ();
+ c_line_new (0, frag_now_fix (), l, frag_now);
+
+ if (appline)
+ new_logical_line ((char *) NULL, l - 1);
+
+#ifndef NO_LISTING
+ {
+ extern int listing;
+
+ if (listing)
+ {
+ if (! appline)
+ l += line_base - 1;
+ listing_source_line ((unsigned int) l);
+ }
+
+ }
+#endif
+ demand_empty_rest_of_line ();
+}
+
+/*
+ * def()
+ *
+ * Handle .def directives.
+ *
+ * One might ask : why can't we symbol_new if the symbol does not
+ * already exist and fill it with debug information. Because of
+ * the C_EFCN special symbol. It would clobber the value of the
+ * function symbol before we have a chance to notice that it is
+ * a C_EFCN. And a second reason is that the code is more clear this
+ * way. (at least I think it is :-).
+ *
+ */
+
+#define SKIP_SEMI_COLON() while (*input_line_pointer++ != ';')
+#define SKIP_WHITESPACES() while (*input_line_pointer == ' ' || \
+ *input_line_pointer == '\t') \
+ input_line_pointer++;
+
+static void
+obj_coff_def (what)
+ int what;
+{
+ char name_end; /* Char after the end of name */
+ char *symbol_name; /* Name of the debug symbol */
+ char *symbol_name_copy; /* Temporary copy of the name */
+ unsigned int symbol_name_length;
+
+ if (def_symbol_in_progress != NULL)
+ {
+ as_warn (_(".def pseudo-op used inside of .def/.endef: ignored."));
+ demand_empty_rest_of_line ();
+ return;
+ } /* if not inside .def/.endef */
+
+ SKIP_WHITESPACES ();
+
+ def_symbol_in_progress = (symbolS *) obstack_alloc (&notes, sizeof (*def_symbol_in_progress));
+ memset (def_symbol_in_progress, 0, sizeof (*def_symbol_in_progress));
+
+ symbol_name = input_line_pointer;
+ name_end = get_symbol_end ();
+ symbol_name_length = strlen (symbol_name);
+ symbol_name_copy = xmalloc (symbol_name_length + 1);
+ strcpy (symbol_name_copy, symbol_name);
+#ifdef tc_canonicalize_symbol_name
+ symbol_name_copy = tc_canonicalize_symbol_name (symbol_name_copy);
+#endif
+
+ /* Initialize the new symbol */
+#ifdef STRIP_UNDERSCORE
+ S_SET_NAME (def_symbol_in_progress, (*symbol_name_copy == '_'
+ ? symbol_name_copy + 1
+ : symbol_name_copy));
+#else /* STRIP_UNDERSCORE */
+ S_SET_NAME (def_symbol_in_progress, symbol_name_copy);
+#endif /* STRIP_UNDERSCORE */
+ /* free(symbol_name_copy); */
+ def_symbol_in_progress->sy_name_offset = (unsigned long) ~0;
+ def_symbol_in_progress->sy_number = ~0;
+ def_symbol_in_progress->sy_frag = &zero_address_frag;
+ S_SET_VALUE (def_symbol_in_progress, 0);
+
+ if (S_IS_STRING (def_symbol_in_progress))
+ SF_SET_STRING (def_symbol_in_progress);
+
+ *input_line_pointer = name_end;
+
+ demand_empty_rest_of_line ();
+}
+
+unsigned int dim_index;
+
+
+static void
+obj_coff_endef (ignore)
+ int ignore;
+{
+ symbolS *symbolP = 0;
+ /* DIM BUG FIX sac@cygnus.com */
+ dim_index = 0;
+ if (def_symbol_in_progress == NULL)
+ {
+ as_warn (_(".endef pseudo-op used outside of .def/.endef: ignored."));
+ demand_empty_rest_of_line ();
+ return;
+ } /* if not inside .def/.endef */
+
+ /* Set the section number according to storage class. */
+ switch (S_GET_STORAGE_CLASS (def_symbol_in_progress))
+ {
+ case C_STRTAG:
+ case C_ENTAG:
+ case C_UNTAG:
+ SF_SET_TAG (def_symbol_in_progress);
+ /* intentional fallthrough */
+ case C_FILE:
+ case C_TPDEF:
+ SF_SET_DEBUG (def_symbol_in_progress);
+ S_SET_SEGMENT (def_symbol_in_progress, SEG_DEBUG);
+ break;
+
+ case C_EFCN:
+ SF_SET_LOCAL (def_symbol_in_progress); /* Do not emit this symbol. */
+ /* intentional fallthrough */
+ case C_BLOCK:
+ SF_SET_PROCESS (def_symbol_in_progress); /* Will need processing before writing */
+ /* intentional fallthrough */
+ case C_FCN:
+ S_SET_SEGMENT (def_symbol_in_progress, SEG_E0);
+
+ if (strcmp (S_GET_NAME (def_symbol_in_progress), ".bf") == 0)
+ { /* .bf */
+ if (function_lineoff < 0)
+ {
+ fprintf (stderr, _("`.bf' symbol without preceding function\n"));
+ } /* missing function symbol */
+ SA_GET_SYM_LNNOPTR (last_line_symbol) = function_lineoff;
+
+ SF_SET_PROCESS (last_line_symbol);
+ SF_SET_ADJ_LNNOPTR (last_line_symbol);
+ SF_SET_PROCESS (def_symbol_in_progress);
+ function_lineoff = -1;
+ }
+ /* Value is always set to . */
+ def_symbol_in_progress->sy_frag = frag_now;
+ S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ());
+ break;
+
+#ifdef C_AUTOARG
+ case C_AUTOARG:
+#endif /* C_AUTOARG */
+ case C_AUTO:
+ case C_REG:
+ case C_MOS:
+ case C_MOE:
+ case C_MOU:
+ case C_ARG:
+ case C_REGPARM:
+ case C_FIELD:
+ case C_EOS:
+ SF_SET_DEBUG (def_symbol_in_progress);
+ S_SET_SEGMENT (def_symbol_in_progress, absolute_section);
+ break;
+
+ case C_EXT:
+ case C_WEAKEXT:
+#ifdef TE_PE
+ case C_NT_WEAK:
+#endif
+ case C_STAT:
+ case C_LABEL:
+ /* Valid but set somewhere else (s_comm, s_lcomm, colon) */
+ break;
+
+ case C_USTATIC:
+ case C_EXTDEF:
+ case C_ULABEL:
+ as_warn (_("unexpected storage class %d"), S_GET_STORAGE_CLASS (def_symbol_in_progress));
+ break;
+ } /* switch on storage class */
+
+ /* Now that we have built a debug symbol, try to find if we should
+ merge with an existing symbol or not. If a symbol is C_EFCN or
+ absolute_section or untagged SEG_DEBUG it never merges. We also
+ don't merge labels, which are in a different namespace, nor
+ symbols which have not yet been defined since they are typically
+ unique, nor do we merge tags with non-tags. */
+
+ /* Two cases for functions. Either debug followed by definition or
+ definition followed by debug. For definition first, we will
+ merge the debug symbol into the definition. For debug first, the
+ lineno entry MUST point to the definition function or else it
+ will point off into space when crawl_symbols() merges the debug
+ symbol into the real symbol. Therefor, let's presume the debug
+ symbol is a real function reference. */
+
+ /* FIXME-SOON If for some reason the definition label/symbol is
+ never seen, this will probably leave an undefined symbol at link
+ time. */
+
+ if (S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_EFCN
+ || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_LABEL
+ || (S_GET_SEGMENT (def_symbol_in_progress) == SEG_DEBUG
+ && !SF_GET_TAG (def_symbol_in_progress))
+ || S_GET_SEGMENT (def_symbol_in_progress) == absolute_section
+ || def_symbol_in_progress->sy_value.X_op != O_constant
+ || (symbolP = symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP)) == NULL
+ || (SF_GET_TAG (def_symbol_in_progress) != SF_GET_TAG (symbolP)))
+ {
+ symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP,
+ &symbol_lastP);
+ }
+ else
+ {
+ /* This symbol already exists, merge the newly created symbol
+ into the old one. This is not mandatory. The linker can
+ handle duplicate symbols correctly. But I guess that it save
+ a *lot* of space if the assembly file defines a lot of
+ symbols. [loic] */
+
+ /* The debug entry (def_symbol_in_progress) is merged into the
+ previous definition. */
+
+ c_symbol_merge (def_symbol_in_progress, symbolP);
+ /* FIXME-SOON Should *def_symbol_in_progress be free'd? xoxorich. */
+ def_symbol_in_progress = symbolP;
+
+ if (SF_GET_FUNCTION (def_symbol_in_progress)
+ || SF_GET_TAG (def_symbol_in_progress)
+ || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_STAT)
+ {
+ /* For functions, and tags, and static symbols, the symbol
+ *must* be where the debug symbol appears. Move the
+ existing symbol to the current place. */
+ /* If it already is at the end of the symbol list, do nothing */
+ if (def_symbol_in_progress != symbol_lastP)
+ {
+ symbol_remove (def_symbol_in_progress, &symbol_rootP,
+ &symbol_lastP);
+ symbol_append (def_symbol_in_progress, symbol_lastP,
+ &symbol_rootP, &symbol_lastP);
+ } /* if not already in place */
+ } /* if function */
+ } /* normal or mergable */
+
+ if (SF_GET_TAG (def_symbol_in_progress))
+ {
+ symbolS *oldtag;
+
+ oldtag = symbol_find_base (S_GET_NAME (def_symbol_in_progress),
+ DO_NOT_STRIP);
+ if (oldtag == NULL || ! SF_GET_TAG (oldtag))
+ tag_insert (S_GET_NAME (def_symbol_in_progress),
+ def_symbol_in_progress);
+ }
+
+ if (SF_GET_FUNCTION (def_symbol_in_progress))
+ {
+ know (sizeof (def_symbol_in_progress) <= sizeof (long));
+ function_lineoff
+ = c_line_new (def_symbol_in_progress, 0, 0, &zero_address_frag);
+
+ SF_SET_PROCESS (def_symbol_in_progress);
+
+ if (symbolP == NULL)
+ {
+ /* That is, if this is the first time we've seen the
+ function... */
+ symbol_table_insert (def_symbol_in_progress);
+ } /* definition follows debug */
+ } /* Create the line number entry pointing to the function being defined */
+
+ def_symbol_in_progress = NULL;
+ demand_empty_rest_of_line ();
+}
+
+static void
+obj_coff_dim (ignore)
+ int ignore;
+{
+ int dim_index;
+
+ if (def_symbol_in_progress == NULL)
+ {
+ as_warn (_(".dim pseudo-op used outside of .def/.endef: ignored."));
+ demand_empty_rest_of_line ();
+ return;
+ } /* if not inside .def/.endef */
+
+ S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
+
+ for (dim_index = 0; dim_index < DIMNUM; dim_index++)
+ {
+ SKIP_WHITESPACES ();
+ SA_SET_SYM_DIMEN (def_symbol_in_progress, dim_index,
+ get_absolute_expression ());
+
+ switch (*input_line_pointer)
+ {
+ case ',':
+ input_line_pointer++;
+ break;
+
+ default:
+ as_warn (_("badly formed .dim directive ignored"));
+ /* intentional fallthrough */
+ case '\n':
+ case ';':
+ dim_index = DIMNUM;
+ break;
+ }
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+static void
+obj_coff_line (ignore)
+ int ignore;
+{
+ int this_base;
+ const char *name;
+
+ if (def_symbol_in_progress == NULL)
+ {
+ obj_coff_ln (0);
+ return;
+ }
+
+ name = S_GET_NAME (def_symbol_in_progress);
+ this_base = get_absolute_expression ();
+
+ /* Only .bf symbols indicate the use of a new base line number; the
+ line numbers associated with .ef, .bb, .eb are relative to the
+ start of the containing function. */
+ if (!strcmp (".bf", name))
+ {
+#if 0 /* XXX Can we ever have line numbers going backwards? */
+ if (this_base > line_base)
+#endif
+ {
+ line_base = this_base;
+ }
+
+#ifndef NO_LISTING
+ {
+ extern int listing;
+ if (listing)
+ {
+ listing_source_line ((unsigned int) line_base);
+ }
+ }
+#endif
+ }
+
+ S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
+ SA_SET_SYM_LNNO (def_symbol_in_progress, this_base);
+
+ demand_empty_rest_of_line ();
+}
+
+static void
+obj_coff_size (ignore)
+ int ignore;
+{
+ if (def_symbol_in_progress == NULL)
+ {
+ as_warn (_(".size pseudo-op used outside of .def/.endef ignored."));
+ demand_empty_rest_of_line ();
+ return;
+ } /* if not inside .def/.endef */
+
+ S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
+ SA_SET_SYM_SIZE (def_symbol_in_progress, get_absolute_expression ());
+ demand_empty_rest_of_line ();
+}
+
+static void
+obj_coff_scl (ignore)
+ int ignore;
+{
+ if (def_symbol_in_progress == NULL)
+ {
+ as_warn (_(".scl pseudo-op used outside of .def/.endef ignored."));
+ demand_empty_rest_of_line ();
+ return;
+ } /* if not inside .def/.endef */
+
+ S_SET_STORAGE_CLASS (def_symbol_in_progress, get_absolute_expression ());
+ demand_empty_rest_of_line ();
+}
+
+static void
+obj_coff_tag (ignore)
+ int ignore;
+{
+ char *symbol_name;
+ char name_end;
+
+ if (def_symbol_in_progress == NULL)
+ {
+ as_warn (_(".tag pseudo-op used outside of .def/.endef ignored."));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
+ symbol_name = input_line_pointer;
+ name_end = get_symbol_end ();
+#ifdef tc_canonicalize_symbol_name
+ symbol_name = tc_canonicalize_symbol_name (symbol_name);
+#endif
+
+ /* Assume that the symbol referred to by .tag is always defined.
+ This was a bad assumption. I've added find_or_make. xoxorich. */
+ SA_SET_SYM_TAGNDX (def_symbol_in_progress,
+ (long) tag_find_or_make (symbol_name));
+ if (SA_GET_SYM_TAGNDX (def_symbol_in_progress) == 0L)
+ {
+ as_warn (_("tag not found for .tag %s"), symbol_name);
+ } /* not defined */
+
+ SF_SET_TAGGED (def_symbol_in_progress);
+ *input_line_pointer = name_end;
+
+ demand_empty_rest_of_line ();
+}
+
+static void
+obj_coff_type (ignore)
+ int ignore;
+{
+ if (def_symbol_in_progress == NULL)
+ {
+ as_warn (_(".type pseudo-op used outside of .def/.endef ignored."));
+ demand_empty_rest_of_line ();
+ return;
+ } /* if not inside .def/.endef */
+
+ S_SET_DATA_TYPE (def_symbol_in_progress, get_absolute_expression ());
+
+ if (ISFCN (S_GET_DATA_TYPE (def_symbol_in_progress)) &&
+ S_GET_STORAGE_CLASS (def_symbol_in_progress) != C_TPDEF)
+ {
+ SF_SET_FUNCTION (def_symbol_in_progress);
+ } /* is a function */
+
+ demand_empty_rest_of_line ();
+}
+
+static void
+obj_coff_val (ignore)
+ int ignore;
+{
+ if (def_symbol_in_progress == NULL)
+ {
+ as_warn (_(".val pseudo-op used outside of .def/.endef ignored."));
+ demand_empty_rest_of_line ();
+ return;
+ } /* if not inside .def/.endef */
+
+ if (is_name_beginner (*input_line_pointer))
+ {
+ char *symbol_name = input_line_pointer;
+ char name_end = get_symbol_end ();
+
+#ifdef tc_canonicalize_symbol_name
+ symbol_name = tc_canonicalize_symbol_name (symbol_name);
+#endif
+
+ if (!strcmp (symbol_name, "."))
+ {
+ def_symbol_in_progress->sy_frag = frag_now;
+ S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ());
+ /* If the .val is != from the .def (e.g. statics) */
+ }
+ else if (strcmp (S_GET_NAME (def_symbol_in_progress), symbol_name))
+ {
+ def_symbol_in_progress->sy_value.X_op = O_symbol;
+ def_symbol_in_progress->sy_value.X_add_symbol =
+ symbol_find_or_make (symbol_name);
+ def_symbol_in_progress->sy_value.X_op_symbol = NULL;
+ def_symbol_in_progress->sy_value.X_add_number = 0;
+
+ /* If the segment is undefined when the forward reference is
+ resolved, then copy the segment id from the forward
+ symbol. */
+ SF_SET_GET_SEGMENT (def_symbol_in_progress);
+
+ /* FIXME: gcc can generate address expressions
+ here in unusual cases (search for "obscure"
+ in sdbout.c). We just ignore the offset
+ here, thus generating incorrect debugging
+ information. We ignore the rest of the
+ line just below. */
+ }
+ /* Otherwise, it is the name of a non debug symbol and
+ its value will be calculated later. */
+ *input_line_pointer = name_end;
+
+ /* FIXME: this is to avoid an error message in the
+ FIXME case mentioned just above. */
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+ else
+ {
+ S_SET_VALUE (def_symbol_in_progress,
+ (valueT) get_absolute_expression ());
+ } /* if symbol based */
+
+ demand_empty_rest_of_line ();
+}
+
+#ifdef TE_PE
+
+/* Handle the .linkonce pseudo-op. This is parsed by s_linkonce in
+ read.c, which then calls this object file format specific routine. */
+
+void
+obj_coff_pe_handle_link_once (type)
+ enum linkonce_type type;
+{
+ seg_info (now_seg)->scnhdr.s_flags |= IMAGE_SCN_LNK_COMDAT;
+
+ /* We store the type in the seg_info structure, and use it to set up
+ the auxiliary entry for the section symbol in c_section_symbol. */
+ seg_info (now_seg)->linkonce = type;
+}
+
+#endif /* TE_PE */
+
+void
+coff_obj_read_begin_hook ()
+{
+ /* These had better be the same. Usually 18 bytes. */
+#ifndef BFD_HEADERS
+ know (sizeof (SYMENT) == sizeof (AUXENT));
+ know (SYMESZ == AUXESZ);
+#endif
+ tag_init ();
+}
+
+/* This function runs through the symbol table and puts all the
+ externals onto another chain */
+
+/* The chain of globals. */
+symbolS *symbol_globalP;
+symbolS *symbol_global_lastP;
+
+/* The chain of externals */
+symbolS *symbol_externP;
+symbolS *symbol_extern_lastP;
+
+stack *block_stack;
+symbolS *last_functionP;
+static symbolS *last_bfP;
+symbolS *last_tagP;
+
+static unsigned int
+yank_symbols ()
+{
+ symbolS *symbolP;
+ unsigned int symbol_number = 0;
+ unsigned int last_file_symno = 0;
+
+ struct filename_list *filename_list_scan = filename_list_head;
+
+ for (symbolP = symbol_rootP;
+ symbolP;
+ symbolP = symbolP ? symbol_next (symbolP) : symbol_rootP)
+ {
+ if (symbolP->sy_mri_common)
+ {
+ if (S_GET_STORAGE_CLASS (symbolP) == C_EXT
+#ifdef TE_PE
+ || S_GET_STORAGE_CLASS (symbolP) == C_NT_WEAK
+#endif
+ || S_GET_STORAGE_CLASS (symbolP) == C_WEAKEXT)
+ as_bad (_("%s: global symbols not supported in common sections"),
+ S_GET_NAME (symbolP));
+ symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
+ continue;
+ }
+
+ if (!SF_GET_DEBUG (symbolP))
+ {
+ /* Debug symbols do not need all this rubbish */
+ symbolS *real_symbolP;
+
+ /* L* and C_EFCN symbols never merge. */
+ if (!SF_GET_LOCAL (symbolP)
+ && !SF_GET_STATICS (symbolP)
+ && S_GET_STORAGE_CLASS (symbolP) != C_LABEL
+ && symbolP->sy_value.X_op == O_constant
+ && (real_symbolP = symbol_find_base (S_GET_NAME (symbolP), DO_NOT_STRIP))
+ && real_symbolP != symbolP)
+ {
+ /* FIXME-SOON: where do dups come from?
+ Maybe tag references before definitions? xoxorich. */
+ /* Move the debug data from the debug symbol to the
+ real symbol. Do NOT do the oposite (i.e. move from
+ real symbol to debug symbol and remove real symbol from the
+ list.) Because some pointers refer to the real symbol
+ whereas no pointers refer to the debug symbol. */
+ c_symbol_merge (symbolP, real_symbolP);
+ /* Replace the current symbol by the real one */
+ /* The symbols will never be the last or the first
+ because : 1st symbol is .file and 3 last symbols are
+ .text, .data, .bss */
+ symbol_remove (real_symbolP, &symbol_rootP, &symbol_lastP);
+ symbol_insert (real_symbolP, symbolP, &symbol_rootP, &symbol_lastP);
+ symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
+ symbolP = real_symbolP;
+ } /* if not local but dup'd */
+
+ if (flag_readonly_data_in_text && (S_GET_SEGMENT (symbolP) == SEG_E1))
+ {
+ S_SET_SEGMENT (symbolP, SEG_E0);
+ } /* push data into text */
+
+ resolve_symbol_value (symbolP, 1);
+
+ if (S_GET_STORAGE_CLASS (symbolP) == C_NULL)
+ {
+ if (!S_IS_DEFINED (symbolP) && !SF_GET_LOCAL (symbolP))
+ {
+ S_SET_EXTERNAL (symbolP);
+ }
+ else if (S_GET_SEGMENT (symbolP) == SEG_E0)
+ {
+ S_SET_STORAGE_CLASS (symbolP, C_LABEL);
+ }
+ else
+ {
+ S_SET_STORAGE_CLASS (symbolP, C_STAT);
+ }
+ }
+
+ /* Mainly to speed up if not -g */
+ if (SF_GET_PROCESS (symbolP))
+ {
+ /* Handle the nested blocks auxiliary info. */
+ if (S_GET_STORAGE_CLASS (symbolP) == C_BLOCK)
+ {
+ if (!strcmp (S_GET_NAME (symbolP), ".bb"))
+ stack_push (block_stack, (char *) &symbolP);
+ else
+ { /* .eb */
+ register symbolS *begin_symbolP;
+ begin_symbolP = *(symbolS **) stack_pop (block_stack);
+ if (begin_symbolP == (symbolS *) 0)
+ as_warn (_("mismatched .eb"));
+ else
+ SA_SET_SYM_ENDNDX (begin_symbolP, symbol_number + 2);
+ }
+ }
+ /* If we are able to identify the type of a function, and we
+ are out of a function (last_functionP == 0) then, the
+ function symbol will be associated with an auxiliary
+ entry. */
+ if (last_functionP == (symbolS *) 0 &&
+ SF_GET_FUNCTION (symbolP))
+ {
+ last_functionP = symbolP;
+
+ if (S_GET_NUMBER_AUXILIARY (symbolP) < 1)
+ {
+ S_SET_NUMBER_AUXILIARY (symbolP, 1);
+ } /* make it at least 1 */
+
+ /* Clobber possible stale .dim information. */
+#if 0
+ /* Iffed out by steve - this fries the lnnoptr info too */
+ bzero (symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen,
+ sizeof (symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen));
+#endif
+ }
+ if (S_GET_STORAGE_CLASS (symbolP) == C_FCN)
+ {
+ if (strcmp (S_GET_NAME (symbolP), ".bf") == 0)
+ {
+ if (last_bfP != NULL)
+ SA_SET_SYM_ENDNDX (last_bfP, symbol_number);
+ last_bfP = symbolP;
+ }
+ }
+ else if (S_GET_STORAGE_CLASS (symbolP) == C_EFCN)
+ {
+ /* I don't even know if this is needed for sdb. But
+ the standard assembler generates it, so... */
+ if (last_functionP == (symbolS *) 0)
+ as_fatal (_("C_EFCN symbol out of scope"));
+ SA_SET_SYM_FSIZE (last_functionP,
+ (long) (S_GET_VALUE (symbolP) -
+ S_GET_VALUE (last_functionP)));
+ SA_SET_SYM_ENDNDX (last_functionP, symbol_number);
+ last_functionP = (symbolS *) 0;
+ }
+ }
+ }
+ else if (SF_GET_TAG (symbolP))
+ {
+ /* First descriptor of a structure must point to
+ the first slot after the structure description. */
+ last_tagP = symbolP;
+
+ }
+ else if (S_GET_STORAGE_CLASS (symbolP) == C_EOS)
+ {
+ /* +2 take in account the current symbol */
+ SA_SET_SYM_ENDNDX (last_tagP, symbol_number + 2);
+ }
+ else if (S_GET_STORAGE_CLASS (symbolP) == C_FILE)
+ {
+ /* If the filename was too long to fit in the
+ auxent, put it in the string table */
+ if (SA_GET_FILE_FNAME_ZEROS (symbolP) == 0
+ && SA_GET_FILE_FNAME_OFFSET (symbolP) != 0)
+ {
+ SA_SET_FILE_FNAME_OFFSET (symbolP, string_byte_count);
+ string_byte_count += strlen (filename_list_scan->filename) + 1;
+ filename_list_scan = filename_list_scan->next;
+ }
+ if (S_GET_VALUE (symbolP))
+ {
+ S_SET_VALUE (symbolP, last_file_symno);
+ last_file_symno = symbol_number;
+ } /* no one points at the first .file symbol */
+ } /* if debug or tag or eos or file */
+
+#ifdef tc_frob_coff_symbol
+ tc_frob_coff_symbol (symbolP);
+#endif
+
+ /* We must put the external symbols apart. The loader
+ does not bomb if we do not. But the references in
+ the endndx field for a .bb symbol are not corrected
+ if an external symbol is removed between .bb and .be.
+ I.e in the following case :
+ [20] .bb endndx = 22
+ [21] foo external
+ [22] .be
+ ld will move the symbol 21 to the end of the list but
+ endndx will still be 22 instead of 21. */
+
+
+ if (SF_GET_LOCAL (symbolP))
+ {
+ /* remove C_EFCN and LOCAL (L...) symbols */
+ /* next pointer remains valid */
+ symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
+
+ }
+ else if (symbolP->sy_value.X_op == O_symbol
+ && (! S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP)))
+ {
+ /* Skip symbols which were equated to undefined or common
+ symbols. */
+ symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
+ }
+ else if (!S_IS_DEFINED (symbolP)
+ && !S_IS_DEBUG (symbolP)
+ && !SF_GET_STATICS (symbolP)
+ && (S_GET_STORAGE_CLASS (symbolP) == C_EXT
+#ifdef TE_PE
+ || S_GET_STORAGE_CLASS (symbolP) == C_NT_WEAK
+#endif
+ || S_GET_STORAGE_CLASS (symbolP) == C_WEAKEXT))
+ {
+ /* if external, Remove from the list */
+ symbolS *hold = symbol_previous (symbolP);
+
+ symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
+ symbol_clear_list_pointers (symbolP);
+ symbol_append (symbolP, symbol_extern_lastP, &symbol_externP, &symbol_extern_lastP);
+ symbolP = hold;
+ }
+ else if (! S_IS_DEBUG (symbolP)
+ && ! SF_GET_STATICS (symbolP)
+ && ! SF_GET_FUNCTION (symbolP)
+ && (S_GET_STORAGE_CLASS (symbolP) == C_EXT
+#ifdef TE_PE
+ || S_GET_STORAGE_CLASS (symbolP) == C_NT_WEAK
+#endif
+ || S_GET_STORAGE_CLASS (symbolP) == C_NT_WEAK))
+ {
+ symbolS *hold = symbol_previous (symbolP);
+
+ /* The O'Reilly COFF book says that defined global symbols
+ come at the end of the symbol table, just before
+ undefined global symbols. */
+
+ symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
+ symbol_clear_list_pointers (symbolP);
+ symbol_append (symbolP, symbol_global_lastP, &symbol_globalP,
+ &symbol_global_lastP);
+ symbolP = hold;
+ }
+ else
+ {
+ if (SF_GET_STRING (symbolP))
+ {
+ symbolP->sy_name_offset = string_byte_count;
+ string_byte_count += strlen (S_GET_NAME (symbolP)) + 1;
+ }
+ else
+ {
+ symbolP->sy_name_offset = 0;
+ } /* fix "long" names */
+
+ symbolP->sy_number = symbol_number;
+ symbol_number += 1 + S_GET_NUMBER_AUXILIARY (symbolP);
+ } /* if local symbol */
+ } /* traverse the symbol list */
+ return symbol_number;
+
+}
+
+
+static unsigned int
+glue_symbols (head, tail)
+ symbolS **head;
+ symbolS **tail;
+{
+ unsigned int symbol_number = 0;
+
+ while (*head != NULL)
+ {
+ symbolS *tmp = *head;
+
+ /* append */
+ symbol_remove (tmp, head, tail);
+ symbol_append (tmp, symbol_lastP, &symbol_rootP, &symbol_lastP);
+
+ /* and process */
+ if (SF_GET_STRING (tmp))
+ {
+ tmp->sy_name_offset = string_byte_count;
+ string_byte_count += strlen (S_GET_NAME (tmp)) + 1;
+ }
+ else
+ {
+ tmp->sy_name_offset = 0;
+ } /* fix "long" names */
+
+ tmp->sy_number = symbol_number;
+ symbol_number += 1 + S_GET_NUMBER_AUXILIARY (tmp);
+ } /* append the entire extern chain */
+
+ return symbol_number;
+}
+
+static unsigned int
+tie_tags ()
+{
+ unsigned int symbol_number = 0;
+ symbolS *symbolP;
+
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
+ {
+ symbolP->sy_number = symbol_number;
+
+ if (SF_GET_TAGGED (symbolP))
+ {
+ SA_SET_SYM_TAGNDX
+ (symbolP,
+ ((symbolS *) SA_GET_SYM_TAGNDX (symbolP))->sy_number);
+ }
+
+ symbol_number += 1 + S_GET_NUMBER_AUXILIARY (symbolP);
+ }
+
+ return symbol_number;
+}
+
+static void
+crawl_symbols (h, abfd)
+ object_headers *h;
+ bfd * abfd;
+{
+ unsigned int i;
+
+ /* Initialize the stack used to keep track of the matching .bb .be */
+
+ block_stack = stack_init (512, sizeof (symbolS *));
+
+ /* The symbol list should be ordered according to the following sequence
+ * order :
+ * . .file symbol
+ * . debug entries for functions
+ * . fake symbols for the sections, including .text .data and .bss
+ * . defined symbols
+ * . undefined symbols
+ * But this is not mandatory. The only important point is to put the
+ * undefined symbols at the end of the list.
+ */
+
+ /* Is there a .file symbol ? If not insert one at the beginning. */
+ if (symbol_rootP == NULL
+ || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE)
+ {
+ c_dot_file_symbol ("fake");
+ }
+
+ /*
+ * Build up static symbols for the sections, they are filled in later
+ */
+
+
+ for (i = SEG_E0; i < SEG_LAST; i++)
+ if (segment_info[i].scnhdr.s_name[0])
+ segment_info[i].dot = c_section_symbol (segment_info[i].name,
+ i - SEG_E0 + 1);
+
+ /* Take all the externals out and put them into another chain */
+ H_SET_SYMBOL_TABLE_SIZE (h, yank_symbols ());
+ /* Take the externals and glue them onto the end.*/
+ H_SET_SYMBOL_TABLE_SIZE (h,
+ (H_GET_SYMBOL_COUNT (h)
+ + glue_symbols (&symbol_globalP,
+ &symbol_global_lastP)
+ + glue_symbols (&symbol_externP,
+ &symbol_extern_lastP)));
+
+ H_SET_SYMBOL_TABLE_SIZE (h, tie_tags ());
+ know (symbol_globalP == NULL);
+ know (symbol_global_lastP == NULL);
+ know (symbol_externP == NULL);
+ know (symbol_extern_lastP == NULL);
+}
+
+/*
+ * Find strings by crawling along symbol table chain.
+ */
+
+void
+w_strings (where)
+ char *where;
+{
+ symbolS *symbolP;
+ struct filename_list *filename_list_scan = filename_list_head;
+
+ /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
+ md_number_to_chars (where, (valueT) string_byte_count, 4);
+ where += 4;
+
+#ifdef COFF_LONG_SECTION_NAMES
+ /* Support long section names as found in PE. This code must
+ coordinate with that in coff_header_append and write_object_file. */
+ {
+ unsigned int i;
+
+ for (i = SEG_E0; i < SEG_LAST; i++)
+ {
+ if (segment_info[i].scnhdr.s_name[0]
+ && strlen (segment_info[i].name) > SCNNMLEN)
+ {
+ unsigned int size;
+
+ size = strlen (segment_info[i].name) + 1;
+ memcpy (where, segment_info[i].name, size);
+ where += size;
+ }
+ }
+ }
+#endif /* COFF_LONG_SECTION_NAMES */
+
+ for (symbolP = symbol_rootP;
+ symbolP;
+ symbolP = symbol_next (symbolP))
+ {
+ unsigned int size;
+
+ if (SF_GET_STRING (symbolP))
+ {
+ size = strlen (S_GET_NAME (symbolP)) + 1;
+ memcpy (where, S_GET_NAME (symbolP), size);
+ where += size;
+ }
+ if (S_GET_STORAGE_CLASS (symbolP) == C_FILE
+ && SA_GET_FILE_FNAME_ZEROS (symbolP) == 0
+ && SA_GET_FILE_FNAME_OFFSET (symbolP) != 0)
+ {
+ size = strlen (filename_list_scan->filename) + 1;
+ memcpy (where, filename_list_scan->filename, size);
+ filename_list_scan = filename_list_scan ->next;
+ where += size;
+ }
+ }
+}
+
+static void
+do_linenos_for (abfd, h, file_cursor)
+ bfd * abfd;
+ object_headers * h;
+ unsigned long *file_cursor;
+{
+ unsigned int idx;
+ unsigned long start = *file_cursor;
+
+ for (idx = SEG_E0; idx < SEG_LAST; idx++)
+ {
+ segment_info_type *s = segment_info + idx;
+
+
+ if (s->scnhdr.s_nlnno != 0)
+ {
+ struct lineno_list *line_ptr;
+
+ struct external_lineno *buffer =
+ (struct external_lineno *) xmalloc (s->scnhdr.s_nlnno * LINESZ);
+
+ struct external_lineno *dst = buffer;
+
+ /* Run through the table we've built and turn it into its external
+ form, take this chance to remove duplicates */
+
+ for (line_ptr = s->lineno_list_head;
+ line_ptr != (struct lineno_list *) NULL;
+ line_ptr = line_ptr->next)
+ {
+
+ if (line_ptr->line.l_lnno == 0)
+ {
+ /* Turn a pointer to a symbol into the symbols' index */
+ line_ptr->line.l_addr.l_symndx =
+ ((symbolS *) line_ptr->line.l_addr.l_symndx)->sy_number;
+ }
+ else
+ {
+ line_ptr->line.l_addr.l_paddr += ((struct frag *) (line_ptr->frag))->fr_address;
+ }
+
+
+ (void) bfd_coff_swap_lineno_out (abfd, &(line_ptr->line), dst);
+ dst++;
+
+ }
+
+ s->scnhdr.s_lnnoptr = *file_cursor;
+
+ bfd_write (buffer, 1, s->scnhdr.s_nlnno * LINESZ, abfd);
+ free (buffer);
+
+ *file_cursor += s->scnhdr.s_nlnno * LINESZ;
+ }
+ }
+ H_SET_LINENO_SIZE (h, *file_cursor - start);
+}
+
+
+/* Now we run through the list of frag chains in a segment and
+ make all the subsegment frags appear at the end of the
+ list, as if the seg 0 was extra long */
+
+static void
+remove_subsegs ()
+{
+ unsigned int i;
+
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ {
+ frchainS *head = segment_info[i].frchainP;
+ fragS dummy;
+ fragS *prev_frag = &dummy;
+
+ while (head && head->frch_seg == i)
+ {
+ prev_frag->fr_next = head->frch_root;
+ prev_frag = head->frch_last;
+ head = head->frch_next;
+ }
+ prev_frag->fr_next = 0;
+ }
+}
+
+unsigned long machine;
+int coff_flags;
+extern void
+write_object_file ()
+{
+ int i;
+ const char *name;
+ struct frchain *frchain_ptr;
+
+ object_headers headers;
+ unsigned long file_cursor;
+ bfd *abfd;
+ unsigned int addr;
+ abfd = bfd_openw (out_file_name, TARGET_FORMAT);
+
+
+ if (abfd == 0)
+ {
+ as_perror (_("FATAL: Can't create %s"), out_file_name);
+ exit (EXIT_FAILURE);
+ }
+ bfd_set_format (abfd, bfd_object);
+ bfd_set_arch_mach (abfd, BFD_ARCH, machine);
+
+ string_byte_count = 4;
+
+ for (frchain_ptr = frchain_root;
+ frchain_ptr != (struct frchain *) NULL;
+ frchain_ptr = frchain_ptr->frch_next)
+ {
+ /* Run through all the sub-segments and align them up. Also
+ close any open frags. We tack a .fill onto the end of the
+ frag chain so that any .align's size can be worked by looking
+ at the next frag. */
+
+ subseg_set (frchain_ptr->frch_seg, frchain_ptr->frch_subseg);
+#ifndef SUB_SEGMENT_ALIGN
+#define SUB_SEGMENT_ALIGN(SEG) 1
+#endif
+#ifdef md_do_align
+ md_do_align (SUB_SEGMENT_ALIGN (now_seg), (char *) NULL, 0, 0,
+ alignment_done);
+#endif
+ frag_align (SUB_SEGMENT_ALIGN (now_seg), NOP_OPCODE, 0);
+#ifdef md_do_align
+ alignment_done:
+#endif
+ frag_wane (frag_now);
+ frag_now->fr_fix = 0;
+ know (frag_now->fr_next == NULL);
+ }
+
+
+ remove_subsegs ();
+
+
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ {
+ relax_segment (segment_info[i].frchainP->frch_root, i);
+ }
+
+ H_SET_NUMBER_OF_SECTIONS (&headers, 0);
+
+ /* Find out how big the sections are, and set the addresses. */
+ addr = 0;
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ {
+ long size;
+
+ segment_info[i].scnhdr.s_paddr = addr;
+ segment_info[i].scnhdr.s_vaddr = addr;
+
+ if (segment_info[i].scnhdr.s_name[0])
+ {
+ H_SET_NUMBER_OF_SECTIONS (&headers,
+ H_GET_NUMBER_OF_SECTIONS (&headers) + 1);
+
+#ifdef COFF_LONG_SECTION_NAMES
+ /* Support long section names as found in PE. This code
+ must coordinate with that in coff_header_append and
+ w_strings. */
+ {
+ unsigned int len;
+
+ len = strlen (segment_info[i].name);
+ if (len > SCNNMLEN)
+ string_byte_count += len + 1;
+ }
+#endif /* COFF_LONG_SECTION_NAMES */
+ }
+
+ size = size_section (abfd, (unsigned int) i);
+ addr += size;
+
+ /* I think the section alignment is only used on the i960; the
+ i960 needs it, and it should do no harm on other targets. */
+#ifdef ALIGNMENT_IN_S_FLAGS
+ segment_info[i].scnhdr.s_flags |= (section_alignment[i] & 0xF) << 8;
+#else
+ segment_info[i].scnhdr.s_align = 1 << section_alignment[i];
+#endif
+
+ if (i == SEG_E0)
+ H_SET_TEXT_SIZE (&headers, size);
+ else if (i == SEG_E1)
+ H_SET_DATA_SIZE (&headers, size);
+ else if (i == SEG_E2)
+ H_SET_BSS_SIZE (&headers, size);
+ }
+
+ /* Turn the gas native symbol table shape into a coff symbol table */
+ crawl_symbols (&headers, abfd);
+
+ if (string_byte_count == 4)
+ string_byte_count = 0;
+
+ H_SET_STRING_SIZE (&headers, string_byte_count);
+
+#ifdef tc_frob_file
+ tc_frob_file ();
+#endif
+
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ {
+ fixup_mdeps (segment_info[i].frchainP->frch_root, &headers, i);
+ fixup_segment (&segment_info[i], i);
+ }
+
+ /* Look for ".stab" segments and fill in their initial symbols
+ correctly. */
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ {
+ name = segment_info[i].name;
+
+ if (name != NULL
+ && strncmp (".stab", name, 5) == 0
+ && strncmp (".stabstr", name, 8) != 0)
+ adjust_stab_section (abfd, i);
+ }
+
+ file_cursor = H_GET_TEXT_FILE_OFFSET (&headers);
+
+ bfd_seek (abfd, (file_ptr) file_cursor, 0);
+
+ /* Plant the data */
+
+ fill_section (abfd, &headers, &file_cursor);
+
+ do_relocs_for (abfd, &headers, &file_cursor);
+
+ do_linenos_for (abfd, &headers, &file_cursor);
+
+ H_SET_FILE_MAGIC_NUMBER (&headers, COFF_MAGIC);
+#ifndef OBJ_COFF_OMIT_TIMESTAMP
+ H_SET_TIME_STAMP (&headers, (long)time((time_t *)0));
+#else
+ H_SET_TIME_STAMP (&headers, 0);
+#endif
+#ifdef TC_COFF_SET_MACHINE
+ TC_COFF_SET_MACHINE (&headers);
+#endif
+
+#ifndef COFF_FLAGS
+#define COFF_FLAGS 0
+#endif
+
+#ifdef KEEP_RELOC_INFO
+ H_SET_FLAGS (&headers, ((H_GET_LINENO_SIZE(&headers) ? 0 : F_LNNO) |
+ COFF_FLAGS | coff_flags));
+#else
+ H_SET_FLAGS (&headers, ((H_GET_LINENO_SIZE(&headers) ? 0 : F_LNNO) |
+ (H_GET_RELOCATION_SIZE(&headers) ? 0 : F_RELFLG) |
+ COFF_FLAGS | coff_flags));
+#endif
+
+ {
+ unsigned int symtable_size = H_GET_SYMBOL_TABLE_SIZE (&headers);
+ char *buffer1 = xmalloc (symtable_size + string_byte_count + 1);
+
+ H_SET_SYMBOL_TABLE_POINTER (&headers, bfd_tell (abfd));
+ w_symbols (abfd, buffer1, symbol_rootP);
+ if (string_byte_count > 0)
+ w_strings (buffer1 + symtable_size);
+ bfd_write (buffer1, 1, symtable_size + string_byte_count, abfd);
+ free (buffer1);
+ }
+
+ coff_header_append (abfd, &headers);
+#if 0
+ /* Recent changes to write need this, but where it should
+ go is up to Ken.. */
+ if (bfd_close_all_done (abfd) == false)
+ as_fatal (_("Can't close %s: %s"), out_file_name,
+ bfd_errmsg (bfd_get_error ()));
+#else
+ {
+ extern bfd *stdoutput;
+ stdoutput = abfd;
+ }
+#endif
+
+}
+
+/* Add a new segment. This is called from subseg_new via the
+ obj_new_segment macro. */
+
+segT
+obj_coff_add_segment (name)
+ const char *name;
+{
+ unsigned int i;
+
+#ifndef COFF_LONG_SECTION_NAMES
+ char buf[SCNNMLEN + 1];
+
+ strncpy (buf, name, SCNNMLEN);
+ buf[SCNNMLEN] = '\0';
+ name = buf;
+#endif
+
+ for (i = SEG_E0; i < SEG_LAST && segment_info[i].scnhdr.s_name[0]; i++)
+ if (strcmp (name, segment_info[i].name) == 0)
+ return (segT) i;
+
+ if (i == SEG_LAST)
+ {
+ as_bad (_("Too many new sections; can't add \"%s\""), name);
+ return now_seg;
+ }
+
+ /* Add a new section. */
+ strncpy (segment_info[i].scnhdr.s_name, name,
+ sizeof (segment_info[i].scnhdr.s_name));
+ segment_info[i].scnhdr.s_flags = STYP_REG;
+ segment_info[i].name = xstrdup (name);
+
+ return (segT) i;
+}
+
+/*
+ * implement the .section pseudo op:
+ * .section name {, "flags"}
+ * ^ ^
+ * | +--- optional flags: 'b' for bss
+ * | 'i' for info
+ * +-- section name 'l' for lib
+ * 'n' for noload
+ * 'o' for over
+ * 'w' for data
+ * 'd' (apparently m88k for data)
+ * 'x' for text
+ * 'r' for read-only data
+ * But if the argument is not a quoted string, treat it as a
+ * subsegment number.
+ */
+
+void
+obj_coff_section (ignore)
+ int ignore;
+{
+ /* Strip out the section name */
+ char *section_name, *name;
+ char c;
+ unsigned int exp;
+ long flags;
+
+ if (flag_mri)
+ {
+ char type;
+
+ s_mri_sect (&type);
+ flags = 0;
+ if (type == 'C')
+ flags = STYP_TEXT;
+ else if (type == 'D')
+ flags = STYP_DATA;
+ segment_info[now_seg].scnhdr.s_flags |= flags;
+
+ return;
+ }
+
+ section_name = input_line_pointer;
+ c = get_symbol_end ();
+
+ name = xmalloc (input_line_pointer - section_name + 1);
+ strcpy (name, section_name);
+
+ *input_line_pointer = c;
+
+ exp = 0;
+ flags = 0;
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == ',')
+ {
+ ++input_line_pointer;
+ SKIP_WHITESPACE ();
+
+ if (*input_line_pointer != '"')
+ exp = get_absolute_expression ();
+ else
+ {
+ ++input_line_pointer;
+ while (*input_line_pointer != '"'
+ && ! is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ switch (*input_line_pointer)
+ {
+ case 'b': flags |= STYP_BSS; break;
+ case 'i': flags |= STYP_INFO; break;
+ case 'l': flags |= STYP_LIB; break;
+ case 'n': flags |= STYP_NOLOAD; break;
+ case 'o': flags |= STYP_OVER; break;
+ case 'd':
+ case 'w': flags |= STYP_DATA; break;
+ case 'x': flags |= STYP_TEXT; break;
+ case 'r': flags |= STYP_LIT; break;
+ default:
+ as_warn(_("unknown section attribute '%c'"),
+ *input_line_pointer);
+ break;
+ }
+ ++input_line_pointer;
+ }
+ if (*input_line_pointer == '"')
+ ++input_line_pointer;
+ }
+ }
+
+ subseg_new (name, (subsegT) exp);
+
+ segment_info[now_seg].scnhdr.s_flags |= flags;
+
+ demand_empty_rest_of_line ();
+}
+
+
+static void
+obj_coff_text (ignore)
+ int ignore;
+{
+ subseg_new (".text", get_absolute_expression ());
+}
+
+
+static void
+obj_coff_data (ignore)
+ int ignore;
+{
+ if (flag_readonly_data_in_text)
+ subseg_new (".text", get_absolute_expression () + 1000);
+ else
+ subseg_new (".data", get_absolute_expression ());
+}
+
+static void
+obj_coff_ident (ignore)
+ int ignore;
+{
+ segT current_seg = now_seg; /* save current seg */
+ subsegT current_subseg = now_subseg;
+ subseg_new (".comment", 0); /* .comment seg */
+ stringer (1); /* read string */
+ subseg_set (current_seg, current_subseg); /* restore current seg */
+}
+
+void
+c_symbol_merge (debug, normal)
+ symbolS *debug;
+ symbolS *normal;
+{
+ S_SET_DATA_TYPE (normal, S_GET_DATA_TYPE (debug));
+ S_SET_STORAGE_CLASS (normal, S_GET_STORAGE_CLASS (debug));
+
+ if (S_GET_NUMBER_AUXILIARY (debug) > S_GET_NUMBER_AUXILIARY (normal))
+ {
+ S_SET_NUMBER_AUXILIARY (normal, S_GET_NUMBER_AUXILIARY (debug));
+ } /* take the most we have */
+
+ if (S_GET_NUMBER_AUXILIARY (debug) > 0)
+ {
+ memcpy ((char *) &normal->sy_symbol.ost_auxent[0],
+ (char *) &debug->sy_symbol.ost_auxent[0],
+ (unsigned int) (S_GET_NUMBER_AUXILIARY (debug) * AUXESZ));
+ } /* Move all the auxiliary information */
+
+ /* Move the debug flags. */
+ SF_SET_DEBUG_FIELD (normal, SF_GET_DEBUG_FIELD (debug));
+} /* c_symbol_merge() */
+
+static int
+c_line_new (symbol, paddr, line_number, frag)
+ symbolS * symbol;
+ long paddr;
+ int line_number;
+ fragS * frag;
+{
+ struct lineno_list *new_line =
+ (struct lineno_list *) xmalloc (sizeof (struct lineno_list));
+
+ segment_info_type *s = segment_info + now_seg;
+ new_line->line.l_lnno = line_number;
+
+ if (line_number == 0)
+ {
+ last_line_symbol = symbol;
+ new_line->line.l_addr.l_symndx = (long) symbol;
+ }
+ else
+ {
+ new_line->line.l_addr.l_paddr = paddr;
+ }
+
+ new_line->frag = (char *) frag;
+ new_line->next = (struct lineno_list *) NULL;
+
+
+ if (s->lineno_list_head == (struct lineno_list *) NULL)
+ {
+ s->lineno_list_head = new_line;
+ }
+ else
+ {
+ s->lineno_list_tail->next = new_line;
+ }
+ s->lineno_list_tail = new_line;
+ return LINESZ * s->scnhdr.s_nlnno++;
+}
+
+void
+c_dot_file_symbol (filename)
+ char *filename;
+{
+ symbolS *symbolP;
+
+ symbolP = symbol_new (".file",
+ SEG_DEBUG,
+ 0,
+ &zero_address_frag);
+
+ S_SET_STORAGE_CLASS (symbolP, C_FILE);
+ S_SET_NUMBER_AUXILIARY (symbolP, 1);
+
+ if (strlen (filename) > FILNMLEN)
+ {
+ /* Filename is too long to fit into an auxent,
+ we stick it into the string table instead. We keep
+ a linked list of the filenames we find so we can emit
+ them later.*/
+ struct filename_list *f = ((struct filename_list *)
+ xmalloc (sizeof (struct filename_list)));
+
+ f->filename = filename;
+ f->next = 0;
+
+ SA_SET_FILE_FNAME_ZEROS (symbolP, 0);
+ SA_SET_FILE_FNAME_OFFSET (symbolP, 1);
+
+ if (filename_list_tail)
+ filename_list_tail->next = f;
+ else
+ filename_list_head = f;
+ filename_list_tail = f;
+ }
+ else
+ {
+ SA_SET_FILE_FNAME (symbolP, filename);
+ }
+#ifndef NO_LISTING
+ {
+ extern int listing;
+ if (listing)
+ {
+ listing_source_file (filename);
+ }
+
+ }
+
+#endif
+ SF_SET_DEBUG (symbolP);
+ S_SET_VALUE (symbolP, (valueT) previous_file_symbol);
+
+ previous_file_symbol = symbolP;
+
+ /* Make sure that the symbol is first on the symbol chain */
+ if (symbol_rootP != symbolP)
+ {
+ symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
+ symbol_insert (symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP);
+ }
+} /* c_dot_file_symbol() */
+
+/*
+ * Build a 'section static' symbol.
+ */
+
+symbolS *
+c_section_symbol (name, idx)
+ char *name;
+ int idx;
+{
+ symbolS *symbolP;
+
+ symbolP = symbol_find_base (name, DO_NOT_STRIP);
+ if (symbolP == NULL)
+ symbolP = symbol_new (name, idx, 0, &zero_address_frag);
+ else
+ {
+ /* Mmmm. I just love violating interfaces. Makes me feel...dirty. */
+ S_SET_SEGMENT (symbolP, idx);
+ symbolP->sy_frag = &zero_address_frag;
+ }
+
+ S_SET_STORAGE_CLASS (symbolP, C_STAT);
+ S_SET_NUMBER_AUXILIARY (symbolP, 1);
+
+ SF_SET_STATICS (symbolP);
+
+#ifdef TE_DELTA
+ /* manfred@s-direktnet.de: section symbols *must* have the LOCAL bit cleared,
+ which is set by the new definition of LOCAL_LABEL in tc-m68k.h. */
+ SF_CLEAR_LOCAL (symbolP);
+#endif
+#ifdef TE_PE
+ /* If the .linkonce pseudo-op was used for this section, we must
+ store the information in the auxiliary entry for the section
+ symbol. */
+ if (segment_info[idx].linkonce != LINKONCE_UNSET)
+ {
+ int type;
+
+ switch (segment_info[idx].linkonce)
+ {
+ default:
+ abort ();
+ case LINKONCE_DISCARD:
+ type = IMAGE_COMDAT_SELECT_ANY;
+ break;
+ case LINKONCE_ONE_ONLY:
+ type = IMAGE_COMDAT_SELECT_NODUPLICATES;
+ break;
+ case LINKONCE_SAME_SIZE:
+ type = IMAGE_COMDAT_SELECT_SAME_SIZE;
+ break;
+ case LINKONCE_SAME_CONTENTS:
+ type = IMAGE_COMDAT_SELECT_EXACT_MATCH;
+ break;
+ }
+
+ SYM_AUXENT (symbolP)->x_scn.x_comdat = type;
+ }
+#endif /* TE_PE */
+
+ return symbolP;
+} /* c_section_symbol() */
+
+static void
+w_symbols (abfd, where, symbol_rootP)
+ bfd * abfd;
+ char *where;
+ symbolS * symbol_rootP;
+{
+ symbolS *symbolP;
+ unsigned int i;
+
+ /* First fill in those values we have only just worked out */
+ for (i = SEG_E0; i < SEG_LAST; i++)
+ {
+ symbolP = segment_info[i].dot;
+ if (symbolP)
+ {
+ SA_SET_SCN_SCNLEN (symbolP, segment_info[i].scnhdr.s_size);
+ SA_SET_SCN_NRELOC (symbolP, segment_info[i].scnhdr.s_nreloc);
+ SA_SET_SCN_NLINNO (symbolP, segment_info[i].scnhdr.s_nlnno);
+ }
+ }
+
+ /*
+ * Emit all symbols left in the symbol chain.
+ */
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
+ {
+ /* Used to save the offset of the name. It is used to point
+ to the string in memory but must be a file offset. */
+ register char *temp;
+
+ /* We can't fix the lnnoptr field in yank_symbols with the other
+ adjustments, because we have to wait until we know where they
+ go in the file. */
+ if (SF_GET_ADJ_LNNOPTR (symbolP))
+ {
+ SA_GET_SYM_LNNOPTR (symbolP) +=
+ segment_info[S_GET_SEGMENT (symbolP)].scnhdr.s_lnnoptr;
+ }
+
+ tc_coff_symbol_emit_hook (symbolP);
+
+ temp = S_GET_NAME (symbolP);
+ if (SF_GET_STRING (symbolP))
+ {
+ S_SET_OFFSET (symbolP, symbolP->sy_name_offset);
+ S_SET_ZEROES (symbolP, 0);
+ }
+ else
+ {
+ memset (symbolP->sy_symbol.ost_entry.n_name, 0, SYMNMLEN);
+ strncpy (symbolP->sy_symbol.ost_entry.n_name, temp, SYMNMLEN);
+ }
+ where = symbol_to_chars (abfd, where, symbolP);
+ S_SET_NAME (symbolP, temp);
+ }
+
+} /* w_symbols() */
+
+static void
+obj_coff_lcomm (ignore)
+ int ignore;
+{
+ s_lcomm(0);
+ return;
+#if 0
+ char *name;
+ char c;
+ int temp;
+ char *p;
+
+ symbolS *symbolP;
+
+ name = input_line_pointer;
+
+ c = get_symbol_end ();
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("Expected comma after name"));
+ ignore_rest_of_line ();
+ return;
+ }
+ if (*input_line_pointer == '\n')
+ {
+ as_bad (_("Missing size expression"));
+ return;
+ }
+ input_line_pointer++;
+ if ((temp = get_absolute_expression ()) < 0)
+ {
+ as_warn (_("lcomm length (%d.) <0! Ignored."), temp);
+ ignore_rest_of_line ();
+ return;
+ }
+ *p = 0;
+
+ symbolP = symbol_find_or_make(name);
+
+ if (S_GET_SEGMENT(symbolP) == SEG_UNKNOWN &&
+ S_GET_VALUE(symbolP) == 0)
+ {
+ if (! need_pass_2)
+ {
+ char *p;
+ segT current_seg = now_seg; /* save current seg */
+ subsegT current_subseg = now_subseg;
+
+ subseg_set (SEG_E2, 1);
+ symbolP->sy_frag = frag_now;
+ p = frag_var(rs_org, 1, 1, (relax_substateT)0, symbolP,
+ (offsetT) temp, (char *) 0);
+ *p = 0;
+ subseg_set (current_seg, current_subseg); /* restore current seg */
+ S_SET_SEGMENT(symbolP, SEG_E2);
+ S_SET_STORAGE_CLASS(symbolP, C_STAT);
+ }
+ }
+ else
+ as_bad(_("Symbol %s already defined"), name);
+
+ demand_empty_rest_of_line();
+#endif
+}
+
+static void
+fixup_mdeps (frags, h, this_segment)
+ fragS * frags;
+ object_headers * h;
+ segT this_segment;
+{
+ subseg_change (this_segment, 0);
+ while (frags)
+ {
+ switch (frags->fr_type)
+ {
+ case rs_align:
+ case rs_align_code:
+ case rs_org:
+#ifdef HANDLE_ALIGN
+ HANDLE_ALIGN (frags);
+#endif
+ frags->fr_type = rs_fill;
+ frags->fr_offset =
+ ((frags->fr_next->fr_address - frags->fr_address - frags->fr_fix)
+ / frags->fr_var);
+ break;
+ case rs_machine_dependent:
+ md_convert_frag (h, this_segment, frags);
+ frag_wane (frags);
+ break;
+ default:
+ ;
+ }
+ frags = frags->fr_next;
+ }
+}
+
+#if 1
+
+#ifndef TC_FORCE_RELOCATION
+#define TC_FORCE_RELOCATION(fix) 0
+#endif
+
+static void
+fixup_segment (segP, this_segment_type)
+ segment_info_type * segP;
+ segT this_segment_type;
+{
+ register fixS * fixP;
+ register symbolS *add_symbolP;
+ register symbolS *sub_symbolP;
+ long add_number;
+ register int size;
+ register char *place;
+ register long where;
+ register char pcrel;
+ register fragS *fragP;
+ register segT add_symbol_segment = absolute_section;
+
+ for (fixP = segP->fix_root; fixP; fixP = fixP->fx_next)
+ {
+ fragP = fixP->fx_frag;
+ know (fragP);
+ where = fixP->fx_where;
+ place = fragP->fr_literal + where;
+ size = fixP->fx_size;
+ add_symbolP = fixP->fx_addsy;
+ sub_symbolP = fixP->fx_subsy;
+ add_number = fixP->fx_offset;
+ pcrel = fixP->fx_pcrel;
+
+ /* We want function-relative stabs to work on systems which
+ may use a relaxing linker; thus we must handle the sym1-sym2
+ fixups function-relative stabs generates.
+
+ Of course, if you actually enable relaxing in the linker, the
+ line and block scoping information is going to be incorrect
+ in some cases. The only way to really fix this is to support
+ a reloc involving the difference of two symbols. */
+ if (linkrelax
+ && (!sub_symbolP || pcrel))
+ continue;
+
+#ifdef TC_I960
+ if (fixP->fx_tcbit && SF_GET_CALLNAME (add_symbolP))
+ {
+ /* Relocation should be done via the associated 'bal' entry
+ point symbol. */
+
+ if (!SF_GET_BALNAME (tc_get_bal_of_call (add_symbolP)))
+ {
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("No 'bal' entry point for leafproc %s"),
+ S_GET_NAME (add_symbolP));
+ continue;
+ }
+ fixP->fx_addsy = add_symbolP = tc_get_bal_of_call (add_symbolP);
+ }
+#endif
+
+ /* Make sure the symbols have been resolved; this may not have
+ happened if these are expression symbols. */
+ if (add_symbolP != NULL && ! add_symbolP->sy_resolved)
+ resolve_symbol_value (add_symbolP, 1);
+
+ if (add_symbolP != NULL)
+ {
+ /* If this fixup is against a symbol which has been equated
+ to another symbol, convert it to the other symbol. */
+ if (add_symbolP->sy_value.X_op == O_symbol
+ && (! S_IS_DEFINED (add_symbolP)
+ || S_IS_COMMON (add_symbolP)))
+ {
+ while (add_symbolP->sy_value.X_op == O_symbol
+ && (! S_IS_DEFINED (add_symbolP)
+ || S_IS_COMMON (add_symbolP)))
+ {
+ symbolS *n;
+
+ /* We must avoid looping, as that can occur with a
+ badly written program. */
+ n = add_symbolP->sy_value.X_add_symbol;
+ if (n == add_symbolP)
+ break;
+ add_number += add_symbolP->sy_value.X_add_number;
+ add_symbolP = n;
+ }
+ fixP->fx_addsy = add_symbolP;
+ fixP->fx_offset = add_number;
+ }
+ }
+
+ if (sub_symbolP != NULL && ! sub_symbolP->sy_resolved)
+ resolve_symbol_value (sub_symbolP, 1);
+
+ if (add_symbolP != NULL
+ && add_symbolP->sy_mri_common)
+ {
+ know (add_symbolP->sy_value.X_op == O_symbol);
+ add_number += S_GET_VALUE (add_symbolP);
+ fixP->fx_offset = add_number;
+ add_symbolP = fixP->fx_addsy = add_symbolP->sy_value.X_add_symbol;
+ }
+
+ if (add_symbolP)
+ {
+ add_symbol_segment = S_GET_SEGMENT (add_symbolP);
+ } /* if there is an addend */
+
+ if (sub_symbolP)
+ {
+ if (add_symbolP == NULL || add_symbol_segment == absolute_section)
+ {
+ if (add_symbolP != NULL)
+ {
+ add_number += S_GET_VALUE (add_symbolP);
+ add_symbolP = NULL;
+ fixP->fx_addsy = NULL;
+ }
+
+ /* It's just -sym. */
+ if (S_GET_SEGMENT (sub_symbolP) == absolute_section)
+ {
+ add_number -= S_GET_VALUE (sub_symbolP);
+ fixP->fx_subsy = 0;
+ fixP->fx_done = 1;
+ }
+ else
+ {
+#ifndef TC_M68K
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Negative of non-absolute symbol %s"),
+ S_GET_NAME (sub_symbolP));
+#endif
+ add_number -= S_GET_VALUE (sub_symbolP);
+ } /* not absolute */
+
+ /* if sub_symbol is in the same segment that add_symbol
+ and add_symbol is either in DATA, TEXT, BSS or ABSOLUTE */
+ }
+ else if (S_GET_SEGMENT (sub_symbolP) == add_symbol_segment
+ && SEG_NORMAL (add_symbol_segment))
+ {
+ /* Difference of 2 symbols from same segment. Can't
+ make difference of 2 undefineds: 'value' means
+ something different for N_UNDF. */
+#ifdef TC_I960
+ /* Makes no sense to use the difference of 2 arbitrary symbols
+ as the target of a call instruction. */
+ if (fixP->fx_tcbit)
+ {
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("callj to difference of 2 symbols"));
+ }
+#endif /* TC_I960 */
+ add_number += S_GET_VALUE (add_symbolP) -
+ S_GET_VALUE (sub_symbolP);
+ add_symbolP = NULL;
+
+ if (!TC_FORCE_RELOCATION (fixP))
+ {
+ fixP->fx_addsy = NULL;
+ fixP->fx_subsy = NULL;
+ fixP->fx_done = 1;
+#ifdef TC_M68K /* is this right? */
+ pcrel = 0;
+ fixP->fx_pcrel = 0;
+#endif
+ }
+ }
+ else
+ {
+ /* Different segments in subtraction. */
+ know (!(S_IS_EXTERNAL (sub_symbolP) && (S_GET_SEGMENT (sub_symbolP) == absolute_section)));
+
+ if ((S_GET_SEGMENT (sub_symbolP) == absolute_section))
+ {
+ add_number -= S_GET_VALUE (sub_symbolP);
+ }
+#ifdef DIFF_EXPR_OK
+ else if (S_GET_SEGMENT (sub_symbolP) == this_segment_type
+#if 0 /* Okay for 68k, at least... */
+ && !pcrel
+#endif
+ )
+ {
+ /* Make it pc-relative. */
+ add_number += (md_pcrel_from (fixP)
+ - S_GET_VALUE (sub_symbolP));
+ pcrel = 1;
+ fixP->fx_pcrel = 1;
+ sub_symbolP = 0;
+ fixP->fx_subsy = 0;
+ }
+#endif
+ else
+ {
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Can't emit reloc {- %s-seg symbol \"%s\"} @ file address %ld."),
+ segment_name (S_GET_SEGMENT (sub_symbolP)),
+ S_GET_NAME (sub_symbolP),
+ (long) (fragP->fr_address + where));
+ } /* if absolute */
+ }
+ } /* if sub_symbolP */
+
+ if (add_symbolP)
+ {
+ if (add_symbol_segment == this_segment_type && pcrel)
+ {
+ /*
+ * This fixup was made when the symbol's segment was
+ * SEG_UNKNOWN, but it is now in the local segment.
+ * So we know how to do the address without relocation.
+ */
+#ifdef TC_I960
+ /* reloc_callj() may replace a 'call' with a 'calls' or a 'bal',
+ * in which cases it modifies *fixP as appropriate. In the case
+ * of a 'calls', no further work is required, and *fixP has been
+ * set up to make the rest of the code below a no-op.
+ */
+ reloc_callj (fixP);
+#endif /* TC_I960 */
+
+ add_number += S_GET_VALUE (add_symbolP);
+ add_number -= md_pcrel_from (fixP);
+
+ /* We used to do
+ add_number -= segP->scnhdr.s_vaddr;
+ if defined (TC_I386) || defined (TE_LYNX). I now
+ think that was an error propagated from the case when
+ we are going to emit the relocation. If we are not
+ going to emit the relocation, then we just want to
+ set add_number to the difference between the symbols.
+ This is a case that would only arise when there is a
+ PC relative reference from a section other than .text
+ to a symbol defined in the same section, and the
+ reference is not relaxed. Since jump instructions on
+ the i386 are relaxed, this could only arise with a
+ call instruction. */
+
+ pcrel = 0; /* Lie. Don't want further pcrel processing. */
+ if (!TC_FORCE_RELOCATION (fixP))
+ {
+ fixP->fx_addsy = NULL;
+ fixP->fx_done = 1;
+ }
+ }
+ else
+ {
+ switch (add_symbol_segment)
+ {
+ case absolute_section:
+#ifdef TC_I960
+ reloc_callj (fixP); /* See comment about reloc_callj() above*/
+#endif /* TC_I960 */
+ add_number += S_GET_VALUE (add_symbolP);
+ add_symbolP = NULL;
+
+ if (!TC_FORCE_RELOCATION (fixP))
+ {
+ fixP->fx_addsy = NULL;
+ fixP->fx_done = 1;
+ }
+ break;
+ default:
+
+
+#if defined(TC_A29K) || (defined(TE_PE) && defined(TC_I386)) || defined(TC_M88K)
+ /* This really should be handled in the linker, but
+ backward compatibility forbids. */
+ add_number += S_GET_VALUE (add_symbolP);
+#else
+ add_number += S_GET_VALUE (add_symbolP) +
+ segment_info[S_GET_SEGMENT (add_symbolP)].scnhdr.s_paddr;
+#endif
+ break;
+
+ case SEG_UNKNOWN:
+#ifdef TC_I960
+ if ((int) fixP->fx_bit_fixP == 13)
+ {
+ /* This is a COBR instruction. They have only a
+ * 13-bit displacement and are only to be used
+ * for local branches: flag as error, don't generate
+ * relocation.
+ */
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("can't use COBR format with external label"));
+ fixP->fx_addsy = NULL;
+ fixP->fx_done = 1;
+ continue;
+ } /* COBR */
+#endif /* TC_I960 */
+#if ((defined (TC_I386) || defined (TE_LYNX) || defined (TE_AUX)) && !defined(TE_PE)) || defined (COFF_COMMON_ADDEND)
+ /* 386 COFF uses a peculiar format in which the
+ value of a common symbol is stored in the .text
+ segment (I've checked this on SVR3.2 and SCO
+ 3.2.2) Ian Taylor <ian@cygnus.com>. */
+ /* This is also true for 68k COFF on sysv machines
+ (Checked on Motorola sysv68 R3V6 and R3V7.1, and also on
+ UNIX System V/M68000, Release 1.0 from ATT/Bell Labs)
+ Philippe De Muyter <phdm@info.ucl.ac.be>. */
+ if (S_IS_COMMON (add_symbolP))
+ add_number += S_GET_VALUE (add_symbolP);
+#endif
+ break;
+
+
+ } /* switch on symbol seg */
+ } /* if not in local seg */
+ } /* if there was a + symbol */
+
+ if (pcrel)
+ {
+#if !defined(TC_M88K) && !(defined(TE_PE) && defined(TC_I386)) && !defined(TC_A29K)
+ /* This adjustment is not correct on the m88k, for which the
+ linker does all the computation. */
+ add_number -= md_pcrel_from (fixP);
+#endif
+ if (add_symbolP == 0)
+ {
+ fixP->fx_addsy = &abs_symbol;
+ } /* if there's an add_symbol */
+#if defined (TC_I386) || defined (TE_LYNX) || defined (TC_I960) || defined (TC_M68K)
+ /* On the 386 we must adjust by the segment vaddr as well.
+ Ian Taylor.
+
+ I changed the i960 to work this way as well. This is
+ compatible with the current GNU linker behaviour. I do
+ not know what other i960 COFF assemblers do. This is not
+ a common case: normally, only assembler code will contain
+ a PC relative reloc, and only branches which do not
+ originate in the .text section will have a non-zero
+ address.
+
+ I changed the m68k to work this way as well. This will
+ break existing PC relative relocs from sections which do
+ not start at address 0, but it will make ld -r work.
+ Ian Taylor, 4 Oct 96. */
+
+ add_number -= segP->scnhdr.s_vaddr;
+#endif
+ } /* if pcrel */
+
+ if (!fixP->fx_bit_fixP && ! fixP->fx_no_overflow)
+ {
+#ifndef TC_M88K
+ /* The m88k uses the offset field of the reloc to get around
+ this problem. */
+ if ((size == 1
+ && ((add_number & ~0xFF)
+ || (fixP->fx_signed && (add_number & 0x80)))
+ && ((add_number & ~0xFF) != (-1 & ~0xFF)
+ || (add_number & 0x80) == 0))
+ || (size == 2
+ && ((add_number & ~0xFFFF)
+ || (fixP->fx_signed && (add_number & 0x8000)))
+ && ((add_number & ~0xFFFF) != (-1 & ~0xFFFF)
+ || (add_number & 0x8000) == 0)))
+ {
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Value of %ld too large for field of %d bytes at 0x%lx"),
+ (long) add_number, size,
+ (unsigned long) (fragP->fr_address + where));
+ }
+#endif
+#ifdef WARN_SIGNED_OVERFLOW_WORD
+ /* Warn if a .word value is too large when treated as a
+ signed number. We already know it is not too negative.
+ This is to catch over-large switches generated by gcc on
+ the 68k. */
+ if (!flag_signed_overflow_ok
+ && size == 2
+ && add_number > 0x7fff)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Signed .word overflow; switch may be too large; %ld at 0x%lx"),
+ (long) add_number,
+ (unsigned long) (fragP->fr_address + where));
+#endif
+ } /* not a bit fix */
+ /* Once this fix has been applied, we don't have to output
+ anything nothing more need be done. */
+#ifdef MD_APPLY_FIX3
+ md_apply_fix3 (fixP, (valueT *) &add_number, this_segment_type);
+#else
+ md_apply_fix (fixP, add_number);
+#endif
+ } /* For each fixS in this segment. */
+} /* fixup_segment() */
+
+#endif
+
+/* The first entry in a .stab section is special. */
+
+void
+obj_coff_init_stab_section (seg)
+ segT seg;
+{
+ char *file;
+ char *p;
+ char *stabstr_name;
+ unsigned int stroff;
+
+ /* Make space for this first symbol. */
+ p = frag_more (12);
+ /* Zero it out. */
+ memset (p, 0, 12);
+ as_where (&file, (unsigned int *) NULL);
+ stabstr_name = (char *) alloca (strlen (segment_info[seg].name) + 4);
+ strcpy (stabstr_name, segment_info[seg].name);
+ strcat (stabstr_name, "str");
+ stroff = get_stab_string_offset (file, stabstr_name);
+ know (stroff == 1);
+ md_number_to_chars (p, stroff, 4);
+}
+
+/* Fill in the counts in the first entry in a .stab section. */
+
+static void
+adjust_stab_section(abfd, seg)
+ bfd *abfd;
+ segT seg;
+{
+ segT stabstrseg = SEG_UNKNOWN;
+ const char *secname, *name2;
+ char *name;
+ char *p = NULL;
+ int i, strsz = 0, nsyms;
+ fragS *frag = segment_info[seg].frchainP->frch_root;
+
+ /* Look for the associated string table section. */
+
+ secname = segment_info[seg].name;
+ name = (char *) alloca (strlen (secname) + 4);
+ strcpy (name, secname);
+ strcat (name, "str");
+
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ {
+ name2 = segment_info[i].name;
+ if (name2 != NULL && strncmp(name2, name, 8) == 0)
+ {
+ stabstrseg = i;
+ break;
+ }
+ }
+
+ /* If we found the section, get its size. */
+ if (stabstrseg != SEG_UNKNOWN)
+ strsz = size_section (abfd, stabstrseg);
+
+ nsyms = size_section (abfd, seg) / 12 - 1;
+
+ /* Look for the first frag of sufficient size for the initial stab
+ symbol, and collect a pointer to it. */
+ while (frag && frag->fr_fix < 12)
+ frag = frag->fr_next;
+ assert (frag != 0);
+ p = frag->fr_literal;
+ assert (p != 0);
+
+ /* Write in the number of stab symbols and the size of the string
+ table. */
+ bfd_h_put_16 (abfd, (bfd_vma) nsyms, (bfd_byte *) p + 6);
+ bfd_h_put_32 (abfd, (bfd_vma) strsz, (bfd_byte *) p + 8);
+}
+
+#endif /* not BFD_ASSEMBLER */
+
+const pseudo_typeS obj_pseudo_table[] =
+{
+ {"def", obj_coff_def, 0},
+ {"dim", obj_coff_dim, 0},
+ {"endef", obj_coff_endef, 0},
+ {"line", obj_coff_line, 0},
+ {"ln", obj_coff_ln, 0},
+ {"appline", obj_coff_ln, 1},
+ {"scl", obj_coff_scl, 0},
+ {"size", obj_coff_size, 0},
+ {"tag", obj_coff_tag, 0},
+ {"type", obj_coff_type, 0},
+ {"val", obj_coff_val, 0},
+ {"section", obj_coff_section, 0},
+ {"sect", obj_coff_section, 0},
+ /* FIXME: We ignore the MRI short attribute. */
+ {"section.s", obj_coff_section, 0},
+ {"sect.s", obj_coff_section, 0},
+ /* We accept the .bss directive for backward compatibility with
+ earlier versions of gas. */
+ {"bss", obj_coff_bss, 0},
+ {"weak", obj_coff_weak, 0},
+#ifndef BFD_ASSEMBLER
+ {"use", obj_coff_section, 0},
+ {"text", obj_coff_text, 0},
+ {"data", obj_coff_data, 0},
+ {"lcomm", obj_coff_lcomm, 0},
+ {"ident", obj_coff_ident, 0},
+#else
+ {"optim", s_ignore, 0}, /* For sun386i cc (?) */
+ {"ident", s_ignore, 0}, /* we don't yet handle this. */
+#endif
+ {"version", s_ignore, 0},
+ {"ABORT", s_abort, 0},
+#ifdef TC_M88K
+ /* The m88k uses sdef instead of def. */
+ {"sdef", obj_coff_def, 0},
+#endif
+ {NULL} /* end sentinel */
+}; /* obj_pseudo_table */
+
+#ifdef BFD_ASSEMBLER
+
+/* Support for a COFF emulation. */
+
+static void
+coff_pop_insert ()
+{
+ pop_insert (obj_pseudo_table);
+}
+
+static int
+coff_sec_sym_ok_for_reloc (sec)
+ asection *sec;
+{
+ return 0;
+}
+
+static void
+no_func ()
+{
+ abort ();
+}
+
+const struct format_ops coff_format_ops =
+{
+ bfd_target_coff_flavour,
+ 0,
+ 1,
+ coff_frob_symbol,
+ no_func,
+ coff_frob_file_after_relocs,
+ 0, 0,
+ 0, 0,
+ 0,
+#if 0
+ obj_generate_asm_lineno,
+#else
+ no_func,
+#endif
+#if 0
+ obj_stab,
+#else
+ no_func,
+#endif
+ coff_sec_sym_ok_for_reloc,
+ coff_pop_insert,
+#if 0
+ obj_set_ext,
+#else
+ no_func,
+#endif
+ coff_obj_read_begin_hook,
+ coff_obj_symbol_new_hook,
+};
+
+#endif
diff --git a/gas/config/obj-coff.h b/gas/config/obj-coff.h
new file mode 100644
index 0000000000..465047796f
--- /dev/null
+++ b/gas/config/obj-coff.h
@@ -0,0 +1,841 @@
+/* coff object file format
+ Copyright (C) 1989, 90, 91, 92, 94, 95, 96, 97, 98, 1999
+ Free Software Foundation, Inc.
+
+ This file is part of GAS.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#ifndef OBJ_FORMAT_H
+#define OBJ_FORMAT_H
+
+#define OBJ_COFF 1
+
+#ifndef BFD_ASSEMBLER
+
+#define WORKING_DOT_WORD
+#define WARN_SIGNED_OVERFLOW_WORD
+#define OBJ_COFF_OMIT_OPTIONAL_HEADER
+#define BFD_HEADERS
+#define BFD
+
+#endif
+
+#include "targ-cpu.h"
+
+#include "bfd.h"
+
+/* This internal_lineno crap is to stop namespace pollution from the
+ bfd internal coff headerfile. */
+#define internal_lineno bfd_internal_lineno
+#include "coff/internal.h"
+#undef internal_lineno
+
+/* CPU-specific setup: */
+
+#ifdef TC_ARM
+#include "coff/arm.h"
+#ifndef TARGET_FORMAT
+#define TARGET_FORMAT "coff-arm"
+#endif
+#endif
+
+#ifdef TC_PPC
+#ifdef TE_PE
+#include "coff/powerpc.h"
+#else
+#include "coff/rs6000.h"
+#endif
+#endif
+
+#ifdef TC_SPARC
+#include "coff/sparc.h"
+#endif
+
+#ifdef TC_I386
+#include "coff/i386.h"
+
+#ifdef TE_PE
+#define TARGET_FORMAT "pe-i386"
+#endif
+
+#ifndef TARGET_FORMAT
+#define TARGET_FORMAT "coff-i386"
+#endif
+#endif
+
+#ifdef TC_M68K
+#include "coff/m68k.h"
+#ifndef TARGET_FORMAT
+#define TARGET_FORMAT "coff-m68k"
+#endif
+#endif
+
+#ifdef TC_A29K
+#include "coff/a29k.h"
+#define TARGET_FORMAT "coff-a29k-big"
+#endif
+
+#ifdef TC_I960
+#include "coff/i960.h"
+#define TARGET_FORMAT "coff-Intel-little"
+#endif
+
+#ifdef TC_Z8K
+#include "coff/z8k.h"
+#define TARGET_FORMAT "coff-z8k"
+#endif
+
+#ifdef TC_H8300
+#include "coff/h8300.h"
+#define TARGET_FORMAT "coff-h8300"
+#endif
+
+#ifdef TC_H8500
+#include "coff/h8500.h"
+#define TARGET_FORMAT "coff-h8500"
+#endif
+
+#ifdef TC_SH
+#include "coff/sh.h"
+#define TARGET_FORMAT \
+ (shl \
+ ? (sh_small ? "coff-shl-small" : "coff-shl") \
+ : (sh_small ? "coff-sh-small" : "coff-sh"))
+#endif
+
+#ifdef TC_M88K
+#include "coff/m88k.h"
+#define TARGET_FORMAT "coff-m88kbcs"
+#endif
+
+#ifdef TC_W65
+#include "coff/w65.h"
+#define TARGET_FORMAT "coff-w65"
+#endif
+
+#ifdef TC_TIC30
+#include "coff/tic30.h"
+#define TARGET_FORMAT "coff-tic30"
+#endif
+
+#ifdef TC_TIC80
+#include "coff/tic80.h"
+#define TARGET_FORMAT "coff-tic80"
+#define ALIGNMENT_IN_S_FLAGS 1
+#endif
+
+#ifdef TC_MCORE
+#include "coff/mcore.h"
+#ifndef TARGET_FORMAT
+#define TARGET_FORMAT "pe-mcore"
+#endif
+#endif
+
+/* Targets may also set this. Also, if BFD_ASSEMBLER is defined, this
+ will already have been defined. */
+#undef SYMBOLS_NEED_BACKPOINTERS
+#define SYMBOLS_NEED_BACKPOINTERS 1
+
+#ifndef OBJ_COFF_MAX_AUXENTRIES
+#define OBJ_COFF_MAX_AUXENTRIES 1
+#endif /* OBJ_COFF_MAX_AUXENTRIES */
+
+extern void coff_obj_symbol_new_hook PARAMS ((struct symbol *));
+#define obj_symbol_new_hook coff_obj_symbol_new_hook
+
+extern void coff_obj_read_begin_hook PARAMS ((void));
+#define obj_read_begin_hook coff_obj_read_begin_hook
+
+/* ***********************************************************************
+
+ This file really contains two implementations of the COFF back end.
+ They are in the process of being merged, but this is only a
+ preliminary, mechanical merging. Many definitions that are
+ identical between the two are still found in both versions.
+
+ The first version, with BFD_ASSEMBLER defined, uses high-level BFD
+ interfaces and data structures. The second version, with
+ BFD_ASSEMBLER not defined, also uses BFD, but mostly for swapping
+ data structures and for doing the actual I/O. The latter defines
+ the preprocessor symbols BFD and BFD_HEADERS. Try not to let this
+ confuse you.
+
+ These two are in the process of being merged, and eventually the
+ BFD_ASSEMBLER version should take over completely. Release timing
+ issues and namespace problems convinced me to merge the two
+ together in this fashion, a little sooner than I would have liked.
+ The real merge should be much better done by the time the next
+ release comes out.
+
+ For now, the structure of this file is:
+ <common>
+ #ifdef BFD_ASSEMBLER
+ <one version>
+ #else
+ <other version>
+ #endif
+ <common>
+ Unfortunately, the common portions are very small at the moment,
+ and many declarations or definitions are duplicated. The structure
+ of obj-coff.c is similar.
+
+ See doc/internals.texi for a brief discussion of the history, if
+ you care.
+
+ Ken Raeburn, 5 May 1994
+
+ *********************************************************************** */
+
+#ifdef BFD_ASSEMBLER
+
+#include "bfd/libcoff.h"
+
+#define OUTPUT_FLAVOR bfd_target_coff_flavour
+
+/* SYMBOL TABLE */
+
+/* Alter the field names, for now, until we've fixed up the other
+ references to use the new name. */
+#ifdef TC_I960
+#define TC_SYMFIELD_TYPE struct symbol *
+#define sy_tc bal
+#endif
+
+#define OBJ_SYMFIELD_TYPE unsigned long
+#define sy_obj sy_flags
+
+#define SYM_AUXENT(S) (&coffsymbol ((S)->bsym)->native[1].u.auxent)
+#define SYM_AUXINFO(S) (&coffsymbol ((S)->bsym)->native[1])
+
+#define DO_NOT_STRIP 0
+
+extern void obj_coff_section PARAMS ((int));
+
+/* The number of auxiliary entries */
+#define S_GET_NUMBER_AUXILIARY(s) (coffsymbol((s)->bsym)->native->u.syment.n_numaux)
+/* The number of auxiliary entries */
+#define S_SET_NUMBER_AUXILIARY(s,v) (S_GET_NUMBER_AUXILIARY (s) = (v))
+
+/* True if a symbol name is in the string table, i.e. its length is > 8. */
+#define S_IS_STRING(s) (strlen(S_GET_NAME(s)) > 8 ? 1 : 0)
+
+extern int S_SET_DATA_TYPE PARAMS ((struct symbol *, int));
+extern int S_SET_STORAGE_CLASS PARAMS ((struct symbol *, int));
+extern int S_GET_STORAGE_CLASS PARAMS ((struct symbol *));
+extern void SA_SET_SYM_ENDNDX PARAMS ((struct symbol *, struct symbol *));
+
+/* Auxiliary entry macros. SA_ stands for symbol auxiliary */
+/* Omit the tv related fields */
+/* Accessors */
+
+#define SA_GET_SYM_TAGNDX(s) (SYM_AUXENT (s)->x_sym.x_tagndx.l)
+#define SA_GET_SYM_LNNO(s) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_lnno)
+#define SA_GET_SYM_SIZE(s) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_size)
+#define SA_GET_SYM_FSIZE(s) (SYM_AUXENT (s)->x_sym.x_misc.x_fsize)
+#define SA_GET_SYM_LNNOPTR(s) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_lnnoptr)
+#define SA_GET_SYM_ENDNDX(s) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_endndx)
+#define SA_GET_SYM_DIMEN(s,i) (SYM_AUXENT (s)->x_sym.x_fcnary.x_ary.x_dimen[(i)])
+#define SA_GET_FILE_FNAME(s) (SYM_AUXENT (s)->x_file.x_fname)
+#define SA_GET_SCN_SCNLEN(s) (SYM_AUXENT (s)->x_scn.x_scnlen)
+#define SA_GET_SCN_NRELOC(s) (SYM_AUXENT (s)->x_scn.x_nreloc)
+#define SA_GET_SCN_NLINNO(s) (SYM_AUXENT (s)->x_scn.x_nlinno)
+
+#define SA_SET_SYM_LNNO(s,v) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_lnno=(v))
+#define SA_SET_SYM_SIZE(s,v) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_size=(v))
+#define SA_SET_SYM_FSIZE(s,v) (SYM_AUXENT (s)->x_sym.x_misc.x_fsize=(v))
+#define SA_SET_SYM_LNNOPTR(s,v) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_lnnoptr=(v))
+#define SA_SET_SYM_DIMEN(s,i,v) (SYM_AUXENT (s)->x_sym.x_fcnary.x_ary.x_dimen[(i)]=(v))
+#define SA_SET_FILE_FNAME(s,v) strncpy(SYM_AUXENT (s)->x_file.x_fname,(v),FILNMLEN)
+#define SA_SET_SCN_SCNLEN(s,v) (SYM_AUXENT (s)->x_scn.x_scnlen=(v))
+#define SA_SET_SCN_NRELOC(s,v) (SYM_AUXENT (s)->x_scn.x_nreloc=(v))
+#define SA_SET_SCN_NLINNO(s,v) (SYM_AUXENT (s)->x_scn.x_nlinno=(v))
+
+/*
+ * Internal use only definitions. SF_ stands for symbol flags.
+ *
+ * These values can be assigned to sy_symbol.ost_flags field of a symbolS.
+ *
+ * You'll break i960 if you shift the SYSPROC bits anywhere else. for
+ * more on the balname/callname hack, see tc-i960.h. b.out is done
+ * differently.
+ */
+
+#define SF_I960_MASK (0x000001ff) /* Bits 0-8 are used by the i960 port. */
+#define SF_SYSPROC (0x0000003f) /* bits 0-5 are used to store the sysproc number */
+#define SF_IS_SYSPROC (0x00000040) /* bit 6 marks symbols that are sysprocs */
+#define SF_BALNAME (0x00000080) /* bit 7 marks BALNAME symbols */
+#define SF_CALLNAME (0x00000100) /* bit 8 marks CALLNAME symbols */
+
+#define SF_NORMAL_MASK (0x0000ffff) /* bits 12-15 are general purpose. */
+
+#define SF_STATICS (0x00001000) /* Mark the .text & all symbols */
+#define SF_DEFINED (0x00002000) /* Symbol is defined in this file */
+#define SF_STRING (0x00004000) /* Symbol name length > 8 */
+#define SF_LOCAL (0x00008000) /* Symbol must not be emitted */
+
+#define SF_DEBUG_MASK (0xffff0000) /* bits 16-31 are debug info */
+
+#define SF_FUNCTION (0x00010000) /* The symbol is a function */
+#define SF_PROCESS (0x00020000) /* Process symbol before write */
+#define SF_TAGGED (0x00040000) /* Is associated with a tag */
+#define SF_TAG (0x00080000) /* Is a tag */
+#define SF_DEBUG (0x00100000) /* Is in debug or abs section */
+#define SF_GET_SEGMENT (0x00200000) /* Get the section of the forward symbol. */
+/* All other bits are unused. */
+
+/* Accessors */
+#define SF_GET(s) ((s)->sy_flags)
+#define SF_GET_DEBUG(s) ((s)->bsym->flags & BSF_DEBUGGING)
+#define SF_SET_DEBUG(s) ((s)->bsym->flags |= BSF_DEBUGGING)
+#define SF_GET_NORMAL_FIELD(s) (SF_GET (s) & SF_NORMAL_MASK)
+#define SF_GET_DEBUG_FIELD(s) (SF_GET (s) & SF_DEBUG_MASK)
+#define SF_GET_FILE(s) (SF_GET (s) & SF_FILE)
+#define SF_GET_STATICS(s) (SF_GET (s) & SF_STATICS)
+#define SF_GET_DEFINED(s) (SF_GET (s) & SF_DEFINED)
+#define SF_GET_STRING(s) (SF_GET (s) & SF_STRING)
+#define SF_GET_LOCAL(s) (SF_GET (s) & SF_LOCAL)
+#define SF_GET_FUNCTION(s) (SF_GET (s) & SF_FUNCTION)
+#define SF_GET_PROCESS(s) (SF_GET (s) & SF_PROCESS)
+#define SF_GET_TAGGED(s) (SF_GET (s) & SF_TAGGED)
+#define SF_GET_TAG(s) (SF_GET (s) & SF_TAG)
+#define SF_GET_GET_SEGMENT(s) (SF_GET (s) & SF_GET_SEGMENT)
+#define SF_GET_I960(s) (SF_GET (s) & SF_I960_MASK) /* used by i960 */
+#define SF_GET_BALNAME(s) (SF_GET (s) & SF_BALNAME) /* used by i960 */
+#define SF_GET_CALLNAME(s) (SF_GET (s) & SF_CALLNAME) /* used by i960 */
+#define SF_GET_IS_SYSPROC(s) (SF_GET (s) & SF_IS_SYSPROC) /* used by i960 */
+#define SF_GET_SYSPROC(s) (SF_GET (s) & SF_SYSPROC) /* used by i960 */
+
+/* Modifiers */
+#define SF_SET(s,v) (SF_GET (s) = (v))
+#define SF_SET_NORMAL_FIELD(s,v)(SF_GET (s) |= ((v) & SF_NORMAL_MASK))
+#define SF_SET_DEBUG_FIELD(s,v) (SF_GET (s) |= ((v) & SF_DEBUG_MASK))
+#define SF_SET_FILE(s) (SF_GET (s) |= SF_FILE)
+#define SF_SET_STATICS(s) (SF_GET (s) |= SF_STATICS)
+#define SF_SET_DEFINED(s) (SF_GET (s) |= SF_DEFINED)
+#define SF_SET_STRING(s) (SF_GET (s) |= SF_STRING)
+#define SF_SET_LOCAL(s) (SF_GET (s) |= SF_LOCAL)
+#define SF_CLEAR_LOCAL(s) (SF_GET (s) &= ~SF_LOCAL)
+#define SF_SET_FUNCTION(s) (SF_GET (s) |= SF_FUNCTION)
+#define SF_SET_PROCESS(s) (SF_GET (s) |= SF_PROCESS)
+#define SF_SET_TAGGED(s) (SF_GET (s) |= SF_TAGGED)
+#define SF_SET_TAG(s) (SF_GET (s) |= SF_TAG)
+#define SF_SET_GET_SEGMENT(s) (SF_GET (s) |= SF_GET_SEGMENT)
+#define SF_SET_I960(s,v) (SF_GET (s) |= ((v) & SF_I960_MASK)) /* used by i960 */
+#define SF_SET_BALNAME(s) (SF_GET (s) |= SF_BALNAME) /* used by i960 */
+#define SF_SET_CALLNAME(s) (SF_GET (s) |= SF_CALLNAME) /* used by i960 */
+#define SF_SET_IS_SYSPROC(s) (SF_GET (s) |= SF_IS_SYSPROC) /* used by i960 */
+#define SF_SET_SYSPROC(s,v) (SF_GET (s) |= ((v) & SF_SYSPROC)) /* used by i960 */
+
+/* -------------- Line number handling ------- */
+extern int text_lineno_number;
+extern int coff_line_base;
+extern int coff_n_line_nos;
+
+#define obj_emit_lineno(WHERE,LINE,FILE_START) abort ()
+extern void coff_add_linesym PARAMS ((struct symbol *));
+
+
+void c_dot_file_symbol PARAMS ((char *filename));
+#define obj_app_file c_dot_file_symbol
+
+extern void coff_frob_symbol PARAMS ((struct symbol *, int *));
+extern void coff_adjust_symtab PARAMS ((void));
+extern void coff_frob_section PARAMS ((segT));
+extern void coff_adjust_section_syms PARAMS ((bfd *, asection *, PTR));
+extern void coff_frob_file_after_relocs PARAMS ((void));
+#define obj_frob_symbol(S,P) coff_frob_symbol(S,&P)
+#ifndef obj_adjust_symtab
+#define obj_adjust_symtab() coff_adjust_symtab()
+#endif
+#define obj_frob_section(S) coff_frob_section (S)
+#define obj_frob_file_after_relocs() coff_frob_file_after_relocs ()
+
+extern struct symbol *coff_last_function;
+
+/* Forward the segment of a forwarded symbol, handle assignments that
+ just copy symbol values, etc. */
+#ifndef TE_I386AIX
+#define OBJ_COPY_SYMBOL_ATTRIBUTES(dest,src) \
+ (SF_GET_GET_SEGMENT (dest) \
+ ? (S_SET_SEGMENT (dest, S_GET_SEGMENT (src)), 0) \
+ : 0)
+#else
+#define OBJ_COPY_SYMBOL_ATTRIBUTES(dest,src) \
+ (SF_GET_GET_SEGMENT (dest) && S_GET_SEGMENT (dest) == SEG_UNKNOWN \
+ ? (S_SET_SEGMENT (dest, S_GET_SEGMENT (src)), 0) \
+ : 0)
+#endif
+
+/* sanity check */
+
+#ifdef TC_I960
+#ifndef C_LEAFSTAT
+hey ! Where is the C_LEAFSTAT definition ? i960 - coff support is depending on it.
+#endif /* no C_LEAFSTAT */
+#endif /* TC_I960 */
+
+#else /* not BFD_ASSEMBLER */
+
+#ifdef TC_A29K
+/* Allow translate from aout relocs to coff relocs */
+#define NO_RELOC 20
+#define RELOC_32 1
+#define RELOC_8 2
+#define RELOC_CONST 3
+#define RELOC_CONSTH 4
+#define RELOC_JUMPTARG 5
+#define RELOC_BASE22 6
+#define RELOC_HI22 7
+#define RELOC_LO10 8
+#define RELOC_BASE13 9
+#define RELOC_WDISP22 10
+#define RELOC_WDISP30 11
+#endif
+
+extern const segT N_TYPE_seg[];
+
+/* Magic number of paged executable. */
+#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE 0x8300
+
+
+/* SYMBOL TABLE */
+
+/* Symbol table entry data type */
+
+typedef struct
+{
+ /* Basic symbol */
+ struct internal_syment ost_entry;
+ /* Auxiliary entry. */
+ union internal_auxent ost_auxent[OBJ_COFF_MAX_AUXENTRIES];
+ /* obj_coff internal use only flags */
+ unsigned int ost_flags;
+} obj_symbol_type;
+
+#ifndef DO_NOT_STRIP
+#define DO_NOT_STRIP 0
+#endif
+/* Symbol table macros and constants */
+
+/* Possible and usefull section number in symbol table
+ * The values of TEXT, DATA and BSS may not be portable.
+ */
+
+#define C_ABS_SECTION N_ABS
+#define C_UNDEF_SECTION N_UNDEF
+#define C_DEBUG_SECTION N_DEBUG
+#define C_NTV_SECTION N_TV
+#define C_PTV_SECTION P_TV
+#define C_REGISTER_SECTION 50
+
+/*
+ * Macros to extract information from a symbol table entry.
+ * This syntaxic indirection allows independence regarding a.out or coff.
+ * The argument (s) of all these macros is a pointer to a symbol table entry.
+ */
+
+/* Predicates */
+/* True if the symbol is external */
+#define S_IS_EXTERNAL(s) ((s)->sy_symbol.ost_entry.n_scnum == C_UNDEF_SECTION)
+/* True if symbol has been defined, ie :
+ section > 0 (DATA, TEXT or BSS)
+ section == 0 and value > 0 (external bss symbol) */
+#define S_IS_DEFINED(s) \
+ ((s)->sy_symbol.ost_entry.n_scnum > C_UNDEF_SECTION \
+ || ((s)->sy_symbol.ost_entry.n_scnum == C_UNDEF_SECTION \
+ && S_GET_VALUE (s) > 0) \
+ || ((s)->sy_symbol.ost_entry.n_scnum == C_ABS_SECTION))
+/* True if a debug special symbol entry */
+#define S_IS_DEBUG(s) ((s)->sy_symbol.ost_entry.n_scnum == C_DEBUG_SECTION)
+/* True if a symbol is local symbol name */
+/* A symbol name whose name includes ^A is a gas internal pseudo symbol */
+#define S_IS_LOCAL(s) \
+ ((s)->sy_symbol.ost_entry.n_scnum == C_REGISTER_SECTION \
+ || (S_LOCAL_NAME(s) && ! flag_keep_locals && ! S_IS_DEBUG (s)) \
+ || strchr (S_GET_NAME (s), '\001') != NULL \
+ || strchr (S_GET_NAME (s), '\002') != NULL \
+ || (flag_strip_local_absolute \
+ && !S_IS_EXTERNAL(s) \
+ && (s)->sy_symbol.ost_entry.n_scnum == C_ABS_SECTION))
+/* True if a symbol is not defined in this file */
+#define S_IS_EXTERN(s) ((s)->sy_symbol.ost_entry.n_scnum == 0 \
+ && S_GET_VALUE (s) == 0)
+/*
+ * True if a symbol can be multiply defined (bss symbols have this def
+ * though it is bad practice)
+ */
+#define S_IS_COMMON(s) ((s)->sy_symbol.ost_entry.n_scnum == 0 \
+ && S_GET_VALUE (s) != 0)
+/* True if a symbol name is in the string table, i.e. its length is > 8. */
+#define S_IS_STRING(s) (strlen(S_GET_NAME(s)) > 8 ? 1 : 0)
+
+/* True if a symbol is defined as weak. */
+#ifdef TE_PE
+#define S_IS_WEAK(s) \
+ ((s)->sy_symbol.ost_entry.n_sclass == C_NT_WEAK \
+ || (s)->sy_symbol.ost_entry.n_sclass == C_WEAKEXT)
+#else
+#define S_IS_WEAK(s) \
+ ((s)->sy_symbol.ost_entry.n_sclass == C_WEAKEXT)
+#endif
+
+/* Accessors */
+/* The name of the symbol */
+#define S_GET_NAME(s) ((char*)(s)->sy_symbol.ost_entry.n_offset)
+/* The pointer to the string table */
+#define S_GET_OFFSET(s) ((s)->sy_symbol.ost_entry.n_offset)
+/* The numeric value of the segment */
+#define S_GET_SEGMENT(s) s_get_segment(s)
+/* The data type */
+#define S_GET_DATA_TYPE(s) ((s)->sy_symbol.ost_entry.n_type)
+/* The storage class */
+#define S_GET_STORAGE_CLASS(s) ((s)->sy_symbol.ost_entry.n_sclass)
+/* The number of auxiliary entries */
+#define S_GET_NUMBER_AUXILIARY(s) ((s)->sy_symbol.ost_entry.n_numaux)
+
+/* Modifiers */
+/* Set the name of the symbol */
+#define S_SET_NAME(s,v) ((s)->sy_symbol.ost_entry.n_offset = (unsigned long)(v))
+/* Set the offset of the symbol */
+#define S_SET_OFFSET(s,v) ((s)->sy_symbol.ost_entry.n_offset = (v))
+/* The numeric value of the segment */
+#define S_SET_SEGMENT(s,v) ((s)->sy_symbol.ost_entry.n_scnum = SEGMENT_TO_SYMBOL_TYPE(v))
+/* The data type */
+#define S_SET_DATA_TYPE(s,v) ((s)->sy_symbol.ost_entry.n_type = (v))
+/* The storage class */
+#define S_SET_STORAGE_CLASS(s,v) ((s)->sy_symbol.ost_entry.n_sclass = (v))
+/* The number of auxiliary entries */
+#define S_SET_NUMBER_AUXILIARY(s,v) ((s)->sy_symbol.ost_entry.n_numaux = (v))
+
+/* Additional modifiers */
+/* The symbol is external (does not mean undefined) */
+#define S_SET_EXTERNAL(s) { S_SET_STORAGE_CLASS(s, C_EXT) ; SF_CLEAR_LOCAL(s); }
+
+/* Auxiliary entry macros. SA_ stands for symbol auxiliary */
+/* Omit the tv related fields */
+/* Accessors */
+#define SYM_AUXENT(S) (&(S)->sy_symbol.ost_auxent[0])
+
+#define SA_GET_SYM_TAGNDX(s) (SYM_AUXENT (s)->x_sym.x_tagndx.l)
+#define SA_GET_SYM_LNNO(s) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_lnno)
+#define SA_GET_SYM_SIZE(s) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_size)
+#define SA_GET_SYM_FSIZE(s) (SYM_AUXENT (s)->x_sym.x_misc.x_fsize)
+#define SA_GET_SYM_LNNOPTR(s) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_lnnoptr)
+#define SA_GET_SYM_ENDNDX(s) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_endndx.l)
+#define SA_GET_SYM_DIMEN(s,i) (SYM_AUXENT (s)->x_sym.x_fcnary.x_ary.x_dimen[(i)])
+#define SA_GET_FILE_FNAME(s) (SYM_AUXENT (s)->x_file.x_fname)
+#define SA_GET_FILE_FNAME_OFFSET(s) (SYM_AUXENT (s)->x_file.x_n.x_offset)
+#define SA_GET_FILE_FNAME_ZEROS(s) (SYM_AUXENT (s)->x_file.x_n.x_zeroes)
+#define SA_GET_SCN_SCNLEN(s) (SYM_AUXENT (s)->x_scn.x_scnlen)
+#define SA_GET_SCN_NRELOC(s) (SYM_AUXENT (s)->x_scn.x_nreloc)
+#define SA_GET_SCN_NLINNO(s) (SYM_AUXENT (s)->x_scn.x_nlinno)
+
+/* Modifiers */
+#define SA_SET_SYM_TAGNDX(s,v) (SYM_AUXENT (s)->x_sym.x_tagndx.l=(v))
+#define SA_SET_SYM_LNNO(s,v) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_lnno=(v))
+#define SA_SET_SYM_SIZE(s,v) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_size=(v))
+#define SA_SET_SYM_FSIZE(s,v) (SYM_AUXENT (s)->x_sym.x_misc.x_fsize=(v))
+#define SA_SET_SYM_LNNOPTR(s,v) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_lnnoptr=(v))
+#define SA_SET_SYM_ENDNDX(s,v) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_endndx.l=(v))
+#define SA_SET_SYM_DIMEN(s,i,v) (SYM_AUXENT (s)->x_sym.x_fcnary.x_ary.x_dimen[(i)]=(v))
+#define SA_SET_FILE_FNAME(s,v) strncpy(SYM_AUXENT (s)->x_file.x_fname,(v),FILNMLEN)
+#define SA_SET_FILE_FNAME_OFFSET(s,v) (SYM_AUXENT (s)->x_file.x_n.x_offset=(v))
+#define SA_SET_FILE_FNAME_ZEROS(s,v) (SYM_AUXENT (s)->x_file.x_n.x_zeroes=(v))
+#define SA_SET_SCN_SCNLEN(s,v) (SYM_AUXENT (s)->x_scn.x_scnlen=(v))
+#define SA_SET_SCN_NRELOC(s,v) (SYM_AUXENT (s)->x_scn.x_nreloc=(v))
+#define SA_SET_SCN_NLINNO(s,v) (SYM_AUXENT (s)->x_scn.x_nlinno=(v))
+
+/*
+ * Internal use only definitions. SF_ stands for symbol flags.
+ *
+ * These values can be assigned to sy_symbol.ost_flags field of a symbolS.
+ *
+ * You'll break i960 if you shift the SYSPROC bits anywhere else. for
+ * more on the balname/callname hack, see tc-i960.h. b.out is done
+ * differently.
+ */
+
+#define SF_I960_MASK (0x000001ff) /* Bits 0-8 are used by the i960 port. */
+#define SF_SYSPROC (0x0000003f) /* bits 0-5 are used to store the sysproc number */
+#define SF_IS_SYSPROC (0x00000040) /* bit 6 marks symbols that are sysprocs */
+#define SF_BALNAME (0x00000080) /* bit 7 marks BALNAME symbols */
+#define SF_CALLNAME (0x00000100) /* bit 8 marks CALLNAME symbols */
+
+#define SF_NORMAL_MASK (0x0000ffff) /* bits 12-15 are general purpose. */
+
+#define SF_STATICS (0x00001000) /* Mark the .text & all symbols */
+#define SF_DEFINED (0x00002000) /* Symbol is defined in this file */
+#define SF_STRING (0x00004000) /* Symbol name length > 8 */
+#define SF_LOCAL (0x00008000) /* Symbol must not be emitted */
+
+#define SF_DEBUG_MASK (0xffff0000) /* bits 16-31 are debug info */
+
+#define SF_FUNCTION (0x00010000) /* The symbol is a function */
+#define SF_PROCESS (0x00020000) /* Process symbol before write */
+#define SF_TAGGED (0x00040000) /* Is associated with a tag */
+#define SF_TAG (0x00080000) /* Is a tag */
+#define SF_DEBUG (0x00100000) /* Is in debug or abs section */
+#define SF_GET_SEGMENT (0x00200000) /* Get the section of the forward symbol. */
+#define SF_ADJ_LNNOPTR (0x00400000) /* Has a lnnoptr */
+/* All other bits are unused. */
+
+/* Accessors */
+#define SF_GET(s) ((s)->sy_symbol.ost_flags)
+#define SF_GET_NORMAL_FIELD(s) (SF_GET (s) & SF_NORMAL_MASK)
+#define SF_GET_DEBUG_FIELD(s) (SF_GET (s) & SF_DEBUG_MASK)
+#define SF_GET_FILE(s) (SF_GET (s) & SF_FILE)
+#define SF_GET_STATICS(s) (SF_GET (s) & SF_STATICS)
+#define SF_GET_DEFINED(s) (SF_GET (s) & SF_DEFINED)
+#define SF_GET_STRING(s) (SF_GET (s) & SF_STRING)
+#define SF_GET_LOCAL(s) (SF_GET (s) & SF_LOCAL)
+#define SF_GET_FUNCTION(s) (SF_GET (s) & SF_FUNCTION)
+#define SF_GET_PROCESS(s) (SF_GET (s) & SF_PROCESS)
+#define SF_GET_DEBUG(s) (SF_GET (s) & SF_DEBUG)
+#define SF_GET_TAGGED(s) (SF_GET (s) & SF_TAGGED)
+#define SF_GET_TAG(s) (SF_GET (s) & SF_TAG)
+#define SF_GET_GET_SEGMENT(s) (SF_GET (s) & SF_GET_SEGMENT)
+#define SF_GET_ADJ_LNNOPTR(s) (SF_GET (s) & SF_ADJ_LNNOPTR)
+#define SF_GET_I960(s) (SF_GET (s) & SF_I960_MASK) /* used by i960 */
+#define SF_GET_BALNAME(s) (SF_GET (s) & SF_BALNAME) /* used by i960 */
+#define SF_GET_CALLNAME(s) (SF_GET (s) & SF_CALLNAME) /* used by i960 */
+#define SF_GET_IS_SYSPROC(s) (SF_GET (s) & SF_IS_SYSPROC) /* used by i960 */
+#define SF_GET_SYSPROC(s) (SF_GET (s) & SF_SYSPROC) /* used by i960 */
+
+/* Modifiers */
+#define SF_SET(s,v) (SF_GET (s) = (v))
+#define SF_SET_NORMAL_FIELD(s,v)(SF_GET (s) |= ((v) & SF_NORMAL_MASK))
+#define SF_SET_DEBUG_FIELD(s,v) (SF_GET (s) |= ((v) & SF_DEBUG_MASK))
+#define SF_SET_FILE(s) (SF_GET (s) |= SF_FILE)
+#define SF_SET_STATICS(s) (SF_GET (s) |= SF_STATICS)
+#define SF_SET_DEFINED(s) (SF_GET (s) |= SF_DEFINED)
+#define SF_SET_STRING(s) (SF_GET (s) |= SF_STRING)
+#define SF_SET_LOCAL(s) (SF_GET (s) |= SF_LOCAL)
+#define SF_CLEAR_LOCAL(s) (SF_GET (s) &= ~SF_LOCAL)
+#define SF_SET_FUNCTION(s) (SF_GET (s) |= SF_FUNCTION)
+#define SF_SET_PROCESS(s) (SF_GET (s) |= SF_PROCESS)
+#define SF_SET_DEBUG(s) (SF_GET (s) |= SF_DEBUG)
+#define SF_SET_TAGGED(s) (SF_GET (s) |= SF_TAGGED)
+#define SF_SET_TAG(s) (SF_GET (s) |= SF_TAG)
+#define SF_SET_GET_SEGMENT(s) (SF_GET (s) |= SF_GET_SEGMENT)
+#define SF_SET_ADJ_LNNOPTR(s) (SF_GET (s) |= SF_ADJ_LNNOPTR)
+#define SF_SET_I960(s,v) (SF_GET (s) |= ((v) & SF_I960_MASK)) /* used by i960 */
+#define SF_SET_BALNAME(s) (SF_GET (s) |= SF_BALNAME) /* used by i960 */
+#define SF_SET_CALLNAME(s) (SF_GET (s) |= SF_CALLNAME) /* used by i960 */
+#define SF_SET_IS_SYSPROC(s) (SF_GET (s) |= SF_IS_SYSPROC) /* used by i960 */
+#define SF_SET_SYSPROC(s,v) (SF_GET (s) |= ((v) & SF_SYSPROC)) /* used by i960 */
+
+/* File header macro and type definition */
+
+/*
+ * File position calculators. Beware to use them when all the
+ * appropriate fields are set in the header.
+ */
+
+#ifdef OBJ_COFF_OMIT_OPTIONAL_HEADER
+#define OBJ_COFF_AOUTHDRSZ (0)
+#else
+#define OBJ_COFF_AOUTHDRSZ (AOUTHDRSZ)
+#endif /* OBJ_COFF_OMIT_OPTIONAL_HEADER */
+
+#define H_GET_FILE_SIZE(h) \
+ (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \
+ H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \
+ H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \
+ H_GET_RELOCATION_SIZE(h) + H_GET_LINENO_SIZE(h) + \
+ H_GET_SYMBOL_TABLE_SIZE(h) + \
+ (h)->string_table_size)
+#define H_GET_TEXT_FILE_OFFSET(h) \
+ (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \
+ H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ)
+#define H_GET_DATA_FILE_OFFSET(h) \
+ (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \
+ H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \
+ H_GET_TEXT_SIZE(h))
+#define H_GET_BSS_FILE_OFFSET(h) 0
+#define H_GET_RELOCATION_FILE_OFFSET(h) \
+ (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \
+ H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \
+ H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h))
+#define H_GET_LINENO_FILE_OFFSET(h) \
+ (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \
+ H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \
+ H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \
+ H_GET_RELOCATION_SIZE(h))
+#define H_GET_SYMBOL_TABLE_FILE_OFFSET(h) \
+ (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \
+ H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \
+ H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \
+ H_GET_RELOCATION_SIZE(h) + H_GET_LINENO_SIZE(h))
+
+/* Accessors */
+/* aouthdr */
+#define H_GET_MAGIC_NUMBER(h) ((h)->aouthdr.magic)
+#define H_GET_VERSION_STAMP(h) ((h)->aouthdr.vstamp)
+#define H_GET_TEXT_SIZE(h) ((h)->aouthdr.tsize)
+#define H_GET_DATA_SIZE(h) ((h)->aouthdr.dsize)
+#define H_GET_BSS_SIZE(h) ((h)->aouthdr.bsize)
+#define H_GET_ENTRY_POINT(h) ((h)->aouthdr.entry)
+#define H_GET_TEXT_START(h) ((h)->aouthdr.text_start)
+#define H_GET_DATA_START(h) ((h)->aouthdr.data_start)
+/* filehdr */
+#define H_GET_FILE_MAGIC_NUMBER(h) ((h)->filehdr.f_magic)
+#define H_GET_NUMBER_OF_SECTIONS(h) ((h)->filehdr.f_nscns)
+#define H_GET_TIME_STAMP(h) ((h)->filehdr.f_timdat)
+#define H_GET_SYMBOL_TABLE_POINTER(h) ((h)->filehdr.f_symptr)
+#define H_GET_SYMBOL_COUNT(h) ((h)->filehdr.f_nsyms)
+#define H_GET_SYMBOL_TABLE_SIZE(h) (H_GET_SYMBOL_COUNT(h) * SYMESZ)
+#define H_GET_SIZEOF_OPTIONAL_HEADER(h) ((h)->filehdr.f_opthdr)
+#define H_GET_FLAGS(h) ((h)->filehdr.f_flags)
+/* Extra fields to achieve bsd a.out compatibility and for convenience */
+#define H_GET_RELOCATION_SIZE(h) ((h)->relocation_size)
+#define H_GET_STRING_SIZE(h) ((h)->string_table_size)
+#define H_GET_LINENO_SIZE(h) ((h)->lineno_size)
+
+#ifndef OBJ_COFF_OMIT_OPTIONAL_HEADER
+#define H_GET_HEADER_SIZE(h) (sizeof(FILHDR) \
+ + sizeof(AOUTHDR)\
+ + (H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ))
+#else /* OBJ_COFF_OMIT_OPTIONAL_HEADER */
+#define H_GET_HEADER_SIZE(h) (sizeof(FILHDR) \
+ + (H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ))
+#endif /* OBJ_COFF_OMIT_OPTIONAL_HEADER */
+
+#define H_GET_TEXT_RELOCATION_SIZE(h) (text_section_header.s_nreloc * RELSZ)
+#define H_GET_DATA_RELOCATION_SIZE(h) (data_section_header.s_nreloc * RELSZ)
+
+/* Modifiers */
+/* aouthdr */
+#define H_SET_MAGIC_NUMBER(h,v) ((h)->aouthdr.magic = (v))
+#define H_SET_VERSION_STAMP(h,v) ((h)->aouthdr.vstamp = (v))
+#define H_SET_TEXT_SIZE(h,v) ((h)->aouthdr.tsize = (v))
+#define H_SET_DATA_SIZE(h,v) ((h)->aouthdr.dsize = (v))
+#define H_SET_BSS_SIZE(h,v) ((h)->aouthdr.bsize = (v))
+#define H_SET_ENTRY_POINT(h,v) ((h)->aouthdr.entry = (v))
+#define H_SET_TEXT_START(h,v) ((h)->aouthdr.text_start = (v))
+#define H_SET_DATA_START(h,v) ((h)->aouthdr.data_start = (v))
+/* filehdr */
+#define H_SET_FILE_MAGIC_NUMBER(h,v) ((h)->filehdr.f_magic = (v))
+#define H_SET_NUMBER_OF_SECTIONS(h,v) ((h)->filehdr.f_nscns = (v))
+#define H_SET_TIME_STAMP(h,v) ((h)->filehdr.f_timdat = (v))
+#define H_SET_SYMBOL_TABLE_POINTER(h,v) ((h)->filehdr.f_symptr = (v))
+#define H_SET_SYMBOL_TABLE_SIZE(h,v) ((h)->filehdr.f_nsyms = (v))
+#define H_SET_SIZEOF_OPTIONAL_HEADER(h,v) ((h)->filehdr.f_opthdr = (v))
+#define H_SET_FLAGS(h,v) ((h)->filehdr.f_flags = (v))
+/* Extra fields to achieve bsd a.out compatibility and for convinience */
+#define H_SET_RELOCATION_SIZE(h,t,d) ((h)->relocation_size = (t)+(d))
+#define H_SET_STRING_SIZE(h,v) ((h)->string_table_size = (v))
+#define H_SET_LINENO_SIZE(h,v) ((h)->lineno_size = (v))
+
+/* Segment flipping */
+
+typedef struct
+{
+ struct internal_aouthdr aouthdr; /* a.out header */
+ struct internal_filehdr filehdr; /* File header, not machine dep. */
+ long string_table_size; /* names + '\0' + sizeof(int) */
+ long relocation_size; /* Cumulated size of relocation
+ information for all sections in
+ bytes. */
+ long lineno_size; /* Size of the line number information
+ table in bytes */
+} object_headers;
+
+
+
+struct lineno_list
+{
+ struct bfd_internal_lineno line;
+ char *frag; /* Frag to which the line number is related */
+ struct lineno_list *next; /* Forward chain pointer */
+};
+
+
+
+
+#define obj_segment_name(i) (segment_info[(int) (i)].scnhdr.s_name)
+
+#define obj_add_segment(s) obj_coff_add_segment (s)
+
+extern segT obj_coff_add_segment PARAMS ((const char *));
+
+extern void obj_coff_section PARAMS ((int));
+
+extern void c_dot_file_symbol PARAMS ((char *filename));
+#define obj_app_file c_dot_file_symbol
+extern void obj_extra_stuff PARAMS ((object_headers * headers));
+
+extern segT s_get_segment PARAMS ((struct symbol * ptr));
+
+extern void c_section_header PARAMS ((struct internal_scnhdr * header,
+ char *name,
+ long core_address,
+ long size,
+ long data_ptr,
+ long reloc_ptr,
+ long lineno_ptr,
+ long reloc_number,
+ long lineno_number,
+ long alignment));
+
+#ifndef tc_coff_symbol_emit_hook
+void tc_coff_symbol_emit_hook PARAMS ((struct symbol *));
+#endif
+
+/* sanity check */
+
+#ifdef TC_I960
+#ifndef C_LEAFSTAT
+hey ! Where is the C_LEAFSTAT definition ? i960 - coff support is depending on it.
+#endif /* no C_LEAFSTAT */
+#endif /* TC_I960 */
+extern struct internal_scnhdr data_section_header;
+extern struct internal_scnhdr text_section_header;
+
+/* Forward the segment of a forwarded symbol. */
+#define OBJ_COPY_SYMBOL_ATTRIBUTES(dest,src) \
+ (SF_GET_GET_SEGMENT (dest) \
+ ? (S_SET_SEGMENT (dest, S_GET_SEGMENT (src)), 0) \
+ : 0)
+
+#ifdef TE_PE
+#define obj_handle_link_once(t) obj_coff_pe_handle_link_once (t)
+extern void obj_coff_pe_handle_link_once ();
+#endif
+
+#endif /* not BFD_ASSEMBLER */
+
+/* In COFF, if a symbol is defined using .def/.val SYM/.endef, it's OK
+ to redefine the symbol later on. This can happen if C symbols use
+ a prefix, and a symbol is defined both with and without the prefix,
+ as in start/_start/__start in gcc/libgcc1-test.c. */
+#define RESOLVE_SYMBOL_REDEFINITION(sym) \
+(SF_GET_GET_SEGMENT (sym) \
+ ? (sym->sy_frag = frag_now, \
+ S_SET_VALUE (sym, frag_now_fix ()), \
+ S_SET_SEGMENT (sym, now_seg), \
+ 0) \
+ : 0)
+
+/* Stabs in a coff file go into their own section. */
+#define SEPARATE_STAB_SECTIONS 1
+
+/* We need 12 bytes at the start of the section to hold some initial
+ information. */
+extern void obj_coff_init_stab_section PARAMS ((segT));
+#define INIT_STAB_SECTION(seg) obj_coff_init_stab_section (seg)
+
+#endif /* OBJ_FORMAT_H */
diff --git a/gas/config/obj-ecoff.c b/gas/config/obj-ecoff.c
new file mode 100644
index 0000000000..ec3ce8811b
--- /dev/null
+++ b/gas/config/obj-ecoff.c
@@ -0,0 +1,309 @@
+/* ECOFF object file format.
+ Copyright (C) 1993, 94, 95, 96, 1997, 1998 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+ This file was put together by Ian Lance Taylor <ian@cygnus.com>.
+
+ This file is part of GAS.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#define OBJ_HEADER "obj-ecoff.h"
+#include "as.h"
+#include "coff/internal.h"
+#include "bfd/libcoff.h"
+#include "bfd/libecoff.h"
+
+/* Almost all of the ECOFF support is actually in ecoff.c in the main
+ gas directory. This file mostly just arranges to call that one at
+ the right times. */
+
+static int ecoff_sec_sym_ok_for_reloc PARAMS ((asection *));
+static void obj_ecoff_frob_symbol PARAMS ((symbolS *, int *));
+static void ecoff_pop_insert PARAMS ((void));
+
+/* These are the pseudo-ops we support in this file. Only those
+ relating to debugging information are supported here.
+
+ The following pseudo-ops from the Kane and Heinrich MIPS book
+ should be defined here, but are currently unsupported: .aent,
+ .bgnb, .endb, .verstamp, .vreg.
+
+ The following pseudo-ops from the Kane and Heinrich MIPS book are
+ MIPS CPU specific, and should be defined by tc-mips.c: .alias,
+ .extern, .galive, .gjaldef, .gjrlive, .livereg, .noalias, .option,
+ .rdata, .sdata, .set.
+
+ The following pseudo-ops from the Kane and Heinrich MIPS book are
+ not MIPS CPU specific, but are also not ECOFF specific. I have
+ only listed the ones which are not already in read.c. It's not
+ completely clear where these should be defined, but tc-mips.c is
+ probably the most reasonable place: .asciiz, .asm0, .endr, .err,
+ .half, .lab, .repeat, .struct, .weakext. */
+
+const pseudo_typeS obj_pseudo_table[] =
+{
+ /* COFF style debugging information. .ln is not used; .loc is used
+ instead. */
+ { "def", ecoff_directive_def, 0 },
+ { "dim", ecoff_directive_dim, 0 },
+ { "endef", ecoff_directive_endef, 0 },
+ { "file", ecoff_directive_file, 0 },
+ { "scl", ecoff_directive_scl, 0 },
+ { "size", ecoff_directive_size, 0 },
+ { "esize", ecoff_directive_size, 0 },
+ { "tag", ecoff_directive_tag, 0 },
+ { "type", ecoff_directive_type, 0 },
+ { "etype", ecoff_directive_type, 0 },
+ { "val", ecoff_directive_val, 0 },
+
+ /* ECOFF specific debugging information. */
+ { "begin", ecoff_directive_begin, 0 },
+ { "bend", ecoff_directive_bend, 0 },
+ { "end", ecoff_directive_end, 0 },
+ { "ent", ecoff_directive_ent, 0 },
+ { "fmask", ecoff_directive_fmask, 0 },
+ { "frame", ecoff_directive_frame, 0 },
+ { "loc", ecoff_directive_loc, 0 },
+ { "mask", ecoff_directive_mask, 0 },
+
+ /* Other ECOFF directives. */
+ { "extern", ecoff_directive_extern, 0 },
+
+#ifndef TC_MIPS
+ /* For TC_MIPS, tc-mips.c adds this. */
+ { "weakext", ecoff_directive_weakext, 0 },
+#endif
+
+ /* These are used on Irix. I don't know how to implement them. */
+ { "bgnb", s_ignore, 0 },
+ { "endb", s_ignore, 0 },
+ { "verstamp", s_ignore, 0 },
+
+ /* Sentinel. */
+ { NULL }
+};
+
+/* Swap out the symbols and debugging information for BFD. */
+
+void
+ecoff_frob_file ()
+{
+ const struct ecoff_debug_swap * const debug_swap
+ = &ecoff_backend (stdoutput)->debug_swap;
+ bfd_vma addr;
+ asection *sec;
+ HDRR *hdr;
+ char *buf;
+ char *set;
+
+ /* Set the section VMA values. We force the .sdata and .sbss
+ sections to the end to ensure that their VMA addresses are close
+ together so that the GP register can address both of them. We
+ put the .bss section after the .sbss section.
+
+ Also, for the Alpha, we must sort the sections, to make sure they
+ appear in the output file in the correct order. (Actually, maybe
+ this is a job for BFD. But the VMAs computed would be out of
+ whack if we computed them given our initial, random ordering.
+ It's possible that that wouldn't break things; I could do some
+ experimenting sometime and find out.
+
+ This output ordering of sections is magic, on the Alpha, at
+ least. The .lita section must come before .lit8 and .lit4,
+ otherwise the OSF/1 linker may silently trash the .lit{4,8}
+ section contents. Also, .text must preceed .rdata. These differ
+ from the order described in some parts of the DEC OSF/1 Assembly
+ Language Programmer's Guide, but that order doesn't seem to work
+ with their linker.
+
+ I don't know if section ordering on the MIPS is important. */
+
+ static const char *const names[] = {
+ /* text segment */
+ ".text", ".rdata", ".init", ".fini",
+ /* data segment */
+ ".data", ".lita", ".lit8", ".lit4", ".sdata", ".got",
+ /* bss segment */
+ ".sbss", ".bss",
+ };
+#define n_names (sizeof (names) / sizeof (names[0]))
+
+ addr = 0;
+ {
+ /* Sections that match names, order to be straightened out later. */
+ asection *secs[n_names];
+ /* Linked list of sections with non-matching names. Random ordering. */
+ asection *other_sections = 0;
+ /* Pointer to next section, since we're destroying the original
+ ordering. */
+ asection *next;
+
+ int i;
+
+ for (i = 0; i < n_names; i++)
+ secs[i] = 0;
+ for (sec = stdoutput->sections; sec != (asection *) NULL; sec = next)
+ {
+ next = sec->next;
+ for (i = 0; i < n_names; i++)
+ if (!strcmp (sec->name, names[i]))
+ {
+ secs[i] = sec;
+ break;
+ }
+ if (i == n_names)
+ {
+ bfd_set_section_vma (stdoutput, sec, addr);
+ addr += bfd_section_size (stdoutput, sec);
+ sec->next = other_sections;
+ other_sections = sec;
+ }
+ }
+ for (i = 0; i < n_names; i++)
+ if (secs[i])
+ {
+ sec = secs[i];
+ bfd_set_section_vma (stdoutput, sec, addr);
+ addr += bfd_section_size (stdoutput, sec);
+ }
+ for (i = n_names - 1; i >= 0; i--)
+ if (secs[i])
+ {
+ sec = secs[i];
+ sec->next = other_sections;
+ other_sections = sec;
+ }
+ stdoutput->sections = other_sections;
+ }
+
+ /* Build the ECOFF debugging information. */
+ assert (ecoff_data (stdoutput) != 0);
+ hdr = &ecoff_data (stdoutput)->debug_info.symbolic_header;
+ ecoff_build_debug (hdr, &buf, debug_swap);
+
+ /* Finish up the ecoff_tdata structure. */
+ set = buf;
+#define SET(ptr, count, type, size) \
+ if (hdr->count == 0) \
+ ecoff_data (stdoutput)->debug_info.ptr = (type) NULL; \
+ else \
+ { \
+ ecoff_data (stdoutput)->debug_info.ptr = (type) set; \
+ set += hdr->count * size; \
+ }
+
+ SET (line, cbLine, unsigned char *, sizeof (unsigned char));
+ SET (external_dnr, idnMax, PTR, debug_swap->external_dnr_size);
+ SET (external_pdr, ipdMax, PTR, debug_swap->external_pdr_size);
+ SET (external_sym, isymMax, PTR, debug_swap->external_sym_size);
+ SET (external_opt, ioptMax, PTR, debug_swap->external_opt_size);
+ SET (external_aux, iauxMax, union aux_ext *, sizeof (union aux_ext));
+ SET (ss, issMax, char *, sizeof (char));
+ SET (ssext, issExtMax, char *, sizeof (char));
+ SET (external_rfd, crfd, PTR, debug_swap->external_rfd_size);
+ SET (external_fdr, ifdMax, PTR, debug_swap->external_fdr_size);
+ SET (external_ext, iextMax, PTR, debug_swap->external_ext_size);
+
+#undef SET
+
+ /* Fill in the register masks. */
+ {
+ unsigned long gprmask = 0;
+ unsigned long fprmask = 0;
+ unsigned long *cprmask = NULL;
+
+#ifdef TC_MIPS
+ /* Fill in the MIPS register masks. It's probably not worth
+ setting up a generic interface for this. */
+ gprmask = mips_gprmask;
+ cprmask = mips_cprmask;
+#endif
+
+#ifdef TC_ALPHA
+ alpha_frob_ecoff_data ();
+
+ if (! bfd_ecoff_set_gp_value (stdoutput, alpha_gp_value))
+ as_fatal (_("Can't set GP value"));
+
+ gprmask = alpha_gprmask;
+ fprmask = alpha_fprmask;
+#endif
+
+ if (! bfd_ecoff_set_regmasks (stdoutput, gprmask, fprmask, cprmask))
+ as_fatal (_("Can't set register masks"));
+ }
+}
+
+/* This is called by the ECOFF code to set the external information
+ for a symbol. We just pass it on to BFD, which expects the swapped
+ information to be stored in the native field of the symbol. */
+
+void
+obj_ecoff_set_ext (sym, ext)
+ symbolS *sym;
+ EXTR *ext;
+{
+ const struct ecoff_debug_swap * const debug_swap
+ = &ecoff_backend (stdoutput)->debug_swap;
+ ecoff_symbol_type *esym;
+
+ know (bfd_asymbol_flavour (sym->bsym) == bfd_target_ecoff_flavour);
+ esym = ecoffsymbol (sym->bsym);
+ esym->local = false;
+ esym->native = xmalloc (debug_swap->external_ext_size);
+ (*debug_swap->swap_ext_out) (stdoutput, ext, esym->native);
+}
+
+static int
+ecoff_sec_sym_ok_for_reloc (sec)
+ asection *sec;
+{
+ return 1;
+}
+
+static void
+obj_ecoff_frob_symbol (sym, puntp)
+ symbolS *sym;
+ int *puntp;
+{
+ ecoff_frob_symbol (sym);
+}
+
+static void
+ecoff_pop_insert ()
+{
+ pop_insert (obj_pseudo_table);
+}
+
+const struct format_ops ecoff_format_ops =
+{
+ bfd_target_ecoff_flavour,
+ 0,
+ 1,
+ obj_ecoff_frob_symbol,
+ ecoff_frob_file,
+ 0,
+ 0, 0,
+ 0, 0,
+ 0,
+ ecoff_generate_asm_lineno,
+ ecoff_stab,
+ ecoff_sec_sym_ok_for_reloc,
+ ecoff_pop_insert,
+ ecoff_set_ext,
+ ecoff_read_begin_hook,
+ ecoff_symbol_new_hook,
+};
diff --git a/gas/config/obj-ecoff.h b/gas/config/obj-ecoff.h
new file mode 100644
index 0000000000..427e619ee1
--- /dev/null
+++ b/gas/config/obj-ecoff.h
@@ -0,0 +1,67 @@
+/* ECOFF object file format header file.
+ Copyright (C) 1993, 94, 95, 96, 97, 1999 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+ Written by Ian Lance Taylor <ian@cygnus.com>.
+
+ This file is part of GAS.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#define OBJ_ECOFF 1
+
+/* Use the generic ECOFF debugging code. */
+#define ECOFF_DEBUGGING 1
+
+#define OUTPUT_FLAVOR bfd_target_ecoff_flavour
+
+#include "targ-cpu.h"
+
+#include "ecoff.h"
+
+/* For each gas symbol we keep track of which file it came from, of
+ whether we have generated an ECOFF symbol for it, and whether the
+ symbols is undefined (this last is needed to distinguish a .extern
+ symbols from a .comm symbol). */
+
+#define TARGET_SYMBOL_FIELDS \
+ struct efdr *ecoff_file; \
+ struct localsym *ecoff_symbol; \
+ valueT ecoff_extern_size;
+
+/* Modify the ECOFF symbol. */
+#define obj_frob_symbol(symp, punt) ecoff_frob_symbol (symp)
+
+/* This is used to write the symbolic data in the format that BFD
+ expects it. */
+extern void ecoff_frob_file PARAMS ((void));
+#define obj_frob_file() ecoff_frob_file ()
+
+/* We use the ECOFF functions as our hooks. */
+#define obj_read_begin_hook ecoff_read_begin_hook
+#define obj_symbol_new_hook ecoff_symbol_new_hook
+
+/* Record file switches in the ECOFF symbol table. */
+#define obj_app_file(name) ecoff_new_file (name)
+
+/* At the moment we don't want to do any stabs processing in read.c. */
+#define OBJ_PROCESS_STAB(seg, what, string, type, other, desc) \
+ ecoff_stab ((seg), (what), (string), (type), (other), (desc))
+
+#define EMIT_SECTION_SYMBOLS 0
+#define obj_sec_sym_ok_for_reloc(SEC) 1
+
+#define obj_ecoff_set_ext ecoff_set_ext
+extern void obj_ecoff_set_ext PARAMS ((struct symbol *, EXTR *));
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
new file mode 100644
index 0000000000..f50c4b7257
--- /dev/null
+++ b/gas/config/obj-elf.c
@@ -0,0 +1,1764 @@
+/* ELF object file format
+ Copyright (C) 1992, 93, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2,
+ or (at your option) any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#define OBJ_HEADER "obj-elf.h"
+#include "as.h"
+#include "subsegs.h"
+#include "obstack.h"
+
+#ifndef ECOFF_DEBUGGING
+#define ECOFF_DEBUGGING 0
+#else
+#define NEED_ECOFF_DEBUG
+#endif
+
+#ifdef NEED_ECOFF_DEBUG
+#include "ecoff.h"
+#endif
+
+#ifdef TC_ALPHA
+#include "elf/alpha.h"
+#endif
+
+#ifdef TC_MIPS
+#include "elf/mips.h"
+#endif
+
+#ifdef TC_PPC
+#include "elf/ppc.h"
+#endif
+
+static bfd_vma elf_s_get_size PARAMS ((symbolS *));
+static void elf_s_set_size PARAMS ((symbolS *, bfd_vma));
+static bfd_vma elf_s_get_align PARAMS ((symbolS *));
+static void elf_s_set_align PARAMS ((symbolS *, bfd_vma));
+static void elf_copy_symbol_attributes PARAMS ((symbolS *, symbolS *));
+static int elf_sec_sym_ok_for_reloc PARAMS ((asection *));
+static void adjust_stab_sections PARAMS ((bfd *, asection *, PTR));
+
+#ifdef NEED_ECOFF_DEBUG
+static boolean elf_get_extr PARAMS ((asymbol *, EXTR *));
+static void elf_set_index PARAMS ((asymbol *, bfd_size_type));
+#endif
+
+static void obj_elf_line PARAMS ((int));
+void obj_elf_version PARAMS ((int));
+static void obj_elf_size PARAMS ((int));
+static void obj_elf_type PARAMS ((int));
+static void obj_elf_ident PARAMS ((int));
+static void obj_elf_weak PARAMS ((int));
+static void obj_elf_local PARAMS ((int));
+static void obj_elf_common PARAMS ((int));
+static void obj_elf_symver PARAMS ((int));
+static void obj_elf_vtable_inherit PARAMS ((int));
+static void obj_elf_vtable_entry PARAMS ((int));
+static void obj_elf_data PARAMS ((int));
+static void obj_elf_text PARAMS ((int));
+static void obj_elf_subsection PARAMS ((int));
+
+static const pseudo_typeS elf_pseudo_table[] =
+{
+ {"comm", obj_elf_common, 0},
+ {"ident", obj_elf_ident, 0},
+ {"local", obj_elf_local, 0},
+ {"previous", obj_elf_previous, 0},
+ {"section", obj_elf_section, 0},
+ {"section.s", obj_elf_section, 0},
+ {"sect", obj_elf_section, 0},
+ {"sect.s", obj_elf_section, 0},
+ {"size", obj_elf_size, 0},
+ {"type", obj_elf_type, 0},
+ {"version", obj_elf_version, 0},
+ {"weak", obj_elf_weak, 0},
+
+ /* These are used for stabs-in-elf configurations. */
+ {"line", obj_elf_line, 0},
+
+ /* This is a GNU extension to handle symbol versions. */
+ {"symver", obj_elf_symver, 0},
+
+ /* A GNU extension to change subsection only. */
+ {"subsection", obj_elf_subsection, 0},
+
+ /* These are GNU extensions to aid in garbage collecting C++ vtables. */
+ {"vtable_inherit", obj_elf_vtable_inherit, 0},
+ {"vtable_entry", obj_elf_vtable_entry, 0},
+
+ /* These are used for dwarf. */
+ {"2byte", cons, 2},
+ {"4byte", cons, 4},
+ {"8byte", cons, 8},
+
+ /* We need to trap the section changing calls to handle .previous. */
+ {"data", obj_elf_data, 0},
+ {"text", obj_elf_text, 0},
+
+ /* End sentinel. */
+ {NULL},
+};
+
+static const pseudo_typeS ecoff_debug_pseudo_table[] =
+{
+#ifdef NEED_ECOFF_DEBUG
+ /* COFF style debugging information for ECOFF. .ln is not used; .loc
+ is used instead. */
+ { "def", ecoff_directive_def, 0 },
+ { "dim", ecoff_directive_dim, 0 },
+ { "endef", ecoff_directive_endef, 0 },
+ { "file", ecoff_directive_file, 0 },
+ { "scl", ecoff_directive_scl, 0 },
+ { "tag", ecoff_directive_tag, 0 },
+ { "val", ecoff_directive_val, 0 },
+
+ /* COFF debugging requires pseudo-ops .size and .type, but ELF
+ already has meanings for those. We use .esize and .etype
+ instead. These are only generated by gcc anyhow. */
+ { "esize", ecoff_directive_size, 0 },
+ { "etype", ecoff_directive_type, 0 },
+
+ /* ECOFF specific debugging information. */
+ { "begin", ecoff_directive_begin, 0 },
+ { "bend", ecoff_directive_bend, 0 },
+ { "end", ecoff_directive_end, 0 },
+ { "ent", ecoff_directive_ent, 0 },
+ { "fmask", ecoff_directive_fmask, 0 },
+ { "frame", ecoff_directive_frame, 0 },
+ { "loc", ecoff_directive_loc, 0 },
+ { "mask", ecoff_directive_mask, 0 },
+
+ /* Other ECOFF directives. */
+ { "extern", ecoff_directive_extern, 0 },
+
+ /* These are used on Irix. I don't know how to implement them. */
+ { "alias", s_ignore, 0 },
+ { "bgnb", s_ignore, 0 },
+ { "endb", s_ignore, 0 },
+ { "lab", s_ignore, 0 },
+ { "noalias", s_ignore, 0 },
+ { "verstamp", s_ignore, 0 },
+ { "vreg", s_ignore, 0 },
+#endif
+
+ {NULL} /* end sentinel */
+};
+
+#undef NO_RELOC
+#include "aout/aout64.h"
+
+/* This is called when the assembler starts. */
+
+void
+elf_begin ()
+{
+ /* Add symbols for the known sections to the symbol table. */
+ symbol_table_insert (section_symbol (bfd_get_section_by_name (stdoutput,
+ TEXT_SECTION_NAME)));
+ symbol_table_insert (section_symbol (bfd_get_section_by_name (stdoutput,
+ DATA_SECTION_NAME)));
+ symbol_table_insert (section_symbol (bfd_get_section_by_name (stdoutput,
+ BSS_SECTION_NAME)));
+}
+
+void
+elf_pop_insert ()
+{
+ pop_insert (elf_pseudo_table);
+ if (ECOFF_DEBUGGING)
+ pop_insert (ecoff_debug_pseudo_table);
+}
+
+static bfd_vma
+elf_s_get_size (sym)
+ symbolS *sym;
+{
+ return S_GET_SIZE (sym);
+}
+
+static void
+elf_s_set_size (sym, sz)
+ symbolS *sym;
+ bfd_vma sz;
+{
+ S_SET_SIZE (sym, sz);
+}
+
+static bfd_vma
+elf_s_get_align (sym)
+ symbolS *sym;
+{
+ return S_GET_ALIGN (sym);
+}
+
+static void
+elf_s_set_align (sym, align)
+ symbolS *sym;
+ bfd_vma align;
+{
+ S_SET_ALIGN (sym, align);
+}
+
+static void
+elf_copy_symbol_attributes (dest, src)
+ symbolS *dest, *src;
+{
+ OBJ_COPY_SYMBOL_ATTRIBUTES (dest, src);
+}
+
+static int
+elf_sec_sym_ok_for_reloc (sec)
+ asection *sec;
+{
+ return obj_sec_sym_ok_for_reloc (sec);
+}
+
+void
+elf_file_symbol (s)
+ char *s;
+{
+ symbolS *sym;
+
+ sym = symbol_new (s, absolute_section, (valueT) 0, (struct frag *) 0);
+ sym->sy_frag = &zero_address_frag;
+ sym->bsym->flags |= BSF_FILE;
+
+ if (symbol_rootP != sym)
+ {
+ symbol_remove (sym, &symbol_rootP, &symbol_lastP);
+ symbol_insert (sym, symbol_rootP, &symbol_rootP, &symbol_lastP);
+#ifdef DEBUG
+ verify_symbol_chain (symbol_rootP, symbol_lastP);
+#endif
+ }
+
+#ifdef NEED_ECOFF_DEBUG
+ ecoff_new_file (s);
+#endif
+}
+
+static void
+obj_elf_common (ignore)
+ int ignore;
+{
+ char *name;
+ char c;
+ char *p;
+ int temp, size;
+ symbolS *symbolP;
+ int have_align;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ /* just after name is now '\0' */
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("Expected comma after symbol-name"));
+ ignore_rest_of_line ();
+ return;
+ }
+ input_line_pointer++; /* skip ',' */
+ if ((temp = get_absolute_expression ()) < 0)
+ {
+ as_bad (_(".COMMon length (%d.) <0! Ignored."), temp);
+ ignore_rest_of_line ();
+ return;
+ }
+ size = temp;
+ *p = 0;
+ symbolP = symbol_find_or_make (name);
+ *p = c;
+ if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
+ {
+ as_bad (_("Ignoring attempt to re-define symbol"));
+ ignore_rest_of_line ();
+ return;
+ }
+ if (S_GET_VALUE (symbolP) != 0)
+ {
+ if (S_GET_VALUE (symbolP) != size)
+ {
+ as_warn (_("Length of .comm \"%s\" is already %ld. Not changed to %d."),
+ S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size);
+ }
+ }
+ know (symbolP->sy_frag == &zero_address_frag);
+ if (*input_line_pointer != ',')
+ have_align = 0;
+ else
+ {
+ have_align = 1;
+ input_line_pointer++;
+ SKIP_WHITESPACE ();
+ }
+ if (! have_align || *input_line_pointer != '"')
+ {
+ if (! have_align)
+ temp = 0;
+ else
+ {
+ temp = get_absolute_expression ();
+ if (temp < 0)
+ {
+ temp = 0;
+ as_warn (_("Common alignment negative; 0 assumed"));
+ }
+ }
+ if (symbolP->local)
+ {
+ segT old_sec;
+ int old_subsec;
+ char *pfrag;
+ int align;
+
+ /* allocate_bss: */
+ old_sec = now_seg;
+ old_subsec = now_subseg;
+ if (temp)
+ {
+ /* convert to a power of 2 alignment */
+ for (align = 0; (temp & 1) == 0; temp >>= 1, ++align);
+ if (temp != 1)
+ {
+ as_bad (_("Common alignment not a power of 2"));
+ ignore_rest_of_line ();
+ return;
+ }
+ }
+ else
+ align = 0;
+ record_alignment (bss_section, align);
+ subseg_set (bss_section, 0);
+ if (align)
+ frag_align (align, 0, 0);
+ if (S_GET_SEGMENT (symbolP) == bss_section)
+ symbolP->sy_frag->fr_symbol = 0;
+ symbolP->sy_frag = frag_now;
+ pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
+ (offsetT) size, (char *) 0);
+ *pfrag = 0;
+ S_SET_SIZE (symbolP, size);
+ S_SET_SEGMENT (symbolP, bss_section);
+ S_CLEAR_EXTERNAL (symbolP);
+ subseg_set (old_sec, old_subsec);
+ }
+ else
+ {
+ allocate_common:
+ S_SET_VALUE (symbolP, (valueT) size);
+ S_SET_ALIGN (symbolP, temp);
+ S_SET_EXTERNAL (symbolP);
+ S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
+ }
+ }
+ else
+ {
+ input_line_pointer++;
+ /* @@ Some use the dot, some don't. Can we get some consistency?? */
+ if (*input_line_pointer == '.')
+ input_line_pointer++;
+ /* @@ Some say data, some say bss. */
+ if (strncmp (input_line_pointer, "bss\"", 4)
+ && strncmp (input_line_pointer, "data\"", 5))
+ {
+ while (*--input_line_pointer != '"')
+ ;
+ input_line_pointer--;
+ goto bad_common_segment;
+ }
+ while (*input_line_pointer++ != '"')
+ ;
+ goto allocate_common;
+ }
+
+ symbolP->bsym->flags |= BSF_OBJECT;
+
+ demand_empty_rest_of_line ();
+ return;
+
+ {
+ bad_common_segment:
+ p = input_line_pointer;
+ while (*p && *p != '\n')
+ p++;
+ c = *p;
+ *p = '\0';
+ as_bad (_("bad .common segment %s"), input_line_pointer + 1);
+ *p = c;
+ input_line_pointer = p;
+ ignore_rest_of_line ();
+ return;
+ }
+}
+
+static void
+obj_elf_local (ignore)
+ int ignore;
+{
+ char *name;
+ int c;
+ symbolS *symbolP;
+
+ do
+ {
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ symbolP = symbol_find_or_make (name);
+ *input_line_pointer = c;
+ SKIP_WHITESPACE ();
+ S_CLEAR_EXTERNAL (symbolP);
+ symbolP->local = 1;
+ if (c == ',')
+ {
+ input_line_pointer++;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '\n')
+ c = '\n';
+ }
+ }
+ while (c == ',');
+ demand_empty_rest_of_line ();
+}
+
+static void
+obj_elf_weak (ignore)
+ int ignore;
+{
+ char *name;
+ int c;
+ symbolS *symbolP;
+
+ do
+ {
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ symbolP = symbol_find_or_make (name);
+ *input_line_pointer = c;
+ SKIP_WHITESPACE ();
+ S_SET_WEAK (symbolP);
+ symbolP->local = 1;
+ if (c == ',')
+ {
+ input_line_pointer++;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '\n')
+ c = '\n';
+ }
+ }
+ while (c == ',');
+ demand_empty_rest_of_line ();
+}
+
+static segT previous_section;
+static int previous_subsection;
+
+/* Handle the .section pseudo-op. This code supports two different
+ syntaxes.
+
+ The first is found on Solaris, and looks like
+ .section ".sec1",#alloc,#execinstr,#write
+ Here the names after '#' are the SHF_* flags to turn on for the
+ section. I'm not sure how it determines the SHT_* type (BFD
+ doesn't really give us control over the type, anyhow).
+
+ The second format is found on UnixWare, and probably most SVR4
+ machines, and looks like
+ .section .sec1,"a",@progbits
+ The quoted string may contain any combination of a, w, x, and
+ represents the SHF_* flags to turn on for the section. The string
+ beginning with '@' can be progbits or nobits. There should be
+ other possibilities, but I don't know what they are. In any case,
+ BFD doesn't really let us set the section type. */
+
+/* Certain named sections have particular defined types, listed on p.
+ 4-19 of the ABI. */
+struct special_section
+{
+ const char *name;
+ int type;
+ int attributes;
+};
+
+static struct special_section special_sections[] =
+{
+ { ".bss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
+ { ".comment", SHT_PROGBITS, 0 },
+ { ".data", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+ { ".data1", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+ { ".debug", SHT_PROGBITS, 0 },
+ { ".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+ { ".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+ { ".line", SHT_PROGBITS, 0 },
+ { ".note", SHT_NOTE, 0 },
+ { ".rodata", SHT_PROGBITS, SHF_ALLOC },
+ { ".rodata1", SHT_PROGBITS, SHF_ALLOC },
+ { ".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+
+#ifdef ELF_TC_SPECIAL_SECTIONS
+ ELF_TC_SPECIAL_SECTIONS
+#endif
+
+#if 0
+ /* The following section names are special, but they can not
+ reasonably appear in assembler code. Some of the attributes are
+ processor dependent. */
+ { ".dynamic", SHT_DYNAMIC, SHF_ALLOC /* + SHF_WRITE */ },
+ { ".dynstr", SHT_STRTAB, SHF_ALLOC },
+ { ".dynsym", SHT_DYNSYM, SHF_ALLOC },
+ { ".got", SHT_PROGBITS, 0 },
+ { ".hash", SHT_HASH, SHF_ALLOC },
+ { ".interp", SHT_PROGBITS, /* SHF_ALLOC */ },
+ { ".plt", SHT_PROGBITS, 0 },
+ { ".shstrtab",SHT_STRTAB, 0 },
+ { ".strtab", SHT_STRTAB, /* SHF_ALLOC */ },
+ { ".symtab", SHT_SYMTAB, /* SHF_ALLOC */ },
+#endif
+
+ { NULL, 0, 0 }
+};
+
+void
+obj_elf_section (xxx)
+ int xxx;
+{
+ char *string;
+ int new_sec;
+ segT sec;
+ int type, attr;
+ int i;
+ flagword flags;
+ symbolS *secsym;
+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+ if (flag_mri)
+ {
+ char mri_type;
+
+ previous_section = now_seg;
+ previous_subsection = now_subseg;
+
+ s_mri_sect (&mri_type);
+
+#ifdef md_elf_section_change_hook
+ md_elf_section_change_hook ();
+#endif
+
+ return;
+ }
+
+ /* Get name of section. */
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '"')
+ {
+ string = demand_copy_C_string (&xxx);
+ if (string == NULL)
+ {
+ ignore_rest_of_line ();
+ return;
+ }
+ }
+ else
+ {
+ char *p = input_line_pointer;
+ char c;
+ while (0 == strchr ("\n\t,; ", *p))
+ p++;
+ if (p == input_line_pointer)
+ {
+ as_warn (_("Missing section name"));
+ ignore_rest_of_line ();
+ return;
+ }
+ c = *p;
+ *p = 0;
+ string = xmalloc ((unsigned long) (p - input_line_pointer + 1));
+ strcpy (string, input_line_pointer);
+ *p = c;
+ input_line_pointer = p;
+ }
+
+ /* Switch to the section, creating it if necessary. */
+ previous_section = now_seg;
+ previous_subsection = now_subseg;
+
+ new_sec = bfd_get_section_by_name (stdoutput, string) == NULL;
+ sec = subseg_new (string, 0);
+
+ /* If this section already existed, we don't bother to change the
+ flag values. */
+ if (! new_sec)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ ++input_line_pointer;
+
+#ifdef md_elf_section_change_hook
+ md_elf_section_change_hook ();
+#endif
+
+ return;
+ }
+
+ SKIP_WHITESPACE ();
+
+ type = SHT_NULL;
+ attr = 0;
+
+ if (*input_line_pointer == ',')
+ {
+ /* Skip the comma. */
+ ++input_line_pointer;
+
+ SKIP_WHITESPACE ();
+
+ if (*input_line_pointer == '"')
+ {
+ /* Pick up a string with a combination of a, w, x. */
+ ++input_line_pointer;
+ while (*input_line_pointer != '"')
+ {
+ switch (*input_line_pointer)
+ {
+ case 'a':
+ attr |= SHF_ALLOC;
+ break;
+ case 'w':
+ attr |= SHF_WRITE;
+ break;
+ case 'x':
+ attr |= SHF_EXECINSTR;
+ break;
+ default:
+ {
+ char *bad_msg = _("Bad .section directive: want a,w,x in string");
+#ifdef md_elf_section_letter
+ int md_attr = md_elf_section_letter (*input_line_pointer, &bad_msg);
+ if (md_attr)
+ attr |= md_attr;
+ else
+#endif
+ {
+ as_warn (bad_msg);
+ ignore_rest_of_line ();
+ return;
+ }
+ }
+ }
+ ++input_line_pointer;
+ }
+
+ /* Skip the closing quote. */
+ ++input_line_pointer;
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == ',')
+ {
+ ++input_line_pointer;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '@' || *input_line_pointer == '%')
+ {
+ ++input_line_pointer;
+ if (strncmp (input_line_pointer, "progbits",
+ sizeof "progbits" - 1) == 0)
+ {
+ type = SHT_PROGBITS;
+ input_line_pointer += sizeof "progbits" - 1;
+ }
+ else if (strncmp (input_line_pointer, "nobits",
+ sizeof "nobits" - 1) == 0)
+ {
+ type = SHT_NOBITS;
+ input_line_pointer += sizeof "nobits" - 1;
+ }
+ else
+ {
+#ifdef md_elf_section_type
+ int md_type = md_elf_section_type (&input_line_pointer);
+ if (md_type)
+ type = md_type;
+ else
+#endif
+ {
+ as_warn (_("Unrecognized section type"));
+ ignore_rest_of_line ();
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ do
+ {
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != '#')
+ {
+ as_warn (_("Bad .section directive - character following name is not '#'"));
+ ignore_rest_of_line ();
+ return;
+ }
+ ++input_line_pointer;
+ if (strncmp (input_line_pointer, "write",
+ sizeof "write" - 1) == 0)
+ {
+ attr |= SHF_WRITE;
+ input_line_pointer += sizeof "write" - 1;
+ }
+ else if (strncmp (input_line_pointer, "alloc",
+ sizeof "alloc" - 1) == 0)
+ {
+ attr |= SHF_ALLOC;
+ input_line_pointer += sizeof "alloc" - 1;
+ }
+ else if (strncmp (input_line_pointer, "execinstr",
+ sizeof "execinstr" - 1) == 0)
+ {
+ attr |= SHF_EXECINSTR;
+ input_line_pointer += sizeof "execinstr" - 1;
+ }
+ else
+ {
+#ifdef md_elf_section_word
+ int md_attr = md_elf_section_word (&input_line_pointer);
+ if (md_attr)
+ attr |= md_attr;
+ else
+#endif
+ {
+ as_warn (_("Unrecognized section attribute"));
+ ignore_rest_of_line ();
+ return;
+ }
+ }
+ SKIP_WHITESPACE ();
+ }
+ while (*input_line_pointer++ == ',');
+ --input_line_pointer;
+ }
+ }
+
+ /* See if this is one of the special sections. */
+ for (i = 0; special_sections[i].name != NULL; i++)
+ {
+ if (string[1] == special_sections[i].name[1]
+ && strcmp (string, special_sections[i].name) == 0)
+ {
+ if (type == SHT_NULL)
+ type = special_sections[i].type;
+ else if (type != special_sections[i].type)
+ as_warn (_("Setting incorrect section type for %s"), string);
+
+ if ((attr &~ special_sections[i].attributes) != 0)
+ {
+ /* As a GNU extension, we permit a .note section to be
+ allocatable. If the linker sees an allocateable
+ .note section, it will create a PT_NOTE segment in
+ the output file. */
+ if (strcmp (string, ".note") != 0
+ || attr != SHF_ALLOC)
+ as_warn (_("Setting incorrect section attributes for %s"),
+ string);
+ }
+ attr |= special_sections[i].attributes;
+
+ break;
+ }
+ }
+
+ flags = (SEC_RELOC
+ | ((attr & SHF_WRITE) ? 0 : SEC_READONLY)
+ | ((attr & SHF_ALLOC) ? SEC_ALLOC : 0)
+ | (((attr & SHF_ALLOC) && type != SHT_NOBITS) ? SEC_LOAD : 0)
+ | ((attr & SHF_EXECINSTR) ? SEC_CODE : 0));
+ if (special_sections[i].name == NULL)
+ {
+ if (type == SHT_PROGBITS)
+ flags |= SEC_ALLOC | SEC_LOAD;
+ else if (type == SHT_NOBITS)
+ {
+ flags |= SEC_ALLOC;
+ flags &=~ SEC_LOAD;
+ }
+
+#ifdef md_elf_section_flags
+ flags = md_elf_section_flags (flags, attr, type);
+#endif
+ }
+
+ /* Prevent SEC_HAS_CONTENTS from being inadvertently set. */
+ if (type == SHT_NOBITS)
+ seg_info (sec)->bss = 1;
+
+ bfd_set_section_flags (stdoutput, sec, flags);
+
+ /* Add a symbol for this section to the symbol table. */
+ secsym = symbol_find (string);
+ if (secsym != NULL)
+ secsym->bsym = sec->symbol;
+ else
+ symbol_table_insert (section_symbol (sec));
+
+#ifdef md_elf_section_change_hook
+ md_elf_section_change_hook ();
+#endif
+
+ demand_empty_rest_of_line ();
+}
+
+/* Change to the .data section. */
+
+static void
+obj_elf_data (i)
+ int i;
+{
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+ previous_section = now_seg;
+ previous_subsection = now_subseg;
+ s_data (i);
+
+#ifdef md_elf_section_change_hook
+ md_elf_section_change_hook ();
+#endif
+}
+
+/* Change to the .text section. */
+
+static void
+obj_elf_text (i)
+ int i;
+{
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+ previous_section = now_seg;
+ previous_subsection = now_subseg;
+ s_text (i);
+
+#ifdef md_elf_section_change_hook
+ md_elf_section_change_hook ();
+#endif
+}
+
+static void
+obj_elf_subsection (ignore)
+ int ignore;
+{
+ register int temp;
+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+ previous_section = now_seg;
+ previous_subsection = now_subseg;
+
+ temp = get_absolute_expression ();
+ subseg_set (now_seg, (subsegT) temp);
+ demand_empty_rest_of_line ();
+
+#ifdef md_elf_section_change_hook
+ md_elf_section_change_hook ();
+#endif
+}
+
+/* This can be called from the processor backends if they change
+ sections. */
+
+void
+obj_elf_section_change_hook ()
+{
+ previous_section = now_seg;
+ previous_subsection = now_subseg;
+}
+
+void
+obj_elf_previous (ignore)
+ int ignore;
+{
+ if (previous_section == 0)
+ {
+ as_bad (_(".previous without corresponding .section; ignored"));
+ return;
+ }
+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+ subseg_set (previous_section, previous_subsection);
+ previous_section = 0;
+
+#ifdef md_elf_section_change_hook
+ md_elf_section_change_hook ();
+#endif
+}
+
+static void
+obj_elf_line (ignore)
+ int ignore;
+{
+ /* Assume delimiter is part of expression. BSD4.2 as fails with
+ delightful bug, so we are not being incompatible here. */
+ new_logical_line ((char *) NULL, (int) (get_absolute_expression ()));
+ demand_empty_rest_of_line ();
+}
+
+/* This handles the .symver pseudo-op, which is used to specify a
+ symbol version. The syntax is ``.symver NAME,SYMVERNAME''.
+ SYMVERNAME may contain ELF_VER_CHR ('@') characters. This
+ pseudo-op causes the assembler to emit a symbol named SYMVERNAME
+ with the same value as the symbol NAME. */
+
+static void
+obj_elf_symver (ignore)
+ int ignore;
+{
+ char *name;
+ char c;
+ symbolS *sym;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+
+ sym = symbol_find_or_make (name);
+
+ *input_line_pointer = c;
+
+ if (sym->sy_obj.versioned_name != NULL)
+ {
+ as_bad (_("multiple .symver directives for symbol `%s'"),
+ S_GET_NAME (sym));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("expected comma after name in .symver"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ ++input_line_pointer;
+ name = input_line_pointer;
+ while (1)
+ {
+ c = get_symbol_end ();
+ if (c != ELF_VER_CHR)
+ break;
+ *input_line_pointer++ = c;
+ }
+
+ sym->sy_obj.versioned_name = xstrdup (name);
+
+ *input_line_pointer = c;
+
+ if (strchr (sym->sy_obj.versioned_name, ELF_VER_CHR) == NULL)
+ {
+ as_bad (_("missing version name in `%s' for symbol `%s'"),
+ sym->sy_obj.versioned_name, S_GET_NAME (sym));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* This handles the .vtable_inherit pseudo-op, which is used to indicate
+ to the linker the hierarchy in which a particular table resides. The
+ syntax is ".vtable_inherit CHILDNAME, PARENTNAME". */
+
+static void
+obj_elf_vtable_inherit (ignore)
+{
+ char *cname, *pname;
+ symbolS *csym, *psym;
+ char c, bad = 0;
+
+ if (*input_line_pointer == '#')
+ ++input_line_pointer;
+
+ cname = input_line_pointer;
+ c = get_symbol_end ();
+ csym = symbol_find (cname);
+
+ /* GCFIXME: should check that we don't have two .vtable_inherits for
+ the same child symbol. Also, we can currently only do this if the
+ child symbol is already exists and is placed in a fragment. */
+
+ if (csym == NULL || csym->sy_frag == NULL)
+ {
+ as_bad ("expected `%s' to have already been set for .vtable_inherit",
+ cname);
+ bad = 1;
+ }
+
+ *input_line_pointer = c;
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
+ {
+ as_bad ("expected comma after name in .vtable_inherit");
+ ignore_rest_of_line ();
+ return;
+ }
+
+ ++input_line_pointer;
+ SKIP_WHITESPACE ();
+
+ if (*input_line_pointer == '#')
+ ++input_line_pointer;
+
+ if (input_line_pointer[0] == '0'
+ && (input_line_pointer[1] == '\0'
+ || isspace(input_line_pointer[1])))
+ {
+ psym = section_symbol (absolute_section);
+ ++input_line_pointer;
+ }
+ else
+ {
+ pname = input_line_pointer;
+ c = get_symbol_end ();
+ psym = symbol_find_or_make (pname);
+ *input_line_pointer = c;
+ }
+
+ demand_empty_rest_of_line ();
+
+ if (bad)
+ return;
+
+ assert (csym->sy_value.X_op == O_constant);
+ fix_new (csym->sy_frag, csym->sy_value.X_add_number, 0, psym, 0, 0,
+ BFD_RELOC_VTABLE_INHERIT);
+}
+
+/* This handles the .vtable_entry pseudo-op, which is used to indicate
+ to the linker that a vtable slot was used. The syntax is
+ ".vtable_entry tablename, offset". */
+
+static void
+obj_elf_vtable_entry (ignore)
+{
+ char *name;
+ symbolS *sym;
+ offsetT offset;
+ char c;
+
+ if (*input_line_pointer == '#')
+ ++input_line_pointer;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ sym = symbol_find_or_make (name);
+ *input_line_pointer = c;
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
+ {
+ as_bad ("expected comma after name in .vtable_entry");
+ ignore_rest_of_line ();
+ return;
+ }
+
+ ++input_line_pointer;
+ if (*input_line_pointer == '#')
+ ++input_line_pointer;
+
+ offset = get_absolute_expression ();
+
+ fix_new (frag_now, frag_now_fix (), 0, sym, offset, 0,
+ BFD_RELOC_VTABLE_ENTRY);
+
+ demand_empty_rest_of_line ();
+}
+
+void
+obj_read_begin_hook ()
+{
+#ifdef NEED_ECOFF_DEBUG
+ if (ECOFF_DEBUGGING)
+ ecoff_read_begin_hook ();
+#endif
+}
+
+void
+obj_symbol_new_hook (symbolP)
+ symbolS *symbolP;
+{
+ symbolP->sy_obj.size = NULL;
+ symbolP->sy_obj.versioned_name = NULL;
+
+#ifdef NEED_ECOFF_DEBUG
+ if (ECOFF_DEBUGGING)
+ ecoff_symbol_new_hook (symbolP);
+#endif
+}
+
+void
+obj_elf_version (ignore)
+ int ignore;
+{
+ char *name;
+ unsigned int c;
+ char ch;
+ char *p;
+ asection *seg = now_seg;
+ subsegT subseg = now_subseg;
+ Elf_Internal_Note i_note;
+ Elf_External_Note e_note;
+ asection *note_secp = (asection *) NULL;
+ int i, len;
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '\"')
+ {
+ ++input_line_pointer; /* -> 1st char of string. */
+ name = input_line_pointer;
+
+ while (is_a_char (c = next_char_of_string ()))
+ ;
+ c = *input_line_pointer;
+ *input_line_pointer = '\0';
+ *(input_line_pointer - 1) = '\0';
+ *input_line_pointer = c;
+
+ /* create the .note section */
+
+ note_secp = subseg_new (".note", 0);
+ bfd_set_section_flags (stdoutput,
+ note_secp,
+ SEC_HAS_CONTENTS | SEC_READONLY);
+
+ /* process the version string */
+
+ len = strlen (name);
+
+ i_note.namesz = ((len + 1) + 3) & ~3; /* round this to word boundary */
+ i_note.descsz = 0; /* no description */
+ i_note.type = NT_VERSION;
+ p = frag_more (sizeof (e_note.namesz));
+ md_number_to_chars (p, (valueT) i_note.namesz, 4);
+ p = frag_more (sizeof (e_note.descsz));
+ md_number_to_chars (p, (valueT) i_note.descsz, 4);
+ p = frag_more (sizeof (e_note.type));
+ md_number_to_chars (p, (valueT) i_note.type, 4);
+
+ for (i = 0; i < len; i++)
+ {
+ ch = *(name + i);
+ {
+ FRAG_APPEND_1_CHAR (ch);
+ }
+ }
+ frag_align (2, 0, 0);
+
+ subseg_set (seg, subseg);
+ }
+ else
+ {
+ as_bad (_("Expected quoted string"));
+ }
+ demand_empty_rest_of_line ();
+}
+
+static void
+obj_elf_size (ignore)
+ int ignore;
+{
+ char *name = input_line_pointer;
+ char c = get_symbol_end ();
+ char *p;
+ expressionS exp;
+ symbolS *sym;
+
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
+ {
+ *p = 0;
+ as_bad (_("expected comma after name `%s' in .size directive"), name);
+ *p = c;
+ ignore_rest_of_line ();
+ return;
+ }
+ input_line_pointer++;
+ expression (&exp);
+ if (exp.X_op == O_absent)
+ {
+ as_bad (_("missing expression in .size directive"));
+ exp.X_op = O_constant;
+ exp.X_add_number = 0;
+ }
+ *p = 0;
+ sym = symbol_find_or_make (name);
+ *p = c;
+ if (exp.X_op == O_constant)
+ S_SET_SIZE (sym, exp.X_add_number);
+ else
+ {
+ sym->sy_obj.size = (expressionS *) xmalloc (sizeof (expressionS));
+ *sym->sy_obj.size = exp;
+ }
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the ELF .type pseudo-op. This sets the type of a symbol.
+ There are four syntaxes:
+
+ The first (used on Solaris) is
+ .type SYM,#function
+ The second (used on UnixWare) is
+ .type SYM,@function
+ The third (reportedly to be used on Irix 6.0) is
+ .type SYM STT_FUNC
+ The fourth (used on NetBSD/Arm and Linux/ARM) is
+ .type SYM,%function
+ */
+
+static void
+obj_elf_type (ignore)
+ int ignore;
+{
+ char *name;
+ char c;
+ int type;
+ const char *typename;
+ symbolS *sym;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ sym = symbol_find_or_make (name);
+ *input_line_pointer = c;
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == ',')
+ ++input_line_pointer;
+
+ SKIP_WHITESPACE ();
+ if ( *input_line_pointer == '#'
+ || *input_line_pointer == '@'
+ || *input_line_pointer == '%')
+ ++input_line_pointer;
+
+ typename = input_line_pointer;
+ c = get_symbol_end ();
+
+ type = 0;
+ if (strcmp (typename, "function") == 0
+ || strcmp (typename, "STT_FUNC") == 0)
+ type = BSF_FUNCTION;
+ else if (strcmp (typename, "object") == 0
+ || strcmp (typename, "STT_OBJECT") == 0)
+ type = BSF_OBJECT;
+ else
+ as_bad (_("ignoring unrecognized symbol type \"%s\""), typename);
+
+ *input_line_pointer = c;
+
+ sym->bsym->flags |= type;
+
+ demand_empty_rest_of_line ();
+}
+
+static void
+obj_elf_ident (ignore)
+ int ignore;
+{
+ static segT comment_section;
+ segT old_section = now_seg;
+ int old_subsection = now_subseg;
+
+ if (!comment_section)
+ {
+ char *p;
+ comment_section = subseg_new (".comment", 0);
+ bfd_set_section_flags (stdoutput, comment_section,
+ SEC_READONLY | SEC_HAS_CONTENTS);
+ p = frag_more (1);
+ *p = 0;
+ }
+ else
+ subseg_set (comment_section, 0);
+ stringer (1);
+ subseg_set (old_section, old_subsection);
+}
+
+#ifdef INIT_STAB_SECTION
+
+/* The first entry in a .stabs section is special. */
+
+void
+obj_elf_init_stab_section (seg)
+ segT seg;
+{
+ char *file;
+ char *p;
+ char *stabstr_name;
+ unsigned int stroff;
+
+ /* Force the section to align to a longword boundary. Without this,
+ UnixWare ar crashes. */
+ bfd_set_section_alignment (stdoutput, seg, 2);
+
+ /* Make space for this first symbol. */
+ p = frag_more (12);
+ /* Zero it out. */
+ memset (p, 0, 12);
+ as_where (&file, (unsigned int *) NULL);
+ stabstr_name = (char *) alloca (strlen (segment_name (seg)) + 4);
+ strcpy (stabstr_name, segment_name (seg));
+ strcat (stabstr_name, "str");
+ stroff = get_stab_string_offset (file, stabstr_name);
+ know (stroff == 1);
+ md_number_to_chars (p, stroff, 4);
+ seg_info (seg)->stabu.p = p;
+}
+
+#endif
+
+/* Fill in the counts in the first entry in a .stabs section. */
+
+static void
+adjust_stab_sections (abfd, sec, xxx)
+ bfd *abfd;
+ asection *sec;
+ PTR xxx;
+{
+ char *name;
+ asection *strsec;
+ char *p;
+ int strsz, nsyms;
+
+ if (strncmp (".stab", sec->name, 5))
+ return;
+ if (!strcmp ("str", sec->name + strlen (sec->name) - 3))
+ return;
+
+ name = (char *) alloca (strlen (sec->name) + 4);
+ strcpy (name, sec->name);
+ strcat (name, "str");
+ strsec = bfd_get_section_by_name (abfd, name);
+ if (strsec)
+ strsz = bfd_section_size (abfd, strsec);
+ else
+ strsz = 0;
+ nsyms = bfd_section_size (abfd, sec) / 12 - 1;
+
+ p = seg_info (sec)->stabu.p;
+ assert (p != 0);
+
+ bfd_h_put_16 (abfd, (bfd_vma) nsyms, (bfd_byte *) p + 6);
+ bfd_h_put_32 (abfd, (bfd_vma) strsz, (bfd_byte *) p + 8);
+}
+
+#ifdef NEED_ECOFF_DEBUG
+
+/* This function is called by the ECOFF code. It is supposed to
+ record the external symbol information so that the backend can
+ write it out correctly. The ELF backend doesn't actually handle
+ this at the moment, so we do it ourselves. We save the information
+ in the symbol. */
+
+void
+elf_ecoff_set_ext (sym, ext)
+ symbolS *sym;
+ struct ecoff_extr *ext;
+{
+ sym->bsym->udata.p = (PTR) ext;
+}
+
+/* This function is called by bfd_ecoff_debug_externals. It is
+ supposed to *EXT to the external symbol information, and return
+ whether the symbol should be used at all. */
+
+static boolean
+elf_get_extr (sym, ext)
+ asymbol *sym;
+ EXTR *ext;
+{
+ if (sym->udata.p == NULL)
+ return false;
+ *ext = *(EXTR *) sym->udata.p;
+ return true;
+}
+
+/* This function is called by bfd_ecoff_debug_externals. It has
+ nothing to do for ELF. */
+
+/*ARGSUSED*/
+static void
+elf_set_index (sym, indx)
+ asymbol *sym;
+ bfd_size_type indx;
+{
+}
+
+#endif /* NEED_ECOFF_DEBUG */
+
+void
+elf_frob_symbol (symp, puntp)
+ symbolS *symp;
+ int *puntp;
+{
+#ifdef NEED_ECOFF_DEBUG
+ if (ECOFF_DEBUGGING)
+ ecoff_frob_symbol (symp);
+#endif
+
+ if (symp->sy_obj.size != NULL)
+ {
+ switch (symp->sy_obj.size->X_op)
+ {
+ case O_subtract:
+ S_SET_SIZE (symp,
+ (S_GET_VALUE (symp->sy_obj.size->X_add_symbol)
+ + symp->sy_obj.size->X_add_number
+ - S_GET_VALUE (symp->sy_obj.size->X_op_symbol)));
+ break;
+ case O_constant:
+ S_SET_SIZE (symp,
+ (S_GET_VALUE (symp->sy_obj.size->X_add_symbol)
+ + symp->sy_obj.size->X_add_number));
+ break;
+ default:
+ as_bad (_(".size expression too complicated to fix up"));
+ break;
+ }
+ free (symp->sy_obj.size);
+ symp->sy_obj.size = NULL;
+ }
+
+ if (symp->sy_obj.versioned_name != NULL)
+ {
+ /* This symbol was given a new name with the .symver directive.
+
+ If this is an external reference, just rename the symbol to
+ include the version string. This will make the relocs be
+ against the correct versioned symbol.
+
+ If this is a definition, add an alias. FIXME: Using an alias
+ will permit the debugging information to refer to the right
+ symbol. However, it's not clear whether it is the best
+ approach. */
+
+ if (! S_IS_DEFINED (symp))
+ {
+ char *p;
+
+ /* Verify that the name isn't using the @@ syntax--this is
+ reserved for definitions of the default version to link
+ against. */
+ p = strchr (symp->sy_obj.versioned_name, ELF_VER_CHR);
+ know (p != NULL);
+ if (p[1] == ELF_VER_CHR)
+ {
+ as_bad (_("invalid attempt to declare external version name as default in symbol `%s'"),
+ symp->sy_obj.versioned_name);
+ *puntp = true;
+ }
+ S_SET_NAME (symp, symp->sy_obj.versioned_name);
+ }
+ else
+ {
+ symbolS *symp2;
+
+ /* FIXME: Creating a new symbol here is risky. We're in the
+ final loop over the symbol table. We can get away with
+ it only because the symbol goes to the end of the list,
+ where the loop will still see it. It would probably be
+ better to do this in obj_frob_file_before_adjust. */
+
+ symp2 = symbol_find_or_make (symp->sy_obj.versioned_name);
+
+ /* Now we act as though we saw symp2 = sym. */
+
+ S_SET_SEGMENT (symp2, S_GET_SEGMENT (symp));
+
+ /* Subtracting out the frag address here is a hack because
+ we are in the middle of the final loop. */
+ S_SET_VALUE (symp2, S_GET_VALUE (symp) - symp->sy_frag->fr_address);
+
+ symp2->sy_frag = symp->sy_frag;
+
+ /* This will copy over the size information. */
+ copy_symbol_attributes (symp2, symp);
+
+ if (S_IS_WEAK (symp))
+ S_SET_WEAK (symp2);
+
+ if (S_IS_EXTERNAL (symp))
+ S_SET_EXTERNAL (symp2);
+ }
+ }
+
+ /* Double check weak symbols. */
+ if (symp->bsym->flags & BSF_WEAK)
+ {
+ if (S_IS_COMMON (symp))
+ as_bad (_("Symbol `%s' can not be both weak and common"),
+ S_GET_NAME (symp));
+ }
+
+#ifdef TC_MIPS
+ /* The Irix 5 and 6 assemblers set the type of any common symbol and
+ any undefined non-function symbol to STT_OBJECT. We try to be
+ compatible, since newer Irix 5 and 6 linkers care. However, we
+ only set undefined symbols to be STT_OBJECT if we are on Irix,
+ because that is the only time gcc will generate the necessary
+ .global directives to mark functions. */
+
+ if (S_IS_COMMON (symp))
+ symp->bsym->flags |= BSF_OBJECT;
+
+ if (strstr (TARGET_OS, "irix") != NULL
+ && (! S_IS_DEFINED (symp) && ((symp->bsym->flags & BSF_FUNCTION) == 0)))
+ symp->bsym->flags |= BSF_OBJECT;
+#endif
+
+#ifdef TC_PPC
+ /* Frob the PowerPC, so that the symbol always has object type
+ if it is not some other type. VxWorks needs this. */
+ if ((symp->bsym->flags & (BSF_FUNCTION | BSF_FILE | BSF_SECTION_SYM)) == 0
+ && S_IS_DEFINED (symp))
+ symp->bsym->flags |= BSF_OBJECT;
+#endif
+}
+
+void
+elf_frob_file ()
+{
+ bfd_map_over_sections (stdoutput, adjust_stab_sections, (PTR) 0);
+
+#ifdef elf_tc_final_processing
+ elf_tc_final_processing ();
+#endif
+}
+
+/* It is required that we let write_relocs have the opportunity to
+ optimize away fixups before output has begun, since it is possible
+ to eliminate all fixups for a section and thus we never should
+ have generated the relocation section. */
+
+void
+elf_frob_file_after_relocs ()
+{
+#ifdef NEED_ECOFF_DEBUG
+ if (ECOFF_DEBUGGING)
+ /* Generate the ECOFF debugging information. */
+ {
+ const struct ecoff_debug_swap *debug_swap;
+ struct ecoff_debug_info debug;
+ char *buf;
+ asection *sec;
+
+ debug_swap
+ = get_elf_backend_data (stdoutput)->elf_backend_ecoff_debug_swap;
+ know (debug_swap != (const struct ecoff_debug_swap *) NULL);
+ ecoff_build_debug (&debug.symbolic_header, &buf, debug_swap);
+
+ /* Set up the pointers in debug. */
+#define SET(ptr, offset, type) \
+ debug.ptr = (type) (buf + debug.symbolic_header.offset)
+
+ SET (line, cbLineOffset, unsigned char *);
+ SET (external_dnr, cbDnOffset, PTR);
+ SET (external_pdr, cbPdOffset, PTR);
+ SET (external_sym, cbSymOffset, PTR);
+ SET (external_opt, cbOptOffset, PTR);
+ SET (external_aux, cbAuxOffset, union aux_ext *);
+ SET (ss, cbSsOffset, char *);
+ SET (external_fdr, cbFdOffset, PTR);
+ SET (external_rfd, cbRfdOffset, PTR);
+ /* ssext and external_ext are set up just below. */
+
+#undef SET
+
+ /* Set up the external symbols. */
+ debug.ssext = debug.ssext_end = NULL;
+ debug.external_ext = debug.external_ext_end = NULL;
+ if (! bfd_ecoff_debug_externals (stdoutput, &debug, debug_swap, true,
+ elf_get_extr, elf_set_index))
+ as_fatal (_("Failed to set up debugging information: %s"),
+ bfd_errmsg (bfd_get_error ()));
+
+ sec = bfd_get_section_by_name (stdoutput, ".mdebug");
+ assert (sec != NULL);
+
+ know (stdoutput->output_has_begun == false);
+
+ /* We set the size of the section, call bfd_set_section_contents
+ to force the ELF backend to allocate a file position, and then
+ write out the data. FIXME: Is this really the best way to do
+ this? */
+ sec->_raw_size = bfd_ecoff_debug_size (stdoutput, &debug, debug_swap);
+
+ if (! bfd_set_section_contents (stdoutput, sec, (PTR) NULL,
+ (file_ptr) 0, (bfd_size_type) 0))
+ as_fatal (_("Can't start writing .mdebug section: %s"),
+ bfd_errmsg (bfd_get_error ()));
+
+ know (stdoutput->output_has_begun == true);
+ know (sec->filepos != 0);
+
+ if (! bfd_ecoff_write_debug (stdoutput, &debug, debug_swap,
+ sec->filepos))
+ as_fatal (_("Could not write .mdebug section: %s"),
+ bfd_errmsg (bfd_get_error ()));
+ }
+#endif /* NEED_ECOFF_DEBUG */
+}
+
+#ifdef SCO_ELF
+
+/* Heavily plagarized from obj_elf_version. The idea is to emit the
+ SCO specific identifier in the .notes section to satisfy the SCO
+ linker.
+
+ This looks more complicated than it really is. As opposed to the
+ "obvious" solution, this should handle the cross dev cases
+ correctly. (i.e, hosting on a 64 bit big endian processor, but
+ generating SCO Elf code) Efficiency isn't a concern, as there
+ should be exactly one of these sections per object module.
+
+ SCO OpenServer 5 identifies it's ELF modules with a standard ELF
+ .note section.
+
+ int_32 namesz = 4 ; Name size
+ int_32 descsz = 12 ; Descriptive information
+ int_32 type = 1 ;
+ char name[4] = "SCO" ; Originator name ALWAYS SCO + NULL
+ int_32 version = (major ver # << 16) | version of tools ;
+ int_32 source = (tool_id << 16 ) | 1 ;
+ int_32 info = 0 ; These are set by the SCO tools, but we
+ don't know enough about the source
+ environment to set them. SCO ld currently
+ ignores them, and recommends we set them
+ to zero. */
+
+#define SCO_MAJOR_VERSION 0x1
+#define SCO_MINOR_VERSION 0x1
+
+void
+sco_id ()
+{
+
+ char *name;
+ unsigned int c;
+ char ch;
+ char *p;
+ asection *seg = now_seg;
+ subsegT subseg = now_subseg;
+ Elf_Internal_Note i_note;
+ Elf_External_Note e_note;
+ asection *note_secp = (asection *) NULL;
+ int i, len;
+
+ /* create the .note section */
+
+ note_secp = subseg_new (".note", 0);
+ bfd_set_section_flags (stdoutput,
+ note_secp,
+ SEC_HAS_CONTENTS | SEC_READONLY);
+
+ /* process the version string */
+
+ i_note.namesz = 4;
+ i_note.descsz = 12; /* 12 descriptive bytes */
+ i_note.type = NT_VERSION; /* Contains a version string */
+
+ p = frag_more (sizeof (i_note.namesz));
+ md_number_to_chars (p, (valueT) i_note.namesz, 4);
+
+ p = frag_more (sizeof (i_note.descsz));
+ md_number_to_chars (p, (valueT) i_note.descsz, 4);
+
+ p = frag_more (sizeof (i_note.type));
+ md_number_to_chars (p, (valueT) i_note.type, 4);
+
+ p = frag_more (4);
+ strcpy (p, "SCO");
+
+ /* Note: this is the version number of the ELF we're representing */
+ p = frag_more (4);
+ md_number_to_chars (p, (SCO_MAJOR_VERSION << 16) | (SCO_MINOR_VERSION), 4);
+
+ /* Here, we pick a magic number for ourselves (yes, I "registered"
+ it with SCO. The bottom bit shows that we are compat with the
+ SCO ABI. */
+ p = frag_more (4);
+ md_number_to_chars (p, 0x4c520000 | 0x0001, 4);
+
+ /* If we knew (or cared) what the source language options were, we'd
+ fill them in here. SCO has given us permission to ignore these
+ and just set them to zero. */
+ p = frag_more (4);
+ md_number_to_chars (p, 0x0000, 4);
+
+ frag_align (2, 0, 0);
+
+ /* We probably can't restore the current segment, for there likely
+ isn't one yet... */
+ if (seg && subseg)
+ subseg_set (seg, subseg);
+
+}
+
+#endif /* SCO_ELF */
+
+const struct format_ops elf_format_ops =
+{
+ bfd_target_elf_flavour,
+ 0,
+ 1,
+ elf_frob_symbol,
+ elf_frob_file,
+ elf_frob_file_after_relocs,
+ elf_s_get_size, elf_s_set_size,
+ elf_s_get_align, elf_s_set_align,
+ elf_copy_symbol_attributes,
+#ifdef NEED_ECOFF_DEBUG
+ ecoff_generate_asm_lineno,
+ ecoff_stab,
+#else
+ 0,
+ 0, /* process_stab */
+#endif
+ elf_sec_sym_ok_for_reloc,
+ elf_pop_insert,
+#ifdef NEED_ECOFF_DEBUG
+ elf_ecoff_set_ext,
+#else
+ 0,
+#endif
+ obj_read_begin_hook,
+ obj_symbol_new_hook,
+};
diff --git a/gas/config/obj-elf.h b/gas/config/obj-elf.h
new file mode 100644
index 0000000000..2f4bc5f977
--- /dev/null
+++ b/gas/config/obj-elf.h
@@ -0,0 +1,194 @@
+/* ELF object file format.
+ Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+
+/* HP PA-RISC support was contributed by the Center for Software Science
+ at the University of Utah. */
+
+#ifndef _OBJ_ELF_H
+#define _OBJ_ELF_H
+
+#define OBJ_ELF 1
+
+#define OUTPUT_FLAVOR bfd_target_elf_flavour
+
+#include <bfd.h>
+
+#define BYTES_IN_WORD 4 /* for now */
+#include "bfd/elf-bfd.h"
+
+/* Additional information we keep for each symbol. */
+
+/* FIXME: For some reason, this structure is needed both here and in
+ obj-multi.h. */
+#ifndef OBJ_SYMFIELD_TYPE
+struct elf_obj_sy
+{
+ /* Use this to keep track of .size expressions that involve
+ differences that we can't compute yet. */
+ expressionS *size;
+
+ /* The name specified by the .symver directive. */
+ char *versioned_name;
+};
+#endif
+
+#define OBJ_SYMFIELD_TYPE struct elf_obj_sy
+
+/* Symbol fields used by the ELF back end. */
+#define ELF_TARGET_SYMBOL_FIELDS int local:1;
+
+/* Don't change this; change ELF_TARGET_SYMBOL_FIELDS instead. */
+#define TARGET_SYMBOL_FIELDS ELF_TARGET_SYMBOL_FIELDS
+
+#include "targ-cpu.h"
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE !FALSE
+#endif
+
+#define obj_begin() elf_begin ()
+extern void elf_begin PARAMS ((void));
+
+/* should be conditional on address size! */
+#define elf_symbol(asymbol) ((elf_symbol_type *)(&(asymbol)->the_bfd))
+
+#define S_GET_SIZE(S) (elf_symbol ((S)->bsym)->internal_elf_sym.st_size)
+#define S_SET_SIZE(S,V) \
+ (elf_symbol((S)->bsym)->internal_elf_sym.st_size = (V))
+
+#define S_GET_ALIGN(S) (elf_symbol ((S)->bsym)->internal_elf_sym.st_value)
+#define S_SET_ALIGN(S,V) \
+ (elf_symbol ((S)->bsym)->internal_elf_sym.st_value = (V))
+
+#define S_GET_OTHER(S) (elf_symbol ((S)->bsym)->internal_elf_sym.st_other)
+#define S_SET_OTHER(S,V) \
+ (elf_symbol ((S)->bsym)->internal_elf_sym.st_other = (V))
+
+extern asection *gdb_section;
+
+#define obj_frob_file elf_frob_file
+extern void elf_frob_file PARAMS ((void));
+
+#define obj_frob_file_after_relocs elf_frob_file_after_relocs
+extern void elf_frob_file_after_relocs PARAMS ((void));
+
+#define obj_app_file elf_file_symbol
+extern void elf_file_symbol PARAMS ((char *));
+
+extern void obj_elf_section_change_hook PARAMS ((void));
+
+extern void obj_elf_section PARAMS ((int));
+extern void obj_elf_previous PARAMS ((int));
+extern void obj_elf_version PARAMS ((int));
+
+/* BFD wants to write the udata field, which is a no-no for the
+ globally defined sections. */
+#define obj_sec_sym_ok_for_reloc(SEC) ((SEC)->owner != 0)
+
+/* When setting one symbol equal to another, by default we probably
+ want them to have the same "size", whatever it means in the current
+ context. */
+#define OBJ_COPY_SYMBOL_ATTRIBUTES(DEST,SRC) \
+do \
+ { \
+ if ((SRC)->sy_obj.size) \
+ { \
+ if ((DEST)->sy_obj.size == NULL) \
+ (DEST)->sy_obj.size = \
+ (expressionS *) xmalloc (sizeof (expressionS)); \
+ *(DEST)->sy_obj.size = *(SRC)->sy_obj.size; \
+ } \
+ else \
+ { \
+ if ((DEST)->sy_obj.size != NULL) \
+ free ((DEST)->sy_obj.size); \
+ (DEST)->sy_obj.size = NULL; \
+ } \
+ S_SET_SIZE ((DEST), S_GET_SIZE (SRC)); \
+ S_SET_OTHER ((DEST), S_GET_OTHER (SRC)); \
+ } \
+while (0)
+
+/* Stabs go in a separate section. */
+#define SEPARATE_STAB_SECTIONS 1
+
+/* We need 12 bytes at the start of the section to hold some initial
+ information. */
+extern void obj_elf_init_stab_section PARAMS ((segT));
+#define INIT_STAB_SECTION(seg) obj_elf_init_stab_section (seg)
+
+#ifdef TC_ALPHA
+#define ECOFF_DEBUGGING alpha_flag_mdebug
+extern int alpha_flag_mdebug;
+#endif
+
+/* For now, always set ECOFF_DEBUGGING for a MIPS target. */
+#ifdef TC_MIPS
+#ifdef MIPS_STABS_ELF
+#define ECOFF_DEBUGGING 0
+#else
+#define ECOFF_DEBUGGING 1
+#endif /* MIPS_STABS_ELF */
+#endif /* TC_MIPS */
+
+#ifdef ECOFF_DEBUGGING
+/* If we are generating ECOFF debugging information, we need some
+ additional fields for each symbol. */
+#undef TARGET_SYMBOL_FIELDS
+#define TARGET_SYMBOL_FIELDS \
+ ELF_TARGET_SYMBOL_FIELDS \
+ struct efdr *ecoff_file; \
+ struct localsym *ecoff_symbol; \
+ valueT ecoff_extern_size;
+
+/* We smuggle stabs in ECOFF rather than using a separate section.
+ The Irix linker can not handle a separate stabs section. */
+
+#undef SEPARATE_STAB_SECTIONS
+#define SEPARATE_STAB_SECTIONS (!ECOFF_DEBUGGING)
+
+#undef INIT_STAB_SECTION
+#define INIT_STAB_SECTION(seg) \
+ ((void)(ECOFF_DEBUGGING ? 0 : (obj_elf_init_stab_section (seg), 0)))
+
+#define OBJ_PROCESS_STAB(seg, what, string, type, other, desc) \
+ if (ECOFF_DEBUGGING) \
+ ecoff_stab ((seg), (what), (string), (type), (other), (desc))
+#endif /* ECOFF_DEBUGGING */
+
+extern void elf_frob_symbol PARAMS ((struct symbol *, int *));
+#ifndef obj_frob_symbol
+#define obj_frob_symbol(symp, punt) elf_frob_symbol (symp, &punt)
+#endif
+
+extern void elf_pop_insert PARAMS ((void));
+#define obj_pop_insert() elf_pop_insert()
+
+#ifndef OBJ_MAYBE_ELF
+#define obj_ecoff_set_ext elf_ecoff_set_ext
+#ifdef ANSI_PROTOTYPES
+struct ecoff_extr;
+#endif
+extern void elf_ecoff_set_ext PARAMS ((struct symbol *, struct ecoff_extr *));
+#endif
+
+#endif /* _OBJ_ELF_H */
diff --git a/gas/config/obj-evax.c b/gas/config/obj-evax.c
new file mode 100644
index 0000000000..e818c83b90
--- /dev/null
+++ b/gas/config/obj-evax.c
@@ -0,0 +1,83 @@
+/* obj-evax.c - EVAX (openVMS/Alpha) object file format.
+ Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+ Contributed by Klaus Kämpf (kkaempf@progis.de) of
+ proGIS Software, Aachen, Germany.
+
+ This file is part of GAS, the GNU Assembler
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA. */
+
+#define OBJ_HEADER "obj-evax.h"
+
+#include "as.h"
+
+static void s_evax_weak PARAMS ((int));
+
+const pseudo_typeS obj_pseudo_table[] =
+{
+ { "weak", s_evax_weak, 0},
+ {0, 0, 0},
+}; /* obj_pseudo_table */
+
+void obj_read_begin_hook () {}
+
+/* Handle the weak specific pseudo-op. */
+
+static void
+s_evax_weak (ignore)
+ int ignore;
+{
+ char *name;
+ int c;
+ symbolS *symbolP;
+ char *stop = NULL;
+ char stopc;
+
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
+
+ do
+ {
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ symbolP = symbol_find_or_make (name);
+ *input_line_pointer = c;
+ SKIP_WHITESPACE ();
+ S_SET_WEAK (symbolP);
+ if (c == ',')
+ {
+ input_line_pointer++;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '\n')
+ c = '\n';
+ }
+ }
+ while (c == ',');
+
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+
+ demand_empty_rest_of_line ();
+}
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of obj-evax.c */
diff --git a/gas/config/obj-evax.h b/gas/config/obj-evax.h
new file mode 100644
index 0000000000..1d9db19f41
--- /dev/null
+++ b/gas/config/obj-evax.h
@@ -0,0 +1,95 @@
+/* This file is obj-evax.h
+ Copyright (C) 1996 Free Software Foundation, Inc.
+ Contributed by Klaus Kämpf (kkaempf@progis.de) of
+ proGIS Software, Aachen, Germany.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA. */
+
+/*
+ * This file is obj-evax.h and is intended to be a template for
+ * object format specific header files.
+ */
+
+/* define an obj specific macro off which target cpu back ends may key. */
+#define OBJ_EVAX 1
+
+/* include whatever target cpu is appropriate. */
+#include "targ-cpu.h"
+
+#ifdef BFD_ASSEMBLER
+#define OUTPUT_FLAVOR bfd_target_evax_flavour
+#endif
+
+/*
+ * SYMBOLS
+ */
+
+/*
+ * If your object format needs to reorder symbols, define this. When
+ * defined, symbols are kept on a doubly linked list and functions are
+ * made available for push, insert, append, and delete. If not defined,
+ * symbols are kept on a singly linked list, only the append and clear
+ * facilities are available, and they are macros.
+ */
+
+/* #define SYMBOLS_NEED_PACKPOINTERS */
+
+/* */
+typedef struct
+ {
+ void *nothing;
+ }
+obj_symbol_type; /* should be the format's symbol structure */
+
+typedef void *object_headers;
+
+#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (0) /* your magic number */
+
+#define OBJ_EMIT_LINENO(a,b,c) /* must be *something*. This no-op's it out. */
+
+#define obj_symbol_new_hook(s) {;}
+
+#define S_SET_OTHER(S,V)
+#define S_SET_TYPE(S,T)
+#define S_SET_DESC(S,D)
+#define S_GET_OTHER(S) 0
+#define S_GET_TYPE(S) 0
+#define S_GET_DESC(S) 0
+
+#define PDSC_S_K_KIND_FP_STACK 9
+#define PDSC_S_K_KIND_FP_REGISTER 10
+#define PDSC_S_K_KIND_NULL 8
+
+#define PDSC_S_K_MIN_STACK_SIZE 32
+#define PDSC_S_K_MIN_REGISTER_SIZE 24
+#define PDSC_S_K_NULL_SIZE 16
+
+#define PDSC_S_M_BASE_REG_IS_FP 0x80 /* low byte */
+#define PDSC_S_M_NATIVE 0x10 /* high byte */
+#define PDSC_S_M_NO_JACKET 0x20 /* high byte */
+
+#define LKP_S_K_SIZE 16
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of obj-evax.h */
diff --git a/gas/config/obj-generic.c b/gas/config/obj-generic.c
new file mode 100644
index 0000000000..69fc3d1dbf
--- /dev/null
+++ b/gas/config/obj-generic.c
@@ -0,0 +1,41 @@
+/* This file is obj-generic.c and is intended to be a template for
+ object format specific source files.
+
+ Copyright (C) 1987-1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* As in 0f12.456 */
+/* or 0d1.2345e12 */
+char FLT_CHARS[] = "rRsSfFdDxXpP";
+
+/* These chars start a comment anywhere in a source file (except inside
+ another comment */
+const char comment_chars[] = "#";
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of obj-generic.c */
diff --git a/gas/config/obj-generic.h b/gas/config/obj-generic.h
new file mode 100644
index 0000000000..dc18e43970
--- /dev/null
+++ b/gas/config/obj-generic.h
@@ -0,0 +1,80 @@
+/* This file is obj-generic.h
+ Copyright (C) 1987-1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * This file is obj-generic.h and is intended to be a template for
+ * object format specific header files.
+ */
+
+/* define an obj specific macro off which target cpu back ends may key. */
+#define OBJ_GENERIC 1
+
+/* include whatever target cpu is appropriate. */
+#include "targ-cpu.h"
+
+/*
+ * SYMBOLS
+ */
+
+/*
+ * If your object format needs to reorder symbols, define this. When
+ * defined, symbols are kept on a doubly linked list and functions are
+ * made available for push, insert, append, and delete. If not defined,
+ * symbols are kept on a singly linked list, only the append and clear
+ * facilities are available, and they are macros.
+ */
+
+/* #define SYMBOLS_NEED_PACKPOINTERS */
+
+/* */
+typedef struct
+ {
+ void *nothing;
+ }
+
+obj_symbol_type; /* should be the format's symbol structure */
+
+typedef void *object_headers;
+
+/* symbols have names */
+#define S_GET_NAME(s) ("foo") /* get the name of a symbolP */
+#define S_SET_NAME(s,v) ;
+/* symbols have segments */
+#define S_GET_SEGMENT(s) (SEG_UNKNOWN)
+#define S_SET_SEGMENT(s,v) ;
+/* symbols may be external */
+#define S_IS_EXTERNAL(s) (0)
+#define S_SET_EXTERNAL(s) ;
+
+/* symbols may or may not be defined */
+#define S_IS_DEFINED(s) (0)
+
+
+#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (0) /* your magic number */
+
+#define OBJ_EMIT_LINENO(a,b,c) /* must be *something*. This no-op's it out. */
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of obj-generic.h */
diff --git a/gas/config/obj-hp300.c b/gas/config/obj-hp300.c
new file mode 100644
index 0000000000..6e9cc53927
--- /dev/null
+++ b/gas/config/obj-hp300.c
@@ -0,0 +1,52 @@
+/* This file is obj-hp300.h
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "config/obj-aout.c"
+
+/* Aout file generation & utilities */
+void
+hp300_header_append (where, headers)
+ char **where;
+ object_headers *headers;
+{
+ tc_headers_hook (headers);
+
+#define DO(FIELD) \
+ { \
+ md_number_to_chars (*where, headers->header.FIELD, sizeof (headers->header.FIELD)); \
+ *where += sizeof (headers->header.FIELD); \
+ }
+
+ DO (a_info);
+ DO (a_spare1);
+ DO (a_spare2);
+ DO (a_text);
+ DO (a_data);
+ DO (a_bss);
+ DO (a_trsize);
+ DO (a_drsize);
+ DO (a_spare3);
+ DO (a_spare4);
+ DO (a_spare5);
+ DO (a_entry);
+ DO (a_spare6);
+ DO (a_spare7);
+ DO (a_syms);
+ DO (a_spare8);
+}
diff --git a/gas/config/obj-hp300.h b/gas/config/obj-hp300.h
new file mode 100644
index 0000000000..ff4006b604
--- /dev/null
+++ b/gas/config/obj-hp300.h
@@ -0,0 +1,71 @@
+/* This file is obj-hp300.h
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define __STRUCT_EXEC_OVERRIDE__
+
+struct exec_bytes
+{
+ unsigned char a_info[4]; /* a_machtype/a_magic */
+ unsigned char a_spare1[4];
+ unsigned char a_spare2[4];
+ unsigned char a_text[4]; /* length of text, in bytes */
+ unsigned char a_data[4]; /* length of data, in bytes */
+ unsigned char a_bss[4]; /* length of uninitialized data area for file, in bytes */
+ unsigned char a_trsize[4]; /* length of relocation info for text, in bytes */
+ unsigned char a_drsize[4]; /* length of relocation info for data, in bytes */
+ unsigned char a_spare3[4]; /* HP = pascal interface size */
+ unsigned char a_spare4[4]; /* HP = symbol table size */
+ unsigned char a_spare5[4]; /* HP = debug name table size */
+ unsigned char a_entry[4]; /* start address */
+ unsigned char a_spare6[4]; /* HP = source line table size */
+ unsigned char a_spare7[4]; /* HP = value table size */
+ unsigned char a_syms[4]; /* length of symbol table data in file, in bytes */
+ unsigned char a_spare8[4];
+};
+
+/* How big the "struct exec" is on disk */
+#define EXEC_BYTES_SIZE (16 * 4)
+
+struct exec
+{
+ unsigned long a_info;
+ unsigned long a_spare1;
+ unsigned long a_spare2;
+ unsigned long a_text;
+ unsigned long a_data;
+ unsigned long a_bss;
+ unsigned long a_trsize;
+ unsigned long a_drsize;
+ unsigned long a_spare3;
+ unsigned long a_spare4;
+ unsigned long a_spare5;
+ unsigned long a_entry;
+ unsigned long a_spare6;
+ unsigned long a_spare7;
+ unsigned long a_syms;
+ unsigned long a_spare8;
+};
+
+#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (OMAGIC)
+#define AOUT_VERSION 0x02
+#define AOUT_MACHTYPE 0x0c
+#define OMAGIC 0x106
+
+#define obj_header_append hp300_header_append
+#include "config/obj-aout.h"
diff --git a/gas/config/obj-ieee.c b/gas/config/obj-ieee.c
new file mode 100644
index 0000000000..30a0798e29
--- /dev/null
+++ b/gas/config/obj-ieee.c
@@ -0,0 +1,627 @@
+/* obj-format for ieee-695 records.
+ Copyright (C) 1991, 92, 93, 94, 95, 1997, 1998 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+
+/*
+ created by
+
+ steve chamberlain steve@cygnus.com
+ */
+
+/*
+ this will hopefully become the port through which bfd and gas talk,
+ for the moment, only ieee is known to work well.
+ */
+
+#include "bfd.h"
+#include "as.h"
+#include "subsegs.h"
+#include "output-file.h"
+#include "frags.h"
+
+bfd *abfd;
+
+/* How many addresses does the .align take? */
+static relax_addressT
+relax_align (address, alignment)
+ register relax_addressT address; /* Address now. */
+ register long alignment; /* Alignment (binary). */
+{
+ relax_addressT mask;
+ relax_addressT new_address;
+
+ mask = ~((~0) << alignment);
+ new_address = (address + mask) & (~mask);
+ return (new_address - address);
+} /* relax_align() */
+
+/* calculate the size of the frag chain and create a bfd section
+ to contain all of it */
+static void
+DEFUN (size_section, (abfd, idx),
+ bfd * abfd AND
+ unsigned int idx)
+{
+ asection *sec;
+ unsigned int size = 0;
+ fragS *frag = segment_info[idx].frag_root;
+ while (frag)
+ {
+ if (frag->fr_address != size)
+ {
+ printf (_("Out of step\n"));
+ size = frag->fr_address;
+ }
+ size += frag->fr_fix;
+ switch (frag->fr_type)
+ {
+ case rs_fill:
+ case rs_org:
+ size += frag->fr_offset * frag->fr_var;
+ break;
+ case rs_align:
+ case rs_align_code:
+ {
+ addressT off;
+
+ off = relax_align (size, frag->fr_offset);
+ if (frag->fr_subtype != 0 && off > frag->fr_subtype)
+ off = 0;
+ size += off;
+ }
+ }
+ frag = frag->fr_next;
+ }
+ if (size)
+ {
+ char *name = segment_info[idx].name;
+ if (name == (char *) NULL)
+ {
+ name = ".data";
+ }
+ segment_info[idx].user_stuff = (char *) (sec = bfd_make_section (abfd, name));
+ /* Make it output through itself */
+ sec->output_section = sec;
+ sec->flags |= SEC_HAS_CONTENTS;
+ bfd_set_section_size (abfd, sec, size);
+ }
+}
+
+/* run through a frag chain and write out the data to go with it */
+static void
+DEFUN (fill_section, (abfd, idx),
+ bfd * abfd AND
+ unsigned int idx)
+{
+ asection *sec = segment_info[idx].user_stuff;
+ if (sec)
+ {
+ fragS *frag = segment_info[idx].frag_root;
+ unsigned int offset = 0;
+ while (frag)
+ {
+ unsigned int fill_size;
+ unsigned int count;
+ switch (frag->fr_type)
+ {
+ case rs_fill:
+ case rs_align:
+ case rs_org:
+ if (frag->fr_fix)
+ {
+ bfd_set_section_contents (abfd,
+ sec,
+ frag->fr_literal,
+ frag->fr_address,
+ frag->fr_fix);
+ }
+ offset += frag->fr_fix;
+ fill_size = frag->fr_var;
+ if (fill_size)
+ {
+ unsigned int off = frag->fr_fix;
+ for (count = frag->fr_offset; count; count--)
+ {
+ bfd_set_section_contents (abfd, sec,
+ frag->fr_literal +
+ frag->fr_fix,
+ frag->fr_address + off,
+ fill_size);
+ off += fill_size;
+ }
+ }
+ break;
+ default:
+ abort ();
+ }
+ frag = frag->fr_next;
+ }
+ }
+}
+
+/* Count the relocations in a chain */
+
+static unsigned int
+DEFUN (count_entries_in_chain, (idx),
+ unsigned int idx)
+{
+ unsigned int nrelocs;
+ fixS *fixup_ptr;
+
+ /* Count the relocations */
+ fixup_ptr = segment_info[idx].fix_root;
+ nrelocs = 0;
+ while (fixup_ptr != (fixS *) NULL)
+ {
+ fixup_ptr = fixup_ptr->fx_next;
+ nrelocs++;
+ }
+ return nrelocs;
+}
+
+/* output all the relocations for a section */
+void
+DEFUN (do_relocs_for, (idx),
+ unsigned int idx)
+{
+ unsigned int nrelocs;
+ arelent **reloc_ptr_vector;
+ arelent *reloc_vector;
+ asymbol **ptrs;
+ asection *section = (asection *) (segment_info[idx].user_stuff);
+ unsigned int i;
+ fixS *from;
+ if (section)
+ {
+ nrelocs = count_entries_in_chain (idx);
+
+ reloc_ptr_vector = (arelent **) malloc ((nrelocs + 1) * sizeof (arelent *));
+ reloc_vector = (arelent *) malloc (nrelocs * sizeof (arelent));
+ ptrs = (asymbol **) malloc (nrelocs * sizeof (asymbol *));
+ from = segment_info[idx].fix_root;
+ for (i = 0; i < nrelocs; i++)
+ {
+ arelent *to = reloc_vector + i;
+ asymbol *s;
+ reloc_ptr_vector[i] = to;
+ to->howto = (reloc_howto_type *) (from->fx_r_type);
+
+#if 0 /* We can't represent complicated things in a reloc yet */
+ if (from->fx_addsy == 0 || from->fx_subsy != 0) abort();
+#endif
+
+ s = &(from->fx_addsy->sy_symbol.sy);
+ to->address = ((char *) (from->fx_frag->fr_address +
+ from->fx_where))
+ - ((char *) (&(from->fx_frag->fr_literal)));
+ to->addend = from->fx_offset;
+ /* If we know the symbol which we want to relocate to, turn
+ this reloaction into a section relative.
+
+ If this relocation is pcrelative, and we know the
+ destination, we still want to keep the relocation - since
+ the linker might relax some of the bytes, but it stops
+ being pc relative and turns into an absolute relocation. */
+ if (s)
+ {
+ if ((s->flags & BSF_UNDEFINED) == 0)
+ {
+ to->section = s->section;
+
+ /* We can refer directly to the value field here,
+ rather than using S_GET_VALUE, because this is
+ only called after do_symbols, which sets up the
+ value field. */
+ to->addend += s->value;
+
+ to->sym_ptr_ptr = 0;
+ if (to->howto->pcrel_offset)
+ {
+ /* This is a pcrel relocation, the addend should be adjusted */
+ to->addend -= to->address + 1;
+ }
+ }
+ else
+ {
+ to->section = 0;
+ *ptrs = &(from->fx_addsy->sy_symbol.sy);
+ to->sym_ptr_ptr = ptrs;
+
+ if (to->howto->pcrel_offset)
+ {
+ /* This is a pcrel relocation, the addend should be adjusted */
+ to->addend -= to->address - 1;
+ }
+ }
+
+ }
+ else
+ {
+ to->section = 0;
+ }
+
+ ptrs++;
+ from = from->fx_next;
+ }
+
+ /* attatch to the section */
+ section->orelocation = reloc_ptr_vector;
+ section->reloc_count = nrelocs;
+ section->flags |= SEC_LOAD;
+ }
+}
+
+/* do the symbols.. */
+static void
+DEFUN (do_symbols, (abfd),
+ bfd * abfd)
+{
+ extern symbolS *symbol_rootP;
+ symbolS *ptr;
+ asymbol **symbol_ptr_vec;
+ asymbol *symbol_vec;
+ unsigned int count = 0;
+ unsigned int index;
+
+
+ for (ptr = symbol_rootP;
+ ptr != (symbolS *) NULL;
+ ptr = ptr->sy_next)
+ {
+ if (SEG_NORMAL (ptr->sy_symbol.seg))
+ {
+ ptr->sy_symbol.sy.section =
+ (asection *) (segment_info[ptr->sy_symbol.seg].user_stuff);
+ S_SET_VALUE (ptr, S_GET_VALUE (ptr) + ptr->sy_frag->fr_address);
+ if (ptr->sy_symbol.sy.flags == 0)
+ {
+ ptr->sy_symbol.sy.flags = BSF_LOCAL;
+ }
+ }
+ else
+ {
+ switch (ptr->sy_symbol.seg)
+ {
+ case SEG_ABSOLUTE:
+ ptr->sy_symbol.sy.flags |= BSF_ABSOLUTE;
+ ptr->sy_symbol.sy.section = 0;
+ break;
+ case SEG_UNKNOWN:
+ ptr->sy_symbol.sy.flags = BSF_UNDEFINED;
+ ptr->sy_symbol.sy.section = 0;
+ break;
+ default:
+ abort ();
+ }
+ }
+ ptr->sy_symbol.sy.value = S_GET_VALUE (ptr);
+ count++;
+ }
+ symbol_ptr_vec = (asymbol **) malloc ((count + 1) * sizeof (asymbol *));
+
+ index = 0;
+ for (ptr = symbol_rootP;
+ ptr != (symbolS *) NULL;
+ ptr = ptr->sy_next)
+ {
+ symbol_ptr_vec[index] = &(ptr->sy_symbol.sy);
+ index++;
+ }
+ symbol_ptr_vec[index] = 0;
+ abfd->outsymbols = symbol_ptr_vec;
+ abfd->symcount = count;
+}
+
+/* The generic as->bfd converter. Other backends may have special case
+ code */
+
+void
+DEFUN_VOID (bfd_as_write_hook)
+{
+ int i;
+
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ {
+ size_section (abfd, i);
+ }
+
+
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ fill_section (abfd, i);
+
+ do_symbols (abfd);
+
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ do_relocs_for (i);
+
+}
+
+S_SET_SEGMENT (x, y)
+ symbolS *x;
+ int y;
+{
+ x->sy_symbol.seg = y;
+}
+
+S_IS_DEFINED (x)
+ symbolS *x;
+{
+ if (SEG_NORMAL (x->sy_symbol.seg))
+ {
+ return 1;
+ }
+ switch (x->sy_symbol.seg)
+ {
+ case SEG_UNKNOWN:
+ return 0;
+ default:
+ abort ();
+ }
+}
+
+S_IS_EXTERNAL (x)
+{
+ abort ();
+}
+
+S_GET_DESC (x)
+{
+ abort ();
+}
+
+S_GET_SEGMENT (x)
+ symbolS *x;
+{
+ return x->sy_symbol.seg;
+}
+
+S_SET_EXTERNAL (x)
+ symbolS *x;
+{
+ x->sy_symbol.sy.flags |= BSF_GLOBAL | BSF_EXPORT;
+}
+
+S_SET_NAME (x, y)
+ symbolS *x;
+ char *y;
+{
+ x->sy_symbol.sy.name = y;
+}
+
+S_GET_OTHER (x)
+{
+ abort ();
+}
+
+S_IS_DEBUG (x)
+{
+ abort ();
+}
+
+#ifndef segment_name
+char *
+segment_name ()
+{
+ abort ();
+}
+#endif
+
+void
+obj_read_begin_hook ()
+{
+}
+
+static void
+obj_ieee_section (ignore)
+ int ignore;
+{
+ extern char *input_line_pointer;
+ extern char is_end_of_line[];
+ char *p = input_line_pointer;
+ char *s = p;
+ int i;
+ /* Look up the name, if it doesn't exist, make it */
+ while (*p && *p != ' ' && *p != ',' && !is_end_of_line[*p])
+ {
+ p++;
+ }
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ {
+ if (segment_info[i].hadone)
+ {
+ if (strncmp (segment_info[i].name, s, p - s) == 0)
+ {
+ goto ok;
+
+ }
+ }
+ else
+ break;
+ }
+ if (i == SEG_UNKNOWN)
+ {
+ as_bad (_("too many sections"));
+ return;
+ }
+
+ segment_info[i].hadone = 1;
+ segment_info[i].name = malloc (p - s + 1);
+ memcpy (segment_info[i].name, s, p - s);
+ segment_info[i].name[p - s] = 0;
+ok:
+ subseg_set (i, 0);
+ while (!is_end_of_line[*p])
+ p++;
+ input_line_pointer = p;
+
+}
+
+
+void cons ();
+void s_ignore ();
+
+
+void s_globl ();
+const pseudo_typeS obj_pseudo_table[] =
+{
+ {"section", obj_ieee_section, 0},
+ {"data.b", cons, 1},
+ {"data.w", cons, 2},
+ {"data.l", cons, 4},
+ {"export", s_globl, 0},
+ {"option", s_ignore, 0},
+ {"end", s_ignore, 0},
+ {"import", s_ignore, 0},
+ {"sdata", stringer, 0},
+ 0,
+
+};
+
+
+
+void
+obj_symbol_new_hook (symbolP)
+ symbolS *symbolP;
+{
+ symbolP->sy_symbol.sy.the_bfd = abfd;
+}
+
+
+
+
+
+#if 1
+extern void
+DEFUN_VOID (write_object_file)
+{
+ int i;
+ struct frchain *frchain_ptr;
+ struct frag *frag_ptr;
+
+ abfd = bfd_openw (out_file_name, "ieee");
+
+ if (abfd == 0)
+ {
+ as_perror (_("FATAL: Can't create %s"), out_file_name);
+ exit (EXIT_FAILURE);
+ }
+ bfd_set_format (abfd, bfd_object);
+ bfd_set_arch_mach (abfd, bfd_arch_h8300, 0);
+ subseg_set (1, 0);
+ subseg_set (2, 0);
+ subseg_set (3, 0);
+ for (frchain_ptr = frchain_root;
+ frchain_ptr != (struct frchain *) NULL;
+ frchain_ptr = frchain_ptr->frch_next)
+ {
+ /* Run through all the sub-segments and align them up. Also close any
+ open frags. We tack a .fill onto the end of the frag chain so
+ that any .align's size can be worked by looking at the next
+ frag. */
+
+ subseg_set (frchain_ptr->frch_seg, frchain_ptr->frch_subseg);
+#ifndef SUB_SEGMENT_ALIGN
+#define SUB_SEGMENT_ALIGN(SEG) 2
+#endif
+ frag_align (SUB_SEGMENT_ALIGN (now_seg), 0, 0);
+ frag_wane (frag_now);
+ frag_now->fr_fix = 0;
+ know (frag_now->fr_next == NULL);
+ }
+
+ /* Now build one big frag chain for each segment, linked through
+ fr_next. */
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ {
+
+ fragS **prev_frag_ptr_ptr;
+ struct frchain *next_frchain_ptr;
+
+ /* struct frag **head_ptr = segment_info[i].frag_root;*/
+
+ segment_info[i].frag_root = segment_info[i].frchainP->frch_root;
+#if 0
+ /* Im not sure what this is for */
+ for (frchain_ptr = segment_info[i].frchainP->frch_root;
+ frchain_ptr != (struct frchain *) NULL;
+ frchain_ptr = frchain_ptr->frch_next)
+ {
+ *head_ptr = frchain_ptr;
+ head_ptr = &frchain_ptr->next;
+ }
+
+
+#endif
+ }
+
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ {
+ relax_segment (segment_info[i].frag_root, i);
+ }
+
+ /* Now the addresses of the frags are correct within the segment */
+
+ bfd_as_write_hook ();
+ bfd_close (abfd);
+}
+
+#endif
+
+H_SET_TEXT_SIZE (a, b)
+{
+ abort ();
+}
+
+H_GET_TEXT_SIZE ()
+{
+ abort ();
+}
+
+H_SET_BSS_SIZE ()
+{
+ abort ();
+}
+
+H_SET_STRING_SIZE ()
+{
+ abort ();
+}
+
+H_SET_RELOCATION_SIZE ()
+{
+ abort ();
+}
+
+H_SET_MAGIC_NUMBER ()
+{
+ abort ();
+}
+
+H_GET_FILE_SIZE ()
+{
+ abort ();
+}
+
+H_GET_TEXT_RELOCATION_SIZE ()
+{
+ abort ();
+}
+
+/* end of obj-ieee.c */
diff --git a/gas/config/obj-ieee.h b/gas/config/obj-ieee.h
new file mode 100644
index 0000000000..4a0f126ebe
--- /dev/null
+++ b/gas/config/obj-ieee.h
@@ -0,0 +1,50 @@
+/* This file is obj-ieee.h
+
+ Copyright (C) 1987-1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define BFD 1
+
+#include <bfd.h>
+
+typedef struct
+{
+ asymbol sy;
+ int seg;
+}
+
+obj_symbol_type;
+
+#define S_GET_NAME(s) (((s)->sy_symbol.sy.name))
+
+typedef struct
+ {
+ int x;
+ }
+
+object_headers;
+
+#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE 1
+
+
+int lineno_rootP;
+
+
+#define IEEE_STYLE
+
+/* end of obj-ieee.h */
diff --git a/gas/config/obj-multi.c b/gas/config/obj-multi.c
new file mode 100644
index 0000000000..d115093aff
--- /dev/null
+++ b/gas/config/obj-multi.c
@@ -0,0 +1,4 @@
+/* foo */
+
+#include "as.h"
+
diff --git a/gas/config/obj-multi.h b/gas/config/obj-multi.h
new file mode 100644
index 0000000000..fe8d98d0d6
--- /dev/null
+++ b/gas/config/obj-multi.h
@@ -0,0 +1,50 @@
+/* hi */
+
+#include "emul.h"
+#include "targ-cpu.h"
+
+#define OUTPUT_FLAVOR (this_format->flavor)
+#define obj_frob_symbol(S,P) (this_format->frob_symbol)(S,&(P))
+#define obj_frob_file (this_format->frob_file)
+#define obj_frob_file_after_relocs (this_format->frob_file_after_relocs)
+#define obj_ecoff_set_ext (this_format->ecoff_set_ext)
+#define obj_pop_insert (this_format->pop_insert)
+#define obj_read_begin_hook() (this_format->read_begin_hook?this_format->read_begin_hook():(void)0)
+#define obj_symbol_new_hook (this_format->symbol_new_hook)
+#define obj_sec_sym_ok_for_reloc (this_format->sec_sym_ok_for_reloc)
+#define S_GET_SIZE (this_format->s_get_size)
+#define S_SET_SIZE (this_format->s_set_size)
+#define S_GET_ALIGN (this_format->s_get_align)
+#define S_SET_ALIGN (this_format->s_set_align)
+#define OBJ_COPY_SYMBOL_ATTRIBUTES (this_format->copy_symbol_attributes)
+#define OBJ_PROCESS_STAB (this_format->process_stab)
+
+#if defined (OBJ_MAYBE_ECOFF) || (defined (OBJ_MAYBE_ELF) && defined (TC_MIPS))
+#define ECOFF_DEBUGGING 1
+#endif
+
+/* FIXME: What's the story here? Why do we have to define
+ OBJ_SYMFIELD_TYPE both here and in obj-elf.h? */
+#ifdef OBJ_MAYBE_ELF
+struct elf_obj_sy
+{
+ expressionS *size;
+ char *versioned_name;
+};
+#define OBJ_SYMFIELD_TYPE struct elf_obj_sy
+#define ELF_TARGET_SYMBOL_FIELDS int local:1;
+#else
+#define ELF_TARGET_SYMBOL_FIELDS
+#endif
+
+#ifdef ECOFF_DEBUGGING
+struct efdr;
+struct localsym;
+#define ECOFF_DEBUG_TARGET_SYMBOL_FIELDS struct efdr *ecoff_file; struct localsym *ecoff_symbol; valueT ecoff_extern_size;
+#else
+#define ECOFF_DEBUG_TARGET_SYMBOL_FIELDS
+#endif
+
+#define TARGET_SYMBOL_FIELDS \
+ ELF_TARGET_SYMBOL_FIELDS \
+ ECOFF_DEBUG_TARGET_SYMBOL_FIELDS
diff --git a/gas/config/obj-som.c b/gas/config/obj-som.c
new file mode 100644
index 0000000000..80af18fd37
--- /dev/null
+++ b/gas/config/obj-som.c
@@ -0,0 +1,307 @@
+/* SOM object file format.
+ Copyright (C) 1993, 1998 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2,
+ or (at your option) any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ Written by the Center for Software Science at the University of Utah
+ and by Cygnus Support. */
+
+#include "as.h"
+#include "subsegs.h"
+#include "aout/stab_gnu.h"
+#include "obstack.h"
+
+/* SOM does not need any pseudo-ops. */
+
+const pseudo_typeS obj_pseudo_table[] =
+{
+ {NULL}
+};
+
+static int version_seen = 0;
+static int copyright_seen = 0;
+static int compiler_seen = 0;
+
+/* Unused by SOM. */
+void obj_read_begin_hook () {}
+
+/* Handle a .compiler directive. This is intended to create the
+ compilation unit auxiliary header for MPE such that the linkeditor
+ can handle SOM extraction from archives. The format of the quoted
+ string is "sourcefile language version" and is delimited by blanks.*/
+
+void
+obj_som_compiler (unused)
+ int unused;
+{
+ char *buf;
+ char c;
+ char *filename;
+ char *language_name;
+ char *p;
+ char *version_id;
+
+ if (compiler_seen)
+ {
+ as_bad ("Only one .compiler pseudo-op per file!");
+ ignore_rest_of_line ();
+ return;
+ }
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '\"')
+ {
+ buf = input_line_pointer;
+ ++input_line_pointer;
+ while (is_a_char (next_char_of_string ()))
+ ;
+ c = *input_line_pointer;
+ *input_line_pointer = '\000';
+ }
+ else
+ {
+ as_bad ("Expected quoted string");
+ ignore_rest_of_line ();
+ return;
+ }
+
+ /* Parse the quoted string into its component parts. Skip the
+ quote. */
+ filename = buf + 1;
+ p = filename;
+ while (*p != ' ' && *p != '\000')
+ p++;
+ if (*p == '\000')
+ {
+ as_bad (".compiler directive missing language and version");
+ return;
+ }
+ *p = '\000';
+
+ language_name = ++p;
+ while (*p != ' ' && *p != '\000') p++;
+ if (*p == '\000')
+ {
+ as_bad (".compiler directive missing version");
+ return;
+ }
+ *p = '\000';
+
+ version_id = ++p;
+ while (*p != '\000') p++;
+ /* Remove the trailing quote. */
+ *(--p) = '\000';
+
+ compiler_seen = 1;
+ if (! bfd_som_attach_compilation_unit (stdoutput, filename, language_name,
+ "GNU Tools", version_id))
+ {
+ bfd_perror (stdoutput->filename);
+ as_fatal ("FATAL: Attaching compiler header %s", stdoutput->filename);
+ }
+ *input_line_pointer = c;
+ demand_empty_rest_of_line ();
+}
+
+/* Handle a .version directive. */
+
+void
+obj_som_version (unused)
+ int unused;
+{
+ char *version, c;
+
+ if (version_seen)
+ {
+ as_bad (_("Only one .version pseudo-op per file!"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '\"')
+ {
+ version = input_line_pointer;
+ ++input_line_pointer;
+ while (is_a_char (next_char_of_string ()))
+ ;
+ c = *input_line_pointer;
+ *input_line_pointer = '\000';
+ }
+ else
+ {
+ as_bad (_("Expected quoted string"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ version_seen = 1;
+ if (bfd_som_attach_aux_hdr (stdoutput, VERSION_AUX_ID, version) == false)
+ {
+ bfd_perror (stdoutput->filename);
+ as_perror (_("FATAL: Attaching version header %s"), stdoutput->filename);
+ exit (EXIT_FAILURE);
+ }
+ *input_line_pointer = c;
+ demand_empty_rest_of_line ();
+}
+
+/* Handle a .copyright directive. This probably isn't complete, but
+ it's of dubious value anyway and (IMHO) not worth the time to finish.
+ If you care about copyright strings that much, you fix it. */
+
+void
+obj_som_copyright (unused)
+ int unused;
+{
+ char *copyright, c;
+
+ if (copyright_seen)
+ {
+ as_bad (_("Only one .copyright pseudo-op per file!"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '\"')
+ {
+ copyright = input_line_pointer;
+ ++input_line_pointer;
+ while (is_a_char (next_char_of_string ()))
+ ;
+ c = *input_line_pointer;
+ *input_line_pointer = '\000';
+ }
+ else
+ {
+ as_bad (_("Expected quoted string"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ copyright_seen = 1;
+ if (bfd_som_attach_aux_hdr (stdoutput, COPYRIGHT_AUX_ID, copyright) == false)
+ {
+ bfd_perror (stdoutput->filename);
+ as_perror (_("FATAL: Attaching copyright header %s"), stdoutput->filename);
+ exit (EXIT_FAILURE);
+ }
+ *input_line_pointer = c;
+ demand_empty_rest_of_line ();
+}
+
+/* Perform any initialization necessary for stabs support.
+
+ For SOM we need to create the space which will contain the
+ two stabs subspaces. Additionally we need to set up the
+ space/subspace relationships and set space/subspace attributes
+ which BFD does not understand. */
+
+void
+obj_som_init_stab_section (seg)
+ segT seg;
+{
+ segT saved_seg = now_seg;
+ segT space;
+ subsegT saved_subseg = now_subseg;
+ char *p, *file;
+ unsigned int stroff;
+
+ /* Make the space which will contain the debug subspaces. */
+ space = bfd_make_section_old_way (stdoutput, "$GDB_DEBUG$");
+
+ /* Set SOM specific attributes for the space. In particular we set
+ the space "defined", "private", "sort_key", and "spnum" values.
+
+ Due to a bug in pxdb (called by hpux linker), the sort keys
+ of the various stabs spaces/subspaces need to be "small". We
+ reserve range 72/73 which appear to work well. */
+ obj_set_section_attributes (space, 1, 1, 72, 2);
+ bfd_set_section_alignment (stdoutput, space, 2);
+
+ /* Set the containing space for both stab sections to be $GDB_DEBUG$
+ (just created above). Also set some attributes which BFD does
+ not understand. In particular, access bits, sort keys, and load
+ quadrant. */
+ obj_set_subsection_attributes (seg, space, 0x1f, 73, 0);
+ bfd_set_section_alignment (stdoutput, seg, 2);
+
+ /* Make some space for the first special stab entry and zero the memory.
+ It contains information about the length of this file's
+ stab string and the like. Using it avoids the need to
+ relocate the stab strings.
+
+ The $GDB_STRINGS$ space will be created as a side effect of
+ the call to get_stab_string_offset. */
+ p = frag_more (12);
+ memset (p, 0, 12);
+ as_where (&file, (unsigned int *) NULL);
+ stroff = get_stab_string_offset (file, "$GDB_STRINGS$");
+ know (stroff == 1);
+ md_number_to_chars (p, stroff, 4);
+ seg_info (seg)->stabu.p = p;
+
+ /* Set the containing space for both stab sections to be $GDB_DEBUG$
+ (just created above). Also set some attributes which BFD does
+ not understand. In particular, access bits, sort keys, and load
+ quadrant. */
+ seg = bfd_get_section_by_name (stdoutput, "$GDB_STRINGS$");
+ obj_set_subsection_attributes (seg, space, 0x1f, 72, 0);
+ bfd_set_section_alignment (stdoutput, seg, 2);
+
+ subseg_set (saved_seg, saved_subseg);
+}
+
+/* Fill in the counts in the first entry in a .stabs section. */
+
+static void
+adjust_stab_sections (abfd, sec, xxx)
+ bfd *abfd;
+ asection *sec;
+ PTR xxx;
+{
+ asection *strsec;
+ char *p;
+ int strsz, nsyms;
+
+ if (strcmp ("$GDB_SYMBOLS$", sec->name))
+ return;
+
+ strsec = bfd_get_section_by_name (abfd, "$GDB_STRINGS$");
+ if (strsec)
+ strsz = bfd_section_size (abfd, strsec);
+ else
+ strsz = 0;
+ nsyms = bfd_section_size (abfd, sec) / 12 - 1;
+
+ p = seg_info (sec)->stabu.p;
+ assert (p != 0);
+
+ bfd_h_put_16 (abfd, (bfd_vma) nsyms, (bfd_byte *) p + 6);
+ bfd_h_put_32 (abfd, (bfd_vma) strsz, (bfd_byte *) p + 8);
+}
+
+/* Called late in the asssembly phase to adjust the special
+ stab entry and to set the starting address for each code subspace. */
+
+void
+som_frob_file ()
+{
+ bfd_map_over_sections (stdoutput, adjust_stab_sections, (PTR) 0);
+}
diff --git a/gas/config/obj-som.h b/gas/config/obj-som.h
new file mode 100644
index 0000000000..62087b125f
--- /dev/null
+++ b/gas/config/obj-som.h
@@ -0,0 +1,73 @@
+/* SOM object file format.
+ Copyright (C) 1993, 1994, 1995, 1998 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ Written by the Center for Software Science at the University of Utah
+ and by Cygnus Support. */
+
+#ifndef _OBJ_SOM_H
+#define _OBJ_SOM_H
+
+#define OBJ_SOM 1
+
+#include <bfd.h>
+#include "bfd/som.h"
+#include "targ-cpu.h"
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE !FALSE
+#endif
+
+/* should be conditional on address size! */
+#define som_symbol(asymbol) ((som_symbol_type *)(&(asymbol)->the_bfd))
+
+extern void som_file_symbol PARAMS ((char *));
+extern void obj_som_version PARAMS ((int));
+extern void obj_som_init_stab_section PARAMS ((segT));
+extern void obj_som_copyright PARAMS ((int));
+extern void obj_som_compiler PARAMS ((int));
+
+#define obj_symbol_new_hook(s) {;}
+
+/* SOM has several attributes for spaces/subspaces which can not
+ be easily expressed in BFD. We use these macros to trigger calls
+ into the SOM BFD backend to set these attributes. */
+#define obj_set_section_attributes bfd_som_set_section_attributes
+#define obj_set_subsection_attributes bfd_som_set_subsection_attributes
+
+/* Likewise for symbol types. */
+#define obj_set_symbol_type bfd_som_set_symbol_type
+
+/* Stabs go in a separate sections. GDB expects to find them in sections
+ with the names $GDB_SYMBOLS$ and $GDB_STRINGS$ rather than .stab and
+ .stabstr. */
+#define SEPARATE_STAB_SECTIONS 1
+#define STAB_SECTION_NAME "$GDB_SYMBOLS$"
+#define STAB_STRING_SECTION_NAME "$GDB_STRINGS$"
+
+/* We use INIT_STAB_SECTION to record the space/subspace relationships
+ for the various debugging sections. */
+#define INIT_STAB_SECTION(seg) obj_som_init_stab_section (seg)
+
+/* We'll be updating the magic 1st stab entry once the entire assembly
+ fail has been processed. */
+#define obj_frob_file() som_frob_file()
+
+#endif /* _OBJ_SOM_H */
diff --git a/gas/config/obj-vms.c b/gas/config/obj-vms.c
new file mode 100644
index 0000000000..0f08f8eb3f
--- /dev/null
+++ b/gas/config/obj-vms.c
@@ -0,0 +1,5549 @@
+/* vms.c -- Write out a VAX/VMS object file
+ Copyright (C) 1987, 88, 92, 94, 95, 97, 1998 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GAS 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 more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+/* Written by David L. Kashtan */
+/* Modified by Eric Youngdale to write VMS debug records for program
+ variables */
+
+/* Want all of obj-vms.h (as obj-format.h, via targ-env.h, via as.h). */
+#define WANT_VMS_OBJ_DEFS
+
+#include "as.h"
+#include "config.h"
+#include "subsegs.h"
+#include "obstack.h"
+
+/* What we do if there is a goof. */
+#define error as_fatal
+
+#ifdef VMS /* These are of no use if we are cross assembling. */
+#include <fab.h> /* Define File Access Block */
+#include <nam.h> /* Define NAM Block */
+#include <xab.h> /* Define XAB - all different types*/
+extern int sys$open(), sys$close(), sys$asctim();
+#endif
+
+/*
+ * Version string of the compiler that produced the code we are
+ * assembling. (And this assembler, if we do not have compiler info.)
+ */
+char *compiler_version_string;
+
+extern int flag_hash_long_names; /* -+ */
+extern int flag_one; /* -1; compatibility with gcc 1.x */
+extern int flag_show_after_trunc; /* -H */
+extern int flag_no_hash_mixed_case; /* -h NUM */
+
+/* Flag that determines how we map names. This takes several values, and
+ * is set with the -h switch. A value of zero implies names should be
+ * upper case, and the presence of the -h switch inhibits the case hack.
+ * No -h switch at all sets vms_name_mapping to 0, and allows case hacking.
+ * A value of 2 (set with -h2) implies names should be
+ * all lower case, with no case hack. A value of 3 (set with -h3) implies
+ * that case should be preserved. */
+
+/* If the -+ switch is given, then the hash is appended to any name that is
+ * longer than 31 characters, regardless of the setting of the -h switch.
+ */
+
+char vms_name_mapping = 0;
+
+static symbolS *Entry_Point_Symbol = 0; /* Pointer to "_main" */
+
+/*
+ * We augment the "gas" symbol structure with this
+ */
+struct VMS_Symbol
+{
+ struct VMS_Symbol *Next;
+ symbolS *Symbol;
+ int Size;
+ int Psect_Index;
+ int Psect_Offset;
+};
+
+struct VMS_Symbol *VMS_Symbols = 0;
+struct VMS_Symbol *Ctors_Symbols = 0;
+struct VMS_Symbol *Dtors_Symbols = 0;
+
+/* We need this to keep track of the various input files, so that we can
+ * give the debugger the correct source line.
+ */
+
+struct input_file
+{
+ struct input_file *next;
+ struct input_file *same_file_fpnt;
+ int file_number;
+ int max_line;
+ int min_line;
+ int offset;
+ char flag;
+ char *name;
+ symbolS *spnt;
+};
+
+static struct input_file *file_root = (struct input_file *) NULL;
+
+
+/*
+ * Styles of PSECTS (program sections) that we generate; just shorthand
+ * to avoid lists of section attributes. Used by VMS_Psect_Spec().
+ */
+enum ps_type
+{
+ ps_TEXT, ps_DATA, ps_COMMON, ps_CONST, ps_CTORS, ps_DTORS
+};
+
+/*
+ * This enum is used to keep track of the various types of variables that
+ * may be present.
+ */
+
+enum advanced_type
+{
+ BASIC, POINTER, ARRAY, ENUM, STRUCT, UNION, FUNCTION, VOID, ALIAS, UNKNOWN
+};
+
+/*
+ * This structure contains the information from the stabs directives, and the
+ * information is filled in by VMS_typedef_parse. Everything that is needed
+ * to generate the debugging record for a given symbol is present here.
+ * This could be done more efficiently, using nested struct/unions, but for now
+ * I am happy that it works.
+ */
+struct VMS_DBG_Symbol
+{
+ struct VMS_DBG_Symbol *next;
+ /* description of what this is */
+ enum advanced_type advanced;
+ /* this record is for this type */
+ int dbx_type;
+ /* For advanced types this is the type referred to. I.e., the type
+ a pointer points to, or the type of object that makes up an
+ array. */
+ int type2;
+ /* Use this type when generating a variable def */
+ int VMS_type;
+ /* used for arrays - this will be present for all */
+ int index_min;
+ /* entries, but will be meaningless for non-arrays */
+ int index_max;
+ /* Size in bytes of the data type. For an array, this is the size
+ of one element in the array */
+ int data_size;
+ /* Number of the structure/union/enum - used for ref */
+ int struc_numb;
+};
+
+#define SYMTYPLST_SIZE (1<<4) /* 16; must be power of two */
+#define SYMTYP_HASH(x) ((unsigned)(x) & (SYMTYPLST_SIZE-1))
+struct VMS_DBG_Symbol *VMS_Symbol_type_list[SYMTYPLST_SIZE];
+
+/*
+ * We need this structure to keep track of forward references to
+ * struct/union/enum that have not been defined yet. When they are ultimately
+ * defined, then we can go back and generate the TIR commands to make a back
+ * reference.
+ */
+
+struct forward_ref
+{
+ struct forward_ref *next;
+ int dbx_type;
+ int struc_numb;
+ char resolved;
+};
+
+struct forward_ref *f_ref_root = (struct forward_ref *) NULL;
+
+/*
+ * This routine is used to compare the names of certain types to various
+ * fixed types that are known by the debugger.
+ */
+#define type_check(X) !strcmp (symbol_name, X)
+
+/*
+ * This variable is used to keep track of the name of the symbol we are
+ * working on while we are parsing the stabs directives.
+ */
+static const char *symbol_name;
+
+/* We use this counter to assign numbers to all of the structures, unions
+ * and enums that we define. When we actually declare a variable to the
+ * debugger, we can simply do it by number, rather than describing the
+ * whole thing each time.
+ */
+
+static structure_count = 0;
+
+/* This variable is used to indicate that we are making the last attempt to
+ parse the stabs, and that we should define as much as we can, and ignore
+ the rest */
+
+static int final_pass;
+
+/* This variable is used to keep track of the current structure number
+ * for a given variable. If this is < 0, that means that the structure
+ * has not yet been defined to the debugger. This is still cool, since
+ * the VMS object language has ways of fixing things up after the fact,
+ * so we just make a note of this, and generate fixups at the end.
+ */
+static int struct_number;
+
+/* This is used to distinguish between D_float and G_float for telling
+ the debugger about doubles. gcc outputs the same .stabs regardless
+ of whether -mg is used to select alternate doubles. */
+
+static int vax_g_doubles = 0;
+
+/* Local symbol references (used to handle N_ABS symbols; gcc does not
+ generate those, but they're possible with hand-coded assembler input)
+ are always made relative to some particular environment. If the current
+ input has any such symbols, then we expect this to get incremented
+ exactly once and end up having all of them be in environment #0. */
+
+static int Current_Environment = -1;
+
+/* Every object file must specify an module name, which is also used by
+ traceback records. Set in Write_VMS_MHD_Records(). */
+
+static char Module_Name[255+1];
+
+/*
+ * Variable descriptors are used tell the debugger the data types of certain
+ * more complicated variables (basically anything involving a structure,
+ * union, enum, array or pointer). Some non-pointer variables of the
+ * basic types that the debugger knows about do not require a variable
+ * descriptor.
+ *
+ * Since it is impossible to have a variable descriptor longer than 128
+ * bytes by virtue of the way that the VMS object language is set up,
+ * it makes not sense to make the arrays any longer than this, or worrying
+ * about dynamic sizing of the array.
+ *
+ * These are the arrays and counters that we use to build a variable
+ * descriptor.
+ */
+
+#define MAX_DEBUG_RECORD 128
+static char Local[MAX_DEBUG_RECORD]; /* buffer for variable descriptor */
+static char Asuffix[MAX_DEBUG_RECORD]; /* buffer for array descriptor */
+static int Lpnt; /* index into Local */
+static int Apoint; /* index into Asuffix */
+static char overflow; /* flag to indicate we have written too much*/
+static int total_len; /* used to calculate the total length of variable
+ descriptor plus array descriptor - used for len byte*/
+
+/* Flag if we have told user about finding global constants in the text
+ section. */
+static int gave_compiler_message = 0;
+
+
+/*
+ * Global data (Object records limited to 512 bytes by VAX-11 "C" runtime)
+ */
+static int VMS_Object_File_FD; /* File Descriptor for object file */
+static char Object_Record_Buffer[512]; /* Buffer for object file records */
+static int Object_Record_Offset;/* Offset to end of data */
+static int Current_Object_Record_Type; /* Type of record in above */
+
+/*
+ * Macros for moving data around. Must work on big-endian systems.
+ */
+#ifdef VMS /* These are more efficient for VMS->VMS systems */
+#define COPY_LONG(dest,val) ( *(long *)(dest) = (val) )
+#define COPY_SHORT(dest,val) ( *(short *)(dest) = (val) )
+#else
+#define COPY_LONG(dest,val) md_number_to_chars ((dest), (val), 4)
+#define COPY_SHORT(dest,val) md_number_to_chars ((dest), (val), 2)
+#endif
+/*
+ * Macros for placing data into the object record buffer.
+ */
+#define PUT_LONG(val) \
+ ( COPY_LONG (&Object_Record_Buffer[Object_Record_Offset], (val)), \
+ Object_Record_Offset += 4 )
+
+#define PUT_SHORT(val) \
+ ( COPY_SHORT (&Object_Record_Buffer[Object_Record_Offset], (val)), \
+ Object_Record_Offset += 2 )
+
+#define PUT_CHAR(val) ( Object_Record_Buffer[Object_Record_Offset++] = (val) )
+
+#define PUT_COUNTED_STRING(cp) do { \
+ register const char *p = (cp); \
+ PUT_CHAR ((char) strlen (p)); \
+ while (*p) PUT_CHAR (*p++); } while (0)
+
+/*
+ * Macro for determining if a Name has psect attributes attached
+ * to it.
+ */
+#define PSECT_ATTRIBUTES_STRING "$$PsectAttributes_"
+#define PSECT_ATTRIBUTES_STRING_LENGTH 18
+
+#define HAS_PSECT_ATTRIBUTES(Name) \
+ (strncmp ((*Name == '_' ? Name + 1 : Name), \
+ PSECT_ATTRIBUTES_STRING, \
+ PSECT_ATTRIBUTES_STRING_LENGTH) == 0)
+
+
+ /* in: segT out: N_TYPE bits */
+const short seg_N_TYPE[] =
+{
+ N_ABS,
+ N_TEXT,
+ N_DATA,
+ N_BSS,
+ N_UNDF, /* unknown */
+ N_UNDF, /* error */
+ N_UNDF, /* expression */
+ N_UNDF, /* debug */
+ N_UNDF, /* ntv */
+ N_UNDF, /* ptv */
+ N_REGISTER, /* register */
+};
+
+const segT N_TYPE_seg[N_TYPE + 2] =
+{ /* N_TYPE == 0x1E = 32-2 */
+ SEG_UNKNOWN, /* N_UNDF == 0 */
+ SEG_GOOF,
+ SEG_ABSOLUTE, /* N_ABS == 2 */
+ SEG_GOOF,
+ SEG_TEXT, /* N_TEXT == 4 */
+ SEG_GOOF,
+ SEG_DATA, /* N_DATA == 6 */
+ SEG_GOOF,
+ SEG_BSS, /* N_BSS == 8 */
+ SEG_GOOF,
+ SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
+ SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
+ SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
+ SEG_REGISTER, /* dummy N_REGISTER for regs = 30 */
+ SEG_GOOF,
+};
+
+
+/* Local support routines which return a value. */
+
+static struct input_file *find_file PARAMS ((symbolS *));
+static struct VMS_DBG_Symbol *find_symbol PARAMS ((int));
+static symbolS *Define_Routine PARAMS ((symbolS *,int,symbolS *,int));
+
+static char *cvt_integer PARAMS ((char *,int *));
+static char *fix_name PARAMS ((char *));
+static char *get_struct_name PARAMS ((char *));
+
+static offsetT VMS_Initialized_Data_Size PARAMS ((symbolS *,unsigned));
+
+static int VMS_TBT_Source_File PARAMS ((char *,int));
+static int gen1 PARAMS ((struct VMS_DBG_Symbol *,int));
+static int forward_reference PARAMS ((char *));
+static int final_forward_reference PARAMS ((struct VMS_DBG_Symbol *));
+static int VMS_typedef_parse PARAMS ((char *));
+static int hash_string PARAMS ((const char *));
+static int VMS_Psect_Spec PARAMS ((const char *,int,enum ps_type,
+ struct VMS_Symbol *));
+
+/* Local support routines which don't directly return any value. */
+
+static void s_const PARAMS ((int));
+static void Create_VMS_Object_File PARAMS ((void));
+static void Flush_VMS_Object_Record_Buffer PARAMS ((void));
+static void Set_VMS_Object_File_Record PARAMS ((int));
+static void Close_VMS_Object_File PARAMS ((void));
+static void vms_tir_stack_psect PARAMS ((int,int,int));
+static void VMS_Store_Immediate_Data PARAMS ((const char *,int,int));
+static void VMS_Set_Data PARAMS ((int,int,int,int));
+static void VMS_Store_Struct PARAMS ((int));
+static void VMS_Def_Struct PARAMS ((int));
+static void VMS_Set_Struct PARAMS ((int));
+static void VMS_TBT_Module_Begin PARAMS ((void));
+static void VMS_TBT_Module_End PARAMS ((void));
+static void VMS_TBT_Routine_Begin PARAMS ((symbolS *,int));
+static void VMS_TBT_Routine_End PARAMS ((int,symbolS *));
+static void VMS_TBT_Block_Begin PARAMS ((symbolS *,int,char *));
+static void VMS_TBT_Block_End PARAMS ((valueT));
+static void VMS_TBT_Line_PC_Correlation PARAMS ((int,int,int,int));
+static void VMS_TBT_Source_Lines PARAMS ((int,int,int));
+static void fpush PARAMS ((int,int));
+static void rpush PARAMS ((int,int));
+static void array_suffix PARAMS ((struct VMS_DBG_Symbol *));
+static void new_forward_ref PARAMS ((int));
+static void generate_suffix PARAMS ((struct VMS_DBG_Symbol *,int));
+static void bitfield_suffix PARAMS ((struct VMS_DBG_Symbol *,int));
+static void setup_basic_type PARAMS ((struct VMS_DBG_Symbol *));
+static void VMS_DBG_record PARAMS ((struct VMS_DBG_Symbol *,int,int,char *));
+static void VMS_local_stab_Parse PARAMS ((symbolS *));
+static void VMS_stab_parse PARAMS ((symbolS *,int,int,int,int));
+static void VMS_GSYM_Parse PARAMS ((symbolS *,int));
+static void VMS_LCSYM_Parse PARAMS ((symbolS *,int));
+static void VMS_STSYM_Parse PARAMS ((symbolS *,int));
+static void VMS_RSYM_Parse PARAMS ((symbolS *,symbolS *,int));
+static void VMS_LSYM_Parse PARAMS ((void));
+static void Define_Local_Symbols PARAMS ((symbolS *,symbolS *,symbolS *,int));
+static void Write_VMS_MHD_Records PARAMS ((void));
+static void Write_VMS_EOM_Record PARAMS ((int,valueT));
+static void VMS_Case_Hack_Symbol PARAMS ((const char *,char *));
+static void VMS_Modify_Psect_Attributes PARAMS ((const char *,int *));
+static void VMS_Global_Symbol_Spec PARAMS ((const char *,int,int,int));
+static void VMS_Local_Environment_Setup PARAMS ((const char *));
+static void VMS_Emit_Globalvalues PARAMS ((unsigned,unsigned,char *));
+static void VMS_Procedure_Entry_Pt PARAMS ((char *,int,int,int));
+static void VMS_Set_Psect PARAMS ((int,int,int));
+static void VMS_Store_Repeated_Data PARAMS ((int,char *,int,int));
+static void VMS_Store_PIC_Symbol_Reference PARAMS ((symbolS *,int,
+ int,int,int,int));
+static void VMS_Fix_Indirect_Reference PARAMS ((int,int,fragS *,fragS *));
+
+/* Support code which used to be inline within vms_write_object_file. */
+static void vms_fixup_text_section PARAMS ((unsigned,struct frag *,struct frag *));
+static void synthesize_data_segment PARAMS ((unsigned,unsigned,struct frag *));
+static void vms_fixup_data_section PARAMS ((unsigned,unsigned));
+static void global_symbol_directory PARAMS ((unsigned,unsigned));
+static void local_symbols_DST PARAMS ((symbolS *,symbolS *));
+static void vms_build_DST PARAMS ((unsigned));
+static void vms_fixup_xtors_section PARAMS ((struct VMS_Symbol *, int));
+
+
+/* The following code defines the special types of pseudo-ops that we
+ use with VMS. */
+
+unsigned char const_flag = IN_DEFAULT_SECTION;
+
+static void
+s_const (arg)
+ int arg; /* 3rd field from obj_pseudo_table[]; not needed here */
+{
+ /* Since we don't need `arg', use it as our scratch variable so that
+ we won't get any "not used" warnings about it. */
+ arg = get_absolute_expression ();
+ subseg_set (SEG_DATA, (subsegT) arg);
+ const_flag = 1;
+ demand_empty_rest_of_line ();
+}
+
+const pseudo_typeS obj_pseudo_table[] =
+{
+ {"const", s_const, 0},
+ {0, 0, 0},
+}; /* obj_pseudo_table */
+
+
+/* Routine to perform RESOLVE_SYMBOL_REDEFINITION(). */
+
+int
+vms_resolve_symbol_redef (sym)
+ symbolS *sym;
+{
+ /*
+ * If the new symbol is .comm AND it has a size of zero,
+ * we ignore it (i.e. the old symbol overrides it)
+ */
+ if (SEGMENT_TO_SYMBOL_TYPE ((int) now_seg) == (N_UNDF | N_EXT)
+ && frag_now_fix () == 0)
+ {
+ as_warn (_("compiler emitted zero-size common symbol `%s' already defined"),
+ S_GET_NAME (sym));
+ return 1;
+ }
+ /*
+ * If the old symbol is .comm and it has a size of zero,
+ * we override it with the new symbol value.
+ */
+ if (S_IS_EXTERNAL (sym) && S_IS_DEFINED (sym) && S_GET_VALUE (sym) == 0)
+ {
+ as_warn (_("compiler redefined zero-size common symbol `%s'"),
+ S_GET_NAME (sym));
+ sym->sy_frag = frag_now;
+ S_SET_OTHER (sym, const_flag);
+ S_SET_VALUE (sym, frag_now_fix ());
+ /* Keep N_EXT bit. */
+ sym->sy_symbol.n_type |= SEGMENT_TO_SYMBOL_TYPE ((int) now_seg);
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* `tc_frob_label' handler for colon(symbols.c), used to examine the
+ dummy label(s) gcc inserts at the beginning of each file it generates.
+ gcc 1.x put "gcc_compiled."; gcc 2.x (as of 2.7) puts "gcc2_compiled."
+ and "__gnu_language_<name>" and possibly "__vax_<type>_doubles". */
+
+void
+vms_check_for_special_label (symbolP)
+symbolS *symbolP;
+{
+ /* Special labels only occur prior to explicit section directives. */
+ if ((const_flag & IN_DEFAULT_SECTION) != 0)
+ {
+ char *sym_name = S_GET_NAME (symbolP);
+
+ if (*sym_name == '_')
+ ++sym_name;
+
+ if (!strcmp (sym_name, "__vax_g_doubles"))
+ vax_g_doubles = 1;
+#if 0 /* not necessary */
+ else if (!strcmp (sym_name, "__vax_d_doubles"))
+ vax_g_doubles = 0;
+#endif
+#if 0 /* these are potential alternatives to tc-vax.c's md_parse_options() */
+ else if (!strcmp (sym_name, "gcc_compiled."))
+ flag_one = 1;
+ else if (!strcmp (sym_name, "__gnu_language_cplusplus"))
+ flag_hash_long_names = 1;
+#endif
+ }
+ return;
+}
+
+
+void
+obj_read_begin_hook ()
+{
+ return;
+}
+
+
+void
+obj_crawl_symbol_chain (headers)
+ object_headers *headers;
+{
+ symbolS *symbolP;
+ symbolS **symbolPP;
+ int symbol_number = 0;
+
+ symbolPP = &symbol_rootP; /* -> last symbol chain link. */
+ while ((symbolP = *symbolPP) != NULL)
+ {
+ resolve_symbol_value (symbolP, 1);
+
+ /* OK, here is how we decide which symbols go out into the
+ brave new symtab. Symbols that do are:
+
+ * symbols with no name (stabd's?)
+ * symbols with debug info in their N_TYPE
+ * symbols with \1 as their 3rd character (numeric labels)
+ * "local labels" needed for PIC fixups
+
+ Symbols that don't are:
+ * symbols that are registers
+
+ All other symbols are output. We complain if a deleted
+ symbol was marked external. */
+
+ if (!S_IS_REGISTER (symbolP))
+ {
+ symbolP->sy_number = symbol_number++;
+ symbolP->sy_name_offset = 0;
+ symbolPP = &(symbol_next (symbolP));
+ }
+ else
+ {
+ if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP))
+ {
+ as_bad (_("Local symbol %s never defined"), S_GET_NAME (symbolP));
+ } /* oops. */
+
+ /* Unhook it from the chain. */
+ *symbolPP = symbol_next (symbolP);
+ } /* if this symbol should be in the output */
+
+ } /* for each symbol */
+
+ H_SET_STRING_SIZE (headers, string_byte_count);
+ H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number);
+} /* obj_crawl_symbol_chain() */
+
+
+ /****** VMS OBJECT FILE HACKING ROUTINES *******/
+
+
+/* Create the VMS object file. */
+
+static void
+Create_VMS_Object_File ()
+{
+#if defined(eunice) || !defined(VMS)
+ VMS_Object_File_FD = creat (out_file_name, 0777, "var");
+#else /* eunice */
+ VMS_Object_File_FD = creat (out_file_name, 0, "rfm=var",
+ "ctx=bin", "mbc=16", "deq=64", "fop=tef",
+ "shr=nil");
+#endif /* eunice */
+ /* Deal with errors. */
+ if (VMS_Object_File_FD < 0)
+ as_fatal (_("Couldn't create VMS object file \"%s\""), out_file_name);
+ /* Initialize object file hacking variables. */
+ Object_Record_Offset = 0;
+ Current_Object_Record_Type = -1;
+}
+
+
+/* Flush the object record buffer to the object file. */
+
+static void
+Flush_VMS_Object_Record_Buffer ()
+{
+ /* If the buffer is empty, there's nothing to do. */
+ if (Object_Record_Offset == 0)
+ return;
+
+#ifndef VMS /* For cross-assembly purposes. */
+ {
+ char RecLen[2];
+
+ /* "Variable-length record" files have a two byte length field
+ prepended to each record. It's normally out-of-band, and native
+ VMS output will insert it automatically for this type of file.
+ When cross-assembling, we must write it explicitly. */
+ md_number_to_chars (RecLen, Object_Record_Offset, 2);
+ if (write (VMS_Object_File_FD, RecLen, 2) != 2)
+ error (_("I/O error writing VMS object file (length prefix)"));
+ /* We also need to force the actual record to be an even number of
+ bytes. For native output, that's automatic; when cross-assembling,
+ pad with a NUL byte if length is odd. Do so _after_ writing the
+ pre-padded length. Since our buffer is defined with even size,
+ an odd offset implies that it has some room left. */
+ if ((Object_Record_Offset & 1) != 0)
+ Object_Record_Buffer[Object_Record_Offset++] = '\0';
+ }
+#endif /* not VMS */
+
+ /* Write the data to the file. */
+ if (write (VMS_Object_File_FD, Object_Record_Buffer, Object_Record_Offset)
+ != Object_Record_Offset)
+ error (_("I/O error writing VMS object file"));
+
+ /* The buffer is now empty. */
+ Object_Record_Offset = 0;
+}
+
+
+/* Declare a particular type of object file record. */
+
+static void
+Set_VMS_Object_File_Record (Type)
+ int Type;
+{
+ /* If the type matches, we are done. */
+ if (Type == Current_Object_Record_Type)
+ return;
+ /* Otherwise: flush the buffer. */
+ Flush_VMS_Object_Record_Buffer ();
+ /* Remember the new type. */
+ Current_Object_Record_Type = Type;
+}
+
+
+/* Close the VMS Object file. */
+
+static void
+Close_VMS_Object_File ()
+{
+ /* Flush (should never be necessary) and reset saved record-type context. */
+ Set_VMS_Object_File_Record (-1);
+
+#ifndef VMS /* For cross-assembly purposes. */
+ {
+ char RecLen[2];
+ int minus_one = -1;
+
+ /* Write a 2 byte record-length field of -1 into the file, which
+ means end-of-block when read, hence end-of-file when occurring
+ in the file's last block. It is only needed for variable-length
+ record files transferred to VMS as fixed-length record files
+ (typical for binary FTP; NFS shouldn't need it, but it won't hurt). */
+ md_number_to_chars (RecLen, minus_one, 2);
+ write (VMS_Object_File_FD, RecLen, 2);
+ }
+#else
+ /* When written on a VMS system, the file header (cf inode) will record
+ the actual end-of-file position and no inline marker is needed. */
+#endif
+
+ close (VMS_Object_File_FD);
+}
+
+
+ /****** Text Information and Relocation routines ******/
+
+
+/* Stack Psect base followed by signed, varying-sized offset.
+ Common to several object records. */
+
+static void
+vms_tir_stack_psect (Psect_Index, Offset, Force)
+ int Psect_Index;
+ int Offset;
+ int Force;
+{
+ int psect_width, offset_width;
+
+ psect_width = ((unsigned) Psect_Index > 255) ? 2 : 1;
+ offset_width = (Force || Offset > 32767 || Offset < -32768) ? 4
+ : (Offset > 127 || Offset < -128) ? 2 : 1;
+#define Sta_P(p,o) (((o)<<1) | ((p)-1))
+ /* byte or word psect; byte, word, or longword offset */
+ switch (Sta_P(psect_width,offset_width))
+ {
+ case Sta_P(1,1): PUT_CHAR (TIR_S_C_STA_PB);
+ PUT_CHAR ((char)(unsigned char) Psect_Index);
+ PUT_CHAR ((char) Offset);
+ break;
+ case Sta_P(1,2): PUT_CHAR (TIR_S_C_STA_PW);
+ PUT_CHAR ((char)(unsigned char) Psect_Index);
+ PUT_SHORT (Offset);
+ break;
+ case Sta_P(1,4): PUT_CHAR (TIR_S_C_STA_PL);
+ PUT_CHAR ((char)(unsigned char) Psect_Index);
+ PUT_LONG (Offset);
+ break;
+ case Sta_P(2,1): PUT_CHAR (TIR_S_C_STA_WPB);
+ PUT_SHORT (Psect_Index);
+ PUT_CHAR ((char) Offset);
+ break;
+ case Sta_P(2,2): PUT_CHAR (TIR_S_C_STA_WPW);
+ PUT_SHORT (Psect_Index);
+ PUT_SHORT (Offset);
+ break;
+ case Sta_P(2,4): PUT_CHAR (TIR_S_C_STA_WPL);
+ PUT_SHORT (Psect_Index);
+ PUT_LONG (Offset);
+ break;
+ }
+#undef Sta_P
+}
+
+
+/* Store immediate data in current Psect. */
+
+static void
+VMS_Store_Immediate_Data (Pointer, Size, Record_Type)
+ const char *Pointer;
+ int Size;
+ int Record_Type;
+{
+ register int i;
+
+ Set_VMS_Object_File_Record (Record_Type);
+ /* We can only store as most 128 bytes at a time due to the way that
+ TIR commands are encoded. */
+ while (Size > 0)
+ {
+ i = (Size > 128) ? 128 : Size;
+ Size -= i;
+ /* If we cannot accommodate this record, flush the buffer. */
+ if ((Object_Record_Offset + i + 1) >= sizeof Object_Record_Buffer)
+ Flush_VMS_Object_Record_Buffer ();
+ /* If the buffer is empty we must insert record type. */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (Record_Type);
+ /* Store the count. The Store Immediate TIR command is implied by
+ a negative command byte, and the length of the immediate data
+ is abs(command_byte). So, we write the negated length value. */
+ PUT_CHAR ((char) (-i & 0xff));
+ /* Now store the data. */
+ while (--i >= 0)
+ PUT_CHAR (*Pointer++);
+ }
+ /* Flush the buffer if it is more than 75% full. */
+ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
+ Flush_VMS_Object_Record_Buffer ();
+}
+
+
+/* Make a data reference. */
+
+static void
+VMS_Set_Data (Psect_Index, Offset, Record_Type, Force)
+ int Psect_Index;
+ int Offset;
+ int Record_Type;
+ int Force;
+{
+ Set_VMS_Object_File_Record (Record_Type);
+ /* If the buffer is empty we must insert the record type. */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (Record_Type);
+ /* Stack the Psect base with its offset. */
+ vms_tir_stack_psect (Psect_Index, Offset, Force);
+ /* Set relocation base. */
+ PUT_CHAR (TIR_S_C_STO_PIDR);
+ /* Flush the buffer if it is more than 75% full. */
+ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
+ Flush_VMS_Object_Record_Buffer ();
+}
+
+
+/* Make a debugger reference to a struct, union or enum. */
+
+static void
+VMS_Store_Struct (Struct_Index)
+ int Struct_Index;
+{
+ /* We are writing a debug record. */
+ Set_VMS_Object_File_Record (OBJ_S_C_DBG);
+ /* If the buffer is empty we must insert the record type. */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (OBJ_S_C_DBG);
+ PUT_CHAR (TIR_S_C_STA_UW);
+ PUT_SHORT (Struct_Index);
+ PUT_CHAR (TIR_S_C_CTL_STKDL);
+ PUT_CHAR (TIR_S_C_STO_L);
+ /* Flush the buffer if it is more than 75% full. */
+ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
+ Flush_VMS_Object_Record_Buffer ();
+}
+
+
+/* Make a debugger reference to partially define a struct, union or enum. */
+
+static void
+VMS_Def_Struct (Struct_Index)
+ int Struct_Index;
+{
+ /* We are writing a debug record. */
+ Set_VMS_Object_File_Record (OBJ_S_C_DBG);
+ /* If the buffer is empty we must insert the record type. */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (OBJ_S_C_DBG);
+ PUT_CHAR (TIR_S_C_STA_UW);
+ PUT_SHORT (Struct_Index);
+ PUT_CHAR (TIR_S_C_CTL_DFLOC);
+ /* Flush the buffer if it is more than 75% full. */
+ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
+ Flush_VMS_Object_Record_Buffer ();
+}
+
+static void
+VMS_Set_Struct (Struct_Index)
+ int Struct_Index;
+{ /* see previous functions for comments */
+ Set_VMS_Object_File_Record (OBJ_S_C_DBG);
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (OBJ_S_C_DBG);
+ PUT_CHAR (TIR_S_C_STA_UW);
+ PUT_SHORT (Struct_Index);
+ PUT_CHAR (TIR_S_C_CTL_STLOC);
+ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
+ Flush_VMS_Object_Record_Buffer ();
+}
+
+
+ /****** Traceback Information routines ******/
+
+
+/* Write the Traceback Module Begin record. */
+
+static void
+VMS_TBT_Module_Begin ()
+{
+ register char *cp, *cp1;
+ int Size;
+ char Local[256];
+
+ /* Arrange to store the data locally (leave room for size byte). */
+ cp = &Local[1];
+ /* Begin module. */
+ *cp++ = DST_S_C_MODBEG;
+ *cp++ = 0; /* flags; not used */
+ /*
+ * Language type == "C"
+ *
+ * (FIXME: this should be based on the input...)
+ */
+ COPY_LONG (cp, DST_S_C_C);
+ cp += 4;
+ /* Store the module name. */
+ *cp++ = (char) strlen (Module_Name);
+ cp1 = Module_Name;
+ while (*cp1)
+ *cp++ = *cp1++;
+ /* Now we can store the record size. */
+ Size = (cp - Local);
+ Local[0] = Size - 1;
+ /* Put it into the object record. */
+ VMS_Store_Immediate_Data (Local, Size, OBJ_S_C_TBT);
+}
+
+
+/* Write the Traceback Module End record. */
+
+static void
+VMS_TBT_Module_End ()
+{
+ char Local[2];
+
+ /* End module. */
+ Local[0] = 1;
+ Local[1] = DST_S_C_MODEND;
+ /* Put it into the object record. */
+ VMS_Store_Immediate_Data (Local, 2, OBJ_S_C_TBT);
+}
+
+
+/* Write a Traceback Routine Begin record. */
+
+static void
+VMS_TBT_Routine_Begin (symbolP, Psect)
+ symbolS *symbolP;
+ int Psect;
+{
+ register char *cp, *cp1;
+ char *Name;
+ int Offset;
+ int Size;
+ char Local[512];
+
+ /* Strip the leading "_" from the name. */
+ Name = S_GET_NAME (symbolP);
+ if (*Name == '_')
+ Name++;
+ /* Get the text psect offset. */
+ Offset = S_GET_VALUE (symbolP);
+ /* Set the record size. */
+ Size = 1 + 1 + 4 + 1 + strlen (Name);
+ Local[0] = Size;
+ /* DST type "routine begin". */
+ Local[1] = DST_S_C_RTNBEG;
+ /* Uses CallS/CallG. */
+ Local[2] = 0;
+ /* Store the data so far. */
+ VMS_Store_Immediate_Data (Local, 3, OBJ_S_C_TBT);
+ /* Make sure we are still generating a OBJ_S_C_TBT record. */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (OBJ_S_C_TBT);
+ /* Stack the address. */
+ vms_tir_stack_psect (Psect, Offset, 0);
+ /* Store the data reference. */
+ PUT_CHAR (TIR_S_C_STO_PIDR);
+ /* Store the counted string as data. */
+ cp = Local;
+ cp1 = Name;
+ Size = strlen (cp1) + 1;
+ *cp++ = Size - 1;
+ while (*cp1)
+ *cp++ = *cp1++;
+ VMS_Store_Immediate_Data (Local, Size, OBJ_S_C_TBT);
+}
+
+
+/* Write a Traceback Routine End record.
+
+ We *must* search the symbol table to find the next routine, since the
+ assember has a way of reassembling the symbol table OUT OF ORDER Thus
+ the next routine in the symbol list is not necessarily the next one in
+ memory. For debugging to work correctly we must know the size of the
+ routine. */
+
+static void
+VMS_TBT_Routine_End (Max_Size, sp)
+ int Max_Size;
+ symbolS *sp;
+{
+ symbolS *symbolP;
+ int Size = 0x7fffffff;
+ char Local[16];
+ valueT sym_value, sp_value = S_GET_VALUE (sp);
+
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
+ {
+ if (!S_IS_DEBUG (symbolP) && S_GET_TYPE (symbolP) == N_TEXT)
+ {
+ if (*S_GET_NAME (symbolP) == 'L')
+ continue;
+ sym_value = S_GET_VALUE (symbolP);
+ if (sym_value > sp_value && sym_value < Size)
+ Size = sym_value;
+
+ /*
+ * Dummy labels like "gcc_compiled." should no longer reach here.
+ */
+#if 0
+ else
+ /* check if gcc_compiled. has size of zero */
+ if (sym_value == sp_value &&
+ sp != symbolP &&
+ (!strcmp (S_GET_NAME (sp), "gcc_compiled.") ||
+ !strcmp (S_GET_NAME (sp), "gcc2_compiled.")))
+ Size = sym_value;
+#endif
+ }
+ }
+ if (Size == 0x7fffffff)
+ Size = Max_Size;
+ Size -= sp_value; /* and get the size of the routine */
+ /* Record Size. */
+ Local[0] = 6;
+ /* DST type is "routine end". */
+ Local[1] = DST_S_C_RTNEND;
+ Local[2] = 0; /* unused */
+ /* Size of routine. */
+ COPY_LONG (&Local[3], Size);
+ /* Store the record. */
+ VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_TBT);
+}
+
+
+/* Write a Traceback Block Begin record. */
+
+static void
+VMS_TBT_Block_Begin (symbolP, Psect, Name)
+ symbolS *symbolP;
+ int Psect;
+ char *Name;
+{
+ register char *cp, *cp1;
+ int Offset;
+ int Size;
+ char Local[512];
+
+ /* Set the record size. */
+ Size = 1 + 1 + 4 + 1 + strlen (Name);
+ Local[0] = Size;
+ /* DST type is "begin block"; we simulate with a phony routine. */
+ Local[1] = DST_S_C_BLKBEG;
+ /* Uses CallS/CallG. */
+ Local[2] = 0;
+ /* Store the data so far. */
+ VMS_Store_Immediate_Data (Local, 3, OBJ_S_C_DBG);
+ /* Make sure we are still generating a debug record. */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (OBJ_S_C_DBG);
+ /* Now get the symbol address. */
+ PUT_CHAR (TIR_S_C_STA_WPL);
+ PUT_SHORT (Psect);
+ /* Get the text psect offset. */
+ Offset = S_GET_VALUE (symbolP);
+ PUT_LONG (Offset);
+ /* Store the data reference. */
+ PUT_CHAR (TIR_S_C_STO_PIDR);
+ /* Store the counted string as data. */
+ cp = Local;
+ cp1 = Name;
+ Size = strlen (cp1) + 1;
+ *cp++ = Size - 1;
+ while (*cp1)
+ *cp++ = *cp1++;
+ VMS_Store_Immediate_Data (Local, Size, OBJ_S_C_DBG);
+}
+
+
+/* Write a Traceback Block End record. */
+
+static void
+VMS_TBT_Block_End (Size)
+ valueT Size;
+{
+ char Local[16];
+
+ Local[0] = 6; /* record length */
+ /* DST type is "block end"; simulate with a phony end routine. */
+ Local[1] = DST_S_C_BLKEND;
+ Local[2] = 0; /* unused, must be zero */
+ COPY_LONG (&Local[3], Size);
+ VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_DBG);
+}
+
+
+/* Write a Line number <-> Program Counter correlation record. */
+
+static void
+VMS_TBT_Line_PC_Correlation (Line_Number, Offset, Psect, Do_Delta)
+ int Line_Number;
+ int Offset;
+ int Psect;
+ int Do_Delta;
+{
+ register char *cp;
+ char Local[64];
+
+ if (Do_Delta == 0)
+ {
+ /*
+ * If not delta, set our PC/Line number correlation.
+ */
+ cp = &Local[1]; /* Put size in Local[0] later. */
+ /* DST type is "Line Number/PC correlation". */
+ *cp++ = DST_S_C_LINE_NUM;
+ /* Set Line number. */
+ if (Line_Number - 1 <= 255)
+ {
+ *cp++ = DST_S_C_SET_LINUM_B;
+ *cp++ = (char) (Line_Number - 1);
+ }
+ else if (Line_Number - 1 <= 65535)
+ {
+ *cp++ = DST_S_C_SET_LINE_NUM;
+ COPY_SHORT (cp, Line_Number - 1), cp += 2;
+ }
+ else
+ {
+ *cp++ = DST_S_C_SET_LINUM_L;
+ COPY_LONG (cp, Line_Number - 1), cp += 4;
+ }
+ /* Set PC. */
+ *cp++ = DST_S_C_SET_ABS_PC;
+ /* Store size now that we know it, then output the data. */
+ Local[0] = cp - &Local[1];
+ /* Account for the space that TIR_S_C_STO_PIDR will use for the PC. */
+ Local[0] += 4; /* size includes length of another longword */
+ VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT);
+ /* Make sure we are still generating a OBJ_S_C_TBT record. */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (OBJ_S_C_TBT);
+ vms_tir_stack_psect (Psect, Offset, 0);
+ PUT_CHAR (TIR_S_C_STO_PIDR);
+ /* Do a PC offset of 0 to register the line number. */
+ Local[0] = 2;
+ Local[1] = DST_S_C_LINE_NUM;
+ Local[2] = 0; /* Increment PC by 0 and register line # */
+ VMS_Store_Immediate_Data (Local, 3, OBJ_S_C_TBT);
+ }
+ else
+ {
+ if (Do_Delta < 0)
+ {
+ /*
+ * When delta is negative, terminate the line numbers.
+ */
+ Local[0] = 1 + 1 + 4;
+ Local[1] = DST_S_C_LINE_NUM;
+ Local[2] = DST_S_C_TERM_L;
+ COPY_LONG (&Local[3], Offset);
+ VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_TBT);
+ return;
+ }
+ /*
+ * Do a PC/Line delta.
+ */
+ cp = &Local[1];
+ *cp++ = DST_S_C_LINE_NUM;
+ if (Line_Number > 1)
+ {
+ /* We need to increment the line number. */
+ if (Line_Number - 1 <= 255)
+ {
+ *cp++ = DST_S_C_INCR_LINUM;
+ *cp++ = Line_Number - 1;
+ }
+ else if (Line_Number - 1 <= 65535)
+ {
+ *cp++ = DST_S_C_INCR_LINUM_W;
+ COPY_SHORT (cp, Line_Number - 1), cp += 2;
+ }
+ else
+ {
+ *cp++ = DST_S_C_INCR_LINUM_L;
+ COPY_LONG (cp, Line_Number - 1), cp += 4;
+ }
+ }
+ /*
+ * Increment the PC
+ */
+ if (Offset <= 128)
+ {
+ /* Small offsets are encoded as negative numbers, rather than the
+ usual non-negative type code followed by another data field. */
+ *cp++ = (char) -Offset;
+ }
+ else if (Offset <= 65535)
+ {
+ *cp++ = DST_S_C_DELTA_PC_W;
+ COPY_SHORT (cp, Offset), cp += 2;
+ }
+ else
+ {
+ *cp++ = DST_S_C_DELTA_PC_L;
+ COPY_LONG (cp, Offset), cp += 4;
+ }
+ /* Set size now that be know it, then output the data. */
+ Local[0] = cp - &Local[1];
+ VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT);
+ }
+}
+
+
+/* Describe a source file to the debugger. */
+
+static int
+VMS_TBT_Source_File (Filename, ID_Number)
+ char *Filename;
+ int ID_Number;
+{
+ register char *cp;
+ int len, rfo, ffb, ebk;
+ char cdt[8];
+ char Local[512];
+#ifdef VMS /* Used for native assembly */
+ unsigned Status;
+ struct FAB fab; /* RMS file access block */
+ struct NAM nam; /* file name information */
+ struct XABDAT xabdat; /* date+time fields */
+ struct XABFHC xabfhc; /* file header characteristics */
+ char resultant_string_buffer[255 + 1];
+
+ /*
+ * Set up RMS structures:
+ */
+ /* FAB -- file access block */
+ memset ((char *) &fab, 0, sizeof fab);
+ fab.fab$b_bid = FAB$C_BID;
+ fab.fab$b_bln = (unsigned char) sizeof fab;
+ fab.fab$l_fna = Filename;
+ fab.fab$b_fns = (unsigned char) strlen (Filename);
+ fab.fab$l_nam = (char *) &nam;
+ fab.fab$l_xab = (char *) &xabdat;
+ /* NAM -- file name block */
+ memset ((char *) &nam, 0, sizeof nam);
+ nam.nam$b_bid = NAM$C_BID;
+ nam.nam$b_bln = (unsigned char) sizeof nam;
+ nam.nam$l_rsa = resultant_string_buffer;
+ nam.nam$b_rss = (unsigned char) (sizeof resultant_string_buffer - 1);
+ /* XABs -- extended attributes blocks */
+ memset ((char *) &xabdat, 0, sizeof xabdat);
+ xabdat.xab$b_cod = XAB$C_DAT;
+ xabdat.xab$b_bln = (unsigned char) sizeof xabdat;
+ xabdat.xab$l_nxt = (char *) &xabfhc;
+ memset ((char *) &xabfhc, 0, sizeof xabfhc);
+ xabfhc.xab$b_cod = XAB$C_FHC;
+ xabfhc.xab$b_bln = (unsigned char) sizeof xabfhc;
+ xabfhc.xab$l_nxt = 0;
+ /*
+ * Get the file information
+ */
+ Status = sys$open (&fab);
+ if (!(Status & 1))
+ {
+ as_tsktsk (_("Couldn't find source file \"%s\", status=%%X%x"),
+ Filename, Status);
+ return 0;
+ }
+ sys$close (&fab);
+ /* Now extract fields of interest. */
+ memcpy (cdt, (char *) &xabdat.xab$q_cdt, 8); /* creation date */
+ ebk = xabfhc.xab$l_ebk; /* end-of-file block */
+ ffb = xabfhc.xab$w_ffb; /* first free byte of last block */
+ rfo = xabfhc.xab$b_rfo; /* record format */
+ len = nam.nam$b_rsl; /* length of Filename */
+ resultant_string_buffer[len] = '\0';
+ Filename = resultant_string_buffer; /* full filename */
+#else /* Cross-assembly */
+ /* [Perhaps we ought to use actual values derived from stat() here?] */
+ memset (cdt, 0, 8); /* null VMS quadword binary time */
+ ebk = ffb = rfo = 0;
+ len = strlen (Filename);
+ if (len > 255) /* a single byte is used as count prefix */
+ {
+ Filename += (len - 255); /* tail end is more significant */
+ len = 255;
+ }
+#endif /* VMS */
+
+ cp = &Local[1]; /* fill in record length later */
+ *cp++ = DST_S_C_SOURCE; /* DST type is "source file" */
+ *cp++ = DST_S_C_SRC_FORMFEED; /* formfeeds count as source records */
+ *cp++ = DST_S_C_SRC_DECLFILE; /* declare source file */
+ know (cp == &Local[4]);
+ *cp++ = 0; /* fill in this length below */
+ *cp++ = 0; /* flags; must be zero */
+ COPY_SHORT (cp, ID_Number), cp += 2; /* file ID number */
+ memcpy (cp, cdt, 8), cp += 8; /* creation date+time */
+ COPY_LONG (cp, ebk), cp += 4; /* end-of-file block */
+ COPY_SHORT (cp, ffb), cp += 2; /* first free byte of last block */
+ *cp++ = (char) rfo; /* RMS record format */
+ /* Filename. */
+ *cp++ = (char) len;
+ while (--len >= 0)
+ *cp++ = *Filename++;
+ /* Library module name (none). */
+ *cp++ = 0;
+ /* Now that size is known, fill it in and write out the record. */
+ Local[4] = cp - &Local[5]; /* source file declaration size */
+ Local[0] = cp - &Local[1]; /* TBT record size */
+ VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT);
+ return 1;
+}
+
+
+/* Traceback information is described in terms of lines from compiler
+ listing files, not lines from source files. We need to set up the
+ correlation between listing line numbers and source line numbers.
+ Since gcc's .stabn directives refer to the source lines, we just
+ need to describe a one-to-one correspondence. */
+
+static void
+VMS_TBT_Source_Lines (ID_Number, Starting_Line_Number, Number_Of_Lines)
+ int ID_Number;
+ int Starting_Line_Number;
+ int Number_Of_Lines;
+{
+ char *cp;
+ int chunk_limit;
+ char Local[128]; /* room enough to describe 1310700 lines... */
+
+ cp = &Local[1]; /* Put size in Local[0] later. */
+ *cp++ = DST_S_C_SOURCE; /* DST type is "source file". */
+ *cp++ = DST_S_C_SRC_SETFILE; /* Set Source File. */
+ COPY_SHORT (cp, ID_Number), cp += 2; /* File ID Number. */
+ /* Set record number and define lines. Since no longword form of
+ SRC_DEFLINES is available, we need to be able to cope with any huge
+ files a chunk at a time. It doesn't matter for tracebacks, since
+ unspecified lines are mapped one-to-one and work out right, but it
+ does matter within the debugger. Without this explicit mapping,
+ it will complain about lines not existing in the module. */
+ chunk_limit = (sizeof Local - 5) / 6;
+ if (Number_Of_Lines > 65535 * chunk_limit) /* avoid buffer overflow */
+ Number_Of_Lines = 65535 * chunk_limit;
+ while (Number_Of_Lines > 65535)
+ {
+ *cp++ = DST_S_C_SRC_SETREC_L;
+ COPY_LONG (cp, Starting_Line_Number), cp += 4;
+ *cp++ = DST_S_C_SRC_DEFLINES_W;
+ COPY_SHORT (cp, 65535), cp += 2;
+ Starting_Line_Number += 65535;
+ Number_Of_Lines -= 65535;
+ }
+ /* Set record number and define lines, normal case. */
+ if (Starting_Line_Number <= 65535)
+ {
+ *cp++ = DST_S_C_SRC_SETREC_W;
+ COPY_SHORT (cp, Starting_Line_Number), cp += 2;
+ }
+ else
+ {
+ *cp++ = DST_S_C_SRC_SETREC_L;
+ COPY_LONG (cp, Starting_Line_Number), cp += 4;
+ }
+ *cp++ = DST_S_C_SRC_DEFLINES_W;
+ COPY_SHORT (cp, Number_Of_Lines), cp += 2;
+ /* Set size now that be know it, then output the data. */
+ Local[0] = cp - &Local[1];
+ VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT);
+}
+
+
+ /****** Debugger Information support routines ******/
+
+
+/* This routine locates a file in the list of files. If an entry does
+ not exist, one is created. For include files, a new entry is always
+ created such that inline functions can be properly debugged. */
+
+static struct input_file *
+find_file (sp)
+ symbolS *sp;
+{
+ struct input_file *same_file = 0;
+ struct input_file *fpnt, *last = 0;
+ char *sp_name;
+
+ for (fpnt = file_root; fpnt; fpnt = fpnt->next)
+ {
+ if (fpnt->spnt == sp)
+ return fpnt;
+ last = fpnt;
+ }
+ sp_name = S_GET_NAME (sp);
+ for (fpnt = file_root; fpnt; fpnt = fpnt->next)
+ {
+ if (strcmp (sp_name, fpnt->name) == 0)
+ {
+ if (fpnt->flag == 1)
+ return fpnt;
+ same_file = fpnt;
+ break;
+ }
+ }
+ fpnt = (struct input_file *) xmalloc (sizeof (struct input_file));
+ if (!file_root)
+ file_root = fpnt;
+ else
+ last->next = fpnt;
+ fpnt->next = 0;
+ fpnt->name = sp_name;
+ fpnt->min_line = 0x7fffffff;
+ fpnt->max_line = 0;
+ fpnt->offset = 0;
+ fpnt->flag = 0;
+ fpnt->file_number = 0;
+ fpnt->spnt = sp;
+ fpnt->same_file_fpnt = same_file;
+ return fpnt;
+}
+
+
+/* This routine converts a number string into an integer, and stops when
+ it sees an invalid character. The return value is the address of the
+ character just past the last character read. No error is generated. */
+
+static char *
+cvt_integer (str, rtn)
+ char *str;
+ int *rtn;
+{
+ int ival = 0, sgn = 1;
+
+ if (*str == '-')
+ sgn = -1, ++str;
+ while (*str >= '0' && *str <= '9')
+ ival = 10 * ival + *str++ - '0';
+ *rtn = sgn * ival;
+ return str;
+}
+
+
+/*
+ * The following functions and definitions are used to generate object
+ * records that will describe program variables to the VMS debugger.
+ *
+ * This file contains many of the routines needed to output debugging info
+ * into the object file that the VMS debugger needs to understand symbols.
+ * These routines are called very late in the assembly process, and thus
+ * we can be fairly lax about changing things, since the GSD and the TIR
+ * sections have already been output.
+ */
+
+
+/* This routine fixes the names that are generated by C++, ".this" is a good
+ example. The period does not work for the debugger, since it looks like
+ the syntax for a structure element, and thus it gets mightily confused.
+
+ We also use this to strip the PsectAttribute hack from the name before we
+ write a debugger record. */
+
+static char *
+fix_name (pnt)
+ char *pnt;
+{
+ char *pnt1;
+
+ /* Kill any leading "_". */
+ if (*pnt == '_')
+ pnt++;
+
+ /* Is there a Psect Attribute to skip?? */
+ if (HAS_PSECT_ATTRIBUTES (pnt))
+ {
+ /* Yes: Skip it. */
+ pnt += PSECT_ATTRIBUTES_STRING_LENGTH;
+ while (*pnt)
+ {
+ if ((pnt[0] == '$') && (pnt[1] == '$'))
+ {
+ pnt += 2;
+ break;
+ }
+ pnt++;
+ }
+ }
+
+ /* Here we fix the .this -> $this conversion. */
+ for (pnt1 = pnt; *pnt1 != 0; pnt1++)
+ if (*pnt1 == '.')
+ *pnt1 = '$';
+
+ return pnt;
+}
+
+
+/* When defining a structure, this routine is called to find the name of
+ the actual structure. It is assumed that str points to the equal sign
+ in the definition, and it moves backward until it finds the start of the
+ name. If it finds a 0, then it knows that this structure def is in the
+ outermost level, and thus symbol_name points to the symbol name. */
+
+static char *
+get_struct_name (str)
+ char *str;
+{
+ char *pnt;
+ pnt = str;
+ while ((*pnt != ':') && (*pnt != '\0'))
+ pnt--;
+ if (*pnt == '\0')
+ return (char *) symbol_name;
+ *pnt-- = '\0';
+ while ((*pnt != ';') && (*pnt != '='))
+ pnt--;
+ if (*pnt == ';')
+ return pnt + 1;
+ while ((*pnt < '0') || (*pnt > '9'))
+ pnt++;
+ while ((*pnt >= '0') && (*pnt <= '9'))
+ pnt++;
+ return pnt;
+}
+
+
+/* Search symbol list for type number dbx_type.
+ Return a pointer to struct. */
+
+static struct VMS_DBG_Symbol *
+find_symbol (dbx_type)
+ int dbx_type;
+{
+ struct VMS_DBG_Symbol *spnt;
+
+ spnt = VMS_Symbol_type_list[SYMTYP_HASH (dbx_type)];
+ while (spnt)
+ {
+ if (spnt->dbx_type == dbx_type)
+ break;
+ spnt = spnt->next;
+ }
+ if (!spnt || spnt->advanced != ALIAS)
+ return spnt;
+ return find_symbol (spnt->type2);
+}
+
+
+#if 0 /* obsolete */
+/* this routine puts info into either Local or Asuffix, depending on the sign
+ * of size. The reason is that it is easier to build the variable descriptor
+ * backwards, while the array descriptor is best built forwards. In the end
+ * they get put together, if there is not a struct/union/enum along the way
+ */
+static void
+push (value, size1)
+ int value, size1;
+{
+ if (size1 < 0)
+ {
+ size1 = -size1;
+ if (Lpnt < size1)
+ {
+ overflow = 1;
+ Lpnt = 1;
+ return;
+ }
+ Lpnt -= size1;
+ md_number_to_chars (&Local[Lpnt + 1], value, size1);
+ }
+ else
+ {
+ if (Apoint + size1 >= MAX_DEBUG_RECORD)
+ {
+ overflow = 1;
+ Apoint = MAX_DEBUG_RECORD - 1;
+ return;
+ }
+ md_number_to_chars (&Asuffix[Apoint], value, size1);
+ Apoint += size1;
+ }
+}
+#endif
+
+
+static void
+fpush (value, size)
+ int value, size;
+{
+ if (Apoint + size >= MAX_DEBUG_RECORD)
+ {
+ overflow = 1;
+ Apoint = MAX_DEBUG_RECORD - 1;
+ return;
+ }
+ if (size == 1)
+ Asuffix[Apoint++] = (char) value;
+ else
+ {
+ md_number_to_chars (&Asuffix[Apoint], value, size);
+ Apoint += size;
+ }
+}
+
+static void
+rpush (value, size)
+ int value, size;
+{
+ if (Lpnt < size)
+ {
+ overflow = 1;
+ Lpnt = 1;
+ return;
+ }
+ if (size == 1)
+ Local[Lpnt--] = (char) value;
+ else
+ {
+ Lpnt -= size;
+ md_number_to_chars (&Local[Lpnt + 1], value, size);
+ }
+}
+
+
+/* This routine generates the array descriptor for a given array. */
+
+static void
+array_suffix (spnt2)
+ struct VMS_DBG_Symbol *spnt2;
+{
+ struct VMS_DBG_Symbol *spnt;
+ struct VMS_DBG_Symbol *spnt1;
+ int rank;
+ int total_size;
+
+ rank = 0;
+ spnt = spnt2;
+ while (spnt->advanced != ARRAY)
+ {
+ spnt = find_symbol (spnt->type2);
+ if (!spnt)
+ return;
+ }
+ spnt1 = spnt;
+ total_size = 1;
+ while (spnt1->advanced == ARRAY)
+ {
+ rank++;
+ total_size *= (spnt1->index_max - spnt1->index_min + 1);
+ spnt1 = find_symbol (spnt1->type2);
+ }
+ total_size = total_size * spnt1->data_size;
+ fpush (spnt1->data_size, 2); /* element size */
+ if (spnt1->VMS_type == DBG_S_C_ADVANCED_TYPE)
+ fpush (0, 1);
+ else
+ fpush (spnt1->VMS_type, 1); /* element type */
+ fpush (DSC_K_CLASS_A, 1); /* descriptor class */
+ fpush (0, 4); /* base address */
+ fpush (0, 1); /* scale factor -- not applicable */
+ fpush (0, 1); /* digit count -- not applicable */
+ fpush (0xc0, 1); /* flags: multiplier block & bounds present */
+ fpush (rank, 1); /* number of dimensions */
+ fpush (total_size, 4);
+ fpush (0, 4); /* pointer to element [0][0]...[0] */
+ spnt1 = spnt;
+ while (spnt1->advanced == ARRAY)
+ {
+ fpush (spnt1->index_max - spnt1->index_min + 1, 4);
+ spnt1 = find_symbol (spnt1->type2);
+ }
+ spnt1 = spnt;
+ while (spnt1->advanced == ARRAY)
+ {
+ fpush (spnt1->index_min, 4);
+ fpush (spnt1->index_max, 4);
+ spnt1 = find_symbol (spnt1->type2);
+ }
+}
+
+
+/* This routine generates the start of a variable descriptor based upon
+ a struct/union/enum that has yet to be defined. We define this spot as
+ a new location, and save four bytes for the address. When the struct is
+ finally defined, then we can go back and plug in the correct address. */
+
+static void
+new_forward_ref (dbx_type)
+ int dbx_type;
+{
+ struct forward_ref *fpnt;
+ fpnt = (struct forward_ref *) xmalloc (sizeof (struct forward_ref));
+ fpnt->next = f_ref_root;
+ f_ref_root = fpnt;
+ fpnt->dbx_type = dbx_type;
+ fpnt->struc_numb = ++structure_count;
+ fpnt->resolved = 'N';
+ rpush (DST_K_TS_IND, 1); /* indirect type specification */
+ total_len = 5;
+ rpush (total_len, 2);
+ struct_number = -fpnt->struc_numb;
+}
+
+
+/* This routine generates the variable descriptor used to describe non-basic
+ variables. It calls itself recursively until it gets to the bottom of it
+ all, and then builds the descriptor backwards. It is easiest to do it
+ this way since we must periodically write length bytes, and it is easiest
+ if we know the value when it is time to write it. */
+
+static int
+gen1 (spnt, array_suffix_len)
+ struct VMS_DBG_Symbol *spnt;
+ int array_suffix_len;
+{
+ struct VMS_DBG_Symbol *spnt1;
+ int i;
+
+ switch (spnt->advanced)
+ {
+ case VOID:
+ rpush (DBG_S_C_VOID, 1);
+ total_len += 1;
+ rpush (total_len, 2);
+ return 0;
+ case BASIC:
+ case FUNCTION:
+ if (array_suffix_len == 0)
+ {
+ rpush (spnt->VMS_type, 1);
+ rpush (DBG_S_C_BASIC, 1);
+ total_len = 2;
+ rpush (total_len, 2);
+ return 1;
+ }
+ rpush (0, 4);
+ rpush (DST_K_VFLAGS_DSC, 1);
+ rpush (DST_K_TS_DSC, 1); /* descriptor type specification */
+ total_len = -2;
+ return 1;
+ case STRUCT:
+ case UNION:
+ case ENUM:
+ struct_number = spnt->struc_numb;
+ if (struct_number < 0)
+ {
+ new_forward_ref (spnt->dbx_type);
+ return 1;
+ }
+ rpush (DBG_S_C_STRUCT, 1);
+ total_len = 5;
+ rpush (total_len, 2);
+ return 1;
+ case POINTER:
+ spnt1 = find_symbol (spnt->type2);
+ i = 1;
+ if (!spnt1)
+ new_forward_ref (spnt->type2);
+ else
+ i = gen1 (spnt1, 0);
+ if (i)
+ { /* (*void) is a special case, do not put pointer suffix */
+ rpush (DBG_S_C_POINTER, 1);
+ total_len += 3;
+ rpush (total_len, 2);
+ }
+ return 1;
+ case ARRAY:
+ spnt1 = spnt;
+ while (spnt1->advanced == ARRAY)
+ {
+ spnt1 = find_symbol (spnt1->type2);
+ if (!spnt1)
+ {
+ as_tsktsk (_("debugger forward reference error, dbx type %d"),
+ spnt->type2);
+ return 0;
+ }
+ }
+/* It is too late to generate forward references, so the user gets a message.
+ * This should only happen on a compiler error */
+ (void) gen1 (spnt1, 1);
+ i = Apoint;
+ array_suffix (spnt);
+ array_suffix_len = Apoint - i;
+ switch (spnt1->advanced)
+ {
+ case BASIC:
+ case FUNCTION:
+ break;
+ default:
+ rpush (0, 2);
+ total_len += 2;
+ rpush (total_len, 2);
+ rpush (DST_K_VFLAGS_DSC, 1);
+ rpush (1, 1); /* flags: element value spec included */
+ rpush (1, 1); /* one dimension */
+ rpush (DBG_S_C_COMPLEX_ARRAY, 1);
+ }
+ total_len += array_suffix_len + 8;
+ rpush (total_len, 2);
+ break;
+ default: /* lint suppression */
+ break;
+ }
+ return 0;
+}
+
+
+/* This generates a suffix for a variable. If it is not a defined type yet,
+ then dbx_type contains the type we are expecting so we can generate a
+ forward reference. This calls gen1 to build most of the descriptor, and
+ then it puts the icing on at the end. It then dumps whatever is needed
+ to get a complete descriptor (i.e. struct reference, array suffix). */
+
+static void
+generate_suffix (spnt, dbx_type)
+ struct VMS_DBG_Symbol *spnt;
+ int dbx_type;
+{
+ static const char pvoid[6] = {
+ 5, /* record.length == 5 */
+ DST_K_TYPSPEC, /* record.type == 1 (type specification) */
+ 0, /* name.length == 0, no name follows */
+ 1, 0, /* type.length == 1 {2 bytes, little endian} */
+ DBG_S_C_VOID /* type.type == 5 (pointer to unspecified) */
+ };
+ int i;
+
+ Apoint = 0;
+ Lpnt = MAX_DEBUG_RECORD - 1;
+ total_len = 0;
+ struct_number = 0;
+ overflow = 0;
+ if (!spnt)
+ new_forward_ref (dbx_type);
+ else
+ {
+ if (spnt->VMS_type != DBG_S_C_ADVANCED_TYPE)
+ return; /* no suffix needed */
+ gen1 (spnt, 0);
+ }
+ rpush (0, 1); /* no name (len==0) */
+ rpush (DST_K_TYPSPEC, 1);
+ total_len += 4;
+ rpush (total_len, 1);
+ /* If the variable descriptor overflows the record, output a descriptor
+ for a pointer to void. */
+ if ((total_len >= MAX_DEBUG_RECORD) || overflow)
+ {
+ as_warn (_("Variable descriptor %d too complicated. Defined as `void *'."),
+ spnt->dbx_type);
+ VMS_Store_Immediate_Data (pvoid, 6, OBJ_S_C_DBG);
+ return;
+ }
+ i = 0;
+ while (Lpnt < MAX_DEBUG_RECORD - 1)
+ Local[i++] = Local[++Lpnt];
+ Lpnt = i;
+ /* we use this for reference to structure that has already been defined */
+ if (struct_number > 0)
+ {
+ VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
+ Lpnt = 0;
+ VMS_Store_Struct (struct_number);
+ }
+ /* We use this for a forward reference to a structure that has yet to
+ be defined. We store four bytes of zero to make room for the actual
+ address once it is known. */
+ if (struct_number < 0)
+ {
+ struct_number = -struct_number;
+ VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
+ Lpnt = 0;
+ VMS_Def_Struct (struct_number);
+ COPY_LONG (&Local[Lpnt], 0L);
+ Lpnt += 4;
+ VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
+ Lpnt = 0;
+ }
+ i = 0;
+ while (i < Apoint)
+ Local[Lpnt++] = Asuffix[i++];
+ if (Lpnt != 0)
+ VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
+ Lpnt = 0;
+}
+
+
+ /* "novel length" type doesn't work for simple atomic types */
+#define USE_BITSTRING_DESCRIPTOR(t) ((t)->advanced == BASIC)
+#undef SETUP_BASIC_TYPES
+
+/* This routine generates a type description for a bitfield. */
+
+static void
+bitfield_suffix (spnt, width)
+ struct VMS_DBG_Symbol *spnt;
+ int width;
+{
+ Local[Lpnt++] = 13; /* rec.len==13 */
+ Local[Lpnt++] = DST_K_TYPSPEC; /* a type specification record */
+ Local[Lpnt++] = 0; /* not named */
+ COPY_SHORT (&Local[Lpnt], 9); /* typ.len==9 */
+ Lpnt += 2;
+ Local[Lpnt++] = DST_K_TS_NOV_LENG; /* This type is a "novel length"
+ incarnation of some other type. */
+ COPY_LONG (&Local[Lpnt], width); /* size in bits == novel length */
+ Lpnt += 4;
+ VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
+ Lpnt = 0;
+ /* assert( spnt->struc_numb > 0 ); */
+ VMS_Store_Struct (spnt->struc_numb); /* output 4 more bytes */
+}
+
+
+/* Formally define a builtin type, so that it can serve as the target of
+ an indirect reference. It makes bitfield_suffix() easier by avoiding
+ the need to use a forward reference for the first occurrence of each
+ type used in a bitfield. */
+
+static void
+setup_basic_type (spnt)
+ struct VMS_DBG_Symbol *spnt;
+{
+#ifdef SETUP_BASIC_TYPES
+ /* This would be very useful if "novel length" fields actually worked
+ with basic types like they do with enumerated types. However,
+ they do not, so this isn't worth doing just so that you can use
+ EXAMINE/TYPE=(__long_long_int) instead of EXAMINE/QUAD. */
+ char *p;
+#ifndef SETUP_SYNONYM_TYPES
+ /* This determines whether compatible things like `int' and `long int'
+ ought to have distinct type records rather than sharing one. */
+ struct VMS_DBG_Symbol *spnt2;
+
+ /* first check whether this type has already been seen by another name */
+ for (spnt2 = VMS_Symbol_type_list[SYMTYP_HASH (spnt->VMS_type)];
+ spnt2;
+ spnt2 = spnt2->next)
+ if (spnt2 != spnt && spnt2->VMS_type == spnt->VMS_type)
+ {
+ spnt->struc_numb = spnt2->struc_numb;
+ return;
+ }
+#endif
+
+ /* `structure number' doesn't really mean `structure'; it means an index
+ into a linker maintained set of saved locations which can be referenced
+ again later. */
+ spnt->struc_numb = ++structure_count;
+ VMS_Def_Struct (spnt->struc_numb); /* remember where this type lives */
+ /* define the simple scalar type */
+ Local[Lpnt++] = 6 + strlen (symbol_name) + 2; /* rec.len */
+ Local[Lpnt++] = DST_K_TYPSPEC; /* rec.typ==type specification */
+ Local[Lpnt++] = strlen (symbol_name) + 2;
+ Local[Lpnt++] = '_'; /* prefix name with "__" */
+ Local[Lpnt++] = '_';
+ for (p = symbol_name; *p; p++)
+ Local[Lpnt++] = *p == ' ' ? '_' : *p;
+ COPY_SHORT (&Local[Lpnt], 2); /* typ.len==2 */
+ Lpnt += 2;
+ Local[Lpnt++] = DST_K_TS_ATOM; /* typ.kind is simple type */
+ Local[Lpnt++] = spnt->VMS_type; /* typ.type */
+ VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
+ Lpnt = 0;
+#endif /* SETUP_BASIC_TYPES */
+ return;
+}
+
+
+/* This routine generates a symbol definition for a C symbol for the debugger.
+ It takes a psect and offset for global symbols; if psect < 0, then this is
+ a local variable and the offset is relative to FP. In this case it can
+ be either a variable (Offset < 0) or a parameter (Offset > 0). */
+
+static void
+VMS_DBG_record (spnt, Psect, Offset, Name)
+ struct VMS_DBG_Symbol *spnt;
+ int Psect;
+ int Offset;
+ char *Name;
+{
+ char *Name_pnt;
+ int len;
+ int i = 0;
+
+ /* if there are bad characters in name, convert them */
+ Name_pnt = fix_name (Name);
+
+ len = strlen (Name_pnt);
+ if (Psect < 0)
+ { /* this is a local variable, referenced to SP */
+ Local[i++] = 7 + len;
+ Local[i++] = spnt->VMS_type;
+ Local[i++] = (Offset > 0) ? DBG_C_FUNCTION_PARAM : DBG_C_LOCAL_SYM;
+ COPY_LONG (&Local[i], Offset);
+ i += 4;
+ }
+ else
+ {
+ Local[i++] = 7 + len;
+ Local[i++] = spnt->VMS_type;
+ Local[i++] = DST_K_VALKIND_ADDR;
+ VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
+ i = 0;
+ VMS_Set_Data (Psect, Offset, OBJ_S_C_DBG, 0);
+ }
+ Local[i++] = len;
+ while (*Name_pnt != '\0')
+ Local[i++] = *Name_pnt++;
+ VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
+ if (spnt->VMS_type == DBG_S_C_ADVANCED_TYPE)
+ generate_suffix (spnt, 0);
+}
+
+
+/* This routine parses the stabs entries in order to make the definition
+ for the debugger of local symbols and function parameters. */
+
+static void
+VMS_local_stab_Parse (sp)
+ symbolS *sp;
+{
+ struct VMS_DBG_Symbol *spnt;
+ char *pnt;
+ char *pnt1;
+ char *str;
+ int dbx_type;
+
+ dbx_type = 0;
+ str = S_GET_NAME (sp);
+ pnt = (char *) strchr (str, ':');
+ if (!pnt)
+ return; /* no colon present */
+ pnt1 = pnt++; /* save this for later, and skip colon */
+ if (*pnt == 'c')
+ return; /* ignore static constants */
+
+/* there is one little catch that we must be aware of. Sometimes function
+ * parameters are optimized into registers, and the compiler, in its infiite
+ * wisdom outputs stabs records for *both*. In general we want to use the
+ * register if it is present, so we must search the rest of the symbols for
+ * this function to see if this parameter is assigned to a register.
+ */
+ {
+ symbolS *sp1;
+ char *str1;
+ char *pnt2;
+
+ if (*pnt == 'p')
+ {
+ for (sp1 = symbol_next (sp); sp1; sp1 = symbol_next (sp1))
+ {
+ if (!S_IS_DEBUG (sp1))
+ continue;
+ if (S_GET_RAW_TYPE (sp1) == N_FUN)
+ {
+ pnt2 = (char *) strchr (S_GET_NAME (sp1), ':') + 1;
+ if (*pnt2 == 'F' || *pnt2 == 'f')
+ break;
+ }
+ if (S_GET_RAW_TYPE (sp1) != N_RSYM)
+ continue;
+ str1 = S_GET_NAME (sp1); /* and get the name */
+ pnt2 = str;
+ while (*pnt2 != ':')
+ {
+ if (*pnt2 != *str1)
+ break;
+ pnt2++;
+ str1++;
+ }
+ if (*str1 == ':' && *pnt2 == ':')
+ return; /* they are the same! lets skip this one */
+ } /* for */
+ pnt++; /* skip p in case no register */
+ } /* if */
+ } /* p block */
+
+ pnt = cvt_integer (pnt, &dbx_type);
+ spnt = find_symbol (dbx_type);
+ if (!spnt)
+ return; /*Dunno what this is*/
+ *pnt1 = '\0';
+ VMS_DBG_record (spnt, -1, S_GET_VALUE (sp), str);
+ *pnt1 = ':'; /* and restore the string */
+ return;
+}
+
+
+/* This routine parses a stabs entry to find the information required
+ to define a variable. It is used for global and static variables.
+ Basically we need to know the address of the symbol. With older
+ versions of the compiler, const symbols are treated differently, in
+ that if they are global they are written into the text psect. The
+ global symbol entry for such a const is actually written as a program
+ entry point (Yuk!!), so if we cannot find a symbol in the list of
+ psects, we must search the entry points as well. static consts are
+ even harder, since they are never assigned a memory address. The
+ compiler passes a stab to tell us the value, but I am not sure what
+ to do with it. */
+
+static void
+VMS_stab_parse (sp, expected_type, type1, type2, Text_Psect)
+ symbolS *sp;
+ int expected_type; /* char */
+ int type1, type2, Text_Psect;
+{
+ char *pnt;
+ char *pnt1;
+ char *str;
+ symbolS *sp1;
+ struct VMS_DBG_Symbol *spnt;
+ struct VMS_Symbol *vsp;
+ int dbx_type;
+
+ dbx_type = 0;
+ str = S_GET_NAME (sp);
+ pnt = (char *) strchr (str, ':');
+ if (!pnt)
+ return; /* no colon present */
+ pnt1 = pnt; /* save this for later*/
+ pnt++;
+ if (*pnt == expected_type)
+ {
+ pnt = cvt_integer (pnt + 1, &dbx_type);
+ spnt = find_symbol (dbx_type);
+ if (!spnt)
+ return; /*Dunno what this is*/
+ /*
+ * Now we need to search the symbol table to find the psect and
+ * offset for this variable.
+ */
+ *pnt1 = '\0';
+ vsp = VMS_Symbols;
+ while (vsp)
+ {
+ pnt = S_GET_NAME (vsp->Symbol);
+ if (pnt && *pnt++ == '_'
+ /* make sure name is the same and symbol type matches */
+ && strcmp (pnt, str) == 0
+ && (S_GET_RAW_TYPE (vsp->Symbol) == type1
+ || S_GET_RAW_TYPE (vsp->Symbol) == type2))
+ break;
+ vsp = vsp->Next;
+ }
+ if (vsp)
+ {
+ VMS_DBG_record (spnt, vsp->Psect_Index, vsp->Psect_Offset, str);
+ *pnt1 = ':'; /* and restore the string */
+ return;
+ }
+ /* The symbol was not in the symbol list, but it may be an
+ "entry point" if it was a constant. */
+ for (sp1 = symbol_rootP; sp1; sp1 = symbol_next (sp1))
+ {
+ /*
+ * Dispatch on STAB type
+ */
+ if (S_IS_DEBUG (sp1) || (S_GET_TYPE (sp1) != N_TEXT))
+ continue;
+ pnt = S_GET_NAME (sp1);
+ if (*pnt == '_')
+ pnt++;
+ if (strcmp (pnt, str) == 0)
+ {
+ if (!gave_compiler_message && expected_type == 'G')
+ {
+ char *long_const_msg = _("\
+***Warning - the assembly code generated by the compiler has placed \n\
+ global constant(s) in the text psect. These will not be available to \n\
+ other modules, since this is not the correct way to handle this. You \n\
+ have two options: 1) get a patched compiler that does not put global \n\
+ constants in the text psect, or 2) remove the 'const' keyword from \n\
+ definitions of global variables in your source module(s). Don't say \n\
+ I didn't warn you! \n");
+
+ as_tsktsk (long_const_msg);
+ gave_compiler_message = 1;
+ }
+ VMS_DBG_record (spnt,
+ Text_Psect,
+ S_GET_VALUE (sp1),
+ str);
+ *pnt1 = ':';
+ /* fool assembler to not output this as a routine in the TBT */
+ pnt1 = S_GET_NAME (sp1);
+ *pnt1 = 'L';
+ S_SET_NAME (sp1, pnt1);
+ return;
+ }
+ }
+ }
+ *pnt1 = ':'; /* and restore the string */
+ return;
+}
+
+
+/* Simpler interfaces into VMS_stab_parse(). */
+
+static void
+VMS_GSYM_Parse (sp, Text_Psect)
+ symbolS *sp;
+ int Text_Psect;
+{ /* Global variables */
+ VMS_stab_parse (sp, 'G', (N_UNDF | N_EXT), (N_DATA | N_EXT), Text_Psect);
+}
+
+static void
+VMS_LCSYM_Parse (sp, Text_Psect)
+ symbolS *sp;
+ int Text_Psect;
+{ /* Static symbols - uninitialized */
+ VMS_stab_parse (sp, 'S', N_BSS, -1, Text_Psect);
+}
+
+static void
+VMS_STSYM_Parse (sp, Text_Psect)
+ symbolS *sp;
+ int Text_Psect;
+{ /* Static symbols - initialized */
+ VMS_stab_parse (sp, 'S', N_DATA, -1, Text_Psect);
+}
+
+
+/* For register symbols, we must figure out what range of addresses
+ within the psect are valid. We will use the brackets in the stab
+ directives to give us guidance as to the PC range that this variable
+ is in scope. I am still not completely comfortable with this but
+ as I learn more, I seem to get a better handle on what is going on.
+ Caveat Emptor. */
+
+static void
+VMS_RSYM_Parse (sp, Current_Routine, Text_Psect)
+ symbolS *sp, *Current_Routine;
+ int Text_Psect;
+{
+ symbolS *symbolP;
+ struct VMS_DBG_Symbol *spnt;
+ char *pnt;
+ char *pnt1;
+ char *str;
+ int dbx_type;
+ int len;
+ int i = 0;
+ int bcnt = 0;
+ int Min_Offset = -1; /* min PC of validity */
+ int Max_Offset = 0; /* max PC of validity */
+
+ for (symbolP = sp; symbolP; symbolP = symbol_next (symbolP))
+ {
+ /*
+ * Dispatch on STAB type
+ */
+ switch (S_GET_RAW_TYPE (symbolP))
+ {
+ case N_LBRAC:
+ if (bcnt++ == 0)
+ Min_Offset = S_GET_VALUE (symbolP);
+ break;
+ case N_RBRAC:
+ if (--bcnt == 0)
+ Max_Offset = S_GET_VALUE (symbolP) - 1;
+ break;
+ }
+ if ((Min_Offset != -1) && (bcnt == 0))
+ break;
+ if (S_GET_RAW_TYPE (symbolP) == N_FUN)
+ {
+ pnt = (char *) strchr (S_GET_NAME (symbolP), ':') + 1;
+ if (*pnt == 'F' || *pnt == 'f') break;
+ }
+ }
+
+ /* Check to see that the addresses were defined. If not, then there
+ were no brackets in the function, and we must try to search for
+ the next function. Since functions can be in any order, we should
+ search all of the symbol list to find the correct ending address. */
+ if (Min_Offset == -1)
+ {
+ int Max_Source_Offset;
+ int This_Offset;
+
+ Min_Offset = S_GET_VALUE (sp);
+ Max_Source_Offset = Min_Offset; /* just in case no N_SLINEs found */
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
+ switch (S_GET_RAW_TYPE (symbolP))
+ {
+ case N_TEXT | N_EXT:
+ This_Offset = S_GET_VALUE (symbolP);
+ if (This_Offset > Min_Offset && This_Offset < Max_Offset)
+ Max_Offset = This_Offset;
+ break;
+ case N_SLINE:
+ This_Offset = S_GET_VALUE (symbolP);
+ if (This_Offset > Max_Source_Offset)
+ Max_Source_Offset = This_Offset;
+ break;
+ }
+ /* If this is the last routine, then we use the PC of the last source
+ line as a marker of the max PC for which this reg is valid. */
+ if (Max_Offset == 0x7fffffff)
+ Max_Offset = Max_Source_Offset;
+ }
+
+ dbx_type = 0;
+ str = S_GET_NAME (sp);
+ if ((pnt = (char *) strchr (str, ':')) == 0)
+ return; /* no colon present */
+ pnt1 = pnt; /* save this for later*/
+ pnt++;
+ if (*pnt != 'r')
+ return;
+ pnt = cvt_integer (pnt + 1, &dbx_type);
+ spnt = find_symbol (dbx_type);
+ if (!spnt)
+ return; /*Dunno what this is yet*/
+ *pnt1 = '\0';
+ pnt = fix_name (S_GET_NAME (sp)); /* if there are bad characters in name, convert them */
+ len = strlen (pnt);
+ Local[i++] = 25 + len;
+ Local[i++] = spnt->VMS_type;
+ Local[i++] = DST_K_VFLAGS_TVS; /* trailing value specified */
+ COPY_LONG (&Local[i], 1 + len); /* relative offset, beyond name */
+ i += 4;
+ Local[i++] = len; /* name length (ascic prefix) */
+ while (*pnt != '\0')
+ Local[i++] = *pnt++;
+ Local[i++] = DST_K_VS_FOLLOWS; /* value specification follows */
+ COPY_SHORT (&Local[i], 15); /* length of rest of record */
+ i += 2;
+ Local[i++] = DST_K_VS_ALLOC_SPLIT; /* split lifetime */
+ Local[i++] = 1; /* one binding follows */
+ VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
+ i = 0;
+ VMS_Set_Data (Text_Psect, Min_Offset, OBJ_S_C_DBG, 1);
+ VMS_Set_Data (Text_Psect, Max_Offset, OBJ_S_C_DBG, 1);
+ Local[i++] = DST_K_VALKIND_REG; /* nested value spec */
+ COPY_LONG (&Local[i], S_GET_VALUE (sp));
+ i += 4;
+ VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
+ *pnt1 = ':';
+ if (spnt->VMS_type == DBG_S_C_ADVANCED_TYPE)
+ generate_suffix (spnt, 0);
+}
+
+
+/* This function examines a structure definition, checking all of the elements
+ to make sure that all of them are fully defined. The only thing that we
+ kick out are arrays of undefined structs, since we do not know how big
+ they are. All others we can handle with a normal forward reference. */
+
+static int
+forward_reference (pnt)
+ char *pnt;
+{
+ struct VMS_DBG_Symbol *spnt, *spnt1;
+ int i;
+
+ pnt = cvt_integer (pnt + 1, &i);
+ if (*pnt == ';')
+ return 0; /* no forward references */
+ do
+ {
+ pnt = (char *) strchr (pnt, ':');
+ pnt = cvt_integer (pnt + 1, &i);
+ spnt = find_symbol (i);
+ while (spnt && (spnt->advanced == POINTER || spnt->advanced == ARRAY))
+ {
+ spnt1 = find_symbol (spnt->type2);
+ if (spnt->advanced == ARRAY && !spnt1)
+ return 1;
+ spnt = spnt1;
+ }
+ pnt = cvt_integer (pnt + 1, &i);
+ pnt = cvt_integer (pnt + 1, &i);
+ } while (*++pnt != ';');
+ return 0; /* no forward refences found */
+}
+
+
+/* Used to check a single element of a structure on the final pass. */
+
+static int
+final_forward_reference (spnt)
+ struct VMS_DBG_Symbol *spnt;
+{
+ struct VMS_DBG_Symbol *spnt1;
+
+ while (spnt && (spnt->advanced == POINTER || spnt->advanced == ARRAY))
+ {
+ spnt1 = find_symbol (spnt->type2);
+ if (spnt->advanced == ARRAY && !spnt1)
+ return 1;
+ spnt = spnt1;
+ }
+ return 0; /* no forward refences found */
+}
+
+
+/* This routine parses the stabs directives to find any definitions of dbx
+ type numbers. It makes a note of all of them, creating a structure
+ element of VMS_DBG_Symbol that describes it. This also generates the
+ info for the debugger that describes the struct/union/enum, so that
+ further references to these data types will be by number
+
+ We have to process pointers right away, since there can be references
+ to them later in the same stabs directive. We cannot have forward
+ references to pointers, (but we can have a forward reference to a
+ pointer to a structure/enum/union) and this is why we process them
+ immediately. After we process the pointer, then we search for defs
+ that are nested even deeper.
+
+ 8/15/92: We have to process arrays right away too, because there can
+ be multiple references to identical array types in one structure
+ definition, and only the first one has the definition. */
+
+static int
+VMS_typedef_parse (str)
+ char *str;
+{
+ char *pnt;
+ char *pnt1;
+ const char *pnt2;
+ int i;
+ int dtype;
+ struct forward_ref *fpnt;
+ int i1, i2, i3, len;
+ struct VMS_DBG_Symbol *spnt;
+ struct VMS_DBG_Symbol *spnt1;
+
+ /* check for any nested def's */
+ pnt = (char *) strchr (str + 1, '=');
+ if (pnt && str[1] != '*' && (str[1] != 'a' || str[2] != 'r')
+ && VMS_typedef_parse (pnt) == 1)
+ return 1;
+ /* now find dbx_type of entry */
+ pnt = str - 1;
+ if (*pnt == 'c')
+ { /* check for static constants */
+ *str = '\0'; /* for now we ignore them */
+ return 0;
+ }
+ while ((*pnt <= '9') && (*pnt >= '0'))
+ pnt--;
+ pnt++; /* and get back to the number */
+ cvt_integer (pnt, &i1);
+ spnt = find_symbol (i1);
+ /* first see if this has been defined already, due to forward reference */
+ if (!spnt)
+ {
+ i2 = SYMTYP_HASH (i1);
+ spnt = (struct VMS_DBG_Symbol *) xmalloc (sizeof (struct VMS_DBG_Symbol));
+ spnt->next = VMS_Symbol_type_list[i2];
+ VMS_Symbol_type_list[i2] = spnt;
+ spnt->dbx_type = i1; /* and save the type */
+ spnt->type2 = spnt->VMS_type = spnt->data_size = 0;
+ spnt->index_min = spnt->index_max = spnt->struc_numb = 0;
+ }
+ /*
+ * For structs and unions, do a partial parse, otherwise we sometimes get
+ * circular definitions that are impossible to resolve. We read enough
+ * info so that any reference to this type has enough info to be resolved.
+ */
+ pnt = str + 1; /* point to character past equal sign */
+ if (*pnt >= '0' && *pnt <= '9')
+ {
+ if (type_check ("void"))
+ { /* this is the void symbol */
+ *str = '\0';
+ spnt->advanced = VOID;
+ return 0;
+ }
+ if (type_check ("unknown type"))
+ {
+ *str = '\0';
+ spnt->advanced = UNKNOWN;
+ return 0;
+ }
+ pnt1 = cvt_integer (pnt, &i1);
+ if (i1 != spnt->dbx_type)
+ {
+ spnt->advanced = ALIAS;
+ spnt->type2 = i1;
+ strcpy (str, pnt1);
+ return 0;
+ }
+ as_tsktsk (_("debugginer output: %d is an unknown untyped variable."),
+ spnt->dbx_type);
+ return 1; /* do not know what this is */
+ }
+
+ pnt = str + 1; /* point to character past equal sign */
+ switch (*pnt)
+ {
+ case 'r':
+ spnt->advanced = BASIC;
+ if (type_check ("int"))
+ {
+ spnt->VMS_type = DBG_S_C_SLINT;
+ spnt->data_size = 4;
+ }
+ else if (type_check ("long int"))
+ {
+ spnt->VMS_type = DBG_S_C_SLINT;
+ spnt->data_size = 4;
+ }
+ else if (type_check ("unsigned int"))
+ {
+ spnt->VMS_type = DBG_S_C_ULINT;
+ spnt->data_size = 4;
+ }
+ else if (type_check ("long unsigned int"))
+ {
+ spnt->VMS_type = DBG_S_C_ULINT;
+ spnt->data_size = 4;
+ }
+ else if (type_check ("short int"))
+ {
+ spnt->VMS_type = DBG_S_C_SSINT;
+ spnt->data_size = 2;
+ }
+ else if (type_check ("short unsigned int"))
+ {
+ spnt->VMS_type = DBG_S_C_USINT;
+ spnt->data_size = 2;
+ }
+ else if (type_check ("char"))
+ {
+ spnt->VMS_type = DBG_S_C_SCHAR;
+ spnt->data_size = 1;
+ }
+ else if (type_check ("signed char"))
+ {
+ spnt->VMS_type = DBG_S_C_SCHAR;
+ spnt->data_size = 1;
+ }
+ else if (type_check ("unsigned char"))
+ {
+ spnt->VMS_type = DBG_S_C_UCHAR;
+ spnt->data_size = 1;
+ }
+ else if (type_check ("float"))
+ {
+ spnt->VMS_type = DBG_S_C_REAL4;
+ spnt->data_size = 4;
+ }
+ else if (type_check ("double"))
+ {
+ spnt->VMS_type = vax_g_doubles ? DBG_S_C_REAL8_G : DBG_S_C_REAL8;
+ spnt->data_size = 8;
+ }
+ else if (type_check ("long double"))
+ {
+ /* same as double, at least for now */
+ spnt->VMS_type = vax_g_doubles ? DBG_S_C_REAL8_G : DBG_S_C_REAL8;
+ spnt->data_size = 8;
+ }
+ else if (type_check ("long long int"))
+ {
+ spnt->VMS_type = DBG_S_C_SQUAD; /* signed quadword */
+ spnt->data_size = 8;
+ }
+ else if (type_check ("long long unsigned int"))
+ {
+ spnt->VMS_type = DBG_S_C_UQUAD; /* unsigned quadword */
+ spnt->data_size = 8;
+ }
+ else if (type_check ("complex float"))
+ {
+ spnt->VMS_type = DBG_S_C_COMPLX4;
+ spnt->data_size = 2 * 4;
+ }
+ else if (type_check ("complex double"))
+ {
+ spnt->VMS_type = vax_g_doubles ? DBG_S_C_COMPLX8_G : DBG_S_C_COMPLX8;
+ spnt->data_size = 2 * 8;
+ }
+ else if (type_check ("complex long double"))
+ {
+ /* same as complex double, at least for now */
+ spnt->VMS_type = vax_g_doubles ? DBG_S_C_COMPLX8_G : DBG_S_C_COMPLX8;
+ spnt->data_size = 2 * 8;
+ }
+ else
+ {
+ /* [pr]
+ * Shouldn't get here, but if we do, something
+ * more substantial ought to be done...
+ */
+ spnt->VMS_type = 0;
+ spnt->data_size = 0;
+ }
+ if (spnt->VMS_type != 0)
+ setup_basic_type (spnt);
+ pnt1 = (char *) strchr (str, ';') + 1;
+ break;
+ case 's':
+ case 'u':
+ spnt->advanced = (*pnt == 's') ? STRUCT : UNION;
+ spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
+ pnt1 = cvt_integer (pnt + 1, &spnt->data_size);
+ if (!final_pass && forward_reference (pnt))
+ {
+ spnt->struc_numb = -1;
+ return 1;
+ }
+ spnt->struc_numb = ++structure_count;
+ pnt1--;
+ pnt = get_struct_name (str);
+ VMS_Def_Struct (spnt->struc_numb);
+ i = 0;
+ for (fpnt = f_ref_root; fpnt; fpnt = fpnt->next)
+ if (fpnt->dbx_type == spnt->dbx_type)
+ {
+ fpnt->resolved = 'Y';
+ VMS_Set_Struct (fpnt->struc_numb);
+ VMS_Store_Struct (spnt->struc_numb);
+ i++;
+ }
+ if (i > 0)
+ VMS_Set_Struct (spnt->struc_numb);
+ i = 0;
+ Local[i++] = 11 + strlen (pnt);
+ Local[i++] = DBG_S_C_STRUCT_START;
+ Local[i++] = DST_K_VFLAGS_NOVAL; /* structure definition only */
+ COPY_LONG (&Local[i], 0L); /* hence value is unused */
+ i += 4;
+ Local[i++] = strlen (pnt);
+ pnt2 = pnt;
+ while (*pnt2 != '\0')
+ Local[i++] = *pnt2++;
+ i2 = spnt->data_size * 8; /* number of bits */
+ COPY_LONG (&Local[i], i2);
+ i += 4;
+ VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
+ i = 0;
+ if (pnt != symbol_name)
+ {
+ pnt += strlen (pnt);
+ *pnt = ':';
+ } /* replace colon for later */
+ while (*++pnt1 != ';')
+ {
+ pnt = (char *) strchr (pnt1, ':');
+ *pnt = '\0';
+ pnt2 = pnt1;
+ pnt1 = cvt_integer (pnt + 1, &dtype);
+ pnt1 = cvt_integer (pnt1 + 1, &i2);
+ pnt1 = cvt_integer (pnt1 + 1, &i3);
+ spnt1 = find_symbol (dtype);
+ len = strlen (pnt2);
+ if (spnt1 && (spnt1->advanced == BASIC || spnt1->advanced == ENUM)
+ && ((i3 != spnt1->data_size * 8) || (i2 % 8 != 0)))
+ { /* bitfield */
+ if (USE_BITSTRING_DESCRIPTOR (spnt1))
+ {
+ /* This uses a type descriptor, which doesn't work if
+ the enclosing structure has been placed in a register.
+ Also, enum bitfields degenerate to simple integers. */
+ int unsigned_type = (spnt1->VMS_type == DBG_S_C_ULINT
+ || spnt1->VMS_type == DBG_S_C_USINT
+ || spnt1->VMS_type == DBG_S_C_UCHAR
+ || spnt1->VMS_type == DBG_S_C_UQUAD
+ || spnt1->advanced == ENUM); /* (approximate) */
+ Apoint = 0;
+ fpush (19 + len, 1);
+ fpush (unsigned_type ? DBG_S_C_UBITU : DBG_S_C_SBITU, 1);
+ fpush (DST_K_VFLAGS_DSC, 1); /* specified by descriptor */
+ fpush (1 + len, 4); /* relative offset to descriptor */
+ fpush (len, 1); /* length byte (ascic prefix) */
+ while (*pnt2 != '\0') /* name bytes */
+ fpush (*pnt2++, 1);
+ fpush (i3, 2); /* dsc length == size of bitfield */
+ /* dsc type == un?signed bitfield */
+ fpush (unsigned_type ? DBG_S_C_UBITU : DBG_S_C_SBITU, 1);
+ fpush (DSC_K_CLASS_UBS, 1); /* dsc class == unaligned bitstring */
+ fpush (0x00, 4); /* dsc pointer == zeroes */
+ fpush (i2, 4); /* start position */
+ VMS_Store_Immediate_Data (Asuffix, Apoint, OBJ_S_C_DBG);
+ Apoint = 0;
+ }
+ else
+ {
+ /* Use a "novel length" type specification, which works
+ right for register structures and for enum bitfields
+ but results in larger object modules. */
+ Local[i++] = 7 + len;
+ Local[i++] = DBG_S_C_ADVANCED_TYPE; /* type spec follows */
+ Local[i++] = DBG_S_C_STRUCT_ITEM; /* value is a bit offset */
+ COPY_LONG (&Local[i], i2); /* bit offset */
+ i += 4;
+ Local[i++] = strlen (pnt2);
+ while (*pnt2 != '\0')
+ Local[i++] = *pnt2++;
+ VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
+ i = 0;
+ bitfield_suffix (spnt1, i3);
+ }
+ }
+ else
+ { /* not a bitfield */
+ /* check if this is a forward reference */
+ if (final_pass && final_forward_reference (spnt1))
+ {
+ as_tsktsk (_("debugger output: structure element `%s' has undefined type"),
+ pnt2);
+ continue;
+ }
+ Local[i++] = 7 + len;
+ Local[i++] = spnt1 ? spnt1->VMS_type : DBG_S_C_ADVANCED_TYPE;
+ Local[i++] = DBG_S_C_STRUCT_ITEM;
+ COPY_LONG (&Local[i], i2); /* bit offset */
+ i += 4;
+ Local[i++] = strlen (pnt2);
+ while (*pnt2 != '\0')
+ Local[i++] = *pnt2++;
+ VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
+ i = 0;
+ if (!spnt1)
+ generate_suffix (spnt1, dtype);
+ else if (spnt1->VMS_type == DBG_S_C_ADVANCED_TYPE)
+ generate_suffix (spnt1, 0);
+ }
+ }
+ pnt1++;
+ Local[i++] = 0x01; /* length byte */
+ Local[i++] = DBG_S_C_STRUCT_END;
+ VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
+ i = 0;
+ break;
+ case 'e':
+ spnt->advanced = ENUM;
+ spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
+ spnt->struc_numb = ++structure_count;
+ spnt->data_size = 4;
+ VMS_Def_Struct (spnt->struc_numb);
+ i = 0;
+ for (fpnt = f_ref_root; fpnt; fpnt = fpnt->next)
+ if (fpnt->dbx_type == spnt->dbx_type)
+ {
+ fpnt->resolved = 'Y';
+ VMS_Set_Struct (fpnt->struc_numb);
+ VMS_Store_Struct (spnt->struc_numb);
+ i++;
+ }
+ if (i > 0)
+ VMS_Set_Struct (spnt->struc_numb);
+ i = 0;
+ len = strlen (symbol_name);
+ Local[i++] = 3 + len;
+ Local[i++] = DBG_S_C_ENUM_START;
+ Local[i++] = 4 * 8; /* enum values are 32 bits */
+ Local[i++] = len;
+ pnt2 = symbol_name;
+ while (*pnt2 != '\0')
+ Local[i++] = *pnt2++;
+ VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
+ i = 0;
+ while (*++pnt != ';')
+ {
+ pnt1 = (char *) strchr (pnt, ':');
+ *pnt1++ = '\0';
+ pnt1 = cvt_integer (pnt1, &i1);
+ len = strlen (pnt);
+ Local[i++] = 7 + len;
+ Local[i++] = DBG_S_C_ENUM_ITEM;
+ Local[i++] = DST_K_VALKIND_LITERAL;
+ COPY_LONG (&Local[i], i1);
+ i += 4;
+ Local[i++] = len;
+ pnt2 = pnt;
+ while (*pnt != '\0')
+ Local[i++] = *pnt++;
+ VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
+ i = 0;
+ pnt = pnt1; /* Skip final semicolon */
+ }
+ Local[i++] = 0x01; /* len byte */
+ Local[i++] = DBG_S_C_ENUM_END;
+ VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
+ i = 0;
+ pnt1 = pnt + 1;
+ break;
+ case 'a':
+ spnt->advanced = ARRAY;
+ spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
+ pnt = (char *) strchr (pnt, ';');
+ if (!pnt)
+ return 1;
+ pnt1 = cvt_integer (pnt + 1, &spnt->index_min);
+ pnt1 = cvt_integer (pnt1 + 1, &spnt->index_max);
+ pnt1 = cvt_integer (pnt1 + 1, &spnt->type2);
+ pnt = (char *) strchr (str + 1, '=');
+ if (pnt && VMS_typedef_parse (pnt) == 1)
+ return 1;
+ break;
+ case 'f':
+ spnt->advanced = FUNCTION;
+ spnt->VMS_type = DBG_S_C_FUNCTION_ADDR;
+ /* this masquerades as a basic type*/
+ spnt->data_size = 4;
+ pnt1 = cvt_integer (pnt + 1, &spnt->type2);
+ break;
+ case '*':
+ spnt->advanced = POINTER;
+ spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
+ spnt->data_size = 4;
+ pnt1 = cvt_integer (pnt + 1, &spnt->type2);
+ pnt = (char *) strchr (str + 1, '=');
+ if (pnt && VMS_typedef_parse (pnt) == 1)
+ return 1;
+ break;
+ default:
+ spnt->advanced = UNKNOWN;
+ spnt->VMS_type = 0;
+ as_tsktsk (_("debugger output: %d is an unknown type of variable."),
+ spnt->dbx_type);
+ return 1; /* unable to decipher */
+ }
+ /* This removes the evidence of the definition so that the outer levels
+ of parsing do not have to worry about it. */
+ pnt = str;
+ while (*pnt1 != '\0')
+ *pnt++ = *pnt1++;
+ *pnt = '\0';
+ return 0;
+}
+
+
+/* This is the root routine that parses the stabs entries for definitions.
+ it calls VMS_typedef_parse, which can in turn call itself. We need to
+ be careful, since sometimes there are forward references to other symbol
+ types, and these cannot be resolved until we have completed the parse.
+
+ Also check and see if we are using continuation stabs, if we are, then
+ paste together the entire contents of the stab before we pass it to
+ VMS_typedef_parse. */
+
+static void
+VMS_LSYM_Parse ()
+{
+ char *pnt;
+ char *pnt1;
+ char *pnt2;
+ char *str;
+ char *parse_buffer = 0;
+ char fixit[10];
+ int incomplete, pass, incom1;
+ struct forward_ref *fpnt;
+ symbolS *sp;
+
+ pass = 0;
+ final_pass = 0;
+ incomplete = 0;
+ do
+ {
+ incom1 = incomplete;
+ incomplete = 0;
+ for (sp = symbol_rootP; sp; sp = symbol_next (sp))
+ {
+ /*
+ * Deal with STAB symbols
+ */
+ if (S_IS_DEBUG (sp))
+ {
+ /*
+ * Dispatch on STAB type
+ */
+ switch (S_GET_RAW_TYPE (sp))
+ {
+ case N_GSYM:
+ case N_LCSYM:
+ case N_STSYM:
+ case N_PSYM:
+ case N_RSYM:
+ case N_LSYM:
+ case N_FUN: /*sometimes these contain typedefs*/
+ str = S_GET_NAME (sp);
+ symbol_name = str;
+ pnt = str + strlen (str) - 1;
+ if (*pnt == '?') /* Continuation stab. */
+ {
+ symbolS *spnext;
+ int tlen = 0;
+
+ spnext = sp;
+ do {
+ tlen += strlen (str) - 1;
+ spnext = symbol_next (spnext);
+ str = S_GET_NAME (spnext);
+ pnt = str + strlen (str) - 1;
+ } while (*pnt == '?');
+ tlen += strlen (str);
+ parse_buffer = (char *) xmalloc (tlen + 1);
+ strcpy (parse_buffer, S_GET_NAME (sp));
+ pnt2 = parse_buffer + strlen (parse_buffer) - 1;
+ *pnt2 = '\0';
+ spnext = sp;
+ do {
+ spnext = symbol_next (spnext);
+ str = S_GET_NAME (spnext);
+ strcat (pnt2, str);
+ pnt2 += strlen (str) - 1;
+ *str = '\0'; /* Erase this string */
+ /* S_SET_NAME (spnext, str); */
+ if (*pnt2 != '?') break;
+ *pnt2 = '\0';
+ } while (1);
+ str = parse_buffer;
+ symbol_name = str;
+ }
+ if ((pnt = (char *) strchr (str, ':')) != 0)
+ {
+ *pnt = '\0';
+ pnt1 = pnt + 1;
+ if ((pnt2 = (char *) strchr (pnt1, '=')) != 0)
+ incomplete += VMS_typedef_parse (pnt2);
+ if (parse_buffer)
+ {
+ /* At this point the parse buffer should just
+ contain name:nn. If it does not, then we
+ are in real trouble. Anyway, this is always
+ shorter than the original line. */
+ pnt2 = S_GET_NAME (sp);
+ strcpy (pnt2, parse_buffer);
+ /* S_SET_NAME (sp, pnt2); */
+ free (parse_buffer), parse_buffer = 0;
+ }
+ *pnt = ':'; /* put back colon to restore dbx_type */
+ }
+ break;
+ } /*switch*/
+ } /* if */
+ } /*for*/
+ pass++;
+ /*
+ * Make one last pass, if needed, and define whatever we can
+ * that is left.
+ */
+ if (final_pass == 0 && incomplete == incom1)
+ {
+ final_pass = 1;
+ incom1++; /* Force one last pass through */
+ }
+ } while (incomplete != 0 && incomplete != incom1);
+ /* repeat until all refs resolved if possible */
+/* if (pass > 1) printf (" Required %d passes\n", pass); */
+ if (incomplete != 0)
+ {
+ as_tsktsk (_("debugger output: Unable to resolve %d circular references."),
+ incomplete);
+ }
+ fpnt = f_ref_root;
+ symbol_name = "\0";
+ while (fpnt)
+ {
+ if (fpnt->resolved != 'Y')
+ {
+ if (find_symbol (fpnt->dbx_type))
+ {
+ as_tsktsk (_("debugger forward reference error, dbx type %d"),
+ fpnt->dbx_type);
+ break;
+ }
+ fixit[0] = 0;
+ sprintf (&fixit[1], "%d=s4;", fpnt->dbx_type);
+ pnt2 = (char *) strchr (&fixit[1], '=');
+ VMS_typedef_parse (pnt2);
+ }
+ fpnt = fpnt->next;
+ }
+}
+
+
+static void
+Define_Local_Symbols (s0P, s2P, Current_Routine, Text_Psect)
+ symbolS *s0P, *s2P;
+ symbolS *Current_Routine;
+ int Text_Psect;
+{
+ symbolS *s1P; /* each symbol from s0P .. s2P (exclusive) */
+
+ for (s1P = symbol_next (s0P); s1P != s2P; s1P = symbol_next (s1P))
+ {
+ if (!s1P)
+ break; /* and return */
+ if (S_GET_RAW_TYPE (s1P) == N_FUN)
+ {
+ char *pnt = (char *) strchr (S_GET_NAME (s1P), ':') + 1;
+ if (*pnt == 'F' || *pnt == 'f') break;
+ }
+ if (!S_IS_DEBUG (s1P))
+ continue;
+ /*
+ * Dispatch on STAB type
+ */
+ switch (S_GET_RAW_TYPE (s1P))
+ {
+ default:
+ continue; /* not left or right brace */
+
+ case N_LSYM:
+ case N_PSYM:
+ VMS_local_stab_Parse (s1P);
+ break;
+
+ case N_RSYM:
+ VMS_RSYM_Parse (s1P, Current_Routine, Text_Psect);
+ break;
+ } /*switch*/
+ } /* for */
+}
+
+
+/* This function crawls the symbol chain searching for local symbols that
+ need to be described to the debugger. When we enter a new scope with
+ a "{", it creates a new "block", which helps the debugger keep track
+ of which scope we are currently in. */
+
+static symbolS *
+Define_Routine (s0P, Level, Current_Routine, Text_Psect)
+ symbolS *s0P;
+ int Level;
+ symbolS *Current_Routine;
+ int Text_Psect;
+{
+ symbolS *s1P;
+ valueT Offset;
+ int rcount = 0;
+
+ for (s1P = symbol_next (s0P); s1P != 0; s1P = symbol_next (s1P))
+ {
+ if (S_GET_RAW_TYPE (s1P) == N_FUN)
+ {
+ char *pnt = (char *) strchr (S_GET_NAME (s1P), ':') + 1;
+ if (*pnt == 'F' || *pnt == 'f') break;
+ }
+ if (!S_IS_DEBUG (s1P))
+ continue;
+ /*
+ * Dispatch on STAB type
+ */
+ switch (S_GET_RAW_TYPE (s1P))
+ {
+ default:
+ continue; /* not left or right brace */
+
+ case N_LBRAC:
+ if (Level != 0)
+ {
+ char str[10];
+ sprintf (str, "$%d", rcount++);
+ VMS_TBT_Block_Begin (s1P, Text_Psect, str);
+ }
+ Offset = S_GET_VALUE (s1P); /* side-effect: fully resolve symbol */
+ Define_Local_Symbols (s0P, s1P, Current_Routine, Text_Psect);
+ s1P = Define_Routine (s1P, Level + 1, Current_Routine, Text_Psect);
+ if (Level != 0)
+ VMS_TBT_Block_End (S_GET_VALUE (s1P) - Offset);
+ s0P = s1P;
+ break;
+
+ case N_RBRAC:
+ return s1P;
+ } /*switch*/
+ } /* for */
+
+ /* We end up here if there were no brackets in this function.
+ Define everything. */
+ Define_Local_Symbols (s0P, (symbolS *)0, Current_Routine, Text_Psect);
+ return s1P;
+}
+
+
+#ifndef VMS
+#include <sys/types.h>
+#include <time.h>
+static void get_VMS_time_on_unix PARAMS ((char *));
+
+/* Manufacture a VMS-like time string on a Unix based system. */
+static void
+get_VMS_time_on_unix (Now)
+ char *Now;
+{
+ char *pnt;
+ time_t timeb;
+
+ time (&timeb);
+ pnt = ctime (&timeb);
+ pnt[3] = 0;
+ pnt[7] = 0;
+ pnt[10] = 0;
+ pnt[16] = 0;
+ pnt[24] = 0;
+ sprintf (Now, "%2s-%3s-%s %s", pnt + 8, pnt + 4, pnt + 20, pnt + 11);
+}
+#endif /* not VMS */
+
+
+/* Write the MHD (Module Header) records. */
+
+static void
+Write_VMS_MHD_Records ()
+{
+ register const char *cp;
+ register char *cp1;
+ register int i;
+#ifdef VMS
+ struct { unsigned short len, mbz; char *ptr; } Descriptor;
+#endif
+ char Now[17+1];
+
+ /* We are writing a module header record. */
+ Set_VMS_Object_File_Record (OBJ_S_C_HDR);
+ /*
+ * ***************************
+ * *MAIN MODULE HEADER RECORD*
+ * ***************************
+ */
+ /* Store record type and header type. */
+ PUT_CHAR (OBJ_S_C_HDR);
+ PUT_CHAR (MHD_S_C_MHD);
+ /* Structure level is 0. */
+ PUT_CHAR (OBJ_S_C_STRLVL);
+ /* Maximum record size is size of the object record buffer. */
+ PUT_SHORT (sizeof (Object_Record_Buffer));
+
+ /*
+ * FIXME: module name and version should be user
+ * specifiable via `.ident' and/or `#pragma ident'.
+ */
+
+ /* Get module name (the FILENAME part of the object file). */
+ cp = out_file_name;
+ cp1 = Module_Name;
+ while (*cp)
+ {
+ if (*cp == ']' || *cp == '>' || *cp == ':' || *cp == '/')
+ {
+ cp1 = Module_Name;
+ cp++;
+ continue;
+ }
+ *cp1++ = islower (*cp) ? toupper (*cp++) : *cp++;
+ }
+ *cp1 = '\0';
+
+ /* Limit it to 31 characters and store in the object record. */
+ while (--cp1 >= Module_Name)
+ if (*cp1 == '.')
+ *cp1 = '\0';
+ if (strlen (Module_Name) > 31)
+ {
+ if (flag_hash_long_names)
+ as_tsktsk (_("Module name truncated: %s\n"), Module_Name);
+ Module_Name[31] = '\0';
+ }
+ PUT_COUNTED_STRING (Module_Name);
+ /* Module Version is "V1.0". */
+ PUT_COUNTED_STRING ("V1.0");
+ /* Creation time is "now" (17 chars of time string): "dd-MMM-yyyy hh:mm". */
+#ifndef VMS
+ get_VMS_time_on_unix (Now);
+#else /* VMS */
+ Descriptor.len = sizeof Now - 1;
+ Descriptor.mbz = 0; /* type & class unspecified */
+ Descriptor.ptr = Now;
+ (void) sys$asctim ((unsigned short *)0, &Descriptor, (long *)0, 0);
+#endif /* VMS */
+ for (i = 0; i < 17; i++)
+ PUT_CHAR (Now[i]);
+ /* Patch time is "never" (17 zeros). */
+ for (i = 0; i < 17; i++)
+ PUT_CHAR (0);
+ /* Force this to be a separate output record. */
+ Flush_VMS_Object_Record_Buffer ();
+
+ /*
+ * *************************
+ * *LANGUAGE PROCESSOR NAME*
+ * *************************
+ */
+ /* Store record type and header type. */
+ PUT_CHAR (OBJ_S_C_HDR);
+ PUT_CHAR (MHD_S_C_LNM);
+ /*
+ * Store language processor name and version (not a counted string!).
+ *
+ * This is normally supplied by the gcc driver for the command line
+ * which invokes gas. If absent, we fall back to gas's version.
+ */
+ cp = compiler_version_string;
+ if (cp == 0)
+ {
+ cp = "GNU AS V";
+ while (*cp)
+ PUT_CHAR (*cp++);
+ cp = VERSION;
+ }
+ while (*cp >= ' ')
+ PUT_CHAR (*cp++);
+ /* Force this to be a separate output record. */
+ Flush_VMS_Object_Record_Buffer ();
+}
+
+
+/* Write the EOM (End Of Module) record. */
+
+static void
+Write_VMS_EOM_Record (Psect, Offset)
+ int Psect;
+ valueT Offset;
+{
+ /*
+ * We are writing an end-of-module record
+ * (this assumes that the entry point will always be in a psect
+ * represented by a single byte, which is the case for code in
+ * Text_Psect==0)
+ */
+ Set_VMS_Object_File_Record (OBJ_S_C_EOM);
+ PUT_CHAR (OBJ_S_C_EOM); /* Record type. */
+ PUT_CHAR (0); /* Error severity level (we ignore it). */
+ /*
+ * Store the entry point, if it exists
+ */
+ if (Psect >= 0)
+ {
+ PUT_CHAR (Psect);
+ PUT_LONG (Offset);
+ }
+ /* Flush the record; this will be our final output. */
+ Flush_VMS_Object_Record_Buffer ();
+}
+
+
+/* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/
+
+static int
+hash_string (ptr)
+ const char *ptr;
+{
+ register const unsigned char *p = (unsigned char *) ptr;
+ register const unsigned char *end = p + strlen (ptr);
+ register unsigned char c;
+ register int hash = 0;
+
+ while (p != end)
+ {
+ c = *p++;
+ hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
+ }
+ return hash;
+}
+
+/*
+ * Generate a Case-Hacked VMS symbol name (limited to 31 chars)
+ */
+static void
+VMS_Case_Hack_Symbol (In, Out)
+ register const char *In;
+ register char *Out;
+{
+ long int init;
+ long int result;
+ char *pnt = 0;
+ char *new_name;
+ const char *old_name;
+ register int i;
+ int destructor = 0; /*hack to allow for case sens in a destructor*/
+ int truncate = 0;
+ int Case_Hack_Bits = 0;
+ int Saw_Dollar = 0;
+ static char Hex_Table[16] =
+ {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+ /*
+ * Kill any leading "_"
+ */
+ if ((In[0] == '_') && ((In[1] > '9') || (In[1] < '0')))
+ In++;
+
+ new_name = Out; /* save this for later*/
+
+#if barfoo /* Dead code */
+ if ((In[0] == '_') && (In[1] == '$') && (In[2] == '_'))
+ destructor = 1;
+#endif
+
+ /* We may need to truncate the symbol, save the hash for later*/
+ result = (strlen (In) > 23) ? hash_string (In) : 0;
+ /*
+ * Is there a Psect Attribute to skip??
+ */
+ if (HAS_PSECT_ATTRIBUTES (In))
+ {
+ /*
+ * Yes: Skip it
+ */
+ In += PSECT_ATTRIBUTES_STRING_LENGTH;
+ while (*In)
+ {
+ if ((In[0] == '$') && (In[1] == '$'))
+ {
+ In += 2;
+ break;
+ }
+ In++;
+ }
+ }
+
+ old_name = In;
+/* if (strlen (In) > 31 && flag_hash_long_names)
+ as_tsktsk ("Symbol name truncated: %s\n", In); */
+ /*
+ * Do the case conversion
+ */
+ i = 23; /* Maximum of 23 chars */
+ while (*In && (--i >= 0))
+ {
+ Case_Hack_Bits <<= 1;
+ if (*In == '$')
+ Saw_Dollar = 1;
+ if ((destructor == 1) && (i == 21))
+ Saw_Dollar = 0;
+ switch (vms_name_mapping)
+ {
+ case 0:
+ if (isupper (*In)) {
+ *Out++ = *In++;
+ Case_Hack_Bits |= 1;
+ } else {
+ *Out++ = islower (*In) ? toupper (*In++) : *In++;
+ }
+ break;
+ case 3: *Out++ = *In++;
+ break;
+ case 2:
+ if (islower (*In)) {
+ *Out++ = *In++;
+ } else {
+ *Out++ = isupper (*In) ? tolower (*In++) : *In++;
+ }
+ break;
+ }
+ }
+ /*
+ * If we saw a dollar sign, we don't do case hacking
+ */
+ if (flag_no_hash_mixed_case || Saw_Dollar)
+ Case_Hack_Bits = 0;
+
+ /*
+ * If we have more than 23 characters and everything is lowercase
+ * we can insert the full 31 characters
+ */
+ if (*In)
+ {
+ /*
+ * We have more than 23 characters
+ * If we must add the case hack, then we have truncated the str
+ */
+ pnt = Out;
+ truncate = 1;
+ if (Case_Hack_Bits == 0)
+ {
+ /*
+ * And so far they are all lower case:
+ * Check up to 8 more characters
+ * and ensure that they are lowercase
+ */
+ for (i = 0; (In[i] != 0) && (i < 8); i++)
+ if (isupper (In[i]) && !Saw_Dollar && !flag_no_hash_mixed_case)
+ break;
+
+ if (In[i] == 0)
+ truncate = 0;
+
+ if ((i == 8) || (In[i] == 0))
+ {
+ /*
+ * They are: Copy up to 31 characters
+ * to the output string
+ */
+ i = 8;
+ while ((--i >= 0) && (*In))
+ switch (vms_name_mapping){
+ case 0: *Out++ = islower (*In) ? toupper (*In++) : *In++;
+ break;
+ case 3: *Out++ = *In++;
+ break;
+ case 2: *Out++ = isupper (*In) ? tolower (*In++) : *In++;
+ break;
+ }
+ }
+ }
+ }
+ /*
+ * If there were any uppercase characters in the name we
+ * take on the case hacking string
+ */
+
+ /* Old behavior for regular GNU-C compiler */
+ if (!flag_hash_long_names)
+ truncate = 0;
+ if ((Case_Hack_Bits != 0) || (truncate == 1))
+ {
+ if (truncate == 0)
+ {
+ *Out++ = '_';
+ for (i = 0; i < 6; i++)
+ {
+ *Out++ = Hex_Table[Case_Hack_Bits & 0xf];
+ Case_Hack_Bits >>= 4;
+ }
+ *Out++ = 'X';
+ }
+ else
+ {
+ Out = pnt; /*Cut back to 23 characters maximum */
+ *Out++ = '_';
+ for (i = 0; i < 7; i++)
+ {
+ init = result & 0x01f;
+ *Out++ = (init < 10) ? ('0' + init) : ('A' + init - 10);
+ result = result >> 5;
+ }
+ }
+ } /*Case Hack */
+ /*
+ * Done
+ */
+ *Out = 0;
+ if (truncate == 1 && flag_hash_long_names && flag_show_after_trunc)
+ as_tsktsk (_("Symbol %s replaced by %s\n"), old_name, new_name);
+}
+
+
+/*
+ * Scan a symbol name for a psect attribute specification
+ */
+#define GLOBALSYMBOL_BIT 0x10000
+#define GLOBALVALUE_BIT 0x20000
+
+
+static void
+VMS_Modify_Psect_Attributes (Name, Attribute_Pointer)
+ const char *Name;
+ int *Attribute_Pointer;
+{
+ register int i;
+ register const char *cp;
+ int Negate;
+ static const struct
+ {
+ const char *Name;
+ int Value;
+ } Attributes[] =
+ {
+ {"PIC", GPS_S_M_PIC},
+ {"LIB", GPS_S_M_LIB},
+ {"OVR", GPS_S_M_OVR},
+ {"REL", GPS_S_M_REL},
+ {"GBL", GPS_S_M_GBL},
+ {"SHR", GPS_S_M_SHR},
+ {"EXE", GPS_S_M_EXE},
+ {"RD", GPS_S_M_RD},
+ {"WRT", GPS_S_M_WRT},
+ {"VEC", GPS_S_M_VEC},
+ {"GLOBALSYMBOL", GLOBALSYMBOL_BIT},
+ {"GLOBALVALUE", GLOBALVALUE_BIT},
+ {0, 0}
+ };
+
+ /*
+ * Kill leading "_"
+ */
+ if (*Name == '_')
+ Name++;
+ /*
+ * Check for a PSECT attribute list
+ */
+ if (!HAS_PSECT_ATTRIBUTES (Name))
+ return; /* If not, return */
+ /*
+ * Skip the attribute list indicator
+ */
+ Name += PSECT_ATTRIBUTES_STRING_LENGTH;
+ /*
+ * Process the attributes ("_" separated, "$" terminated)
+ */
+ while (*Name != '$')
+ {
+ /*
+ * Assume not negating
+ */
+ Negate = 0;
+ /*
+ * Check for "NO"
+ */
+ if ((Name[0] == 'N') && (Name[1] == 'O'))
+ {
+ /*
+ * We are negating (and skip the NO)
+ */
+ Negate = 1;
+ Name += 2;
+ }
+ /*
+ * Find the token delimiter
+ */
+ cp = Name;
+ while (*cp && (*cp != '_') && (*cp != '$'))
+ cp++;
+ /*
+ * Look for the token in the attribute list
+ */
+ for (i = 0; Attributes[i].Name; i++)
+ {
+ /*
+ * If the strings match, set/clear the attr.
+ */
+ if (strncmp (Name, Attributes[i].Name, cp - Name) == 0)
+ {
+ /*
+ * Set or clear
+ */
+ if (Negate)
+ *Attribute_Pointer &=
+ ~Attributes[i].Value;
+ else
+ *Attribute_Pointer |=
+ Attributes[i].Value;
+ /*
+ * Done
+ */
+ break;
+ }
+ }
+ /*
+ * Now skip the attribute
+ */
+ Name = cp;
+ if (*Name == '_')
+ Name++;
+ }
+}
+
+
+#define GBLSYM_REF 0
+#define GBLSYM_DEF 1
+#define GBLSYM_VAL 2
+#define GBLSYM_LCL 4 /* not GBL after all... */
+#define GBLSYM_WEAK 8
+
+/*
+ * Define a global symbol (or possibly a local one).
+ */
+static void
+VMS_Global_Symbol_Spec (Name, Psect_Number, Psect_Offset, Flags)
+ const char *Name;
+ int Psect_Number;
+ int Psect_Offset;
+ int Flags;
+{
+ char Local[32];
+
+ /*
+ * We are writing a GSD record
+ */
+ Set_VMS_Object_File_Record (OBJ_S_C_GSD);
+ /*
+ * If the buffer is empty we must insert the GSD record type
+ */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (OBJ_S_C_GSD);
+ /*
+ * We are writing a Global (or local) symbol definition subrecord.
+ */
+ PUT_CHAR ((Flags & GBLSYM_LCL) != 0 ? GSD_S_C_LSY :
+ ((unsigned) Psect_Number <= 255) ? GSD_S_C_SYM : GSD_S_C_SYMW);
+ /*
+ * Data type is undefined
+ */
+ PUT_CHAR (0);
+ /*
+ * Switch on Definition/Reference
+ */
+ if ((Flags & GBLSYM_DEF) == 0)
+ {
+ /*
+ * Reference
+ */
+ PUT_SHORT (((Flags & GBLSYM_VAL) == 0) ? GSY_S_M_REL : 0);
+ if ((Flags & GBLSYM_LCL) != 0) /* local symbols have extra field */
+ PUT_SHORT (Current_Environment);
+ }
+ else
+ {
+ int sym_flags;
+
+ /*
+ * Definition
+ *[ assert (LSY_S_M_DEF == GSY_S_M_DEF && LSY_S_M_REL == GSY_S_M_REL); ]
+ */
+ sym_flags = GSY_S_M_DEF;
+ if (Flags & GBLSYM_WEAK)
+ sym_flags |= GSY_S_M_WEAK;
+ if ((Flags & GBLSYM_VAL) == 0)
+ sym_flags |= GSY_S_M_REL;
+ PUT_SHORT (sym_flags);
+ if ((Flags & GBLSYM_LCL) != 0) /* local symbols have extra field */
+ PUT_SHORT (Current_Environment);
+ /*
+ * Psect Number
+ */
+ if ((Flags & GBLSYM_LCL) == 0 && (unsigned) Psect_Number <= 255)
+ PUT_CHAR (Psect_Number);
+ else
+ PUT_SHORT (Psect_Number);
+ /*
+ * Offset
+ */
+ PUT_LONG (Psect_Offset);
+ }
+ /*
+ * Finally, the global symbol name
+ */
+ VMS_Case_Hack_Symbol (Name, Local);
+ PUT_COUNTED_STRING (Local);
+ /*
+ * Flush the buffer if it is more than 75% full
+ */
+ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
+ Flush_VMS_Object_Record_Buffer ();
+}
+
+/*
+ * Define an environment to support local symbol references.
+ * This is just to mollify the linker; we don't actually do
+ * anything useful with it.
+ */
+static void
+VMS_Local_Environment_Setup (Env_Name)
+ const char *Env_Name;
+{
+ /* We are writing a GSD record. */
+ Set_VMS_Object_File_Record (OBJ_S_C_GSD);
+ /* If the buffer is empty we must insert the GSD record type. */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (OBJ_S_C_GSD);
+ /* We are writing an ENV subrecord. */
+ PUT_CHAR (GSD_S_C_ENV);
+
+ ++Current_Environment; /* index of environment being defined */
+
+ /* ENV$W_FLAGS: we are defining the next environment. It's not nested. */
+ PUT_SHORT (ENV_S_M_DEF);
+ /* ENV$W_ENVINDX: index is always 0 for non-nested definitions. */
+ PUT_SHORT (0);
+
+ /* ENV$B_NAMLNG + ENV$T_NAME: environment name in ASCIC format. */
+ if (!Env_Name) Env_Name = "";
+ PUT_COUNTED_STRING ((char *)Env_Name);
+
+ /* Flush the buffer if it is more than 75% full. */
+ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
+ Flush_VMS_Object_Record_Buffer ();
+}
+
+
+/*
+ * Define a psect
+ */
+static int
+VMS_Psect_Spec (Name, Size, Type, vsp)
+ const char *Name;
+ int Size;
+ enum ps_type Type;
+ struct VMS_Symbol *vsp;
+{
+ char Local[32];
+ int Psect_Attributes;
+
+ /*
+ * Generate the appropriate PSECT flags given the PSECT type
+ */
+ switch (Type)
+ {
+ case ps_TEXT:
+ /* Text psects are PIC,noOVR,REL,noGBL,SHR,EXE,RD,noWRT. */
+ Psect_Attributes = (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_SHR|GPS_S_M_EXE
+ |GPS_S_M_RD);
+ break;
+ case ps_DATA:
+ /* Data psects are PIC,noOVR,REL,noGBL,noSHR,noEXE,RD,WRT. */
+ Psect_Attributes = (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_RD|GPS_S_M_WRT);
+ break;
+ case ps_COMMON:
+ /* Common block psects are: PIC,OVR,REL,GBL,noSHR,noEXE,RD,WRT. */
+ Psect_Attributes = (GPS_S_M_PIC|GPS_S_M_OVR|GPS_S_M_REL|GPS_S_M_GBL
+ |GPS_S_M_RD|GPS_S_M_WRT);
+ break;
+ case ps_CONST:
+ /* Const data psects are: PIC,OVR,REL,GBL,noSHR,noEXE,RD,noWRT. */
+ Psect_Attributes = (GPS_S_M_PIC|GPS_S_M_OVR|GPS_S_M_REL|GPS_S_M_GBL
+ |GPS_S_M_RD);
+ break;
+ case ps_CTORS:
+ /* Ctor psects are PIC,noOVR,REL,GBL,noSHR,noEXE,RD,noWRT. */
+ Psect_Attributes = (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_GBL|GPS_S_M_RD);
+ break;
+ case ps_DTORS:
+ /* Dtor psects are PIC,noOVR,REL,GBL,noSHR,noEXE,RD,noWRT. */
+ Psect_Attributes = (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_GBL|GPS_S_M_RD);
+ break;
+ default:
+ /* impossible */
+ error (_("Unknown VMS psect type (%ld)"), (long) Type);
+ break;
+ }
+ /*
+ * Modify the psect attributes according to any attribute string
+ */
+ if (vsp && S_GET_TYPE (vsp->Symbol) == N_ABS)
+ Psect_Attributes |= GLOBALVALUE_BIT;
+ else if (HAS_PSECT_ATTRIBUTES (Name))
+ VMS_Modify_Psect_Attributes (Name, &Psect_Attributes);
+ /*
+ * Check for globalref/def/val.
+ */
+ if ((Psect_Attributes & GLOBALVALUE_BIT) != 0)
+ {
+ /*
+ * globalvalue symbols were generated before. This code
+ * prevents unsightly psect buildup, and makes sure that
+ * fixup references are emitted correctly.
+ */
+ vsp->Psect_Index = -1; /* to catch errors */
+ S_SET_TYPE (vsp->Symbol, N_UNDF); /* make refs work */
+ return 1; /* decrement psect counter */
+ }
+
+ if ((Psect_Attributes & GLOBALSYMBOL_BIT) != 0)
+ {
+ switch (S_GET_RAW_TYPE (vsp->Symbol))
+ {
+ case N_UNDF | N_EXT:
+ VMS_Global_Symbol_Spec (Name, vsp->Psect_Index,
+ vsp->Psect_Offset, GBLSYM_REF);
+ vsp->Psect_Index = -1;
+ S_SET_TYPE (vsp->Symbol, N_UNDF);
+ return 1; /* return and indicate no psect */
+ case N_DATA | N_EXT:
+ VMS_Global_Symbol_Spec (Name, vsp->Psect_Index,
+ vsp->Psect_Offset, GBLSYM_DEF);
+ /* In this case we still generate the psect */
+ break;
+ default:
+ as_fatal (_("Globalsymbol attribute for symbol %s was unexpected."),
+ Name);
+ break;
+ } /* switch */
+ }
+
+ Psect_Attributes &= 0xffff; /* clear out the globalref/def stuff */
+ /*
+ * We are writing a GSD record
+ */
+ Set_VMS_Object_File_Record (OBJ_S_C_GSD);
+ /*
+ * If the buffer is empty we must insert the GSD record type
+ */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (OBJ_S_C_GSD);
+ /*
+ * We are writing a PSECT definition subrecord
+ */
+ PUT_CHAR (GSD_S_C_PSC);
+ /*
+ * Psects are always LONGWORD aligned
+ */
+ PUT_CHAR (2);
+ /*
+ * Specify the psect attributes
+ */
+ PUT_SHORT (Psect_Attributes);
+ /*
+ * Specify the allocation
+ */
+ PUT_LONG (Size);
+ /*
+ * Finally, the psect name
+ */
+ VMS_Case_Hack_Symbol (Name, Local);
+ PUT_COUNTED_STRING (Local);
+ /*
+ * Flush the buffer if it is more than 75% full
+ */
+ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
+ Flush_VMS_Object_Record_Buffer ();
+ return 0;
+}
+
+
+/* Given the pointer to a symbol we calculate how big the data at the
+ symbol is. We do this by looking for the next symbol (local or global)
+ which will indicate the start of another datum. */
+
+static offsetT
+VMS_Initialized_Data_Size (s0P, End_Of_Data)
+ register symbolS *s0P;
+ unsigned End_Of_Data;
+{
+ symbolS *s1P;
+ valueT s0P_val = S_GET_VALUE (s0P), s1P_val,
+ nearest_val = (valueT) End_Of_Data;
+
+ /* Find the nearest symbol what follows this one. */
+ for (s1P = symbol_rootP; s1P; s1P = symbol_next (s1P))
+ {
+ /* The data type must match. */
+ if (S_GET_TYPE (s1P) != N_DATA)
+ continue;
+ s1P_val = S_GET_VALUE (s1P);
+ if (s1P_val > s0P_val && s1P_val < nearest_val)
+ nearest_val = s1P_val;
+ }
+ /* Calculate its size. */
+ return (offsetT) (nearest_val - s0P_val);
+}
+
+
+/* Check symbol names for the Psect hack with a globalvalue, and then
+ generate globalvalues for those that have it. */
+
+static void
+VMS_Emit_Globalvalues (text_siz, data_siz, Data_Segment)
+ unsigned text_siz;
+ unsigned data_siz;
+ char *Data_Segment;
+{
+ register symbolS *sp;
+ char *stripped_name, *Name;
+ int Size;
+ int Psect_Attributes;
+ int globalvalue;
+ int typ, abstyp;
+
+ /*
+ * Scan the symbol table for globalvalues, and emit def/ref when
+ * required. These will be caught again later and converted to
+ * N_UNDF
+ */
+ for (sp = symbol_rootP; sp; sp = sp->sy_next)
+ {
+ typ = S_GET_RAW_TYPE (sp);
+ abstyp = ((typ & ~N_EXT) == N_ABS);
+ /*
+ * See if this is something we want to look at.
+ */
+ if (!abstyp &&
+ typ != (N_DATA | N_EXT) &&
+ typ != (N_UNDF | N_EXT))
+ continue;
+ /*
+ * See if this has globalvalue specification.
+ */
+ Name = S_GET_NAME (sp);
+
+ if (abstyp)
+ {
+ stripped_name = 0;
+ Psect_Attributes = GLOBALVALUE_BIT;
+ }
+ else if (HAS_PSECT_ATTRIBUTES (Name))
+ {
+ stripped_name = (char *) xmalloc (strlen (Name) + 1);
+ strcpy (stripped_name, Name);
+ Psect_Attributes = 0;
+ VMS_Modify_Psect_Attributes (stripped_name, &Psect_Attributes);
+ }
+ else
+ continue;
+
+ if ((Psect_Attributes & GLOBALVALUE_BIT) != 0)
+ {
+ switch (typ)
+ {
+ case N_ABS:
+ /* Local symbol references will want
+ to have an environment defined. */
+ if (Current_Environment < 0)
+ VMS_Local_Environment_Setup (".N_ABS");
+ VMS_Global_Symbol_Spec (Name, 0,
+ S_GET_VALUE (sp),
+ GBLSYM_DEF|GBLSYM_VAL|GBLSYM_LCL);
+ break;
+ case N_ABS | N_EXT:
+ VMS_Global_Symbol_Spec (Name, 0,
+ S_GET_VALUE (sp),
+ GBLSYM_DEF|GBLSYM_VAL);
+ break;
+ case N_UNDF | N_EXT:
+ VMS_Global_Symbol_Spec (stripped_name, 0, 0, GBLSYM_VAL);
+ break;
+ case N_DATA | N_EXT:
+ Size = VMS_Initialized_Data_Size (sp, text_siz + data_siz);
+ if (Size > 4)
+ error (_("Invalid data type for globalvalue"));
+ globalvalue = md_chars_to_number (Data_Segment +
+ S_GET_VALUE (sp) - text_siz , Size);
+ /* Three times for good luck. The linker seems to get confused
+ if there are fewer than three */
+ VMS_Global_Symbol_Spec (stripped_name, 0, 0, GBLSYM_VAL);
+ VMS_Global_Symbol_Spec (stripped_name, 0, globalvalue,
+ GBLSYM_DEF|GBLSYM_VAL);
+ VMS_Global_Symbol_Spec (stripped_name, 0, globalvalue,
+ GBLSYM_DEF|GBLSYM_VAL);
+ break;
+ default:
+ as_warn (_("Invalid globalvalue of %s"), stripped_name);
+ break;
+ } /* switch */
+ } /* if */
+ if (stripped_name) free (stripped_name); /* clean up */
+ } /* for */
+
+}
+
+
+/*
+ * Define a procedure entry pt/mask
+ */
+static void
+VMS_Procedure_Entry_Pt (Name, Psect_Number, Psect_Offset, Entry_Mask)
+ char *Name;
+ int Psect_Number;
+ int Psect_Offset;
+ int Entry_Mask;
+{
+ char Local[32];
+
+ /*
+ * We are writing a GSD record
+ */
+ Set_VMS_Object_File_Record (OBJ_S_C_GSD);
+ /*
+ * If the buffer is empty we must insert the GSD record type
+ */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (OBJ_S_C_GSD);
+ /*
+ * We are writing a Procedure Entry Pt/Mask subrecord
+ */
+ PUT_CHAR (((unsigned) Psect_Number <= 255) ? GSD_S_C_EPM : GSD_S_C_EPMW);
+ /*
+ * Data type is undefined
+ */
+ PUT_CHAR (0);
+ /*
+ * Flags = "RELOCATABLE" and "DEFINED"
+ */
+ PUT_SHORT (GSY_S_M_DEF | GSY_S_M_REL);
+ /*
+ * Psect Number
+ */
+ if ((unsigned) Psect_Number <= 255)
+ PUT_CHAR (Psect_Number);
+ else
+ PUT_SHORT (Psect_Number);
+ /*
+ * Offset
+ */
+ PUT_LONG (Psect_Offset);
+ /*
+ * Entry mask
+ */
+ PUT_SHORT (Entry_Mask);
+ /*
+ * Finally, the global symbol name
+ */
+ VMS_Case_Hack_Symbol (Name, Local);
+ PUT_COUNTED_STRING (Local);
+ /*
+ * Flush the buffer if it is more than 75% full
+ */
+ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
+ Flush_VMS_Object_Record_Buffer ();
+}
+
+
+/*
+ * Set the current location counter to a particular Psect and Offset
+ */
+static void
+VMS_Set_Psect (Psect_Index, Offset, Record_Type)
+ int Psect_Index;
+ int Offset;
+ int Record_Type;
+{
+ /*
+ * We are writing a "Record_Type" record
+ */
+ Set_VMS_Object_File_Record (Record_Type);
+ /*
+ * If the buffer is empty we must insert the record type
+ */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (Record_Type);
+ /*
+ * Stack the Psect base + Offset
+ */
+ vms_tir_stack_psect (Psect_Index, Offset, 0);
+ /*
+ * Set relocation base
+ */
+ PUT_CHAR (TIR_S_C_CTL_SETRB);
+ /*
+ * Flush the buffer if it is more than 75% full
+ */
+ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
+ Flush_VMS_Object_Record_Buffer ();
+}
+
+
+/*
+ * Store repeated immediate data in current Psect
+ */
+static void
+VMS_Store_Repeated_Data (Repeat_Count, Pointer, Size, Record_Type)
+ int Repeat_Count;
+ register char *Pointer;
+ int Size;
+ int Record_Type;
+{
+
+ /*
+ * Ignore zero bytes/words/longwords
+ */
+ switch (Size)
+ {
+ case 4:
+ if (Pointer[3] != 0 || Pointer[2] != 0) break;
+ /* else FALLTHRU */
+ case 2:
+ if (Pointer[1] != 0) break;
+ /* else FALLTHRU */
+ case 1:
+ if (Pointer[0] != 0) break;
+ /* zero value */
+ return;
+ default:
+ break;
+ }
+ /*
+ * If the data is too big for a TIR_S_C_STO_RIVB sub-record
+ * then we do it manually
+ */
+ if (Size > 255)
+ {
+ while (--Repeat_Count >= 0)
+ VMS_Store_Immediate_Data (Pointer, Size, Record_Type);
+ return;
+ }
+ /*
+ * We are writing a "Record_Type" record
+ */
+ Set_VMS_Object_File_Record (Record_Type);
+ /*
+ * If the buffer is empty we must insert record type
+ */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (Record_Type);
+ /*
+ * Stack the repeat count
+ */
+ PUT_CHAR (TIR_S_C_STA_LW);
+ PUT_LONG (Repeat_Count);
+ /*
+ * And now the command and its data
+ */
+ PUT_CHAR (TIR_S_C_STO_RIVB);
+ PUT_CHAR (Size);
+ while (--Size >= 0)
+ PUT_CHAR (*Pointer++);
+ /*
+ * Flush the buffer if it is more than 75% full
+ */
+ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
+ Flush_VMS_Object_Record_Buffer ();
+}
+
+
+/*
+ * Store a Position Independent Reference
+ */
+static void
+VMS_Store_PIC_Symbol_Reference (Symbol, Offset, PC_Relative,
+ Psect, Psect_Offset, Record_Type)
+ symbolS *Symbol;
+ int Offset;
+ int PC_Relative;
+ int Psect;
+ int Psect_Offset;
+ int Record_Type;
+{
+ register struct VMS_Symbol *vsp = Symbol->sy_obj;
+ char Local[32];
+ int local_sym = 0;
+
+ /*
+ * We are writing a "Record_Type" record
+ */
+ Set_VMS_Object_File_Record (Record_Type);
+ /*
+ * If the buffer is empty we must insert record type
+ */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (Record_Type);
+ /*
+ * Set to the appropriate offset in the Psect.
+ * For a Code reference we need to fix the operand
+ * specifier as well, so back up 1 byte;
+ * for a Data reference we just store HERE.
+ */
+ VMS_Set_Psect (Psect,
+ PC_Relative ? Psect_Offset - 1 : Psect_Offset,
+ Record_Type);
+ /*
+ * Make sure we are still generating a "Record Type" record
+ */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (Record_Type);
+ /*
+ * Dispatch on symbol type (so we can stack its value)
+ */
+ switch (S_GET_RAW_TYPE (Symbol))
+ {
+ /*
+ * Global symbol
+ */
+ case N_ABS:
+ local_sym = 1;
+ /*FALLTHRU*/
+ case N_ABS | N_EXT:
+#ifdef NOT_VAX_11_C_COMPATIBLE
+ case N_UNDF | N_EXT:
+ case N_DATA | N_EXT:
+#endif /* NOT_VAX_11_C_COMPATIBLE */
+ case N_UNDF:
+ case N_TEXT | N_EXT:
+ /*
+ * Get the symbol name (case hacked)
+ */
+ VMS_Case_Hack_Symbol (S_GET_NAME (Symbol), Local);
+ /*
+ * Stack the global symbol value
+ */
+ if (!local_sym)
+ {
+ PUT_CHAR (TIR_S_C_STA_GBL);
+ }
+ else
+ {
+ /* Local symbols have an extra field. */
+ PUT_CHAR (TIR_S_C_STA_LSY);
+ PUT_SHORT (Current_Environment);
+ }
+ PUT_COUNTED_STRING (Local);
+ if (Offset)
+ {
+ /*
+ * Stack the longword offset
+ */
+ PUT_CHAR (TIR_S_C_STA_LW);
+ PUT_LONG (Offset);
+ /*
+ * Add the two, leaving the result on the stack
+ */
+ PUT_CHAR (TIR_S_C_OPR_ADD);
+ }
+ break;
+ /*
+ * Uninitialized local data
+ */
+ case N_BSS:
+ /*
+ * Stack the Psect (+offset)
+ */
+ vms_tir_stack_psect (vsp->Psect_Index,
+ vsp->Psect_Offset + Offset,
+ 0);
+ break;
+ /*
+ * Local text
+ */
+ case N_TEXT:
+ /*
+ * Stack the Psect (+offset)
+ */
+ vms_tir_stack_psect (vsp->Psect_Index,
+ S_GET_VALUE (Symbol) + Offset,
+ 0);
+ break;
+ /*
+ * Initialized local or global data
+ */
+ case N_DATA:
+#ifndef NOT_VAX_11_C_COMPATIBLE
+ case N_UNDF | N_EXT:
+ case N_DATA | N_EXT:
+#endif /* NOT_VAX_11_C_COMPATIBLE */
+ /*
+ * Stack the Psect (+offset)
+ */
+ vms_tir_stack_psect (vsp->Psect_Index,
+ vsp->Psect_Offset + Offset,
+ 0);
+ break;
+ }
+ /*
+ * Store either a code or data reference
+ */
+ PUT_CHAR (PC_Relative ? TIR_S_C_STO_PICR : TIR_S_C_STO_PIDR);
+ /*
+ * Flush the buffer if it is more than 75% full
+ */
+ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
+ Flush_VMS_Object_Record_Buffer ();
+}
+
+
+/*
+ * Check in the text area for an indirect pc-relative reference
+ * and fix it up with addressing mode 0xff [PC indirect]
+ *
+ * THIS SHOULD BE REPLACED BY THE USE OF TIR_S_C_STO_PIRR IN THE
+ * PIC CODE GENERATING FIXUP ROUTINE.
+ */
+static void
+VMS_Fix_Indirect_Reference (Text_Psect, Offset, fragP, text_frag_root)
+ int Text_Psect;
+ int Offset;
+ register fragS *fragP;
+ fragS *text_frag_root;
+{
+ /*
+ * The addressing mode byte is 1 byte before the address
+ */
+ Offset--;
+ /*
+ * Is it in THIS frag??
+ */
+ if ((Offset < fragP->fr_address) ||
+ (Offset >= (fragP->fr_address + fragP->fr_fix)))
+ {
+ /*
+ * We need to search for the fragment containing this
+ * Offset
+ */
+ for (fragP = text_frag_root; fragP; fragP = fragP->fr_next)
+ {
+ if ((Offset >= fragP->fr_address) &&
+ (Offset < (fragP->fr_address + fragP->fr_fix)))
+ break;
+ }
+ /*
+ * If we couldn't find the frag, things are BAD!!
+ */
+ if (fragP == 0)
+ error (_("Couldn't find fixup fragment when checking for indirect reference"));
+ }
+ /*
+ * Check for indirect PC relative addressing mode
+ */
+ if (fragP->fr_literal[Offset - fragP->fr_address] == (char) 0xff)
+ {
+ static char Address_Mode = (char) 0xff;
+
+ /*
+ * Yes: Store the indirect mode back into the image
+ * to fix up the damage done by STO_PICR
+ */
+ VMS_Set_Psect (Text_Psect, Offset, OBJ_S_C_TIR);
+ VMS_Store_Immediate_Data (&Address_Mode, 1, OBJ_S_C_TIR);
+ }
+}
+
+
+/*
+ * If the procedure "main()" exists we have to add the instruction
+ * "jsb c$main_args" at the beginning to be compatible with VAX-11 "C".
+ *
+ * FIXME: the macro name `HACK_DEC_C_STARTUP' should be renamed
+ * to `HACK_VAXCRTL_STARTUP' because Digital's compiler
+ * named "DEC C" uses run-time library "DECC$SHR", but this
+ * startup code is for "VAXCRTL", the library for Digital's
+ * older "VAX C". Also, this extra code isn't needed for
+ * supporting gcc because it already generates the VAXCRTL
+ * startup call when compiling main(). The reference to
+ * `flag_hash_long_names' looks very suspicious too;
+ * probably an old-style command line option was inadvertently
+ * overloaded here, then blindly converted into the new one.
+ */
+void
+vms_check_for_main ()
+{
+ register symbolS *symbolP;
+#ifdef HACK_DEC_C_STARTUP /* JF */
+ register struct frchain *frchainP;
+ register fragS *fragP;
+ register fragS **prev_fragPP;
+ register struct fix *fixP;
+ register fragS *New_Frag;
+ int i;
+#endif /* HACK_DEC_C_STARTUP */
+
+ symbolP = (symbolS *) symbol_find ("_main");
+ if (symbolP && !S_IS_DEBUG (symbolP) &&
+ S_IS_EXTERNAL (symbolP) && (S_GET_TYPE (symbolP) == N_TEXT))
+ {
+#ifdef HACK_DEC_C_STARTUP
+ if (!flag_hash_long_names)
+ {
+#endif
+ /*
+ * Remember the entry point symbol
+ */
+ Entry_Point_Symbol = symbolP;
+#ifdef HACK_DEC_C_STARTUP
+ }
+ else
+ {
+ /*
+ * Scan all the fragment chains for the one with "_main"
+ * (Actually we know the fragment from the symbol, but we need
+ * the previous fragment so we can change its pointer)
+ */
+ frchainP = frchain_root;
+ while (frchainP)
+ {
+ /*
+ * Scan all the fragments in this chain, remembering
+ * the "previous fragment"
+ */
+ prev_fragPP = &frchainP->frch_root;
+ fragP = frchainP->frch_root;
+ while (fragP && (fragP != frchainP->frch_last))
+ {
+ /*
+ * Is this the fragment?
+ */
+ if (fragP == symbolP->sy_frag)
+ {
+ /*
+ * Yes: Modify the fragment by replacing
+ * it with a new fragment.
+ */
+ New_Frag = (fragS *)
+ xmalloc (sizeof (*New_Frag) +
+ fragP->fr_fix +
+ fragP->fr_var +
+ 5);
+ /*
+ * The fragments are the same except
+ * that the "fixed" area is larger
+ */
+ *New_Frag = *fragP;
+ New_Frag->fr_fix += 6;
+ /*
+ * Copy the literal data opening a hole
+ * 2 bytes after "_main" (i.e. just after
+ * the entry mask). Into which we place
+ * the JSB instruction.
+ */
+ New_Frag->fr_literal[0] = fragP->fr_literal[0];
+ New_Frag->fr_literal[1] = fragP->fr_literal[1];
+ New_Frag->fr_literal[2] = 0x16; /* Jsb */
+ New_Frag->fr_literal[3] = 0xef;
+ New_Frag->fr_literal[4] = 0;
+ New_Frag->fr_literal[5] = 0;
+ New_Frag->fr_literal[6] = 0;
+ New_Frag->fr_literal[7] = 0;
+ for (i = 2; i < fragP->fr_fix + fragP->fr_var; i++)
+ New_Frag->fr_literal[i + 6] =
+ fragP->fr_literal[i];
+ /*
+ * Now replace the old fragment with the
+ * newly generated one.
+ */
+ *prev_fragPP = New_Frag;
+ /*
+ * Remember the entry point symbol
+ */
+ Entry_Point_Symbol = symbolP;
+ /*
+ * Scan the text area fixup structures
+ * as offsets in the fragment may have
+ * changed
+ */
+ for (fixP = text_fix_root; fixP; fixP = fixP->fx_next)
+ {
+ /*
+ * Look for references to this
+ * fragment.
+ */
+ if (fixP->fx_frag == fragP)
+ {
+ /*
+ * Change the fragment
+ * pointer
+ */
+ fixP->fx_frag = New_Frag;
+ /*
+ * If the offset is after
+ * the entry mask we need
+ * to account for the JSB
+ * instruction we just
+ * inserted.
+ */
+ if (fixP->fx_where >= 2)
+ fixP->fx_where += 6;
+ }
+ }
+ /*
+ * Scan the symbols as offsets in the
+ * fragment may have changed
+ */
+ for (symbolP = symbol_rootP;
+ symbolP;
+ symbolP = symbol_next (symbolP))
+ {
+ /*
+ * Look for references to this
+ * fragment.
+ */
+ if (symbolP->sy_frag == fragP)
+ {
+ /*
+ * Change the fragment
+ * pointer
+ */
+ symbolP->sy_frag = New_Frag;
+ /*
+ * If the offset is after
+ * the entry mask we need
+ * to account for the JSB
+ * instruction we just
+ * inserted.
+ */
+ if (S_GET_VALUE (symbolP) >= 2)
+ S_SET_VALUE (symbolP,
+ S_GET_VALUE (symbolP) + 6);
+ }
+ }
+ /*
+ * Make a symbol reference to
+ * "_c$main_args" so we can get
+ * its address inserted into the
+ * JSB instruction.
+ */
+ symbolP = (symbolS *) xmalloc (sizeof (*symbolP));
+ S_SET_NAME (symbolP, "_C$MAIN_ARGS");
+ S_SET_TYPE (symbolP, N_UNDF);
+ S_SET_OTHER (symbolP, 0);
+ S_SET_DESC (symbolP, 0);
+ S_SET_VALUE (symbolP, 0);
+ symbolP->sy_name_offset = 0;
+ symbolP->sy_number = 0;
+ symbolP->sy_obj = 0;
+ symbolP->sy_frag = New_Frag;
+ symbolP->sy_resolved = 0;
+ symbolP->sy_resolving = 0;
+ /* this actually inserts at the beginning of the list */
+ symbol_append (symbol_rootP, symbolP,
+ &symbol_rootP, &symbol_lastP);
+
+ symbol_rootP = symbolP;
+ /*
+ * Generate a text fixup structure
+ * to get "_c$main_args" stored into the
+ * JSB instruction.
+ */
+ fixP = (struct fix *) xmalloc (sizeof (*fixP));
+ fixP->fx_frag = New_Frag;
+ fixP->fx_where = 4;
+ fixP->fx_addsy = symbolP;
+ fixP->fx_subsy = 0;
+ fixP->fx_offset = 0;
+ fixP->fx_size = 4;
+ fixP->fx_pcrel = 1;
+ fixP->fx_next = text_fix_root;
+ text_fix_root = fixP;
+ /*
+ * Now make sure we exit from the loop
+ */
+ frchainP = 0;
+ break;
+ }
+ /*
+ * Try the next fragment
+ */
+ prev_fragPP = &fragP->fr_next;
+ fragP = fragP->fr_next;
+ }
+ /*
+ * Try the next fragment chain
+ */
+ if (frchainP)
+ frchainP = frchainP->frch_next;
+ }
+ }
+#endif /* HACK_DEC_C_STARTUP */
+ }
+}
+
+
+/*
+ * Beginning of vms_write_object_file().
+ */
+
+static
+struct vms_obj_state {
+
+ /* Next program section index to use. */
+ int psect_number;
+
+ /* Psect index for code. Always ends up #0. */
+ int text_psect;
+
+ /* Psect index for initialized static variables. */
+ int data_psect;
+
+ /* Psect index for uninitialized static variables. */
+ int bss_psect;
+
+ /* Psect index for static constructors. */
+ int ctors_psect;
+
+ /* Psect index for static destructors. */
+ int dtors_psect;
+
+ /* Number of bytes used for local symbol data. */
+ int local_initd_data_size;
+
+ /* Dynamic buffer for initialized data. */
+ char *data_segment;
+
+} vms_obj_state;
+
+#define Psect_Number vms_obj_state.psect_number
+#define Text_Psect vms_obj_state.text_psect
+#define Data_Psect vms_obj_state.data_psect
+#define Bss_Psect vms_obj_state.bss_psect
+#define Ctors_Psect vms_obj_state.ctors_psect
+#define Dtors_Psect vms_obj_state.dtors_psect
+#define Local_Initd_Data_Size vms_obj_state.local_initd_data_size
+#define Data_Segment vms_obj_state.data_segment
+
+
+#define IS_GXX_VTABLE(symP) (strncmp (S_GET_NAME (symP), "__vt.", 5) == 0)
+#define IS_GXX_XTOR(symP) (strncmp (S_GET_NAME (symP), "__GLOBAL_.", 10) == 0)
+#define XTOR_SIZE 4
+
+
+/* Perform text segment fixups. */
+
+static void
+vms_fixup_text_section (text_siz, text_frag_root, data_frag_root)
+ unsigned text_siz;
+ struct frag *text_frag_root;
+ struct frag *data_frag_root;
+{
+ register fragS *fragP;
+ register struct fix *fixP;
+ offsetT dif;
+
+ /* Scan the text fragments. */
+ for (fragP = text_frag_root; fragP; fragP = fragP->fr_next)
+ {
+ /* Stop if we get to the data fragments. */
+ if (fragP == data_frag_root)
+ break;
+ /* Ignore fragments with no data. */
+ if ((fragP->fr_fix == 0) && (fragP->fr_var == 0))
+ continue;
+ /* Go the the appropriate offset in the Text Psect. */
+ VMS_Set_Psect (Text_Psect, fragP->fr_address, OBJ_S_C_TIR);
+ /* Store the "fixed" part. */
+ if (fragP->fr_fix)
+ VMS_Store_Immediate_Data (fragP->fr_literal,
+ fragP->fr_fix,
+ OBJ_S_C_TIR);
+ /* Store the "variable" part. */
+ if (fragP->fr_var && fragP->fr_offset)
+ VMS_Store_Repeated_Data (fragP->fr_offset,
+ fragP->fr_literal + fragP->fr_fix,
+ fragP->fr_var,
+ OBJ_S_C_TIR);
+ } /* text frag loop */
+
+ /*
+ * Now we go through the text segment fixups and generate
+ * TIR records to fix up addresses within the Text Psect.
+ */
+ for (fixP = text_fix_root; fixP; fixP = fixP->fx_next)
+ {
+ /* We DO handle the case of "Symbol - Symbol" as
+ long as it is in the same segment. */
+ if (fixP->fx_subsy && fixP->fx_addsy)
+ {
+ /* They need to be in the same segment. */
+ if (S_GET_RAW_TYPE (fixP->fx_subsy) !=
+ S_GET_RAW_TYPE (fixP->fx_addsy))
+ error (_("Fixup data addsy and subsy don't have the same type"));
+ /* And they need to be in one that we can check the psect on. */
+ if ((S_GET_TYPE (fixP->fx_addsy) != N_DATA) &&
+ (S_GET_TYPE (fixP->fx_addsy) != N_TEXT))
+ error (_("Fixup data addsy and subsy don't have an appropriate type"));
+ /* This had better not be PC relative! */
+ if (fixP->fx_pcrel)
+ error (_("Fixup data is erroneously \"pcrel\""));
+ /* Subtract their values to get the difference. */
+ dif = S_GET_VALUE (fixP->fx_addsy) - S_GET_VALUE (fixP->fx_subsy);
+ md_number_to_chars (Local, (valueT)dif, fixP->fx_size);
+ /* Now generate the fixup object records;
+ set the psect and store the data. */
+ VMS_Set_Psect (Text_Psect,
+ fixP->fx_where + fixP->fx_frag->fr_address,
+ OBJ_S_C_TIR);
+ VMS_Store_Immediate_Data (Local,
+ fixP->fx_size,
+ OBJ_S_C_TIR);
+ continue; /* done with this fixup */
+ } /* if fx_subsy && fx_addsy */
+ /* Size will HAVE to be "long". */
+ if (fixP->fx_size != 4)
+ error (_("Fixup datum is not a longword"));
+ /* Symbol must be "added" (if it is ever
+ subtracted we can fix this assumption). */
+ if (fixP->fx_addsy == 0)
+ error (_("Fixup datum is not \"fixP->fx_addsy\""));
+ /* Store the symbol value in a PIC fashion. */
+ VMS_Store_PIC_Symbol_Reference (fixP->fx_addsy,
+ fixP->fx_offset,
+ fixP->fx_pcrel,
+ Text_Psect,
+ fixP->fx_where + fixP->fx_frag->fr_address,
+ OBJ_S_C_TIR);
+ /*
+ * Check for indirect address reference, which has to be fixed up
+ * (as the linker will screw it up with TIR_S_C_STO_PICR)...
+ */
+ if (fixP->fx_pcrel)
+ VMS_Fix_Indirect_Reference (Text_Psect,
+ fixP->fx_where + fixP->fx_frag->fr_address,
+ fixP->fx_frag,
+ text_frag_root);
+ } /* text fix loop */
+}
+
+
+/* Create a buffer holding the data segment. */
+
+static void
+synthesize_data_segment (data_siz, text_siz, data_frag_root)
+ unsigned data_siz, text_siz;
+ struct frag *data_frag_root;
+{
+ register fragS *fragP;
+ char *fill_literal;
+ long fill_size, count, i;
+
+ /* Allocate the data segment. */
+ Data_Segment = (char *) xmalloc (data_siz);
+ /* Run through the data fragments, filling in the segment. */
+ for (fragP = data_frag_root; fragP; fragP = fragP->fr_next)
+ {
+ i = fragP->fr_address - text_siz;
+ if (fragP->fr_fix)
+ memcpy (Data_Segment + i, fragP->fr_literal, fragP->fr_fix);
+ i += fragP->fr_fix;
+
+ if ((fill_size = fragP->fr_var) != 0)
+ {
+ fill_literal = fragP->fr_literal + fragP->fr_fix;
+ for (count = fragP->fr_offset; count; count--)
+ {
+ memcpy (Data_Segment + i, fill_literal, fill_size);
+ i += fill_size;
+ }
+ }
+ } /* data frag loop */
+
+ return;
+}
+
+
+/* Perform data segment fixups. */
+
+static void
+vms_fixup_data_section (data_siz, text_siz)
+ unsigned data_siz, text_siz;
+{
+ register struct VMS_Symbol *vsp;
+ register struct fix *fixP;
+ register symbolS *sp;
+ addressT fr_address;
+ offsetT dif;
+ valueT val;
+
+ /* Run through all the data symbols and store the data. */
+ for (vsp = VMS_Symbols; vsp; vsp = vsp->Next)
+ {
+ /* Ignore anything other than data symbols. */
+ if (S_GET_TYPE (vsp->Symbol) != N_DATA)
+ continue;
+ /* Set the Psect + Offset. */
+ VMS_Set_Psect (vsp->Psect_Index,
+ vsp->Psect_Offset,
+ OBJ_S_C_TIR);
+ /* Store the data. */
+ val = S_GET_VALUE (vsp->Symbol);
+ VMS_Store_Immediate_Data (Data_Segment + val - text_siz,
+ vsp->Size,
+ OBJ_S_C_TIR);
+ } /* N_DATA symbol loop */
+
+ /*
+ * Now we go through the data segment fixups and generate
+ * TIR records to fix up addresses within the Data Psects.
+ */
+ for (fixP = data_fix_root; fixP; fixP = fixP->fx_next)
+ {
+ /* Find the symbol for the containing datum. */
+ for (vsp = VMS_Symbols; vsp; vsp = vsp->Next)
+ {
+ /* Only bother with Data symbols. */
+ sp = vsp->Symbol;
+ if (S_GET_TYPE (sp) != N_DATA)
+ continue;
+ /* Ignore symbol if After fixup. */
+ val = S_GET_VALUE (sp);
+ fr_address = fixP->fx_frag->fr_address;
+ if (val > fixP->fx_where + fr_address)
+ continue;
+ /* See if the datum is here. */
+ if (val + vsp->Size <= fixP->fx_where + fr_address)
+ continue;
+ /* We DO handle the case of "Symbol - Symbol" as
+ long as it is in the same segment. */
+ if (fixP->fx_subsy && fixP->fx_addsy)
+ {
+ /* They need to be in the same segment. */
+ if (S_GET_RAW_TYPE (fixP->fx_subsy) !=
+ S_GET_RAW_TYPE (fixP->fx_addsy))
+ error (_("Fixup data addsy and subsy don't have the same type"));
+ /* And they need to be in one that we can check the psect on. */
+ if ((S_GET_TYPE (fixP->fx_addsy) != N_DATA) &&
+ (S_GET_TYPE (fixP->fx_addsy) != N_TEXT))
+ error (_("Fixup data addsy and subsy don't have an appropriate type"));
+ /* This had better not be PC relative! */
+ if (fixP->fx_pcrel)
+ error (_("Fixup data is erroneously \"pcrel\""));
+ /* Subtract their values to get the difference. */
+ dif = S_GET_VALUE (fixP->fx_addsy) - S_GET_VALUE (fixP->fx_subsy);
+ md_number_to_chars (Local, (valueT)dif, fixP->fx_size);
+ /*
+ * Now generate the fixup object records;
+ * set the psect and store the data.
+ */
+ VMS_Set_Psect (vsp->Psect_Index,
+ fr_address + fixP->fx_where
+ - val + vsp->Psect_Offset,
+ OBJ_S_C_TIR);
+ VMS_Store_Immediate_Data (Local,
+ fixP->fx_size,
+ OBJ_S_C_TIR);
+ break; /* done with this fixup */
+ }
+ /* Size will HAVE to be "long". */
+ if (fixP->fx_size != 4)
+ error (_("Fixup datum is not a longword"));
+ /* Symbol must be "added" (if it is ever
+ subtracted we can fix this assumption). */
+ if (fixP->fx_addsy == 0)
+ error (_("Fixup datum is not \"fixP->fx_addsy\""));
+ /* Store the symbol value in a PIC fashion. */
+ VMS_Store_PIC_Symbol_Reference (fixP->fx_addsy,
+ fixP->fx_offset,
+ fixP->fx_pcrel,
+ vsp->Psect_Index,
+ fr_address + fixP->fx_where
+ - val + vsp->Psect_Offset,
+ OBJ_S_C_TIR);
+ /* Done with this fixup. */
+ break;
+ } /* vms_symbol loop */
+
+ } /* data fix loop */
+}
+
+/* Perform ctors/dtors segment fixups. */
+
+static void
+vms_fixup_xtors_section (symbols, sect_no)
+ struct VMS_Symbol *symbols;
+ int sect_no;
+{
+ register struct VMS_Symbol *vsp;
+
+ /* Run through all the symbols and store the data. */
+ for (vsp = symbols; vsp; vsp = vsp->Next)
+ {
+ register symbolS *sp;
+
+ /* Set relocation base. */
+ VMS_Set_Psect (vsp->Psect_Index, vsp->Psect_Offset, OBJ_S_C_TIR);
+
+ sp = vsp->Symbol;
+ /* Stack the Psect base with its offset. */
+ VMS_Set_Data (Text_Psect, S_GET_VALUE (sp), OBJ_S_C_TIR, 0);
+ }
+ /* Flush the buffer if it is more than 75% full. */
+ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
+ Flush_VMS_Object_Record_Buffer ();
+
+ return;
+}
+
+
+/* Define symbols for the linker. */
+
+static void
+global_symbol_directory (text_siz, data_siz)
+ unsigned text_siz, data_siz;
+{
+ register fragS *fragP;
+ register symbolS *sp;
+ register struct VMS_Symbol *vsp;
+ int Globalref, define_as_global_symbol;
+
+#if 0
+ /* The g++ compiler does not write out external references to
+ vtables correctly. Check for this and holler if we see it
+ happening. If that compiler bug is ever fixed we can remove
+ this.
+
+ (Jun'95: gcc 2.7.0's cc1plus still exhibits this behavior.)
+
+ This was reportedly fixed as of June 2, 1998. */
+
+ for (sp = symbol_rootP; sp; sp = symbol_next (sp))
+ if (S_GET_RAW_TYPE (sp) == N_UNDF && IS_GXX_VTABLE (sp))
+ {
+ S_SET_TYPE (sp, N_UNDF | N_EXT);
+ S_SET_OTHER (sp, 1);
+ as_warn (_("g++ wrote an extern reference to `%s' as a routine.\nI will fix it, but I hope that it was note really a routine."),
+ S_GET_NAME (sp));
+ }
+#endif
+
+ /*
+ * Now scan the symbols and emit the appropriate GSD records
+ */
+ for (sp = symbol_rootP; sp; sp = symbol_next (sp))
+ {
+ define_as_global_symbol = 0;
+ vsp = 0;
+ /* Dispatch on symbol type. */
+ switch (S_GET_RAW_TYPE (sp))
+ {
+
+ /* Global uninitialized data. */
+ case N_UNDF | N_EXT:
+ /* Make a VMS data symbol entry. */
+ vsp = (struct VMS_Symbol *) xmalloc (sizeof *vsp);
+ vsp->Symbol = sp;
+ vsp->Size = S_GET_VALUE (sp);
+ vsp->Psect_Index = Psect_Number++;
+ vsp->Psect_Offset = 0;
+ vsp->Next = VMS_Symbols;
+ VMS_Symbols = vsp;
+ sp->sy_obj = vsp;
+ /* Make the psect for this data. */
+ Globalref = VMS_Psect_Spec (S_GET_NAME (sp),
+ vsp->Size,
+ S_GET_OTHER (sp) ? ps_CONST : ps_COMMON,
+ vsp);
+ if (Globalref)
+ Psect_Number--;
+#ifdef NOT_VAX_11_C_COMPATIBLE
+ define_as_global_symbol = 1;
+#else
+ /* See if this is an external vtable. We want to help the
+ linker find these things in libraries, so we make a symbol
+ reference. This is not compatible with VAX-C usage for
+ variables, but since vtables are only used internally by
+ g++, we can get away with this hack. */
+ define_as_global_symbol = IS_GXX_VTABLE (sp);
+#endif
+ break;
+
+ /* Local uninitialized data. */
+ case N_BSS:
+ /* Make a VMS data symbol entry. */
+ vsp = (struct VMS_Symbol *) xmalloc (sizeof *vsp);
+ vsp->Symbol = sp;
+ vsp->Size = 0;
+ vsp->Psect_Index = Bss_Psect;
+ vsp->Psect_Offset = S_GET_VALUE (sp) - bss_address_frag.fr_address;
+ vsp->Next = VMS_Symbols;
+ VMS_Symbols = vsp;
+ sp->sy_obj = vsp;
+ break;
+
+ /* Global initialized data. */
+ case N_DATA | N_EXT:
+ /* Make a VMS data symbol entry. */
+ vsp = (struct VMS_Symbol *) xmalloc (sizeof *vsp);
+ vsp->Symbol = sp;
+ vsp->Size = VMS_Initialized_Data_Size (sp, text_siz + data_siz);
+ vsp->Psect_Index = Psect_Number++;
+ vsp->Psect_Offset = 0;
+ vsp->Next = VMS_Symbols;
+ VMS_Symbols = vsp;
+ sp->sy_obj = vsp;
+ /* Make its psect. */
+ Globalref = VMS_Psect_Spec (S_GET_NAME (sp),
+ vsp->Size,
+ S_GET_OTHER (sp) ? ps_CONST : ps_COMMON,
+ vsp);
+ if (Globalref)
+ Psect_Number--;
+#ifdef NOT_VAX_11_C_COMPATIBLE
+ define_as_global_symbol = 1;
+#else
+ /* See N_UNDF|N_EXT above for explanation. */
+ define_as_global_symbol = IS_GXX_VTABLE (sp);
+#endif
+ break;
+
+ /* Local initialized data. */
+ case N_DATA:
+ {
+ char *sym_name = S_GET_NAME (sp);
+
+ /* Always suppress local numeric labels. */
+ if (sym_name && strcmp (sym_name, FAKE_LABEL_NAME) == 0)
+ break;
+
+ /* Make a VMS data symbol entry. */
+ vsp = (struct VMS_Symbol *) xmalloc (sizeof *vsp);
+ vsp->Symbol = sp;
+ vsp->Size = VMS_Initialized_Data_Size (sp, text_siz + data_siz);
+ vsp->Psect_Index = Data_Psect;
+ vsp->Psect_Offset = Local_Initd_Data_Size;
+ Local_Initd_Data_Size += vsp->Size;
+ vsp->Next = VMS_Symbols;
+ VMS_Symbols = vsp;
+ sp->sy_obj = vsp;
+ }
+ break;
+
+ /* Global Text definition. */
+ case N_TEXT | N_EXT:
+ {
+
+ if (IS_GXX_XTOR (sp))
+ {
+ vsp = (struct VMS_Symbol *) xmalloc (sizeof *vsp);
+ vsp->Symbol = sp;
+ vsp->Size = XTOR_SIZE;
+ sp->sy_obj = vsp;
+ switch ((S_GET_NAME (sp))[10])
+ {
+ case 'I':
+ vsp->Psect_Index = Ctors_Psect;
+ vsp->Psect_Offset = (Ctors_Symbols==0)?0:(Ctors_Symbols->Psect_Offset+XTOR_SIZE);
+ vsp->Next = Ctors_Symbols;
+ Ctors_Symbols = vsp;
+ break;
+ case 'D':
+ vsp->Psect_Index = Dtors_Psect;
+ vsp->Psect_Offset = (Dtors_Symbols==0)?0:(Dtors_Symbols->Psect_Offset+XTOR_SIZE);
+ vsp->Next = Dtors_Symbols;
+ Dtors_Symbols = vsp;
+ break;
+ case 'G':
+ as_warn (_("Can't handle global xtors symbols yet."));
+ break;
+ default:
+ as_warn (_("Unknown %s"), S_GET_NAME (sp));
+ break;
+ }
+ }
+ else
+ {
+ unsigned short Entry_Mask;
+
+ /* Get the entry mask. */
+ fragP = sp->sy_frag;
+ /* First frag might be empty if we're generating listings.
+ So skip empty rs_fill frags. */
+ while (fragP && fragP->fr_type == rs_fill && fragP->fr_fix == 0)
+ fragP = fragP->fr_next;
+
+ /* If first frag doesn't contain the data, what do we do?
+ If it's possibly smaller than two bytes, that would
+ imply that the entry mask is not stored where we're
+ expecting it.
+
+ If you can find a test case that triggers this, report
+ it (and tell me what the entry mask field ought to be),
+ and I'll try to fix it. KR */
+ if (fragP->fr_fix < 2)
+ abort ();
+
+ Entry_Mask = (fragP->fr_literal[0] & 0x00ff) |
+ ((fragP->fr_literal[1] & 0x00ff) << 8);
+ /* Define the procedure entry point. */
+ VMS_Procedure_Entry_Pt (S_GET_NAME (sp),
+ Text_Psect,
+ S_GET_VALUE (sp),
+ Entry_Mask);
+ }
+ break;
+ }
+
+ /* Local Text definition. */
+ case N_TEXT:
+ /* Make a VMS data symbol entry. */
+ if (Text_Psect != -1)
+ {
+ vsp = (struct VMS_Symbol *) xmalloc (sizeof *vsp);
+ vsp->Symbol = sp;
+ vsp->Size = 0;
+ vsp->Psect_Index = Text_Psect;
+ vsp->Psect_Offset = S_GET_VALUE (sp);
+ vsp->Next = VMS_Symbols;
+ VMS_Symbols = vsp;
+ sp->sy_obj = vsp;
+ }
+ break;
+
+ /* Global Reference. */
+ case N_UNDF:
+ /* Make a GSD global symbol reference record. */
+ VMS_Global_Symbol_Spec (S_GET_NAME (sp),
+ 0,
+ 0,
+ GBLSYM_REF);
+ break;
+
+ /* Absolute symbol. */
+ case N_ABS:
+ case N_ABS | N_EXT:
+ /* gcc doesn't generate these;
+ VMS_Emit_Globalvalue handles them though. */
+ vsp = (struct VMS_Symbol *) xmalloc (sizeof *vsp);
+ vsp->Symbol = sp;
+ vsp->Size = 4; /* always assume 32 bits */
+ vsp->Psect_Index = 0;
+ vsp->Psect_Offset = S_GET_VALUE (sp);
+ vsp->Next = VMS_Symbols;
+ VMS_Symbols = vsp;
+ sp->sy_obj = vsp;
+ break;
+
+ /* Anything else. */
+ default:
+ /* Ignore STAB symbols, including .stabs emitted by g++. */
+ if (S_IS_DEBUG (sp) || (S_GET_TYPE (sp) == 22))
+ break;
+ /*
+ * Error otherwise.
+ */
+ as_tsktsk (_("unhandled stab type %d"), S_GET_TYPE (sp));
+ break;
+ }
+
+ /* Global symbols have different linkage than external variables. */
+ if (define_as_global_symbol)
+ VMS_Global_Symbol_Spec (S_GET_NAME (sp),
+ vsp->Psect_Index,
+ 0,
+ GBLSYM_DEF);
+ }
+
+ return;
+}
+
+
+/* Output debugger symbol table information for symbols which
+ are local to a specific routine. */
+
+static void
+local_symbols_DST (s0P, Current_Routine)
+ symbolS *s0P, *Current_Routine;
+{
+ symbolS *s1P;
+ char *s0P_name, *pnt0, *pnt1;
+
+ s0P_name = S_GET_NAME (s0P);
+ if (*s0P_name++ != '_')
+ return;
+
+ for (s1P = Current_Routine; s1P; s1P = symbol_next (s1P))
+ {
+#if 0 /* redundant; RAW_TYPE != N_FUN suffices */
+ if (!S_IS_DEBUG (s1P))
+ continue;
+#endif
+ if (S_GET_RAW_TYPE (s1P) != N_FUN)
+ continue;
+ pnt0 = s0P_name;
+ pnt1 = S_GET_NAME (s1P);
+ /* We assume the two strings are never exactly equal... */
+ while (*pnt0++ == *pnt1++)
+ {
+ }
+ /* Found it if s0P name is exhausted and s1P name has ":F" or ":f" next.
+ Note: both pointers have advanced one past the non-matching char. */
+ if ((*pnt1 == 'F' || *pnt1 == 'f') && *--pnt1 == ':' && *--pnt0 == '\0')
+ {
+ Define_Routine (s1P, 0, Current_Routine, Text_Psect);
+ return;
+ }
+ }
+}
+
+
+/* Construct and output the debug symbol table. */
+
+static void
+vms_build_DST (text_siz)
+ unsigned text_siz;
+{
+ register symbolS *symbolP;
+ symbolS *Current_Routine = 0;
+ struct input_file *Cur_File = 0;
+ offsetT Cur_Offset = -1;
+ int Cur_Line_Number = 0;
+ int File_Number = 0;
+ int Debugger_Offset = 0;
+ int file_available;
+ int dsc;
+ offsetT val;
+
+ /* Write the Traceback Begin Module record. */
+ VMS_TBT_Module_Begin ();
+
+ /*
+ * Output debugging info for global variables and static variables
+ * that are not specific to one routine. We also need to examine
+ * all stabs directives, to find the definitions to all of the
+ * advanced data types, and this is done by VMS_LSYM_Parse. This
+ * needs to be done before any definitions are output to the object
+ * file, since there can be forward references in the stabs
+ * directives. When through with parsing, the text of the stabs
+ * directive is altered, with the definitions removed, so that later
+ * passes will see directives as they would be written if the type
+ * were already defined.
+ *
+ * We also look for files and include files, and make a list of
+ * them. We examine the source file numbers to establish the actual
+ * lines that code was generated from, and then generate offsets.
+ */
+ VMS_LSYM_Parse ();
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
+ {
+ /* Only deal with STAB symbols here. */
+ if (!S_IS_DEBUG (symbolP))
+ continue;
+ /*
+ * Dispatch on STAB type.
+ */
+ switch (S_GET_RAW_TYPE (symbolP))
+ {
+ case N_SLINE:
+ dsc = S_GET_DESC (symbolP);
+ if (dsc > Cur_File->max_line)
+ Cur_File->max_line = dsc;
+ if (dsc < Cur_File->min_line)
+ Cur_File->min_line = dsc;
+ break;
+ case N_SO:
+ Cur_File = find_file (symbolP);
+ Cur_File->flag = 1;
+ Cur_File->min_line = 1;
+ break;
+ case N_SOL:
+ Cur_File = find_file (symbolP);
+ break;
+ case N_GSYM:
+ VMS_GSYM_Parse (symbolP, Text_Psect);
+ break;
+ case N_LCSYM:
+ VMS_LCSYM_Parse (symbolP, Text_Psect);
+ break;
+ case N_FUN: /* For static constant symbols */
+ case N_STSYM:
+ VMS_STSYM_Parse (symbolP, Text_Psect);
+ break;
+ default:
+ break;
+ } /* switch */
+ } /* for */
+
+ /*
+ * Now we take a quick sweep through the files and assign offsets
+ * to each one. This will essentially be the starting line number to
+ * the debugger for each file. Output the info for the debugger to
+ * specify the files, and then tell it how many lines to use.
+ */
+ for (Cur_File = file_root; Cur_File; Cur_File = Cur_File->next)
+ {
+ if (Cur_File->max_line == 0)
+ continue;
+ if ((strncmp (Cur_File->name, "GNU_GXX_INCLUDE:", 16) == 0) &&
+ !flag_debug)
+ continue;
+ if ((strncmp (Cur_File->name, "GNU_CC_INCLUDE:", 15) == 0) &&
+ !flag_debug)
+ continue;
+ /* show a few extra lines at the start of the region selected */
+ if (Cur_File->min_line > 2)
+ Cur_File->min_line -= 2;
+ Cur_File->offset = Debugger_Offset - Cur_File->min_line + 1;
+ Debugger_Offset += Cur_File->max_line - Cur_File->min_line + 1;
+ if (Cur_File->same_file_fpnt)
+ {
+ Cur_File->file_number = Cur_File->same_file_fpnt->file_number;
+ }
+ else
+ {
+ Cur_File->file_number = ++File_Number;
+ file_available = VMS_TBT_Source_File (Cur_File->name,
+ Cur_File->file_number);
+ if (!file_available)
+ {
+ Cur_File->file_number = 0;
+ File_Number--;
+ continue;
+ }
+ }
+ VMS_TBT_Source_Lines (Cur_File->file_number,
+ Cur_File->min_line,
+ Cur_File->max_line - Cur_File->min_line + 1);
+ } /* for */
+ Cur_File = (struct input_file *) NULL;
+
+ /*
+ * Scan the symbols and write out the routines
+ * (this makes the assumption that symbols are in
+ * order of ascending text segment offset)
+ */
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
+ {
+ /*
+ * Deal with text symbols.
+ */
+ if (!S_IS_DEBUG (symbolP) && S_GET_TYPE (symbolP) == N_TEXT)
+ {
+ /*
+ * Ignore symbols starting with "L", as they are local symbols.
+ */
+ if (*S_GET_NAME (symbolP) == 'L')
+ continue;
+ /*
+ * If there is a routine start defined, terminate it.
+ */
+ if (Current_Routine)
+ VMS_TBT_Routine_End (text_siz, Current_Routine);
+
+ /*
+ * Check for & skip dummy labels like "gcc_compiled.".
+ * They're identified by the IN_DEFAULT_SECTION flag.
+ */
+ if ((S_GET_OTHER (symbolP) & IN_DEFAULT_SECTION) != 0 &&
+ S_GET_VALUE (symbolP) == 0)
+ continue;
+ /*
+ * Store the routine begin traceback info.
+ */
+ VMS_TBT_Routine_Begin (symbolP, Text_Psect);
+ Current_Routine = symbolP;
+ /*
+ * Define symbols local to this routine.
+ */
+ local_symbols_DST (symbolP, Current_Routine);
+ /*
+ * Done
+ */
+ continue;
+
+ }
+ /*
+ * Deal with STAB symbols.
+ */
+ else if (S_IS_DEBUG (symbolP))
+ {
+ /*
+ * Dispatch on STAB type.
+ */
+ switch (S_GET_RAW_TYPE (symbolP))
+ {
+ /*
+ * Line number
+ */
+ case N_SLINE:
+ /* Offset the line into the correct portion of the file. */
+ if (Cur_File->file_number == 0)
+ break;
+ val = S_GET_VALUE (symbolP);
+ /* Sometimes the same offset gets several source lines
+ assigned to it. We should be selective about which
+ lines we allow, we should prefer lines that are in
+ the main source file when debugging inline functions. */
+ if (val == Cur_Offset && Cur_File->file_number != 1)
+ break;
+
+ /* calculate actual debugger source line */
+ dsc = S_GET_DESC (symbolP) + Cur_File->offset;
+ S_SET_DESC (symbolP, dsc);
+ /*
+ * Define PC/Line correlation.
+ */
+ if (Cur_Offset == -1)
+ {
+ /*
+ * First N_SLINE; set up initial correlation.
+ */
+ VMS_TBT_Line_PC_Correlation (dsc,
+ val,
+ Text_Psect,
+ 0);
+ }
+ else if ((dsc - Cur_Line_Number) <= 0)
+ {
+ /*
+ * Line delta is not +ve, we need to close the line and
+ * start a new PC/Line correlation.
+ */
+ VMS_TBT_Line_PC_Correlation (0,
+ val - Cur_Offset,
+ 0,
+ -1);
+ VMS_TBT_Line_PC_Correlation (dsc,
+ val,
+ Text_Psect,
+ 0);
+ }
+ else
+ {
+ /*
+ * Line delta is +ve, all is well.
+ */
+ VMS_TBT_Line_PC_Correlation (dsc - Cur_Line_Number,
+ val - Cur_Offset,
+ 0,
+ 1);
+ }
+ /* Update the current line/PC info. */
+ Cur_Line_Number = dsc;
+ Cur_Offset = val;
+ break;
+
+ /*
+ * Source file
+ */
+ case N_SO:
+ /* Remember that we had a source file and emit
+ the source file debugger record. */
+ Cur_File = find_file (symbolP);
+ break;
+
+ case N_SOL:
+ /* We need to make sure that we are really in the actual
+ source file when we compute the maximum line number.
+ Otherwise the debugger gets really confused. */
+ Cur_File = find_file (symbolP);
+ break;
+
+ default:
+ break;
+ } /* switch */
+ } /* if (IS_DEBUG) */
+ } /* for */
+
+ /*
+ * If there is a routine start defined, terminate it
+ * (and the line numbers).
+ */
+ if (Current_Routine)
+ {
+ /* Terminate the line numbers. */
+ VMS_TBT_Line_PC_Correlation (0,
+ text_siz - S_GET_VALUE (Current_Routine),
+ 0,
+ -1);
+ /* Terminate the routine. */
+ VMS_TBT_Routine_End (text_siz, Current_Routine);
+ }
+
+ /* Write the Traceback End Module TBT record. */
+ VMS_TBT_Module_End ();
+}
+
+
+/* Write a VAX/VMS object file (everything else has been done!). */
+
+void
+vms_write_object_file (text_siz, data_siz, bss_siz, text_frag_root,
+ data_frag_root)
+ unsigned text_siz;
+ unsigned data_siz;
+ unsigned bss_siz;
+ fragS *text_frag_root;
+ fragS *data_frag_root;
+{
+ register struct VMS_Symbol *vsp;
+
+ /*
+ * Initialize program section indices; values get updated later.
+ */
+ Psect_Number = 0; /* next Psect Index to use */
+ Text_Psect = -1; /* Text Psect Index */
+ Data_Psect = -2; /* Data Psect Index JF: Was -1 */
+ Bss_Psect = -3; /* Bss Psect Index JF: Was -1 */
+ Ctors_Psect = -4; /* Ctors Psect Index */
+ Dtors_Psect = -5; /* Dtors Psect Index */
+ /* Initialize other state variables. */
+ Data_Segment = 0;
+ Local_Initd_Data_Size = 0;
+
+ /*
+ * Create the actual output file and populate it with required
+ * "module header" information.
+ */
+ Create_VMS_Object_File ();
+ Write_VMS_MHD_Records ();
+
+ /*
+ * Create the Data segment:
+ *
+ * Since this is REALLY hard to do any other way,
+ * we actually manufacture the data segment and
+ * then store the appropriate values out of it.
+ * We need to generate this early, so that globalvalues
+ * can be properly emitted.
+ */
+ if (data_siz > 0)
+ synthesize_data_segment (data_siz, text_siz, data_frag_root);
+
+
+ /******* Global Symbol Directory *******/
+
+ /*
+ * Emit globalvalues now. We must do this before the text psect is
+ * defined, or we will get linker warnings about multiply defined
+ * symbols. All of the globalvalues "reference" psect 0, although
+ * it really does not have anything to do with it.
+ */
+ VMS_Emit_Globalvalues (text_siz, data_siz, Data_Segment);
+ /*
+ * Define the Text Psect
+ */
+ Text_Psect = Psect_Number++;
+ VMS_Psect_Spec ("$code", text_siz, ps_TEXT, 0);
+ /*
+ * Define the BSS Psect
+ */
+ if (bss_siz > 0)
+ {
+ Bss_Psect = Psect_Number++;
+ VMS_Psect_Spec ("$uninitialized_data", bss_siz, ps_DATA, 0);
+ }
+ /*
+ * Define symbols to the linker.
+ */
+ global_symbol_directory (text_siz, data_siz);
+ /*
+ * Define the Data Psect
+ */
+ if (data_siz > 0 && Local_Initd_Data_Size > 0)
+ {
+ Data_Psect = Psect_Number++;
+ VMS_Psect_Spec ("$data", Local_Initd_Data_Size, ps_DATA, 0);
+ /*
+ * Local initialized data (N_DATA) symbols need to be updated to the
+ * proper value of Data_Psect now that it's actually been defined.
+ * (A dummy value was used in global_symbol_directory() above.)
+ */
+ for (vsp = VMS_Symbols; vsp; vsp = vsp->Next)
+ if (vsp->Psect_Index < 0 && S_GET_RAW_TYPE (vsp->Symbol) == N_DATA)
+ vsp->Psect_Index = Data_Psect;
+ }
+
+
+ if (Ctors_Symbols != 0)
+ {
+ char *ps_name = "$ctors";
+ Ctors_Psect = Psect_Number++;
+ VMS_Psect_Spec (ps_name, Ctors_Symbols->Psect_Offset + XTOR_SIZE,
+ ps_CTORS, 0);
+ VMS_Global_Symbol_Spec (ps_name, Ctors_Psect,
+ 0, GBLSYM_DEF|GBLSYM_WEAK);
+ for (vsp = Ctors_Symbols; vsp; vsp = vsp->Next)
+ vsp->Psect_Index = Ctors_Psect;
+ }
+
+ if (Dtors_Symbols != 0)
+ {
+ char *ps_name = "$dtors";
+ Dtors_Psect = Psect_Number++;
+ VMS_Psect_Spec (ps_name, Dtors_Symbols->Psect_Offset + XTOR_SIZE,
+ ps_DTORS, 0);
+ VMS_Global_Symbol_Spec (ps_name, Dtors_Psect,
+ 0, GBLSYM_DEF|GBLSYM_WEAK);
+ for (vsp = Dtors_Symbols; vsp; vsp = vsp->Next)
+ vsp->Psect_Index = Dtors_Psect;
+ }
+
+ /******* Text Information and Relocation Records *******/
+
+ /*
+ * Write the text segment data
+ */
+ if (text_siz > 0)
+ vms_fixup_text_section (text_siz, text_frag_root, data_frag_root);
+ /*
+ * Write the data segment data, then discard it.
+ */
+ if (data_siz > 0)
+ {
+ vms_fixup_data_section (data_siz, text_siz);
+ free (Data_Segment), Data_Segment = 0;
+ }
+
+ if (Ctors_Symbols != 0)
+ {
+ vms_fixup_xtors_section (Ctors_Symbols, Ctors_Psect);
+ }
+
+ if (Dtors_Symbols != 0)
+ {
+ vms_fixup_xtors_section (Dtors_Symbols, Dtors_Psect);
+ }
+
+
+ /******* Debugger Symbol Table Records *******/
+
+ vms_build_DST (text_siz);
+
+
+ /******* Wrap things up *******/
+
+ /*
+ * Write the End Of Module record
+ */
+ if (Entry_Point_Symbol)
+ Write_VMS_EOM_Record (Text_Psect, S_GET_VALUE (Entry_Point_Symbol));
+ else
+ Write_VMS_EOM_Record (-1, (valueT) 0);
+
+ /*
+ * All done, close the object file
+ */
+ Close_VMS_Object_File ();
+}
+
+/* end of obj-vms.c */
diff --git a/gas/config/obj-vms.h b/gas/config/obj-vms.h
new file mode 100644
index 0000000000..ac0c1fb356
--- /dev/null
+++ b/gas/config/obj-vms.h
@@ -0,0 +1,552 @@
+/* VMS object file format
+ Copyright (C) 1989, 90, 91, 92, 93, 94, 95, 96, 1997
+ Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2,
+or (at your option) any later version.
+
+GAS 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 more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+/* Tag to validate a.out object file format processing */
+#define OBJ_VMS 1
+
+#include "targ-cpu.h"
+
+#define LONGWORD_ALIGNMENT 2
+
+/* This macro controls subsection alignment within a section.
+ *
+ * Under VAX/VMS, the linker (and PSECT specifications)
+ * take care of correctly aligning the segments.
+ * Doing the alignment here (on initialized data) can
+ * mess up the calculation of global data PSECT sizes.
+ */
+#define SUB_SEGMENT_ALIGN(SEG) \
+ (((SEG) == data_section) ? 0 : LONGWORD_ALIGNMENT)
+
+/* This flag is used to remember whether we are in the const or the
+ data section. By and large they are identical, but we set a no-write
+ bit for psects in the const section. */
+
+extern unsigned char const_flag;
+
+/* This is overloaded onto const_flag, for convenience. It's used to flag
+ dummy labels like "gcc2_compiled." which occur before the first .text
+ or .data section directive. */
+
+#define IN_DEFAULT_SECTION 0x80
+
+/* These are defined in obj-vms.c. */
+extern const short seg_N_TYPE[];
+extern const segT N_TYPE_seg[];
+
+#undef NO_RELOC
+enum reloc_type
+ {
+ NO_RELOC, RELOC_32
+ };
+
+#define N_BADMAG(x) (0)
+#define N_TXTOFF(x) ( sizeof(struct exec) )
+#define N_DATOFF(x) ( N_TXTOFF(x) + (x).a_text )
+#define N_TROFF(x) ( N_DATOFF(x) + (x).a_data )
+#define N_DROFF(x) ( N_TROFF(x) + (x).a_trsize )
+#define N_SYMOFF(x) ( N_DROFF(x) + (x).a_drsize )
+#define N_STROFF(x) ( N_SYMOFF(x) + (x).a_syms )
+
+/* We use this copy of the exec header for VMS. We do not actually use it, but
+ what we actually do is let gas fill in the relevant slots, and when we get
+ around to writing an obj file, we just pick out what we need. */
+
+struct exec
+{
+ unsigned long a_text; /* length of text, in bytes */
+ unsigned long a_data; /* length of data, in bytes */
+ unsigned long a_bss; /* length of uninitialized data area for file, in bytes */
+ unsigned long a_trsize; /* length of relocation info for text, in bytes */
+ unsigned long a_drsize; /* length of relocation info for data, in bytes */
+ unsigned long a_entry; /* start address */
+ unsigned long a_syms; /* length of symbol table data in file, in bytes */
+};
+
+typedef struct
+ {
+ struct exec header; /* a.out header */
+ long string_table_size; /* names + '\0' + sizeof(int) */
+ }
+object_headers;
+
+/* A single entry in the symbol table
+ * (this started as a clone of bout.h's nlist, but much was unneeded).
+ */
+struct nlist
+ {
+ char *n_name;
+ unsigned char n_type; /* See below */
+ unsigned char n_other; /* used for const_flag and "default section" */
+ unsigned : 16; /* padding for alignment */
+ int n_desc; /* source line number for N_SLINE stabs */
+ };
+
+/* Legal values of n_type (see aout/stab.def for the majority of the codes).
+ */
+#define N_UNDF 0 /* Undefined symbol */
+#define N_ABS 2 /* Absolute symbol */
+#define N_TEXT 4 /* Text symbol */
+#define N_DATA 6 /* Data symbol */
+#define N_BSS 8 /* BSS symbol */
+#define N_FN 31 /* Filename symbol */
+
+#define N_EXT 1 /* External symbol (OR'd in with one of above) */
+#define N_TYPE 036 /* Mask for all the type bits */
+
+#define N_STAB 0340 /* Mask for all bits used for SDB entries */
+
+#include "aout/stab_gnu.h"
+
+/* SYMBOL TABLE */
+/* Symbol table entry data type */
+
+typedef struct nlist obj_symbol_type; /* Symbol table entry */
+
+/* Symbol table macros and constants */
+
+#define OBJ_SYMFIELD_TYPE struct VMS_Symbol *
+
+/*
+ * Macros to extract information from a symbol table entry.
+ * This syntaxic indirection allows independence regarding a.out or coff.
+ * The argument (s) of all these macros is a pointer to a symbol table entry.
+ */
+
+/* True if the symbol is external */
+#define S_IS_EXTERNAL(s) ((s)->sy_symbol.n_type & N_EXT)
+
+/* True if symbol has been defined, ie is in N_{TEXT,DATA,BSS,ABS} or N_EXT */
+#define S_IS_DEFINED(s) (S_GET_TYPE(s) != N_UNDF)
+
+#define S_IS_COMMON(s) (S_GET_TYPE(s) == N_UNDF && S_GET_VALUE(s) != 0)
+
+#define S_IS_REGISTER(s) ((s)->sy_symbol.n_type == N_REGISTER)
+
+/* True if a debug special symbol entry */
+#define S_IS_DEBUG(s) ((s)->sy_symbol.n_type & N_STAB)
+/* True if a symbol is local symbol name */
+/* A symbol name whose name begin with ^A is a gas internal pseudo symbol
+ nameless symbols come from .stab directives. */
+#define S_IS_LOCAL(s) (S_GET_NAME(s) && \
+ !S_IS_DEBUG(s) && \
+ (strchr(S_GET_NAME(s), '\001') != 0 || \
+ strchr(S_GET_NAME(s), '\002') != 0 || \
+ (S_LOCAL_NAME(s) && !flag_keep_locals)))
+/* True if a symbol is not defined in this file */
+#define S_IS_EXTERN(s) ((s)->sy_symbol.n_type & N_EXT)
+/* True if the symbol has been generated because of a .stabd directive */
+#define S_IS_STABD(s) (S_GET_NAME(s) == (char *)0)
+
+/* Accessors */
+/* The name of the symbol */
+#define S_GET_NAME(s) ((s)->sy_symbol.n_name)
+/* The pointer to the string table */
+#define S_GET_OFFSET(s) ((s)->sy_name_offset)
+/* The raw type of the symbol */
+#define S_GET_RAW_TYPE(s) ((s)->sy_symbol.n_type)
+/* The type of the symbol */
+#define S_GET_TYPE(s) ((s)->sy_symbol.n_type & N_TYPE)
+/* The numeric value of the segment */
+#define S_GET_SEGMENT(s) (N_TYPE_seg[S_GET_TYPE(s)])
+/* The n_other expression value */
+#define S_GET_OTHER(s) ((s)->sy_symbol.n_other)
+/* The n_desc expression value */
+#define S_GET_DESC(s) ((s)->sy_symbol.n_desc)
+
+/* Modifiers */
+/* Assume that a symbol cannot be simultaneously in more than on segment */
+/* set segment */
+#define S_SET_SEGMENT(s,seg) ((s)->sy_symbol.n_type &= ~N_TYPE,(s)->sy_symbol.n_type|=SEGMENT_TO_SYMBOL_TYPE(seg))
+/* The symbol is external */
+#define S_SET_EXTERNAL(s) ((s)->sy_symbol.n_type |= N_EXT)
+/* The symbol is not external */
+#define S_CLEAR_EXTERNAL(s) ((s)->sy_symbol.n_type &= ~N_EXT)
+/* Set the name of the symbol */
+#define S_SET_NAME(s,v) ((s)->sy_symbol.n_name = (v))
+/* Set the offset in the string table */
+#define S_SET_OFFSET(s,v) ((s)->sy_name_offset = (v))
+/* Set the n_other expression value */
+#define S_SET_OTHER(s,v) ((s)->sy_symbol.n_other = (v))
+/* Set the n_desc expression value */
+#define S_SET_DESC(s,v) ((s)->sy_symbol.n_desc = (v))
+/* Set the n_type expression value */
+#define S_SET_TYPE(s,v) ((s)->sy_symbol.n_type = (v))
+
+
+/* File header macro and type definition */
+
+#define H_GET_TEXT_SIZE(h) ((h)->header.a_text)
+#define H_GET_DATA_SIZE(h) ((h)->header.a_data)
+#define H_GET_BSS_SIZE(h) ((h)->header.a_bss)
+
+#define H_SET_TEXT_SIZE(h,v) ((h)->header.a_text = md_section_align(SEG_TEXT, (v)))
+#define H_SET_DATA_SIZE(h,v) ((h)->header.a_data = md_section_align(SEG_DATA, (v)))
+#define H_SET_BSS_SIZE(h,v) ((h)->header.a_bss = md_section_align(SEG_BSS, (v)))
+
+#define H_SET_STRING_SIZE(h,v) ((h)->string_table_size = (v))
+#define H_SET_SYMBOL_TABLE_SIZE(h,v) ((h)->header.a_syms = (v) * \
+ sizeof(struct nlist))
+
+/* line numbering stuff. */
+#define OBJ_EMIT_LINENO(a, b, c) {;}
+
+#define obj_symbol_new_hook(s) {;}
+
+/* Force structure tags into scope so that their use in prototypes
+ will never be their first occurance. */
+struct fix;
+struct symbol;
+struct frag;
+
+/* obj-vms routines visible to the rest of gas. */
+
+extern void tc_aout_fix_to_chars PARAMS ((char *,struct fix *,relax_addressT));
+
+extern int vms_resolve_symbol_redef PARAMS ((struct symbol *));
+#define RESOLVE_SYMBOL_REDEFINITION(X) vms_resolve_symbol_redef(X)
+
+/* Compiler-generated label "__vax_g_doubles" is used to augment .stabs. */
+extern void vms_check_for_special_label PARAMS ((struct symbol *));
+#define obj_frob_label(X) vms_check_for_special_label(X)
+
+extern void vms_check_for_main PARAMS ((void));
+
+extern void vms_write_object_file PARAMS ((unsigned,unsigned,unsigned,
+ struct frag *,struct frag *));
+
+/* VMS executables are nothing like a.out, but the VMS port of gcc uses
+ a.out format stabs which obj-vms.c then translates. */
+
+#define AOUT_STABS
+
+
+#ifdef WANT_VMS_OBJ_DEFS
+
+/* The rest of this file contains definitions for constants used within
+ the actual VMS object file. We do not use a $ in the symbols (as per
+ usual VMS convention) since System V gags on it. */
+
+#define OBJ_S_C_HDR 0
+#define OBJ_S_C_HDR_MHD 0
+#define OBJ_S_C_HDR_LNM 1
+#define OBJ_S_C_HDR_SRC 2
+#define OBJ_S_C_HDR_TTL 3
+#define OBJ_S_C_HDR_CPR 4
+#define OBJ_S_C_HDR_MTC 5
+#define OBJ_S_C_HDR_GTX 6
+#define OBJ_S_C_GSD 1
+#define OBJ_S_C_GSD_PSC 0
+#define OBJ_S_C_GSD_SYM 1
+#define OBJ_S_C_GSD_EPM 2
+#define OBJ_S_C_GSD_PRO 3
+#define OBJ_S_C_GSD_SYMW 4
+#define OBJ_S_C_GSD_EPMW 5
+#define OBJ_S_C_GSD_PROW 6
+#define OBJ_S_C_GSD_IDC 7
+#define OBJ_S_C_GSD_ENV 8
+#define OBJ_S_C_GSD_LSY 9
+#define OBJ_S_C_GSD_LEPM 10
+#define OBJ_S_C_GSD_LPRO 11
+#define OBJ_S_C_GSD_SPSC 12
+#define OBJ_S_C_TIR 2
+#define OBJ_S_C_EOM 3
+#define OBJ_S_C_DBG 4
+#define OBJ_S_C_TBT 5
+#define OBJ_S_C_LNK 6
+#define OBJ_S_C_EOMW 7
+#define OBJ_S_C_MAXRECTYP 7
+#define OBJ_S_K_SUBTYP 1
+#define OBJ_S_C_SUBTYP 1
+#define OBJ_S_C_MAXRECSIZ 2048
+#define OBJ_S_C_STRLVL 0
+#define OBJ_S_C_SYMSIZ 31
+#define OBJ_S_C_STOREPLIM -1
+#define OBJ_S_C_PSCALILIM 9
+
+#define MHD_S_C_MHD 0
+#define MHD_S_C_LNM 1
+#define MHD_S_C_SRC 2
+#define MHD_S_C_TTL 3
+#define MHD_S_C_CPR 4
+#define MHD_S_C_MTC 5
+#define MHD_S_C_GTX 6
+#define MHD_S_C_MAXHDRTYP 6
+
+#define GSD_S_K_ENTRIES 1
+#define GSD_S_C_ENTRIES 1
+#define GSD_S_C_PSC 0
+#define GSD_S_C_SYM 1
+#define GSD_S_C_EPM 2
+#define GSD_S_C_PRO 3
+#define GSD_S_C_SYMW 4
+#define GSD_S_C_EPMW 5
+#define GSD_S_C_PROW 6
+#define GSD_S_C_IDC 7
+#define GSD_S_C_ENV 8
+#define GSD_S_C_LSY 9
+#define GSD_S_C_LEPM 10
+#define GSD_S_C_LPRO 11
+#define GSD_S_C_SPSC 12
+#define GSD_S_C_SYMV 13
+#define GSD_S_C_EPMV 14
+#define GSD_S_C_PROV 15
+#define GSD_S_C_MAXRECTYP 15
+
+#define GSY_S_M_WEAK 1
+#define GSY_S_M_DEF 2
+#define GSY_S_M_UNI 4
+#define GSY_S_M_REL 8
+
+#define LSY_S_M_DEF 2
+#define LSY_S_M_REL 8
+
+#define ENV_S_M_DEF 1
+#define ENV_S_M_NESTED 2
+
+#define GPS_S_M_PIC 1
+#define GPS_S_M_LIB 2
+#define GPS_S_M_OVR 4
+#define GPS_S_M_REL 8
+#define GPS_S_M_GBL 16
+#define GPS_S_M_SHR 32
+#define GPS_S_M_EXE 64
+#define GPS_S_M_RD 128
+#define GPS_S_M_WRT 256
+#define GPS_S_M_VEC 512
+#define GPS_S_K_NAME 9
+#define GPS_S_C_NAME 9
+
+#define TIR_S_C_STA_GBL 0
+#define TIR_S_C_STA_SB 1
+#define TIR_S_C_STA_SW 2
+#define TIR_S_C_STA_LW 3
+#define TIR_S_C_STA_PB 4
+#define TIR_S_C_STA_PW 5
+#define TIR_S_C_STA_PL 6
+#define TIR_S_C_STA_UB 7
+#define TIR_S_C_STA_UW 8
+#define TIR_S_C_STA_BFI 9
+#define TIR_S_C_STA_WFI 10
+#define TIR_S_C_STA_LFI 11
+#define TIR_S_C_STA_EPM 12
+#define TIR_S_C_STA_CKARG 13
+#define TIR_S_C_STA_WPB 14
+#define TIR_S_C_STA_WPW 15
+#define TIR_S_C_STA_WPL 16
+#define TIR_S_C_STA_LSY 17
+#define TIR_S_C_STA_LIT 18
+#define TIR_S_C_STA_LEPM 19
+#define TIR_S_C_MAXSTACOD 19
+#define TIR_S_C_MINSTOCOD 20
+#define TIR_S_C_STO_SB 20
+#define TIR_S_C_STO_SW 21
+#define TIR_S_C_STO_L 22
+#define TIR_S_C_STO_BD 23
+#define TIR_S_C_STO_WD 24
+#define TIR_S_C_STO_LD 25
+#define TIR_S_C_STO_LI 26
+#define TIR_S_C_STO_PIDR 27
+#define TIR_S_C_STO_PICR 28
+#define TIR_S_C_STO_RSB 29
+#define TIR_S_C_STO_RSW 30
+#define TIR_S_C_STO_RL 31
+#define TIR_S_C_STO_VPS 32
+#define TIR_S_C_STO_USB 33
+#define TIR_S_C_STO_USW 34
+#define TIR_S_C_STO_RUB 35
+#define TIR_S_C_STO_RUW 36
+#define TIR_S_C_STO_B 37
+#define TIR_S_C_STO_W 38
+#define TIR_S_C_STO_RB 39
+#define TIR_S_C_STO_RW 40
+#define TIR_S_C_STO_RIVB 41
+#define TIR_S_C_STO_PIRR 42
+#define TIR_S_C_MAXSTOCOD 42
+#define TIR_S_C_MINOPRCOD 50
+#define TIR_S_C_OPR_NOP 50
+#define TIR_S_C_OPR_ADD 51
+#define TIR_S_C_OPR_SUB 52
+#define TIR_S_C_OPR_MUL 53
+#define TIR_S_C_OPR_DIV 54
+#define TIR_S_C_OPR_AND 55
+#define TIR_S_C_OPR_IOR 56
+#define TIR_S_C_OPR_EOR 57
+#define TIR_S_C_OPR_NEG 58
+#define TIR_S_C_OPR_COM 59
+#define TIR_S_C_OPR_INSV 60
+#define TIR_S_C_OPR_ASH 61
+#define TIR_S_C_OPR_USH 62
+#define TIR_S_C_OPR_ROT 63
+#define TIR_S_C_OPR_SEL 64
+#define TIR_S_C_OPR_REDEF 65
+#define TIR_S_C_OPR_DFLIT 66
+#define TIR_S_C_MAXOPRCOD 66
+#define TIR_S_C_MINCTLCOD 80
+#define TIR_S_C_CTL_SETRB 80
+#define TIR_S_C_CTL_AUGRB 81
+#define TIR_S_C_CTL_DFLOC 82
+#define TIR_S_C_CTL_STLOC 83
+#define TIR_S_C_CTL_STKDL 84
+#define TIR_S_C_MAXCTLCOD 84
+
+/*
+ * Debugger symbol definitions: These are done by hand, as no
+ * machine-readable version seems
+ * to be available.
+ */
+#define DST_S_C_C 7 /* Language == "C" */
+#define DST_S_C_CXX 15 /* Language == "C++" */
+#define DST_S_C_VERSION 153
+#define DST_S_C_SOURCE 155 /* Source file */
+#define DST_S_C_PROLOG 162
+#define DST_S_C_BLKBEG 176 /* Beginning of block */
+#define DST_S_C_BLKEND 177 /* End of block */
+#define DST_S_C_ENTRY 181
+#define DST_S_C_PSECT 184
+#define DST_S_C_LINE_NUM 185 /* Line Number */
+#define DST_S_C_LBLORLIT 186
+#define DST_S_C_LABEL 187
+#define DST_S_C_MODBEG 188 /* Beginning of module */
+#define DST_S_C_MODEND 189 /* End of module */
+#define DST_S_C_RTNBEG 190 /* Beginning of routine */
+#define DST_S_C_RTNEND 191 /* End of routine */
+#define DST_S_C_DELTA_PC_W 1 /* Incr PC */
+#define DST_S_C_INCR_LINUM 2 /* Incr Line # */
+#define DST_S_C_INCR_LINUM_W 3 /* Incr Line # */
+#define DST_S_C_SET_LINUM_INCR 4
+#define DST_S_C_SET_LINUM_INCR_W 5
+#define DST_S_C_RESET_LINUM_INCR 6
+#define DST_S_C_BEG_STMT_MODE 7
+#define DST_S_C_END_STMT_MODE 8
+#define DST_S_C_SET_LINE_NUM 9 /* Set Line # */
+#define DST_S_C_SET_PC 10
+#define DST_S_C_SET_PC_W 11
+#define DST_S_C_SET_PC_L 12
+#define DST_S_C_SET_STMTNUM 13
+#define DST_S_C_TERM 14 /* End of lines */
+#define DST_S_C_TERM_W 15 /* End of lines */
+#define DST_S_C_SET_ABS_PC 16 /* Set PC */
+#define DST_S_C_DELTA_PC_L 17 /* Incr PC */
+#define DST_S_C_INCR_LINUM_L 18 /* Incr Line # */
+#define DST_S_C_SET_LINUM_B 19 /* Set Line # */
+#define DST_S_C_SET_LINUM_L 20 /* Set Line # */
+#define DST_S_C_TERM_L 21 /* End of lines */
+/* these are used with DST_S_C_SOURCE */
+#define DST_S_C_SRC_DECLFILE 1 /* Declare source file */
+#define DST_S_C_SRC_SETFILE 2 /* Set source file */
+#define DST_S_C_SRC_SETREC_L 3 /* Set record, longword value */
+#define DST_S_C_SRC_SETREC_W 4 /* Set record, word value */
+#define DST_S_C_SRC_DEFLINES_W 10 /* # of line, word counter */
+#define DST_S_C_SRC_DEFLINES_B 11 /* # of line, byte counter */
+#define DST_S_C_SRC_FORMFEED 16 /* ^L counts as a record */
+/* the following are the codes for the various data types. Anything not on
+ * the list is included under 'advanced_type'
+ */
+#define DBG_S_C_UCHAR 0x02
+#define DBG_S_C_USINT 0x03
+#define DBG_S_C_ULINT 0x04
+#define DBG_S_C_UQUAD 0x05
+#define DBG_S_C_SCHAR 0x06
+#define DBG_S_C_SSINT 0x07
+#define DBG_S_C_SLINT 0x08
+#define DBG_S_C_SQUAD 0x09
+#define DBG_S_C_REAL4 0x0a
+#define DBG_S_C_REAL8 0x0b /* D_float double */
+#define DBG_S_C_COMPLX4 0x0c /* 2xF_float complex float */
+#define DBG_S_C_COMPLX8 0x0d /* 2xD_float complex double */
+#define DBG_S_C_REAL8_G 0x1b /* G_float double */
+#define DBG_S_C_COMPLX8_G 0x1d /* 2xG_float complex double */
+#define DBG_S_C_FUNCTION_ADDR 0x17
+#define DBG_S_C_ADVANCED_TYPE 0xa3
+/* Some of these are just for future reference. [pr]
+ */
+#define DBG_S_C_UBITA 0x01 /* unsigned, aligned bit field */
+#define DBG_S_C_UBITU 0x22 /* unsigned, unaligned bit field */
+#define DBG_S_C_SBITA 0x29 /* signed, aligned bit field */
+#define DBG_S_C_SBITU 0x2a /* signed, unaligned bit field */
+#define DBG_S_C_CSTRING 0x2e /* asciz ('\0' terminated) string */
+#define DBG_S_C_WCHAR 0x38 /* wchar_t */
+/* These are descriptor class codes.
+ */
+#define DSC_K_CLASS_S 0x01 /* static (fixed length) */
+#define DSC_K_CLASS_D 0x02 /* dynamic string (not via malloc!) */
+#define DSC_K_CLASS_A 0x04 /* array */
+#define DSC_K_CLASS_UBS 0x0d /* unaligned bit string */
+/* These are the codes that are used to generate the definitions of struct
+ * union and enum records
+ */
+#define DBG_S_C_ENUM_ITEM 0xa4
+#define DBG_S_C_ENUM_START 0xa5
+#define DBG_S_C_ENUM_END 0xa6
+#define DBG_S_C_STRUCT_ITEM DST_K_VFLAGS_BITOFFS /* 0xff */
+#define DBG_S_C_STRUCT_START 0xab
+#define DBG_S_C_STRUCT_END 0xac
+#define DST_K_TYPSPEC 0xaf /* type specification */
+/* These codes are used in the generation of the symbol definition records
+ */
+#define DST_K_VFLAGS_NOVAL 0x80 /* struct definition only */
+#define DST_K_VFLAGS_DSC 0xfa /* descriptor used */
+#define DST_K_VFLAGS_TVS 0xfb /* trailing value specified */
+#define DST_K_VS_FOLLOWS 0xfd /* value spec follows */
+#define DST_K_VFLAGS_BITOFFS 0xff /* value contains bit offset */
+#define DST_K_VALKIND_LITERAL 0
+#define DST_K_VALKIND_ADDR 1
+#define DST_K_VALKIND_DESC 2
+#define DST_K_VALKIND_REG 3
+#define DST_K_REG_VAX_AP 0x0c /* R12 */
+#define DST_K_REG_VAX_FP 0x0d /* R13 */
+#define DST_K_REG_VAX_SP 0x0e /* R14 */
+#define DST_V_VALKIND 0 /* offset of valkind field */
+#define DST_V_INDIRECT 2 /* offset to indirect bit */
+#define DST_V_DISP 3 /* offset to displacement bit */
+#define DST_V_REGNUM 4 /* offset to register number */
+#define DST_M_INDIRECT (1<<DST_V_INDIRECT)
+#define DST_M_DISP (1<<DST_V_DISP)
+#define DBG_C_FUNCTION_PARAM /* 0xc9 */ \
+ (DST_K_VALKIND_ADDR|DST_M_DISP|(DST_K_REG_VAX_AP<<DST_V_REGNUM))
+#define DBG_C_LOCAL_SYM /* 0xd9 */ \
+ (DST_K_VALKIND_ADDR|DST_M_DISP|(DST_K_REG_VAX_FP<<DST_V_REGNUM))
+/* Kinds of value specifications
+ */
+#define DST_K_VS_ALLOC_SPLIT 3 /* split lifetime */
+/* Kinds of type specifications
+ */
+#define DST_K_TS_ATOM 0x01 /* atomic type specification */
+#define DST_K_TS_DSC 0x02 /* descriptor type spec */
+#define DST_K_TS_IND 0x03 /* indirect type specification */
+#define DST_K_TS_TPTR 0x04 /* typed pointer type spec */
+#define DST_K_TS_PTR 0x05 /* pointer type spec */
+#define DST_K_TS_ARRAY 0x07 /* array type spec */
+#define DST_K_TS_NOV_LENG 0x0e /* novel length type spec */
+/* These are the codes that are used in the suffix records to determine the
+ * actual data type
+ */
+#define DBG_S_C_BASIC DST_K_TS_ATOM
+#define DBG_S_C_BASIC_ARRAY DST_K_TS_DSC
+#define DBG_S_C_STRUCT DST_K_TS_IND
+#define DBG_S_C_POINTER DST_K_TS_TPTR
+#define DBG_S_C_VOID DST_K_TS_PTR
+#define DBG_S_C_COMPLEX_ARRAY DST_K_TS_ARRAY
+
+#endif /* WANT_VMS_OBJ_DEFS */
+
+/* end of obj-vms.h */
diff --git a/gas/config/tc-a29k.c b/gas/config/tc-a29k.c
new file mode 100644
index 0000000000..600fec5885
--- /dev/null
+++ b/gas/config/tc-a29k.c
@@ -0,0 +1,1296 @@
+/* tc-a29k.c -- Assemble for the AMD 29000.
+ Copyright (C) 1989, 90, 91, 92, 93, 94, 95, 1998
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* John Gilmore has reorganized this module somewhat, to make it easier
+ to convert it to new machines' assemblers as desired. There was too
+ much bloody rewriting required before. There still probably is. */
+
+#include <ctype.h>
+#include "as.h"
+
+#include "opcode/a29k.h"
+
+/* Make it easier to clone this machine desc into another one. */
+#define machine_opcode a29k_opcode
+#define machine_opcodes a29k_opcodes
+#define machine_ip a29k_ip
+#define machine_it a29k_it
+
+#define IMMEDIATE_BIT 0x01000000 /* Turns RB into Immediate */
+#define ABSOLUTE_BIT 0x01000000 /* Turns PC-relative to Absolute */
+#define CE_BIT 0x00800000 /* Coprocessor enable in LOAD */
+#define UI_BIT 0x00000080 /* Unsigned integer in CONVERT */
+
+/* handle of the OPCODE hash table */
+static struct hash_control *op_hash = NULL;
+
+struct machine_it
+ {
+ char *error;
+ unsigned long opcode;
+ struct nlist *nlistp;
+ expressionS exp;
+ int pcrel;
+ int reloc_offset; /* Offset of reloc within insn */
+
+ int reloc;
+ }
+the_insn;
+
+static void machine_ip PARAMS ((char *str));
+/* static void print_insn PARAMS ((struct machine_it *insn)); */
+#ifndef OBJ_COFF
+static void s_data1 PARAMS ((void));
+static void s_use PARAMS ((int));
+#endif
+
+const pseudo_typeS
+md_pseudo_table[] =
+{
+ {"align", s_align_bytes, 4},
+ {"block", s_space, 0},
+ {"cputype", s_ignore, 0}, /* CPU as 29000 or 29050 */
+ {"reg", s_lsym, 0}, /* Register equate, same as equ */
+ {"space", s_ignore, 0}, /* Listing control */
+ {"sect", s_ignore, 0}, /* Creation of coff sections */
+#ifndef OBJ_COFF
+ /* We can do this right with coff. */
+ {"use", s_use, 0},
+#endif
+ {"word", cons, 4},
+ {NULL, 0, 0},
+};
+
+#if defined(BFD_HEADERS)
+#ifdef RELSZ
+const int md_reloc_size = RELSZ; /* Coff headers */
+#else
+const int md_reloc_size = 12; /* something else headers */
+#endif
+#else
+const int md_reloc_size = 12; /* Not bfdized*/
+#endif
+
+/* This array holds the chars that always start a comment. If the
+ pre-processor is disabled, these aren't very useful */
+const char comment_chars[] = ";";
+
+/* This array holds the chars that only start a comment at the beginning of
+ a line. If the line seems to have the form '# 123 filename'
+ .line and .file directives will appear in the pre-processed output */
+/* Note that input_file.c hand checks for '#' at the beginning of the
+ first line of the input file. This is because the compiler outputs
+ #NO_APP at the beginning of its output. */
+/* Also note that comments like this one will always work */
+const char line_comment_chars[] = "#";
+
+/* We needed an unused char for line separation to work around the
+ lack of macros, using sed and such. */
+const char line_separator_chars[] = "@";
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* As in 0f12.456 */
+/* or 0d1.2345e12 */
+const char FLT_CHARS[] = "rRsSfFdDxXpP";
+
+/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
+ changed in read.c. Ideally it shouldn't have to know about it at
+ all, but nothing is ideal around here. */
+
+/*
+ * anull bit - causes the branch delay slot instructions to not be executed
+ */
+#define ANNUL (1 << 29)
+
+#ifndef OBJ_COFF
+
+static void
+s_use (ignore)
+ int ignore;
+{
+ if (strncmp (input_line_pointer, ".text", 5) == 0)
+ {
+ input_line_pointer += 5;
+ s_text (0);
+ return;
+ }
+ if (strncmp (input_line_pointer, ".data", 5) == 0)
+ {
+ input_line_pointer += 5;
+ s_data (0);
+ return;
+ }
+ if (strncmp (input_line_pointer, ".data1", 6) == 0)
+ {
+ input_line_pointer += 6;
+ s_data1 ();
+ return;
+ }
+ /* Literals can't go in the text segment because you can't read from
+ instruction memory on some 29k's. So, into initialized data. */
+ if (strncmp (input_line_pointer, ".lit", 4) == 0)
+ {
+ input_line_pointer += 4;
+ subseg_set (SEG_DATA, 200);
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ as_bad (_("Unknown segment type"));
+ demand_empty_rest_of_line ();
+}
+
+static void
+s_data1 ()
+{
+ subseg_set (SEG_DATA, 1);
+ demand_empty_rest_of_line ();
+}
+
+#endif /* OBJ_COFF */
+
+/* Install symbol definition that maps REGNAME to REGNO.
+ FIXME-SOON: These are not recognized in mixed case. */
+
+static void
+insert_sreg (regname, regnum)
+ char *regname;
+ int regnum;
+{
+ /* FIXME-SOON, put something in these syms so they won't be output
+ to the symbol table of the resulting object file. */
+
+ /* Must be large enough to hold the names of the special registers. */
+ char buf[80];
+ int i;
+
+ symbol_table_insert (symbol_new (regname, SEG_REGISTER, (valueT) regnum,
+ &zero_address_frag));
+ for (i = 0; regname[i]; i++)
+ buf[i] = islower (regname[i]) ? toupper (regname[i]) : regname[i];
+ buf[i] = '\0';
+
+ symbol_table_insert (symbol_new (buf, SEG_REGISTER, (valueT) regnum,
+ &zero_address_frag));
+}
+
+/* Install symbol definitions for assorted special registers.
+ See ASM29K Ref page 2-9. */
+
+void
+define_some_regs ()
+{
+#define SREG 256
+
+ /* Protected special-purpose register names */
+ insert_sreg ("vab", SREG + 0);
+ insert_sreg ("ops", SREG + 1);
+ insert_sreg ("cps", SREG + 2);
+ insert_sreg ("cfg", SREG + 3);
+ insert_sreg ("cha", SREG + 4);
+ insert_sreg ("chd", SREG + 5);
+ insert_sreg ("chc", SREG + 6);
+ insert_sreg ("rbp", SREG + 7);
+ insert_sreg ("tmc", SREG + 8);
+ insert_sreg ("tmr", SREG + 9);
+ insert_sreg ("pc0", SREG + 10);
+ insert_sreg ("pc1", SREG + 11);
+ insert_sreg ("pc2", SREG + 12);
+ insert_sreg ("mmu", SREG + 13);
+ insert_sreg ("lru", SREG + 14);
+
+ /* Additional protected special-purpose registers for the 29050 */
+ insert_sreg ("rsn", SREG + 15);
+ insert_sreg ("rma0", SREG + 16);
+ insert_sreg ("rmc0", SREG + 17);
+ insert_sreg ("rma1", SREG + 18);
+ insert_sreg ("rmc1", SREG + 19);
+ insert_sreg ("spc0", SREG + 20);
+ insert_sreg ("spc1", SREG + 21);
+ insert_sreg ("spc2", SREG + 22);
+ insert_sreg ("iba0", SREG + 23);
+ insert_sreg ("ibc0", SREG + 24);
+ insert_sreg ("iba1", SREG + 25);
+ insert_sreg ("ibc1", SREG + 26);
+
+ /* Additional registers for the 29040. */
+ insert_sreg ("dba", SREG + 27);
+ insert_sreg ("dbc", SREG + 28);
+ insert_sreg ("cir", SREG + 29);
+ insert_sreg ("cdr", SREG + 30);
+
+ /* Unprotected special-purpose register names */
+ insert_sreg ("ipc", SREG + 128);
+ insert_sreg ("ipa", SREG + 129);
+ insert_sreg ("ipb", SREG + 130);
+ insert_sreg ("q", SREG + 131);
+ insert_sreg ("alu", SREG + 132);
+ insert_sreg ("bp", SREG + 133);
+ insert_sreg ("fc", SREG + 134);
+ insert_sreg ("cr", SREG + 135);
+ insert_sreg ("fpe", SREG + 160);
+ insert_sreg ("inte", SREG + 161);
+ insert_sreg ("fps", SREG + 162);
+ /* "", SREG+163); Reserved */
+ insert_sreg ("exop", SREG + 164);
+}
+
+/* This function is called once, at assembler startup time. It should
+ set up all the tables, etc., that the MD part of the assembler will
+ need. */
+void
+md_begin ()
+{
+ register const char *retval = NULL;
+ int lose = 0;
+ register int skipnext = 0;
+ register unsigned int i;
+ register char *strend, *strend2;
+
+ /* Hash up all the opcodes for fast use later. */
+
+ op_hash = hash_new ();
+
+ for (i = 0; i < num_opcodes; i++)
+ {
+ const char *name = machine_opcodes[i].name;
+
+ if (skipnext)
+ {
+ skipnext = 0;
+ continue;
+ }
+
+ /* Hack to avoid multiple opcode entries. We pre-locate all the
+ variations (b/i field and P/A field) and handle them. */
+
+ if (!strcmp (name, machine_opcodes[i + 1].name))
+ {
+ if ((machine_opcodes[i].opcode & 0x01000000) != 0
+ || (machine_opcodes[i + 1].opcode & 0x01000000) == 0
+ || ((machine_opcodes[i].opcode | 0x01000000)
+ != machine_opcodes[i + 1].opcode))
+ goto bad_table;
+ strend = machine_opcodes[i].args + strlen (machine_opcodes[i].args) - 1;
+ strend2 = machine_opcodes[i + 1].args + strlen (machine_opcodes[i + 1].args) - 1;
+ switch (*strend)
+ {
+ case 'b':
+ if (*strend2 != 'i')
+ goto bad_table;
+ break;
+ case 'P':
+ if (*strend2 != 'A')
+ goto bad_table;
+ break;
+ default:
+ bad_table:
+ fprintf (stderr, "internal error: can't handle opcode %s\n",
+ name);
+ lose = 1;
+ }
+
+ /* OK, this is an i/b or A/P pair. We skip the
+ higher-valued one, and let the code for operand checking
+ handle OR-ing in the bit. */
+ skipnext = 1;
+ }
+
+ retval = hash_insert (op_hash, name, (PTR) &machine_opcodes[i]);
+ if (retval != NULL)
+ {
+ fprintf (stderr, "internal error: can't hash `%s': %s\n",
+ machine_opcodes[i].name, retval);
+ lose = 1;
+ }
+ }
+
+ if (lose)
+ as_fatal (_("Broken assembler. No assembly attempted."));
+
+ define_some_regs ();
+}
+
+/* Assemble a single instruction. Its label has already been handled
+ by the generic front end. We just parse opcode and operands, and
+ produce the bytes of data and relocation. */
+
+void
+md_assemble (str)
+ char *str;
+{
+ char *toP;
+
+ know (str);
+ machine_ip (str);
+ toP = frag_more (4);
+ /* put out the opcode */
+ md_number_to_chars (toP, the_insn.opcode, 4);
+
+ /* put out the symbol-dependent stuff */
+ if (the_insn.reloc != NO_RELOC)
+ {
+ fix_new_exp (frag_now,
+ (toP - frag_now->fr_literal + the_insn.reloc_offset),
+ 4, /* size */
+ &the_insn.exp,
+ the_insn.pcrel,
+ the_insn.reloc);
+ }
+}
+
+char *
+parse_operand (s, operandp, opt)
+ char *s;
+ expressionS *operandp;
+ int opt;
+{
+ char *save = input_line_pointer;
+ char *new;
+
+ input_line_pointer = s;
+ expression (operandp);
+ if (operandp->X_op == O_absent && ! opt)
+ as_bad (_("missing operand"));
+ new = input_line_pointer;
+ input_line_pointer = save;
+ return new;
+}
+
+/* Instruction parsing. Takes a string containing the opcode.
+ Operands are at input_line_pointer. Output is in the_insn.
+ Warnings or errors are generated. */
+
+static void
+machine_ip (str)
+ char *str;
+{
+ char *s;
+ const char *args;
+ struct machine_opcode *insn;
+ char *argsStart;
+ unsigned long opcode;
+ expressionS the_operand;
+ expressionS *operand = &the_operand;
+ unsigned int reg;
+
+ /* Must handle `div0' opcode. */
+ s = str;
+ if (isalpha (*s))
+ for (; isalnum (*s); ++s)
+ if (isupper (*s))
+ *s = tolower (*s);
+
+ switch (*s)
+ {
+ case '\0':
+ break;
+
+ case ' ': /* FIXME-SOMEDAY more whitespace */
+ *s++ = '\0';
+ break;
+
+ default:
+ as_bad (_("Unknown opcode: `%s'"), str);
+ return;
+ }
+ if ((insn = (struct machine_opcode *) hash_find (op_hash, str)) == NULL)
+ {
+ as_bad (_("Unknown opcode `%s'."), str);
+ return;
+ }
+ argsStart = s;
+ opcode = insn->opcode;
+ memset (&the_insn, '\0', sizeof (the_insn));
+ the_insn.reloc = NO_RELOC;
+
+ /* Build the opcode, checking as we go to make sure that the
+ operands match.
+
+ If an operand matches, we modify the_insn or opcode appropriately,
+ and do a "continue". If an operand fails to match, we "break". */
+
+ if (insn->args[0] != '\0')
+ {
+ /* Prime the pump. */
+ s = parse_operand (s, operand, insn->args[0] == 'I');
+ }
+
+ for (args = insn->args;; ++args)
+ {
+ switch (*args)
+ {
+
+ case '\0': /* end of args */
+ if (*s == '\0')
+ {
+ /* We are truly done. */
+ the_insn.opcode = opcode;
+ return;
+ }
+ as_bad (_("Too many operands: %s"), s);
+ break;
+
+ case ',': /* Must match a comma */
+ if (*s++ == ',')
+ {
+ /* Parse next operand. */
+ s = parse_operand (s, operand, args[1] == 'I');
+ continue;
+ }
+ break;
+
+ case 'v': /* Trap numbers (immediate field) */
+ if (operand->X_op == O_constant)
+ {
+ if (operand->X_add_number < 256)
+ {
+ opcode |= (operand->X_add_number << 16);
+ continue;
+ }
+ else
+ {
+ as_bad (_("Immediate value of %ld is too large"),
+ (long) operand->X_add_number);
+ continue;
+ }
+ }
+ the_insn.reloc = RELOC_8;
+ the_insn.reloc_offset = 1; /* BIG-ENDIAN Byte 1 of insn */
+ the_insn.exp = *operand;
+ continue;
+
+ case 'b': /* A general register or 8-bit immediate */
+ case 'i':
+ /* We treat the two cases identically since we mashed
+ them together in the opcode table. */
+ if (operand->X_op == O_register)
+ goto general_reg;
+
+ /* Make sure the 'i' case really exists. */
+ if ((insn->opcode | IMMEDIATE_BIT) != (insn + 1)->opcode)
+ break;
+
+ opcode |= IMMEDIATE_BIT;
+ if (operand->X_op == O_constant)
+ {
+ if (operand->X_add_number < 256)
+ {
+ opcode |= operand->X_add_number;
+ continue;
+ }
+ else
+ {
+ as_bad (_("Immediate value of %ld is too large"),
+ (long) operand->X_add_number);
+ continue;
+ }
+ }
+ the_insn.reloc = RELOC_8;
+ the_insn.reloc_offset = 3; /* BIG-ENDIAN Byte 3 of insn */
+ the_insn.exp = *operand;
+ continue;
+
+ case 'a': /* next operand must be a register */
+ case 'c':
+ general_reg:
+ /* lrNNN or grNNN or %%expr or a user-def register name */
+ if (operand->X_op != O_register)
+ break; /* Only registers */
+ know (operand->X_add_symbol == 0);
+ know (operand->X_op_symbol == 0);
+ reg = operand->X_add_number;
+ if (reg >= SREG)
+ break; /* No special registers */
+
+ /* Got the register, now figure out where it goes in the
+ opcode. */
+ switch (*args)
+ {
+ case 'a':
+ opcode |= reg << 8;
+ continue;
+
+ case 'b':
+ case 'i':
+ opcode |= reg;
+ continue;
+
+ case 'c':
+ opcode |= reg << 16;
+ continue;
+ }
+ as_fatal (_("failed sanity check."));
+ break;
+
+ case 'x': /* 16 bit constant, zero-extended */
+ case 'X': /* 16 bit constant, one-extended */
+ if (operand->X_op == O_constant)
+ {
+ opcode |= (operand->X_add_number & 0xFF) << 0 |
+ ((operand->X_add_number & 0xFF00) << 8);
+ continue;
+ }
+ the_insn.reloc = RELOC_CONST;
+ the_insn.exp = *operand;
+ continue;
+
+ case 'h':
+ if (operand->X_op == O_constant)
+ {
+ opcode |= (operand->X_add_number & 0x00FF0000) >> 16 |
+ (((unsigned long) operand->X_add_number
+ /* avoid sign ext */ & 0xFF000000) >> 8);
+ continue;
+ }
+ the_insn.reloc = RELOC_CONSTH;
+ the_insn.exp = *operand;
+ continue;
+
+ case 'P': /* PC-relative jump address */
+ case 'A': /* Absolute jump address */
+ /* These two are treated together since we folded the
+ opcode table entries together. */
+ if (operand->X_op == O_constant)
+ {
+ /* Make sure the 'A' case really exists. */
+ if ((insn->opcode | ABSOLUTE_BIT) != (insn + 1)->opcode)
+ break;
+ {
+ bfd_vma v, mask;
+ mask = 0x1ffff;
+ v = operand->X_add_number & ~ mask;
+ if (v)
+ as_bad ("call/jmp target out of range");
+ }
+ opcode |= ABSOLUTE_BIT |
+ (operand->X_add_number & 0x0003FC00) << 6 |
+ ((operand->X_add_number & 0x000003FC) >> 2);
+ continue;
+ }
+ the_insn.reloc = RELOC_JUMPTARG;
+ the_insn.exp = *operand;
+ the_insn.pcrel = 1; /* Assume PC-relative jump */
+ /* FIXME-SOON, Do we figure out whether abs later, after
+ know sym val? */
+ continue;
+
+ case 'e': /* Coprocessor enable bit for LOAD/STORE insn */
+ if (operand->X_op == O_constant)
+ {
+ if (operand->X_add_number == 0)
+ continue;
+ if (operand->X_add_number == 1)
+ {
+ opcode |= CE_BIT;
+ continue;
+ }
+ }
+ break;
+
+ case 'n': /* Control bits for LOAD/STORE instructions */
+ if (operand->X_op == O_constant &&
+ operand->X_add_number < 128)
+ {
+ opcode |= (operand->X_add_number << 16);
+ continue;
+ }
+ break;
+
+ case 's': /* Special register number */
+ if (operand->X_op != O_register)
+ break; /* Only registers */
+ if (operand->X_add_number < SREG)
+ break; /* Not a special register */
+ opcode |= (operand->X_add_number & 0xFF) << 8;
+ continue;
+
+ case 'u': /* UI bit of CONVERT */
+ if (operand->X_op == O_constant)
+ {
+ if (operand->X_add_number == 0)
+ continue;
+ if (operand->X_add_number == 1)
+ {
+ opcode |= UI_BIT;
+ continue;
+ }
+ }
+ break;
+
+ case 'r': /* RND bits of CONVERT */
+ if (operand->X_op == O_constant &&
+ operand->X_add_number < 8)
+ {
+ opcode |= operand->X_add_number << 4;
+ continue;
+ }
+ break;
+
+ case 'I': /* ID bits of INV and IRETINV. */
+ /* This operand is optional. */
+ if (operand->X_op == O_absent)
+ continue;
+ else if (operand->X_op == O_constant
+ && operand->X_add_number < 4)
+ {
+ opcode |= operand->X_add_number << 16;
+ continue;
+ }
+ break;
+
+ case 'd': /* FD bits of CONVERT */
+ if (operand->X_op == O_constant &&
+ operand->X_add_number < 4)
+ {
+ opcode |= operand->X_add_number << 2;
+ continue;
+ }
+ break;
+
+
+ case 'f': /* FS bits of CONVERT */
+ if (operand->X_op == O_constant &&
+ operand->X_add_number < 4)
+ {
+ opcode |= operand->X_add_number << 0;
+ continue;
+ }
+ break;
+
+ case 'C':
+ if (operand->X_op == O_constant &&
+ operand->X_add_number < 4)
+ {
+ opcode |= operand->X_add_number << 16;
+ continue;
+ }
+ break;
+
+ case 'F':
+ if (operand->X_op == O_constant &&
+ operand->X_add_number < 16)
+ {
+ opcode |= operand->X_add_number << 18;
+ continue;
+ }
+ break;
+
+ default:
+ BAD_CASE (*args);
+ }
+ /* Types or values of args don't match. */
+ as_bad ("Invalid operands");
+ return;
+ }
+}
+
+/* This is identical to the md_atof in m68k.c. I think this is right,
+ but I'm not sure.
+
+ Turn a string in input_line_pointer into a floating point constant
+ of type type, and store the appropriate bytes in *litP. The number
+ of LITTLENUMS emitted is stored in *sizeP . An error message is
+ returned, or NULL on OK. */
+
+/* Equal to MAX_PRECISION in atof-ieee.c */
+#define MAX_LITTLENUMS 6
+
+char *
+md_atof (type, litP, sizeP)
+ char type;
+ char *litP;
+ int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ char *t;
+
+ switch (type)
+ {
+
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ prec = 4;
+ break;
+
+ case 'x':
+ case 'X':
+ prec = 6;
+ break;
+
+ case 'p':
+ case 'P':
+ prec = 6;
+ break;
+
+ default:
+ *sizeP = 0;
+ return "Bad call to MD_ATOF()";
+ }
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+ *sizeP = prec * sizeof (LITTLENUM_TYPE);
+ for (wordP = words; prec--;)
+ {
+ md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+ return 0;
+}
+
+/*
+ * Write out big-endian.
+ */
+void
+md_number_to_chars (buf, val, n)
+ char *buf;
+ valueT val;
+ int n;
+{
+ number_to_chars_bigendian (buf, val, n);
+}
+
+void
+md_apply_fix (fixP, val)
+ fixS *fixP;
+ long val;
+{
+ char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
+
+ fixP->fx_addnumber = val; /* Remember value for emit_reloc */
+
+
+ know (fixP->fx_size == 4);
+ know (fixP->fx_r_type < NO_RELOC);
+
+ /* This is a hack. There should be a better way to handle this. */
+ if (fixP->fx_r_type == RELOC_WDISP30 && fixP->fx_addsy)
+ {
+ val += fixP->fx_where + fixP->fx_frag->fr_address;
+ }
+
+ switch (fixP->fx_r_type)
+ {
+
+ case RELOC_32:
+ buf[0] = val >> 24;
+ buf[1] = val >> 16;
+ buf[2] = val >> 8;
+ buf[3] = val;
+ break;
+
+ case RELOC_8:
+ buf[0] = val;
+ break;
+
+ case RELOC_WDISP30:
+ val = (val >>= 2) + 1;
+ buf[0] |= (val >> 24) & 0x3f;
+ buf[1] = (val >> 16);
+ buf[2] = val >> 8;
+ buf[3] = val;
+ break;
+
+ case RELOC_HI22:
+ buf[1] |= (val >> 26) & 0x3f;
+ buf[2] = val >> 18;
+ buf[3] = val >> 10;
+ break;
+
+ case RELOC_LO10:
+ buf[2] |= (val >> 8) & 0x03;
+ buf[3] = val;
+ break;
+
+ case RELOC_BASE13:
+ buf[2] |= (val >> 8) & 0x1f;
+ buf[3] = val;
+ break;
+
+ case RELOC_WDISP22:
+ val = (val >>= 2) + 1;
+ /* FALLTHROUGH */
+ case RELOC_BASE22:
+ buf[1] |= (val >> 16) & 0x3f;
+ buf[2] = val >> 8;
+ buf[3] = val;
+ break;
+
+ case RELOC_JUMPTARG: /* 00XX00XX pattern in a word */
+ if (!fixP->fx_done)
+ {
+ /* The linker tries to support both AMD and old GNU style
+ R_IREL relocs. That means that if the addend is exactly
+ the negative of the address within the section, the
+ linker will not handle it correctly. */
+ if (fixP->fx_pcrel
+ && val != 0
+ && val == - (fixP->fx_frag->fr_address + fixP->fx_where))
+ as_bad_where
+ (fixP->fx_file, fixP->fx_line,
+ "the linker will not handle this relocation correctly");
+ }
+ else if (fixP->fx_pcrel)
+ {
+ long v = val >> 17;
+ if (v != 0 && v != -1)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "call/jmp target out of range");
+ }
+ else
+ /* this case was supposed to be handled in machine_ip */
+ abort ();
+ buf[1] = val >> 10; /* Holds bits 0003FFFC of address */
+ buf[3] = val >> 2;
+ break;
+
+ case RELOC_CONST: /* 00XX00XX pattern in a word */
+ buf[1] = val >> 8; /* Holds bits 0000XXXX */
+ buf[3] = val;
+ break;
+
+ case RELOC_CONSTH: /* 00XX00XX pattern in a word */
+ buf[1] = val >> 24; /* Holds bits XXXX0000 */
+ buf[3] = val >> 16;
+ break;
+
+ case NO_RELOC:
+ default:
+ as_bad (_("bad relocation type: 0x%02x"), fixP->fx_r_type);
+ break;
+ }
+}
+
+#ifdef OBJ_COFF
+short
+tc_coff_fix2rtype (fixP)
+ fixS *fixP;
+{
+
+ switch (fixP->fx_r_type)
+ {
+ case RELOC_32:
+ return (R_WORD);
+ case RELOC_8:
+ return (R_BYTE);
+ case RELOC_CONST:
+ return (R_ILOHALF);
+ case RELOC_CONSTH:
+ return (R_IHIHALF);
+ case RELOC_JUMPTARG:
+ return (R_IREL);
+ default:
+ printf (_("need %o3\n"), fixP->fx_r_type);
+ abort ();
+ } /* switch on type */
+
+ return (0);
+}
+
+#endif /* OBJ_COFF */
+
+/* should never be called for 29k */
+void
+md_convert_frag (headers, seg, fragP)
+ object_headers *headers;
+ segT seg;
+ register fragS *fragP;
+{
+ as_fatal (_("a29k_convert_frag\n"));
+}
+
+/* should never be called for a29k */
+int
+md_estimate_size_before_relax (fragP, segtype)
+ register fragS *fragP;
+ segT segtype;
+{
+ as_fatal (_("a29k_estimate_size_before_relax\n"));
+ return 0;
+}
+
+#if 0
+/* for debugging only */
+static void
+print_insn (insn)
+ struct machine_it *insn;
+{
+ char *Reloc[] =
+ {
+ "RELOC_8",
+ "RELOC_16",
+ "RELOC_32",
+ "RELOC_DISP8",
+ "RELOC_DISP16",
+ "RELOC_DISP32",
+ "RELOC_WDISP30",
+ "RELOC_WDISP22",
+ "RELOC_HI22",
+ "RELOC_22",
+ "RELOC_13",
+ "RELOC_LO10",
+ "RELOC_SFA_BASE",
+ "RELOC_SFA_OFF13",
+ "RELOC_BASE10",
+ "RELOC_BASE13",
+ "RELOC_BASE22",
+ "RELOC_PC10",
+ "RELOC_PC22",
+ "RELOC_JMP_TBL",
+ "RELOC_SEGOFF16",
+ "RELOC_GLOB_DAT",
+ "RELOC_JMP_SLOT",
+ "RELOC_RELATIVE",
+ "NO_RELOC"
+ };
+
+ if (insn->error)
+ {
+ fprintf (stderr, "ERROR: %s\n");
+ }
+ fprintf (stderr, "opcode=0x%08x\n", insn->opcode);
+ fprintf (stderr, "reloc = %s\n", Reloc[insn->reloc]);
+ fprintf (stderr, "exp = {\n");
+ fprintf (stderr, "\t\tX_add_symbol = %s\n",
+ insn->exp.X_add_symbol ?
+ (S_GET_NAME (insn->exp.X_add_symbol) ?
+ S_GET_NAME (insn->exp.X_add_symbol) : "???") : "0");
+ fprintf (stderr, "\t\tX_op_symbol = %s\n",
+ insn->exp.X_op_symbol ?
+ (S_GET_NAME (insn->exp.X_op_symbol) ?
+ S_GET_NAME (insn->exp.X_op_symbol) : "???") : "0");
+ fprintf (stderr, "\t\tX_add_number = %d\n",
+ insn->exp.X_add_number);
+ fprintf (stderr, "}\n");
+}
+
+#endif
+
+/* Translate internal representation of relocation info to target format.
+
+ On sparc/29k: first 4 bytes are normal unsigned long address, next three
+ bytes are index, most sig. byte first. Byte 7 is broken up with
+ bit 7 as external, bits 6 & 5 unused, and the lower
+ five bits as relocation type. Next 4 bytes are long addend. */
+/* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */
+
+#ifdef OBJ_AOUT
+
+void
+tc_aout_fix_to_chars (where, fixP, segment_address_in_file)
+ char *where;
+ fixS *fixP;
+ relax_addressT segment_address_in_file;
+{
+ long r_symbolnum;
+
+ know (fixP->fx_r_type < NO_RELOC);
+ know (fixP->fx_addsy != NULL);
+
+ md_number_to_chars (where,
+ fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
+ 4);
+
+ r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy)
+ ? S_GET_TYPE (fixP->fx_addsy)
+ : fixP->fx_addsy->sy_number);
+
+ where[4] = (r_symbolnum >> 16) & 0x0ff;
+ where[5] = (r_symbolnum >> 8) & 0x0ff;
+ where[6] = r_symbolnum & 0x0ff;
+ where[7] = (((!S_IS_DEFINED (fixP->fx_addsy)) << 7) & 0x80) | (0 & 0x60) | (fixP->fx_r_type & 0x1F);
+ /* Also easy */
+ md_number_to_chars (&where[8], fixP->fx_addnumber, 4);
+}
+
+#endif /* OBJ_AOUT */
+
+CONST char *md_shortopts = "";
+struct option md_longopts[] = {
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof(md_longopts);
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ return 0;
+}
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+}
+
+/* This is called when a line is unrecognized. This is used to handle
+ definitions of a29k style local labels. */
+
+int
+a29k_unrecognized_line (c)
+ int c;
+{
+ int lab;
+ char *s;
+
+ if (c != '$'
+ || ! isdigit ((unsigned char) input_line_pointer[0]))
+ return 0;
+
+ s = input_line_pointer;
+
+ lab = 0;
+ while (isdigit ((unsigned char) *s))
+ {
+ lab = lab * 10 + *s - '0';
+ ++s;
+ }
+
+ if (*s != ':')
+ {
+ /* Not a label definition. */
+ return 0;
+ }
+
+ if (dollar_label_defined (lab))
+ {
+ as_bad (_("label \"$%d\" redefined"), lab);
+ return 0;
+ }
+
+ define_dollar_label (lab);
+ colon (dollar_label_name (lab, 0));
+ input_line_pointer = s + 1;
+
+ return 1;
+}
+
+/* Default the values of symbols known that should be "predefined". We
+ don't bother to predefine them unless you actually use one, since there
+ are a lot of them. */
+
+symbolS *
+md_undefined_symbol (name)
+ char *name;
+{
+ long regnum;
+ char testbuf[5 + /*SLOP*/ 5];
+
+ if (name[0] == 'g' || name[0] == 'G'
+ || name[0] == 'l' || name[0] == 'L'
+ || name[0] == 's' || name[0] == 'S')
+ {
+ /* Perhaps a global or local register name */
+ if (name[1] == 'r' || name[1] == 'R')
+ {
+ long maxreg;
+
+ /* Parse the number, make sure it has no extra zeroes or
+ trailing chars. */
+ regnum = atol (&name[2]);
+
+ if (name[0] == 's' || name[0] == 'S')
+ maxreg = 255;
+ else
+ maxreg = 127;
+ if (regnum > maxreg)
+ return NULL;
+
+ sprintf (testbuf, "%ld", regnum);
+ if (strcmp (testbuf, &name[2]) != 0)
+ return NULL; /* gr007 or lr7foo or whatever */
+
+ /* We have a wiener! Define and return a new symbol for it. */
+ if (name[0] == 'l' || name[0] == 'L')
+ regnum += 128;
+ else if (name[0] == 's' || name[0] == 'S')
+ regnum += SREG;
+ return (symbol_new (name, SEG_REGISTER, (valueT) regnum,
+ &zero_address_frag));
+ }
+ }
+
+ return NULL;
+}
+
+/* Parse an operand that is machine-specific. */
+
+void
+md_operand (expressionP)
+ expressionS *expressionP;
+{
+
+ if (input_line_pointer[0] == '%' && input_line_pointer[1] == '%')
+ {
+ /* We have a numeric register expression. No biggy. */
+ input_line_pointer += 2; /* Skip %% */
+ (void) expression (expressionP);
+ if (expressionP->X_op != O_constant
+ || expressionP->X_add_number > 255)
+ as_bad (_("Invalid expression after %%%%\n"));
+ expressionP->X_op = O_register;
+ }
+ else if (input_line_pointer[0] == '&')
+ {
+ /* We are taking the 'address' of a register...this one is not
+ in the manual, but it *is* in traps/fpsymbol.h! What they
+ seem to want is the register number, as an absolute number. */
+ input_line_pointer++; /* Skip & */
+ (void) expression (expressionP);
+ if (expressionP->X_op != O_register)
+ as_bad (_("Invalid register in & expression"));
+ else
+ expressionP->X_op = O_constant;
+ }
+ else if (input_line_pointer[0] == '$'
+ && isdigit ((unsigned char) input_line_pointer[1]))
+ {
+ long lab;
+ char *name;
+ symbolS *sym;
+
+ /* This is a local label. */
+ ++input_line_pointer;
+ lab = (long) get_absolute_expression ();
+ if (dollar_label_defined (lab))
+ {
+ name = dollar_label_name (lab, 0);
+ sym = symbol_find (name);
+ }
+ else
+ {
+ name = dollar_label_name (lab, 1);
+ sym = symbol_find_or_make (name);
+ }
+
+ expressionP->X_op = O_symbol;
+ expressionP->X_add_symbol = sym;
+ expressionP->X_add_number = 0;
+ }
+ else if (input_line_pointer[0] == '$')
+ {
+ char *s;
+ char type;
+ int fieldnum, fieldlimit;
+ LITTLENUM_TYPE floatbuf[8];
+
+ /* $float(), $doubleN(), or $extendN() convert floating values
+ to integers. */
+
+ s = input_line_pointer;
+
+ ++s;
+
+ fieldnum = 0;
+ if (strncmp (s, "double", sizeof "double" - 1) == 0)
+ {
+ s += sizeof "double" - 1;
+ type = 'd';
+ fieldlimit = 2;
+ }
+ else if (strncmp (s, "float", sizeof "float" - 1) == 0)
+ {
+ s += sizeof "float" - 1;
+ type = 'f';
+ fieldlimit = 1;
+ }
+ else if (strncmp (s, "extend", sizeof "extend" - 1) == 0)
+ {
+ s += sizeof "extend" - 1;
+ type = 'x';
+ fieldlimit = 4;
+ }
+ else
+ {
+ return;
+ }
+
+ if (isdigit (*s))
+ {
+ fieldnum = *s - '0';
+ ++s;
+ }
+ if (fieldnum >= fieldlimit)
+ return;
+
+ SKIP_WHITESPACE ();
+ if (*s != '(')
+ return;
+ ++s;
+ SKIP_WHITESPACE ();
+
+ s = atof_ieee (s, type, floatbuf);
+ if (s == NULL)
+ return;
+ s = s;
+
+ SKIP_WHITESPACE ();
+ if (*s != ')')
+ return;
+ ++s;
+ SKIP_WHITESPACE ();
+
+ input_line_pointer = s;
+ expressionP->X_op = O_constant;
+ expressionP->X_unsigned = 1;
+ expressionP->X_add_number = ((floatbuf[fieldnum * 2]
+ << LITTLENUM_NUMBER_OF_BITS)
+ + floatbuf[fieldnum * 2 + 1]);
+ }
+}
+
+/* Round up a section size to the appropriate boundary. */
+valueT
+md_section_align (segment, size)
+ segT segment;
+ valueT size;
+{
+ return size; /* Byte alignment is fine */
+}
+
+/* Exactly what point is a PC-relative offset relative TO?
+ On the 29000, they're relative to the address of the instruction,
+ which we have set up as the address of the fixup too. */
+long
+md_pcrel_from (fixP)
+ fixS *fixP;
+{
+ return fixP->fx_where + fixP->fx_frag->fr_address;
+}
+
+/* end of tc-a29k.c */
diff --git a/gas/config/tc-a29k.h b/gas/config/tc-a29k.h
new file mode 100644
index 0000000000..b60f605825
--- /dev/null
+++ b/gas/config/tc-a29k.h
@@ -0,0 +1,54 @@
+/* tc-a29k.h -- Assemble for the AMD 29000.
+ Copyright (C) 1989, 90, 91, 92, 93, 95, 1998 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GAS 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 more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#define TC_A29K
+
+#define TARGET_BYTES_BIG_ENDIAN 1
+
+#define WORKING_DOT_WORD
+
+#define LEX_DOLLAR 1
+
+#define tc_unrecognized_line(c) a29k_unrecognized_line (c)
+extern int a29k_unrecognized_line PARAMS ((int));
+
+#define tc_headers_hook(a) ; /* not used */
+#define tc_headers_hook(a) ; /* not used */
+#define tc_crawl_symbol_chain(a) ; /* not used */
+#define tc_coff_symbol_emit_hook(a) ; /* not used */
+
+#define AOUT_MACHTYPE 101
+#define TC_COFF_FIX2RTYPE(fix_ptr) tc_coff_fix2rtype(fix_ptr)
+#define BFD_ARCH bfd_arch_a29k
+#define COFF_MAGIC SIPFBOMAGIC
+/* Should the reloc be output ?
+ on the 29k, this is true only if there is a symbol attatched.
+ on the h8, this is allways true, since no fixup is done
+*/
+#define TC_COUNT_RELOC(x) (x->fx_addsy)
+#define TC_CONS_RELOC RELOC_32
+
+#define COFF_FLAGS F_AR32W
+#define reloc_type int
+#define NEED_FX_R_TYPE
+
+#define ZERO_BASED_SEGMENTS
+
+/* end of tc-a29k.h */
diff --git a/gas/config/tc-alpha.c b/gas/config/tc-alpha.c
new file mode 100644
index 0000000000..568617f74e
--- /dev/null
+++ b/gas/config/tc-alpha.c
@@ -0,0 +1,4762 @@
+/* tc-alpha.c - Processor-specific code for the DEC Alpha AXP CPU.
+ Copyright (C) 1989, 93-98, 1999 Free Software Foundation, Inc.
+ Contributed by Carnegie Mellon University, 1993.
+ Written by Alessandro Forin, based on earlier gas-1.38 target CPU files.
+ Modified by Ken Raeburn for gas-2.x and ECOFF support.
+ Modified by Richard Henderson for ELF support.
+ Modified by Klaus K"ampf for EVAX (openVMS/Alpha) support.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1993 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include "as.h"
+#include "subsegs.h"
+#include "ecoff.h"
+
+#include "opcode/alpha.h"
+
+#ifdef OBJ_ELF
+#include "elf/alpha.h"
+#endif
+
+#include <ctype.h>
+
+
+/* Local types */
+
+#define MAX_INSN_FIXUPS 2
+#define MAX_INSN_ARGS 5
+
+struct alpha_fixup
+{
+ expressionS exp;
+ bfd_reloc_code_real_type reloc;
+};
+
+struct alpha_insn
+{
+ unsigned insn;
+ int nfixups;
+ struct alpha_fixup fixups[MAX_INSN_FIXUPS];
+};
+
+enum alpha_macro_arg
+{
+ MACRO_EOA = 1, MACRO_IR, MACRO_PIR, MACRO_CPIR, MACRO_FPR, MACRO_EXP
+};
+
+struct alpha_macro
+{
+ const char *name;
+ void (*emit) PARAMS ((const expressionS *, int, const PTR));
+ const PTR arg;
+ enum alpha_macro_arg argsets[16];
+};
+
+/* Two extra symbols we want to see in our input. This is a blatent
+ misuse of the expressionS.X_op field. */
+
+#define O_pregister (O_max+1) /* O_register, but in parentheses */
+#define O_cpregister (O_pregister+1) /* + a leading comma */
+
+/* Macros for extracting the type and number of encoded register tokens */
+
+#define is_ir_num(x) (((x) & 32) == 0)
+#define is_fpr_num(x) (((x) & 32) != 0)
+#define regno(x) ((x) & 31)
+
+/* Something odd inherited from the old assembler */
+
+#define note_gpreg(R) (alpha_gprmask |= (1 << (R)))
+#define note_fpreg(R) (alpha_fprmask |= (1 << (R)))
+
+/* Predicates for 16- and 32-bit ranges */
+/* XXX: The non-shift version appears to trigger a compiler bug when
+ cross-assembling from x86 w/ gcc 2.7.2. */
+
+#if 1
+#define range_signed_16(x) \
+ (((offsetT)(x) >> 15) == 0 || ((offsetT)(x) >> 15) == -1)
+#define range_signed_32(x) \
+ (((offsetT)(x) >> 31) == 0 || ((offsetT)(x) >> 31) == -1)
+#else
+#define range_signed_16(x) ((offsetT)(x) >= -(offsetT)0x8000 && \
+ (offsetT)(x) <= (offsetT)0x7FFF)
+#define range_signed_32(x) ((offsetT)(x) >= -(offsetT)0x80000000 && \
+ (offsetT)(x) <= (offsetT)0x7FFFFFFF)
+#endif
+
+/* Macros for sign extending from 16- and 32-bits. */
+/* XXX: The cast macros will work on all the systems that I care about,
+ but really a predicate should be found to use the non-cast forms. */
+
+#if 1
+#define sign_extend_16(x) ((short)(x))
+#define sign_extend_32(x) ((int)(x))
+#else
+#define sign_extend_16(x) ((offsetT)(((x) & 0xFFFF) ^ 0x8000) - 0x8000)
+#define sign_extend_32(x) ((offsetT)(((x) & 0xFFFFFFFF) \
+ ^ 0x80000000) - 0x80000000)
+#endif
+
+/* Macros to build tokens */
+
+#define set_tok_reg(t, r) (memset(&(t), 0, sizeof(t)), \
+ (t).X_op = O_register, \
+ (t).X_add_number = (r))
+#define set_tok_preg(t, r) (memset(&(t), 0, sizeof(t)), \
+ (t).X_op = O_pregister, \
+ (t).X_add_number = (r))
+#define set_tok_cpreg(t, r) (memset(&(t), 0, sizeof(t)), \
+ (t).X_op = O_cpregister, \
+ (t).X_add_number = (r))
+#define set_tok_freg(t, r) (memset(&(t), 0, sizeof(t)), \
+ (t).X_op = O_register, \
+ (t).X_add_number = (r)+32)
+#define set_tok_sym(t, s, a) (memset(&(t), 0, sizeof(t)), \
+ (t).X_op = O_symbol, \
+ (t).X_add_symbol = (s), \
+ (t).X_add_number = (a))
+#define set_tok_const(t, n) (memset(&(t), 0, sizeof(t)), \
+ (t).X_op = O_constant, \
+ (t).X_add_number = (n))
+
+
+/* Prototypes for all local functions */
+
+static int tokenize_arguments PARAMS ((char *, expressionS *, int));
+static const struct alpha_opcode *find_opcode_match
+ PARAMS ((const struct alpha_opcode *, const expressionS *, int *, int *));
+static const struct alpha_macro *find_macro_match
+ PARAMS ((const struct alpha_macro *, const expressionS *, int *));
+static unsigned insert_operand
+ PARAMS ((unsigned, const struct alpha_operand *, offsetT, char *, unsigned));
+static void assemble_insn
+ PARAMS ((const struct alpha_opcode *, const expressionS *, int,
+ struct alpha_insn *));
+static void emit_insn PARAMS ((struct alpha_insn *));
+static void assemble_tokens_to_insn
+ PARAMS ((const char *, const expressionS *, int, struct alpha_insn *));
+static void assemble_tokens
+ PARAMS ((const char *, const expressionS *, int, int));
+
+static int load_expression
+ PARAMS ((int, const expressionS *, int *, expressionS *));
+
+static void emit_ldgp PARAMS ((const expressionS *, int, const PTR));
+static void emit_division PARAMS ((const expressionS *, int, const PTR));
+static void emit_lda PARAMS ((const expressionS *, int, const PTR));
+static void emit_ldah PARAMS ((const expressionS *, int, const PTR));
+static void emit_ir_load PARAMS ((const expressionS *, int, const PTR));
+static void emit_loadstore PARAMS ((const expressionS *, int, const PTR));
+static void emit_jsrjmp PARAMS ((const expressionS *, int, const PTR));
+static void emit_ldX PARAMS ((const expressionS *, int, const PTR));
+static void emit_ldXu PARAMS ((const expressionS *, int, const PTR));
+static void emit_uldX PARAMS ((const expressionS *, int, const PTR));
+static void emit_uldXu PARAMS ((const expressionS *, int, const PTR));
+static void emit_ldil PARAMS ((const expressionS *, int, const PTR));
+static void emit_stX PARAMS ((const expressionS *, int, const PTR));
+static void emit_ustX PARAMS ((const expressionS *, int, const PTR));
+static void emit_sextX PARAMS ((const expressionS *, int, const PTR));
+static void emit_retjcr PARAMS ((const expressionS *, int, const PTR));
+
+static void s_alpha_text PARAMS ((int));
+static void s_alpha_data PARAMS ((int));
+#ifndef OBJ_ELF
+static void s_alpha_comm PARAMS ((int));
+static void s_alpha_rdata PARAMS ((int));
+#endif
+#ifdef OBJ_ECOFF
+static void s_alpha_sdata PARAMS ((int));
+#endif
+#ifdef OBJ_ELF
+static void s_alpha_section PARAMS ((int));
+static void s_alpha_ent PARAMS ((int));
+static void s_alpha_end PARAMS ((int));
+static void s_alpha_mask PARAMS ((int));
+static void s_alpha_frame PARAMS ((int));
+static void s_alpha_prologue PARAMS ((int));
+static void s_alpha_coff_wrapper PARAMS ((int));
+#endif
+#ifdef OBJ_EVAX
+static void s_alpha_section PARAMS ((int));
+#endif
+static void s_alpha_gprel32 PARAMS ((int));
+static void s_alpha_float_cons PARAMS ((int));
+static void s_alpha_proc PARAMS ((int));
+static void s_alpha_set PARAMS ((int));
+static void s_alpha_base PARAMS ((int));
+static void s_alpha_align PARAMS ((int));
+static void s_alpha_stringer PARAMS ((int));
+static void s_alpha_space PARAMS ((int));
+
+static void create_literal_section PARAMS ((const char *, segT *, symbolS **));
+#ifndef OBJ_ELF
+static void select_gp_value PARAMS ((void));
+#endif
+static void alpha_align PARAMS ((int, char *, symbolS *, int));
+
+
+/* Generic assembler global variables which must be defined by all
+ targets. */
+
+/* Characters which always start a comment. */
+const char comment_chars[] = "#";
+
+/* Characters which start a comment at the beginning of a line. */
+const char line_comment_chars[] = "#";
+
+/* Characters which may be used to separate multiple commands on a
+ single line. */
+const char line_separator_chars[] = ";";
+
+/* Characters which are used to indicate an exponent in a floating
+ point number. */
+const char EXP_CHARS[] = "eE";
+
+/* Characters which mean that a number is a floating point constant,
+ as in 0d1.0. */
+#if 0
+const char FLT_CHARS[] = "dD";
+#else
+/* XXX: Do all of these really get used on the alpha?? */
+char FLT_CHARS[] = "rRsSfFdDxXpP";
+#endif
+
+#ifdef OBJ_EVAX
+const char *md_shortopts = "Fm:g+1h:HG:";
+#else
+const char *md_shortopts = "Fm:gG:";
+#endif
+
+struct option md_longopts[] = {
+#define OPTION_32ADDR (OPTION_MD_BASE)
+ { "32addr", no_argument, NULL, OPTION_32ADDR },
+#define OPTION_RELAX (OPTION_32ADDR+1)
+ { "relax", no_argument, NULL, OPTION_RELAX },
+#ifdef OBJ_ELF
+#define OPTION_MDEBUG (OPTION_RELAX+1)
+#define OPTION_NO_MDEBUG (OPTION_MDEBUG+1)
+ { "mdebug", no_argument, NULL, OPTION_MDEBUG },
+ { "no-mdebug", no_argument, NULL, OPTION_NO_MDEBUG },
+#endif
+ { NULL, no_argument, NULL, 0 }
+};
+
+size_t md_longopts_size = sizeof(md_longopts);
+
+
+#ifdef OBJ_EVAX
+#define AXP_REG_R0 0
+#define AXP_REG_R16 16
+#define AXP_REG_R17 17
+#undef AXP_REG_T9
+#define AXP_REG_T9 22
+#undef AXP_REG_T10
+#define AXP_REG_T10 23
+#undef AXP_REG_T11
+#define AXP_REG_T11 24
+#undef AXP_REG_T12
+#define AXP_REG_T12 25
+#define AXP_REG_AI 25
+#undef AXP_REG_FP
+#define AXP_REG_FP 29
+
+#undef AXP_REG_GP
+#define AXP_REG_GP AXP_REG_PV
+#endif /* OBJ_EVAX */
+
+/* The cpu for which we are generating code */
+static unsigned alpha_target = AXP_OPCODE_BASE;
+static const char *alpha_target_name = "<all>";
+
+/* The hash table of instruction opcodes */
+static struct hash_control *alpha_opcode_hash;
+
+/* The hash table of macro opcodes */
+static struct hash_control *alpha_macro_hash;
+
+#ifdef OBJ_ECOFF
+/* The $gp relocation symbol */
+static symbolS *alpha_gp_symbol;
+
+/* XXX: what is this, and why is it exported? */
+valueT alpha_gp_value;
+#endif
+
+/* The current $gp register */
+static int alpha_gp_register = AXP_REG_GP;
+
+/* A table of the register symbols */
+static symbolS *alpha_register_table[64];
+
+/* Constant sections, or sections of constants */
+#ifdef OBJ_ECOFF
+static segT alpha_lita_section;
+static segT alpha_lit4_section;
+#endif
+#ifdef OBJ_EVAX
+static segT alpha_link_section;
+static segT alpha_ctors_section;
+static segT alpha_dtors_section;
+#endif
+static segT alpha_lit8_section;
+
+/* Symbols referring to said sections. */
+#ifdef OBJ_ECOFF
+static symbolS *alpha_lita_symbol;
+static symbolS *alpha_lit4_symbol;
+#endif
+#ifdef OBJ_EVAX
+static symbolS *alpha_link_symbol;
+static symbolS *alpha_ctors_symbol;
+static symbolS *alpha_dtors_symbol;
+#endif
+static symbolS *alpha_lit8_symbol;
+
+/* Literal for .litX+0x8000 within .lita */
+#ifdef OBJ_ECOFF
+static offsetT alpha_lit4_literal;
+static offsetT alpha_lit8_literal;
+#endif
+
+/* The active .ent symbol. */
+#ifdef OBJ_ELF
+static symbolS *alpha_cur_ent_sym;
+#endif
+
+/* Is the assembler not allowed to use $at? */
+static int alpha_noat_on = 0;
+
+/* Are macros enabled? */
+static int alpha_macros_on = 1;
+
+/* Are floats disabled? */
+static int alpha_nofloats_on = 0;
+
+/* Are addresses 32 bit? */
+static int alpha_addr32_on = 0;
+
+/* Symbol labelling the current insn. When the Alpha gas sees
+ foo:
+ .quad 0
+ and the section happens to not be on an eight byte boundary, it
+ will align both the symbol and the .quad to an eight byte boundary. */
+static symbolS *alpha_insn_label;
+
+/* Whether we should automatically align data generation pseudo-ops.
+ .align 0 will turn this off. */
+static int alpha_auto_align_on = 1;
+
+/* The known current alignment of the current section. */
+static int alpha_current_align;
+
+/* These are exported to ECOFF code. */
+unsigned long alpha_gprmask, alpha_fprmask;
+
+/* Whether the debugging option was seen. */
+static int alpha_debug;
+
+#ifdef OBJ_ELF
+/* Whether we are emitting an mdebug section. */
+int alpha_flag_mdebug = 1;
+#endif
+
+/* Don't fully resolve relocations, allowing code movement in the linker. */
+static int alpha_flag_relax;
+
+/* What value to give to bfd_set_gp_size. */
+static int g_switch_value = 8;
+
+#ifdef OBJ_EVAX
+/* Collect information about current procedure here. */
+static struct {
+ symbolS *symbol; /* proc pdesc symbol */
+ int pdsckind;
+ int framereg; /* register for frame pointer */
+ int framesize; /* size of frame */
+ int rsa_offset;
+ int ra_save;
+ int fp_save;
+ long imask;
+ long fmask;
+ int type;
+ int prologue;
+} alpha_evax_proc;
+
+static int alpha_flag_hash_long_names = 0; /* -+ */
+static int alpha_flag_show_after_trunc = 0; /* -H */
+
+/* If the -+ switch is given, then a hash is appended to any name that is
+ * longer than 64 characters, else longer symbol names are truncated.
+ */
+
+#endif
+
+/* A table of CPU names and opcode sets. */
+
+static const struct cpu_type
+{
+ const char *name;
+ unsigned flags;
+} cpu_types[] =
+{
+ /* Ad hoc convention: cpu number gets palcode, process code doesn't.
+ This supports usage under DU 4.0b that does ".arch ev4", and
+ usage in MILO that does -m21064. Probably something more
+ specific like -m21064-pal should be used, but oh well. */
+
+ { "21064", AXP_OPCODE_BASE|AXP_OPCODE_EV4 },
+ { "21064a", AXP_OPCODE_BASE|AXP_OPCODE_EV4 },
+ { "21066", AXP_OPCODE_BASE|AXP_OPCODE_EV4 },
+ { "21068", AXP_OPCODE_BASE|AXP_OPCODE_EV4 },
+ { "21164", AXP_OPCODE_BASE|AXP_OPCODE_EV5 },
+ { "21164a", AXP_OPCODE_BASE|AXP_OPCODE_EV5|AXP_OPCODE_BWX },
+ { "21164pc", (AXP_OPCODE_BASE|AXP_OPCODE_EV5|AXP_OPCODE_BWX
+ |AXP_OPCODE_MAX) },
+ { "21264", (AXP_OPCODE_BASE|AXP_OPCODE_EV6|AXP_OPCODE_BWX
+ |AXP_OPCODE_MAX|AXP_OPCODE_CIX) },
+
+ { "ev4", AXP_OPCODE_BASE },
+ { "ev45", AXP_OPCODE_BASE },
+ { "lca45", AXP_OPCODE_BASE },
+ { "ev5", AXP_OPCODE_BASE },
+ { "ev56", AXP_OPCODE_BASE|AXP_OPCODE_BWX },
+ { "pca56", AXP_OPCODE_BASE|AXP_OPCODE_BWX|AXP_OPCODE_MAX },
+ { "ev6", AXP_OPCODE_BASE|AXP_OPCODE_BWX|AXP_OPCODE_MAX|AXP_OPCODE_CIX },
+
+ { "all", AXP_OPCODE_BASE },
+ { 0 }
+};
+
+/* The macro table */
+
+static const struct alpha_macro alpha_macros[] = {
+/* Load/Store macros */
+ { "lda", emit_lda, NULL,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ldah", emit_ldah, NULL,
+ { MACRO_IR, MACRO_EXP, MACRO_EOA } },
+
+ { "ldl", emit_ir_load, "ldl",
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ldl_l", emit_ir_load, "ldl_l",
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ldq", emit_ir_load, "ldq",
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ldq_l", emit_ir_load, "ldq_l",
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ldq_u", emit_ir_load, "ldq_u",
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ldf", emit_loadstore, "ldf",
+ { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+ { "ldg", emit_loadstore, "ldg",
+ { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+ { "lds", emit_loadstore, "lds",
+ { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+ { "ldt", emit_loadstore, "ldt",
+ { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+
+ { "ldb", emit_ldX, (PTR)0,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ldbu", emit_ldXu, (PTR)0,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ldw", emit_ldX, (PTR)1,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ldwu", emit_ldXu, (PTR)1,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+
+ { "uldw", emit_uldX, (PTR)1,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "uldwu", emit_uldXu, (PTR)1,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "uldl", emit_uldX, (PTR)2,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "uldlu", emit_uldXu, (PTR)2,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "uldq", emit_uldXu, (PTR)3,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+
+ { "ldgp", emit_ldgp, NULL,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA } },
+
+ { "ldi", emit_lda, NULL,
+ { MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ldil", emit_ldil, NULL,
+ { MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ldiq", emit_lda, NULL,
+ { MACRO_IR, MACRO_EXP, MACRO_EOA } },
+#if 0
+ { "ldif" emit_ldiq, NULL,
+ { MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+ { "ldid" emit_ldiq, NULL,
+ { MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+ { "ldig" emit_ldiq, NULL,
+ { MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+ { "ldis" emit_ldiq, NULL,
+ { MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+ { "ldit" emit_ldiq, NULL,
+ { MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+#endif
+
+ { "stl", emit_loadstore, "stl",
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "stl_c", emit_loadstore, "stl_c",
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "stq", emit_loadstore, "stq",
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "stq_c", emit_loadstore, "stq_c",
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "stq_u", emit_loadstore, "stq_u",
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "stf", emit_loadstore, "stf",
+ { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+ { "stg", emit_loadstore, "stg",
+ { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+ { "sts", emit_loadstore, "sts",
+ { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+ { "stt", emit_loadstore, "stt",
+ { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+
+ { "stb", emit_stX, (PTR)0,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "stw", emit_stX, (PTR)1,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ustw", emit_ustX, (PTR)1,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ustl", emit_ustX, (PTR)2,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ustq", emit_ustX, (PTR)3,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+
+/* Arithmetic macros */
+#if 0
+ { "absl" emit_absl, 1, { IR } },
+ { "absl" emit_absl, 2, { IR, IR } },
+ { "absl" emit_absl, 2, { EXP, IR } },
+ { "absq" emit_absq, 1, { IR } },
+ { "absq" emit_absq, 2, { IR, IR } },
+ { "absq" emit_absq, 2, { EXP, IR } },
+#endif
+
+ { "sextb", emit_sextX, (PTR)0,
+ { MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EOA,
+ /* MACRO_EXP, MACRO_IR, MACRO_EOA */ } },
+ { "sextw", emit_sextX, (PTR)1,
+ { MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EOA,
+ /* MACRO_EXP, MACRO_IR, MACRO_EOA */ } },
+
+ { "divl", emit_division, "__divl",
+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_IR, MACRO_EOA,
+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
+ { "divlu", emit_division, "__divlu",
+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_IR, MACRO_EOA,
+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
+ { "divq", emit_division, "__divq",
+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_IR, MACRO_EOA,
+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
+ { "divqu", emit_division, "__divqu",
+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_IR, MACRO_EOA,
+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
+ { "reml", emit_division, "__reml",
+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_IR, MACRO_EOA,
+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
+ { "remlu", emit_division, "__remlu",
+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_IR, MACRO_EOA,
+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
+ { "remq", emit_division, "__remq",
+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_IR, MACRO_EOA,
+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
+ { "remqu", emit_division, "__remqu",
+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_IR, MACRO_EOA,
+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
+
+ { "jsr", emit_jsrjmp, "jsr",
+ { MACRO_PIR, MACRO_EXP, MACRO_EOA,
+ MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA,
+ MACRO_EXP, MACRO_EOA } },
+ { "jmp", emit_jsrjmp, "jmp",
+ { MACRO_PIR, MACRO_EXP, MACRO_EOA,
+ MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA,
+ MACRO_EXP, MACRO_EOA } },
+ { "ret", emit_retjcr, "ret",
+ { MACRO_IR, MACRO_EXP, MACRO_EOA,
+ MACRO_IR, MACRO_EOA,
+ MACRO_PIR, MACRO_EXP, MACRO_EOA,
+ MACRO_PIR, MACRO_EOA,
+ MACRO_EXP, MACRO_EOA,
+ MACRO_EOA } },
+ { "jcr", emit_retjcr, "jcr",
+ { MACRO_IR, MACRO_EXP, MACRO_EOA,
+ MACRO_IR, MACRO_EOA,
+ MACRO_PIR, MACRO_EXP, MACRO_EOA,
+ MACRO_PIR, MACRO_EOA,
+ MACRO_EXP, MACRO_EOA,
+ MACRO_EOA } },
+ { "jsr_coroutine", emit_retjcr, "jcr",
+ { MACRO_IR, MACRO_EXP, MACRO_EOA,
+ MACRO_IR, MACRO_EOA,
+ MACRO_PIR, MACRO_EXP, MACRO_EOA,
+ MACRO_PIR, MACRO_EOA,
+ MACRO_EXP, MACRO_EOA,
+ MACRO_EOA } },
+};
+
+static const int alpha_num_macros
+ = sizeof(alpha_macros) / sizeof(*alpha_macros);
+
+/* Public interface functions */
+
+/* This function is called once, at assembler startup time. It sets
+ up all the tables, etc. that the MD part of the assembler will
+ need, that can be determined before arguments are parsed. */
+
+void
+md_begin ()
+{
+ unsigned int i;
+
+ /* Create the opcode hash table */
+
+ alpha_opcode_hash = hash_new ();
+ for (i = 0; i < alpha_num_opcodes; )
+ {
+ const char *name, *retval, *slash;
+
+ name = alpha_opcodes[i].name;
+ retval = hash_insert (alpha_opcode_hash, name, (PTR)&alpha_opcodes[i]);
+ if (retval)
+ as_fatal (_("internal error: can't hash opcode `%s': %s"), name, retval);
+
+ /* Some opcodes include modifiers of various sorts with a "/mod"
+ syntax, like the architecture manual suggests. However, for
+ use with gcc at least, we also need access to those same opcodes
+ without the "/". */
+
+ if ((slash = strchr (name, '/')) != NULL)
+ {
+ char *p = xmalloc (strlen (name));
+ memcpy (p, name, slash - name);
+ strcpy (p + (slash - name), slash + 1);
+
+ (void)hash_insert(alpha_opcode_hash, p, (PTR)&alpha_opcodes[i]);
+ /* Ignore failures -- the opcode table does duplicate some
+ variants in different forms, like "hw_stq" and "hw_st/q". */
+ }
+
+ while (++i < alpha_num_opcodes
+ && (alpha_opcodes[i].name == name
+ || !strcmp (alpha_opcodes[i].name, name)))
+ continue;
+ }
+
+ /* Create the macro hash table */
+
+ alpha_macro_hash = hash_new ();
+ for (i = 0; i < alpha_num_macros; )
+ {
+ const char *name, *retval;
+
+ name = alpha_macros[i].name;
+ retval = hash_insert (alpha_macro_hash, name, (PTR)&alpha_macros[i]);
+ if (retval)
+ as_fatal (_("internal error: can't hash macro `%s': %s"), name, retval);
+
+ while (++i < alpha_num_macros
+ && (alpha_macros[i].name == name
+ || !strcmp (alpha_macros[i].name, name)))
+ continue;
+ }
+
+ /* Construct symbols for each of the registers */
+
+ for (i = 0; i < 32; ++i)
+ {
+ char name[4];
+ sprintf(name, "$%d", i);
+ alpha_register_table[i] = symbol_create(name, reg_section, i,
+ &zero_address_frag);
+ }
+ for (; i < 64; ++i)
+ {
+ char name[5];
+ sprintf(name, "$f%d", i-32);
+ alpha_register_table[i] = symbol_create(name, reg_section, i,
+ &zero_address_frag);
+ }
+
+ /* Create the special symbols and sections we'll be using */
+
+ /* So .sbss will get used for tiny objects. */
+ bfd_set_gp_size (stdoutput, g_switch_value);
+
+#ifdef OBJ_ECOFF
+ create_literal_section (".lita", &alpha_lita_section, &alpha_lita_symbol);
+
+ /* For handling the GP, create a symbol that won't be output in the
+ symbol table. We'll edit it out of relocs later. */
+ alpha_gp_symbol = symbol_create ("<GP value>", alpha_lita_section, 0x8000,
+ &zero_address_frag);
+#endif
+
+#ifdef OBJ_EVAX
+ create_literal_section (".link", &alpha_link_section, &alpha_link_symbol);
+#endif
+
+#ifdef OBJ_ELF
+ if (ECOFF_DEBUGGING)
+ {
+ segT sec = subseg_new(".mdebug", (subsegT)0);
+ bfd_set_section_flags(stdoutput, sec, SEC_HAS_CONTENTS|SEC_READONLY);
+ bfd_set_section_alignment(stdoutput, sec, 3);
+ }
+#endif /* OBJ_ELF */
+
+ subseg_set(text_section, 0);
+}
+
+/* The public interface to the instruction assembler. */
+
+void
+md_assemble (str)
+ char *str;
+{
+ char opname[32]; /* current maximum is 13 */
+ expressionS tok[MAX_INSN_ARGS];
+ int ntok, opnamelen, trunclen;
+
+ /* split off the opcode */
+ opnamelen = strspn (str, "abcdefghijklmnopqrstuvwxyz_/468");
+ trunclen = (opnamelen < sizeof (opname) - 1
+ ? opnamelen
+ : sizeof (opname) - 1);
+ memcpy (opname, str, trunclen);
+ opname[trunclen] = '\0';
+
+ /* tokenize the rest of the line */
+ if ((ntok = tokenize_arguments (str + opnamelen, tok, MAX_INSN_ARGS)) < 0)
+ {
+ as_bad (_("syntax error"));
+ return;
+ }
+
+ /* finish it off */
+ assemble_tokens (opname, tok, ntok, alpha_macros_on);
+}
+
+/* Round up a section's size to the appropriate boundary. */
+
+valueT
+md_section_align (seg, size)
+ segT seg;
+ valueT size;
+{
+ int align = bfd_get_section_alignment(stdoutput, seg);
+ valueT mask = ((valueT)1 << align) - 1;
+
+ return (size + mask) & ~mask;
+}
+
+/* Turn a string in input_line_pointer into a floating point constant
+ of type type, and store the appropriate bytes in *litP. The number
+ of LITTLENUMS emitted is stored in *sizeP. An error message is
+ returned, or NULL on OK. */
+
+/* Equal to MAX_PRECISION in atof-ieee.c */
+#define MAX_LITTLENUMS 6
+
+extern char *vax_md_atof PARAMS ((int, char *, int *));
+
+char *
+md_atof (type, litP, sizeP)
+ char type;
+ char *litP;
+ int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ char *t;
+
+ switch (type)
+ {
+ /* VAX floats */
+ case 'G':
+ /* VAX md_atof doesn't like "G" for some reason. */
+ type = 'g';
+ case 'F':
+ case 'D':
+ return vax_md_atof (type, litP, sizeP);
+
+ /* IEEE floats */
+ case 'f':
+ prec = 2;
+ break;
+
+ case 'd':
+ prec = 4;
+ break;
+
+ case 'x':
+ case 'X':
+ prec = 6;
+ break;
+
+ case 'p':
+ case 'P':
+ prec = 6;
+ break;
+
+ default:
+ *sizeP = 0;
+ return _("Bad call to MD_ATOF()");
+ }
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+ *sizeP = prec * sizeof (LITTLENUM_TYPE);
+
+ for (wordP = words + prec - 1; prec--;)
+ {
+ md_number_to_chars (litP, (long) (*wordP--), sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+
+ return 0;
+}
+
+/* Take care of the target-specific command-line options. */
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ switch (c)
+ {
+ case 'F':
+ alpha_nofloats_on = 1;
+ break;
+
+ case OPTION_32ADDR:
+ alpha_addr32_on = 1;
+ break;
+
+ case 'g':
+ alpha_debug = 1;
+ break;
+
+ case 'G':
+ g_switch_value = atoi(arg);
+ break;
+
+ case 'm':
+ {
+ const struct cpu_type *p;
+ for (p = cpu_types; p->name; ++p)
+ if (strcmp(arg, p->name) == 0)
+ {
+ alpha_target_name = p->name, alpha_target = p->flags;
+ goto found;
+ }
+ as_warn(_("Unknown CPU identifier `%s'"), arg);
+ found:;
+ }
+ break;
+
+#ifdef OBJ_EVAX
+ case '+': /* For g++. Hash any name > 63 chars long. */
+ alpha_flag_hash_long_names = 1;
+ break;
+
+ case 'H': /* Show new symbol after hash truncation */
+ alpha_flag_show_after_trunc = 1;
+ break;
+
+ case 'h': /* for gnu-c/vax compatibility. */
+ break;
+#endif
+
+ case OPTION_RELAX:
+ alpha_flag_relax = 1;
+ break;
+
+#ifdef OBJ_ELF
+ case OPTION_MDEBUG:
+ alpha_flag_mdebug = 1;
+ break;
+ case OPTION_NO_MDEBUG:
+ alpha_flag_mdebug = 0;
+ break;
+#endif
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Print a description of the command-line options that we accept. */
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+ fputs(_("\
+Alpha options:\n\
+-32addr treat addresses as 32-bit values\n\
+-F lack floating point instructions support\n\
+-mev4 | -mev45 | -mev5 | -mev56 | -mpca56 | -mev6 | -mall\n\
+ specify variant of Alpha architecture\n\
+-m21064 | -m21066 | -m21164 | -m21164a | -m21164pc | -m21264\n\
+ these variants include PALcode opcodes\n"),
+ stream);
+#ifdef OBJ_EVAX
+ fputs (_("\
+VMS options:\n\
+-+ hash encode (don't truncate) names longer than 64 characters\n\
+-H show new symbol after hash truncation\n"),
+ stream);
+#endif
+}
+
+/* Decide from what point a pc-relative relocation is relative to,
+ relative to the pc-relative fixup. Er, relatively speaking. */
+
+long
+md_pcrel_from (fixP)
+ fixS *fixP;
+{
+ valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_ALPHA_GPDISP:
+ case BFD_RELOC_ALPHA_GPDISP_HI16:
+ case BFD_RELOC_ALPHA_GPDISP_LO16:
+ return addr;
+ default:
+ return fixP->fx_size + addr;
+ }
+}
+
+/* Attempt to simplify or even eliminate a fixup. The return value is
+ ignored; perhaps it was once meaningful, but now it is historical.
+ To indicate that a fixup has been eliminated, set fixP->fx_done.
+
+ For ELF, here it is that we transform the GPDISP_HI16 reloc we used
+ internally into the GPDISP reloc used externally. We had to do
+ this so that we'd have the GPDISP_LO16 reloc as a tag to compute
+ the distance to the "lda" instruction for setting the addend to
+ GPDISP. */
+
+int
+md_apply_fix (fixP, valueP)
+ fixS *fixP;
+ valueT *valueP;
+{
+ char * const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where;
+ valueT value = *valueP;
+ unsigned image, size;
+
+ switch (fixP->fx_r_type)
+ {
+ /* The GPDISP relocations are processed internally with a symbol
+ referring to the current function; we need to drop in a value
+ which, when added to the address of the start of the function,
+ gives the desired GP. */
+ case BFD_RELOC_ALPHA_GPDISP_HI16:
+ {
+ fixS *next = fixP->fx_next;
+ assert (next->fx_r_type == BFD_RELOC_ALPHA_GPDISP_LO16);
+
+ fixP->fx_offset = (next->fx_frag->fr_address + next->fx_where
+ - fixP->fx_frag->fr_address - fixP->fx_where);
+
+ value = (value - sign_extend_16 (value)) >> 16;
+ }
+#ifdef OBJ_ELF
+ fixP->fx_r_type = BFD_RELOC_ALPHA_GPDISP;
+#endif
+ goto do_reloc_gp;
+
+ case BFD_RELOC_ALPHA_GPDISP_LO16:
+ value = sign_extend_16 (value);
+ fixP->fx_offset = 0;
+#ifdef OBJ_ELF
+ fixP->fx_done = 1;
+#endif
+
+ do_reloc_gp:
+ fixP->fx_addsy = section_symbol (absolute_section);
+ md_number_to_chars (fixpos, value, 2);
+ break;
+
+ case BFD_RELOC_16:
+ if (fixP->fx_pcrel)
+ fixP->fx_r_type = BFD_RELOC_16_PCREL;
+ size = 2;
+ goto do_reloc_xx;
+ case BFD_RELOC_32:
+ if (fixP->fx_pcrel)
+ fixP->fx_r_type = BFD_RELOC_32_PCREL;
+ size = 4;
+ goto do_reloc_xx;
+ case BFD_RELOC_64:
+ if (fixP->fx_pcrel)
+ fixP->fx_r_type = BFD_RELOC_64_PCREL;
+ size = 8;
+ do_reloc_xx:
+ if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0)
+ {
+ md_number_to_chars (fixpos, value, size);
+ goto done;
+ }
+ return 1;
+
+#ifdef OBJ_ECOFF
+ case BFD_RELOC_GPREL32:
+ assert (fixP->fx_subsy == alpha_gp_symbol);
+ fixP->fx_subsy = 0;
+ /* FIXME: inherited this obliviousness of `value' -- why? */
+ md_number_to_chars (fixpos, -alpha_gp_value, 4);
+ break;
+#endif
+#ifdef OBJ_ELF
+ case BFD_RELOC_GPREL32:
+ return 1;
+#endif
+
+ case BFD_RELOC_23_PCREL_S2:
+ if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0)
+ {
+ image = bfd_getl32(fixpos);
+ image = (image & ~0x1FFFFF) | ((value >> 2) & 0x1FFFFF);
+ goto write_done;
+ }
+ return 1;
+
+ case BFD_RELOC_ALPHA_HINT:
+ if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0)
+ {
+ image = bfd_getl32(fixpos);
+ image = (image & ~0x3FFF) | ((value >> 2) & 0x3FFF);
+ goto write_done;
+ }
+ return 1;
+
+#ifdef OBJ_ECOFF
+ case BFD_RELOC_ALPHA_LITERAL:
+ md_number_to_chars (fixpos, value, 2);
+ return 1;
+
+ case BFD_RELOC_ALPHA_LITUSE:
+ return 1;
+#endif
+#ifdef OBJ_ELF
+ case BFD_RELOC_ALPHA_ELF_LITERAL:
+ case BFD_RELOC_ALPHA_LITUSE:
+ return 1;
+#endif
+#ifdef OBJ_EVAX
+ case BFD_RELOC_ALPHA_LINKAGE:
+ case BFD_RELOC_ALPHA_CODEADDR:
+ return 1;
+#endif
+
+ default:
+ {
+ const struct alpha_operand *operand;
+
+ if ((int)fixP->fx_r_type >= 0)
+ as_fatal (_("unhandled relocation type %s"),
+ bfd_get_reloc_code_name (fixP->fx_r_type));
+
+ assert (-(int)fixP->fx_r_type < alpha_num_operands);
+ operand = &alpha_operands[-(int)fixP->fx_r_type];
+
+ /* The rest of these fixups only exist internally during symbol
+ resolution and have no representation in the object file.
+ Therefore they must be completely resolved as constants. */
+
+ if (fixP->fx_addsy != 0
+ && fixP->fx_addsy->bsym->section != absolute_section)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("non-absolute expression in constant field"));
+
+ image = bfd_getl32(fixpos);
+ image = insert_operand(image, operand, (offsetT)value,
+ fixP->fx_file, fixP->fx_line);
+ }
+ goto write_done;
+ }
+
+ if (fixP->fx_addsy != 0 || fixP->fx_pcrel != 0)
+ return 1;
+ else
+ {
+ as_warn_where(fixP->fx_file, fixP->fx_line,
+ _("type %d reloc done?\n"), (int)fixP->fx_r_type);
+ goto done;
+ }
+
+write_done:
+ md_number_to_chars(fixpos, image, 4);
+
+done:
+ fixP->fx_done = 1;
+ return 0;
+}
+
+/*
+ * Look for a register name in the given symbol.
+ */
+
+symbolS *
+md_undefined_symbol(name)
+ char *name;
+{
+ if (*name == '$')
+ {
+ int is_float = 0, num;
+
+ switch (*++name)
+ {
+ case 'f':
+ if (name[1] == 'p' && name[2] == '\0')
+ return alpha_register_table[AXP_REG_FP];
+ is_float = 32;
+ /* FALLTHRU */
+
+ case 'r':
+ if (!isdigit(*++name))
+ break;
+ /* FALLTHRU */
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ if (name[1] == '\0')
+ num = name[0] - '0';
+ else if (name[0] != '0' && isdigit(name[1]) && name[2] == '\0')
+ {
+ num = (name[0] - '0') * 10 + name[1] - '0';
+ if (num >= 32)
+ break;
+ }
+ else
+ break;
+
+ if (!alpha_noat_on && num == AXP_REG_AT)
+ as_warn(_("Used $at without \".set noat\""));
+ return alpha_register_table[num + is_float];
+
+ case 'a':
+ if (name[1] == 't' && name[2] == '\0')
+ {
+ if (!alpha_noat_on)
+ as_warn(_("Used $at without \".set noat\""));
+ return alpha_register_table[AXP_REG_AT];
+ }
+ break;
+
+ case 'g':
+ if (name[1] == 'p' && name[2] == '\0')
+ return alpha_register_table[alpha_gp_register];
+ break;
+
+ case 's':
+ if (name[1] == 'p' && name[2] == '\0')
+ return alpha_register_table[AXP_REG_SP];
+ break;
+ }
+ }
+ return NULL;
+}
+
+#ifdef OBJ_ECOFF
+/* @@@ Magic ECOFF bits. */
+
+void
+alpha_frob_ecoff_data ()
+{
+ select_gp_value ();
+ /* $zero and $f31 are read-only */
+ alpha_gprmask &= ~1;
+ alpha_fprmask &= ~1;
+}
+#endif
+
+/* Hook to remember a recently defined label so that the auto-align
+ code can adjust the symbol after we know what alignment will be
+ required. */
+
+void
+alpha_define_label (sym)
+ symbolS *sym;
+{
+ alpha_insn_label = sym;
+}
+
+/* Return true if we must always emit a reloc for a type and false if
+ there is some hope of resolving it a assembly time. */
+
+int
+alpha_force_relocation (f)
+ fixS *f;
+{
+ if (alpha_flag_relax)
+ return 1;
+
+ switch (f->fx_r_type)
+ {
+ case BFD_RELOC_ALPHA_GPDISP_HI16:
+ case BFD_RELOC_ALPHA_GPDISP_LO16:
+ case BFD_RELOC_ALPHA_GPDISP:
+#ifdef OBJ_ECOFF
+ case BFD_RELOC_ALPHA_LITERAL:
+#endif
+#ifdef OBJ_ELF
+ case BFD_RELOC_ALPHA_ELF_LITERAL:
+#endif
+ case BFD_RELOC_ALPHA_LITUSE:
+ case BFD_RELOC_GPREL32:
+#ifdef OBJ_EVAX
+ case BFD_RELOC_ALPHA_LINKAGE:
+ case BFD_RELOC_ALPHA_CODEADDR:
+#endif
+ return 1;
+
+ case BFD_RELOC_23_PCREL_S2:
+ case BFD_RELOC_32:
+ case BFD_RELOC_64:
+ case BFD_RELOC_ALPHA_HINT:
+ return 0;
+
+ default:
+ assert((int)f->fx_r_type < 0 && -(int)f->fx_r_type < alpha_num_operands);
+ return 0;
+ }
+}
+
+/* Return true if we can partially resolve a relocation now. */
+
+int
+alpha_fix_adjustable (f)
+ fixS *f;
+{
+#ifdef OBJ_ELF
+ /* Prevent all adjustments to global symbols */
+ if (S_IS_EXTERN (f->fx_addsy) || S_IS_WEAK (f->fx_addsy))
+ return 0;
+#endif
+
+ /* Are there any relocation types for which we must generate a reloc
+ but we can adjust the values contained within it? */
+ switch (f->fx_r_type)
+ {
+ case BFD_RELOC_ALPHA_GPDISP_HI16:
+ case BFD_RELOC_ALPHA_GPDISP_LO16:
+ case BFD_RELOC_ALPHA_GPDISP:
+ return 0;
+
+#ifdef OBJ_ECOFF
+ case BFD_RELOC_ALPHA_LITERAL:
+#endif
+#ifdef OBJ_ELF
+ case BFD_RELOC_ALPHA_ELF_LITERAL:
+#endif
+#ifdef OBJ_EVAX
+ case BFD_RELOC_ALPHA_LINKAGE:
+ case BFD_RELOC_ALPHA_CODEADDR:
+#endif
+ return 1;
+
+ case BFD_RELOC_ALPHA_LITUSE:
+ return 0;
+
+ case BFD_RELOC_GPREL32:
+ case BFD_RELOC_23_PCREL_S2:
+ case BFD_RELOC_32:
+ case BFD_RELOC_64:
+ case BFD_RELOC_ALPHA_HINT:
+ return 1;
+
+ default:
+ assert ((int)f->fx_r_type < 0
+ && - (int)f->fx_r_type < alpha_num_operands);
+ return 1;
+ }
+ /*NOTREACHED*/
+}
+
+/* Generate the BFD reloc to be stuck in the object file from the
+ fixup used internally in the assembler. */
+
+arelent *
+tc_gen_reloc (sec, fixp)
+ asection *sec;
+ fixS *fixp;
+{
+ arelent *reloc;
+
+ reloc = (arelent *) xmalloc (sizeof (arelent));
+ reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+ reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+
+ /* Make sure none of our internal relocations make it this far.
+ They'd better have been fully resolved by this point. */
+ assert ((int)fixp->fx_r_type > 0);
+
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
+ if (reloc->howto == NULL)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("cannot represent `%s' relocation in object file"),
+ bfd_get_reloc_code_name (fixp->fx_r_type));
+ return NULL;
+ }
+
+ if (!fixp->fx_pcrel != !reloc->howto->pc_relative)
+ {
+ as_fatal (_("internal error? cannot generate `%s' relocation"),
+ bfd_get_reloc_code_name (fixp->fx_r_type));
+ }
+ assert (!fixp->fx_pcrel == !reloc->howto->pc_relative);
+
+#ifdef OBJ_ECOFF
+ if (fixp->fx_r_type == BFD_RELOC_ALPHA_LITERAL)
+ {
+ /* fake out bfd_perform_relocation. sigh */
+ reloc->addend = -alpha_gp_value;
+ }
+ else
+#endif
+ {
+ reloc->addend = fixp->fx_offset;
+#ifdef OBJ_ELF
+ /*
+ * Ohhh, this is ugly. The problem is that if this is a local global
+ * symbol, the relocation will entirely be performed at link time, not
+ * at assembly time. bfd_perform_reloc doesn't know about this sort
+ * of thing, and as a result we need to fake it out here.
+ */
+ if ((S_IS_EXTERN (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy))
+ && !S_IS_COMMON(fixp->fx_addsy))
+ reloc->addend -= fixp->fx_addsy->bsym->value;
+#endif
+ }
+
+ return reloc;
+}
+
+/* Parse a register name off of the input_line and return a register
+ number. Gets md_undefined_symbol above to do the register name
+ matching for us.
+
+ Only called as a part of processing the ECOFF .frame directive. */
+
+int
+tc_get_register (frame)
+ int frame;
+{
+ int framereg = AXP_REG_SP;
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '$')
+ {
+ char *s = input_line_pointer;
+ char c = get_symbol_end ();
+ symbolS *sym = md_undefined_symbol (s);
+
+ *strchr(s, '\0') = c;
+ if (sym && (framereg = S_GET_VALUE (sym)) <= 31)
+ goto found;
+ }
+ as_warn (_("frame reg expected, using $%d."), framereg);
+
+found:
+ note_gpreg (framereg);
+ return framereg;
+}
+
+/* This is called before the symbol table is processed. In order to
+ work with gcc when using mips-tfile, we must keep all local labels.
+ However, in other cases, we want to discard them. If we were
+ called with -g, but we didn't see any debugging information, it may
+ mean that gcc is smuggling debugging information through to
+ mips-tfile, in which case we must generate all local labels. */
+
+#ifdef OBJ_ECOFF
+
+void
+alpha_frob_file_before_adjust ()
+{
+ if (alpha_debug != 0
+ && ! ecoff_debugging_seen)
+ flag_keep_locals = 1;
+}
+
+#endif /* OBJ_ECOFF */
+
+/* Parse the arguments to an opcode. */
+
+static int
+tokenize_arguments (str, tok, ntok)
+ char *str;
+ expressionS tok[];
+ int ntok;
+{
+ expressionS *end_tok = tok + ntok;
+ char *old_input_line_pointer;
+ int saw_comma = 0, saw_arg = 0;
+
+ memset (tok, 0, sizeof (*tok) * ntok);
+
+ /* Save and restore input_line_pointer around this function */
+ old_input_line_pointer = input_line_pointer;
+ input_line_pointer = str;
+
+ while (tok < end_tok && *input_line_pointer)
+ {
+ SKIP_WHITESPACE ();
+ switch (*input_line_pointer)
+ {
+ case '\0':
+ goto fini;
+
+ case ',':
+ ++input_line_pointer;
+ if (saw_comma || !saw_arg)
+ goto err;
+ saw_comma = 1;
+ break;
+
+ case '(':
+ {
+ char *hold = input_line_pointer++;
+
+ /* First try for parenthesized register ... */
+ expression (tok);
+ if (*input_line_pointer == ')' && tok->X_op == O_register)
+ {
+ tok->X_op = (saw_comma ? O_cpregister : O_pregister);
+ saw_comma = 0;
+ saw_arg = 1;
+ ++input_line_pointer;
+ ++tok;
+ break;
+ }
+
+ /* ... then fall through to plain expression */
+ input_line_pointer = hold;
+ }
+
+ default:
+ if (saw_arg && !saw_comma)
+ goto err;
+ expression (tok);
+ if (tok->X_op == O_illegal || tok->X_op == O_absent)
+ goto err;
+
+ saw_comma = 0;
+ saw_arg = 1;
+ ++tok;
+ break;
+ }
+ }
+
+fini:
+ if (saw_comma)
+ goto err;
+ input_line_pointer = old_input_line_pointer;
+ return ntok - (end_tok - tok);
+
+err:
+ input_line_pointer = old_input_line_pointer;
+ return -1;
+}
+
+/* Search forward through all variants of an opcode looking for a
+ syntax match. */
+
+static const struct alpha_opcode *
+find_opcode_match(first_opcode, tok, pntok, pcpumatch)
+ const struct alpha_opcode *first_opcode;
+ const expressionS *tok;
+ int *pntok;
+ int *pcpumatch;
+{
+ const struct alpha_opcode *opcode = first_opcode;
+ int ntok = *pntok;
+ int got_cpu_match = 0;
+
+ do
+ {
+ const unsigned char *opidx;
+ int tokidx = 0;
+
+ /* Don't match opcodes that don't exist on this architecture */
+ if (!(opcode->flags & alpha_target))
+ goto match_failed;
+
+ got_cpu_match = 1;
+
+ for (opidx = opcode->operands; *opidx; ++opidx)
+ {
+ const struct alpha_operand *operand = &alpha_operands[*opidx];
+
+ /* only take input from real operands */
+ if (operand->flags & AXP_OPERAND_FAKE)
+ continue;
+
+ /* when we expect input, make sure we have it */
+ if (tokidx >= ntok)
+ {
+ if ((operand->flags & AXP_OPERAND_OPTIONAL_MASK) == 0)
+ goto match_failed;
+ continue;
+ }
+
+ /* match operand type with expression type */
+ switch (operand->flags & AXP_OPERAND_TYPECHECK_MASK)
+ {
+ case AXP_OPERAND_IR:
+ if (tok[tokidx].X_op != O_register
+ || !is_ir_num(tok[tokidx].X_add_number))
+ goto match_failed;
+ break;
+ case AXP_OPERAND_FPR:
+ if (tok[tokidx].X_op != O_register
+ || !is_fpr_num(tok[tokidx].X_add_number))
+ goto match_failed;
+ break;
+ case AXP_OPERAND_IR|AXP_OPERAND_PARENS:
+ if (tok[tokidx].X_op != O_pregister
+ || !is_ir_num(tok[tokidx].X_add_number))
+ goto match_failed;
+ break;
+ case AXP_OPERAND_IR|AXP_OPERAND_PARENS|AXP_OPERAND_COMMA:
+ if (tok[tokidx].X_op != O_cpregister
+ || !is_ir_num(tok[tokidx].X_add_number))
+ goto match_failed;
+ break;
+
+ case AXP_OPERAND_RELATIVE:
+ case AXP_OPERAND_SIGNED:
+ case AXP_OPERAND_UNSIGNED:
+ switch (tok[tokidx].X_op)
+ {
+ case O_illegal:
+ case O_absent:
+ case O_register:
+ case O_pregister:
+ case O_cpregister:
+ goto match_failed;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ /* everything else should have been fake */
+ abort();
+ }
+ ++tokidx;
+ }
+
+ /* possible match -- did we use all of our input? */
+ if (tokidx == ntok)
+ {
+ *pntok = ntok;
+ return opcode;
+ }
+
+ match_failed:;
+ }
+ while (++opcode-alpha_opcodes < alpha_num_opcodes
+ && !strcmp(opcode->name, first_opcode->name));
+
+ if (*pcpumatch)
+ *pcpumatch = got_cpu_match;
+
+ return NULL;
+}
+
+/* Search forward through all variants of a macro looking for a syntax
+ match. */
+
+static const struct alpha_macro *
+find_macro_match(first_macro, tok, pntok)
+ const struct alpha_macro *first_macro;
+ const expressionS *tok;
+ int *pntok;
+{
+ const struct alpha_macro *macro = first_macro;
+ int ntok = *pntok;
+
+ do
+ {
+ const enum alpha_macro_arg *arg = macro->argsets;
+ int tokidx = 0;
+
+ while (*arg)
+ {
+ switch (*arg)
+ {
+ case MACRO_EOA:
+ if (tokidx == ntok)
+ return macro;
+ else
+ tokidx = 0;
+ break;
+
+ case MACRO_IR:
+ if (tokidx >= ntok || tok[tokidx].X_op != O_register
+ || !is_ir_num(tok[tokidx].X_add_number))
+ goto match_failed;
+ ++tokidx;
+ break;
+ case MACRO_PIR:
+ if (tokidx >= ntok || tok[tokidx].X_op != O_pregister
+ || !is_ir_num(tok[tokidx].X_add_number))
+ goto match_failed;
+ ++tokidx;
+ break;
+ case MACRO_CPIR:
+ if (tokidx >= ntok || tok[tokidx].X_op != O_cpregister
+ || !is_ir_num(tok[tokidx].X_add_number))
+ goto match_failed;
+ ++tokidx;
+ break;
+ case MACRO_FPR:
+ if (tokidx >= ntok || tok[tokidx].X_op != O_register
+ || !is_fpr_num(tok[tokidx].X_add_number))
+ goto match_failed;
+ ++tokidx;
+ break;
+
+ case MACRO_EXP:
+ if (tokidx >= ntok)
+ goto match_failed;
+ switch (tok[tokidx].X_op)
+ {
+ case O_illegal:
+ case O_absent:
+ case O_register:
+ case O_pregister:
+ case O_cpregister:
+ goto match_failed;
+
+ default:
+ break;
+ }
+ ++tokidx;
+ break;
+
+ match_failed:
+ while (*arg != MACRO_EOA)
+ ++arg;
+ tokidx = 0;
+ break;
+ }
+ ++arg;
+ }
+ }
+ while (++macro-alpha_macros < alpha_num_macros
+ && !strcmp(macro->name, first_macro->name));
+
+ return NULL;
+}
+
+/* Insert an operand value into an instruction. */
+
+static unsigned
+insert_operand(insn, operand, val, file, line)
+ unsigned insn;
+ const struct alpha_operand *operand;
+ offsetT val;
+ char *file;
+ unsigned line;
+{
+ if (operand->bits != 32 && !(operand->flags & AXP_OPERAND_NOOVERFLOW))
+ {
+ offsetT min, max;
+
+ if (operand->flags & AXP_OPERAND_SIGNED)
+ {
+ max = (1 << (operand->bits - 1)) - 1;
+ min = -(1 << (operand->bits - 1));
+ }
+ else
+ {
+ max = (1 << operand->bits) - 1;
+ min = 0;
+ }
+
+ if (val < min || val > max)
+ {
+ const char *err =
+ _("operand out of range (%s not between %d and %d)");
+ char buf[sizeof (val) * 3 + 2];
+
+ sprint_value(buf, val);
+ if (file)
+ as_warn_where(file, line, err, buf, min, max);
+ else
+ as_warn(err, buf, min, max);
+ }
+ }
+
+ if (operand->insert)
+ {
+ const char *errmsg = NULL;
+
+ insn = (*operand->insert) (insn, val, &errmsg);
+ if (errmsg)
+ as_warn (errmsg);
+ }
+ else
+ insn |= ((val & ((1 << operand->bits) - 1)) << operand->shift);
+
+ return insn;
+}
+
+/*
+ * Turn an opcode description and a set of arguments into
+ * an instruction and a fixup.
+ */
+
+static void
+assemble_insn(opcode, tok, ntok, insn)
+ const struct alpha_opcode *opcode;
+ const expressionS *tok;
+ int ntok;
+ struct alpha_insn *insn;
+{
+ const unsigned char *argidx;
+ unsigned image;
+ int tokidx = 0;
+
+ memset (insn, 0, sizeof (*insn));
+ image = opcode->opcode;
+
+ for (argidx = opcode->operands; *argidx; ++argidx)
+ {
+ const struct alpha_operand *operand = &alpha_operands[*argidx];
+ const expressionS *t;
+
+ if (operand->flags & AXP_OPERAND_FAKE)
+ {
+ /* fake operands take no value and generate no fixup */
+ image = insert_operand(image, operand, 0, NULL, 0);
+ continue;
+ }
+
+ if (tokidx >= ntok)
+ {
+ switch (operand->flags & AXP_OPERAND_OPTIONAL_MASK)
+ {
+ case AXP_OPERAND_DEFAULT_FIRST:
+ t = &tok[0];
+ break;
+ case AXP_OPERAND_DEFAULT_SECOND:
+ t = &tok[1];
+ break;
+ case AXP_OPERAND_DEFAULT_ZERO:
+ {
+ static const expressionS zero_exp = { 0, 0, 0, O_constant, 1 };
+ t = &zero_exp;
+ }
+ break;
+ default:
+ abort();
+ }
+ }
+ else
+ t = &tok[tokidx++];
+
+ switch (t->X_op)
+ {
+ case O_register:
+ case O_pregister:
+ case O_cpregister:
+ image = insert_operand(image, operand, regno(t->X_add_number),
+ NULL, 0);
+ break;
+
+ case O_constant:
+ image = insert_operand(image, operand, t->X_add_number, NULL, 0);
+ break;
+
+ default:
+ {
+ struct alpha_fixup *fixup;
+
+ if (insn->nfixups >= MAX_INSN_FIXUPS)
+ as_fatal(_("too many fixups"));
+
+ fixup = &insn->fixups[insn->nfixups++];
+
+ fixup->exp = *t;
+ fixup->reloc = operand->default_reloc;
+ }
+ break;
+ }
+ }
+
+ insn->insn = image;
+}
+
+/*
+ * Actually output an instruction with its fixup.
+ */
+
+static void
+emit_insn (insn)
+ struct alpha_insn *insn;
+{
+ char *f;
+ int i;
+
+ /* Take care of alignment duties */
+ if (alpha_auto_align_on && alpha_current_align < 2)
+ alpha_align (2, (char *) NULL, alpha_insn_label, 0);
+ if (alpha_current_align > 2)
+ alpha_current_align = 2;
+ alpha_insn_label = NULL;
+
+ /* Write out the instruction. */
+ f = frag_more (4);
+ md_number_to_chars (f, insn->insn, 4);
+
+ /* Apply the fixups in order */
+ for (i = 0; i < insn->nfixups; ++i)
+ {
+ const struct alpha_operand *operand;
+ struct alpha_fixup *fixup = &insn->fixups[i];
+ int size, pcrel;
+ fixS *fixP;
+
+ /* Some fixups are only used internally and so have no howto */
+ if ((int)fixup->reloc < 0)
+ {
+ operand = &alpha_operands[-(int)fixup->reloc];
+ size = 4;
+ pcrel = ((operand->flags & AXP_OPERAND_RELATIVE) != 0);
+ }
+#ifdef OBJ_ELF
+ /* These relocation types are only used internally. */
+ else if (fixup->reloc == BFD_RELOC_ALPHA_GPDISP_HI16
+ || fixup->reloc == BFD_RELOC_ALPHA_GPDISP_LO16)
+ {
+ size = 2, pcrel = 0;
+ }
+#endif
+ else
+ {
+ reloc_howto_type *reloc_howto
+ = bfd_reloc_type_lookup (stdoutput, fixup->reloc);
+ assert (reloc_howto);
+
+ size = bfd_get_reloc_size (reloc_howto);
+ pcrel = reloc_howto->pc_relative;
+ }
+ assert (size >= 1 && size <= 4);
+
+ fixP = fix_new_exp (frag_now, f - frag_now->fr_literal, size,
+ &fixup->exp, pcrel, fixup->reloc);
+
+ /* Turn off complaints that the addend is too large for some fixups */
+ switch (fixup->reloc)
+ {
+ case BFD_RELOC_ALPHA_GPDISP_LO16:
+#ifdef OBJ_ECOFF
+ case BFD_RELOC_ALPHA_LITERAL:
+#endif
+#ifdef OBJ_ELF
+ case BFD_RELOC_ALPHA_ELF_LITERAL:
+#endif
+ case BFD_RELOC_GPREL32:
+ fixP->fx_no_overflow = 1;
+ break;
+
+ default:
+ if ((int)fixup->reloc < 0)
+ {
+ if (operand->flags & AXP_OPERAND_NOOVERFLOW)
+ fixP->fx_no_overflow = 1;
+ }
+ break;
+ }
+ }
+}
+
+/* Given an opcode name and a pre-tokenized set of arguments, assemble
+ the insn, but do not emit it.
+
+ Note that this implies no macros allowed, since we can't store more
+ than one insn in an insn structure. */
+
+static void
+assemble_tokens_to_insn(opname, tok, ntok, insn)
+ const char *opname;
+ const expressionS *tok;
+ int ntok;
+ struct alpha_insn *insn;
+{
+ const struct alpha_opcode *opcode;
+
+ /* search opcodes */
+ opcode = (const struct alpha_opcode *) hash_find (alpha_opcode_hash, opname);
+ if (opcode)
+ {
+ int cpumatch;
+ opcode = find_opcode_match (opcode, tok, &ntok, &cpumatch);
+ if (opcode)
+ {
+ assemble_insn (opcode, tok, ntok, insn);
+ return;
+ }
+ else if (cpumatch)
+ as_bad (_("inappropriate arguments for opcode `%s'"), opname);
+ else
+ as_bad (_("opcode `%s' not supported for target %s"), opname,
+ alpha_target_name);
+ }
+ else
+ as_bad (_("unknown opcode `%s'"), opname);
+}
+
+/* Given an opcode name and a pre-tokenized set of arguments, take the
+ opcode all the way through emission. */
+
+static void
+assemble_tokens (opname, tok, ntok, local_macros_on)
+ const char *opname;
+ const expressionS *tok;
+ int ntok;
+ int local_macros_on;
+{
+ int found_something = 0;
+ const struct alpha_opcode *opcode;
+ const struct alpha_macro *macro;
+ int cpumatch = 1;
+
+ /* search macros */
+ if (local_macros_on)
+ {
+ macro = ((const struct alpha_macro *)
+ hash_find (alpha_macro_hash, opname));
+ if (macro)
+ {
+ found_something = 1;
+ macro = find_macro_match (macro, tok, &ntok);
+ if (macro)
+ {
+ (*macro->emit) (tok, ntok, macro->arg);
+ return;
+ }
+ }
+ }
+
+ /* search opcodes */
+ opcode = (const struct alpha_opcode *) hash_find (alpha_opcode_hash, opname);
+ if (opcode)
+ {
+ found_something = 1;
+ opcode = find_opcode_match (opcode, tok, &ntok, &cpumatch);
+ if (opcode)
+ {
+ struct alpha_insn insn;
+ assemble_insn (opcode, tok, ntok, &insn);
+ emit_insn (&insn);
+ return;
+ }
+ }
+
+ if (found_something)
+ if (cpumatch)
+ as_bad (_("inappropriate arguments for opcode `%s'"), opname);
+ else
+ as_bad (_("opcode `%s' not supported for target %s"), opname,
+ alpha_target_name);
+ else
+ as_bad (_("unknown opcode `%s'"), opname);
+}
+
+
+/* Some instruction sets indexed by lg(size) */
+static const char * const sextX_op[] = { "sextb", "sextw", "sextl", NULL };
+static const char * const insXl_op[] = { "insbl", "inswl", "insll", "insql" };
+static const char * const insXh_op[] = { NULL, "inswh", "inslh", "insqh" };
+static const char * const extXl_op[] = { "extbl", "extwl", "extll", "extql" };
+static const char * const extXh_op[] = { NULL, "extwh", "extlh", "extqh" };
+static const char * const mskXl_op[] = { "mskbl", "mskwl", "mskll", "mskql" };
+static const char * const mskXh_op[] = { NULL, "mskwh", "msklh", "mskqh" };
+static const char * const stX_op[] = { "stb", "stw", "stl", "stq" };
+static const char * const ldX_op[] = { "ldb", "ldw", "ldll", "ldq" };
+static const char * const ldXu_op[] = { "ldbu", "ldwu", NULL, NULL };
+
+/* Implement the ldgp macro. */
+
+static void
+emit_ldgp (tok, ntok, unused)
+ const expressionS *tok;
+ int ntok;
+ const PTR unused;
+{
+#ifdef OBJ_AOUT
+FIXME
+#endif
+#if defined(OBJ_ECOFF) || defined(OBJ_ELF)
+ /* from "ldgp r1,n(r2)", generate "ldah r1,X(R2); lda r1,Y(r1)"
+ with appropriate constants and relocations. */
+ struct alpha_insn insn;
+ expressionS newtok[3];
+ expressionS addend;
+
+ /* We're going to need this symbol in md_apply_fix(). */
+ (void) section_symbol (absolute_section);
+
+#ifdef OBJ_ECOFF
+ if (regno (tok[2].X_add_number) == AXP_REG_PV)
+ ecoff_set_gp_prolog_size (0);
+#endif
+
+ newtok[0] = tok[0];
+ set_tok_const (newtok[1], 0);
+ newtok[2] = tok[2];
+
+ assemble_tokens_to_insn ("ldah", newtok, 3, &insn);
+
+ addend = tok[1];
+
+#ifdef OBJ_ECOFF
+ if (addend.X_op != O_constant)
+ as_bad (_("can not resolve expression"));
+ addend.X_op = O_symbol;
+ addend.X_add_symbol = alpha_gp_symbol;
+#endif
+
+ insn.nfixups = 1;
+ insn.fixups[0].exp = addend;
+ insn.fixups[0].reloc = BFD_RELOC_ALPHA_GPDISP_HI16;
+
+ emit_insn (&insn);
+
+ set_tok_preg (newtok[2], tok[0].X_add_number);
+
+ assemble_tokens_to_insn ("lda", newtok, 3, &insn);
+
+#ifdef OBJ_ECOFF
+ addend.X_add_number += 4;
+#endif
+
+ insn.nfixups = 1;
+ insn.fixups[0].exp = addend;
+ insn.fixups[0].reloc = BFD_RELOC_ALPHA_GPDISP_LO16;
+
+ emit_insn (&insn);
+#endif /* OBJ_ECOFF || OBJ_ELF */
+}
+
+#ifdef OBJ_EVAX
+
+/* Add symbol+addend to link pool.
+ Return offset from basesym to entry in link pool.
+
+ Add new fixup only if offset isn't 16bit. */
+
+valueT
+add_to_link_pool (basesym, sym, addend)
+ symbolS *basesym;
+ symbolS *sym;
+ offsetT addend;
+{
+ segT current_section = now_seg;
+ int current_subsec = now_subseg;
+ valueT offset;
+ bfd_reloc_code_real_type reloc_type;
+ char *p;
+ segment_info_type *seginfo = seg_info (alpha_link_section);
+ fixS *fixp;
+
+ offset = -basesym->sy_obj;
+
+ /* @@ This assumes all entries in a given section will be of the same
+ size... Probably correct, but unwise to rely on. */
+ /* This must always be called with the same subsegment. */
+
+ if (seginfo->frchainP)
+ for (fixp = seginfo->frchainP->fix_root;
+ fixp != (fixS *) NULL;
+ fixp = fixp->fx_next, offset += 8)
+ {
+ if (fixp->fx_addsy == sym && fixp->fx_offset == addend)
+ {
+ if (range_signed_16 (offset))
+ {
+ return offset;
+ }
+ }
+ }
+
+ /* Not found in 16bit signed range. */
+
+ subseg_set (alpha_link_section, 0);
+ p = frag_more (8);
+ memset (p, 0, 8);
+
+ fix_new (frag_now, p - frag_now->fr_literal, 8, sym, addend, 0,
+ BFD_RELOC_64);
+
+ subseg_set (current_section, current_subsec);
+ seginfo->literal_pool_size += 8;
+ return offset;
+}
+
+#endif /* OBJ_EVAX */
+
+/* Load a (partial) expression into a target register.
+
+ If poffset is not null, after the call it will either contain
+ O_constant 0, or a 16-bit offset appropriate for any MEM format
+ instruction. In addition, pbasereg will be modified to point to
+ the base register to use in that MEM format instruction.
+
+ In any case, *pbasereg should contain a base register to add to the
+ expression. This will normally be either AXP_REG_ZERO or
+ alpha_gp_register. Symbol addresses will always be loaded via $gp,
+ so "foo($0)" is interpreted as adding the address of foo to $0;
+ i.e. "ldq $targ, LIT($gp); addq $targ, $0, $targ". Odd, perhaps,
+ but this is what OSF/1 does.
+
+ Finally, the return value is true if the calling macro may emit a
+ LITUSE reloc if otherwise appropriate. */
+
+static int
+load_expression (targreg, exp, pbasereg, poffset)
+ int targreg;
+ const expressionS *exp;
+ int *pbasereg;
+ expressionS *poffset;
+{
+ int emit_lituse = 0;
+ offsetT addend = exp->X_add_number;
+ int basereg = *pbasereg;
+ struct alpha_insn insn;
+ expressionS newtok[3];
+
+ switch (exp->X_op)
+ {
+ case O_symbol:
+ {
+#ifdef OBJ_ECOFF
+ offsetT lit;
+
+ /* attempt to reduce .lit load by splitting the offset from
+ its symbol when possible, but don't create a situation in
+ which we'd fail. */
+ if (!range_signed_32 (addend) &&
+ (alpha_noat_on || targreg == AXP_REG_AT))
+ {
+ lit = add_to_literal_pool (exp->X_add_symbol, addend,
+ alpha_lita_section, 8);
+ addend = 0;
+ }
+ else
+ {
+ lit = add_to_literal_pool (exp->X_add_symbol, 0,
+ alpha_lita_section, 8);
+ }
+
+ if (lit >= 0x8000)
+ as_fatal (_("overflow in literal (.lita) table"));
+
+ /* emit "ldq r, lit(gp)" */
+
+ if (basereg != alpha_gp_register && targreg == basereg)
+ {
+ if (alpha_noat_on)
+ as_bad (_("macro requires $at register while noat in effect"));
+ if (targreg == AXP_REG_AT)
+ as_bad (_("macro requires $at while $at in use"));
+
+ set_tok_reg (newtok[0], AXP_REG_AT);
+ }
+ else
+ set_tok_reg (newtok[0], targreg);
+ set_tok_sym (newtok[1], alpha_lita_symbol, lit);
+ set_tok_preg (newtok[2], alpha_gp_register);
+
+ assemble_tokens_to_insn ("ldq", newtok, 3, &insn);
+
+ assert (insn.nfixups == 1);
+ insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITERAL;
+#endif /* OBJ_ECOFF */
+#ifdef OBJ_ELF
+ /* emit "ldq r, gotoff(gp)" */
+
+ if (basereg != alpha_gp_register && targreg == basereg)
+ {
+ if (alpha_noat_on)
+ as_bad (_("macro requires $at register while noat in effect"));
+ if (targreg == AXP_REG_AT)
+ as_bad (_("macro requires $at while $at in use"));
+
+ set_tok_reg (newtok[0], AXP_REG_AT);
+ }
+ else
+ set_tok_reg (newtok[0], targreg);
+
+ /* XXX: Disable this .got minimizing optimization so that we can get
+ better instruction offset knowledge in the compiler. This happens
+ very infrequently anyway. */
+ if (1 || (!range_signed_32 (addend)
+ && (alpha_noat_on || targreg == AXP_REG_AT)))
+ {
+ newtok[1] = *exp;
+ addend = 0;
+ }
+ else
+ {
+ set_tok_sym (newtok[1], exp->X_add_symbol, 0);
+ }
+
+ set_tok_preg (newtok[2], alpha_gp_register);
+
+ assemble_tokens_to_insn ("ldq", newtok, 3, &insn);
+
+ assert (insn.nfixups == 1);
+ insn.fixups[0].reloc = BFD_RELOC_ALPHA_ELF_LITERAL;
+#endif /* OBJ_ELF */
+#ifdef OBJ_EVAX
+ offsetT link;
+
+ /* Find symbol or symbol pointer in link section. */
+
+ if (exp->X_add_symbol == alpha_evax_proc.symbol)
+ {
+ if (range_signed_16 (addend))
+ {
+ set_tok_reg (newtok[0], targreg);
+ set_tok_const (newtok[1], addend);
+ set_tok_preg (newtok[2], basereg);
+ assemble_tokens_to_insn ("lda", newtok, 3, &insn);
+ addend = 0;
+ }
+ else
+ {
+ set_tok_reg (newtok[0], targreg);
+ set_tok_const (newtok[1], 0);
+ set_tok_preg (newtok[2], basereg);
+ assemble_tokens_to_insn ("lda", newtok, 3, &insn);
+ }
+ }
+ else
+ {
+ if (!range_signed_32 (addend))
+ {
+ link = add_to_link_pool (alpha_evax_proc.symbol,
+ exp->X_add_symbol, addend);
+ addend = 0;
+ }
+ else
+ {
+ link = add_to_link_pool (alpha_evax_proc.symbol,
+ exp->X_add_symbol, 0);
+ }
+ set_tok_reg (newtok[0], targreg);
+ set_tok_const (newtok[1], link);
+ set_tok_preg (newtok[2], basereg);
+ assemble_tokens_to_insn ("ldq", newtok, 3, &insn);
+ }
+#endif /* OBJ_EVAX */
+
+ emit_insn(&insn);
+
+#ifndef OBJ_EVAX
+ emit_lituse = 1;
+
+ if (basereg != alpha_gp_register && basereg != AXP_REG_ZERO)
+ {
+ /* emit "addq r, base, r" */
+
+ set_tok_reg (newtok[1], basereg);
+ set_tok_reg (newtok[2], targreg);
+ assemble_tokens ("addq", newtok, 3, 0);
+ }
+#endif
+
+ basereg = targreg;
+ }
+ break;
+
+ case O_constant:
+ break;
+
+ case O_subtract:
+ /* Assume that this difference expression will be resolved to an
+ absolute value and that that value will fit in 16 bits. */
+
+ set_tok_reg (newtok[0], targreg);
+ newtok[1] = *exp;
+ set_tok_preg (newtok[2], basereg);
+ assemble_tokens ("lda", newtok, 3, 0);
+
+ if (poffset)
+ set_tok_const (*poffset, 0);
+ return 0;
+
+ case O_big:
+ if (exp->X_add_number > 0)
+ as_bad (_("bignum invalid; zero assumed"));
+ else
+ as_bad (_("floating point number invalid; zero assumed"));
+ addend = 0;
+ break;
+
+ default:
+ as_bad (_("can't handle expression"));
+ addend = 0;
+ break;
+ }
+
+ if (!range_signed_32 (addend))
+ {
+ offsetT lit;
+
+ /* for 64-bit addends, just put it in the literal pool */
+
+#ifdef OBJ_EVAX
+ /* emit "ldq targreg, lit(basereg)" */
+ lit = add_to_link_pool (alpha_evax_proc.symbol,
+ section_symbol (absolute_section), addend);
+ set_tok_reg (newtok[0], targreg);
+ set_tok_const (newtok[1], lit);
+ set_tok_preg (newtok[2], alpha_gp_register);
+ assemble_tokens ("ldq", newtok, 3, 0);
+#else
+
+ if (alpha_lit8_section == NULL)
+ {
+ create_literal_section (".lit8",
+ &alpha_lit8_section,
+ &alpha_lit8_symbol);
+
+#ifdef OBJ_ECOFF
+ alpha_lit8_literal = add_to_literal_pool (alpha_lit8_symbol, 0x8000,
+ alpha_lita_section, 8);
+ if (alpha_lit8_literal >= 0x8000)
+ as_fatal (_("overflow in literal (.lita) table"));
+#endif
+ }
+
+ lit = add_to_literal_pool (NULL, addend, alpha_lit8_section, 8) - 0x8000;
+ if (lit >= 0x8000)
+ as_fatal (_("overflow in literal (.lit8) table"));
+
+ /* emit "lda litreg, .lit8+0x8000" */
+
+ if (targreg == basereg)
+ {
+ if (alpha_noat_on)
+ as_bad (_("macro requires $at register while noat in effect"));
+ if (targreg == AXP_REG_AT)
+ as_bad (_("macro requires $at while $at in use"));
+
+ set_tok_reg (newtok[0], AXP_REG_AT);
+ }
+ else
+ set_tok_reg (newtok[0], targreg);
+#ifdef OBJ_ECOFF
+ set_tok_sym (newtok[1], alpha_lita_symbol, alpha_lit8_literal);
+#endif
+#ifdef OBJ_ELF
+ set_tok_sym (newtok[1], alpha_lit8_symbol, 0x8000);
+#endif
+ set_tok_preg (newtok[2], alpha_gp_register);
+
+ assemble_tokens_to_insn ("ldq", newtok, 3, &insn);
+
+ assert (insn.nfixups == 1);
+#ifdef OBJ_ECOFF
+ insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITERAL;
+#endif
+#ifdef OBJ_ELF
+ insn.fixups[0].reloc = BFD_RELOC_ALPHA_ELF_LITERAL;
+#endif
+
+ emit_insn (&insn);
+
+ /* emit "ldq litreg, lit(litreg)" */
+
+ set_tok_const (newtok[1], lit);
+ set_tok_preg (newtok[2], newtok[0].X_add_number);
+
+ assemble_tokens_to_insn ("ldq", newtok, 3, &insn);
+
+ assert (insn.nfixups < MAX_INSN_FIXUPS);
+ if (insn.nfixups > 0)
+ {
+ memmove (&insn.fixups[1], &insn.fixups[0],
+ sizeof(struct alpha_fixup) * insn.nfixups);
+ }
+ insn.nfixups++;
+ insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITUSE;
+ insn.fixups[0].exp.X_op = O_constant;
+ insn.fixups[0].exp.X_add_number = 1;
+ emit_lituse = 0;
+
+ emit_insn (&insn);
+
+ /* emit "addq litreg, base, target" */
+
+ if (basereg != AXP_REG_ZERO)
+ {
+ set_tok_reg (newtok[1], basereg);
+ set_tok_reg (newtok[2], targreg);
+ assemble_tokens ("addq", newtok, 3, 0);
+ }
+#endif /* !OBJ_EVAX */
+
+ if (poffset)
+ set_tok_const (*poffset, 0);
+ *pbasereg = targreg;
+ }
+ else
+ {
+ offsetT low, high, extra, tmp;
+
+ /* for 32-bit operands, break up the addend */
+
+ low = sign_extend_16 (addend);
+ tmp = addend - low;
+ high = sign_extend_16 (tmp >> 16);
+
+ if (tmp - (high << 16))
+ {
+ extra = 0x4000;
+ tmp -= 0x40000000;
+ high = sign_extend_16 (tmp >> 16);
+ }
+ else
+ extra = 0;
+
+ set_tok_reg (newtok[0], targreg);
+ set_tok_preg (newtok[2], basereg);
+
+ if (extra)
+ {
+ /* emit "ldah r, extra(r) */
+ set_tok_const (newtok[1], extra);
+ assemble_tokens ("ldah", newtok, 3, 0);
+ set_tok_preg (newtok[2], basereg = targreg);
+ }
+
+ if (high)
+ {
+ /* emit "ldah r, high(r) */
+ set_tok_const (newtok[1], high);
+ assemble_tokens ("ldah", newtok, 3, 0);
+ basereg = targreg;
+ set_tok_preg (newtok[2], basereg);
+ }
+
+ if ((low && !poffset) || (!poffset && basereg != targreg))
+ {
+ /* emit "lda r, low(base)" */
+ set_tok_const (newtok[1], low);
+ assemble_tokens ("lda", newtok, 3, 0);
+ basereg = targreg;
+ low = 0;
+ }
+
+ if (poffset)
+ set_tok_const (*poffset, low);
+ *pbasereg = basereg;
+ }
+
+ return emit_lituse;
+}
+
+/* The lda macro differs from the lda instruction in that it handles
+ most simple expressions, particualrly symbol address loads and
+ large constants. */
+
+static void
+emit_lda (tok, ntok, unused)
+ const expressionS *tok;
+ int ntok;
+ const PTR unused;
+{
+ int basereg;
+
+ if (ntok == 2)
+ basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : alpha_gp_register);
+ else
+ basereg = tok[2].X_add_number;
+
+ (void) load_expression (tok[0].X_add_number, &tok[1], &basereg, NULL);
+}
+
+/* The ldah macro differs from the ldah instruction in that it has $31
+ as an implied base register. */
+
+static void
+emit_ldah (tok, ntok, unused)
+ const expressionS *tok;
+ int ntok;
+ const PTR unused;
+{
+ expressionS newtok[3];
+
+ newtok[0] = tok[0];
+ newtok[1] = tok[1];
+ set_tok_preg (newtok[2], AXP_REG_ZERO);
+
+ assemble_tokens ("ldah", newtok, 3, 0);
+}
+
+/* Handle all "simple" integer register loads -- ldq, ldq_l, ldq_u,
+ etc. They differ from the real instructions in that they do simple
+ expressions like the lda macro. */
+
+static void
+emit_ir_load (tok, ntok, opname)
+ const expressionS *tok;
+ int ntok;
+ const PTR opname;
+{
+ int basereg, lituse;
+ expressionS newtok[3];
+ struct alpha_insn insn;
+
+ if (ntok == 2)
+ basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : alpha_gp_register);
+ else
+ basereg = tok[2].X_add_number;
+
+ lituse = load_expression (tok[0].X_add_number, &tok[1], &basereg,
+ &newtok[1]);
+
+ newtok[0] = tok[0];
+ set_tok_preg (newtok[2], basereg);
+
+ assemble_tokens_to_insn ((const char *)opname, newtok, 3, &insn);
+
+ if (lituse)
+ {
+ assert (insn.nfixups < MAX_INSN_FIXUPS);
+ if (insn.nfixups > 0)
+ {
+ memmove (&insn.fixups[1], &insn.fixups[0],
+ sizeof(struct alpha_fixup) * insn.nfixups);
+ }
+ insn.nfixups++;
+ insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITUSE;
+ insn.fixups[0].exp.X_op = O_constant;
+ insn.fixups[0].exp.X_add_number = 1;
+ }
+
+ emit_insn (&insn);
+}
+
+/* Handle fp register loads, and both integer and fp register stores.
+ Again, we handle simple expressions. */
+
+static void
+emit_loadstore (tok, ntok, opname)
+ const expressionS *tok;
+ int ntok;
+ const PTR opname;
+{
+ int basereg, lituse;
+ expressionS newtok[3];
+ struct alpha_insn insn;
+
+ if (ntok == 2)
+ basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : alpha_gp_register);
+ else
+ basereg = tok[2].X_add_number;
+
+ if (tok[1].X_op != O_constant || !range_signed_16(tok[1].X_add_number))
+ {
+ if (alpha_noat_on)
+ as_bad (_("macro requires $at register while noat in effect"));
+
+ lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, &newtok[1]);
+ }
+ else
+ {
+ newtok[1] = tok[1];
+ lituse = 0;
+ }
+
+ newtok[0] = tok[0];
+ set_tok_preg (newtok[2], basereg);
+
+ assemble_tokens_to_insn ((const char *)opname, newtok, 3, &insn);
+
+ if (lituse)
+ {
+ assert (insn.nfixups < MAX_INSN_FIXUPS);
+ if (insn.nfixups > 0)
+ {
+ memmove (&insn.fixups[1], &insn.fixups[0],
+ sizeof(struct alpha_fixup) * insn.nfixups);
+ }
+ insn.nfixups++;
+ insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITUSE;
+ insn.fixups[0].exp.X_op = O_constant;
+ insn.fixups[0].exp.X_add_number = 1;
+ }
+
+ emit_insn (&insn);
+}
+
+/* Load a half-word or byte as an unsigned value. */
+
+static void
+emit_ldXu (tok, ntok, vlgsize)
+ const expressionS *tok;
+ int ntok;
+ const PTR vlgsize;
+{
+ if (alpha_target & AXP_OPCODE_BWX)
+ emit_ir_load (tok, ntok, ldXu_op[(long)vlgsize]);
+ else
+ {
+ expressionS newtok[3];
+
+ if (alpha_noat_on)
+ as_bad (_("macro requires $at register while noat in effect"));
+
+ /* emit "lda $at, exp" */
+
+ memcpy (newtok, tok, sizeof (expressionS) * ntok);
+ newtok[0].X_add_number = AXP_REG_AT;
+ assemble_tokens ("lda", newtok, ntok, 1);
+
+ /* emit "ldq_u targ, 0($at)" */
+
+ newtok[0] = tok[0];
+ set_tok_const (newtok[1], 0);
+ set_tok_preg (newtok[2], AXP_REG_AT);
+ assemble_tokens ("ldq_u", newtok, 3, 1);
+
+ /* emit "extXl targ, $at, targ" */
+
+ set_tok_reg (newtok[1], AXP_REG_AT);
+ newtok[2] = newtok[0];
+ assemble_tokens (extXl_op[(long)vlgsize], newtok, 3, 1);
+ }
+}
+
+/* Load a half-word or byte as a signed value. */
+
+static void
+emit_ldX (tok, ntok, vlgsize)
+ const expressionS *tok;
+ int ntok;
+ const PTR vlgsize;
+{
+ emit_ldXu (tok, ntok, vlgsize);
+ assemble_tokens (sextX_op[(long)vlgsize], tok, 1, 1);
+}
+
+/* Load an integral value from an unaligned address as an unsigned
+ value. */
+
+static void
+emit_uldXu (tok, ntok, vlgsize)
+ const expressionS *tok;
+ int ntok;
+ const PTR vlgsize;
+{
+ long lgsize = (long)vlgsize;
+ expressionS newtok[3];
+
+ if (alpha_noat_on)
+ as_bad (_("macro requires $at register while noat in effect"));
+
+ /* emit "lda $at, exp" */
+
+ memcpy (newtok, tok, sizeof (expressionS) * ntok);
+ newtok[0].X_add_number = AXP_REG_AT;
+ assemble_tokens ("lda", newtok, ntok, 1);
+
+ /* emit "ldq_u $t9, 0($at)" */
+
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ set_tok_const (newtok[1], 0);
+ set_tok_preg (newtok[2], AXP_REG_AT);
+ assemble_tokens ("ldq_u", newtok, 3, 1);
+
+ /* emit "ldq_u $t10, size-1($at)" */
+
+ set_tok_reg (newtok[0], AXP_REG_T10);
+ set_tok_const (newtok[1], (1<<lgsize)-1);
+ assemble_tokens ("ldq_u", newtok, 3, 1);
+
+ /* emit "extXl $t9, $at, $t9" */
+
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ set_tok_reg (newtok[1], AXP_REG_AT);
+ set_tok_reg (newtok[2], AXP_REG_T9);
+ assemble_tokens (extXl_op[lgsize], newtok, 3, 1);
+
+ /* emit "extXh $t10, $at, $t10" */
+
+ set_tok_reg (newtok[0], AXP_REG_T10);
+ set_tok_reg (newtok[2], AXP_REG_T10);
+ assemble_tokens (extXh_op[lgsize], newtok, 3, 1);
+
+ /* emit "or $t9, $t10, targ" */
+
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ set_tok_reg (newtok[1], AXP_REG_T10);
+ newtok[2] = tok[0];
+ assemble_tokens ("or", newtok, 3, 1);
+}
+
+/* Load an integral value from an unaligned address as a signed value.
+ Note that quads should get funneled to the unsigned load since we
+ don't have to do the sign extension. */
+
+static void
+emit_uldX (tok, ntok, vlgsize)
+ const expressionS *tok;
+ int ntok;
+ const PTR vlgsize;
+{
+ emit_uldXu (tok, ntok, vlgsize);
+ assemble_tokens (sextX_op[(long)vlgsize], tok, 1, 1);
+}
+
+/* Implement the ldil macro. */
+
+static void
+emit_ldil (tok, ntok, unused)
+ const expressionS *tok;
+ int ntok;
+ const PTR unused;
+{
+ expressionS newtok[2];
+
+ memcpy (newtok, tok, sizeof(newtok));
+ newtok[1].X_add_number = sign_extend_32 (tok[1].X_add_number);
+
+ assemble_tokens ("lda", newtok, ntok, 1);
+}
+
+/* Store a half-word or byte. */
+
+static void
+emit_stX (tok, ntok, vlgsize)
+ const expressionS *tok;
+ int ntok;
+ const PTR vlgsize;
+{
+ int lgsize = (int)(long)vlgsize;
+
+ if (alpha_target & AXP_OPCODE_BWX)
+ emit_loadstore (tok, ntok, stX_op[lgsize]);
+ else
+ {
+ expressionS newtok[3];
+
+ if (alpha_noat_on)
+ as_bad(_("macro requires $at register while noat in effect"));
+
+ /* emit "lda $at, exp" */
+
+ memcpy (newtok, tok, sizeof (expressionS) * ntok);
+ newtok[0].X_add_number = AXP_REG_AT;
+ assemble_tokens ("lda", newtok, ntok, 1);
+
+ /* emit "ldq_u $t9, 0($at)" */
+
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ set_tok_const (newtok[1], 0);
+ set_tok_preg (newtok[2], AXP_REG_AT);
+ assemble_tokens ("ldq_u", newtok, 3, 1);
+
+ /* emit "insXl src, $at, $t10" */
+
+ newtok[0] = tok[0];
+ set_tok_reg (newtok[1], AXP_REG_AT);
+ set_tok_reg (newtok[2], AXP_REG_T10);
+ assemble_tokens (insXl_op[lgsize], newtok, 3, 1);
+
+ /* emit "mskXl $t9, $at, $t9" */
+
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ newtok[2] = newtok[0];
+ assemble_tokens (mskXl_op[lgsize], newtok, 3, 1);
+
+ /* emit "or $t9, $t10, $t9" */
+
+ set_tok_reg (newtok[1], AXP_REG_T10);
+ assemble_tokens ("or", newtok, 3, 1);
+
+ /* emit "stq_u $t9, 0($at) */
+
+ set_tok_const (newtok[1], 0);
+ set_tok_preg (newtok[2], AXP_REG_AT);
+ assemble_tokens ("stq_u", newtok, 3, 1);
+ }
+}
+
+/* Store an integer to an unaligned address. */
+
+static void
+emit_ustX (tok, ntok, vlgsize)
+ const expressionS *tok;
+ int ntok;
+ const PTR vlgsize;
+{
+ int lgsize = (int)(long)vlgsize;
+ expressionS newtok[3];
+
+ /* emit "lda $at, exp" */
+
+ memcpy (newtok, tok, sizeof (expressionS) * ntok);
+ newtok[0].X_add_number = AXP_REG_AT;
+ assemble_tokens ("lda", newtok, ntok, 1);
+
+ /* emit "ldq_u $9, 0($at)" */
+
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ set_tok_const (newtok[1], 0);
+ set_tok_preg (newtok[2], AXP_REG_AT);
+ assemble_tokens ("ldq_u", newtok, 3, 1);
+
+ /* emit "ldq_u $10, size-1($at)" */
+
+ set_tok_reg (newtok[0], AXP_REG_T10);
+ set_tok_const (newtok[1], (1 << lgsize)-1);
+ assemble_tokens ("ldq_u", newtok, 3, 1);
+
+ /* emit "insXl src, $at, $t11" */
+
+ newtok[0] = tok[0];
+ set_tok_reg (newtok[1], AXP_REG_AT);
+ set_tok_reg (newtok[2], AXP_REG_T11);
+ assemble_tokens (insXl_op[lgsize], newtok, 3, 1);
+
+ /* emit "insXh src, $at, $t12" */
+
+ set_tok_reg (newtok[2], AXP_REG_T12);
+ assemble_tokens (insXh_op[lgsize], newtok, 3, 1);
+
+ /* emit "mskXl $t9, $at, $t9" */
+
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ newtok[2] = newtok[0];
+ assemble_tokens (mskXl_op[lgsize], newtok, 3, 1);
+
+ /* emit "mskXh $t10, $at, $t10" */
+
+ set_tok_reg (newtok[0], AXP_REG_T10);
+ newtok[2] = newtok[0];
+ assemble_tokens (mskXh_op[lgsize], newtok, 3, 1);
+
+ /* emit "or $t9, $t11, $t9" */
+
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ set_tok_reg (newtok[1], AXP_REG_T11);
+ newtok[2] = newtok[0];
+ assemble_tokens ("or", newtok, 3, 1);
+
+ /* emit "or $t10, $t12, $t10" */
+
+ set_tok_reg (newtok[0], AXP_REG_T10);
+ set_tok_reg (newtok[1], AXP_REG_T12);
+ newtok[2] = newtok[0];
+ assemble_tokens ("or", newtok, 3, 1);
+
+ /* emit "stq_u $t9, 0($at)" */
+
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ set_tok_const (newtok[1], 0);
+ set_tok_preg (newtok[2], AXP_REG_AT);
+ assemble_tokens ("stq_u", newtok, 3, 1);
+
+ /* emit "stq_u $t10, size-1($at)" */
+
+ set_tok_reg (newtok[0], AXP_REG_T10);
+ set_tok_const (newtok[1], (1 << lgsize)-1);
+ assemble_tokens ("stq_u", newtok, 3, 1);
+}
+
+/* Sign extend a half-word or byte. The 32-bit sign extend is
+ implemented as "addl $31, $r, $t" in the opcode table. */
+
+static void
+emit_sextX (tok, ntok, vlgsize)
+ const expressionS *tok;
+ int ntok;
+ const PTR vlgsize;
+{
+ long lgsize = (long)vlgsize;
+
+ if (alpha_target & AXP_OPCODE_BWX)
+ assemble_tokens (sextX_op[lgsize], tok, ntok, 0);
+ else
+ {
+ int bitshift = 64 - 8 * (1 << lgsize);
+ expressionS newtok[3];
+
+ /* emit "sll src,bits,dst" */
+
+ newtok[0] = tok[0];
+ set_tok_const (newtok[1], bitshift);
+ newtok[2] = tok[ntok - 1];
+ assemble_tokens ("sll", newtok, 3, 1);
+
+ /* emit "sra dst,bits,dst" */
+
+ newtok[0] = newtok[2];
+ assemble_tokens ("sra", newtok, 3, 1);
+ }
+}
+
+/* Implement the division and modulus macros. */
+
+#ifdef OBJ_EVAX
+
+/* Make register usage like in normal procedure call.
+ Don't clobber PV and RA. */
+
+static void
+emit_division (tok, ntok, symname)
+ const expressionS *tok;
+ int ntok;
+ const PTR symname;
+{
+ /* DIVISION and MODULUS. Yech.
+ *
+ * Convert
+ * OP x,y,result
+ * to
+ * mov x,R16 # if x != R16
+ * mov y,R17 # if y != R17
+ * lda AT,__OP
+ * jsr AT,(AT),0
+ * mov R0,result
+ *
+ * with appropriate optimizations if R0,R16,R17 are the registers
+ * specified by the compiler.
+ */
+
+ int xr, yr, rr;
+ symbolS *sym;
+ expressionS newtok[3];
+
+ xr = regno (tok[0].X_add_number);
+ yr = regno (tok[1].X_add_number);
+
+ if (ntok < 3)
+ rr = xr;
+ else
+ rr = regno (tok[2].X_add_number);
+
+ /* Move the operands into the right place */
+ if (yr == AXP_REG_R16 && xr == AXP_REG_R17)
+ {
+ /* They are in exactly the wrong order -- swap through AT */
+
+ if (alpha_noat_on)
+ as_bad (_("macro requires $at register while noat in effect"));
+
+ set_tok_reg (newtok[0], AXP_REG_R16);
+ set_tok_reg (newtok[1], AXP_REG_AT);
+ assemble_tokens ("mov", newtok, 2, 1);
+
+ set_tok_reg (newtok[0], AXP_REG_R17);
+ set_tok_reg (newtok[1], AXP_REG_R16);
+ assemble_tokens ("mov", newtok, 2, 1);
+
+ set_tok_reg (newtok[0], AXP_REG_AT);
+ set_tok_reg (newtok[1], AXP_REG_R17);
+ assemble_tokens ("mov", newtok, 2, 1);
+ }
+ else
+ {
+ if (yr == AXP_REG_R16)
+ {
+ set_tok_reg (newtok[0], AXP_REG_R16);
+ set_tok_reg (newtok[1], AXP_REG_R17);
+ assemble_tokens ("mov", newtok, 2, 1);
+ }
+
+ if (xr != AXP_REG_R16)
+ {
+ set_tok_reg (newtok[0], xr);
+ set_tok_reg (newtok[1], AXP_REG_R16);
+ assemble_tokens ("mov", newtok, 2, 1);
+ }
+
+ if (yr != AXP_REG_R16 && yr != AXP_REG_R17)
+ {
+ set_tok_reg (newtok[0], yr);
+ set_tok_reg (newtok[1], AXP_REG_R17);
+ assemble_tokens ("mov", newtok, 2, 1);
+ }
+ }
+
+ sym = symbol_find_or_make ((const char *)symname);
+
+ set_tok_reg (newtok[0], AXP_REG_AT);
+ set_tok_sym (newtok[1], sym, 0);
+ assemble_tokens ("lda", newtok, 2, 1);
+
+ /* Call the division routine */
+ set_tok_reg (newtok[0], AXP_REG_AT);
+ set_tok_cpreg (newtok[1], AXP_REG_AT);
+ set_tok_const (newtok[2], 0);
+ assemble_tokens ("jsr", newtok, 3, 1);
+
+ /* Move the result to the right place */
+ if (rr != AXP_REG_R0)
+ {
+ set_tok_reg (newtok[0], AXP_REG_R0);
+ set_tok_reg (newtok[1], rr);
+ assemble_tokens ("mov", newtok, 2, 1);
+ }
+}
+
+#else /* !OBJ_EVAX */
+
+static void
+emit_division (tok, ntok, symname)
+ const expressionS *tok;
+ int ntok;
+ const PTR symname;
+{
+ /* DIVISION and MODULUS. Yech.
+ * Convert
+ * OP x,y,result
+ * to
+ * lda pv,__OP
+ * mov x,t10
+ * mov y,t11
+ * jsr t9,(pv),__OP
+ * mov t12,result
+ *
+ * with appropriate optimizations if t10,t11,t12 are the registers
+ * specified by the compiler.
+ */
+
+ int xr, yr, rr;
+ symbolS *sym;
+ expressionS newtok[3];
+
+ xr = regno (tok[0].X_add_number);
+ yr = regno (tok[1].X_add_number);
+
+ if (ntok < 3)
+ rr = xr;
+ else
+ rr = regno (tok[2].X_add_number);
+
+ sym = symbol_find_or_make ((const char *)symname);
+
+ /* Move the operands into the right place */
+ if (yr == AXP_REG_T10 && xr == AXP_REG_T11)
+ {
+ /* They are in exactly the wrong order -- swap through AT */
+
+ if (alpha_noat_on)
+ as_bad (_("macro requires $at register while noat in effect"));
+
+ set_tok_reg (newtok[0], AXP_REG_T10);
+ set_tok_reg (newtok[1], AXP_REG_AT);
+ assemble_tokens ("mov", newtok, 2, 1);
+
+ set_tok_reg (newtok[0], AXP_REG_T11);
+ set_tok_reg (newtok[1], AXP_REG_T10);
+ assemble_tokens ("mov", newtok, 2, 1);
+
+ set_tok_reg (newtok[0], AXP_REG_AT);
+ set_tok_reg (newtok[1], AXP_REG_T11);
+ assemble_tokens ("mov", newtok, 2, 1);
+ }
+ else
+ {
+ if (yr == AXP_REG_T10)
+ {
+ set_tok_reg (newtok[0], AXP_REG_T10);
+ set_tok_reg (newtok[1], AXP_REG_T11);
+ assemble_tokens ("mov", newtok, 2, 1);
+ }
+
+ if (xr != AXP_REG_T10)
+ {
+ set_tok_reg (newtok[0], xr);
+ set_tok_reg (newtok[1], AXP_REG_T10);
+ assemble_tokens ("mov", newtok, 2, 1);
+ }
+
+ if (yr != AXP_REG_T10 && yr != AXP_REG_T11)
+ {
+ set_tok_reg (newtok[0], yr);
+ set_tok_reg (newtok[1], AXP_REG_T11);
+ assemble_tokens ("mov", newtok, 2, 1);
+ }
+ }
+
+ /* Call the division routine */
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ set_tok_sym (newtok[1], sym, 0);
+ assemble_tokens ("jsr", newtok, 2, 1);
+
+ /* Reload the GP register */
+#ifdef OBJ_AOUT
+FIXME
+#endif
+#if defined(OBJ_ECOFF) || defined(OBJ_ELF)
+ set_tok_reg (newtok[0], alpha_gp_register);
+ set_tok_const (newtok[1], 0);
+ set_tok_preg (newtok[2], AXP_REG_T9);
+ assemble_tokens ("ldgp", newtok, 3, 1);
+#endif
+
+ /* Move the result to the right place */
+ if (rr != AXP_REG_T12)
+ {
+ set_tok_reg (newtok[0], AXP_REG_T12);
+ set_tok_reg (newtok[1], rr);
+ assemble_tokens ("mov", newtok, 2, 1);
+ }
+}
+
+#endif /* !OBJ_EVAX */
+
+/* The jsr and jmp macros differ from their instruction counterparts
+ in that they can load the target address and default most
+ everything. */
+
+static void
+emit_jsrjmp (tok, ntok, vopname)
+ const expressionS *tok;
+ int ntok;
+ const PTR vopname;
+{
+ const char *opname = (const char *) vopname;
+ struct alpha_insn insn;
+ expressionS newtok[3];
+ int r, tokidx = 0, lituse = 0;
+
+ if (tokidx < ntok && tok[tokidx].X_op == O_register)
+ r = regno (tok[tokidx++].X_add_number);
+ else
+ r = strcmp (opname, "jmp") == 0 ? AXP_REG_ZERO : AXP_REG_RA;
+
+ set_tok_reg (newtok[0], r);
+
+ if (tokidx < ntok &&
+ (tok[tokidx].X_op == O_pregister || tok[tokidx].X_op == O_cpregister))
+ r = regno (tok[tokidx++].X_add_number);
+#ifdef OBJ_EVAX
+ /* keep register if jsr $n.<sym> */
+#else
+ else
+ {
+ int basereg = alpha_gp_register;
+ lituse = load_expression (r = AXP_REG_PV, &tok[tokidx], &basereg, NULL);
+ }
+#endif
+
+ set_tok_cpreg (newtok[1], r);
+
+#ifdef OBJ_EVAX
+ /* FIXME: Add hint relocs to BFD for evax. */
+#else
+ if (tokidx < ntok)
+ newtok[2] = tok[tokidx];
+ else
+#endif
+ set_tok_const (newtok[2], 0);
+
+ assemble_tokens_to_insn (opname, newtok, 3, &insn);
+
+ /* add the LITUSE fixup */
+ if (lituse)
+ {
+ assert (insn.nfixups < MAX_INSN_FIXUPS);
+ if (insn.nfixups > 0)
+ {
+ memmove (&insn.fixups[1], &insn.fixups[0],
+ sizeof(struct alpha_fixup) * insn.nfixups);
+ }
+ insn.nfixups++;
+ insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITUSE;
+ insn.fixups[0].exp.X_op = O_constant;
+ insn.fixups[0].exp.X_add_number = 3;
+ }
+
+ emit_insn (&insn);
+}
+
+/* The ret and jcr instructions differ from their instruction
+ counterparts in that everything can be defaulted. */
+
+static void
+emit_retjcr (tok, ntok, vopname)
+ const expressionS *tok;
+ int ntok;
+ const PTR vopname;
+{
+ const char *opname = (const char *)vopname;
+ expressionS newtok[3];
+ int r, tokidx = 0;
+
+ if (tokidx < ntok && tok[tokidx].X_op == O_register)
+ r = regno (tok[tokidx++].X_add_number);
+ else
+ r = AXP_REG_ZERO;
+
+ set_tok_reg (newtok[0], r);
+
+ if (tokidx < ntok &&
+ (tok[tokidx].X_op == O_pregister || tok[tokidx].X_op == O_cpregister))
+ r = regno (tok[tokidx++].X_add_number);
+ else
+ r = AXP_REG_RA;
+
+ set_tok_cpreg (newtok[1], r);
+
+ if (tokidx < ntok)
+ newtok[2] = tok[tokidx];
+ else
+ set_tok_const (newtok[2], strcmp(opname, "ret") == 0);
+
+ assemble_tokens (opname, newtok, 3, 0);
+}
+
+/* Assembler directives */
+
+/* Handle the .text pseudo-op. This is like the usual one, but it
+ clears alpha_insn_label and restores auto alignment. */
+
+static void
+s_alpha_text (i)
+ int i;
+
+{
+ s_text (i);
+ alpha_insn_label = NULL;
+ alpha_auto_align_on = 1;
+ alpha_current_align = 0;
+}
+
+/* Handle the .data pseudo-op. This is like the usual one, but it
+ clears alpha_insn_label and restores auto alignment. */
+
+static void
+s_alpha_data (i)
+ int i;
+{
+ s_data (i);
+ alpha_insn_label = NULL;
+ alpha_auto_align_on = 1;
+ alpha_current_align = 0;
+}
+
+#if defined (OBJ_ECOFF) || defined (OBJ_EVAX)
+
+/* Handle the OSF/1 and openVMS .comm pseudo quirks.
+ openVMS constructs a section for every common symbol. */
+
+static void
+s_alpha_comm (ignore)
+ int ignore;
+{
+ register char *name;
+ register char c;
+ register char *p;
+ offsetT temp;
+ register symbolS *symbolP;
+
+#ifdef OBJ_EVAX
+ segT current_section = now_seg;
+ int current_subsec = now_subseg;
+ segT new_seg;
+#endif
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+
+ /* just after name is now '\0' */
+ p = input_line_pointer;
+ *p = c;
+
+ SKIP_WHITESPACE ();
+
+ /* Alpha OSF/1 compiler doesn't provide the comma, gcc does. */
+ if (*input_line_pointer == ',')
+ {
+ input_line_pointer++;
+ SKIP_WHITESPACE ();
+ }
+ if ((temp = get_absolute_expression ()) < 0)
+ {
+ as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) temp);
+ ignore_rest_of_line ();
+ return;
+ }
+
+ *p = 0;
+ symbolP = symbol_find_or_make (name);
+
+#ifdef OBJ_EVAX
+ /* Make a section for the common symbol. */
+ new_seg = subseg_new (xstrdup (name), 0);
+#endif
+
+ *p = c;
+
+#ifdef OBJ_EVAX
+ /* alignment might follow */
+ if (*input_line_pointer == ',')
+ {
+ offsetT align;
+
+ input_line_pointer++;
+ align = get_absolute_expression ();
+ bfd_set_section_alignment (stdoutput, new_seg, align);
+ }
+#endif
+
+ if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
+ {
+ as_bad (_("Ignoring attempt to re-define symbol"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+#ifdef OBJ_EVAX
+ if (bfd_section_size (stdoutput, new_seg) > 0)
+ {
+ if (bfd_section_size (stdoutput, new_seg) != temp)
+ as_bad (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."),
+ S_GET_NAME (symbolP),
+ (long) bfd_section_size (stdoutput, new_seg),
+ (long) temp);
+ }
+#else
+ if (S_GET_VALUE (symbolP))
+ {
+ if (S_GET_VALUE (symbolP) != (valueT) temp)
+ as_bad (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."),
+ S_GET_NAME (symbolP),
+ (long) S_GET_VALUE (symbolP),
+ (long) temp);
+ }
+#endif
+ else
+ {
+#ifdef OBJ_EVAX
+ subseg_set (new_seg, 0);
+ p = frag_more (temp);
+ new_seg->flags |= SEC_IS_COMMON;
+ if (! S_IS_DEFINED (symbolP))
+ symbolP->bsym->section = new_seg;
+#else
+ S_SET_VALUE (symbolP, (valueT) temp);
+#endif
+ S_SET_EXTERNAL (symbolP);
+ }
+
+#ifdef OBJ_EVAX
+ subseg_set (current_section, current_subsec);
+#endif
+
+ know (symbolP->sy_frag == &zero_address_frag);
+
+ demand_empty_rest_of_line ();
+}
+
+#endif /* ! OBJ_ELF */
+
+#ifdef OBJ_ECOFF
+
+/* Handle the .rdata pseudo-op. This is like the usual one, but it
+ clears alpha_insn_label and restores auto alignment. */
+
+static void
+s_alpha_rdata (ignore)
+ int ignore;
+{
+ int temp;
+
+ temp = get_absolute_expression ();
+ subseg_new (".rdata", 0);
+ demand_empty_rest_of_line ();
+ alpha_insn_label = NULL;
+ alpha_auto_align_on = 1;
+ alpha_current_align = 0;
+}
+
+#endif
+
+#ifdef OBJ_ECOFF
+
+/* Handle the .sdata pseudo-op. This is like the usual one, but it
+ clears alpha_insn_label and restores auto alignment. */
+
+static void
+s_alpha_sdata (ignore)
+ int ignore;
+{
+ int temp;
+
+ temp = get_absolute_expression ();
+ subseg_new (".sdata", 0);
+ demand_empty_rest_of_line ();
+ alpha_insn_label = NULL;
+ alpha_auto_align_on = 1;
+ alpha_current_align = 0;
+}
+#endif
+
+#ifdef OBJ_ELF
+
+/* Handle the .section pseudo-op. This is like the usual one, but it
+ clears alpha_insn_label and restores auto alignment. */
+
+static void
+s_alpha_section (ignore)
+ int ignore;
+{
+ obj_elf_section (ignore);
+
+ alpha_insn_label = NULL;
+ alpha_auto_align_on = 1;
+ alpha_current_align = 0;
+}
+
+static void
+s_alpha_ent (dummy)
+ int dummy;
+{
+ if (ECOFF_DEBUGGING)
+ ecoff_directive_ent (0);
+ else
+ {
+ char *name, name_end;
+ name = input_line_pointer;
+ name_end = get_symbol_end ();
+
+ if (! is_name_beginner (*name))
+ {
+ as_warn (_(".ent directive has no name"));
+ *input_line_pointer = name_end;
+ }
+ else
+ {
+ symbolS *sym;
+
+ if (alpha_cur_ent_sym)
+ as_warn (_("nested .ent directives"));
+
+ sym = symbol_find_or_make (name);
+ sym->bsym->flags |= BSF_FUNCTION;
+ alpha_cur_ent_sym = sym;
+
+ /* The .ent directive is sometimes followed by a number. Not sure
+ what it really means, but ignore it. */
+ *input_line_pointer = name_end;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == ',')
+ {
+ input_line_pointer++;
+ SKIP_WHITESPACE ();
+ }
+ if (isdigit (*input_line_pointer) || *input_line_pointer == '-')
+ (void) get_absolute_expression ();
+ }
+ demand_empty_rest_of_line ();
+ }
+}
+
+static void
+s_alpha_end (dummy)
+ int dummy;
+{
+ if (ECOFF_DEBUGGING)
+ ecoff_directive_end (0);
+ else
+ {
+ char *name, name_end;
+ name = input_line_pointer;
+ name_end = get_symbol_end ();
+
+ if (! is_name_beginner (*name))
+ {
+ as_warn (_(".end directive has no name"));
+ *input_line_pointer = name_end;
+ }
+ else
+ {
+ symbolS *sym;
+
+ sym = symbol_find (name);
+ if (sym != alpha_cur_ent_sym)
+ as_warn (_(".end directive names different symbol than .ent"));
+
+ /* Create an expression to calculate the size of the function. */
+ if (sym)
+ {
+ sym->sy_obj.size = (expressionS *) xmalloc (sizeof (expressionS));
+ sym->sy_obj.size->X_op = O_subtract;
+ sym->sy_obj.size->X_add_symbol
+ = symbol_new ("L0\001", now_seg, frag_now_fix (), frag_now);
+ sym->sy_obj.size->X_op_symbol = sym;
+ sym->sy_obj.size->X_add_number = 0;
+ }
+
+ alpha_cur_ent_sym = NULL;
+
+ *input_line_pointer = name_end;
+ }
+ demand_empty_rest_of_line ();
+ }
+}
+
+static void
+s_alpha_mask (fp)
+ int fp;
+{
+ if (ECOFF_DEBUGGING)
+ {
+ if (fp)
+ ecoff_directive_fmask (0);
+ else
+ ecoff_directive_mask (0);
+ }
+ else
+ discard_rest_of_line ();
+}
+
+static void
+s_alpha_frame (dummy)
+ int dummy;
+{
+ if (ECOFF_DEBUGGING)
+ ecoff_directive_frame (0);
+ else
+ discard_rest_of_line ();
+}
+
+static void
+s_alpha_prologue (ignore)
+ int ignore;
+{
+ symbolS *sym;
+ int arg;
+
+ arg = get_absolute_expression ();
+ demand_empty_rest_of_line ();
+
+ if (ECOFF_DEBUGGING)
+ sym = ecoff_get_cur_proc_sym ();
+ else
+ sym = alpha_cur_ent_sym;
+ know (sym != NULL);
+
+ switch (arg)
+ {
+ case 0: /* No PV required. */
+ S_SET_OTHER (sym, STO_ALPHA_NOPV);
+ break;
+ case 1: /* Std GP load. */
+ S_SET_OTHER (sym, STO_ALPHA_STD_GPLOAD);
+ break;
+ case 2: /* Non-std use of PV. */
+ break;
+
+ default:
+ as_bad (_("Invalid argument %d to .prologue."), arg);
+ break;
+ }
+}
+
+static void
+s_alpha_coff_wrapper (which)
+ int which;
+{
+ static void (* const fns[]) PARAMS ((int)) = {
+ ecoff_directive_begin,
+ ecoff_directive_bend,
+ ecoff_directive_def,
+ ecoff_directive_dim,
+ ecoff_directive_endef,
+ ecoff_directive_file,
+ ecoff_directive_scl,
+ ecoff_directive_tag,
+ ecoff_directive_val,
+ ecoff_directive_loc,
+ };
+
+ assert (which >= 0 && which < sizeof(fns)/sizeof(*fns));
+
+ if (ECOFF_DEBUGGING)
+ (*fns[which])(0);
+ else
+ {
+ as_bad (_("ECOFF debugging is disabled."));
+ ignore_rest_of_line ();
+ }
+}
+#endif /* OBJ_ELF */
+
+#ifdef OBJ_EVAX
+
+/* Handle the section specific pseudo-op. */
+
+static void
+s_alpha_section (secid)
+ int secid;
+{
+ int temp;
+#define EVAX_SECTION_COUNT 5
+ static char *section_name[EVAX_SECTION_COUNT+1] =
+ { "NULL", ".rdata", ".comm", ".link", ".ctors", ".dtors" };
+
+ if ((secid <= 0) || (secid > EVAX_SECTION_COUNT))
+ {
+ as_fatal (_("Unknown section directive"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+ temp = get_absolute_expression ();
+ subseg_new (section_name[secid], 0);
+ demand_empty_rest_of_line ();
+ alpha_insn_label = NULL;
+ alpha_auto_align_on = 1;
+ alpha_current_align = 0;
+}
+
+
+/* Parse .ent directives. */
+
+static void
+s_alpha_ent (ignore)
+ int ignore;
+{
+ symbolS *symbol;
+ expressionS symexpr;
+
+ alpha_evax_proc.pdsckind = 0;
+ alpha_evax_proc.framereg = -1;
+ alpha_evax_proc.framesize = 0;
+ alpha_evax_proc.rsa_offset = 0;
+ alpha_evax_proc.ra_save = AXP_REG_RA;
+ alpha_evax_proc.fp_save = -1;
+ alpha_evax_proc.imask = 0;
+ alpha_evax_proc.fmask = 0;
+ alpha_evax_proc.prologue = 0;
+ alpha_evax_proc.type = 0;
+
+ expression (&symexpr);
+
+ if (symexpr.X_op != O_symbol)
+ {
+ as_fatal (_(".ent directive has no symbol"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ symbol = make_expr_symbol (&symexpr);
+ symbol->bsym->flags |= BSF_FUNCTION;
+ alpha_evax_proc.symbol = symbol;
+
+ demand_empty_rest_of_line ();
+ return;
+}
+
+
+/* Parse .frame <framreg>,<framesize>,RA,<rsa_offset> directives. */
+
+static void
+s_alpha_frame (ignore)
+ int ignore;
+{
+ long val;
+
+ alpha_evax_proc.framereg = tc_get_register (1);
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer++ != ','
+ || get_absolute_expression_and_terminator (&val) != ',')
+ {
+ as_warn (_("Bad .frame directive 1./2. param"));
+ --input_line_pointer;
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ alpha_evax_proc.framesize = val;
+
+ (void) tc_get_register (1);
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer++ != ',')
+ {
+ as_warn (_("Bad .frame directive 3./4. param"));
+ --input_line_pointer;
+ demand_empty_rest_of_line ();
+ return;
+ }
+ alpha_evax_proc.rsa_offset = get_absolute_expression ();
+
+ return;
+}
+
+static void
+s_alpha_pdesc (ignore)
+ int ignore;
+{
+ char *name;
+ char name_end;
+ long val;
+ register char *p;
+ expressionS exp;
+ symbolS *entry_sym;
+ fixS *fixp;
+ segment_info_type *seginfo = seg_info (alpha_link_section);
+
+ if (now_seg != alpha_link_section)
+ {
+ as_bad (_(".pdesc directive not in link (.link) section"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ if ((alpha_evax_proc.symbol == 0)
+ || (!S_IS_DEFINED (alpha_evax_proc.symbol)))
+ {
+ as_fatal (_(".pdesc has no matching .ent"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ alpha_evax_proc.symbol->sy_obj = (valueT)seginfo->literal_pool_size;
+
+ expression (&exp);
+ if (exp.X_op != O_symbol)
+ {
+ as_warn (_(".pdesc directive has no entry symbol"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ entry_sym = make_expr_symbol (&exp);
+ /* Save bfd symbol of proc desc in function symbol. */
+ alpha_evax_proc.symbol->bsym->udata.p = (PTR)entry_sym->bsym;
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer++ != ',')
+ {
+ as_warn (_("No comma after .pdesc <entryname>"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ SKIP_WHITESPACE ();
+ name = input_line_pointer;
+ name_end = get_symbol_end ();
+
+ if (strncmp(name, "stack", 5) == 0)
+ {
+ alpha_evax_proc.pdsckind = PDSC_S_K_KIND_FP_STACK;
+ }
+ else if (strncmp(name, "reg", 3) == 0)
+ {
+ alpha_evax_proc.pdsckind = PDSC_S_K_KIND_FP_REGISTER;
+ }
+ else if (strncmp(name, "null", 4) == 0)
+ {
+ alpha_evax_proc.pdsckind = PDSC_S_K_KIND_NULL;
+ }
+ else
+ {
+ as_fatal (_("unknown procedure kind"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ *input_line_pointer = name_end;
+ demand_empty_rest_of_line ();
+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+ frag_align (3, 0, 0);
+ p = frag_more (16);
+ fixp = fix_new (frag_now, p - frag_now->fr_literal, 8, 0, 0, 0, 0);
+ fixp->fx_done = 1;
+ seginfo->literal_pool_size += 16;
+
+ *p = alpha_evax_proc.pdsckind
+ | ((alpha_evax_proc.framereg == 29) ? PDSC_S_M_BASE_REG_IS_FP : 0);
+ *(p+1) = PDSC_S_M_NATIVE
+ | PDSC_S_M_NO_JACKET;
+
+ switch (alpha_evax_proc.pdsckind)
+ {
+ case PDSC_S_K_KIND_NULL:
+ *(p+2) = 0;
+ *(p+3) = 0;
+ break;
+ case PDSC_S_K_KIND_FP_REGISTER:
+ *(p+2) = alpha_evax_proc.fp_save;
+ *(p+3) = alpha_evax_proc.ra_save;
+ break;
+ case PDSC_S_K_KIND_FP_STACK:
+ md_number_to_chars (p+2, (valueT)alpha_evax_proc.rsa_offset, 2);
+ break;
+ default: /* impossible */
+ break;
+ }
+
+ *(p+4) = 0;
+ *(p+5) = alpha_evax_proc.type & 0x0f;
+
+ /* Signature offset. */
+ md_number_to_chars (p+6, (valueT)0, 2);
+
+ fix_new_exp (frag_now, p-frag_now->fr_literal+8, 8, &exp, 0, BFD_RELOC_64);
+
+ if (alpha_evax_proc.pdsckind == PDSC_S_K_KIND_NULL)
+ return;
+
+ /* Add dummy fix to make add_to_link_pool work. */
+ p = frag_more (8);
+ fixp = fix_new (frag_now, p - frag_now->fr_literal, 8, 0, 0, 0, 0);
+ fixp->fx_done = 1;
+ seginfo->literal_pool_size += 8;
+
+ /* pdesc+16: Size. */
+ md_number_to_chars (p, (valueT)alpha_evax_proc.framesize, 4);
+
+ md_number_to_chars (p+4, (valueT)0, 2);
+
+ /* Entry length. */
+ md_number_to_chars (p+6, alpha_evax_proc.prologue, 2);
+
+ if (alpha_evax_proc.pdsckind == PDSC_S_K_KIND_FP_REGISTER)
+ return;
+
+ /* Add dummy fix to make add_to_link_pool work. */
+ p = frag_more (8);
+ fixp = fix_new (frag_now, p - frag_now->fr_literal, 8, 0, 0, 0, 0);
+ fixp->fx_done = 1;
+ seginfo->literal_pool_size += 8;
+
+ /* pdesc+24: register masks. */
+
+ md_number_to_chars (p, alpha_evax_proc.imask, 4);
+ md_number_to_chars (p+4, alpha_evax_proc.fmask, 4);
+
+ return;
+}
+
+
+/* Support for crash debug on vms. */
+
+static void
+s_alpha_name (ignore)
+ int ignore;
+{
+ register char *p;
+ expressionS exp;
+ segment_info_type *seginfo = seg_info (alpha_link_section);
+
+ if (now_seg != alpha_link_section)
+ {
+ as_bad (_(".name directive not in link (.link) section"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ expression (&exp);
+ if (exp.X_op != O_symbol)
+ {
+ as_warn (_(".name directive has no symbol"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ demand_empty_rest_of_line ();
+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+ frag_align (3, 0, 0);
+ p = frag_more (8);
+ seginfo->literal_pool_size += 8;
+
+ fix_new_exp (frag_now, p-frag_now->fr_literal, 8, &exp, 0, BFD_RELOC_64);
+
+ return;
+}
+
+
+static void
+s_alpha_linkage (ignore)
+ int ignore;
+{
+ expressionS exp;
+ char *p;
+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+ expression (&exp);
+ if (exp.X_op != O_symbol)
+ {
+ as_fatal (_("No symbol after .linkage"));
+ }
+ else
+ {
+ p = frag_more (LKP_S_K_SIZE);
+ memset (p, 0, LKP_S_K_SIZE);
+ fix_new_exp (frag_now, p - frag_now->fr_literal, LKP_S_K_SIZE, &exp, 0,\
+ BFD_RELOC_ALPHA_LINKAGE);
+ }
+ demand_empty_rest_of_line ();
+
+ return;
+}
+
+
+static void
+s_alpha_code_address (ignore)
+ int ignore;
+{
+ expressionS exp;
+ char *p;
+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+ expression (&exp);
+ if (exp.X_op != O_symbol)
+ {
+ as_fatal (_("No symbol after .code_address"));
+ }
+ else
+ {
+ p = frag_more (8);
+ memset (p, 0, 8);
+ fix_new_exp (frag_now, p - frag_now->fr_literal, 8, &exp, 0,\
+ BFD_RELOC_ALPHA_CODEADDR);
+ }
+ demand_empty_rest_of_line ();
+
+ return;
+}
+
+
+static void
+s_alpha_fp_save (ignore)
+ int ignore;
+{
+
+ alpha_evax_proc.fp_save = tc_get_register (1);
+
+ demand_empty_rest_of_line ();
+ return;
+}
+
+
+static void
+s_alpha_mask (ignore)
+ int ignore;
+{
+ long val;
+
+ if (get_absolute_expression_and_terminator (&val) != ',')
+ {
+ as_warn (_("Bad .mask directive"));
+ --input_line_pointer;
+ }
+ else
+ {
+ alpha_evax_proc.imask = val;
+ (void)get_absolute_expression ();
+ }
+ demand_empty_rest_of_line ();
+
+ return;
+}
+
+
+static void
+s_alpha_fmask (ignore)
+ int ignore;
+{
+ long val;
+
+ if (get_absolute_expression_and_terminator (&val) != ',')
+ {
+ as_warn (_("Bad .fmask directive"));
+ --input_line_pointer;
+ }
+ else
+ {
+ alpha_evax_proc.fmask = val;
+ (void) get_absolute_expression ();
+ }
+ demand_empty_rest_of_line ();
+
+ return;
+}
+
+static void
+s_alpha_end (ignore)
+ int ignore;
+{
+ char c;
+
+ c = get_symbol_end ();
+ *input_line_pointer = c;
+ demand_empty_rest_of_line ();
+ alpha_evax_proc.symbol = 0;
+
+ return;
+}
+
+
+static void
+s_alpha_file (ignore)
+ int ignore;
+{
+ symbolS *s;
+ int length;
+ static char case_hack[32];
+
+ extern char *demand_copy_string PARAMS ((int *lenP));
+
+ sprintf (case_hack, "<CASE:%01d%01d>",
+ alpha_flag_hash_long_names, alpha_flag_show_after_trunc);
+
+ s = symbol_find_or_make (case_hack);
+ s->bsym->flags |= BSF_FILE;
+
+ get_absolute_expression ();
+ s = symbol_find_or_make (demand_copy_string (&length));
+ s->bsym->flags |= BSF_FILE;
+ demand_empty_rest_of_line ();
+
+ return;
+}
+#endif /* OBJ_EVAX */
+
+/* Handle the .gprel32 pseudo op. */
+
+static void
+s_alpha_gprel32 (ignore)
+ int ignore;
+{
+ expressionS e;
+ char *p;
+
+ SKIP_WHITESPACE ();
+ expression (&e);
+
+#ifdef OBJ_ELF
+ switch (e.X_op)
+ {
+ case O_constant:
+ e.X_add_symbol = section_symbol(absolute_section);
+ e.X_op = O_symbol;
+ /* FALLTHRU */
+ case O_symbol:
+ break;
+ default:
+ abort();
+ }
+#else
+#ifdef OBJ_ECOFF
+ switch (e.X_op)
+ {
+ case O_constant:
+ e.X_add_symbol = section_symbol (absolute_section);
+ /* fall through */
+ case O_symbol:
+ e.X_op = O_subtract;
+ e.X_op_symbol = alpha_gp_symbol;
+ break;
+ default:
+ abort ();
+ }
+#endif
+#endif
+
+ if (alpha_auto_align_on && alpha_current_align < 2)
+ alpha_align (2, (char *) NULL, alpha_insn_label, 0);
+ if (alpha_current_align > 2)
+ alpha_current_align = 2;
+ alpha_insn_label = NULL;
+
+ p = frag_more (4);
+ memset (p, 0, 4);
+ fix_new_exp (frag_now, p-frag_now->fr_literal, 4,
+ &e, 0, BFD_RELOC_GPREL32);
+}
+
+/* Handle floating point allocation pseudo-ops. This is like the
+ generic vresion, but it makes sure the current label, if any, is
+ correctly aligned. */
+
+static void
+s_alpha_float_cons (type)
+ int type;
+{
+ int log_size;
+
+ switch (type)
+ {
+ default:
+ case 'f':
+ case 'F':
+ log_size = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'G':
+ log_size = 3;
+ break;
+
+ case 'x':
+ case 'X':
+ case 'p':
+ case 'P':
+ log_size = 4;
+ break;
+ }
+
+ if (alpha_auto_align_on && alpha_current_align < log_size)
+ alpha_align (log_size, (char *) NULL, alpha_insn_label, 0);
+ if (alpha_current_align > log_size)
+ alpha_current_align = log_size;
+ alpha_insn_label = NULL;
+
+ float_cons (type);
+}
+
+/* Handle the .proc pseudo op. We don't really do much with it except
+ parse it. */
+
+static void
+s_alpha_proc (is_static)
+ int is_static;
+{
+ char *name;
+ char c;
+ char *p;
+ symbolS *symbolP;
+ int temp;
+
+ /* Takes ".proc name,nargs" */
+ SKIP_WHITESPACE ();
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ p = input_line_pointer;
+ symbolP = symbol_find_or_make (name);
+ *p = c;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
+ {
+ *p = 0;
+ as_warn (_("Expected comma after name \"%s\""), name);
+ *p = c;
+ temp = 0;
+ ignore_rest_of_line ();
+ }
+ else
+ {
+ input_line_pointer++;
+ temp = get_absolute_expression ();
+ }
+ /* symbolP->sy_other = (signed char) temp; */
+ as_warn (_("unhandled: .proc %s,%d"), name, temp);
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the .set pseudo op. This is used to turn on and off most of
+ the assembler features. */
+
+static void
+s_alpha_set (x)
+ int x;
+{
+ char *name, ch, *s;
+ int yesno = 1;
+
+ SKIP_WHITESPACE ();
+ name = input_line_pointer;
+ ch = get_symbol_end ();
+
+ s = name;
+ if (s[0] == 'n' && s[1] == 'o')
+ {
+ yesno = 0;
+ s += 2;
+ }
+ if (!strcmp ("reorder", s))
+ /* ignore */ ;
+ else if (!strcmp ("at", s))
+ alpha_noat_on = !yesno;
+ else if (!strcmp ("macro", s))
+ alpha_macros_on = yesno;
+ else if (!strcmp ("move", s))
+ /* ignore */ ;
+ else if (!strcmp ("volatile", s))
+ /* ignore */ ;
+ else
+ as_warn (_("Tried to .set unrecognized mode `%s'"), name);
+
+ *input_line_pointer = ch;
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the .base pseudo op. This changes the assembler's notion of
+ the $gp register. */
+
+static void
+s_alpha_base (ignore)
+ int ignore;
+{
+#if 0
+ if (first_32bit_quadrant)
+ {
+ /* not fatal, but it might not work in the end */
+ as_warn (_("File overrides no-base-register option."));
+ first_32bit_quadrant = 0;
+ }
+#endif
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '$')
+ { /* $rNN form */
+ input_line_pointer++;
+ if (*input_line_pointer == 'r')
+ input_line_pointer++;
+ }
+
+ alpha_gp_register = get_absolute_expression ();
+ if (alpha_gp_register < 0 || alpha_gp_register > 31)
+ {
+ alpha_gp_register = AXP_REG_GP;
+ as_warn (_("Bad base register, using $%d."), alpha_gp_register);
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the .align pseudo-op. This aligns to a power of two. It
+ also adjusts any current instruction label. We treat this the same
+ way the MIPS port does: .align 0 turns off auto alignment. */
+
+static void
+s_alpha_align (ignore)
+ int ignore;
+{
+ int align;
+ char fill, *pfill;
+ long max_alignment = 15;
+
+ align = get_absolute_expression ();
+ if (align > max_alignment)
+ {
+ align = max_alignment;
+ as_bad (_("Alignment too large: %d. assumed"), align);
+ }
+ else if (align < 0)
+ {
+ as_warn (_("Alignment negative: 0 assumed"));
+ align = 0;
+ }
+
+ if (*input_line_pointer == ',')
+ {
+ input_line_pointer++;
+ fill = get_absolute_expression ();
+ pfill = &fill;
+ }
+ else
+ pfill = NULL;
+
+ if (align != 0)
+ {
+ alpha_auto_align_on = 1;
+ alpha_align (align, pfill, alpha_insn_label, 1);
+ }
+ else
+ {
+ alpha_auto_align_on = 0;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* Hook the normal string processor to reset known alignment. */
+
+static void
+s_alpha_stringer (terminate)
+ int terminate;
+{
+ alpha_current_align = 0;
+ alpha_insn_label = NULL;
+ stringer (terminate);
+}
+
+/* Hook the normal space processing to reset known alignment. */
+
+static void
+s_alpha_space (ignore)
+ int ignore;
+{
+ alpha_current_align = 0;
+ alpha_insn_label = NULL;
+ s_space (ignore);
+}
+
+/* Hook into cons for auto-alignment. */
+
+void
+alpha_cons_align (size)
+ int size;
+{
+ int log_size;
+
+ log_size = 0;
+ while ((size >>= 1) != 0)
+ ++log_size;
+
+ if (alpha_auto_align_on && alpha_current_align < log_size)
+ alpha_align (log_size, (char *) NULL, alpha_insn_label, 0);
+ if (alpha_current_align > log_size)
+ alpha_current_align = log_size;
+ alpha_insn_label = NULL;
+}
+
+/* Here come the .uword, .ulong, and .uquad explicitly unaligned
+ pseudos. We just turn off auto-alignment and call down to cons. */
+
+static void
+s_alpha_ucons (bytes)
+ int bytes;
+{
+ int hold = alpha_auto_align_on;
+ alpha_auto_align_on = 0;
+ cons (bytes);
+ alpha_auto_align_on = hold;
+}
+
+/* Switch the working cpu type. */
+
+static void
+s_alpha_arch (ignored)
+ int ignored;
+{
+ char *name, ch;
+ const struct cpu_type *p;
+
+ SKIP_WHITESPACE ();
+ name = input_line_pointer;
+ ch = get_symbol_end ();
+
+ for (p = cpu_types; p->name; ++p)
+ if (strcmp(name, p->name) == 0)
+ {
+ alpha_target_name = p->name, alpha_target = p->flags;
+ goto found;
+ }
+ as_warn("Unknown CPU identifier `%s'", name);
+
+found:
+ *input_line_pointer = ch;
+ demand_empty_rest_of_line ();
+}
+
+
+
+#ifdef DEBUG1
+/* print token expression with alpha specific extension. */
+
+static void
+alpha_print_token(f, exp)
+ FILE *f;
+ const expressionS *exp;
+{
+ switch (exp->X_op)
+ {
+ case O_cpregister:
+ putc (',', f);
+ /* FALLTHRU */
+ case O_pregister:
+ putc ('(', f);
+ {
+ expressionS nexp = *exp;
+ nexp.X_op = O_register;
+ print_expr (f, &nexp);
+ }
+ putc (')', f);
+ break;
+ default:
+ print_expr (f, exp);
+ break;
+ }
+ return;
+}
+#endif
+
+/* The target specific pseudo-ops which we support. */
+
+const pseudo_typeS md_pseudo_table[] =
+{
+#ifdef OBJ_ECOFF
+ {"comm", s_alpha_comm, 0}, /* osf1 compiler does this */
+ {"rdata", s_alpha_rdata, 0},
+#endif
+ {"text", s_alpha_text, 0},
+ {"data", s_alpha_data, 0},
+#ifdef OBJ_ECOFF
+ {"sdata", s_alpha_sdata, 0},
+#endif
+#ifdef OBJ_ELF
+ {"section", s_alpha_section, 0},
+ {"section.s", s_alpha_section, 0},
+ {"sect", s_alpha_section, 0},
+ {"sect.s", s_alpha_section, 0},
+#endif
+#ifdef OBJ_EVAX
+ { "pdesc", s_alpha_pdesc, 0},
+ { "name", s_alpha_name, 0},
+ { "linkage", s_alpha_linkage, 0},
+ { "code_address", s_alpha_code_address, 0},
+ { "ent", s_alpha_ent, 0},
+ { "frame", s_alpha_frame, 0},
+ { "fp_save", s_alpha_fp_save, 0},
+ { "mask", s_alpha_mask, 0},
+ { "fmask", s_alpha_fmask, 0},
+ { "end", s_alpha_end, 0},
+ { "file", s_alpha_file, 0},
+ { "rdata", s_alpha_section, 1},
+ { "comm", s_alpha_comm, 0},
+ { "link", s_alpha_section, 3},
+ { "ctors", s_alpha_section, 4},
+ { "dtors", s_alpha_section, 5},
+#endif
+#ifdef OBJ_ELF
+ /* Frame related pseudos. */
+ {"ent", s_alpha_ent, 0},
+ {"end", s_alpha_end, 0},
+ {"mask", s_alpha_mask, 0},
+ {"fmask", s_alpha_mask, 1},
+ {"frame", s_alpha_frame, 0},
+ {"prologue", s_alpha_prologue, 0},
+ /* COFF debugging related pseudos. */
+ {"begin", s_alpha_coff_wrapper, 0},
+ {"bend", s_alpha_coff_wrapper, 1},
+ {"def", s_alpha_coff_wrapper, 2},
+ {"dim", s_alpha_coff_wrapper, 3},
+ {"endef", s_alpha_coff_wrapper, 4},
+ {"file", s_alpha_coff_wrapper, 5},
+ {"scl", s_alpha_coff_wrapper, 6},
+ {"tag", s_alpha_coff_wrapper, 7},
+ {"val", s_alpha_coff_wrapper, 8},
+ {"loc", s_alpha_coff_wrapper, 9},
+#else
+ {"prologue", s_ignore, 0},
+#endif
+ {"gprel32", s_alpha_gprel32, 0},
+ {"t_floating", s_alpha_float_cons, 'd'},
+ {"s_floating", s_alpha_float_cons, 'f'},
+ {"f_floating", s_alpha_float_cons, 'F'},
+ {"g_floating", s_alpha_float_cons, 'G'},
+ {"d_floating", s_alpha_float_cons, 'D'},
+
+ {"proc", s_alpha_proc, 0},
+ {"aproc", s_alpha_proc, 1},
+ {"set", s_alpha_set, 0},
+ {"reguse", s_ignore, 0},
+ {"livereg", s_ignore, 0},
+ {"base", s_alpha_base, 0}, /*??*/
+ {"option", s_ignore, 0},
+ {"aent", s_ignore, 0},
+ {"ugen", s_ignore, 0},
+ {"eflag", s_ignore, 0},
+
+ {"align", s_alpha_align, 0},
+ {"double", s_alpha_float_cons, 'd'},
+ {"float", s_alpha_float_cons, 'f'},
+ {"single", s_alpha_float_cons, 'f'},
+ {"ascii", s_alpha_stringer, 0},
+ {"asciz", s_alpha_stringer, 1},
+ {"string", s_alpha_stringer, 1},
+ {"space", s_alpha_space, 0},
+ {"skip", s_alpha_space, 0},
+ {"zero", s_alpha_space, 0},
+
+/* Unaligned data pseudos. */
+ {"uword", s_alpha_ucons, 2},
+ {"ulong", s_alpha_ucons, 4},
+ {"uquad", s_alpha_ucons, 8},
+
+#ifdef OBJ_ELF
+/* Dwarf wants these versions of unaligned. */
+ {"2byte", s_alpha_ucons, 2},
+ {"4byte", s_alpha_ucons, 4},
+ {"8byte", s_alpha_ucons, 8},
+#endif
+
+/* We don't do any optimizing, so we can safely ignore these. */
+ {"noalias", s_ignore, 0},
+ {"alias", s_ignore, 0},
+
+ {"arch", s_alpha_arch, 0},
+
+ {NULL, 0, 0},
+};
+
+
+/* Build a BFD section with its flags set appropriately for the .lita,
+ .lit8, or .lit4 sections. */
+
+static void
+create_literal_section (name, secp, symp)
+ const char *name;
+ segT *secp;
+ symbolS **symp;
+{
+ segT current_section = now_seg;
+ int current_subsec = now_subseg;
+ segT new_sec;
+
+ *secp = new_sec = subseg_new (name, 0);
+ subseg_set (current_section, current_subsec);
+ bfd_set_section_alignment (stdoutput, new_sec, 4);
+ bfd_set_section_flags (stdoutput, new_sec,
+ SEC_RELOC | SEC_ALLOC | SEC_LOAD | SEC_READONLY
+ | SEC_DATA);
+
+ S_CLEAR_EXTERNAL (*symp = section_symbol (new_sec));
+}
+
+#ifdef OBJ_ECOFF
+
+/* @@@ GP selection voodoo. All of this seems overly complicated and
+ unnecessary; which is the primary reason it's for ECOFF only. */
+
+static inline void
+maybe_set_gp (sec)
+ asection *sec;
+{
+ bfd_vma vma;
+ if (!sec)
+ return;
+ vma = bfd_get_section_vma (foo, sec);
+ if (vma && vma < alpha_gp_value)
+ alpha_gp_value = vma;
+}
+
+static void
+select_gp_value ()
+{
+ assert (alpha_gp_value == 0);
+
+ /* Get minus-one in whatever width... */
+ alpha_gp_value = 0; alpha_gp_value--;
+
+ /* Select the smallest VMA of these existing sections. */
+ maybe_set_gp (alpha_lita_section);
+#if 0
+ /* These were disabled before -- should we use them? */
+ maybe_set_gp (sdata);
+ maybe_set_gp (lit8_sec);
+ maybe_set_gp (lit4_sec);
+#endif
+
+/* @@ Will a simple 0x8000 work here? If not, why not? */
+#define GP_ADJUSTMENT (0x8000 - 0x10)
+
+ alpha_gp_value += GP_ADJUSTMENT;
+
+ S_SET_VALUE (alpha_gp_symbol, alpha_gp_value);
+
+#ifdef DEBUG1
+ printf (_("Chose GP value of %lx\n"), alpha_gp_value);
+#endif
+}
+#endif /* OBJ_ECOFF */
+
+/* Called internally to handle all alignment needs. This takes care
+ of eliding calls to frag_align if'n the cached current alignment
+ says we've already got it, as well as taking care of the auto-align
+ feature wrt labels. */
+
+static void
+alpha_align (n, pfill, label, force)
+ int n;
+ char *pfill;
+ symbolS *label;
+ int force;
+{
+ if (alpha_current_align >= n)
+ return;
+
+ if (pfill == NULL)
+ {
+ if (n > 2
+ && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
+ {
+ static char const unop[4] = { 0x00, 0x00, 0xe0, 0x2f };
+ static char const nopunop[8] = {
+ 0x1f, 0x04, 0xff, 0x47,
+ 0x00, 0x00, 0xe0, 0x2f
+ };
+
+ /* First, make sure we're on a four-byte boundary, in case
+ someone has been putting .byte values into the text
+ section. The DEC assembler silently fills with unaligned
+ no-op instructions. This will zero-fill, then nop-fill
+ with proper alignment. */
+ if (alpha_current_align < 2)
+ frag_align (2, 0, 0);
+ if (alpha_current_align < 3)
+ frag_align_pattern (3, unop, sizeof unop, 0);
+ if (n > 3)
+ frag_align_pattern (n, nopunop, sizeof nopunop, 0);
+ }
+ else
+ frag_align (n, 0, 0);
+ }
+ else
+ frag_align (n, *pfill, 0);
+
+ alpha_current_align = n;
+
+ if (label != NULL)
+ {
+ assert (S_GET_SEGMENT (label) == now_seg);
+ label->sy_frag = frag_now;
+ S_SET_VALUE (label, (valueT) frag_now_fix ());
+ }
+
+ record_alignment(now_seg, n);
+
+ /* ??? if alpha_flag_relax && force && elf, record the requested alignment
+ in a reloc for the linker to see. */
+}
+
+/* The Alpha has support for some VAX floating point types, as well as for
+ IEEE floating point. We consider IEEE to be the primary floating point
+ format, and sneak in the VAX floating point support here. */
+#define md_atof vax_md_atof
+#include "config/atof-vax.c"
diff --git a/gas/config/tc-alpha.h b/gas/config/tc-alpha.h
new file mode 100644
index 0000000000..ca6903a70a
--- /dev/null
+++ b/gas/config/tc-alpha.h
@@ -0,0 +1,104 @@
+/* This file is tc-alpha.h
+ Copyright (C) 1994, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
+ Written by Ken Raeburn <raeburn@cygnus.com>.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#define TC_ALPHA
+
+#define TARGET_BYTES_BIG_ENDIAN 0
+
+#define WORKING_DOT_WORD
+
+#define TARGET_ARCH bfd_arch_alpha
+
+#define TARGET_FORMAT (OUTPUT_FLAVOR == bfd_target_ecoff_flavour \
+ ? "ecoff-littlealpha" \
+ : OUTPUT_FLAVOR == bfd_target_elf_flavour \
+ ? "elf64-alpha" \
+ : OUTPUT_FLAVOR == bfd_target_evax_flavour \
+ ? "vms-alpha" \
+ : "unknown-format")
+
+#define NEED_LITERAL_POOL
+#define TC_HANDLES_FX_DONE
+#define REPEAT_CONS_EXPRESSIONS
+
+extern int alpha_force_relocation PARAMS ((struct fix *));
+extern int alpha_fix_adjustable PARAMS ((struct fix *));
+
+extern unsigned long alpha_gprmask, alpha_fprmask;
+extern valueT alpha_gp_value;
+
+#define TC_FORCE_RELOCATION(FIXP) alpha_force_relocation (FIXP)
+#define tc_fix_adjustable(FIXP) alpha_fix_adjustable (FIXP)
+#define RELOC_REQUIRES_SYMBOL
+
+/* This expression evaluates to false if the relocation is for a local
+ object for which we still want to do the relocation at runtime.
+ True if we are willing to perform this relocation while building
+ the .o file. This is only used for pcrel relocations. */
+
+#define TC_RELOC_RTSYM_LOC_FIXUP(FIX) \
+ ((FIX)->fx_addsy == NULL \
+ || (! S_IS_EXTERNAL ((FIX)->fx_addsy) \
+ && ! S_IS_WEAK ((FIX)->fx_addsy) \
+ && S_IS_DEFINED ((FIX)->fx_addsy) \
+ && ! S_IS_COMMON ((FIX)->fx_addsy)))
+
+#define md_convert_frag(b,s,f) as_fatal ("alpha convert_frag\n")
+#define md_estimate_size_before_relax(f,s) \
+ (as_fatal("estimate_size_before_relax called"),1)
+#define md_operand(x)
+
+#ifdef OBJ_EVAX
+
+/* This field keeps the symbols position in the link section. */
+#define OBJ_SYMFIELD_TYPE valueT
+
+#define TC_CONS_FIX_NEW(FRAG,OFF,LEN,EXP) \
+ fix_new_exp (FRAG, OFF, (int)LEN, EXP, 0, \
+ LEN == 2 ? BFD_RELOC_16 \
+ : LEN == 4 ? BFD_RELOC_32 \
+ : LEN == 8 ? BFD_RELOC_64 \
+ : BFD_RELOC_ALPHA_LINKAGE);
+#endif
+
+#define md_number_to_chars number_to_chars_littleendian
+
+extern int tc_get_register PARAMS ((int frame));
+extern void alpha_frob_ecoff_data PARAMS ((void));
+
+#define tc_frob_label(sym) alpha_define_label (sym)
+extern void alpha_define_label PARAMS ((struct symbol *));
+
+#define md_cons_align(nbytes) alpha_cons_align (nbytes)
+extern void alpha_cons_align PARAMS ((int));
+
+#ifdef OBJ_ECOFF
+#define tc_frob_file_before_adjust() alpha_frob_file_before_adjust ()
+extern void alpha_frob_file_before_adjust PARAMS ((void));
+#endif
+
+#define DIFF_EXPR_OK /* foo-. gets turned into PC relative relocs */
+
+#ifdef OBJ_ELF
+#define ELF_TC_SPECIAL_SECTIONS \
+ { ".sdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_ALPHA_GPREL }, \
+ { ".sbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_ALPHA_GPREL },
+#endif
diff --git a/gas/config/tc-arc.c b/gas/config/tc-arc.c
new file mode 100644
index 0000000000..c07c2d791a
--- /dev/null
+++ b/gas/config/tc-arc.c
@@ -0,0 +1,1481 @@
+/* tc-arc.c -- Assembler for the ARC
+ Copyright (C) 1994, 1995, 1997, 1998 Free Software Foundation, Inc.
+ Contributed by Doug Evans (dje@cygnus.com).
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "as.h"
+#include "subsegs.h"
+#include "opcode/arc.h"
+#include "elf/arc.h"
+
+extern int arc_get_mach PARAMS ((char *));
+
+static arc_insn arc_insert_operand PARAMS ((arc_insn,
+ const struct arc_operand *, int,
+ const struct arc_operand_value *,
+ offsetT, char *, unsigned int));
+static void arc_common PARAMS ((int));
+static void arc_cpu PARAMS ((int));
+/*static void arc_rename PARAMS ((int));*/
+static int get_arc_exp_reloc_type PARAMS ((int, int, expressionS *,
+ expressionS *));
+
+const pseudo_typeS md_pseudo_table[] =
+{
+ { "align", s_align_bytes, 0 }, /* Defaulting is invalid (0) */
+ { "common", arc_common, 0 },
+/*{ "hword", cons, 2 }, - already exists */
+ { "word", cons, 4 },
+/*{ "xword", cons, 8 },*/
+ { "cpu", arc_cpu, 0 },
+/*{ "rename", arc_rename, 0 },*/
+ { NULL, 0, 0 },
+};
+
+/* This array holds the chars that always start a comment. If the
+ pre-processor is disabled, these aren't very useful */
+const char comment_chars[] = "#;";
+
+/* This array holds the chars that only start a comment at the beginning of
+ a line. If the line seems to have the form '# 123 filename'
+ .line and .file directives will appear in the pre-processed output */
+/* Note that input_file.c hand checks for '#' at the beginning of the
+ first line of the input file. This is because the compiler outputs
+ #NO_APP at the beginning of its output. */
+/* Also note that comments started like this one will always
+ work if '/' isn't otherwise defined. */
+const char line_comment_chars[] = "#";
+
+const char line_separator_chars[] = "";
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* As in 0f12.456 */
+/* or 0d1.2345e12 */
+const char FLT_CHARS[] = "rRsSfFdD";
+
+/* Byte order. */
+extern int target_big_endian;
+const char *arc_target_format = DEFAULT_TARGET_FORMAT;
+static int byte_order = DEFAULT_BYTE_ORDER;
+
+/* One of bfd_mach_arc_xxx. */
+static int arc_mach_type = bfd_mach_arc_base;
+
+/* Non-zero if the cpu type has been explicitly specified. */
+static int mach_type_specified_p = 0;
+
+/* Non-zero if opcode tables have been initialized.
+ A .cpu command must appear before any instructions. */
+static int cpu_tables_init_p = 0;
+
+static struct hash_control *arc_suffix_hash = NULL;
+
+const char *md_shortopts = "";
+struct option md_longopts[] =
+{
+#define OPTION_EB (OPTION_MD_BASE + 0)
+ {"EB", no_argument, NULL, OPTION_EB},
+#define OPTION_EL (OPTION_MD_BASE + 1)
+ {"EL", no_argument, NULL, OPTION_EL},
+ { NULL, no_argument, NULL, 0 }
+};
+size_t md_longopts_size = sizeof (md_longopts);
+
+/*
+ * md_parse_option
+ *
+ * Invocation line includes a switch not recognized by the base assembler.
+ * See if it's a processor-specific option.
+ */
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ switch (c)
+ {
+ case OPTION_EB:
+ byte_order = BIG_ENDIAN;
+ arc_target_format = "elf32-bigarc";
+ break;
+ case OPTION_EL:
+ byte_order = LITTLE_ENDIAN;
+ arc_target_format = "elf32-littlearc";
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+ fprintf (stream, _("\
+ARC options:\n\
+-EB generate big endian output\n\
+-EL generate little endian output\n"));
+}
+
+/* This function is called once, at assembler startup time. It should
+ set up all the tables, etc. that the MD part of the assembler will need.
+ Opcode selection is defered until later because we might see a .cpu
+ command. */
+
+void
+md_begin ()
+{
+ /* The endianness can be chosen "at the factory". */
+ target_big_endian = byte_order == BIG_ENDIAN;
+
+ if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, arc_mach_type))
+ as_warn (_("could not set architecture and machine"));
+
+ /* Assume the base cpu. This call is necessary because we need to
+ initialize `arc_operand_map' which may be needed before we see the
+ first insn. */
+ arc_opcode_init_tables (arc_get_opcode_mach (bfd_mach_arc_base,
+ target_big_endian));
+}
+
+/* Initialize the various opcode and operand tables.
+ MACH is one of bfd_mach_arc_xxx. */
+
+static void
+init_opcode_tables (mach)
+ int mach;
+{
+ register unsigned int i;
+ char *last;
+
+ if ((arc_suffix_hash = hash_new ()) == NULL)
+ as_fatal (_("virtual memory exhausted"));
+
+ if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, mach))
+ as_warn (_("could not set architecture and machine"));
+
+ /* This initializes a few things in arc-opc.c that we need.
+ This must be called before the various arc_xxx_supported fns. */
+ arc_opcode_init_tables (arc_get_opcode_mach (mach, target_big_endian));
+
+ /* Only put the first entry of each equivalently named suffix in the
+ table. */
+ last = "";
+ for (i = 0; i < arc_suffixes_count; i++)
+ {
+ if (! arc_opval_supported (&arc_suffixes[i]))
+ continue;
+ if (strcmp (arc_suffixes[i].name, last) != 0)
+ hash_insert (arc_suffix_hash, arc_suffixes[i].name, (PTR) (arc_suffixes + i));
+ last = arc_suffixes[i].name;
+ }
+
+ /* Since registers don't have a prefix, we put them in the symbol table so
+ they can't be used as symbols. This also simplifies argument parsing as
+ we can let gas parse registers for us. The recorded register number is
+ the index in `arc_reg_names'. */
+ for (i = 0; i < arc_reg_names_count; i++)
+ {
+ if (! arc_opval_supported (&arc_reg_names[i]))
+ continue;
+ /* Use symbol_create here instead of symbol_new so we don't try to
+ output registers into the object file's symbol table. */
+ symbol_table_insert (symbol_create (arc_reg_names[i].name, reg_section,
+ i, &zero_address_frag));
+ }
+
+ /* Tell `s_cpu' it's too late. */
+ cpu_tables_init_p = 1;
+}
+
+/* Insert an operand value into an instruction.
+ If REG is non-NULL, it is a register number and ignore VAL. */
+
+static arc_insn
+arc_insert_operand (insn, operand, mods, reg, val, file, line)
+ arc_insn insn;
+ const struct arc_operand *operand;
+ int mods;
+ const struct arc_operand_value *reg;
+ offsetT val;
+ char *file;
+ unsigned int line;
+{
+ if (operand->bits != 32)
+ {
+ long min, max;
+ offsetT test;
+
+ if ((operand->flags & ARC_OPERAND_SIGNED) != 0)
+ {
+ if ((operand->flags & ARC_OPERAND_SIGNOPT) != 0)
+ max = (1 << operand->bits) - 1;
+ else
+ max = (1 << (operand->bits - 1)) - 1;
+ min = - (1 << (operand->bits - 1));
+ }
+ else
+ {
+ max = (1 << operand->bits) - 1;
+ min = 0;
+ }
+
+ if ((operand->flags & ARC_OPERAND_NEGATIVE) != 0)
+ test = - val;
+ else
+ test = val;
+
+ if (test < (offsetT) min || test > (offsetT) max)
+ {
+ const char *err =
+ _("operand out of range (%s not between %ld and %ld)");
+ char buf[100];
+
+ sprint_value (buf, test);
+ if (file == (char *) NULL)
+ as_warn (err, buf, min, max);
+ else
+ as_warn_where (file, line, err, buf, min, max);
+ }
+ }
+
+ if (operand->insert)
+ {
+ const char *errmsg;
+
+ errmsg = NULL;
+ insn = (*operand->insert) (insn, operand, mods, reg, (long) val, &errmsg);
+ if (errmsg != (const char *) NULL)
+ as_warn (errmsg);
+ }
+ else
+ insn |= (((long) val & ((1 << operand->bits) - 1))
+ << operand->shift);
+
+ return insn;
+}
+
+/* We need to keep a list of fixups. We can't simply generate them as
+ we go, because that would require us to first create the frag, and
+ that would screw up references to ``.''. */
+
+struct arc_fixup
+{
+ /* index into `arc_operands' */
+ int opindex;
+ expressionS exp;
+};
+
+#define MAX_FIXUPS 5
+
+#define MAX_SUFFIXES 5
+
+/* This routine is called for each instruction to be assembled. */
+
+void
+md_assemble (str)
+ char *str;
+{
+ const struct arc_opcode *opcode;
+ char *start;
+ arc_insn insn;
+ static int init_tables_p = 0;
+
+ /* Opcode table initialization is deferred until here because we have to
+ wait for a possible .cpu command. */
+ if (!init_tables_p)
+ {
+ init_opcode_tables (arc_mach_type);
+ init_tables_p = 1;
+ }
+
+ /* Skip leading white space. */
+ while (isspace (*str))
+ str++;
+
+ /* The instructions are stored in lists hashed by the first letter (though
+ we needn't care how they're hashed). Get the first in the list. */
+
+ opcode = arc_opcode_lookup_asm (str);
+
+ /* Keep looking until we find a match. */
+
+ start = str;
+ for ( ; opcode != NULL; opcode = ARC_OPCODE_NEXT_ASM (opcode))
+ {
+ int past_opcode_p, fc, num_suffixes;
+ char *syn;
+ struct arc_fixup fixups[MAX_FIXUPS];
+ /* Used as a sanity check. If we need a limm reloc, make sure we ask
+ for an extra 4 bytes from frag_more. */
+ int limm_reloc_p;
+ const struct arc_operand_value *insn_suffixes[MAX_SUFFIXES];
+
+ /* Is this opcode supported by the selected cpu? */
+ if (! arc_opcode_supported (opcode))
+ continue;
+
+ /* Scan the syntax string. If it doesn't match, try the next one. */
+
+ arc_opcode_init_insert ();
+ insn = opcode->value;
+ fc = 0;
+ past_opcode_p = 0;
+ num_suffixes = 0;
+ limm_reloc_p = 0;
+
+ /* We don't check for (*str != '\0') here because we want to parse
+ any trailing fake arguments in the syntax string. */
+ for (str = start, syn = opcode->syntax; *syn != '\0'; )
+ {
+ int mods;
+ const struct arc_operand *operand;
+
+ /* Non operand chars must match exactly. */
+ if (*syn != '%' || *++syn == '%')
+ {
+ /* Handle '+' specially as we want to allow "ld r0,[sp-4]". */
+ /* ??? The syntax has changed to [sp,-4]. */
+ if (0 && *syn == '+' && *str == '-')
+ {
+ /* Skip over syn's +, but leave str's - alone.
+ That makes the case identical to "ld r0,[sp+-4]". */
+ ++syn;
+ }
+ else if (*str == *syn)
+ {
+ if (*syn == ' ')
+ past_opcode_p = 1;
+ ++syn;
+ ++str;
+ }
+ else
+ break;
+ continue;
+ }
+
+ /* We have an operand. Pick out any modifiers. */
+ mods = 0;
+ while (ARC_MOD_P (arc_operands[arc_operand_map[*syn]].flags))
+ {
+ mods |= arc_operands[arc_operand_map[*syn]].flags & ARC_MOD_BITS;
+ ++syn;
+ }
+ operand = arc_operands + arc_operand_map[*syn];
+ if (operand->fmt == 0)
+ as_fatal (_("unknown syntax format character `%c'"), *syn);
+
+ if (operand->flags & ARC_OPERAND_FAKE)
+ {
+ const char *errmsg = NULL;
+ if (operand->insert)
+ {
+ insn = (*operand->insert) (insn, operand, mods, NULL, 0, &errmsg);
+ /* If we get an error, go on to try the next insn. */
+ if (errmsg)
+ break;
+ }
+ ++syn;
+ }
+ /* Are we finished with suffixes? */
+ else if (!past_opcode_p)
+ {
+ int found;
+ char c;
+ char *s,*t;
+ const struct arc_operand_value *suf,*suffix,*suffix_end;
+
+ if (!(operand->flags & ARC_OPERAND_SUFFIX))
+ abort ();
+
+ /* If we're at a space in the input string, we want to skip the
+ remaining suffixes. There may be some fake ones though, so
+ just go on to try the next one. */
+ if (*str == ' ')
+ {
+ ++syn;
+ continue;
+ }
+
+ s = str;
+ if (mods & ARC_MOD_DOT)
+ {
+ if (*s != '.')
+ break;
+ ++s;
+ }
+ else
+ {
+ /* This can happen in "b.nd foo" and we're currently looking
+ for "%q" (ie: a condition code suffix). */
+ if (*s == '.')
+ {
+ ++syn;
+ continue;
+ }
+ }
+
+ /* Pick the suffix out and look it up via the hash table. */
+ for (t = s; *t && isalpha (*t); ++t)
+ continue;
+ c = *t;
+ *t = '\0';
+ suf = hash_find (arc_suffix_hash, s);
+ *t = c;
+ if (!suf)
+ {
+ /* This can happen in "blle foo" and we're currently using
+ the template "b%q%.n %j". The "bl" insn occurs later in
+ the table so "lle" isn't an illegal suffix. */
+ break;
+ }
+
+ /* Is it the right type? Note that the same character is used
+ several times, so we have to examine all of them. This is
+ relatively efficient as equivalent entries are kept
+ together. If it's not the right type, don't increment `str'
+ so we try the next one in the series. */
+ found = 0;
+ suffix_end = arc_suffixes + arc_suffixes_count;
+ for (suffix = suf;
+ suffix < suffix_end && strcmp (suffix->name, suf->name) == 0;
+ ++suffix)
+ {
+ if (arc_operands[suffix->type].fmt == *syn)
+ {
+ /* Insert the suffix's value into the insn. */
+ if (operand->insert)
+ insn = (*operand->insert) (insn, operand,
+ mods, NULL, suffix->value,
+ NULL);
+ else
+ insn |= suffix->value << operand->shift;
+
+ str = t;
+ found = 1;
+ break;
+ }
+ }
+ ++syn;
+ if (!found)
+ ; /* Wrong type. Just go on to try next insn entry. */
+ else
+ {
+ if (num_suffixes == MAX_SUFFIXES)
+ as_bad (_("too many suffixes"));
+ else
+ insn_suffixes[num_suffixes++] = suffix;
+ }
+ }
+ else
+ /* This is either a register or an expression of some kind. */
+ {
+ char c;
+ char *hold;
+ const struct arc_operand_value *reg = NULL;
+ long value = 0;
+ expressionS exp;
+
+ if (operand->flags & ARC_OPERAND_SUFFIX)
+ abort ();
+
+ /* Is there anything left to parse?
+ We don't check for this at the top because we want to parse
+ any trailing fake arguments in the syntax string. */
+ if (*str == '\0')
+ break;
+#if 0
+ /* Is this a syntax character? Eg: is there a '[' present when
+ there shouldn't be? */
+ if (!isalnum (*str)
+ /* '.' as in ".LLC0" */
+ && *str != '.'
+ /* '_' as in "_print" */
+ && *str != '_'
+ /* '-' as in "[fp,-4]" */
+ && *str != '-'
+ /* '%' as in "%ia(_func)" */
+ && *str != '%')
+ break;
+#endif
+
+ /* Parse the operand. */
+ hold = input_line_pointer;
+ input_line_pointer = str;
+ expression (&exp);
+ str = input_line_pointer;
+ input_line_pointer = hold;
+
+ if (exp.X_op == O_illegal)
+ as_bad (_("illegal operand"));
+ else if (exp.X_op == O_absent)
+ as_bad (_("missing operand"));
+ else if (exp.X_op == O_constant)
+ {
+ value = exp.X_add_number;
+ }
+ else if (exp.X_op == O_register)
+ {
+ reg = arc_reg_names + exp.X_add_number;
+ }
+ else
+ {
+ /* We need to generate a fixup for this expression. */
+ if (fc >= MAX_FIXUPS)
+ as_fatal (_("too many fixups"));
+ fixups[fc].exp = exp;
+
+ /* If this is a register constant (IE: one whose
+ register value gets stored as 61-63) then this
+ must be a limm. We don't support shimm relocs. */
+ /* ??? This bit could use some cleaning up.
+ Referencing the format chars like this goes
+ against style. */
+#define IS_REG_OPERAND(o) ((o) == 'a' || (o) == 'b' || (o) == 'c')
+ if (IS_REG_OPERAND (*syn))
+ {
+ const char *junk;
+
+ fixups[fc].opindex = arc_operand_map['L'];
+ limm_reloc_p = 1;
+ /* Tell insert_reg we need a limm. This is
+ needed because the value at this point is
+ zero, a shimm. */
+ /* ??? We need a cleaner interface than this. */
+ (*arc_operands[arc_operand_map['Q']].insert)
+ (insn, operand, mods, reg, 0L, &junk);
+ }
+ else
+ fixups[fc].opindex = arc_operand_map[*syn];
+ ++fc;
+ value = 0;
+ }
+
+ /* Insert the register or expression into the instruction. */
+ if (operand->insert)
+ {
+ const char *errmsg = NULL;
+ insn = (*operand->insert) (insn, operand, mods,
+ reg, (long) value, &errmsg);
+#if 0
+ if (errmsg != (const char *) NULL)
+ as_warn (errmsg);
+#endif
+ /* FIXME: We want to try shimm insns for limm ones. But if
+ the constant won't fit, we must go on to try the next
+ possibility. Where do we issue warnings for constants
+ that are too big then? At present, we'll flag the insn
+ as unrecognizable! Maybe have the "bad instruction"
+ error message include our `errmsg'? */
+ if (errmsg != (const char *) NULL)
+ break;
+ }
+ else
+ insn |= (value & ((1 << operand->bits) - 1)) << operand->shift;
+
+ ++syn;
+ }
+ }
+
+ /* If we're at the end of the syntax string, we're done. */
+ /* FIXME: try to move this to a separate function. */
+ if (*syn == '\0')
+ {
+ int i;
+ char *f;
+ long limm, limm_p;
+
+ /* For the moment we assume a valid `str' can only contain blanks
+ now. IE: We needn't try again with a longer version of the
+ insn and it is assumed that longer versions of insns appear
+ before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
+
+ while (isspace (*str))
+ ++str;
+
+ if (*str != '\0')
+ as_bad (_("junk at end of line: `%s'"), str);
+
+ /* Is there a limm value? */
+ limm_p = arc_opcode_limm_p (&limm);
+
+ /* Perform various error and warning tests. */
+
+ {
+ static int in_delay_slot_p = 0;
+ static int prev_insn_needs_cc_nop_p = 0;
+ /* delay slot type seen */
+ int delay_slot_type = ARC_DELAY_NONE;
+ /* conditional execution flag seen */
+ int conditional = 0;
+ /* 1 if condition codes are being set */
+ int cc_set_p = 0;
+ /* 1 if conditional branch, including `b' "branch always" */
+ int cond_branch_p = opcode->flags & ARC_OPCODE_COND_BRANCH;
+ int need_cc_nop_p = 0;
+
+ for (i = 0; i < num_suffixes; ++i)
+ {
+ switch (arc_operands[insn_suffixes[i]->type].fmt)
+ {
+ case 'n' :
+ delay_slot_type = insn_suffixes[i]->value;
+ break;
+ case 'q' :
+ conditional = insn_suffixes[i]->value;
+ break;
+ case 'f' :
+ cc_set_p = 1;
+ break;
+ }
+ }
+
+ /* Putting an insn with a limm value in a delay slot is supposed to
+ be legal, but let's warn the user anyway. Ditto for 8 byte
+ jumps with delay slots. */
+ if (in_delay_slot_p && limm_p)
+ as_warn (_("8 byte instruction in delay slot"));
+ if (delay_slot_type != ARC_DELAY_NONE && limm_p)
+ as_warn (_("8 byte jump instruction with delay slot"));
+ in_delay_slot_p = (delay_slot_type != ARC_DELAY_NONE) && !limm_p;
+
+ /* Warn when a conditional branch immediately follows a set of
+ the condition codes. Note that this needn't be done if the
+ insn that sets the condition codes uses a limm. */
+ if (cond_branch_p && conditional != 0 /* 0 = "always" */
+ && prev_insn_needs_cc_nop_p)
+ as_warn (_("conditional branch follows set of flags"));
+ prev_insn_needs_cc_nop_p = cc_set_p && !limm_p;
+ }
+
+ /* Write out the instruction.
+ It is important to fetch enough space in one call to `frag_more'.
+ We use (f - frag_now->fr_literal) to compute where we are and we
+ don't want frag_now to change between calls. */
+ if (limm_p)
+ {
+ f = frag_more (8);
+ md_number_to_chars (f, insn, 4);
+ md_number_to_chars (f + 4, limm, 4);
+ }
+ else if (limm_reloc_p)
+ {
+ /* We need a limm reloc, but the tables think we don't. */
+ abort ();
+ }
+ else
+ {
+ f = frag_more (4);
+ md_number_to_chars (f, insn, 4);
+ }
+
+ /* Create any fixups. */
+ for (i = 0; i < fc; ++i)
+ {
+ int op_type, reloc_type;
+ expressionS exptmp;
+ const struct arc_operand *operand;
+
+ /* Create a fixup for this operand.
+ At this point we do not use a bfd_reloc_code_real_type for
+ operands residing in the insn, but instead just use the
+ operand index. This lets us easily handle fixups for any
+ operand type, although that is admittedly not a very exciting
+ feature. We pick a BFD reloc type in md_apply_fix.
+
+ Limm values (4 byte immediate "constants") must be treated
+ normally because they're not part of the actual insn word
+ and thus the insertion routines don't handle them. */
+
+ if (arc_operands[fixups[i].opindex].flags & ARC_OPERAND_LIMM)
+ {
+ op_type = fixups[i].opindex;
+ /* FIXME: can we add this data to the operand table? */
+ if (op_type == arc_operand_map['L'])
+ reloc_type = BFD_RELOC_32;
+ else if (op_type == arc_operand_map['J'])
+ reloc_type = BFD_RELOC_ARC_B26;
+ else
+ abort ();
+ reloc_type = get_arc_exp_reloc_type (1, reloc_type,
+ &fixups[i].exp,
+ &exptmp);
+ }
+ else
+ {
+ op_type = get_arc_exp_reloc_type (0, fixups[i].opindex,
+ &fixups[i].exp, &exptmp);
+ reloc_type = op_type + (int) BFD_RELOC_UNUSED;
+ }
+ operand = &arc_operands[op_type];
+ fix_new_exp (frag_now,
+ ((f - frag_now->fr_literal)
+ + (operand->flags & ARC_OPERAND_LIMM ? 4 : 0)), 4,
+ &exptmp,
+ (operand->flags & ARC_OPERAND_RELATIVE_BRANCH) != 0,
+ (bfd_reloc_code_real_type) reloc_type);
+ }
+
+ /* All done. */
+ return;
+ }
+
+ /* Try the next entry. */
+ }
+
+ as_bad (_("bad instruction `%s'"), start);
+}
+
+/* ??? This was copied from tc-sparc.c, I think. Is it necessary? */
+
+static void
+arc_common (ignore)
+ int ignore;
+{
+ char *name;
+ char c;
+ char *p;
+ int temp, size;
+ symbolS *symbolP;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ /* just after name is now '\0' */
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("expected comma after symbol-name"));
+ ignore_rest_of_line ();
+ return;
+ }
+ input_line_pointer++; /* skip ',' */
+ if ((temp = get_absolute_expression ()) < 0)
+ {
+ as_bad (_(".COMMon length (%d.) <0! Ignored."), temp);
+ ignore_rest_of_line ();
+ return;
+ }
+ size = temp;
+ *p = 0;
+ symbolP = symbol_find_or_make (name);
+ *p = c;
+ if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
+ {
+ as_bad (_("ignoring attempt to re-define symbol"));
+ ignore_rest_of_line ();
+ return;
+ }
+ if (S_GET_VALUE (symbolP) != 0)
+ {
+ if (S_GET_VALUE (symbolP) != size)
+ {
+ as_warn (_("Length of .comm \"%s\" is already %ld. Not changed to %d."),
+ S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size);
+ }
+ }
+ assert (symbolP->sy_frag == &zero_address_frag);
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("expected comma after common length"));
+ ignore_rest_of_line ();
+ return;
+ }
+ input_line_pointer++;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != '"')
+ {
+ temp = get_absolute_expression ();
+ if (temp < 0)
+ {
+ temp = 0;
+ as_warn (_("Common alignment negative; 0 assumed"));
+ }
+ if (symbolP->local)
+ {
+ segT old_sec;
+ int old_subsec;
+ char *p;
+ int align;
+
+ allocate_bss:
+ old_sec = now_seg;
+ old_subsec = now_subseg;
+ align = temp;
+ record_alignment (bss_section, align);
+ subseg_set (bss_section, 0);
+ if (align)
+ frag_align (align, 0, 0);
+ if (S_GET_SEGMENT (symbolP) == bss_section)
+ symbolP->sy_frag->fr_symbol = 0;
+ symbolP->sy_frag = frag_now;
+ p = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
+ (offsetT) size, (char *) 0);
+ *p = 0;
+ S_SET_SEGMENT (symbolP, bss_section);
+ S_CLEAR_EXTERNAL (symbolP);
+ subseg_set (old_sec, old_subsec);
+ }
+ else
+ {
+ allocate_common:
+ S_SET_VALUE (symbolP, (valueT) size);
+ S_SET_ALIGN (symbolP, temp);
+ S_SET_EXTERNAL (symbolP);
+ S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
+ }
+ }
+ else
+ {
+ input_line_pointer++;
+ /* ??? Some say data, some say bss. */
+ if (strncmp (input_line_pointer, ".bss\"", 5)
+ && strncmp (input_line_pointer, ".data\"", 6))
+ {
+ input_line_pointer--;
+ goto bad_common_segment;
+ }
+ while (*input_line_pointer++ != '"')
+ ;
+ goto allocate_common;
+ }
+ demand_empty_rest_of_line ();
+ return;
+
+ {
+ bad_common_segment:
+ p = input_line_pointer;
+ while (*p && *p != '\n')
+ p++;
+ c = *p;
+ *p = '\0';
+ as_bad (_("bad .common segment %s"), input_line_pointer + 1);
+ *p = c;
+ input_line_pointer = p;
+ ignore_rest_of_line ();
+ return;
+ }
+}
+
+/* Select the cpu we're assembling for. */
+
+static void
+arc_cpu (ignore)
+ int ignore;
+{
+ int mach;
+ char c;
+ char *cpu;
+
+ /* If an instruction has already been seen, it's too late. */
+ if (cpu_tables_init_p)
+ {
+ as_bad (_(".cpu command must appear before any instructions"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ cpu = input_line_pointer;
+ c = get_symbol_end ();
+ mach = arc_get_mach (cpu);
+ *input_line_pointer = c;
+ if (mach == -1)
+ goto bad_cpu;
+
+ demand_empty_rest_of_line ();
+
+ /* The cpu may have been selected on the command line.
+ The choices must match. */
+ /* ??? This was a command line option early on. It's gone now, but
+ leave this in. */
+ if (mach_type_specified_p && mach != arc_mach_type)
+ as_bad (_(".cpu conflicts with previous value"));
+ else
+ {
+ arc_mach_type = mach;
+ mach_type_specified_p = 1;
+ if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, mach))
+ as_warn (_("could not set architecture and machine"));
+ }
+ return;
+
+ bad_cpu:
+ as_bad (_("bad .cpu op"));
+ ignore_rest_of_line ();
+}
+
+#if 0
+/* The .rename pseudo-op. This is used by gcc to implement
+ -mmangle-cpu-libgcc. */
+
+static void
+arc_rename (ignore)
+ int ignore;
+{
+ char *name,*new;
+ char c;
+ symbolS *sym;
+ int len;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ sym = symbol_find_or_make (name);
+ *input_line_pointer = c;
+
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("missing rename string"));
+ ignore_rest_of_line ();
+ return;
+ }
+ ++input_line_pointer;
+ SKIP_WHITESPACE ();
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ if (*name == '\0')
+ {
+ *input_line_pointer = c;
+ as_bad (_("invalid symbol to rename to"));
+ ignore_rest_of_line ();
+ return;
+ }
+ new = (char *) xmalloc (strlen (name) + 1);
+ strcpy (new, name);
+ *input_line_pointer = c;
+ sym->sy_tc.real_name = new;
+
+ demand_empty_rest_of_line ();
+}
+#endif
+
+/* Turn a string in input_line_pointer into a floating point constant of type
+ type, and store the appropriate bytes in *litP. The number of LITTLENUMS
+ emitted is stored in *sizeP.
+ An error message is returned, or NULL on OK. */
+
+/* Equal to MAX_PRECISION in atof-ieee.c */
+#define MAX_LITTLENUMS 6
+
+char *
+md_atof (type, litP, sizeP)
+ char type;
+ char *litP;
+ int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ char *t;
+ char *atof_ieee ();
+
+ switch (type)
+ {
+ case 'f':
+ case 'F':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ prec = 4;
+ break;
+
+ default:
+ *sizeP = 0;
+ return _("bad call to md_atof");
+ }
+
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+ *sizeP = prec * sizeof (LITTLENUM_TYPE);
+ for (wordP = words; prec--;)
+ {
+ md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+
+ return NULL;
+}
+
+/* Write a value out to the object file, using the appropriate
+ endianness. */
+
+void
+md_number_to_chars (buf, val, n)
+ char *buf;
+ valueT val;
+ int n;
+{
+ if (target_big_endian)
+ number_to_chars_bigendian (buf, val, n);
+ else
+ number_to_chars_littleendian (buf, val, n);
+}
+
+/* Round up a section size to the appropriate boundary. */
+
+valueT
+md_section_align (segment, size)
+ segT segment;
+ valueT size;
+{
+ int align = bfd_get_section_alignment (stdoutput, segment);
+
+ return ((size + (1 << align) - 1) & (-1 << align));
+}
+
+/* We don't have any form of relaxing. */
+
+int
+md_estimate_size_before_relax (fragp, seg)
+ fragS *fragp;
+ asection *seg;
+{
+ abort ();
+}
+
+/* Convert a machine dependent frag. We never generate these. */
+
+void
+md_convert_frag (abfd, sec, fragp)
+ bfd *abfd;
+ asection *sec;
+ fragS *fragp;
+{
+ abort ();
+}
+
+/* Parse an operand that is machine-specific.
+
+ The ARC has a special %-op to adjust addresses so they're usable in
+ branches. The "st" is short for the STatus register.
+ ??? Later expand this to take a flags value too.
+
+ ??? We can't create new expression types so we map the %-op's onto the
+ existing syntax. This means that the user could use the chosen syntax
+ to achieve the same effect. Perhaps put a special cookie in X_add_number
+ to mark the expression as special. */
+
+void
+md_operand (expressionP)
+ expressionS *expressionP;
+{
+ char *p = input_line_pointer;
+
+ if (*p == '%' && strncmp (p, "%st(", 4) == 0)
+ {
+ input_line_pointer += 4;
+ expression (expressionP);
+ if (*input_line_pointer != ')')
+ {
+ as_bad (_("missing ')' in %-op"));
+ return;
+ }
+ ++input_line_pointer;
+ if (expressionP->X_op == O_symbol
+ && expressionP->X_add_number == 0
+ /* I think this test is unnecessary but just as a sanity check... */
+ && expressionP->X_op_symbol == NULL)
+ {
+ expressionS two;
+
+ expressionP->X_op = O_right_shift;
+ two.X_op = O_constant;
+ two.X_add_symbol = two.X_op_symbol = NULL;
+ two.X_add_number = 2;
+ expressionP->X_op_symbol = make_expr_symbol (&two);
+ }
+ /* allow %st(sym1-sym2) */
+ else if (expressionP->X_op == O_subtract
+ && expressionP->X_add_symbol != NULL
+ && expressionP->X_op_symbol != NULL
+ && expressionP->X_add_number == 0)
+ {
+ expressionS two;
+
+ expressionP->X_add_symbol = make_expr_symbol (expressionP);
+ expressionP->X_op = O_right_shift;
+ two.X_op = O_constant;
+ two.X_add_symbol = two.X_op_symbol = NULL;
+ two.X_add_number = 2;
+ expressionP->X_op_symbol = make_expr_symbol (&two);
+ }
+ else
+ {
+ as_bad (_("expression too complex for %%st"));
+ return;
+ }
+ }
+}
+
+/* We have no need to default values of symbols.
+ We could catch register names here, but that is handled by inserting
+ them all in the symbol table to begin with. */
+
+symbolS *
+md_undefined_symbol (name)
+ char *name;
+{
+ return 0;
+}
+
+/* Functions concerning expressions. */
+
+/* Parse a .byte, .word, etc. expression.
+
+ Values for the status register are specified with %st(label).
+ `label' will be right shifted by 2. */
+
+void
+arc_parse_cons_expression (exp, nbytes)
+ expressionS *exp;
+ int nbytes;
+{
+ expr (0, exp);
+}
+
+/* Record a fixup for a cons expression. */
+
+void
+arc_cons_fix_new (frag, where, nbytes, exp)
+ fragS *frag;
+ int where;
+ int nbytes;
+ expressionS *exp;
+{
+ if (nbytes == 4)
+ {
+ int reloc_type;
+ expressionS exptmp;
+
+ /* This may be a special ARC reloc (eg: %st()). */
+ reloc_type = get_arc_exp_reloc_type (1, BFD_RELOC_32, exp, &exptmp);
+ fix_new_exp (frag, where, nbytes, &exptmp, 0, reloc_type);
+ }
+ else
+ {
+ fix_new_exp (frag, where, nbytes, exp, 0,
+ nbytes == 2 ? BFD_RELOC_16
+ : nbytes == 8 ? BFD_RELOC_64
+ : BFD_RELOC_32);
+ }
+}
+
+/* Functions concerning relocs. */
+
+/* The location from which a PC relative jump should be calculated,
+ given a PC relative reloc. */
+
+long
+md_pcrel_from (fixP)
+ fixS *fixP;
+{
+ if (fixP->fx_addsy != (symbolS *) NULL
+ && ! S_IS_DEFINED (fixP->fx_addsy))
+ {
+ /* The symbol is undefined. Let the linker figure it out. */
+ return 0;
+ }
+
+ /* Return the address of the delay slot. */
+ return fixP->fx_frag->fr_address + fixP->fx_where + fixP->fx_size;
+}
+
+/* Compute the reloc type of an expression.
+ The possibly modified expression is stored in EXPNEW.
+
+ This is used to convert the expressions generated by the %-op's into
+ the appropriate operand type. It is called for both data in instructions
+ (operands) and data outside instructions (variables, debugging info, etc.).
+
+ Currently supported %-ops:
+
+ %st(symbol): represented as "symbol >> 2"
+ "st" is short for STatus as in the status register (pc)
+
+ DEFAULT_TYPE is the type to use if no special processing is required.
+
+ DATA_P is non-zero for data or limm values, zero for insn operands.
+ Remember that the opcode "insertion fns" cannot be used on data, they're
+ only for inserting operands into insns. They also can't be used for limm
+ values as the insertion routines don't handle limm values. When called for
+ insns we return fudged reloc types (real_value - BFD_RELOC_UNUSED). When
+ called for data or limm values we use real reloc types. */
+
+static int
+get_arc_exp_reloc_type (data_p, default_type, exp, expnew)
+ int data_p;
+ int default_type;
+ expressionS *exp;
+ expressionS *expnew;
+{
+ /* If the expression is "symbol >> 2" we must change it to just "symbol",
+ as fix_new_exp can't handle it. Similarily for (symbol - symbol) >> 2.
+ That's ok though. What's really going on here is that we're using
+ ">> 2" as a special syntax for specifying BFD_RELOC_ARC_B26. */
+
+ if (exp->X_op == O_right_shift
+ && exp->X_op_symbol != NULL
+ && exp->X_op_symbol->sy_value.X_op == O_constant
+ && exp->X_op_symbol->sy_value.X_add_number == 2
+ && exp->X_add_number == 0)
+ {
+ if (exp->X_add_symbol != NULL
+ && (exp->X_add_symbol->sy_value.X_op == O_constant
+ || exp->X_add_symbol->sy_value.X_op == O_symbol))
+ {
+ *expnew = *exp;
+ expnew->X_op = O_symbol;
+ expnew->X_op_symbol = NULL;
+ return data_p ? BFD_RELOC_ARC_B26 : arc_operand_map['J'];
+ }
+ else if (exp->X_add_symbol != NULL
+ && exp->X_add_symbol->sy_value.X_op == O_subtract)
+ {
+ *expnew = exp->X_add_symbol->sy_value;
+ return data_p ? BFD_RELOC_ARC_B26 : arc_operand_map['J'];
+ }
+ }
+
+ *expnew = *exp;
+ return default_type;
+}
+
+/* Apply a fixup to the object code. This is called for all the
+ fixups we generated by the call to fix_new_exp, above. In the call
+ above we used a reloc code which was the largest legal reloc code
+ plus the operand index. Here we undo that to recover the operand
+ index. At this point all symbol values should be fully resolved,
+ and we attempt to completely resolve the reloc. If we can not do
+ that, we determine the correct reloc code and put it back in the fixup. */
+
+int
+md_apply_fix3 (fixP, valueP, seg)
+ fixS *fixP;
+ valueT *valueP;
+ segT seg;
+{
+ /*char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;*/
+ valueT value;
+
+ /* FIXME FIXME FIXME: The value we are passed in *valueP includes
+ the symbol values. Since we are using BFD_ASSEMBLER, if we are
+ doing this relocation the code in write.c is going to call
+ bfd_perform_relocation, which is also going to use the symbol
+ value. That means that if the reloc is fully resolved we want to
+ use *valueP since bfd_perform_relocation is not being used.
+ However, if the reloc is not fully resolved we do not want to use
+ *valueP, and must use fx_offset instead. However, if the reloc
+ is PC relative, we do want to use *valueP since it includes the
+ result of md_pcrel_from. This is confusing. */
+
+ if (fixP->fx_addsy == (symbolS *) NULL)
+ {
+ value = *valueP;
+ fixP->fx_done = 1;
+ }
+ else if (fixP->fx_pcrel)
+ {
+ value = *valueP;
+ /* ELF relocations are against symbols.
+ If this symbol is in a different section then we need to leave it for
+ the linker to deal with. Unfortunately, md_pcrel_from can't tell,
+ so we have to undo it's effects here. */
+ if (S_IS_DEFINED (fixP->fx_addsy)
+ && S_GET_SEGMENT (fixP->fx_addsy) != seg)
+ value += md_pcrel_from (fixP);
+ }
+ else
+ {
+ value = fixP->fx_offset;
+ if (fixP->fx_subsy != (symbolS *) NULL)
+ {
+ if (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section)
+ value -= S_GET_VALUE (fixP->fx_subsy);
+ else
+ {
+ /* We can't actually support subtracting a symbol. */
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("expression too complex"));
+ }
+ }
+ }
+
+ if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
+ {
+ int opindex;
+ const struct arc_operand *operand;
+ char *where;
+ arc_insn insn;
+
+ opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
+
+ operand = &arc_operands[opindex];
+
+ /* Fetch the instruction, insert the fully resolved operand
+ value, and stuff the instruction back again. */
+ where = fixP->fx_frag->fr_literal + fixP->fx_where;
+ if (target_big_endian)
+ insn = bfd_getb32 ((unsigned char *) where);
+ else
+ insn = bfd_getl32 ((unsigned char *) where);
+ insn = arc_insert_operand (insn, operand, -1, NULL, (offsetT) value,
+ fixP->fx_file, fixP->fx_line);
+ if (target_big_endian)
+ bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
+ else
+ bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
+
+ if (fixP->fx_done)
+ {
+ /* Nothing else to do here. */
+ return 1;
+ }
+
+ /* Determine a BFD reloc value based on the operand information.
+ We are only prepared to turn a few of the operands into relocs.
+ !!! Note that we can't handle limm values here. Since we're using
+ implicit addends the addend must be inserted into the instruction,
+ however, the opcode insertion routines currently do nothing with
+ limm values. */
+ if (operand->fmt == 'B')
+ {
+ assert ((operand->flags & ARC_OPERAND_RELATIVE_BRANCH) != 0
+ && operand->bits == 20
+ && operand->shift == 7);
+ fixP->fx_r_type = BFD_RELOC_ARC_B22_PCREL;
+ }
+ else if (0 && operand->fmt == 'J')
+ {
+ assert ((operand->flags & ARC_OPERAND_ABSOLUTE_BRANCH) != 0
+ && operand->bits == 24
+ && operand->shift == 32);
+ fixP->fx_r_type = BFD_RELOC_ARC_B26;
+ }
+ else if (0 && operand->fmt == 'L')
+ {
+ assert ((operand->flags & ARC_OPERAND_LIMM) != 0
+ && operand->bits == 32
+ && operand->shift == 32);
+ fixP->fx_r_type = BFD_RELOC_32;
+ }
+ else
+ {
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("unresolved expression that must be resolved"));
+ fixP->fx_done = 1;
+ return 1;
+ }
+ }
+ else
+ {
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_8:
+ md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
+ value, 1);
+ break;
+ case BFD_RELOC_16:
+ md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
+ value, 2);
+ break;
+ case BFD_RELOC_32:
+ md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
+ value, 4);
+ break;
+#if 0
+ case BFD_RELOC_64:
+ md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
+ value, 8);
+ break;
+#endif
+ case BFD_RELOC_ARC_B26:
+ /* If !fixP->fx_done then `value' is an implicit addend.
+ We must shift it right by 2 in this case as well because the
+ linker performs the relocation and then adds this in (as opposed
+ to adding this in and then shifting right by 2). */
+ value >>= 2;
+ md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
+ value, 4);
+ break;
+ default:
+ abort ();
+ }
+ }
+
+ fixP->fx_addnumber = value;
+
+ return 1;
+}
+
+/* Translate internal representation of relocation info to BFD target
+ format. */
+
+arelent *
+tc_gen_reloc (section, fixP)
+ asection *section;
+ fixS *fixP;
+{
+ arelent *reloc;
+
+ reloc = (arelent *) xmalloc (sizeof (arelent));
+
+ reloc->sym_ptr_ptr = &fixP->fx_addsy->bsym;
+ reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
+ if (reloc->howto == (reloc_howto_type *) NULL)
+ {
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("internal error: can't export reloc type %d (`%s')"),
+ fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type));
+ return NULL;
+ }
+
+ assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
+
+ reloc->addend = fixP->fx_addnumber;
+
+ return reloc;
+}
+
+/* Frobbers. */
+
+#if 0
+/* Set the real name if the .rename pseudo-op was used.
+ Return 1 if the symbol should not be included in the symbol table. */
+
+int
+arc_frob_symbol (sym)
+ symbolS *sym;
+{
+ if (sym->sy_tc.real_name != (char *) NULL)
+ S_SET_NAME (sym, sym->sy_tc.real_name);
+
+ return 0;
+}
+#endif
diff --git a/gas/config/tc-arc.h b/gas/config/tc-arc.h
new file mode 100644
index 0000000000..6a95ff4b61
--- /dev/null
+++ b/gas/config/tc-arc.h
@@ -0,0 +1,71 @@
+/* tc-arc.h - Macros and type defines for the ARC.
+ Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc.
+ Contributed by Doug Evans (dje@cygnus.com).
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2,
+ or (at your option) any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#define TC_ARC 1
+
+#define TARGET_BYTES_BIG_ENDIAN 0
+
+#define LOCAL_LABELS_FB 1
+
+#define TARGET_ARCH bfd_arch_arc
+
+#define LITTLE_ENDIAN 1234
+#define BIG_ENDIAN 4321
+
+/* The endianness of the target format may change based on command
+ line arguments. */
+extern const char *arc_target_format;
+#define DEFAULT_TARGET_FORMAT "elf32-littlearc"
+#define TARGET_FORMAT arc_target_format
+#define DEFAULT_BYTE_ORDER LITTLE_ENDIAN
+
+#define WORKING_DOT_WORD
+
+#define LISTING_HEADER "ARC GAS "
+
+#define TC_HANDLES_FX_DONE
+
+#define MD_APPLY_FIX3
+
+/* The ARC needs to parse reloc specifiers in .word. */
+
+extern void arc_parse_cons_expression ();
+#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) \
+arc_parse_cons_expression (EXP, NBYTES)
+
+extern void arc_cons_fix_new ();
+#define TC_CONS_FIX_NEW(FRAG, WHERE, NBYTES, EXP) \
+arc_cons_fix_new (FRAG, WHERE, NBYTES, EXP)
+
+#if 0
+/* Extra stuff that we need to keep track of for each symbol. */
+struct arc_tc_sy
+{
+ /* The real name, if the symbol was renamed. */
+ char *real_name;
+};
+
+#define TC_SYMFIELD_TYPE struct arc_tc_sy
+
+/* Finish up the symbol. */
+extern int arc_frob_symbol PARAMS ((struct symbol *));
+#define tc_frob_symbol(sym, punt) punt = arc_frob_symbol (sym)
+#endif
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
new file mode 100644
index 0000000000..d898bf0ecd
--- /dev/null
+++ b/gas/config/tc-arm.c
@@ -0,0 +1,6857 @@
+/* tc-arm.c -- Assemble for the ARM
+ Copyright (C) 1994, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
+ Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
+ Modified by David Taylor (dtaylor@armltd.co.uk)
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include <ctype.h>
+#include <string.h>
+#define NO_RELOC 0
+#include "as.h"
+
+/* need TARGET_CPU */
+#include "config.h"
+#include "subsegs.h"
+#include "obstack.h"
+#include "symbols.h"
+#include "listing.h"
+
+#ifdef OBJ_ELF
+#include "elf/arm.h"
+#endif
+
+/* Types of processor to assemble for. */
+#define ARM_1 0x00000001
+#define ARM_2 0x00000002
+#define ARM_3 0x00000004
+#define ARM_250 ARM_3
+#define ARM_6 0x00000008
+#define ARM_7 ARM_6 /* same core instruction set */
+#define ARM_8 ARM_6 /* same core instruction set */
+#define ARM_9 ARM_6 /* same core instruction set */
+#define ARM_CPU_MASK 0x0000000f
+
+/* The following bitmasks control CPU extensions (ARM7 onwards): */
+#define ARM_LONGMUL 0x00000010 /* allow long multiplies */
+#define ARM_HALFWORD 0x00000020 /* allow half word loads */
+#define ARM_THUMB 0x00000040 /* allow BX instruction */
+
+#define ARM_ARCHv4 (ARM_7 | ARM_LONGMUL | ARM_HALFWORD)
+
+/* Some useful combinations: */
+#define ARM_ANY 0x00ffffff
+#define ARM_2UP 0x00fffffe
+#define ARM_ALL ARM_2UP /* Not arm1 only */
+#define ARM_3UP 0x00fffffc
+#define ARM_6UP 0x00fffff8 /* Includes ARM7 */
+
+#define FPU_CORE 0x80000000
+#define FPU_FPA10 0x40000000
+#define FPU_FPA11 0x40000000
+#define FPU_NONE 0
+
+/* Some useful combinations */
+#define FPU_ALL 0xff000000 /* Note this is ~ARM_ANY */
+#define FPU_MEMMULTI 0x7f000000 /* Not fpu_core */
+
+
+#ifndef CPU_DEFAULT
+#if defined __thumb__
+#define CPU_DEFAULT (ARM_ARCHv4 | ARM_THUMB)
+#else
+#define CPU_DEFAULT ARM_ALL
+#endif
+#endif
+
+#ifndef FPU_DEFAULT
+#define FPU_DEFAULT FPU_ALL
+#endif
+
+#define streq(a,b) (strcmp (a, b) == 0)
+
+static unsigned long cpu_variant = CPU_DEFAULT | FPU_DEFAULT;
+static int target_oabi = 0;
+
+#if defined OBJ_COFF || defined OBJ_ELF
+/* Flags stored in private area of BFD structure */
+static boolean uses_apcs_26 = false;
+static boolean support_interwork = false;
+static boolean uses_apcs_float = false;
+static boolean pic_code = false;
+#endif
+
+/* This array holds the chars that always start a comment. If the
+ pre-processor is disabled, these aren't very useful */
+CONST char comment_chars[] = "@";
+
+/* This array holds the chars that only start a comment at the beginning of
+ a line. If the line seems to have the form '# 123 filename'
+ .line and .file directives will appear in the pre-processed output */
+/* Note that input_file.c hand checks for '#' at the beginning of the
+ first line of the input file. This is because the compiler outputs
+ #NO_APP at the beginning of its output. */
+/* Also note that comments like this one will always work. */
+CONST char line_comment_chars[] = "#";
+
+#ifdef TE_LINUX
+CONST char line_separator_chars[] = ";";
+#else
+CONST char line_separator_chars[] = "";
+#endif
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+CONST char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* As in 0f12.456 */
+/* or 0d1.2345e12 */
+
+CONST char FLT_CHARS[] = "rRsSfFdDxXeEpP";
+
+/* Prefix characters that indicate the start of an immediate
+ value. */
+#define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
+
+#ifdef OBJ_ELF
+symbolS * GOT_symbol; /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
+#endif
+
+CONST int md_reloc_size = 8; /* Size of relocation record */
+
+static int thumb_mode = 0; /* non-zero if assembling thumb instructions */
+
+typedef struct arm_fix
+{
+ int thumb_mode;
+} arm_fix_data;
+
+struct arm_it
+{
+ CONST char * error;
+ unsigned long instruction;
+ int suffix;
+ int size;
+ struct
+ {
+ bfd_reloc_code_real_type type;
+ expressionS exp;
+ int pc_rel;
+ } reloc;
+};
+
+struct arm_it inst;
+
+struct asm_shift
+{
+ CONST char * template;
+ unsigned long value;
+};
+
+static CONST struct asm_shift shift[] =
+{
+ {"asl", 0},
+ {"lsl", 0},
+ {"lsr", 0x00000020},
+ {"asr", 0x00000040},
+ {"ror", 0x00000060},
+ {"rrx", 0x00000060},
+ {"ASL", 0},
+ {"LSL", 0},
+ {"LSR", 0x00000020},
+ {"ASR", 0x00000040},
+ {"ROR", 0x00000060},
+ {"RRX", 0x00000060}
+};
+
+#define NO_SHIFT_RESTRICT 1
+#define SHIFT_RESTRICT 0
+
+#define NUM_FLOAT_VALS 8
+
+CONST char * fp_const[] =
+{
+ "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
+};
+
+/* Number of littlenums required to hold an extended precision number */
+#define MAX_LITTLENUMS 6
+
+LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
+
+#define FAIL (-1)
+#define SUCCESS (0)
+
+#define SUFF_S 1
+#define SUFF_D 2
+#define SUFF_E 3
+#define SUFF_P 4
+
+#define CP_T_X 0x00008000
+#define CP_T_Y 0x00400000
+#define CP_T_Pre 0x01000000
+#define CP_T_UD 0x00800000
+#define CP_T_WB 0x00200000
+
+#define CONDS_BIT (0x00100000)
+#define LOAD_BIT (0x00100000)
+#define TRANS_BIT (0x00200000)
+
+struct asm_cond
+{
+ CONST char * template;
+ unsigned long value;
+};
+
+/* This is to save a hash look-up in the common case */
+#define COND_ALWAYS 0xe0000000
+
+static CONST struct asm_cond conds[] =
+{
+ {"eq", 0x00000000},
+ {"ne", 0x10000000},
+ {"cs", 0x20000000}, {"hs", 0x20000000},
+ {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
+ {"mi", 0x40000000},
+ {"pl", 0x50000000},
+ {"vs", 0x60000000},
+ {"vc", 0x70000000},
+ {"hi", 0x80000000},
+ {"ls", 0x90000000},
+ {"ge", 0xa0000000},
+ {"lt", 0xb0000000},
+ {"gt", 0xc0000000},
+ {"le", 0xd0000000},
+ {"al", 0xe0000000},
+ {"nv", 0xf0000000}
+};
+
+/* Warning: If the top bit of the set_bits is set, then the standard
+ instruction bitmask is ignored, and the new bitmask is taken from
+ the set_bits: */
+struct asm_flg
+{
+ CONST char * template; /* Basic flag string */
+ unsigned long set_bits; /* Bits to set */
+};
+
+static CONST struct asm_flg s_flag[] =
+{
+ {"s", CONDS_BIT},
+ {NULL, 0}
+};
+
+static CONST struct asm_flg ldr_flags[] =
+{
+ {"b", 0x00400000},
+ {"t", TRANS_BIT},
+ {"bt", 0x00400000 | TRANS_BIT},
+ {"h", 0x801000b0},
+ {"sh", 0x801000f0},
+ {"sb", 0x801000d0},
+ {NULL, 0}
+};
+
+static CONST struct asm_flg str_flags[] =
+{
+ {"b", 0x00400000},
+ {"t", TRANS_BIT},
+ {"bt", 0x00400000 | TRANS_BIT},
+ {"h", 0x800000b0},
+ {NULL, 0}
+};
+
+static CONST struct asm_flg byte_flag[] =
+{
+ {"b", 0x00400000},
+ {NULL, 0}
+};
+
+static CONST struct asm_flg cmp_flags[] =
+{
+ {"s", CONDS_BIT},
+ {"p", 0x0010f000},
+ {NULL, 0}
+};
+
+static CONST struct asm_flg ldm_flags[] =
+{
+ {"ed", 0x01800000},
+ {"fd", 0x00800000},
+ {"ea", 0x01000000},
+ {"fa", 0x08000000},
+ {"ib", 0x01800000},
+ {"ia", 0x00800000},
+ {"db", 0x01000000},
+ {"da", 0x08000000},
+ {NULL, 0}
+};
+
+static CONST struct asm_flg stm_flags[] =
+{
+ {"ed", 0x08000000},
+ {"fd", 0x01000000},
+ {"ea", 0x00800000},
+ {"fa", 0x01800000},
+ {"ib", 0x01800000},
+ {"ia", 0x00800000},
+ {"db", 0x01000000},
+ {"da", 0x08000000},
+ {NULL, 0}
+};
+
+static CONST struct asm_flg lfm_flags[] =
+{
+ {"fd", 0x00800000},
+ {"ea", 0x01000000},
+ {NULL, 0}
+};
+
+static CONST struct asm_flg sfm_flags[] =
+{
+ {"fd", 0x01000000},
+ {"ea", 0x00800000},
+ {NULL, 0}
+};
+
+static CONST struct asm_flg round_flags[] =
+{
+ {"p", 0x00000020},
+ {"m", 0x00000040},
+ {"z", 0x00000060},
+ {NULL, 0}
+};
+
+/* The implementation of the FIX instruction is broken on some assemblers,
+ in that it accepts a precision specifier as well as a rounding specifier,
+ despite the fact that this is meaningless. To be more compatible, we
+ accept it as well, though of course it does not set any bits. */
+static CONST struct asm_flg fix_flags[] =
+{
+ {"p", 0x00000020},
+ {"m", 0x00000040},
+ {"z", 0x00000060},
+ {"sp", 0x00000020},
+ {"sm", 0x00000040},
+ {"sz", 0x00000060},
+ {"dp", 0x00000020},
+ {"dm", 0x00000040},
+ {"dz", 0x00000060},
+ {"ep", 0x00000020},
+ {"em", 0x00000040},
+ {"ez", 0x00000060},
+ {NULL, 0}
+};
+
+static CONST struct asm_flg except_flag[] =
+{
+ {"e", 0x00400000},
+ {NULL, 0}
+};
+
+static CONST struct asm_flg cplong_flag[] =
+{
+ {"l", 0x00400000},
+ {NULL, 0}
+};
+
+struct asm_psr
+{
+ CONST char * template;
+ unsigned long number;
+};
+
+#define PSR_FIELD_MASK 0x000f0000
+
+#define PSR_FLAGS 0x00080000
+#define PSR_CONTROL 0x00010000 /* Undocumented instruction, its use is discouraged by ARM */
+#define PSR_ALL 0x00090000
+
+#define CPSR_ALL 0
+#define SPSR_ALL 1
+#define CPSR_FLG 2
+#define SPSR_FLG 3
+#define CPSR_CTL 4
+#define SPSR_CTL 5
+
+static CONST struct asm_psr psrs[] =
+{
+ /* Valid <psr>'s */
+ {"cpsr", CPSR_ALL},
+ {"cpsr_all", CPSR_ALL},
+ {"spsr", SPSR_ALL},
+ {"spsr_all", SPSR_ALL},
+
+ /* Valid <psrf>'s */
+ {"cpsr_flg", CPSR_FLG},
+ {"spsr_flg", SPSR_FLG},
+
+ /* Valid <psrc>'s */
+ {"cpsr_c", CPSR_CTL},
+ {"cpsr_ctl", CPSR_CTL},
+ {"spsr_c", SPSR_CTL},
+ {"spsr_ctl", SPSR_CTL}
+};
+
+/* Functions called by parser */
+/* ARM instructions */
+static void do_arit PARAMS ((char *operands, unsigned long flags));
+static void do_cmp PARAMS ((char *operands, unsigned long flags));
+static void do_mov PARAMS ((char *operands, unsigned long flags));
+static void do_ldst PARAMS ((char *operands, unsigned long flags));
+static void do_ldmstm PARAMS ((char *operands, unsigned long flags));
+static void do_branch PARAMS ((char *operands, unsigned long flags));
+static void do_swi PARAMS ((char *operands, unsigned long flags));
+/* Pseudo Op codes */
+static void do_adr PARAMS ((char *operands, unsigned long flags));
+static void do_nop PARAMS ((char *operands, unsigned long flags));
+/* ARM 2 */
+static void do_mul PARAMS ((char *operands, unsigned long flags));
+static void do_mla PARAMS ((char *operands, unsigned long flags));
+/* ARM 3 */
+static void do_swap PARAMS ((char *operands, unsigned long flags));
+/* ARM 6 */
+static void do_msr PARAMS ((char *operands, unsigned long flags));
+static void do_mrs PARAMS ((char *operands, unsigned long flags));
+/* ARM 7M */
+static void do_mull PARAMS ((char *operands, unsigned long flags));
+/* ARM THUMB */
+static void do_bx PARAMS ((char *operands, unsigned long flags));
+
+/* Coprocessor Instructions */
+static void do_cdp PARAMS ((char *operands, unsigned long flags));
+static void do_lstc PARAMS ((char *operands, unsigned long flags));
+static void do_co_reg PARAMS ((char *operands, unsigned long flags));
+static void do_fp_ctrl PARAMS ((char *operands, unsigned long flags));
+static void do_fp_ldst PARAMS ((char *operands, unsigned long flags));
+static void do_fp_ldmstm PARAMS ((char *operands, unsigned long flags));
+static void do_fp_dyadic PARAMS ((char *operands, unsigned long flags));
+static void do_fp_monadic PARAMS ((char *operands, unsigned long flags));
+static void do_fp_cmp PARAMS ((char *operands, unsigned long flags));
+static void do_fp_from_reg PARAMS ((char *operands, unsigned long flags));
+static void do_fp_to_reg PARAMS ((char *operands, unsigned long flags));
+
+static void fix_new_arm PARAMS ((fragS *frag, int where,
+ short int size, expressionS *exp,
+ int pc_rel, int reloc));
+static int arm_reg_parse PARAMS ((char **ccp));
+static int arm_psr_parse PARAMS ((char **ccp));
+static void symbol_locate PARAMS ((symbolS *, CONST char *, segT,
+ valueT, fragS *));
+static int add_to_lit_pool PARAMS ((void));
+static unsigned validate_immediate PARAMS ((unsigned));
+static int validate_offset_imm PARAMS ((int, int));
+static void opcode_select PARAMS ((int));
+static void end_of_line PARAMS ((char *));
+static int reg_required_here PARAMS ((char **, int));
+static int psr_required_here PARAMS ((char **, int, int));
+static int co_proc_number PARAMS ((char **));
+static int cp_opc_expr PARAMS ((char **, int, int));
+static int cp_reg_required_here PARAMS ((char **, int));
+static int fp_reg_required_here PARAMS ((char **, int));
+static int cp_address_offset PARAMS ((char **));
+static int cp_address_required_here PARAMS ((char **));
+static int my_get_float_expression PARAMS ((char **));
+static int skip_past_comma PARAMS ((char **));
+static int walk_no_bignums PARAMS ((symbolS *));
+static int negate_data_op PARAMS ((unsigned long *,
+ unsigned long));
+static int data_op2 PARAMS ((char **));
+static int fp_op2 PARAMS ((char **));
+static long reg_list PARAMS ((char **));
+static void thumb_load_store PARAMS ((char *, int, int));
+static int decode_shift PARAMS ((char **, int));
+static int ldst_extend PARAMS ((char **, int));
+static void thumb_add_sub PARAMS ((char *, int));
+static void insert_reg PARAMS ((int));
+static void thumb_shift PARAMS ((char *, int));
+static void thumb_mov_compare PARAMS ((char *, int));
+static void set_constant_flonums PARAMS ((void));
+static valueT md_chars_to_number PARAMS ((char *, int));
+static void insert_reg_alias PARAMS ((char *, int));
+static void output_inst PARAMS ((char *));
+#ifdef OBJ_ELF
+static bfd_reloc_code_real_type arm_parse_reloc(void);
+#endif
+
+/* ARM instructions take 4bytes in the object file, Thumb instructions
+ take 2: */
+#define INSN_SIZE 4
+
+/* LONGEST_INST is the longest basic instruction name without conditions or
+ * flags.
+ * ARM7M has 4 of length 5
+ */
+
+#define LONGEST_INST 5
+
+struct asm_opcode
+{
+ CONST char * template; /* Basic string to match */
+ unsigned long value; /* Basic instruction code */
+ CONST char * comp_suffix; /* Compulsory suffix that must follow conds */
+ CONST struct asm_flg * flags; /* Bits to toggle if flag 'n' set */
+ unsigned long variants; /* Which CPU variants this exists for */
+ /* Function to call to parse args */
+ void (* parms) PARAMS ((char *, unsigned long));
+};
+
+static CONST struct asm_opcode insns[] =
+{
+/* ARM Instructions */
+ {"and", 0x00000000, NULL, s_flag, ARM_ANY, do_arit},
+ {"eor", 0x00200000, NULL, s_flag, ARM_ANY, do_arit},
+ {"sub", 0x00400000, NULL, s_flag, ARM_ANY, do_arit},
+ {"rsb", 0x00600000, NULL, s_flag, ARM_ANY, do_arit},
+ {"add", 0x00800000, NULL, s_flag, ARM_ANY, do_arit},
+ {"adc", 0x00a00000, NULL, s_flag, ARM_ANY, do_arit},
+ {"sbc", 0x00c00000, NULL, s_flag, ARM_ANY, do_arit},
+ {"rsc", 0x00e00000, NULL, s_flag, ARM_ANY, do_arit},
+ {"orr", 0x01800000, NULL, s_flag, ARM_ANY, do_arit},
+ {"bic", 0x01c00000, NULL, s_flag, ARM_ANY, do_arit},
+ {"tst", 0x01000000, NULL, cmp_flags, ARM_ANY, do_cmp},
+ {"teq", 0x01200000, NULL, cmp_flags, ARM_ANY, do_cmp},
+ {"cmp", 0x01400000, NULL, cmp_flags, ARM_ANY, do_cmp},
+ {"cmn", 0x01600000, NULL, cmp_flags, ARM_ANY, do_cmp},
+ {"mov", 0x01a00000, NULL, s_flag, ARM_ANY, do_mov},
+ {"mvn", 0x01e00000, NULL, s_flag, ARM_ANY, do_mov},
+ {"str", 0x04000000, NULL, str_flags, ARM_ANY, do_ldst},
+ {"ldr", 0x04100000, NULL, ldr_flags, ARM_ANY, do_ldst},
+ {"stm", 0x08000000, NULL, stm_flags, ARM_ANY, do_ldmstm},
+ {"ldm", 0x08100000, NULL, ldm_flags, ARM_ANY, do_ldmstm},
+ {"swi", 0x0f000000, NULL, NULL, ARM_ANY, do_swi},
+ {"bl", 0x0bfffffe, NULL, NULL, ARM_ANY, do_branch},
+ {"b", 0x0afffffe, NULL, NULL, ARM_ANY, do_branch},
+
+/* Pseudo ops */
+ {"adr", 0x028f0000, NULL, NULL, ARM_ANY, do_adr},
+ {"nop", 0x01a00000, NULL, NULL, ARM_ANY, do_nop},
+
+/* ARM 2 multiplies */
+ {"mul", 0x00000090, NULL, s_flag, ARM_2UP, do_mul},
+ {"mla", 0x00200090, NULL, s_flag, ARM_2UP, do_mla},
+
+/* ARM 3 - swp instructions */
+ {"swp", 0x01000090, NULL, byte_flag, ARM_3UP, do_swap},
+
+/* ARM 6 Coprocessor instructions */
+ {"mrs", 0x010f0000, NULL, NULL, ARM_6UP, do_mrs},
+ {"msr", 0x0120f000, NULL, NULL, ARM_6UP, do_msr},
+/* ScottB: our code uses 0x0128f000 for msr.
+ NickC: but this is wrong because the bits 16 and 19 are handled
+ by the PSR_xxx defines above. */
+
+/* ARM 7M long multiplies - need signed/unsigned flags! */
+ {"smull", 0x00c00090, NULL, s_flag, ARM_LONGMUL, do_mull},
+ {"umull", 0x00800090, NULL, s_flag, ARM_LONGMUL, do_mull},
+ {"smlal", 0x00e00090, NULL, s_flag, ARM_LONGMUL, do_mull},
+ {"umlal", 0x00a00090, NULL, s_flag, ARM_LONGMUL, do_mull},
+
+/* ARM THUMB interworking */
+ {"bx", 0x012fff10, NULL, NULL, ARM_THUMB, do_bx},
+
+/* Floating point instructions */
+ {"wfs", 0x0e200110, NULL, NULL, FPU_ALL, do_fp_ctrl},
+ {"rfs", 0x0e300110, NULL, NULL, FPU_ALL, do_fp_ctrl},
+ {"wfc", 0x0e400110, NULL, NULL, FPU_ALL, do_fp_ctrl},
+ {"rfc", 0x0e500110, NULL, NULL, FPU_ALL, do_fp_ctrl},
+ {"ldf", 0x0c100100, "sdep", NULL, FPU_ALL, do_fp_ldst},
+ {"stf", 0x0c000100, "sdep", NULL, FPU_ALL, do_fp_ldst},
+ {"lfm", 0x0c100200, NULL, lfm_flags, FPU_MEMMULTI, do_fp_ldmstm},
+ {"sfm", 0x0c000200, NULL, sfm_flags, FPU_MEMMULTI, do_fp_ldmstm},
+ {"mvf", 0x0e008100, "sde", round_flags, FPU_ALL, do_fp_monadic},
+ {"mnf", 0x0e108100, "sde", round_flags, FPU_ALL, do_fp_monadic},
+ {"abs", 0x0e208100, "sde", round_flags, FPU_ALL, do_fp_monadic},
+ {"rnd", 0x0e308100, "sde", round_flags, FPU_ALL, do_fp_monadic},
+ {"sqt", 0x0e408100, "sde", round_flags, FPU_ALL, do_fp_monadic},
+ {"log", 0x0e508100, "sde", round_flags, FPU_ALL, do_fp_monadic},
+ {"lgn", 0x0e608100, "sde", round_flags, FPU_ALL, do_fp_monadic},
+ {"exp", 0x0e708100, "sde", round_flags, FPU_ALL, do_fp_monadic},
+ {"sin", 0x0e808100, "sde", round_flags, FPU_ALL, do_fp_monadic},
+ {"cos", 0x0e908100, "sde", round_flags, FPU_ALL, do_fp_monadic},
+ {"tan", 0x0ea08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
+ {"asn", 0x0eb08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
+ {"acs", 0x0ec08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
+ {"atn", 0x0ed08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
+ {"urd", 0x0ee08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
+ {"nrm", 0x0ef08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
+ {"adf", 0x0e000100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
+ {"suf", 0x0e200100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
+ {"rsf", 0x0e300100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
+ {"muf", 0x0e100100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
+ {"dvf", 0x0e400100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
+ {"rdf", 0x0e500100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
+ {"pow", 0x0e600100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
+ {"rpw", 0x0e700100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
+ {"rmf", 0x0e800100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
+ {"fml", 0x0e900100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
+ {"fdv", 0x0ea00100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
+ {"frd", 0x0eb00100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
+ {"pol", 0x0ec00100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
+ {"cmf", 0x0e90f110, NULL, except_flag, FPU_ALL, do_fp_cmp},
+ {"cnf", 0x0eb0f110, NULL, except_flag, FPU_ALL, do_fp_cmp},
+/* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should not
+ be an optional suffix, but part of the instruction. To be compatible,
+ we accept either. */
+ {"cmfe", 0x0ed0f110, NULL, NULL, FPU_ALL, do_fp_cmp},
+ {"cnfe", 0x0ef0f110, NULL, NULL, FPU_ALL, do_fp_cmp},
+ {"flt", 0x0e000110, "sde", round_flags, FPU_ALL, do_fp_from_reg},
+ {"fix", 0x0e100110, NULL, fix_flags, FPU_ALL, do_fp_to_reg},
+
+/* Generic copressor instructions */
+ {"cdp", 0x0e000000, NULL, NULL, ARM_2UP, do_cdp},
+ {"ldc", 0x0c100000, NULL, cplong_flag, ARM_2UP, do_lstc},
+ {"stc", 0x0c000000, NULL, cplong_flag, ARM_2UP, do_lstc},
+ {"mcr", 0x0e000010, NULL, NULL, ARM_2UP, do_co_reg},
+ {"mrc", 0x0e100010, NULL, NULL, ARM_2UP, do_co_reg},
+};
+
+/* defines for various bits that we will want to toggle */
+
+#define INST_IMMEDIATE 0x02000000
+#define OFFSET_REG 0x02000000
+#define HWOFFSET_IMM 0x00400000
+#define SHIFT_BY_REG 0x00000010
+#define PRE_INDEX 0x01000000
+#define INDEX_UP 0x00800000
+#define WRITE_BACK 0x00200000
+#define MULTI_SET_PSR 0x00400000
+
+#define LITERAL_MASK 0xf000f000
+#define COND_MASK 0xf0000000
+#define OPCODE_MASK 0xfe1fffff
+#define DATA_OP_SHIFT 21
+
+/* Codes to distinguish the arithmetic instructions */
+
+#define OPCODE_AND 0
+#define OPCODE_EOR 1
+#define OPCODE_SUB 2
+#define OPCODE_RSB 3
+#define OPCODE_ADD 4
+#define OPCODE_ADC 5
+#define OPCODE_SBC 6
+#define OPCODE_RSC 7
+#define OPCODE_TST 8
+#define OPCODE_TEQ 9
+#define OPCODE_CMP 10
+#define OPCODE_CMN 11
+#define OPCODE_ORR 12
+#define OPCODE_MOV 13
+#define OPCODE_BIC 14
+#define OPCODE_MVN 15
+
+static void do_t_nop PARAMS ((char *operands));
+static void do_t_arit PARAMS ((char *operands));
+static void do_t_add PARAMS ((char *operands));
+static void do_t_asr PARAMS ((char *operands));
+static void do_t_branch9 PARAMS ((char *operands));
+static void do_t_branch12 PARAMS ((char *operands));
+static void do_t_branch23 PARAMS ((char *operands));
+static void do_t_bx PARAMS ((char *operands));
+static void do_t_compare PARAMS ((char *operands));
+static void do_t_ldmstm PARAMS ((char *operands));
+static void do_t_ldr PARAMS ((char *operands));
+static void do_t_ldrb PARAMS ((char *operands));
+static void do_t_ldrh PARAMS ((char *operands));
+static void do_t_lds PARAMS ((char *operands));
+static void do_t_lsl PARAMS ((char *operands));
+static void do_t_lsr PARAMS ((char *operands));
+static void do_t_mov PARAMS ((char *operands));
+static void do_t_push_pop PARAMS ((char *operands));
+static void do_t_str PARAMS ((char *operands));
+static void do_t_strb PARAMS ((char *operands));
+static void do_t_strh PARAMS ((char *operands));
+static void do_t_sub PARAMS ((char *operands));
+static void do_t_swi PARAMS ((char *operands));
+static void do_t_adr PARAMS ((char *operands));
+
+#define T_OPCODE_MUL 0x4340
+#define T_OPCODE_TST 0x4200
+#define T_OPCODE_CMN 0x42c0
+#define T_OPCODE_NEG 0x4240
+#define T_OPCODE_MVN 0x43c0
+
+#define T_OPCODE_ADD_R3 0x1800
+#define T_OPCODE_SUB_R3 0x1a00
+#define T_OPCODE_ADD_HI 0x4400
+#define T_OPCODE_ADD_ST 0xb000
+#define T_OPCODE_SUB_ST 0xb080
+#define T_OPCODE_ADD_SP 0xa800
+#define T_OPCODE_ADD_PC 0xa000
+#define T_OPCODE_ADD_I8 0x3000
+#define T_OPCODE_SUB_I8 0x3800
+#define T_OPCODE_ADD_I3 0x1c00
+#define T_OPCODE_SUB_I3 0x1e00
+
+#define T_OPCODE_ASR_R 0x4100
+#define T_OPCODE_LSL_R 0x4080
+#define T_OPCODE_LSR_R 0x40c0
+#define T_OPCODE_ASR_I 0x1000
+#define T_OPCODE_LSL_I 0x0000
+#define T_OPCODE_LSR_I 0x0800
+
+#define T_OPCODE_MOV_I8 0x2000
+#define T_OPCODE_CMP_I8 0x2800
+#define T_OPCODE_CMP_LR 0x4280
+#define T_OPCODE_MOV_HR 0x4600
+#define T_OPCODE_CMP_HR 0x4500
+
+#define T_OPCODE_LDR_PC 0x4800
+#define T_OPCODE_LDR_SP 0x9800
+#define T_OPCODE_STR_SP 0x9000
+#define T_OPCODE_LDR_IW 0x6800
+#define T_OPCODE_STR_IW 0x6000
+#define T_OPCODE_LDR_IH 0x8800
+#define T_OPCODE_STR_IH 0x8000
+#define T_OPCODE_LDR_IB 0x7800
+#define T_OPCODE_STR_IB 0x7000
+#define T_OPCODE_LDR_RW 0x5800
+#define T_OPCODE_STR_RW 0x5000
+#define T_OPCODE_LDR_RH 0x5a00
+#define T_OPCODE_STR_RH 0x5200
+#define T_OPCODE_LDR_RB 0x5c00
+#define T_OPCODE_STR_RB 0x5400
+
+#define T_OPCODE_PUSH 0xb400
+#define T_OPCODE_POP 0xbc00
+
+#define T_OPCODE_BRANCH 0xe7fe
+
+static int thumb_reg PARAMS ((char ** str, int hi_lo));
+
+#define THUMB_SIZE 2 /* Size of thumb instruction */
+#define THUMB_REG_LO 0x1
+#define THUMB_REG_HI 0x2
+#define THUMB_REG_ANY 0x3
+
+#define THUMB_H1 0x0080
+#define THUMB_H2 0x0040
+
+#define THUMB_ASR 0
+#define THUMB_LSL 1
+#define THUMB_LSR 2
+
+#define THUMB_MOVE 0
+#define THUMB_COMPARE 1
+
+#define THUMB_LOAD 0
+#define THUMB_STORE 1
+
+#define THUMB_PP_PC_LR 0x0100
+
+/* These three are used for immediate shifts, do not alter */
+#define THUMB_WORD 2
+#define THUMB_HALFWORD 1
+#define THUMB_BYTE 0
+
+struct thumb_opcode
+{
+ CONST char * template; /* Basic string to match */
+ unsigned long value; /* Basic instruction code */
+ int size;
+ void (* parms) PARAMS ((char *)); /* Function to call to parse args */
+};
+
+static CONST struct thumb_opcode tinsns[] =
+{
+ {"adc", 0x4140, 2, do_t_arit},
+ {"add", 0x0000, 2, do_t_add},
+ {"and", 0x4000, 2, do_t_arit},
+ {"asr", 0x0000, 2, do_t_asr},
+ {"b", T_OPCODE_BRANCH, 2, do_t_branch12},
+ {"beq", 0xd0fe, 2, do_t_branch9},
+ {"bne", 0xd1fe, 2, do_t_branch9},
+ {"bcs", 0xd2fe, 2, do_t_branch9},
+ {"bhs", 0xd2fe, 2, do_t_branch9},
+ {"bcc", 0xd3fe, 2, do_t_branch9},
+ {"bul", 0xd3fe, 2, do_t_branch9},
+ {"blo", 0xd3fe, 2, do_t_branch9},
+ {"bmi", 0xd4fe, 2, do_t_branch9},
+ {"bpl", 0xd5fe, 2, do_t_branch9},
+ {"bvs", 0xd6fe, 2, do_t_branch9},
+ {"bvc", 0xd7fe, 2, do_t_branch9},
+ {"bhi", 0xd8fe, 2, do_t_branch9},
+ {"bls", 0xd9fe, 2, do_t_branch9},
+ {"bge", 0xdafe, 2, do_t_branch9},
+ {"blt", 0xdbfe, 2, do_t_branch9},
+ {"bgt", 0xdcfe, 2, do_t_branch9},
+ {"ble", 0xddfe, 2, do_t_branch9},
+ {"bic", 0x4380, 2, do_t_arit},
+ {"bl", 0xf7fffffe, 4, do_t_branch23},
+ {"bx", 0x4700, 2, do_t_bx},
+ {"cmn", T_OPCODE_CMN, 2, do_t_arit},
+ {"cmp", 0x0000, 2, do_t_compare},
+ {"eor", 0x4040, 2, do_t_arit},
+ {"ldmia", 0xc800, 2, do_t_ldmstm},
+ {"ldr", 0x0000, 2, do_t_ldr},
+ {"ldrb", 0x0000, 2, do_t_ldrb},
+ {"ldrh", 0x0000, 2, do_t_ldrh},
+ {"ldrsb", 0x5600, 2, do_t_lds},
+ {"ldrsh", 0x5e00, 2, do_t_lds},
+ {"ldsb", 0x5600, 2, do_t_lds},
+ {"ldsh", 0x5e00, 2, do_t_lds},
+ {"lsl", 0x0000, 2, do_t_lsl},
+ {"lsr", 0x0000, 2, do_t_lsr},
+ {"mov", 0x0000, 2, do_t_mov},
+ {"mul", T_OPCODE_MUL, 2, do_t_arit},
+ {"mvn", T_OPCODE_MVN, 2, do_t_arit},
+ {"neg", T_OPCODE_NEG, 2, do_t_arit},
+ {"orr", 0x4300, 2, do_t_arit},
+ {"pop", 0xbc00, 2, do_t_push_pop},
+ {"push", 0xb400, 2, do_t_push_pop},
+ {"ror", 0x41c0, 2, do_t_arit},
+ {"sbc", 0x4180, 2, do_t_arit},
+ {"stmia", 0xc000, 2, do_t_ldmstm},
+ {"str", 0x0000, 2, do_t_str},
+ {"strb", 0x0000, 2, do_t_strb},
+ {"strh", 0x0000, 2, do_t_strh},
+ {"swi", 0xdf00, 2, do_t_swi},
+ {"sub", 0x0000, 2, do_t_sub},
+ {"tst", T_OPCODE_TST, 2, do_t_arit},
+ /* Pseudo ops: */
+ {"adr", 0x0000, 2, do_t_adr},
+ {"nop", 0x46C0, 2, do_t_nop}, /* mov r8,r8 */
+};
+
+struct reg_entry
+{
+ CONST char * name;
+ int number;
+};
+
+#define int_register(reg) ((reg) >= 0 && (reg) <= 15)
+#define cp_register(reg) ((reg) >= 32 && (reg) <= 47)
+#define fp_register(reg) ((reg) >= 16 && (reg) <= 23)
+
+#define REG_PC 15
+#define REG_LR 14
+#define REG_SP 13
+
+/* These are the standard names; Users can add aliases with .req */
+static CONST struct reg_entry reg_table[] =
+{
+ /* Processor Register Numbers */
+ {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
+ {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
+ {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
+ {"r12", 12}, {"r13", REG_SP},{"r14", REG_LR},{"r15", REG_PC},
+ /* APCS conventions */
+ {"a1", 0}, {"a2", 1}, {"a3", 2}, {"a4", 3},
+ {"v1", 4}, {"v2", 5}, {"v3", 6}, {"v4", 7}, {"v5", 8},
+ {"v6", 9}, {"sb", 9}, {"v7", 10}, {"sl", 10},
+ {"fp", 11}, {"ip", 12}, {"sp", REG_SP},{"lr", REG_LR},{"pc", REG_PC},
+ /* FP Registers */
+ {"f0", 16}, {"f1", 17}, {"f2", 18}, {"f3", 19},
+ {"f4", 20}, {"f5", 21}, {"f6", 22}, {"f7", 23},
+ {"c0", 32}, {"c1", 33}, {"c2", 34}, {"c3", 35},
+ {"c4", 36}, {"c5", 37}, {"c6", 38}, {"c7", 39},
+ {"c8", 40}, {"c9", 41}, {"c10", 42}, {"c11", 43},
+ {"c12", 44}, {"c13", 45}, {"c14", 46}, {"c15", 47},
+ {"cr0", 32}, {"cr1", 33}, {"cr2", 34}, {"cr3", 35},
+ {"cr4", 36}, {"cr5", 37}, {"cr6", 38}, {"cr7", 39},
+ {"cr8", 40}, {"cr9", 41}, {"cr10", 42}, {"cr11", 43},
+ {"cr12", 44}, {"cr13", 45}, {"cr14", 46}, {"cr15", 47},
+ {NULL, 0}
+};
+
+#define bad_args _("Bad arguments to instruction");
+#define bad_pc _("r15 not allowed here");
+
+static struct hash_control * arm_ops_hsh = NULL;
+static struct hash_control * arm_tops_hsh = NULL;
+static struct hash_control * arm_cond_hsh = NULL;
+static struct hash_control * arm_shift_hsh = NULL;
+static struct hash_control * arm_reg_hsh = NULL;
+static struct hash_control * arm_psr_hsh = NULL;
+
+/* This table describes all the machine specific pseudo-ops the assembler
+ has to support. The fields are:
+ pseudo-op name without dot
+ function to call to execute this pseudo-op
+ Integer arg to pass to the function
+ */
+
+static void s_req PARAMS ((int));
+static void s_align PARAMS ((int));
+static void s_bss PARAMS ((int));
+static void s_even PARAMS ((int));
+static void s_ltorg PARAMS ((int));
+static void s_arm PARAMS ((int));
+static void s_thumb PARAMS ((int));
+static void s_code PARAMS ((int));
+static void s_force_thumb PARAMS ((int));
+static void s_thumb_func PARAMS ((int));
+#ifdef OBJ_ELF
+static void s_arm_elf_cons PARAMS ((int));
+#endif
+
+static int my_get_expression PARAMS ((expressionS *, char **));
+
+CONST pseudo_typeS md_pseudo_table[] =
+{
+ {"req", s_req, 0}, /* Never called becasue '.req' does not start line */
+ {"bss", s_bss, 0},
+ {"align", s_align, 0},
+ {"arm", s_arm, 0},
+ {"thumb", s_thumb, 0},
+ {"code", s_code, 0},
+ {"force_thumb", s_force_thumb, 0},
+ {"thumb_func", s_thumb_func, 0},
+ {"even", s_even, 0},
+ {"ltorg", s_ltorg, 0},
+ {"pool", s_ltorg, 0},
+#ifdef OBJ_ELF
+ {"word", s_arm_elf_cons, 4},
+ {"long", s_arm_elf_cons, 4},
+#else
+ {"word", cons, 4},
+#endif
+ {"extend", float_cons, 'x'},
+ {"ldouble", float_cons, 'x'},
+ {"packed", float_cons, 'p'},
+ {0, 0, 0}
+};
+
+/* Stuff needed to resolve the label ambiguity
+ As:
+ ...
+ label: <insn>
+ may differ from:
+ ...
+ label:
+ <insn>
+*/
+
+symbolS * last_label_seen;
+static int label_is_thumb_function_name = false;
+
+/* Literal stuff */
+
+#define MAX_LITERAL_POOL_SIZE 1024
+
+typedef struct literalS
+{
+ struct expressionS exp;
+ struct arm_it * inst;
+} literalT;
+
+literalT literals[MAX_LITERAL_POOL_SIZE];
+int next_literal_pool_place = 0; /* Next free entry in the pool */
+int lit_pool_num = 1; /* Next literal pool number */
+symbolS * current_poolP = NULL;
+symbolS * symbol_make_empty PARAMS ((void));
+
+static int
+add_to_lit_pool ()
+{
+ int lit_count = 0;
+
+ if (current_poolP == NULL)
+ current_poolP = symbol_make_empty ();
+
+ /* Check if this literal value is already in the pool: */
+ while (lit_count < next_literal_pool_place)
+ {
+ if (literals[lit_count].exp.X_op == inst.reloc.exp.X_op
+ && inst.reloc.exp.X_op == O_constant
+ && literals[lit_count].exp.X_add_number == inst.reloc.exp.X_add_number
+ && literals[lit_count].exp.X_unsigned == inst.reloc.exp.X_unsigned)
+ break;
+ lit_count++;
+ }
+
+ if (lit_count == next_literal_pool_place) /* new entry */
+ {
+ if (next_literal_pool_place > MAX_LITERAL_POOL_SIZE)
+ {
+ inst.error = _("Literal Pool Overflow");
+ return FAIL;
+ }
+
+ literals[next_literal_pool_place].exp = inst.reloc.exp;
+ lit_count = next_literal_pool_place++;
+ }
+
+ inst.reloc.exp.X_op = O_symbol;
+ inst.reloc.exp.X_add_number = (lit_count) * 4 - 8;
+ inst.reloc.exp.X_add_symbol = current_poolP;
+
+ return SUCCESS;
+}
+
+/* Can't use symbol_new here, so have to create a symbol and then at
+ a later date assign it a value. Thats what these functions do. */
+static void
+symbol_locate (symbolP, name, segment, valu, frag)
+ symbolS * symbolP;
+ CONST char * name; /* It is copied, the caller can modify */
+ segT segment; /* Segment identifier (SEG_<something>) */
+ valueT valu; /* Symbol value */
+ fragS * frag; /* Associated fragment */
+{
+ unsigned int name_length;
+ char * preserved_copy_of_name;
+
+ name_length = strlen (name) + 1; /* +1 for \0 */
+ obstack_grow (&notes, name, name_length);
+ preserved_copy_of_name = obstack_finish (&notes);
+#ifdef STRIP_UNDERSCORE
+ if (preserved_copy_of_name[0] == '_')
+ preserved_copy_of_name++;
+#endif
+
+#ifdef tc_canonicalize_symbol_name
+ preserved_copy_of_name =
+ tc_canonicalize_symbol_name (preserved_copy_of_name);
+#endif
+
+ S_SET_NAME (symbolP, preserved_copy_of_name);
+
+ S_SET_SEGMENT (symbolP, segment);
+ S_SET_VALUE (symbolP, valu);
+ symbol_clear_list_pointers(symbolP);
+
+ symbolP->sy_frag = frag;
+
+ /* Link to end of symbol chain. */
+ {
+ extern int symbol_table_frozen;
+ if (symbol_table_frozen)
+ abort ();
+ }
+
+ symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
+
+ obj_symbol_new_hook (symbolP);
+
+#ifdef tc_symbol_new_hook
+ tc_symbol_new_hook (symbolP);
+#endif
+
+#ifdef DEBUG_SYMS
+ verify_symbol_chain (symbol_rootP, symbol_lastP);
+#endif /* DEBUG_SYMS */
+}
+
+symbolS *
+symbol_make_empty ()
+{
+ symbolS * symbolP;
+
+ symbolP = (symbolS *) obstack_alloc (&notes, sizeof (symbolS));
+
+ /* symbol must be born in some fixed state. This seems as good as any. */
+ memset (symbolP, 0, sizeof (symbolS));
+
+ symbolP->bsym = bfd_make_empty_symbol (stdoutput);
+ assert (symbolP->bsym != 0);
+ symbolP->bsym->udata.p = (PTR) symbolP;
+
+ return symbolP;
+}
+
+/* Check that an immediate is valid, and if so, convert it to the right format. */
+
+static unsigned int
+validate_immediate (val)
+ unsigned int val;
+{
+ unsigned int a;
+ unsigned int i;
+
+#define rotate_left(v, n) (v << n | v >> (32 - n))
+
+ for (i = 0; i < 32; i += 2)
+ if ((a = rotate_left (val, i)) <= 0xff)
+ return a | (i << 7); /* 12-bit pack: [shift-cnt,const] */
+
+ return FAIL;
+}
+
+static int
+validate_offset_imm (val, hwse)
+ int val;
+ int hwse;
+{
+ if ((hwse && (val < -255 || val > 255))
+ || (val < -4095 || val > 4095))
+ return FAIL;
+ return val;
+}
+
+
+static void
+s_req (a)
+ int a;
+{
+ as_bad (_("Invalid syntax for .req directive."));
+}
+
+static void
+s_bss (ignore)
+ int ignore;
+{
+ /* We don't support putting frags in the BSS segment, we fake it by
+ marking in_bss, then looking at s_skip for clues?.. */
+ subseg_set (bss_section, 0);
+ demand_empty_rest_of_line ();
+}
+
+static void
+s_even (ignore)
+ int ignore;
+{
+ if (!need_pass_2) /* Never make frag if expect extra pass. */
+ frag_align (1, 0, 0);
+
+ record_alignment (now_seg, 1);
+
+ demand_empty_rest_of_line ();
+}
+
+static void
+s_ltorg (internal)
+ int internal;
+{
+ int lit_count = 0;
+ char sym_name[20];
+
+ if (current_poolP == NULL)
+ {
+ /* Nothing to do */
+ if (!internal)
+ as_tsktsk (_("Nothing to put in the pool\n"));
+ return;
+ }
+
+ /* Align pool as you have word accesses */
+ /* Only make a frag if we have to ... */
+ if (!need_pass_2)
+ frag_align (2, 0, 0);
+
+ record_alignment (now_seg, 2);
+
+ if (internal)
+ as_tsktsk (_("Inserting implicit pool at change of section"));
+
+ sprintf (sym_name, "$$lit_\002%x", lit_pool_num++);
+
+ symbol_locate (current_poolP, sym_name, now_seg,
+ (valueT) frag_now_fix (), frag_now);
+ symbol_table_insert (current_poolP);
+
+ ARM_SET_THUMB (current_poolP, thumb_mode);
+
+#if defined OBJ_COFF || defined OBJ_ELF
+ ARM_SET_INTERWORK (current_poolP, support_interwork);
+#endif
+
+ while (lit_count < next_literal_pool_place)
+ /* First output the expression in the instruction to the pool */
+ emit_expr (&(literals[lit_count++].exp), 4); /* .word */
+
+ next_literal_pool_place = 0;
+ current_poolP = NULL;
+}
+
+static void
+s_align (unused) /* Same as s_align_ptwo but align 0 => align 2 */
+ int unused;
+{
+ register int temp;
+ register long temp_fill;
+ long max_alignment = 15;
+
+ temp = get_absolute_expression ();
+ if (temp > max_alignment)
+ as_bad (_("Alignment too large: %d. assumed."), temp = max_alignment);
+ else if (temp < 0)
+ {
+ as_bad (_("Alignment negative. 0 assumed."));
+ temp = 0;
+ }
+
+ if (*input_line_pointer == ',')
+ {
+ input_line_pointer++;
+ temp_fill = get_absolute_expression ();
+ }
+ else
+ temp_fill = 0;
+
+ if (!temp)
+ temp = 2;
+
+ /* Only make a frag if we HAVE to. . . */
+ if (temp && !need_pass_2)
+ frag_align (temp, (int) temp_fill, 0);
+ demand_empty_rest_of_line ();
+
+ record_alignment (now_seg, temp);
+}
+
+static void
+s_force_thumb (ignore)
+ int ignore;
+{
+ /* If we are not already in thumb mode go into it, EVEN if
+ the target processor does not support thumb instructions.
+ This is used by gcc/config/arm/lib1funcs.asm for example
+ to compile interworking support functions even if the
+ target processor should not support interworking. */
+
+ if (! thumb_mode)
+ {
+ thumb_mode = 1;
+
+ record_alignment (now_seg, 1);
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+static void
+s_thumb_func (ignore)
+ int ignore;
+{
+ /* The following label is the name/address of the start of a Thumb function.
+ We need to know this for the interworking support. */
+
+ label_is_thumb_function_name = true;
+
+ demand_empty_rest_of_line ();
+}
+
+static void
+opcode_select (width)
+ int width;
+{
+ switch (width)
+ {
+ case 16:
+ if (! thumb_mode)
+ {
+ if (! (cpu_variant & ARM_THUMB))
+ as_bad (_("selected processor does not support THUMB opcodes"));
+ thumb_mode = 1;
+ /* No need to force the alignment, since we will have been
+ coming from ARM mode, which is word-aligned. */
+ record_alignment (now_seg, 1);
+ }
+ break;
+
+ case 32:
+ if (thumb_mode)
+ {
+ if ((cpu_variant & ARM_ANY) == ARM_THUMB)
+ as_bad (_("selected processor does not support ARM opcodes"));
+ thumb_mode = 0;
+ if (!need_pass_2)
+ frag_align (2, 0, 0);
+ record_alignment (now_seg, 1);
+ }
+ break;
+
+ default:
+ as_bad (_("invalid instruction size selected (%d)"), width);
+ }
+}
+
+static void
+s_arm (ignore)
+ int ignore;
+{
+ opcode_select (32);
+ demand_empty_rest_of_line ();
+}
+
+static void
+s_thumb (ignore)
+ int ignore;
+{
+ opcode_select (16);
+ demand_empty_rest_of_line ();
+}
+
+static void
+s_code (unused)
+ int unused;
+{
+ register int temp;
+
+ temp = get_absolute_expression ();
+ switch (temp)
+ {
+ case 16:
+ case 32:
+ opcode_select (temp);
+ break;
+
+ default:
+ as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
+ }
+}
+
+static void
+end_of_line (str)
+ char * str;
+{
+ while (*str == ' ')
+ str++;
+
+ if (*str != '\0')
+ inst.error = _("Garbage following instruction");
+}
+
+static int
+skip_past_comma (str)
+ char ** str;
+{
+ char *p = *str, c;
+ int comma = 0;
+
+ while ((c = *p) == ' ' || c == ',')
+ {
+ p++;
+ if (c == ',' && comma++)
+ return FAIL;
+ }
+
+ if (c == '\0')
+ return FAIL;
+
+ *str = p;
+ return comma ? SUCCESS : FAIL;
+}
+
+/* A standard register must be given at this point. Shift is the place to
+ put it in the instruction. */
+
+static int
+reg_required_here (str, shift)
+ char ** str;
+ int shift;
+{
+ static char buff [128]; /* XXX */
+ int reg;
+ char * start = *str;
+
+ if ((reg = arm_reg_parse (str)) != FAIL && int_register (reg))
+ {
+ if (shift >= 0)
+ inst.instruction |= reg << shift;
+ return reg;
+ }
+
+ /* Restore the start point, we may have got a reg of the wrong class. */
+ *str = start;
+
+ /* In the few cases where we might be able to accept something else
+ this error can be overridden */
+ sprintf (buff, _("Register expected, not '%.100s'"), start);
+ inst.error = buff;
+
+ return FAIL;
+}
+
+static int
+psr_required_here (str, cpsr, spsr)
+ char ** str;
+ int cpsr;
+ int spsr;
+{
+ int psr;
+ char * start = *str;
+ psr = arm_psr_parse (str);
+
+ if (psr == cpsr || psr == spsr)
+ {
+ if (psr == spsr)
+ inst.instruction |= 1 << 22;
+
+ return SUCCESS;
+ }
+
+ /* In the few cases where we might be able to accept something else
+ this error can be overridden */
+ inst.error = _("<psr(f)> expected");
+
+ /* Restore the start point. */
+ *str = start;
+ return FAIL;
+}
+
+static int
+co_proc_number (str)
+ char **str;
+{
+ int processor, pchar;
+
+ while (**str == ' ')
+ (*str)++;
+
+ /* The data sheet seems to imply that just a number on its own is valid
+ here, but the RISC iX assembler seems to accept a prefix 'p'. We will
+ accept either. */
+ if (**str == 'p' || **str == 'P')
+ (*str)++;
+
+ pchar = *(*str)++;
+ if (pchar >= '0' && pchar <= '9')
+ {
+ processor = pchar - '0';
+ if (**str >= '0' && **str <= '9')
+ {
+ processor = processor * 10 + *(*str)++ - '0';
+ if (processor > 15)
+ {
+ inst.error = _("Illegal co-processor number");
+ return FAIL;
+ }
+ }
+ }
+ else
+ {
+ inst.error = _("Bad or missing co-processor number");
+ return FAIL;
+ }
+
+ inst.instruction |= processor << 8;
+ return SUCCESS;
+}
+
+static int
+cp_opc_expr (str, where, length)
+ char ** str;
+ int where;
+ int length;
+{
+ expressionS expr;
+
+ while (**str == ' ')
+ (*str)++;
+
+ memset (&expr, '\0', sizeof (expr));
+
+ if (my_get_expression (&expr, str))
+ return FAIL;
+ if (expr.X_op != O_constant)
+ {
+ inst.error = _("bad or missing expression");
+ return FAIL;
+ }
+
+ if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
+ {
+ inst.error = _("immediate co-processor expression too large");
+ return FAIL;
+ }
+
+ inst.instruction |= expr.X_add_number << where;
+ return SUCCESS;
+}
+
+static int
+cp_reg_required_here (str, where)
+ char ** str;
+ int where;
+{
+ int reg;
+ char * start = *str;
+
+ if ((reg = arm_reg_parse (str)) != FAIL && cp_register (reg))
+ {
+ reg &= 15;
+ inst.instruction |= reg << where;
+ return reg;
+ }
+
+ /* In the few cases where we might be able to accept something else
+ this error can be overridden */
+ inst.error = _("Co-processor register expected");
+
+ /* Restore the start point */
+ *str = start;
+ return FAIL;
+}
+
+static int
+fp_reg_required_here (str, where)
+ char ** str;
+ int where;
+{
+ int reg;
+ char * start = *str;
+
+ if ((reg = arm_reg_parse (str)) != FAIL && fp_register (reg))
+ {
+ reg &= 7;
+ inst.instruction |= reg << where;
+ return reg;
+ }
+
+ /* In the few cases where we might be able to accept something else
+ this error can be overridden */
+ inst.error = _("Floating point register expected");
+
+ /* Restore the start point */
+ *str = start;
+ return FAIL;
+}
+
+static int
+cp_address_offset (str)
+ char ** str;
+{
+ int offset;
+
+ while (**str == ' ')
+ (*str)++;
+
+ if (! is_immediate_prefix (**str))
+ {
+ inst.error = _("immediate expression expected");
+ return FAIL;
+ }
+
+ (*str)++;
+
+ if (my_get_expression (& inst.reloc.exp, str))
+ return FAIL;
+
+ if (inst.reloc.exp.X_op == O_constant)
+ {
+ offset = inst.reloc.exp.X_add_number;
+
+ if (offset & 3)
+ {
+ inst.error = _("co-processor address must be word aligned");
+ return FAIL;
+ }
+
+ if (offset > 1023 || offset < -1023)
+ {
+ inst.error = _("offset too large");
+ return FAIL;
+ }
+
+ if (offset >= 0)
+ inst.instruction |= INDEX_UP;
+ else
+ offset = -offset;
+
+ inst.instruction |= offset >> 2;
+ }
+ else
+ inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
+
+ return SUCCESS;
+}
+
+static int
+cp_address_required_here (str)
+ char ** str;
+{
+ char * p = * str;
+ int pre_inc = 0;
+ int write_back = 0;
+
+ if (*p == '[')
+ {
+ int reg;
+
+ p++;
+ while (*p == ' ')
+ p++;
+
+ if ((reg = reg_required_here (& p, 16)) == FAIL)
+ return FAIL;
+
+ while (*p == ' ')
+ p++;
+
+ if (*p == ']')
+ {
+ p++;
+
+ if (skip_past_comma (& p) == SUCCESS)
+ {
+ /* [Rn], #expr */
+ write_back = WRITE_BACK;
+
+ if (reg == REG_PC)
+ {
+ inst.error = _("pc may not be used in post-increment");
+ return FAIL;
+ }
+
+ if (cp_address_offset (& p) == FAIL)
+ return FAIL;
+ }
+ else
+ pre_inc = PRE_INDEX | INDEX_UP;
+ }
+ else
+ {
+ /* '['Rn, #expr']'[!] */
+
+ if (skip_past_comma (& p) == FAIL)
+ {
+ inst.error = _("pre-indexed expression expected");
+ return FAIL;
+ }
+
+ pre_inc = PRE_INDEX;
+
+ if (cp_address_offset (& p) == FAIL)
+ return FAIL;
+
+ while (*p == ' ')
+ p++;
+
+ if (*p++ != ']')
+ {
+ inst.error = _("missing ]");
+ return FAIL;
+ }
+
+ while (*p == ' ')
+ p++;
+
+ if (*p == '!')
+ {
+ if (reg == REG_PC)
+ {
+ inst.error = _("pc may not be used with write-back");
+ return FAIL;
+ }
+
+ p++;
+ write_back = WRITE_BACK;
+ }
+ }
+ }
+ else
+ {
+ if (my_get_expression (&inst.reloc.exp, &p))
+ return FAIL;
+
+ inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
+ inst.reloc.exp.X_add_number -= 8; /* PC rel adjust */
+ inst.reloc.pc_rel = 1;
+ inst.instruction |= (REG_PC << 16);
+ pre_inc = PRE_INDEX;
+ }
+
+ inst.instruction |= write_back | pre_inc;
+ *str = p;
+ return SUCCESS;
+}
+
+static void
+do_nop (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ /* Do nothing really */
+ inst.instruction |= flags; /* This is pointless */
+ end_of_line (str);
+ return;
+}
+
+static void
+do_mrs (str, flags)
+ char *str;
+ unsigned long flags;
+{
+ /* Only one syntax */
+ while (*str == ' ')
+ str++;
+
+ if (reg_required_here (&str, 12) == FAIL)
+ {
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || psr_required_here (& str, CPSR_ALL, SPSR_ALL) == FAIL)
+ {
+ inst.error = _("<psr> expected");
+ return;
+ }
+
+ inst.instruction |= flags;
+ end_of_line (str);
+ return;
+}
+
+/* Three possible forms: "<psr>, Rm", "<psrf>, Rm", "<psrf>, #expression" */
+static void
+do_msr (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ int reg;
+
+ while (*str == ' ')
+ str ++;
+
+ if (psr_required_here (&str, CPSR_ALL, SPSR_ALL) == SUCCESS)
+ {
+ inst.instruction |= PSR_ALL;
+
+ /* Sytax should be "<psr>, Rm" */
+ if (skip_past_comma (&str) == FAIL
+ || (reg = reg_required_here (&str, 0)) == FAIL)
+ {
+ inst.error = bad_args;
+ return;
+ }
+ }
+ else
+ {
+ if (psr_required_here (& str, CPSR_FLG, SPSR_FLG) == SUCCESS)
+ inst.instruction |= PSR_FLAGS;
+ else if (psr_required_here (& str, CPSR_CTL, SPSR_CTL) == SUCCESS)
+ inst.instruction |= PSR_CONTROL;
+ else
+ {
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL)
+ {
+ inst.error = bad_args;
+ return;
+ }
+
+ /* Syntax could be "<psrf>, rm", "<psrf>, #expression" */
+
+ if ((reg = reg_required_here (& str, 0)) != FAIL)
+ ;
+ /* Immediate expression */
+ else if (is_immediate_prefix (* str))
+ {
+ str ++;
+ inst.error = NULL;
+
+ if (my_get_expression (& inst.reloc.exp, & str))
+ {
+ inst.error = _("Register or shift expression expected");
+ return;
+ }
+
+ if (inst.reloc.exp.X_add_symbol)
+ {
+ inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
+ inst.reloc.pc_rel = 0;
+ }
+ else
+ {
+ unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
+ if (value == FAIL)
+ {
+ inst.error = _("Invalid constant");
+ return;
+ }
+
+ inst.instruction |= value;
+ }
+
+ flags |= INST_IMMEDIATE;
+ }
+ else
+ {
+ inst.error = _("Error: unrecognised syntax for second argument to msr instruction");
+ return;
+ }
+ }
+
+ inst.error = NULL;
+ inst.instruction |= flags;
+ end_of_line (str);
+ return;
+}
+
+/* Long Multiply Parser
+ UMULL RdLo, RdHi, Rm, Rs
+ SMULL RdLo, RdHi, Rm, Rs
+ UMLAL RdLo, RdHi, Rm, Rs
+ SMLAL RdLo, RdHi, Rm, Rs
+*/
+static void
+do_mull (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ int rdlo, rdhi, rm, rs;
+
+ /* only one format "rdlo, rdhi, rm, rs" */
+ while (*str == ' ')
+ str++;
+
+ if ((rdlo = reg_required_here (&str, 12)) == FAIL)
+ {
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || (rdhi = reg_required_here (&str, 16)) == FAIL)
+ {
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || (rm = reg_required_here (&str, 0)) == FAIL)
+ {
+ inst.error = bad_args;
+ return;
+ }
+
+ /* rdhi, rdlo and rm must all be different */
+ if (rdlo == rdhi || rdlo == rm || rdhi == rm)
+ as_tsktsk (_("rdhi, rdlo and rm must all be different"));
+
+ if (skip_past_comma (&str) == FAIL
+ || (rs = reg_required_here (&str, 8)) == FAIL)
+ {
+ inst.error = bad_args;
+ return;
+ }
+
+ if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
+ {
+ inst.error = bad_pc;
+ return;
+ }
+
+ inst.instruction |= flags;
+ end_of_line (str);
+ return;
+}
+
+static void
+do_mul (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ int rd, rm;
+
+ /* only one format "rd, rm, rs" */
+ while (*str == ' ')
+ str++;
+
+ if ((rd = reg_required_here (&str, 16)) == FAIL)
+ {
+ inst.error = bad_args;
+ return;
+ }
+
+ if (rd == REG_PC)
+ {
+ inst.error = bad_pc;
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || (rm = reg_required_here (&str, 0)) == FAIL)
+ {
+ inst.error = bad_args;
+ return;
+ }
+
+ if (rm == REG_PC)
+ {
+ inst.error = bad_pc;
+ return;
+ }
+
+ if (rm == rd)
+ as_tsktsk (_("rd and rm should be different in mul"));
+
+ if (skip_past_comma (&str) == FAIL
+ || (rm = reg_required_here (&str, 8)) == FAIL)
+ {
+ inst.error = bad_args;
+ return;
+ }
+
+ if (rm == REG_PC)
+ {
+ inst.error = bad_pc;
+ return;
+ }
+
+ inst.instruction |= flags;
+ end_of_line (str);
+ return;
+}
+
+static void
+do_mla (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ int rd, rm;
+
+ /* only one format "rd, rm, rs, rn" */
+ while (*str == ' ')
+ str++;
+
+ if ((rd = reg_required_here (&str, 16)) == FAIL)
+ {
+ inst.error = bad_args;
+ return;
+ }
+
+ if (rd == REG_PC)
+ {
+ inst.error = bad_pc;
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || (rm = reg_required_here (&str, 0)) == FAIL)
+ {
+ inst.error = bad_args;
+ return;
+ }
+
+ if (rm == REG_PC)
+ {
+ inst.error = bad_pc;
+ return;
+ }
+
+ if (rm == rd)
+ as_tsktsk (_("rd and rm should be different in mla"));
+
+ if (skip_past_comma (&str) == FAIL
+ || (rd = reg_required_here (&str, 8)) == FAIL
+ || skip_past_comma (&str) == FAIL
+ || (rm = reg_required_here (&str, 12)) == FAIL)
+ {
+ inst.error = bad_args;
+ return;
+ }
+
+ if (rd == REG_PC || rm == REG_PC)
+ {
+ inst.error = bad_pc;
+ return;
+ }
+
+ inst.instruction |= flags;
+ end_of_line (str);
+ return;
+}
+
+/* Returns the index into fp_values of a floating point number, or -1 if
+ not in the table. */
+static int
+my_get_float_expression (str)
+ char ** str;
+{
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ char * save_in;
+ expressionS exp;
+ int i;
+ int j;
+
+ memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
+ /* Look for a raw floating point number */
+ if ((save_in = atof_ieee (*str, 'x', words)) != NULL
+ && (is_end_of_line [(int)(*save_in)] || *save_in == '\0'))
+ {
+ for (i = 0; i < NUM_FLOAT_VALS; i++)
+ {
+ for (j = 0; j < MAX_LITTLENUMS; j++)
+ {
+ if (words[j] != fp_values[i][j])
+ break;
+ }
+
+ if (j == MAX_LITTLENUMS)
+ {
+ *str = save_in;
+ return i;
+ }
+ }
+ }
+
+ /* Try and parse a more complex expression, this will probably fail
+ unless the code uses a floating point prefix (eg "0f") */
+ save_in = input_line_pointer;
+ input_line_pointer = *str;
+ if (expression (&exp) == absolute_section
+ && exp.X_op == O_big
+ && exp.X_add_number < 0)
+ {
+ /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
+ Ditto for 15. */
+ if (gen_to_words (words, 5, (long)15) == 0)
+ {
+ for (i = 0; i < NUM_FLOAT_VALS; i++)
+ {
+ for (j = 0; j < MAX_LITTLENUMS; j++)
+ {
+ if (words[j] != fp_values[i][j])
+ break;
+ }
+
+ if (j == MAX_LITTLENUMS)
+ {
+ *str = input_line_pointer;
+ input_line_pointer = save_in;
+ return i;
+ }
+ }
+ }
+ }
+
+ *str = input_line_pointer;
+ input_line_pointer = save_in;
+ return -1;
+}
+
+/* Return true if anything in the expression is a bignum */
+static int
+walk_no_bignums (sp)
+ symbolS * sp;
+{
+ if (sp->sy_value.X_op == O_big)
+ return 1;
+
+ if (sp->sy_value.X_add_symbol)
+ {
+ return (walk_no_bignums (sp->sy_value.X_add_symbol)
+ || (sp->sy_value.X_op_symbol
+ && walk_no_bignums (sp->sy_value.X_op_symbol)));
+ }
+
+ return 0;
+}
+
+static int
+my_get_expression (ep, str)
+ expressionS * ep;
+ char ** str;
+{
+ char * save_in;
+ segT seg;
+
+ save_in = input_line_pointer;
+ input_line_pointer = *str;
+ seg = expression (ep);
+
+#ifdef OBJ_AOUT
+ if (seg != absolute_section
+ && seg != text_section
+ && seg != data_section
+ && seg != bss_section
+ && seg != undefined_section)
+ {
+ inst.error = _("bad_segment");
+ *str = input_line_pointer;
+ input_line_pointer = save_in;
+ return 1;
+ }
+#endif
+
+ /* Get rid of any bignums now, so that we don't generate an error for which
+ we can't establish a line number later on. Big numbers are never valid
+ in instructions, which is where this routine is always called. */
+ if (ep->X_op == O_big
+ || (ep->X_add_symbol
+ && (walk_no_bignums (ep->X_add_symbol)
+ || (ep->X_op_symbol
+ && walk_no_bignums (ep->X_op_symbol)))))
+ {
+ inst.error = _("Invalid constant");
+ *str = input_line_pointer;
+ input_line_pointer = save_in;
+ return 1;
+ }
+
+ *str = input_line_pointer;
+ input_line_pointer = save_in;
+ return 0;
+}
+
+/* unrestrict should be one if <shift> <register> is permitted for this
+ instruction */
+
+static int
+decode_shift (str, unrestrict)
+ char ** str;
+ int unrestrict;
+{
+ struct asm_shift * shft;
+ char * p;
+ char c;
+
+ while (**str == ' ')
+ (*str)++;
+
+ for (p = *str; isalpha (*p); p++)
+ ;
+
+ if (p == *str)
+ {
+ inst.error = _("Shift expression expected");
+ return FAIL;
+ }
+
+ c = *p;
+ *p = '\0';
+ shft = (struct asm_shift *) hash_find (arm_shift_hsh, *str);
+ *p = c;
+ if (shft)
+ {
+ if (!strncmp (*str, "rrx", 3)
+ || !strncmp (*str, "RRX", 3))
+ {
+ *str = p;
+ inst.instruction |= shft->value;
+ return SUCCESS;
+ }
+
+ while (*p == ' ')
+ p++;
+
+ if (unrestrict && reg_required_here (&p, 8) != FAIL)
+ {
+ inst.instruction |= shft->value | SHIFT_BY_REG;
+ *str = p;
+ return SUCCESS;
+ }
+ else if (is_immediate_prefix (* p))
+ {
+ inst.error = NULL;
+ p++;
+ if (my_get_expression (&inst.reloc.exp, &p))
+ return FAIL;
+
+ /* Validate some simple #expressions */
+ if (inst.reloc.exp.X_op == O_constant)
+ {
+ unsigned num = inst.reloc.exp.X_add_number;
+
+ /* Reject operations greater than 32, or lsl #32 */
+ if (num > 32 || (num == 32 && shft->value == 0))
+ {
+ inst.error = _("Invalid immediate shift");
+ return FAIL;
+ }
+
+ /* Shifts of zero should be converted to lsl (which is zero)*/
+ if (num == 0)
+ {
+ *str = p;
+ return SUCCESS;
+ }
+
+ /* Shifts of 32 are encoded as 0, for those shifts that
+ support it. */
+ if (num == 32)
+ num = 0;
+
+ inst.instruction |= (num << 7) | shft->value;
+ *str = p;
+ return SUCCESS;
+ }
+
+ inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
+ inst.reloc.pc_rel = 0;
+ inst.instruction |= shft->value;
+ *str = p;
+ return SUCCESS;
+ }
+ else
+ {
+ inst.error = unrestrict ? _("shift requires register or #expression")
+ : _("shift requires #expression");
+ *str = p;
+ return FAIL;
+ }
+ }
+
+ inst.error = _("Shift expression expected");
+ return FAIL;
+}
+
+/* Do those data_ops which can take a negative immediate constant */
+/* by altering the instuction. A bit of a hack really */
+/* MOV <-> MVN
+ AND <-> BIC
+ ADC <-> SBC
+ by inverting the second operand, and
+ ADD <-> SUB
+ CMP <-> CMN
+ by negating the second operand.
+*/
+static int
+negate_data_op (instruction, value)
+ unsigned long * instruction;
+ unsigned long value;
+{
+ int op, new_inst;
+ unsigned long negated, inverted;
+
+ negated = validate_immediate (-value);
+ inverted = validate_immediate (~value);
+
+ op = (*instruction >> DATA_OP_SHIFT) & 0xf;
+ switch (op)
+ {
+ /* First negates */
+ case OPCODE_SUB: /* ADD <-> SUB */
+ new_inst = OPCODE_ADD;
+ value = negated;
+ break;
+
+ case OPCODE_ADD:
+ new_inst = OPCODE_SUB;
+ value = negated;
+ break;
+
+ case OPCODE_CMP: /* CMP <-> CMN */
+ new_inst = OPCODE_CMN;
+ value = negated;
+ break;
+
+ case OPCODE_CMN:
+ new_inst = OPCODE_CMP;
+ value = negated;
+ break;
+
+ /* Now Inverted ops */
+ case OPCODE_MOV: /* MOV <-> MVN */
+ new_inst = OPCODE_MVN;
+ value = inverted;
+ break;
+
+ case OPCODE_MVN:
+ new_inst = OPCODE_MOV;
+ value = inverted;
+ break;
+
+ case OPCODE_AND: /* AND <-> BIC */
+ new_inst = OPCODE_BIC;
+ value = inverted;
+ break;
+
+ case OPCODE_BIC:
+ new_inst = OPCODE_AND;
+ value = inverted;
+ break;
+
+ case OPCODE_ADC: /* ADC <-> SBC */
+ new_inst = OPCODE_SBC;
+ value = inverted;
+ break;
+
+ case OPCODE_SBC:
+ new_inst = OPCODE_ADC;
+ value = inverted;
+ break;
+
+ /* We cannot do anything */
+ default:
+ return FAIL;
+ }
+
+ if (value == FAIL)
+ return FAIL;
+
+ *instruction &= OPCODE_MASK;
+ *instruction |= new_inst << DATA_OP_SHIFT;
+ return value;
+}
+
+static int
+data_op2 (str)
+ char ** str;
+{
+ int value;
+ expressionS expr;
+
+ while (**str == ' ')
+ (*str)++;
+
+ if (reg_required_here (str, 0) != FAIL)
+ {
+ if (skip_past_comma (str) == SUCCESS)
+ {
+ /* Shift operation on register */
+ return decode_shift (str, NO_SHIFT_RESTRICT);
+ }
+ return SUCCESS;
+ }
+ else
+ {
+ /* Immediate expression */
+ if (is_immediate_prefix (**str))
+ {
+ (*str)++;
+ inst.error = NULL;
+ if (my_get_expression (&inst.reloc.exp, str))
+ return FAIL;
+
+ if (inst.reloc.exp.X_add_symbol)
+ {
+ inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
+ inst.reloc.pc_rel = 0;
+ }
+ else
+ {
+ if (skip_past_comma (str) == SUCCESS)
+ {
+ /* #x, y -- ie explicit rotation by Y */
+ if (my_get_expression (&expr, str))
+ return FAIL;
+
+ if (expr.X_op != O_constant)
+ {
+ inst.error = _("Constant expression expected");
+ return FAIL;
+ }
+
+ /* Rotate must be a multiple of 2 */
+ if (((unsigned) expr.X_add_number) > 30
+ || (expr.X_add_number & 1) != 0
+ || ((unsigned) inst.reloc.exp.X_add_number) > 255)
+ {
+ inst.error = _("Invalid constant");
+ return FAIL;
+ }
+ inst.instruction |= INST_IMMEDIATE;
+ inst.instruction |= inst.reloc.exp.X_add_number;
+ inst.instruction |= expr.X_add_number << 7;
+ return SUCCESS;
+ }
+
+ /* Implicit rotation, select a suitable one */
+ value = validate_immediate (inst.reloc.exp.X_add_number);
+
+ if (value == FAIL)
+ {
+ /* Can't be done, perhaps the code reads something like
+ "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be ok */
+ if ((value = negate_data_op (&inst.instruction,
+ inst.reloc.exp.X_add_number))
+ == FAIL)
+ {
+ inst.error = _("Invalid constant");
+ return FAIL;
+ }
+ }
+
+ inst.instruction |= value;
+ }
+
+ inst.instruction |= INST_IMMEDIATE;
+ return SUCCESS;
+ }
+
+ (*str)++;
+ inst.error = _("Register or shift expression expected");
+ return FAIL;
+ }
+}
+
+static int
+fp_op2 (str)
+ char ** str;
+{
+ while (**str == ' ')
+ (*str)++;
+
+ if (fp_reg_required_here (str, 0) != FAIL)
+ return SUCCESS;
+ else
+ {
+ /* Immediate expression */
+ if (*((*str)++) == '#')
+ {
+ int i;
+
+ inst.error = NULL;
+ while (**str == ' ')
+ (*str)++;
+
+ /* First try and match exact strings, this is to guarantee that
+ some formats will work even for cross assembly */
+
+ for (i = 0; fp_const[i]; i++)
+ {
+ if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
+ {
+ char *start = *str;
+
+ *str += strlen (fp_const[i]);
+ if (is_end_of_line[(int)**str] || **str == '\0')
+ {
+ inst.instruction |= i + 8;
+ return SUCCESS;
+ }
+ *str = start;
+ }
+ }
+
+ /* Just because we didn't get a match doesn't mean that the
+ constant isn't valid, just that it is in a format that we
+ don't automatically recognize. Try parsing it with
+ the standard expression routines. */
+ if ((i = my_get_float_expression (str)) >= 0)
+ {
+ inst.instruction |= i + 8;
+ return SUCCESS;
+ }
+
+ inst.error = _("Invalid floating point immediate expression");
+ return FAIL;
+ }
+ inst.error = _("Floating point register or immediate expression expected");
+ return FAIL;
+ }
+}
+
+static void
+do_arit (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ while (*str == ' ')
+ str++;
+
+ if (reg_required_here (&str, 12) == FAIL
+ || skip_past_comma (&str) == FAIL
+ || reg_required_here (&str, 16) == FAIL
+ || skip_past_comma (&str) == FAIL
+ || data_op2 (&str) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ inst.instruction |= flags;
+ end_of_line (str);
+ return;
+}
+
+static void
+do_adr (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ /* This is a pseudo-op of the form "adr rd, label" to be converted
+ into a relative address of the form "add rd, pc, #label-.-8" */
+
+ while (*str == ' ')
+ str++;
+
+ if (reg_required_here (&str, 12) == FAIL
+ || skip_past_comma (&str) == FAIL
+ || my_get_expression (&inst.reloc.exp, &str))
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+ /* Frag hacking will turn this into a sub instruction if the offset turns
+ out to be negative. */
+ inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
+ inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
+ inst.reloc.pc_rel = 1;
+ inst.instruction |= flags;
+ end_of_line (str);
+ return;
+}
+
+static void
+do_cmp (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ while (*str == ' ')
+ str++;
+
+ if (reg_required_here (&str, 16) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || data_op2 (&str) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ inst.instruction |= flags;
+ if ((flags & 0x0000f000) == 0)
+ inst.instruction |= CONDS_BIT;
+
+ end_of_line (str);
+ return;
+}
+
+static void
+do_mov (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ while (*str == ' ')
+ str++;
+
+ if (reg_required_here (&str, 12) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || data_op2 (&str) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ inst.instruction |= flags;
+ end_of_line (str);
+ return;
+}
+
+static int
+ldst_extend (str, hwse)
+ char ** str;
+ int hwse;
+{
+ int add = INDEX_UP;
+
+ switch (**str)
+ {
+ case '#':
+ case '$':
+ (*str)++;
+ if (my_get_expression (& inst.reloc.exp, str))
+ return FAIL;
+
+ if (inst.reloc.exp.X_op == O_constant)
+ {
+ int value = inst.reloc.exp.X_add_number;
+
+ if ((hwse && (value < -255 || value > 255))
+ || (value < -4095 || value > 4095))
+ {
+ inst.error = _("address offset too large");
+ return FAIL;
+ }
+
+ if (value < 0)
+ {
+ value = -value;
+ add = 0;
+ }
+
+ /* Halfword and signextension instructions have the
+ immediate value split across bits 11..8 and bits 3..0 */
+ if (hwse)
+ inst.instruction |= add | HWOFFSET_IMM | (value >> 4) << 8 | value & 0xF;
+ else
+ inst.instruction |= add | value;
+ }
+ else
+ {
+ if (hwse)
+ {
+ inst.instruction |= HWOFFSET_IMM;
+ inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
+ }
+ else
+ inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
+ inst.reloc.pc_rel = 0;
+ }
+ return SUCCESS;
+
+ case '-':
+ add = 0; /* and fall through */
+ case '+':
+ (*str)++; /* and fall through */
+ default:
+ if (reg_required_here (str, 0) == FAIL)
+ return FAIL;
+
+ if (hwse)
+ inst.instruction |= add;
+ else
+ {
+ inst.instruction |= add | OFFSET_REG;
+ if (skip_past_comma (str) == SUCCESS)
+ return decode_shift (str, SHIFT_RESTRICT);
+ }
+
+ return SUCCESS;
+ }
+}
+
+static void
+do_ldst (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ int halfword = 0;
+ int pre_inc = 0;
+ int conflict_reg;
+ int value;
+
+ /* This is not ideal, but it is the simplest way of dealing with the
+ ARM7T halfword instructions (since they use a different
+ encoding, but the same mnemonic): */
+ if (halfword = ((flags & 0x80000000) != 0))
+ {
+ /* This is actually a load/store of a halfword, or a
+ signed-extension load */
+ if ((cpu_variant & ARM_HALFWORD) == 0)
+ {
+ inst.error
+ = _("Processor does not support halfwords or signed bytes");
+ return;
+ }
+
+ inst.instruction = (inst.instruction & COND_MASK)
+ | (flags & ~COND_MASK);
+
+ flags = 0;
+ }
+
+ while (*str == ' ')
+ str++;
+
+ if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (& str) == FAIL)
+ {
+ inst.error = _("Address expected");
+ return;
+ }
+
+ if (*str == '[')
+ {
+ int reg;
+
+ str++;
+ while (*str == ' ')
+ str++;
+
+ if ((reg = reg_required_here (&str, 16)) == FAIL)
+ return;
+
+ conflict_reg = (((conflict_reg == reg)
+ && (inst.instruction & LOAD_BIT))
+ ? 1 : 0);
+
+ while (*str == ' ')
+ str++;
+
+ if (*str == ']')
+ {
+ str++;
+ if (skip_past_comma (&str) == SUCCESS)
+ {
+ /* [Rn],... (post inc) */
+ if (ldst_extend (&str, halfword) == FAIL)
+ return;
+ if (conflict_reg)
+ as_warn (_("destination register same as write-back base\n"));
+ }
+ else
+ {
+ /* [Rn] */
+ if (halfword)
+ inst.instruction |= HWOFFSET_IMM;
+
+ while (*str == ' ')
+ str++;
+
+ if (*str == '!')
+ {
+ if (conflict_reg)
+ as_warn (_("destination register same as write-back base\n"));
+ str++;
+ inst.instruction |= WRITE_BACK;
+ }
+
+ flags |= INDEX_UP;
+ if (! (flags & TRANS_BIT))
+ pre_inc = 1;
+ }
+ }
+ else
+ {
+ /* [Rn,...] */
+ if (skip_past_comma (&str) == FAIL)
+ {
+ inst.error = _("pre-indexed expression expected");
+ return;
+ }
+
+ pre_inc = 1;
+ if (ldst_extend (&str, halfword) == FAIL)
+ return;
+
+ while (*str == ' ')
+ str++;
+
+ if (*str++ != ']')
+ {
+ inst.error = _("missing ]");
+ return;
+ }
+
+ while (*str == ' ')
+ str++;
+
+ if (*str == '!')
+ {
+ if (conflict_reg)
+ as_tsktsk (_("destination register same as write-back base\n"));
+ str++;
+ inst.instruction |= WRITE_BACK;
+ }
+ }
+ }
+ else if (*str == '=')
+ {
+ /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op */
+ str++;
+
+ while (*str == ' ')
+ str++;
+
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+
+ if (inst.reloc.exp.X_op != O_constant
+ && inst.reloc.exp.X_op != O_symbol)
+ {
+ inst.error = _("Constant expression expected");
+ return;
+ }
+
+ if (inst.reloc.exp.X_op == O_constant
+ && (value = validate_immediate(inst.reloc.exp.X_add_number)) != FAIL)
+ {
+ /* This can be done with a mov instruction */
+ inst.instruction &= LITERAL_MASK;
+ inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
+ inst.instruction |= (flags & COND_MASK) | (value & 0xfff);
+ end_of_line(str);
+ return;
+ }
+ else
+ {
+ /* Insert into literal pool */
+ if (add_to_lit_pool () == FAIL)
+ {
+ if (!inst.error)
+ inst.error = _("literal pool insertion failed");
+ return;
+ }
+
+ /* Change the instruction exp to point to the pool */
+ if (halfword)
+ {
+ inst.instruction |= HWOFFSET_IMM;
+ inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
+ }
+ else
+ inst.reloc.type = BFD_RELOC_ARM_LITERAL;
+ inst.reloc.pc_rel = 1;
+ inst.instruction |= (REG_PC << 16);
+ pre_inc = 1;
+ }
+ }
+ else
+ {
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+
+ if (halfword)
+ {
+ inst.instruction |= HWOFFSET_IMM;
+ inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
+ }
+ else
+ inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
+ inst.reloc.exp.X_add_number -= 8; /* PC rel adjust */
+ inst.reloc.pc_rel = 1;
+ inst.instruction |= (REG_PC << 16);
+ pre_inc = 1;
+ }
+
+ if (pre_inc && (flags & TRANS_BIT))
+ inst.error = _("Pre-increment instruction with translate");
+
+ inst.instruction |= flags | (pre_inc ? PRE_INDEX : 0);
+ end_of_line (str);
+ return;
+}
+
+static long
+reg_list (strp)
+ char ** strp;
+{
+ char * str = *strp;
+ long range = 0;
+ int another_range;
+
+ /* We come back here if we get ranges concatenated by '+' or '|' */
+ do
+ {
+ another_range = 0;
+
+ if (*str == '{')
+ {
+ int in_range = 0;
+ int cur_reg = -1;
+
+ str++;
+ do
+ {
+ int reg;
+
+ while (*str == ' ')
+ str++;
+
+ if ((reg = reg_required_here (& str, -1)) == FAIL)
+ return FAIL;
+
+ if (in_range)
+ {
+ int i;
+
+ if (reg <= cur_reg)
+ {
+ inst.error = _("Bad range in register list");
+ return FAIL;
+ }
+
+ for (i = cur_reg + 1; i < reg; i++)
+ {
+ if (range & (1 << i))
+ as_tsktsk
+ (_("Warning: Duplicated register (r%d) in register list"),
+ i);
+ else
+ range |= 1 << i;
+ }
+ in_range = 0;
+ }
+
+ if (range & (1 << reg))
+ as_tsktsk (_("Warning: Duplicated register (r%d) in register list"),
+ reg);
+ else if (reg <= cur_reg)
+ as_tsktsk (_("Warning: Register range not in ascending order"));
+
+ range |= 1 << reg;
+ cur_reg = reg;
+ } while (skip_past_comma (&str) != FAIL
+ || (in_range = 1, *str++ == '-'));
+ str--;
+ while (*str == ' ')
+ str++;
+
+ if (*str++ != '}')
+ {
+ inst.error = _("Missing `}'");
+ return FAIL;
+ }
+ }
+ else
+ {
+ expressionS expr;
+
+ if (my_get_expression (&expr, &str))
+ return FAIL;
+
+ if (expr.X_op == O_constant)
+ {
+ if (expr.X_add_number
+ != (expr.X_add_number & 0x0000ffff))
+ {
+ inst.error = _("invalid register mask");
+ return FAIL;
+ }
+
+ if ((range & expr.X_add_number) != 0)
+ {
+ int regno = range & expr.X_add_number;
+
+ regno &= -regno;
+ regno = (1 << regno) - 1;
+ as_tsktsk
+ (_("Warning: Duplicated register (r%d) in register list"),
+ regno);
+ }
+
+ range |= expr.X_add_number;
+ }
+ else
+ {
+ if (inst.reloc.type != 0)
+ {
+ inst.error = _("expression too complex");
+ return FAIL;
+ }
+
+ memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
+ inst.reloc.type = BFD_RELOC_ARM_MULTI;
+ inst.reloc.pc_rel = 0;
+ }
+ }
+
+ while (*str == ' ')
+ str++;
+
+ if (*str == '|' || *str == '+')
+ {
+ str++;
+ another_range = 1;
+ }
+ } while (another_range);
+
+ *strp = str;
+ return range;
+}
+
+static void
+do_ldmstm (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ int base_reg;
+ long range;
+
+ while (*str == ' ')
+ str++;
+
+ if ((base_reg = reg_required_here (&str, 16)) == FAIL)
+ return;
+
+ if (base_reg == REG_PC)
+ {
+ inst.error = _("r15 not allowed as base register");
+ return;
+ }
+
+ while (*str == ' ')
+ str++;
+ if (*str == '!')
+ {
+ flags |= WRITE_BACK;
+ str++;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || (range = reg_list (&str)) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (*str == '^')
+ {
+ str++;
+ flags |= MULTI_SET_PSR;
+ }
+
+ inst.instruction |= flags | range;
+ end_of_line (str);
+ return;
+}
+
+static void
+do_swi (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ while (*str == ' ')
+ str++;
+
+ /* Allow optional leading '#'. */
+ if (is_immediate_prefix (*str))
+ str++;
+
+ if (my_get_expression (& inst.reloc.exp, & str))
+ return;
+
+ inst.reloc.type = BFD_RELOC_ARM_SWI;
+ inst.reloc.pc_rel = 0;
+ inst.instruction |= flags;
+
+ end_of_line (str);
+
+ return;
+}
+
+static void
+do_swap (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ int reg;
+
+ while (*str == ' ')
+ str++;
+
+ if ((reg = reg_required_here (&str, 12)) == FAIL)
+ return;
+
+ if (reg == REG_PC)
+ {
+ inst.error = _("r15 not allowed in swap");
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || (reg = reg_required_here (&str, 0)) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (reg == REG_PC)
+ {
+ inst.error = _("r15 not allowed in swap");
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || *str++ != '[')
+ {
+ inst.error = bad_args;
+ return;
+ }
+
+ while (*str == ' ')
+ str++;
+
+ if ((reg = reg_required_here (&str, 16)) == FAIL)
+ return;
+
+ if (reg == REG_PC)
+ {
+ inst.error = bad_pc;
+ return;
+ }
+
+ while (*str == ' ')
+ str++;
+
+ if (*str++ != ']')
+ {
+ inst.error = _("missing ]");
+ return;
+ }
+
+ inst.instruction |= flags;
+ end_of_line (str);
+ return;
+}
+
+static void
+do_branch (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+
+#ifdef OBJ_ELF
+ {
+ char * save_in;
+
+ /* ScottB: February 5, 1998 */
+ /* Check to see of PLT32 reloc required for the instruction. */
+
+ /* arm_parse_reloc() works on input_line_pointer.
+ We actually want to parse the operands to the branch instruction
+ passed in 'str'. Save the input pointer and restore it later. */
+ save_in = input_line_pointer;
+ input_line_pointer = str;
+ if (inst.reloc.exp.X_op == O_symbol
+ && *str == '('
+ && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
+ {
+ inst.reloc.type = BFD_RELOC_ARM_PLT32;
+ inst.reloc.pc_rel = 0;
+ /* Modify str to point to after parsed operands, otherwise
+ end_of_line() will complain about the (PLT) left in str. */
+ str = input_line_pointer;
+ }
+ else
+ {
+ inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
+ inst.reloc.pc_rel = 1;
+ }
+ input_line_pointer = save_in;
+ }
+#else
+ inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
+ inst.reloc.pc_rel = 1;
+#endif /* OBJ_ELF */
+
+ end_of_line (str);
+ return;
+}
+
+static void
+do_bx (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ int reg;
+
+ while (*str == ' ')
+ str++;
+
+ if ((reg = reg_required_here (&str, 0)) == FAIL)
+ return;
+
+ if (reg == REG_PC)
+ as_tsktsk (_("Use of r15 in bx has undefined behaviour"));
+
+ end_of_line (str);
+ return;
+}
+
+static void
+do_cdp (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ /* Co-processor data operation.
+ Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
+ while (*str == ' ')
+ str++;
+
+ if (co_proc_number (&str) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || cp_opc_expr (&str, 20,4) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || cp_reg_required_here (&str, 12) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || cp_reg_required_here (&str, 16) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || cp_reg_required_here (&str, 0) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) == SUCCESS)
+ {
+ if (cp_opc_expr (&str, 5, 3) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+ }
+
+ end_of_line (str);
+ return;
+}
+
+static void
+do_lstc (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ /* Co-processor register load/store.
+ Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
+
+ while (*str == ' ')
+ str++;
+
+ if (co_proc_number (&str) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || cp_reg_required_here (&str, 12) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || cp_address_required_here (&str) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ inst.instruction |= flags;
+ end_of_line (str);
+ return;
+}
+
+static void
+do_co_reg (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ /* Co-processor register transfer.
+ Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
+
+ while (*str == ' ')
+ str++;
+
+ if (co_proc_number (&str) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || cp_opc_expr (&str, 21, 3) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || reg_required_here (&str, 12) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || cp_reg_required_here (&str, 16) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || cp_reg_required_here (&str, 0) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) == SUCCESS)
+ {
+ if (cp_opc_expr (&str, 5, 3) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+ }
+
+ end_of_line (str);
+ return;
+}
+
+static void
+do_fp_ctrl (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ /* FP control registers.
+ Format: <WFS|RFS|WFC|RFC>{cond} Rn */
+
+ while (*str == ' ')
+ str++;
+
+ if (reg_required_here (&str, 12) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ end_of_line (str);
+ return;
+}
+
+static void
+do_fp_ldst (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ while (*str == ' ')
+ str++;
+
+ switch (inst.suffix)
+ {
+ case SUFF_S:
+ break;
+ case SUFF_D:
+ inst.instruction |= CP_T_X;
+ break;
+ case SUFF_E:
+ inst.instruction |= CP_T_Y;
+ break;
+ case SUFF_P:
+ inst.instruction |= CP_T_X | CP_T_Y;
+ break;
+ default:
+ abort ();
+ }
+
+ if (fp_reg_required_here (&str, 12) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || cp_address_required_here (&str) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ end_of_line (str);
+}
+
+static void
+do_fp_ldmstm (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ int num_regs;
+
+ while (*str == ' ')
+ str++;
+
+ if (fp_reg_required_here (&str, 12) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ /* Get Number of registers to transfer */
+ if (skip_past_comma (&str) == FAIL
+ || my_get_expression (&inst.reloc.exp, &str))
+ {
+ if (! inst.error)
+ inst.error = _("constant expression expected");
+ return;
+ }
+
+ if (inst.reloc.exp.X_op != O_constant)
+ {
+ inst.error = _("Constant value required for number of registers");
+ return;
+ }
+
+ num_regs = inst.reloc.exp.X_add_number;
+
+ if (num_regs < 1 || num_regs > 4)
+ {
+ inst.error = _("number of registers must be in the range [1:4]");
+ return;
+ }
+
+ switch (num_regs)
+ {
+ case 1:
+ inst.instruction |= CP_T_X;
+ break;
+ case 2:
+ inst.instruction |= CP_T_Y;
+ break;
+ case 3:
+ inst.instruction |= CP_T_Y | CP_T_X;
+ break;
+ case 4:
+ break;
+ default:
+ abort ();
+ }
+
+ if (flags)
+ {
+ int reg;
+ int write_back;
+ int offset;
+
+ /* The instruction specified "ea" or "fd", so we can only accept
+ [Rn]{!}. The instruction does not really support stacking or
+ unstacking, so we have to emulate these by setting appropriate
+ bits and offsets. */
+ if (skip_past_comma (&str) == FAIL
+ || *str != '[')
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ str++;
+ while (*str == ' ')
+ str++;
+
+ if ((reg = reg_required_here (&str, 16)) == FAIL)
+ return;
+
+ while (*str == ' ')
+ str++;
+
+ if (*str != ']')
+ {
+ inst.error = bad_args;
+ return;
+ }
+
+ str++;
+ if (*str == '!')
+ {
+ write_back = 1;
+ str++;
+ if (reg == REG_PC)
+ {
+ inst.error = _("R15 not allowed as base register with write-back");
+ return;
+ }
+ }
+ else
+ write_back = 0;
+
+ if (flags & CP_T_Pre)
+ {
+ /* Pre-decrement */
+ offset = 3 * num_regs;
+ if (write_back)
+ flags |= CP_T_WB;
+ }
+ else
+ {
+ /* Post-increment */
+ if (write_back)
+ {
+ flags |= CP_T_WB;
+ offset = 3 * num_regs;
+ }
+ else
+ {
+ /* No write-back, so convert this into a standard pre-increment
+ instruction -- aesthetically more pleasing. */
+ flags = CP_T_Pre | CP_T_UD;
+ offset = 0;
+ }
+ }
+
+ inst.instruction |= flags | offset;
+ }
+ else if (skip_past_comma (&str) == FAIL
+ || cp_address_required_here (&str) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ end_of_line (str);
+}
+
+static void
+do_fp_dyadic (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ while (*str == ' ')
+ str++;
+
+ switch (inst.suffix)
+ {
+ case SUFF_S:
+ break;
+ case SUFF_D:
+ inst.instruction |= 0x00000080;
+ break;
+ case SUFF_E:
+ inst.instruction |= 0x00080000;
+ break;
+ default:
+ abort ();
+ }
+
+ if (fp_reg_required_here (&str, 12) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || fp_reg_required_here (&str, 16) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || fp_op2 (&str) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ inst.instruction |= flags;
+ end_of_line (str);
+ return;
+}
+
+static void
+do_fp_monadic (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ while (*str == ' ')
+ str++;
+
+ switch (inst.suffix)
+ {
+ case SUFF_S:
+ break;
+ case SUFF_D:
+ inst.instruction |= 0x00000080;
+ break;
+ case SUFF_E:
+ inst.instruction |= 0x00080000;
+ break;
+ default:
+ abort ();
+ }
+
+ if (fp_reg_required_here (&str, 12) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || fp_op2 (&str) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ inst.instruction |= flags;
+ end_of_line (str);
+ return;
+}
+
+static void
+do_fp_cmp (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ while (*str == ' ')
+ str++;
+
+ if (fp_reg_required_here (&str, 16) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || fp_op2 (&str) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ inst.instruction |= flags;
+ end_of_line (str);
+ return;
+}
+
+static void
+do_fp_from_reg (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ while (*str == ' ')
+ str++;
+
+ switch (inst.suffix)
+ {
+ case SUFF_S:
+ break;
+ case SUFF_D:
+ inst.instruction |= 0x00000080;
+ break;
+ case SUFF_E:
+ inst.instruction |= 0x00080000;
+ break;
+ default:
+ abort ();
+ }
+
+ if (fp_reg_required_here (&str, 16) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || reg_required_here (&str, 12) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ inst.instruction |= flags;
+ end_of_line (str);
+ return;
+}
+
+static void
+do_fp_to_reg (str, flags)
+ char * str;
+ unsigned long flags;
+{
+ while (*str == ' ')
+ str++;
+
+ if (reg_required_here (&str, 12) == FAIL)
+ return;
+
+ if (skip_past_comma (&str) == FAIL
+ || fp_reg_required_here (&str, 0) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ inst.instruction |= flags;
+ end_of_line (str);
+ return;
+}
+
+/* Thumb specific routines */
+
+/* Parse and validate that a register is of the right form, this saves
+ repeated checking of this information in many similar cases.
+ Unlike the 32-bit case we do not insert the register into the opcode
+ here, since the position is often unknown until the full instruction
+ has been parsed. */
+static int
+thumb_reg (strp, hi_lo)
+ char ** strp;
+ int hi_lo;
+{
+ int reg;
+
+ if ((reg = reg_required_here (strp, -1)) == FAIL)
+ return FAIL;
+
+ switch (hi_lo)
+ {
+ case THUMB_REG_LO:
+ if (reg > 7)
+ {
+ inst.error = _("lo register required");
+ return FAIL;
+ }
+ break;
+
+ case THUMB_REG_HI:
+ if (reg < 8)
+ {
+ inst.error = _("hi register required");
+ return FAIL;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return reg;
+}
+
+/* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
+ was SUB. */
+static void
+thumb_add_sub (str, subtract)
+ char * str;
+ int subtract;
+{
+ int Rd, Rs, Rn = FAIL;
+
+ while (*str == ' ')
+ str++;
+
+ if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
+ || skip_past_comma (&str) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (is_immediate_prefix (*str))
+ {
+ Rs = Rd;
+ str++;
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+ }
+ else
+ {
+ if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
+ return;
+
+ if (skip_past_comma (&str) == FAIL)
+ {
+ /* Two operand format, shuffle the registers and pretend there
+ are 3 */
+ Rn = Rs;
+ Rs = Rd;
+ }
+ else if (is_immediate_prefix (*str))
+ {
+ str++;
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+ }
+ else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
+ return;
+ }
+
+ /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
+ for the latter case, EXPR contains the immediate that was found. */
+ if (Rn != FAIL)
+ {
+ /* All register format. */
+ if (Rd > 7 || Rs > 7 || Rn > 7)
+ {
+ if (Rs != Rd)
+ {
+ inst.error = _("dest and source1 must be the same register");
+ return;
+ }
+
+ /* Can't do this for SUB */
+ if (subtract)
+ {
+ inst.error = _("subtract valid only on lo regs");
+ return;
+ }
+
+ inst.instruction = (T_OPCODE_ADD_HI
+ | (Rd > 7 ? THUMB_H1 : 0)
+ | (Rn > 7 ? THUMB_H2 : 0));
+ inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
+ }
+ else
+ {
+ inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
+ inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
+ }
+ }
+ else
+ {
+ /* Immediate expression, now things start to get nasty. */
+
+ /* First deal with HI regs, only very restricted cases allowed:
+ Adjusting SP, and using PC or SP to get an address. */
+ if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
+ || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
+ {
+ inst.error = _("invalid Hi register with immediate");
+ return;
+ }
+
+ if (inst.reloc.exp.X_op != O_constant)
+ {
+ /* Value isn't known yet, all we can do is store all the fragments
+ we know about in the instruction and let the reloc hacking
+ work it all out. */
+ inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
+ inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
+ }
+ else
+ {
+ int offset = inst.reloc.exp.X_add_number;
+
+ if (subtract)
+ offset = -offset;
+
+ if (offset < 0)
+ {
+ offset = -offset;
+ subtract = 1;
+
+ /* Quick check, in case offset is MIN_INT */
+ if (offset < 0)
+ {
+ inst.error = _("immediate value out of range");
+ return;
+ }
+ }
+ else
+ subtract = 0;
+
+ if (Rd == REG_SP)
+ {
+ if (offset & ~0x1fc)
+ {
+ inst.error = _("invalid immediate value for stack adjust");
+ return;
+ }
+ inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
+ inst.instruction |= offset >> 2;
+ }
+ else if (Rs == REG_PC || Rs == REG_SP)
+ {
+ if (subtract
+ || (offset & ~0x3fc))
+ {
+ inst.error = _("invalid immediate for address calculation");
+ return;
+ }
+ inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
+ : T_OPCODE_ADD_SP);
+ inst.instruction |= (Rd << 8) | (offset >> 2);
+ }
+ else if (Rs == Rd)
+ {
+ if (offset & ~0xff)
+ {
+ inst.error = _("immediate value out of range");
+ return;
+ }
+ inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
+ inst.instruction |= (Rd << 8) | offset;
+ }
+ else
+ {
+ if (offset & ~0x7)
+ {
+ inst.error = _("immediate value out of range");
+ return;
+ }
+ inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
+ inst.instruction |= Rd | (Rs << 3) | (offset << 6);
+ }
+ }
+ }
+ end_of_line (str);
+}
+
+static void
+thumb_shift (str, shift)
+ char * str;
+ int shift;
+{
+ int Rd, Rs, Rn = FAIL;
+
+ while (*str == ' ')
+ str++;
+
+ if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
+ || skip_past_comma (&str) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (is_immediate_prefix (*str))
+ {
+ /* Two operand immediate format, set Rs to Rd. */
+ Rs = Rd;
+ str++;
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+ }
+ else
+ {
+ if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
+ return;
+
+ if (skip_past_comma (&str) == FAIL)
+ {
+ /* Two operand format, shuffle the registers and pretend there
+ are 3 */
+ Rn = Rs;
+ Rs = Rd;
+ }
+ else if (is_immediate_prefix (*str))
+ {
+ str++;
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+ }
+ else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
+ return;
+ }
+
+ /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
+ for the latter case, EXPR contains the immediate that was found. */
+
+ if (Rn != FAIL)
+ {
+ if (Rs != Rd)
+ {
+ inst.error = _("source1 and dest must be same register");
+ return;
+ }
+
+ switch (shift)
+ {
+ case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
+ case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
+ case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
+ }
+
+ inst.instruction |= Rd | (Rn << 3);
+ }
+ else
+ {
+ switch (shift)
+ {
+ case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
+ case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
+ case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
+ }
+
+ if (inst.reloc.exp.X_op != O_constant)
+ {
+ /* Value isn't known yet, create a dummy reloc and let reloc
+ hacking fix it up */
+
+ inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
+ }
+ else
+ {
+ unsigned shift_value = inst.reloc.exp.X_add_number;
+
+ if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
+ {
+ inst.error = _("Invalid immediate for shift");
+ return;
+ }
+
+ /* Shifts of zero are handled by converting to LSL */
+ if (shift_value == 0)
+ inst.instruction = T_OPCODE_LSL_I;
+
+ /* Shifts of 32 are encoded as a shift of zero */
+ if (shift_value == 32)
+ shift_value = 0;
+
+ inst.instruction |= shift_value << 6;
+ }
+
+ inst.instruction |= Rd | (Rs << 3);
+ }
+ end_of_line (str);
+}
+
+static void
+thumb_mov_compare (str, move)
+ char * str;
+ int move;
+{
+ int Rd, Rs = FAIL;
+
+ while (*str == ' ')
+ str++;
+
+ if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
+ || skip_past_comma (&str) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (is_immediate_prefix (*str))
+ {
+ str++;
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+ }
+ else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
+ return;
+
+ if (Rs != FAIL)
+ {
+ if (Rs < 8 && Rd < 8)
+ {
+ if (move == THUMB_MOVE)
+ /* A move of two lowregs is encoded as ADD Rd, Rs, #0
+ since a MOV instruction produces unpredictable results */
+ inst.instruction = T_OPCODE_ADD_I3;
+ else
+ inst.instruction = T_OPCODE_CMP_LR;
+ inst.instruction |= Rd | (Rs << 3);
+ }
+ else
+ {
+ if (move == THUMB_MOVE)
+ inst.instruction = T_OPCODE_MOV_HR;
+ else
+ inst.instruction = T_OPCODE_CMP_HR;
+
+ if (Rd > 7)
+ inst.instruction |= THUMB_H1;
+
+ if (Rs > 7)
+ inst.instruction |= THUMB_H2;
+
+ inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
+ }
+ }
+ else
+ {
+ if (Rd > 7)
+ {
+ inst.error = _("only lo regs allowed with immediate");
+ return;
+ }
+
+ if (move == THUMB_MOVE)
+ inst.instruction = T_OPCODE_MOV_I8;
+ else
+ inst.instruction = T_OPCODE_CMP_I8;
+
+ inst.instruction |= Rd << 8;
+
+ if (inst.reloc.exp.X_op != O_constant)
+ inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
+ else
+ {
+ unsigned value = inst.reloc.exp.X_add_number;
+
+ if (value > 255)
+ {
+ inst.error = _("invalid immediate");
+ return;
+ }
+
+ inst.instruction |= value;
+ }
+ }
+
+ end_of_line (str);
+}
+
+static void
+thumb_load_store (str, load_store, size)
+ char * str;
+ int load_store;
+ int size;
+{
+ int Rd, Rb, Ro = FAIL;
+
+ while (*str == ' ')
+ str++;
+
+ if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
+ || skip_past_comma (&str) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (*str == '[')
+ {
+ str++;
+ if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
+ return;
+
+ if (skip_past_comma (&str) != FAIL)
+ {
+ if (is_immediate_prefix (*str))
+ {
+ str++;
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+ }
+ else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
+ return;
+ }
+ else
+ {
+ inst.reloc.exp.X_op = O_constant;
+ inst.reloc.exp.X_add_number = 0;
+ }
+
+ if (*str != ']')
+ {
+ inst.error = _("expected ']'");
+ return;
+ }
+ str++;
+ }
+ else if (*str == '=')
+ {
+ /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op */
+ str++;
+
+ while (*str == ' ')
+ str++;
+
+ if (my_get_expression (& inst.reloc.exp, & str))
+ return;
+
+ end_of_line (str);
+
+ if ( inst.reloc.exp.X_op != O_constant
+ && inst.reloc.exp.X_op != O_symbol)
+ {
+ inst.error = "Constant expression expected";
+ return;
+ }
+
+ if (inst.reloc.exp.X_op == O_constant
+ && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
+ {
+ /* This can be done with a mov instruction */
+
+ inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
+ inst.instruction |= inst.reloc.exp.X_add_number;
+ return;
+ }
+
+ /* Insert into literal pool */
+ if (add_to_lit_pool () == FAIL)
+ {
+ if (!inst.error)
+ inst.error = "literal pool insertion failed";
+ return;
+ }
+
+ inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
+ inst.reloc.pc_rel = 1;
+ inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
+ inst.reloc.exp.X_add_number += 4; /* Adjust ARM pipeline offset to Thumb */
+
+ return;
+ }
+ else
+ {
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+
+ inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
+ inst.reloc.pc_rel = 1;
+ inst.reloc.exp.X_add_number -= 4; /* Pipeline offset */
+ inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
+ end_of_line (str);
+ return;
+ }
+
+ if (Rb == REG_PC || Rb == REG_SP)
+ {
+ if (size != THUMB_WORD)
+ {
+ inst.error = _("byte or halfword not valid for base register");
+ return;
+ }
+ else if (Rb == REG_PC && load_store != THUMB_LOAD)
+ {
+ inst.error = _("R15 based store not allowed");
+ return;
+ }
+ else if (Ro != FAIL)
+ {
+ inst.error = _("Invalid base register for register offset");
+ return;
+ }
+
+ if (Rb == REG_PC)
+ inst.instruction = T_OPCODE_LDR_PC;
+ else if (load_store == THUMB_LOAD)
+ inst.instruction = T_OPCODE_LDR_SP;
+ else
+ inst.instruction = T_OPCODE_STR_SP;
+
+ inst.instruction |= Rd << 8;
+ if (inst.reloc.exp.X_op == O_constant)
+ {
+ unsigned offset = inst.reloc.exp.X_add_number;
+
+ if (offset & ~0x3fc)
+ {
+ inst.error = _("invalid offset");
+ return;
+ }
+
+ inst.instruction |= offset >> 2;
+ }
+ else
+ inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
+ }
+ else if (Rb > 7)
+ {
+ inst.error = _("invalid base register in load/store");
+ return;
+ }
+ else if (Ro == FAIL)
+ {
+ /* Immediate offset */
+ if (size == THUMB_WORD)
+ inst.instruction = (load_store == THUMB_LOAD
+ ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
+ else if (size == THUMB_HALFWORD)
+ inst.instruction = (load_store == THUMB_LOAD
+ ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
+ else
+ inst.instruction = (load_store == THUMB_LOAD
+ ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
+
+ inst.instruction |= Rd | (Rb << 3);
+
+ if (inst.reloc.exp.X_op == O_constant)
+ {
+ unsigned offset = inst.reloc.exp.X_add_number;
+
+ if (offset & ~(0x1f << size))
+ {
+ inst.error = _("Invalid offset");
+ return;
+ }
+ inst.instruction |= (offset >> size) << 6;
+ }
+ else
+ inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
+ }
+ else
+ {
+ /* Register offset */
+ if (size == THUMB_WORD)
+ inst.instruction = (load_store == THUMB_LOAD
+ ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
+ else if (size == THUMB_HALFWORD)
+ inst.instruction = (load_store == THUMB_LOAD
+ ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
+ else
+ inst.instruction = (load_store == THUMB_LOAD
+ ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
+
+ inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
+ }
+
+ end_of_line (str);
+}
+
+static void
+do_t_nop (str)
+ char * str;
+{
+ /* Do nothing */
+ end_of_line (str);
+ return;
+}
+
+/* Handle the Format 4 instructions that do not have equivalents in other
+ formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
+ BIC and MVN. */
+static void
+do_t_arit (str)
+ char * str;
+{
+ int Rd, Rs, Rn;
+
+ while (*str == ' ')
+ str++;
+
+ if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
+ return;
+
+ if (skip_past_comma (&str) == FAIL
+ || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) != FAIL)
+ {
+ /* Three operand format not allowed for TST, CMN, NEG and MVN.
+ (It isn't allowed for CMP either, but that isn't handled by this
+ function.) */
+ if (inst.instruction == T_OPCODE_TST
+ || inst.instruction == T_OPCODE_CMN
+ || inst.instruction == T_OPCODE_NEG
+ || inst.instruction == T_OPCODE_MVN)
+ {
+ inst.error = bad_args;
+ return;
+ }
+
+ if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
+ return;
+
+ if (Rs != Rd)
+ {
+ inst.error = _("dest and source1 one must be the same register");
+ return;
+ }
+ Rs = Rn;
+ }
+
+ if (inst.instruction == T_OPCODE_MUL
+ && Rs == Rd)
+ as_tsktsk (_("Rs and Rd must be different in MUL"));
+
+ inst.instruction |= Rd | (Rs << 3);
+ end_of_line (str);
+}
+
+static void
+do_t_add (str)
+ char * str;
+{
+ thumb_add_sub (str, 0);
+}
+
+static void
+do_t_asr (str)
+ char * str;
+{
+ thumb_shift (str, THUMB_ASR);
+}
+
+static void
+do_t_branch9 (str)
+ char * str;
+{
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+ inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
+ inst.reloc.pc_rel = 1;
+ end_of_line (str);
+}
+
+static void
+do_t_branch12 (str)
+ char * str;
+{
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+ inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
+ inst.reloc.pc_rel = 1;
+ end_of_line (str);
+}
+
+/* Find the real, Thumb encoded start of a Thumb function. */
+
+static symbolS *
+find_real_start (symbolP)
+ symbolS * symbolP;
+{
+ char * real_start;
+ const char * name = S_GET_NAME (symbolP);
+ symbolS * new_target;
+
+ /* This definitonmust agree with the one in gcc/config/arm/thumb.c */
+#define STUB_NAME ".real_start_of"
+
+ if (name == NULL)
+ abort();
+
+ /* Names that start with '.' are local labels, not function entry points.
+ The compiler may generate BL instructions to these labels because it
+ needs to perform a branch to a far away location. */
+ if (name[0] == '.')
+ return symbolP;
+
+ real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
+ sprintf (real_start, "%s%s", STUB_NAME, name);
+
+ new_target = symbol_find (real_start);
+
+ if (new_target == NULL)
+ {
+ as_warn ("Failed to find real start of function: %s\n", name);
+ new_target = symbolP;
+ }
+
+ free (real_start);
+
+ return new_target;
+}
+
+
+static void
+do_t_branch23 (str)
+ char * str;
+{
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+ inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
+ inst.reloc.pc_rel = 1;
+ end_of_line (str);
+
+ /* If the destination of the branch is a defined symbol which does not have
+ the THUMB_FUNC attribute, then we must be calling a function which has
+ the (interfacearm) attribute. We look for the Thumb entry point to that
+ function and change the branch to refer to that function instead. */
+ if ( inst.reloc.exp.X_op == O_symbol
+ && inst.reloc.exp.X_add_symbol != NULL
+ && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
+ && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
+ inst.reloc.exp.X_add_symbol = find_real_start (inst.reloc.exp.X_add_symbol);
+}
+
+static void
+do_t_bx (str)
+ char * str;
+{
+ int reg;
+
+ while (*str == ' ')
+ str++;
+
+ if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
+ return;
+
+ /* This sets THUMB_H2 from the top bit of reg. */
+ inst.instruction |= reg << 3;
+
+ /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
+ should cause the alignment to be checked once it is known. This is
+ because BX PC only works if the instruction is word aligned. */
+
+ end_of_line (str);
+}
+
+static void
+do_t_compare (str)
+ char * str;
+{
+ thumb_mov_compare (str, THUMB_COMPARE);
+}
+
+static void
+do_t_ldmstm (str)
+ char * str;
+{
+ int Rb;
+ long range;
+
+ while (*str == ' ')
+ str++;
+
+ if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
+ return;
+
+ if (*str != '!')
+ as_warn (_("Inserted missing '!': load/store multiple always writes back base register"));
+ else
+ str++;
+
+ if (skip_past_comma (&str) == FAIL
+ || (range = reg_list (&str)) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (inst.reloc.type != BFD_RELOC_NONE)
+ {
+ /* This really doesn't seem worth it. */
+ inst.reloc.type = BFD_RELOC_NONE;
+ inst.error = _("Expression too complex");
+ return;
+ }
+
+ if (range & ~0xff)
+ {
+ inst.error = _("only lo-regs valid in load/store multiple");
+ return;
+ }
+
+ inst.instruction |= (Rb << 8) | range;
+ end_of_line (str);
+}
+
+static void
+do_t_ldr (str)
+ char * str;
+{
+ thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
+}
+
+static void
+do_t_ldrb (str)
+ char * str;
+{
+ thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
+}
+
+static void
+do_t_ldrh (str)
+ char * str;
+{
+ thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
+}
+
+static void
+do_t_lds (str)
+ char * str;
+{
+ int Rd, Rb, Ro;
+
+ while (*str == ' ')
+ str++;
+
+ if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
+ || skip_past_comma (&str) == FAIL
+ || *str++ != '['
+ || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
+ || skip_past_comma (&str) == FAIL
+ || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
+ || *str++ != ']')
+ {
+ if (! inst.error)
+ inst.error = _("Syntax: ldrs[b] Rd, [Rb, Ro]");
+ return;
+ }
+
+ inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
+ end_of_line (str);
+}
+
+static void
+do_t_lsl (str)
+ char * str;
+{
+ thumb_shift (str, THUMB_LSL);
+}
+
+static void
+do_t_lsr (str)
+ char * str;
+{
+ thumb_shift (str, THUMB_LSR);
+}
+
+static void
+do_t_mov (str)
+ char * str;
+{
+ thumb_mov_compare (str, THUMB_MOVE);
+}
+
+static void
+do_t_push_pop (str)
+ char * str;
+{
+ long range;
+
+ while (*str == ' ')
+ str++;
+
+ if ((range = reg_list (&str)) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (inst.reloc.type != BFD_RELOC_NONE)
+ {
+ /* This really doesn't seem worth it. */
+ inst.reloc.type = BFD_RELOC_NONE;
+ inst.error = _("Expression too complex");
+ return;
+ }
+
+ if (range & ~0xff)
+ {
+ if ((inst.instruction == T_OPCODE_PUSH
+ && (range & ~0xff) == 1 << REG_LR)
+ || (inst.instruction == T_OPCODE_POP
+ && (range & ~0xff) == 1 << REG_PC))
+ {
+ inst.instruction |= THUMB_PP_PC_LR;
+ range &= 0xff;
+ }
+ else
+ {
+ inst.error = _("invalid register list to push/pop instruction");
+ return;
+ }
+ }
+
+ inst.instruction |= range;
+ end_of_line (str);
+}
+
+static void
+do_t_str (str)
+ char * str;
+{
+ thumb_load_store (str, THUMB_STORE, THUMB_WORD);
+}
+
+static void
+do_t_strb (str)
+ char * str;
+{
+ thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
+}
+
+static void
+do_t_strh (str)
+ char * str;
+{
+ thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
+}
+
+static void
+do_t_sub (str)
+ char * str;
+{
+ thumb_add_sub (str, 1);
+}
+
+static void
+do_t_swi (str)
+ char * str;
+{
+ while (*str == ' ')
+ str++;
+
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+
+ inst.reloc.type = BFD_RELOC_ARM_SWI;
+ end_of_line (str);
+ return;
+}
+
+static void
+do_t_adr (str)
+ char * str;
+{
+ /* This is a pseudo-op of the form "adr rd, label" to be converted
+ into a relative address of the form "add rd, pc, #label-.-4" */
+ while (*str == ' ')
+ str++;
+
+ if (reg_required_here (&str, 4) == FAIL /* Store Rd in temporary location inside instruction. */
+ || skip_past_comma (&str) == FAIL
+ || my_get_expression (&inst.reloc.exp, &str))
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
+ inst.reloc.exp.X_add_number -= 4; /* PC relative adjust */
+ inst.reloc.pc_rel = 1;
+ inst.instruction |= REG_PC; /* Rd is already placed into the instruction */
+ end_of_line (str);
+}
+
+static void
+insert_reg (entry)
+ int entry;
+{
+ int len = strlen (reg_table[entry].name) + 2;
+ char * buf = (char *) xmalloc (len);
+ char * buf2 = (char *) xmalloc (len);
+ int i = 0;
+
+#ifdef REGISTER_PREFIX
+ buf[i++] = REGISTER_PREFIX;
+#endif
+
+ strcpy (buf + i, reg_table[entry].name);
+
+ for (i = 0; buf[i]; i++)
+ buf2[i] = islower (buf[i]) ? toupper (buf[i]) : buf[i];
+
+ buf2[i] = '\0';
+
+ hash_insert (arm_reg_hsh, buf, (PTR) &reg_table[entry]);
+ hash_insert (arm_reg_hsh, buf2, (PTR) &reg_table[entry]);
+}
+
+static void
+insert_reg_alias (str, regnum)
+ char *str;
+ int regnum;
+{
+ struct reg_entry *new =
+ (struct reg_entry *)xmalloc (sizeof (struct reg_entry));
+ char *name = xmalloc (strlen (str) + 1);
+ strcpy (name, str);
+
+ new->name = name;
+ new->number = regnum;
+
+ hash_insert (arm_reg_hsh, name, (PTR) new);
+}
+
+static void
+set_constant_flonums ()
+{
+ int i;
+
+ for (i = 0; i < NUM_FLOAT_VALS; i++)
+ if (atof_ieee ((char *)fp_const[i], 'x', fp_values[i]) == NULL)
+ abort ();
+}
+
+void
+md_begin ()
+{
+ int i;
+
+ if ( (arm_ops_hsh = hash_new ()) == NULL
+ || (arm_tops_hsh = hash_new ()) == NULL
+ || (arm_cond_hsh = hash_new ()) == NULL
+ || (arm_shift_hsh = hash_new ()) == NULL
+ || (arm_reg_hsh = hash_new ()) == NULL
+ || (arm_psr_hsh = hash_new ()) == NULL)
+ as_fatal (_("Virtual memory exhausted"));
+
+ for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
+ hash_insert (arm_ops_hsh, insns[i].template, (PTR) (insns + i));
+ for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
+ hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
+ for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
+ hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
+ for (i = 0; i < sizeof (shift) / sizeof (struct asm_shift); i++)
+ hash_insert (arm_shift_hsh, shift[i].template, (PTR) (shift + i));
+ for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
+ hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
+
+ for (i = 0; reg_table[i].name; i++)
+ insert_reg (i);
+
+ set_constant_flonums ();
+
+#if defined OBJ_COFF || defined OBJ_ELF
+ {
+ unsigned int flags = 0;
+
+ /* Set the flags in the private structure */
+ if (uses_apcs_26) flags |= F_APCS26;
+ if (support_interwork) flags |= F_INTERWORK;
+ if (uses_apcs_float) flags |= F_APCS_FLOAT;
+ if (pic_code) flags |= F_PIC;
+
+ bfd_set_private_flags (stdoutput, flags);
+ }
+#endif
+
+ {
+ unsigned mach;
+
+ /* Record the CPU type as well */
+ switch (cpu_variant & ARM_CPU_MASK)
+ {
+ case ARM_2:
+ mach = bfd_mach_arm_2;
+ break;
+
+ case ARM_3: /* also ARM_250 */
+ mach = bfd_mach_arm_2a;
+ break;
+
+ default:
+ case ARM_6 | ARM_3 | ARM_2: /* Actually no CPU type defined */
+ mach = bfd_mach_arm_4;
+ break;
+
+ case ARM_7: /* also ARM_6 */
+ mach = bfd_mach_arm_3;
+ break;
+ }
+
+ /* Catch special cases */
+ if (cpu_variant != (FPU_DEFAULT | CPU_DEFAULT))
+ {
+ if (cpu_variant & ARM_THUMB)
+ mach = bfd_mach_arm_4T;
+ else if ((cpu_variant & ARM_ARCHv4) == ARM_ARCHv4)
+ mach = bfd_mach_arm_4;
+ else if (cpu_variant & ARM_LONGMUL)
+ mach = bfd_mach_arm_3M;
+ }
+
+ bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
+ }
+}
+
+/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
+ for use in the a.out file, and stores them in the array pointed to by buf.
+ This knows about the endian-ness of the target machine and does
+ THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
+ 2 (short) and 4 (long) Floating numbers are put out as a series of
+ LITTLENUMS (shorts, here at least)
+ */
+void
+md_number_to_chars (buf, val, n)
+ char * buf;
+ valueT val;
+ int n;
+{
+ if (target_big_endian)
+ number_to_chars_bigendian (buf, val, n);
+ else
+ number_to_chars_littleendian (buf, val, n);
+}
+
+static valueT
+md_chars_to_number (buf, n)
+ char * buf;
+ int n;
+{
+ valueT result = 0;
+ unsigned char * where = (unsigned char *) buf;
+
+ if (target_big_endian)
+ {
+ while (n--)
+ {
+ result <<= 8;
+ result |= (*where++ & 255);
+ }
+ }
+ else
+ {
+ while (n--)
+ {
+ result <<= 8;
+ result |= (where[n] & 255);
+ }
+ }
+
+ return result;
+}
+
+/* Turn a string in input_line_pointer into a floating point constant
+ of type TYPE, and store the appropriate bytes in *litP. The number
+ of LITTLENUMS emitted is stored in *sizeP . An error message is
+ returned, or NULL on OK.
+
+ Note that fp constants aren't represent in the normal way on the ARM.
+ In big endian mode, things are as expected. However, in little endian
+ mode fp constants are big-endian word-wise, and little-endian byte-wise
+ within the words. For example, (double) 1.1 in big endian mode is
+ the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
+ the byte sequence 99 99 f1 3f 9a 99 99 99.
+
+ ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
+
+char *
+md_atof (type, litP, sizeP)
+ char type;
+ char * litP;
+ int * sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ char *t;
+ int i;
+
+ switch (type)
+ {
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ prec = 4;
+ break;
+
+ case 'x':
+ case 'X':
+ prec = 6;
+ break;
+
+ case 'p':
+ case 'P':
+ prec = 6;
+ break;
+
+ default:
+ *sizeP = 0;
+ return _("Bad call to MD_ATOF()");
+ }
+
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+ *sizeP = prec * 2;
+
+ if (target_big_endian)
+ {
+ for (i = 0; i < prec; i++)
+ {
+ md_number_to_chars (litP, (valueT) words[i], 2);
+ litP += 2;
+ }
+ }
+ else
+ {
+ /* For a 4 byte float the order of elements in `words' is 1 0. For an
+ 8 byte float the order is 1 0 3 2. */
+ for (i = 0; i < prec; i += 2)
+ {
+ md_number_to_chars (litP, (valueT) words[i + 1], 2);
+ md_number_to_chars (litP + 2, (valueT) words[i], 2);
+ litP += 4;
+ }
+ }
+
+ return 0;
+}
+
+/* The knowledge of the PC's pipeline offset is built into the relocs
+ for the ELF port and into the insns themselves for the COFF port. */
+long
+md_pcrel_from (fixP)
+ fixS * fixP;
+{
+ if ( fixP->fx_addsy
+ && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
+ && fixP->fx_subsy == NULL)
+ return 0;
+
+ if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
+ {
+ /* PC relative addressing on the Thumb is slightly odd
+ as the bottom two bits of the PC are forced to zero
+ for the calculation */
+ return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
+ }
+
+ return fixP->fx_where + fixP->fx_frag->fr_address;
+}
+
+/* Round up a section size to the appropriate boundary. */
+valueT
+md_section_align (segment, size)
+ segT segment;
+ valueT size;
+{
+#ifdef OBJ_ELF
+ /* Don't align the dwarf2 debug sections */
+ if (!strncmp (segment->name, ".debug", 5))
+ return size;
+#endif
+ /* Round all sects to multiple of 4 */
+ return (size + 3) & ~3;
+}
+
+/* Under ELF we need to default _GLOBAL_OFFSET_TABLE. Otherwise
+ we have no need to default values of symbols. */
+
+/* ARGSUSED */
+symbolS *
+md_undefined_symbol (name)
+ char * name;
+{
+#ifdef OBJ_ELF
+ if (name[0] == '_' && name[1] == 'G'
+ && streq (name, GLOBAL_OFFSET_TABLE_NAME))
+ {
+ if (!GOT_symbol)
+ {
+ if (symbol_find (name))
+ as_bad ("GOT already in the symbol table");
+
+ GOT_symbol = symbol_new (name, undefined_section,
+ (valueT)0, & zero_address_frag);
+ }
+
+ return GOT_symbol;
+ }
+#endif
+
+ return 0;
+}
+
+/* arm_reg_parse () := if it looks like a register, return its token and
+ advance the pointer. */
+
+static int
+arm_reg_parse (ccp)
+ register char ** ccp;
+{
+ char * start = * ccp;
+ char c;
+ char * p;
+ struct reg_entry * reg;
+
+#ifdef REGISTER_PREFIX
+ if (*start != REGISTER_PREFIX)
+ return FAIL;
+ p = start + 1;
+#else
+ p = start;
+#ifdef OPTIONAL_REGISTER_PREFIX
+ if (*p == OPTIONAL_REGISTER_PREFIX)
+ p++, start++;
+#endif
+#endif
+ if (!isalpha (*p) || !is_name_beginner (*p))
+ return FAIL;
+
+ c = *p++;
+ while (isalpha (c) || isdigit (c) || c == '_')
+ c = *p++;
+
+ *--p = 0;
+ reg = (struct reg_entry *) hash_find (arm_reg_hsh, start);
+ *p = c;
+
+ if (reg)
+ {
+ *ccp = p;
+ return reg->number;
+ }
+
+ return FAIL;
+}
+
+static int
+arm_psr_parse (ccp)
+ register char ** ccp;
+{
+ char * start = * ccp;
+ char c;
+ char * p;
+ CONST struct asm_psr * psr;
+
+ p = start;
+ c = *p++;
+ while (isalpha (c) || c == '_')
+ c = *p++;
+
+ *--p = 0;
+ psr = (CONST struct asm_psr *) hash_find (arm_psr_hsh, start);
+ *p = c;
+
+ if (psr)
+ {
+ *ccp = p;
+ return psr->number;
+ }
+
+ return FAIL;
+}
+
+int
+md_apply_fix3 (fixP, val, seg)
+ fixS * fixP;
+ valueT * val;
+ segT seg;
+{
+ offsetT value = * val;
+ offsetT newval;
+ unsigned int newimm;
+ unsigned long temp;
+ int sign;
+ char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
+ arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
+
+ assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
+
+ /* Note whether this will delete the relocation. */
+#if 0 /* patch from REarnshaw to JDavis (disabled for the moment, since it doesn't work fully) */
+ if ((fixP->fx_addsy == 0 || fixP->fx_addsy->sy_value.X_op == O_constant)
+ && !fixP->fx_pcrel)
+#else
+ if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
+#endif
+ fixP->fx_done = 1;
+
+ /* If this symbol is in a different section then we need to leave it for
+ the linker to deal with. Unfortunately, md_pcrel_from can't tell,
+ so we have to undo it's effects here. */
+ if (fixP->fx_pcrel)
+ {
+ if (fixP->fx_addsy != NULL
+ && S_IS_DEFINED (fixP->fx_addsy)
+ && S_GET_SEGMENT (fixP->fx_addsy) != seg)
+ {
+ if (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH)
+ value = 0;
+ else
+ value += md_pcrel_from (fixP);
+ }
+ }
+
+ fixP->fx_addnumber = value; /* Remember value for emit_reloc */
+
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_ARM_IMMEDIATE:
+ newimm = validate_immediate (value);
+ temp = md_chars_to_number (buf, INSN_SIZE);
+
+ /* If the instruction will fail, see if we can fix things up by
+ changing the opcode. */
+ if (newimm == (unsigned int) FAIL
+ && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
+ {
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("invalid constant (%x) after fixup\n"), value);
+ break;
+ }
+
+ newimm |= (temp & 0xfffff000);
+ md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
+ break;
+
+ case BFD_RELOC_ARM_OFFSET_IMM:
+ sign = value >= 0;
+ if ((value = validate_offset_imm (value, 0)) == FAIL)
+ {
+ as_bad (_("bad immediate value for offset (%d)"), val);
+ break;
+ }
+ if (value < 0)
+ value = -value;
+
+ newval = md_chars_to_number (buf, INSN_SIZE);
+ newval &= 0xff7ff000;
+ newval |= value | (sign ? INDEX_UP : 0);
+ md_number_to_chars (buf, newval, INSN_SIZE);
+ break;
+
+ case BFD_RELOC_ARM_OFFSET_IMM8:
+ case BFD_RELOC_ARM_HWLITERAL:
+ sign = value >= 0;
+ if ((value = validate_offset_imm (value, 1)) == FAIL)
+ {
+ if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("invalid literal constant: pool needs to be closer\n"));
+ else
+ as_bad (_("bad immediate value for offset (%d)"), value);
+ break;
+ }
+
+ if (value < 0)
+ value = -value;
+
+ newval = md_chars_to_number (buf, INSN_SIZE);
+ newval &= 0xff7ff0f0;
+ newval |= ((value >> 4) << 8) | value & 0xf | (sign ? INDEX_UP : 0);
+ md_number_to_chars (buf, newval, INSN_SIZE);
+ break;
+
+ case BFD_RELOC_ARM_LITERAL:
+ sign = value >= 0;
+ if (value < 0)
+ value = -value;
+
+ if ((value = validate_offset_imm (value, 0)) == FAIL)
+ {
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("invalid literal constant: pool needs to be closer\n"));
+ break;
+ }
+
+ newval = md_chars_to_number (buf, INSN_SIZE);
+ newval &= 0xff7ff000;
+ newval |= value | (sign ? INDEX_UP : 0);
+ md_number_to_chars (buf, newval, INSN_SIZE);
+ break;
+
+ case BFD_RELOC_ARM_SHIFT_IMM:
+ newval = md_chars_to_number (buf, INSN_SIZE);
+ if (((unsigned long) value) > 32
+ || (value == 32
+ && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
+ {
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("shift expression is too large"));
+ break;
+ }
+
+ if (value == 0)
+ newval &= ~0x60; /* Shifts of zero must be done as lsl */
+ else if (value == 32)
+ value = 0;
+ newval &= 0xfffff07f;
+ newval |= (value & 0x1f) << 7;
+ md_number_to_chars (buf, newval , INSN_SIZE);
+ break;
+
+ case BFD_RELOC_ARM_SWI:
+ if (arm_data->thumb_mode)
+ {
+ if (((unsigned long) value) > 0xff)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Invalid swi expression"));
+ newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
+ newval |= value;
+ md_number_to_chars (buf, newval, THUMB_SIZE);
+ }
+ else
+ {
+ if (((unsigned long) value) > 0x00ffffff)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Invalid swi expression"));
+ newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
+ newval |= value;
+ md_number_to_chars (buf, newval , INSN_SIZE);
+ }
+ break;
+
+ case BFD_RELOC_ARM_MULTI:
+ if (((unsigned long) value) > 0xffff)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Invalid expression in load/store multiple"));
+ newval = value | md_chars_to_number (buf, INSN_SIZE);
+ md_number_to_chars (buf, newval, INSN_SIZE);
+ break;
+
+ case BFD_RELOC_ARM_PCREL_BRANCH:
+ newval = md_chars_to_number (buf, INSN_SIZE);
+#ifdef OBJ_ELF
+ newval &= 0xff000000;
+ if (! target_oabi)
+ value = fixP->fx_offset;
+ else
+#else
+ value = (value >> 2) & 0x00ffffff;
+#endif
+ value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
+ newval = value | (newval & 0xff000000);
+ md_number_to_chars (buf, newval, INSN_SIZE);
+ break;
+
+ case BFD_RELOC_THUMB_PCREL_BRANCH9: /* conditional branch */
+ newval = md_chars_to_number (buf, THUMB_SIZE);
+ {
+ addressT diff = (newval & 0xff) << 1;
+ if (diff & 0x100)
+ diff |= ~0xff;
+
+ value += diff;
+ if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Branch out of range"));
+ newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
+ }
+ md_number_to_chars (buf, newval, THUMB_SIZE);
+ break;
+
+ case BFD_RELOC_THUMB_PCREL_BRANCH12: /* unconditional branch */
+ newval = md_chars_to_number (buf, THUMB_SIZE);
+ {
+ addressT diff = (newval & 0x7ff) << 1;
+ if (diff & 0x800)
+ diff |= ~0x7ff;
+
+ value += diff;
+ if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Branch out of range"));
+ newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
+ }
+ md_number_to_chars (buf, newval, THUMB_SIZE);
+ break;
+
+ case BFD_RELOC_THUMB_PCREL_BRANCH23:
+ {
+ offsetT newval2;
+ addressT diff;
+
+ newval = md_chars_to_number (buf, THUMB_SIZE);
+ newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
+ diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
+ if (diff & 0x400000)
+ diff |= ~0x3fffff;
+ value += diff;
+ if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Branch with link out of range"));
+
+ newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
+ newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
+ md_number_to_chars (buf, newval, THUMB_SIZE);
+ md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
+ }
+ break;
+
+ case BFD_RELOC_8:
+ if (fixP->fx_done || fixP->fx_pcrel)
+ md_number_to_chars (buf, value, 1);
+#ifdef OBJ_ELF
+ else if (!target_oabi)
+ {
+ value = fixP->fx_offset;
+ md_number_to_chars (buf, value, 1);
+ }
+#endif
+ break;
+
+ case BFD_RELOC_16:
+ if (fixP->fx_done || fixP->fx_pcrel)
+ md_number_to_chars (buf, value, 2);
+#ifdef OBJ_ELF
+ else if (!target_oabi)
+ {
+ value = fixP->fx_offset;
+ md_number_to_chars (buf, value, 2);
+ }
+#endif
+ break;
+
+#ifdef OBJ_ELF
+ case BFD_RELOC_ARM_GOT32:
+ case BFD_RELOC_ARM_GOTOFF:
+ md_number_to_chars (buf, 0, 4);
+ break;
+#endif
+
+ case BFD_RELOC_RVA:
+ case BFD_RELOC_32:
+ if (fixP->fx_done || fixP->fx_pcrel)
+ md_number_to_chars (buf, value, 4);
+#ifdef OBJ_ELF
+ else if (!target_oabi)
+ {
+ value = fixP->fx_offset;
+ md_number_to_chars (buf, value, 4);
+ }
+#endif
+ break;
+
+#ifdef OBJ_ELF
+ case BFD_RELOC_ARM_PLT32:
+ /* It appears the instruction is fully prepared at this point. */
+ break;
+#endif
+
+ case BFD_RELOC_ARM_GOTPC:
+ md_number_to_chars (buf, value, 4);
+ break;
+
+ case BFD_RELOC_ARM_CP_OFF_IMM:
+ sign = value >= 0;
+ if (value < -1023 || value > 1023 || (value & 3))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Illegal value for co-processor offset"));
+ if (value < 0)
+ value = -value;
+ newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
+ newval |= (value >> 2) | (sign ? INDEX_UP : 0);
+ md_number_to_chars (buf, newval , INSN_SIZE);
+ break;
+
+ case BFD_RELOC_ARM_THUMB_OFFSET:
+ newval = md_chars_to_number (buf, THUMB_SIZE);
+ /* Exactly what ranges, and where the offset is inserted depends on
+ the type of instruction, we can establish this from the top 4 bits */
+ switch (newval >> 12)
+ {
+ case 4: /* PC load */
+ /* Thumb PC loads are somewhat odd, bit 1 of the PC is
+ forced to zero for these loads, so we will need to round
+ up the offset if the instruction address is not word
+ aligned (since the final address produced must be, and
+ we can only describe word-aligned immediate offsets). */
+
+ if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Invalid offset, target not word aligned (0x%08X)"),
+ (unsigned int)(fixP->fx_frag->fr_address + fixP->fx_where + value));
+
+ if ((value + 2) & ~0x3fe)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Invalid offset"));
+
+ /* Round up, since pc will be rounded down. */
+ newval |= (value + 2) >> 2;
+ break;
+
+ case 9: /* SP load/store */
+ if (value & ~0x3fc)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Invalid offset"));
+ newval |= value >> 2;
+ break;
+
+ case 6: /* Word load/store */
+ if (value & ~0x7c)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Invalid offset"));
+ newval |= value << 4; /* 6 - 2 */
+ break;
+
+ case 7: /* Byte load/store */
+ if (value & ~0x1f)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Invalid offset"));
+ newval |= value << 6;
+ break;
+
+ case 8: /* Halfword load/store */
+ if (value & ~0x3e)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Invalid offset"));
+ newval |= value << 5; /* 6 - 1 */
+ break;
+
+ default:
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "Unable to process relocation for thumb opcode: %x", newval);
+ break;
+ }
+ md_number_to_chars (buf, newval, THUMB_SIZE);
+ break;
+
+ case BFD_RELOC_ARM_THUMB_ADD:
+ /* This is a complicated relocation, since we use it for all of
+ the following immediate relocations:
+ 3bit ADD/SUB
+ 8bit ADD/SUB
+ 9bit ADD/SUB SP word-aligned
+ 10bit ADD PC/SP word-aligned
+
+ The type of instruction being processed is encoded in the
+ instruction field:
+ 0x8000 SUB
+ 0x00F0 Rd
+ 0x000F Rs
+ */
+ newval = md_chars_to_number (buf, THUMB_SIZE);
+ {
+ int rd = (newval >> 4) & 0xf;
+ int rs = newval & 0xf;
+ int subtract = newval & 0x8000;
+
+ if (rd == REG_SP)
+ {
+ if (value & ~0x1fc)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Invalid immediate for stack address calculation"));
+ newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
+ newval |= value >> 2;
+ }
+ else if (rs == REG_PC || rs == REG_SP)
+ {
+ if (subtract ||
+ value & ~0x3fc)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Invalid immediate for address calculation (value = 0x%08X)"), value);
+ newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
+ newval |= rd << 8;
+ newval |= value >> 2;
+ }
+ else if (rs == rd)
+ {
+ if (value & ~0xff)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Invalid 8bit immediate"));
+ newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
+ newval |= (rd << 8) | value;
+ }
+ else
+ {
+ if (value & ~0x7)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Invalid 3bit immediate"));
+ newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
+ newval |= rd | (rs << 3) | (value << 6);
+ }
+ }
+ md_number_to_chars (buf, newval , THUMB_SIZE);
+ break;
+
+ case BFD_RELOC_ARM_THUMB_IMM:
+ newval = md_chars_to_number (buf, THUMB_SIZE);
+ switch (newval >> 11)
+ {
+ case 0x04: /* 8bit immediate MOV */
+ case 0x05: /* 8bit immediate CMP */
+ if (value < 0 || value > 255)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Invalid immediate: %d is too large"), value);
+ newval |= value;
+ break;
+
+ default:
+ abort ();
+ }
+ md_number_to_chars (buf, newval , THUMB_SIZE);
+ break;
+
+ case BFD_RELOC_ARM_THUMB_SHIFT:
+ /* 5bit shift value (0..31) */
+ if (value < 0 || value > 31)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Illegal Thumb shift value: %d"), value);
+ newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
+ newval |= value << 6;
+ md_number_to_chars (buf, newval , THUMB_SIZE);
+ break;
+
+ case BFD_RELOC_VTABLE_INHERIT:
+ case BFD_RELOC_VTABLE_ENTRY:
+ fixP->fx_done = 0;
+ return 1;
+
+ case BFD_RELOC_NONE:
+ default:
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Bad relocation fixup type (%d)\n"), fixP->fx_r_type);
+ }
+
+ return 1;
+}
+
+/* Translate internal representation of relocation info to BFD target
+ format. */
+arelent *
+tc_gen_reloc (section, fixp)
+ asection * section;
+ fixS * fixp;
+{
+ arelent * reloc;
+ bfd_reloc_code_real_type code;
+
+ reloc = (arelent *) xmalloc (sizeof (arelent));
+
+ reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+ reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+
+ /* @@ Why fx_addnumber sometimes and fx_offset other times? */
+#ifndef OBJ_ELF
+ if (fixp->fx_pcrel == 0)
+ reloc->addend = fixp->fx_offset;
+ else
+ reloc->addend = fixp->fx_offset = reloc->address;
+#else /* OBJ_ELF */
+ reloc->addend = fixp->fx_offset;
+#endif
+
+ switch (fixp->fx_r_type)
+ {
+ case BFD_RELOC_8:
+ if (fixp->fx_pcrel)
+ {
+ code = BFD_RELOC_8_PCREL;
+ break;
+ }
+
+ case BFD_RELOC_16:
+ if (fixp->fx_pcrel)
+ {
+ code = BFD_RELOC_16_PCREL;
+ break;
+ }
+
+ case BFD_RELOC_32:
+ if (fixp->fx_pcrel)
+ {
+ code = BFD_RELOC_32_PCREL;
+ break;
+ }
+
+ case BFD_RELOC_ARM_PCREL_BRANCH:
+ case BFD_RELOC_RVA:
+ case BFD_RELOC_THUMB_PCREL_BRANCH9:
+ case BFD_RELOC_THUMB_PCREL_BRANCH12:
+ case BFD_RELOC_THUMB_PCREL_BRANCH23:
+ case BFD_RELOC_VTABLE_ENTRY:
+ case BFD_RELOC_VTABLE_INHERIT:
+ code = fixp->fx_r_type;
+ break;
+
+ case BFD_RELOC_ARM_LITERAL:
+ case BFD_RELOC_ARM_HWLITERAL:
+ /* If this is called then the a literal has been referenced across
+ a section boundry - possibly due to an implicit dump */
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("Literal referenced across section boundry (Implicit dump?)"));
+ return NULL;
+
+ case BFD_RELOC_ARM_GOTPC:
+ assert (fixp->fx_pcrel != 0);
+ code = fixp->fx_r_type;
+ code = BFD_RELOC_32_PCREL;
+ break;
+
+#ifdef OBJ_ELF
+ case BFD_RELOC_ARM_GOT32:
+ case BFD_RELOC_ARM_GOTOFF:
+ case BFD_RELOC_ARM_PLT32:
+ code = fixp->fx_r_type;
+ break;
+#endif
+
+ case BFD_RELOC_ARM_IMMEDIATE:
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("Internal_relocation (type %d) not fixed up (IMMEDIATE)"),
+ fixp->fx_r_type);
+ return NULL;
+
+ case BFD_RELOC_ARM_OFFSET_IMM:
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("Internal_relocation (type %d) not fixed up (OFFSET_IMM)"),
+ fixp->fx_r_type);
+ return NULL;
+
+ default:
+ {
+ char * type;
+ switch (fixp->fx_r_type)
+ {
+ case BFD_RELOC_ARM_IMMEDIATE: type = "IMMEDIATE"; break;
+ case BFD_RELOC_ARM_OFFSET_IMM: type = "OFFSET_IMM"; break;
+ case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
+ case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
+ case BFD_RELOC_ARM_SWI: type = "SWI"; break;
+ case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
+ case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
+ case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
+ case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
+ case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
+ case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
+ default: type = "<unknown>"; break;
+ }
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("Can not represent %s relocation in this object file format (%d)"),
+ type, fixp->fx_pcrel);
+ return NULL;
+ }
+ }
+
+#ifdef OBJ_ELF
+ if (code == BFD_RELOC_32_PCREL
+ && GOT_symbol
+ && fixp->fx_addsy == GOT_symbol)
+ code = BFD_RELOC_ARM_GOTPC;
+#endif
+
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
+
+ if (reloc->howto == NULL)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("Can not represent %s relocation in this object file format"),
+ bfd_get_reloc_code_name (code));
+ return NULL;
+ }
+
+ return reloc;
+}
+
+int
+md_estimate_size_before_relax (fragP, segtype)
+ fragS * fragP;
+ segT segtype;
+{
+ as_fatal (_("md_estimate_size_before_relax\n"));
+ return 1;
+}
+
+static void
+output_inst (str)
+ char * str;
+{
+ char * to = NULL;
+
+ if (inst.error)
+ {
+ as_bad (inst.error);
+ return;
+ }
+
+ to = frag_more (inst.size);
+ if (thumb_mode && (inst.size > THUMB_SIZE))
+ {
+ assert (inst.size == (2 * THUMB_SIZE));
+ md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
+ md_number_to_chars (to + 2, inst.instruction, THUMB_SIZE);
+ }
+ else
+ md_number_to_chars (to, inst.instruction, inst.size);
+
+ if (inst.reloc.type != BFD_RELOC_NONE)
+ fix_new_arm (frag_now, to - frag_now->fr_literal,
+ inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
+ inst.reloc.type);
+
+ return;
+}
+
+void
+md_assemble (str)
+ char * str;
+{
+ char c;
+ char * p;
+ char * q;
+ char * start;
+
+ /* Align the instruction.
+ This may not be the right thing to do but ... */
+ /* arm_align (2, 0); */
+ listing_prev_line (); /* Defined in listing.h */
+
+ /* Align the previous label if needed. */
+ if (last_label_seen != NULL)
+ {
+ last_label_seen->sy_frag = frag_now;
+ S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
+ S_SET_SEGMENT (last_label_seen, now_seg);
+ }
+
+ memset (&inst, '\0', sizeof (inst));
+ inst.reloc.type = BFD_RELOC_NONE;
+
+ if (*str == ' ')
+ str++; /* Skip leading white space */
+
+ /* Scan up to the end of the op-code, which must end in white space or
+ end of string. */
+ for (start = p = str; *p != '\0'; p++)
+ if (*p == ' ')
+ break;
+
+ if (p == str)
+ {
+ as_bad (_("No operator -- statement `%s'\n"), str);
+ return;
+ }
+
+ if (thumb_mode)
+ {
+ CONST struct thumb_opcode *opcode;
+
+ c = *p;
+ *p = '\0';
+ opcode = (CONST struct thumb_opcode *) hash_find (arm_tops_hsh, str);
+ *p = c;
+ if (opcode)
+ {
+ inst.instruction = opcode->value;
+ inst.size = opcode->size;
+ (*opcode->parms)(p);
+ output_inst (start);
+ return;
+ }
+ }
+ else
+ {
+ CONST struct asm_opcode *opcode;
+
+ inst.size = INSN_SIZE;
+ /* p now points to the end of the opcode, probably white space, but we
+ have to break the opcode up in case it contains condionals and flags;
+ keep trying with progressively smaller basic instructions until one
+ matches, or we run out of opcode. */
+ q = (p - str > LONGEST_INST) ? str + LONGEST_INST : p;
+ for (; q != str; q--)
+ {
+ c = *q;
+ *q = '\0';
+ opcode = (CONST struct asm_opcode *) hash_find (arm_ops_hsh, str);
+ *q = c;
+ if (opcode && opcode->template)
+ {
+ unsigned long flag_bits = 0;
+ char *r;
+
+ /* Check that this instruction is supported for this CPU */
+ if ((opcode->variants & cpu_variant) == 0)
+ goto try_shorter;
+
+ inst.instruction = opcode->value;
+ if (q == p) /* Just a simple opcode */
+ {
+ if (opcode->comp_suffix != 0)
+ as_bad (_("Opcode `%s' must have suffix from <%s>\n"), str,
+ opcode->comp_suffix);
+ else
+ {
+ inst.instruction |= COND_ALWAYS;
+ (*opcode->parms)(q, 0);
+ }
+ output_inst (start);
+ return;
+ }
+
+ /* Now check for a conditional */
+ r = q;
+ if (p - r >= 2)
+ {
+ CONST struct asm_cond *cond;
+ char d = *(r + 2);
+
+ *(r + 2) = '\0';
+ cond = (CONST struct asm_cond *) hash_find (arm_cond_hsh, r);
+ *(r + 2) = d;
+ if (cond)
+ {
+ if (cond->value == 0xf0000000)
+ as_tsktsk (
+_("Warning: Use of the 'nv' conditional is deprecated\n"));
+
+ inst.instruction |= cond->value;
+ r += 2;
+ }
+ else
+ inst.instruction |= COND_ALWAYS;
+ }
+ else
+ inst.instruction |= COND_ALWAYS;
+
+ /* if there is a compulsory suffix, it should come here, before
+ any optional flags. */
+ if (opcode->comp_suffix)
+ {
+ CONST char *s = opcode->comp_suffix;
+
+ while (*s)
+ {
+ inst.suffix++;
+ if (*r == *s)
+ break;
+ s++;
+ }
+
+ if (*s == '\0')
+ {
+ as_bad (_("Opcode `%s' must have suffix from <%s>\n"), str,
+ opcode->comp_suffix);
+ return;
+ }
+
+ r++;
+ }
+
+ /* The remainder, if any should now be flags for the instruction;
+ Scan these checking each one found with the opcode. */
+ if (r != p)
+ {
+ char d;
+ CONST struct asm_flg *flag = opcode->flags;
+
+ if (flag)
+ {
+ int flagno;
+
+ d = *p;
+ *p = '\0';
+
+ for (flagno = 0; flag[flagno].template; flagno++)
+ {
+ if (streq (r, flag[flagno].template))
+ {
+ flag_bits |= flag[flagno].set_bits;
+ break;
+ }
+ }
+
+ *p = d;
+ if (! flag[flagno].template)
+ goto try_shorter;
+ }
+ else
+ goto try_shorter;
+ }
+
+ (*opcode->parms) (p, flag_bits);
+ output_inst (start);
+ return;
+ }
+
+ try_shorter:
+ ;
+ }
+ }
+
+ /* It wasn't an instruction, but it might be a register alias of the form
+ alias .req reg
+ */
+ q = p;
+ while (*q == ' ')
+ q++;
+
+ c = *p;
+ *p = '\0';
+
+ if (*q && !strncmp (q, ".req ", 4))
+ {
+ int reg;
+ char * copy_of_str = str;
+ char * r;
+
+ q += 4;
+ while (*q == ' ')
+ q++;
+
+ for (r = q; *r != '\0'; r++)
+ if (*r == ' ')
+ break;
+
+ if (r != q)
+ {
+ int regnum;
+ char d = *r;
+
+ *r = '\0';
+ regnum = arm_reg_parse (& q);
+ *r = d;
+
+ reg = arm_reg_parse (& str);
+
+ if (reg == FAIL)
+ {
+ if (regnum != FAIL)
+ {
+ insert_reg_alias (str, regnum);
+ }
+ else
+ {
+ as_warn (_("register '%s' does not exist\n"), q);
+ }
+ }
+ else if (regnum != FAIL)
+ {
+ if (reg != regnum)
+ as_warn (_("ignoring redefinition of register alias '%s'"), copy_of_str );
+
+ /* Do not warn abpout redefinitions to the same alias. */
+ }
+ else
+ as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
+ copy_of_str, q);
+ }
+ else
+ as_warn (_("ignoring incomplete .req pseuso op"));
+
+ *p = c;
+ return;
+ }
+
+ *p = c;
+ as_bad (_("bad instruction `%s'"), start);
+}
+
+/*
+ * md_parse_option
+ * Invocation line includes a switch not recognized by the base assembler.
+ * See if it's a processor-specific option. These are:
+ * Cpu variants, the arm part is optional:
+ * -m[arm]1 Currently not supported.
+ * -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
+ * -m[arm]3 Arm 3 processor
+ * -m[arm]6[xx], Arm 6 processors
+ * -m[arm]7[xx][t][[d]m] Arm 7 processors
+ * -mstrongarm[110] Arm 8 processors
+ * -mall All (except the ARM1)
+ * FP variants:
+ * -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
+ * -mfpe-old (No float load/store multiples)
+ * -mno-fpu Disable all floating point instructions
+ * Run-time endian selection:
+ * -EB big endian cpu
+ * -EL little endian cpu
+ * ARM Procedure Calling Standard:
+ * -mapcs-32 32 bit APCS
+ * -mapcs-26 26 bit APCS
+ * -mapcs-float Pass floats in float regs
+ * -mapcs-reentrant Position independent code
+ * -mthumb-interwork Code supports Arm/Thumb interworking
+ * -moabi Old ELF ABI
+ */
+
+CONST char * md_shortopts = "m:k";
+struct option md_longopts[] =
+{
+#ifdef ARM_BI_ENDIAN
+#define OPTION_EB (OPTION_MD_BASE + 0)
+ {"EB", no_argument, NULL, OPTION_EB},
+#define OPTION_EL (OPTION_MD_BASE + 1)
+ {"EL", no_argument, NULL, OPTION_EL},
+#ifdef OBJ_ELF
+#define OPTION_OABI (OPTION_MD_BASE +2)
+ {"oabi", no_argument, NULL, OPTION_OABI},
+#endif
+#endif
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof (md_longopts);
+
+int
+md_parse_option (c, arg)
+ int c;
+ char * arg;
+{
+ char * str = arg;
+
+ switch (c)
+ {
+#ifdef ARM_BI_ENDIAN
+ case OPTION_EB:
+ target_big_endian = 1;
+ break;
+ case OPTION_EL:
+ target_big_endian = 0;
+ break;
+#endif
+
+ case 'm':
+ switch (*str)
+ {
+ case 'f':
+ if (streq (str, "fpa10"))
+ cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_FPA10;
+ else if (streq (str, "fpa11"))
+ cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_FPA11;
+ else if (streq (str, "fpe-old"))
+ cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_CORE;
+ else
+ goto bad;
+ break;
+
+ case 'n':
+ if (streq (str, "no-fpu"))
+ cpu_variant &= ~FPU_ALL;
+ break;
+
+#ifdef OBJ_ELF
+ case 'o':
+ if (streq (str, "oabi"))
+ target_oabi = true;
+ break;
+#endif
+
+ case 't':
+ /* Limit assembler to generating only Thumb instructions: */
+ if (streq (str, "thumb"))
+ {
+ cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_THUMB;
+ cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_NONE;
+ thumb_mode = 1;
+ }
+ else if (streq (str, "thumb-interwork"))
+ {
+ cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_THUMB | ARM_ARCHv4;
+#if defined OBJ_COFF || defined OBJ_ELF
+ support_interwork = true;
+#endif
+ }
+ else
+ goto bad;
+ break;
+
+ default:
+ if (streq (str, "all"))
+ {
+ cpu_variant = ARM_ALL | FPU_ALL;
+ return 1;
+ }
+#if defined OBJ_COFF || defined OBJ_ELF
+ if (! strncmp (str, "apcs-", 5))
+ {
+ /* GCC passes on all command line options starting "-mapcs-..."
+ to us, so we must parse them here. */
+
+ str += 5;
+
+ if (streq (str, "32"))
+ {
+ uses_apcs_26 = false;
+ return 1;
+ }
+ else if (streq (str, "26"))
+ {
+ uses_apcs_26 = true;
+ return 1;
+ }
+ else if (streq (str, "frame"))
+ {
+ /* Stack frames are being generated - does not affect
+ linkage of code. */
+ return 1;
+ }
+ else if (streq (str, "stack-check"))
+ {
+ /* Stack checking is being performed - does not affect
+ linkage, but does require that the functions
+ __rt_stkovf_split_small and __rt_stkovf_split_big be
+ present in the final link. */
+
+ return 1;
+ }
+ else if (streq (str, "float"))
+ {
+ /* Floating point arguments are being passed in the floating
+ point registers. This does affect linking, since this
+ version of the APCS is incompatible with the version that
+ passes floating points in the integer registers. */
+
+ uses_apcs_float = true;
+ return 1;
+ }
+ else if (streq (str, "reentrant"))
+ {
+ /* Reentrant code has been generated. This does affect
+ linking, since there is no point in linking reentrant/
+ position independent code with absolute position code. */
+ pic_code = true;
+ return 1;
+ }
+
+ as_bad (_("Unrecognised APCS switch -m%s"), arg);
+ return 0;
+ }
+#endif
+ /* Strip off optional "arm" */
+ if (! strncmp (str, "arm", 3))
+ str += 3;
+
+ switch (*str)
+ {
+ case '1':
+ if (streq (str, "1"))
+ cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_1;
+ else
+ goto bad;
+ break;
+
+ case '2':
+ if (streq (str, "2"))
+ cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_2;
+ else if (streq (str, "250"))
+ cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_250;
+ else
+ goto bad;
+ break;
+
+ case '3':
+ if (streq (str, "3"))
+ cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_3;
+ else
+ goto bad;
+ break;
+
+ case '6':
+ switch (strtol (str, NULL, 10))
+ {
+ case 6:
+ case 60:
+ case 600:
+ case 610:
+ case 620:
+ cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_6;
+ break;
+ default:
+ goto bad;
+ }
+ break;
+
+ case '7':
+ switch (strtol (str, & str, 10)) /* Eat the processor name */
+ {
+ case 7:
+ case 70:
+ case 700:
+ case 710:
+ case 7100:
+ case 7500:
+ break;
+ default:
+ goto bad;
+ }
+ cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7;
+ for (; *str; str++)
+ {
+ switch (* str)
+ {
+ case 't':
+ cpu_variant |= (ARM_THUMB | ARM_ARCHv4);
+ break;
+
+ case 'm':
+ cpu_variant |= ARM_LONGMUL;
+ break;
+
+ case 'f': /* fe => fp enabled cpu. */
+ if (str[1] == 'e')
+ ++ str;
+ else
+ goto bad;
+
+ case 'c': /* Left over from 710c processor name. */
+ case 'd': /* Debug */
+ case 'i': /* Embedded ICE */
+ /* Included for completeness in ARM processor naming. */
+ break;
+
+ default:
+ goto bad;
+ }
+ }
+ break;
+
+ case '8':
+ if (streq (str, "8") || streq (str, "810"))
+ cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_8 | ARM_ARCHv4 | ARM_LONGMUL;
+ else
+ goto bad;
+ break;
+
+ case '9':
+ if (streq (str, "9"))
+ cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_9 | ARM_ARCHv4 | ARM_LONGMUL;
+ else if (streq (str, "9tdmi"))
+ cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_9 | ARM_ARCHv4 | ARM_LONGMUL | ARM_THUMB;
+ else
+ goto bad;
+ break;
+
+ case 's':
+ if (streq (str, "strongarm")
+ || streq (str, "strongarm110")
+ || streq (str, "strongarm1100"))
+ cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_8 | ARM_ARCHv4 | ARM_LONGMUL;
+ else
+ goto bad;
+ break;
+
+ case 'v':
+ /* Select variant based on architecture rather than processor */
+ switch (*++str)
+ {
+ case '2':
+ switch (*++str)
+ {
+ case 'a': cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_3; break;
+ case 0: cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_2; break;
+ default: as_bad (_("Invalid architecture variant -m%s"), arg); break;
+ }
+ break;
+
+ case '3':
+ cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7;
+
+ switch (*++str)
+ {
+ case 'm': cpu_variant |= ARM_LONGMUL; break;
+ case 0: break;
+ default: as_bad (_("Invalid architecture variant -m%s"), arg); break;
+ }
+ break;
+
+ case '4':
+ cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_ARCHv4;
+
+ switch (*++str)
+ {
+ case 't': cpu_variant |= ARM_THUMB; break;
+ case 0: break;
+ default: as_bad (_("Invalid architecture variant -m%s"), arg); break;
+ }
+ break;
+
+ default:
+ as_bad (_("Invalid architecture variant -m%s"), arg);
+ break;
+ }
+ break;
+
+ default:
+ bad:
+ as_bad (_("Invalid processor variant -m%s"), arg);
+ return 0;
+ }
+ }
+ break;
+
+ case 'k':
+ pic_code = 1;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+void
+md_show_usage (fp)
+ FILE * fp;
+{
+ fprintf (fp,
+_("\
+ ARM Specific Assembler Options:\n\
+ -m[arm][<processor name>] select processor variant\n\
+ -m[arm]v[2|2a|3|3m|4|4t] select architecture variant\n\
+ -mthumb only allow Thumb instructions\n\
+ -mthumb-interwork mark the assembled code as supporting interworking\n\
+ -mall allow any instruction\n\
+ -mfpa10, -mfpa11 select floating point architecture\n\
+ -mfpe-old don't allow floating-point multiple instructions\n\
+ -mno-fpu don't allow any floating-point instructions.\n"));
+ fprintf (fp,
+_("\
+ -k generate PIC code.\n"));
+#if defined OBJ_COFF || defined OBJ_ELF
+ fprintf (fp,
+_("\
+ -mapcs-32, -mapcs-26 specify which ARM Procedure Calling Standard to use\n"));
+ fprintf (fp,
+_("\
+ -mapcs-float floating point args are passed in FP regs\n"));
+ fprintf (fp,
+_("\
+ -mapcs-reentrant the code is position independent/reentrant\n"));
+ #endif
+#ifdef OBJ_ELF
+ fprintf (fp,
+_("\
+ -moabi support the old ELF ABI\n"));
+#endif
+#ifdef ARM_BI_ENDIAN
+ fprintf (fp,
+_("\
+ -EB assemble code for a big endian cpu\n\
+ -EL assemble code for a little endian cpu\n"));
+#endif
+}
+
+/* We need to be able to fix up arbitrary expressions in some statements.
+ This is so that we can handle symbols that are an arbitrary distance from
+ the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
+ which returns part of an address in a form which will be valid for
+ a data instruction. We do this by pushing the expression into a symbol
+ in the expr_section, and creating a fix for that. */
+
+static void
+fix_new_arm (frag, where, size, exp, pc_rel, reloc)
+ fragS * frag;
+ int where;
+ short int size;
+ expressionS * exp;
+ int pc_rel;
+ int reloc;
+{
+ fixS * new_fix;
+ arm_fix_data * arm_data;
+
+ switch (exp->X_op)
+ {
+ case O_constant:
+ case O_symbol:
+ case O_add:
+ case O_subtract:
+ new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
+ break;
+
+ default:
+ new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
+ pc_rel, reloc);
+ break;
+ }
+
+ /* Mark whether the fix is to a THUMB instruction, or an ARM instruction */
+ arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
+ new_fix->tc_fix_data = (PTR) arm_data;
+ arm_data->thumb_mode = thumb_mode;
+
+ return;
+}
+
+
+/*
+ * This fix_new is called by cons via TC_CONS_FIX_NEW
+ *
+ * We check the expression to see if it is of the form
+ * __GLOBAL_OFFSET_TABLE + ???
+ * If it is then this is a PC relative reference to the GOT.
+ * i.e.
+ * ldr sl, L1
+ * add sl, pc, sl
+ * L2:
+ * ...
+ * L1:
+ * .word __GLOBAL_OFFSET_TABLE + (. - (L2 + 4))
+ *
+ * In this case use a reloc type BFD_RELOC_ARM_GOTPC instead of the
+ * normal BFD_RELOC_{16,32,64}
+ */
+
+void
+cons_fix_new_arm (frag, where, size, exp)
+ fragS * frag;
+ int where;
+ int size;
+ expressionS * exp;
+{
+ bfd_reloc_code_real_type type;
+ int pcrel = 0;
+
+ /* Pick a reloc ...
+ *
+ * @@ Should look at CPU word size.
+ */
+ switch (size)
+ {
+ case 2:
+ type = BFD_RELOC_16;
+ break;
+ case 4:
+ default:
+ type = BFD_RELOC_32;
+ break;
+ case 8:
+ type = BFD_RELOC_64;
+ break;
+ }
+
+ /* Look for possible GOTPC reloc */
+
+ /*
+ * Look for pic assembler and 'undef symbol + expr symbol' expression
+ * and a 32 bit size.
+ */
+
+ fix_new_exp (frag, where, (int) size, exp, pcrel, type);
+}
+
+/* A good place to do this, although this was probably not intended
+ * for this kind of use. We need to dump the literal pool before
+ * references are made to a null symbol pointer. */
+void
+arm_cleanup ()
+{
+ if (current_poolP != NULL)
+ {
+ subseg_set (text_section, 0); /* Put it at the end of text section */
+ s_ltorg (0);
+ listing_prev_line ();
+ }
+}
+
+void
+arm_start_line_hook ()
+{
+ last_label_seen = NULL;
+}
+
+void
+arm_frob_label (sym)
+ symbolS * sym;
+{
+ last_label_seen = sym;
+
+ ARM_SET_THUMB (sym, thumb_mode);
+
+#if defined OBJ_COFF || defined OBJ_ELF
+ ARM_SET_INTERWORK (sym, support_interwork);
+#endif
+
+ if (label_is_thumb_function_name)
+ {
+ /* When the address of a Thumb function is taken the bottom
+ bit of that address should be set. This will allow
+ interworking between Arm and Thumb functions to work
+ correctly. */
+
+ THUMB_SET_FUNC (sym, 1);
+
+ label_is_thumb_function_name = false;
+ }
+}
+
+/* Adjust the symbol table. This marks Thumb symbols as distinct from
+ ARM ones. */
+
+void
+arm_adjust_symtab ()
+{
+#ifdef OBJ_COFF
+ symbolS * sym;
+
+ for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
+ {
+ if (ARM_IS_THUMB (sym))
+ {
+ if (THUMB_IS_FUNC (sym))
+ {
+ /* Mark the symbol as a Thumb function. */
+ if ( S_GET_STORAGE_CLASS (sym) == C_STAT
+ || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
+ S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
+
+ else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
+ S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
+ else
+ as_bad (_("%s: unexpected function type: %d"),
+ S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
+ }
+ else switch (S_GET_STORAGE_CLASS (sym))
+ {
+ case C_EXT:
+ S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
+ break;
+ case C_STAT:
+ S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
+ break;
+ case C_LABEL:
+ S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
+ break;
+ default: /* do nothing */
+ break;
+ }
+ }
+
+ if (ARM_IS_INTERWORK (sym))
+ coffsymbol(sym->bsym)->native->u.syment.n_flags = 0xFF;
+ }
+#endif
+#ifdef OBJ_ELF
+ symbolS * sym;
+ elf_symbol_type * elf_sym;
+ char bind;
+
+ for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
+ {
+ if (ARM_IS_THUMB (sym))
+ {
+ if (THUMB_IS_FUNC (sym))
+ {
+ elf_sym = elf_symbol (sym->bsym);
+ bind = ELF_ST_BIND (elf_sym);
+ elf_sym->internal_elf_sym.st_info = ELF_ST_INFO (bind, STT_ARM_TFUNC);
+ }
+ }
+ }
+#endif
+}
+
+int
+arm_data_in_code ()
+{
+ if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
+ {
+ *input_line_pointer = '/';
+ input_line_pointer += 5;
+ *input_line_pointer = 0;
+ return 1;
+ }
+
+ return 0;
+}
+
+char *
+arm_canonicalize_symbol_name (name)
+ char * name;
+{
+ int len;
+
+ if (thumb_mode && (len = strlen (name)) > 5
+ && streq (name + len - 5, "/data"))
+ {
+ *(name + len - 5) = 0;
+ }
+
+ return name;
+}
+
+boolean
+arm_validate_fix (fixP)
+ fixS * fixP;
+{
+ /* If the destination of the branch is a defined symbol which does not have
+ the THUMB_FUNC attribute, then we must be calling a function which has
+ the (interfacearm) attribute. We look for the Thumb entry point to that
+ function and change the branch to refer to that function instead. */
+ if ( fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
+ && fixP->fx_addsy != NULL
+ && S_IS_DEFINED (fixP->fx_addsy)
+ && ! THUMB_IS_FUNC (fixP->fx_addsy))
+ {
+ fixP->fx_addsy = find_real_start (fixP->fx_addsy);
+ return true;
+ }
+
+ return false;
+}
+
+#ifdef OBJ_ELF
+/* Relocations against Thumb function names must be left unadjusted,
+ so that the linker can use this information to correctly set the
+ bottom bit of their addresses. The MIPS version of this function
+ also prevents relocations that are mips-16 specific, but I do not
+ know why it does this.
+
+ FIXME:
+ There is one other problem that ought to be addressed here, but
+ which currently is not: Taking the address of a label (rather
+ than a function) and then later jumping to that address. Such
+ addresses also ought to have their bottom bit set (assuming that
+ they reside in Thumb code), but at the moment they will not. */
+
+boolean
+arm_fix_adjustable (fixP)
+ fixS * fixP;
+{
+
+ if (fixP->fx_addsy == NULL)
+ return 1;
+
+ /* Prevent all adjustments to global symbols. */
+ if (S_IS_EXTERN (fixP->fx_addsy))
+ return 0;
+
+ if (S_IS_WEAK (fixP->fx_addsy))
+ return 0;
+
+ if (THUMB_IS_FUNC (fixP->fx_addsy)
+ && fixP->fx_subsy == NULL)
+ return 0;
+
+ /* We need the symbol name for the VTABLE entries */
+ if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ return 0;
+
+ return 1;
+}
+
+const char *
+elf32_arm_target_format ()
+{
+ if (target_big_endian)
+ if (target_oabi)
+ return "elf32-bigarm-oabi";
+ else
+ return "elf32-bigarm";
+ else
+ if (target_oabi)
+ return "elf32-littlearm-oabi";
+ else
+ return "elf32-littlearm";
+}
+
+void
+armelf_frob_symbol (symp, puntp)
+ symbolS * symp;
+ int * puntp;
+{
+ elf_frob_symbol (symp, puntp);
+}
+
+int
+arm_force_relocation (fixp)
+ struct fix * fixp;
+{
+ if ( fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
+ || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH)
+ return 1;
+
+ return 0;
+}
+
+static bfd_reloc_code_real_type
+arm_parse_reloc ()
+{
+ char id[16];
+ char * ip;
+ int i;
+ static struct
+ {
+ char * str;
+ int len;
+ bfd_reloc_code_real_type reloc;
+ }
+ reloc_map[] =
+ {
+#define MAP(str,reloc) { str, sizeof (str)-1, reloc }
+ MAP ("(got)", BFD_RELOC_ARM_GOT32),
+ MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
+ /* ScottB: Jan 30, 1998 */
+ /* Added support for parsing "var(PLT)" branch instructions */
+ /* generated by GCC for PLT relocs */
+ MAP ("(plt)", BFD_RELOC_ARM_PLT32),
+ NULL, 0, BFD_RELOC_UNUSED
+#undef MAP
+ };
+
+ for (i = 0, ip = input_line_pointer;
+ i < sizeof (id) && (isalnum (*ip) || ispunct (*ip));
+ i++, ip++)
+ id[i] = tolower (*ip);
+
+ for (i = 0; reloc_map[i].str; i++)
+ if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
+ break;
+
+ input_line_pointer += reloc_map[i].len;
+
+ return reloc_map[i].reloc;
+}
+
+static void
+s_arm_elf_cons (nbytes)
+ int nbytes;
+{
+ expressionS exp;
+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+ if (is_it_end_of_statement ())
+ {
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+#ifdef md_cons_align
+ md_cons_align (nbytes);
+#endif
+
+ do
+ {
+ bfd_reloc_code_real_type reloc;
+
+ expression (& exp);
+
+ if (exp.X_op == O_symbol
+ && * input_line_pointer == '('
+ && (reloc = arm_parse_reloc()) != BFD_RELOC_UNUSED)
+ {
+ reloc_howto_type * howto = bfd_reloc_type_lookup (stdoutput, reloc);
+ int size = bfd_get_reloc_size (howto);
+
+ if (size > nbytes)
+ as_bad ("%s relocations do not fit in %d bytes", howto->name, nbytes);
+ else
+ {
+ register char * p = frag_more ((int) nbytes);
+ int offset = nbytes - size;
+
+ fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
+ & exp, 0, reloc);
+ }
+ }
+ else
+ emit_expr (& exp, (unsigned int) nbytes);
+ }
+ while (*input_line_pointer++ == ',');
+
+ input_line_pointer--; /* Put terminator back into stream. */
+ demand_empty_rest_of_line ();
+}
+
+#endif /* OBJ_ELF */
+
diff --git a/gas/config/tc-arm.h b/gas/config/tc-arm.h
new file mode 100644
index 0000000000..bf99e243b5
--- /dev/null
+++ b/gas/config/tc-arm.h
@@ -0,0 +1,204 @@
+/* This file is tc-arm.h
+ Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+ Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
+ Modified by David Taylor (dtaylor@armltd.co.uk)
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#define TC_ARM 1
+
+#ifndef TARGET_BYTES_BIG_ENDIAN
+#define TARGET_BYTES_BIG_ENDIAN 0
+#endif
+
+#define WORKING_DOT_WORD
+
+#define COFF_MAGIC ARMMAGIC
+#define TARGET_ARCH bfd_arch_arm
+
+#define AOUT_MACHTYPE 0
+
+#define DIFF_EXPR_OK
+
+#ifdef LITTLE_ENDIAN
+#undef LITTLE_ENDIAN
+#endif
+
+#ifdef BIG_ENDIAN
+#undef BIG_ENDIAN
+#endif
+
+#define LITTLE_ENDIAN 1234
+#define BIG_ENDIAN 4321
+
+#if defined OBJ_AOUT
+#if defined TE_RISCIX
+# define TARGET_FORMAT "a.out-riscix"
+#elif defined TE_LINUX
+# define ARM_BI_ENDIAN
+# define TARGET_FORMAT "a.out-arm-linux"
+#elif defined TE_NetBSD
+# define TARGET_FORMAT "a.out-arm-netbsd"
+#else
+# define ARM_BI_ENDIAN
+# define TARGET_FORMAT \
+ (target_big_endian ? "a.out-arm-big" : "a.out-arm-little")
+#endif
+#endif /* OBJ_AOUT */
+
+#ifdef OBJ_AIF
+#define TARGET_FORMAT "aif"
+#endif
+
+#if defined OBJ_COFF || defined OBJ_ELF
+# define ARM_BI_ENDIAN
+
+# define TC_VALIDATE_FIX(fixP, segType, Label) \
+ if (arm_validate_fix (fixP)) add_symbolP = fixP->fx_addsy
+ extern boolean arm_validate_fix PARAMS ((struct fix *));
+#endif
+
+#ifdef OBJ_COFF
+# if defined TE_PE
+# define TC_FORCE_RELOCATION(x) ((x)->fx_r_type == BFD_RELOC_RVA)
+# ifdef TE_EPOC
+# define TARGET_FORMAT (target_big_endian ? "epoc-pe-arm-big" : "epoc-pe-arm-little")
+# else
+# define TARGET_FORMAT (target_big_endian ? "pe-arm-big" : "pe-arm-little")
+# endif
+# else
+# define TARGET_FORMAT (target_big_endian ? "coff-arm-big" : "coff-arm-little")
+# endif
+#endif
+
+#ifdef OBJ_ELF
+# define TARGET_FORMAT elf32_arm_target_format()
+ extern const char * elf32_arm_target_format PARAMS ((void));
+
+# define TC_FORCE_RELOCATION(fixp) arm_force_relocation (fixp)
+ extern int arm_force_relocation PARAMS ((struct fix *));
+#endif
+
+#define md_convert_frag(b, s, f) {as_fatal (_("arm convert_frag\n"));}
+
+#define md_cleanup() arm_cleanup ()
+ extern void arm_cleanup PARAMS ((void));
+
+#define md_start_line_hook() arm_start_line_hook ()
+ extern void arm_start_line_hook PARAMS ((void));
+
+#define tc_frob_label(S) arm_frob_label (S)
+ extern void arm_frob_label PARAMS ((struct symbol *));
+
+/* We also need to mark assembler created symbols: */
+#define tc_frob_fake_label(S) arm_frob_label (S)
+
+/* NOTE: The fake label creation in stabs.c:s_stab_generic() has
+ deliberately not been updated to mark assembler created stabs
+ symbols as Thumb. */
+
+#ifdef OBJ_ELF
+#define obj_fix_adjustable(fixP) arm_fix_adjustable (fixP)
+#else
+#define obj_fix_adjustable(fixP) 0
+#endif
+
+/* We need to keep some local information on symbols. */
+
+#define TC_SYMFIELD_TYPE unsigned int
+#define ARM_GET_FLAG(s) ((s)->sy_tc)
+#define ARM_SET_FLAG(s,v) ((s)->sy_tc |= (v))
+#define ARM_RESET_FLAG(s,v) ((s)->sy_tc &= ~(v))
+
+#define ARM_FLAG_THUMB (1 << 0) /* The symbol is a Thumb symbol rather than an Arm symbol. */
+#define ARM_FLAG_INTERWORK (1 << 1) /* The symbol is attached to code that suppports interworking. */
+#define THUMB_FLAG_FUNC (1 << 2) /* The symbol is attached to the start of a Thumb function. */
+
+#define ARM_IS_THUMB(s) (ARM_GET_FLAG (s) & ARM_FLAG_THUMB)
+#define ARM_IS_INTERWORK(s) (ARM_GET_FLAG (s) & ARM_FLAG_INTERWORK)
+#define THUMB_IS_FUNC(s) (ARM_GET_FLAG (s) & THUMB_FLAG_FUNC)
+
+#define ARM_SET_THUMB(s,t) ((t) ? ARM_SET_FLAG (s, ARM_FLAG_THUMB) : ARM_RESET_FLAG (s, ARM_FLAG_THUMB))
+#define ARM_SET_INTERWORK(s,t) ((t) ? ARM_SET_FLAG (s, ARM_FLAG_INTERWORK) : ARM_RESET_FLAG (s, ARM_FLAG_INTERWORK))
+#define THUMB_SET_FUNC(s,t) ((t) ? ARM_SET_FLAG (s, THUMB_FLAG_FUNC) : ARM_RESET_FLAG (s, THUMB_FLAG_FUNC))
+
+
+#define TC_FIX_TYPE PTR
+#define TC_INIT_FIX_DATA(FIXP) ((FIXP)->tc_fix_data = NULL)
+
+#define TC_START_LABEL(C,STR) \
+ (c == ':' || (c == '/' && arm_data_in_code ()))
+int arm_data_in_code PARAMS ((void));
+
+#define tc_canonicalize_symbol_name(str) \
+ arm_canonicalize_symbol_name (str);
+char * arm_canonicalize_symbol_name PARAMS ((char *));
+
+#define obj_adjust_symtab() arm_adjust_symtab ()
+ extern void arm_adjust_symtab PARAMS ((void));
+
+#ifdef OBJ_ELF
+#define obj_frob_symbol(sym, punt) armelf_frob_symbol (sym, punt)
+#endif
+
+#define tc_aout_pre_write_hook(x) {;} /* not used */
+
+#define LISTING_HEADER "ARM GAS "
+
+#define OPTIONAL_REGISTER_PREFIX '%'
+
+#define md_operand(x)
+
+#define TC_HANDLES_FX_DONE
+
+#define MD_APPLY_FIX3
+
+#define LOCAL_LABEL(name) (name[0] == '.' && (name[1] == 'L'))
+#define LOCAL_LABELS_FB 1
+
+/* This expression evaluates to false if the relocation is for a local object
+ for which we still want to do the relocation at runtime. True if we
+ are willing to perform this relocation while building the .o file.
+ This is only used for pcrel relocations, so GOTOFF does not need to be
+ checked here. I am not sure if some of the others are ever used with
+ pcrel, but it is easier to be safe than sorry. */
+
+#define TC_RELOC_RTSYM_LOC_FIXUP(FIX) \
+ ( (FIX)->fx_r_type != BFD_RELOC_ARM_GOT12 \
+ && (FIX)->fx_r_type != BFD_RELOC_ARM_GOT32 \
+ && (FIX)->fx_r_type != BFD_RELOC_32)
+
+#define TC_CONS_FIX_NEW cons_fix_new_arm
+ extern void cons_fix_new_arm PARAMS ((fragS *, int, int, expressionS *));
+
+/* Don't allow symbols to be discarded on GOT related relocs,
+ nor on globals. */
+#define tc_fix_adjustable(x) (\
+ ((x)->fx_r_type == BFD_RELOC_ARM_PLT32 \
+ || (x)->fx_r_type == BFD_RELOC_ARM_GOT32 \
+ || (x)->fx_r_type == BFD_RELOC_ARM_GOTOFF \
+ || S_IS_EXTERN ((x)->fx_addsy) \
+ || S_IS_WEAK ((x)->fx_addsy)) ? 0 : 1)
+
+#ifdef OBJ_ELF
+#define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_"
+#else
+#define GLOBAL_OFFSET_TABLE_NAME "__GLOBAL_OFFSET_TABLE_"
+#endif
+
+/* end of tc-arm.h */
diff --git a/gas/config/tc-d10v.c b/gas/config/tc-d10v.c
new file mode 100644
index 0000000000..cf38f3e1e7
--- /dev/null
+++ b/gas/config/tc-d10v.c
@@ -0,0 +1,1636 @@
+/* tc-d10v.c -- Assembler code for the Mitsubishi D10V
+
+ Copyright (C) 1996, 1997, 1998 Free Software Foundation.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "as.h"
+#include "subsegs.h"
+#include "opcode/d10v.h"
+#include "elf/ppc.h"
+
+const char comment_chars[] = ";";
+const char line_comment_chars[] = "#";
+const char line_separator_chars[] = "";
+const char *md_shortopts = "O";
+const char EXP_CHARS[] = "eE";
+const char FLT_CHARS[] = "dD";
+
+int Optimizing = 0;
+
+#define AT_WORD_P(X) ((X)->X_op == O_right_shift \
+ && (X)->X_op_symbol != NULL \
+ && (X)->X_op_symbol->sy_value.X_op == O_constant \
+ && (X)->X_op_symbol->sy_value.X_add_number == AT_WORD_RIGHT_SHIFT)
+#define AT_WORD_RIGHT_SHIFT 2
+
+
+/* fixups */
+#define MAX_INSN_FIXUPS (5)
+struct d10v_fixup
+{
+ expressionS exp;
+ int operand;
+ int pcrel;
+ int size;
+ bfd_reloc_code_real_type reloc;
+};
+
+typedef struct _fixups
+{
+ int fc;
+ struct d10v_fixup fix[MAX_INSN_FIXUPS];
+ struct _fixups *next;
+} Fixups;
+
+static Fixups FixUps[2];
+static Fixups *fixups;
+
+/* True if instruction swapping warnings should be inhibited. */
+static unsigned char flag_warn_suppress_instructionswap; /* --nowarnswap */
+
+/* local functions */
+static int reg_name_search PARAMS ((char *name));
+static int register_name PARAMS ((expressionS *expressionP));
+static int check_range PARAMS ((unsigned long num, int bits, int flags));
+static int postfix PARAMS ((char *p));
+static bfd_reloc_code_real_type get_reloc PARAMS ((struct d10v_operand *op));
+static int get_operands PARAMS ((expressionS exp[]));
+static struct d10v_opcode *find_opcode PARAMS ((struct d10v_opcode *opcode, expressionS ops[]));
+static unsigned long build_insn PARAMS ((struct d10v_opcode *opcode, expressionS *opers, unsigned long insn));
+static void write_long PARAMS ((struct d10v_opcode *opcode, unsigned long insn, Fixups *fx));
+static void write_1_short PARAMS ((struct d10v_opcode *opcode, unsigned long insn, Fixups *fx));
+static int write_2_short PARAMS ((struct d10v_opcode *opcode1, unsigned long insn1,
+ struct d10v_opcode *opcode2, unsigned long insn2, int exec_type, Fixups *fx));
+static unsigned long do_assemble PARAMS ((char *str, struct d10v_opcode **opcode));
+static unsigned long d10v_insert_operand PARAMS (( unsigned long insn, int op_type,
+ offsetT value, int left, fixS *fix));
+static int parallel_ok PARAMS ((struct d10v_opcode *opcode1, unsigned long insn1,
+ struct d10v_opcode *opcode2, unsigned long insn2,
+ int exec_type));
+static symbolS * find_symbol_matching_register PARAMS ((expressionS *));
+
+struct option md_longopts[] =
+{
+#define OPTION_NOWARNSWAP (OPTION_MD_BASE)
+ {"nowarnswap", no_argument, NULL, OPTION_NOWARNSWAP},
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof(md_longopts);
+
+static void d10v_dot_word PARAMS ((int));
+
+/* The target specific pseudo-ops which we support. */
+const pseudo_typeS md_pseudo_table[] =
+{
+ { "word", d10v_dot_word, 2 },
+ { NULL, NULL, 0 }
+};
+
+/* Opcode hash table. */
+static struct hash_control *d10v_hash;
+
+/* reg_name_search does a binary search of the d10v_predefined_registers
+ array to see if "name" is a valid regiter name. Returns the register
+ number from the array on success, or -1 on failure. */
+
+static int
+reg_name_search (name)
+ char *name;
+{
+ int middle, low, high;
+ int cmp;
+
+ low = 0;
+ high = d10v_reg_name_cnt() - 1;
+
+ do
+ {
+ middle = (low + high) / 2;
+ cmp = strcasecmp (name, d10v_predefined_registers[middle].name);
+ if (cmp < 0)
+ high = middle - 1;
+ else if (cmp > 0)
+ low = middle + 1;
+ else
+ return d10v_predefined_registers[middle].value;
+ }
+ while (low <= high);
+ return -1;
+}
+
+/* register_name() checks the string at input_line_pointer
+ to see if it is a valid register name */
+
+static int
+register_name (expressionP)
+ expressionS *expressionP;
+{
+ int reg_number;
+ char c, *p = input_line_pointer;
+
+ while (*p && *p!='\n' && *p!='\r' && *p !=',' && *p!=' ' && *p!=')')
+ p++;
+
+ c = *p;
+ if (c)
+ *p++ = 0;
+
+ /* look to see if it's in the register table */
+ reg_number = reg_name_search (input_line_pointer);
+ if (reg_number >= 0)
+ {
+ expressionP->X_op = O_register;
+ /* temporarily store a pointer to the string here */
+ expressionP->X_op_symbol = (struct symbol *)input_line_pointer;
+ expressionP->X_add_number = reg_number;
+ input_line_pointer = p;
+ return 1;
+ }
+ if (c)
+ *(p-1) = c;
+ return 0;
+}
+
+
+static int
+check_range (num, bits, flags)
+ unsigned long num;
+ int bits;
+ int flags;
+{
+ long min, max, bit1;
+ int retval=0;
+
+ /* don't bother checking 16-bit values */
+ if (bits == 16)
+ return 0;
+
+ if (flags & OPERAND_SHIFT)
+ {
+ /* all special shift operands are unsigned */
+ /* and <= 16. We allow 0 for now. */
+ if (num>16)
+ return 1;
+ else
+ return 0;
+ }
+
+ if (flags & OPERAND_SIGNED)
+ {
+ max = (1 << (bits - 1))-1;
+ min = - (1 << (bits - 1));
+ if (((long)num > max) || ((long)num < min))
+ retval = 1;
+ }
+ else
+ {
+ max = (1 << bits) - 1;
+ min = 0;
+ if ((num > max) || (num < min))
+ retval = 1;
+ }
+ return retval;
+}
+
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+ fprintf(stream, _("D10V options:\n\
+-O optimize. Will do some operations in parallel.\n"));
+}
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ switch (c)
+ {
+ case 'O':
+ /* Optimize. Will attempt to parallelize operations */
+ Optimizing = 1;
+ break;
+ case OPTION_NOWARNSWAP:
+ flag_warn_suppress_instructionswap = 1;
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+symbolS *
+md_undefined_symbol (name)
+ char *name;
+{
+ return 0;
+}
+
+/* Turn a string in input_line_pointer into a floating point constant of type
+ type, and store the appropriate bytes in *litP. The number of LITTLENUMS
+ emitted is stored in *sizeP . An error message is returned, or NULL on OK.
+ */
+char *
+md_atof (type, litP, sizeP)
+ int type;
+ char *litP;
+ int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[4];
+ char *t;
+ int i;
+
+ switch (type)
+ {
+ case 'f':
+ prec = 2;
+ break;
+ case 'd':
+ prec = 4;
+ break;
+ default:
+ *sizeP = 0;
+ return _("bad call to md_atof");
+ }
+
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+
+ *sizeP = prec * 2;
+
+ for (i = 0; i < prec; i++)
+ {
+ md_number_to_chars (litP, (valueT) words[i], 2);
+ litP += 2;
+ }
+ return NULL;
+}
+
+void
+md_convert_frag (abfd, sec, fragP)
+ bfd *abfd;
+ asection *sec;
+ fragS *fragP;
+{
+ abort ();
+}
+
+valueT
+md_section_align (seg, addr)
+ asection *seg;
+ valueT addr;
+{
+ int align = bfd_get_section_alignment (stdoutput, seg);
+ return ((addr + (1 << align) - 1) & (-1 << align));
+}
+
+
+void
+md_begin ()
+{
+ char *prev_name = "";
+ struct d10v_opcode *opcode;
+ d10v_hash = hash_new();
+
+ /* Insert unique names into hash table. The D10v instruction set
+ has many identical opcode names that have different opcodes based
+ on the operands. This hash table then provides a quick index to
+ the first opcode with a particular name in the opcode table. */
+
+ for (opcode = (struct d10v_opcode *)d10v_opcodes; opcode->name; opcode++)
+ {
+ if (strcmp (prev_name, opcode->name))
+ {
+ prev_name = (char *)opcode->name;
+ hash_insert (d10v_hash, opcode->name, (char *) opcode);
+ }
+ }
+
+ fixups = &FixUps[0];
+ FixUps[0].next = &FixUps[1];
+ FixUps[1].next = &FixUps[0];
+}
+
+
+/* this function removes the postincrement or postdecrement
+ operator ( '+' or '-' ) from an expression */
+
+static int postfix (p)
+ char *p;
+{
+ while (*p != '-' && *p != '+')
+ {
+ if (*p==0 || *p=='\n' || *p=='\r')
+ break;
+ p++;
+ }
+
+ if (*p == '-')
+ {
+ *p = ' ';
+ return (-1);
+ }
+ if (*p == '+')
+ {
+ *p = ' ';
+ return (1);
+ }
+
+ return (0);
+}
+
+
+static bfd_reloc_code_real_type
+get_reloc (op)
+ struct d10v_operand *op;
+{
+ int bits = op->bits;
+
+ if (bits <= 4)
+ return (0);
+
+ if (op->flags & OPERAND_ADDR)
+ {
+ if (bits == 8)
+ return (BFD_RELOC_D10V_10_PCREL_R);
+ else
+ return (BFD_RELOC_D10V_18_PCREL);
+ }
+
+ return (BFD_RELOC_16);
+}
+
+
+/* get_operands parses a string of operands and returns
+ an array of expressions */
+
+static int
+get_operands (exp)
+ expressionS exp[];
+{
+ char *p = input_line_pointer;
+ int numops = 0;
+ int post = 0;
+
+ while (*p)
+ {
+ while (*p == ' ' || *p == '\t' || *p == ',')
+ p++;
+ if (*p==0 || *p=='\n' || *p=='\r')
+ break;
+
+ if (*p == '@')
+ {
+ p++;
+ exp[numops].X_op = O_absent;
+ if (*p == '(')
+ {
+ p++;
+ exp[numops].X_add_number = OPERAND_ATPAR;
+ }
+ else if (*p == '-')
+ {
+ p++;
+ exp[numops].X_add_number = OPERAND_ATMINUS;
+ }
+ else
+ {
+ exp[numops].X_add_number = OPERAND_ATSIGN;
+ post = postfix (p);
+ }
+ numops++;
+ continue;
+ }
+
+ if (*p == ')')
+ {
+ /* just skip the trailing paren */
+ p++;
+ continue;
+ }
+
+ input_line_pointer = p;
+
+ /* check to see if it might be a register name */
+ if (!register_name (&exp[numops]))
+ {
+ /* parse as an expression */
+ expression (&exp[numops]);
+ }
+
+ if (strncasecmp (input_line_pointer, "@word", 5) == 0)
+ {
+ input_line_pointer += 5;
+ if (exp[numops].X_op == O_register)
+ {
+ /* if it looked like a register name but was followed by
+ "@word" then it was really a symbol, so change it to
+ one */
+ exp[numops].X_op = O_symbol;
+ exp[numops].X_add_symbol = symbol_find_or_make ((char *)exp[numops].X_op_symbol);
+ }
+
+ /* check for identifier@word+constant */
+ if (*input_line_pointer == '-' || *input_line_pointer == '+')
+ {
+ char *orig_line = input_line_pointer;
+ expressionS new_exp;
+ expression (&new_exp);
+ exp[numops].X_add_number = new_exp.X_add_number;
+ }
+
+ /* convert expr into a right shift by AT_WORD_RIGHT_SHIFT */
+ {
+ expressionS new_exp;
+ memset (&new_exp, 0, sizeof new_exp);
+ new_exp.X_add_number = AT_WORD_RIGHT_SHIFT;
+ new_exp.X_op = O_constant;
+ new_exp.X_unsigned = 1;
+ exp[numops].X_op_symbol = make_expr_symbol (&new_exp);
+ exp[numops].X_op = O_right_shift;
+ }
+
+ know (AT_WORD_P (&exp[numops]));
+ }
+
+ if (exp[numops].X_op == O_illegal)
+ as_bad (_("illegal operand"));
+ else if (exp[numops].X_op == O_absent)
+ as_bad (_("missing operand"));
+
+ numops++;
+ p = input_line_pointer;
+ }
+
+ switch (post)
+ {
+ case -1: /* postdecrement mode */
+ exp[numops].X_op = O_absent;
+ exp[numops++].X_add_number = OPERAND_MINUS;
+ break;
+ case 1: /* postincrement mode */
+ exp[numops].X_op = O_absent;
+ exp[numops++].X_add_number = OPERAND_PLUS;
+ break;
+ }
+
+ exp[numops].X_op = 0;
+ return (numops);
+}
+
+static unsigned long
+d10v_insert_operand (insn, op_type, value, left, fix)
+ unsigned long insn;
+ int op_type;
+ offsetT value;
+ int left;
+ fixS *fix;
+{
+ int shift, bits;
+
+ shift = d10v_operands[op_type].shift;
+ if (left)
+ shift += 15;
+
+ bits = d10v_operands[op_type].bits;
+
+ /* truncate to the proper number of bits */
+ if (check_range (value, bits, d10v_operands[op_type].flags))
+ as_bad_where (fix->fx_file, fix->fx_line, _("operand out of range: %d"), value);
+
+ value &= 0x7FFFFFFF >> (31 - bits);
+ insn |= (value << shift);
+
+ return insn;
+}
+
+
+/* build_insn takes a pointer to the opcode entry in the opcode table
+ and the array of operand expressions and returns the instruction */
+
+static unsigned long
+build_insn (opcode, opers, insn)
+ struct d10v_opcode *opcode;
+ expressionS *opers;
+ unsigned long insn;
+{
+ int i, bits, shift, flags, format;
+ unsigned long number;
+
+ /* the insn argument is only used for the DIVS kludge */
+ if (insn)
+ format = LONG_R;
+ else
+ {
+ insn = opcode->opcode;
+ format = opcode->format;
+ }
+
+ for (i=0;opcode->operands[i];i++)
+ {
+ flags = d10v_operands[opcode->operands[i]].flags;
+ bits = d10v_operands[opcode->operands[i]].bits;
+ shift = d10v_operands[opcode->operands[i]].shift;
+ number = opers[i].X_add_number;
+
+ if (flags & OPERAND_REG)
+ {
+ number &= REGISTER_MASK;
+ if (format == LONG_L)
+ shift += 15;
+ }
+
+ if (opers[i].X_op != O_register && opers[i].X_op != O_constant)
+ {
+ /* now create a fixup */
+
+ if (fixups->fc >= MAX_INSN_FIXUPS)
+ as_fatal (_("too many fixups"));
+
+ if (AT_WORD_P (&opers[i]))
+ {
+ /* Reconize XXX>>1+N aka XXX@word+N as special (AT_WORD) */
+ fixups->fix[fixups->fc].reloc = BFD_RELOC_D10V_18;
+ opers[i].X_op = O_symbol;
+ opers[i].X_op_symbol = NULL; /* Should free it */
+ /* number is left shifted by AT_WORD_RIGHT_SHIFT so
+ that, it is aligned with the symbol's value. Later,
+ BFD_RELOC_D10V_18 will right shift (symbol_value +
+ X_add_number). */
+ number <<= AT_WORD_RIGHT_SHIFT;
+ opers[i].X_add_number = number;
+ }
+ else
+ fixups->fix[fixups->fc].reloc =
+ get_reloc((struct d10v_operand *)&d10v_operands[opcode->operands[i]]);
+
+ if (fixups->fix[fixups->fc].reloc == BFD_RELOC_16 ||
+ fixups->fix[fixups->fc].reloc == BFD_RELOC_D10V_18)
+ fixups->fix[fixups->fc].size = 2;
+ else
+ fixups->fix[fixups->fc].size = 4;
+
+ fixups->fix[fixups->fc].exp = opers[i];
+ fixups->fix[fixups->fc].operand = opcode->operands[i];
+ fixups->fix[fixups->fc].pcrel = (flags & OPERAND_ADDR) ? true : false;
+ (fixups->fc)++;
+ }
+
+ /* truncate to the proper number of bits */
+ if ((opers[i].X_op == O_constant) && check_range (number, bits, flags))
+ as_bad (_("operand out of range: %d"),number);
+ number &= 0x7FFFFFFF >> (31 - bits);
+ insn = insn | (number << shift);
+ }
+
+ /* kludge: for DIVS, we need to put the operands in twice */
+ /* on the second pass, format is changed to LONG_R to force */
+ /* the second set of operands to not be shifted over 15 */
+ if ((opcode->opcode == OPCODE_DIVS) && (format==LONG_L))
+ insn = build_insn (opcode, opers, insn);
+
+ return insn;
+}
+
+/* write out a long form instruction */
+static void
+write_long (opcode, insn, fx)
+ struct d10v_opcode *opcode;
+ unsigned long insn;
+ Fixups *fx;
+{
+ int i, where;
+ char *f = frag_more(4);
+
+ insn |= FM11;
+ number_to_chars_bigendian (f, insn, 4);
+
+ for (i=0; i < fx->fc; i++)
+ {
+ if (fx->fix[i].reloc)
+ {
+ where = f - frag_now->fr_literal;
+ if (fx->fix[i].size == 2)
+ where += 2;
+
+ if (fx->fix[i].reloc == BFD_RELOC_D10V_18)
+ fx->fix[i].operand |= 4096;
+
+ fix_new_exp (frag_now,
+ where,
+ fx->fix[i].size,
+ &(fx->fix[i].exp),
+ fx->fix[i].pcrel,
+ fx->fix[i].operand|2048);
+ }
+ }
+ fx->fc = 0;
+}
+
+
+/* write out a short form instruction by itself */
+static void
+write_1_short (opcode, insn, fx)
+ struct d10v_opcode *opcode;
+ unsigned long insn;
+ Fixups *fx;
+{
+ char *f = frag_more(4);
+ int i, where;
+
+ if (opcode->exec_type & PARONLY)
+ as_fatal (_("Instruction must be executed in parallel with another instruction."));
+
+ /* the other container needs to be NOP */
+ /* according to 4.3.1: for FM=00, sub-instructions performed only
+ by IU cannot be encoded in L-container. */
+ if (opcode->unit == IU)
+ insn |= FM00 | (NOP << 15); /* right container */
+ else
+ insn = FM00 | (insn << 15) | NOP; /* left container */
+
+ number_to_chars_bigendian (f, insn, 4);
+ for (i=0; i < fx->fc; i++)
+ {
+ if (fx->fix[i].reloc)
+ {
+ where = f - frag_now->fr_literal;
+ if (fx->fix[i].size == 2)
+ where += 2;
+
+ if (fx->fix[i].reloc == BFD_RELOC_D10V_18)
+ fx->fix[i].operand |= 4096;
+
+ /* if it's an R reloc, we may have to switch it to L */
+ if ( (fx->fix[i].reloc == BFD_RELOC_D10V_10_PCREL_R) && (opcode->unit != IU) )
+ fx->fix[i].operand |= 1024;
+
+ fix_new_exp (frag_now,
+ where,
+ fx->fix[i].size,
+ &(fx->fix[i].exp),
+ fx->fix[i].pcrel,
+ fx->fix[i].operand|2048);
+ }
+ }
+ fx->fc = 0;
+}
+
+/* write out a short form instruction if possible */
+/* return number of instructions not written out */
+static int
+write_2_short (opcode1, insn1, opcode2, insn2, exec_type, fx)
+ struct d10v_opcode *opcode1, *opcode2;
+ unsigned long insn1, insn2;
+ int exec_type;
+ Fixups *fx;
+{
+ unsigned long insn;
+ char *f;
+ int i,j, where;
+
+ if ( (exec_type != 1) && ((opcode1->exec_type & PARONLY)
+ || (opcode2->exec_type & PARONLY)))
+ as_fatal (_("Instruction must be executed in parallel"));
+
+ if ( (opcode1->format & LONG_OPCODE) || (opcode2->format & LONG_OPCODE))
+ as_fatal (_("Long instructions may not be combined."));
+
+ if(opcode1->exec_type & BRANCH_LINK && exec_type == 0)
+ {
+ /* Instructions paired with a subroutine call are executed before the
+ subroutine, so don't do these pairings unless explicitly requested. */
+ write_1_short (opcode1, insn1, fx->next);
+ return (1);
+ }
+
+ switch (exec_type)
+ {
+ case 0: /* order not specified */
+ if ( Optimizing && parallel_ok (opcode1, insn1, opcode2, insn2, exec_type))
+ {
+ /* parallel */
+ if (opcode1->unit == IU)
+ insn = FM00 | (insn2 << 15) | insn1;
+ else if (opcode2->unit == MU)
+ insn = FM00 | (insn2 << 15) | insn1;
+ else
+ {
+ insn = FM00 | (insn1 << 15) | insn2;
+ fx = fx->next;
+ }
+ }
+ else if (opcode1->unit == IU)
+ {
+ /* reverse sequential */
+ insn = FM10 | (insn2 << 15) | insn1;
+ }
+ else
+ {
+ /* sequential */
+ insn = FM01 | (insn1 << 15) | insn2;
+ fx = fx->next;
+ }
+ break;
+ case 1: /* parallel */
+ if (opcode1->exec_type & SEQ || opcode2->exec_type & SEQ)
+ as_fatal (_("One of these instructions may not be executed in parallel."));
+
+ if (opcode1->unit == IU)
+ {
+ if (opcode2->unit == IU)
+ as_fatal (_("Two IU instructions may not be executed in parallel"));
+ if (!flag_warn_suppress_instructionswap)
+ as_warn (_("Swapping instruction order"));
+ insn = FM00 | (insn2 << 15) | insn1;
+ }
+ else if (opcode2->unit == MU)
+ {
+ if (opcode1->unit == MU)
+ as_fatal (_("Two MU instructions may not be executed in parallel"));
+ if (!flag_warn_suppress_instructionswap)
+ as_warn (_("Swapping instruction order"));
+ insn = FM00 | (insn2 << 15) | insn1;
+ }
+ else
+ {
+ insn = FM00 | (insn1 << 15) | insn2;
+ fx = fx->next;
+ }
+ break;
+ case 2: /* sequential */
+ if (opcode1->unit != IU)
+ insn = FM01 | (insn1 << 15) | insn2;
+ else if (opcode2->unit == MU || opcode2->unit == EITHER)
+ {
+ if (!flag_warn_suppress_instructionswap)
+ as_warn (_("Swapping instruction order"));
+ insn = FM10 | (insn2 << 15) | insn1;
+ }
+ else
+ as_fatal (_("IU instruction may not be in the left container"));
+ fx = fx->next;
+ break;
+ case 3: /* reverse sequential */
+ if (opcode2->unit != MU)
+ insn = FM10 | (insn1 << 15) | insn2;
+ else if (opcode1->unit == IU || opcode1->unit == EITHER)
+ {
+ if (!flag_warn_suppress_instructionswap)
+ as_warn (_("Swapping instruction order"));
+ insn = FM01 | (insn2 << 15) | insn1;
+ }
+ else
+ as_fatal (_("MU instruction may not be in the right container"));
+ fx = fx->next;
+ break;
+ default:
+ as_fatal (_("unknown execution type passed to write_2_short()"));
+ }
+
+ f = frag_more(4);
+ number_to_chars_bigendian (f, insn, 4);
+
+ for (j=0; j<2; j++)
+ {
+ for (i=0; i < fx->fc; i++)
+ {
+ if (fx->fix[i].reloc)
+ {
+ where = f - frag_now->fr_literal;
+ if (fx->fix[i].size == 2)
+ where += 2;
+
+ if ( (fx->fix[i].reloc == BFD_RELOC_D10V_10_PCREL_R) && (j == 0) )
+ fx->fix[i].operand |= 1024;
+
+ if (fx->fix[i].reloc == BFD_RELOC_D10V_18)
+ fx->fix[i].operand |= 4096;
+
+ fix_new_exp (frag_now,
+ where,
+ fx->fix[i].size,
+ &(fx->fix[i].exp),
+ fx->fix[i].pcrel,
+ fx->fix[i].operand|2048);
+ }
+ }
+ fx->fc = 0;
+ fx = fx->next;
+ }
+ return (0);
+}
+
+
+/* Check 2 instructions and determine if they can be safely */
+/* executed in parallel. Returns 1 if they can be. */
+static int
+parallel_ok (op1, insn1, op2, insn2, exec_type)
+ struct d10v_opcode *op1, *op2;
+ unsigned long insn1, insn2;
+ int exec_type;
+{
+ int i, j, flags, mask, shift, regno;
+ unsigned long ins, mod[2], used[2];
+ struct d10v_opcode *op;
+
+ if ((op1->exec_type & SEQ) != 0 || (op2->exec_type & SEQ) != 0
+ || (op1->exec_type & PAR) == 0 || (op2->exec_type & PAR) == 0
+ || (op1->unit == BOTH) || (op2->unit == BOTH)
+ || (op1->unit == IU && op2->unit == IU)
+ || (op1->unit == MU && op2->unit == MU))
+ return 0;
+
+ /* If the first instruction is a branch and this is auto parallazation,
+ don't combine with any second instruction. */
+ if (exec_type == 0 && (op1->exec_type & BRANCH) != 0)
+ return 0;
+
+ /* The idea here is to create two sets of bitmasks (mod and used)
+ which indicate which registers are modified or used by each
+ instruction. The operation can only be done in parallel if
+ instruction 1 and instruction 2 modify different registers, and
+ the first instruction does not modify registers that the second
+ is using (The second instruction can modify registers that the
+ first is using as they are only written back after the first
+ instruction has completed). Accesses to control registers, PSW,
+ and memory are treated as accesses to a single register. So if
+ both instructions write memory or if the first instruction writes
+ memory and the second reads, then they cannot be done in
+ parallel. Likewise, if the first instruction mucks with the psw
+ and the second reads the PSW (which includes C, F0, and F1), then
+ they cannot operate safely in parallel. */
+
+ /* the bitmasks (mod and used) look like this (bit 31 = MSB) */
+ /* r0-r15 0-15 */
+ /* a0-a1 16-17 */
+ /* cr (not psw) 18 */
+ /* psw 19 */
+ /* mem 20 */
+
+ for (j=0;j<2;j++)
+ {
+ if (j == 0)
+ {
+ op = op1;
+ ins = insn1;
+ }
+ else
+ {
+ op = op2;
+ ins = insn2;
+ }
+ mod[j] = used[j] = 0;
+ if (op->exec_type & BRANCH_LINK)
+ mod[j] |= 1 << 13;
+
+ for (i = 0; op->operands[i]; i++)
+ {
+ flags = d10v_operands[op->operands[i]].flags;
+ shift = d10v_operands[op->operands[i]].shift;
+ mask = 0x7FFFFFFF >> (31 - d10v_operands[op->operands[i]].bits);
+ if (flags & OPERAND_REG)
+ {
+ regno = (ins >> shift) & mask;
+ if (flags & (OPERAND_ACC0|OPERAND_ACC1))
+ regno += 16;
+ else if (flags & OPERAND_CONTROL) /* mvtc or mvfc */
+ {
+ if (regno == 0)
+ regno = 19;
+ else
+ regno = 18;
+ }
+ else if (flags & (OPERAND_FFLAG|OPERAND_CFLAG))
+ regno = 19;
+
+ if ( flags & OPERAND_DEST )
+ {
+ mod[j] |= 1 << regno;
+ if (flags & OPERAND_EVEN)
+ mod[j] |= 1 << (regno + 1);
+ }
+ else
+ {
+ used[j] |= 1 << regno ;
+ if (flags & OPERAND_EVEN)
+ used[j] |= 1 << (regno + 1);
+
+ /* Auto inc/dec also modifies the register. */
+ if (op->operands[i+1] != 0
+ && (d10v_operands[op->operands[i+1]].flags
+ & (OPERAND_PLUS | OPERAND_MINUS)) != 0)
+ mod[j] |= 1 << regno;
+ }
+ }
+ else if (flags & OPERAND_ATMINUS)
+ {
+ /* SP implicitly used/modified */
+ mod[j] |= 1 << 15;
+ used[j] |= 1 << 15;
+ }
+ }
+ if (op->exec_type & RMEM)
+ used[j] |= 1 << 20;
+ else if (op->exec_type & WMEM)
+ mod[j] |= 1 << 20;
+ else if (op->exec_type & RF0)
+ used[j] |= 1 << 19;
+ else if (op->exec_type & WF0)
+ mod[j] |= 1 << 19;
+ else if (op->exec_type & WCAR)
+ mod[j] |= 1 << 19;
+ }
+ if ((mod[0] & mod[1]) == 0 && (mod[0] & used[1]) == 0)
+ return 1;
+ return 0;
+}
+
+
+/* This is the main entry point for the machine-dependent assembler. str points to a
+ machine-dependent instruction. This function is supposed to emit the frags/bytes
+ it assembles to. For the D10V, it mostly handles the special VLIW parsing and packing
+ and leaves the difficult stuff to do_assemble().
+ */
+
+static unsigned long prev_insn;
+static struct d10v_opcode *prev_opcode = 0;
+static subsegT prev_subseg;
+static segT prev_seg = 0;;
+static int etype = 0; /* saved extype. used for multiline instructions */
+
+void
+md_assemble (str)
+ char *str;
+{
+ struct d10v_opcode * opcode;
+ unsigned long insn;
+ int extype = 0; /* execution type; parallel, etc */
+ char * str2;
+
+ if (etype == 0)
+ {
+ /* look for the special multiple instruction separators */
+ str2 = strstr (str, "||");
+ if (str2)
+ extype = 1;
+ else
+ {
+ str2 = strstr (str, "->");
+ if (str2)
+ extype = 2;
+ else
+ {
+ str2 = strstr (str, "<-");
+ if (str2)
+ extype = 3;
+ }
+ }
+ /* str2 points to the separator, if one */
+ if (str2)
+ {
+ *str2 = 0;
+
+ /* if two instructions are present and we already have one saved
+ then first write it out */
+ d10v_cleanup ();
+
+ /* assemble first instruction and save it */
+ prev_insn = do_assemble (str, &prev_opcode);
+ if (prev_insn == -1)
+ as_fatal (_("can't find opcode "));
+ fixups = fixups->next;
+ str = str2 + 2;
+ }
+ }
+
+ insn = do_assemble (str, &opcode);
+ if (insn == -1)
+ {
+ if (extype)
+ {
+ etype = extype;
+ return;
+ }
+ as_fatal (_("can't find opcode "));
+ }
+
+ if (etype)
+ {
+ extype = etype;
+ etype = 0;
+ }
+
+ /* if this is a long instruction, write it and any previous short instruction */
+ if (opcode->format & LONG_OPCODE)
+ {
+ if (extype)
+ as_fatal (_("Unable to mix instructions as specified"));
+ d10v_cleanup ();
+ write_long (opcode, insn, fixups);
+ prev_opcode = NULL;
+ return;
+ }
+
+ if (prev_opcode && prev_seg && ((prev_seg != now_seg) || (prev_subseg != now_subseg)))
+ d10v_cleanup();
+
+ if (prev_opcode && (write_2_short (prev_opcode, prev_insn, opcode, insn, extype, fixups) == 0))
+ {
+ /* no instructions saved */
+ prev_opcode = NULL;
+ }
+ else
+ {
+ if (extype)
+ as_fatal (_("Unable to mix instructions as specified"));
+ /* save off last instruction so it may be packed on next pass */
+ prev_opcode = opcode;
+ prev_insn = insn;
+ prev_seg = now_seg;
+ prev_subseg = now_subseg;
+ fixups = fixups->next;
+ }
+}
+
+
+/* do_assemble assembles a single instruction and returns an opcode */
+/* it returns -1 (an invalid opcode) on error */
+
+static unsigned long
+do_assemble (str, opcode)
+ char *str;
+ struct d10v_opcode **opcode;
+{
+ unsigned char *op_start, *save;
+ unsigned char *op_end;
+ char name[20];
+ int nlen = 0;
+ expressionS myops[6];
+ unsigned long insn;
+
+ /* Drop leading whitespace. */
+ while (*str == ' ')
+ str++;
+
+ /* Find the opcode end. */
+ for (op_start = op_end = (unsigned char *) (str);
+ *op_end
+ && nlen < 20
+ && !is_end_of_line[*op_end] && *op_end != ' ';
+ op_end++)
+ {
+ name[nlen] = tolower (op_start[nlen]);
+ nlen++;
+ }
+ name[nlen] = 0;
+
+ if (nlen == 0)
+ return -1;
+
+ /* Find the first opcode with the proper name. */
+ *opcode = (struct d10v_opcode *)hash_find (d10v_hash, name);
+ if (*opcode == NULL)
+ as_fatal (_("unknown opcode: %s"),name);
+
+ save = input_line_pointer;
+ input_line_pointer = op_end;
+ *opcode = find_opcode (*opcode, myops);
+ if (*opcode == 0)
+ return -1;
+ input_line_pointer = save;
+
+ insn = build_insn ((*opcode), myops, 0);
+ return (insn);
+}
+
+/* Find the symbol which has the same name as the register in the given expression. */
+static symbolS *
+find_symbol_matching_register (exp)
+ expressionS * exp;
+{
+ int i;
+
+ if (exp->X_op != O_register)
+ return NULL;
+
+ /* Find the name of the register. */
+ for (i = d10v_reg_name_cnt (); i--;)
+ if (d10v_predefined_registers [i].value == exp->X_add_number)
+ break;
+
+ if (i < 0)
+ abort ();
+
+ /* Now see if a symbol has been defined with the same name. */
+ return symbol_find (d10v_predefined_registers [i].name);
+}
+
+
+/* find_opcode() gets a pointer to an entry in the opcode table. */
+/* It must look at all opcodes with the same name and use the operands */
+/* to choose the correct opcode. */
+
+static struct d10v_opcode *
+find_opcode (opcode, myops)
+ struct d10v_opcode *opcode;
+ expressionS myops[];
+{
+ int i, match, done;
+ struct d10v_opcode *next_opcode;
+
+ /* get all the operands and save them as expressions */
+ get_operands (myops);
+
+ /* now see if the operand is a fake. If so, find the correct size */
+ /* instruction, if possible */
+ if (opcode->format == OPCODE_FAKE)
+ {
+ int opnum = opcode->operands[0];
+ int flags;
+
+ if (myops[opnum].X_op == O_register)
+ {
+ myops[opnum].X_op = O_symbol;
+ myops[opnum].X_add_symbol = symbol_find_or_make ((char *)myops[opnum].X_op_symbol);
+ myops[opnum].X_add_number = 0;
+ myops[opnum].X_op_symbol = NULL;
+ }
+
+ next_opcode=opcode+1;
+
+ /* If the first operand is supposed to be a register, make sure
+ we got a valid one. */
+ flags = d10v_operands[next_opcode->operands[0]].flags;
+ if (flags & OPERAND_REG)
+ {
+ int X_op = myops[0].X_op;
+ int num = myops[0].X_add_number;
+
+ if (X_op != O_register
+ || (num & ~flags
+ & (OPERAND_GPR | OPERAND_ACC0 | OPERAND_ACC1
+ | OPERAND_FFLAG | OPERAND_CFLAG | OPERAND_CONTROL)))
+ {
+ as_bad (_("bad opcode or operands"));
+ return 0;
+ }
+ }
+
+ if (myops[opnum].X_op == O_constant || (myops[opnum].X_op == O_symbol &&
+ S_IS_DEFINED(myops[opnum].X_add_symbol) &&
+ (S_GET_SEGMENT(myops[opnum].X_add_symbol) == now_seg)))
+ {
+ for (i=0; opcode->operands[i+1]; i++)
+ {
+ int bits = d10v_operands[next_opcode->operands[opnum]].bits;
+ int flags = d10v_operands[next_opcode->operands[opnum]].flags;
+ if (flags & OPERAND_ADDR)
+ bits += 2;
+ if (myops[opnum].X_op == O_constant)
+ {
+ if (!check_range (myops[opnum].X_add_number, bits, flags))
+ return next_opcode;
+ }
+ else
+ {
+ fragS *f;
+ long value;
+ /* calculate the current address by running through the previous frags */
+ /* and adding our current offset */
+ for (value = 0, f = frchain_now->frch_root; f; f = f->fr_next)
+ value += f->fr_fix + f->fr_offset;
+
+ if (flags & OPERAND_ADDR)
+ value = S_GET_VALUE(myops[opnum].X_add_symbol) - value -
+ (obstack_next_free(&frchain_now->frch_obstack) - frag_now->fr_literal);
+ else
+ value = S_GET_VALUE(myops[opnum].X_add_symbol);
+
+ if (AT_WORD_P (&myops[opnum]))
+ {
+ if (bits > 4)
+ {
+ bits += 2;
+ if (!check_range (value, bits, flags))
+ return next_opcode;
+ }
+ }
+ else if (!check_range (value, bits, flags))
+ return next_opcode;
+ }
+ next_opcode++;
+ }
+ as_fatal (_("value out of range"));
+ }
+ else
+ {
+ /* not a constant, so use a long instruction */
+ return opcode+2;
+ }
+ }
+ else
+ {
+ match = 0;
+ /* now search the opcode table table for one with operands */
+ /* that matches what we've got */
+ while (!match)
+ {
+ match = 1;
+ for (i = 0; opcode->operands[i]; i++)
+ {
+ int flags = d10v_operands[opcode->operands[i]].flags;
+ int X_op = myops[i].X_op;
+ int num = myops[i].X_add_number;
+
+ if (X_op == 0)
+ {
+ match = 0;
+ break;
+ }
+
+ if (flags & OPERAND_REG)
+ {
+ if ((X_op != O_register)
+ || (num & ~flags
+ & (OPERAND_GPR | OPERAND_ACC0 | OPERAND_ACC1
+ | OPERAND_FFLAG | OPERAND_CFLAG
+ | OPERAND_CONTROL)))
+ {
+ match = 0;
+ break;
+ }
+ }
+
+ if (((flags & OPERAND_MINUS) && ((X_op != O_absent) || (num != OPERAND_MINUS))) ||
+ ((flags & OPERAND_PLUS) && ((X_op != O_absent) || (num != OPERAND_PLUS))) ||
+ ((flags & OPERAND_ATMINUS) && ((X_op != O_absent) || (num != OPERAND_ATMINUS))) ||
+ ((flags & OPERAND_ATPAR) && ((X_op != O_absent) || (num != OPERAND_ATPAR))) ||
+ ((flags & OPERAND_ATSIGN) && ((X_op != O_absent) || (num != OPERAND_ATSIGN))))
+ {
+ match = 0;
+ break;
+ }
+
+ /* Unfortunatly, for the indirect operand in instructions such as
+ ``ldb r1, @(c,r14)'' this function can be passed X_op == O_register
+ (because 'c' is a valid register name). However we cannot just
+ ignore the case when X_op == O_register but flags & OPERAND_REG is
+ null, so we check to see if a symbol of the same name as the register
+ exists. If the symbol does exist, then the parser was unable to
+ distinguish the two cases and we fix things here. (Ref: PR14826) */
+
+ if (!(flags & OPERAND_REG) && (X_op == O_register))
+ {
+ symbolS * sym;
+
+ sym = find_symbol_matching_register (& myops[i]);
+
+ if (sym != NULL)
+ {
+ myops [i].X_op == X_op == O_symbol;
+ myops [i].X_add_symbol = sym;
+ }
+ else
+ as_bad
+ (_("illegal operand - register name found where none expected"));
+ }
+ }
+
+ /* We're only done if the operands matched so far AND there
+ are no more to check. */
+ if (match && myops[i].X_op == 0)
+ break;
+ else
+ match = 0;
+
+ next_opcode = opcode + 1;
+
+ if (next_opcode->opcode == 0)
+ break;
+
+ if (strcmp (next_opcode->name, opcode->name))
+ break;
+
+ opcode = next_opcode;
+ }
+ }
+
+ if (!match)
+ {
+ as_bad (_("bad opcode or operands"));
+ return (0);
+ }
+
+ /* Check that all registers that are required to be even are. */
+ /* Also, if any operands were marked as registers, but were really symbols */
+ /* fix that here. */
+ for (i=0; opcode->operands[i]; i++)
+ {
+ if ((d10v_operands[opcode->operands[i]].flags & OPERAND_EVEN) &&
+ (myops[i].X_add_number & 1))
+ as_fatal (_("Register number must be EVEN"));
+ if (myops[i].X_op == O_register)
+ {
+ if (!(d10v_operands[opcode->operands[i]].flags & OPERAND_REG))
+ {
+ myops[i].X_op = O_symbol;
+ myops[i].X_add_symbol = symbol_find_or_make ((char *)myops[i].X_op_symbol);
+ myops[i].X_add_number = 0;
+ myops[i].X_op_symbol = NULL;
+ }
+ }
+ }
+ return opcode;
+}
+
+/* if while processing a fixup, a reloc really needs to be created */
+/* then it is done here */
+
+arelent *
+tc_gen_reloc (seg, fixp)
+ asection *seg;
+ fixS *fixp;
+{
+ arelent *reloc;
+ reloc = (arelent *) xmalloc (sizeof (arelent));
+ reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+ reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
+ if (reloc->howto == (reloc_howto_type *) NULL)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("reloc %d not supported by object file format"), (int)fixp->fx_r_type);
+ return NULL;
+ }
+
+ if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ reloc->address = fixp->fx_offset;
+
+ reloc->addend = fixp->fx_addnumber;
+
+ return reloc;
+}
+
+int
+md_estimate_size_before_relax (fragp, seg)
+ fragS *fragp;
+ asection *seg;
+{
+ abort ();
+ return 0;
+}
+
+long
+md_pcrel_from_section (fixp, sec)
+ fixS *fixp;
+ segT sec;
+{
+ if (fixp->fx_addsy != (symbolS *)NULL && (!S_IS_DEFINED (fixp->fx_addsy) ||
+ (S_GET_SEGMENT (fixp->fx_addsy) != sec)))
+ return 0;
+ return fixp->fx_frag->fr_address + fixp->fx_where;
+}
+
+int
+md_apply_fix3 (fixp, valuep, seg)
+ fixS *fixp;
+ valueT *valuep;
+ segT seg;
+{
+ char *where;
+ unsigned long insn;
+ long value;
+ int op_type;
+ int left=0;
+
+ if (fixp->fx_addsy == (symbolS *) NULL)
+ {
+ value = *valuep;
+ fixp->fx_done = 1;
+ }
+ else if (fixp->fx_pcrel)
+ value = *valuep;
+ else
+ {
+ value = fixp->fx_offset;
+ if (fixp->fx_subsy != (symbolS *) NULL)
+ {
+ if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
+ value -= S_GET_VALUE (fixp->fx_subsy);
+ else
+ {
+ /* We don't actually support subtracting a symbol. */
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("expression too complex"));
+ }
+ }
+ }
+
+ op_type = fixp->fx_r_type;
+ if (op_type & 2048)
+ {
+ op_type -= 2048;
+ if (op_type & 1024)
+ {
+ op_type -= 1024;
+ fixp->fx_r_type = BFD_RELOC_D10V_10_PCREL_L;
+ left = 1;
+ }
+ else if (op_type & 4096)
+ {
+ op_type -= 4096;
+ fixp->fx_r_type = BFD_RELOC_D10V_18;
+ }
+ else
+ fixp->fx_r_type = get_reloc((struct d10v_operand *)&d10v_operands[op_type]);
+ }
+
+ /* Fetch the instruction, insert the fully resolved operand
+ value, and stuff the instruction back again. */
+ where = fixp->fx_frag->fr_literal + fixp->fx_where;
+ insn = bfd_getb32 ((unsigned char *) where);
+
+ switch (fixp->fx_r_type)
+ {
+ case BFD_RELOC_D10V_10_PCREL_L:
+ case BFD_RELOC_D10V_10_PCREL_R:
+ case BFD_RELOC_D10V_18_PCREL:
+ case BFD_RELOC_D10V_18:
+ /* instruction addresses are always right-shifted by 2 */
+ value >>= AT_WORD_RIGHT_SHIFT;
+ if (fixp->fx_size == 2)
+ bfd_putb16 ((bfd_vma) value, (unsigned char *) where);
+ else
+ {
+ struct d10v_opcode *rep, *repi;
+
+ rep = (struct d10v_opcode *) hash_find (d10v_hash, "rep");
+ repi = (struct d10v_opcode *) hash_find (d10v_hash, "repi");
+ if ((insn & FM11) == FM11
+ && (repi != NULL && (insn & repi->mask) == repi->opcode
+ || rep != NULL && (insn & rep->mask) == rep->opcode)
+ && value < 4)
+ as_fatal
+ (_("line %d: rep or repi must include at least 4 instructions"),
+ fixp->fx_line);
+ insn = d10v_insert_operand (insn, op_type, (offsetT)value, left, fixp);
+ bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
+ }
+ break;
+ case BFD_RELOC_32:
+ bfd_putb32 ((bfd_vma) value, (unsigned char *) where);
+ break;
+ case BFD_RELOC_16:
+ bfd_putb16 ((bfd_vma) value, (unsigned char *) where);
+ break;
+
+ case BFD_RELOC_VTABLE_INHERIT:
+ case BFD_RELOC_VTABLE_ENTRY:
+ fixp->fx_done = 0;
+ return 1;
+
+ default:
+ as_fatal (_("line %d: unknown relocation type: 0x%x"),fixp->fx_line,fixp->fx_r_type);
+ }
+ return 0;
+}
+
+/* d10v_cleanup() is called after the assembler has finished parsing the input
+ file or after a label is defined. Because the D10V assembler sometimes saves short
+ instructions to see if it can package them with the next instruction, there may
+ be a short instruction that still needs written. */
+int
+d10v_cleanup ()
+{
+ segT seg;
+ subsegT subseg;
+
+ if (prev_opcode && etype == 0)
+ {
+ seg = now_seg;
+ subseg = now_subseg;
+ if (prev_seg)
+ subseg_set (prev_seg, prev_subseg);
+ write_1_short (prev_opcode, prev_insn, fixups->next);
+ subseg_set (seg, subseg);
+ prev_opcode = NULL;
+ }
+ return 1;
+}
+
+/* Like normal .word, except support @word */
+/* clobbers input_line_pointer, checks end-of-line. */
+static void
+d10v_dot_word (nbytes)
+ register int nbytes; /* 1=.byte, 2=.word, 4=.long */
+{
+ expressionS exp;
+ bfd_reloc_code_real_type reloc;
+ char *p;
+ int offset;
+
+ if (is_it_end_of_statement ())
+ {
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ do
+ {
+ expression (&exp);
+ if (!strncasecmp (input_line_pointer, "@word", 5))
+ {
+ exp.X_add_number = 0;
+ input_line_pointer += 5;
+
+ p = frag_more (2);
+ fix_new_exp (frag_now, p - frag_now->fr_literal, 2,
+ &exp, 0, BFD_RELOC_D10V_18);
+ }
+ else
+ emit_expr (&exp, 2);
+ }
+ while (*input_line_pointer++ == ',');
+
+ input_line_pointer--; /* Put terminator back into stream. */
+ demand_empty_rest_of_line ();
+}
+
+
+/* Mitsubishi asked that we support some old syntax that apparently */
+/* had immediate operands starting with '#'. This is in some of their */
+/* sample code but is not documented (although it appears in some */
+/* examples in their assembler manual). For now, we'll solve this */
+/* compatibility problem by simply ignoring any '#' at the beginning */
+/* of an operand. */
+
+/* operands that begin with '#' should fall through to here */
+/* from expr.c */
+
+void
+md_operand (expressionP)
+ expressionS *expressionP;
+{
+ if (*input_line_pointer == '#')
+ {
+ input_line_pointer++;
+ expression (expressionP);
+ }
+}
+
+boolean
+d10v_fix_adjustable (fixP)
+ fixS *fixP;
+{
+
+ if (fixP->fx_addsy == NULL)
+ return 1;
+
+ /* Prevent all adjustments to global symbols. */
+ if (S_IS_EXTERN (fixP->fx_addsy))
+ return 0;
+ if (S_IS_WEAK (fixP->fx_addsy))
+ return 0;
+
+ /* We need the symbol name for the VTABLE entries */
+ if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ return 0;
+
+ return 1;
+}
+
+int
+d10v_force_relocation (fixp)
+ struct fix *fixp;
+{
+ if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ return 1;
+
+ return 0;
+}
diff --git a/gas/config/tc-d10v.h b/gas/config/tc-d10v.h
new file mode 100644
index 0000000000..c6ffd5c3ea
--- /dev/null
+++ b/gas/config/tc-d10v.h
@@ -0,0 +1,62 @@
+/* tc-d10v.h -- Header file for tc-d10v.c.
+ Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+ Written by Martin Hunt, Cygnus Support.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#define TC_D10V
+
+#define TARGET_BYTES_BIG_ENDIAN 0
+
+#ifndef BFD_ASSEMBLER
+ #error D10V support requires BFD_ASSEMBLER
+#endif
+
+/* The target BFD architecture. */
+#define TARGET_ARCH bfd_arch_d10v
+
+#define TARGET_FORMAT "elf32-d10v"
+
+#define MD_APPLY_FIX3
+
+/* call md_pcrel_from_section, not md_pcrel_from */
+#define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from_section(FIXP, SEC)
+
+/* Permit temporary numeric labels. */
+#define LOCAL_LABELS_FB 1
+
+#define DIFF_EXPR_OK /* .-foo gets turned into PC relative relocs */
+
+/* We don't need to handle .word strangely. */
+#define WORKING_DOT_WORD
+
+#define md_number_to_chars number_to_chars_bigendian
+
+int d10v_cleanup PARAMS ((void));
+#define md_after_pass_hook() d10v_cleanup()
+#define md_cleanup() d10v_cleanup()
+#define md_do_align(a,b,c,d,e) d10v_cleanup()
+#define tc_frob_label(sym) do {\
+ d10v_cleanup(); \
+ S_SET_VALUE (sym, (valueT) frag_now_fix ()); \
+} while (0)
+
+#define obj_fix_adjustable(fixP) d10v_fix_adjustable(fixP)
+#define TC_FORCE_RELOCATION(fixp) d10v_force_relocation(fixp)
+extern int d10v_force_relocation PARAMS ((struct fix *));
+
diff --git a/gas/config/tc-d30v.c b/gas/config/tc-d30v.c
new file mode 100644
index 0000000000..c5033ba33f
--- /dev/null
+++ b/gas/config/tc-d30v.c
@@ -0,0 +1,2218 @@
+/* tc-d30v.c -- Assembler code for the Mitsubishi D30V
+
+ Copyright (C) 1997, 1998 Free Software Foundation.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "as.h"
+#include "subsegs.h"
+#include "opcode/d30v.h"
+
+const char comment_chars[] = ";";
+const char line_comment_chars[] = "#";
+const char line_separator_chars[] = "";
+const char *md_shortopts = "OnNcC";
+const char EXP_CHARS[] = "eE";
+const char FLT_CHARS[] = "dD";
+
+#define NOP_MULTIPLY 1
+#define NOP_ALL 2
+static int warn_nops = 0;
+static int Optimizing = 0;
+static int warn_register_name_conflicts = 1;
+
+#define FORCE_SHORT 1
+#define FORCE_LONG 2
+
+/* EXEC types. */
+typedef enum _exec_type
+{
+ EXEC_UNKNOWN, /* no order specified */
+ EXEC_PARALLEL, /* done in parallel (FM=00) */
+ EXEC_SEQ, /* sequential (FM=01) */
+ EXEC_REVSEQ /* reverse sequential (FM=10) */
+} exec_type_enum;
+
+/* fixups */
+#define MAX_INSN_FIXUPS (5)
+struct d30v_fixup
+{
+ expressionS exp;
+ int operand;
+ int pcrel;
+ int size;
+ bfd_reloc_code_real_type reloc;
+};
+
+typedef struct _fixups
+{
+ int fc;
+ struct d30v_fixup fix[MAX_INSN_FIXUPS];
+ struct _fixups *next;
+} Fixups;
+
+static Fixups FixUps[2];
+static Fixups *fixups;
+
+/* Whether current and previous instruction are word multiply insns. */
+static int cur_mul32_p = 0;
+static int prev_mul32_p = 0;
+
+/* The flag_explicitly_parallel is true iff the instruction being assembled
+ has been explicitly written as a parallel short-instruction pair by the
+ human programmer. It is used in parallel_ok() to distinguish between
+ those dangerous parallelizations attempted by the human, which are to be
+ allowed, and those attempted by the assembler, which are not. It is set
+ from md_assemble(). */
+static int flag_explicitly_parallel = 0;
+static int flag_xp_state = 0;
+
+/* Whether current and previous left sub-instruction disables
+ execution of right sub-instruction. */
+static int cur_left_kills_right_p = 0;
+static int prev_left_kills_right_p = 0;
+
+/* The known current alignment of the current section. */
+static int d30v_current_align;
+static segT d30v_current_align_seg;
+
+/* The last seen label in the current section. This is used to auto-align
+ labels preceeding instructions. */
+static symbolS *d30v_last_label;
+
+/* Two nops */
+#define NOP_LEFT ((long long) NOP << 32)
+#define NOP_RIGHT ((long long) NOP)
+#define NOP2 (FM00 | NOP_LEFT | NOP_RIGHT)
+
+/* local functions */
+static int reg_name_search PARAMS ((char *name));
+static int register_name PARAMS ((expressionS *expressionP));
+static int check_range PARAMS ((unsigned long num, int bits, int flags));
+static int postfix PARAMS ((char *p));
+static bfd_reloc_code_real_type get_reloc PARAMS ((struct d30v_operand *op, int rel_flag));
+static int get_operands PARAMS ((expressionS exp[], int cmp_hack));
+static struct d30v_format *find_format PARAMS ((struct d30v_opcode *opcode,
+ expressionS ops[],int fsize, int cmp_hack));
+static long long build_insn PARAMS ((struct d30v_insn *opcode, expressionS *opers));
+static void write_long PARAMS ((struct d30v_insn *opcode, long long insn, Fixups *fx));
+static void write_1_short PARAMS ((struct d30v_insn *opcode, long long insn,
+ Fixups *fx, int use_sequential));
+static int write_2_short PARAMS ((struct d30v_insn *opcode1, long long insn1,
+ struct d30v_insn *opcode2, long long insn2, exec_type_enum exec_type, Fixups *fx));
+static long long do_assemble PARAMS ((char *str, struct d30v_insn *opcode,
+ int shortp, int is_parallel));
+static int parallel_ok PARAMS ((struct d30v_insn *opcode1, unsigned long insn1,
+ struct d30v_insn *opcode2, unsigned long insn2,
+ exec_type_enum exec_type));
+static void d30v_number_to_chars PARAMS ((char *buf, long long value, int nbytes));
+static void check_size PARAMS ((long value, int bits, char *file, int line));
+static void d30v_align PARAMS ((int, char *, symbolS *));
+static void s_d30v_align PARAMS ((int));
+static void s_d30v_text PARAMS ((int));
+static void s_d30v_data PARAMS ((int));
+static void s_d30v_section PARAMS ((int));
+
+struct option md_longopts[] = {
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof(md_longopts);
+
+
+/* The target specific pseudo-ops which we support. */
+const pseudo_typeS md_pseudo_table[] =
+{
+ { "word", cons, 4 },
+ { "hword", cons, 2 },
+ { "align", s_d30v_align, 0 },
+ { "text", s_d30v_text, 0 },
+ { "data", s_d30v_data, 0 },
+ { "section", s_d30v_section, 0 },
+ { "section.s", s_d30v_section, 0 },
+ { "sect", s_d30v_section, 0 },
+ { "sect.s", s_d30v_section, 0 },
+ { NULL, NULL, 0 }
+};
+
+/* Opcode hash table. */
+static struct hash_control *d30v_hash;
+
+/* reg_name_search does a binary search of the pre_defined_registers
+ array to see if "name" is a valid regiter name. Returns the register
+ number from the array on success, or -1 on failure. */
+
+static int
+reg_name_search (name)
+ char *name;
+{
+ int middle, low, high;
+ int cmp;
+
+ low = 0;
+ high = reg_name_cnt () - 1;
+
+ do
+ {
+ middle = (low + high) / 2;
+ cmp = strcasecmp (name, pre_defined_registers[middle].name);
+ if (cmp < 0)
+ high = middle - 1;
+ else if (cmp > 0)
+ low = middle + 1;
+ else
+ {
+ if (symbol_find (name) != NULL)
+ {
+ if (warn_register_name_conflicts)
+ as_warn (_("Register name %s conflicts with symbol of the same name"),
+ name);
+ }
+
+ return pre_defined_registers[middle].value;
+ }
+ }
+ while (low <= high);
+
+ return -1;
+}
+
+/* register_name() checks the string at input_line_pointer
+ to see if it is a valid register name. */
+
+static int
+register_name (expressionP)
+ expressionS *expressionP;
+{
+ int reg_number;
+ char c, *p = input_line_pointer;
+
+ while (*p && *p!='\n' && *p!='\r' && *p !=',' && *p!=' ' && *p!=')')
+ p++;
+
+ c = *p;
+ if (c)
+ *p++ = 0;
+
+ /* look to see if it's in the register table */
+ reg_number = reg_name_search (input_line_pointer);
+ if (reg_number >= 0)
+ {
+ expressionP->X_op = O_register;
+ /* temporarily store a pointer to the string here */
+ expressionP->X_op_symbol = (struct symbol *)input_line_pointer;
+ expressionP->X_add_number = reg_number;
+ input_line_pointer = p;
+ return 1;
+ }
+ if (c)
+ *(p-1) = c;
+ return 0;
+}
+
+
+static int
+check_range (num, bits, flags)
+ unsigned long num;
+ int bits;
+ int flags;
+{
+ long min, max;
+ int retval=0;
+
+ /* don't bother checking 32-bit values */
+ if (bits == 32)
+ return 0;
+
+ if (flags & OPERAND_SHIFT)
+ {
+ /* We know that all shifts are right by three bits.... */
+
+ if (flags & OPERAND_SIGNED)
+ num = (unsigned long) (((/*signed*/ long) num) >> 3);
+ else
+ num >>= 3;
+ }
+
+ if (flags & OPERAND_SIGNED)
+ {
+ max = (1 << (bits - 1))-1;
+ min = - (1 << (bits - 1));
+ if (((long)num > max) || ((long)num < min))
+ retval = 1;
+ }
+ else
+ {
+ max = (1 << bits) - 1;
+ min = 0;
+ if ((num > max) || (num < min))
+ retval = 1;
+ }
+
+ return retval;
+}
+
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+ fprintf (stream, _("\nD30V options:\n\
+-O Make adjacent short instructions parallel if possible.\n\
+-n Warn about all NOPs inserted by the assembler.\n\
+-N Warn about NOPs inserted after word multiplies.\n\
+-c Warn about symbols whoes names match register names.\n\
+-C Opposite of -C. -c is the default.\n"));
+}
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ switch (c)
+ {
+ /* Optimize. Will attempt to parallelize operations */
+ case 'O':
+ Optimizing = 1;
+ break;
+
+ /* Warn about all NOPS that the assembler inserts. */
+ case 'n':
+ warn_nops = NOP_ALL;
+ break;
+
+ /* Warn about the NOPS that the assembler inserts because of the
+ multiply hazard. */
+ case 'N':
+ warn_nops = NOP_MULTIPLY;
+ break;
+
+ case 'c':
+ warn_register_name_conflicts = 1;
+ break;
+
+ case 'C':
+ warn_register_name_conflicts = 0;
+ break;
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+symbolS *
+md_undefined_symbol (name)
+ char *name;
+{
+ return 0;
+}
+
+/* Turn a string in input_line_pointer into a floating point constant of type
+ type, and store the appropriate bytes in *litP. The number of LITTLENUMS
+ emitted is stored in *sizeP . An error message is returned, or NULL on OK.
+ */
+char *
+md_atof (type, litP, sizeP)
+ int type;
+ char *litP;
+ int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[4];
+ char *t;
+ int i;
+
+ switch (type)
+ {
+ case 'f':
+ prec = 2;
+ break;
+ case 'd':
+ prec = 4;
+ break;
+ default:
+ *sizeP = 0;
+ return _("bad call to md_atof");
+ }
+
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+
+ *sizeP = prec * 2;
+
+ for (i = 0; i < prec; i++)
+ {
+ md_number_to_chars (litP, (valueT) words[i], 2);
+ litP += 2;
+ }
+ return NULL;
+}
+
+void
+md_convert_frag (abfd, sec, fragP)
+ bfd *abfd;
+ asection *sec;
+ fragS *fragP;
+{
+ abort ();
+}
+
+valueT
+md_section_align (seg, addr)
+ asection *seg;
+ valueT addr;
+{
+ int align = bfd_get_section_alignment (stdoutput, seg);
+ return ((addr + (1 << align) - 1) & (-1 << align));
+}
+
+
+void
+md_begin ()
+{
+ struct d30v_opcode * opcode;
+ d30v_hash = hash_new ();
+
+ /* Insert opcode names into a hash table. */
+ for (opcode = (struct d30v_opcode *)d30v_opcode_table; opcode->name; opcode++)
+ hash_insert (d30v_hash, opcode->name, (char *) opcode);
+
+ fixups = &FixUps[0];
+ FixUps[0].next = &FixUps[1];
+ FixUps[1].next = &FixUps[0];
+
+ d30v_current_align_seg = now_seg;
+}
+
+
+/* this function removes the postincrement or postdecrement
+ operator ( '+' or '-' ) from an expression */
+
+static int postfix (p)
+ char *p;
+{
+ while (*p != '-' && *p != '+')
+ {
+ if (*p==0 || *p=='\n' || *p=='\r' || *p==' ' || *p==',')
+ break;
+ p++;
+ }
+
+ if (*p == '-')
+ {
+ *p = ' ';
+ return (-1);
+ }
+ if (*p == '+')
+ {
+ *p = ' ';
+ return (1);
+ }
+
+ return (0);
+}
+
+
+static bfd_reloc_code_real_type
+get_reloc (op, rel_flag)
+ struct d30v_operand *op;
+ int rel_flag;
+{
+ switch (op->bits)
+ {
+ case 6:
+ if (op->flags & OPERAND_SHIFT)
+ return BFD_RELOC_D30V_9_PCREL;
+ else
+ return BFD_RELOC_D30V_6;
+ break;
+ case 12:
+ if (!(op->flags & OPERAND_SHIFT))
+ as_warn (_("unexpected 12-bit reloc type"));
+ if (rel_flag == RELOC_PCREL)
+ return BFD_RELOC_D30V_15_PCREL;
+ else
+ return BFD_RELOC_D30V_15;
+ case 18:
+ if (!(op->flags & OPERAND_SHIFT))
+ as_warn (_("unexpected 18-bit reloc type"));
+ if (rel_flag == RELOC_PCREL)
+ return BFD_RELOC_D30V_21_PCREL;
+ else
+ return BFD_RELOC_D30V_21;
+ case 32:
+ if (rel_flag == RELOC_PCREL)
+ return BFD_RELOC_D30V_32_PCREL;
+ else
+ return BFD_RELOC_D30V_32;
+ default:
+ return 0;
+ }
+}
+
+/* get_operands parses a string of operands and returns
+ an array of expressions */
+
+static int
+get_operands (exp, cmp_hack)
+ expressionS exp[];
+ int cmp_hack;
+{
+ char *p = input_line_pointer;
+ int numops = 0;
+ int post = 0;
+
+ if (cmp_hack)
+ {
+ exp[numops].X_op = O_absent;
+ exp[numops++].X_add_number = cmp_hack - 1;
+ }
+
+ while (*p)
+ {
+ while (*p == ' ' || *p == '\t' || *p == ',')
+ p++;
+ if (*p==0 || *p=='\n' || *p=='\r')
+ break;
+
+ if (*p == '@')
+ {
+ p++;
+ exp[numops].X_op = O_absent;
+ if (*p == '(')
+ {
+ p++;
+ exp[numops].X_add_number = OPERAND_ATPAR;
+ post = postfix (p);
+ }
+ else if (*p == '-')
+ {
+ p++;
+ exp[numops].X_add_number = OPERAND_ATMINUS;
+ }
+ else
+ {
+ exp[numops].X_add_number = OPERAND_ATSIGN;
+ post = postfix (p);
+ }
+ numops++;
+ continue;
+ }
+
+ if (*p == ')')
+ {
+ /* just skip the trailing paren */
+ p++;
+ continue;
+ }
+
+ input_line_pointer = p;
+
+ /* check to see if it might be a register name */
+ if (!register_name (&exp[numops]))
+ {
+ /* parse as an expression */
+ expression (&exp[numops]);
+ }
+
+ if (exp[numops].X_op == O_illegal)
+ as_bad (_("illegal operand"));
+ else if (exp[numops].X_op == O_absent)
+ as_bad (_("missing operand"));
+
+ numops++;
+ p = input_line_pointer;
+
+ switch (post)
+ {
+ case -1: /* postdecrement mode */
+ exp[numops].X_op = O_absent;
+ exp[numops++].X_add_number = OPERAND_MINUS;
+ break;
+ case 1: /* postincrement mode */
+ exp[numops].X_op = O_absent;
+ exp[numops++].X_add_number = OPERAND_PLUS;
+ break;
+ }
+ post = 0;
+ }
+
+ exp[numops].X_op = 0;
+ return (numops);
+}
+
+/* build_insn generates the instruction. It does everything */
+/* but write the FM bits. */
+
+static long long
+build_insn (opcode, opers)
+ struct d30v_insn *opcode;
+ expressionS *opers;
+{
+ int i, length, bits, shift, flags;
+ unsigned int number, id=0;
+ long long insn;
+ struct d30v_opcode *op = opcode->op;
+ struct d30v_format *form = opcode->form;
+
+ insn = opcode->ecc << 28 | op->op1 << 25 | op->op2 << 20 | form->modifier << 18;
+
+ for (i=0; form->operands[i]; i++)
+ {
+ flags = d30v_operand_table[form->operands[i]].flags;
+
+ /* must be a register or number */
+ if (!(flags & OPERAND_REG) && !(flags & OPERAND_NUM) &&
+ !(flags & OPERAND_NAME) && !(flags & OPERAND_SPECIAL))
+ continue;
+
+ bits = d30v_operand_table[form->operands[i]].bits;
+ if (flags & OPERAND_SHIFT)
+ bits += 3;
+
+ length = d30v_operand_table[form->operands[i]].length;
+ shift = 12 - d30v_operand_table[form->operands[i]].position;
+ if (opers[i].X_op != O_symbol)
+ number = opers[i].X_add_number;
+ else
+ number = 0;
+ if (flags & OPERAND_REG)
+ {
+ /* check for mvfsys or mvtsys control registers */
+ if (flags & OPERAND_CONTROL && (number & 0x7f) > MAX_CONTROL_REG)
+ {
+ /* PSWL or PSWH */
+ id = (number & 0x7f) - MAX_CONTROL_REG;
+ number = 0;
+ }
+ else if (number & OPERAND_FLAG)
+ {
+ id = 3; /* number is a flag register */
+ }
+ number &= 0x7F;
+ }
+ else if (flags & OPERAND_SPECIAL)
+ {
+ number = id;
+ }
+
+ if (opers[i].X_op != O_register && opers[i].X_op != O_constant && !(flags & OPERAND_NAME))
+ {
+ /* now create a fixup */
+
+ if (fixups->fc >= MAX_INSN_FIXUPS)
+ as_fatal (_("too many fixups"));
+
+ fixups->fix[fixups->fc].reloc =
+ get_reloc ((struct d30v_operand *)&d30v_operand_table[form->operands[i]], op->reloc_flag);
+ fixups->fix[fixups->fc].size = 4;
+ fixups->fix[fixups->fc].exp = opers[i];
+ fixups->fix[fixups->fc].operand = form->operands[i];
+ if (fixups->fix[fixups->fc].reloc == BFD_RELOC_D30V_9_PCREL)
+ fixups->fix[fixups->fc].pcrel = RELOC_PCREL;
+ else
+ fixups->fix[fixups->fc].pcrel = op->reloc_flag;
+ (fixups->fc)++;
+ }
+
+ /* truncate to the proper number of bits */
+ if ((opers[i].X_op == O_constant) && check_range (number, bits, flags))
+ as_bad (_("operand out of range: %d"),number);
+ if (bits < 31)
+ number &= 0x7FFFFFFF >> (31 - bits);
+ if (flags & OPERAND_SHIFT)
+ number >>= 3;
+ if (bits == 32)
+ {
+ /* it's a LONG instruction */
+ insn |= (number >> 26); /* top 6 bits */
+ insn <<= 32; /* shift the first word over */
+ insn |= ((number & 0x03FC0000) << 2); /* next 8 bits */
+ insn |= number & 0x0003FFFF; /* bottom 18 bits */
+ }
+ else
+ insn |= number << shift;
+ }
+ return insn;
+}
+
+
+/* write out a long form instruction */
+static void
+write_long (opcode, insn, fx)
+ struct d30v_insn *opcode;
+ long long insn;
+ Fixups *fx;
+{
+ int i, where;
+ char *f = frag_more (8);
+
+ insn |= FM11;
+ d30v_number_to_chars (f, insn, 8);
+
+ for (i=0; i < fx->fc; i++)
+ {
+ if (fx->fix[i].reloc)
+ {
+ where = f - frag_now->fr_literal;
+ fix_new_exp (frag_now,
+ where,
+ fx->fix[i].size,
+ &(fx->fix[i].exp),
+ fx->fix[i].pcrel,
+ fx->fix[i].reloc);
+ }
+ }
+ fx->fc = 0;
+}
+
+
+/* Write out a short form instruction by itself. */
+static void
+write_1_short (opcode, insn, fx, use_sequential)
+ struct d30v_insn *opcode;
+ long long insn;
+ Fixups *fx;
+ int use_sequential;
+{
+ char *f = frag_more (8);
+ int i, where;
+
+ if (warn_nops == NOP_ALL)
+ as_warn (_("%s NOP inserted"), use_sequential ?
+ _("sequential") : _("parallel"));
+
+ /* The other container needs to be NOP. */
+ if (use_sequential)
+ {
+ /* Use a sequential NOP rather than a parallel one,
+ as the current instruction is a FLAG_MUL32 type one
+ and the next instruction is a load. */
+
+ /* According to 4.3.1: for FM=01, sub-instructions performed
+ only by IU cannot be encoded in L-container. */
+
+ if (opcode->op->unit == IU)
+ insn |= FM10 | NOP_LEFT; /* right then left */
+ else
+ insn = FM01 | (insn << 32) | NOP_RIGHT; /* left then right */
+ }
+ else
+ {
+ /* According to 4.3.1: for FM=00, sub-instructions performed
+ only by IU cannot be encoded in L-container. */
+
+ if (opcode->op->unit == IU)
+ insn |= FM00 | NOP_LEFT; /* right container */
+ else
+ insn = FM00 | (insn << 32) | NOP_RIGHT; /* left container */
+ }
+
+ d30v_number_to_chars (f, insn, 8);
+
+ for (i=0; i < fx->fc; i++)
+ {
+ if (fx->fix[i].reloc)
+ {
+ where = f - frag_now->fr_literal;
+ fix_new_exp (frag_now,
+ where,
+ fx->fix[i].size,
+ &(fx->fix[i].exp),
+ fx->fix[i].pcrel,
+ fx->fix[i].reloc);
+ }
+ }
+ fx->fc = 0;
+}
+
+/* Write out a short form instruction if possible.
+ Return number of instructions not written out. */
+static int
+write_2_short (opcode1, insn1, opcode2, insn2, exec_type, fx)
+ struct d30v_insn *opcode1, *opcode2;
+ long long insn1, insn2;
+ exec_type_enum exec_type;
+ Fixups *fx;
+{
+ long long insn = NOP2;
+ char *f;
+ int i,j, where;
+
+ if (exec_type == EXEC_SEQ
+ && (opcode1->op->flags_used & (FLAG_JMP | FLAG_JSR))
+ && ((opcode1->op->flags_used & FLAG_DELAY) == 0)
+ && ((opcode1->ecc == ECC_AL) || ! Optimizing))
+ {
+ /* Unconditional, non-delayed branches kill instructions in
+ the right bin. Conditional branches don't always but if
+ we are not optimizing, then we have been asked to produce
+ an error about such constructs. For the purposes of this
+ test, subroutine calls are considered to be branches. */
+ write_1_short (opcode1, insn1, fx->next, false);
+ return 1;
+ }
+
+ /* Note: we do not have to worry about subroutine calls occuring
+ in the right hand container. The return address is always
+ aligned to the next 64 bit boundary, be that 64 or 32 bit away. */
+
+ switch (exec_type)
+ {
+ case EXEC_UNKNOWN: /* Order not specified. */
+ if (Optimizing
+ && parallel_ok (opcode1, insn1, opcode2, insn2, exec_type)
+ && ! ( (opcode1->op->unit == EITHER_BUT_PREFER_MU
+ || opcode1->op->unit == MU)
+ &&
+ ( opcode2->op->unit == EITHER_BUT_PREFER_MU
+ || opcode2->op->unit == MU)))
+ {
+ /* parallel */
+ exec_type = EXEC_PARALLEL;
+
+ if (opcode1->op->unit == IU
+ || opcode2->op->unit == MU
+ || opcode2->op->unit == EITHER_BUT_PREFER_MU)
+ insn = FM00 | (insn2 << 32) | insn1;
+ else
+ {
+ insn = FM00 | (insn1 << 32) | insn2;
+ fx = fx->next;
+ }
+ }
+ else if (opcode1->op->flags_used & (FLAG_JMP | FLAG_JSR)
+ && ((opcode1->op->flags_used & FLAG_DELAY) == 0)
+ && ((opcode1->ecc == ECC_AL) || ! Optimizing))
+ {
+ /* We must emit (non-delayed) branch type instructions
+ on their own with nothing in the right container. */
+ write_1_short (opcode1, insn1, fx->next, false);
+ return 1;
+ }
+ else if (prev_left_kills_right_p)
+ {
+ /* The left instruction kils the right slot, so we
+ must leave it empty. */
+ write_1_short (opcode1, insn1, fx->next, false);
+ return 1;
+ }
+ else if (opcode1->op->unit == IU
+ || (opcode1->op->unit == EITHER
+ && opcode2->op->unit == EITHER_BUT_PREFER_MU))
+ {
+ /* reverse sequential */
+ insn = FM10 | (insn2 << 32) | insn1;
+ exec_type = EXEC_REVSEQ;
+ }
+ else
+ {
+ /* sequential */
+ insn = FM01 | (insn1 << 32) | insn2;
+ fx = fx->next;
+ exec_type = EXEC_SEQ;
+ }
+ break;
+
+ case EXEC_PARALLEL: /* parallel */
+ flag_explicitly_parallel = flag_xp_state;
+ if (! parallel_ok (opcode1, insn1, opcode2, insn2, exec_type))
+ as_bad (_("Instructions may not be executed in parallel"));
+ else if (opcode1->op->unit == IU)
+ {
+ if (opcode2->op->unit == IU)
+ as_bad (_("Two IU instructions may not be executed in parallel"));
+ as_warn (_("Swapping instruction order"));
+ insn = FM00 | (insn2 << 32) | insn1;
+ }
+ else if (opcode2->op->unit == MU)
+ {
+ if (opcode1->op->unit == MU)
+ as_bad (_("Two MU instructions may not be executed in parallel"));
+ else if (opcode1->op->unit == EITHER_BUT_PREFER_MU)
+ as_warn (_("Executing %s in IU may not work"), opcode1->op->name);
+ as_warn (_("Swapping instruction order"));
+ insn = FM00 | (insn2 << 32) | insn1;
+ }
+ else
+ {
+ if (opcode2->op->unit == EITHER_BUT_PREFER_MU)
+ as_warn (_("Executing %s in IU may not work"), opcode2->op->name);
+
+ insn = FM00 | (insn1 << 32) | insn2;
+ fx = fx->next;
+ }
+ flag_explicitly_parallel = 0;
+ break;
+
+ case EXEC_SEQ: /* sequential */
+ if (opcode1->op->unit == IU)
+ as_bad (_("IU instruction may not be in the left container"));
+ if (prev_left_kills_right_p)
+ as_bad (_("special left instruction `%s' kills instruction "
+ "`%s' in right container"),
+ opcode1->op->name, opcode2->op->name);
+ if (opcode2->op->unit == EITHER_BUT_PREFER_MU)
+ as_warn (_("Executing %s in IU may not work"), opcode2->op->name);
+ insn = FM01 | (insn1 << 32) | insn2;
+ fx = fx->next;
+ break;
+
+ case EXEC_REVSEQ: /* reverse sequential */
+ if (opcode2->op->unit == MU)
+ as_bad (_("MU instruction may not be in the right container"));
+ if (opcode2->op->unit == EITHER_BUT_PREFER_MU)
+ as_warn (_("Executing %s in IU may not work"), opcode2->op->name);
+ insn = FM10 | (insn1 << 32) | insn2;
+ fx = fx->next;
+ break;
+
+ default:
+ as_fatal (_("unknown execution type passed to write_2_short()"));
+ }
+
+ /* printf ("writing out %llx\n",insn); */
+ f = frag_more (8);
+ d30v_number_to_chars (f, insn, 8);
+
+ /* If the previous instruction was a 32-bit multiply but it is put into a
+ parallel container, mark the current instruction as being a 32-bit
+ multiply. */
+ if (prev_mul32_p && exec_type == EXEC_PARALLEL)
+ cur_mul32_p = 1;
+
+ for (j=0; j<2; j++)
+ {
+ for (i=0; i < fx->fc; i++)
+ {
+ if (fx->fix[i].reloc)
+ {
+ where = (f - frag_now->fr_literal) + 4*j;
+
+ fix_new_exp (frag_now,
+ where,
+ fx->fix[i].size,
+ &(fx->fix[i].exp),
+ fx->fix[i].pcrel,
+ fx->fix[i].reloc);
+ }
+ }
+
+ fx->fc = 0;
+ fx = fx->next;
+ }
+
+ return 0;
+}
+
+
+/* Check 2 instructions and determine if they can be safely */
+/* executed in parallel. Returns 1 if they can be. */
+static int
+parallel_ok (op1, insn1, op2, insn2, exec_type)
+ struct d30v_insn *op1, *op2;
+ unsigned long insn1, insn2;
+ exec_type_enum exec_type;
+{
+ int i, j, shift, regno, bits, ecc;
+ unsigned long flags, mask, flags_set1, flags_set2, flags_used1, flags_used2;
+ unsigned long ins, mod_reg[2][3], used_reg[2][3], flag_reg[2];
+ struct d30v_format *f;
+ struct d30v_opcode *op;
+
+ /* section 4.3: both instructions must not be IU or MU only */
+ if ((op1->op->unit == IU && op2->op->unit == IU)
+ || (op1->op->unit == MU && op2->op->unit == MU))
+ return 0;
+
+ /* first instruction must not be a jump to safely optimize, unless this
+ is an explicit parallel operation. */
+ if (exec_type != EXEC_PARALLEL
+ && (op1->op->flags_used & (FLAG_JMP | FLAG_JSR)))
+ return 0;
+
+ /* If one instruction is /TX or /XT and the other is /FX or /XF respectively,
+ then it is safe to allow the two to be done as parallel ops, since only
+ one will ever be executed at a time. */
+ if ((op1->ecc == ECC_TX && op2->ecc == ECC_FX)
+ || (op1->ecc == ECC_FX && op2->ecc == ECC_TX)
+ || (op1->ecc == ECC_XT && op2->ecc == ECC_XF)
+ || (op1->ecc == ECC_XF && op2->ecc == ECC_XT))
+ return 1;
+
+ /* [0] r0-r31
+ [1] r32-r63
+ [2] a0, a1, flag registers */
+
+ for (j = 0; j < 2; j++)
+ {
+ if (j == 0)
+ {
+ f = op1->form;
+ op = op1->op;
+ ecc = op1->ecc;
+ ins = insn1;
+ }
+ else
+ {
+ f = op2->form;
+ op = op2->op;
+ ecc = op2->ecc;
+ ins = insn2;
+ }
+ flag_reg[j] = 0;
+ mod_reg[j][0] = mod_reg[j][1] = 0;
+ used_reg[j][0] = used_reg[j][1] = 0;
+
+ if (flag_explicitly_parallel)
+ {
+ /* For human specified parallel instructions we have been asked
+ to ignore the possibility that both instructions could modify
+ bits in the PSW, so we initialise the mod & used arrays to 0.
+ We have been asked, however, to refuse to allow parallel
+ instructions which explicitly set the same flag register,
+ eg "cmpne f0,r1,0x10 || cmpeq f0, r5, 0x2", so further on we test
+ for the use of a flag register and set a bit in the mod or used
+ array appropriately. */
+
+ mod_reg[j][2] = 0;
+ used_reg[j][2] = 0;
+ }
+ else
+ {
+ mod_reg[j][2] = (op->flags_set & FLAG_ALL);
+ used_reg[j][2] = (op->flags_used & FLAG_ALL);
+ }
+
+ /* BSR/JSR always sets R62 */
+ if (op->flags_used & FLAG_JSR)
+ mod_reg[j][1] = (1L << (62-32));
+
+ /* conditional execution affects the flags_used */
+ switch (ecc)
+ {
+ case ECC_TX:
+ case ECC_FX:
+ used_reg[j][2] |= flag_reg[j] = FLAG_0;
+ break;
+
+ case ECC_XT:
+ case ECC_XF:
+ used_reg[j][2] |= flag_reg[j] = FLAG_1;
+ break;
+
+ case ECC_TT:
+ case ECC_TF:
+ used_reg[j][2] |= flag_reg[j] = (FLAG_0 | FLAG_1);
+ break;
+ }
+
+ for (i = 0; f->operands[i]; i++)
+ {
+ flags = d30v_operand_table[f->operands[i]].flags;
+ shift = 12 - d30v_operand_table[f->operands[i]].position;
+ bits = d30v_operand_table[f->operands[i]].bits;
+ if (bits == 32)
+ mask = 0xffffffff;
+ else
+ mask = 0x7FFFFFFF >> (31 - bits);
+
+ if ((flags & OPERAND_PLUS) || (flags & OPERAND_MINUS))
+ {
+ /* this is a post-increment or post-decrement */
+ /* the previous register needs to be marked as modified */
+
+ shift = 12 - d30v_operand_table[f->operands[i-1]].position;
+ regno = (ins >> shift) & 0x3f;
+ if (regno >= 32)
+ mod_reg[j][1] |= 1L << (regno - 32);
+ else
+ mod_reg[j][0] |= 1L << regno;
+ }
+ else if (flags & OPERAND_REG)
+ {
+ regno = (ins >> shift) & mask;
+ /* the memory write functions don't have a destination register */
+ if ((flags & OPERAND_DEST) && !(op->flags_set & FLAG_MEM))
+ {
+ /* MODIFIED registers and flags */
+ if (flags & OPERAND_ACC)
+ {
+ if (regno == 0)
+ mod_reg[j][2] |= FLAG_A0;
+ else if (regno == 1)
+ mod_reg[j][2] |= FLAG_A1;
+ else
+ abort ();
+ }
+ else if (flags & OPERAND_FLAG)
+ mod_reg[j][2] |= 1L << regno;
+ else if (!(flags & OPERAND_CONTROL))
+ {
+ int r, z;
+
+ /* need to check if there are two destination */
+ /* registers, for example ld2w */
+ if (flags & OPERAND_2REG)
+ z = 1;
+ else
+ z = 0;
+
+ for (r = regno; r <= regno + z; r++)
+ {
+ if (r >= 32)
+ mod_reg[j][1] |= 1L << (r - 32);
+ else
+ mod_reg[j][0] |= 1L << r;
+ }
+ }
+ }
+ else
+ {
+ /* USED, but not modified registers and flags */
+ if (flags & OPERAND_ACC)
+ {
+ if (regno == 0)
+ used_reg[j][2] |= FLAG_A0;
+ else if (regno == 1)
+ used_reg[j][2] |= FLAG_A1;
+ else
+ abort ();
+ }
+ else if (flags & OPERAND_FLAG)
+ used_reg[j][2] |= 1L << regno;
+ else if (!(flags & OPERAND_CONTROL))
+ {
+ int r, z;
+
+ /* need to check if there are two source */
+ /* registers, for example st2w */
+ if (flags & OPERAND_2REG)
+ z = 1;
+ else
+ z = 0;
+
+ for (r = regno; r <= regno + z; r++)
+ {
+ if (r >= 32)
+ used_reg[j][1] |= 1L << (r - 32);
+ else
+ used_reg[j][0] |= 1L << r;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ flags_set1 = op1->op->flags_set;
+ flags_set2 = op2->op->flags_set;
+ flags_used1 = op1->op->flags_used;
+ flags_used2 = op2->op->flags_used;
+
+ /* ST2W/ST4HB combined with ADDppp/SUBppp is illegal. */
+ if (((flags_set1 & (FLAG_MEM | FLAG_2WORD)) == (FLAG_MEM | FLAG_2WORD)
+ && (flags_used2 & FLAG_ADDSUBppp) != 0)
+ || ((flags_set2 & (FLAG_MEM | FLAG_2WORD)) == (FLAG_MEM | FLAG_2WORD)
+ && (flags_used1 & FLAG_ADDSUBppp) != 0))
+ return 0;
+
+ /* Load instruction combined with half-word multiply is illegal. */
+ if (((flags_used1 & FLAG_MEM) != 0 && (flags_used2 & FLAG_MUL16))
+ || ((flags_used2 & FLAG_MEM) != 0 && (flags_used1 & FLAG_MUL16)))
+ return 0;
+
+ /* Specifically allow add || add by removing carry, overflow bits dependency.
+ This is safe, even if an addc follows since the IU takes the argument in
+ the right container, and it writes its results last.
+ However, don't paralellize add followed by addc or sub followed by
+ subb. */
+
+ if (mod_reg[0][2] == FLAG_CVVA && mod_reg[1][2] == FLAG_CVVA
+ && (used_reg[0][2] & ~flag_reg[0]) == 0
+ && (used_reg[1][2] & ~flag_reg[1]) == 0
+ && op1->op->unit == EITHER && op2->op->unit == EITHER)
+ {
+ mod_reg[0][2] = mod_reg[1][2] = 0;
+ }
+
+ for (j = 0; j < 3; j++)
+ {
+ /* If the second instruction depends on the first, we obviously
+ cannot parallelize. Note, the mod flag implies use, so
+ check that as well. */
+ /* If flag_explicitly_parallel is set, then the case of the
+ second instruction using a register the first instruction
+ modifies is assumed to be okay; we trust the human. We
+ don't trust the human if both instructions modify the same
+ register but we do trust the human if they modify the same
+ flags. */
+ /* We have now been requested not to trust the human if the
+ instructions modify the same flag registers either. */
+ if (flag_explicitly_parallel)
+ {
+ if ((mod_reg[0][j] & mod_reg[1][j]) != 0)
+ return 0;
+ }
+ else
+ if ((mod_reg[0][j] & (mod_reg[1][j] | used_reg[1][j])) != 0)
+ return 0;
+ }
+
+ return 1;
+}
+
+
+/* This is the main entry point for the machine-dependent assembler. str points to a
+ machine-dependent instruction. This function is supposed to emit the frags/bytes
+ it assembles to. For the D30V, it mostly handles the special VLIW parsing and packing
+ and leaves the difficult stuff to do_assemble(). */
+
+static long long prev_insn = -1;
+static struct d30v_insn prev_opcode;
+static subsegT prev_subseg;
+static segT prev_seg = 0;
+
+void
+md_assemble (str)
+ char *str;
+{
+ struct d30v_insn opcode;
+ long long insn;
+ exec_type_enum extype = EXEC_UNKNOWN; /* execution type; parallel, etc */
+ static exec_type_enum etype = EXEC_UNKNOWN; /* saved extype. used for multiline instructions */
+ char *str2;
+
+ if ((prev_insn != -1) && prev_seg
+ && ((prev_seg != now_seg) || (prev_subseg != now_subseg)))
+ d30v_cleanup (false);
+
+ if (d30v_current_align < 3)
+ d30v_align (3, NULL, d30v_last_label);
+ else if (d30v_current_align > 3)
+ d30v_current_align = 3;
+ d30v_last_label = NULL;
+
+ flag_explicitly_parallel = 0;
+ flag_xp_state = 0;
+ if (etype == EXEC_UNKNOWN)
+ {
+ /* look for the special multiple instruction separators */
+ str2 = strstr (str, "||");
+ if (str2)
+ {
+ extype = EXEC_PARALLEL;
+ flag_xp_state = 1;
+ }
+ else
+ {
+ str2 = strstr (str, "->");
+ if (str2)
+ extype = EXEC_SEQ;
+ else
+ {
+ str2 = strstr (str, "<-");
+ if (str2)
+ extype = EXEC_REVSEQ;
+ }
+ }
+ /* str2 points to the separator, if one */
+ if (str2)
+ {
+ *str2 = 0;
+
+ /* if two instructions are present and we already have one saved
+ then first write it out */
+ d30v_cleanup (false);
+
+ /* Assemble first instruction and save it. */
+ prev_insn = do_assemble (str, &prev_opcode, 1, 0);
+ if (prev_insn == -1)
+ as_bad (_("Cannot assemble instruction"));
+ if (prev_opcode.form != NULL && prev_opcode.form->form >= LONG)
+ as_bad (_("First opcode is long. Unable to mix instructions as specified."));
+ fixups = fixups->next;
+ str = str2 + 2;
+ prev_seg = now_seg;
+ prev_subseg = now_subseg;
+ }
+ }
+
+ insn = do_assemble (str, &opcode,
+ (extype != EXEC_UNKNOWN || etype != EXEC_UNKNOWN),
+ extype == EXEC_PARALLEL);
+ if (insn == -1)
+ {
+ if (extype != EXEC_UNKNOWN)
+ etype = extype;
+ as_bad (_("Cannot assemble instruction"));
+ return;
+ }
+
+ if (etype != EXEC_UNKNOWN)
+ {
+ extype = etype;
+ etype = EXEC_UNKNOWN;
+ }
+
+ /* Word multiply instructions must not be followed by either a load or a
+ 16-bit multiply instruction in the next cycle. */
+ if ( (extype != EXEC_REVSEQ)
+ && prev_mul32_p
+ && (opcode.op->flags_used & (FLAG_MEM | FLAG_MUL16)))
+ {
+ /* However, load and multiply should able to be combined in a parallel
+ operation, so check for that first. */
+ if (prev_insn != -1
+ && (opcode.op->flags_used & FLAG_MEM)
+ && opcode.form->form < LONG
+ && (extype == EXEC_PARALLEL || (Optimizing && extype == EXEC_UNKNOWN))
+ && parallel_ok (&prev_opcode, (long)prev_insn,
+ &opcode, (long)insn, extype)
+ && write_2_short (&prev_opcode, (long)prev_insn,
+ &opcode, (long)insn, extype, fixups) == 0)
+ {
+ /* no instructions saved */
+ prev_insn = -1;
+ return;
+ }
+ else
+ {
+ /* Can't parallelize, flush previous instruction and emit a word of NOPS,
+ unless the previous instruction is a NOP, in which case just flush it,
+ as this will generate a word of NOPs for us. */
+
+ if (prev_insn != -1 && (strcmp (prev_opcode.op->name, "nop") == 0))
+ d30v_cleanup (false);
+ else
+ {
+ char * f;
+
+ if (prev_insn != -1)
+ d30v_cleanup (true);
+ else
+ {
+ f = frag_more (8);
+ d30v_number_to_chars (f, NOP2, 8);
+
+ if (warn_nops == NOP_ALL || warn_nops == NOP_MULTIPLY)
+ {
+ if (opcode.op->flags_used & FLAG_MEM)
+ as_warn (_("word of NOPs added between word multiply and load"));
+ else
+ as_warn (_("word of NOPs added between word multiply and 16-bit multiply"));
+ }
+ }
+ }
+
+ extype = EXEC_UNKNOWN;
+ }
+ }
+ else if ( (extype == EXEC_REVSEQ)
+ && cur_mul32_p
+ && (prev_opcode.op->flags_used & (FLAG_MEM | FLAG_MUL16)))
+ {
+ /* Can't parallelize, flush current instruction and add a sequential NOP. */
+ write_1_short (& opcode, (long) insn, fixups->next->next, true);
+
+ /* Make the previous instruction the current one. */
+ extype = EXEC_UNKNOWN;
+ insn = prev_insn;
+ now_seg = prev_seg;
+ now_subseg = prev_subseg;
+ prev_insn = -1;
+ cur_mul32_p = prev_mul32_p;
+ prev_mul32_p = 0;
+ memcpy (&opcode, &prev_opcode, sizeof (prev_opcode));
+ }
+
+ /* If this is a long instruction, write it and any previous short instruction. */
+ if (opcode.form->form >= LONG)
+ {
+ if (extype != EXEC_UNKNOWN)
+ as_bad (_("Instruction uses long version, so it cannot be mixed as specified"));
+ d30v_cleanup (false);
+ write_long (& opcode, insn, fixups);
+ prev_insn = -1;
+ }
+ else if ((prev_insn != -1)
+ && (write_2_short
+ (& prev_opcode, (long) prev_insn, & opcode,
+ (long) insn, extype, fixups) == 0))
+ {
+ /* No instructions saved. */
+ prev_insn = -1;
+ }
+ else
+ {
+ if (extype != EXEC_UNKNOWN)
+ as_bad (_("Unable to mix instructions as specified"));
+
+ /* Save off last instruction so it may be packed on next pass. */
+ memcpy (&prev_opcode, &opcode, sizeof (prev_opcode));
+ prev_insn = insn;
+ prev_seg = now_seg;
+ prev_subseg = now_subseg;
+ fixups = fixups->next;
+ prev_mul32_p = cur_mul32_p;
+ }
+}
+
+
+/* do_assemble assembles a single instruction and returns an opcode */
+/* it returns -1 (an invalid opcode) on error */
+
+#define NAME_BUF_LEN 20
+
+static long long
+do_assemble (str, opcode, shortp, is_parallel)
+ char *str;
+ struct d30v_insn *opcode;
+ int shortp;
+ int is_parallel;
+{
+ unsigned char * op_start;
+ unsigned char * save;
+ unsigned char * op_end;
+ char name [NAME_BUF_LEN];
+ int cmp_hack;
+ int nlen = 0;
+ int fsize = (shortp ? FORCE_SHORT : 0);
+ expressionS myops [6];
+ long long insn;
+
+ /* Drop leading whitespace */
+ while (* str == ' ')
+ str ++;
+
+ /* find the opcode end */
+ for (op_start = op_end = (unsigned char *) (str);
+ * op_end
+ && nlen < (NAME_BUF_LEN - 1)
+ && * op_end != '/'
+ && !is_end_of_line[*op_end] && *op_end != ' ';
+ op_end++)
+ {
+ name[nlen] = tolower (op_start[nlen]);
+ nlen++;
+ }
+
+ if (nlen == 0)
+ return -1;
+
+ name[nlen] = 0;
+
+ /* if there is an execution condition code, handle it */
+ if (*op_end == '/')
+ {
+ int i = 0;
+ while ( (i < ECC_MAX) && strncasecmp (d30v_ecc_names[i], op_end + 1, 2))
+ i++;
+
+ if (i == ECC_MAX)
+ {
+ char tmp[4];
+ strncpy (tmp, op_end + 1, 2);
+ tmp[2] = 0;
+ as_bad (_("unknown condition code: %s"),tmp);
+ return -1;
+ }
+ /* printf ("condition code=%d\n",i); */
+ opcode->ecc = i;
+ op_end += 3;
+ }
+ else
+ opcode->ecc = ECC_AL;
+
+
+ /* CMP and CMPU change their name based on condition codes */
+ if (!strncmp (name, "cmp", 3))
+ {
+ int p,i;
+ char **str = (char **)d30v_cc_names;
+ if (name[3] == 'u')
+ p = 4;
+ else
+ p = 3;
+
+ for (i=1; *str && strncmp (*str, & name[p], 2); i++, str++)
+ ;
+
+ /* cmpu only supports some condition codes */
+ if (p == 4)
+ {
+ if (i < 3 || i > 6)
+ {
+ name[p+2]=0;
+ as_bad (_("cmpu doesn't support condition code %s"),&name[p]);
+ }
+ }
+
+ if (!*str)
+ {
+ name[p+2]=0;
+ as_bad (_("unknown condition code: %s"),&name[p]);
+ }
+
+ cmp_hack = i;
+ name[p] = 0;
+ }
+ else
+ cmp_hack = 0;
+
+ /* printf("cmp_hack=%d\n",cmp_hack); */
+
+ /* need to look for .s or .l */
+ if (name[nlen-2] == '.')
+ {
+ switch (name[nlen-1])
+ {
+ case 's':
+ fsize = FORCE_SHORT;
+ break;
+ case 'l':
+ fsize = FORCE_LONG;
+ break;
+ }
+ name[nlen-2] = 0;
+ }
+
+ /* find the first opcode with the proper name */
+ opcode->op = (struct d30v_opcode *)hash_find (d30v_hash, name);
+ if (opcode->op == NULL)
+ {
+ as_bad (_("unknown opcode: %s"),name);
+ return -1;
+ }
+
+ save = input_line_pointer;
+ input_line_pointer = op_end;
+ while (!(opcode->form = find_format (opcode->op, myops, fsize, cmp_hack)))
+ {
+ opcode->op++;
+ if (opcode->op->name == NULL || strcmp (opcode->op->name, name))
+ {
+ as_bad (_("operands for opcode `%s' do not match any valid format"), name);
+ return -1;
+ }
+ }
+ input_line_pointer = save;
+
+ insn = build_insn (opcode, myops);
+
+ /* Propigate multiply status */
+ if (insn != -1)
+ {
+ if (is_parallel && prev_mul32_p)
+ cur_mul32_p = 1;
+ else
+ {
+ prev_mul32_p = cur_mul32_p;
+ cur_mul32_p = (opcode->op->flags_used & FLAG_MUL32) != 0;
+ }
+ }
+
+ /* Propagate left_kills_right status */
+ if (insn != -1)
+ {
+ prev_left_kills_right_p = cur_left_kills_right_p;
+
+ if (opcode->op->flags_set & FLAG_LKR)
+ {
+ cur_left_kills_right_p = 1;
+
+ if (strcmp (opcode->op->name, "mvtsys") == 0)
+ {
+ /* Left kills right for only mvtsys only for PSW/PSWH/PSWL/flags target. */
+ if ((myops[0].X_op == O_register) &&
+ ((myops[0].X_add_number == OPERAND_CONTROL) || /* psw */
+ (myops[0].X_add_number == OPERAND_CONTROL+MAX_CONTROL_REG+2) || /* pswh */
+ (myops[0].X_add_number == OPERAND_CONTROL+MAX_CONTROL_REG+1) || /* pswl */
+ (myops[0].X_add_number == OPERAND_FLAG+0) || /* f0 */
+ (myops[0].X_add_number == OPERAND_FLAG+1) || /* f1 */
+ (myops[0].X_add_number == OPERAND_FLAG+2) || /* f2 */
+ (myops[0].X_add_number == OPERAND_FLAG+3) || /* f3 */
+ (myops[0].X_add_number == OPERAND_FLAG+4) || /* f4 */
+ (myops[0].X_add_number == OPERAND_FLAG+5) || /* f5 */
+ (myops[0].X_add_number == OPERAND_FLAG+6) || /* f6 */
+ (myops[0].X_add_number == OPERAND_FLAG+7))) /* f7 */
+ {
+ cur_left_kills_right_p = 1;
+ }
+ else
+ {
+ /* Other mvtsys target registers don't kill right instruction. */
+ cur_left_kills_right_p = 0;
+ }
+ } /* mvtsys */
+ }
+ else
+ cur_left_kills_right_p = 0;
+ }
+
+ return insn;
+}
+
+
+/* find_format() gets a pointer to an entry in the format table.
+ It must look at all formats for an opcode and use the operands
+ to choose the correct one. Returns NULL on error. */
+
+static struct d30v_format *
+find_format (opcode, myops, fsize, cmp_hack)
+ struct d30v_opcode *opcode;
+ expressionS myops[];
+ int fsize;
+ int cmp_hack;
+{
+ int numops, match, index, i=0, j, k;
+ struct d30v_format *fm;
+
+ if (opcode == NULL)
+ return NULL;
+
+ /* Get all the operands and save them as expressions. */
+ numops = get_operands (myops, cmp_hack);
+
+ while ((index = opcode->format[i++]) != 0)
+ {
+ if (fsize == FORCE_SHORT && index >= LONG)
+ continue;
+
+ if (fsize == FORCE_LONG && index < LONG)
+ continue;
+
+ fm = (struct d30v_format *)&d30v_format_table[index];
+ k = index;
+ while (fm->form == index)
+ {
+ match = 1;
+ /* Now check the operands for compatibility. */
+ for (j = 0; match && fm->operands[j]; j++)
+ {
+ int flags = d30v_operand_table[fm->operands[j]].flags;
+ int bits = d30v_operand_table[fm->operands[j]].bits;
+ int X_op = myops[j].X_op;
+ int num = myops[j].X_add_number;
+
+ if (flags & OPERAND_SPECIAL)
+ break;
+ else if (X_op == O_illegal)
+ match = 0;
+ else if (flags & OPERAND_REG)
+ {
+ if (X_op != O_register
+ || ((flags & OPERAND_ACC) && !(num & OPERAND_ACC))
+ || (!(flags & OPERAND_ACC) && (num & OPERAND_ACC))
+ || ((flags & OPERAND_FLAG) && !(num & OPERAND_FLAG))
+ || (!(flags & (OPERAND_FLAG | OPERAND_CONTROL)) && (num & OPERAND_FLAG))
+ || ((flags & OPERAND_CONTROL)
+ && !(num & (OPERAND_CONTROL | OPERAND_FLAG))))
+ {
+ match = 0;
+ }
+ }
+ else if (((flags & OPERAND_MINUS)
+ && (X_op != O_absent || num != OPERAND_MINUS))
+ || ((flags & OPERAND_PLUS)
+ && (X_op != O_absent || num != OPERAND_PLUS))
+ || ((flags & OPERAND_ATMINUS)
+ && (X_op != O_absent || num != OPERAND_ATMINUS))
+ || ((flags & OPERAND_ATPAR)
+ && (X_op != O_absent || num != OPERAND_ATPAR))
+ || ((flags & OPERAND_ATSIGN)
+ && (X_op != O_absent || num != OPERAND_ATSIGN)))
+ {
+ match=0;
+ }
+ else if (flags & OPERAND_NUM)
+ {
+ /* A number can be a constant or symbol expression. */
+
+ /* If we have found a register name, but that name also
+ matches a symbol, then re-parse the name as an expression. */
+ if (X_op == O_register
+ && symbol_find ((char *) myops[j].X_op_symbol))
+ {
+ input_line_pointer = (char *) myops[j].X_op_symbol;
+ expression (& myops[j]);
+ }
+
+ /* Turn an expression into a symbol for later resolution. */
+ if (X_op != O_absent && X_op != O_constant
+ && X_op != O_symbol && X_op != O_register
+ && X_op != O_big)
+ {
+ symbolS *sym = make_expr_symbol (&myops[j]);
+ myops[j].X_op = X_op = O_symbol;
+ myops[j].X_add_symbol = sym;
+ myops[j].X_add_number = num = 0;
+ }
+
+ if (fm->form >= LONG)
+ {
+ /* If we're testing for a LONG format, either fits. */
+ if (X_op != O_constant && X_op != O_symbol)
+ match = 0;
+ }
+ else if (fm->form < LONG
+ && ((fsize == FORCE_SHORT && X_op == O_symbol)
+ || (fm->form == SHORT_D2 && j == 0)))
+ match = 1;
+ /* This is the tricky part. Will the constant or symbol
+ fit into the space in the current format? */
+ else if (X_op == O_constant)
+ {
+ if (check_range (num, bits, flags))
+ match = 0;
+ }
+ else if (X_op == O_symbol
+ && S_IS_DEFINED (myops[j].X_add_symbol)
+ && S_GET_SEGMENT (myops[j].X_add_symbol) == now_seg
+ && opcode->reloc_flag == RELOC_PCREL)
+ {
+ /* If the symbol is defined, see if the value will fit
+ into the form we're considering. */
+ fragS *f;
+ long value;
+
+ /* Calculate the current address by running through the
+ previous frags and adding our current offset. */
+ value = 0;
+ for (f = frchain_now->frch_root; f; f = f->fr_next)
+ value += f->fr_fix + f->fr_offset;
+ value = (S_GET_VALUE (myops[j].X_add_symbol) - value
+ - (obstack_next_free (&frchain_now->frch_obstack)
+ - frag_now->fr_literal));
+ if (check_range (value, bits, flags))
+ match = 0;
+ }
+ else
+ match = 0;
+ }
+ }
+ /* printf("through the loop: match=%d\n",match); */
+ /* We're only done if the operands matched so far AND there
+ are no more to check. */
+ if (match && myops[j].X_op == 0)
+ {
+ /* Final check - issue a warning if an odd numbered register
+ is used as the first register in an instruction that reads
+ or writes 2 registers. */
+
+ for (j = 0; fm->operands[j]; j++)
+ if (myops[j].X_op == O_register
+ && (myops[j].X_add_number & 1)
+ && (d30v_operand_table[fm->operands[j]].flags & OPERAND_2REG))
+ as_warn (\
+_("Odd numbered register used as target of multi-register instruction"));
+
+ return fm;
+ }
+ fm = (struct d30v_format *)&d30v_format_table[++k];
+ }
+ /* printf("trying another format: i=%d\n",i); */
+ }
+ return NULL;
+}
+
+/* if while processing a fixup, a reloc really needs to be created */
+/* then it is done here */
+
+arelent *
+tc_gen_reloc (seg, fixp)
+ asection *seg;
+ fixS *fixp;
+{
+ arelent *reloc;
+ reloc = (arelent *) xmalloc (sizeof (arelent));
+ reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+ reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
+ if (reloc->howto == (reloc_howto_type *) NULL)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("reloc %d not supported by object file format"), (int)fixp->fx_r_type);
+ return NULL;
+ }
+ reloc->addend = fixp->fx_addnumber;
+ return reloc;
+}
+
+int
+md_estimate_size_before_relax (fragp, seg)
+ fragS *fragp;
+ asection *seg;
+{
+ abort ();
+ return 0;
+}
+
+long
+md_pcrel_from_section (fixp, sec)
+ fixS *fixp;
+ segT sec;
+{
+ if (fixp->fx_addsy != (symbolS *)NULL && (!S_IS_DEFINED (fixp->fx_addsy) ||
+ (S_GET_SEGMENT (fixp->fx_addsy) != sec)))
+ return 0;
+ return fixp->fx_frag->fr_address + fixp->fx_where;
+}
+
+int
+md_apply_fix3 (fixp, valuep, seg)
+ fixS * fixp;
+ valueT * valuep;
+ segT seg;
+{
+ char * where;
+ unsigned long insn, insn2;
+ long value;
+
+ if (fixp->fx_addsy == (symbolS *) NULL)
+ {
+ value = * valuep;
+ fixp->fx_done = 1;
+ }
+ else if (fixp->fx_pcrel)
+ value = * valuep;
+ else
+ {
+ value = fixp->fx_offset;
+
+ if (fixp->fx_subsy != (symbolS *) NULL)
+ {
+ if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
+ value -= S_GET_VALUE (fixp->fx_subsy);
+ else
+ {
+ /* We don't actually support subtracting a symbol. */
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("expression too complex"));
+ }
+ }
+ }
+
+ /* Fetch the instruction, insert the fully resolved operand
+ value, and stuff the instruction back again. */
+ where = fixp->fx_frag->fr_literal + fixp->fx_where;
+ insn = bfd_getb32 ((unsigned char *) where);
+
+ switch (fixp->fx_r_type)
+ {
+ case BFD_RELOC_8: /* Check for a bad .byte directive. */
+ if (fixp->fx_addsy != NULL)
+ as_bad (_("line %d: unable to place address of symbol '%s' into a byte"),
+ fixp->fx_line, S_GET_NAME (fixp->fx_addsy));
+ else if (((unsigned)value) > 0xff)
+ as_bad (_("line %d: unable to place value %x into a byte"),
+ fixp->fx_line, value);
+ else
+ * (unsigned char *) where = value;
+ break;
+
+ case BFD_RELOC_16: /* Check for a bad .short directive. */
+ if (fixp->fx_addsy != NULL)
+ as_bad (_("line %d: unable to place address of symbol '%s' into a short"),
+ fixp->fx_line, S_GET_NAME (fixp->fx_addsy));
+ else if (((unsigned)value) > 0xffff)
+ as_bad (_("line %d: unable to place value %x into a short"),
+ fixp->fx_line, value);
+ else
+ bfd_putb16 ((bfd_vma) value, (unsigned char *) where);
+ break;
+
+ case BFD_RELOC_64: /* Check for a bad .quad directive. */
+ if (fixp->fx_addsy != NULL)
+ as_bad (_("line %d: unable to place address of symbol '%s' into a quad"),
+ fixp->fx_line, S_GET_NAME (fixp->fx_addsy));
+ else
+ {
+ bfd_putb32 ((bfd_vma) value, (unsigned char *) where);
+ bfd_putb32 (0, ((unsigned char *) where) + 4);
+ }
+ break;
+
+ case BFD_RELOC_D30V_6:
+ check_size (value, 6, fixp->fx_file, fixp->fx_line);
+ insn |= value & 0x3F;
+ bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
+ break;
+
+ case BFD_RELOC_D30V_9_PCREL:
+ if (fixp->fx_where & 0x7)
+ {
+ if (fixp->fx_done)
+ value += 4;
+ else
+ fixp->fx_r_type = BFD_RELOC_D30V_9_PCREL_R;
+ }
+ check_size (value, 9, fixp->fx_file, fixp->fx_line);
+ insn |= ((value >> 3) & 0x3F) << 12;
+ bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
+ break;
+
+ case BFD_RELOC_D30V_15:
+ check_size (value, 15, fixp->fx_file, fixp->fx_line);
+ insn |= (value >> 3) & 0xFFF;
+ bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
+ break;
+
+ case BFD_RELOC_D30V_15_PCREL:
+ if (fixp->fx_where & 0x7)
+ {
+ if (fixp->fx_done)
+ value += 4;
+ else
+ fixp->fx_r_type = BFD_RELOC_D30V_15_PCREL_R;
+ }
+ check_size (value, 15, fixp->fx_file, fixp->fx_line);
+ insn |= (value >> 3) & 0xFFF;
+ bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
+ break;
+
+ case BFD_RELOC_D30V_21:
+ check_size (value, 21, fixp->fx_file, fixp->fx_line);
+ insn |= (value >> 3) & 0x3FFFF;
+ bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
+ break;
+
+ case BFD_RELOC_D30V_21_PCREL:
+ if (fixp->fx_where & 0x7)
+ {
+ if (fixp->fx_done)
+ value += 4;
+ else
+ fixp->fx_r_type = BFD_RELOC_D30V_21_PCREL_R;
+ }
+ check_size (value, 21, fixp->fx_file, fixp->fx_line);
+ insn |= (value >> 3) & 0x3FFFF;
+ bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
+ break;
+
+ case BFD_RELOC_D30V_32:
+ insn2 = bfd_getb32 ((unsigned char *) where + 4);
+ insn |= (value >> 26) & 0x3F; /* top 6 bits */
+ insn2 |= ((value & 0x03FC0000) << 2); /* next 8 bits */
+ insn2 |= value & 0x0003FFFF; /* bottom 18 bits */
+ bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
+ bfd_putb32 ((bfd_vma) insn2, (unsigned char *) where + 4);
+ break;
+
+ case BFD_RELOC_D30V_32_PCREL:
+ insn2 = bfd_getb32 ((unsigned char *) where + 4);
+ insn |= (value >> 26) & 0x3F; /* top 6 bits */
+ insn2 |= ((value & 0x03FC0000) << 2); /* next 8 bits */
+ insn2 |= value & 0x0003FFFF; /* bottom 18 bits */
+ bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
+ bfd_putb32 ((bfd_vma) insn2, (unsigned char *) where + 4);
+ break;
+
+ case BFD_RELOC_32:
+ bfd_putb32 ((bfd_vma) value, (unsigned char *) where);
+ break;
+
+ default:
+ as_bad (_("line %d: unknown relocation type: 0x%x"),
+ fixp->fx_line,fixp->fx_r_type);
+ }
+
+ return 0;
+}
+
+
+/* d30v_cleanup() is called after the assembler has finished parsing the input
+ file or after a label is defined. Because the D30V assembler sometimes saves short
+ instructions to see if it can package them with the next instruction, there may
+ be a short instruction that still needs written. */
+int
+d30v_cleanup (use_sequential)
+ int use_sequential;
+{
+ segT seg;
+ subsegT subseg;
+
+ if (prev_insn != -1)
+ {
+ seg = now_seg;
+ subseg = now_subseg;
+ subseg_set (prev_seg, prev_subseg);
+ write_1_short (&prev_opcode, (long)prev_insn, fixups->next, use_sequential);
+ subseg_set (seg, subseg);
+ prev_insn = -1;
+ if (use_sequential)
+ prev_mul32_p = false;
+ }
+ return 1;
+}
+
+static void
+d30v_number_to_chars (buf, value, n)
+ char *buf; /* Return 'nbytes' of chars here. */
+ long long value; /* The value of the bits. */
+ int n; /* Number of bytes in the output. */
+{
+ while (n--)
+ {
+ buf[n] = value & 0xff;
+ value >>= 8;
+ }
+}
+
+
+/* This function is called at the start of every line. */
+/* it checks to see if the first character is a '.' */
+/* which indicates the start of a pseudo-op. If it is, */
+/* then write out any unwritten instructions */
+
+void
+d30v_start_line ()
+{
+ char *c = input_line_pointer;
+
+ while (isspace (*c))
+ c++;
+
+ if (*c == '.')
+ d30v_cleanup (false);
+}
+
+static void
+check_size (value, bits, file, line)
+ long value;
+ int bits;
+ char *file;
+ int line;
+{
+ int tmp, max;
+
+ if (value < 0)
+ tmp = ~value;
+ else
+ tmp = value;
+
+ max = (1 << (bits - 1)) - 1;
+
+ if (tmp > max)
+ as_bad_where (file, line, _("value too large to fit in %d bits"), bits);
+
+ return;
+}
+
+/* d30v_frob_label() is called when after a label is recognized. */
+
+void
+d30v_frob_label (lab)
+ symbolS *lab;
+{
+ /* Emit any pending instructions. */
+ d30v_cleanup (false);
+
+ /* Update the label's address with the current output pointer. */
+ lab->sy_frag = frag_now;
+ S_SET_VALUE (lab, (valueT) frag_now_fix ());
+
+ /* Record this label for future adjustment after we find out what
+ kind of data it references, and the required alignment therewith. */
+ d30v_last_label = lab;
+}
+
+/* Hook into cons for capturing alignment changes. */
+
+void
+d30v_cons_align (size)
+ int size;
+{
+ int log_size;
+
+ log_size = 0;
+ while ((size >>= 1) != 0)
+ ++log_size;
+
+ if (d30v_current_align < log_size)
+ d30v_align (log_size, (char *) NULL, NULL);
+ else if (d30v_current_align > log_size)
+ d30v_current_align = log_size;
+ d30v_last_label = NULL;
+}
+
+/* Called internally to handle all alignment needs. This takes care
+ of eliding calls to frag_align if'n the cached current alignment
+ says we've already got it, as well as taking care of the auto-aligning
+ labels wrt code. */
+
+static void
+d30v_align (n, pfill, label)
+ int n;
+ char *pfill;
+ symbolS *label;
+{
+ /* The front end is prone to changing segments out from under us
+ temporarily when -g is in effect. */
+ int switched_seg_p = (d30v_current_align_seg != now_seg);
+
+ /* Do not assume that if 'd30v_current_align >= n' and
+ '! switched_seg_p' that it is safe to avoid performing
+ this alignement request. The alignment of the current frag
+ can be changed under our feet, for example by a .ascii
+ directive in the source code. cf testsuite/gas/d30v/reloc.s */
+
+ d30v_cleanup (false);
+
+ if (pfill == NULL)
+ {
+ if (n > 2
+ && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
+ {
+ static char const nop[4] = { 0x00, 0xf0, 0x00, 0x00 };
+
+ /* First, make sure we're on a four-byte boundary, in case
+ someone has been putting .byte values the text section. */
+ if (d30v_current_align < 2 || switched_seg_p)
+ frag_align (2, 0, 0);
+ frag_align_pattern (n, nop, sizeof nop, 0);
+ }
+ else
+ frag_align (n, 0, 0);
+ }
+ else
+ frag_align (n, *pfill, 0);
+
+ if (!switched_seg_p)
+ d30v_current_align = n;
+
+ if (label != NULL)
+ {
+ symbolS * sym;
+ int label_seen = false;
+ struct frag * old_frag;
+ valueT old_value;
+ valueT new_value;
+
+ assert (S_GET_SEGMENT (label) == now_seg);
+
+ old_frag = label->sy_frag;
+ old_value = S_GET_VALUE (label);
+ new_value = (valueT) frag_now_fix ();
+
+ /* It is possible to have more than one label at a particular
+ address, especially if debugging is enabled, so we must
+ take care to adjust all the labels at this address in this
+ fragment. To save time we search from the end of the symbol
+ list, backwards, since the symbols we are interested in are
+ almost certainly the ones that were most recently added.
+ Also to save time we stop searching once we have seen at least
+ one matching label, and we encounter a label that is no longer
+ in the target fragment. Note, this search is guaranteed to
+ find at least one match when sym == label, so no special case
+ code is necessary. */
+ for (sym = symbol_lastP; sym != NULL; sym = sym->sy_previous)
+ {
+ if (sym->sy_frag == old_frag && S_GET_VALUE (sym) == old_value)
+ {
+ label_seen = true;
+ sym->sy_frag = frag_now;
+ S_SET_VALUE (sym, new_value);
+ }
+ else if (label_seen && sym->sy_frag != old_frag)
+ break;
+ }
+ }
+
+ record_alignment (now_seg, n);
+}
+
+/* Handle the .align pseudo-op. This aligns to a power of two. We
+ hook here to latch the current alignment. */
+
+static void
+s_d30v_align (ignore)
+ int ignore;
+{
+ int align;
+ char fill, *pfill = NULL;
+ long max_alignment = 15;
+
+ align = get_absolute_expression ();
+ if (align > max_alignment)
+ {
+ align = max_alignment;
+ as_warn (_("Alignment too large: %d assumed"), align);
+ }
+ else if (align < 0)
+ {
+ as_warn (_("Alignment negative: 0 assumed"));
+ align = 0;
+ }
+
+ if (*input_line_pointer == ',')
+ {
+ input_line_pointer++;
+ fill = get_absolute_expression ();
+ pfill = &fill;
+ }
+
+ d30v_last_label = NULL;
+ d30v_align (align, pfill, NULL);
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the .text pseudo-op. This is like the usual one, but it
+ clears the saved last label and resets known alignment. */
+
+static void
+s_d30v_text (i)
+ int i;
+
+{
+ s_text (i);
+ d30v_last_label = NULL;
+ d30v_current_align = 0;
+ d30v_current_align_seg = now_seg;
+}
+
+/* Handle the .data pseudo-op. This is like the usual one, but it
+ clears the saved last label and resets known alignment. */
+
+static void
+s_d30v_data (i)
+ int i;
+{
+ s_data (i);
+ d30v_last_label = NULL;
+ d30v_current_align = 0;
+ d30v_current_align_seg = now_seg;
+}
+
+/* Handle the .section pseudo-op. This is like the usual one, but it
+ clears the saved last label and resets known alignment. */
+
+static void
+s_d30v_section (ignore)
+ int ignore;
+{
+ obj_elf_section (ignore);
+ d30v_last_label = NULL;
+ d30v_current_align = 0;
+ d30v_current_align_seg = now_seg;
+}
diff --git a/gas/config/tc-d30v.h b/gas/config/tc-d30v.h
new file mode 100644
index 0000000000..acce285693
--- /dev/null
+++ b/gas/config/tc-d30v.h
@@ -0,0 +1,59 @@
+/* tc-310v.h -- Header file for tc-d30v.c.
+ Copyright (C) 1997 Free Software Foundation, Inc.
+ Written by Martin Hunt, Cygnus Support.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TC_D30V
+
+#ifndef BFD_ASSEMBLER
+ #error D30V support requires BFD_ASSEMBLER
+#endif
+
+/* The target BFD architecture. */
+#define TARGET_ARCH bfd_arch_d30v
+#define TARGET_FORMAT "elf32-d30v"
+#define TARGET_BYTES_BIG_ENDIAN 1
+
+#define md_operand(x)
+
+#define MD_APPLY_FIX3
+
+/* call md_pcrel_from_section, not md_pcrel_from */
+#define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from_section(FIXP, SEC)
+
+/* Permit temporary numeric labels. */
+#define LOCAL_LABELS_FB 1
+
+#define DIFF_EXPR_OK /* .-foo gets turned into PC relative relocs */
+
+/* We don't need to handle .word strangely. */
+#define WORKING_DOT_WORD
+
+#define md_number_to_chars number_to_chars_bigendian
+
+int d30v_cleanup PARAMS ((int));
+#define md_after_pass_hook() d30v_cleanup (false)
+#define md_cleanup() d30v_cleanup (false)
+#define TC_START_LABEL(ch, ptr) (ch == ':' && d30v_cleanup (false))
+#define md_start_line_hook() d30v_start_line (false)
+
+void d30v_frob_label PARAMS ((struct symbol *));
+#define tc_frob_label(sym) d30v_frob_label(sym)
+
+void d30v_cons_align PARAMS ((int));
+#define md_cons_align(nbytes) d30v_cons_align(nbytes)
diff --git a/gas/config/tc-fr30.c b/gas/config/tc-fr30.c
new file mode 100644
index 0000000000..aa075b7322
--- /dev/null
+++ b/gas/config/tc-fr30.c
@@ -0,0 +1,664 @@
+/* tc-fr30.c -- Assembler for the Fujitsu FR30.
+ Copyright (C) 1998, 1999 Free Software Foundation.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "as.h"
+#include "subsegs.h"
+#include "symcat.h"
+#include "opcodes/fr30-desc.h"
+#include "opcodes/fr30-opc.h"
+#include "cgen.h"
+
+/* Structure to hold all of the different components describing
+ an individual instruction. */
+typedef struct
+{
+ const CGEN_INSN * insn;
+ const CGEN_INSN * orig_insn;
+ CGEN_FIELDS fields;
+#if CGEN_INT_INSN_P
+ CGEN_INSN_INT buffer [1];
+#define INSN_VALUE(buf) (*(buf))
+#else
+ unsigned char buffer [CGEN_MAX_INSN_SIZE];
+#define INSN_VALUE(buf) (buf)
+#endif
+ char * addr;
+ fragS * frag;
+ int num_fixups;
+ fixS * fixups [GAS_CGEN_MAX_FIXUPS];
+ int indices [MAX_OPERAND_INSTANCES];
+}
+fr30_insn;
+
+const char comment_chars[] = ";";
+const char line_comment_chars[] = "#";
+const char line_separator_chars[] = "|";
+const char EXP_CHARS[] = "eE";
+const char FLT_CHARS[] = "dD";
+
+#define FR30_SHORTOPTS ""
+const char * md_shortopts = FR30_SHORTOPTS;
+
+struct option md_longopts[] =
+{
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof (md_longopts);
+
+int
+md_parse_option (c, arg)
+ int c;
+ char * arg;
+{
+ switch (c)
+ {
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+void
+md_show_usage (stream)
+ FILE * stream;
+{
+ fprintf (stream, _(" FR30 specific command line options:\n"));
+}
+
+/* The target specific pseudo-ops which we support. */
+const pseudo_typeS md_pseudo_table[] =
+{
+ { "word", cons, 4 },
+ { NULL, NULL, 0 }
+};
+
+
+void
+md_begin ()
+{
+ flagword applicable;
+ segT seg;
+ subsegT subseg;
+
+ /* Initialize the `cgen' interface. */
+
+ /* Set the machine number and endian. */
+ gas_cgen_cpu_desc = fr30_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0,
+ CGEN_CPU_OPEN_ENDIAN,
+ CGEN_ENDIAN_BIG,
+ CGEN_CPU_OPEN_END);
+ fr30_cgen_init_asm (gas_cgen_cpu_desc);
+
+ /* This is a callback from cgen to gas to parse operands. */
+ cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
+}
+
+void
+md_assemble (str)
+ char * str;
+{
+ static int last_insn_had_delay_slot = 0;
+ fr30_insn insn;
+ char * errmsg;
+ char * str2 = NULL;
+
+ /* Initialize GAS's cgen interface for a new instruction. */
+ gas_cgen_init_parse ();
+
+ insn.insn = fr30_cgen_assemble_insn
+ (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
+
+ if (!insn.insn)
+ {
+ as_bad (errmsg);
+ return;
+ }
+
+ /* Doesn't really matter what we pass for RELAX_P here. */
+ gas_cgen_finish_insn (insn.insn, insn.buffer,
+ CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);
+
+ /* Warn about invalid insns in delay slots. */
+ if (last_insn_had_delay_slot
+ && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_NOT_IN_DELAY_SLOT))
+ as_warn (_("Instruction %s not allowed in a delay slot."),
+ CGEN_INSN_NAME (insn.insn));
+
+ last_insn_had_delay_slot
+ = CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_DELAY_SLOT);
+}
+
+/* The syntax in the manual says constants begin with '#'.
+ We just ignore it. */
+
+void
+md_operand (expressionP)
+ expressionS * expressionP;
+{
+ if (* input_line_pointer == '#')
+ {
+ input_line_pointer ++;
+ expression (expressionP);
+ }
+}
+
+valueT
+md_section_align (segment, size)
+ segT segment;
+ valueT size;
+{
+ int align = bfd_get_section_alignment (stdoutput, segment);
+ return ((size + (1 << align) - 1) & (-1 << align));
+}
+
+symbolS *
+md_undefined_symbol (name)
+ char * name;
+{
+ return 0;
+}
+
+/* Interface to relax_segment. */
+
+/* FIXME: Build table by hand, get it working, then machine generate. */
+
+const relax_typeS md_relax_table[] =
+{
+/* The fields are:
+ 1) most positive reach of this state,
+ 2) most negative reach of this state,
+ 3) how many bytes this mode will add to the size of the current frag
+ 4) which index into the table to try if we can't fit into this one. */
+
+ /* The first entry must be unused because an `rlx_more' value of zero ends
+ each list. */
+ {1, 1, 0, 0},
+
+ /* The displacement used by GAS is from the end of the 2 byte insn,
+ so we subtract 2 from the following. */
+ /* 16 bit insn, 8 bit disp -> 10 bit range.
+ This doesn't handle a branch in the right slot at the border:
+ the "& -4" isn't taken into account. It's not important enough to
+ complicate things over it, so we subtract an extra 2 (or + 2 in -ve
+ case). */
+ {511 - 2 - 2, -512 - 2 + 2, 0, 2 },
+ /* 32 bit insn, 24 bit disp -> 26 bit range. */
+ {0x2000000 - 1 - 2, -0x2000000 - 2, 2, 0 },
+ /* Same thing, but with leading nop for alignment. */
+ {0x2000000 - 1 - 2, -0x2000000 - 2, 4, 0 }
+};
+
+long
+fr30_relax_frag (fragP, stretch)
+ fragS * fragP;
+ long stretch;
+{
+ /* Address of branch insn. */
+ long address = fragP->fr_address + fragP->fr_fix - 2;
+ long growth = 0;
+
+ /* Keep 32 bit insns aligned on 32 bit boundaries. */
+ if (fragP->fr_subtype == 2)
+ {
+ if ((address & 3) != 0)
+ {
+ fragP->fr_subtype = 3;
+ growth = 2;
+ }
+ }
+ else if (fragP->fr_subtype == 3)
+ {
+ if ((address & 3) == 0)
+ {
+ fragP->fr_subtype = 2;
+ growth = -2;
+ }
+ }
+ else
+ {
+ growth = relax_frag (fragP, stretch);
+
+ /* Long jump on odd halfword boundary? */
+ if (fragP->fr_subtype == 2 && (address & 3) != 0)
+ {
+ fragP->fr_subtype = 3;
+ growth += 2;
+ }
+ }
+
+ return growth;
+}
+
+/* Return an initial guess of the length by which a fragment must grow to
+ hold a branch to reach its destination.
+ Also updates fr_type/fr_subtype as necessary.
+
+ Called just before doing relaxation.
+ Any symbol that is now undefined will not become defined.
+ The guess for fr_var is ACTUALLY the growth beyond fr_fix.
+ Whatever we do to grow fr_fix or fr_var contributes to our returned value.
+ Although it may not be explicit in the frag, pretend fr_var starts with a
+ 0 value. */
+
+int
+md_estimate_size_before_relax (fragP, segment)
+ fragS * fragP;
+ segT segment;
+{
+ int old_fr_fix = fragP->fr_fix;
+
+ /* The only thing we have to handle here are symbols outside of the
+ current segment. They may be undefined or in a different segment in
+ which case linker scripts may place them anywhere.
+ However, we can't finish the fragment here and emit the reloc as insn
+ alignment requirements may move the insn about. */
+
+ if (S_GET_SEGMENT (fragP->fr_symbol) != segment)
+ {
+ /* The symbol is undefined in this segment.
+ Change the relaxation subtype to the max allowable and leave
+ all further handling to md_convert_frag. */
+ fragP->fr_subtype = 2;
+
+#if 0 /* Can't use this, but leave in for illustration. */
+ /* Change 16 bit insn to 32 bit insn. */
+ fragP->fr_opcode[0] |= 0x80;
+
+ /* Increase known (fixed) size of fragment. */
+ fragP->fr_fix += 2;
+
+ /* Create a relocation for it. */
+ fix_new (fragP, old_fr_fix, 4,
+ fragP->fr_symbol,
+ fragP->fr_offset, 1 /* pcrel */,
+ /* FIXME: Can't use a real BFD reloc here.
+ gas_cgen_md_apply_fix3 can't handle it. */
+ BFD_RELOC_FR30_26_PCREL);
+
+ /* Mark this fragment as finished. */
+ frag_wane (fragP);
+#else
+ {
+ const CGEN_INSN * insn;
+ int i;
+
+ /* Update the recorded insn.
+ Fortunately we don't have to look very far.
+ FIXME: Change this to record in the instruction the next higher
+ relaxable insn to use. */
+ for (i = 0, insn = fragP->fr_cgen.insn; i < 4; i++, insn++)
+ {
+ if ((strcmp (CGEN_INSN_MNEMONIC (insn),
+ CGEN_INSN_MNEMONIC (fragP->fr_cgen.insn))
+ == 0)
+ && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAX))
+ break;
+ }
+ if (i == 4)
+ abort ();
+
+ fragP->fr_cgen.insn = insn;
+ return 2;
+ }
+#endif
+ }
+
+ return (fragP->fr_var + fragP->fr_fix - old_fr_fix);
+}
+
+/* *fragP has been relaxed to its final size, and now needs to have
+ the bytes inside it modified to conform to the new size.
+
+ Called after relaxation is finished.
+ fragP->fr_type == rs_machine_dependent.
+ fragP->fr_subtype is the subtype of what the address relaxed to. */
+
+void
+md_convert_frag (abfd, sec, fragP)
+ bfd * abfd;
+ segT sec;
+ fragS * fragP;
+{
+#if 0
+ char * opcode;
+ char * displacement;
+ int target_address;
+ int opcode_address;
+ int extension;
+ int addend;
+
+ opcode = fragP->fr_opcode;
+
+ /* Address opcode resides at in file space. */
+ opcode_address = fragP->fr_address + fragP->fr_fix - 2;
+
+ switch (fragP->fr_subtype)
+ {
+ case 1 :
+ extension = 0;
+ displacement = & opcode[1];
+ break;
+ case 2 :
+ opcode[0] |= 0x80;
+ extension = 2;
+ displacement = & opcode[1];
+ break;
+ case 3 :
+ opcode[2] = opcode[0] | 0x80;
+ md_number_to_chars (opcode, PAR_NOP_INSN, 2);
+ opcode_address += 2;
+ extension = 4;
+ displacement = & opcode[3];
+ break;
+ default :
+ abort ();
+ }
+
+ if (S_GET_SEGMENT (fragP->fr_symbol) != sec)
+ {
+ /* symbol must be resolved by linker */
+ if (fragP->fr_offset & 3)
+ as_warn (_("Addend to unresolved symbol not on word boundary."));
+ addend = fragP->fr_offset >> 2;
+ }
+ else
+ {
+ /* Address we want to reach in file space. */
+ target_address = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset;
+ target_address += fragP->fr_symbol->sy_frag->fr_address;
+ addend = (target_address - (opcode_address & -4)) >> 2;
+ }
+
+ /* Create a relocation for symbols that must be resolved by the linker.
+ Otherwise output the completed insn. */
+
+ if (S_GET_SEGMENT (fragP->fr_symbol) != sec)
+ {
+ assert (fragP->fr_subtype != 1);
+ assert (fragP->fr_cgen.insn != 0);
+ gas_cgen_record_fixup (fragP,
+ /* Offset of branch insn in frag. */
+ fragP->fr_fix + extension - 4,
+ fragP->fr_cgen.insn,
+ 4 /*length*/,
+ /* FIXME: quick hack */
+#if 0
+ CGEN_OPERAND_ENTRY (fragP->fr_cgen.opindex),
+#else
+ CGEN_OPERAND_ENTRY (FR30_OPERAND_DISP24),
+#endif
+ fragP->fr_cgen.opinfo,
+ fragP->fr_symbol, fragP->fr_offset);
+ }
+
+#define SIZE_FROM_RELAX_STATE(n) ((n) == 1 ? 1 : 3)
+
+ md_number_to_chars (displacement, (valueT) addend,
+ SIZE_FROM_RELAX_STATE (fragP->fr_subtype));
+
+ fragP->fr_fix += extension;
+#endif
+}
+
+/* Functions concerning relocs. */
+
+/* The location from which a PC relative jump should be calculated,
+ given a PC relative reloc. */
+
+long
+md_pcrel_from_section (fixP, sec)
+ fixS * fixP;
+ segT sec;
+{
+ if (fixP->fx_addsy != (symbolS *) NULL
+ && (! S_IS_DEFINED (fixP->fx_addsy)
+ || S_GET_SEGMENT (fixP->fx_addsy) != sec))
+ {
+ /* The symbol is undefined (or is defined but not in this section).
+ Let the linker figure it out. */
+ return 0;
+ }
+
+ return (fixP->fx_frag->fr_address + fixP->fx_where) & ~1;
+}
+
+/* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
+ Returns BFD_RELOC_NONE if no reloc type can be found.
+ *FIXP may be modified if desired. */
+
+bfd_reloc_code_real_type
+md_cgen_lookup_reloc (insn, operand, fixP)
+ const CGEN_INSN * insn;
+ const CGEN_OPERAND * operand;
+ fixS * fixP;
+{
+ switch (operand->type)
+ {
+ case FR30_OPERAND_LABEL9: fixP->fx_pcrel = 1; return BFD_RELOC_FR30_9_PCREL;
+ case FR30_OPERAND_LABEL12: fixP->fx_pcrel = 1; return BFD_RELOC_FR30_12_PCREL;
+ case FR30_OPERAND_DISP10: return BFD_RELOC_FR30_10_IN_8;
+ case FR30_OPERAND_DISP9: return BFD_RELOC_FR30_9_IN_8;
+ case FR30_OPERAND_DISP8: return BFD_RELOC_FR30_8_IN_8;
+ case FR30_OPERAND_UDISP6: return BFD_RELOC_FR30_6_IN_4;
+ case FR30_OPERAND_I8: return BFD_RELOC_8;
+ case FR30_OPERAND_I32: return BFD_RELOC_FR30_48;
+ case FR30_OPERAND_I20: return BFD_RELOC_FR30_20;
+ default : /* avoid -Wall warning */
+ break;
+ }
+
+ return BFD_RELOC_NONE;
+}
+
+/* See whether we need to force a relocation into the output file.
+ This is used to force out switch and PC relative relocations when
+ relaxing. */
+
+int
+fr30_force_relocation (fix)
+ fixS * fix;
+{
+ if ( fix->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fix->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ return 1;
+
+ return 0;
+}
+
+/* Write a value out to the object file, using the appropriate endianness. */
+
+void
+md_number_to_chars (buf, val, n)
+ char * buf;
+ valueT val;
+ int n;
+{
+ number_to_chars_bigendian (buf, val, n);
+}
+
+/* Turn a string in input_line_pointer into a floating point constant of type
+ type, and store the appropriate bytes in *litP. The number of LITTLENUMS
+ emitted is stored in *sizeP . An error message is returned, or NULL on OK.
+*/
+
+/* Equal to MAX_PRECISION in atof-ieee.c */
+#define MAX_LITTLENUMS 6
+
+char *
+md_atof (type, litP, sizeP)
+ char type;
+ char * litP;
+ int * sizeP;
+{
+ int i;
+ int prec;
+ LITTLENUM_TYPE words [MAX_LITTLENUMS];
+ char * t;
+ char * atof_ieee ();
+
+ switch (type)
+ {
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ prec = 4;
+ break;
+
+ /* FIXME: Some targets allow other format chars for bigger sizes here. */
+
+ default:
+ * sizeP = 0;
+ return _("Bad call to md_atof()");
+ }
+
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+ * sizeP = prec * sizeof (LITTLENUM_TYPE);
+
+ for (i = 0; i < prec; i++)
+ {
+ md_number_to_chars (litP, (valueT) words[i],
+ sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+
+ return 0;
+}
+
+/* Worker function for fr30_is_colon_insn(). */
+static char
+restore_colon (advance_i_l_p_by)
+ int advance_i_l_p_by;
+{
+ char c;
+
+ /* Restore the colon, and advance input_line_pointer to
+ the end of the new symbol. */
+ * input_line_pointer = ':';
+ input_line_pointer += advance_i_l_p_by;
+ c = * input_line_pointer;
+ * input_line_pointer = 0;
+
+ return c;
+}
+
+/* Determines if the symbol starting at START and ending in
+ a colon that was at the location pointed to by INPUT_LINE_POINTER
+ (but which has now been replaced bu a NUL) is in fact an
+ LDI:8, LDI:20, LDI:32, CALL:D. JMP:D, RET:D or Bcc:D instruction.
+ If it is, then it restores the colon, advances INPUT_LINE_POINTER
+ to the real end of the instruction/symbol, and returns the character
+ that really terminated the symbol. Otherwise it returns 0. */
+char
+fr30_is_colon_insn (start)
+ char * start;
+{
+ char * i_l_p = input_line_pointer;
+
+ /* Check to see if the symbol parsed so far is 'ldi' */
+ if ( (start[0] != 'l' && start[0] != 'L')
+ || (start[1] != 'd' && start[1] != 'D')
+ || (start[2] != 'i' && start[2] != 'I')
+ || start[3] != 0)
+ {
+ /* Nope - check to see a 'd' follows the colon. */
+ if ( (i_l_p[1] == 'd' || i_l_p[1] == 'D')
+ && (i_l_p[2] == ' ' || i_l_p[2] == '\t' || i_l_p[2] == '\n'))
+ {
+ /* Yup - it might be delay slot instruction. */
+ int i;
+ static char * delay_insns [] =
+ {
+ "call", "jmp", "ret", "bra", "bno",
+ "beq", "bne", "bc", "bnc", "bn",
+ "bp", "bv", "bnv", "blt", "bge",
+ "ble", "bgt", "bls", "bhi"
+ };
+
+ for (i = sizeof (delay_insns) / sizeof (delay_insns[0]); i--;)
+ {
+ char * insn = delay_insns[i];
+ int len = strlen (insn);
+
+ if (start [len] != 0)
+ continue;
+
+ while (len --)
+ if (tolower (start [len]) != insn [len])
+ break;
+
+ if (len == -1)
+ return restore_colon (1);
+ }
+ }
+
+ /* Nope - it is a normal label. */
+ return 0;
+ }
+
+ /* Check to see if the text following the colon is '8' */
+ if (i_l_p[1] == '8' && (i_l_p[2] == ' ' || i_l_p[2] == '\t'))
+ return restore_colon (2);
+
+ /* Check to see if the text following the colon is '20' */
+ else if (i_l_p[1] == '2' && i_l_p[2] =='0' && (i_l_p[3] == ' ' || i_l_p[3] == '\t'))
+ return restore_colon (3);
+
+ /* Check to see if the text following the colon is '32' */
+ else if (i_l_p[1] == '3' && i_l_p[2] =='2' && (i_l_p[3] == ' ' || i_l_p[3] == '\t'))
+ return restore_colon (3);
+
+ return 0;
+}
+
+boolean
+fr30_fix_adjustable (fixP)
+ fixS * fixP;
+{
+ if (fixP->fx_addsy == NULL)
+ return 1;
+
+#if 0
+ /* Prevent all adjustments to global symbols. */
+ if (S_IS_EXTERN (fixP->fx_addsy))
+ return 0;
+
+ if (S_IS_WEAK (fixP->fx_addsy))
+ return 0;
+#endif
+
+ /* We need the symbol name for the VTABLE entries */
+ if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ return 0;
+
+ return 1;
+}
diff --git a/gas/config/tc-fr30.h b/gas/config/tc-fr30.h
new file mode 100644
index 0000000000..a672d8bab1
--- /dev/null
+++ b/gas/config/tc-fr30.h
@@ -0,0 +1,81 @@
+/* tc-fr30.h -- Header file for tc-fr30.c.
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#define TC_FR30
+
+#ifndef BFD_ASSEMBLER
+/* leading space so will compile with cc */
+ #error FR30 support requires BFD_ASSEMBLER
+#endif
+
+#define LISTING_HEADER "FR30 GAS "
+
+/* The target BFD architecture. */
+#define TARGET_ARCH bfd_arch_fr30
+
+#define TARGET_FORMAT "elf32-fr30"
+
+#define TARGET_BYTES_BIG_ENDIAN 1
+
+/* call md_pcrel_from_section, not md_pcrel_from */
+long md_pcrel_from_section PARAMS ((struct fix *, segT));
+#define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from_section (FIXP, SEC)
+
+/* Permit temporary numeric labels. */
+#define LOCAL_LABELS_FB 1
+
+#define DIFF_EXPR_OK /* .-foo gets turned into PC relative relocs */
+
+/* We don't need to handle .word strangely. */
+#define WORKING_DOT_WORD
+
+#define MD_APPLY_FIX3
+#define md_apply_fix3 gas_cgen_md_apply_fix3
+
+#define obj_fix_adjustable(fixP) fr30_fix_adjustable (fixP)
+extern boolean fr30_fix_adjustable PARAMS ((struct fix *));
+
+/* When relaxing, we need to emit various relocs we otherwise wouldn't. */
+#define TC_FORCE_RELOCATION(fix) fr30_force_relocation (fix)
+extern int fr30_force_relocation PARAMS ((struct fix *));
+
+#define TC_HANDLES_FX_DONE
+
+#define tc_gen_reloc gas_cgen_tc_gen_reloc
+
+/* Call md_pcrel_from_section(), not md_pcrel_from(). */
+#define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from_section (FIXP, SEC)
+extern long md_pcrel_from_section PARAMS ((struct fix *, segT));
+
+/* For 8 vs 16 vs 32 bit branch selection. */
+#define TC_GENERIC_RELAX_TABLE md_relax_table
+extern const struct relax_type md_relax_table[];
+
+/* We need a special version of the TC_START_LABEL macro so that we
+ allow the LDI:8, LDI:20, LDI:32 and delay slot instructions to be
+ parsed as such. Note - in a HORRIBLE HACK, we make use of the
+ knowledge that this marco is only ever evaluated in one place
+ (read_a_source_file in read.c) where we can access the local
+ variable 's' - the start of the symbol that was terminated by
+ 'character'. Also we need to be able to change the contents of
+ the local variable 'c' which is passed to this macro as 'character'. */
+#define TC_START_LABEL(character, i_l_p) \
+ ((character) != ':' ? 0 : (character = fr30_is_colon_insn (s)) ? 0 : ((character = ':'), 1))
+extern char fr30_is_colon_insn PARAMS ((char *));
diff --git a/gas/config/tc-generic.c b/gas/config/tc-generic.c
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/gas/config/tc-generic.c
diff --git a/gas/config/tc-generic.h b/gas/config/tc-generic.h
new file mode 100644
index 0000000000..72df020316
--- /dev/null
+++ b/gas/config/tc-generic.h
@@ -0,0 +1,39 @@
+/* This file is tc-generic.h
+
+ Copyright (C) 1987, 91, 92, 95, 1997 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License along
+ with GAS; see the file COPYING. If not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * This file is tc-generic.h and is intended to be a template for target cpu
+ * specific header files. It is my intent that this file compile. It is also
+ * my intent that this file grow into something that can be used as both a
+ * template for porting, and a stub for testing. xoxorich.
+ */
+
+#define TC_GENERIC 1
+
+#define TARGET_BYTES_BIG_ENDIAN 0
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of tc-generic.h */
diff --git a/gas/config/tc-h8300.c b/gas/config/tc-h8300.c
new file mode 100644
index 0000000000..115ada1542
--- /dev/null
+++ b/gas/config/tc-h8300.c
@@ -0,0 +1,1595 @@
+/* tc-h8300.c -- Assemble code for the Hitachi H8/300
+ Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 1998 Free Software Foundation.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+
+/*
+ Written By Steve Chamberlain
+ sac@cygnus.com
+ */
+
+#include <stdio.h>
+#include "as.h"
+#include "subsegs.h"
+#include "bfd.h"
+#define DEFINE_TABLE
+#define h8_opcodes ops
+#include "opcode/h8300.h"
+#include <ctype.h>
+
+const char comment_chars[] =
+{';', 0};
+const char line_separator_chars[] =
+{0};
+const char line_comment_chars[] = "#";
+
+/* This table describes all the machine specific pseudo-ops the assembler
+ has to support. The fields are:
+ pseudo-op name without dot
+ function to call to execute this pseudo-op
+ Integer arg to pass to the function
+ */
+
+void cons ();
+
+int Hmode;
+int Smode;
+#define PSIZE (Hmode ? L_32 : L_16)
+#define DMODE (L_16)
+#define DSYMMODE (Hmode ? L_24 : L_16)
+int bsize = L_8; /* default branch displacement */
+
+
+void
+h8300hmode ()
+{
+ Hmode = 1;
+ Smode = 0;
+}
+
+void
+h8300smode ()
+{
+ Smode = 1;
+ Hmode = 1;
+}
+void
+sbranch (size)
+ int size;
+{
+ bsize = size;
+}
+
+static void pint ()
+{
+ cons (Hmode ? 4 : 2);
+}
+
+const pseudo_typeS md_pseudo_table[] =
+{
+
+ {"h8300h", h8300hmode, 0},
+ {"h8300s", h8300smode, 0},
+ {"sbranch", sbranch, L_8},
+ {"lbranch", sbranch, L_16},
+
+ {"int", pint, 0},
+ {"data.b", cons, 1},
+ {"data.w", cons, 2},
+ {"data.l", cons, 4},
+ {"form", listing_psize, 0},
+ {"heading", listing_title, 0},
+ {"import", s_ignore, 0},
+ {"page", listing_eject, 0},
+ {"program", s_ignore, 0},
+ {0, 0, 0}
+};
+
+const int md_reloc_size;
+
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* As in 0f12.456 */
+/* or 0d1.2345e12 */
+const char FLT_CHARS[] = "rRsSfFdDxXpP";
+
+static struct hash_control *opcode_hash_control; /* Opcode mnemonics */
+
+/*
+ This function is called once, at assembler startup time. This should
+ set up all the tables, etc that the MD part of the assembler needs
+ */
+
+
+void
+md_begin ()
+{
+ struct h8_opcode *opcode;
+ char prev_buffer[100];
+ int idx = 0;
+
+ opcode_hash_control = hash_new ();
+ prev_buffer[0] = 0;
+
+ for (opcode = h8_opcodes; opcode->name; opcode++)
+ {
+ /* Strip off any . part when inserting the opcode and only enter
+ unique codes into the hash table
+ */
+ char *src = opcode->name;
+ unsigned int len = strlen (src);
+ char *dst = malloc (len + 1);
+ char *buffer = dst;
+
+ opcode->size = 0;
+ while (*src)
+ {
+ if (*src == '.')
+ {
+ src++;
+ opcode->size = *src;
+ break;
+ }
+ *dst++ = *src++;
+ }
+ *dst++ = 0;
+ if (strcmp (buffer, prev_buffer))
+ {
+ hash_insert (opcode_hash_control, buffer, (char *) opcode);
+ strcpy (prev_buffer, buffer);
+ idx++;
+ }
+ opcode->idx = idx;
+
+
+ /* Find the number of operands */
+ opcode->noperands = 0;
+ while (opcode->args.nib[opcode->noperands] != E)
+ opcode->noperands++;
+ /* Find the length of the opcode in bytes */
+ opcode->length = 0;
+ while (opcode->data.nib[opcode->length * 2] != E)
+ opcode->length++;
+ }
+
+ linkrelax = 1;
+}
+
+
+struct h8_exp
+{
+ char *e_beg;
+ char *e_end;
+ expressionS e_exp;
+};
+int dispreg;
+int opsize; /* Set when a register size is seen */
+
+
+struct h8_op
+{
+ op_type mode;
+ unsigned reg;
+ expressionS exp;
+};
+
+/*
+ parse operands
+ WREG r0,r1,r2,r3,r4,r5,r6,r7,fp,sp
+ r0l,r0h,..r7l,r7h
+ @WREG
+ @WREG+
+ @-WREG
+ #const
+ ccr
+*/
+
+/* try and parse a reg name, returns number of chars consumed */
+int
+parse_reg (src, mode, reg, direction)
+ char *src;
+ op_type *mode;
+ unsigned int *reg;
+ int direction;
+
+{
+ char *end;
+ int len;
+
+ /* Cribbed from get_symbol_end(). */
+ if (!is_name_beginner (*src) || *src == '\001')
+ return 0;
+ end = src+1;
+ while (is_part_of_name (*end) || *end == '\001')
+ end++;
+ len = end - src;
+
+ if (len == 2 && src[0] == 's' && src[1] == 'p')
+ {
+ *mode = PSIZE | REG | direction;
+ *reg = 7;
+ return len;
+ }
+ if (len == 3 && src[0] == 'c' && src[1] == 'c' && src[2] == 'r')
+ {
+ *mode = CCR;
+ *reg = 0;
+ return len;
+ }
+ if (len == 3 && src[0] == 'e' && src[1] == 'x' && src[2] == 'r')
+ {
+ *mode = EXR;
+ *reg = 0;
+ return len;
+ }
+ if (len == 2 && src[0] == 'f' && src[1] == 'p')
+ {
+ *mode = PSIZE | REG | direction;
+ *reg = 6;
+ return len;
+ }
+ if (len == 3 && src[0] == 'e' && src[1] == 'r'
+ && src[2] >= '0' && src[2] <= '7')
+ {
+ *mode = L_32 | REG | direction;
+ *reg = src[2] - '0';
+ if (!Hmode)
+ as_warn (_("Reg not valid for H8/300"));
+ return len;
+ }
+ if (len == 2 && src[0] == 'e' && src[1] >= '0' && src[1] <= '7')
+ {
+ *mode = L_16 | REG | direction;
+ *reg = src[1] - '0' + 8;
+ if (!Hmode)
+ as_warn (_("Reg not valid for H8/300"));
+ return len;
+ }
+
+ if (src[0] == 'r')
+ {
+ if (src[1] >= '0' && src[1] <= '7')
+ {
+ if (len == 3 && src[2] == 'l')
+ {
+ *mode = L_8 | REG | direction;
+ *reg = (src[1] - '0') + 8;
+ return len;
+ }
+ if (len == 3 && src[2] == 'h')
+ {
+ *mode = L_8 | REG | direction;
+ *reg = (src[1] - '0');
+ return len;
+ }
+ if (len == 2)
+ {
+ *mode = L_16 | REG | direction;
+ *reg = (src[1] - '0');
+ return len;
+ }
+ }
+ }
+
+ return 0;
+}
+
+char *
+parse_exp (s, op)
+ char *s;
+ expressionS * op;
+{
+ char *save = input_line_pointer;
+ char *new;
+
+ input_line_pointer = s;
+ expression (op);
+ if (op->X_op == O_absent)
+ as_bad (_("missing operand"));
+ new = input_line_pointer;
+ input_line_pointer = save;
+ return new;
+}
+
+static char *
+skip_colonthing (ptr, exp, mode)
+ char *ptr;
+ expressionS *exp;
+ int *mode;
+{
+ if (*ptr == ':')
+ {
+ ptr++;
+ *mode &= ~SIZE;
+ if (*ptr == '8')
+ {
+ ptr++;
+ /* ff fill any 8 bit quantity */
+ /* exp->X_add_number -= 0x100;*/
+ *mode |= L_8;
+ }
+ else
+ {
+ if (*ptr == '2')
+ {
+ *mode |= L_24;
+ }
+ else if (*ptr == '3')
+ {
+ *mode |= L_32;
+ }
+ else if (*ptr == '1')
+ {
+ *mode |= L_16;
+ }
+ while (isdigit (*ptr))
+ ptr++;
+ }
+ }
+ return ptr;
+}
+
+/* The many forms of operand:
+
+ Rn Register direct
+ @Rn Register indirect
+ @(exp[:16], Rn) Register indirect with displacement
+ @Rn+
+ @-Rn
+ @aa:8 absolute 8 bit
+ @aa:16 absolute 16 bit
+ @aa absolute 16 bit
+
+ #xx[:size] immediate data
+ @(exp:[8], pc) pc rel
+ @@aa[:8] memory indirect
+
+ */
+
+char *
+colonmod24 (op, src)
+ struct h8_op *op;
+ char *src;
+
+{
+ int mode = 0;
+ src = skip_colonthing (src, &op->exp, &mode);
+
+ if (!mode)
+ {
+ /* Choose a default mode */
+ if (op->exp.X_add_number < -32768
+ || op->exp.X_add_number > 32767)
+ {
+ if (Hmode)
+ mode = L_24;
+ else
+ mode = L_16;
+ }
+ else if (op->exp.X_add_symbol
+ || op->exp.X_op_symbol)
+ mode = DSYMMODE;
+ else
+ mode = DMODE;
+ }
+ op->mode |= mode;
+ return src;
+
+}
+
+
+static void
+get_operand (ptr, op, dst, direction)
+ char **ptr;
+ struct h8_op *op;
+ unsigned int dst;
+ int direction;
+{
+ char *src = *ptr;
+ op_type mode;
+ unsigned int num;
+ unsigned int len;
+
+ op->mode = E;
+
+ /* Gross. Gross. ldm and stm have a format not easily handled
+ by get_operand. We deal with it explicitly here. */
+ if (src[0] == 'e' && src[1] == 'r' && isdigit(src[2])
+ && src[3] == '-' && src[4] == 'e' && src[5] == 'r' && isdigit(src[6]))
+ {
+ int low, high;
+
+ low = src[2] - '0';
+ high = src[6] - '0';
+
+ if (high < low)
+ as_bad (_("Invalid register list for ldm/stm\n"));
+
+ if (low % 2)
+ as_bad (_("Invalid register list for ldm/stm\n"));
+
+ if (high - low > 3)
+ as_bad (_("Invalid register list for ldm/stm\n"));
+
+ if (high - low != 1
+ && low % 4)
+ as_bad (_("Invalid register list for ldm/stm\n"));
+
+ /* Even sicker. We encode two registers into op->reg. One
+ for the low register to save, the other for the high
+ register to save; we also set the high bit in op->reg
+ so we know this is "very special". */
+ op->reg = 0x80000000 | (high << 8) | low;
+ op->mode = REG;
+ *ptr = src + 7;
+ return;
+ }
+
+ len = parse_reg (src, &op->mode, &op->reg, direction);
+ if (len)
+ {
+ *ptr = src + len;
+ return;
+ }
+
+ if (*src == '@')
+ {
+ src++;
+ if (*src == '@')
+ {
+ src++;
+ src = parse_exp (src, &op->exp);
+
+ src = skip_colonthing (src, &op->exp, &op->mode);
+
+ *ptr = src;
+
+ op->mode = MEMIND;
+ return;
+
+ }
+
+
+ if (*src == '-')
+ {
+ src++;
+ len = parse_reg (src, &mode, &num, direction);
+ if (len == 0)
+ {
+ /* Oops, not a reg after all, must be ordinary exp */
+ src--;
+ /* must be a symbol */
+ op->mode = ABS | PSIZE | direction;
+ *ptr = skip_colonthing (parse_exp (src, &op->exp),
+ &op->exp, &op->mode);
+
+ return;
+
+
+ }
+
+
+ if ((mode & SIZE) != PSIZE)
+ as_bad (_("Wrong size pointer register for architecture."));
+ op->mode = RDDEC;
+ op->reg = num;
+ *ptr = src + len;
+ return;
+ }
+ if (*src == '(')
+ {
+ /* Disp */
+ src++;
+
+ /* Start off assuming a 16 bit offset */
+
+
+ src = parse_exp (src, &op->exp);
+
+ src = colonmod24 (op, src);
+
+ if (*src == ')')
+ {
+ src++;
+ op->mode |= ABS | direction;
+ *ptr = src;
+ return;
+ }
+
+ if (*src != ',')
+ {
+ as_bad (_("expected @(exp, reg16)"));
+ return;
+
+ }
+ src++;
+
+ len = parse_reg (src, &mode, &op->reg, direction);
+ if (len == 0 || !(mode & REG))
+ {
+ as_bad (_("expected @(exp, reg16)"));
+ return;
+ }
+ op->mode |= DISP | direction;
+ dispreg = op->reg;
+ src += len;
+ src = skip_colonthing (src, &op->exp, &op->mode);
+
+ if (*src != ')' && '(')
+ {
+ as_bad (_("expected @(exp, reg16)"));
+ return;
+ }
+ *ptr = src + 1;
+
+ return;
+ }
+ len = parse_reg (src, &mode, &num, direction);
+
+ if (len)
+ {
+ src += len;
+ if (*src == '+')
+ {
+ src++;
+ if ((mode & SIZE) != PSIZE)
+ as_bad (_("Wrong size pointer register for architecture."));
+ op->mode = RSINC;
+ op->reg = num;
+ *ptr = src;
+ return;
+ }
+ if ((mode & SIZE) != PSIZE)
+ as_bad (_("Wrong size pointer register for architecture."));
+
+ op->mode = direction | IND | PSIZE;
+ op->reg = num;
+ *ptr = src;
+
+ return;
+ }
+ else
+ {
+ /* must be a symbol */
+
+ op->mode = ABS | direction;
+ src = parse_exp (src, &op->exp);
+
+ *ptr = colonmod24 (op, src);
+
+ return;
+ }
+ }
+
+
+ if (*src == '#')
+ {
+ src++;
+ op->mode = IMM;
+ src = parse_exp (src, &op->exp);
+ *ptr = skip_colonthing (src, &op->exp, &op->mode);
+
+ return;
+ }
+ else if (strncmp (src, "mach", 4) == 0
+ || strncmp (src, "macl", 4) == 0)
+ {
+ op->reg = src[3] == 'l';
+ op->mode = MACREG;
+ *ptr = src + 4;
+ return;
+ }
+ else
+ {
+ src = parse_exp (src, &op->exp);
+ /* Trailing ':' size ? */
+ if (*src == ':')
+ {
+ if (src[1] == '1' && src[2] == '6')
+ {
+ op->mode = PCREL | L_16;
+ src += 3;
+ }
+ else if (src[1] == '8')
+ {
+ op->mode = PCREL | L_8;
+ src += 2;
+ }
+ else
+ {
+ as_bad (_("expect :8 or :16 here"));
+ }
+ }
+ else
+ {
+ op->mode = PCREL | bsize;
+ }
+ *ptr = src;
+ }
+}
+
+
+static
+char *
+get_operands (noperands, op_end, operand)
+ unsigned int noperands;
+ char *op_end;
+ struct h8_op *operand;
+{
+ char *ptr = op_end;
+
+ switch (noperands)
+ {
+ case 0:
+ operand[0].mode = 0;
+ operand[1].mode = 0;
+ break;
+
+ case 1:
+ ptr++;
+ get_operand (&ptr, operand + 0, 0, SRC);
+ if (*ptr == ',')
+ {
+ ptr++;
+ get_operand (&ptr, operand + 1, 1, DST);
+ }
+ else
+ {
+ operand[1].mode = 0;
+ }
+
+ break;
+ case 2:
+ ptr++;
+ get_operand (&ptr, operand + 0, 0, SRC);
+ if (*ptr == ',')
+ ptr++;
+ get_operand (&ptr, operand + 1, 1, DST);
+ break;
+
+ default:
+ abort ();
+ }
+
+
+ return ptr;
+}
+
+/* Passed a pointer to a list of opcodes which use different
+ addressing modes, return the opcode which matches the opcodes
+ provided
+ */
+static
+struct h8_opcode *
+get_specific (opcode, operands, size)
+ struct h8_opcode *opcode;
+ struct h8_op *operands;
+ int size;
+{
+ struct h8_opcode *this_try = opcode;
+ int found = 0;
+
+ unsigned int this_index = opcode->idx;
+
+ /* There's only one ldm/stm and it's easier to just
+ get out quick for them. */
+ if (strcmp (opcode->name, "stm.l") == 0
+ || strcmp (opcode->name, "ldm.l") == 0)
+ return this_try;
+
+ while (this_index == opcode->idx && !found)
+ {
+ found = 1;
+
+ this_try = opcode++;
+ if (this_try->noperands == 0)
+ {
+ int this_size;
+
+ this_size = this_try->how & SN;
+ if (this_size != size && (this_size != SB || size != SN))
+ found = 0;
+ }
+ else
+ {
+ unsigned int i;
+
+ for (i = 0; i < this_try->noperands && found; i++)
+ {
+ op_type op = this_try->args.nib[i];
+ int x = operands[i].mode;
+
+ if ((op & (DISP | REG)) == (DISP | REG)
+ && ((x & (DISP | REG)) == (DISP | REG)))
+ {
+ dispreg = operands[i].reg;
+ }
+ else if (op & REG)
+ {
+ if (!(x & REG))
+ found = 0;
+
+ if (x & L_P)
+ x = (x & ~L_P) | (Hmode ? L_32 : L_16);
+ if (op & L_P)
+ op = (op & ~L_P) | (Hmode ? L_32 : L_16);
+
+ opsize = op & SIZE;
+
+ /* The size of the reg is v important */
+ if ((op & SIZE) != (x & SIZE))
+ found = 0;
+ }
+ else if ((op & ABSJMP) && (x & ABS))
+ {
+ operands[i].mode &= ~ABS;
+ operands[i].mode |= ABSJMP;
+ /* But it may not be 24 bits long */
+ if (!Hmode)
+ {
+ operands[i].mode &= ~SIZE;
+ operands[i].mode |= L_16;
+ }
+ }
+ else if ((op & (KBIT | DBIT)) && (x & IMM))
+ {
+ /* This is ok if the immediate value is sensible */
+ }
+ else if (op & PCREL)
+ {
+ /* The size of the displacement is important */
+ if ((op & SIZE) != (x & SIZE))
+ found = 0;
+ }
+ else if ((op & (DISP | IMM | ABS))
+ && (op & (DISP | IMM | ABS)) == (x & (DISP | IMM | ABS)))
+ {
+ /* Promote a L_24 to L_32 if it makes us match. */
+ if ((x & L_24) && (op & L_32))
+ {
+ x &= ~L_24;
+ x |= L_32;
+ }
+ /* Promote an L8 to L_16 if it makes us match. */
+ if (op & ABS && op & L_8 && op & DISP)
+ {
+ if (x & L_16)
+ found= 1;
+ }
+ else if ((x & SIZE) != 0
+ && ((op & SIZE) != (x & SIZE)))
+ found = 0;
+ }
+ else if ((op & MACREG) != (x & MACREG))
+ {
+ found = 0;
+ }
+ else if ((op & MODE) != (x & MODE))
+ {
+ found = 0;
+ }
+ }
+ }
+ }
+ if (found)
+ return this_try;
+ else
+ return 0;
+}
+
+static void
+check_operand (operand, width, string)
+ struct h8_op *operand;
+ unsigned int width;
+ char *string;
+{
+ if (operand->exp.X_add_symbol == 0
+ && operand->exp.X_op_symbol == 0)
+ {
+
+ /* No symbol involved, let's look at offset, it's dangerous if any of
+ the high bits are not 0 or ff's, find out by oring or anding with
+ the width and seeing if the answer is 0 or all fs*/
+
+ if ((operand->exp.X_add_number & ~width) != 0 &&
+ (operand->exp.X_add_number | width) != (~0))
+ {
+ if (width == 255
+ && (operand->exp.X_add_number & 0xff00) == 0xff00)
+ {
+ /* Just ignore this one - which happens when trying to
+ fit a 16 bit address truncated into an 8 bit address
+ of something like bset. */
+ }
+ else
+ {
+ as_warn (_("operand %s0x%lx out of range."), string,
+ (unsigned long) operand->exp.X_add_number);
+ }
+ }
+ }
+
+}
+
+/* RELAXMODE has one of 3 values:
+
+ 0 Output a "normal" reloc, no relaxing possible for this insn/reloc
+
+ 1 Output a relaxable 24bit absolute mov.w address relocation
+ (may relax into a 16bit absolute address).
+
+ 2 Output a relaxable 16/24 absolute mov.b address relocation
+ (may relax into an 8bit absolute address). */
+
+static void
+do_a_fix_imm (offset, operand, relaxmode)
+ int offset;
+ struct h8_op *operand;
+ int relaxmode;
+{
+ int idx;
+ int size;
+ int where;
+
+
+ char *t = operand->mode & IMM ? "#" : "@";
+
+ if (operand->exp.X_add_symbol == 0)
+ {
+ char *bytes = frag_now->fr_literal + offset;
+ switch (operand->mode & SIZE)
+ {
+ case L_2:
+ check_operand (operand, 0x3, t);
+ bytes[0] |= (operand->exp.X_add_number) << 4;
+ break;
+ case L_3:
+ check_operand (operand, 0x7, t);
+ bytes[0] |= (operand->exp.X_add_number) << 4;
+ break;
+ case L_8:
+ check_operand (operand, 0xff, t);
+ bytes[0] = operand->exp.X_add_number;
+ break;
+ case L_16:
+ check_operand (operand, 0xffff, t);
+ bytes[0] = operand->exp.X_add_number >> 8;
+ bytes[1] = operand->exp.X_add_number >> 0;
+ break;
+ case L_24:
+ check_operand (operand, 0xffffff, t);
+ bytes[0] = operand->exp.X_add_number >> 16;
+ bytes[1] = operand->exp.X_add_number >> 8;
+ bytes[2] = operand->exp.X_add_number >> 0;
+ break;
+
+ case L_32:
+ /* This should be done with bfd */
+ bytes[0] = operand->exp.X_add_number >> 24;
+ bytes[1] = operand->exp.X_add_number >> 16;
+ bytes[2] = operand->exp.X_add_number >> 8;
+ bytes[3] = operand->exp.X_add_number >> 0;
+ break;
+ }
+
+ }
+ else
+ {
+ switch (operand->mode & SIZE)
+ {
+
+ case L_24:
+ case L_32:
+ size = 4;
+ where = (operand->mode & SIZE) == L_24 ? -1 : 0;
+ if (relaxmode == 2)
+ idx = R_MOV24B1;
+ else if (relaxmode == 1)
+ idx = R_MOVL1;
+ else
+ idx = R_RELLONG;
+ break;
+ default:
+ as_bad(_("Can't work out size of operand.\n"));
+ case L_16:
+ size = 2;
+ where = 0;
+ if (relaxmode == 2)
+ idx = R_MOV16B1;
+ else
+ idx = R_RELWORD;
+ operand->exp.X_add_number = (short)operand->exp.X_add_number;
+ break;
+ case L_8:
+ size = 1;
+ where = 0;
+ idx = R_RELBYTE;
+ /* This used to use a cast to char, but that fails if char is an
+ unsigned type. We can't use `signed char', as that isn't valid
+ K&R C. */
+ if (operand->exp.X_add_number & 0x80)
+ operand->exp.X_add_number |= ((offsetT) -1 << 8);
+ else
+ operand->exp.X_add_number &= 0xff;
+ }
+
+ fix_new_exp (frag_now,
+ offset + where,
+ size,
+ &operand->exp,
+ 0,
+ idx);
+ }
+
+}
+
+/* Now we know what sort of opcodes it is, lets build the bytes -
+ */
+static void
+build_bytes (this_try, operand)
+ struct h8_opcode *this_try;
+ struct h8_op *operand;
+{
+ unsigned int i;
+
+ char *output = frag_more (this_try->length);
+ op_type *nibble_ptr = this_try->data.nib;
+ op_type c;
+ unsigned int nibble_count = 0;
+ int absat;
+ int immat;
+ int nib;
+ int movb = 0;
+ char asnibbles[30];
+ char *p = asnibbles;
+
+ if (!(this_try->inbase || Hmode))
+ as_warn (_("Opcode `%s' with these operand types not available in H8/300 mode"),
+ this_try->name);
+
+ while (*nibble_ptr != E)
+ {
+ int d;
+ c = *nibble_ptr++;
+
+ d = (c & (DST | SRC_IN_DST)) != 0;
+
+ if (c < 16)
+ {
+ nib = c;
+ }
+ else
+ {
+
+ if (c & (REG | IND | INC | DEC))
+ {
+ nib = operand[d].reg;
+ }
+ else if ((c & DISPREG) == (DISPREG))
+ {
+ nib = dispreg;
+ }
+ else if (c & ABS )
+ {
+ operand[d].mode = c;
+ absat = nibble_count / 2;
+ nib = 0;
+ }
+ else if (c & (IMM | PCREL | ABS | ABSJMP | DISP))
+ {
+ operand[d].mode = c;
+ immat = nibble_count / 2;
+ nib = 0;
+ }
+ else if (c & IGNORE)
+ {
+ nib = 0;
+ }
+ else if (c & DBIT)
+ {
+ switch (operand[0].exp.X_add_number)
+ {
+ case 1:
+ nib = c;
+ break;
+ case 2:
+ nib = 0x8 | c;
+ break;
+ default:
+ as_bad (_("Need #1 or #2 here"));
+ }
+ }
+ else if (c & KBIT)
+ {
+ switch (operand[0].exp.X_add_number)
+ {
+ case 1:
+ nib = 0;
+ break;
+ case 2:
+ nib = 8;
+ break;
+ case 4:
+ if (!Hmode)
+ as_warn (_("#4 not valid on H8/300."));
+ nib = 9;
+ break;
+
+ default:
+ as_bad (_("Need #1 or #2 here"));
+ break;
+ }
+ /* stop it making a fix */
+ operand[0].mode = 0;
+ }
+
+ if (c & MEMRELAX)
+ {
+ operand[d].mode |= MEMRELAX;
+ }
+
+ if (c & B31)
+ {
+ nib |= 0x8;
+ }
+
+ if (c & MACREG)
+ {
+ nib = 2 + operand[d].reg;
+ }
+ }
+ nibble_count++;
+
+ *p++ = nib;
+ }
+
+ /* Disgusting. Why, oh why didn't someone ask us for advice
+ on the assembler format. */
+ if (strcmp (this_try->name, "stm.l") == 0
+ || strcmp (this_try->name, "ldm.l") == 0)
+ {
+ int high, low;
+ high = (operand[this_try->name[0] == 'l' ? 1 : 0].reg >> 8) & 0xf;
+ low = operand[this_try->name[0] == 'l' ? 1 : 0].reg & 0xf;
+
+ asnibbles[2] = high - low;
+ asnibbles[7] = (this_try->name[0] == 'l') ? high : low;
+ }
+
+ for (i = 0; i < this_try->length; i++)
+ {
+ output[i] = (asnibbles[i * 2] << 4) | asnibbles[i * 2 + 1];
+ }
+
+ /* Note if this is a movb instruction -- there's a special relaxation
+ which only applies to them. */
+ if (strcmp (this_try->name, "mov.b") == 0)
+ movb = 1;
+
+ /* output any fixes */
+ for (i = 0; i < 2; i++)
+ {
+ int x = operand[i].mode;
+
+ if (x & (IMM | DISP))
+ {
+ do_a_fix_imm (output - frag_now->fr_literal + immat,
+ operand + i, x & MEMRELAX != 0);
+ }
+ else if (x & ABS)
+ {
+ do_a_fix_imm (output - frag_now->fr_literal + absat,
+ operand + i, x & MEMRELAX ? movb + 1 : 0);
+ }
+ else if (x & PCREL)
+ {
+ int size16 = x & L_16;
+ int where = size16 ? 2 : 1;
+ int size = size16 ? 2 : 1;
+ int type = size16 ? R_PCRWORD : R_PCRBYTE;
+
+ check_operand (operand + i, size16 ? 0x7fff : 0x7f, "@");
+
+ if (operand[i].exp.X_add_number & 1)
+ {
+ as_warn (_("branch operand has odd offset (%lx)\n"),
+ (unsigned long) operand->exp.X_add_number);
+ }
+
+ operand[i].exp.X_add_number -= 1;
+ /* This used to use a cast to char, but that fails if char is an
+ unsigned type. We can't use `signed char', as that isn't valid
+ K&R C. */
+ if (operand[i].exp.X_add_number & 0x80)
+ operand[i].exp.X_add_number |= ((offsetT) -1 << 8);
+ else
+ operand[i].exp.X_add_number &= 0xff;
+
+ fix_new_exp (frag_now,
+ output - frag_now->fr_literal + where,
+ size,
+ &operand[i].exp,
+ 1,
+ type);
+ }
+ else if (x & MEMIND)
+ {
+
+ check_operand (operand + i, 0xff, "@@");
+ fix_new_exp (frag_now,
+ output - frag_now->fr_literal + 1,
+ 1,
+ &operand[i].exp,
+ 0,
+ R_MEM_INDIRECT);
+ }
+ else if (x & ABSJMP)
+ {
+ /* This jmp may be a jump or a branch */
+
+ check_operand (operand + i, Hmode ? 0xffffff : 0xffff, "@");
+ if (operand[i].exp.X_add_number & 1)
+ {
+ as_warn (_("branch operand has odd offset (%lx)\n"),
+ (unsigned long) operand->exp.X_add_number);
+ }
+ if (!Hmode)
+ operand[i].exp.X_add_number = (short) operand[i].exp.X_add_number;
+ fix_new_exp (frag_now,
+ output - frag_now->fr_literal,
+ 4,
+ &operand[i].exp,
+ 0,
+ R_JMPL1);
+ }
+ }
+
+}
+
+/*
+ try and give an intelligent error message for common and simple to
+ detect errors
+ */
+
+static void
+clever_message (opcode, operand)
+ struct h8_opcode *opcode;
+ struct h8_op *operand;
+{
+ /* Find out if there was more than one possible opccode */
+
+ if ((opcode + 1)->idx != opcode->idx)
+ {
+ unsigned int argn;
+
+ /* Only one opcode of this flavour, try and guess which operand
+ didn't match */
+ for (argn = 0; argn < opcode->noperands; argn++)
+ {
+ switch (opcode->args.nib[argn])
+ {
+ case RD16:
+ if (operand[argn].mode != RD16)
+ {
+ as_bad (_("destination operand must be 16 bit register"));
+ return;
+
+ }
+ break;
+
+ case RS8:
+
+ if (operand[argn].mode != RS8)
+ {
+ as_bad (_("source operand must be 8 bit register"));
+ return;
+ }
+ break;
+
+ case ABS16DST:
+ if (operand[argn].mode != ABS16DST)
+ {
+ as_bad (_("destination operand must be 16bit absolute address"));
+ return;
+ }
+ break;
+ case RD8:
+ if (operand[argn].mode != RD8)
+ {
+ as_bad (_("destination operand must be 8 bit register"));
+ return;
+ }
+ break;
+
+
+ case ABS16SRC:
+ if (operand[argn].mode != ABS16SRC)
+ {
+ as_bad (_("source operand must be 16bit absolute address"));
+ return;
+ }
+ break;
+
+ }
+ }
+ }
+ as_bad (_("invalid operands"));
+}
+
+/* This is the guts of the machine-dependent assembler. STR points to a
+ machine dependent instruction. This funciton is supposed to emit
+ the frags/bytes it assembles to.
+ */
+
+
+
+void
+md_assemble (str)
+ char *str;
+{
+ char *op_start;
+ char *op_end;
+ struct h8_op operand[2];
+ struct h8_opcode *opcode;
+ struct h8_opcode *prev_opcode;
+
+ char *dot = 0;
+ char c;
+ int size;
+
+ /* Drop leading whitespace */
+ while (*str == ' ')
+ str++;
+
+ /* find the op code end */
+ for (op_start = op_end = str;
+ *op_end != 0 && *op_end != ' ';
+ op_end++)
+ {
+ if (*op_end == '.')
+ {
+ dot = op_end + 1;
+ *op_end = 0;
+ op_end += 2;
+ break;
+ }
+ }
+
+ ;
+
+ if (op_end == op_start)
+ {
+ as_bad (_("can't find opcode "));
+ }
+ c = *op_end;
+
+ *op_end = 0;
+
+ opcode = (struct h8_opcode *) hash_find (opcode_hash_control,
+ op_start);
+
+ if (opcode == NULL)
+ {
+ as_bad (_("unknown opcode"));
+ return;
+ }
+
+ /* We use to set input_line_pointer to the result of get_operands,
+ but that is wrong. Our caller assumes we don't change it. */
+
+ (void) get_operands (opcode->noperands, op_end, operand);
+ *op_end = c;
+ prev_opcode = opcode;
+
+ size = SN;
+ if (dot)
+ {
+ switch (*dot)
+ {
+ case 'b':
+ size = SB;
+ break;
+
+ case 'w':
+ size = SW;
+ break;
+
+ case 'l':
+ size = SL;
+ break;
+ }
+ }
+ opcode = get_specific (opcode, operand, size);
+
+ if (opcode == 0)
+ {
+ /* Couldn't find an opcode which matched the operands */
+ char *where = frag_more (2);
+
+ where[0] = 0x0;
+ where[1] = 0x0;
+ clever_message (prev_opcode, operand);
+
+ return;
+ }
+ if (opcode->size && dot)
+ {
+ if (opcode->size != *dot)
+ {
+ as_warn (_("mismatch between opcode size and operand size"));
+ }
+ }
+
+ build_bytes (opcode, operand);
+
+}
+
+void
+tc_crawl_symbol_chain (headers)
+ object_headers * headers;
+{
+ printf (_("call to tc_crawl_symbol_chain \n"));
+}
+
+symbolS *
+md_undefined_symbol (name)
+ char *name;
+{
+ return 0;
+}
+
+void
+tc_headers_hook (headers)
+ object_headers * headers;
+{
+ printf (_("call to tc_headers_hook \n"));
+}
+
+/* Various routines to kill one day */
+/* Equal to MAX_PRECISION in atof-ieee.c */
+#define MAX_LITTLENUMS 6
+
+/* Turn a string in input_line_pointer into a floating point constant of type
+ type, and store the appropriate bytes in *litP. The number of LITTLENUMS
+ emitted is stored in *sizeP . An error message is returned, or NULL on OK.
+ */
+char *
+md_atof (type, litP, sizeP)
+ char type;
+ char *litP;
+ int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ char *t;
+ char *atof_ieee ();
+
+ switch (type)
+ {
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ prec = 4;
+ break;
+
+ case 'x':
+ case 'X':
+ prec = 6;
+ break;
+
+ case 'p':
+ case 'P':
+ prec = 6;
+ break;
+
+ default:
+ *sizeP = 0;
+ return _("Bad call to MD_ATOF()");
+ }
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+
+ *sizeP = prec * sizeof (LITTLENUM_TYPE);
+ for (wordP = words; prec--;)
+ {
+ md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+ return 0;
+}
+
+CONST char *md_shortopts = "";
+struct option md_longopts[] = {
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof(md_longopts);
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ return 0;
+}
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+}
+
+void
+tc_aout_fix_to_chars ()
+{
+ printf (_("call to tc_aout_fix_to_chars \n"));
+ abort ();
+}
+
+void
+md_convert_frag (headers, seg, fragP)
+ object_headers *headers;
+ segT seg;
+ fragS *fragP;
+{
+ printf (_("call to md_convert_frag \n"));
+ abort ();
+}
+
+valueT
+md_section_align (seg, size)
+ segT seg;
+ valueT size;
+{
+ return ((size + (1 << section_alignment[(int) seg]) - 1) & (-1 << section_alignment[(int) seg]));
+
+}
+
+void
+md_apply_fix (fixP, val)
+ fixS *fixP;
+ long val;
+{
+ char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
+
+ switch (fixP->fx_size)
+ {
+ case 1:
+ *buf++ = val;
+ break;
+ case 2:
+ *buf++ = (val >> 8);
+ *buf++ = val;
+ break;
+ case 4:
+ *buf++ = (val >> 24);
+ *buf++ = (val >> 16);
+ *buf++ = (val >> 8);
+ *buf++ = val;
+ break;
+ default:
+ abort ();
+ }
+}
+
+int
+md_estimate_size_before_relax (fragP, segment_type)
+ register fragS *fragP;
+ register segT segment_type;
+{
+ printf (_("call tomd_estimate_size_before_relax \n"));
+ abort ();
+}
+
+/* Put number into target byte order */
+
+void
+md_number_to_chars (ptr, use, nbytes)
+ char *ptr;
+ valueT use;
+ int nbytes;
+{
+ number_to_chars_bigendian (ptr, use, nbytes);
+}
+long
+md_pcrel_from (fixP)
+ fixS *fixP;
+{
+ abort ();
+}
+
+
+void
+tc_reloc_mangle (fix_ptr, intr, base)
+ fixS *fix_ptr;
+ struct internal_reloc *intr;
+ bfd_vma base;
+
+{
+ symbolS *symbol_ptr;
+
+ symbol_ptr = fix_ptr->fx_addsy;
+
+ /* If this relocation is attached to a symbol then it's ok
+ to output it */
+ if (fix_ptr->fx_r_type == TC_CONS_RELOC)
+ {
+ /* cons likes to create reloc32's whatever the size of the reloc..
+ */
+ switch (fix_ptr->fx_size)
+ {
+ case 4:
+ intr->r_type = R_RELLONG;
+ break;
+ case 2:
+ intr->r_type = R_RELWORD;
+ break;
+ case 1:
+ intr->r_type = R_RELBYTE;
+ break;
+ default:
+ abort ();
+
+ }
+
+ }
+ else
+ {
+ intr->r_type = fix_ptr->fx_r_type;
+ }
+
+ intr->r_vaddr = fix_ptr->fx_frag->fr_address + fix_ptr->fx_where + base;
+ intr->r_offset = fix_ptr->fx_offset;
+
+ if (symbol_ptr)
+ {
+ if (symbol_ptr->sy_number != -1)
+ intr->r_symndx = symbol_ptr->sy_number;
+ else
+ {
+ symbolS *segsym;
+
+ /* This case arises when a reference is made to `.'. */
+ segsym = seg_info (S_GET_SEGMENT (symbol_ptr))->dot;
+ if (segsym == NULL)
+ intr->r_symndx = -1;
+ else
+ {
+ intr->r_symndx = segsym->sy_number;
+ intr->r_offset += S_GET_VALUE (symbol_ptr);
+ }
+ }
+ }
+ else
+ intr->r_symndx = -1;
+
+
+}
+
+/* end of tc-h8300.c */
diff --git a/gas/config/tc-h8300.h b/gas/config/tc-h8300.h
new file mode 100644
index 0000000000..2a2a7040f3
--- /dev/null
+++ b/gas/config/tc-h8300.h
@@ -0,0 +1,58 @@
+/* This file is tc-h8300.h
+ Copyright (C) 1987-1992, 93, 94, 95, 96, 97, 1998
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+
+#define TC_H8300
+
+#define TARGET_BYTES_BIG_ENDIAN 1
+
+#if ANSI_PROTOTYPES
+struct internal_reloc;
+#endif
+
+#define WORKING_DOT_WORD
+
+/* This macro translates between an internal fix and an coff reloc type */
+#define TC_COFF_FIX2RTYPE(fixP) abort();
+
+#define BFD_ARCH bfd_arch_h8300
+#define COFF_MAGIC ( Smode ? 0x8302 : Hmode ? 0x8301 : 0x8300)
+#define TC_COUNT_RELOC(x) (1)
+#define IGNORE_NONSTANDARD_ESCAPES
+
+#define tc_coff_symbol_emit_hook(a) ; /* not used */
+#define TC_RELOC_MANGLE(s,a,b,c) tc_reloc_mangle(a,b,c)
+extern void tc_reloc_mangle
+ PARAMS ((struct fix *, struct internal_reloc *, bfd_vma));
+
+#define TC_CONS_RELOC (Hmode ? R_RELLONG: R_RELWORD)
+
+#define DO_NOT_STRIP 0
+#define LISTING_HEADER "Hitachi H8/300 GAS "
+#define NEED_FX_R_TYPE 1
+#define RELOC_32 1234
+
+extern int Hmode;
+extern int Smode;
+
+#define md_operand(x)
+
+/* end of tc-h8300.h */
diff --git a/gas/config/tc-h8500.c b/gas/config/tc-h8500.c
new file mode 100644
index 0000000000..9dec3e2e6a
--- /dev/null
+++ b/gas/config/tc-h8500.c
@@ -0,0 +1,1633 @@
+/* tc-h8500.c -- Assemble code for the Hitachi H8/500
+ Copyright (C) 1993, 94, 95, 1998 Free Software Foundation.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/*
+ Written By Steve Chamberlain
+ sac@cygnus.com
+ */
+
+#include <stdio.h>
+#include "as.h"
+#include "bfd.h"
+#include "subsegs.h"
+#define DEFINE_TABLE
+#define ASSEMBLER_TABLE
+#include "opcodes/h8500-opc.h"
+#include <ctype.h>
+
+const char comment_chars[] = "!";
+const char line_separator_chars[] = ";";
+const char line_comment_chars[] = "!#";
+
+/* This table describes all the machine specific pseudo-ops the assembler
+ has to support. The fields are:
+ pseudo-op name without dot
+ function to call to execute this pseudo-op
+ Integer arg to pass to the function
+ */
+
+void cons ();
+
+const pseudo_typeS md_pseudo_table[] =
+{
+ {"int", cons, 2},
+ {"data.b", cons, 1},
+ {"data.w", cons, 2},
+ {"data.l", cons, 4},
+ {"form", listing_psize, 0},
+ {"heading", listing_title, 0},
+ {"import", s_ignore, 0},
+ {"page", listing_eject, 0},
+ {"program", s_ignore, 0},
+ {0, 0, 0}
+};
+
+const int md_reloc_size;
+
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* As in 0f12.456 */
+/* or 0d1.2345e12 */
+const char FLT_CHARS[] = "rRsSfFdDxXpP";
+
+#define C(a,b) ENCODE_RELAX(a,b)
+#define ENCODE_RELAX(what,length) (((what) << 2) + (length))
+
+#define GET_WHAT(x) ((x>>2))
+
+#define BYTE_DISP 1
+#define WORD_DISP 2
+#define UNDEF_BYTE_DISP 0
+#define UNDEF_WORD_DISP 3
+
+#define BRANCH 1
+#define SCB_F 2
+#define SCB_TST 3
+#define END 4
+
+#define BYTE_F 127
+#define BYTE_B -126
+#define WORD_F 32767
+#define WORD_B 32768
+
+relax_typeS md_relax_table[C (END, 0)];
+
+static struct hash_control *opcode_hash_control; /* Opcode mnemonics */
+
+/*
+ This function is called once, at assembler startup time. This should
+ set up all the tables, etc that the MD part of the assembler needs
+ */
+
+void
+md_begin ()
+{
+ h8500_opcode_info *opcode;
+ char prev_buffer[100];
+ int idx = 0;
+ register relax_typeS *table;
+
+ opcode_hash_control = hash_new ();
+ prev_buffer[0] = 0;
+
+ /* Insert unique names into hash table */
+ for (opcode = h8500_table; opcode->name; opcode++)
+ {
+ if (idx != opcode->idx)
+ {
+ hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
+ idx++;
+ }
+ }
+
+ /* Initialize the relax table. We use a local variable to avoid
+ warnings about modifying a supposedly const data structure. */
+ table = (relax_typeS *) md_relax_table;
+ table[C (BRANCH, BYTE_DISP)].rlx_forward = BYTE_F;
+ table[C (BRANCH, BYTE_DISP)].rlx_backward = BYTE_B;
+ table[C (BRANCH, BYTE_DISP)].rlx_length = 2;
+ table[C (BRANCH, BYTE_DISP)].rlx_more = C (BRANCH, WORD_DISP);
+
+ table[C (BRANCH, WORD_DISP)].rlx_forward = WORD_F;
+ table[C (BRANCH, WORD_DISP)].rlx_backward = WORD_B;
+ table[C (BRANCH, WORD_DISP)].rlx_length = 3;
+ table[C (BRANCH, WORD_DISP)].rlx_more = 0;
+
+ table[C (SCB_F, BYTE_DISP)].rlx_forward = BYTE_F;
+ table[C (SCB_F, BYTE_DISP)].rlx_backward = BYTE_B;
+ table[C (SCB_F, BYTE_DISP)].rlx_length = 3;
+ table[C (SCB_F, BYTE_DISP)].rlx_more = C (SCB_F, WORD_DISP);
+
+ table[C (SCB_F, WORD_DISP)].rlx_forward = WORD_F;
+ table[C (SCB_F, WORD_DISP)].rlx_backward = WORD_B;
+ table[C (SCB_F, WORD_DISP)].rlx_length = 8;
+ table[C (SCB_F, WORD_DISP)].rlx_more = 0;
+
+ table[C (SCB_TST, BYTE_DISP)].rlx_forward = BYTE_F;
+ table[C (SCB_TST, BYTE_DISP)].rlx_backward = BYTE_B;
+ table[C (SCB_TST, BYTE_DISP)].rlx_length = 3;
+ table[C (SCB_TST, BYTE_DISP)].rlx_more = C (SCB_TST, WORD_DISP);
+
+ table[C (SCB_TST, WORD_DISP)].rlx_forward = WORD_F;
+ table[C (SCB_TST, WORD_DISP)].rlx_backward = WORD_B;
+ table[C (SCB_TST, WORD_DISP)].rlx_length = 10;
+ table[C (SCB_TST, WORD_DISP)].rlx_more = 0;
+
+}
+
+static int rn; /* register number used by RN */
+static int rs; /* register number used by RS */
+static int rd; /* register number used by RD */
+static int crb; /* byte size cr */
+static int crw; /* word sized cr */
+static int cr; /* unknown size cr */
+
+static expressionS displacement;/* displacement expression */
+static int displacement_size; /* and size if given */
+
+static int immediate_inpage;
+static expressionS immediate; /* immediate expression */
+static int immediate_size; /* and size if given */
+
+static expressionS absolute; /* absolute expression */
+static int absolute_size; /* and size if given */
+
+typedef struct
+{
+ int type;
+ int reg;
+ expressionS exp;
+ int page;
+}
+
+h8500_operand_info;
+
+/* try and parse a reg name, returns number of chars consumed */
+static int
+parse_reg (src, mode, reg)
+ char *src;
+ int *mode;
+ int *reg;
+{
+ char *end;
+ int len;
+
+ /* Cribbed from get_symbol_end(). */
+ if (!is_name_beginner (*src) || *src == '\001')
+ return 0;
+ end = src+1;
+ while (is_part_of_name (*end) || *end == '\001')
+ end++;
+ len = end - src;
+
+ if (len == 2 && src[0] == 'r')
+ {
+ if (src[1] >= '0' && src[1] <= '7')
+ {
+ *mode = RN;
+ *reg = (src[1] - '0');
+ return len;
+ }
+ }
+ if (len == 2 && src[0] == 's' && src[1] == 'p')
+ {
+ *mode = RN;
+ *reg = 7;
+ return len;
+ }
+ if (len == 3 && src[0] == 'c' && src[1] == 'c' && src[2] == 'r')
+ {
+ *mode = CRB;
+ *reg = 1;
+ return len;
+ }
+ if (len == 2 && src[0] == 's' && src[1] == 'r')
+ {
+ *mode = CRW;
+ *reg = 0;
+ return len;
+ }
+ if (len == 2 && src[0] == 'b' && src[1] == 'r')
+ {
+ *mode = CRB;
+ *reg = 3;
+ return len;
+ }
+ if (len == 2 && src[0] == 'e' && src[1] == 'p')
+ {
+ *mode = CRB;
+ *reg = 4;
+ return len;
+ }
+ if (len == 2 && src[0] == 'd' && src[1] == 'p')
+ {
+ *mode = CRB;
+ *reg = 5;
+ return len;
+ }
+ if (len == 2 && src[0] == 't' && src[1] == 'p')
+ {
+ *mode = CRB;
+ *reg = 7;
+ return len;
+ }
+ if (len == 2 && src[0] == 'f' && src[1] == 'p')
+ {
+ *mode = RN;
+ *reg = 6;
+ return len;
+ }
+ return 0;
+}
+
+static
+char *
+parse_exp (s, op, page)
+ char *s;
+ expressionS *op;
+ int *page;
+{
+ char *save;
+ char *new;
+
+ save = input_line_pointer;
+
+ *page = 0;
+ if (s[0] == '%')
+ {
+ if (s[1] == 'p' && s[2] == 'a' && s[3] == 'g' && s[4] == 'e')
+ {
+ s += 5;
+ *page = 'p';
+ }
+ if (s[1] == 'h' && s[2] == 'i' && s[3] == '1' && s[4] == '6')
+ {
+ s += 5;
+ *page = 'h';
+ }
+ else if (s[1] == 'o' && s[2] == 'f' && s[3] == 'f')
+ {
+ s += 4;
+ *page = 'o';
+ }
+ }
+
+ input_line_pointer = s;
+
+ expression (op);
+ if (op->X_op == O_absent)
+ as_bad (_("missing operand"));
+ new = input_line_pointer;
+ input_line_pointer = save;
+ return new;
+}
+
+typedef enum
+ {
+ exp_signed, exp_unsigned, exp_sandu
+ } sign_type;
+
+
+static char *
+skip_colonthing (sign, ptr, exp, def, size8, size16, size24)
+ sign_type sign;
+ char *ptr;
+ h8500_operand_info *exp;
+ int def;
+ int size8;
+ int size16;
+ int size24;
+{
+ ptr = parse_exp (ptr, &exp->exp, &exp->page);
+ if (*ptr == ':')
+ {
+ ptr++;
+ if (*ptr == '8')
+ {
+ ptr++;
+ exp->type = size8;
+ }
+ else if (ptr[0] == '1' & ptr[1] == '6')
+ {
+ ptr += 2;
+ exp->type = size16;
+ }
+ else if (ptr[0] == '2' & ptr[1] == '4')
+ {
+ if (!size24)
+ {
+ as_bad (_(":24 not valid for this opcode"));
+ }
+ ptr += 2;
+ exp->type = size24;
+ }
+ else
+ {
+ as_bad (_("expect :8,:16 or :24"));
+ exp->type = size16;
+ }
+ }
+ else
+ {
+ if (exp->page == 'p')
+ {
+ exp->type = IMM8;
+ }
+ else if (exp->page == 'h')
+ {
+ exp->type = IMM16;
+ }
+ else
+ {
+ /* Let's work out the size from the context */
+ int n = exp->exp.X_add_number;
+ if (size8
+ && exp->exp.X_op == O_constant
+ && ((sign == exp_signed && (n >= -128 && n <= 127))
+ || (sign == exp_unsigned && (n >= 0 && (n <= 255)))
+ || (sign == exp_sandu && (n >= -128 && (n <= 255)))))
+ {
+ exp->type = size8;
+ }
+ else
+ {
+ exp->type = def;
+ }
+ }
+ }
+ return ptr;
+}
+
+static int
+parse_reglist (src, op)
+ char *src;
+ h8500_operand_info *op;
+{
+ int mode;
+ int rn;
+ int mask = 0;
+ int rm;
+ int idx = 1; /* skip ( */
+
+ while (src[idx] && src[idx] != ')')
+ {
+ int done = parse_reg (src + idx, &mode, &rn);
+
+ if (done)
+ {
+ idx += done;
+ mask |= 1 << rn;
+ }
+ else
+ {
+ as_bad (_("syntax error in reg list"));
+ return 0;
+ }
+ if (src[idx] == '-')
+ {
+ idx++;
+ done = parse_reg (src + idx, &mode, &rm);
+ if (done)
+ {
+ idx += done;
+ while (rn <= rm)
+ {
+ mask |= 1 << rn;
+ rn++;
+ }
+ }
+ else
+ {
+ as_bad (_("missing final register in range"));
+ }
+ }
+ if (src[idx] == ',')
+ idx++;
+ }
+ idx++;
+ op->exp.X_add_symbol = 0;
+ op->exp.X_op_symbol = 0;
+ op->exp.X_add_number = mask;
+ op->exp.X_op = O_constant;
+ op->exp.X_unsigned = 1;
+ op->type = IMM8;
+ return idx;
+
+}
+
+/* The many forms of operand:
+
+ Rn Register direct
+ @Rn Register indirect
+ @(disp[:size], Rn) Register indirect with displacement
+ @Rn+
+ @-Rn
+ @aa[:size] absolute
+ #xx[:size] immediate data
+
+ */
+
+static void
+get_operand (ptr, op, ispage)
+ char **ptr;
+ h8500_operand_info *op;
+ char ispage;
+{
+ char *src = *ptr;
+ int mode;
+ unsigned int num;
+ unsigned int len;
+ op->page = 0;
+ if (src[0] == '(' && src[1] == 'r')
+ {
+ /* This is a register list */
+ *ptr = src + parse_reglist (src, op);
+ return;
+ }
+
+ len = parse_reg (src, &op->type, &op->reg);
+
+ if (len)
+ {
+ *ptr = src + len;
+ return;
+ }
+
+ if (*src == '@')
+ {
+ src++;
+ if (*src == '-')
+ {
+ src++;
+ len = parse_reg (src, &mode, &num);
+ if (len == 0)
+ {
+ /* Oops, not a reg after all, must be ordinary exp */
+ src--;
+ /* must be a symbol */
+ *ptr = skip_colonthing (exp_unsigned, src,
+ op, ABS16, ABS8, ABS16, ABS24);
+ return;
+ }
+
+ op->type = RNDEC;
+ op->reg = num;
+ *ptr = src + len;
+ return;
+ }
+ if (*src == '(')
+ {
+ /* Disp */
+ src++;
+
+ src = skip_colonthing (exp_signed, src,
+ op, RNIND_D16, RNIND_D8, RNIND_D16, 0);
+
+ if (*src != ',')
+ {
+ as_bad (_("expected @(exp, Rn)"));
+ return;
+ }
+ src++;
+ len = parse_reg (src, &mode, &op->reg);
+ if (len == 0 || mode != RN)
+ {
+ as_bad (_("expected @(exp, Rn)"));
+ return;
+ }
+ src += len;
+ if (*src != ')')
+ {
+ as_bad (_("expected @(exp, Rn)"));
+ return;
+ }
+ *ptr = src + 1;
+ return;
+ }
+ len = parse_reg (src, &mode, &num);
+
+ if (len)
+ {
+ src += len;
+ if (*src == '+')
+ {
+ src++;
+ if (mode != RN)
+ {
+ as_bad (_("@Rn+ needs word register"));
+ return;
+ }
+ op->type = RNINC;
+ op->reg = num;
+ *ptr = src;
+ return;
+ }
+ if (mode != RN)
+ {
+ as_bad (_("@Rn needs word register"));
+ return;
+ }
+ op->type = RNIND;
+ op->reg = num;
+ *ptr = src;
+ return;
+ }
+ else
+ {
+ /* must be a symbol */
+ *ptr =
+ skip_colonthing (exp_unsigned, src, op,
+ ispage ? ABS24 : ABS16, ABS8, ABS16, ABS24);
+ return;
+ }
+ }
+
+ if (*src == '#')
+ {
+ src++;
+ *ptr = skip_colonthing (exp_sandu, src, op, IMM16, IMM8, IMM16, ABS24);
+ return;
+ }
+ else
+ {
+ *ptr = skip_colonthing (exp_signed, src, op,
+ ispage ? ABS24 : PCREL8, PCREL8, PCREL16, ABS24);
+ }
+}
+
+static
+char *
+get_operands (info, args, operand)
+ h8500_opcode_info *info;
+ char *args;
+ h8500_operand_info *operand;
+
+{
+ char *ptr = args;
+
+ switch (info->nargs)
+ {
+ case 0:
+ operand[0].type = 0;
+ operand[1].type = 0;
+ break;
+
+ case 1:
+ ptr++;
+ get_operand (&ptr, operand + 0, info->name[0] == 'p');
+ operand[1].type = 0;
+ break;
+
+ case 2:
+ ptr++;
+ get_operand (&ptr, operand + 0, 0);
+ if (*ptr == ',')
+ ptr++;
+ get_operand (&ptr, operand + 1, 0);
+ break;
+
+ default:
+ abort ();
+ }
+
+ return ptr;
+}
+
+/* Passed a pointer to a list of opcodes which use different
+ addressing modes, return the opcode which matches the opcodes
+ provided
+ */
+
+int pcrel8; /* Set when we've seen a pcrel operand */
+
+static
+h8500_opcode_info *
+get_specific (opcode, operands)
+ h8500_opcode_info *opcode;
+ h8500_operand_info *operands;
+{
+ h8500_opcode_info *this_try = opcode;
+ int found = 0;
+ unsigned int noperands = opcode->nargs;
+
+ unsigned int this_index = opcode->idx;
+
+ while (this_index == opcode->idx && !found)
+ {
+ unsigned int i;
+
+ this_try = opcode++;
+
+ /* look at both operands needed by the opcodes and provided by
+ the user*/
+ for (i = 0; i < noperands; i++)
+ {
+ h8500_operand_info *user = operands + i;
+
+ switch (this_try->arg_type[i])
+ {
+ case FPIND_D8:
+ /* Opcode needs (disp:8,fp) */
+ if (user->type == RNIND_D8 && user->reg == 6)
+ {
+ displacement = user->exp;
+ continue;
+ }
+ break;
+ case RDIND_D16:
+ if (user->type == RNIND_D16)
+ {
+ displacement = user->exp;
+ rd = user->reg;
+ continue;
+ }
+ break;
+ case RDIND_D8:
+ if (user->type == RNIND_D8)
+ {
+ displacement = user->exp;
+ rd = user->reg;
+ continue;
+ }
+ break;
+ case RNIND_D16:
+ case RNIND_D8:
+ if (user->type == this_try->arg_type[i])
+ {
+ displacement = user->exp;
+ rn = user->reg;
+ continue;
+ }
+ break;
+
+ case SPDEC:
+ if (user->type == RNDEC && user->reg == 7)
+ {
+ continue;
+ }
+ break;
+ case SPINC:
+ if (user->type == RNINC && user->reg == 7)
+ {
+ continue;
+ }
+ break;
+ case ABS16:
+ if (user->type == ABS16)
+ {
+ absolute = user->exp;
+ continue;
+ }
+ break;
+ case ABS8:
+ if (user->type == ABS8)
+ {
+ absolute = user->exp;
+ continue;
+ }
+ break;
+ case ABS24:
+ if (user->type == ABS24)
+ {
+ absolute = user->exp;
+ continue;
+ }
+ break;
+
+ case CRB:
+ if ((user->type == CRB || user->type == CR) && user->reg != 0)
+ {
+ crb = user->reg;
+ continue;
+ }
+ break;
+ case CRW:
+ if ((user->type == CRW || user->type == CR) && user->reg == 0)
+ {
+ crw = user->reg;
+ continue;
+ }
+ break;
+ case DISP16:
+ if (user->type == DISP16)
+ {
+ displacement = user->exp;
+ continue;
+ }
+ break;
+ case DISP8:
+ if (user->type == DISP8)
+ {
+ displacement = user->exp;
+ continue;
+ }
+ break;
+ case FP:
+ if (user->type == RN && user->reg == 6)
+ {
+ continue;
+ }
+ break;
+ case PCREL16:
+ if (user->type == PCREL16)
+ {
+ displacement = user->exp;
+ continue;
+ }
+ break;
+ case PCREL8:
+ if (user->type == PCREL8)
+ {
+ displacement = user->exp;
+ pcrel8 = 1;
+ continue;
+ }
+ break;
+
+ case IMM16:
+ if (user->type == IMM16
+ || user->type == IMM8)
+ {
+ immediate_inpage = user->page;
+ immediate = user->exp;
+ continue;
+ }
+ break;
+ case RLIST:
+ case IMM8:
+ if (user->type == IMM8)
+ {
+ immediate_inpage = user->page;
+ immediate = user->exp;
+ continue;
+ }
+ break;
+ case IMM4:
+ if (user->type == IMM8)
+ {
+ immediate_inpage = user->page;
+ immediate = user->exp;
+ continue;
+ }
+ break;
+ case QIM:
+ if (user->type == IMM8
+ && user->exp.X_op == O_constant
+ &&
+ (user->exp.X_add_number == -2
+ || user->exp.X_add_number == -1
+ || user->exp.X_add_number == 1
+ || user->exp.X_add_number == 2))
+ {
+ immediate_inpage = user->page;
+ immediate = user->exp;
+ continue;
+ }
+ break;
+ case RD:
+ if (user->type == RN)
+ {
+ rd = user->reg;
+ continue;
+ }
+ break;
+ case RS:
+ if (user->type == RN)
+ {
+ rs = user->reg;
+ continue;
+ }
+ break;
+ case RDIND:
+ if (user->type == RNIND)
+ {
+ rd = user->reg;
+ continue;
+
+ }
+ break;
+ case RNINC:
+ case RNIND:
+ case RNDEC:
+ case RN:
+
+ if (user->type == this_try->arg_type[i])
+ {
+ rn = user->reg;
+ continue;
+ }
+ break;
+ case SP:
+ if (user->type == RN && user->reg == 7)
+ {
+ continue;
+ }
+ break;
+ default:
+ printf (_("unhandled %d\n"), this_try->arg_type[i]);
+ break;
+ }
+
+ /* If we get here this didn't work out */
+ goto fail;
+ }
+ found = 1;
+ fail:;
+
+ }
+
+ if (found)
+ return this_try;
+ else
+ return 0;
+}
+
+int
+check (operand, low, high)
+ expressionS *operand;
+ int low;
+ int high;
+{
+ if (operand->X_op != O_constant
+ || operand->X_add_number < low
+ || operand->X_add_number > high)
+ {
+ as_bad (_("operand must be absolute in range %d..%d"), low, high);
+ }
+ return operand->X_add_number;
+}
+
+static
+void
+insert (output, index, exp, reloc, pcrel)
+ char *output;
+ int index;
+ expressionS *exp;
+ int reloc;
+ int pcrel;
+{
+ fix_new_exp (frag_now,
+ output - frag_now->fr_literal + index,
+ 4, /* always say size is 4, but we know better */
+ exp,
+ pcrel,
+ reloc);
+}
+
+void
+build_relaxable_instruction (opcode, operand)
+ h8500_opcode_info *opcode;
+ h8500_operand_info *operand;
+{
+ /* All relaxable instructions start life as two bytes but can become
+ three bytes long if a lonely branch and up to 9 bytes if long scb
+ */
+ char *p;
+ int len;
+ int type;
+
+ if (opcode->bytes[0].contents == 0x01)
+ {
+ type = SCB_F;
+ }
+ else if (opcode->bytes[0].contents == 0x06
+ || opcode->bytes[0].contents == 0x07)
+ {
+ type = SCB_TST;
+ }
+ else
+ {
+ type = BRANCH;
+ }
+
+ p = frag_var (rs_machine_dependent,
+ md_relax_table[C (type, WORD_DISP)].rlx_length,
+ len = md_relax_table[C (type, BYTE_DISP)].rlx_length,
+ C (type, UNDEF_BYTE_DISP),
+ displacement.X_add_symbol,
+ displacement.X_add_number,
+ 0);
+
+ p[0] = opcode->bytes[0].contents;
+ if (type != BRANCH)
+ {
+ p[1] = opcode->bytes[1].contents | rs;
+ }
+}
+
+/* Now we know what sort of opcodes it is, lets build the bytes -
+ */
+static void
+build_bytes (opcode, operand)
+ h8500_opcode_info *opcode;
+ h8500_operand_info *operand;
+
+{
+ int index;
+
+ if (pcrel8)
+ {
+ pcrel8 = 0;
+ build_relaxable_instruction (opcode, operand);
+ }
+ else
+ {
+ char *output = frag_more (opcode->length);
+
+ memset (output, 0, opcode->length);
+ for (index = 0; index < opcode->length; index++)
+ {
+ output[index] = opcode->bytes[index].contents;
+
+ switch (opcode->bytes[index].insert)
+ {
+ default:
+ printf (_("failed for %d\n"), opcode->bytes[index].insert);
+ break;
+ case 0:
+ break;
+ case RN:
+ output[index] |= rn;
+ break;
+ case RD:
+ case RDIND:
+
+ output[index] |= rd;
+ break;
+ case RS:
+ output[index] |= rs;
+ break;
+ case DISP16:
+ insert (output, index, &displacement, R_H8500_IMM16, 0);
+ index++;
+ break;
+ case DISP8:
+ case FPIND_D8:
+ insert (output, index, &displacement, R_H8500_IMM8, 0);
+ break;
+
+ case IMM16:
+ {
+ int p;
+ switch (immediate_inpage) {
+ case 'p':
+ p = R_H8500_HIGH16;
+ break;
+ case 'h':
+ p = R_H8500_HIGH16;
+ break;
+ default:
+ p = R_H8500_IMM16;
+ break;
+ }
+
+ insert (output, index, &immediate,p, 0);
+ }
+
+ index++;
+ break;
+ case RLIST:
+ case IMM8:
+ if (immediate_inpage)
+ {
+ insert (output, index, &immediate, R_H8500_HIGH8, 0);
+ }
+ else
+ {
+ insert (output, index, &immediate, R_H8500_IMM8, 0);
+ }
+ break;
+ case PCREL16:
+ insert (output, index, &displacement, R_H8500_PCREL16, 1);
+ index++;
+ break;
+ case PCREL8:
+ insert (output, index, &displacement, R_H8500_PCREL8, 1);
+ break;
+ case IMM4:
+ output[index] |= check (&immediate, 0, 15);
+ break;
+ case CR:
+
+ output[index] |= cr;
+ if (cr == 0)
+ {
+ output[0] |= 0x8;
+ }
+ else
+ {
+ output[0] &= ~0x8;
+ }
+
+ break;
+
+ case CRB:
+ output[index] |= crb;
+ output[0] &= ~0x8;
+ break;
+ case CRW:
+ output[index] |= crw;
+ output[0] |= 0x8;
+ break;
+ case ABS24:
+ insert (output, index, &absolute, R_H8500_IMM24, 0);
+ index += 2;
+ break;
+ case ABS16:
+ insert (output, index, &absolute, R_H8500_IMM16, 0);
+ index++;
+ break;
+ case ABS8:
+ insert (output, index, &absolute, R_H8500_IMM8, 0);
+ break;
+ case QIM:
+ switch (immediate.X_add_number)
+ {
+ case -2:
+ output[index] |= 0x5;
+ break;
+ case -1:
+ output[index] |= 0x4;
+ break;
+ case 1:
+ output[index] |= 0;
+ break;
+ case 2:
+ output[index] |= 1;
+ break;
+ }
+ break;
+ }
+ }
+ }
+}
+
+/* This is the guts of the machine-dependent assembler. STR points to a
+ machine dependent instruction. This funciton is supposed to emit
+ the frags/bytes it assembles to.
+ */
+
+void
+DEFUN (md_assemble, (str),
+ char *str)
+{
+ char *op_start;
+ char *op_end;
+ h8500_operand_info operand[2];
+ h8500_opcode_info *opcode;
+ h8500_opcode_info *prev_opcode;
+ char name[11];
+
+ int nlen = 0;
+
+ /* Drop leading whitespace */
+ while (*str == ' ')
+ str++;
+
+ /* find the op code end */
+ for (op_start = op_end = str;
+ *op_end &&
+ !is_end_of_line[*op_end] && *op_end != ' ';
+ op_end++)
+ {
+ if ( /**op_end != '.'
+ && *op_end != ':'
+ && */ nlen < 10)
+ {
+ name[nlen++] = *op_end;
+ }
+ }
+ name[nlen] = 0;
+
+ if (op_end == op_start)
+ {
+ as_bad (_("can't find opcode "));
+ }
+
+ opcode = (h8500_opcode_info *) hash_find (opcode_hash_control, name);
+
+ if (opcode == NULL)
+ {
+ as_bad (_("unknown opcode"));
+ return;
+ }
+
+ get_operands (opcode, op_end, operand);
+ prev_opcode = opcode;
+
+ opcode = get_specific (opcode, operand);
+
+ if (opcode == 0)
+ {
+ /* Couldn't find an opcode which matched the operands */
+ char *where = frag_more (2);
+
+ where[0] = 0x0;
+ where[1] = 0x0;
+ as_bad (_("invalid operands for opcode"));
+ return;
+ }
+
+ build_bytes (opcode, operand);
+
+}
+
+void
+DEFUN (tc_crawl_symbol_chain, (headers),
+ object_headers * headers)
+{
+ printf (_("call to tc_crawl_symbol_chain \n"));
+}
+
+symbolS *
+DEFUN (md_undefined_symbol, (name),
+ char *name)
+{
+ return 0;
+}
+
+void
+DEFUN (tc_headers_hook, (headers),
+ object_headers * headers)
+{
+ printf (_("call to tc_headers_hook \n"));
+}
+
+/* Various routines to kill one day */
+/* Equal to MAX_PRECISION in atof-ieee.c */
+#define MAX_LITTLENUMS 6
+
+/* Turn a string in input_line_pointer into a floating point constant of type
+ type, and store the appropriate bytes in *litP. The number of LITTLENUMS
+ emitted is stored in *sizeP . An error message is returned, or NULL on OK.
+ */
+char *
+md_atof (type, litP, sizeP)
+ char type;
+ char *litP;
+ int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ char *t;
+ char *atof_ieee ();
+
+ switch (type)
+ {
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ prec = 4;
+ break;
+
+ case 'x':
+ case 'X':
+ prec = 6;
+ break;
+
+ case 'p':
+ case 'P':
+ prec = 6;
+ break;
+
+ default:
+ *sizeP = 0;
+ return _("Bad call to MD_ATOF()");
+ }
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+
+ *sizeP = prec * sizeof (LITTLENUM_TYPE);
+ for (wordP = words; prec--;)
+ {
+ md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+ return 0;
+}
+
+CONST char *md_shortopts = "";
+struct option md_longopts[] = {
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof(md_longopts);
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ return 0;
+}
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+}
+
+void
+tc_aout_fix_to_chars ()
+{
+ printf (_("call to tc_aout_fix_to_chars \n"));
+ abort ();
+}
+
+static
+void
+wordify_scb (buffer, disp_size, inst_size)
+ char *buffer;
+ int *disp_size;
+ int *inst_size;
+{
+ int rn = buffer[1] & 0x7;
+
+ switch (buffer[0])
+ {
+ case 0x0e: /* BSR */
+ case 0x20:
+ case 0x21:
+ case 0x22:
+ case 0x23:
+ case 0x24:
+ case 0x25:
+ case 0x26:
+ case 0x27:
+ case 0x28:
+ case 0x29:
+ case 0x2a:
+ case 0x2b:
+ case 0x2c:
+ case 0x2d:
+ case 0x2e:
+ case 0x2f:
+ buffer[0] |= 0x10;
+ buffer[1] = 0;
+ buffer[2] = 0;
+ *disp_size = 2;
+ *inst_size = 1;
+ return;
+ default:
+ abort ();
+
+ case 0x01:
+ *inst_size = 6;
+ *disp_size = 2;
+ break;
+ case 0x06:
+ *inst_size = 8;
+ *disp_size = 2;
+
+ *buffer++ = 0x26; /* bne + 8 */
+ *buffer++ = 0x08;
+ break;
+ case 0x07:
+ *inst_size = 8;
+ *disp_size = 2;
+ *buffer++ = 0x27; /* bne + 8 */
+ *buffer++ = 0x08;
+ break;
+
+ }
+ *buffer++ = 0xa8 | rn; /* addq -1,rn */
+ *buffer++ = 0x0c;
+ *buffer++ = 0x04; /* cmp #0xff:8, rn */
+ *buffer++ = 0xff;
+ *buffer++ = 0x70 | rn;
+ *buffer++ = 0x36; /* bne ... */
+ *buffer++ = 0;
+ *buffer++ = 0;
+}
+
+/*
+called after relaxing, change the frags so they know how big they are
+*/
+void
+md_convert_frag (headers, seg, fragP)
+ object_headers *headers;
+ segT seg;
+ fragS *fragP;
+{
+ int disp_size = 0;
+ int inst_size = 0;
+ char *buffer = fragP->fr_fix + fragP->fr_literal;
+
+ switch (fragP->fr_subtype)
+ {
+ case C (BRANCH, BYTE_DISP):
+ disp_size = 1;
+ inst_size = 1;
+ break;
+
+ case C (SCB_F, BYTE_DISP):
+ case C (SCB_TST, BYTE_DISP):
+ disp_size = 1;
+ inst_size = 2;
+ break;
+
+ /* Branches to a known 16 bit displacement */
+
+ /* Turn on the 16bit bit */
+ case C (BRANCH, WORD_DISP):
+ case C (SCB_F, WORD_DISP):
+ case C (SCB_TST, WORD_DISP):
+ wordify_scb (buffer, &disp_size, &inst_size);
+ break;
+
+ case C (BRANCH, UNDEF_WORD_DISP):
+ case C (SCB_F, UNDEF_WORD_DISP):
+ case C (SCB_TST, UNDEF_WORD_DISP):
+ /* This tried to be relaxed, but didn't manage it, it now needs a
+ fix */
+ wordify_scb (buffer, &disp_size, &inst_size);
+
+ /* Make a reloc */
+ fix_new (fragP,
+ fragP->fr_fix + inst_size,
+ 4,
+ fragP->fr_symbol,
+ fragP->fr_offset,
+ 0,
+ R_H8500_PCREL16);
+
+ fragP->fr_fix += disp_size + inst_size;
+ fragP->fr_var = 0;
+ return;
+ break;
+ default:
+ abort ();
+ }
+ if (inst_size)
+ {
+ /* Get the address of the end of the instruction */
+ int next_inst = fragP->fr_fix + fragP->fr_address + disp_size + inst_size;
+ int targ_addr = (S_GET_VALUE (fragP->fr_symbol) +
+ fragP->fr_offset);
+ int disp = targ_addr - next_inst;
+
+ md_number_to_chars (buffer + inst_size, disp, disp_size);
+ fragP->fr_fix += disp_size + inst_size;
+ fragP->fr_var = 0;
+ }
+}
+
+valueT
+md_section_align (seg, size)
+ segT seg ;
+ valueT size;
+{
+ return ((size + (1 << section_alignment[(int) seg]) - 1)
+ & (-1 << section_alignment[(int) seg]));
+
+}
+
+void
+md_apply_fix (fixP, val)
+ fixS *fixP;
+ long val;
+{
+ char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
+
+ if (fixP->fx_r_type == 0)
+ {
+ fixP->fx_r_type = fixP->fx_size == 4 ? R_H8500_IMM32 : R_H8500_IMM16;
+ }
+
+ switch (fixP->fx_r_type)
+ {
+
+ case R_H8500_IMM8:
+ case R_H8500_PCREL8:
+ *buf++ = val;
+ break;
+ case R_H8500_IMM16:
+ case R_H8500_LOW16:
+ case R_H8500_PCREL16:
+ *buf++ = (val >> 8);
+ *buf++ = val;
+ break;
+ case R_H8500_HIGH8:
+ *buf++ = val >> 16;
+ break;
+ case R_H8500_HIGH16:
+ *buf++ = val >> 24;
+ *buf++ = val >> 16;
+ break;
+ case R_H8500_IMM24:
+ *buf++ = (val >> 16);
+ *buf++ = (val >> 8);
+ *buf++ = val;
+ break;
+ case R_H8500_IMM32:
+ *buf++ = (val >> 24);
+ *buf++ = (val >> 16);
+ *buf++ = (val >> 8);
+ *buf++ = val;
+ break;
+ default:
+ abort ();
+
+ }
+}
+
+/*
+called just before address relaxation, return the length
+by which a fragment must grow to reach it's destination
+*/
+int
+md_estimate_size_before_relax (fragP, segment_type)
+ register fragS *fragP;
+ register segT segment_type;
+{
+ int what = GET_WHAT (fragP->fr_subtype);
+
+ switch (fragP->fr_subtype)
+ {
+ default:
+ abort ();
+ case C (BRANCH, UNDEF_BYTE_DISP):
+ case C (SCB_F, UNDEF_BYTE_DISP):
+ case C (SCB_TST, UNDEF_BYTE_DISP):
+ /* used to be a branch to somewhere which was unknown */
+ if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type)
+ {
+ /* Got a symbol and it's defined in this segment, become byte
+ sized - maybe it will fix up */
+ fragP->fr_subtype = C (what, BYTE_DISP);
+ fragP->fr_var = md_relax_table[C (what, BYTE_DISP)].rlx_length;
+ }
+ else
+ {
+ /* Its got a segment, but its not ours, so it will always be long */
+ fragP->fr_subtype = C (what, UNDEF_WORD_DISP);
+ fragP->fr_var = md_relax_table[C (what, WORD_DISP)].rlx_length;
+ return md_relax_table[C (what, WORD_DISP)].rlx_length;
+ }
+ }
+ return fragP->fr_var;
+}
+
+/* Put number into target byte order */
+
+void
+md_number_to_chars (ptr, use, nbytes)
+ char *ptr;
+ valueT use;
+ int nbytes;
+{
+ number_to_chars_bigendian (ptr, use, nbytes);
+}
+
+long
+md_pcrel_from (fixP)
+ fixS *fixP;
+{
+ return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
+}
+
+/*ARGSUSED*/
+void
+tc_coff_symbol_emit_hook (ignore)
+ symbolS *ignore;
+{
+}
+
+short
+tc_coff_fix2rtype (fix_ptr)
+ fixS *fix_ptr;
+{
+ if (fix_ptr->fx_r_type == RELOC_32)
+ {
+ /* cons likes to create reloc32's whatever the size of the reloc..
+ */
+ switch (fix_ptr->fx_size)
+ {
+ case 2:
+ return R_H8500_IMM16;
+ break;
+ case 1:
+ return R_H8500_IMM8;
+ break;
+ default:
+ abort ();
+ }
+ }
+ return fix_ptr->fx_r_type;
+}
+
+void
+tc_reloc_mangle (fix_ptr, intr, base)
+ fixS *fix_ptr;
+ struct internal_reloc *intr;
+ bfd_vma base;
+
+{
+ symbolS *symbol_ptr;
+
+ symbol_ptr = fix_ptr->fx_addsy;
+
+ /* If this relocation is attached to a symbol then it's ok
+ to output it */
+ if (fix_ptr->fx_r_type == RELOC_32)
+ {
+ /* cons likes to create reloc32's whatever the size of the reloc..
+ */
+ switch (fix_ptr->fx_size)
+ {
+ case 2:
+ intr->r_type = R_IMM16;
+ break;
+ case 1:
+ intr->r_type = R_IMM8;
+ break;
+ default:
+ abort ();
+ }
+ }
+ else
+ {
+ intr->r_type = fix_ptr->fx_r_type;
+ }
+
+ intr->r_vaddr = fix_ptr->fx_frag->fr_address + fix_ptr->fx_where + base;
+ intr->r_offset = fix_ptr->fx_offset;
+
+ /* Turn the segment of the symbol into an offset. */
+ if (symbol_ptr)
+ {
+ symbolS *dot;
+
+ dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot;
+ if (dot)
+ {
+ /* intr->r_offset -=
+ segment_info[S_GET_SEGMENT(symbol_ptr)].scnhdr.s_paddr;*/
+ intr->r_offset += S_GET_VALUE (symbol_ptr);
+ intr->r_symndx = dot->sy_number;
+ }
+ else
+ {
+ intr->r_symndx = symbol_ptr->sy_number;
+ }
+
+ }
+ else
+ {
+ intr->r_symndx = -1;
+ }
+
+}
+
+
+
+int
+start_label (ptr)
+ char *ptr;
+{
+ /* Check for :s.w */
+ if (isalpha (ptr[1]) && ptr[2] == '.')
+ return 0;
+ /* Check for :s */
+ if (isalpha (ptr[1]) && !isalpha (ptr[2]))
+ return 0;
+ return 1;
+}
+
+
+int
+tc_coff_sizemachdep (frag)
+ fragS *frag;
+{
+ return md_relax_table[frag->fr_subtype].rlx_length;
+}
+
+/* end of tc-h8500.c */
+
diff --git a/gas/config/tc-h8500.h b/gas/config/tc-h8500.h
new file mode 100644
index 0000000000..2a53ec35ce
--- /dev/null
+++ b/gas/config/tc-h8500.h
@@ -0,0 +1,57 @@
+/* This file is tc-h8500.h
+ Copyright (C) 1993, 95, 97, 1998 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+
+#define TC_H8500
+
+#define TARGET_BYTES_BIG_ENDIAN 1
+
+#if ANSI_PROTOTYPES
+struct internal_reloc;
+#endif
+
+#define WORKING_DOT_WORD
+
+/* This macro translates between an internal fix and an coff reloc type */
+#define TC_COFF_FIX2RTYPE(fixP) tc_coff_fix2rtype(fixP)
+
+#define BFD_ARCH bfd_arch_h8500
+#define COFF_MAGIC 0x8500
+#define TC_COUNT_RELOC(x) ((x)->fx_addsy||(x)->fx_subsy)
+#define IGNORE_NONSTANDARD_ESCAPES
+
+#define TC_RELOC_MANGLE(s,a,b,c) tc_reloc_mangle(a,b,c)
+extern void tc_reloc_mangle
+ PARAMS ((struct fix *, struct internal_reloc *, bfd_vma));
+
+#define DO_NOT_STRIP 0
+#define LISTING_HEADER "Hitachi H8/500 GAS "
+#define NEED_FX_R_TYPE 1
+#define RELOC_32 1234
+
+#define TC_START_LABEL(ch, ptr) (ch == ':' && start_label(ptr))
+#define TC_COFF_SIZEMACHDEP(frag) tc_coff_sizemachdep(frag)
+
+#define md_operand(x)
+
+extern struct relax_type md_relax_table[];
+#define TC_GENERIC_RELAX_TABLE md_relax_table
+
+/* end of tc-h8500.h */
diff --git a/gas/config/tc-hppa.c b/gas/config/tc-hppa.c
new file mode 100644
index 0000000000..8785de8769
--- /dev/null
+++ b/gas/config/tc-hppa.c
@@ -0,0 +1,6716 @@
+/* tc-hppa.c -- Assemble for the PA
+ Copyright (C) 1989, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+
+/* HP PA-RISC support was contributed by the Center for Software Science
+ at the University of Utah. */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include "as.h"
+#include "subsegs.h"
+
+#include "bfd/libhppa.h"
+#include "bfd/libbfd.h"
+
+/* Be careful, this file includes data *declarations*. */
+#include "opcode/hppa.h"
+
+/* A "convient" place to put object file dependencies which do
+ not need to be seen outside of tc-hppa.c. */
+#ifdef OBJ_ELF
+/* Names of various debugging spaces/subspaces. */
+#define GDB_DEBUG_SPACE_NAME ".stab"
+#define GDB_STRINGS_SUBSPACE_NAME ".stabstr"
+#define GDB_SYMBOLS_SUBSPACE_NAME ".stab"
+#define UNWIND_SECTION_NAME ".PARISC.unwind"
+/* Nonzero if CODE is a fixup code needing further processing. */
+
+/* Object file formats specify relocation types. */
+typedef elf32_hppa_reloc_type reloc_type;
+
+/* Object file formats specify BFD symbol types. */
+typedef elf_symbol_type obj_symbol_type;
+
+/* How to generate a relocation. */
+#define hppa_gen_reloc_type hppa_elf_gen_reloc_type
+
+/* ELF objects can have versions, but apparently do not have anywhere
+ to store a copyright string. */
+#define obj_version obj_elf_version
+#define obj_copyright obj_elf_version
+
+/* Use space aliases. */
+#define USE_ALIASES 1
+#endif
+
+#ifdef OBJ_SOM
+/* Names of various debugging spaces/subspaces. */
+#define GDB_DEBUG_SPACE_NAME "$GDB_DEBUG$"
+#define GDB_STRINGS_SUBSPACE_NAME "$GDB_STRINGS$"
+#define GDB_SYMBOLS_SUBSPACE_NAME "$GDB_SYMBOLS$"
+#define UNWIND_SECTION_NAME "$UNWIND$"
+
+/* Object file formats specify relocation types. */
+typedef int reloc_type;
+
+/* SOM objects can have both a version string and a copyright string. */
+#define obj_version obj_som_version
+#define obj_copyright obj_som_copyright
+
+/* Do not use space aliases. */
+#define USE_ALIASES 0
+
+/* How to generate a relocation. */
+#define hppa_gen_reloc_type hppa_som_gen_reloc_type
+
+/* Object file formats specify BFD symbol types. */
+typedef som_symbol_type obj_symbol_type;
+
+/* This apparently isn't in older versions of hpux reloc.h. */
+#ifndef R_DLT_REL
+#define R_DLT_REL 0x78
+#endif
+#endif
+
+#ifndef R_N0SEL
+#define R_N0SEL 0xd8
+#endif
+
+#ifndef R_N1SEL
+#define R_N1SEL 0xd9
+#endif
+
+/* Various structures and types used internally in tc-hppa.c. */
+
+/* Unwind table and descriptor. FIXME: Sync this with GDB version. */
+
+struct unwind_desc
+ {
+ unsigned int cannot_unwind:1;
+ unsigned int millicode:1;
+ unsigned int millicode_save_rest:1;
+ unsigned int region_desc:2;
+ unsigned int save_sr:2;
+ unsigned int entry_fr:4;
+ unsigned int entry_gr:5;
+ unsigned int args_stored:1;
+ unsigned int call_fr:5;
+ unsigned int call_gr:5;
+ unsigned int save_sp:1;
+ unsigned int save_rp:1;
+ unsigned int save_rp_in_frame:1;
+ unsigned int extn_ptr_defined:1;
+ unsigned int cleanup_defined:1;
+
+ unsigned int hpe_interrupt_marker:1;
+ unsigned int hpux_interrupt_marker:1;
+ unsigned int reserved:3;
+ unsigned int frame_size:27;
+ };
+
+struct unwind_table
+ {
+ /* Starting and ending offsets of the region described by
+ descriptor. */
+ unsigned int start_offset;
+ unsigned int end_offset;
+ struct unwind_desc descriptor;
+ };
+
+/* This structure is used by the .callinfo, .enter, .leave pseudo-ops to
+ control the entry and exit code they generate. It is also used in
+ creation of the correct stack unwind descriptors.
+
+ NOTE: GAS does not support .enter and .leave for the generation of
+ prologues and epilogues. FIXME.
+
+ The fields in structure roughly correspond to the arguments available on the
+ .callinfo pseudo-op. */
+
+struct call_info
+ {
+ /* The unwind descriptor being built. */
+ struct unwind_table ci_unwind;
+
+ /* Name of this function. */
+ symbolS *start_symbol;
+
+ /* (temporary) symbol used to mark the end of this function. */
+ symbolS *end_symbol;
+
+ /* Next entry in the chain. */
+ struct call_info *ci_next;
+ };
+
+/* Operand formats for FP instructions. Note not all FP instructions
+ allow all four formats to be used (for example fmpysub only allows
+ SGL and DBL). */
+typedef enum
+ {
+ SGL, DBL, ILLEGAL_FMT, QUAD, W, UW, DW, UDW, QW, UQW
+ }
+fp_operand_format;
+
+/* This fully describes the symbol types which may be attached to
+ an EXPORT or IMPORT directive. Only SOM uses this formation
+ (ELF has no need for it). */
+typedef enum
+ {
+ SYMBOL_TYPE_UNKNOWN,
+ SYMBOL_TYPE_ABSOLUTE,
+ SYMBOL_TYPE_CODE,
+ SYMBOL_TYPE_DATA,
+ SYMBOL_TYPE_ENTRY,
+ SYMBOL_TYPE_MILLICODE,
+ SYMBOL_TYPE_PLABEL,
+ SYMBOL_TYPE_PRI_PROG,
+ SYMBOL_TYPE_SEC_PROG,
+ }
+pa_symbol_type;
+
+/* This structure contains information needed to assemble
+ individual instructions. */
+struct pa_it
+ {
+ /* Holds the opcode after parsing by pa_ip. */
+ unsigned long opcode;
+
+ /* Holds an expression associated with the current instruction. */
+ expressionS exp;
+
+ /* Does this instruction use PC-relative addressing. */
+ int pcrel;
+
+ /* Floating point formats for operand1 and operand2. */
+ fp_operand_format fpof1;
+ fp_operand_format fpof2;
+
+
+ /* Holds the field selector for this instruction
+ (for example L%, LR%, etc). */
+ long field_selector;
+
+ /* Holds any argument relocation bits associated with this
+ instruction. (instruction should be some sort of call). */
+ long arg_reloc;
+
+ /* The format specification for this instruction. */
+ int format;
+
+ /* The relocation (if any) associated with this instruction. */
+ reloc_type reloc;
+ };
+
+/* PA-89 floating point registers are arranged like this:
+
+
+ +--------------+--------------+
+ | 0 or 16L | 16 or 16R |
+ +--------------+--------------+
+ | 1 or 17L | 17 or 17R |
+ +--------------+--------------+
+ | | |
+
+ . . .
+ . . .
+ . . .
+
+ | | |
+ +--------------+--------------+
+ | 14 or 30L | 30 or 30R |
+ +--------------+--------------+
+ | 15 or 31L | 31 or 31R |
+ +--------------+--------------+
+
+
+ The following is a version of pa_parse_number that
+ handles the L/R notation and returns the correct
+ value to put into the instruction register field.
+ The correct value to put into the instruction is
+ encoded in the structure 'pa_11_fp_reg_struct'. */
+
+struct pa_11_fp_reg_struct
+ {
+ /* The register number. */
+ char number_part;
+
+ /* L/R selector. */
+ char l_r_select;
+ };
+
+/* Additional information needed to build argument relocation stubs. */
+struct call_desc
+ {
+ /* The argument relocation specification. */
+ unsigned int arg_reloc;
+
+ /* Number of arguments. */
+ unsigned int arg_count;
+ };
+
+/* This structure defines an entry in the subspace dictionary
+ chain. */
+
+struct subspace_dictionary_chain
+ {
+ /* Nonzero if this space has been defined by the user code. */
+ unsigned int ssd_defined;
+
+ /* Name of this subspace. */
+ char *ssd_name;
+
+ /* GAS segment and subsegment associated with this subspace. */
+ asection *ssd_seg;
+ int ssd_subseg;
+
+ /* Next space in the subspace dictionary chain. */
+ struct subspace_dictionary_chain *ssd_next;
+ };
+
+typedef struct subspace_dictionary_chain ssd_chain_struct;
+
+/* This structure defines an entry in the subspace dictionary
+ chain. */
+
+struct space_dictionary_chain
+ {
+ /* Nonzero if this space has been defined by the user code or
+ as a default space. */
+ unsigned int sd_defined;
+
+ /* Nonzero if this spaces has been defined by the user code. */
+ unsigned int sd_user_defined;
+
+ /* The space number (or index). */
+ unsigned int sd_spnum;
+
+ /* The name of this subspace. */
+ char *sd_name;
+
+ /* GAS segment to which this subspace corresponds. */
+ asection *sd_seg;
+
+ /* Current subsegment number being used. */
+ int sd_last_subseg;
+
+ /* The chain of subspaces contained within this space. */
+ ssd_chain_struct *sd_subspaces;
+
+ /* The next entry in the space dictionary chain. */
+ struct space_dictionary_chain *sd_next;
+ };
+
+typedef struct space_dictionary_chain sd_chain_struct;
+
+/* Structure for previous label tracking. Needed so that alignments,
+ callinfo declarations, etc can be easily attached to a particular
+ label. */
+typedef struct label_symbol_struct
+ {
+ struct symbol *lss_label;
+ sd_chain_struct *lss_space;
+ struct label_symbol_struct *lss_next;
+ }
+label_symbol_struct;
+
+/* This structure defines attributes of the default subspace
+ dictionary entries. */
+
+struct default_subspace_dict
+ {
+ /* Name of the subspace. */
+ char *name;
+
+ /* FIXME. Is this still needed? */
+ char defined;
+
+ /* Nonzero if this subspace is loadable. */
+ char loadable;
+
+ /* Nonzero if this subspace contains only code. */
+ char code_only;
+
+ /* Nonzero if this is a common subspace. */
+ char common;
+
+ /* Nonzero if this is a common subspace which allows symbols
+ to be multiply defined. */
+ char dup_common;
+
+ /* Nonzero if this subspace should be zero filled. */
+ char zero;
+
+ /* Sort key for this subspace. */
+ unsigned char sort;
+
+ /* Access control bits for this subspace. Can represent RWX access
+ as well as privilege level changes for gateways. */
+ int access;
+
+ /* Index of containing space. */
+ int space_index;
+
+ /* Alignment (in bytes) of this subspace. */
+ int alignment;
+
+ /* Quadrant within space where this subspace should be loaded. */
+ int quadrant;
+
+ /* An index into the default spaces array. */
+ int def_space_index;
+
+ /* An alias for this section (or NULL if no alias exists). */
+ char *alias;
+
+ /* Subsegment associated with this subspace. */
+ subsegT subsegment;
+ };
+
+/* This structure defines attributes of the default space
+ dictionary entries. */
+
+struct default_space_dict
+ {
+ /* Name of the space. */
+ char *name;
+
+ /* Space number. It is possible to identify spaces within
+ assembly code numerically! */
+ int spnum;
+
+ /* Nonzero if this space is loadable. */
+ char loadable;
+
+ /* Nonzero if this space is "defined". FIXME is still needed */
+ char defined;
+
+ /* Nonzero if this space can not be shared. */
+ char private;
+
+ /* Sort key for this space. */
+ unsigned char sort;
+
+ /* Segment associated with this space. */
+ asection *segment;
+
+ /* An alias for this section (or NULL if no alias exists). */
+ char *alias;
+ };
+
+/* Extra information needed to perform fixups (relocations) on the PA. */
+struct hppa_fix_struct
+ {
+ /* The field selector. */
+ enum hppa_reloc_field_selector_type_alt fx_r_field;
+
+ /* Type of fixup. */
+ int fx_r_type;
+
+ /* Format of fixup. */
+ int fx_r_format;
+
+ /* Argument relocation bits. */
+ long fx_arg_reloc;
+
+ /* The segment this fixup appears in. */
+ segT segment;
+ };
+
+/* Structure to hold information about predefined registers. */
+
+struct pd_reg
+ {
+ char *name;
+ int value;
+ };
+
+/* This structure defines the mapping from a FP condition string
+ to a condition number which can be recorded in an instruction. */
+struct fp_cond_map
+ {
+ char *string;
+ int cond;
+ };
+
+/* This structure defines a mapping from a field selector
+ string to a field selector type. */
+struct selector_entry
+ {
+ char *prefix;
+ int field_selector;
+ };
+
+/* Prototypes for functions local to tc-hppa.c. */
+
+static void pa_check_current_space_and_subspace PARAMS ((void));
+static fp_operand_format pa_parse_fp_format PARAMS ((char **s));
+static void pa_cons PARAMS ((int));
+static void pa_data PARAMS ((int));
+static void pa_float_cons PARAMS ((int));
+static void pa_fill PARAMS ((int));
+static void pa_lcomm PARAMS ((int));
+static void pa_lsym PARAMS ((int));
+static void pa_stringer PARAMS ((int));
+static void pa_text PARAMS ((int));
+static void pa_version PARAMS ((int));
+static int pa_parse_fp_cmp_cond PARAMS ((char **));
+static int get_expression PARAMS ((char *));
+static int pa_get_absolute_expression PARAMS ((struct pa_it *, char **));
+static int evaluate_absolute PARAMS ((struct pa_it *));
+static unsigned int pa_build_arg_reloc PARAMS ((char *));
+static unsigned int pa_align_arg_reloc PARAMS ((unsigned int, unsigned int));
+static int pa_parse_nullif PARAMS ((char **));
+static int pa_parse_nonneg_cmpsub_cmpltr PARAMS ((char **, int));
+static int pa_parse_neg_cmpsub_cmpltr PARAMS ((char **, int));
+static int pa_parse_neg_add_cmpltr PARAMS ((char **, int));
+static int pa_parse_nonneg_add_cmpltr PARAMS ((char **, int));
+static void pa_align PARAMS ((int));
+static void pa_block PARAMS ((int));
+static void pa_brtab PARAMS ((int));
+static void pa_try PARAMS ((int));
+static void pa_call PARAMS ((int));
+static void pa_call_args PARAMS ((struct call_desc *));
+static void pa_callinfo PARAMS ((int));
+static void pa_code PARAMS ((int));
+static void pa_comm PARAMS ((int));
+#ifdef OBJ_SOM
+static void pa_compiler PARAMS ((int));
+#endif
+static void pa_copyright PARAMS ((int));
+static void pa_end PARAMS ((int));
+static void pa_enter PARAMS ((int));
+static void pa_entry PARAMS ((int));
+static void pa_equ PARAMS ((int));
+static void pa_exit PARAMS ((int));
+static void pa_export PARAMS ((int));
+static void pa_type_args PARAMS ((symbolS *, int));
+static void pa_import PARAMS ((int));
+static void pa_label PARAMS ((int));
+static void pa_leave PARAMS ((int));
+static void pa_level PARAMS ((int));
+static void pa_origin PARAMS ((int));
+static void pa_proc PARAMS ((int));
+static void pa_procend PARAMS ((int));
+static void pa_space PARAMS ((int));
+static void pa_spnum PARAMS ((int));
+static void pa_subspace PARAMS ((int));
+static void pa_param PARAMS ((int));
+static void pa_undefine_label PARAMS ((void));
+static int need_pa11_opcode PARAMS ((struct pa_it *,
+ struct pa_11_fp_reg_struct *));
+static int pa_parse_number PARAMS ((char **, struct pa_11_fp_reg_struct *));
+static label_symbol_struct *pa_get_label PARAMS ((void));
+static sd_chain_struct *create_new_space PARAMS ((char *, int, int,
+ int, int, int,
+ asection *, int));
+static ssd_chain_struct *create_new_subspace PARAMS ((sd_chain_struct *,
+ char *, int, int,
+ int, int, int,
+ int, int, int, int,
+ int, asection *));
+static ssd_chain_struct *update_subspace PARAMS ((sd_chain_struct *,
+ char *, int, int, int,
+ int, int, int, int,
+ int, int, int,
+ asection *));
+static sd_chain_struct *is_defined_space PARAMS ((char *));
+static ssd_chain_struct *is_defined_subspace PARAMS ((char *));
+static sd_chain_struct *pa_segment_to_space PARAMS ((asection *));
+static ssd_chain_struct *pa_subsegment_to_subspace PARAMS ((asection *,
+ subsegT));
+static sd_chain_struct *pa_find_space_by_number PARAMS ((int));
+static unsigned int pa_subspace_start PARAMS ((sd_chain_struct *, int));
+static void pa_ip PARAMS ((char *));
+static void fix_new_hppa PARAMS ((fragS *, int, int, symbolS *,
+ long, expressionS *, int,
+ bfd_reloc_code_real_type,
+ enum hppa_reloc_field_selector_type_alt,
+ int, long, int *));
+static int is_end_of_statement PARAMS ((void));
+static int reg_name_search PARAMS ((char *));
+static int pa_chk_field_selector PARAMS ((char **));
+static int is_same_frag PARAMS ((fragS *, fragS *));
+static void process_exit PARAMS ((void));
+static sd_chain_struct *pa_parse_space_stmt PARAMS ((char *, int));
+static int log2 PARAMS ((int));
+static int pa_next_subseg PARAMS ((sd_chain_struct *));
+static unsigned int pa_stringer_aux PARAMS ((char *));
+static void pa_spaces_begin PARAMS ((void));
+
+#ifdef OBJ_ELF
+static void hppa_elf_mark_end_of_function PARAMS ((void));
+static void pa_build_unwind_subspace PARAMS ((struct call_info *));
+#endif
+
+/* File and gloally scoped variable declarations. */
+
+/* Root and final entry in the space chain. */
+static sd_chain_struct *space_dict_root;
+static sd_chain_struct *space_dict_last;
+
+/* The current space and subspace. */
+static sd_chain_struct *current_space;
+static ssd_chain_struct *current_subspace;
+
+/* Root of the call_info chain. */
+static struct call_info *call_info_root;
+
+/* The last call_info (for functions) structure
+ seen so it can be associated with fixups and
+ function labels. */
+static struct call_info *last_call_info;
+
+/* The last call description (for actual calls). */
+static struct call_desc last_call_desc;
+
+/* handle of the OPCODE hash table */
+static struct hash_control *op_hash = NULL;
+
+/* This array holds the chars that always start a comment. If the
+ pre-processor is disabled, these aren't very useful. */
+const char comment_chars[] = ";";
+
+/* Table of pseudo ops for the PA. FIXME -- how many of these
+ are now redundant with the overall GAS and the object file
+ dependent tables? */
+const pseudo_typeS md_pseudo_table[] =
+{
+ /* align pseudo-ops on the PA specify the actual alignment requested,
+ not the log2 of the requested alignment. */
+ {"align", pa_align, 8},
+ {"begin_brtab", pa_brtab, 1},
+ {"begin_try", pa_try, 1},
+ {"block", pa_block, 1},
+ {"blockz", pa_block, 0},
+ {"byte", pa_cons, 1},
+ {"call", pa_call, 0},
+ {"callinfo", pa_callinfo, 0},
+ {"code", pa_code, 0},
+ {"comm", pa_comm, 0},
+#ifdef OBJ_SOM
+ {"compiler", pa_compiler, 0},
+#endif
+ {"copyright", pa_copyright, 0},
+ {"data", pa_data, 0},
+ {"double", pa_float_cons, 'd'},
+ {"end", pa_end, 0},
+ {"end_brtab", pa_brtab, 0},
+ {"end_try", pa_try, 0},
+ {"enter", pa_enter, 0},
+ {"entry", pa_entry, 0},
+ {"equ", pa_equ, 0},
+ {"exit", pa_exit, 0},
+ {"export", pa_export, 0},
+ {"fill", pa_fill, 0},
+ {"float", pa_float_cons, 'f'},
+ {"half", pa_cons, 2},
+ {"import", pa_import, 0},
+ {"int", pa_cons, 4},
+ {"label", pa_label, 0},
+ {"lcomm", pa_lcomm, 0},
+ {"leave", pa_leave, 0},
+ {"level", pa_level, 0},
+ {"long", pa_cons, 4},
+ {"lsym", pa_lsym, 0},
+ {"nsubspa", pa_subspace, 1},
+ {"octa", pa_cons, 16},
+ {"org", pa_origin, 0},
+ {"origin", pa_origin, 0},
+ {"param", pa_param, 0},
+ {"proc", pa_proc, 0},
+ {"procend", pa_procend, 0},
+ {"quad", pa_cons, 8},
+ {"reg", pa_equ, 1},
+ {"short", pa_cons, 2},
+ {"single", pa_float_cons, 'f'},
+ {"space", pa_space, 0},
+ {"spnum", pa_spnum, 0},
+ {"string", pa_stringer, 0},
+ {"stringz", pa_stringer, 1},
+ {"subspa", pa_subspace, 0},
+ {"text", pa_text, 0},
+ {"version", pa_version, 0},
+ {"word", pa_cons, 4},
+ {NULL, 0, 0}
+};
+
+/* This array holds the chars that only start a comment at the beginning of
+ a line. If the line seems to have the form '# 123 filename'
+ .line and .file directives will appear in the pre-processed output.
+
+ Note that input_file.c hand checks for '#' at the beginning of the
+ first line of the input file. This is because the compiler outputs
+ #NO_APP at the beginning of its output.
+
+ Also note that C style comments will always work. */
+const char line_comment_chars[] = "#";
+
+/* This array holds the characters which act as line separators. */
+const char line_separator_chars[] = "!";
+
+/* Chars that can be used to separate mant from exp in floating point nums. */
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant.
+ As in 0f12.456 or 0d1.2345e12.
+
+ Be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
+ changed in read.c. Ideally it shouldn't hae to know abou it at
+ all, but nothing is ideal around here. */
+const char FLT_CHARS[] = "rRsSfFdDxXpP";
+
+static struct pa_it the_insn;
+
+/* Points to the end of an expression just parsed by get_expressoin
+ and friends. FIXME. This shouldn't be handled with a file-global
+ variable. */
+static char *expr_end;
+
+/* Nonzero if a .callinfo appeared within the current procedure. */
+static int callinfo_found;
+
+/* Nonzero if the assembler is currently within a .entry/.exit pair. */
+static int within_entry_exit;
+
+/* Nonzero if the assembler is currently within a procedure definition. */
+static int within_procedure;
+
+/* Handle on strucutre which keep track of the last symbol
+ seen in each subspace. */
+static label_symbol_struct *label_symbols_rootp = NULL;
+
+/* Holds the last field selector. */
+static int hppa_field_selector;
+
+
+/* A dummy bfd symbol so that all relocations have symbols of some kind. */
+static symbolS *dummy_symbol;
+
+/* Nonzero if errors are to be printed. */
+static int print_errors = 1;
+
+/* List of registers that are pre-defined:
+
+ Each general register has one predefined name of the form
+ %r<REGNUM> which has the value <REGNUM>.
+
+ Space and control registers are handled in a similar manner,
+ but use %sr<REGNUM> and %cr<REGNUM> as their predefined names.
+
+ Likewise for the floating point registers, but of the form
+ %fr<REGNUM>. Floating point registers have additional predefined
+ names with 'L' and 'R' suffixes (e.g. %fr19L, %fr19R) which
+ again have the value <REGNUM>.
+
+ Many registers also have synonyms:
+
+ %r26 - %r23 have %arg0 - %arg3 as synonyms
+ %r28 - %r29 have %ret0 - %ret1 as synonyms
+ %r30 has %sp as a synonym
+ %r27 has %dp as a synonym
+ %r2 has %rp as a synonym
+
+ Almost every control register has a synonym; they are not listed
+ here for brevity.
+
+ The table is sorted. Suitable for searching by a binary search. */
+
+static const struct pd_reg pre_defined_registers[] =
+{
+ {"%arg0", 26},
+ {"%arg1", 25},
+ {"%arg2", 24},
+ {"%arg3", 23},
+ {"%cr0", 0},
+ {"%cr10", 10},
+ {"%cr11", 11},
+ {"%cr12", 12},
+ {"%cr13", 13},
+ {"%cr14", 14},
+ {"%cr15", 15},
+ {"%cr16", 16},
+ {"%cr17", 17},
+ {"%cr18", 18},
+ {"%cr19", 19},
+ {"%cr20", 20},
+ {"%cr21", 21},
+ {"%cr22", 22},
+ {"%cr23", 23},
+ {"%cr24", 24},
+ {"%cr25", 25},
+ {"%cr26", 26},
+ {"%cr27", 27},
+ {"%cr28", 28},
+ {"%cr29", 29},
+ {"%cr30", 30},
+ {"%cr31", 31},
+ {"%cr8", 8},
+ {"%cr9", 9},
+ {"%dp", 27},
+ {"%eiem", 15},
+ {"%eirr", 23},
+ {"%fr0", 0},
+ {"%fr0l", 0},
+ {"%fr0r", 0},
+ {"%fr1", 1},
+ {"%fr10", 10},
+ {"%fr10l", 10},
+ {"%fr10r", 10},
+ {"%fr11", 11},
+ {"%fr11l", 11},
+ {"%fr11r", 11},
+ {"%fr12", 12},
+ {"%fr12l", 12},
+ {"%fr12r", 12},
+ {"%fr13", 13},
+ {"%fr13l", 13},
+ {"%fr13r", 13},
+ {"%fr14", 14},
+ {"%fr14l", 14},
+ {"%fr14r", 14},
+ {"%fr15", 15},
+ {"%fr15l", 15},
+ {"%fr15r", 15},
+ {"%fr16", 16},
+ {"%fr16l", 16},
+ {"%fr16r", 16},
+ {"%fr17", 17},
+ {"%fr17l", 17},
+ {"%fr17r", 17},
+ {"%fr18", 18},
+ {"%fr18l", 18},
+ {"%fr18r", 18},
+ {"%fr19", 19},
+ {"%fr19l", 19},
+ {"%fr19r", 19},
+ {"%fr1l", 1},
+ {"%fr1r", 1},
+ {"%fr2", 2},
+ {"%fr20", 20},
+ {"%fr20l", 20},
+ {"%fr20r", 20},
+ {"%fr21", 21},
+ {"%fr21l", 21},
+ {"%fr21r", 21},
+ {"%fr22", 22},
+ {"%fr22l", 22},
+ {"%fr22r", 22},
+ {"%fr23", 23},
+ {"%fr23l", 23},
+ {"%fr23r", 23},
+ {"%fr24", 24},
+ {"%fr24l", 24},
+ {"%fr24r", 24},
+ {"%fr25", 25},
+ {"%fr25l", 25},
+ {"%fr25r", 25},
+ {"%fr26", 26},
+ {"%fr26l", 26},
+ {"%fr26r", 26},
+ {"%fr27", 27},
+ {"%fr27l", 27},
+ {"%fr27r", 27},
+ {"%fr28", 28},
+ {"%fr28l", 28},
+ {"%fr28r", 28},
+ {"%fr29", 29},
+ {"%fr29l", 29},
+ {"%fr29r", 29},
+ {"%fr2l", 2},
+ {"%fr2r", 2},
+ {"%fr3", 3},
+ {"%fr30", 30},
+ {"%fr30l", 30},
+ {"%fr30r", 30},
+ {"%fr31", 31},
+ {"%fr31l", 31},
+ {"%fr31r", 31},
+ {"%fr3l", 3},
+ {"%fr3r", 3},
+ {"%fr4", 4},
+ {"%fr4l", 4},
+ {"%fr4r", 4},
+ {"%fr5", 5},
+ {"%fr5l", 5},
+ {"%fr5r", 5},
+ {"%fr6", 6},
+ {"%fr6l", 6},
+ {"%fr6r", 6},
+ {"%fr7", 7},
+ {"%fr7l", 7},
+ {"%fr7r", 7},
+ {"%fr8", 8},
+ {"%fr8l", 8},
+ {"%fr8r", 8},
+ {"%fr9", 9},
+ {"%fr9l", 9},
+ {"%fr9r", 9},
+ {"%hta", 25},
+ {"%iir", 19},
+ {"%ior", 21},
+ {"%ipsw", 22},
+ {"%isr", 20},
+ {"%itmr", 16},
+ {"%iva", 14},
+ {"%pcoq", 18},
+ {"%pcsq", 17},
+ {"%pidr1", 8},
+ {"%pidr2", 9},
+ {"%pidr3", 12},
+ {"%pidr4", 13},
+ {"%ppda", 24},
+ {"%r0", 0},
+ {"%r1", 1},
+ {"%r10", 10},
+ {"%r11", 11},
+ {"%r12", 12},
+ {"%r13", 13},
+ {"%r14", 14},
+ {"%r15", 15},
+ {"%r16", 16},
+ {"%r17", 17},
+ {"%r18", 18},
+ {"%r19", 19},
+ {"%r2", 2},
+ {"%r20", 20},
+ {"%r21", 21},
+ {"%r22", 22},
+ {"%r23", 23},
+ {"%r24", 24},
+ {"%r25", 25},
+ {"%r26", 26},
+ {"%r27", 27},
+ {"%r28", 28},
+ {"%r29", 29},
+ {"%r3", 3},
+ {"%r30", 30},
+ {"%r31", 31},
+ {"%r4", 4},
+ {"%r5", 5},
+ {"%r6", 6},
+ {"%r7", 7},
+ {"%r8", 8},
+ {"%r9", 9},
+ {"%rctr", 0},
+ {"%ret0", 28},
+ {"%ret1", 29},
+ {"%rp", 2},
+ {"%sar", 11},
+ {"%sp", 30},
+ {"%sr0", 0},
+ {"%sr1", 1},
+ {"%sr2", 2},
+ {"%sr3", 3},
+ {"%sr4", 4},
+ {"%sr5", 5},
+ {"%sr6", 6},
+ {"%sr7", 7},
+ {"%tr0", 24},
+ {"%tr1", 25},
+ {"%tr2", 26},
+ {"%tr3", 27},
+ {"%tr4", 28},
+ {"%tr5", 29},
+ {"%tr6", 30},
+ {"%tr7", 31}
+};
+
+/* This table is sorted by order of the length of the string. This is
+ so we check for <> before we check for <. If we had a <> and checked
+ for < first, we would get a false match. */
+static const struct fp_cond_map fp_cond_map[] =
+{
+ {"false?", 0},
+ {"false", 1},
+ {"true?", 30},
+ {"true", 31},
+ {"!<=>", 3},
+ {"!?>=", 8},
+ {"!?<=", 16},
+ {"!<>", 7},
+ {"!>=", 11},
+ {"!?>", 12},
+ {"?<=", 14},
+ {"!<=", 19},
+ {"!?<", 20},
+ {"?>=", 22},
+ {"!?=", 24},
+ {"!=t", 27},
+ {"<=>", 29},
+ {"=t", 5},
+ {"?=", 6},
+ {"?<", 10},
+ {"<=", 13},
+ {"!>", 15},
+ {"?>", 18},
+ {">=", 21},
+ {"!<", 23},
+ {"<>", 25},
+ {"!=", 26},
+ {"!?", 28},
+ {"?", 2},
+ {"=", 4},
+ {"<", 9},
+ {">", 17}
+};
+
+static const struct selector_entry selector_table[] =
+{
+ {"f", e_fsel},
+ {"l", e_lsel},
+ {"ld", e_ldsel},
+ {"lp", e_lpsel},
+ {"lr", e_lrsel},
+ {"ls", e_lssel},
+ {"lt", e_ltsel},
+ {"n", e_nsel},
+ {"nl", e_nlsel},
+ {"nlr", e_nlrsel},
+ {"p", e_psel},
+ {"r", e_rsel},
+ {"rd", e_rdsel},
+ {"rp", e_rpsel},
+ {"rr", e_rrsel},
+ {"rs", e_rssel},
+ {"rt", e_rtsel},
+ {"t", e_tsel},
+};
+
+/* default space and subspace dictionaries */
+
+#define GDB_SYMBOLS GDB_SYMBOLS_SUBSPACE_NAME
+#define GDB_STRINGS GDB_STRINGS_SUBSPACE_NAME
+
+/* pre-defined subsegments (subspaces) for the HPPA. */
+#define SUBSEG_CODE 0
+#define SUBSEG_LIT 1
+#define SUBSEG_MILLI 2
+#define SUBSEG_DATA 0
+#define SUBSEG_BSS 2
+#define SUBSEG_UNWIND 3
+#define SUBSEG_GDB_STRINGS 0
+#define SUBSEG_GDB_SYMBOLS 1
+
+static struct default_subspace_dict pa_def_subspaces[] =
+{
+ {"$CODE$", 1, 1, 1, 0, 0, 0, 24, 0x2c, 0, 8, 0, 0, ".text", SUBSEG_CODE},
+ {"$DATA$", 1, 1, 0, 0, 0, 0, 24, 0x1f, 1, 8, 1, 1, ".data", SUBSEG_DATA},
+ {"$LIT$", 1, 1, 0, 0, 0, 0, 16, 0x2c, 0, 8, 0, 0, ".text", SUBSEG_LIT},
+ {"$MILLICODE$", 1, 1, 0, 0, 0, 0, 8, 0x2c, 0, 8, 0, 0, ".text", SUBSEG_MILLI},
+ {"$BSS$", 1, 1, 0, 0, 0, 1, 80, 0x1f, 1, 8, 1, 1, ".bss", SUBSEG_BSS},
+#ifdef OBJ_ELF
+ {"$UNWIND$", 1, 1, 0, 0, 0, 0, 64, 0x2c, 0, 4, 0, 0, ".PARISC.unwind", SUBSEG_UNWIND},
+#endif
+ {NULL, 0, 1, 0, 0, 0, 0, 255, 0x1f, 0, 4, 0, 0, 0}
+};
+
+static struct default_space_dict pa_def_spaces[] =
+{
+ {"$TEXT$", 0, 1, 1, 0, 8, ASEC_NULL, ".text"},
+ {"$PRIVATE$", 1, 1, 1, 1, 16, ASEC_NULL, ".data"},
+ {NULL, 0, 0, 0, 0, 0, ASEC_NULL, NULL}
+};
+
+/* Misc local definitions used by the assembler. */
+
+/* Return nonzero if the string pointed to by S potentially represents
+ a right or left half of a FP register */
+#define IS_R_SELECT(S) (*(S) == 'R' || *(S) == 'r')
+#define IS_L_SELECT(S) (*(S) == 'L' || *(S) == 'l')
+
+/* These macros are used to maintain spaces/subspaces. */
+#define SPACE_DEFINED(space_chain) (space_chain)->sd_defined
+#define SPACE_USER_DEFINED(space_chain) (space_chain)->sd_user_defined
+#define SPACE_SPNUM(space_chain) (space_chain)->sd_spnum
+#define SPACE_NAME(space_chain) (space_chain)->sd_name
+
+#define SUBSPACE_DEFINED(ss_chain) (ss_chain)->ssd_defined
+#define SUBSPACE_NAME(ss_chain) (ss_chain)->ssd_name
+
+/* Insert FIELD into OPCODE starting at bit START. Continue pa_ip
+ main loop after insertion. */
+
+#define INSERT_FIELD_AND_CONTINUE(OPCODE, FIELD, START) \
+ { \
+ ((OPCODE) |= (FIELD) << (START)); \
+ continue; \
+ }
+
+/* Simple range checking for FIELD againt HIGH and LOW bounds.
+ IGNORE is used to suppress the error message. */
+
+#define CHECK_FIELD(FIELD, HIGH, LOW, IGNORE) \
+ { \
+ if ((FIELD) > (HIGH) || (FIELD) < (LOW)) \
+ { \
+ if (! IGNORE) \
+ as_bad (_("Field out of range [%d..%d] (%d)."), (LOW), (HIGH), \
+ (int) (FIELD));\
+ break; \
+ } \
+ }
+
+#define is_DP_relative(exp) \
+ ((exp).X_op == O_subtract \
+ && strcmp((exp).X_op_symbol->bsym->name, "$global$") == 0)
+
+#define is_PC_relative(exp) \
+ ((exp).X_op == O_subtract \
+ && strcmp((exp).X_op_symbol->bsym->name, "$PIC_pcrel$0") == 0)
+
+/* We need some complex handling for stabs (sym1 - sym2). Luckily, we'll
+ always be able to reduce the expression to a constant, so we don't
+ need real complex handling yet. */
+#define is_complex(exp) \
+ ((exp).X_op != O_constant && (exp).X_op != O_symbol)
+
+/* Actual functions to implement the PA specific code for the assembler. */
+
+/* Called before writing the object file. Make sure entry/exit and
+ proc/procend pairs match. */
+
+void
+pa_check_eof ()
+{
+ if (within_entry_exit)
+ as_fatal (_("Missing .exit\n"));
+
+ if (within_procedure)
+ as_fatal (_("Missing .procend\n"));
+}
+
+/* Check to make sure we have a valid space and subspace. */
+
+static void
+pa_check_current_space_and_subspace ()
+{
+ if (current_space == NULL)
+ as_fatal (_("Not in a space.\n"));
+
+ if (current_subspace == NULL)
+ as_fatal (_("Not in a subspace.\n"));
+}
+
+/* Returns a pointer to the label_symbol_struct for the current space.
+ or NULL if no label_symbol_struct exists for the current space. */
+
+static label_symbol_struct *
+pa_get_label ()
+{
+ label_symbol_struct *label_chain;
+ sd_chain_struct *space_chain = current_space;
+
+ for (label_chain = label_symbols_rootp;
+ label_chain;
+ label_chain = label_chain->lss_next)
+ if (space_chain == label_chain->lss_space && label_chain->lss_label)
+ return label_chain;
+
+ return NULL;
+}
+
+/* Defines a label for the current space. If one is already defined,
+ this function will replace it with the new label. */
+
+void
+pa_define_label (symbol)
+ symbolS *symbol;
+{
+ label_symbol_struct *label_chain = pa_get_label ();
+ sd_chain_struct *space_chain = current_space;
+
+ if (label_chain)
+ label_chain->lss_label = symbol;
+ else
+ {
+ /* Create a new label entry and add it to the head of the chain. */
+ label_chain
+ = (label_symbol_struct *) xmalloc (sizeof (label_symbol_struct));
+ label_chain->lss_label = symbol;
+ label_chain->lss_space = space_chain;
+ label_chain->lss_next = NULL;
+
+ if (label_symbols_rootp)
+ label_chain->lss_next = label_symbols_rootp;
+
+ label_symbols_rootp = label_chain;
+ }
+}
+
+/* Removes a label definition for the current space.
+ If there is no label_symbol_struct entry, then no action is taken. */
+
+static void
+pa_undefine_label ()
+{
+ label_symbol_struct *label_chain;
+ label_symbol_struct *prev_label_chain = NULL;
+ sd_chain_struct *space_chain = current_space;
+
+ for (label_chain = label_symbols_rootp;
+ label_chain;
+ label_chain = label_chain->lss_next)
+ {
+ if (space_chain == label_chain->lss_space && label_chain->lss_label)
+ {
+ /* Remove the label from the chain and free its memory. */
+ if (prev_label_chain)
+ prev_label_chain->lss_next = label_chain->lss_next;
+ else
+ label_symbols_rootp = label_chain->lss_next;
+
+ free (label_chain);
+ break;
+ }
+ prev_label_chain = label_chain;
+ }
+}
+
+
+/* An HPPA-specific version of fix_new. This is required because the HPPA
+ code needs to keep track of some extra stuff. Each call to fix_new_hppa
+ results in the creation of an instance of an hppa_fix_struct. An
+ hppa_fix_struct stores the extra information along with a pointer to the
+ original fixS. This is attached to the original fixup via the
+ tc_fix_data field. */
+
+static void
+fix_new_hppa (frag, where, size, add_symbol, offset, exp, pcrel,
+ r_type, r_field, r_format, arg_reloc, unwind_bits)
+ fragS *frag;
+ int where;
+ int size;
+ symbolS *add_symbol;
+ long offset;
+ expressionS *exp;
+ int pcrel;
+ bfd_reloc_code_real_type r_type;
+ enum hppa_reloc_field_selector_type_alt r_field;
+ int r_format;
+ long arg_reloc;
+ int* unwind_bits;
+{
+ fixS *new_fix;
+
+ struct hppa_fix_struct *hppa_fix = (struct hppa_fix_struct *)
+ obstack_alloc (&notes, sizeof (struct hppa_fix_struct));
+
+ if (exp != NULL)
+ new_fix = fix_new_exp (frag, where, size, exp, pcrel, r_type);
+ else
+ new_fix = fix_new (frag, where, size, add_symbol, offset, pcrel, r_type);
+ new_fix->tc_fix_data = (void *) hppa_fix;
+ hppa_fix->fx_r_type = r_type;
+ hppa_fix->fx_r_field = r_field;
+ hppa_fix->fx_r_format = r_format;
+ hppa_fix->fx_arg_reloc = arg_reloc;
+ hppa_fix->segment = now_seg;
+#ifdef OBJ_SOM
+ if (r_type == R_ENTRY || r_type == R_EXIT)
+ new_fix->fx_offset = *unwind_bits;
+#endif
+
+ /* foo-$global$ is used to access non-automatic storage. $global$
+ is really just a marker and has served its purpose, so eliminate
+ it now so as not to confuse write.c. */
+ if (new_fix->fx_subsy
+ && !strcmp (S_GET_NAME (new_fix->fx_subsy), "$global$"))
+ new_fix->fx_subsy = NULL;
+}
+
+/* Parse a .byte, .word, .long expression for the HPPA. Called by
+ cons via the TC_PARSE_CONS_EXPRESSION macro. */
+
+void
+parse_cons_expression_hppa (exp)
+ expressionS *exp;
+{
+ hppa_field_selector = pa_chk_field_selector (&input_line_pointer);
+ expression (exp);
+}
+
+/* This fix_new is called by cons via TC_CONS_FIX_NEW.
+ hppa_field_selector is set by the parse_cons_expression_hppa. */
+
+void
+cons_fix_new_hppa (frag, where, size, exp)
+ fragS *frag;
+ int where;
+ int size;
+ expressionS *exp;
+{
+ unsigned int rel_type;
+
+ /* Get a base relocation type. */
+ if (is_DP_relative (*exp))
+ rel_type = R_HPPA_GOTOFF;
+ else if (is_complex (*exp))
+ rel_type = R_HPPA_COMPLEX;
+ else
+ rel_type = R_HPPA;
+
+ if (hppa_field_selector != e_psel && hppa_field_selector != e_fsel)
+ as_warn (_("Invalid field selector. Assuming F%%."));
+
+ fix_new_hppa (frag, where, size,
+ (symbolS *) NULL, (offsetT) 0, exp, 0, rel_type,
+ hppa_field_selector, 32, 0, NULL);
+
+ /* Reset field selector to its default state. */
+ hppa_field_selector = 0;
+}
+
+/* This function is called once, at assembler startup time. It should
+ set up all the tables, etc. that the MD part of the assembler will need. */
+
+void
+md_begin ()
+{
+ const char *retval = NULL;
+ int lose = 0;
+ unsigned int i = 0;
+
+ last_call_info = NULL;
+ call_info_root = NULL;
+
+ /* Set the default machine type. */
+ if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, 10))
+ as_warn (_("could not set architecture and machine"));
+
+ /* Folding of text and data segments fails miserably on the PA.
+ Warn user and disable "-R" option. */
+ if (flag_readonly_data_in_text)
+ {
+ as_warn (_("-R option not supported on this target."));
+ flag_readonly_data_in_text = 0;
+ }
+
+ pa_spaces_begin ();
+
+ op_hash = hash_new ();
+
+ while (i < NUMOPCODES)
+ {
+ const char *name = pa_opcodes[i].name;
+ retval = hash_insert (op_hash, name, (struct pa_opcode *) &pa_opcodes[i]);
+ if (retval != NULL && *retval != '\0')
+ {
+ as_fatal (_("Internal error: can't hash `%s': %s\n"), name, retval);
+ lose = 1;
+ }
+ do
+ {
+ if ((pa_opcodes[i].match & pa_opcodes[i].mask)
+ != pa_opcodes[i].match)
+ {
+ fprintf (stderr, _("internal error: losing opcode: `%s' \"%s\"\n"),
+ pa_opcodes[i].name, pa_opcodes[i].args);
+ lose = 1;
+ }
+ ++i;
+ }
+ while (i < NUMOPCODES && !strcmp (pa_opcodes[i].name, name));
+ }
+
+ if (lose)
+ as_fatal (_("Broken assembler. No assembly attempted."));
+
+ /* SOM will change text_section. To make sure we never put
+ anything into the old one switch to the new one now. */
+ subseg_set (text_section, 0);
+
+ dummy_symbol = symbol_find_or_make ("L$dummy");
+ S_SET_SEGMENT (dummy_symbol, text_section);
+}
+
+/* Assemble a single instruction storing it into a frag. */
+void
+md_assemble (str)
+ char *str;
+{
+ char *to;
+
+ /* The had better be something to assemble. */
+ assert (str);
+
+ /* If we are within a procedure definition, make sure we've
+ defined a label for the procedure; handle case where the
+ label was defined after the .PROC directive.
+
+ Note there's not need to diddle with the segment or fragment
+ for the label symbol in this case. We have already switched
+ into the new $CODE$ subspace at this point. */
+ if (within_procedure && last_call_info->start_symbol == NULL)
+ {
+ label_symbol_struct *label_symbol = pa_get_label ();
+
+ if (label_symbol)
+ {
+ if (label_symbol->lss_label)
+ {
+ last_call_info->start_symbol = label_symbol->lss_label;
+ label_symbol->lss_label->bsym->flags |= BSF_FUNCTION;
+#ifdef OBJ_SOM
+ /* Also handle allocation of a fixup to hold the unwind
+ information when the label appears after the proc/procend. */
+ if (within_entry_exit)
+ {
+ char *where = frag_more (0);
+
+ fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
+ NULL, (offsetT) 0, NULL,
+ 0, R_HPPA_ENTRY, e_fsel, 0, 0,
+ (int *)&last_call_info->ci_unwind.descriptor);
+ }
+#endif
+ }
+ else
+ as_bad (_("Missing function name for .PROC (corrupted label chain)"));
+ }
+ else
+ as_bad (_("Missing function name for .PROC"));
+ }
+
+ /* Assemble the instruction. Results are saved into "the_insn". */
+ pa_ip (str);
+
+ /* Get somewhere to put the assembled instrution. */
+ to = frag_more (4);
+
+ /* Output the opcode. */
+ md_number_to_chars (to, the_insn.opcode, 4);
+
+ /* If necessary output more stuff. */
+ if (the_insn.reloc != R_HPPA_NONE)
+ fix_new_hppa (frag_now, (to - frag_now->fr_literal), 4, NULL,
+ (offsetT) 0, &the_insn.exp, the_insn.pcrel,
+ the_insn.reloc, the_insn.field_selector,
+ the_insn.format, the_insn.arg_reloc, NULL);
+}
+
+/* Do the real work for assembling a single instruction. Store results
+ into the global "the_insn" variable. */
+
+static void
+pa_ip (str)
+ char *str;
+{
+ char *error_message = "";
+ char *s, c, *argstart, *name, *save_s;
+ const char *args;
+ int match = FALSE;
+ int comma = 0;
+ int cmpltr, nullif, flag, cond, num;
+ unsigned long opcode;
+ struct pa_opcode *insn;
+
+ /* We must have a valid space and subspace. */
+ pa_check_current_space_and_subspace ();
+
+ /* Skip to something interesting. */
+ for (s = str; isupper (*s) || islower (*s) || (*s >= '0' && *s <= '3'); ++s)
+ ;
+
+ switch (*s)
+ {
+
+ case '\0':
+ break;
+
+ case ',':
+ comma = 1;
+
+ /*FALLTHROUGH */
+
+ case ' ':
+ *s++ = '\0';
+ break;
+
+ default:
+ as_fatal (_("Unknown opcode: `%s'"), str);
+ }
+
+ save_s = str;
+
+ /* Convert everything into lower case. */
+ while (*save_s)
+ {
+ if (isupper (*save_s))
+ *save_s = tolower (*save_s);
+ save_s++;
+ }
+
+ /* Look up the opcode in the has table. */
+ if ((insn = (struct pa_opcode *) hash_find (op_hash, str)) == NULL)
+ {
+ as_bad ("Unknown opcode: `%s'", str);
+ return;
+ }
+
+ if (comma)
+ {
+ *--s = ',';
+ }
+
+ /* Mark the location where arguments for the instruction start, then
+ start processing them. */
+ argstart = s;
+ for (;;)
+ {
+ /* Do some initialization. */
+ opcode = insn->match;
+ memset (&the_insn, 0, sizeof (the_insn));
+
+ the_insn.reloc = R_HPPA_NONE;
+
+ /* If this instruction is specific to a particular architecture,
+ then set a new architecture. */
+ /* But do not automatically promote to pa2.0. The automatic promotion
+ crud is for compatability with HP's old assemblers only. */
+ if (insn->arch < 20
+ && bfd_get_mach (stdoutput) < insn->arch)
+ {
+ if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, insn->arch))
+ as_warn (_("could not update architecture and machine"));
+ }
+ else if (bfd_get_mach (stdoutput) < insn->arch)
+ {
+ match = FALSE;
+ goto failed;
+ }
+
+ /* Build the opcode, checking as we go to make
+ sure that the operands match. */
+ for (args = insn->args;; ++args)
+ {
+ switch (*args)
+ {
+
+ /* End of arguments. */
+ case '\0':
+ if (*s == '\0')
+ match = TRUE;
+ break;
+
+ case '+':
+ if (*s == '+')
+ {
+ ++s;
+ continue;
+ }
+ if (*s == '-')
+ continue;
+ break;
+
+ /* These must match exactly. */
+ case '(':
+ case ')':
+ case ',':
+ case ' ':
+ if (*s++ == *args)
+ continue;
+ break;
+
+ /* Handle a 5 bit register or control register field at 10. */
+ case 'b':
+ case '^':
+ num = pa_parse_number (&s, 0);
+ CHECK_FIELD (num, 31, 0, 0);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 21);
+
+ /* Handle a 5 bit register field at 15. */
+ case 'x':
+ num = pa_parse_number (&s, 0);
+ CHECK_FIELD (num, 31, 0, 0);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 16);
+
+ /* Handle a 5 bit register field at 31. */
+ case 'y':
+ case 't':
+ num = pa_parse_number (&s, 0);
+ CHECK_FIELD (num, 31, 0, 0);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
+
+ /* Handle a 5 bit field length at 31. */
+ case 'T':
+ num = pa_get_absolute_expression (&the_insn, &s);
+ s = expr_end;
+ CHECK_FIELD (num, 32, 1, 0);
+ INSERT_FIELD_AND_CONTINUE (opcode, 32 - num, 0);
+
+ /* Handle a 5 bit immediate at 15. */
+ case '5':
+ num = pa_get_absolute_expression (&the_insn, &s);
+ s = expr_end;
+ CHECK_FIELD (num, 15, -16, 0);
+ low_sign_unext (num, 5, &num);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 16);
+
+ /* Handle a 5 bit immediate at 31. */
+ case 'V':
+ num = pa_get_absolute_expression (&the_insn, &s);
+ s = expr_end;
+ CHECK_FIELD (num, 15, -16, 0)
+ low_sign_unext (num, 5, &num);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
+
+ /* Handle an unsigned 5 bit immediate at 31. */
+ case 'r':
+ num = pa_get_absolute_expression (&the_insn, &s);
+ s = expr_end;
+ CHECK_FIELD (num, 31, 0, 0);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
+
+ /* Handle an unsigned 5 bit immediate at 15. */
+ case 'R':
+ num = pa_get_absolute_expression (&the_insn, &s);
+ s = expr_end;
+ CHECK_FIELD (num, 31, 0, 0);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 16);
+
+ /* Handle a 2 bit space identifier at 17. */
+ case 's':
+ num = pa_parse_number (&s, 0);
+ CHECK_FIELD (num, 3, 0, 1);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 14);
+
+ /* Handle a 3 bit space identifier at 18. */
+ case 'S':
+ num = pa_parse_number (&s, 0);
+ CHECK_FIELD (num, 7, 0, 1);
+ dis_assemble_3 (num, &num);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 13);
+
+ /* Handle a completer for an indexing load or store. */
+ case 'c':
+ {
+ int uu = 0;
+ int m = 0;
+ int i = 0;
+ while (*s == ',' && i < 2)
+ {
+ s++;
+ if (strncasecmp (s, "sm", 2) == 0)
+ {
+ uu = 1;
+ m = 1;
+ s++;
+ i++;
+ }
+ else if (strncasecmp (s, "m", 1) == 0)
+ m = 1;
+ else if (strncasecmp (s, "s", 1) == 0)
+ uu = 1;
+ else
+ as_bad (_("Invalid Indexed Load Completer."));
+ s++;
+ i++;
+ }
+ if (i > 2)
+ as_bad (_("Invalid Indexed Load Completer Syntax."));
+ opcode |= m << 5;
+ INSERT_FIELD_AND_CONTINUE (opcode, uu, 13);
+ }
+
+ /* Handle a short load/store completer. */
+ case 'C':
+ {
+ int a = 0;
+ int m = 0;
+ if (*s == ',')
+ {
+ s++;
+ if (strncasecmp (s, "ma", 2) == 0)
+ {
+ a = 0;
+ m = 1;
+ }
+ else if (strncasecmp (s, "mb", 2) == 0)
+ {
+ a = 1;
+ m = 1;
+ }
+ else
+ as_bad (_("Invalid Short Load/Store Completer."));
+ s += 2;
+ }
+
+ if (*args == 'C')
+ {
+ opcode |= m << 5;
+ INSERT_FIELD_AND_CONTINUE (opcode, a, 13);
+ }
+ }
+
+ /* Handle a stbys completer. */
+ case 'Y':
+ {
+ int a = 0;
+ int m = 0;
+ int i = 0;
+ while (*s == ',' && i < 2)
+ {
+ s++;
+ if (strncasecmp (s, "m", 1) == 0)
+ m = 1;
+ else if (strncasecmp (s, "b", 1) == 0)
+ a = 0;
+ else if (strncasecmp (s, "e", 1) == 0)
+ a = 1;
+ else
+ as_bad (_("Invalid Store Bytes Short Completer"));
+ s++;
+ i++;
+ }
+ if (i > 2)
+ as_bad (_("Invalid Store Bytes Short Completer"));
+ opcode |= m << 5;
+ INSERT_FIELD_AND_CONTINUE (opcode, a, 13);
+ }
+
+ /* Handle a non-negated compare/stubtract condition. */
+ case '<':
+ cmpltr = pa_parse_nonneg_cmpsub_cmpltr (&s, 1);
+ if (cmpltr < 0)
+ {
+ as_bad (_("Invalid Compare/Subtract Condition: %c"), *s);
+ cmpltr = 0;
+ }
+ INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
+
+ /* Handle a negated or non-negated compare/subtract condition. */
+ case '?':
+ save_s = s;
+ cmpltr = pa_parse_nonneg_cmpsub_cmpltr (&s, 1);
+ if (cmpltr < 0)
+ {
+ s = save_s;
+ cmpltr = pa_parse_neg_cmpsub_cmpltr (&s, 1);
+ if (cmpltr < 0)
+ {
+ as_bad (_("Invalid Compare/Subtract Condition."));
+ cmpltr = 0;
+ }
+ else
+ {
+ /* Negated condition requires an opcode change. */
+ opcode |= 1 << 27;
+ }
+ }
+
+ INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
+
+ /* Handle non-negated add condition. */
+ case '!':
+ cmpltr = pa_parse_nonneg_add_cmpltr (&s, 1);
+ if (cmpltr < 0)
+ {
+ as_bad (_("Invalid Compare/Subtract Condition: %c"), *s);
+ cmpltr = 0;
+ }
+ INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
+
+ /* Handle a negated or non-negated add condition. */
+ case '@':
+ save_s = s;
+ cmpltr = pa_parse_nonneg_add_cmpltr (&s, 1);
+ if (cmpltr < 0)
+ {
+ s = save_s;
+ cmpltr = pa_parse_neg_add_cmpltr (&s, 1);
+ if (cmpltr < 0)
+ {
+ as_bad (_("Invalid Compare/Subtract Condition"));
+ cmpltr = 0;
+ }
+ else
+ {
+ /* Negated condition requires an opcode change. */
+ opcode |= 1 << 27;
+ }
+ }
+ INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
+
+ /* Handle a compare/subtract condition. */
+ case 'a':
+ cmpltr = 0;
+ flag = 0;
+ if (*s == ',')
+ {
+ s++;
+ name = s;
+ while (*s != ',' && *s != ' ' && *s != '\t')
+ s += 1;
+ c = *s;
+ *s = 0x00;
+ if (strcmp (name, "=") == 0)
+ cmpltr = 1;
+ else if (strcmp (name, "<") == 0)
+ cmpltr = 2;
+ else if (strcmp (name, "<=") == 0)
+ cmpltr = 3;
+ else if (strcasecmp (name, "<<") == 0)
+ cmpltr = 4;
+ else if (strcasecmp (name, "<<=") == 0)
+ cmpltr = 5;
+ else if (strcasecmp (name, "sv") == 0)
+ cmpltr = 6;
+ else if (strcasecmp (name, "od") == 0)
+ cmpltr = 7;
+ else if (strcasecmp (name, "tr") == 0)
+ {
+ cmpltr = 0;
+ flag = 1;
+ }
+ else if (strcmp (name, "<>") == 0)
+ {
+ cmpltr = 1;
+ flag = 1;
+ }
+ else if (strcmp (name, ">=") == 0)
+ {
+ cmpltr = 2;
+ flag = 1;
+ }
+ else if (strcmp (name, ">") == 0)
+ {
+ cmpltr = 3;
+ flag = 1;
+ }
+ else if (strcasecmp (name, ">>=") == 0)
+ {
+ cmpltr = 4;
+ flag = 1;
+ }
+ else if (strcasecmp (name, ">>") == 0)
+ {
+ cmpltr = 5;
+ flag = 1;
+ }
+ else if (strcasecmp (name, "nsv") == 0)
+ {
+ cmpltr = 6;
+ flag = 1;
+ }
+ else if (strcasecmp (name, "ev") == 0)
+ {
+ cmpltr = 7;
+ flag = 1;
+ }
+ else
+ as_bad (_("Invalid Add Condition: %s"), name);
+ *s = c;
+ }
+ opcode |= cmpltr << 13;
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 12);
+
+ /* Handle a non-negated add condition. */
+ case 'd':
+ cmpltr = 0;
+ flag = 0;
+ if (*s == ',')
+ {
+ s++;
+ name = s;
+ while (*s != ',' && *s != ' ' && *s != '\t')
+ s += 1;
+ c = *s;
+ *s = 0x00;
+ if (strcmp (name, "=") == 0)
+ cmpltr = 1;
+ else if (strcmp (name, "<") == 0)
+ cmpltr = 2;
+ else if (strcmp (name, "<=") == 0)
+ cmpltr = 3;
+ else if (strcasecmp (name, "nuv") == 0)
+ cmpltr = 4;
+ else if (strcasecmp (name, "znv") == 0)
+ cmpltr = 5;
+ else if (strcasecmp (name, "sv") == 0)
+ cmpltr = 6;
+ else if (strcasecmp (name, "od") == 0)
+ cmpltr = 7;
+ else if (strcasecmp (name, "tr") == 0)
+ {
+ cmpltr = 0;
+ flag = 1;
+ }
+ else if (strcmp (name, "<>") == 0)
+ {
+ cmpltr = 1;
+ flag = 1;
+ }
+ else if (strcmp (name, ">=") == 0)
+ {
+ cmpltr = 2;
+ flag = 1;
+ }
+ else if (strcmp (name, ">") == 0)
+ {
+ cmpltr = 3;
+ flag = 1;
+ }
+ else if (strcasecmp (name, "uv") == 0)
+ {
+ cmpltr = 4;
+ flag = 1;
+ }
+ else if (strcasecmp (name, "vnz") == 0)
+ {
+ cmpltr = 5;
+ flag = 1;
+ }
+ else if (strcasecmp (name, "nsv") == 0)
+ {
+ cmpltr = 6;
+ flag = 1;
+ }
+ else if (strcasecmp (name, "ev") == 0)
+ {
+ cmpltr = 7;
+ flag = 1;
+ }
+ else
+ as_bad (_("Invalid Add Condition: %s"), name);
+ *s = c;
+ }
+ opcode |= cmpltr << 13;
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 12);
+
+ /* HANDLE a logical instruction condition. */
+ case '&':
+ cmpltr = 0;
+ flag = 0;
+ if (*s == ',')
+ {
+ s++;
+ name = s;
+ while (*s != ',' && *s != ' ' && *s != '\t')
+ s += 1;
+ c = *s;
+ *s = 0x00;
+
+
+ if (strcmp (name, "=") == 0)
+ cmpltr = 1;
+ else if (strcmp (name, "<") == 0)
+ cmpltr = 2;
+ else if (strcmp (name, "<=") == 0)
+ cmpltr = 3;
+ else if (strcasecmp (name, "od") == 0)
+ cmpltr = 7;
+ else if (strcasecmp (name, "tr") == 0)
+ {
+ cmpltr = 0;
+ flag = 1;
+ }
+ else if (strcmp (name, "<>") == 0)
+ {
+ cmpltr = 1;
+ flag = 1;
+ }
+ else if (strcmp (name, ">=") == 0)
+ {
+ cmpltr = 2;
+ flag = 1;
+ }
+ else if (strcmp (name, ">") == 0)
+ {
+ cmpltr = 3;
+ flag = 1;
+ }
+ else if (strcasecmp (name, "ev") == 0)
+ {
+ cmpltr = 7;
+ flag = 1;
+ }
+ else
+ as_bad (_("Invalid Logical Instruction Condition."));
+ *s = c;
+ }
+ opcode |= cmpltr << 13;
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 12);
+
+ /* Handle a unit instruction condition. */
+ case 'U':
+ cmpltr = 0;
+ flag = 0;
+ if (*s == ',')
+ {
+ s++;
+
+
+ if (strncasecmp (s, "sbz", 3) == 0)
+ {
+ cmpltr = 2;
+ s += 3;
+ }
+ else if (strncasecmp (s, "shz", 3) == 0)
+ {
+ cmpltr = 3;
+ s += 3;
+ }
+ else if (strncasecmp (s, "sdc", 3) == 0)
+ {
+ cmpltr = 4;
+ s += 3;
+ }
+ else if (strncasecmp (s, "sbc", 3) == 0)
+ {
+ cmpltr = 6;
+ s += 3;
+ }
+ else if (strncasecmp (s, "shc", 3) == 0)
+ {
+ cmpltr = 7;
+ s += 3;
+ }
+ else if (strncasecmp (s, "tr", 2) == 0)
+ {
+ cmpltr = 0;
+ flag = 1;
+ s += 2;
+ }
+ else if (strncasecmp (s, "nbz", 3) == 0)
+ {
+ cmpltr = 2;
+ flag = 1;
+ s += 3;
+ }
+ else if (strncasecmp (s, "nhz", 3) == 0)
+ {
+ cmpltr = 3;
+ flag = 1;
+ s += 3;
+ }
+ else if (strncasecmp (s, "ndc", 3) == 0)
+ {
+ cmpltr = 4;
+ flag = 1;
+ s += 3;
+ }
+ else if (strncasecmp (s, "nbc", 3) == 0)
+ {
+ cmpltr = 6;
+ flag = 1;
+ s += 3;
+ }
+ else if (strncasecmp (s, "nhc", 3) == 0)
+ {
+ cmpltr = 7;
+ flag = 1;
+ s += 3;
+ }
+ else
+ as_bad (_("Invalid Logical Instruction Condition."));
+ }
+ opcode |= cmpltr << 13;
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 12);
+
+ /* Handle a shift/extract/deposit condition. */
+ case '|':
+ case '>':
+ cmpltr = 0;
+ if (*s == ',')
+ {
+ save_s = s++;
+
+
+ name = s;
+ while (*s != ',' && *s != ' ' && *s != '\t')
+ s += 1;
+ c = *s;
+ *s = 0x00;
+ if (strcmp (name, "=") == 0)
+ cmpltr = 1;
+ else if (strcmp (name, "<") == 0)
+ cmpltr = 2;
+ else if (strcasecmp (name, "od") == 0)
+ cmpltr = 3;
+ else if (strcasecmp (name, "tr") == 0)
+ cmpltr = 4;
+ else if (strcmp (name, "<>") == 0)
+ cmpltr = 5;
+ else if (strcmp (name, ">=") == 0)
+ cmpltr = 6;
+ else if (strcasecmp (name, "ev") == 0)
+ cmpltr = 7;
+ /* Handle movb,n. Put things back the way they were.
+ This includes moving s back to where it started. */
+ else if (strcasecmp (name, "n") == 0 && *args == '|')
+ {
+ *s = c;
+ s = save_s;
+ continue;
+ }
+ else
+ as_bad (_("Invalid Shift/Extract/Deposit Condition."));
+ *s = c;
+ }
+ INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
+
+ /* Handle bvb and bb conditions. */
+ case '~':
+ cmpltr = 0;
+ if (*s == ',')
+ {
+ s++;
+ if (strncmp (s, "<", 1) == 0)
+ {
+ cmpltr = 0;
+ s++;
+ }
+ else if (strncmp (s, ">=", 2) == 0)
+ {
+ cmpltr = 1;
+ s += 2;
+ }
+ else
+ as_bad (_("Invalid Bit Branch Condition: %c"), *s);
+ }
+ INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 15);
+
+ /* Handle a system control completer. */
+ case 'Z':
+ if (*s == ',' && (*(s + 1) == 'm' || *(s + 1) == 'M'))
+ {
+ flag = 1;
+ s += 2;
+ }
+ else
+ flag = 0;
+
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 5);
+
+ /* Handle a nullification completer for branch instructions. */
+ case 'n':
+ nullif = pa_parse_nullif (&s);
+ INSERT_FIELD_AND_CONTINUE (opcode, nullif, 1);
+
+ /* Handle a nullification completer for copr and spop insns. */
+ case 'N':
+ nullif = pa_parse_nullif (&s);
+ INSERT_FIELD_AND_CONTINUE (opcode, nullif, 5);
+
+
+ /* Handle a 11 bit immediate at 31. */
+ case 'i':
+ the_insn.field_selector = pa_chk_field_selector (&s);
+ get_expression (s);
+ s = expr_end;
+ if (the_insn.exp.X_op == O_constant)
+ {
+ num = evaluate_absolute (&the_insn);
+ CHECK_FIELD (num, 1023, -1024, 0);
+ low_sign_unext (num, 11, &num);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
+ }
+ else
+ {
+ if (is_DP_relative (the_insn.exp))
+ the_insn.reloc = R_HPPA_GOTOFF;
+ else if (is_PC_relative (the_insn.exp))
+ the_insn.reloc = R_HPPA_PCREL_CALL;
+ else
+ the_insn.reloc = R_HPPA;
+ the_insn.format = 11;
+ continue;
+ }
+
+
+ /* Handle a 14 bit immediate at 31. */
+ case 'j':
+ the_insn.field_selector = pa_chk_field_selector (&s);
+ get_expression (s);
+ s = expr_end;
+ if (the_insn.exp.X_op == O_constant)
+ {
+ num = evaluate_absolute (&the_insn);
+ CHECK_FIELD (num, 8191, -8192, 0);
+ low_sign_unext (num, 14, &num);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
+ }
+ else
+ {
+ if (is_DP_relative (the_insn.exp))
+ the_insn.reloc = R_HPPA_GOTOFF;
+ else if (is_PC_relative (the_insn.exp))
+ the_insn.reloc = R_HPPA_PCREL_CALL;
+ else
+ the_insn.reloc = R_HPPA;
+ the_insn.format = 14;
+ continue;
+ }
+
+ /* Handle a 21 bit immediate at 31. */
+ case 'k':
+ the_insn.field_selector = pa_chk_field_selector (&s);
+ get_expression (s);
+ s = expr_end;
+ if (the_insn.exp.X_op == O_constant)
+ {
+ num = evaluate_absolute (&the_insn);
+ CHECK_FIELD (num >> 11, 1048575, -1048576, 0);
+ dis_assemble_21 (num, &num);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
+ }
+ else
+ {
+ if (is_DP_relative (the_insn.exp))
+ the_insn.reloc = R_HPPA_GOTOFF;
+ else if (is_PC_relative (the_insn.exp))
+ the_insn.reloc = R_HPPA_PCREL_CALL;
+ else
+ the_insn.reloc = R_HPPA;
+ the_insn.format = 21;
+ continue;
+ }
+
+ /* Handle a 12 bit branch displacement. */
+ case 'w':
+ the_insn.field_selector = pa_chk_field_selector (&s);
+ get_expression (s);
+ s = expr_end;
+ the_insn.pcrel = 1;
+ if (!strcmp (S_GET_NAME (the_insn.exp.X_add_symbol), "L$0\001"))
+ {
+ unsigned int w1, w, result;
+
+ num = evaluate_absolute (&the_insn);
+ if (num % 4)
+ {
+ as_bad (_("Branch to unaligned address"));
+ break;
+ }
+ CHECK_FIELD (num, 8199, -8184, 0);
+ sign_unext ((num - 8) >> 2, 12, &result);
+ dis_assemble_12 (result, &w1, &w);
+ INSERT_FIELD_AND_CONTINUE (opcode, ((w1 << 2) | w), 0);
+ }
+ else
+ {
+ the_insn.reloc = R_HPPA_PCREL_CALL;
+ the_insn.format = 12;
+ the_insn.arg_reloc = last_call_desc.arg_reloc;
+ memset (&last_call_desc, 0, sizeof (struct call_desc));
+ s = expr_end;
+ continue;
+ }
+
+ /* Handle a 17 bit branch displacement. */
+ case 'W':
+ the_insn.field_selector = pa_chk_field_selector (&s);
+ get_expression (s);
+ s = expr_end;
+ the_insn.pcrel = 1;
+ if (!the_insn.exp.X_add_symbol
+ || !strcmp (S_GET_NAME (the_insn.exp.X_add_symbol),
+ "L$0\001"))
+ {
+ unsigned int w2, w1, w, result;
+
+ num = evaluate_absolute (&the_insn);
+ if (num % 4)
+ {
+ as_bad (_("Branch to unaligned address"));
+ break;
+ }
+ CHECK_FIELD (num, 262143, -262144, 0);
+
+ if (the_insn.exp.X_add_symbol)
+ num -= 8;
+
+ sign_unext (num >> 2, 17, &result);
+ dis_assemble_17 (result, &w1, &w2, &w);
+ INSERT_FIELD_AND_CONTINUE (opcode,
+ ((w2 << 2) | (w1 << 16) | w), 0);
+ }
+ else
+ {
+ the_insn.reloc = R_HPPA_PCREL_CALL;
+ the_insn.format = 17;
+ the_insn.arg_reloc = last_call_desc.arg_reloc;
+ memset (&last_call_desc, 0, sizeof (struct call_desc));
+ continue;
+ }
+
+ /* Handle an absolute 17 bit branch target. */
+ case 'z':
+ the_insn.field_selector = pa_chk_field_selector (&s);
+ get_expression (s);
+ s = expr_end;
+ the_insn.pcrel = 0;
+ if (!the_insn.exp.X_add_symbol
+ || !strcmp (S_GET_NAME (the_insn.exp.X_add_symbol),
+ "L$0\001"))
+ {
+ unsigned int w2, w1, w, result;
+
+ num = evaluate_absolute (&the_insn);
+ if (num % 4)
+ {
+ as_bad (_("Branch to unaligned address"));
+ break;
+ }
+ CHECK_FIELD (num, 262143, -262144, 0);
+
+ if (the_insn.exp.X_add_symbol)
+ num -= 8;
+
+ sign_unext (num >> 2, 17, &result);
+ dis_assemble_17 (result, &w1, &w2, &w);
+ INSERT_FIELD_AND_CONTINUE (opcode,
+ ((w2 << 2) | (w1 << 16) | w), 0);
+ }
+ else
+ {
+ the_insn.reloc = R_HPPA_ABS_CALL;
+ the_insn.format = 17;
+ the_insn.arg_reloc = last_call_desc.arg_reloc;
+ memset (&last_call_desc, 0, sizeof (struct call_desc));
+ continue;
+ }
+
+ /* Handle a 5 bit shift count at 26. */
+ case 'p':
+ num = pa_get_absolute_expression (&the_insn, &s);
+ s = expr_end;
+ CHECK_FIELD (num, 31, 0, 0);
+ INSERT_FIELD_AND_CONTINUE (opcode, 31 - num, 5);
+
+ /* Handle a 5 bit bit position at 26. */
+ case 'P':
+ num = pa_get_absolute_expression (&the_insn, &s);
+ s = expr_end;
+ CHECK_FIELD (num, 31, 0, 0);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 5);
+
+ /* Handle a 5 bit immediate at 10. */
+ case 'Q':
+
+ num = pa_get_absolute_expression (&the_insn, &s);
+ if (the_insn.exp.X_op != O_constant)
+ break;
+ s = expr_end;
+ CHECK_FIELD (num, 31, 0, 0);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 21);
+
+ /* Handle a 13 bit immediate at 18. */
+ case 'A':
+ num = pa_get_absolute_expression (&the_insn, &s);
+ s = expr_end;
+ CHECK_FIELD (num, 8191, 0, 0);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 13);
+
+ /* Handle a 26 bit immediate at 31. */
+ case 'D':
+ num = pa_get_absolute_expression (&the_insn, &s);
+ s = expr_end;
+ CHECK_FIELD (num, 671108864, 0, 0);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
+
+ /* Handle a 3 bit SFU identifier at 25. */
+ case 'f':
+ if (*s++ != ',')
+ as_bad (_("Invalid SFU identifier"));
+ num = pa_get_absolute_expression (&the_insn, &s);
+ s = expr_end;
+ CHECK_FIELD (num, 7, 0, 0);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 6);
+
+ /* Handle a 20 bit SOP field for spop0. */
+ case 'O':
+ num = pa_get_absolute_expression (&the_insn, &s);
+ s = expr_end;
+ CHECK_FIELD (num, 1048575, 0, 0);
+ num = (num & 0x1f) | ((num & 0x000fffe0) << 6);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
+
+ /* Handle a 15bit SOP field for spop1. */
+ case 'o':
+ num = pa_get_absolute_expression (&the_insn, &s);
+ s = expr_end;
+ CHECK_FIELD (num, 32767, 0, 0);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 11);
+
+ /* Handle a 10bit SOP field for spop3. */
+ case '0':
+ num = pa_get_absolute_expression (&the_insn, &s);
+ s = expr_end;
+ CHECK_FIELD (num, 1023, 0, 0);
+ num = (num & 0x1f) | ((num & 0x000003e0) << 6);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
+
+ /* Handle a 15 bit SOP field for spop2. */
+ case '1':
+ num = pa_get_absolute_expression (&the_insn, &s);
+ s = expr_end;
+ CHECK_FIELD (num, 32767, 0, 0);
+ num = (num & 0x1f) | ((num & 0x00007fe0) << 6);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
+
+ /* Handle a 3-bit co-processor ID field. */
+ case 'u':
+ if (*s++ != ',')
+ as_bad (_("Invalid COPR identifier"));
+ num = pa_get_absolute_expression (&the_insn, &s);
+ s = expr_end;
+ CHECK_FIELD (num, 7, 0, 0);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 6);
+
+ /* Handle a 22bit SOP field for copr. */
+ case '2':
+ num = pa_get_absolute_expression (&the_insn, &s);
+ s = expr_end;
+ CHECK_FIELD (num, 4194303, 0, 0);
+ num = (num & 0x1f) | ((num & 0x003fffe0) << 4);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
+
+
+ /* Handle a source FP operand format completer. */
+ case 'F':
+ flag = pa_parse_fp_format (&s);
+ the_insn.fpof1 = flag;
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
+
+ /* Handle a destination FP operand format completer. */
+ case 'G':
+ /* pa_parse_format needs the ',' prefix. */
+ s--;
+ flag = pa_parse_fp_format (&s);
+ the_insn.fpof2 = flag;
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 13);
+
+ /* Handle FP compare conditions. */
+ case 'M':
+ cond = pa_parse_fp_cmp_cond (&s);
+ INSERT_FIELD_AND_CONTINUE (opcode, cond, 0);
+
+ /* Handle L/R register halves like 't'. */
+ case 'v':
+ {
+ struct pa_11_fp_reg_struct result;
+
+ pa_parse_number (&s, &result);
+ CHECK_FIELD (result.number_part, 31, 0, 0);
+ opcode |= result.number_part;
+
+ /* 0x30 opcodes are FP arithmetic operation opcodes
+ and need to be turned into 0x38 opcodes. This
+ is not necessary for loads/stores. */
+ if (need_pa11_opcode (&the_insn, &result)
+ && ((opcode & 0xfc000000) == 0x30000000))
+ opcode |= 1 << 27;
+
+ INSERT_FIELD_AND_CONTINUE (opcode, result.l_r_select & 1, 6);
+ }
+
+ /* Handle L/R register halves like 'b'. */
+ case 'E':
+ {
+ struct pa_11_fp_reg_struct result;
+
+ pa_parse_number (&s, &result);
+ CHECK_FIELD (result.number_part, 31, 0, 0);
+ opcode |= result.number_part << 21;
+ if (need_pa11_opcode (&the_insn, &result))
+ {
+ opcode |= (result.l_r_select & 1) << 7;
+ opcode |= 1 << 27;
+ }
+ continue;
+ }
+
+ /* Handle L/R register halves like 'b'. */
+ case '3':
+ {
+ struct pa_11_fp_reg_struct result;
+ int regnum;
+
+ pa_parse_number (&s, &result);
+ CHECK_FIELD (result.number_part, 31, 0, 0);
+ opcode |= (result.number_part & 0x1c) << 11;
+ opcode |= (result.number_part & 0x3) << 9;
+ opcode |= (result.l_r_select & 1) << 8;
+ continue;
+ }
+
+ /* Handle L/R register halves like 'x'. */
+ case 'e':
+ {
+ struct pa_11_fp_reg_struct result;
+
+ pa_parse_number (&s, &result);
+ CHECK_FIELD (result.number_part, 31, 0, 0);
+ opcode |= (result.number_part & 0x1f) << 16;
+ if (need_pa11_opcode (&the_insn, &result))
+ {
+ opcode |= (result.l_r_select & 1) << 1;
+ }
+ continue;
+ }
+
+ /* Handle L/R register halves like 'x'. */
+ case 'X':
+ {
+ struct pa_11_fp_reg_struct result;
+
+ pa_parse_number (&s, &result);
+ CHECK_FIELD (result.number_part, 31, 0, 0);
+ opcode |= (result.number_part & 0x1f) << 16;
+ if (need_pa11_opcode (&the_insn, &result))
+ {
+ opcode |= (result.l_r_select & 1) << 12;
+ opcode |= 1 << 27;
+ }
+ continue;
+ }
+
+ /* Handle a 5 bit register field at 10. */
+ case '4':
+ {
+ struct pa_11_fp_reg_struct result;
+
+ pa_parse_number (&s, &result);
+ CHECK_FIELD (result.number_part, 31, 0, 0);
+ if (the_insn.fpof1 == SGL)
+ {
+ if (result.number_part < 16)
+ {
+ as_bad (_("Invalid register for single precision fmpyadd or fmpysub"));
+ break;
+ }
+
+ result.number_part &= 0xF;
+ result.number_part |= (result.l_r_select & 1) << 4;
+ }
+ INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 21);
+ }
+
+ /* Handle a 5 bit register field at 15. */
+ case '6':
+ {
+ struct pa_11_fp_reg_struct result;
+
+ pa_parse_number (&s, &result);
+ CHECK_FIELD (result.number_part, 31, 0, 0);
+ if (the_insn.fpof1 == SGL)
+ {
+ if (result.number_part < 16)
+ {
+ as_bad (_("Invalid register for single precision fmpyadd or fmpysub"));
+ break;
+ }
+ result.number_part &= 0xF;
+ result.number_part |= (result.l_r_select & 1) << 4;
+ }
+ INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 16);
+ }
+
+ /* Handle a 5 bit register field at 31. */
+ case '7':
+ {
+ struct pa_11_fp_reg_struct result;
+
+ pa_parse_number (&s, &result);
+ CHECK_FIELD (result.number_part, 31, 0, 0);
+ if (the_insn.fpof1 == SGL)
+ {
+ if (result.number_part < 16)
+ {
+ as_bad (_("Invalid register for single precision fmpyadd or fmpysub"));
+ break;
+ }
+ result.number_part &= 0xF;
+ result.number_part |= (result.l_r_select & 1) << 4;
+ }
+ INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 0);
+ }
+
+ /* Handle a 5 bit register field at 20. */
+ case '8':
+ {
+ struct pa_11_fp_reg_struct result;
+
+ pa_parse_number (&s, &result);
+ CHECK_FIELD (result.number_part, 31, 0, 0);
+ if (the_insn.fpof1 == SGL)
+ {
+ if (result.number_part < 16)
+ {
+ as_bad (_("Invalid register for single precision fmpyadd or fmpysub"));
+ break;
+ }
+ result.number_part &= 0xF;
+ result.number_part |= (result.l_r_select & 1) << 4;
+ }
+ INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 11);
+ }
+
+ /* Handle a 5 bit register field at 25. */
+ case '9':
+ {
+ struct pa_11_fp_reg_struct result;
+
+ pa_parse_number (&s, &result);
+ CHECK_FIELD (result.number_part, 31, 0, 0);
+ if (the_insn.fpof1 == SGL)
+ {
+ if (result.number_part < 16)
+ {
+ as_bad (_("Invalid register for single precision fmpyadd or fmpysub"));
+ break;
+ }
+ result.number_part &= 0xF;
+ result.number_part |= (result.l_r_select & 1) << 4;
+ }
+ INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 6);
+ }
+
+ /* Handle a floating point operand format at 26.
+ Only allows single and double precision. */
+ case 'H':
+ flag = pa_parse_fp_format (&s);
+ switch (flag)
+ {
+ case SGL:
+ opcode |= 0x20;
+ case DBL:
+ the_insn.fpof1 = flag;
+ continue;
+
+ case QUAD:
+ case ILLEGAL_FMT:
+ default:
+ as_bad (_("Invalid Floating Point Operand Format."));
+ }
+ break;
+
+ default:
+ abort ();
+ }
+ break;
+ }
+
+ failed:
+ /* Check if the args matched. */
+ if (match == FALSE)
+ {
+ if (&insn[1] - pa_opcodes < (int) NUMOPCODES
+ && !strcmp (insn->name, insn[1].name))
+ {
+ ++insn;
+ s = argstart;
+ continue;
+ }
+ else
+ {
+ as_bad (_("Invalid operands %s"), error_message);
+ return;
+ }
+ }
+ break;
+ }
+
+ the_insn.opcode = opcode;
+}
+
+/* Turn a string in input_line_pointer into a floating point constant of type
+ type, and store the appropriate bytes in *litP. The number of LITTLENUMS
+ emitted is stored in *sizeP . An error message or NULL is returned. */
+
+#define MAX_LITTLENUMS 6
+
+char *
+md_atof (type, litP, sizeP)
+ char type;
+ char *litP;
+ int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ char *t;
+
+ switch (type)
+ {
+
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ prec = 4;
+ break;
+
+ case 'x':
+ case 'X':
+ prec = 6;
+ break;
+
+ case 'p':
+ case 'P':
+ prec = 6;
+ break;
+
+ default:
+ *sizeP = 0;
+ return _("Bad call to MD_ATOF()");
+ }
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+ *sizeP = prec * sizeof (LITTLENUM_TYPE);
+ for (wordP = words; prec--;)
+ {
+ md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+ return NULL;
+}
+
+/* Write out big-endian. */
+
+void
+md_number_to_chars (buf, val, n)
+ char *buf;
+ valueT val;
+ int n;
+{
+ number_to_chars_bigendian (buf, val, n);
+}
+
+/* Translate internal representation of relocation info to BFD target
+ format. */
+
+arelent **
+tc_gen_reloc (section, fixp)
+ asection *section;
+ fixS *fixp;
+{
+ arelent *reloc;
+ struct hppa_fix_struct *hppa_fixp;
+ bfd_reloc_code_real_type code;
+ static arelent *no_relocs = NULL;
+ arelent **relocs;
+ bfd_reloc_code_real_type **codes;
+ int n_relocs;
+ int i;
+
+ hppa_fixp = (struct hppa_fix_struct *) fixp->tc_fix_data;
+ if (fixp->fx_addsy == 0)
+ return &no_relocs;
+ assert (hppa_fixp != 0);
+ assert (section != 0);
+
+ reloc = (arelent *) xmalloc (sizeof (arelent));
+
+ reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+ codes = (bfd_reloc_code_real_type **) hppa_gen_reloc_type (stdoutput,
+ fixp->fx_r_type,
+ hppa_fixp->fx_r_format,
+ hppa_fixp->fx_r_field,
+ fixp->fx_subsy != NULL,
+ fixp->fx_addsy->bsym);
+
+ if (codes == NULL)
+ abort ();
+
+ for (n_relocs = 0; codes[n_relocs]; n_relocs++)
+ ;
+
+ relocs = (arelent **) xmalloc (sizeof (arelent *) * n_relocs + 1);
+ reloc = (arelent *) xmalloc (sizeof (arelent) * n_relocs);
+ for (i = 0; i < n_relocs; i++)
+ relocs[i] = &reloc[i];
+
+ relocs[n_relocs] = NULL;
+
+#ifdef OBJ_ELF
+ switch (fixp->fx_r_type)
+ {
+ default:
+ assert (n_relocs == 1);
+
+ code = *codes[0];
+
+ reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
+ reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+ reloc->addend = 0; /* default */
+
+ assert (reloc->howto && code == reloc->howto->type);
+
+ /* Now, do any processing that is dependent on the relocation type. */
+ switch (code)
+ {
+ case R_PARISC_DLTREL21L:
+ case R_PARISC_DLTREL14R:
+ case R_PARISC_DLTREL14F:
+ case R_PARISC_PLABEL32:
+ case R_PARISC_PLABEL21L:
+ case R_PARISC_PLABEL14R:
+ /* For plabel relocations, the addend of the
+ relocation should be either 0 (no static link) or 2
+ (static link required).
+
+ FIXME: We always assume no static link!
+
+ We also slam a zero addend into the DLT relative relocs;
+ it doesn't make a lot of sense to use any addend since
+ it gets you a different (eg unknown) DLT entry. */
+ reloc->addend = 0;
+ break;
+
+ case R_PARISC_PCREL21L:
+ case R_PARISC_PCREL17R:
+ case R_PARISC_PCREL17F:
+ case R_PARISC_PCREL17C:
+ case R_PARISC_PCREL14R:
+ case R_PARISC_PCREL14F:
+ /* The constant is stored in the instruction. */
+ reloc->addend = HPPA_R_ADDEND (hppa_fixp->fx_arg_reloc, 0);
+ break;
+ default:
+ reloc->addend = fixp->fx_offset;
+ break;
+ }
+ break;
+ }
+#else /* OBJ_SOM */
+
+ /* Walk over reach relocation returned by the BFD backend. */
+ for (i = 0; i < n_relocs; i++)
+ {
+ code = *codes[i];
+
+ relocs[i]->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+ relocs[i]->howto = bfd_reloc_type_lookup (stdoutput, code);
+ relocs[i]->address = fixp->fx_frag->fr_address + fixp->fx_where;
+
+ switch (code)
+ {
+ case R_COMP2:
+ /* The only time we ever use a R_COMP2 fixup is for the difference
+ of two symbols. With that in mind we fill in all four
+ relocs now and break out of the loop. */
+ assert (i == 1);
+ relocs[0]->sym_ptr_ptr = (asymbol **) &bfd_abs_symbol;
+ relocs[0]->howto = bfd_reloc_type_lookup (stdoutput, *codes[0]);
+ relocs[0]->address = fixp->fx_frag->fr_address + fixp->fx_where;
+ relocs[0]->addend = 0;
+ relocs[1]->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+ relocs[1]->howto = bfd_reloc_type_lookup (stdoutput, *codes[1]);
+ relocs[1]->address = fixp->fx_frag->fr_address + fixp->fx_where;
+ relocs[1]->addend = 0;
+ relocs[2]->sym_ptr_ptr = &fixp->fx_subsy->bsym;
+ relocs[2]->howto = bfd_reloc_type_lookup (stdoutput, *codes[2]);
+ relocs[2]->address = fixp->fx_frag->fr_address + fixp->fx_where;
+ relocs[2]->addend = 0;
+ relocs[3]->sym_ptr_ptr = (asymbol **) &bfd_abs_symbol;
+ relocs[3]->howto = bfd_reloc_type_lookup (stdoutput, *codes[3]);
+ relocs[3]->address = fixp->fx_frag->fr_address + fixp->fx_where;
+ relocs[3]->addend = 0;
+ relocs[4]->sym_ptr_ptr = (asymbol **) &bfd_abs_symbol;
+ relocs[4]->howto = bfd_reloc_type_lookup (stdoutput, *codes[4]);
+ relocs[4]->address = fixp->fx_frag->fr_address + fixp->fx_where;
+ relocs[4]->addend = 0;
+ goto done;
+ case R_PCREL_CALL:
+ case R_ABS_CALL:
+ relocs[i]->addend = HPPA_R_ADDEND (hppa_fixp->fx_arg_reloc, 0);
+ break;
+
+ case R_DLT_REL:
+ case R_DATA_PLABEL:
+ case R_CODE_PLABEL:
+ /* For plabel relocations, the addend of the
+ relocation should be either 0 (no static link) or 2
+ (static link required).
+
+ FIXME: We always assume no static link!
+
+ We also slam a zero addend into the DLT relative relocs;
+ it doesn't make a lot of sense to use any addend since
+ it gets you a different (eg unknown) DLT entry. */
+ relocs[i]->addend = 0;
+ break;
+
+ case R_N_MODE:
+ case R_S_MODE:
+ case R_D_MODE:
+ case R_R_MODE:
+ case R_FSEL:
+ case R_LSEL:
+ case R_RSEL:
+ case R_BEGIN_BRTAB:
+ case R_END_BRTAB:
+ case R_BEGIN_TRY:
+ case R_N0SEL:
+ case R_N1SEL:
+ /* There is no symbol or addend associated with these fixups. */
+ relocs[i]->sym_ptr_ptr = &dummy_symbol->bsym;
+ relocs[i]->addend = 0;
+ break;
+
+ case R_END_TRY:
+ case R_ENTRY:
+ case R_EXIT:
+ /* There is no symbol associated with these fixups. */
+ relocs[i]->sym_ptr_ptr = &dummy_symbol->bsym;
+ relocs[i]->addend = fixp->fx_offset;
+ break;
+
+ default:
+ relocs[i]->addend = fixp->fx_offset;
+ }
+ }
+
+ done:
+#endif
+
+ return relocs;
+}
+
+/* Process any machine dependent frag types. */
+
+void
+md_convert_frag (abfd, sec, fragP)
+ register bfd *abfd;
+ register asection *sec;
+ register fragS *fragP;
+{
+ unsigned int address;
+
+ if (fragP->fr_type == rs_machine_dependent)
+ {
+ switch ((int) fragP->fr_subtype)
+ {
+ case 0:
+ fragP->fr_type = rs_fill;
+ know (fragP->fr_var == 1);
+ know (fragP->fr_next);
+ address = fragP->fr_address + fragP->fr_fix;
+ if (address % fragP->fr_offset)
+ {
+ fragP->fr_offset =
+ fragP->fr_next->fr_address
+ - fragP->fr_address
+ - fragP->fr_fix;
+ }
+ else
+ fragP->fr_offset = 0;
+ break;
+ }
+ }
+}
+
+/* Round up a section size to the appropriate boundary. */
+
+valueT
+md_section_align (segment, size)
+ asection *segment;
+ valueT size;
+{
+ int align = bfd_get_section_alignment (stdoutput, segment);
+ int align2 = (1 << align) - 1;
+
+ return (size + align2) & ~align2;
+}
+
+/* Return the approximate size of a frag before relaxation has occurred. */
+int
+md_estimate_size_before_relax (fragP, segment)
+ register fragS *fragP;
+ asection *segment;
+{
+ int size;
+
+ size = 0;
+
+ while ((fragP->fr_fix + size) % fragP->fr_offset)
+ size++;
+
+ return size;
+}
+
+CONST char *md_shortopts = "";
+struct option md_longopts[] = {
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof(md_longopts);
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ return 0;
+}
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+}
+
+/* We have no need to default values of symbols. */
+
+symbolS *
+md_undefined_symbol (name)
+ char *name;
+{
+ return 0;
+}
+
+/* Apply a fixup to an instruction. */
+
+int
+md_apply_fix (fixP, valp)
+ fixS *fixP;
+ valueT *valp;
+{
+ char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
+ struct hppa_fix_struct *hppa_fixP;
+ long new_val, result = 0;
+ unsigned int w1, w2, w, resulti;
+
+ hppa_fixP = (struct hppa_fix_struct *) fixP->tc_fix_data;
+ /* SOM uses R_HPPA_ENTRY and R_HPPA_EXIT relocations which can
+ never be "applied" (they are just markers). Likewise for
+ R_HPPA_BEGIN_BRTAB and R_HPPA_END_BRTAB. */
+#ifdef OBJ_SOM
+ if (fixP->fx_r_type == R_HPPA_ENTRY
+ || fixP->fx_r_type == R_HPPA_EXIT
+ || fixP->fx_r_type == R_HPPA_BEGIN_BRTAB
+ || fixP->fx_r_type == R_HPPA_END_BRTAB
+ || fixP->fx_r_type == R_HPPA_BEGIN_TRY)
+ return 1;
+
+ /* Disgusting. We must set fx_offset ourselves -- R_HPPA_END_TRY
+ fixups are considered not adjustable, which in turn causes
+ adjust_reloc_syms to not set fx_offset. Ugh. */
+ if (fixP->fx_r_type == R_HPPA_END_TRY)
+ {
+ fixP->fx_offset = *valp;
+ return 1;
+ }
+#endif
+
+ /* There should have been an HPPA specific fixup associated
+ with the GAS fixup. */
+ if (hppa_fixP)
+ {
+ unsigned long buf_wd = bfd_get_32 (stdoutput, buf);
+ unsigned char fmt = bfd_hppa_insn2fmt (buf_wd);
+
+ /* If there is a symbol associated with this fixup, then it's something
+ which will need a SOM relocation (except for some PC-relative relocs).
+ In such cases we should treat the "val" or "addend" as zero since it
+ will be added in as needed from fx_offset in tc_gen_reloc. */
+ if ((fixP->fx_addsy != NULL
+ || fixP->fx_r_type == R_HPPA_NONE)
+#ifdef OBJ_SOM
+ && fmt != 32
+#endif
+ )
+ new_val = ((fmt == 12 || fmt == 17) ? 8 : 0);
+#ifdef OBJ_SOM
+ /* These field selectors imply that we do not want an addend. */
+ else if (hppa_fixP->fx_r_field == e_psel
+ || hppa_fixP->fx_r_field == e_rpsel
+ || hppa_fixP->fx_r_field == e_lpsel
+ || hppa_fixP->fx_r_field == e_tsel
+ || hppa_fixP->fx_r_field == e_rtsel
+ || hppa_fixP->fx_r_field == e_ltsel)
+ new_val = ((fmt == 12 || fmt == 17) ? 8 : 0);
+ /* This is truely disgusting. The machine independent code blindly
+ adds in the value of the symbol being relocated against. Damn! */
+ else if (fmt == 32
+ && fixP->fx_addsy != NULL
+ && S_GET_SEGMENT (fixP->fx_addsy) != bfd_com_section_ptr)
+ new_val = hppa_field_adjust (*valp - S_GET_VALUE (fixP->fx_addsy),
+ 0, hppa_fixP->fx_r_field);
+#endif
+ else
+ new_val = hppa_field_adjust (*valp, 0, hppa_fixP->fx_r_field);
+
+ /* Handle pc-relative exceptions from above. */
+#define arg_reloc_stub_needed(CALLER, CALLEE) \
+ ((CALLEE) && (CALLER) && ((CALLEE) != (CALLER)))
+ if ((fmt == 12 || fmt == 17)
+ && fixP->fx_addsy
+ && fixP->fx_pcrel
+ && !arg_reloc_stub_needed ((long) ((obj_symbol_type *)
+ fixP->fx_addsy->bsym)->tc_data.ap.hppa_arg_reloc,
+ hppa_fixP->fx_arg_reloc)
+ && ((int)(*valp) > -262144 && (int)(*valp) < 262143)
+ && S_GET_SEGMENT (fixP->fx_addsy) == hppa_fixP->segment
+ && !(fixP->fx_subsy
+ && S_GET_SEGMENT (fixP->fx_subsy) != hppa_fixP->segment))
+
+ new_val = hppa_field_adjust (*valp, 0, hppa_fixP->fx_r_field);
+#undef arg_reloc_stub_needed
+
+ switch (fmt)
+ {
+ /* Handle all opcodes with the 'j' operand type. */
+ case 14:
+ CHECK_FIELD (new_val, 8191, -8192, 0);
+
+ /* Mask off 14 bits to be changed. */
+ bfd_put_32 (stdoutput,
+ bfd_get_32 (stdoutput, buf) & 0xffffc000,
+ buf);
+ low_sign_unext (new_val, 14, &resulti);
+ result = resulti;
+ break;
+
+ /* Handle all opcodes with the 'k' operand type. */
+ case 21:
+ CHECK_FIELD (new_val, 2097152, 0, 0);
+
+ /* Mask off 21 bits to be changed. */
+ bfd_put_32 (stdoutput,
+ bfd_get_32 (stdoutput, buf) & 0xffe00000,
+ buf);
+ dis_assemble_21 (new_val, &resulti);
+ result = resulti;
+ break;
+
+ /* Handle all the opcodes with the 'i' operand type. */
+ case 11:
+ CHECK_FIELD (new_val, 1023, -1023, 0);
+
+ /* Mask off 11 bits to be changed. */
+ bfd_put_32 (stdoutput,
+ bfd_get_32 (stdoutput, buf) & 0xffff800,
+ buf);
+ low_sign_unext (new_val, 11, &resulti);
+ result = resulti;
+ break;
+
+ /* Handle all the opcodes with the 'w' operand type. */
+ case 12:
+ CHECK_FIELD (new_val, 8199, -8184, 0);
+
+ /* Mask off 11 bits to be changed. */
+ sign_unext ((new_val - 8) >> 2, 12, &resulti);
+ bfd_put_32 (stdoutput,
+ bfd_get_32 (stdoutput, buf) & 0xffffe002,
+ buf);
+
+ dis_assemble_12 (resulti, &w1, &w);
+ result = ((w1 << 2) | w);
+ break;
+
+ /* Handle some of the opcodes with the 'W' operand type. */
+ case 17:
+ {
+ int distance = *valp;
+
+ CHECK_FIELD (new_val, 262143, -262144, 0);
+
+ /* If this is an absolute branch (ie no link) with an out of
+ range target, then we want to complain. */
+ if (fixP->fx_r_type == R_HPPA_PCREL_CALL
+ && (distance > 262143 || distance < -262144)
+ && (bfd_get_32 (stdoutput, buf) & 0xffe00000) == 0xe8000000)
+ CHECK_FIELD (distance, 262143, -262144, 0);
+
+ /* Mask off 17 bits to be changed. */
+ bfd_put_32 (stdoutput,
+ bfd_get_32 (stdoutput, buf) & 0xffe0e002,
+ buf);
+ sign_unext ((new_val - 8) >> 2, 17, &resulti);
+ dis_assemble_17 (resulti, &w1, &w2, &w);
+ result = ((w2 << 2) | (w1 << 16) | w);
+ break;
+ }
+
+ case 32:
+ result = 0;
+ bfd_put_32 (stdoutput, new_val, buf);
+ break;
+
+ default:
+ as_bad (_("Unknown relocation encountered in md_apply_fix."));
+ return 0;
+ }
+
+ /* Insert the relocation. */
+ bfd_put_32 (stdoutput, bfd_get_32 (stdoutput, buf) | result, buf);
+ return 1;
+ }
+ else
+ {
+ printf (_("no hppa_fixup entry for this fixup (fixP = 0x%x, type = 0x%x)\n"),
+ (unsigned int) fixP, fixP->fx_r_type);
+ return 0;
+ }
+}
+
+/* Exactly what point is a PC-relative offset relative TO?
+ On the PA, they're relative to the address of the offset. */
+
+long
+md_pcrel_from (fixP)
+ fixS *fixP;
+{
+ return fixP->fx_where + fixP->fx_frag->fr_address;
+}
+
+/* Return nonzero if the input line pointer is at the end of
+ a statement. */
+
+static int
+is_end_of_statement ()
+{
+ return ((*input_line_pointer == '\n')
+ || (*input_line_pointer == ';')
+ || (*input_line_pointer == '!'));
+}
+
+/* Read a number from S. The number might come in one of many forms,
+ the most common will be a hex or decimal constant, but it could be
+ a pre-defined register (Yuk!), or an absolute symbol.
+
+ Return a number or -1 for failure.
+
+ When parsing PA-89 FP register numbers RESULT will be
+ the address of a structure to return information about
+ L/R half of FP registers, store results there as appropriate.
+
+ pa_parse_number can not handle negative constants and will fail
+ horribly if it is passed such a constant. */
+
+static int
+pa_parse_number (s, result)
+ char **s;
+ struct pa_11_fp_reg_struct *result;
+{
+ int num;
+ char *name;
+ char c;
+ symbolS *sym;
+ int status;
+ char *p = *s;
+
+ /* Skip whitespace before the number. */
+ while (*p == ' ' || *p == '\t')
+ p = p + 1;
+
+ /* Store info in RESULT if requested by caller. */
+ if (result)
+ {
+ result->number_part = -1;
+ result->l_r_select = -1;
+ }
+ num = -1;
+
+ if (isdigit (*p))
+ {
+ /* Looks like a number. */
+ num = 0;
+
+ if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X'))
+ {
+ /* The number is specified in hex. */
+ p += 2;
+ while (isdigit (*p) || ((*p >= 'a') && (*p <= 'f'))
+ || ((*p >= 'A') && (*p <= 'F')))
+ {
+ if (isdigit (*p))
+ num = num * 16 + *p - '0';
+ else if (*p >= 'a' && *p <= 'f')
+ num = num * 16 + *p - 'a' + 10;
+ else
+ num = num * 16 + *p - 'A' + 10;
+ ++p;
+ }
+ }
+ else
+ {
+ /* The number is specified in decimal. */
+ while (isdigit (*p))
+ {
+ num = num * 10 + *p - '0';
+ ++p;
+ }
+ }
+
+ /* Store info in RESULT if requested by the caller. */
+ if (result)
+ {
+ result->number_part = num;
+
+ if (IS_R_SELECT (p))
+ {
+ result->l_r_select = 1;
+ ++p;
+ }
+ else if (IS_L_SELECT (p))
+ {
+ result->l_r_select = 0;
+ ++p;
+ }
+ else
+ result->l_r_select = 0;
+ }
+ }
+ else if (*p == '%')
+ {
+ /* The number might be a predefined register. */
+ num = 0;
+ name = p;
+ p++;
+ c = *p;
+ /* Tege hack: Special case for general registers as the general
+ code makes a binary search with case translation, and is VERY
+ slow. */
+ if (c == 'r')
+ {
+ p++;
+ if (*p == 'e' && *(p + 1) == 't'
+ && (*(p + 2) == '0' || *(p + 2) == '1'))
+ {
+ p += 2;
+ num = *p - '0' + 28;
+ p++;
+ }
+ else if (*p == 'p')
+ {
+ num = 2;
+ p++;
+ }
+ else if (!isdigit (*p))
+ {
+ if (print_errors)
+ as_bad (_("Undefined register: '%s'."), name);
+ num = -1;
+ }
+ else
+ {
+ do
+ num = num * 10 + *p++ - '0';
+ while (isdigit (*p));
+ }
+ }
+ else
+ {
+ /* Do a normal register search. */
+ while (is_part_of_name (c))
+ {
+ p = p + 1;
+ c = *p;
+ }
+ *p = 0;
+ status = reg_name_search (name);
+ if (status >= 0)
+ num = status;
+ else
+ {
+ if (print_errors)
+ as_bad (_("Undefined register: '%s'."), name);
+ num = -1;
+ }
+ *p = c;
+ }
+
+ /* Store info in RESULT if requested by caller. */
+ if (result)
+ {
+ result->number_part = num;
+ if (IS_R_SELECT (p - 1))
+ result->l_r_select = 1;
+ else if (IS_L_SELECT (p - 1))
+ result->l_r_select = 0;
+ else
+ result->l_r_select = 0;
+ }
+ }
+ else
+ {
+ /* And finally, it could be a symbol in the absolute section which
+ is effectively a constant. */
+ num = 0;
+ name = p;
+ c = *p;
+ while (is_part_of_name (c))
+ {
+ p = p + 1;
+ c = *p;
+ }
+ *p = 0;
+ if ((sym = symbol_find (name)) != NULL)
+ {
+ if (S_GET_SEGMENT (sym) == &bfd_abs_section)
+ num = S_GET_VALUE (sym);
+ else
+ {
+ if (print_errors)
+ as_bad (_("Non-absolute symbol: '%s'."), name);
+ num = -1;
+ }
+ }
+ else
+ {
+ /* There is where we'd come for an undefined symbol
+ or for an empty string. For an empty string we
+ will return zero. That's a concession made for
+ compatability with the braindamaged HP assemblers. */
+ if (*name == 0)
+ num = 0;
+ else
+ {
+ if (print_errors)
+ as_bad (_("Undefined absolute constant: '%s'."), name);
+ num = -1;
+ }
+ }
+ *p = c;
+
+ /* Store info in RESULT if requested by caller. */
+ if (result)
+ {
+ result->number_part = num;
+ if (IS_R_SELECT (p - 1))
+ result->l_r_select = 1;
+ else if (IS_L_SELECT (p - 1))
+ result->l_r_select = 0;
+ else
+ result->l_r_select = 0;
+ }
+ }
+
+ *s = p;
+ return num;
+}
+
+#define REG_NAME_CNT (sizeof(pre_defined_registers) / sizeof(struct pd_reg))
+
+/* Given NAME, find the register number associated with that name, return
+ the integer value associated with the given name or -1 on failure. */
+
+static int
+reg_name_search (name)
+ char *name;
+{
+ int middle, low, high;
+ int cmp;
+
+ low = 0;
+ high = REG_NAME_CNT - 1;
+
+ do
+ {
+ middle = (low + high) / 2;
+ cmp = strcasecmp (name, pre_defined_registers[middle].name);
+ if (cmp < 0)
+ high = middle - 1;
+ else if (cmp > 0)
+ low = middle + 1;
+ else
+ return pre_defined_registers[middle].value;
+ }
+ while (low <= high);
+
+ return -1;
+}
+
+
+/* Return nonzero if the given INSN and L/R information will require
+ a new PA-1.1 opcode. */
+
+static int
+need_pa11_opcode (insn, result)
+ struct pa_it *insn;
+ struct pa_11_fp_reg_struct *result;
+{
+ if (result->l_r_select == 1 && !(insn->fpof1 == DBL && insn->fpof2 == DBL))
+ {
+ /* If this instruction is specific to a particular architecture,
+ then set a new architecture. */
+ if (bfd_get_mach (stdoutput) < pa11)
+ {
+ if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, pa11))
+ as_warn (_("could not update architecture and machine"));
+ }
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+/* Parse a condition for a fcmp instruction. Return the numerical
+ code associated with the condition. */
+
+static int
+pa_parse_fp_cmp_cond (s)
+ char **s;
+{
+ int cond, i;
+
+ cond = 0;
+
+ for (i = 0; i < 32; i++)
+ {
+ if (strncasecmp (*s, fp_cond_map[i].string,
+ strlen (fp_cond_map[i].string)) == 0)
+ {
+ cond = fp_cond_map[i].cond;
+ *s += strlen (fp_cond_map[i].string);
+ /* If not a complete match, back up the input string and
+ report an error. */
+ if (**s != ' ' && **s != '\t')
+ {
+ *s -= strlen (fp_cond_map[i].string);
+ break;
+ }
+ while (**s == ' ' || **s == '\t')
+ *s = *s + 1;
+ return cond;
+ }
+ }
+
+ as_bad (_("Invalid FP Compare Condition: %s"), *s);
+
+ /* Advance over the bogus completer. */
+ while (**s != ',' && **s != ' ' && **s != '\t')
+ *s += 1;
+
+ return 0;
+}
+
+
+/* Parse an FP operand format completer returning the completer
+ type. */
+
+static fp_operand_format
+pa_parse_fp_format (s)
+ char **s;
+{
+ int format;
+
+ format = SGL;
+ if (**s == ',')
+ {
+ *s += 1;
+ if (strncasecmp (*s, "sgl", 3) == 0)
+ {
+ format = SGL;
+ *s += 4;
+ }
+ else if (strncasecmp (*s, "dbl", 3) == 0)
+ {
+ format = DBL;
+ *s += 4;
+ }
+ else if (strncasecmp (*s, "quad", 4) == 0)
+ {
+ format = QUAD;
+ *s += 5;
+ }
+ else
+ {
+ format = ILLEGAL_FMT;
+ as_bad (_("Invalid FP Operand Format: %3s"), *s);
+ }
+ }
+
+ return format;
+}
+
+/* Convert from a selector string into a selector type. */
+
+static int
+pa_chk_field_selector (str)
+ char **str;
+{
+ int middle, low, high;
+ int cmp;
+ char name[4];
+
+ /* Read past any whitespace. */
+ /* FIXME: should we read past newlines and formfeeds??? */
+ while (**str == ' ' || **str == '\t' || **str == '\n' || **str == '\f')
+ *str = *str + 1;
+
+ if ((*str)[1] == '\'' || (*str)[1] == '%')
+ name[0] = tolower ((*str)[0]),
+ name[1] = 0;
+ else if ((*str)[2] == '\'' || (*str)[2] == '%')
+ name[0] = tolower ((*str)[0]),
+ name[1] = tolower ((*str)[1]),
+ name[2] = 0;
+#ifdef OBJ_SOM
+ else if ((*str)[3] == '\'' || (*str)[3] == '%')
+ name[0] = tolower ((*str)[0]),
+ name[1] = tolower ((*str)[1]),
+ name[2] = tolower ((*str)[2]),
+ name[3] = 0;
+#endif
+ else
+ return e_fsel;
+
+ low = 0;
+ high = sizeof (selector_table) / sizeof (struct selector_entry) - 1;
+
+ do
+ {
+ middle = (low + high) / 2;
+ cmp = strcmp (name, selector_table[middle].prefix);
+ if (cmp < 0)
+ high = middle - 1;
+ else if (cmp > 0)
+ low = middle + 1;
+ else
+ {
+ *str += strlen (name) + 1;
+#ifndef OBJ_SOM
+ if (selector_table[middle].field_selector == e_nsel)
+ return e_fsel;
+#endif
+ return selector_table[middle].field_selector;
+ }
+ }
+ while (low <= high);
+
+ return e_fsel;
+}
+
+/* Mark (via expr_end) the end of an expression (I think). FIXME. */
+
+static int
+get_expression (str)
+ char *str;
+{
+ char *save_in;
+ asection *seg;
+
+ save_in = input_line_pointer;
+ input_line_pointer = str;
+ seg = expression (&the_insn.exp);
+ if (!(seg == absolute_section
+ || seg == undefined_section
+ || SEG_NORMAL (seg)))
+ {
+ as_warn (_("Bad segment in expression."));
+ expr_end = input_line_pointer;
+ input_line_pointer = save_in;
+ return 1;
+ }
+ expr_end = input_line_pointer;
+ input_line_pointer = save_in;
+ return 0;
+}
+
+/* Mark (via expr_end) the end of an absolute expression. FIXME. */
+static int
+pa_get_absolute_expression (insn, strp)
+ struct pa_it *insn;
+ char **strp;
+{
+ char *save_in;
+
+ insn->field_selector = pa_chk_field_selector (strp);
+ save_in = input_line_pointer;
+ input_line_pointer = *strp;
+ expression (&insn->exp);
+ /* This is not perfect, but is a huge improvement over doing nothing.
+
+ The PA assembly syntax is ambigious in a variety of ways. Consider
+ this string "4 %r5" Is that the number 4 followed by the register
+ r5, or is that 4 MOD 5?
+
+ If we get a modulo expresion When looking for an absolute, we try
+ again cutting off the input string at the first whitespace character. */
+ if (insn->exp.X_op == O_modulus)
+ {
+ char *s, c;
+ int retval;
+
+ input_line_pointer = *strp;
+ s = *strp;
+ while (*s != ',' && *s != ' ' && *s != '\t')
+ s++;
+
+ c = *s;
+ *s = 0;
+
+ retval = pa_get_absolute_expression (insn, strp);
+
+ input_line_pointer = save_in;
+ *s = c;
+ return evaluate_absolute (insn);
+ }
+ if (insn->exp.X_op != O_constant)
+ {
+ as_bad (_("Bad segment (should be absolute)."));
+ expr_end = input_line_pointer;
+ input_line_pointer = save_in;
+ return 0;
+ }
+ expr_end = input_line_pointer;
+ input_line_pointer = save_in;
+ return evaluate_absolute (insn);
+}
+
+/* Evaluate an absolute expression EXP which may be modified by
+ the selector FIELD_SELECTOR. Return the value of the expression. */
+static int
+evaluate_absolute (insn)
+ struct pa_it *insn;
+{
+ int value;
+ expressionS exp;
+ int field_selector = insn->field_selector;
+
+ exp = insn->exp;
+ value = exp.X_add_number;
+
+ switch (field_selector)
+ {
+ /* No change. */
+ case e_fsel:
+ break;
+
+ /* If bit 21 is on then add 0x800 and arithmetic shift right 11 bits. */
+ case e_lssel:
+ if (value & 0x00000400)
+ value += 0x800;
+ value = (value & 0xfffff800) >> 11;
+ break;
+
+ /* Sign extend from bit 21. */
+ case e_rssel:
+ if (value & 0x00000400)
+ value |= 0xfffff800;
+ else
+ value &= 0x7ff;
+ break;
+
+ /* Arithmetic shift right 11 bits. */
+ case e_lsel:
+ value = (value & 0xfffff800) >> 11;
+ break;
+
+ /* Set bits 0-20 to zero. */
+ case e_rsel:
+ value = value & 0x7ff;
+ break;
+
+ /* Add 0x800 and arithmetic shift right 11 bits. */
+ case e_ldsel:
+ value += 0x800;
+ value = (value & 0xfffff800) >> 11;
+ break;
+
+ /* Set bitgs 0-21 to one. */
+ case e_rdsel:
+ value |= 0xfffff800;
+ break;
+
+#define RSEL_ROUND(c) (((c) + 0x1000) & ~0x1fff)
+ case e_rrsel:
+ value = (RSEL_ROUND (value) & 0x7ff) + (value - RSEL_ROUND (value));
+ break;
+
+ case e_lrsel:
+ value = (RSEL_ROUND (value) >> 11) & 0x1fffff;
+ break;
+#undef RSEL_ROUND
+
+ default:
+ BAD_CASE (field_selector);
+ break;
+ }
+ return value;
+}
+
+/* Given an argument location specification return the associated
+ argument location number. */
+
+static unsigned int
+pa_build_arg_reloc (type_name)
+ char *type_name;
+{
+
+ if (strncasecmp (type_name, "no", 2) == 0)
+ return 0;
+ if (strncasecmp (type_name, "gr", 2) == 0)
+ return 1;
+ else if (strncasecmp (type_name, "fr", 2) == 0)
+ return 2;
+ else if (strncasecmp (type_name, "fu", 2) == 0)
+ return 3;
+ else
+ as_bad (_("Invalid argument location: %s\n"), type_name);
+
+ return 0;
+}
+
+/* Encode and return an argument relocation specification for
+ the given register in the location specified by arg_reloc. */
+
+static unsigned int
+pa_align_arg_reloc (reg, arg_reloc)
+ unsigned int reg;
+ unsigned int arg_reloc;
+{
+ unsigned int new_reloc;
+
+ new_reloc = arg_reloc;
+ switch (reg)
+ {
+ case 0:
+ new_reloc <<= 8;
+ break;
+ case 1:
+ new_reloc <<= 6;
+ break;
+ case 2:
+ new_reloc <<= 4;
+ break;
+ case 3:
+ new_reloc <<= 2;
+ break;
+ default:
+ as_bad (_("Invalid argument description: %d"), reg);
+ }
+
+ return new_reloc;
+}
+
+/* Parse a PA nullification completer (,n). Return nonzero if the
+ completer was found; return zero if no completer was found. */
+
+static int
+pa_parse_nullif (s)
+ char **s;
+{
+ int nullif;
+
+ nullif = 0;
+ if (**s == ',')
+ {
+ *s = *s + 1;
+ if (strncasecmp (*s, "n", 1) == 0)
+ nullif = 1;
+ else
+ {
+ as_bad (_("Invalid Nullification: (%c)"), **s);
+ nullif = 0;
+ }
+ *s = *s + 1;
+ }
+
+ return nullif;
+}
+
+/* Parse a non-negated compare/subtract completer returning the
+ number (for encoding in instrutions) of the given completer.
+
+ ISBRANCH specifies whether or not this is parsing a condition
+ completer for a branch (vs a nullification completer for a
+ computational instruction. */
+
+static int
+pa_parse_nonneg_cmpsub_cmpltr (s, isbranch)
+ char **s;
+ int isbranch;
+{
+ int cmpltr;
+ char *name = *s + 1;
+ char c;
+ char *save_s = *s;
+ int nullify = 0;
+
+ cmpltr = 0;
+ if (**s == ',')
+ {
+ *s += 1;
+ while (**s != ',' && **s != ' ' && **s != '\t')
+ *s += 1;
+ c = **s;
+ **s = 0x00;
+
+
+ if (strcmp (name, "=") == 0)
+ {
+ cmpltr = 1;
+ }
+ else if (strcmp (name, "<") == 0)
+ {
+ cmpltr = 2;
+ }
+ else if (strcmp (name, "<=") == 0)
+ {
+ cmpltr = 3;
+ }
+ else if (strcmp (name, "<<") == 0)
+ {
+ cmpltr = 4;
+ }
+ else if (strcmp (name, "<<=") == 0)
+ {
+ cmpltr = 5;
+ }
+ else if (strcasecmp (name, "sv") == 0)
+ {
+ cmpltr = 6;
+ }
+ else if (strcasecmp (name, "od") == 0)
+ {
+ cmpltr = 7;
+ }
+ /* If we have something like addb,n then there is no condition
+ completer. */
+ else if (strcasecmp (name, "n") == 0 && isbranch)
+ {
+ cmpltr = 0;
+ nullify = 1;
+ }
+ else
+ {
+ cmpltr = -1;
+ }
+ **s = c;
+ }
+
+ /* Reset pointers if this was really a ,n for a branch instruction. */
+ if (nullify)
+ *s = save_s;
+
+
+ return cmpltr;
+}
+
+/* Parse a negated compare/subtract completer returning the
+ number (for encoding in instrutions) of the given completer.
+
+ ISBRANCH specifies whether or not this is parsing a condition
+ completer for a branch (vs a nullification completer for a
+ computational instruction. */
+
+static int
+pa_parse_neg_cmpsub_cmpltr (s, isbranch)
+ char **s;
+ int isbranch;
+{
+ int cmpltr;
+ char *name = *s + 1;
+ char c;
+ char *save_s = *s;
+ int nullify = 0;
+
+ cmpltr = 0;
+ if (**s == ',')
+ {
+ *s += 1;
+ while (**s != ',' && **s != ' ' && **s != '\t')
+ *s += 1;
+ c = **s;
+ **s = 0x00;
+
+
+ if (strcasecmp (name, "tr") == 0)
+ {
+ cmpltr = 0;
+ }
+ else if (strcmp (name, "<>") == 0)
+ {
+ cmpltr = 1;
+ }
+ else if (strcmp (name, ">=") == 0)
+ {
+ cmpltr = 2;
+ }
+ else if (strcmp (name, ">") == 0)
+ {
+ cmpltr = 3;
+ }
+ else if (strcmp (name, ">>=") == 0)
+ {
+ cmpltr = 4;
+ }
+ else if (strcmp (name, ">>") == 0)
+ {
+ cmpltr = 5;
+ }
+ else if (strcasecmp (name, "nsv") == 0)
+ {
+ cmpltr = 6;
+ }
+ else if (strcasecmp (name, "ev") == 0)
+ {
+ cmpltr = 7;
+ }
+ /* If we have something like addb,n then there is no condition
+ completer. */
+ else if (strcasecmp (name, "n") == 0 && isbranch)
+ {
+ cmpltr = 0;
+ nullify = 1;
+ }
+ else
+ {
+ cmpltr = -1;
+ }
+ **s = c;
+ }
+
+ /* Reset pointers if this was really a ,n for a branch instruction. */
+ if (nullify)
+ *s = save_s;
+
+
+ return cmpltr;
+}
+
+
+/* Parse a non-negated addition completer returning the number
+ (for encoding in instrutions) of the given completer.
+
+ ISBRANCH specifies whether or not this is parsing a condition
+ completer for a branch (vs a nullification completer for a
+ computational instruction. */
+
+static int
+pa_parse_nonneg_add_cmpltr (s, isbranch)
+ char **s;
+ int isbranch;
+{
+ int cmpltr;
+ char *name = *s + 1;
+ char c;
+ char *save_s = *s;
+
+ cmpltr = 0;
+ if (**s == ',')
+ {
+ *s += 1;
+ while (**s != ',' && **s != ' ' && **s != '\t')
+ *s += 1;
+ c = **s;
+ **s = 0x00;
+ if (strcmp (name, "=") == 0)
+ {
+ cmpltr = 1;
+ }
+ else if (strcmp (name, "<") == 0)
+ {
+ cmpltr = 2;
+ }
+ else if (strcmp (name, "<=") == 0)
+ {
+ cmpltr = 3;
+ }
+ else if (strcasecmp (name, "nuv") == 0)
+ {
+ cmpltr = 4;
+ }
+ else if (strcasecmp (name, "znv") == 0)
+ {
+ cmpltr = 5;
+ }
+ else if (strcasecmp (name, "sv") == 0)
+ {
+ cmpltr = 6;
+ }
+ else if (strcasecmp (name, "od") == 0)
+ {
+ cmpltr = 7;
+ }
+ /* If we have something like addb,n then there is no condition
+ completer. */
+ else if (strcasecmp (name, "n") == 0 && isbranch)
+ {
+ cmpltr = 0;
+ }
+ else
+ {
+ cmpltr = -1;
+ }
+ **s = c;
+ }
+
+ /* Reset pointers if this was really a ,n for a branch instruction. */
+ if (cmpltr == 0 && *name == 'n' && isbranch)
+ *s = save_s;
+
+ return cmpltr;
+}
+
+/* Parse a negated addition completer returning the number
+ (for encoding in instrutions) of the given completer.
+
+ ISBRANCH specifies whether or not this is parsing a condition
+ completer for a branch (vs a nullification completer for a
+ computational instruction). */
+
+static int
+pa_parse_neg_add_cmpltr (s, isbranch)
+ char **s;
+ int isbranch;
+{
+ int cmpltr;
+ char *name = *s + 1;
+ char c;
+ char *save_s = *s;
+
+ cmpltr = 0;
+ if (**s == ',')
+ {
+ *s += 1;
+ while (**s != ',' && **s != ' ' && **s != '\t')
+ *s += 1;
+ c = **s;
+ **s = 0x00;
+ if (strcasecmp (name, "tr") == 0)
+ {
+ cmpltr = 0;
+ }
+ else if (strcmp (name, "<>") == 0)
+ {
+ cmpltr = 1;
+ }
+ else if (strcmp (name, ">=") == 0)
+ {
+ cmpltr = 2;
+ }
+ else if (strcmp (name, ">") == 0)
+ {
+ cmpltr = 3;
+ }
+ else if (strcasecmp (name, "uv") == 0)
+ {
+ cmpltr = 4;
+ }
+ else if (strcasecmp (name, "vnz") == 0)
+ {
+ cmpltr = 5;
+ }
+ else if (strcasecmp (name, "nsv") == 0)
+ {
+ cmpltr = 6;
+ }
+ else if (strcasecmp (name, "ev") == 0)
+ {
+ cmpltr = 7;
+ }
+ /* If we have something like addb,n then there is no condition
+ completer. */
+ else if (strcasecmp (name, "n") == 0 && isbranch)
+ {
+ cmpltr = 0;
+ }
+ else
+ {
+ cmpltr = -1;
+ }
+ **s = c;
+ }
+
+ /* Reset pointers if this was really a ,n for a branch instruction. */
+ if (cmpltr == 0 && *name == 'n' && isbranch)
+ *s = save_s;
+
+ return cmpltr;
+}
+
+/* Handle an alignment directive. Special so that we can update the
+ alignment of the subspace if necessary. */
+static void
+pa_align (bytes)
+{
+ /* We must have a valid space and subspace. */
+ pa_check_current_space_and_subspace ();
+
+ /* Let the generic gas code do most of the work. */
+ s_align_bytes (bytes);
+
+ /* If bytes is a power of 2, then update the current subspace's
+ alignment if necessary. */
+ if (log2 (bytes) != -1)
+ record_alignment (current_subspace->ssd_seg, log2 (bytes));
+}
+
+/* Handle a .BLOCK type pseudo-op. */
+
+static void
+pa_block (z)
+ int z;
+{
+ char *p;
+ long int temp_fill;
+ unsigned int temp_size;
+ unsigned int i;
+
+ /* We must have a valid space and subspace. */
+ pa_check_current_space_and_subspace ();
+
+ temp_size = get_absolute_expression ();
+
+ /* Always fill with zeros, that's what the HP assembler does. */
+ temp_fill = 0;
+
+ p = frag_var (rs_fill, (int) temp_size, (int) temp_size,
+ (relax_substateT) 0, (symbolS *) 0, (offsetT) 1, NULL);
+ memset (p, 0, temp_size);
+
+ /* Convert 2 bytes at a time. */
+
+ for (i = 0; i < temp_size; i += 2)
+ {
+ md_number_to_chars (p + i,
+ (valueT) temp_fill,
+ (int) ((temp_size - i) > 2 ? 2 : (temp_size - i)));
+ }
+
+ pa_undefine_label ();
+ demand_empty_rest_of_line ();
+}
+
+/* Handle a .begin_brtab and .end_brtab pseudo-op. */
+
+static void
+pa_brtab (begin)
+ int begin;
+{
+
+#ifdef OBJ_SOM
+ /* The BRTAB relocations are only availble in SOM (to denote
+ the beginning and end of branch tables). */
+ char *where = frag_more (0);
+
+ fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
+ NULL, (offsetT) 0, NULL,
+ 0, begin ? R_HPPA_BEGIN_BRTAB : R_HPPA_END_BRTAB,
+ e_fsel, 0, 0, NULL);
+#endif
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle a .begin_try and .end_try pseudo-op. */
+
+static void
+pa_try (begin)
+ int begin;
+{
+#ifdef OBJ_SOM
+ expressionS exp;
+ char *where = frag_more (0);
+
+ if (! begin)
+ expression (&exp);
+
+ /* The TRY relocations are only availble in SOM (to denote
+ the beginning and end of exception handling regions). */
+
+ fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
+ NULL, (offsetT) 0, begin ? NULL : &exp,
+ 0, begin ? R_HPPA_BEGIN_TRY : R_HPPA_END_TRY,
+ e_fsel, 0, 0, NULL);
+#endif
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle a .CALL pseudo-op. This involves storing away information
+ about where arguments are to be found so the linker can detect
+ (and correct) argument location mismatches between caller and callee. */
+
+static void
+pa_call (unused)
+ int unused;
+{
+ /* We must have a valid space and subspace. */
+ pa_check_current_space_and_subspace ();
+
+ pa_call_args (&last_call_desc);
+ demand_empty_rest_of_line ();
+}
+
+/* Do the dirty work of building a call descriptor which describes
+ where the caller placed arguments to a function call. */
+
+static void
+pa_call_args (call_desc)
+ struct call_desc *call_desc;
+{
+ char *name, c, *p;
+ unsigned int temp, arg_reloc;
+
+ while (!is_end_of_statement ())
+ {
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ /* Process a source argument. */
+ if ((strncasecmp (name, "argw", 4) == 0))
+ {
+ temp = atoi (name + 4);
+ p = input_line_pointer;
+ *p = c;
+ input_line_pointer++;
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ arg_reloc = pa_build_arg_reloc (name);
+ call_desc->arg_reloc |= pa_align_arg_reloc (temp, arg_reloc);
+ }
+ /* Process a return value. */
+ else if ((strncasecmp (name, "rtnval", 6) == 0))
+ {
+ p = input_line_pointer;
+ *p = c;
+ input_line_pointer++;
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ arg_reloc = pa_build_arg_reloc (name);
+ call_desc->arg_reloc |= (arg_reloc & 0x3);
+ }
+ else
+ {
+ as_bad (_("Invalid .CALL argument: %s"), name);
+ }
+ p = input_line_pointer;
+ *p = c;
+ if (!is_end_of_statement ())
+ input_line_pointer++;
+ }
+}
+
+/* Return TRUE if FRAG1 and FRAG2 are the same. */
+
+static int
+is_same_frag (frag1, frag2)
+ fragS *frag1;
+ fragS *frag2;
+{
+
+ if (frag1 == NULL)
+ return (FALSE);
+ else if (frag2 == NULL)
+ return (FALSE);
+ else if (frag1 == frag2)
+ return (TRUE);
+ else if (frag2->fr_type == rs_fill && frag2->fr_fix == 0)
+ return (is_same_frag (frag1, frag2->fr_next));
+ else
+ return (FALSE);
+}
+
+#ifdef OBJ_ELF
+/* Build an entry in the UNWIND subspace from the given function
+ attributes in CALL_INFO. This is not needed for SOM as using
+ R_ENTRY and R_EXIT relocations allow the linker to handle building
+ of the unwind spaces. */
+
+static void
+pa_build_unwind_subspace (call_info)
+ struct call_info *call_info;
+{
+ char *unwind;
+ asection *seg, *save_seg;
+ subsegT subseg, save_subseg;
+ int i;
+ char c, *p;
+
+ /* Get into the right seg/subseg. This may involve creating
+ the seg the first time through. Make sure to have the
+ old seg/subseg so that we can reset things when we are done. */
+ subseg = SUBSEG_UNWIND;
+ seg = bfd_get_section_by_name (stdoutput, UNWIND_SECTION_NAME);
+ if (seg == ASEC_NULL)
+ {
+ seg = bfd_make_section_old_way (stdoutput, UNWIND_SECTION_NAME);
+ bfd_set_section_flags (stdoutput, seg,
+ SEC_READONLY | SEC_HAS_CONTENTS
+ | SEC_LOAD | SEC_RELOC);
+ }
+
+ save_seg = now_seg;
+ save_subseg = now_subseg;
+ subseg_set (seg, subseg);
+
+
+ /* Get some space to hold relocation information for the unwind
+ descriptor. */
+ p = frag_more (4);
+ md_number_to_chars (p, 0, 4);
+
+ /* Relocation info. for start offset of the function. */
+ fix_new_hppa (frag_now, p - frag_now->fr_literal, 4,
+ call_info->start_symbol, (offsetT) 0,
+ (expressionS *) NULL, 0, R_PARISC_DIR32, e_fsel, 32, 0, NULL);
+
+ p = frag_more (4);
+ md_number_to_chars (p, 0, 4);
+
+ /* Relocation info. for end offset of the function.
+
+ Because we allow reductions of 32bit relocations for ELF, this will be
+ reduced to section_sym + offset which avoids putting the temporary
+ symbol into the symbol table. It (should) end up giving the same
+ value as call_info->start_symbol + function size once the linker is
+ finished with its work. */
+
+ fix_new_hppa (frag_now, p - frag_now->fr_literal, 4,
+ call_info->end_symbol, (offsetT) 0,
+ (expressionS *) NULL, 0, R_PARISC_DIR32, e_fsel, 32, 0, NULL);
+
+ /* Dump it. */
+ unwind = (char *) &call_info->ci_unwind;
+ for (i = 8; i < sizeof (struct unwind_table); i++)
+ {
+ c = *(unwind + i);
+ {
+ FRAG_APPEND_1_CHAR (c);
+ }
+ }
+
+ /* Return back to the original segment/subsegment. */
+ subseg_set (save_seg, save_subseg);
+}
+#endif
+
+/* Process a .CALLINFO pseudo-op. This information is used later
+ to build unwind descriptors and maybe one day to support
+ .ENTER and .LEAVE. */
+
+static void
+pa_callinfo (unused)
+ int unused;
+{
+ char *name, c, *p;
+ int temp;
+
+ /* We must have a valid space and subspace. */
+ pa_check_current_space_and_subspace ();
+
+ /* .CALLINFO must appear within a procedure definition. */
+ if (!within_procedure)
+ as_bad (_(".callinfo is not within a procedure definition"));
+
+ /* Mark the fact that we found the .CALLINFO for the
+ current procedure. */
+ callinfo_found = TRUE;
+
+ /* Iterate over the .CALLINFO arguments. */
+ while (!is_end_of_statement ())
+ {
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ /* Frame size specification. */
+ if ((strncasecmp (name, "frame", 5) == 0))
+ {
+ p = input_line_pointer;
+ *p = c;
+ input_line_pointer++;
+ temp = get_absolute_expression ();
+ if ((temp & 0x3) != 0)
+ {
+ as_bad (_("FRAME parameter must be a multiple of 8: %d\n"), temp);
+ temp = 0;
+ }
+
+ /* callinfo is in bytes and unwind_desc is in 8 byte units. */
+ last_call_info->ci_unwind.descriptor.frame_size = temp / 8;
+
+ }
+ /* Entry register (GR, GR and SR) specifications. */
+ else if ((strncasecmp (name, "entry_gr", 8) == 0))
+ {
+ p = input_line_pointer;
+ *p = c;
+ input_line_pointer++;
+ temp = get_absolute_expression ();
+ /* The HP assembler accepts 19 as the high bound for ENTRY_GR
+ even though %r19 is caller saved. I think this is a bug in
+ the HP assembler, and we are not going to emulate it. */
+ if (temp < 3 || temp > 18)
+ as_bad (_("Value for ENTRY_GR must be in the range 3..18\n"));
+ last_call_info->ci_unwind.descriptor.entry_gr = temp - 2;
+ }
+ else if ((strncasecmp (name, "entry_fr", 8) == 0))
+ {
+ p = input_line_pointer;
+ *p = c;
+ input_line_pointer++;
+ temp = get_absolute_expression ();
+ /* Similarly the HP assembler takes 31 as the high bound even
+ though %fr21 is the last callee saved floating point register. */
+ if (temp < 12 || temp > 21)
+ as_bad (_("Value for ENTRY_FR must be in the range 12..21\n"));
+ last_call_info->ci_unwind.descriptor.entry_fr = temp - 11;
+ }
+ else if ((strncasecmp (name, "entry_sr", 8) == 0))
+ {
+ p = input_line_pointer;
+ *p = c;
+ input_line_pointer++;
+ temp = get_absolute_expression ();
+ if (temp != 3)
+ as_bad (_("Value for ENTRY_SR must be 3\n"));
+ }
+ /* Note whether or not this function performs any calls. */
+ else if ((strncasecmp (name, "calls", 5) == 0) ||
+ (strncasecmp (name, "caller", 6) == 0))
+ {
+ p = input_line_pointer;
+ *p = c;
+ }
+ else if ((strncasecmp (name, "no_calls", 8) == 0))
+ {
+ p = input_line_pointer;
+ *p = c;
+ }
+ /* Should RP be saved into the stack. */
+ else if ((strncasecmp (name, "save_rp", 7) == 0))
+ {
+ p = input_line_pointer;
+ *p = c;
+ last_call_info->ci_unwind.descriptor.save_rp = 1;
+ }
+ /* Likewise for SP. */
+ else if ((strncasecmp (name, "save_sp", 7) == 0))
+ {
+ p = input_line_pointer;
+ *p = c;
+ last_call_info->ci_unwind.descriptor.save_sp = 1;
+ }
+ /* Is this an unwindable procedure. If so mark it so
+ in the unwind descriptor. */
+ else if ((strncasecmp (name, "no_unwind", 9) == 0))
+ {
+ p = input_line_pointer;
+ *p = c;
+ last_call_info->ci_unwind.descriptor.cannot_unwind = 1;
+ }
+ /* Is this an interrupt routine. If so mark it in the
+ unwind descriptor. */
+ else if ((strncasecmp (name, "hpux_int", 7) == 0))
+ {
+ p = input_line_pointer;
+ *p = c;
+ last_call_info->ci_unwind.descriptor.hpux_interrupt_marker = 1;
+ }
+ /* Is this a millicode routine. "millicode" isn't in my
+ assembler manual, but my copy is old. The HP assembler
+ accepts it, and there's a place in the unwind descriptor
+ to drop the information, so we'll accept it too. */
+ else if ((strncasecmp (name, "millicode", 9) == 0))
+ {
+ p = input_line_pointer;
+ *p = c;
+ last_call_info->ci_unwind.descriptor.millicode = 1;
+ }
+ else
+ {
+ as_bad (_("Invalid .CALLINFO argument: %s"), name);
+ *input_line_pointer = c;
+ }
+ if (!is_end_of_statement ())
+ input_line_pointer++;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* Switch into the code subspace. */
+
+static void
+pa_code (unused)
+ int unused;
+{
+ current_space = is_defined_space ("$TEXT$");
+ current_subspace
+ = pa_subsegment_to_subspace (current_space->sd_seg, 0);
+ s_text (0);
+ pa_undefine_label ();
+}
+
+/* This is different than the standard GAS s_comm(). On HP9000/800 machines,
+ the .comm pseudo-op has the following symtax:
+
+ <label> .comm <length>
+
+ where <label> is optional and is a symbol whose address will be the start of
+ a block of memory <length> bytes long. <length> must be an absolute
+ expression. <length> bytes will be allocated in the current space
+ and subspace.
+
+ Also note the label may not even be on the same line as the .comm.
+
+ This difference in syntax means the colon function will be called
+ on the symbol before we arrive in pa_comm. colon will set a number
+ of attributes of the symbol that need to be fixed here. In particular
+ the value, section pointer, fragment pointer, flags, etc. What
+ a pain.
+
+ This also makes error detection all but impossible. */
+
+static void
+pa_comm (unused)
+ int unused;
+{
+ unsigned int size;
+ symbolS *symbol;
+ label_symbol_struct *label_symbol = pa_get_label ();
+
+ if (label_symbol)
+ symbol = label_symbol->lss_label;
+ else
+ symbol = NULL;
+
+ SKIP_WHITESPACE ();
+ size = get_absolute_expression ();
+
+ if (symbol)
+ {
+ S_SET_VALUE (symbol, size);
+ S_SET_SEGMENT (symbol, bfd_und_section_ptr);
+ S_SET_EXTERNAL (symbol);
+
+ /* colon() has already set the frag to the current location in the
+ current subspace; we need to reset the fragment to the zero address
+ fragment. We also need to reset the segment pointer. */
+ symbol->sy_frag = &zero_address_frag;
+ }
+ demand_empty_rest_of_line ();
+}
+
+/* Process a .END pseudo-op. */
+
+static void
+pa_end (unused)
+ int unused;
+{
+ demand_empty_rest_of_line ();
+}
+
+/* Process a .ENTER pseudo-op. This is not supported. */
+static void
+pa_enter (unused)
+ int unused;
+{
+ /* We must have a valid space and subspace. */
+ pa_check_current_space_and_subspace ();
+
+ as_bad (_("The .ENTER pseudo-op is not supported"));
+ demand_empty_rest_of_line ();
+}
+
+/* Process a .ENTRY pseudo-op. .ENTRY marks the beginning of the
+ procesure. */
+static void
+pa_entry (unused)
+ int unused;
+{
+ /* We must have a valid space and subspace. */
+ pa_check_current_space_and_subspace ();
+
+ if (!within_procedure)
+ as_bad (_("Misplaced .entry. Ignored."));
+ else
+ {
+ if (!callinfo_found)
+ as_bad (_("Missing .callinfo."));
+ }
+ demand_empty_rest_of_line ();
+ within_entry_exit = TRUE;
+
+#ifdef OBJ_SOM
+ /* SOM defers building of unwind descriptors until the link phase.
+ The assembler is responsible for creating an R_ENTRY relocation
+ to mark the beginning of a region and hold the unwind bits, and
+ for creating an R_EXIT relocation to mark the end of the region.
+
+ FIXME. ELF should be using the same conventions! The problem
+ is an unwind requires too much relocation space. Hmmm. Maybe
+ if we split the unwind bits up between the relocations which
+ denote the entry and exit points. */
+ if (last_call_info->start_symbol != NULL)
+ {
+ char *where = frag_more (0);
+
+ fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
+ NULL, (offsetT) 0, NULL,
+ 0, R_HPPA_ENTRY, e_fsel, 0, 0,
+ (int *) &last_call_info->ci_unwind.descriptor);
+ }
+#endif
+}
+
+/* Handle a .EQU pseudo-op. */
+
+static void
+pa_equ (reg)
+ int reg;
+{
+ label_symbol_struct *label_symbol = pa_get_label ();
+ symbolS *symbol;
+
+ if (label_symbol)
+ {
+ symbol = label_symbol->lss_label;
+ if (reg)
+ S_SET_VALUE (symbol, pa_parse_number (&input_line_pointer, 0));
+ else
+ S_SET_VALUE (symbol, (unsigned int) get_absolute_expression ());
+ S_SET_SEGMENT (symbol, bfd_abs_section_ptr);
+ }
+ else
+ {
+ if (reg)
+ as_bad (_(".REG must use a label"));
+ else
+ as_bad (_(".EQU must use a label"));
+ }
+
+ pa_undefine_label ();
+ demand_empty_rest_of_line ();
+}
+
+/* Helper function. Does processing for the end of a function. This
+ usually involves creating some relocations or building special
+ symbols to mark the end of the function. */
+
+static void
+process_exit ()
+{
+ char *where;
+
+ where = frag_more (0);
+
+#ifdef OBJ_ELF
+ /* Mark the end of the function, stuff away the location of the frag
+ for the end of the function, and finally call pa_build_unwind_subspace
+ to add an entry in the unwind table. */
+ hppa_elf_mark_end_of_function ();
+ pa_build_unwind_subspace (last_call_info);
+#else
+ /* SOM defers building of unwind descriptors until the link phase.
+ The assembler is responsible for creating an R_ENTRY relocation
+ to mark the beginning of a region and hold the unwind bits, and
+ for creating an R_EXIT relocation to mark the end of the region.
+
+ FIXME. ELF should be using the same conventions! The problem
+ is an unwind requires too much relocation space. Hmmm. Maybe
+ if we split the unwind bits up between the relocations which
+ denote the entry and exit points. */
+ fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
+ NULL, (offsetT) 0,
+ NULL, 0, R_HPPA_EXIT, e_fsel, 0, 0,
+ (int *) &last_call_info->ci_unwind.descriptor + 1);
+#endif
+}
+
+/* Process a .EXIT pseudo-op. */
+
+static void
+pa_exit (unused)
+ int unused;
+{
+ /* We must have a valid space and subspace. */
+ pa_check_current_space_and_subspace ();
+
+ if (!within_procedure)
+ as_bad (_(".EXIT must appear within a procedure"));
+ else
+ {
+ if (!callinfo_found)
+ as_bad (_("Missing .callinfo"));
+ else
+ {
+ if (!within_entry_exit)
+ as_bad (_("No .ENTRY for this .EXIT"));
+ else
+ {
+ within_entry_exit = FALSE;
+ process_exit ();
+ }
+ }
+ }
+ demand_empty_rest_of_line ();
+}
+
+/* Process a .EXPORT directive. This makes functions external
+ and provides information such as argument relocation entries
+ to callers. */
+
+static void
+pa_export (unused)
+ int unused;
+{
+ char *name, c, *p;
+ symbolS *symbol;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ /* Make sure the given symbol exists. */
+ if ((symbol = symbol_find_or_make (name)) == NULL)
+ {
+ as_bad (_("Cannot define export symbol: %s\n"), name);
+ p = input_line_pointer;
+ *p = c;
+ input_line_pointer++;
+ }
+ else
+ {
+ /* OK. Set the external bits and process argument relocations. */
+ S_SET_EXTERNAL (symbol);
+ p = input_line_pointer;
+ *p = c;
+ if (!is_end_of_statement ())
+ {
+ input_line_pointer++;
+ pa_type_args (symbol, 1);
+ }
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* Helper function to process arguments to a .EXPORT pseudo-op. */
+
+static void
+pa_type_args (symbolP, is_export)
+ symbolS *symbolP;
+ int is_export;
+{
+ char *name, c, *p;
+ unsigned int temp, arg_reloc;
+ pa_symbol_type type = SYMBOL_TYPE_UNKNOWN;
+ obj_symbol_type *symbol = (obj_symbol_type *) symbolP->bsym;
+
+ if (strncasecmp (input_line_pointer, "absolute", 8) == 0)
+
+ {
+ input_line_pointer += 8;
+ symbolP->bsym->flags &= ~BSF_FUNCTION;
+ S_SET_SEGMENT (symbolP, bfd_abs_section_ptr);
+ type = SYMBOL_TYPE_ABSOLUTE;
+ }
+ else if (strncasecmp (input_line_pointer, "code", 4) == 0)
+ {
+ input_line_pointer += 4;
+ /* IMPORTing/EXPORTing CODE types for functions is meaningless for SOM,
+ instead one should be IMPORTing/EXPORTing ENTRY types.
+
+ Complain if one tries to EXPORT a CODE type since that's never
+ done. Both GCC and HP C still try to IMPORT CODE types, so
+ silently fix them to be ENTRY types. */
+ if (symbolP->bsym->flags & BSF_FUNCTION)
+ {
+ if (is_export)
+ as_tsktsk (_("Using ENTRY rather than CODE in export directive for %s"), symbolP->bsym->name);
+
+ symbolP->bsym->flags |= BSF_FUNCTION;
+ type = SYMBOL_TYPE_ENTRY;
+ }
+ else
+ {
+ symbolP->bsym->flags &= ~BSF_FUNCTION;
+ type = SYMBOL_TYPE_CODE;
+ }
+ }
+ else if (strncasecmp (input_line_pointer, "data", 4) == 0)
+ {
+ input_line_pointer += 4;
+ symbolP->bsym->flags &= ~BSF_FUNCTION;
+ type = SYMBOL_TYPE_DATA;
+ }
+ else if ((strncasecmp (input_line_pointer, "entry", 5) == 0))
+ {
+ input_line_pointer += 5;
+ symbolP->bsym->flags |= BSF_FUNCTION;
+ type = SYMBOL_TYPE_ENTRY;
+ }
+ else if (strncasecmp (input_line_pointer, "millicode", 9) == 0)
+ {
+ input_line_pointer += 9;
+ symbolP->bsym->flags |= BSF_FUNCTION;
+ type = SYMBOL_TYPE_MILLICODE;
+ }
+ else if (strncasecmp (input_line_pointer, "plabel", 6) == 0)
+ {
+ input_line_pointer += 6;
+ symbolP->bsym->flags &= ~BSF_FUNCTION;
+ type = SYMBOL_TYPE_PLABEL;
+ }
+ else if (strncasecmp (input_line_pointer, "pri_prog", 8) == 0)
+ {
+ input_line_pointer += 8;
+ symbolP->bsym->flags |= BSF_FUNCTION;
+ type = SYMBOL_TYPE_PRI_PROG;
+ }
+ else if (strncasecmp (input_line_pointer, "sec_prog", 8) == 0)
+ {
+ input_line_pointer += 8;
+ symbolP->bsym->flags |= BSF_FUNCTION;
+ type = SYMBOL_TYPE_SEC_PROG;
+ }
+
+ /* SOM requires much more information about symbol types
+ than BFD understands. This is how we get this information
+ to the SOM BFD backend. */
+#ifdef obj_set_symbol_type
+ obj_set_symbol_type (symbolP->bsym, (int) type);
+#endif
+
+ /* Now that the type of the exported symbol has been handled,
+ handle any argument relocation information. */
+ while (!is_end_of_statement ())
+ {
+ if (*input_line_pointer == ',')
+ input_line_pointer++;
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ /* Argument sources. */
+ if ((strncasecmp (name, "argw", 4) == 0))
+ {
+ p = input_line_pointer;
+ *p = c;
+ input_line_pointer++;
+ temp = atoi (name + 4);
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ arg_reloc = pa_align_arg_reloc (temp, pa_build_arg_reloc (name));
+ symbol->tc_data.ap.hppa_arg_reloc |= arg_reloc;
+ *input_line_pointer = c;
+ }
+ /* The return value. */
+ else if ((strncasecmp (name, "rtnval", 6)) == 0)
+ {
+ p = input_line_pointer;
+ *p = c;
+ input_line_pointer++;
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ arg_reloc = pa_build_arg_reloc (name);
+ symbol->tc_data.ap.hppa_arg_reloc |= arg_reloc;
+ *input_line_pointer = c;
+ }
+ /* Privelege level. */
+ else if ((strncasecmp (name, "priv_lev", 8)) == 0)
+ {
+ p = input_line_pointer;
+ *p = c;
+ input_line_pointer++;
+ temp = atoi (input_line_pointer);
+ symbol->tc_data.ap.hppa_priv_level = temp;
+ c = get_symbol_end ();
+ *input_line_pointer = c;
+ }
+ else
+ {
+ as_bad (_("Undefined .EXPORT/.IMPORT argument (ignored): %s"), name);
+ p = input_line_pointer;
+ *p = c;
+ }
+ if (!is_end_of_statement ())
+ input_line_pointer++;
+ }
+}
+
+/* Handle an .IMPORT pseudo-op. Any symbol referenced in a given
+ assembly file must either be defined in the assembly file, or
+ explicitly IMPORTED from another. */
+
+static void
+pa_import (unused)
+ int unused;
+{
+ char *name, c, *p;
+ symbolS *symbol;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+
+ symbol = symbol_find (name);
+ /* Ugh. We might be importing a symbol defined earlier in the file,
+ in which case all the code below will really screw things up
+ (set the wrong segment, symbol flags & type, etc). */
+ if (symbol == NULL || !S_IS_DEFINED (symbol))
+ {
+ symbol = symbol_find_or_make (name);
+ p = input_line_pointer;
+ *p = c;
+
+ if (!is_end_of_statement ())
+ {
+ input_line_pointer++;
+ pa_type_args (symbol, 0);
+ }
+ else
+ {
+ /* Sigh. To be compatable with the HP assembler and to help
+ poorly written assembly code, we assign a type based on
+ the the current segment. Note only BSF_FUNCTION really
+ matters, we do not need to set the full SYMBOL_TYPE_* info. */
+ if (now_seg == text_section)
+ symbol->bsym->flags |= BSF_FUNCTION;
+
+ /* If the section is undefined, then the symbol is undefined
+ Since this is an import, leave the section undefined. */
+ S_SET_SEGMENT (symbol, bfd_und_section_ptr);
+ }
+ }
+ else
+ {
+ /* The symbol was already defined. Just eat everything up to
+ the end of the current statement. */
+ while (!is_end_of_statement ())
+ input_line_pointer++;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle a .LABEL pseudo-op. */
+
+static void
+pa_label (unused)
+ int unused;
+{
+ char *name, c, *p;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+
+ if (strlen (name) > 0)
+ {
+ colon (name);
+ p = input_line_pointer;
+ *p = c;
+ }
+ else
+ {
+ as_warn (_("Missing label name on .LABEL"));
+ }
+
+ if (!is_end_of_statement ())
+ {
+ as_warn (_("extra .LABEL arguments ignored."));
+ ignore_rest_of_line ();
+ }
+ demand_empty_rest_of_line ();
+}
+
+/* Handle a .LEAVE pseudo-op. This is not supported yet. */
+
+static void
+pa_leave (unused)
+ int unused;
+{
+ /* We must have a valid space and subspace. */
+ pa_check_current_space_and_subspace ();
+
+ as_bad (_("The .LEAVE pseudo-op is not supported"));
+ demand_empty_rest_of_line ();
+}
+
+/* Handle a .LEVEL pseudo-op. */
+
+static void
+pa_level (unused)
+ int unused;
+{
+ char *level;
+
+ level = input_line_pointer;
+ if (strncmp (level, "1.0", 3) == 0)
+ {
+ input_line_pointer += 3;
+ if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, 10))
+ as_warn (_("could not set architecture and machine"));
+ }
+ else if (strncmp (level, "1.1", 3) == 0)
+ {
+ input_line_pointer += 3;
+ if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, 11))
+ as_warn (_("could not set architecture and machine"));
+ }
+ else if (strncmp (level, "2.0", 3) == 0)
+ {
+ input_line_pointer += 3;
+ if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, 20))
+ as_warn (_("could not set architecture and machine"));
+ }
+ else
+ {
+ as_bad (_("Unrecognized .LEVEL argument\n"));
+ ignore_rest_of_line ();
+ }
+ demand_empty_rest_of_line ();
+}
+
+/* Handle a .ORIGIN pseudo-op. */
+
+static void
+pa_origin (unused)
+ int unused;
+{
+ /* We must have a valid space and subspace. */
+ pa_check_current_space_and_subspace ();
+
+ s_org (0);
+ pa_undefine_label ();
+}
+
+/* Handle a .PARAM pseudo-op. This is much like a .EXPORT, except it
+ is for static functions. FIXME. Should share more code with .EXPORT. */
+
+static void
+pa_param (unused)
+ int unused;
+{
+ char *name, c, *p;
+ symbolS *symbol;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+
+ if ((symbol = symbol_find_or_make (name)) == NULL)
+ {
+ as_bad (_("Cannot define static symbol: %s\n"), name);
+ p = input_line_pointer;
+ *p = c;
+ input_line_pointer++;
+ }
+ else
+ {
+ S_CLEAR_EXTERNAL (symbol);
+ p = input_line_pointer;
+ *p = c;
+ if (!is_end_of_statement ())
+ {
+ input_line_pointer++;
+ pa_type_args (symbol, 0);
+ }
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle a .PROC pseudo-op. It is used to mark the beginning
+ of a procedure from a syntatical point of view. */
+
+static void
+pa_proc (unused)
+ int unused;
+{
+ struct call_info *call_info;
+
+ /* We must have a valid space and subspace. */
+ pa_check_current_space_and_subspace ();
+
+ if (within_procedure)
+ as_fatal (_("Nested procedures"));
+
+ /* Reset global variables for new procedure. */
+ callinfo_found = FALSE;
+ within_procedure = TRUE;
+
+ /* Create another call_info structure. */
+ call_info = (struct call_info *) xmalloc (sizeof (struct call_info));
+
+ if (!call_info)
+ as_fatal (_("Cannot allocate unwind descriptor\n"));
+
+ memset (call_info, 0, sizeof (struct call_info));
+
+ call_info->ci_next = NULL;
+
+ if (call_info_root == NULL)
+ {
+ call_info_root = call_info;
+ last_call_info = call_info;
+ }
+ else
+ {
+ last_call_info->ci_next = call_info;
+ last_call_info = call_info;
+ }
+
+ /* set up defaults on call_info structure */
+
+ call_info->ci_unwind.descriptor.cannot_unwind = 0;
+ call_info->ci_unwind.descriptor.region_desc = 1;
+ call_info->ci_unwind.descriptor.hpux_interrupt_marker = 0;
+
+ /* If we got a .PROC pseudo-op, we know that the function is defined
+ locally. Make sure it gets into the symbol table. */
+ {
+ label_symbol_struct *label_symbol = pa_get_label ();
+
+ if (label_symbol)
+ {
+ if (label_symbol->lss_label)
+ {
+ last_call_info->start_symbol = label_symbol->lss_label;
+ label_symbol->lss_label->bsym->flags |= BSF_FUNCTION;
+ }
+ else
+ as_bad (_("Missing function name for .PROC (corrupted label chain)"));
+ }
+ else
+ last_call_info->start_symbol = NULL;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* Process the syntatical end of a procedure. Make sure all the
+ appropriate pseudo-ops were found within the procedure. */
+
+static void
+pa_procend (unused)
+ int unused;
+{
+
+ /* We must have a valid space and subspace. */
+ pa_check_current_space_and_subspace ();
+
+ /* If we are within a procedure definition, make sure we've
+ defined a label for the procedure; handle case where the
+ label was defined after the .PROC directive.
+
+ Note there's not need to diddle with the segment or fragment
+ for the label symbol in this case. We have already switched
+ into the new $CODE$ subspace at this point. */
+ if (within_procedure && last_call_info->start_symbol == NULL)
+ {
+ label_symbol_struct *label_symbol = pa_get_label ();
+
+ if (label_symbol)
+ {
+ if (label_symbol->lss_label)
+ {
+ last_call_info->start_symbol = label_symbol->lss_label;
+ label_symbol->lss_label->bsym->flags |= BSF_FUNCTION;
+#ifdef OBJ_SOM
+ /* Also handle allocation of a fixup to hold the unwind
+ information when the label appears after the proc/procend. */
+ if (within_entry_exit)
+ {
+ char *where = frag_more (0);
+
+ fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
+ NULL, (offsetT) 0, NULL,
+ 0, R_HPPA_ENTRY, e_fsel, 0, 0,
+ (int *) &last_call_info->ci_unwind.descriptor);
+ }
+#endif
+ }
+ else
+ as_bad (_("Missing function name for .PROC (corrupted label chain)"));
+ }
+ else
+ as_bad (_("Missing function name for .PROC"));
+ }
+
+ if (!within_procedure)
+ as_bad (_("misplaced .procend"));
+
+ if (!callinfo_found)
+ as_bad (_("Missing .callinfo for this procedure"));
+
+ if (within_entry_exit)
+ as_bad (_("Missing .EXIT for a .ENTRY"));
+
+#ifdef OBJ_ELF
+ /* ELF needs to mark the end of each function so that it can compute
+ the size of the function (apparently its needed in the symbol table). */
+ hppa_elf_mark_end_of_function ();
+#endif
+
+ within_procedure = FALSE;
+ demand_empty_rest_of_line ();
+ pa_undefine_label ();
+}
+
+/* Parse the parameters to a .SPACE directive; if CREATE_FLAG is nonzero,
+ then create a new space entry to hold the information specified
+ by the parameters to the .SPACE directive. */
+
+static sd_chain_struct *
+pa_parse_space_stmt (space_name, create_flag)
+ char *space_name;
+ int create_flag;
+{
+ char *name, *ptemp, c;
+ char loadable, defined, private, sort;
+ int spnum, temp;
+ asection *seg = NULL;
+ sd_chain_struct *space;
+
+ /* load default values */
+ spnum = 0;
+ sort = 0;
+ loadable = TRUE;
+ defined = TRUE;
+ private = FALSE;
+ if (strcmp (space_name, "$TEXT$") == 0)
+ {
+ seg = pa_def_spaces[0].segment;
+ defined = pa_def_spaces[0].defined;
+ private = pa_def_spaces[0].private;
+ sort = pa_def_spaces[0].sort;
+ spnum = pa_def_spaces[0].spnum;
+ }
+ else if (strcmp (space_name, "$PRIVATE$") == 0)
+ {
+ seg = pa_def_spaces[1].segment;
+ defined = pa_def_spaces[1].defined;
+ private = pa_def_spaces[1].private;
+ sort = pa_def_spaces[1].sort;
+ spnum = pa_def_spaces[1].spnum;
+ }
+
+ if (!is_end_of_statement ())
+ {
+ print_errors = FALSE;
+ ptemp = input_line_pointer + 1;
+ /* First see if the space was specified as a number rather than
+ as a name. According to the PA assembly manual the rest of
+ the line should be ignored. */
+ temp = pa_parse_number (&ptemp, 0);
+ if (temp >= 0)
+ {
+ spnum = temp;
+ input_line_pointer = ptemp;
+ }
+ else
+ {
+ while (!is_end_of_statement ())
+ {
+ input_line_pointer++;
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ if ((strncasecmp (name, "spnum", 5) == 0))
+ {
+ *input_line_pointer = c;
+ input_line_pointer++;
+ spnum = get_absolute_expression ();
+ }
+ else if ((strncasecmp (name, "sort", 4) == 0))
+ {
+ *input_line_pointer = c;
+ input_line_pointer++;
+ sort = get_absolute_expression ();
+ }
+ else if ((strncasecmp (name, "unloadable", 10) == 0))
+ {
+ *input_line_pointer = c;
+ loadable = FALSE;
+ }
+ else if ((strncasecmp (name, "notdefined", 10) == 0))
+ {
+ *input_line_pointer = c;
+ defined = FALSE;
+ }
+ else if ((strncasecmp (name, "private", 7) == 0))
+ {
+ *input_line_pointer = c;
+ private = TRUE;
+ }
+ else
+ {
+ as_bad (_("Invalid .SPACE argument"));
+ *input_line_pointer = c;
+ if (!is_end_of_statement ())
+ input_line_pointer++;
+ }
+ }
+ }
+ print_errors = TRUE;
+ }
+
+ if (create_flag && seg == NULL)
+ seg = subseg_new (space_name, 0);
+
+ /* If create_flag is nonzero, then create the new space with
+ the attributes computed above. Else set the values in
+ an already existing space -- this can only happen for
+ the first occurence of a built-in space. */
+ if (create_flag)
+ space = create_new_space (space_name, spnum, loadable, defined,
+ private, sort, seg, 1);
+ else
+ {
+ space = is_defined_space (space_name);
+ SPACE_SPNUM (space) = spnum;
+ SPACE_DEFINED (space) = defined & 1;
+ SPACE_USER_DEFINED (space) = 1;
+ }
+
+#ifdef obj_set_section_attributes
+ obj_set_section_attributes (seg, defined, private, sort, spnum);
+#endif
+
+ return space;
+}
+
+/* Handle a .SPACE pseudo-op; this switches the current space to the
+ given space, creating the new space if necessary. */
+
+static void
+pa_space (unused)
+ int unused;
+{
+ char *name, c, *space_name, *save_s;
+ int temp;
+ sd_chain_struct *sd_chain;
+
+ if (within_procedure)
+ {
+ as_bad (_("Can\'t change spaces within a procedure definition. Ignored"));
+ ignore_rest_of_line ();
+ }
+ else
+ {
+ /* Check for some of the predefined spaces. FIXME: most of the code
+ below is repeated several times, can we extract the common parts
+ and place them into a subroutine or something similar? */
+ /* FIXME Is this (and the next IF stmt) really right?
+ What if INPUT_LINE_POINTER points to "$TEXT$FOO"? */
+ if (strncmp (input_line_pointer, "$TEXT$", 6) == 0)
+ {
+ input_line_pointer += 6;
+ sd_chain = is_defined_space ("$TEXT$");
+ if (sd_chain == NULL)
+ sd_chain = pa_parse_space_stmt ("$TEXT$", 1);
+ else if (SPACE_USER_DEFINED (sd_chain) == 0)
+ sd_chain = pa_parse_space_stmt ("$TEXT$", 0);
+
+ current_space = sd_chain;
+ subseg_set (text_section, sd_chain->sd_last_subseg);
+ current_subspace
+ = pa_subsegment_to_subspace (text_section,
+ sd_chain->sd_last_subseg);
+ demand_empty_rest_of_line ();
+ return;
+ }
+ if (strncmp (input_line_pointer, "$PRIVATE$", 9) == 0)
+ {
+ input_line_pointer += 9;
+ sd_chain = is_defined_space ("$PRIVATE$");
+ if (sd_chain == NULL)
+ sd_chain = pa_parse_space_stmt ("$PRIVATE$", 1);
+ else if (SPACE_USER_DEFINED (sd_chain) == 0)
+ sd_chain = pa_parse_space_stmt ("$PRIVATE$", 0);
+
+ current_space = sd_chain;
+ subseg_set (data_section, sd_chain->sd_last_subseg);
+ current_subspace
+ = pa_subsegment_to_subspace (data_section,
+ sd_chain->sd_last_subseg);
+ demand_empty_rest_of_line ();
+ return;
+ }
+ if (!strncasecmp (input_line_pointer,
+ GDB_DEBUG_SPACE_NAME,
+ strlen (GDB_DEBUG_SPACE_NAME)))
+ {
+ input_line_pointer += strlen (GDB_DEBUG_SPACE_NAME);
+ sd_chain = is_defined_space (GDB_DEBUG_SPACE_NAME);
+ if (sd_chain == NULL)
+ sd_chain = pa_parse_space_stmt (GDB_DEBUG_SPACE_NAME, 1);
+ else if (SPACE_USER_DEFINED (sd_chain) == 0)
+ sd_chain = pa_parse_space_stmt (GDB_DEBUG_SPACE_NAME, 0);
+
+ current_space = sd_chain;
+
+ {
+ asection *gdb_section
+ = bfd_make_section_old_way (stdoutput, GDB_DEBUG_SPACE_NAME);
+
+ subseg_set (gdb_section, sd_chain->sd_last_subseg);
+ current_subspace
+ = pa_subsegment_to_subspace (gdb_section,
+ sd_chain->sd_last_subseg);
+ }
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ /* It could be a space specified by number. */
+ print_errors = 0;
+ save_s = input_line_pointer;
+ if ((temp = pa_parse_number (&input_line_pointer, 0)) >= 0)
+ {
+ if ((sd_chain = pa_find_space_by_number (temp)))
+ {
+ current_space = sd_chain;
+
+ subseg_set (sd_chain->sd_seg, sd_chain->sd_last_subseg);
+ current_subspace
+ = pa_subsegment_to_subspace (sd_chain->sd_seg,
+ sd_chain->sd_last_subseg);
+ demand_empty_rest_of_line ();
+ return;
+ }
+ }
+
+ /* Not a number, attempt to create a new space. */
+ print_errors = 1;
+ input_line_pointer = save_s;
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ space_name = xmalloc (strlen (name) + 1);
+ strcpy (space_name, name);
+ *input_line_pointer = c;
+
+ sd_chain = pa_parse_space_stmt (space_name, 1);
+ current_space = sd_chain;
+
+ subseg_set (sd_chain->sd_seg, sd_chain->sd_last_subseg);
+ current_subspace = pa_subsegment_to_subspace (sd_chain->sd_seg,
+ sd_chain->sd_last_subseg);
+ demand_empty_rest_of_line ();
+ }
+}
+
+/* Switch to a new space. (I think). FIXME. */
+
+static void
+pa_spnum (unused)
+ int unused;
+{
+ char *name;
+ char c;
+ char *p;
+ sd_chain_struct *space;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ space = is_defined_space (name);
+ if (space)
+ {
+ p = frag_more (4);
+ md_number_to_chars (p, SPACE_SPNUM (space), 4);
+ }
+ else
+ as_warn (_("Undefined space: '%s' Assuming space number = 0."), name);
+
+ *input_line_pointer = c;
+ demand_empty_rest_of_line ();
+}
+
+/* If VALUE is an exact power of two between zero and 2^31, then
+ return log2 (VALUE). Else return -1. */
+
+static int
+log2 (value)
+ int value;
+{
+ int shift = 0;
+
+ while ((1 << shift) != value && shift < 32)
+ shift++;
+
+ if (shift >= 32)
+ return -1;
+ else
+ return shift;
+}
+
+/* Handle a .SUBSPACE pseudo-op; this switches the current subspace to the
+ given subspace, creating the new subspace if necessary.
+
+ FIXME. Should mirror pa_space more closely, in particular how
+ they're broken up into subroutines. */
+
+static void
+pa_subspace (create_new)
+ int create_new;
+{
+ char *name, *ss_name, *alias, c;
+ char loadable, code_only, common, dup_common, zero, sort;
+ int i, access, space_index, alignment, quadrant, applicable, flags;
+ sd_chain_struct *space;
+ ssd_chain_struct *ssd;
+ asection *section;
+
+ if (current_space == NULL)
+ as_fatal (_("Must be in a space before changing or declaring subspaces.\n"));
+
+ if (within_procedure)
+ {
+ as_bad (_("Can\'t change subspaces within a procedure definition. Ignored"));
+ ignore_rest_of_line ();
+ }
+ else
+ {
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ ss_name = xmalloc (strlen (name) + 1);
+ strcpy (ss_name, name);
+ *input_line_pointer = c;
+
+ /* Load default values. */
+ sort = 0;
+ access = 0x7f;
+ loadable = 1;
+ common = 0;
+ dup_common = 0;
+ code_only = 0;
+ zero = 0;
+ space_index = ~0;
+ alignment = 1;
+ quadrant = 0;
+ alias = NULL;
+
+ space = current_space;
+ if (create_new)
+ ssd = NULL;
+ else
+ ssd = is_defined_subspace (ss_name);
+ /* Allow user to override the builtin attributes of subspaces. But
+ only allow the attributes to be changed once! */
+ if (ssd && SUBSPACE_DEFINED (ssd))
+ {
+ subseg_set (ssd->ssd_seg, ssd->ssd_subseg);
+ current_subspace = ssd;
+ if (!is_end_of_statement ())
+ as_warn (_("Parameters of an existing subspace can\'t be modified"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+ else
+ {
+ /* A new subspace. Load default values if it matches one of
+ the builtin subspaces. */
+ i = 0;
+ while (pa_def_subspaces[i].name)
+ {
+ if (strcasecmp (pa_def_subspaces[i].name, ss_name) == 0)
+ {
+ loadable = pa_def_subspaces[i].loadable;
+ common = pa_def_subspaces[i].common;
+ dup_common = pa_def_subspaces[i].dup_common;
+ code_only = pa_def_subspaces[i].code_only;
+ zero = pa_def_subspaces[i].zero;
+ space_index = pa_def_subspaces[i].space_index;
+ alignment = pa_def_subspaces[i].alignment;
+ quadrant = pa_def_subspaces[i].quadrant;
+ access = pa_def_subspaces[i].access;
+ sort = pa_def_subspaces[i].sort;
+ if (USE_ALIASES && pa_def_subspaces[i].alias)
+ alias = pa_def_subspaces[i].alias;
+ break;
+ }
+ i++;
+ }
+ }
+
+ /* We should be working with a new subspace now. Fill in
+ any information as specified by the user. */
+ if (!is_end_of_statement ())
+ {
+ input_line_pointer++;
+ while (!is_end_of_statement ())
+ {
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ if ((strncasecmp (name, "quad", 4) == 0))
+ {
+ *input_line_pointer = c;
+ input_line_pointer++;
+ quadrant = get_absolute_expression ();
+ }
+ else if ((strncasecmp (name, "align", 5) == 0))
+ {
+ *input_line_pointer = c;
+ input_line_pointer++;
+ alignment = get_absolute_expression ();
+ if (log2 (alignment) == -1)
+ {
+ as_bad (_("Alignment must be a power of 2"));
+ alignment = 1;
+ }
+ }
+ else if ((strncasecmp (name, "access", 6) == 0))
+ {
+ *input_line_pointer = c;
+ input_line_pointer++;
+ access = get_absolute_expression ();
+ }
+ else if ((strncasecmp (name, "sort", 4) == 0))
+ {
+ *input_line_pointer = c;
+ input_line_pointer++;
+ sort = get_absolute_expression ();
+ }
+ else if ((strncasecmp (name, "code_only", 9) == 0))
+ {
+ *input_line_pointer = c;
+ code_only = 1;
+ }
+ else if ((strncasecmp (name, "unloadable", 10) == 0))
+ {
+ *input_line_pointer = c;
+ loadable = 0;
+ }
+ else if ((strncasecmp (name, "common", 6) == 0))
+ {
+ *input_line_pointer = c;
+ common = 1;
+ }
+ else if ((strncasecmp (name, "dup_comm", 8) == 0))
+ {
+ *input_line_pointer = c;
+ dup_common = 1;
+ }
+ else if ((strncasecmp (name, "zero", 4) == 0))
+ {
+ *input_line_pointer = c;
+ zero = 1;
+ }
+ else if ((strncasecmp (name, "first", 5) == 0))
+ as_bad (_("FIRST not supported as a .SUBSPACE argument"));
+ else
+ as_bad (_("Invalid .SUBSPACE argument"));
+ if (!is_end_of_statement ())
+ input_line_pointer++;
+ }
+ }
+
+ /* Compute a reasonable set of BFD flags based on the information
+ in the .subspace directive. */
+ applicable = bfd_applicable_section_flags (stdoutput);
+ flags = 0;
+ if (loadable)
+ flags |= (SEC_ALLOC | SEC_LOAD);
+ if (code_only)
+ flags |= SEC_CODE;
+ if (common || dup_common)
+ flags |= SEC_IS_COMMON;
+
+ flags |= SEC_RELOC | SEC_HAS_CONTENTS;
+
+ /* This is a zero-filled subspace (eg BSS). */
+ if (zero)
+ flags &= ~(SEC_LOAD | SEC_HAS_CONTENTS);
+
+ applicable &= flags;
+
+ /* If this is an existing subspace, then we want to use the
+ segment already associated with the subspace.
+
+ FIXME NOW! ELF BFD doesn't appear to be ready to deal with
+ lots of sections. It might be a problem in the PA ELF
+ code, I do not know yet. For now avoid creating anything
+ but the "standard" sections for ELF. */
+ if (create_new)
+ section = subseg_force_new (ss_name, 0);
+ else if (ssd)
+ section = ssd->ssd_seg;
+ else if (alias)
+ section = subseg_new (alias, 0);
+ else if (!alias && USE_ALIASES)
+ {
+ as_warn (_("Ignoring subspace decl due to ELF BFD bugs."));
+ demand_empty_rest_of_line ();
+ return;
+ }
+ else
+ section = subseg_new (ss_name, 0);
+
+ if (zero)
+ seg_info (section)->bss = 1;
+
+ /* Now set the flags. */
+ bfd_set_section_flags (stdoutput, section, applicable);
+
+ /* Record any alignment request for this section. */
+ record_alignment (section, log2 (alignment));
+
+ /* Set the starting offset for this section. */
+ bfd_set_section_vma (stdoutput, section,
+ pa_subspace_start (space, quadrant));
+
+ /* Now that all the flags are set, update an existing subspace,
+ or create a new one. */
+ if (ssd)
+
+ current_subspace = update_subspace (space, ss_name, loadable,
+ code_only, common, dup_common,
+ sort, zero, access, space_index,
+ alignment, quadrant,
+ section);
+ else
+ current_subspace = create_new_subspace (space, ss_name, loadable,
+ code_only, common,
+ dup_common, zero, sort,
+ access, space_index,
+ alignment, quadrant, section);
+
+ demand_empty_rest_of_line ();
+ current_subspace->ssd_seg = section;
+ subseg_set (current_subspace->ssd_seg, current_subspace->ssd_subseg);
+ }
+ SUBSPACE_DEFINED (current_subspace) = 1;
+}
+
+
+/* Create default space and subspace dictionaries. */
+
+static void
+pa_spaces_begin ()
+{
+ int i;
+
+ space_dict_root = NULL;
+ space_dict_last = NULL;
+
+ i = 0;
+ while (pa_def_spaces[i].name)
+ {
+ char *name;
+
+ /* Pick the right name to use for the new section. */
+ if (pa_def_spaces[i].alias && USE_ALIASES)
+ name = pa_def_spaces[i].alias;
+ else
+ name = pa_def_spaces[i].name;
+
+ pa_def_spaces[i].segment = subseg_new (name, 0);
+ create_new_space (pa_def_spaces[i].name, pa_def_spaces[i].spnum,
+ pa_def_spaces[i].loadable, pa_def_spaces[i].defined,
+ pa_def_spaces[i].private, pa_def_spaces[i].sort,
+ pa_def_spaces[i].segment, 0);
+ i++;
+ }
+
+ i = 0;
+ while (pa_def_subspaces[i].name)
+ {
+ char *name;
+ int applicable, subsegment;
+ asection *segment = NULL;
+ sd_chain_struct *space;
+
+ /* Pick the right name for the new section and pick the right
+ subsegment number. */
+ if (pa_def_subspaces[i].alias && USE_ALIASES)
+ {
+ name = pa_def_subspaces[i].alias;
+ subsegment = pa_def_subspaces[i].subsegment;
+ }
+ else
+ {
+ name = pa_def_subspaces[i].name;
+ subsegment = 0;
+ }
+
+ /* Create the new section. */
+ segment = subseg_new (name, subsegment);
+
+
+ /* For SOM we want to replace the standard .text, .data, and .bss
+ sections with our own. We also want to set BFD flags for
+ all the built-in subspaces. */
+ if (!strcmp (pa_def_subspaces[i].name, "$CODE$") && !USE_ALIASES)
+ {
+ text_section = segment;
+ applicable = bfd_applicable_section_flags (stdoutput);
+ bfd_set_section_flags (stdoutput, segment,
+ applicable & (SEC_ALLOC | SEC_LOAD
+ | SEC_RELOC | SEC_CODE
+ | SEC_READONLY
+ | SEC_HAS_CONTENTS));
+ }
+ else if (!strcmp (pa_def_subspaces[i].name, "$DATA$") && !USE_ALIASES)
+ {
+ data_section = segment;
+ applicable = bfd_applicable_section_flags (stdoutput);
+ bfd_set_section_flags (stdoutput, segment,
+ applicable & (SEC_ALLOC | SEC_LOAD
+ | SEC_RELOC
+ | SEC_HAS_CONTENTS));
+
+
+ }
+ else if (!strcmp (pa_def_subspaces[i].name, "$BSS$") && !USE_ALIASES)
+ {
+ bss_section = segment;
+ applicable = bfd_applicable_section_flags (stdoutput);
+ bfd_set_section_flags (stdoutput, segment,
+ applicable & SEC_ALLOC);
+ }
+ else if (!strcmp (pa_def_subspaces[i].name, "$LIT$") && !USE_ALIASES)
+ {
+ applicable = bfd_applicable_section_flags (stdoutput);
+ bfd_set_section_flags (stdoutput, segment,
+ applicable & (SEC_ALLOC | SEC_LOAD
+ | SEC_RELOC
+ | SEC_READONLY
+ | SEC_HAS_CONTENTS));
+ }
+ else if (!strcmp (pa_def_subspaces[i].name, "$MILLICODE$")
+ && !USE_ALIASES)
+ {
+ applicable = bfd_applicable_section_flags (stdoutput);
+ bfd_set_section_flags (stdoutput, segment,
+ applicable & (SEC_ALLOC | SEC_LOAD
+ | SEC_RELOC
+ | SEC_READONLY
+ | SEC_HAS_CONTENTS));
+ }
+ else if (!strcmp (pa_def_subspaces[i].name, "$UNWIND$") && !USE_ALIASES)
+ {
+ applicable = bfd_applicable_section_flags (stdoutput);
+ bfd_set_section_flags (stdoutput, segment,
+ applicable & (SEC_ALLOC | SEC_LOAD
+ | SEC_RELOC
+ | SEC_READONLY
+ | SEC_HAS_CONTENTS));
+ }
+
+ /* Find the space associated with this subspace. */
+ space = pa_segment_to_space (pa_def_spaces[pa_def_subspaces[i].
+ def_space_index].segment);
+ if (space == NULL)
+ {
+ as_fatal (_("Internal error: Unable to find containing space for %s."),
+ pa_def_subspaces[i].name);
+ }
+
+ create_new_subspace (space, name,
+ pa_def_subspaces[i].loadable,
+ pa_def_subspaces[i].code_only,
+ pa_def_subspaces[i].common,
+ pa_def_subspaces[i].dup_common,
+ pa_def_subspaces[i].zero,
+ pa_def_subspaces[i].sort,
+ pa_def_subspaces[i].access,
+ pa_def_subspaces[i].space_index,
+ pa_def_subspaces[i].alignment,
+ pa_def_subspaces[i].quadrant,
+ segment);
+ i++;
+ }
+}
+
+
+
+/* Create a new space NAME, with the appropriate flags as defined
+ by the given parameters. */
+
+static sd_chain_struct *
+create_new_space (name, spnum, loadable, defined, private,
+ sort, seg, user_defined)
+ char *name;
+ int spnum;
+ int loadable;
+ int defined;
+ int private;
+ int sort;
+ asection *seg;
+ int user_defined;
+{
+ sd_chain_struct *chain_entry;
+
+ chain_entry = (sd_chain_struct *) xmalloc (sizeof (sd_chain_struct));
+ if (!chain_entry)
+ as_fatal (_("Out of memory: could not allocate new space chain entry: %s\n"),
+ name);
+
+ SPACE_NAME (chain_entry) = (char *) xmalloc (strlen (name) + 1);
+ strcpy (SPACE_NAME (chain_entry), name);
+ SPACE_DEFINED (chain_entry) = defined;
+ SPACE_USER_DEFINED (chain_entry) = user_defined;
+ SPACE_SPNUM (chain_entry) = spnum;
+
+ chain_entry->sd_seg = seg;
+ chain_entry->sd_last_subseg = -1;
+ chain_entry->sd_subspaces = NULL;
+ chain_entry->sd_next = NULL;
+
+ /* Find spot for the new space based on its sort key. */
+ if (!space_dict_last)
+ space_dict_last = chain_entry;
+
+ if (space_dict_root == NULL)
+ space_dict_root = chain_entry;
+ else
+ {
+ sd_chain_struct *chain_pointer;
+ sd_chain_struct *prev_chain_pointer;
+
+ chain_pointer = space_dict_root;
+ prev_chain_pointer = NULL;
+
+ while (chain_pointer)
+ {
+ prev_chain_pointer = chain_pointer;
+ chain_pointer = chain_pointer->sd_next;
+ }
+
+ /* At this point we've found the correct place to add the new
+ entry. So add it and update the linked lists as appropriate. */
+ if (prev_chain_pointer)
+ {
+ chain_entry->sd_next = chain_pointer;
+ prev_chain_pointer->sd_next = chain_entry;
+ }
+ else
+ {
+ space_dict_root = chain_entry;
+ chain_entry->sd_next = chain_pointer;
+ }
+
+ if (chain_entry->sd_next == NULL)
+ space_dict_last = chain_entry;
+ }
+
+ /* This is here to catch predefined spaces which do not get
+ modified by the user's input. Another call is found at
+ the bottom of pa_parse_space_stmt to handle cases where
+ the user modifies a predefined space. */
+#ifdef obj_set_section_attributes
+ obj_set_section_attributes (seg, defined, private, sort, spnum);
+#endif
+
+ return chain_entry;
+}
+
+/* Create a new subspace NAME, with the appropriate flags as defined
+ by the given parameters.
+
+ Add the new subspace to the subspace dictionary chain in numerical
+ order as defined by the SORT entries. */
+
+static ssd_chain_struct *
+create_new_subspace (space, name, loadable, code_only, common,
+ dup_common, is_zero, sort, access, space_index,
+ alignment, quadrant, seg)
+ sd_chain_struct *space;
+ char *name;
+ int loadable, code_only, common, dup_common, is_zero;
+ int sort;
+ int access;
+ int space_index;
+ int alignment;
+ int quadrant;
+ asection *seg;
+{
+ ssd_chain_struct *chain_entry;
+
+ chain_entry = (ssd_chain_struct *) xmalloc (sizeof (ssd_chain_struct));
+ if (!chain_entry)
+ as_fatal (_("Out of memory: could not allocate new subspace chain entry: %s\n"), name);
+
+ SUBSPACE_NAME (chain_entry) = (char *) xmalloc (strlen (name) + 1);
+ strcpy (SUBSPACE_NAME (chain_entry), name);
+
+ /* Initialize subspace_defined. When we hit a .subspace directive
+ we'll set it to 1 which "locks-in" the subspace attributes. */
+ SUBSPACE_DEFINED (chain_entry) = 0;
+
+ chain_entry->ssd_subseg = USE_ALIASES ? pa_next_subseg (space) : 0;
+ chain_entry->ssd_seg = seg;
+ chain_entry->ssd_next = NULL;
+
+ /* Find spot for the new subspace based on its sort key. */
+ if (space->sd_subspaces == NULL)
+ space->sd_subspaces = chain_entry;
+ else
+ {
+ ssd_chain_struct *chain_pointer;
+ ssd_chain_struct *prev_chain_pointer;
+
+ chain_pointer = space->sd_subspaces;
+ prev_chain_pointer = NULL;
+
+ while (chain_pointer)
+ {
+ prev_chain_pointer = chain_pointer;
+ chain_pointer = chain_pointer->ssd_next;
+ }
+
+ /* Now we have somewhere to put the new entry. Insert it and update
+ the links. */
+ if (prev_chain_pointer)
+ {
+ chain_entry->ssd_next = chain_pointer;
+ prev_chain_pointer->ssd_next = chain_entry;
+ }
+ else
+ {
+ space->sd_subspaces = chain_entry;
+ chain_entry->ssd_next = chain_pointer;
+ }
+ }
+
+#ifdef obj_set_subsection_attributes
+ obj_set_subsection_attributes (seg, space->sd_seg, access,
+ sort, quadrant);
+#endif
+
+ return chain_entry;
+}
+
+/* Update the information for the given subspace based upon the
+ various arguments. Return the modified subspace chain entry. */
+
+static ssd_chain_struct *
+update_subspace (space, name, loadable, code_only, common, dup_common, sort,
+ zero, access, space_index, alignment, quadrant, section)
+ sd_chain_struct *space;
+ char *name;
+ int loadable;
+ int code_only;
+ int common;
+ int dup_common;
+ int zero;
+ int sort;
+ int access;
+ int space_index;
+ int alignment;
+ int quadrant;
+ asection *section;
+{
+ ssd_chain_struct *chain_entry;
+
+ chain_entry = is_defined_subspace (name);
+
+#ifdef obj_set_subsection_attributes
+ obj_set_subsection_attributes (section, space->sd_seg, access,
+ sort, quadrant);
+#endif
+
+ return chain_entry;
+}
+
+/* Return the space chain entry for the space with the name NAME or
+ NULL if no such space exists. */
+
+static sd_chain_struct *
+is_defined_space (name)
+ char *name;
+{
+ sd_chain_struct *chain_pointer;
+
+ for (chain_pointer = space_dict_root;
+ chain_pointer;
+ chain_pointer = chain_pointer->sd_next)
+ {
+ if (strcmp (SPACE_NAME (chain_pointer), name) == 0)
+ return chain_pointer;
+ }
+
+ /* No mapping from segment to space was found. Return NULL. */
+ return NULL;
+}
+
+/* Find and return the space associated with the given seg. If no mapping
+ from the given seg to a space is found, then return NULL.
+
+ Unlike subspaces, the number of spaces is not expected to grow much,
+ so a linear exhaustive search is OK here. */
+
+static sd_chain_struct *
+pa_segment_to_space (seg)
+ asection *seg;
+{
+ sd_chain_struct *space_chain;
+
+ /* Walk through each space looking for the correct mapping. */
+ for (space_chain = space_dict_root;
+ space_chain;
+ space_chain = space_chain->sd_next)
+ {
+ if (space_chain->sd_seg == seg)
+ return space_chain;
+ }
+
+ /* Mapping was not found. Return NULL. */
+ return NULL;
+}
+
+/* Return the space chain entry for the subspace with the name NAME or
+ NULL if no such subspace exists.
+
+ Uses a linear search through all the spaces and subspaces, this may
+ not be appropriate if we ever being placing each function in its
+ own subspace. */
+
+static ssd_chain_struct *
+is_defined_subspace (name)
+ char *name;
+{
+ sd_chain_struct *space_chain;
+ ssd_chain_struct *subspace_chain;
+
+ /* Walk through each space. */
+ for (space_chain = space_dict_root;
+ space_chain;
+ space_chain = space_chain->sd_next)
+ {
+ /* Walk through each subspace looking for a name which matches. */
+ for (subspace_chain = space_chain->sd_subspaces;
+ subspace_chain;
+ subspace_chain = subspace_chain->ssd_next)
+ if (strcmp (SUBSPACE_NAME (subspace_chain), name) == 0)
+ return subspace_chain;
+ }
+
+ /* Subspace wasn't found. Return NULL. */
+ return NULL;
+}
+
+/* Find and return the subspace associated with the given seg. If no
+ mapping from the given seg to a subspace is found, then return NULL.
+
+ If we ever put each procedure/function within its own subspace
+ (to make life easier on the compiler and linker), then this will have
+ to become more efficient. */
+
+static ssd_chain_struct *
+pa_subsegment_to_subspace (seg, subseg)
+ asection *seg;
+ subsegT subseg;
+{
+ sd_chain_struct *space_chain;
+ ssd_chain_struct *subspace_chain;
+
+ /* Walk through each space. */
+ for (space_chain = space_dict_root;
+ space_chain;
+ space_chain = space_chain->sd_next)
+ {
+ if (space_chain->sd_seg == seg)
+ {
+ /* Walk through each subspace within each space looking for
+ the correct mapping. */
+ for (subspace_chain = space_chain->sd_subspaces;
+ subspace_chain;
+ subspace_chain = subspace_chain->ssd_next)
+ if (subspace_chain->ssd_subseg == (int) subseg)
+ return subspace_chain;
+ }
+ }
+
+ /* No mapping from subsegment to subspace found. Return NULL. */
+ return NULL;
+}
+
+/* Given a number, try and find a space with the name number.
+
+ Return a pointer to a space dictionary chain entry for the space
+ that was found or NULL on failure. */
+
+static sd_chain_struct *
+pa_find_space_by_number (number)
+ int number;
+{
+ sd_chain_struct *space_chain;
+
+ for (space_chain = space_dict_root;
+ space_chain;
+ space_chain = space_chain->sd_next)
+ {
+ if (SPACE_SPNUM (space_chain) == (unsigned int) number)
+ return space_chain;
+ }
+
+ /* No appropriate space found. Return NULL. */
+ return NULL;
+}
+
+/* Return the starting address for the given subspace. If the starting
+ address is unknown then return zero. */
+
+static unsigned int
+pa_subspace_start (space, quadrant)
+ sd_chain_struct *space;
+ int quadrant;
+{
+#ifdef OBJ_SOM
+ /* FIXME. Assumes everyone puts read/write data at 0x4000000, this
+ is not correct for the PA OSF1 port. */
+ if ((strcmp (SPACE_NAME (space), "$PRIVATE$") == 0) && quadrant == 1)
+ return 0x40000000;
+ else if (space->sd_seg == data_section && quadrant == 1)
+ return 0x40000000;
+ else
+ return 0;
+#endif
+ return 0;
+}
+
+/* FIXME. Needs documentation. */
+static int
+pa_next_subseg (space)
+ sd_chain_struct *space;
+{
+
+ space->sd_last_subseg++;
+ return space->sd_last_subseg;
+}
+
+/* Helper function for pa_stringer. Used to find the end of
+ a string. */
+
+static unsigned int
+pa_stringer_aux (s)
+ char *s;
+{
+ unsigned int c = *s & CHAR_MASK;
+
+ /* We must have a valid space and subspace. */
+ pa_check_current_space_and_subspace ();
+
+ switch (c)
+ {
+ case '\"':
+ c = NOT_A_CHAR;
+ break;
+ default:
+ break;
+ }
+ return c;
+}
+
+/* Handle a .STRING type pseudo-op. */
+
+static void
+pa_stringer (append_zero)
+ int append_zero;
+{
+ char *s, num_buf[4];
+ unsigned int c;
+ int i;
+
+ /* Preprocess the string to handle PA-specific escape sequences.
+ For example, \xDD where DD is a hexidecimal number should be
+ changed to \OOO where OOO is an octal number. */
+
+ /* Skip the opening quote. */
+ s = input_line_pointer + 1;
+
+ while (is_a_char (c = pa_stringer_aux (s++)))
+ {
+ if (c == '\\')
+ {
+ c = *s;
+ switch (c)
+ {
+ /* Handle \x<num>. */
+ case 'x':
+ {
+ unsigned int number;
+ int num_digit;
+ char dg;
+ char *s_start = s;
+
+ /* Get pas the 'x'. */
+ s++;
+ for (num_digit = 0, number = 0, dg = *s;
+ num_digit < 2
+ && (isdigit (dg) || (dg >= 'a' && dg <= 'f')
+ || (dg >= 'A' && dg <= 'F'));
+ num_digit++)
+ {
+ if (isdigit (dg))
+ number = number * 16 + dg - '0';
+ else if (dg >= 'a' && dg <= 'f')
+ number = number * 16 + dg - 'a' + 10;
+ else
+ number = number * 16 + dg - 'A' + 10;
+
+ s++;
+ dg = *s;
+ }
+ if (num_digit > 0)
+ {
+ switch (num_digit)
+ {
+ case 1:
+ sprintf (num_buf, "%02o", number);
+ break;
+ case 2:
+ sprintf (num_buf, "%03o", number);
+ break;
+ }
+ for (i = 0; i <= num_digit; i++)
+ s_start[i] = num_buf[i];
+ }
+ break;
+ }
+ /* This might be a "\"", skip over the escaped char. */
+ default:
+ s++;
+ break;
+ }
+ }
+ }
+ stringer (append_zero);
+ pa_undefine_label ();
+}
+
+/* Handle a .VERSION pseudo-op. */
+
+static void
+pa_version (unused)
+ int unused;
+{
+ obj_version (0);
+ pa_undefine_label ();
+}
+
+#ifdef OBJ_SOM
+
+/* Handle a .COMPILER pseudo-op. */
+
+static void
+pa_compiler (unused)
+ int unused;
+{
+ obj_som_compiler (0);
+ pa_undefine_label ();
+}
+
+#endif
+
+/* Handle a .COPYRIGHT pseudo-op. */
+
+static void
+pa_copyright (unused)
+ int unused;
+{
+ obj_copyright (0);
+ pa_undefine_label ();
+}
+
+/* Just like a normal cons, but when finished we have to undefine
+ the latest space label. */
+
+static void
+pa_cons (nbytes)
+ int nbytes;
+{
+ cons (nbytes);
+ pa_undefine_label ();
+}
+
+/* Switch to the data space. As usual delete our label. */
+
+static void
+pa_data (unused)
+ int unused;
+{
+ current_space = is_defined_space ("$PRIVATE$");
+ current_subspace
+ = pa_subsegment_to_subspace (current_space->sd_seg, 0);
+ s_data (0);
+ pa_undefine_label ();
+}
+
+/* Like float_cons, but we need to undefine our label. */
+
+static void
+pa_float_cons (float_type)
+ int float_type;
+{
+ float_cons (float_type);
+ pa_undefine_label ();
+}
+
+/* Like s_fill, but delete our label when finished. */
+
+static void
+pa_fill (unused)
+ int unused;
+{
+ /* We must have a valid space and subspace. */
+ pa_check_current_space_and_subspace ();
+
+ s_fill (0);
+ pa_undefine_label ();
+}
+
+/* Like lcomm, but delete our label when finished. */
+
+static void
+pa_lcomm (needs_align)
+ int needs_align;
+{
+ /* We must have a valid space and subspace. */
+ pa_check_current_space_and_subspace ();
+
+ s_lcomm (needs_align);
+ pa_undefine_label ();
+}
+
+/* Like lsym, but delete our label when finished. */
+
+static void
+pa_lsym (unused)
+ int unused;
+{
+ /* We must have a valid space and subspace. */
+ pa_check_current_space_and_subspace ();
+
+ s_lsym (0);
+ pa_undefine_label ();
+}
+
+/* Switch to the text space. Like s_text, but delete our
+ label when finished. */
+static void
+pa_text (unused)
+ int unused;
+{
+ current_space = is_defined_space ("$TEXT$");
+ current_subspace
+ = pa_subsegment_to_subspace (current_space->sd_seg, 0);
+
+ s_text (0);
+ pa_undefine_label ();
+}
+
+/* On the PA relocations which involve function symbols must not be
+ adjusted. This so that the linker can know when/how to create argument
+ relocation stubs for indirect calls and calls to static functions.
+
+ "T" field selectors create DLT relative fixups for accessing
+ globals and statics in PIC code; each DLT relative fixup creates
+ an entry in the DLT table. The entries contain the address of
+ the final target (eg accessing "foo" would create a DLT entry
+ with the address of "foo").
+
+ Unfortunately, the HP linker doesn't take into account any addend
+ when generating the DLT; so accessing $LIT$+8 puts the address of
+ $LIT$ into the DLT rather than the address of $LIT$+8.
+
+ The end result is we can't perform relocation symbol reductions for
+ any fixup which creates entries in the DLT (eg they use "T" field
+ selectors).
+
+ Reject reductions involving symbols with external scope; such
+ reductions make life a living hell for object file editors.
+
+ FIXME. Also reject R_HPPA relocations which are 32bits wide in
+ the code space. The SOM BFD backend doesn't know how to pull the
+ right bits out of an instruction. */
+
+int
+hppa_fix_adjustable (fixp)
+ fixS *fixp;
+{
+ struct hppa_fix_struct *hppa_fix;
+
+ hppa_fix = (struct hppa_fix_struct *) fixp->tc_fix_data;
+
+#ifdef OBJ_SOM
+ /* Reject reductions of symbols in 32bit relocs. */
+ if (fixp->fx_r_type == R_HPPA && hppa_fix->fx_r_format == 32)
+ return 0;
+
+ /* Reject reductions of symbols in sym1-sym2 expressions when
+ the fixup will occur in a CODE subspace.
+
+ XXX FIXME: Long term we probably want to reject all of these;
+ for example reducing in the debug section would lose if we ever
+ supported using the optimizing hp linker. */
+ if (fixp->fx_addsy
+ && fixp->fx_subsy
+ && (hppa_fix->segment->flags & SEC_CODE))
+ {
+ /* Apparently sy_used_in_reloc never gets set for sub symbols. */
+ fixp->fx_subsy->sy_used_in_reloc = 1;
+ return 0;
+ }
+
+ /* We can't adjust any relocs that use LR% and RR% field selectors.
+ That confuses the HP linker. */
+ if (hppa_fix->fx_r_field == e_lrsel
+ || hppa_fix->fx_r_field == e_rrsel
+ || hppa_fix->fx_r_field == e_nlrsel)
+ return 0;
+#endif
+
+ /* Reject reductions of symbols in DLT relative relocs,
+ relocations with plabels. */
+ if (hppa_fix->fx_r_field == e_tsel
+ || hppa_fix->fx_r_field == e_ltsel
+ || hppa_fix->fx_r_field == e_rtsel
+ || hppa_fix->fx_r_field == e_psel
+ || hppa_fix->fx_r_field == e_rpsel
+ || hppa_fix->fx_r_field == e_lpsel)
+ return 0;
+
+ if (fixp->fx_addsy && fixp->fx_addsy->bsym->flags & BSF_GLOBAL)
+ return 0;
+
+ /* Reject absolute calls (jumps). */
+ if (hppa_fix->fx_r_type == R_HPPA_ABS_CALL)
+ return 0;
+
+ /* Reject reductions of function symbols. */
+ if (fixp->fx_addsy == 0
+ || (fixp->fx_addsy->bsym->flags & BSF_FUNCTION) == 0)
+ return 1;
+
+ return 0;
+}
+
+/* Return nonzero if the fixup in FIXP will require a relocation,
+ even it if appears that the fixup could be completely handled
+ within GAS. */
+
+int
+hppa_force_relocation (fixp)
+ fixS *fixp;
+{
+ struct hppa_fix_struct *hppa_fixp;
+ int distance;
+
+ hppa_fixp = (struct hppa_fix_struct *) fixp->tc_fix_data;
+#ifdef OBJ_SOM
+ if (fixp->fx_r_type == R_HPPA_ENTRY || fixp->fx_r_type == R_HPPA_EXIT
+ || fixp->fx_r_type == R_HPPA_BEGIN_BRTAB
+ || fixp->fx_r_type == R_HPPA_END_BRTAB
+ || fixp->fx_r_type == R_HPPA_BEGIN_TRY
+ || fixp->fx_r_type == R_HPPA_END_TRY
+ || (fixp->fx_addsy != NULL && fixp->fx_subsy != NULL
+ && (hppa_fixp->segment->flags & SEC_CODE) != 0))
+ return 1;
+#endif
+
+#define arg_reloc_stub_needed(CALLER, CALLEE) \
+ ((CALLEE) && (CALLER) && ((CALLEE) != (CALLER)))
+
+ /* It is necessary to force PC-relative calls/jumps to have a relocation
+ entry if they're going to need either a argument relocation or long
+ call stub. FIXME. Can't we need the same for absolute calls? */
+ if (fixp->fx_pcrel && fixp->fx_addsy
+ && (arg_reloc_stub_needed ((long) ((obj_symbol_type *)
+ fixp->fx_addsy->bsym)->tc_data.ap.hppa_arg_reloc,
+
+ hppa_fixp->fx_arg_reloc)))
+ return 1;
+ distance = (fixp->fx_offset + S_GET_VALUE (fixp->fx_addsy)
+ - md_pcrel_from (fixp));
+ /* Now check and see if we're going to need a long-branch stub. */
+ if (fixp->fx_r_type == R_HPPA_PCREL_CALL
+ && (distance > 262143 || distance < -262144))
+ return 1;
+
+ if (fixp->fx_r_type == R_HPPA_ABS_CALL)
+ return 1;
+#undef arg_reloc_stub_needed
+
+ /* No need (yet) to force another relocations to be emitted. */
+ return 0;
+}
+
+/* Now for some ELF specific code. FIXME. */
+#ifdef OBJ_ELF
+/* Mark the end of a function so that it's possible to compute
+ the size of the function in hppa_elf_final_processing. */
+
+static void
+hppa_elf_mark_end_of_function ()
+{
+ /* ELF does not have EXIT relocations. All we do is create a
+ temporary symbol marking the end of the function. */
+ char *name = (char *)
+ xmalloc (strlen ("L$\001end_") +
+ strlen (S_GET_NAME (last_call_info->start_symbol)) + 1);
+
+ if (name)
+ {
+ symbolS *symbolP;
+
+ strcpy (name, "L$\001end_");
+ strcat (name, S_GET_NAME (last_call_info->start_symbol));
+
+ /* If we have a .exit followed by a .procend, then the
+ symbol will have already been defined. */
+ symbolP = symbol_find (name);
+ if (symbolP)
+ {
+ /* The symbol has already been defined! This can
+ happen if we have a .exit followed by a .procend.
+
+ This is *not* an error. All we want to do is free
+ the memory we just allocated for the name and continue. */
+ xfree (name);
+ }
+ else
+ {
+ /* symbol value should be the offset of the
+ last instruction of the function */
+ symbolP = symbol_new (name, now_seg, (valueT) (frag_now_fix () - 4),
+ frag_now);
+
+ assert (symbolP);
+ symbolP->bsym->flags = BSF_LOCAL;
+ symbol_table_insert (symbolP);
+ }
+
+ if (symbolP)
+ last_call_info->end_symbol = symbolP;
+ else
+ as_bad (_("Symbol '%s' could not be created."), name);
+
+ }
+ else
+ as_bad (_("No memory for symbol name."));
+
+}
+
+/* For ELF, this function serves one purpose: to setup the st_size
+ field of STT_FUNC symbols. To do this, we need to scan the
+ call_info structure list, determining st_size in by taking the
+ difference in the address of the beginning/end marker symbols. */
+
+void
+elf_hppa_final_processing ()
+{
+ struct call_info *call_info_pointer;
+
+ for (call_info_pointer = call_info_root;
+ call_info_pointer;
+ call_info_pointer = call_info_pointer->ci_next)
+ {
+ elf_symbol_type *esym
+ = (elf_symbol_type *) call_info_pointer->start_symbol->bsym;
+ esym->internal_elf_sym.st_size =
+ S_GET_VALUE (call_info_pointer->end_symbol)
+ - S_GET_VALUE (call_info_pointer->start_symbol) + 4;
+ }
+}
+#endif
diff --git a/gas/config/tc-hppa.h b/gas/config/tc-hppa.h
new file mode 100644
index 0000000000..c1541d9373
--- /dev/null
+++ b/gas/config/tc-hppa.h
@@ -0,0 +1,162 @@
+/* tc-hppa.h -- Header file for the PA
+ Copyright (C) 1989, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+
+/* HP PA-RISC support was contributed by the Center for Software Science
+ at the University of Utah. */
+
+/* Please refrain from exposing the world to the internals of tc-hppa.c
+ when this file is included. This means only declaring exported functions,
+ (please PARAMize them!) not exporting structures and data items which
+ are used solely within tc-hppa.c, etc.
+
+ Also refrain from adding any more object file dependent code, there is
+ already far too much object file format dependent code in this file.
+ In theory this file should contain only exported functions, structures
+ and data declarations common to all PA assemblers. */
+
+#ifndef _TC_HPPA_H
+#define _TC_HPPA_H
+
+#ifndef TC_HPPA
+#define TC_HPPA 1
+#endif
+
+#define TARGET_BYTES_BIG_ENDIAN 1
+
+#define TARGET_ARCH bfd_arch_hppa
+
+#define WORKING_DOT_WORD
+
+/* FIXME. The lack of a place to put things which are both target cpu
+ and target format dependent makes hacks like this necessary. */
+#ifdef OBJ_ELF
+#include "bfd/elf32-hppa.h"
+#define TARGET_FORMAT "elf32-hppa"
+#endif
+
+#ifdef OBJ_SOM
+#include "bfd/som.h"
+#define TARGET_FORMAT "som"
+#endif
+
+/* FIXME. Why oh why aren't these defined somewhere globally? */
+#ifndef FALSE
+#define FALSE (0)
+#define TRUE (!FALSE)
+#endif
+
+#define ASEC_NULL (asection *)0
+
+/* Labels are not required to have a colon for a suffix. */
+#define LABELS_WITHOUT_COLONS
+
+/* FIXME. This should be static and declared in tc-hppa.c, but
+ pa_define_label gets used outside of tc-hppa.c via tc_frob_label.
+ Should also be PARAMized, but symbolS isn't available here. */
+extern void pa_define_label ();
+
+/* FIXME. Types not available here, so they can't be PARAMized. */
+extern void parse_cons_expression_hppa ();
+extern void cons_fix_new_hppa ();
+extern int hppa_force_relocation ();
+
+/* This gets called before writing the object file to make sure
+ things like entry/exit and proc/procend pairs match. */
+extern void pa_check_eof PARAMS ((void));
+#define tc_frob_file pa_check_eof
+
+#define tc_frob_label(sym) pa_define_label (sym)
+
+/* The PA does not need support for either of these. */
+#define tc_crawl_symbol_chain(headers) {;}
+#define tc_headers_hook(headers) {;}
+
+#define RELOC_EXPANSION_POSSIBLE
+#define MAX_RELOC_EXPANSION 6
+
+/* FIXME. More things which are both HPPA and ELF specific. There is
+ nowhere to put such things. */
+#ifdef OBJ_ELF
+#define elf_tc_final_processing elf_hppa_final_processing
+void elf_hppa_final_processing PARAMS ((void));
+#endif
+
+/* The PA needs to parse field selectors in .byte, etc. */
+
+#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) \
+ parse_cons_expression_hppa (EXP)
+#define TC_CONS_FIX_NEW cons_fix_new_hppa
+
+/* On the PA, an equal sign often appears as a condition or nullification
+ completer in an instruction. This can be detected by checking the
+ previous character, if the character is a comma, then the equal is
+ being used as part of an instruction. */
+#define TC_EQUAL_IN_INSN(C, PTR) ((C) == ',')
+
+/* Similarly for an exclamation point. It is used in FP comparison
+ instructions and as an end of line marker. When used in an instruction
+ it will always follow a comma. */
+#define TC_EOL_IN_INSN(PTR) (*(PTR) == '!' && (PTR)[-1] == ',')
+
+#define tc_fix_adjustable hppa_fix_adjustable
+
+/* Because of the strange PA calling conventions, it is sometimes
+ necessary to emit a relocation for a call even though it would
+ normally appear safe to handle it completely within GAS. */
+#define TC_FORCE_RELOCATION(FIXP) hppa_force_relocation (FIXP)
+
+#ifdef OBJ_SOM
+/* If a symbol is imported, but never used, then the symbol should
+ *not* end up in the symbol table. Likewise for absolute symbols
+ with local scope. */
+#define tc_frob_symbol(sym,punt) \
+ if ((S_GET_SEGMENT (sym) == &bfd_und_section && sym->sy_used == 0) \
+ || (S_GET_SEGMENT (sym) == &bfd_abs_section \
+ && (sym->bsym->flags & BSF_EXPORT) == 0)) \
+ punt = 1
+
+/* We need to be able to make relocations involving the difference of
+ two symbols. This includes the difference of two symbols when
+ one of them is undefined (this comes up in PIC code generation).
+
+ We don't define DIFF_EXPR_OK because it does the wrong thing if
+ the add symbol is undefined and the sub symbol is a symbol in
+ the same section as the relocation. We also need some way to
+ specialize some code in adjust_reloc_syms. */
+#define UNDEFINED_DIFFERENCE_OK
+#endif
+
+#ifdef OBJ_ELF
+#define tc_frob_symbol(sym,punt) \
+ { \
+ if ((S_GET_SEGMENT (sym) == &bfd_und_section && sym->sy_used == 0) \
+ || (S_GET_SEGMENT (sym) == &bfd_abs_section \
+ && (sym->bsym->flags & BSF_EXPORT) == 0)) \
+ punt = 1; \
+ }
+#endif
+
+#define md_operand(x)
+
+#define TC_FIX_TYPE PTR
+#define TC_INIT_FIX_DATA(FIXP) ((FIXP)->tc_fix_data = NULL)
+
+#endif /* _TC_HPPA_H */
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
new file mode 100644
index 0000000000..7149d711b9
--- /dev/null
+++ b/gas/config/tc-i386.c
@@ -0,0 +1,4475 @@
+/* i386.c -- Assemble code for the Intel 80386
+ Copyright (C) 1989, 91, 92, 93, 94, 95, 96, 97, 98, 1999
+ Free Software Foundation.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/*
+ Intel 80386 machine specific gas.
+ Written by Eliot Dresselhaus (eliot@mgm.mit.edu).
+ Bugs & suggestions are completely welcome. This is free software.
+ Please help us make it better.
+ */
+
+#include <ctype.h>
+
+#include "as.h"
+#include "subsegs.h"
+#include "opcode/i386.h"
+
+#ifndef TC_RELOC
+#define TC_RELOC(X,Y) (Y)
+#endif
+
+#ifndef REGISTER_WARNINGS
+#define REGISTER_WARNINGS 1
+#endif
+
+#ifndef SCALE1_WHEN_NO_INDEX
+/* Specifying a scale factor besides 1 when there is no index is
+ futile. eg. `mov (%ebx,2),%al' does exactly the same as
+ `mov (%ebx),%al'. To slavishly follow what the programmer
+ specified, set SCALE1_WHEN_NO_INDEX to 0. */
+#define SCALE1_WHEN_NO_INDEX 1
+#endif
+
+#define true 1
+#define false 0
+
+static unsigned int mode_from_disp_size PARAMS ((unsigned int));
+static int fits_in_signed_byte PARAMS ((long));
+static int fits_in_unsigned_byte PARAMS ((long));
+static int fits_in_unsigned_word PARAMS ((long));
+static int fits_in_signed_word PARAMS ((long));
+static int smallest_imm_type PARAMS ((long));
+static int add_prefix PARAMS ((unsigned int));
+static void set_16bit_code_flag PARAMS ((int));
+static void set_intel_syntax PARAMS ((int));
+
+#ifdef BFD_ASSEMBLER
+static bfd_reloc_code_real_type reloc
+ PARAMS ((int, int, bfd_reloc_code_real_type));
+#endif
+
+/* 'md_assemble ()' gathers together information and puts it into a
+ i386_insn. */
+
+struct _i386_insn
+ {
+ /* TM holds the template for the insn were currently assembling. */
+ template tm;
+
+ /* SUFFIX holds the instruction mnemonic suffix if given.
+ (e.g. 'l' for 'movl') */
+ char suffix;
+
+ /* Operands are coded with OPERANDS, TYPES, DISPS, IMMS, and REGS. */
+
+ /* OPERANDS gives the number of given operands. */
+ unsigned int operands;
+
+ /* REG_OPERANDS, DISP_OPERANDS, MEM_OPERANDS, IMM_OPERANDS give the number
+ of given register, displacement, memory operands and immediate
+ operands. */
+ unsigned int reg_operands, disp_operands, mem_operands, imm_operands;
+
+ /* TYPES [i] is the type (see above #defines) which tells us how to
+ search through DISPS [i] & IMMS [i] & REGS [i] for the required
+ operand. */
+ unsigned int types[MAX_OPERANDS];
+
+ /* Displacements (if given) for each operand. */
+ expressionS *disps[MAX_OPERANDS];
+
+ /* Relocation type for operand */
+#ifdef BFD_ASSEMBLER
+ enum bfd_reloc_code_real disp_reloc[MAX_OPERANDS];
+#else
+ int disp_reloc[MAX_OPERANDS];
+#endif
+
+ /* Immediate operands (if given) for each operand. */
+ expressionS *imms[MAX_OPERANDS];
+
+ /* Register operands (if given) for each operand. */
+ const reg_entry *regs[MAX_OPERANDS];
+
+ /* BASE_REG, INDEX_REG, and LOG2_SCALE_FACTOR are used to encode
+ the base index byte below. */
+ const reg_entry *base_reg;
+ const reg_entry *index_reg;
+ unsigned int log2_scale_factor;
+
+ /* SEG gives the seg_entries of this insn. They are zero unless
+ explicit segment overrides are given. */
+ const seg_entry *seg[2]; /* segments for memory operands (if given) */
+
+ /* PREFIX holds all the given prefix opcodes (usually null).
+ PREFIXES is the number of prefix opcodes. */
+ unsigned int prefixes;
+ unsigned char prefix[MAX_PREFIXES];
+
+ /* RM and SIB are the modrm byte and the sib byte where the
+ addressing modes of this insn are encoded. */
+
+ modrm_byte rm;
+ sib_byte sib;
+ };
+
+typedef struct _i386_insn i386_insn;
+
+/* List of chars besides those in app.c:symbol_chars that can start an
+ operand. Used to prevent the scrubber eating vital white-space. */
+#ifdef LEX_AT
+const char extra_symbol_chars[] = "*%-(@";
+#else
+const char extra_symbol_chars[] = "*%-(";
+#endif
+
+/* This array holds the chars that always start a comment. If the
+ pre-processor is disabled, these aren't very useful */
+#if defined (TE_I386AIX) || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) && ! defined (TE_LINUX))
+/* Putting '/' here makes it impossible to use the divide operator.
+ However, we need it for compatibility with SVR4 systems. */
+const char comment_chars[] = "#/";
+#define PREFIX_SEPARATOR '\\'
+#else
+const char comment_chars[] = "#";
+#define PREFIX_SEPARATOR '/'
+#endif
+
+/* This array holds the chars that only start a comment at the beginning of
+ a line. If the line seems to have the form '# 123 filename'
+ .line and .file directives will appear in the pre-processed output */
+/* Note that input_file.c hand checks for '#' at the beginning of the
+ first line of the input file. This is because the compiler outputs
+ #NO_APP at the beginning of its output. */
+/* Also note that comments started like this one will always work if
+ '/' isn't otherwise defined. */
+#if defined (TE_I386AIX) || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) && ! defined (TE_LINUX))
+const char line_comment_chars[] = "";
+#else
+const char line_comment_chars[] = "/";
+#endif
+
+const char line_separator_chars[] = "";
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* As in 0f12.456 */
+/* or 0d1.2345e12 */
+const char FLT_CHARS[] = "fFdDxX";
+
+/* tables for lexical analysis */
+static char mnemonic_chars[256];
+static char register_chars[256];
+static char operand_chars[256];
+static char identifier_chars[256];
+static char digit_chars[256];
+
+/* lexical macros */
+#define is_mnemonic_char(x) (mnemonic_chars[(unsigned char) x])
+#define is_operand_char(x) (operand_chars[(unsigned char) x])
+#define is_register_char(x) (register_chars[(unsigned char) x])
+#define is_space_char(x) ((x) == ' ')
+#define is_identifier_char(x) (identifier_chars[(unsigned char) x])
+#define is_digit_char(x) (digit_chars[(unsigned char) x])
+
+/* put here all non-digit non-letter charcters that may occur in an operand */
+static char operand_special_chars[] = "%$-+(,)*._~/<>|&^!:[@]";
+
+/* md_assemble() always leaves the strings it's passed unaltered. To
+ effect this we maintain a stack of saved characters that we've smashed
+ with '\0's (indicating end of strings for various sub-fields of the
+ assembler instruction). */
+static char save_stack[32];
+static char *save_stack_p; /* stack pointer */
+#define END_STRING_AND_SAVE(s) \
+ do { *save_stack_p++ = *(s); *(s) = '\0'; } while (0)
+#define RESTORE_END_STRING(s) \
+ do { *(s) = *--save_stack_p; } while (0)
+
+/* The instruction we're assembling. */
+static i386_insn i;
+
+/* Possible templates for current insn. */
+static const templates *current_templates;
+
+/* Per instruction expressionS buffers: 2 displacements & 2 immediate max. */
+static expressionS disp_expressions[2], im_expressions[2];
+
+static int this_operand; /* current operand we are working on */
+
+static int flag_do_long_jump; /* FIXME what does this do? */
+
+static int flag_16bit_code; /* 1 if we're writing 16-bit code, 0 if 32-bit */
+
+static int intel_syntax = 0; /* 1 for intel syntax, 0 if att syntax */
+
+static int allow_naked_reg = 0; /* 1 if register prefix % not required */
+
+/* Interface to relax_segment.
+ There are 2 relax states for 386 jump insns: one for conditional &
+ one for unconditional jumps. This is because the these two types
+ of jumps add different sizes to frags when we're figuring out what
+ sort of jump to choose to reach a given label. */
+
+/* types */
+#define COND_JUMP 1 /* conditional jump */
+#define UNCOND_JUMP 2 /* unconditional jump */
+/* sizes */
+#define CODE16 1
+#define SMALL 0
+#define SMALL16 (SMALL|CODE16)
+#define BIG 2
+#define BIG16 (BIG|CODE16)
+
+#ifndef INLINE
+#ifdef __GNUC__
+#define INLINE __inline__
+#else
+#define INLINE
+#endif
+#endif
+
+#define ENCODE_RELAX_STATE(type,size) \
+ ((relax_substateT)((type<<2) | (size)))
+#define SIZE_FROM_RELAX_STATE(s) \
+ ( (((s) & 0x3) == BIG ? 4 : (((s) & 0x3) == BIG16 ? 2 : 1)) )
+
+/* This table is used by relax_frag to promote short jumps to long
+ ones where necessary. SMALL (short) jumps may be promoted to BIG
+ (32 bit long) ones, and SMALL16 jumps to BIG16 (16 bit long). We
+ don't allow a short jump in a 32 bit code segment to be promoted to
+ a 16 bit offset jump because it's slower (requires data size
+ prefix), and doesn't work, unless the destination is in the bottom
+ 64k of the code segment (The top 16 bits of eip are zeroed). */
+
+const relax_typeS md_relax_table[] =
+{
+/* The fields are:
+ 1) most positive reach of this state,
+ 2) most negative reach of this state,
+ 3) how many bytes this mode will add to the size of the current frag
+ 4) which index into the table to try if we can't fit into this one.
+ */
+ {1, 1, 0, 0},
+ {1, 1, 0, 0},
+ {1, 1, 0, 0},
+ {1, 1, 0, 0},
+
+ {127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE (COND_JUMP, BIG)},
+ {127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE (COND_JUMP, BIG16)},
+ /* dword conditionals adds 4 bytes to frag:
+ 1 extra opcode byte, 3 extra displacement bytes. */
+ {0, 0, 4, 0},
+ /* word conditionals add 2 bytes to frag:
+ 1 extra opcode byte, 1 extra displacement byte. */
+ {0, 0, 2, 0},
+
+ {127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE (UNCOND_JUMP, BIG)},
+ {127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE (UNCOND_JUMP, BIG16)},
+ /* dword jmp adds 3 bytes to frag:
+ 0 extra opcode bytes, 3 extra displacement bytes. */
+ {0, 0, 3, 0},
+ /* word jmp adds 1 byte to frag:
+ 0 extra opcode bytes, 1 extra displacement byte. */
+ {0, 0, 1, 0}
+
+};
+
+
+void
+i386_align_code (fragP, count)
+ fragS *fragP;
+ int count;
+{
+ /* Various efficient no-op patterns for aligning code labels. */
+ /* Note: Don't try to assemble the instructions in the comments. */
+ /* 0L and 0w are not legal */
+ static const char f32_1[] =
+ {0x90}; /* nop */
+ static const char f32_2[] =
+ {0x89,0xf6}; /* movl %esi,%esi */
+ static const char f32_3[] =
+ {0x8d,0x76,0x00}; /* leal 0(%esi),%esi */
+ static const char f32_4[] =
+ {0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */
+ static const char f32_5[] =
+ {0x90, /* nop */
+ 0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */
+ static const char f32_6[] =
+ {0x8d,0xb6,0x00,0x00,0x00,0x00}; /* leal 0L(%esi),%esi */
+ static const char f32_7[] =
+ {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */
+ static const char f32_8[] =
+ {0x90, /* nop */
+ 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */
+ static const char f32_9[] =
+ {0x89,0xf6, /* movl %esi,%esi */
+ 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
+ static const char f32_10[] =
+ {0x8d,0x76,0x00, /* leal 0(%esi),%esi */
+ 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
+ static const char f32_11[] =
+ {0x8d,0x74,0x26,0x00, /* leal 0(%esi,1),%esi */
+ 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
+ static const char f32_12[] =
+ {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */
+ 0x8d,0xbf,0x00,0x00,0x00,0x00}; /* leal 0L(%edi),%edi */
+ static const char f32_13[] =
+ {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */
+ 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
+ static const char f32_14[] =
+ {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00, /* leal 0L(%esi,1),%esi */
+ 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */
+ static const char f32_15[] =
+ {0xeb,0x0d,0x90,0x90,0x90,0x90,0x90, /* jmp .+15; lotsa nops */
+ 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90};
+ static const char f16_4[] =
+ {0x8d,0xb4,0x00,0x00}; /* lea 0w(%si),%si */
+ static const char f16_5[] =
+ {0x90, /* nop */
+ 0x8d,0xb4,0x00,0x00}; /* lea 0w(%si),%si */
+ static const char f16_6[] =
+ {0x89,0xf6, /* mov %si,%si */
+ 0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */
+ static const char f16_7[] =
+ {0x8d,0x74,0x00, /* lea 0(%si),%si */
+ 0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */
+ static const char f16_8[] =
+ {0x8d,0xb4,0x00,0x00, /* lea 0w(%si),%si */
+ 0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */
+ static const char *const f32_patt[] = {
+ f32_1, f32_2, f32_3, f32_4, f32_5, f32_6, f32_7, f32_8,
+ f32_9, f32_10, f32_11, f32_12, f32_13, f32_14, f32_15
+ };
+ static const char *const f16_patt[] = {
+ f32_1, f32_2, f32_3, f16_4, f16_5, f16_6, f16_7, f16_8,
+ f32_15, f32_15, f32_15, f32_15, f32_15, f32_15, f32_15
+ };
+
+ if (count > 0 && count <= 15)
+ {
+ if (flag_16bit_code)
+ {
+ memcpy(fragP->fr_literal + fragP->fr_fix,
+ f16_patt[count - 1], count);
+ if (count > 8) /* adjust jump offset */
+ fragP->fr_literal[fragP->fr_fix + 1] = count - 2;
+ }
+ else
+ memcpy(fragP->fr_literal + fragP->fr_fix,
+ f32_patt[count - 1], count);
+ fragP->fr_var = count;
+ }
+}
+
+static char *output_invalid PARAMS ((int c));
+static int i386_operand PARAMS ((char *operand_string));
+static int i386_intel_operand PARAMS ((char *operand_string, int got_a_float));
+static const reg_entry *parse_register PARAMS ((char *reg_string,
+ char **end_op));
+
+#ifndef I386COFF
+static void s_bss PARAMS ((int));
+#endif
+
+symbolS *GOT_symbol; /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
+
+static INLINE unsigned int
+mode_from_disp_size (t)
+ unsigned int t;
+{
+ return (t & Disp8) ? 1 : (t & (Disp16|Disp32)) ? 2 : 0;
+}
+
+static INLINE int
+fits_in_signed_byte (num)
+ long num;
+{
+ return (num >= -128) && (num <= 127);
+} /* fits_in_signed_byte() */
+
+static INLINE int
+fits_in_unsigned_byte (num)
+ long num;
+{
+ return (num & 0xff) == num;
+} /* fits_in_unsigned_byte() */
+
+static INLINE int
+fits_in_unsigned_word (num)
+ long num;
+{
+ return (num & 0xffff) == num;
+} /* fits_in_unsigned_word() */
+
+static INLINE int
+fits_in_signed_word (num)
+ long num;
+{
+ return (-32768 <= num) && (num <= 32767);
+} /* fits_in_signed_word() */
+
+static int
+smallest_imm_type (num)
+ long num;
+{
+#if 0
+ /* This code is disabled because all the Imm1 forms in the opcode table
+ are slower on the i486, and they're the versions with the implicitly
+ specified single-position displacement, which has another syntax if
+ you really want to use that form. If you really prefer to have the
+ one-byte-shorter Imm1 form despite these problems, re-enable this
+ code. */
+ if (num == 1)
+ return Imm1 | Imm8 | Imm8S | Imm16 | Imm32;
+#endif
+ return (fits_in_signed_byte (num)
+ ? (Imm8S | Imm8 | Imm16 | Imm32)
+ : fits_in_unsigned_byte (num)
+ ? (Imm8 | Imm16 | Imm32)
+ : (fits_in_signed_word (num) || fits_in_unsigned_word (num))
+ ? (Imm16 | Imm32)
+ : (Imm32));
+} /* smallest_imm_type() */
+
+/* Returns 0 if attempting to add a prefix where one from the same
+ class already exists, 1 if non rep/repne added, 2 if rep/repne
+ added. */
+static int
+add_prefix (prefix)
+ unsigned int prefix;
+{
+ int ret = 1;
+ int q;
+
+ switch (prefix)
+ {
+ default:
+ abort ();
+
+ case CS_PREFIX_OPCODE:
+ case DS_PREFIX_OPCODE:
+ case ES_PREFIX_OPCODE:
+ case FS_PREFIX_OPCODE:
+ case GS_PREFIX_OPCODE:
+ case SS_PREFIX_OPCODE:
+ q = SEG_PREFIX;
+ break;
+
+ case REPNE_PREFIX_OPCODE:
+ case REPE_PREFIX_OPCODE:
+ ret = 2;
+ /* fall thru */
+ case LOCK_PREFIX_OPCODE:
+ q = LOCKREP_PREFIX;
+ break;
+
+ case FWAIT_OPCODE:
+ q = WAIT_PREFIX;
+ break;
+
+ case ADDR_PREFIX_OPCODE:
+ q = ADDR_PREFIX;
+ break;
+
+ case DATA_PREFIX_OPCODE:
+ q = DATA_PREFIX;
+ break;
+ }
+
+ if (i.prefix[q])
+ {
+ as_bad (_("same type of prefix used twice"));
+ return 0;
+ }
+
+ i.prefixes += 1;
+ i.prefix[q] = prefix;
+ return ret;
+}
+
+static void
+set_16bit_code_flag (new_16bit_code_flag)
+ int new_16bit_code_flag;
+{
+ flag_16bit_code = new_16bit_code_flag;
+}
+
+static void
+set_intel_syntax (syntax_flag)
+ int syntax_flag;
+{
+ /* Find out if register prefixing is specified. */
+ int ask_naked_reg = 0;
+
+ SKIP_WHITESPACE ();
+ if (! is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ char *string = input_line_pointer;
+ int e = get_symbol_end ();
+
+ if (strcmp(string, "prefix") == 0)
+ ask_naked_reg = 1;
+ else if (strcmp(string, "noprefix") == 0)
+ ask_naked_reg = -1;
+ else
+ as_bad (_("Bad argument to syntax directive."));
+ *input_line_pointer = e;
+ }
+ demand_empty_rest_of_line ();
+
+ intel_syntax = syntax_flag;
+
+ if (ask_naked_reg == 0)
+ {
+#ifdef BFD_ASSEMBLER
+ allow_naked_reg = (intel_syntax
+ && (bfd_get_symbol_leading_char (stdoutput) != '\0'));
+#else
+ allow_naked_reg = 0; /* conservative default */
+#endif
+ }
+ else
+ allow_naked_reg = (ask_naked_reg < 0);
+}
+
+const pseudo_typeS md_pseudo_table[] =
+{
+#ifndef I386COFF
+ {"bss", s_bss, 0},
+#endif
+#if !defined(OBJ_AOUT) && !defined(USE_ALIGN_PTWO)
+ {"align", s_align_bytes, 0},
+#else
+ {"align", s_align_ptwo, 0},
+#endif
+ {"ffloat", float_cons, 'f'},
+ {"dfloat", float_cons, 'd'},
+ {"tfloat", float_cons, 'x'},
+ {"value", cons, 2},
+ {"noopt", s_ignore, 0},
+ {"optim", s_ignore, 0},
+ {"code16", set_16bit_code_flag, 1},
+ {"code32", set_16bit_code_flag, 0},
+ {"intel_syntax", set_intel_syntax, 1},
+ {"att_syntax", set_intel_syntax, 0},
+ {0, 0, 0}
+};
+
+/* for interface with expression () */
+extern char *input_line_pointer;
+
+/* hash table for instruction mnemonic lookup */
+static struct hash_control *op_hash;
+/* hash table for register lookup */
+static struct hash_control *reg_hash;
+
+
+void
+md_begin ()
+{
+ const char *hash_err;
+
+ /* initialize op_hash hash table */
+ op_hash = hash_new ();
+
+ {
+ register const template *optab;
+ register templates *core_optab;
+
+ optab = i386_optab; /* setup for loop */
+ core_optab = (templates *) xmalloc (sizeof (templates));
+ core_optab->start = optab;
+
+ while (1)
+ {
+ ++optab;
+ if (optab->name == NULL
+ || strcmp (optab->name, (optab - 1)->name) != 0)
+ {
+ /* different name --> ship out current template list;
+ add to hash table; & begin anew */
+ core_optab->end = optab;
+ hash_err = hash_insert (op_hash,
+ (optab - 1)->name,
+ (PTR) core_optab);
+ if (hash_err)
+ {
+ hash_error:
+ as_fatal (_("Internal Error: Can't hash %s: %s"),
+ (optab - 1)->name,
+ hash_err);
+ }
+ if (optab->name == NULL)
+ break;
+ core_optab = (templates *) xmalloc (sizeof (templates));
+ core_optab->start = optab;
+ }
+ }
+ }
+
+ /* initialize reg_hash hash table */
+ reg_hash = hash_new ();
+ {
+ register const reg_entry *regtab;
+
+ for (regtab = i386_regtab;
+ regtab < i386_regtab + sizeof (i386_regtab) / sizeof (i386_regtab[0]);
+ regtab++)
+ {
+ hash_err = hash_insert (reg_hash, regtab->reg_name, (PTR) regtab);
+ if (hash_err)
+ goto hash_error;
+ }
+ }
+
+ /* fill in lexical tables: mnemonic_chars, operand_chars. */
+ {
+ register int c;
+ register char *p;
+
+ for (c = 0; c < 256; c++)
+ {
+ if (isdigit (c))
+ {
+ digit_chars[c] = c;
+ mnemonic_chars[c] = c;
+ register_chars[c] = c;
+ operand_chars[c] = c;
+ }
+ else if (islower (c))
+ {
+ mnemonic_chars[c] = c;
+ register_chars[c] = c;
+ operand_chars[c] = c;
+ }
+ else if (isupper (c))
+ {
+ mnemonic_chars[c] = tolower (c);
+ register_chars[c] = mnemonic_chars[c];
+ operand_chars[c] = c;
+ }
+
+ if (isalpha (c) || isdigit (c))
+ identifier_chars[c] = c;
+ else if (c >= 128)
+ {
+ identifier_chars[c] = c;
+ operand_chars[c] = c;
+ }
+ }
+
+#ifdef LEX_AT
+ identifier_chars['@'] = '@';
+#endif
+ register_chars[')'] = ')';
+ register_chars['('] = '(';
+ digit_chars['-'] = '-';
+ identifier_chars['_'] = '_';
+ identifier_chars['.'] = '.';
+
+ for (p = operand_special_chars; *p != '\0'; p++)
+ operand_chars[(unsigned char) *p] = *p;
+ }
+
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+ if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
+ {
+ record_alignment (text_section, 2);
+ record_alignment (data_section, 2);
+ record_alignment (bss_section, 2);
+ }
+#endif
+}
+
+void
+i386_print_statistics (file)
+ FILE *file;
+{
+ hash_print_statistics (file, "i386 opcode", op_hash);
+ hash_print_statistics (file, "i386 register", reg_hash);
+}
+
+
+#ifdef DEBUG386
+
+/* debugging routines for md_assemble */
+static void pi PARAMS ((char *, i386_insn *));
+static void pte PARAMS ((template *));
+static void pt PARAMS ((unsigned int));
+static void pe PARAMS ((expressionS *));
+static void ps PARAMS ((symbolS *));
+
+static void
+pi (line, x)
+ char *line;
+ i386_insn *x;
+{
+ register template *p;
+ int i;
+
+ fprintf (stdout, "%s: template ", line);
+ pte (&x->tm);
+ fprintf (stdout, " modrm: mode %x reg %x reg/mem %x",
+ x->rm.mode, x->rm.reg, x->rm.regmem);
+ fprintf (stdout, " base %x index %x scale %x\n",
+ x->bi.base, x->bi.index, x->bi.scale);
+ for (i = 0; i < x->operands; i++)
+ {
+ fprintf (stdout, " #%d: ", i + 1);
+ pt (x->types[i]);
+ fprintf (stdout, "\n");
+ if (x->types[i]
+ & (Reg | SReg2 | SReg3 | Control | Debug | Test | RegMMX))
+ fprintf (stdout, "%s\n", x->regs[i]->reg_name);
+ if (x->types[i] & Imm)
+ pe (x->imms[i]);
+ if (x->types[i] & Disp)
+ pe (x->disps[i]);
+ }
+}
+
+static void
+pte (t)
+ template *t;
+{
+ int i;
+ fprintf (stdout, " %d operands ", t->operands);
+ fprintf (stdout, "opcode %x ",
+ t->base_opcode);
+ if (t->extension_opcode != None)
+ fprintf (stdout, "ext %x ", t->extension_opcode);
+ if (t->opcode_modifier & D)
+ fprintf (stdout, "D");
+ if (t->opcode_modifier & W)
+ fprintf (stdout, "W");
+ fprintf (stdout, "\n");
+ for (i = 0; i < t->operands; i++)
+ {
+ fprintf (stdout, " #%d type ", i + 1);
+ pt (t->operand_types[i]);
+ fprintf (stdout, "\n");
+ }
+}
+
+static void
+pe (e)
+ expressionS *e;
+{
+ fprintf (stdout, " operation %d\n", e->X_op);
+ fprintf (stdout, " add_number %d (%x)\n",
+ e->X_add_number, e->X_add_number);
+ if (e->X_add_symbol)
+ {
+ fprintf (stdout, " add_symbol ");
+ ps (e->X_add_symbol);
+ fprintf (stdout, "\n");
+ }
+ if (e->X_op_symbol)
+ {
+ fprintf (stdout, " op_symbol ");
+ ps (e->X_op_symbol);
+ fprintf (stdout, "\n");
+ }
+}
+
+static void
+ps (s)
+ symbolS *s;
+{
+ fprintf (stdout, "%s type %s%s",
+ S_GET_NAME (s),
+ S_IS_EXTERNAL (s) ? "EXTERNAL " : "",
+ segment_name (S_GET_SEGMENT (s)));
+}
+
+struct type_name
+ {
+ unsigned int mask;
+ char *tname;
+ }
+
+type_names[] =
+{
+ { Reg8, "r8" },
+ { Reg16, "r16" },
+ { Reg32, "r32" },
+ { Imm8, "i8" },
+ { Imm8S, "i8s" },
+ { Imm16, "i16" },
+ { Imm32, "i32" },
+ { Imm1, "i1" },
+ { BaseIndex, "BaseIndex" },
+ { Disp8, "d8" },
+ { Disp16, "d16" },
+ { Disp32, "d32" },
+ { InOutPortReg, "InOutPortReg" },
+ { ShiftCount, "ShiftCount" },
+ { Control, "control reg" },
+ { Test, "test reg" },
+ { Debug, "debug reg" },
+ { FloatReg, "FReg" },
+ { FloatAcc, "FAcc" },
+ { SReg2, "SReg2" },
+ { SReg3, "SReg3" },
+ { Acc, "Acc" },
+ { JumpAbsolute, "Jump Absolute" },
+ { RegMMX, "rMMX" },
+ { EsSeg, "es" },
+ { 0, "" }
+};
+
+static void
+pt (t)
+ unsigned int t;
+{
+ register struct type_name *ty;
+
+ if (t == Unknown)
+ {
+ fprintf (stdout, _("Unknown"));
+ }
+ else
+ {
+ for (ty = type_names; ty->mask; ty++)
+ if (t & ty->mask)
+ fprintf (stdout, "%s, ", ty->tname);
+ }
+ fflush (stdout);
+}
+
+#endif /* DEBUG386 */
+
+int
+tc_i386_force_relocation (fixp)
+ struct fix *fixp;
+{
+#ifdef BFD_ASSEMBLER
+ if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ return 1;
+ return 0;
+#else
+ /* For COFF */
+ return fixp->fx_r_type==7;
+#endif
+}
+
+#ifdef BFD_ASSEMBLER
+static bfd_reloc_code_real_type reloc
+ PARAMS ((int, int, bfd_reloc_code_real_type));
+
+static bfd_reloc_code_real_type
+reloc (size, pcrel, other)
+ int size;
+ int pcrel;
+ bfd_reloc_code_real_type other;
+{
+ if (other != NO_RELOC) return other;
+
+ if (pcrel)
+ {
+ switch (size)
+ {
+ case 1: return BFD_RELOC_8_PCREL;
+ case 2: return BFD_RELOC_16_PCREL;
+ case 4: return BFD_RELOC_32_PCREL;
+ }
+ as_bad (_("Can not do %d byte pc-relative relocation"), size);
+ }
+ else
+ {
+ switch (size)
+ {
+ case 1: return BFD_RELOC_8;
+ case 2: return BFD_RELOC_16;
+ case 4: return BFD_RELOC_32;
+ }
+ as_bad (_("Can not do %d byte relocation"), size);
+ }
+
+ return BFD_RELOC_NONE;
+}
+
+/*
+ * Here we decide which fixups can be adjusted to make them relative to
+ * the beginning of the section instead of the symbol. Basically we need
+ * to make sure that the dynamic relocations are done correctly, so in
+ * some cases we force the original symbol to be used.
+ */
+int
+tc_i386_fix_adjustable(fixP)
+ fixS * fixP;
+{
+#ifdef OBJ_ELF
+ /* Prevent all adjustments to global symbols. */
+ if (S_IS_EXTERN (fixP->fx_addsy))
+ return 0;
+ if (S_IS_WEAK (fixP->fx_addsy))
+ return 0;
+#endif
+ /* adjust_reloc_syms doesn't know about the GOT */
+ if (fixP->fx_r_type == BFD_RELOC_386_GOTOFF
+ || fixP->fx_r_type == BFD_RELOC_386_PLT32
+ || fixP->fx_r_type == BFD_RELOC_386_GOT32
+ || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ return 0;
+ return 1;
+}
+#else
+#define reloc(SIZE,PCREL,OTHER) 0
+#define BFD_RELOC_16 0
+#define BFD_RELOC_32 0
+#define BFD_RELOC_16_PCREL 0
+#define BFD_RELOC_32_PCREL 0
+#define BFD_RELOC_386_PLT32 0
+#define BFD_RELOC_386_GOT32 0
+#define BFD_RELOC_386_GOTOFF 0
+#endif
+
+int
+intel_float_operand (mnemonic)
+ char *mnemonic;
+{
+ if (mnemonic[0] == 'f' && mnemonic[1] =='i')
+ return 0;
+
+ if (mnemonic[0] == 'f')
+ return 1;
+
+ return 0;
+}
+
+/* This is the guts of the machine-dependent assembler. LINE points to a
+ machine dependent instruction. This function is supposed to emit
+ the frags/bytes it assembles to. */
+
+void
+md_assemble (line)
+ char *line;
+{
+ /* Points to template once we've found it. */
+ const template *t;
+
+ /* Count the size of the instruction generated. */
+ int insn_size = 0;
+
+ int j;
+
+ char mnemonic[MAX_MNEM_SIZE];
+
+ /* Initialize globals. */
+ memset (&i, '\0', sizeof (i));
+ for (j = 0; j < MAX_OPERANDS; j++)
+ i.disp_reloc[j] = NO_RELOC;
+ memset (disp_expressions, '\0', sizeof (disp_expressions));
+ memset (im_expressions, '\0', sizeof (im_expressions));
+ save_stack_p = save_stack; /* reset stack pointer */
+
+ /* First parse an instruction mnemonic & call i386_operand for the operands.
+ We assume that the scrubber has arranged it so that line[0] is the valid
+ start of a (possibly prefixed) mnemonic. */
+ {
+ char *l = line;
+ char *token_start = l;
+ char *mnem_p;
+
+ /* Non-zero if we found a prefix only acceptable with string insns. */
+ const char *expecting_string_instruction = NULL;
+
+ while (1)
+ {
+ mnem_p = mnemonic;
+ while ((*mnem_p = mnemonic_chars[(unsigned char) *l]) != 0)
+ {
+ mnem_p++;
+ if (mnem_p >= mnemonic + sizeof (mnemonic))
+ {
+ as_bad (_("no such 386 instruction: `%s'"), token_start);
+ return;
+ }
+ l++;
+ }
+ if (!is_space_char (*l)
+ && *l != END_OF_INSN
+ && *l != PREFIX_SEPARATOR)
+ {
+ as_bad (_("invalid character %s in mnemonic"),
+ output_invalid (*l));
+ return;
+ }
+ if (token_start == l)
+ {
+ if (*l == PREFIX_SEPARATOR)
+ as_bad (_("expecting prefix; got nothing"));
+ else
+ as_bad (_("expecting mnemonic; got nothing"));
+ return;
+ }
+
+ /* Look up instruction (or prefix) via hash table. */
+ current_templates = hash_find (op_hash, mnemonic);
+
+ if (*l != END_OF_INSN
+ && (! is_space_char (*l) || l[1] != END_OF_INSN)
+ && current_templates
+ && (current_templates->start->opcode_modifier & IsPrefix))
+ {
+ /* If we are in 16-bit mode, do not allow addr16 or data16.
+ Similarly, in 32-bit mode, do not allow addr32 or data32. */
+ if ((current_templates->start->opcode_modifier & (Size16 | Size32))
+ && (((current_templates->start->opcode_modifier & Size32) != 0)
+ ^ flag_16bit_code))
+ {
+ as_bad (_("redundant %s prefix"),
+ current_templates->start->name);
+ return;
+ }
+ /* Add prefix, checking for repeated prefixes. */
+ switch (add_prefix (current_templates->start->base_opcode))
+ {
+ case 0:
+ return;
+ case 2:
+ expecting_string_instruction =
+ current_templates->start->name;
+ break;
+ }
+ /* Skip past PREFIX_SEPARATOR and reset token_start. */
+ token_start = ++l;
+ }
+ else
+ break;
+ }
+
+ if (!current_templates)
+ {
+ /* See if we can get a match by trimming off a suffix. */
+ switch (mnem_p[-1])
+ {
+ case DWORD_MNEM_SUFFIX:
+ case WORD_MNEM_SUFFIX:
+ case BYTE_MNEM_SUFFIX:
+ case SHORT_MNEM_SUFFIX:
+#if LONG_MNEM_SUFFIX != DWORD_MNEM_SUFFIX
+ case LONG_MNEM_SUFFIX:
+#endif
+ i.suffix = mnem_p[-1];
+ mnem_p[-1] = '\0';
+ current_templates = hash_find (op_hash, mnemonic);
+ break;
+
+ /* Intel Syntax */
+ case INTEL_DWORD_MNEM_SUFFIX:
+ if (intel_syntax)
+ {
+ i.suffix = mnem_p[-1];
+ mnem_p[-1] = '\0';
+ current_templates = hash_find (op_hash, mnemonic);
+ break;
+ }
+ }
+ if (!current_templates)
+ {
+ as_bad (_("no such 386 instruction: `%s'"), token_start);
+ return;
+ }
+ }
+
+ /* check for rep/repne without a string instruction */
+ if (expecting_string_instruction
+ && !(current_templates->start->opcode_modifier & IsString))
+ {
+ as_bad (_("expecting string instruction after `%s'"),
+ expecting_string_instruction);
+ return;
+ }
+
+ /* There may be operands to parse. */
+ if (*l != END_OF_INSN)
+ {
+ /* parse operands */
+
+ /* 1 if operand is pending after ','. */
+ unsigned int expecting_operand = 0;
+
+ /* Non-zero if operand parens not balanced. */
+ unsigned int paren_not_balanced;
+
+ do
+ {
+ /* skip optional white space before operand */
+ if (is_space_char (*l))
+ ++l;
+ if (!is_operand_char (*l) && *l != END_OF_INSN)
+ {
+ as_bad (_("invalid character %s before operand %d"),
+ output_invalid (*l),
+ i.operands + 1);
+ return;
+ }
+ token_start = l; /* after white space */
+ paren_not_balanced = 0;
+ while (paren_not_balanced || *l != ',')
+ {
+ if (*l == END_OF_INSN)
+ {
+ if (paren_not_balanced)
+ {
+ if (!intel_syntax)
+ as_bad (_("unbalanced parenthesis in operand %d."),
+ i.operands + 1);
+ else
+ as_bad (_("unbalanced brackets in operand %d."),
+ i.operands + 1);
+ return;
+ }
+ else
+ break; /* we are done */
+ }
+ else if (!is_operand_char (*l) && !is_space_char (*l))
+ {
+ as_bad (_("invalid character %s in operand %d"),
+ output_invalid (*l),
+ i.operands + 1);
+ return;
+ }
+ if (!intel_syntax)
+ {
+ if (*l == '(')
+ ++paren_not_balanced;
+ if (*l == ')')
+ --paren_not_balanced;
+ }
+ else
+ {
+ if (*l == '[')
+ ++paren_not_balanced;
+ if (*l == ']')
+ --paren_not_balanced;
+ }
+ l++;
+ }
+ if (l != token_start)
+ { /* yes, we've read in another operand */
+ unsigned int operand_ok;
+ this_operand = i.operands++;
+ if (i.operands > MAX_OPERANDS)
+ {
+ as_bad (_("spurious operands; (%d operands/instruction max)"),
+ MAX_OPERANDS);
+ return;
+ }
+ /* now parse operand adding info to 'i' as we go along */
+ END_STRING_AND_SAVE (l);
+
+ if (intel_syntax)
+ operand_ok = i386_intel_operand (token_start, intel_float_operand (mnemonic));
+ else
+ operand_ok = i386_operand (token_start);
+
+ RESTORE_END_STRING (l); /* restore old contents */
+ if (!operand_ok)
+ return;
+ }
+ else
+ {
+ if (expecting_operand)
+ {
+ expecting_operand_after_comma:
+ as_bad (_("expecting operand after ','; got nothing"));
+ return;
+ }
+ if (*l == ',')
+ {
+ as_bad (_("expecting operand before ','; got nothing"));
+ return;
+ }
+ }
+
+ /* now *l must be either ',' or END_OF_INSN */
+ if (*l == ',')
+ {
+ if (*++l == END_OF_INSN)
+ { /* just skip it, if it's \n complain */
+ goto expecting_operand_after_comma;
+ }
+ expecting_operand = 1;
+ }
+ }
+ while (*l != END_OF_INSN); /* until we get end of insn */
+ }
+ }
+
+ /* Now we've parsed the mnemonic into a set of templates, and have the
+ operands at hand.
+
+ Next, we find a template that matches the given insn,
+ making sure the overlap of the given operands types is consistent
+ with the template operand types. */
+
+#define MATCH(overlap, given, template) \
+ ((overlap) \
+ && ((given) & BaseIndex) == ((overlap) & BaseIndex) \
+ && ((given) & JumpAbsolute) == ((template) & JumpAbsolute))
+
+ /* If given types r0 and r1 are registers they must be of the same type
+ unless the expected operand type register overlap is null.
+ Note that Acc in a template matches every size of reg. */
+#define CONSISTENT_REGISTER_MATCH(m0, g0, t0, m1, g1, t1) \
+ ( ((g0) & Reg) == 0 || ((g1) & Reg) == 0 || \
+ ((g0) & Reg) == ((g1) & Reg) || \
+ ((((m0) & Acc) ? Reg : (t0)) & (((m1) & Acc) ? Reg : (t1)) & Reg) == 0 )
+
+ {
+ register unsigned int overlap0, overlap1;
+ expressionS *exp;
+ unsigned int overlap2;
+ unsigned int found_reverse_match;
+ int suffix_check;
+
+ /* All intel opcodes have reversed operands except for BOUND and ENTER */
+ if (intel_syntax
+ && (strcmp (mnemonic, "enter") != 0)
+ && (strcmp (mnemonic, "bound") != 0)
+ && (strncmp (mnemonic, "fsub", 4) !=0)
+ && (strncmp (mnemonic, "fdiv", 4) !=0))
+ {
+ const reg_entry *temp_reg;
+ expressionS *temp_disp;
+ expressionS *temp_imm;
+ unsigned int temp_type;
+ int xchg1, xchg2;
+
+ if (i.operands == 2)
+ {
+ xchg1 = 0;
+ xchg2 = 1;
+ }
+ else if (i.operands == 3)
+ {
+ xchg1 = 0;
+ xchg2 = 2;
+ }
+
+ if (i.operands > 1)
+ {
+ temp_type = i.types[xchg2];
+ if (temp_type & (Reg | FloatReg))
+ temp_reg = i.regs[xchg2];
+ else if (temp_type & Imm)
+ temp_imm = i.imms[xchg2];
+ else if (temp_type & Disp)
+ temp_disp = i.disps[xchg2];
+
+ i.types[xchg2] = i.types[xchg1];
+
+ if (i.types[xchg1] & (Reg | FloatReg))
+ {
+ i.regs[xchg2] = i.regs[xchg1];
+ i.regs[xchg1] = NULL;
+ }
+ else if (i.types[xchg2] & Imm)
+ {
+ i.imms[xchg2] = i.imms[xchg1];
+ i.imms[xchg1] = NULL;
+ }
+ else if (i.types[xchg2] & Disp)
+ {
+ i.disps[xchg2] = i.disps[xchg1];
+ i.disps[xchg1] = NULL;
+ }
+
+ if (temp_type & (Reg | FloatReg))
+ {
+ i.regs[xchg1] = temp_reg;
+ if (! (i.types[xchg1] & (Reg | FloatReg)))
+ i.regs[xchg2] = NULL;
+ }
+ else if (temp_type & Imm)
+ {
+ i.imms[xchg1] = temp_imm;
+ if (! (i.types[xchg1] & Imm))
+ i.imms[xchg2] = NULL;
+ }
+ else if (temp_type & Disp)
+ {
+ i.disps[xchg1] = temp_disp;
+ if (! (i.types[xchg1] & Disp))
+ i.disps[xchg2] = NULL;
+ }
+
+ i.types[xchg1] = temp_type;
+ }
+ if (!strcmp(mnemonic,"jmp")
+ || !strcmp (mnemonic, "call"))
+ if ((i.types[0] & Reg) || i.types[0] & BaseIndex)
+ i.types[0] |= JumpAbsolute;
+
+ }
+ overlap0 = 0;
+ overlap1 = 0;
+ overlap2 = 0;
+ found_reverse_match = 0;
+ suffix_check = (i.suffix == BYTE_MNEM_SUFFIX
+ ? No_bSuf
+ : (i.suffix == WORD_MNEM_SUFFIX
+ ? No_wSuf
+ : (i.suffix == SHORT_MNEM_SUFFIX
+ ? No_sSuf
+ : (i.suffix == LONG_MNEM_SUFFIX
+ ? No_lSuf
+ : (i.suffix == INTEL_DWORD_MNEM_SUFFIX
+ ? No_dSuf
+ : (i.suffix == LONG_DOUBLE_MNEM_SUFFIX ? No_xSuf : 0))))));
+
+ for (t = current_templates->start;
+ t < current_templates->end;
+ t++)
+ {
+ /* Must have right number of operands. */
+ if (i.operands != t->operands)
+ continue;
+
+ /* For some opcodes, don't check the suffix */
+ if (intel_syntax)
+ {
+ if (strcmp (t->name, "fnstcw")
+ && strcmp (t->name, "fldcw")
+ && (t->opcode_modifier & suffix_check))
+ continue;
+ }
+ /* Must not have disallowed suffix. */
+ else if ((t->opcode_modifier & suffix_check))
+ continue;
+
+ else if (!t->operands)
+ break; /* 0 operands always matches */
+
+ overlap0 = i.types[0] & t->operand_types[0];
+ switch (t->operands)
+ {
+ case 1:
+ if (!MATCH (overlap0, i.types[0], t->operand_types[0]))
+ continue;
+ break;
+ case 2:
+ case 3:
+ overlap1 = i.types[1] & t->operand_types[1];
+ if (!MATCH (overlap0, i.types[0], t->operand_types[0])
+ || !MATCH (overlap1, i.types[1], t->operand_types[1])
+ || !CONSISTENT_REGISTER_MATCH (overlap0, i.types[0],
+ t->operand_types[0],
+ overlap1, i.types[1],
+ t->operand_types[1]))
+ {
+
+ /* check if other direction is valid ... */
+ if ((t->opcode_modifier & (D|FloatD)) == 0)
+ continue;
+
+ /* try reversing direction of operands */
+ overlap0 = i.types[0] & t->operand_types[1];
+ overlap1 = i.types[1] & t->operand_types[0];
+ if (!MATCH (overlap0, i.types[0], t->operand_types[1])
+ || !MATCH (overlap1, i.types[1], t->operand_types[0])
+ || !CONSISTENT_REGISTER_MATCH (overlap0, i.types[0],
+ t->operand_types[1],
+ overlap1, i.types[1],
+ t->operand_types[0]))
+ {
+ /* does not match either direction */
+ continue;
+ }
+ /* found_reverse_match holds which of D or FloatDR
+ we've found. */
+ found_reverse_match = t->opcode_modifier & (D|FloatDR);
+ break;
+ }
+ /* found a forward 2 operand match here */
+ if (t->operands == 3)
+ {
+ /* Here we make use of the fact that there are no
+ reverse match 3 operand instructions, and all 3
+ operand instructions only need to be checked for
+ register consistency between operands 2 and 3. */
+ overlap2 = i.types[2] & t->operand_types[2];
+ if (!MATCH (overlap2, i.types[2], t->operand_types[2])
+ || !CONSISTENT_REGISTER_MATCH (overlap1, i.types[1],
+ t->operand_types[1],
+ overlap2, i.types[2],
+ t->operand_types[2]))
+
+ continue;
+ }
+ /* found either forward/reverse 2 or 3 operand match here:
+ slip through to break */
+ }
+ break; /* we've found a match; break out of loop */
+ } /* for (t = ... */
+ if (t == current_templates->end)
+ { /* we found no match */
+ as_bad (_("suffix or operands invalid for `%s'"),
+ current_templates->start->name);
+ return;
+ }
+
+ if ((t->opcode_modifier & (IsPrefix|IgnoreSize)) == (IsPrefix|IgnoreSize))
+ {
+ /* Warn them that a data or address size prefix doesn't affect
+ assembly of the next line of code. */
+ as_warn (_("stand-alone `%s' prefix"), t->name);
+ }
+
+ /* Copy the template we found. */
+ i.tm = *t;
+ if (found_reverse_match)
+ {
+ i.tm.operand_types[0] = t->operand_types[1];
+ i.tm.operand_types[1] = t->operand_types[0];
+ }
+
+
+ if (i.tm.opcode_modifier & FWait)
+ if (! add_prefix (FWAIT_OPCODE))
+ return;
+
+ /* Check string instruction segment overrides */
+ if ((i.tm.opcode_modifier & IsString) != 0 && i.mem_operands != 0)
+ {
+ int mem_op = (i.types[0] & AnyMem) ? 0 : 1;
+ if ((i.tm.operand_types[mem_op] & EsSeg) != 0)
+ {
+ if (i.seg[0] != NULL && i.seg[0] != &es)
+ {
+ as_bad (_("`%s' operand %d must use `%%es' segment"),
+ i.tm.name,
+ mem_op + 1);
+ return;
+ }
+ /* There's only ever one segment override allowed per instruction.
+ This instruction possibly has a legal segment override on the
+ second operand, so copy the segment to where non-string
+ instructions store it, allowing common code. */
+ i.seg[0] = i.seg[1];
+ }
+ else if ((i.tm.operand_types[mem_op + 1] & EsSeg) != 0)
+ {
+ if (i.seg[1] != NULL && i.seg[1] != &es)
+ {
+ as_bad (_("`%s' operand %d must use `%%es' segment"),
+ i.tm.name,
+ mem_op + 2);
+ return;
+ }
+ }
+ }
+
+ /* If matched instruction specifies an explicit instruction mnemonic
+ suffix, use it. */
+ if (i.tm.opcode_modifier & (Size16 | Size32))
+ {
+ if (i.tm.opcode_modifier & Size16)
+ i.suffix = WORD_MNEM_SUFFIX;
+ else
+ i.suffix = DWORD_MNEM_SUFFIX;
+ }
+ else if (i.reg_operands)
+ {
+ /* If there's no instruction mnemonic suffix we try to invent one
+ based on register operands. */
+ if (!i.suffix)
+ {
+ /* We take i.suffix from the last register operand specified,
+ Destination register type is more significant than source
+ register type. */
+ int op;
+ for (op = i.operands; --op >= 0; )
+ if (i.types[op] & Reg)
+ {
+ i.suffix = ((i.types[op] & Reg8) ? BYTE_MNEM_SUFFIX :
+ (i.types[op] & Reg16) ? WORD_MNEM_SUFFIX :
+ DWORD_MNEM_SUFFIX);
+ break;
+ }
+ }
+ else if (i.suffix == BYTE_MNEM_SUFFIX)
+ {
+ int op;
+ for (op = i.operands; --op >= 0; )
+ {
+ /* If this is an eight bit register, it's OK. If it's
+ the 16 or 32 bit version of an eight bit register,
+ we will just use the low portion, and that's OK too. */
+ if (i.types[op] & Reg8)
+ continue;
+
+ /* movzx and movsx should not generate this warning. */
+ if (intel_syntax
+ && (i.tm.base_opcode == 0xfb7
+ || i.tm.base_opcode == 0xfb6
+ || i.tm.base_opcode == 0xfbe
+ || i.tm.base_opcode == 0xfbf))
+ continue;
+
+ if ((i.types[op] & WordReg) && i.regs[op]->reg_num < 4
+#if 0
+ /* Check that the template allows eight bit regs
+ This kills insns such as `orb $1,%edx', which
+ maybe should be allowed. */
+ && (i.tm.operand_types[op] & (Reg8|InOutPortReg))
+#endif
+ )
+ {
+#if REGISTER_WARNINGS
+ if ((i.tm.operand_types[op] & InOutPortReg) == 0)
+ as_warn (_("using `%%%s' instead of `%%%s' due to `%c' suffix"),
+ (i.regs[op] - (i.types[op] & Reg16 ? 8 : 16))->reg_name,
+ i.regs[op]->reg_name,
+ i.suffix);
+#endif
+ continue;
+ }
+ /* Any other register is bad */
+ if (i.types[op] & (Reg | RegMMX | Control | Debug | Test
+ | FloatReg | FloatAcc | SReg2 | SReg3))
+ {
+ as_bad (_("`%%%s' not allowed with `%s%c'"),
+ i.regs[op]->reg_name,
+ i.tm.name,
+ i.suffix);
+ return;
+ }
+ }
+ }
+ else if (i.suffix == DWORD_MNEM_SUFFIX)
+ {
+ int op;
+ for (op = i.operands; --op >= 0; )
+ /* Reject eight bit registers, except where the template
+ requires them. (eg. movzb) */
+ if ((i.types[op] & Reg8) != 0
+ && (i.tm.operand_types[op] & (Reg16|Reg32|Acc)) != 0)
+ {
+ as_bad (_("`%%%s' not allowed with `%s%c'"),
+ i.regs[op]->reg_name,
+ i.tm.name,
+ i.suffix);
+ return;
+ }
+#if REGISTER_WARNINGS
+ /* Warn if the e prefix on a general reg is missing. */
+ else if ((i.types[op] & Reg16) != 0
+ && (i.tm.operand_types[op] & (Reg32|Acc)) != 0)
+ {
+ as_warn (_("using `%%%s' instead of `%%%s' due to `%c' suffix"),
+ (i.regs[op] + 8)->reg_name,
+ i.regs[op]->reg_name,
+ i.suffix);
+ }
+#endif
+ }
+ else if (i.suffix == WORD_MNEM_SUFFIX)
+ {
+ int op;
+ for (op = i.operands; --op >= 0; )
+ /* Reject eight bit registers, except where the template
+ requires them. (eg. movzb) */
+ if ((i.types[op] & Reg8) != 0
+ && (i.tm.operand_types[op] & (Reg16|Reg32|Acc)) != 0)
+ {
+ as_bad (_("`%%%s' not allowed with `%s%c'"),
+ i.regs[op]->reg_name,
+ i.tm.name,
+ i.suffix);
+ return;
+ }
+#if REGISTER_WARNINGS
+ /* Warn if the e prefix on a general reg is present. */
+ else if ((i.types[op] & Reg32) != 0
+ && (i.tm.operand_types[op] & (Reg16|Acc)) != 0)
+ {
+ as_warn (_("using `%%%s' instead of `%%%s' due to `%c' suffix"),
+ (i.regs[op] - 8)->reg_name,
+ i.regs[op]->reg_name,
+ i.suffix);
+ }
+#endif
+ }
+ else
+ abort();
+ }
+
+ /* Make still unresolved immediate matches conform to size of immediate
+ given in i.suffix. Note: overlap2 cannot be an immediate! */
+ if ((overlap0 & (Imm8 | Imm8S | Imm16 | Imm32))
+ && overlap0 != Imm8 && overlap0 != Imm8S
+ && overlap0 != Imm16 && overlap0 != Imm32)
+ {
+ if (i.suffix)
+ {
+ overlap0 &= (i.suffix == BYTE_MNEM_SUFFIX ? (Imm8 | Imm8S) :
+ (i.suffix == WORD_MNEM_SUFFIX ? Imm16 : Imm32));
+ }
+ else if (overlap0 == (Imm16 | Imm32))
+ {
+ overlap0 =
+ (flag_16bit_code ^ (i.prefix[DATA_PREFIX] != 0)) ? Imm16 : Imm32;
+ }
+ else
+ {
+ as_bad (_("no instruction mnemonic suffix given; can't determine immediate size"));
+ return;
+ }
+ }
+ if ((overlap1 & (Imm8 | Imm8S | Imm16 | Imm32))
+ && overlap1 != Imm8 && overlap1 != Imm8S
+ && overlap1 != Imm16 && overlap1 != Imm32)
+ {
+ if (i.suffix)
+ {
+ overlap1 &= (i.suffix == BYTE_MNEM_SUFFIX ? (Imm8 | Imm8S) :
+ (i.suffix == WORD_MNEM_SUFFIX ? Imm16 : Imm32));
+ }
+ else if (overlap1 == (Imm16 | Imm32))
+ {
+ overlap1 =
+ (flag_16bit_code ^ (i.prefix[DATA_PREFIX] != 0)) ? Imm16 : Imm32;
+ }
+ else
+ {
+ as_bad (_("no instruction mnemonic suffix given; can't determine immediate size"));
+ return;
+ }
+ }
+ assert ((overlap2 & Imm) == 0);
+
+ i.types[0] = overlap0;
+ if (overlap0 & ImplicitRegister)
+ i.reg_operands--;
+ if (overlap0 & Imm1)
+ i.imm_operands = 0; /* kludge for shift insns */
+
+ i.types[1] = overlap1;
+ if (overlap1 & ImplicitRegister)
+ i.reg_operands--;
+
+ i.types[2] = overlap2;
+ if (overlap2 & ImplicitRegister)
+ i.reg_operands--;
+
+ /* Finalize opcode. First, we change the opcode based on the operand
+ size given by i.suffix: We need not change things for byte insns. */
+
+ if (!i.suffix && (i.tm.opcode_modifier & W))
+ {
+ as_bad (_("no instruction mnemonic suffix given and no register operands; can't size instruction"));
+ return;
+ }
+
+ /* For movzx and movsx, need to check the register type */
+ if (intel_syntax
+ && (i.tm.base_opcode == 0xfb6 || i.tm.base_opcode == 0xfbe))
+ if (i.suffix && i.suffix == BYTE_MNEM_SUFFIX)
+ {
+ unsigned int prefix = DATA_PREFIX_OPCODE;
+
+ if ((i.regs[1]->reg_type & Reg16) != 0)
+ if (!add_prefix (prefix))
+ return;
+ }
+
+ if (i.suffix && i.suffix != BYTE_MNEM_SUFFIX)
+ {
+ /* It's not a byte, select word/dword operation. */
+ if (i.tm.opcode_modifier & W)
+ {
+ if (i.tm.opcode_modifier & ShortForm)
+ i.tm.base_opcode |= 8;
+ else
+ i.tm.base_opcode |= 1;
+ }
+ /* Now select between word & dword operations via the operand
+ size prefix, except for instructions that will ignore this
+ prefix anyway. */
+ if (((intel_syntax && (i.suffix == INTEL_DWORD_MNEM_SUFFIX))
+ || i.suffix == DWORD_MNEM_SUFFIX
+ || i.suffix == LONG_MNEM_SUFFIX) == flag_16bit_code
+ && !(i.tm.opcode_modifier & IgnoreSize))
+ {
+ unsigned int prefix = DATA_PREFIX_OPCODE;
+ if (i.tm.opcode_modifier & JumpByte) /* jcxz, loop */
+ prefix = ADDR_PREFIX_OPCODE;
+
+ if (! add_prefix (prefix))
+ return;
+ }
+ /* Size floating point instruction. */
+ if (i.suffix == LONG_MNEM_SUFFIX
+ || (intel_syntax && i.suffix == INTEL_DWORD_MNEM_SUFFIX))
+ {
+ if (i.tm.opcode_modifier & FloatMF)
+ i.tm.base_opcode ^= 4;
+ }
+
+ if (intel_syntax && i.suffix == LONG_DOUBLE_MNEM_SUFFIX)
+ {
+ if (i.tm.opcode_modifier & FloatMF)
+ i.tm.base_opcode ^= 2;
+ }
+ }
+
+ if (i.tm.base_opcode == AMD_3DNOW_OPCODE)
+ {
+ /* These AMD specific instructions have an opcode suffix which
+ is coded in the same place as an 8-bit immediate field
+ would be. Here we fake an 8-bit immediate operand from the
+ opcode suffix stored in tm.extension_opcode. */
+
+ expressionS *exp;
+
+ assert(i.imm_operands == 0 && i.operands <= 2);
+
+ exp = &im_expressions[i.imm_operands++];
+ i.imms[i.operands] = exp;
+ i.types[i.operands++] = Imm8;
+ exp->X_op = O_constant;
+ exp->X_add_number = i.tm.extension_opcode;
+ i.tm.extension_opcode = None;
+ }
+
+ /* For insns with operands there are more diddles to do to the opcode. */
+ if (i.operands)
+ {
+ /* Default segment register this instruction will use
+ for memory accesses. 0 means unknown.
+ This is only for optimizing out unnecessary segment overrides. */
+ const seg_entry *default_seg = 0;
+
+ /* If we found a reverse match we must alter the opcode
+ direction bit. found_reverse_match holds bits to change
+ (different for int & float insns). */
+
+ i.tm.base_opcode ^= found_reverse_match;
+
+ /* The imul $imm, %reg instruction is converted into
+ imul $imm, %reg, %reg, and the clr %reg instruction
+ is converted into xor %reg, %reg. */
+ if (i.tm.opcode_modifier & regKludge)
+ {
+ unsigned int first_reg_op = (i.types[0] & Reg) ? 0 : 1;
+ /* Pretend we saw the extra register operand. */
+ i.regs[first_reg_op+1] = i.regs[first_reg_op];
+ i.reg_operands = 2;
+ }
+
+ if (i.tm.opcode_modifier & ShortForm)
+ {
+ /* The register or float register operand is in operand 0 or 1. */
+ unsigned int op = (i.types[0] & (Reg | FloatReg)) ? 0 : 1;
+ /* Register goes in low 3 bits of opcode. */
+ i.tm.base_opcode |= i.regs[op]->reg_num;
+ if ((i.tm.opcode_modifier & Ugh) != 0)
+ {
+ /* Warn about some common errors, but press on regardless.
+ The first case can be generated by gcc (<= 2.8.1). */
+ if (i.operands == 2)
+ {
+ /* reversed arguments on faddp, fsubp, etc. */
+ as_warn (_("translating to `%s %%%s,%%%s'"), i.tm.name,
+ i.regs[1]->reg_name,
+ i.regs[0]->reg_name);
+ }
+ else
+ {
+ /* extraneous `l' suffix on fp insn */
+ as_warn (_("translating to `%s %%%s'"), i.tm.name,
+ i.regs[0]->reg_name);
+ }
+ }
+ }
+ else if (i.tm.opcode_modifier & Modrm)
+ {
+ /* The opcode is completed (modulo i.tm.extension_opcode which
+ must be put into the modrm byte).
+ Now, we make the modrm & index base bytes based on all the
+ info we've collected. */
+
+ /* i.reg_operands MUST be the number of real register operands;
+ implicit registers do not count. */
+ if (i.reg_operands == 2)
+ {
+ unsigned int source, dest;
+ source = ((i.types[0]
+ & (Reg
+ | SReg2
+ | SReg3
+ | Control
+ | Debug
+ | Test
+ | RegMMX))
+ ? 0 : 1);
+ dest = source + 1;
+
+ /* Certain instructions expect the destination to be
+ in the i.rm.reg field. This is by far the
+ exceptional case. For these instructions, if the
+ source operand is a register, we must reverse the
+ i.rm.reg and i.rm.regmem fields. We accomplish
+ this by pretending that the two register operands
+ were given in the reverse order. */
+ if (i.tm.opcode_modifier & ReverseRegRegmem)
+ {
+ const reg_entry *tmp = i.regs[source];
+ i.regs[source] = i.regs[dest];
+ i.regs[dest] = tmp;
+ }
+
+ i.rm.mode = 3;
+ /* We must be careful to make sure that all
+ segment/control/test/debug/MMX registers go into
+ the i.rm.reg field (despite whether they are
+ source or destination operands). */
+ if (i.regs[dest]->reg_type
+ & (SReg2 | SReg3 | Control | Debug | Test | RegMMX))
+ {
+ i.rm.reg = i.regs[dest]->reg_num;
+ i.rm.regmem = i.regs[source]->reg_num;
+ }
+ else
+ {
+ i.rm.reg = i.regs[source]->reg_num;
+ i.rm.regmem = i.regs[dest]->reg_num;
+ }
+ }
+ else
+ { /* if it's not 2 reg operands... */
+ if (i.mem_operands)
+ {
+ unsigned int fake_zero_displacement = 0;
+ unsigned int op = ((i.types[0] & AnyMem)
+ ? 0
+ : (i.types[1] & AnyMem) ? 1 : 2);
+
+ default_seg = &ds;
+
+ if (! i.base_reg)
+ {
+ i.rm.mode = 0;
+ if (! i.disp_operands)
+ fake_zero_displacement = 1;
+ if (! i.index_reg)
+ {
+ /* Operand is just <disp> */
+ if (flag_16bit_code ^ (i.prefix[ADDR_PREFIX] != 0))
+ {
+ i.rm.regmem = NO_BASE_REGISTER_16;
+ i.types[op] &= ~Disp;
+ i.types[op] |= Disp16;
+ }
+ else
+ {
+ i.rm.regmem = NO_BASE_REGISTER;
+ i.types[op] &= ~Disp;
+ i.types[op] |= Disp32;
+ }
+ }
+ else /* ! i.base_reg && i.index_reg */
+ {
+ i.sib.index = i.index_reg->reg_num;
+ i.sib.base = NO_BASE_REGISTER;
+ i.sib.scale = i.log2_scale_factor;
+ i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
+ i.types[op] &= ~Disp;
+ i.types[op] |= Disp32; /* Must be 32 bit */
+ }
+ }
+ else if (i.base_reg->reg_type & Reg16)
+ {
+ switch (i.base_reg->reg_num)
+ {
+ case 3: /* (%bx) */
+ if (! i.index_reg)
+ i.rm.regmem = 7;
+ else /* (%bx,%si) -> 0, or (%bx,%di) -> 1 */
+ i.rm.regmem = i.index_reg->reg_num - 6;
+ break;
+ case 5: /* (%bp) */
+ default_seg = &ss;
+ if (! i.index_reg)
+ {
+ i.rm.regmem = 6;
+ if ((i.types[op] & Disp) == 0)
+ {
+ /* fake (%bp) into 0(%bp) */
+ i.types[op] |= Disp8;
+ fake_zero_displacement = 1;
+ }
+ }
+ else /* (%bp,%si) -> 2, or (%bp,%di) -> 3 */
+ i.rm.regmem = i.index_reg->reg_num - 6 + 2;
+ break;
+ default: /* (%si) -> 4 or (%di) -> 5 */
+ i.rm.regmem = i.base_reg->reg_num - 6 + 4;
+ }
+ i.rm.mode = mode_from_disp_size (i.types[op]);
+ }
+ else /* i.base_reg and 32 bit mode */
+ {
+ i.rm.regmem = i.base_reg->reg_num;
+ i.sib.base = i.base_reg->reg_num;
+ if (i.base_reg->reg_num == EBP_REG_NUM)
+ {
+ default_seg = &ss;
+ if (i.disp_operands == 0)
+ {
+ fake_zero_displacement = 1;
+ i.types[op] |= Disp8;
+ }
+ }
+ else if (i.base_reg->reg_num == ESP_REG_NUM)
+ {
+ default_seg = &ss;
+ }
+ i.sib.scale = i.log2_scale_factor;
+ if (! i.index_reg)
+ {
+ /* <disp>(%esp) becomes two byte modrm
+ with no index register. We've already
+ stored the code for esp in i.rm.regmem
+ ie. ESCAPE_TO_TWO_BYTE_ADDRESSING. Any
+ base register besides %esp will not use
+ the extra modrm byte. */
+ i.sib.index = NO_INDEX_REGISTER;
+#if ! SCALE1_WHEN_NO_INDEX
+ /* Another case where we force the second
+ modrm byte. */
+ if (i.log2_scale_factor)
+ i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
+#endif
+ }
+ else
+ {
+ i.sib.index = i.index_reg->reg_num;
+ i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
+ }
+ i.rm.mode = mode_from_disp_size (i.types[op]);
+ }
+
+ if (fake_zero_displacement)
+ {
+ /* Fakes a zero displacement assuming that i.types[op]
+ holds the correct displacement size. */
+ exp = &disp_expressions[i.disp_operands++];
+ i.disps[op] = exp;
+ exp->X_op = O_constant;
+ exp->X_add_number = 0;
+ exp->X_add_symbol = (symbolS *) 0;
+ exp->X_op_symbol = (symbolS *) 0;
+ }
+ }
+
+ /* Fill in i.rm.reg or i.rm.regmem field with register
+ operand (if any) based on i.tm.extension_opcode.
+ Again, we must be careful to make sure that
+ segment/control/debug/test/MMX registers are coded
+ into the i.rm.reg field. */
+ if (i.reg_operands)
+ {
+ unsigned int op =
+ ((i.types[0]
+ & (Reg | SReg2 | SReg3 | Control | Debug
+ | Test | RegMMX))
+ ? 0
+ : ((i.types[1]
+ & (Reg | SReg2 | SReg3 | Control | Debug
+ | Test | RegMMX))
+ ? 1
+ : 2));
+ /* If there is an extension opcode to put here, the
+ register number must be put into the regmem field. */
+ if (i.tm.extension_opcode != None)
+ i.rm.regmem = i.regs[op]->reg_num;
+ else
+ i.rm.reg = i.regs[op]->reg_num;
+
+ /* Now, if no memory operand has set i.rm.mode = 0, 1, 2
+ we must set it to 3 to indicate this is a register
+ operand in the regmem field. */
+ if (!i.mem_operands)
+ i.rm.mode = 3;
+ }
+
+ /* Fill in i.rm.reg field with extension opcode (if any). */
+ if (i.tm.extension_opcode != None)
+ i.rm.reg = i.tm.extension_opcode;
+ }
+ }
+ else if (i.tm.opcode_modifier & (Seg2ShortForm | Seg3ShortForm))
+ {
+ if (i.tm.base_opcode == POP_SEG_SHORT && i.regs[0]->reg_num == 1)
+ {
+ as_bad (_("you can't `pop %%cs'"));
+ return;
+ }
+ i.tm.base_opcode |= (i.regs[0]->reg_num << 3);
+ }
+ else if ((i.tm.base_opcode & ~(D|W)) == MOV_AX_DISP32)
+ {
+ default_seg = &ds;
+ }
+ else if ((i.tm.opcode_modifier & IsString) != 0)
+ {
+ /* For the string instructions that allow a segment override
+ on one of their operands, the default segment is ds. */
+ default_seg = &ds;
+ }
+
+ /* If a segment was explicitly specified,
+ and the specified segment is not the default,
+ use an opcode prefix to select it.
+ If we never figured out what the default segment is,
+ then default_seg will be zero at this point,
+ and the specified segment prefix will always be used. */
+ if ((i.seg[0]) && (i.seg[0] != default_seg))
+ {
+ if (! add_prefix (i.seg[0]->seg_prefix))
+ return;
+ }
+ }
+ else if ((i.tm.opcode_modifier & Ugh) != 0)
+ {
+ /* UnixWare fsub no args is alias for fsubp, fadd -> faddp, etc */
+ as_warn (_("translating to `%sp'"), i.tm.name);
+ }
+ }
+
+ /* Handle conversion of 'int $3' --> special int3 insn. */
+ if (i.tm.base_opcode == INT_OPCODE && i.imms[0]->X_add_number == 3)
+ {
+ i.tm.base_opcode = INT3_OPCODE;
+ i.imm_operands = 0;
+ }
+
+ /* We are ready to output the insn. */
+ {
+ register char *p;
+
+ /* Output jumps. */
+ if (i.tm.opcode_modifier & Jump)
+ {
+ long n = (long) i.disps[0]->X_add_number;
+ int prefix = (i.prefix[DATA_PREFIX] != 0);
+ int code16 = 0;
+
+ if (prefix)
+ {
+ i.prefixes -= 1;
+ code16 = CODE16;
+ }
+ if (flag_16bit_code)
+ code16 ^= CODE16;
+
+ if (!intel_syntax && (i.prefixes != 0))
+ as_warn (_("skipping prefixes on this instruction"));
+
+ if (i.disps[0]->X_op == O_constant)
+ {
+ if (fits_in_signed_byte (n))
+ {
+ insn_size += 2;
+ p = frag_more (2);
+ p[0] = i.tm.base_opcode;
+ p[1] = n;
+ }
+ else
+ {
+ /* Use 16-bit jumps only for 16-bit code,
+ because text segments are limited to 64K anyway;
+ Use 32-bit jumps for 32-bit code, because they're faster,
+ and a 16-bit jump will clear the top 16 bits of %eip. */
+ int jmp_size = code16 ? 2 : 4;
+ if (code16 && !fits_in_signed_word (n))
+ {
+ as_bad (_("16-bit jump out of range"));
+ return;
+ }
+
+ if (i.tm.base_opcode == JUMP_PC_RELATIVE)
+ { /* pace */
+ /* unconditional jump */
+ insn_size += prefix + 1 + jmp_size;
+ p = frag_more (prefix + 1 + jmp_size);
+ if (prefix)
+ *p++ = DATA_PREFIX_OPCODE;
+ *p++ = (char) 0xe9;
+ md_number_to_chars (p, (valueT) n, jmp_size);
+ }
+ else
+ {
+ /* conditional jump */
+ insn_size += prefix + 2 + jmp_size;
+ p = frag_more (prefix + 2 + jmp_size);
+ if (prefix)
+ *p++ = DATA_PREFIX_OPCODE;
+ *p++ = TWO_BYTE_OPCODE_ESCAPE;
+ *p++ = i.tm.base_opcode + 0x10;
+ md_number_to_chars (p, (valueT) n, jmp_size);
+ }
+ }
+ }
+ else
+ {
+ int size = code16 ? 2 : 4;
+
+ /* It's a symbol; end frag & setup for relax.
+ Make sure there are more than 6 chars left in the current frag;
+ if not we'll have to start a new one. */
+ frag_grow (prefix + 1 + 2 + size);
+ insn_size += 1 + prefix;
+ p = frag_more (1 + prefix);
+ if (prefix)
+ *p++ = DATA_PREFIX_OPCODE;
+ *p = i.tm.base_opcode;
+ frag_var (rs_machine_dependent,
+ prefix + 2 + size, /* 2 opcode/prefix + displacement */
+ 1,
+ ((unsigned char) *p == JUMP_PC_RELATIVE
+ ? ENCODE_RELAX_STATE (UNCOND_JUMP, SMALL) | code16
+ : ENCODE_RELAX_STATE (COND_JUMP, SMALL) | code16),
+ i.disps[0]->X_add_symbol,
+ (offsetT) n, p);
+ }
+ }
+ else if (i.tm.opcode_modifier & (JumpByte | JumpDword))
+ {
+ int size = (i.tm.opcode_modifier & JumpByte) ? 1 : 4;
+ long n = (long) i.disps[0]->X_add_number;
+
+ if (size == 1) /* then this is a loop or jecxz type instruction */
+ {
+ if (i.prefix[ADDR_PREFIX])
+ {
+ insn_size += 1;
+ FRAG_APPEND_1_CHAR (ADDR_PREFIX_OPCODE);
+ i.prefixes -= 1;
+ }
+ }
+ else
+ {
+ int code16 = 0;
+
+ if (i.prefix[DATA_PREFIX])
+ {
+ insn_size += 1;
+ FRAG_APPEND_1_CHAR (DATA_PREFIX_OPCODE);
+ i.prefixes -= 1;
+ code16 = CODE16;
+ }
+ if (flag_16bit_code)
+ code16 ^= CODE16;
+
+ if (code16)
+ size = 2;
+ }
+
+ if (!intel_syntax && (i.prefixes != 0))
+ as_warn (_("skipping prefixes on this instruction"));
+
+ if (fits_in_unsigned_byte (i.tm.base_opcode))
+ {
+ insn_size += 1 + size;
+ p = frag_more (1 + size);
+ }
+ else
+ {
+ insn_size += 2 + size; /* opcode can be at most two bytes */
+ p = frag_more (2 + size);
+ *p++ = (i.tm.base_opcode >> 8) & 0xff;
+ }
+ *p++ = i.tm.base_opcode & 0xff;
+
+ if (i.disps[0]->X_op == O_constant)
+ {
+ if (size == 1 && !fits_in_signed_byte (n))
+ {
+ as_bad (_("`%s' only takes byte displacement; %ld shortened to %d"),
+ i.tm.name, n, *p);
+ }
+ else if (size == 2 && !fits_in_signed_word (n))
+ {
+ as_bad (_("16-bit jump out of range"));
+ return;
+ }
+ md_number_to_chars (p, (valueT) n, size);
+ }
+ else
+ {
+ fix_new_exp (frag_now, p - frag_now->fr_literal, size,
+ i.disps[0], 1, reloc (size, 1, i.disp_reloc[0]));
+
+ }
+ }
+ else if (i.tm.opcode_modifier & JumpInterSegment)
+ {
+ int size;
+ int reloc_type;
+ int prefix = i.prefix[DATA_PREFIX] != 0;
+ int code16 = 0;
+
+ if (prefix)
+ {
+ code16 = CODE16;
+ i.prefixes -= 1;
+ }
+ if (flag_16bit_code)
+ code16 ^= CODE16;
+
+ size = 4;
+ reloc_type = BFD_RELOC_32;
+ if (code16)
+ {
+ size = 2;
+ reloc_type = BFD_RELOC_16;
+ }
+
+ if (!intel_syntax && (i.prefixes != 0))
+ as_warn (_("skipping prefixes on this instruction"));
+
+ insn_size += prefix + 1 + 2 + size; /* 1 opcode; 2 segment; offset */
+ p = frag_more (prefix + 1 + 2 + size);
+ if (prefix)
+ *p++ = DATA_PREFIX_OPCODE;
+ *p++ = i.tm.base_opcode;
+ if (i.imms[1]->X_op == O_constant)
+ {
+ long n = (long) i.imms[1]->X_add_number;
+
+ if (size == 2 && !fits_in_unsigned_word (n))
+ {
+ as_bad (_("16-bit jump out of range"));
+ return;
+ }
+ md_number_to_chars (p, (valueT) n, size);
+ }
+ else
+ fix_new_exp (frag_now, p - frag_now->fr_literal, size,
+ i.imms[1], 0, reloc_type);
+ if (i.imms[0]->X_op != O_constant)
+ as_bad (_("can't handle non absolute segment in `%s'"),
+ i.tm.name);
+ md_number_to_chars (p + size, (valueT) i.imms[0]->X_add_number, 2);
+ }
+ else
+ {
+ /* Output normal instructions here. */
+ unsigned char *q;
+
+ /* The prefix bytes. */
+ for (q = i.prefix;
+ q < i.prefix + sizeof (i.prefix) / sizeof (i.prefix[0]);
+ q++)
+ {
+ if (*q)
+ {
+ insn_size += 1;
+ p = frag_more (1);
+ md_number_to_chars (p, (valueT) *q, 1);
+ }
+ }
+
+ /* Now the opcode; be careful about word order here! */
+ if (fits_in_unsigned_byte (i.tm.base_opcode))
+ {
+ insn_size += 1;
+ FRAG_APPEND_1_CHAR (i.tm.base_opcode);
+ }
+ else if (fits_in_unsigned_word (i.tm.base_opcode))
+ {
+ insn_size += 2;
+ p = frag_more (2);
+ /* put out high byte first: can't use md_number_to_chars! */
+ *p++ = (i.tm.base_opcode >> 8) & 0xff;
+ *p = i.tm.base_opcode & 0xff;
+ }
+ else
+ { /* opcode is either 3 or 4 bytes */
+ if (i.tm.base_opcode & 0xff000000)
+ {
+ insn_size += 4;
+ p = frag_more (4);
+ *p++ = (i.tm.base_opcode >> 24) & 0xff;
+ }
+ else
+ {
+ insn_size += 3;
+ p = frag_more (3);
+ }
+ *p++ = (i.tm.base_opcode >> 16) & 0xff;
+ *p++ = (i.tm.base_opcode >> 8) & 0xff;
+ *p = (i.tm.base_opcode) & 0xff;
+ }
+
+ /* Now the modrm byte and sib byte (if present). */
+ if (i.tm.opcode_modifier & Modrm)
+ {
+ insn_size += 1;
+ p = frag_more (1);
+ md_number_to_chars (p,
+ (valueT) (i.rm.regmem << 0
+ | i.rm.reg << 3
+ | i.rm.mode << 6),
+ 1);
+ /* If i.rm.regmem == ESP (4)
+ && i.rm.mode != (Register mode)
+ && not 16 bit
+ ==> need second modrm byte. */
+ if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING
+ && i.rm.mode != 3
+ && !(i.base_reg && (i.base_reg->reg_type & Reg16) != 0))
+ {
+ insn_size += 1;
+ p = frag_more (1);
+ md_number_to_chars (p,
+ (valueT) (i.sib.base << 0
+ | i.sib.index << 3
+ | i.sib.scale << 6),
+ 1);
+ }
+ }
+
+ if (i.disp_operands)
+ {
+ register unsigned int n;
+
+ for (n = 0; n < i.operands; n++)
+ {
+ if (i.disps[n])
+ {
+ if (i.disps[n]->X_op == O_constant)
+ {
+ if (i.types[n] & Disp8)
+ {
+ insn_size += 1;
+ p = frag_more (1);
+ md_number_to_chars (p,
+ (valueT) i.disps[n]->X_add_number,
+ 1);
+ }
+ else if (i.types[n] & Disp16)
+ {
+ insn_size += 2;
+ p = frag_more (2);
+ md_number_to_chars (p,
+ (valueT) i.disps[n]->X_add_number,
+ 2);
+ }
+ else
+ { /* Disp32 */
+ insn_size += 4;
+ p = frag_more (4);
+ md_number_to_chars (p,
+ (valueT) i.disps[n]->X_add_number,
+ 4);
+ }
+ }
+ else if (i.types[n] & Disp32)
+ {
+ insn_size += 4;
+ p = frag_more (4);
+ fix_new_exp (frag_now, p - frag_now->fr_literal, 4,
+ i.disps[n], 0,
+ TC_RELOC (i.disp_reloc[n], BFD_RELOC_32));
+ }
+ else
+ { /* must be Disp16 */
+ insn_size += 2;
+ p = frag_more (2);
+ fix_new_exp (frag_now, p - frag_now->fr_literal, 2,
+ i.disps[n], 0,
+ TC_RELOC (i.disp_reloc[n], BFD_RELOC_16));
+ }
+ }
+ }
+ } /* end displacement output */
+
+ /* output immediate */
+ if (i.imm_operands)
+ {
+ register unsigned int n;
+
+ for (n = 0; n < i.operands; n++)
+ {
+ if (i.imms[n])
+ {
+ if (i.imms[n]->X_op == O_constant)
+ {
+ if (i.types[n] & (Imm8 | Imm8S))
+ {
+ insn_size += 1;
+ p = frag_more (1);
+ md_number_to_chars (p,
+ (valueT) i.imms[n]->X_add_number,
+ 1);
+ }
+ else if (i.types[n] & Imm16)
+ {
+ insn_size += 2;
+ p = frag_more (2);
+ md_number_to_chars (p,
+ (valueT) i.imms[n]->X_add_number,
+ 2);
+ }
+ else
+ {
+ insn_size += 4;
+ p = frag_more (4);
+ md_number_to_chars (p,
+ (valueT) i.imms[n]->X_add_number,
+ 4);
+ }
+ }
+ else
+ { /* not absolute_section */
+ /* Need a 32-bit fixup (don't support 8bit
+ non-absolute ims). Try to support other
+ sizes ... */
+ int r_type;
+ int size;
+ int pcrel = 0;
+
+ if (i.types[n] & (Imm8 | Imm8S))
+ size = 1;
+ else if (i.types[n] & Imm16)
+ size = 2;
+ else
+ size = 4;
+ insn_size += size;
+ p = frag_more (size);
+ r_type = reloc (size, 0, i.disp_reloc[0]);
+#ifdef BFD_ASSEMBLER
+ if (r_type == BFD_RELOC_32
+ && GOT_symbol
+ && GOT_symbol == i.imms[n]->X_add_symbol
+ && (i.imms[n]->X_op == O_symbol
+ || (i.imms[n]->X_op == O_add
+ && (i.imms[n]->X_op_symbol->sy_value.X_op
+ == O_subtract))))
+ {
+ r_type = BFD_RELOC_386_GOTPC;
+ i.imms[n]->X_add_number += 3;
+ }
+#endif
+ fix_new_exp (frag_now, p - frag_now->fr_literal, size,
+ i.imms[n], pcrel, r_type);
+ }
+ }
+ }
+ } /* end immediate output */
+ }
+
+#ifdef DEBUG386
+ if (flag_debug)
+ {
+ pi (line, &i);
+ }
+#endif /* DEBUG386 */
+ }
+}
+
+static int i386_is_reg PARAMS ((char *));
+
+static int
+i386_is_reg (reg_string)
+ char *reg_string;
+{
+ register char *s = reg_string;
+ register char *p;
+ char reg_name_given[MAX_REG_NAME_SIZE + 1];
+
+ if (is_space_char (*s))
+ ++s;
+
+ p = reg_name_given;
+ while ((*p++ = register_chars[(unsigned char) *s++]) != '\0')
+ if (p >= reg_name_given + MAX_REG_NAME_SIZE)
+ return 0;
+
+ if (!hash_find (reg_hash, reg_name_given))
+ return 0;
+ else
+ return 1;
+}
+
+static int i386_immediate PARAMS ((char *));
+
+static int
+i386_immediate (imm_start)
+ char *imm_start;
+{
+ char *save_input_line_pointer;
+ segT exp_seg = 0;
+ expressionS * exp;
+
+ if (i.imm_operands == MAX_IMMEDIATE_OPERANDS)
+ {
+ as_bad (_("Only 1 or 2 immediate operands are allowed"));
+ return 0;
+ }
+
+ exp = &im_expressions[i.imm_operands++];
+ i.imms[this_operand] = exp;
+
+ if (is_space_char (*imm_start))
+ ++imm_start;
+
+ save_input_line_pointer = input_line_pointer;
+ input_line_pointer = imm_start;
+
+#ifndef LEX_AT
+ {
+ /*
+ * We can have operands of the form
+ * <symbol>@GOTOFF+<nnn>
+ * Take the easy way out here and copy everything
+ * into a temporary buffer...
+ */
+ register char *cp;
+
+ cp = strchr (input_line_pointer, '@');
+ if (cp != NULL)
+ {
+ char *tmpbuf;
+ int len, first;
+
+ /* GOT relocations are not supported in 16 bit mode */
+ if (flag_16bit_code)
+ as_bad (_("GOT relocations not supported in 16 bit mode"));
+
+ if (GOT_symbol == NULL)
+ GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME);
+
+ if (strncmp (cp + 1, "PLT", 3) == 0)
+ {
+ i.disp_reloc[this_operand] = BFD_RELOC_386_PLT32;
+ len = 3;
+ }
+ else if (strncmp (cp + 1, "GOTOFF", 6) == 0)
+ {
+ i.disp_reloc[this_operand] = BFD_RELOC_386_GOTOFF;
+ len = 6;
+ }
+ else if (strncmp (cp + 1, "GOT", 3) == 0)
+ {
+ i.disp_reloc[this_operand] = BFD_RELOC_386_GOT32;
+ len = 3;
+ }
+ else
+ as_bad (_("Bad reloc specifier in expression"));
+
+ /* Replace the relocation token with ' ', so that errors like
+ foo@GOTOFF1 will be detected. */
+ first = cp - input_line_pointer;
+ tmpbuf = (char *) alloca (strlen(input_line_pointer));
+ memcpy (tmpbuf, input_line_pointer, first);
+ tmpbuf[first] = ' ';
+ strcpy (tmpbuf + first + 1, cp + 1 + len);
+ input_line_pointer = tmpbuf;
+ }
+ }
+#endif
+
+ exp_seg = expression (exp);
+
+ if (*input_line_pointer)
+ as_bad (_("Ignoring junk `%s' after expression"), input_line_pointer);
+
+ input_line_pointer = save_input_line_pointer;
+
+ if (exp->X_op == O_absent)
+ {
+ /* missing or bad expr becomes absolute 0 */
+ as_bad (_("Missing or invalid immediate expression `%s' taken as 0"),
+ imm_start);
+ exp->X_op = O_constant;
+ exp->X_add_number = 0;
+ exp->X_add_symbol = (symbolS *) 0;
+ exp->X_op_symbol = (symbolS *) 0;
+ i.types[this_operand] |= Imm;
+ }
+ else if (exp->X_op == O_constant)
+ {
+ i.types[this_operand] |=
+ smallest_imm_type ((long) exp->X_add_number);
+
+ /* If a suffix is given, this operand may be shortended. */
+ switch (i.suffix)
+ {
+ case WORD_MNEM_SUFFIX:
+ i.types[this_operand] |= Imm16;
+ break;
+ case BYTE_MNEM_SUFFIX:
+ i.types[this_operand] |= Imm16 | Imm8 | Imm8S;
+ break;
+ }
+ }
+#ifdef OBJ_AOUT
+ else if (exp_seg != text_section
+ && exp_seg != data_section
+ && exp_seg != bss_section
+ && exp_seg != undefined_section
+#ifdef BFD_ASSEMBLER
+ && !bfd_is_com_section (exp_seg)
+#endif
+ )
+ {
+ seg_unimplemented:
+ as_bad (_("Unimplemented segment type %d in operand"), exp_seg);
+ return 0;
+ }
+#endif
+ else
+ {
+ /* This is an address. The size of the address will be
+ determined later, depending on destination register,
+ suffix, or the default for the section. We exclude
+ Imm8S here so that `push $foo' and other instructions
+ with an Imm8S form will use Imm16 or Imm32. */
+ i.types[this_operand] |= (Imm8 | Imm16 | Imm32);
+ }
+
+ return 1;
+}
+
+static int i386_scale PARAMS ((char *));
+
+static int
+i386_scale (scale)
+ char *scale;
+{
+ if (!isdigit (*scale))
+ goto bad_scale;
+
+ switch (*scale)
+ {
+ case '0':
+ case '1':
+ i.log2_scale_factor = 0;
+ break;
+ case '2':
+ i.log2_scale_factor = 1;
+ break;
+ case '4':
+ i.log2_scale_factor = 2;
+ break;
+ case '8':
+ i.log2_scale_factor = 3;
+ break;
+ default:
+ bad_scale:
+ as_bad (_("expecting scale factor of 1, 2, 4, or 8: got `%s'"),
+ scale);
+ return 0;
+ }
+ if (i.log2_scale_factor != 0 && ! i.index_reg)
+ {
+ as_warn (_("scale factor of %d without an index register"),
+ 1 << i.log2_scale_factor);
+#if SCALE1_WHEN_NO_INDEX
+ i.log2_scale_factor = 0;
+#endif
+ }
+ return 1;
+}
+
+static int i386_displacement PARAMS ((char *, char *));
+
+static int
+i386_displacement (disp_start, disp_end)
+ char *disp_start;
+ char *disp_end;
+{
+ register expressionS *exp;
+ segT exp_seg = 0;
+ char *save_input_line_pointer;
+ int bigdisp = Disp32;
+
+ /* All of the pieces of the displacement expression are handled together. */
+ if (intel_syntax && i.disp_operands != 0)
+ return 1;
+
+ if (flag_16bit_code ^ (i.prefix[ADDR_PREFIX] != 0))
+ bigdisp = Disp16;
+ i.types[this_operand] |= bigdisp;
+
+ exp = &disp_expressions[i.disp_operands];
+ i.disps[this_operand] = exp;
+ i.disp_reloc[this_operand] = NO_RELOC;
+ i.disp_operands++;
+ save_input_line_pointer = input_line_pointer;
+ input_line_pointer = disp_start;
+ END_STRING_AND_SAVE (disp_end);
+
+#ifndef GCC_ASM_O_HACK
+#define GCC_ASM_O_HACK 0
+#endif
+#if GCC_ASM_O_HACK
+ END_STRING_AND_SAVE (disp_end + 1);
+ if ((i.types[this_operand] & BaseIndex) != 0
+ && displacement_string_end[-1] == '+')
+ {
+ /* This hack is to avoid a warning when using the "o"
+ constraint within gcc asm statements.
+ For instance:
+
+ #define _set_tssldt_desc(n,addr,limit,type) \
+ __asm__ __volatile__ ( \
+ "movw %w2,%0\n\t" \
+ "movw %w1,2+%0\n\t" \
+ "rorl $16,%1\n\t" \
+ "movb %b1,4+%0\n\t" \
+ "movb %4,5+%0\n\t" \
+ "movb $0,6+%0\n\t" \
+ "movb %h1,7+%0\n\t" \
+ "rorl $16,%1" \
+ : "=o"(*(n)) : "q" (addr), "ri"(limit), "i"(type))
+
+ This works great except that the output assembler ends
+ up looking a bit weird if it turns out that there is
+ no offset. You end up producing code that looks like:
+
+ #APP
+ movw $235,(%eax)
+ movw %dx,2+(%eax)
+ rorl $16,%edx
+ movb %dl,4+(%eax)
+ movb $137,5+(%eax)
+ movb $0,6+(%eax)
+ movb %dh,7+(%eax)
+ rorl $16,%edx
+ #NO_APP
+
+ So here we provide the missing zero.
+ */
+
+ *displacement_string_end = '0';
+ }
+#endif
+#ifndef LEX_AT
+ {
+ /*
+ * We can have operands of the form
+ * <symbol>@GOTOFF+<nnn>
+ * Take the easy way out here and copy everything
+ * into a temporary buffer...
+ */
+ register char *cp;
+
+ cp = strchr (input_line_pointer, '@');
+ if (cp != NULL)
+ {
+ char *tmpbuf;
+ int len, first;
+
+ /* GOT relocations are not supported in 16 bit mode */
+ if (flag_16bit_code)
+ as_bad (_("GOT relocations not supported in 16 bit mode"));
+
+ if (GOT_symbol == NULL)
+ GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME);
+
+ if (strncmp (cp + 1, "PLT", 3) == 0)
+ {
+ i.disp_reloc[this_operand] = BFD_RELOC_386_PLT32;
+ len = 3;
+ }
+ else if (strncmp (cp + 1, "GOTOFF", 6) == 0)
+ {
+ i.disp_reloc[this_operand] = BFD_RELOC_386_GOTOFF;
+ len = 6;
+ }
+ else if (strncmp (cp + 1, "GOT", 3) == 0)
+ {
+ i.disp_reloc[this_operand] = BFD_RELOC_386_GOT32;
+ len = 3;
+ }
+ else
+ as_bad (_("Bad reloc specifier in expression"));
+
+ /* Replace the relocation token with ' ', so that errors like
+ foo@GOTOFF1 will be detected. */
+ first = cp - input_line_pointer;
+ tmpbuf = (char *) alloca (strlen(input_line_pointer));
+ memcpy (tmpbuf, input_line_pointer, first);
+ tmpbuf[first] = ' ';
+ strcpy (tmpbuf + first + 1, cp + 1 + len);
+ input_line_pointer = tmpbuf;
+ }
+ }
+#endif
+
+ exp_seg = expression (exp);
+
+#ifdef BFD_ASSEMBLER
+ /* We do this to make sure that the section symbol is in
+ the symbol table. We will ultimately change the relocation
+ to be relative to the beginning of the section */
+ if (i.disp_reloc[this_operand] == BFD_RELOC_386_GOTOFF)
+ {
+ if (S_IS_LOCAL(exp->X_add_symbol)
+ && S_GET_SEGMENT (exp->X_add_symbol) != undefined_section)
+ section_symbol(exp->X_add_symbol->bsym->section);
+ assert (exp->X_op == O_symbol);
+ exp->X_op = O_subtract;
+ exp->X_op_symbol = GOT_symbol;
+ i.disp_reloc[this_operand] = BFD_RELOC_32;
+ }
+#endif
+
+ if (*input_line_pointer)
+ as_bad (_("Ignoring junk `%s' after expression"),
+ input_line_pointer);
+#if GCC_ASM_O_HACK
+ RESTORE_END_STRING (disp_end + 1);
+#endif
+ RESTORE_END_STRING (disp_end);
+ input_line_pointer = save_input_line_pointer;
+
+ if (exp->X_op == O_constant)
+ {
+ if (fits_in_signed_byte (exp->X_add_number))
+ i.types[this_operand] |= Disp8;
+ }
+#ifdef OBJ_AOUT
+ else if (exp_seg != text_section
+ && exp_seg != data_section
+ && exp_seg != bss_section
+ && exp_seg != undefined_section)
+ {
+ as_bad (_ ("Unimplemented segment type %d in operand"), exp_seg);
+ return 0;
+ }
+#endif
+ return 1;
+}
+
+static int i386_operand_modifier PARAMS ((char **, int));
+
+static int
+i386_operand_modifier (op_string, got_a_float)
+ char **op_string;
+ int got_a_float;
+{
+ if (!strncasecmp (*op_string, "BYTE PTR", 8))
+ {
+ i.suffix = BYTE_MNEM_SUFFIX;
+ *op_string += 8;
+ return BYTE_PTR;
+
+ }
+ else if (!strncasecmp (*op_string, "WORD PTR", 8))
+ {
+ i.suffix = WORD_MNEM_SUFFIX;
+ *op_string += 8;
+ return WORD_PTR;
+ }
+
+ else if (!strncasecmp (*op_string, "DWORD PTR", 9))
+ {
+ if (got_a_float)
+ i.suffix = SHORT_MNEM_SUFFIX;
+ else
+ i.suffix = DWORD_MNEM_SUFFIX;
+ *op_string += 9;
+ return DWORD_PTR;
+ }
+
+ else if (!strncasecmp (*op_string, "QWORD PTR", 9))
+ {
+ i.suffix = INTEL_DWORD_MNEM_SUFFIX;
+ *op_string += 9;
+ return QWORD_PTR;
+ }
+
+ else if (!strncasecmp (*op_string, "XWORD PTR", 9))
+ {
+ i.suffix = LONG_DOUBLE_MNEM_SUFFIX;
+ *op_string += 9;
+ return XWORD_PTR;
+ }
+
+ else if (!strncasecmp (*op_string, "SHORT", 5))
+ {
+ *op_string += 5;
+ return SHORT;
+ }
+
+ else if (!strncasecmp (*op_string, "OFFSET FLAT:", 12))
+ {
+ *op_string += 12;
+ return OFFSET_FLAT;
+ }
+
+ else if (!strncasecmp (*op_string, "FLAT", 4))
+ {
+ *op_string += 4;
+ return FLAT;
+ }
+
+ else return NONE_FOUND;
+}
+
+static char * build_displacement_string PARAMS ((int, char *));
+
+static char *
+build_displacement_string (initial_disp, op_string)
+ int initial_disp;
+ char *op_string;
+{
+ char *temp_string = (char *) malloc (strlen (op_string) + 1);
+ char *end_of_operand_string;
+ char *tc;
+ char *temp_disp;
+
+ temp_string[0] = '\0';
+ tc = end_of_operand_string = strchr (op_string, '[');
+ if ( initial_disp && !end_of_operand_string)
+ {
+ strcpy (temp_string, op_string);
+ return (temp_string);
+ }
+
+ /* Build the whole displacement string */
+ if (initial_disp)
+ {
+ strncpy (temp_string, op_string, end_of_operand_string - op_string);
+ temp_string[end_of_operand_string - op_string] = '\0';
+ temp_disp = tc;
+ }
+ else
+ temp_disp = op_string;
+
+ while (*temp_disp != '\0')
+ {
+ int add_minus = (*temp_disp == '-');
+
+ if (*temp_disp == '+' || *temp_disp == '-' || *temp_disp == '[')
+ temp_disp++;
+
+ if (is_space_char (*temp_disp))
+ temp_disp++;
+
+ /* Don't consider registers */
+ if (*temp_disp != REGISTER_PREFIX
+ && !(allow_naked_reg && i386_is_reg (temp_disp)))
+ {
+ char *string_start = temp_disp;
+
+ while (*temp_disp != ']'
+ && *temp_disp != '+'
+ && *temp_disp != '-'
+ && *temp_disp != '*')
+ ++temp_disp;
+
+ if (add_minus)
+ strcat (temp_string, "-");
+ else
+ strcat (temp_string, "+");
+
+ strncat (temp_string, string_start, temp_disp - string_start);
+ if (*temp_disp == '+' || *temp_disp == '-')
+ --temp_disp;
+ }
+
+ while (*temp_disp != '\0'
+ && *temp_disp != '+'
+ && *temp_disp != '-')
+ ++temp_disp;
+ }
+
+ return temp_string;
+}
+
+static int i386_parse_seg PARAMS ((char *));
+
+static int
+i386_parse_seg (op_string)
+ char *op_string;
+{
+ if (is_space_char (*op_string))
+ ++op_string;
+
+ /* Should be one of es, cs, ss, ds fs or gs */
+ switch (*op_string++)
+ {
+ case 'e':
+ i.seg[i.mem_operands] = &es;
+ break;
+ case 'c':
+ i.seg[i.mem_operands] = &cs;
+ break;
+ case 's':
+ i.seg[i.mem_operands] = &ss;
+ break;
+ case 'd':
+ i.seg[i.mem_operands] = &ds;
+ break;
+ case 'f':
+ i.seg[i.mem_operands] = &fs;
+ break;
+ case 'g':
+ i.seg[i.mem_operands] = &gs;
+ break;
+ default:
+ as_bad (_("bad segment name `%s'"), op_string);
+ return 0;
+ }
+
+ if (*op_string++ != 's')
+ {
+ as_bad (_("bad segment name `%s'"), op_string);
+ return 0;
+ }
+
+ if (is_space_char (*op_string))
+ ++op_string;
+
+ if (*op_string != ':')
+ {
+ as_bad (_("bad segment name `%s'"), op_string);
+ return 0;
+ }
+
+ return 1;
+
+}
+
+static int i386_intel_memory_operand PARAMS ((char *));
+
+static int
+i386_intel_memory_operand (op_string)
+ char *op_string;
+{
+
+ char *end_of_operand_string;
+
+ if (is_digit_char (*op_string)
+ && strchr (op_string, '[') == 0)
+ {
+ if (!i386_immediate (op_string))
+ return 0;
+ else
+ return 1;
+ }
+
+ /* Look for displacement preceding open bracket */
+ if (*op_string != '[')
+ {
+ char *end_seg;
+ char *temp_string;
+
+ end_seg = strchr (op_string, ':');
+ if (end_seg)
+ {
+ if (!i386_parse_seg (op_string))
+ return 0;
+ op_string = end_seg + 1;
+ }
+
+ temp_string = build_displacement_string (true, op_string);
+ if (!i386_displacement (temp_string, temp_string + strlen (temp_string)))
+ return 0;
+
+ end_of_operand_string = strchr (op_string, '[');
+ if (!end_of_operand_string)
+ end_of_operand_string = op_string + strlen (op_string);
+
+ if (is_space_char (*end_of_operand_string))
+ --end_of_operand_string;
+
+ op_string = end_of_operand_string;
+ }
+
+ if (*op_string == '[')
+ {
+ ++op_string;
+
+ /* Pick off each component and figure out where it belongs */
+
+ end_of_operand_string = op_string;
+
+ while (*op_string != ']')
+ {
+
+ while (*end_of_operand_string != '+'
+ && *end_of_operand_string != '-'
+ && *end_of_operand_string != '*'
+ && *end_of_operand_string != ']')
+ end_of_operand_string++;
+
+ if (*op_string == '+')
+ {
+ char *temp_string = op_string + 1;
+ if (is_space_char (*temp_string))
+ ++temp_string;
+ if (*temp_string == REGISTER_PREFIX
+ || (allow_naked_reg && i386_is_reg (temp_string)))
+ ++op_string;
+ }
+
+ if (*op_string == REGISTER_PREFIX
+ || (allow_naked_reg && i386_is_reg (op_string)))
+ {
+ const reg_entry *temp_reg;
+ char *end_op;
+
+ END_STRING_AND_SAVE (end_of_operand_string);
+ temp_reg = parse_register (op_string, &end_op);
+ RESTORE_END_STRING (end_of_operand_string);
+
+ if (temp_reg == NULL)
+ return 0;
+
+ if (i.base_reg == NULL)
+ i.base_reg = temp_reg;
+ else
+ i.index_reg = temp_reg;
+
+ i.types[this_operand] |= BaseIndex;
+
+ }
+ else if (is_digit_char (*op_string) || *op_string == '+' || *op_string == '-')
+ {
+
+ char *temp_string = build_displacement_string (false, op_string);
+
+ if (*temp_string == '+')
+ ++temp_string;
+
+ if (!i386_displacement (temp_string, temp_string + strlen (temp_string)))
+ return 0;
+
+ ++op_string;
+ end_of_operand_string = op_string;
+ while (*end_of_operand_string != ']'
+ && *end_of_operand_string != '+'
+ && *end_of_operand_string != '-'
+ && *end_of_operand_string != '*')
+ ++end_of_operand_string;
+ }
+ else if (*op_string == '*')
+ {
+ ++op_string;
+
+ if (i.base_reg && !i.index_reg)
+ {
+ i.index_reg = i.base_reg;
+ i.base_reg = 0;
+ }
+
+ if (!i386_scale (op_string))
+ return 0;
+ }
+ op_string = end_of_operand_string;
+ ++end_of_operand_string;
+ }
+ }
+
+ return 1;
+}
+
+static int i386_intel_operand PARAMS ((char *, int));
+
+static int
+i386_intel_operand (operand_string, got_a_float)
+ char *operand_string;
+ int got_a_float;
+{
+ char *op_string = operand_string;
+
+ int operand_modifier = i386_operand_modifier (&op_string, got_a_float);
+ if (is_space_char (*op_string))
+ ++op_string;
+
+ switch (operand_modifier)
+ {
+ case BYTE_PTR:
+ case WORD_PTR:
+ case DWORD_PTR:
+ case QWORD_PTR:
+ case XWORD_PTR:
+ if ((i.mem_operands == 1
+ && (current_templates->start->opcode_modifier & IsString) == 0)
+ || i.mem_operands == 2)
+ {
+ as_bad (_("too many memory references for `%s'"),
+ current_templates->start->name);
+ return 0;
+ }
+
+ if (!i386_intel_memory_operand (op_string))
+ return 0;
+
+ i.mem_operands++;
+ break;
+
+ case FLAT:
+
+ case OFFSET_FLAT:
+ if (!i386_immediate (op_string))
+ return 0;
+ break;
+
+ case SHORT:
+
+ case NONE_FOUND:
+ /* Should be register or immediate */
+ if (is_digit_char (*op_string)
+ && strchr (op_string, '[') == 0)
+ {
+ if (!i386_immediate (op_string))
+ return 0;
+ }
+ else if (*op_string == REGISTER_PREFIX
+ || (allow_naked_reg
+ && i386_is_reg (op_string)))
+ {
+
+ register const reg_entry * r;
+ char *end_op;
+
+ r = parse_register (op_string, &end_op);
+ if (r == NULL)
+ return 0;
+
+ /* Check for a segment override by searching for ':' after a
+ segment register. */
+ op_string = end_op;
+ if (is_space_char (*op_string))
+ ++op_string;
+ if (*op_string == ':' && (r->reg_type & (SReg2 | SReg3)))
+ {
+ switch (r->reg_num)
+ {
+ case 0:
+ i.seg[i.mem_operands] = &es;
+ break;
+ case 1:
+ i.seg[i.mem_operands] = &cs;
+ break;
+ case 2:
+ i.seg[i.mem_operands] = &ss;
+ break;
+ case 3:
+ i.seg[i.mem_operands] = &ds;
+ break;
+ case 4:
+ i.seg[i.mem_operands] = &fs;
+ break;
+ case 5:
+ i.seg[i.mem_operands] = &gs;
+ break;
+ }
+
+ }
+ i.types[this_operand] |= r->reg_type & ~BaseIndex;
+ i.regs[this_operand] = r;
+ i.reg_operands++;
+ }
+
+ else
+ {
+
+ if (!i386_intel_memory_operand (op_string))
+ return 0;
+
+ i.mem_operands++;
+ }
+ break;
+
+ } /* end switch */
+ /* Special case for (%dx) while doing input/output op. */
+ if (i.base_reg
+ && i.base_reg->reg_type == (Reg16 | InOutPortReg)
+ && i.index_reg == 0
+ && i.log2_scale_factor == 0
+ && i.seg[i.mem_operands] == 0
+ && (i.types[this_operand] & Disp) == 0)
+ {
+ i.types[this_operand] = InOutPortReg;
+ return 1;
+ }
+ /* Make sure the memory operand we've been dealt is valid. */
+ if (flag_16bit_code ^ (i.prefix[ADDR_PREFIX] != 0))
+ {
+ if ((i.base_reg
+ && ((i.base_reg->reg_type & (Reg16|BaseIndex))
+ != (Reg16|BaseIndex)))
+ || (i.index_reg
+ && (((i.index_reg->reg_type & (Reg16|BaseIndex))
+ != (Reg16|BaseIndex))
+ || ! (i.base_reg
+ && i.base_reg->reg_num < 6
+ && i.index_reg->reg_num >= 6
+ && i.log2_scale_factor == 0))))
+ {
+ as_bad (_("`%s' is not a valid %s bit base/index expression"),
+ operand_string, "16");
+ return 0;
+ }
+ }
+ else
+ {
+ if ((i.base_reg
+ && (i.base_reg->reg_type & Reg32) == 0)
+ || (i.index_reg
+ && ((i.index_reg->reg_type & (Reg32|BaseIndex))
+ != (Reg32|BaseIndex))))
+ {
+ as_bad (_("`%s' is not a valid %s bit base/index expression"),
+ operand_string, "32");
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/* Parse OPERAND_STRING into the i386_insn structure I. Returns non-zero
+ on error. */
+
+static int i386_operand PARAMS ((char *));
+
+static int
+i386_operand (operand_string)
+ char *operand_string;
+{
+ char *op_string = operand_string;
+
+ if (is_space_char (*op_string))
+ ++op_string;
+
+ /* We check for an absolute prefix (differentiating,
+ for example, 'jmp pc_relative_label' from 'jmp *absolute_label'. */
+ if (*op_string == ABSOLUTE_PREFIX)
+ {
+ ++op_string;
+ if (is_space_char (*op_string))
+ ++op_string;
+ i.types[this_operand] |= JumpAbsolute;
+ }
+
+ /* Check if operand is a register. */
+ if (*op_string == REGISTER_PREFIX
+ || (allow_naked_reg && i386_is_reg (op_string)))
+ {
+ register const reg_entry *r;
+ char *end_op;
+
+ r = parse_register (op_string, &end_op);
+ if (r == NULL)
+ return 0;
+
+ /* Check for a segment override by searching for ':' after a
+ segment register. */
+ op_string = end_op;
+ if (is_space_char (*op_string))
+ ++op_string;
+ if (*op_string == ':' && (r->reg_type & (SReg2 | SReg3)))
+ {
+ switch (r->reg_num)
+ {
+ case 0:
+ i.seg[i.mem_operands] = &es;
+ break;
+ case 1:
+ i.seg[i.mem_operands] = &cs;
+ break;
+ case 2:
+ i.seg[i.mem_operands] = &ss;
+ break;
+ case 3:
+ i.seg[i.mem_operands] = &ds;
+ break;
+ case 4:
+ i.seg[i.mem_operands] = &fs;
+ break;
+ case 5:
+ i.seg[i.mem_operands] = &gs;
+ break;
+ }
+
+ /* Skip the ':' and whitespace. */
+ ++op_string;
+ if (is_space_char (*op_string))
+ ++op_string;
+
+ /* Pretend given string starts here. */
+ operand_string = op_string;
+ if (!is_digit_char (*op_string)
+ && !is_identifier_char (*op_string)
+ && *op_string != '('
+ && *op_string != ABSOLUTE_PREFIX)
+ {
+ as_bad (_("bad memory operand `%s'"), op_string);
+ return 0;
+ }
+ /* Handle case of %es:*foo. */
+ if (*op_string == ABSOLUTE_PREFIX)
+ {
+ ++op_string;
+ if (is_space_char (*op_string))
+ ++op_string;
+ i.types[this_operand] |= JumpAbsolute;
+ }
+ goto do_memory_reference;
+ }
+ if (*op_string)
+ {
+ as_bad (_("Junk `%s' after register"), op_string);
+ return 0;
+ }
+ i.types[this_operand] |= r->reg_type & ~BaseIndex;
+ i.regs[this_operand] = r;
+ i.reg_operands++;
+ }
+ else if (*op_string == IMMEDIATE_PREFIX)
+ { /* ... or an immediate */
+ ++op_string;
+ if (!i386_immediate (op_string))
+ return 0;
+ }
+ else if (is_digit_char (*op_string)
+ || is_identifier_char (*op_string)
+ || *op_string == '(' )
+ {
+ /* This is a memory reference of some sort. */
+ char *end_of_operand_string;
+ register char *base_string;
+ int found_base_index_form;
+
+ /* Start and end of displacement string expression (if found). */
+ char *displacement_string_start;
+ char *displacement_string_end;
+
+ do_memory_reference:
+
+ if ((i.mem_operands == 1
+ && (current_templates->start->opcode_modifier & IsString) == 0)
+ || i.mem_operands == 2)
+ {
+ as_bad (_("too many memory references for `%s'"),
+ current_templates->start->name);
+ return 0;
+ }
+
+ /* Check for base index form. We detect the base index form by
+ looking for an ')' at the end of the operand, searching
+ for the '(' matching it, and finding a REGISTER_PREFIX or ','
+ after the '('. */
+ found_base_index_form = 0;
+ end_of_operand_string = op_string + strlen (op_string);
+
+ --end_of_operand_string;
+ if (is_space_char (*end_of_operand_string))
+ --end_of_operand_string;
+
+ base_string = end_of_operand_string;
+
+ if (*base_string == ')')
+ {
+ unsigned int parens_balanced = 1;
+ /* We've already checked that the number of left & right ()'s are
+ equal, so this loop will not be infinite. */
+ do
+ {
+ base_string--;
+ if (*base_string == ')')
+ parens_balanced++;
+ if (*base_string == '(')
+ parens_balanced--;
+ }
+ while (parens_balanced);
+
+ /* If there is a displacement set-up for it to be parsed later. */
+ displacement_string_start = op_string;
+ displacement_string_end = base_string;
+
+ /* Skip past '(' and whitespace. */
+ ++base_string;
+ if (is_space_char (*base_string))
+ ++base_string;
+
+ if (*base_string == REGISTER_PREFIX
+ || (allow_naked_reg && i386_is_reg (base_string))
+ || *base_string == ',')
+ found_base_index_form = 1;
+ }
+
+ /* If we can't parse a base index register expression, we've found
+ a pure displacement expression. We set up displacement_string_start
+ and displacement_string_end for the code below. */
+ if (!found_base_index_form)
+ {
+ displacement_string_start = op_string;
+ displacement_string_end = end_of_operand_string + 1;
+ }
+ else
+ {
+ i.types[this_operand] |= BaseIndex;
+
+ /* Find base register (if any). */
+ if (*base_string != ',')
+ {
+ char *end_op;
+
+ /* Trim off the closing ')' so that parse_register won't
+ see it. */
+ END_STRING_AND_SAVE (end_of_operand_string);
+ i.base_reg = parse_register (base_string, &end_op);
+ RESTORE_END_STRING (end_of_operand_string);
+
+ if (i.base_reg == NULL)
+ return 0;
+
+ base_string = end_op;
+ if (is_space_char (*base_string))
+ ++base_string;
+ }
+
+ /* There may be an index reg or scale factor here. */
+ if (*base_string == ',')
+ {
+ ++base_string;
+ if (is_space_char (*base_string))
+ ++base_string;
+
+ if (*base_string == REGISTER_PREFIX
+ || (allow_naked_reg && i386_is_reg (base_string)))
+ {
+ char *end_op;
+
+ END_STRING_AND_SAVE (end_of_operand_string);
+ i.index_reg = parse_register (base_string, &end_op);
+ RESTORE_END_STRING (end_of_operand_string);
+
+ if (i.index_reg == NULL)
+ return 0;
+
+ base_string = end_op;
+ if (is_space_char (*base_string))
+ ++base_string;
+ if (*base_string == ',')
+ {
+ ++base_string;
+ if (is_space_char (*base_string))
+ ++base_string;
+ }
+ else if (*base_string != ')' )
+ {
+ as_bad (_("expecting `,' or `)' after index register in `%s'"),
+ operand_string);
+ return 0;
+ }
+ }
+
+ /* Check for scale factor. */
+ if (isdigit ((unsigned char) *base_string))
+ {
+ if (!i386_scale (base_string))
+ return 0;
+
+ ++base_string;
+ if (is_space_char (*base_string))
+ ++base_string;
+ if (*base_string != ')')
+ {
+ as_bad (_("expecting `)' after scale factor in `%s'"),
+ operand_string);
+ return 0;
+ }
+ }
+ else if (!i.index_reg)
+ {
+ as_bad (_("expecting index register or scale factor after `,'; got '%c'"),
+ *base_string);
+ return 0;
+ }
+ }
+ else if (*base_string != ')')
+ {
+ as_bad (_("expecting `,' or `)' after base register in `%s'"),
+ operand_string);
+ return 0;
+ }
+ }
+
+ /* If there's an expression beginning the operand, parse it,
+ assuming displacement_string_start and
+ displacement_string_end are meaningful. */
+ if (displacement_string_start != displacement_string_end)
+ {
+ if (!i386_displacement (displacement_string_start,
+ displacement_string_end))
+ return 0;
+ }
+
+ /* Special case for (%dx) while doing input/output op. */
+ if (i.base_reg
+ && i.base_reg->reg_type == (Reg16 | InOutPortReg)
+ && i.index_reg == 0
+ && i.log2_scale_factor == 0
+ && i.seg[i.mem_operands] == 0
+ && (i.types[this_operand] & Disp) == 0)
+ {
+ i.types[this_operand] = InOutPortReg;
+ return 1;
+ }
+ /* Make sure the memory operand we've been dealt is valid. */
+ if (flag_16bit_code ^ (i.prefix[ADDR_PREFIX] != 0))
+ {
+ if ((i.base_reg
+ && ((i.base_reg->reg_type & (Reg16|BaseIndex))
+ != (Reg16|BaseIndex)))
+ || (i.index_reg
+ && (((i.index_reg->reg_type & (Reg16|BaseIndex))
+ != (Reg16|BaseIndex))
+ || ! (i.base_reg
+ && i.base_reg->reg_num < 6
+ && i.index_reg->reg_num >= 6
+ && i.log2_scale_factor == 0))))
+ {
+ as_bad (_("`%s' is not a valid %s bit base/index expression"),
+ operand_string, "16");
+ return 0;
+ }
+ }
+ else
+ {
+ if ((i.base_reg
+ && (i.base_reg->reg_type & Reg32) == 0)
+ || (i.index_reg
+ && ((i.index_reg->reg_type & (Reg32|BaseIndex))
+ != (Reg32|BaseIndex))))
+ {
+ as_bad (_("`%s' is not a valid %s bit base/index expression"),
+ operand_string, "32");
+ return 0;
+ }
+ }
+ i.mem_operands++;
+ }
+ else
+ { /* it's not a memory operand; argh! */
+ as_bad (_("invalid char %s beginning operand %d `%s'"),
+ output_invalid (*op_string),
+ this_operand + 1,
+ op_string);
+ return 0;
+ }
+ return 1; /* normal return */
+}
+
+/*
+ * md_estimate_size_before_relax()
+ *
+ * Called just before relax().
+ * Any symbol that is now undefined will not become defined.
+ * Return the correct fr_subtype in the frag.
+ * Return the initial "guess for fr_var" to caller.
+ * The guess for fr_var is ACTUALLY the growth beyond fr_fix.
+ * Whatever we do to grow fr_fix or fr_var contributes to our returned value.
+ * Although it may not be explicit in the frag, pretend fr_var starts with a
+ * 0 value.
+ */
+int
+md_estimate_size_before_relax (fragP, segment)
+ register fragS *fragP;
+ register segT segment;
+{
+ register unsigned char *opcode;
+ register int old_fr_fix;
+
+ old_fr_fix = fragP->fr_fix;
+ opcode = (unsigned char *) fragP->fr_opcode;
+ /* We've already got fragP->fr_subtype right; all we have to do is
+ check for un-relaxable symbols. */
+ if (S_GET_SEGMENT (fragP->fr_symbol) != segment)
+ {
+ /* symbol is undefined in this segment */
+ int code16 = fragP->fr_subtype & CODE16;
+ int size = code16 ? 2 : 4;
+ int pcrel_reloc = code16 ? BFD_RELOC_16_PCREL : BFD_RELOC_32_PCREL;
+
+ switch (opcode[0])
+ {
+ case JUMP_PC_RELATIVE: /* make jmp (0xeb) a dword displacement jump */
+ opcode[0] = 0xe9; /* dword disp jmp */
+ fragP->fr_fix += size;
+ fix_new (fragP, old_fr_fix, size,
+ fragP->fr_symbol,
+ fragP->fr_offset, 1,
+ (GOT_symbol && /* Not quite right - we should switch on
+ presence of @PLT, but I cannot see how
+ to get to that from here. We should have
+ done this in md_assemble to really
+ get it right all of the time, but I
+ think it does not matter that much, as
+ this will be right most of the time. ERY*/
+ S_GET_SEGMENT(fragP->fr_symbol) == undefined_section)
+ ? BFD_RELOC_386_PLT32 : pcrel_reloc);
+ break;
+
+ default:
+ /* This changes the byte-displacement jump 0x7N -->
+ the dword-displacement jump 0x0f8N */
+ opcode[1] = opcode[0] + 0x10;
+ opcode[0] = TWO_BYTE_OPCODE_ESCAPE; /* two-byte escape */
+ fragP->fr_fix += 1 + size; /* we've added an opcode byte */
+ fix_new (fragP, old_fr_fix + 1, size,
+ fragP->fr_symbol,
+ fragP->fr_offset, 1,
+ (GOT_symbol && /* Not quite right - we should switch on
+ presence of @PLT, but I cannot see how
+ to get to that from here. ERY */
+ S_GET_SEGMENT(fragP->fr_symbol) == undefined_section)
+ ? BFD_RELOC_386_PLT32 : pcrel_reloc);
+ break;
+ }
+ frag_wane (fragP);
+ }
+ return (fragP->fr_var + fragP->fr_fix - old_fr_fix);
+} /* md_estimate_size_before_relax() */
+
+/*
+ * md_convert_frag();
+ *
+ * Called after relax() is finished.
+ * In: Address of frag.
+ * fr_type == rs_machine_dependent.
+ * fr_subtype is what the address relaxed to.
+ *
+ * Out: Any fixSs and constants are set up.
+ * Caller will turn frag into a ".space 0".
+ */
+#ifndef BFD_ASSEMBLER
+void
+md_convert_frag (headers, sec, fragP)
+ object_headers *headers;
+ segT sec;
+ register fragS *fragP;
+#else
+void
+md_convert_frag (abfd, sec, fragP)
+ bfd *abfd;
+ segT sec;
+ register fragS *fragP;
+#endif
+{
+ register unsigned char *opcode;
+ unsigned char *where_to_put_displacement = NULL;
+ unsigned int target_address;
+ unsigned int opcode_address;
+ unsigned int extension = 0;
+ int displacement_from_opcode_start;
+
+ opcode = (unsigned char *) fragP->fr_opcode;
+
+ /* Address we want to reach in file space. */
+ target_address = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset;
+#ifdef BFD_ASSEMBLER /* not needed otherwise? */
+ target_address += fragP->fr_symbol->sy_frag->fr_address;
+#endif
+
+ /* Address opcode resides at in file space. */
+ opcode_address = fragP->fr_address + fragP->fr_fix;
+
+ /* Displacement from opcode start to fill into instruction. */
+ displacement_from_opcode_start = target_address - opcode_address;
+
+ switch (fragP->fr_subtype)
+ {
+ case ENCODE_RELAX_STATE (COND_JUMP, SMALL):
+ case ENCODE_RELAX_STATE (COND_JUMP, SMALL16):
+ case ENCODE_RELAX_STATE (UNCOND_JUMP, SMALL):
+ case ENCODE_RELAX_STATE (UNCOND_JUMP, SMALL16):
+ /* don't have to change opcode */
+ extension = 1; /* 1 opcode + 1 displacement */
+ where_to_put_displacement = &opcode[1];
+ break;
+
+ case ENCODE_RELAX_STATE (COND_JUMP, BIG):
+ extension = 5; /* 2 opcode + 4 displacement */
+ opcode[1] = opcode[0] + 0x10;
+ opcode[0] = TWO_BYTE_OPCODE_ESCAPE;
+ where_to_put_displacement = &opcode[2];
+ break;
+
+ case ENCODE_RELAX_STATE (UNCOND_JUMP, BIG):
+ extension = 4; /* 1 opcode + 4 displacement */
+ opcode[0] = 0xe9;
+ where_to_put_displacement = &opcode[1];
+ break;
+
+ case ENCODE_RELAX_STATE (COND_JUMP, BIG16):
+ extension = 3; /* 2 opcode + 2 displacement */
+ opcode[1] = opcode[0] + 0x10;
+ opcode[0] = TWO_BYTE_OPCODE_ESCAPE;
+ where_to_put_displacement = &opcode[2];
+ break;
+
+ case ENCODE_RELAX_STATE (UNCOND_JUMP, BIG16):
+ extension = 2; /* 1 opcode + 2 displacement */
+ opcode[0] = 0xe9;
+ where_to_put_displacement = &opcode[1];
+ break;
+
+ default:
+ BAD_CASE (fragP->fr_subtype);
+ break;
+ }
+ /* now put displacement after opcode */
+ md_number_to_chars ((char *) where_to_put_displacement,
+ (valueT) (displacement_from_opcode_start - extension),
+ SIZE_FROM_RELAX_STATE (fragP->fr_subtype));
+ fragP->fr_fix += extension;
+}
+
+
+int md_short_jump_size = 2; /* size of byte displacement jmp */
+int md_long_jump_size = 5; /* size of dword displacement jmp */
+const int md_reloc_size = 8; /* Size of relocation record */
+
+void
+md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
+ char *ptr;
+ addressT from_addr, to_addr;
+ fragS *frag;
+ symbolS *to_symbol;
+{
+ long offset;
+
+ offset = to_addr - (from_addr + 2);
+ md_number_to_chars (ptr, (valueT) 0xeb, 1); /* opcode for byte-disp jump */
+ md_number_to_chars (ptr + 1, (valueT) offset, 1);
+}
+
+void
+md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
+ char *ptr;
+ addressT from_addr, to_addr;
+ fragS *frag;
+ symbolS *to_symbol;
+{
+ long offset;
+
+ if (flag_do_long_jump)
+ {
+ offset = to_addr - S_GET_VALUE (to_symbol);
+ md_number_to_chars (ptr, (valueT) 0xe9, 1);/* opcode for long jmp */
+ md_number_to_chars (ptr + 1, (valueT) offset, 4);
+ fix_new (frag, (ptr + 1) - frag->fr_literal, 4,
+ to_symbol, (offsetT) 0, 0, BFD_RELOC_32);
+ }
+ else
+ {
+ offset = to_addr - (from_addr + 5);
+ md_number_to_chars (ptr, (valueT) 0xe9, 1);
+ md_number_to_chars (ptr + 1, (valueT) offset, 4);
+ }
+}
+
+/* Apply a fixup (fixS) to segment data, once it has been determined
+ by our caller that we have all the info we need to fix it up.
+
+ On the 386, immediates, displacements, and data pointers are all in
+ the same (little-endian) format, so we don't need to care about which
+ we are handling. */
+
+int
+md_apply_fix3 (fixP, valp, seg)
+ fixS *fixP; /* The fix we're to put in. */
+ valueT *valp; /* Pointer to the value of the bits. */
+ segT seg; /* Segment fix is from. */
+{
+ register char *p = fixP->fx_where + fixP->fx_frag->fr_literal;
+ valueT value = *valp;
+
+ if (fixP->fx_r_type == BFD_RELOC_32 && fixP->fx_pcrel)
+ fixP->fx_r_type = BFD_RELOC_32_PCREL;
+
+#if defined (BFD_ASSEMBLER) && !defined (TE_Mach)
+ /*
+ * This is a hack. There should be a better way to
+ * handle this.
+ */
+ if (fixP->fx_r_type == BFD_RELOC_32_PCREL && fixP->fx_addsy)
+ {
+#ifndef OBJ_AOUT
+ if (OUTPUT_FLAVOR == bfd_target_elf_flavour
+#ifdef TE_PE
+ || OUTPUT_FLAVOR == bfd_target_coff_flavour
+#endif
+ )
+ value += fixP->fx_where + fixP->fx_frag->fr_address;
+#endif
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+ if (OUTPUT_FLAVOR == bfd_target_elf_flavour
+ && (S_GET_SEGMENT (fixP->fx_addsy) == seg
+ || (fixP->fx_addsy->bsym->flags & BSF_SECTION_SYM) != 0)
+ && ! S_IS_EXTERNAL (fixP->fx_addsy)
+ && ! S_IS_WEAK (fixP->fx_addsy)
+ && S_IS_DEFINED (fixP->fx_addsy)
+ && ! S_IS_COMMON (fixP->fx_addsy))
+ {
+ /* Yes, we add the values in twice. This is because
+ bfd_perform_relocation subtracts them out again. I think
+ bfd_perform_relocation is broken, but I don't dare change
+ it. FIXME. */
+ value += fixP->fx_where + fixP->fx_frag->fr_address;
+ }
+#endif
+#if defined (OBJ_COFF) && defined (TE_PE)
+ /* For some reason, the PE format does not store a section
+ address offset for a PC relative symbol. */
+ if (S_GET_SEGMENT (fixP->fx_addsy) != seg)
+ value += md_pcrel_from (fixP);
+#endif
+ }
+
+ /* Fix a few things - the dynamic linker expects certain values here,
+ and we must not dissappoint it. */
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+ if (OUTPUT_FLAVOR == bfd_target_elf_flavour
+ && fixP->fx_addsy)
+ switch (fixP->fx_r_type) {
+ case BFD_RELOC_386_PLT32:
+ /* Make the jump instruction point to the address of the operand. At
+ runtime we merely add the offset to the actual PLT entry. */
+ value = 0xfffffffc;
+ break;
+ case BFD_RELOC_386_GOTPC:
+/*
+ * This is tough to explain. We end up with this one if we have
+ * operands that look like "_GLOBAL_OFFSET_TABLE_+[.-.L284]". The goal
+ * here is to obtain the absolute address of the GOT, and it is strongly
+ * preferable from a performance point of view to avoid using a runtime
+ * relocation for this. The actual sequence of instructions often look
+ * something like:
+ *
+ * call .L66
+ * .L66:
+ * popl %ebx
+ * addl $_GLOBAL_OFFSET_TABLE_+[.-.L66],%ebx
+ *
+ * The call and pop essentially return the absolute address of
+ * the label .L66 and store it in %ebx. The linker itself will
+ * ultimately change the first operand of the addl so that %ebx points to
+ * the GOT, but to keep things simple, the .o file must have this operand
+ * set so that it generates not the absolute address of .L66, but the
+ * absolute address of itself. This allows the linker itself simply
+ * treat a GOTPC relocation as asking for a pcrel offset to the GOT to be
+ * added in, and the addend of the relocation is stored in the operand
+ * field for the instruction itself.
+ *
+ * Our job here is to fix the operand so that it would add the correct
+ * offset so that %ebx would point to itself. The thing that is tricky is
+ * that .-.L66 will point to the beginning of the instruction, so we need
+ * to further modify the operand so that it will point to itself.
+ * There are other cases where you have something like:
+ *
+ * .long $_GLOBAL_OFFSET_TABLE_+[.-.L66]
+ *
+ * and here no correction would be required. Internally in the assembler
+ * we treat operands of this form as not being pcrel since the '.' is
+ * explicitly mentioned, and I wonder whether it would simplify matters
+ * to do it this way. Who knows. In earlier versions of the PIC patches,
+ * the pcrel_adjust field was used to store the correction, but since the
+ * expression is not pcrel, I felt it would be confusing to do it this way.
+ */
+ value -= 1;
+ break;
+ case BFD_RELOC_386_GOT32:
+ value = 0; /* Fully resolved at runtime. No addend. */
+ break;
+ case BFD_RELOC_386_GOTOFF:
+ break;
+
+ case BFD_RELOC_VTABLE_INHERIT:
+ case BFD_RELOC_VTABLE_ENTRY:
+ fixP->fx_done = 0;
+ return 1;
+
+ default:
+ break;
+ }
+#endif
+
+#endif
+ md_number_to_chars (p, value, fixP->fx_size);
+
+ return 1;
+}
+
+#if 0
+/* This is never used. */
+long /* Knows about the byte order in a word. */
+md_chars_to_number (con, nbytes)
+ unsigned char con[]; /* Low order byte 1st. */
+ int nbytes; /* Number of bytes in the input. */
+{
+ long retval;
+ for (retval = 0, con += nbytes - 1; nbytes--; con--)
+ {
+ retval <<= BITS_PER_CHAR;
+ retval |= *con;
+ }
+ return retval;
+}
+#endif /* 0 */
+
+
+#define MAX_LITTLENUMS 6
+
+/* Turn the string pointed to by litP into a floating point constant of type
+ type, and emit the appropriate bytes. The number of LITTLENUMS emitted
+ is stored in *sizeP . An error message is returned, or NULL on OK. */
+char *
+md_atof (type, litP, sizeP)
+ char type;
+ char *litP;
+ int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ char *t;
+
+ switch (type)
+ {
+ case 'f':
+ case 'F':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ prec = 4;
+ break;
+
+ case 'x':
+ case 'X':
+ prec = 5;
+ break;
+
+ default:
+ *sizeP = 0;
+ return _("Bad call to md_atof ()");
+ }
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+
+ *sizeP = prec * sizeof (LITTLENUM_TYPE);
+ /* This loops outputs the LITTLENUMs in REVERSE order; in accord with
+ the bigendian 386. */
+ for (wordP = words + prec - 1; prec--;)
+ {
+ md_number_to_chars (litP, (valueT) (*wordP--), sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+ return 0;
+}
+
+char output_invalid_buf[8];
+
+static char * output_invalid PARAMS ((int));
+
+static char *
+output_invalid (c)
+ int c;
+{
+ if (isprint (c))
+ sprintf (output_invalid_buf, "'%c'", c);
+ else
+ sprintf (output_invalid_buf, "(0x%x)", (unsigned) c);
+ return output_invalid_buf;
+}
+
+/* REG_STRING starts *before* REGISTER_PREFIX. */
+
+static const reg_entry * parse_register PARAMS ((char *, char **));
+
+static const reg_entry *
+parse_register (reg_string, end_op)
+ char *reg_string;
+ char **end_op;
+{
+ register char *s = reg_string;
+ register char *p;
+ char reg_name_given[MAX_REG_NAME_SIZE + 1];
+ const reg_entry *r;
+
+ /* Skip possible REGISTER_PREFIX and possible whitespace. */
+ if (*s == REGISTER_PREFIX)
+ ++s;
+
+ if (is_space_char (*s))
+ ++s;
+
+ p = reg_name_given;
+ while ((*p++ = register_chars[(unsigned char) *s++]) != '\0')
+ {
+ if (p >= reg_name_given + MAX_REG_NAME_SIZE)
+ {
+ if (!allow_naked_reg)
+ {
+ *p = '\0';
+ as_bad (_("bad register name `%s'"), reg_name_given);
+ }
+ return (const reg_entry *) NULL;
+ }
+ }
+
+ *end_op = s - 1;
+
+ r = (const reg_entry *) hash_find (reg_hash, reg_name_given);
+
+ if (r == NULL)
+ {
+ if (!allow_naked_reg)
+ as_bad (_("bad register name `%s'"), reg_name_given);
+ return (const reg_entry *) NULL;
+ }
+
+ return r;
+}
+
+#ifdef OBJ_ELF
+CONST char *md_shortopts = "kmVQ:";
+#else
+CONST char *md_shortopts = "m";
+#endif
+struct option md_longopts[] = {
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof (md_longopts);
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ switch (c)
+ {
+ case 'm':
+ flag_do_long_jump = 1;
+ break;
+
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+ /* -k: Ignore for FreeBSD compatibility. */
+ case 'k':
+ break;
+
+ /* -V: SVR4 argument to print version ID. */
+ case 'V':
+ print_version_id ();
+ break;
+
+ /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section
+ should be emitted or not. FIXME: Not implemented. */
+ case 'Q':
+ break;
+#endif
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+ fprintf (stream, _("\
+-m do long jump\n"));
+}
+
+#ifdef BFD_ASSEMBLER
+#ifdef OBJ_MAYBE_ELF
+#ifdef OBJ_MAYBE_COFF
+
+/* Pick the target format to use. */
+
+const char *
+i386_target_format ()
+{
+ switch (OUTPUT_FLAVOR)
+ {
+ case bfd_target_coff_flavour:
+ return "coff-i386";
+ case bfd_target_elf_flavour:
+ return "elf32-i386";
+ default:
+ abort ();
+ return NULL;
+ }
+}
+
+#endif /* OBJ_MAYBE_COFF */
+#endif /* OBJ_MAYBE_ELF */
+#endif /* BFD_ASSEMBLER */
+
+/* ARGSUSED */
+symbolS *
+md_undefined_symbol (name)
+ char *name;
+{
+ if (*name == '_' && *(name+1) == 'G'
+ && strcmp(name, GLOBAL_OFFSET_TABLE_NAME) == 0)
+ {
+ if (!GOT_symbol)
+ {
+ if (symbol_find (name))
+ as_bad (_("GOT already in symbol table"));
+ GOT_symbol = symbol_new (name, undefined_section,
+ (valueT) 0, &zero_address_frag);
+ };
+ return GOT_symbol;
+ }
+ return 0;
+}
+
+/* Round up a section size to the appropriate boundary. */
+valueT
+md_section_align (segment, size)
+ segT segment;
+ valueT size;
+{
+#ifdef OBJ_AOUT
+#ifdef BFD_ASSEMBLER
+ /* For a.out, force the section size to be aligned. If we don't do
+ this, BFD will align it for us, but it will not write out the
+ final bytes of the section. This may be a bug in BFD, but it is
+ easier to fix it here since that is how the other a.out targets
+ work. */
+ int align;
+
+ align = bfd_get_section_alignment (stdoutput, segment);
+ size = ((size + (1 << align) - 1) & ((valueT) -1 << align));
+#endif
+#endif
+
+ return size;
+}
+
+/* On the i386, PC-relative offsets are relative to the start of the
+ next instruction. That is, the address of the offset, plus its
+ size, since the offset is always the last part of the insn. */
+
+long
+md_pcrel_from (fixP)
+ fixS *fixP;
+{
+ return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
+}
+
+#ifndef I386COFF
+
+static void
+s_bss (ignore)
+ int ignore;
+{
+ register int temp;
+
+ temp = get_absolute_expression ();
+ subseg_set (bss_section, (subsegT) temp);
+ demand_empty_rest_of_line ();
+}
+
+#endif
+
+
+#ifdef BFD_ASSEMBLER
+
+void
+i386_validate_fix (fixp)
+ fixS *fixp;
+{
+ if (fixp->fx_subsy && fixp->fx_subsy == GOT_symbol)
+ {
+ fixp->fx_r_type = BFD_RELOC_386_GOTOFF;
+ fixp->fx_subsy = 0;
+ }
+}
+
+#define F(SZ,PCREL) (((SZ) << 1) + (PCREL))
+#define MAP(SZ,PCREL,TYPE) case F(SZ,PCREL): code = (TYPE); break
+
+arelent *
+tc_gen_reloc (section, fixp)
+ asection *section;
+ fixS *fixp;
+{
+ arelent *rel;
+ bfd_reloc_code_real_type code;
+
+ switch (fixp->fx_r_type)
+ {
+ case BFD_RELOC_386_PLT32:
+ case BFD_RELOC_386_GOT32:
+ case BFD_RELOC_386_GOTOFF:
+ case BFD_RELOC_386_GOTPC:
+ case BFD_RELOC_RVA:
+ case BFD_RELOC_VTABLE_ENTRY:
+ case BFD_RELOC_VTABLE_INHERIT:
+ code = fixp->fx_r_type;
+ break;
+ default:
+ switch (F (fixp->fx_size, fixp->fx_pcrel))
+ {
+ MAP (1, 0, BFD_RELOC_8);
+ MAP (2, 0, BFD_RELOC_16);
+ MAP (4, 0, BFD_RELOC_32);
+ MAP (1, 1, BFD_RELOC_8_PCREL);
+ MAP (2, 1, BFD_RELOC_16_PCREL);
+ MAP (4, 1, BFD_RELOC_32_PCREL);
+ default:
+ if (fixp->fx_pcrel)
+ as_bad (_("Can not do %d byte pc-relative relocation"),
+ fixp->fx_size);
+ else
+ as_bad (_("Can not do %d byte relocation"), fixp->fx_size);
+ code = BFD_RELOC_32;
+ break;
+ }
+ break;
+ }
+#undef MAP
+#undef F
+
+ if (code == BFD_RELOC_32
+ && GOT_symbol
+ && fixp->fx_addsy == GOT_symbol)
+ code = BFD_RELOC_386_GOTPC;
+
+ rel = (arelent *) xmalloc (sizeof (arelent));
+ rel->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+
+ rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
+ /* HACK: Since i386 ELF uses Rel instead of Rela, encode the
+ vtable entry to be used in the relocation's section offset. */
+ if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ rel->address = fixp->fx_offset;
+
+ if (fixp->fx_pcrel)
+ rel->addend = fixp->fx_addnumber;
+ else
+ rel->addend = 0;
+
+ rel->howto = bfd_reloc_type_lookup (stdoutput, code);
+ if (rel->howto == NULL)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("Cannot represent relocation type %s"),
+ bfd_get_reloc_code_name (code));
+ /* Set howto to a garbage value so that we can keep going. */
+ rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
+ assert (rel->howto != NULL);
+ }
+
+ return rel;
+}
+
+#else /* ! BFD_ASSEMBLER */
+
+#if (defined(OBJ_AOUT) | defined(OBJ_BOUT))
+void
+tc_aout_fix_to_chars (where, fixP, segment_address_in_file)
+ char *where;
+ fixS *fixP;
+ relax_addressT segment_address_in_file;
+{
+ /*
+ * In: length of relocation (or of address) in chars: 1, 2 or 4.
+ * Out: GNU LD relocation length code: 0, 1, or 2.
+ */
+
+ static const unsigned char nbytes_r_length[] = {42, 0, 1, 42, 2};
+ long r_symbolnum;
+
+ know (fixP->fx_addsy != NULL);
+
+ md_number_to_chars (where,
+ (valueT) (fixP->fx_frag->fr_address
+ + fixP->fx_where - segment_address_in_file),
+ 4);
+
+ r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy)
+ ? S_GET_TYPE (fixP->fx_addsy)
+ : fixP->fx_addsy->sy_number);
+
+ where[6] = (r_symbolnum >> 16) & 0x0ff;
+ where[5] = (r_symbolnum >> 8) & 0x0ff;
+ where[4] = r_symbolnum & 0x0ff;
+ where[7] = ((((!S_IS_DEFINED (fixP->fx_addsy)) << 3) & 0x08)
+ | ((nbytes_r_length[fixP->fx_size] << 1) & 0x06)
+ | (((fixP->fx_pcrel << 0) & 0x01) & 0x0f));
+}
+
+#endif /* OBJ_AOUT or OBJ_BOUT */
+
+#if defined (I386COFF)
+
+short
+tc_coff_fix2rtype (fixP)
+ fixS *fixP;
+{
+ if (fixP->fx_r_type == R_IMAGEBASE)
+ return R_IMAGEBASE;
+
+ return (fixP->fx_pcrel ?
+ (fixP->fx_size == 1 ? R_PCRBYTE :
+ fixP->fx_size == 2 ? R_PCRWORD :
+ R_PCRLONG) :
+ (fixP->fx_size == 1 ? R_RELBYTE :
+ fixP->fx_size == 2 ? R_RELWORD :
+ R_DIR32));
+}
+
+int
+tc_coff_sizemachdep (frag)
+ fragS *frag;
+{
+ if (frag->fr_next)
+ return (frag->fr_next->fr_address - frag->fr_address);
+ else
+ return 0;
+}
+
+#endif /* I386COFF */
+
+#endif /* BFD_ASSEMBLER? */
+
+/* end of tc-i386.c */
diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h
new file mode 100644
index 0000000000..d876d61b6f
--- /dev/null
+++ b/gas/config/tc-i386.h
@@ -0,0 +1,471 @@
+/* tc-i386.h -- Header file for tc-i386.c
+ Copyright (C) 1989, 92, 93, 94, 95, 96, 97, 1998 Free Software Foundation.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#ifndef TC_I386
+#define TC_I386 1
+
+#ifdef ANSI_PROTOTYPES
+struct fix;
+#endif
+
+#define TARGET_BYTES_BIG_ENDIAN 0
+
+#ifdef TE_LYNX
+#define TARGET_FORMAT "coff-i386-lynx"
+#endif
+
+#ifdef BFD_ASSEMBLER
+/* This is used to determine relocation types in tc-i386.c. The first
+ parameter is the current relocation type, the second one is the desired
+ type. The idea is that if the original type is already some kind of PIC
+ relocation, we leave it alone, otherwise we give it the desired type */
+
+#define TC_RELOC(X,Y) (((X) != BFD_RELOC_386_PLT32 && \
+ (X) != BFD_RELOC_386_GOTOFF && \
+ (X) != BFD_RELOC_386_GOT32 && \
+ (X) != BFD_RELOC_386_GOTPC) ? Y : X)
+
+#define tc_fix_adjustable(X) tc_i386_fix_adjustable(X)
+extern int tc_i386_fix_adjustable PARAMS ((struct fix *));
+
+/* This is the relocation type for direct references to GLOBAL_OFFSET_TABLE.
+ * It comes up in complicated expressions such as
+ * _GLOBAL_OFFSET_TABLE_+[.-.L284], which cannot be expressed normally with
+ * the regular expressions. The fixup specified here when used at runtime
+ * implies that we should add the address of the GOT to the specified location,
+ * and as a result we have simplified the expression into something we can use.
+ */
+#define TC_RELOC_GLOBAL_OFFSET_TABLE BFD_RELOC_386_GOTPC
+
+/* This expression evaluates to false if the relocation is for a local object
+ for which we still want to do the relocation at runtime. True if we
+ are willing to perform this relocation while building the .o file.
+ This is only used for pcrel relocations, so GOTOFF does not need to be
+ checked here. I am not sure if some of the others are ever used with
+ pcrel, but it is easier to be safe than sorry. */
+
+#define TC_RELOC_RTSYM_LOC_FIXUP(FIX) \
+ ((FIX)->fx_r_type != BFD_RELOC_386_PLT32 \
+ && (FIX)->fx_r_type != BFD_RELOC_386_GOT32 \
+ && (FIX)->fx_r_type != BFD_RELOC_386_GOTPC \
+ && ((FIX)->fx_addsy == NULL \
+ || (! S_IS_EXTERNAL ((FIX)->fx_addsy) \
+ && ! S_IS_WEAK ((FIX)->fx_addsy) \
+ && S_IS_DEFINED ((FIX)->fx_addsy) \
+ && ! S_IS_COMMON ((FIX)->fx_addsy))))
+
+#define TARGET_ARCH bfd_arch_i386
+
+#ifdef OBJ_AOUT
+#ifdef TE_NetBSD
+#define TARGET_FORMAT "a.out-i386-netbsd"
+#endif
+#ifdef TE_386BSD
+#define TARGET_FORMAT "a.out-i386-bsd"
+#endif
+#ifdef TE_LINUX
+#define TARGET_FORMAT "a.out-i386-linux"
+#endif
+#ifdef TE_Mach
+#define TARGET_FORMAT "a.out-mach3"
+#endif
+#ifdef TE_DYNIX
+#define TARGET_FORMAT "a.out-i386-dynix"
+#endif
+#ifndef TARGET_FORMAT
+#define TARGET_FORMAT "a.out-i386"
+#endif
+#endif /* OBJ_AOUT */
+
+#ifdef OBJ_ELF
+#define TARGET_FORMAT "elf32-i386"
+#endif
+
+#ifdef OBJ_MAYBE_ELF
+#ifdef OBJ_MAYBE_COFF
+extern const char *i386_target_format PARAMS ((void));
+#define TARGET_FORMAT i386_target_format ()
+#endif
+#endif
+
+#else /* ! BFD_ASSEMBLER */
+
+/* COFF STUFF */
+
+#define COFF_MAGIC I386MAGIC
+#define BFD_ARCH bfd_arch_i386
+#define COFF_FLAGS F_AR32WR
+#define TC_COUNT_RELOC(x) ((x)->fx_addsy || (x)->fx_r_type==7)
+#define TC_COFF_FIX2RTYPE(fixP) tc_coff_fix2rtype(fixP)
+extern short tc_coff_fix2rtype PARAMS ((struct fix *));
+#define TC_COFF_SIZEMACHDEP(frag) tc_coff_sizemachdep(frag)
+extern int tc_coff_sizemachdep PARAMS ((fragS *frag));
+#define SUB_SEGMENT_ALIGN(SEG) 2
+#define TC_RVA_RELOC 7
+/* Need this for PIC relocations */
+#define NEED_FX_R_TYPE
+
+
+#ifdef TE_386BSD
+/* The BSDI linker apparently rejects objects with a machine type of
+ M_386 (100). */
+#define AOUT_MACHTYPE 0
+#else
+#define AOUT_MACHTYPE 100
+#endif
+
+#undef REVERSE_SORT_RELOCS
+
+#endif /* ! BFD_ASSEMBLER */
+
+#define TC_FORCE_RELOCATION(fixp) tc_i386_force_relocation(fixp)
+extern int tc_i386_force_relocation PARAMS ((struct fix *));
+
+#ifdef BFD_ASSEMBLER
+#define NO_RELOC BFD_RELOC_NONE
+#else
+#define NO_RELOC 0
+#endif
+#define tc_coff_symbol_emit_hook(a) ; /* not used */
+
+#ifndef BFD_ASSEMBLER
+#ifndef OBJ_AOUT
+#ifndef TE_PE
+#ifndef TE_GO32
+/* Local labels starts with .L */
+#define LOCAL_LABEL(name) (name[0] == '.' \
+ && (name[1] == 'L' || name[1] == 'X' || name[1] == '.'))
+#endif
+#endif
+#endif
+#endif
+
+#define LOCAL_LABELS_FB 1
+
+#define tc_aout_pre_write_hook(x) {;} /* not used */
+#define tc_crawl_symbol_chain(a) {;} /* not used */
+#define tc_headers_hook(a) {;} /* not used */
+
+extern const char extra_symbol_chars[];
+#define tc_symbol_chars extra_symbol_chars
+
+#define MAX_OPERANDS 3 /* max operands per insn */
+#define MAX_IMMEDIATE_OPERANDS 2/* max immediates per insn (lcall, ljmp) */
+#define MAX_MEMORY_OPERANDS 2 /* max memory refs per insn (string ops) */
+
+/* Prefixes will be emitted in the order defined below.
+ WAIT_PREFIX must be the first prefix since FWAIT is really is an
+ instruction, and so must come before any prefixes. */
+#define WAIT_PREFIX 0
+#define LOCKREP_PREFIX 1
+#define ADDR_PREFIX 2
+#define DATA_PREFIX 3
+#define SEG_PREFIX 4
+#define MAX_PREFIXES 5 /* max prefixes per opcode */
+
+/* we define the syntax here (modulo base,index,scale syntax) */
+#define REGISTER_PREFIX '%'
+#define IMMEDIATE_PREFIX '$'
+#define ABSOLUTE_PREFIX '*'
+
+#define TWO_BYTE_OPCODE_ESCAPE 0x0f
+#define NOP_OPCODE (char) 0x90
+
+/* register numbers */
+#define EBP_REG_NUM 5
+#define ESP_REG_NUM 4
+
+/* modrm_byte.regmem for twobyte escape */
+#define ESCAPE_TO_TWO_BYTE_ADDRESSING ESP_REG_NUM
+/* index_base_byte.index for no index register addressing */
+#define NO_INDEX_REGISTER ESP_REG_NUM
+/* index_base_byte.base for no base register addressing */
+#define NO_BASE_REGISTER EBP_REG_NUM
+#define NO_BASE_REGISTER_16 6
+
+/* these are the instruction mnemonic suffixes. */
+#define DWORD_MNEM_SUFFIX 'l'
+#define WORD_MNEM_SUFFIX 'w'
+#define BYTE_MNEM_SUFFIX 'b'
+#define SHORT_MNEM_SUFFIX 's'
+#define LONG_MNEM_SUFFIX 'l'
+/* Intel Syntax */
+#define LONG_DOUBLE_MNEM_SUFFIX 'x'
+/* Intel Syntax */
+#define INTEL_DWORD_MNEM_SUFFIX 'd'
+
+/* modrm.mode = REGMEM_FIELD_HAS_REG when a register is in there */
+#define REGMEM_FIELD_HAS_REG 0x3/* always = 0x3 */
+#define REGMEM_FIELD_HAS_MEM (~REGMEM_FIELD_HAS_REG)
+
+#define END_OF_INSN '\0'
+
+/* Intel Syntax */
+/* Values 0-4 map onto scale factor */
+#define BYTE_PTR 0
+#define WORD_PTR 1
+#define DWORD_PTR 2
+#define QWORD_PTR 3
+#define XWORD_PTR 4
+#define SHORT 5
+#define OFFSET_FLAT 6
+#define FLAT 7
+#define NONE_FOUND 8
+/*
+ When an operand is read in it is classified by its type. This type includes
+ all the possible ways an operand can be used. Thus, '%eax' is both 'register
+ # 0' and 'The Accumulator'. In our language this is expressed by OR'ing
+ 'Reg32' (any 32 bit register) and 'Acc' (the accumulator).
+ Operands are classified so that we can match given operand types with
+ the opcode table in opcode/i386.h.
+ */
+/* register */
+#define Reg8 0x1 /* 8 bit reg */
+#define Reg16 0x2 /* 16 bit reg */
+#define Reg32 0x4 /* 32 bit reg */
+/* immediate */
+#define Imm8 0x8 /* 8 bit immediate */
+#define Imm8S 0x10 /* 8 bit immediate sign extended */
+#define Imm16 0x20 /* 16 bit immediate */
+#define Imm32 0x40 /* 32 bit immediate */
+#define Imm1 0x80 /* 1 bit immediate */
+/* memory */
+#define BaseIndex 0x100
+/* Disp8,16,32 are used in different ways, depending on the
+ instruction. For jumps, they specify the size of the PC relative
+ displacement, for baseindex type instructions, they specify the
+ size of the offset relative to the base register, and for memory
+ offset instructions such as `mov 1234,%al' they specify the size of
+ the offset relative to the segment base. */
+#define Disp8 0x200 /* 8 bit displacement */
+#define Disp16 0x400 /* 16 bit displacement */
+#define Disp32 0x800 /* 32 bit displacement */
+/* specials */
+#define InOutPortReg 0x1000 /* register to hold in/out port addr = dx */
+#define ShiftCount 0x2000 /* register to hold shift cound = cl */
+#define Control 0x4000 /* Control register */
+#define Debug 0x8000 /* Debug register */
+#define Test 0x10000 /* Test register */
+#define FloatReg 0x20000 /* Float register */
+#define FloatAcc 0x40000 /* Float stack top %st(0) */
+#define SReg2 0x80000 /* 2 bit segment register */
+#define SReg3 0x100000 /* 3 bit segment register */
+#define Acc 0x200000 /* Accumulator %al or %ax or %eax */
+#define JumpAbsolute 0x400000
+#define RegMMX 0x800000 /* MMX register */
+#define EsSeg 0x1000000 /* String insn operand with fixed es segment */
+
+#define Reg (Reg8|Reg16|Reg32) /* gen'l register */
+#define WordReg (Reg16|Reg32)
+#define ImplicitRegister (InOutPortReg|ShiftCount|Acc|FloatAcc)
+#define Imm (Imm8|Imm8S|Imm16|Imm32) /* gen'l immediate */
+#define Disp (Disp8|Disp16|Disp32) /* General displacement */
+#define AnyMem (Disp|BaseIndex) /* General memory */
+/* The following aliases are defined because the opcode table
+ carefully specifies the allowed memory types for each instruction.
+ At the moment we can only tell a memory reference size by the
+ instruction suffix, so there's not much point in defining Mem8,
+ Mem16, Mem32 and Mem64 opcode modifiers - We might as well just use
+ the suffix directly to check memory operands. */
+#define LLongMem AnyMem /* 64 bits (or more) */
+#define LongMem AnyMem /* 32 bit memory ref */
+#define ShortMem AnyMem /* 16 bit memory ref */
+#define WordMem AnyMem /* 16 or 32 bit memory ref */
+#define ByteMem AnyMem /* 8 bit memory ref */
+
+#define SMALLEST_DISP_TYPE(num) \
+ (fits_in_signed_byte(num) ? (Disp8|Disp32) : Disp32)
+
+typedef struct
+{
+ /* instruction name sans width suffix ("mov" for movl insns) */
+ char *name;
+
+ /* how many operands */
+ unsigned int operands;
+
+ /* base_opcode is the fundamental opcode byte without optional
+ prefix(es). */
+ unsigned int base_opcode;
+
+ /* extension_opcode is the 3 bit extension for group <n> insns.
+ This field is also used to store the 8-bit opcode suffix for the
+ AMD 3DNow! instructions.
+ If this template has no extension opcode (the usual case) use None */
+ unsigned int extension_opcode;
+#define None 0xffff /* If no extension_opcode is possible. */
+
+ /* the bits in opcode_modifier are used to generate the final opcode from
+ the base_opcode. These bits also are used to detect alternate forms of
+ the same instruction */
+ unsigned int opcode_modifier;
+
+ /* opcode_modifier bits: */
+#define W 0x1 /* set if operands can be words or dwords
+ encoded the canonical way */
+#define D 0x2 /* D = 0 if Reg --> Regmem;
+ D = 1 if Regmem --> Reg: MUST BE 0x2 */
+#define Modrm 0x4
+#define ReverseRegRegmem 0x8 /* swap reg,regmem fields for 2 reg case */
+#define FloatR 0x8 /* src/dest swap for floats: MUST BE 0x8 */
+#define ShortForm 0x10 /* register is in low 3 bits of opcode */
+#define FloatMF 0x20 /* FP insn memory format bit, sized by 0x4 */
+#define Jump 0x40 /* special case for jump insns. */
+#define JumpDword 0x80 /* call and jump */
+#define JumpByte 0x100 /* loop and jecxz */
+#define JumpInterSegment 0x200 /* special case for intersegment leaps/calls */
+#define FloatD 0x400 /* direction for float insns: MUST BE 0x400 */
+#define Seg2ShortForm 0x800 /* encoding of load segment reg insns */
+#define Seg3ShortForm 0x1000 /* fs/gs segment register insns. */
+#define Size16 0x2000 /* needs size prefix if in 32-bit mode */
+#define Size32 0x4000 /* needs size prefix if in 16-bit mode */
+#define IgnoreSize 0x8000 /* instruction ignores operand size prefix */
+#define No_bSuf 0x10000 /* b suffix on instruction illegal */
+#define No_wSuf 0x20000 /* w suffix on instruction illegal */
+#define No_lSuf 0x40000 /* l suffix on instruction illegal */
+#define No_sSuf 0x80000 /* s suffix on instruction illegal */
+#define FWait 0x100000 /* instruction needs FWAIT */
+#define IsString 0x200000 /* quick test for string instructions */
+#define regKludge 0x400000 /* fake an extra reg operand for clr, imul */
+#define IsPrefix 0x800000 /* opcode is a prefix */
+#define No_dSuf 0x1000000 /* d suffix on instruction illegal */
+#define No_xSuf 0x2000000 /* x suffix on instruction illegal */
+#define Ugh 0x80000000 /* deprecated fp insn, gets a warning */
+
+ /* operand_types[i] describes the type of operand i. This is made
+ by OR'ing together all of the possible type masks. (e.g.
+ 'operand_types[i] = Reg|Imm' specifies that operand i can be
+ either a register or an immediate operand */
+ unsigned int operand_types[3];
+}
+template;
+
+/*
+ 'templates' is for grouping together 'template' structures for opcodes
+ of the same name. This is only used for storing the insns in the grand
+ ole hash table of insns.
+ The templates themselves start at START and range up to (but not including)
+ END.
+ */
+typedef struct
+ {
+ const template *start;
+ const template *end;
+ } templates;
+
+/* these are for register name --> number & type hash lookup */
+typedef struct
+ {
+ char *reg_name;
+ unsigned int reg_type;
+ unsigned int reg_num;
+ }
+reg_entry;
+
+typedef struct
+ {
+ char *seg_name;
+ unsigned int seg_prefix;
+ }
+seg_entry;
+
+/* 386 operand encoding bytes: see 386 book for details of this. */
+typedef struct
+ {
+ unsigned int regmem; /* codes register or memory operand */
+ unsigned int reg; /* codes register operand (or extended opcode) */
+ unsigned int mode; /* how to interpret regmem & reg */
+ }
+modrm_byte;
+
+/* 386 opcode byte to code indirect addressing. */
+typedef struct
+ {
+ unsigned base;
+ unsigned index;
+ unsigned scale;
+ }
+sib_byte;
+
+/* The name of the global offset table generated by the compiler. Allow
+ this to be overridden if need be. */
+#ifndef GLOBAL_OFFSET_TABLE_NAME
+#define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_"
+#endif
+
+#ifdef BFD_ASSEMBLER
+void i386_validate_fix PARAMS ((struct fix *));
+#define TC_VALIDATE_FIX(FIXP,SEGTYPE,SKIP) i386_validate_fix(FIXP)
+#endif
+
+#endif /* TC_I386 */
+
+#define md_operand(x)
+
+extern const struct relax_type md_relax_table[];
+#define TC_GENERIC_RELAX_TABLE md_relax_table
+
+
+extern int flag_16bit_code;
+
+#ifdef BFD_ASSEMBLER
+#define md_maybe_text() \
+ ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
+#else
+#define md_maybe_text() \
+ (now_seg != data_section && now_seg != bss_section)
+#endif
+
+#define md_do_align(n, fill, len, max, around) \
+if ((n) && !need_pass_2 \
+ && (!(fill) || ((char)*(fill) == (char)0x90 && (len) == 1)) \
+ && md_maybe_text ()) \
+ { \
+ char *p; \
+ p = frag_var (rs_align_code, 15, 1, (relax_substateT) max, \
+ (symbolS *) 0, (offsetT) (n), (char *) 0); \
+ *p = 0x90; \
+ goto around; \
+ }
+
+extern void i386_align_code PARAMS ((fragS *, int));
+
+#define HANDLE_ALIGN(fragP) \
+if (fragP->fr_type == rs_align_code) \
+ i386_align_code (fragP, (fragP->fr_next->fr_address \
+ - fragP->fr_address \
+ - fragP->fr_fix));
+
+/* call md_apply_fix3 with segment instead of md_apply_fix */
+#define MD_APPLY_FIX3
+
+void i386_print_statistics PARAMS ((FILE *));
+#define tc_print_statistics i386_print_statistics
+
+#define md_number_to_chars number_to_chars_littleendian
+
+#ifdef SCO_ELF
+#define tc_init_after_args() sco_id ()
+extern void sco_id PARAMS ((void));
+#endif
+
+#define DIFF_EXPR_OK /* foo-. gets turned into PC relative relocs */
+
+/* end of tc-i386.h */
diff --git a/gas/config/tc-i860.c b/gas/config/tc-i860.c
new file mode 100644
index 0000000000..f2e2b19272
--- /dev/null
+++ b/gas/config/tc-i860.c
@@ -0,0 +1,1263 @@
+/* tc-i860.c -- Assemble for the I860
+ Copyright (C) 1989, 92, 93, 94, 95, 1998 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License along
+ with GAS; see the file COPYING. If not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "as.h"
+
+#include "opcode/i860.h"
+
+void md_begin ();
+void md_number_to_chars ();
+void md_assemble ();
+char *md_atof ();
+void md_convert_frag ();
+int md_estimate_size_before_relax ();
+void md_number_to_imm ();
+void md_number_to_disp ();
+void md_number_to_field ();
+void md_ri_to_chars ();
+static void i860_ip ();
+/* void emit_machine_reloc(); */
+
+const int md_reloc_size = sizeof (struct relocation_info);
+
+/* void (*md_emit_relocations)() = emit_machine_reloc; */
+
+/* handle of the OPCODE hash table */
+static struct hash_control *op_hash = NULL;
+
+static void s_dual (), s_enddual ();
+static void s_atmp ();
+
+const pseudo_typeS
+ md_pseudo_table[] =
+{
+ {"dual", s_dual, 4},
+ {"enddual", s_enddual, 4},
+ {"atmp", s_atmp, 4},
+ {NULL, 0, 0},
+};
+
+/* This array holds the chars that always start a comment. If the
+ pre-processor is disabled, these aren't very useful */
+const char comment_chars[] = "!/"; /* JF removed '|' from comment_chars */
+
+/* This array holds the chars that only start a comment at the beginning of
+ a line. If the line seems to have the form '# 123 filename'
+ .line and .file directives will appear in the pre-processed output */
+/* Note that input_file.c hand checks for '#' at the beginning of the
+ first line of the input file. This is because the compiler outputs
+ #NO_APP at the beginning of its output. */
+/* Also note that comments like this one will always work. */
+const char line_comment_chars[] = "#/";
+
+const char line_separator_chars[] = "";
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* As in 0f12.456 */
+/* or 0d1.2345e12 */
+const char FLT_CHARS[] = "rRsSfFdDxXpP";
+
+/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
+ changed in read.c . Ideally it shouldn't have to know about it at all,
+ but nothing is ideal around here.
+ */
+int size_reloc_info = sizeof (struct relocation_info);
+
+static unsigned char octal[256];
+#define isoctal(c) octal[c]
+static unsigned char toHex[256];
+
+struct i860_it
+ {
+ char *error;
+ unsigned long opcode;
+ struct nlist *nlistp;
+ expressionS exp;
+ int pcrel;
+ enum expand_type expand;
+ enum highlow_type highlow;
+ enum reloc_type reloc;
+ } the_insn;
+
+#if __STDC__ == 1
+
+static void print_insn (struct i860_it *insn);
+static int getExpression (char *str);
+
+#else /* not __STDC__ */
+
+static void print_insn ();
+static int getExpression ();
+
+#endif /* not __STDC__ */
+
+static char *expr_end;
+static char last_expand; /* error if expansion after branch */
+
+enum dual
+{
+ DUAL_OFF = 0, DUAL_ON, DUAL_DDOT, DUAL_ONDDOT,
+};
+static enum dual dual_mode = DUAL_OFF; /* dual-instruction mode */
+
+static void
+s_dual () /* floating point instructions have dual set */
+{
+ dual_mode = DUAL_ON;
+}
+
+static void
+s_enddual () /* floating point instructions have dual set */
+{
+ dual_mode = DUAL_OFF;
+}
+
+static int atmp = 31; /* temporary register for pseudo's */
+
+static void
+s_atmp ()
+{
+ register int temp;
+ if (strncmp (input_line_pointer, "sp", 2) == 0)
+ {
+ input_line_pointer += 2;
+ atmp = 2;
+ }
+ else if (strncmp (input_line_pointer, "fp", 2) == 0)
+ {
+ input_line_pointer += 2;
+ atmp = 3;
+ }
+ else if (strncmp (input_line_pointer, "r", 1) == 0)
+ {
+ input_line_pointer += 1;
+ temp = get_absolute_expression ();
+ if (temp >= 0 && temp <= 31)
+ atmp = temp;
+ else
+ as_bad (_("Unknown temporary pseudo register"));
+ }
+ else
+ {
+ as_bad (_("Unknown temporary pseudo register"));
+ }
+ demand_empty_rest_of_line ();
+}
+
+/* This function is called once, at assembler startup time. It should
+ set up all the tables, etc. that the MD part of the assembler will need. */
+void
+md_begin ()
+{
+ register char *retval = NULL;
+ int lose = 0;
+ register unsigned int i = 0;
+
+ op_hash = hash_new ();
+
+ while (i < NUMOPCODES)
+ {
+ const char *name = i860_opcodes[i].name;
+ retval = hash_insert (op_hash, name, &i860_opcodes[i]);
+ if (retval != NULL)
+ {
+ fprintf (stderr, _("internal error: can't hash `%s': %s\n"),
+ i860_opcodes[i].name, retval);
+ lose = 1;
+ }
+ do
+ {
+ if (i860_opcodes[i].match & i860_opcodes[i].lose)
+ {
+ fprintf (stderr, _("internal error: losing opcode: `%s' \"%s\"\n"),
+ i860_opcodes[i].name, i860_opcodes[i].args);
+ lose = 1;
+ }
+ ++i;
+ }
+ while (i < NUMOPCODES
+ && !strcmp (i860_opcodes[i].name, name));
+ }
+
+ if (lose)
+ as_fatal (_("Broken assembler. No assembly attempted."));
+
+ for (i = '0'; i < '8'; ++i)
+ octal[i] = 1;
+ for (i = '0'; i <= '9'; ++i)
+ toHex[i] = i - '0';
+ for (i = 'a'; i <= 'f'; ++i)
+ toHex[i] = i + 10 - 'a';
+ for (i = 'A'; i <= 'F'; ++i)
+ toHex[i] = i + 10 - 'A';
+}
+
+void
+md_assemble (str)
+ char *str;
+{
+ char *toP;
+ int rsd;
+ int no_opcodes = 1;
+ int i;
+ struct i860_it pseudo[3];
+
+ assert (str);
+ i860_ip (str);
+
+ /* check for expandable flag to produce pseudo-instructions */
+ if (the_insn.expand != 0 && the_insn.highlow == NO_SPEC)
+ {
+ for (i = 0; i < 3; i++)
+ pseudo[i] = the_insn;
+
+ switch (the_insn.expand)
+ {
+
+ case E_DELAY:
+ no_opcodes = 1;
+ break;
+
+ case E_MOV:
+ if (the_insn.exp.X_add_symbol == NULL &&
+ the_insn.exp.X_op_symbol == NULL &&
+ (the_insn.exp.X_add_number < (1 << 15) &&
+ the_insn.exp.X_add_number >= -(1 << 15)))
+ break;
+ /* or l%const,r0,ireg_dest */
+ pseudo[0].opcode = (the_insn.opcode & 0x001f0000) | 0xe4000000;
+ pseudo[0].highlow = PAIR;
+ /* orh h%const,ireg_dest,ireg_dest */
+ pseudo[1].opcode = (the_insn.opcode & 0x03ffffff) | 0xec000000 |
+ ((the_insn.opcode & 0x001f0000) << 5);
+ pseudo[1].highlow = HIGH;
+ no_opcodes = 2;
+ break;
+
+ case E_ADDR:
+ if (the_insn.exp.X_add_symbol == NULL &&
+ the_insn.exp.X_op_symbol == NULL)
+ break;
+ /* orh ha%addr_expr,r0,r31 */
+ pseudo[0].opcode = 0xec000000 | (atmp << 16);
+ pseudo[0].highlow = HIGHADJ;
+ pseudo[0].reloc = LOW0; /* must overwrite */
+ /* l%addr_expr(r31),ireg_dest */
+ pseudo[1].opcode = (the_insn.opcode & ~0x003e0000) | (atmp << 21);
+ pseudo[1].highlow = PAIR;
+ no_opcodes = 2;
+ break;
+
+ case E_U32: /* 2nd version emulates Intel as, not doc. */
+ if (the_insn.exp.X_add_symbol == NULL &&
+ the_insn.exp.X_op_symbol == NULL &&
+ (the_insn.exp.X_add_number < (1 << 16) &&
+ the_insn.exp.X_add_number >= 0))
+ break;
+ /* $(opcode)h h%const,ireg_src2,ireg_dest
+ pseudo[0].opcode = (the_insn.opcode & 0xf3ffffff) | 0x0c000000; */
+ /* $(opcode)h h%const,ireg_src2,r31 */
+ pseudo[0].opcode = (the_insn.opcode & 0xf3e0ffff) | 0x0c000000 |
+ (atmp << 16);
+ pseudo[0].highlow = HIGH;
+ /* $(opcode) l%const,ireg_dest,ireg_dest
+ pseudo[1].opcode = (the_insn.opcode & 0xf01f0000) | 0x04000000 |
+ ((the_insn.opcode & 0x001f0000) << 5); */
+ /* $(opcode) l%const,r31,ireg_dest */
+ pseudo[1].opcode = (the_insn.opcode & 0xf01f0000) | 0x04000000 |
+ (atmp << 21);
+ pseudo[1].highlow = PAIR;
+ no_opcodes = 2;
+ break;
+
+ case E_AND: /* 2nd version emulates Intel as, not doc. */
+ if (the_insn.exp.X_add_symbol == NULL &&
+ the_insn.exp.X_op_symbol == NULL &&
+ (the_insn.exp.X_add_number < (1 << 16) &&
+ the_insn.exp.X_add_number >= 0))
+ break;
+ /* andnot h%const,ireg_src2,ireg_dest
+ pseudo[0].opcode = (the_insn.opcode & 0x03ffffff) | 0xd4000000; */
+ /* andnot h%const,ireg_src2,r31 */
+ pseudo[0].opcode = (the_insn.opcode & 0x03e0ffff) | 0xd4000000 |
+ (atmp << 16);
+ pseudo[0].highlow = HIGH;
+ pseudo[0].exp.X_add_number = -1 - the_insn.exp.X_add_number;
+ /* andnot l%const,ireg_dest,ireg_dest
+ pseudo[1].opcode = (the_insn.opcode & 0x001f0000) | 0xd4000000 |
+ ((the_insn.opcode & 0x001f0000) << 5); */
+ /* andnot l%const,r31,ireg_dest */
+ pseudo[1].opcode = (the_insn.opcode & 0x001f0000) | 0xd4000000 |
+ (atmp << 21);
+ pseudo[1].highlow = PAIR;
+ pseudo[1].exp.X_add_number = -1 - the_insn.exp.X_add_number;
+ no_opcodes = 2;
+ break;
+
+ case E_S32:
+ if (the_insn.exp.X_add_symbol == NULL &&
+ the_insn.exp.X_op_symbol == NULL &&
+ (the_insn.exp.X_add_number < (1 << 15) &&
+ the_insn.exp.X_add_number >= -(1 << 15)))
+ break;
+ /* orh h%const,r0,r31 */
+ pseudo[0].opcode = 0xec000000 | (atmp << 16);
+ pseudo[0].highlow = HIGH;
+ /* or l%const,r31,r31 */
+ pseudo[1].opcode = 0xe4000000 | (atmp << 21) | (atmp << 16);
+ pseudo[1].highlow = PAIR;
+ /* r31,ireg_src2,ireg_dest */
+ pseudo[2].opcode = (the_insn.opcode & ~0x0400ffff) | (atmp << 11);
+ pseudo[2].reloc = NO_RELOC;
+ no_opcodes = 3;
+ break;
+
+ default:
+ as_fatal (_("failed sanity check."));
+ }
+
+ the_insn = pseudo[0];
+ /* check for expanded opcode after branch or in dual */
+ if (no_opcodes > 1 && last_expand == 1)
+ as_warn (_("Expanded opcode after delayed branch: `%s'"), str);
+ if (no_opcodes > 1 && dual_mode != DUAL_OFF)
+ as_warn (_("Expanded opcode in dual mode: `%s'"), str);
+ }
+
+ i = 0;
+ do
+ { /* always produce at least one opcode */
+ toP = frag_more (4);
+ /* put out the opcode */
+ md_number_to_chars (toP, the_insn.opcode, 4);
+
+ /* check for expanded opcode after branch or in dual */
+ last_expand = the_insn.pcrel;
+
+ /* put out the symbol-dependent stuff */
+ if (the_insn.reloc != NO_RELOC)
+ {
+ fix_new (frag_now, /* which frag */
+ (toP - frag_now->fr_literal), /* where */
+ 4, /* size */
+ &the_insn.exp,
+ the_insn.pcrel,
+ /* merge bit fields into one argument */
+ (int) (((the_insn.highlow & 0x3) << 4) | (the_insn.reloc & 0xf)));
+ }
+ the_insn = pseudo[++i];
+ }
+ while (--no_opcodes > 0);
+
+}
+
+static void
+i860_ip (str)
+ char *str;
+{
+ char *s;
+ const char *args;
+ char c;
+ unsigned long i;
+ struct i860_opcode *insn;
+ char *argsStart;
+ unsigned long opcode;
+ unsigned int mask;
+ int match = 0;
+ int comma = 0;
+
+
+ for (s = str; islower (*s) || *s == '.' || *s == '3'; ++s)
+ ;
+ switch (*s)
+ {
+
+ case '\0':
+ break;
+
+ case ',':
+ comma = 1;
+
+ /*FALLTHROUGH*/
+
+ case ' ':
+ *s++ = '\0';
+ break;
+
+ default:
+ as_fatal (_("Unknown opcode: `%s'"), str);
+ }
+
+ if (strncmp (str, "d.", 2) == 0)
+ { /* check for d. opcode prefix */
+ if (dual_mode == DUAL_ON)
+ dual_mode = DUAL_ONDDOT;
+ else
+ dual_mode = DUAL_DDOT;
+ str += 2;
+ }
+
+ if ((insn = (struct i860_opcode *) hash_find (op_hash, str)) == NULL)
+ {
+ if (dual_mode == DUAL_DDOT || dual_mode == DUAL_ONDDOT)
+ str -= 2;
+ as_bad (_("Unknown opcode: `%s'"), str);
+ return;
+ }
+ if (comma)
+ {
+ *--s = ',';
+ }
+ argsStart = s;
+ for (;;)
+ {
+ opcode = insn->match;
+ memset (&the_insn, '\0', sizeof (the_insn));
+ the_insn.reloc = NO_RELOC;
+
+ /*
+ * Build the opcode, checking as we go to make
+ * sure that the operands match
+ */
+ for (args = insn->args;; ++args)
+ {
+ switch (*args)
+ {
+
+ case '\0': /* end of args */
+ if (*s == '\0')
+ {
+ match = 1;
+ }
+ break;
+
+ case '+':
+ case '(': /* these must match exactly */
+ case ')':
+ case ',':
+ case ' ':
+ if (*s++ == *args)
+ continue;
+ break;
+
+ case '#': /* must be at least one digit */
+ if (isdigit (*s++))
+ {
+ while (isdigit (*s))
+ {
+ ++s;
+ }
+ continue;
+ }
+ break;
+
+ case '1': /* next operand must be a register */
+ case '2':
+ case 'd':
+ switch (*s)
+ {
+
+ case 'f': /* frame pointer */
+ s++;
+ if (*s++ == 'p')
+ {
+ mask = 0x3;
+ break;
+ }
+ goto error;
+
+ case 's': /* stack pointer */
+ s++;
+ if (*s++ == 'p')
+ {
+ mask = 0x2;
+ break;
+ }
+ goto error;
+
+ case 'r': /* any register */
+ s++;
+ if (!isdigit (c = *s++))
+ {
+ goto error;
+ }
+ if (isdigit (*s))
+ {
+ if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32)
+ {
+ goto error;
+ }
+ }
+ else
+ {
+ c -= '0';
+ }
+ mask = c;
+ break;
+
+ default: /* not this opcode */
+ goto error;
+ }
+ /*
+ * Got the register, now figure out where
+ * it goes in the opcode.
+ */
+ switch (*args)
+ {
+
+ case '1':
+ opcode |= mask << 11;
+ continue;
+
+ case '2':
+ opcode |= mask << 21;
+ continue;
+
+ case 'd':
+ opcode |= mask << 16;
+ continue;
+
+ }
+ break;
+
+ case 'e': /* next operand is a floating point register */
+ case 'f':
+ case 'g':
+ if (*s++ == 'f' && isdigit (*s))
+ {
+ mask = *s++;
+ if (isdigit (*s))
+ {
+ mask = 10 * (mask - '0') + (*s++ - '0');
+ if (mask >= 32)
+ {
+ break;
+ }
+ }
+ else
+ {
+ mask -= '0';
+ }
+ switch (*args)
+ {
+
+ case 'e':
+ opcode |= mask << 11;
+ continue;
+
+ case 'f':
+ opcode |= mask << 21;
+ continue;
+
+ case 'g':
+ opcode |= mask << 16;
+ if (dual_mode != DUAL_OFF)
+ opcode |= (1 << 9); /* dual mode instruction */
+ if (dual_mode == DUAL_DDOT)
+ dual_mode = DUAL_OFF;
+ if (dual_mode == DUAL_ONDDOT)
+ dual_mode = DUAL_ON;
+ if ((opcode & (1 << 10)) && (mask == ((opcode >> 11) & 0x1f)))
+ as_warn (_("Fsr1 equals fdest with Pipelining"));
+ continue;
+ }
+ }
+ break;
+
+ case 'c': /* next operand must be a control register */
+ if (strncmp (s, "fir", 3) == 0)
+ {
+ opcode |= 0x0 << 21;
+ s += 3;
+ continue;
+ }
+ if (strncmp (s, "psr", 3) == 0)
+ {
+ opcode |= 0x1 << 21;
+ s += 3;
+ continue;
+ }
+ if (strncmp (s, "dirbase", 7) == 0)
+ {
+ opcode |= 0x2 << 21;
+ s += 7;
+ continue;
+ }
+ if (strncmp (s, "db", 2) == 0)
+ {
+ opcode |= 0x3 << 21;
+ s += 2;
+ continue;
+ }
+ if (strncmp (s, "fsr", 3) == 0)
+ {
+ opcode |= 0x4 << 21;
+ s += 3;
+ continue;
+ }
+ if (strncmp (s, "epsr", 4) == 0)
+ {
+ opcode |= 0x5 << 21;
+ s += 4;
+ continue;
+ }
+ break;
+
+ case '5': /* 5 bit immediate in src1 */
+ memset (&the_insn, '\0', sizeof (the_insn));
+ if (!getExpression (s))
+ {
+ s = expr_end;
+ if (the_insn.exp.X_add_number & ~0x1f)
+ as_bad (_("5-bit immediate too large"));
+ opcode |= (the_insn.exp.X_add_number & 0x1f) << 11;
+ memset (&the_insn, '\0', sizeof (the_insn));
+ the_insn.reloc = NO_RELOC;
+ continue;
+ }
+ break;
+
+ case 'l': /* 26 bit immediate, relative branch */
+ the_insn.reloc = BRADDR;
+ the_insn.pcrel = 1;
+ goto immediate;
+
+ case 's': /* 16 bit immediate, split relative branch */
+ /* upper 5 bits of offset in dest field */
+ the_insn.pcrel = 1;
+ the_insn.reloc = SPLIT0;
+ goto immediate;
+
+ case 'S': /* 16 bit immediate, split (st), aligned */
+ if (opcode & (1 << 28))
+ if (opcode & 0x1)
+ the_insn.reloc = SPLIT2;
+ else
+ the_insn.reloc = SPLIT1;
+ else
+ the_insn.reloc = SPLIT0;
+ goto immediate;
+
+ case 'I': /* 16 bit immediate, aligned */
+ if (opcode & (1 << 28))
+ if (opcode & 0x1)
+ the_insn.reloc = LOW2;
+ else
+ the_insn.reloc = LOW1;
+ else
+ the_insn.reloc = LOW0;
+ goto immediate;
+
+ case 'i': /* 16 bit immediate */
+ the_insn.reloc = LOW0;
+
+ /*FALLTHROUGH*/
+
+ immediate:
+ if (*s == ' ')
+ s++;
+ if (strncmp (s, "ha%", 3) == 0)
+ {
+ the_insn.highlow = HIGHADJ;
+ s += 3;
+ }
+ else if (strncmp (s, "h%", 2) == 0)
+ {
+ the_insn.highlow = HIGH;
+ s += 2;
+ }
+ else if (strncmp (s, "l%", 2) == 0)
+ {
+ the_insn.highlow = PAIR;
+ s += 2;
+ }
+ the_insn.expand = insn->expand;
+
+ /* Note that if the getExpression() fails, we will still have
+ created U entries in the symbol table for the 'symbols'
+ in the input string. Try not to create U symbols for
+ registers, etc. */
+
+ if (!getExpression (s))
+ {
+ s = expr_end;
+ continue;
+ }
+ break;
+
+ default:
+ as_fatal (_("failed sanity check."));
+ }
+ break;
+ }
+ error:
+ if (match == 0)
+ {
+ /* Args don't match. */
+ if (&insn[1] - i860_opcodes < NUMOPCODES
+ && !strcmp (insn->name, insn[1].name))
+ {
+ ++insn;
+ s = argsStart;
+ continue;
+ }
+ else
+ {
+ as_bad (_("Illegal operands"));
+ return;
+ }
+ }
+ break;
+ }
+
+ the_insn.opcode = opcode;
+}
+
+static int
+getExpression (str)
+ char *str;
+{
+ char *save_in;
+ segT seg;
+
+ save_in = input_line_pointer;
+ input_line_pointer = str;
+ seg = expression (&the_insn.exp);
+ if (seg != absolute_section
+ && seg != undefined_section
+ && ! SEG_NORMAL (seg))
+ {
+ the_insn.error = _("bad segment");
+ expr_end = input_line_pointer;
+ input_line_pointer = save_in;
+ return 1;
+ }
+ expr_end = input_line_pointer;
+ input_line_pointer = save_in;
+ return 0;
+}
+
+
+/*
+ This is identical to the md_atof in m68k.c. I think this is right,
+ but I'm not sure.
+
+ Turn a string in input_line_pointer into a floating point constant of type
+ type, and store the appropriate bytes in *litP. The number of LITTLENUMS
+ emitted is stored in *sizeP . An error message is returned, or NULL on OK.
+ */
+
+/* Equal to MAX_PRECISION in atof-ieee.c */
+#define MAX_LITTLENUMS 6
+
+char *
+md_atof (type, litP, sizeP)
+ char type;
+ char *litP;
+ int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ char *t;
+ char *atof_ieee ();
+
+ switch (type)
+ {
+
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ prec = 4;
+ break;
+
+ case 'x':
+ case 'X':
+ prec = 6;
+ break;
+
+ case 'p':
+ case 'P':
+ prec = 6;
+ break;
+
+ default:
+ *sizeP = 0;
+ return _("Bad call to MD_ATOF()");
+ }
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+ *sizeP = prec * sizeof (LITTLENUM_TYPE);
+ for (wordP = words; prec--;)
+ {
+ md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+ return 0;
+}
+
+/*
+ * Write out big-endian.
+ */
+void
+md_number_to_chars (buf, val, n)
+ char *buf;
+ valueT val;
+ int n;
+{
+ number_to_chars_bigendian (buf, val, n);
+}
+
+void
+md_number_to_imm (buf, val, n, fixP)
+ char *buf;
+ long val;
+ int n;
+ fixS *fixP;
+{
+ enum reloc_type reloc = fixP->fx_r_type & 0xf;
+ enum highlow_type highlow = (fixP->fx_r_type >> 4) & 0x3;
+
+ assert (buf);
+ assert (n == 4); /* always on i860 */
+
+ switch (highlow)
+ {
+
+ case HIGHADJ: /* adjusts the high-order 16-bits */
+ if (val & (1 << 15))
+ val += (1 << 16);
+
+ /*FALLTHROUGH*/
+
+ case HIGH: /* selects the high-order 16-bits */
+ val >>= 16;
+ break;
+
+ case PAIR: /* selects the low-order 16-bits */
+ val = val & 0xffff;
+ break;
+
+ default:
+ break;
+ }
+
+ switch (reloc)
+ {
+
+ case BRADDR: /* br,call,bc,bc.t,bnc,bnc.t w/26-bit immediate */
+ if (fixP->fx_pcrel != 1)
+ as_bad (_("26-bit branch w/o pc relative set: 0x%08x"), val);
+ val >>= 2; /* align pcrel offset, see manual */
+
+ if (val >= (1 << 25) || val < -(1 << 25)) /* check for overflow */
+ as_bad (_("26-bit branch offset overflow: 0x%08x"), val);
+ buf[0] = (buf[0] & 0xfc) | ((val >> 24) & 0x3);
+ buf[1] = val >> 16;
+ buf[2] = val >> 8;
+ buf[3] = val;
+ break;
+
+ case SPLIT2: /* 16 bit immediate, 4-byte aligned */
+ if (val & 0x3)
+ as_bad (_("16-bit immediate 4-byte alignment error: 0x%08x"), val);
+ val &= ~0x3; /* 4-byte align value */
+ /*FALLTHROUGH*/
+ case SPLIT1: /* 16 bit immediate, 2-byte aligned */
+ if (val & 0x1)
+ as_bad (_("16-bit immediate 2-byte alignment error: 0x%08x"), val);
+ val &= ~0x1; /* 2-byte align value */
+ /*FALLTHROUGH*/
+ case SPLIT0: /* st,bla,bte,btne w/16-bit immediate */
+ if (fixP->fx_pcrel == 1)
+ val >>= 2; /* align pcrel offset, see manual */
+ /* check for bounds */
+ if (highlow != PAIR && (val >= (1 << 16) || val < -(1 << 15)))
+ as_bad (_("16-bit branch offset overflow: 0x%08x"), val);
+ buf[1] = (buf[1] & ~0x1f) | ((val >> 11) & 0x1f);
+ buf[2] = (buf[2] & ~0x7) | ((val >> 8) & 0x7);
+ buf[3] |= val; /* perserve bottom opcode bits */
+ break;
+
+ case LOW4: /* fld,pfld,pst,flush 16-byte aligned */
+ if (val & 0xf)
+ as_bad (_("16-bit immediate 16-byte alignment error: 0x%08x"), val);
+ val &= ~0xf; /* 16-byte align value */
+ /*FALLTHROUGH*/
+ case LOW3: /* fld,pfld,pst,flush 8-byte aligned */
+ if (val & 0x7)
+ as_bad (_("16-bit immediate 8-byte alignment error: 0x%08x"), val);
+ val &= ~0x7; /* 8-byte align value */
+ /*FALLTHROUGH*/
+ case LOW2: /* 16 bit immediate, 4-byte aligned */
+ if (val & 0x3)
+ as_bad (_("16-bit immediate 4-byte alignment error: 0x%08x"), val);
+ val &= ~0x3; /* 4-byte align value */
+ /*FALLTHROUGH*/
+ case LOW1: /* 16 bit immediate, 2-byte aligned */
+ if (val & 0x1)
+ as_bad (_("16-bit immediate 2-byte alignment error: 0x%08x"), val);
+ val &= ~0x1; /* 2-byte align value */
+ /*FALLTHROUGH*/
+ case LOW0: /* 16 bit immediate, byte aligned */
+ /* check for bounds */
+ if (highlow != PAIR && (val >= (1 << 16) || val < -(1 << 15)))
+ as_bad (_("16-bit immediate overflow: 0x%08x"), val);
+ buf[2] = val >> 8;
+ buf[3] |= val; /* perserve bottom opcode bits */
+ break;
+
+ case NO_RELOC:
+ default:
+ as_bad (_("bad relocation type: 0x%02x"), reloc);
+ break;
+ }
+}
+
+/* should never be called for i860 */
+void
+md_number_to_disp (buf, val, n)
+ char *buf;
+ long val;
+{
+ as_fatal (_("md_number_to_disp\n"));
+}
+
+/* should never be called for i860 */
+void
+md_number_to_field (buf, val, fix)
+ char *buf;
+ long val;
+ void *fix;
+{
+ as_fatal (_("i860_number_to_field\n"));
+}
+
+/* the bit-field entries in the relocation_info struct plays hell
+ with the byte-order problems of cross-assembly. So as a hack,
+ I added this mach. dependent ri twiddler. Ugly, but it gets
+ you there. -KWK */
+/* on i860: first 4 bytes are normal unsigned long address, next three
+ bytes are index, most sig. byte first. Byte 7 is broken up with
+ bit 7 as pcrel, bit 6 as extern, and the lower six bits as
+ relocation type (highlow 5-4). Next 4 bytes are long addend. */
+/* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */
+void
+md_ri_to_chars (ri_p, ri)
+ struct relocation_info *ri_p, ri;
+{
+#if 0
+ unsigned char the_bytes[sizeof (*ri_p)];
+
+ /* this is easy */
+ md_number_to_chars (the_bytes, ri.r_address, sizeof (ri.r_address));
+ /* now the fun stuff */
+ the_bytes[4] = (ri.r_index >> 16) & 0x0ff;
+ the_bytes[5] = (ri.r_index >> 8) & 0x0ff;
+ the_bytes[6] = ri.r_index & 0x0ff;
+ the_bytes[7] = ((ri.r_extern << 7) & 0x80) | (0 & 0x60) | (ri.r_type & 0x1F);
+ /* Also easy */
+ md_number_to_chars (&the_bytes[8], ri.r_addend, sizeof (ri.r_addend));
+ /* now put it back where you found it, Junior... */
+ memcpy ((char *) ri_p, the_bytes, sizeof (*ri_p));
+#endif
+}
+
+/* should never be called for i860 */
+void
+md_convert_frag (headers, seg, fragP)
+ object_headers *headers;
+ segT seg;
+ register fragS *fragP;
+{
+ as_fatal (_("i860_convert_frag\n"));
+}
+
+/* should never be called for i860 */
+int
+md_estimate_size_before_relax (fragP, segtype)
+ register fragS *fragP;
+ segT segtype;
+{
+ as_fatal (_("i860_estimate_size_before_relax\n"));
+}
+
+/* for debugging only, must match enum reloc_type */
+static char *Reloc[] =
+{
+ "NO_RELOC",
+ "BRADDR",
+ "LOW0",
+ "LOW1",
+ "LOW2",
+ "LOW3",
+ "LOW4",
+ "SPLIT0",
+ "SPLIT1",
+ "SPLIT2",
+ "RELOC_32",
+};
+static char *Highlow[] =
+{
+ "NO_SPEC",
+ "PAIR",
+ "HIGH",
+ "HIGHADJ",
+};
+static void
+print_insn (insn)
+ struct i860_it *insn;
+{
+ if (insn->error)
+ {
+ fprintf (stderr, "ERROR: %s\n");
+ }
+ fprintf (stderr, "opcode=0x%08x\t", insn->opcode);
+ fprintf (stderr, "expand=0x%08x\t", insn->expand);
+ fprintf (stderr, "reloc = %s\t", Reloc[insn->reloc]);
+ fprintf (stderr, "highlow = %s\n", Highlow[insn->highlow]);
+ fprintf (stderr, "exp = {\n");
+ fprintf (stderr, "\t\tX_add_symbol = %s\n",
+ insn->exp.X_add_symbol ?
+ (S_GET_NAME (insn->exp.X_add_symbol) ?
+ S_GET_NAME (insn->exp.X_add_symbol) : "???") : "0");
+ fprintf (stderr, "\t\tX_op_symbol = %s\n",
+ insn->exp.X_op_symbol ?
+ (S_GET_NAME (insn->exp.X_op_symbol) ?
+ S_GET_NAME (insn->exp.X_op_symbol) : "???") : "0");
+ fprintf (stderr, "\t\tX_add_number = %d\n",
+ insn->exp.X_add_number);
+ fprintf (stderr, "}\n");
+}
+
+CONST char *md_shortopts = "";
+struct option md_longopts[] = {
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof(md_longopts);
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ return 0;
+}
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+}
+
+#ifdef comment
+/*
+ * I860 relocations are completely different, so it needs
+ * this machine dependent routine to emit them.
+ */
+void
+emit_machine_reloc (fixP, segment_address_in_file)
+ register fixS *fixP;
+ relax_addressT segment_address_in_file;
+{
+ struct reloc_info_i860 ri;
+ register symbolS *symbolP;
+ extern char *next_object_file_charP;
+ long add_number;
+
+ memset ((char *) &ri, '\0', sizeof (ri));
+ for (; fixP; fixP = fixP->fx_next)
+ {
+
+ if (fixP->fx_r_type & ~0x3f)
+ {
+ as_fatal ("fixP->fx_r_type = %d\n", fixP->fx_r_type);
+ }
+ ri.r_pcrel = fixP->fx_pcrel;
+ ri.r_type = fixP->fx_r_type;
+
+ if ((symbolP = fixP->fx_addsy) != NULL)
+ {
+ ri.r_address = fixP->fx_frag->fr_address +
+ fixP->fx_where - segment_address_in_file;
+ if (!S_IS_DEFINED (symbolP))
+ {
+ ri.r_extern = 1;
+ ri.r_symbolnum = symbolP->sy_number;
+ }
+ else
+ {
+ ri.r_extern = 0;
+ ri.r_symbolnum = S_GET_TYPE (symbolP);
+ }
+ if (symbolP && symbolP->sy_frag)
+ {
+ ri.r_addend = symbolP->sy_frag->fr_address;
+ }
+ ri.r_type = fixP->fx_r_type;
+ if (fixP->fx_pcrel)
+ {
+ /* preserve actual offset vs. pc + 4 */
+ ri.r_addend -= (ri.r_address + 4);
+ }
+ else
+ {
+ ri.r_addend = fixP->fx_addnumber;
+ }
+
+ md_ri_to_chars ((char *) &ri, ri);
+ append (&next_object_file_charP, (char *) &ri, sizeof (ri));
+ }
+ }
+}
+
+#endif /* comment */
+
+#ifdef OBJ_AOUT
+
+/* on i860: first 4 bytes are normal unsigned long address, next three
+ bytes are index, most sig. byte first. Byte 7 is broken up with
+ bit 7 as pcrel, bit 6 as extern, and the lower six bits as
+ relocation type (highlow 5-4). Next 4 bytes are long addend. */
+
+void
+tc_aout_fix_to_chars (where, fixP, segment_address_in_file)
+ char *where;
+ fixS *fixP;
+ relax_addressT segment_address_in_file;
+{
+ long r_index;
+ long r_extern;
+ long r_addend = 0;
+ long r_address;
+
+ know (fixP->fx_addsy);
+ know (!(fixP->fx_r_type & ~0x3f));
+
+ if (!S_IS_DEFINED (fixP->fx_addsy))
+ {
+ r_extern = 1;
+ r_index = fixP->fx_addsy->sy_number;
+ }
+ else
+ {
+ r_extern = 0;
+ r_index = S_GET_TYPE (fixP->fx_addsy);
+ }
+
+ md_number_to_chars (where,
+ r_address = fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
+ 4);
+
+ where[4] = (r_index >> 16) & 0x0ff;
+ where[5] = (r_index >> 8) & 0x0ff;
+ where[6] = r_index & 0x0ff;
+ where[7] = (((fixP->fx_pcrel << 7) & 0x80)
+ | ((r_extern << 6) & 0x40)
+ | (fixP->fx_r_type & 0x3F));
+
+ if (fixP->fx_addsy->sy_frag)
+ {
+ r_addend = fixP->fx_addsy->sy_frag->fr_address;
+ }
+
+ if (fixP->fx_pcrel)
+ {
+ /* preserve actual offset vs. pc + 4 */
+ r_addend -= (r_address + 4);
+ }
+ else
+ {
+ r_addend = fixP->fx_addnumber;
+ }
+
+ md_number_to_chars (&where[8], r_addend, 4);
+}
+
+#endif /* OBJ_AOUT */
+
+/* We have no need to default values of symbols. */
+
+/* ARGSUSED */
+symbolS *
+md_undefined_symbol (name)
+ char *name;
+{
+ return 0;
+}
+
+/* Round up a section size to the appropriate boundary. */
+valueT
+md_section_align (segment, size)
+ segT segment;
+ valueT size;
+{
+ return size; /* Byte alignment is fine */
+}
+
+/* Exactly what point is a PC-relative offset relative TO?
+ On the i860, they're relative to the address of the offset, plus
+ its size. (??? Is this right? FIXME-SOON!) */
+long
+md_pcrel_from (fixP)
+ fixS *fixP;
+{
+ return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
+}
+
+void
+md_apply_fix (fixP, val)
+ fixS *fixP;
+ long val;
+{
+ char *place = fixP->fx_where + fixP->fx_frag->fr_literal;
+
+ /* looks to me like i860 never has bit fixes. Let's see. xoxorich. */
+ know (fixP->fx_bit_fixP == NULL);
+ if (!fixP->fx_bit_fixP)
+ {
+ fixP->fx_addnumber = val;
+ md_number_to_imm (place, val, fixP->fx_size, fixP);
+ }
+ else
+ {
+ md_number_to_field (place, val, fixP->fx_bit_fixP);
+ }
+}
+
+/*
+ * Local Variables:
+ * fill-column: 131
+ * comment-column: 0
+ * End:
+ */
+
+/* end of tc-i860.c */
diff --git a/gas/config/tc-i860.h b/gas/config/tc-i860.h
new file mode 100644
index 0000000000..afb21c1b55
--- /dev/null
+++ b/gas/config/tc-i860.h
@@ -0,0 +1,39 @@
+/* tc-i860.h -- Header file for the I860
+ Copyright (C) 1991, 92, 95, 1998 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License along
+ with GAS; see the file COPYING. If not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TC_I860 1
+
+#define TARGET_BYTES_BIG_ENDIAN 1
+
+#define WORKING_DOT_WORD
+
+#define tc_headers_hook(a) {;} /* not used */
+#define tc_crawl_symbol_chain(a) {;} /* not used */
+#define tc_aout_pre_write_hook(x) {;} /* not used */
+
+#define md_operand(x)
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of tc-i860.h */
diff --git a/gas/config/tc-i960.c b/gas/config/tc-i960.c
new file mode 100644
index 0000000000..936b662199
--- /dev/null
+++ b/gas/config/tc-i960.c
@@ -0,0 +1,3231 @@
+/* tc-i960.c - All the i80960-specific stuff
+ Copyright (C) 1989, 90, 91, 92, 93, 94, 95, 96, 97, 1998
+ Free Software Foundation, Inc.
+
+ This file is part of GAS.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* See comment on md_parse_option for 80960-specific invocation options. */
+
+/* There are 4 different lengths of (potentially) symbol-based displacements
+ in the 80960 instruction set, each of which could require address fix-ups
+ and (in the case of external symbols) emission of relocation directives:
+
+ 32-bit (MEMB)
+ This is a standard length for the base assembler and requires no
+ special action.
+
+ 13-bit (COBR)
+ This is a non-standard length, but the base assembler has a
+ hook for bit field address fixups: the fixS structure can
+ point to a descriptor of the field, in which case our
+ md_number_to_field() routine gets called to process it.
+
+ I made the hook a little cleaner by having fix_new() (in the base
+ assembler) return a pointer to the fixS in question. And I made it a
+ little simpler by storing the field size (in this case 13) instead of
+ of a pointer to another structure: 80960 displacements are ALWAYS
+ stored in the low-order bits of a 4-byte word.
+
+ Since the target of a COBR cannot be external, no relocation
+ directives for this size displacement have to be generated.
+ But the base assembler had to be modified to issue error
+ messages if the symbol did turn out to be external.
+
+ 24-bit (CTRL)
+ Fixups are handled as for the 13-bit case (except that 24 is stored
+ in the fixS).
+
+ The relocation directive generated is the same as that for the 32-bit
+ displacement, except that it's PC-relative (the 32-bit displacement
+ never is). The i80960 version of the linker needs a mod to
+ distinguish and handle the 24-bit case.
+
+ 12-bit (MEMA)
+ MEMA formats are always promoted to MEMB (32-bit) if the displacement
+ is based on a symbol, because it could be relocated at link time.
+ The only time we use the 12-bit format is if an absolute value of
+ less than 4096 is specified, in which case we need neither a fixup nor
+ a relocation directive. */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include "as.h"
+
+#include "obstack.h"
+
+#include "opcode/i960.h"
+
+#if defined (OBJ_AOUT) || defined (OBJ_BOUT)
+
+#define TC_S_IS_SYSPROC(s) ((1<=S_GET_OTHER(s)) && (S_GET_OTHER(s)<=32))
+#define TC_S_IS_BALNAME(s) (S_GET_OTHER(s) == N_BALNAME)
+#define TC_S_IS_CALLNAME(s) (S_GET_OTHER(s) == N_CALLNAME)
+#define TC_S_IS_BADPROC(s) ((S_GET_OTHER(s) != 0) && !TC_S_IS_CALLNAME(s) && !TC_S_IS_BALNAME(s) && !TC_S_IS_SYSPROC(s))
+
+#define TC_S_SET_SYSPROC(s, p) (S_SET_OTHER((s), (p)+1))
+#define TC_S_GET_SYSPROC(s) (S_GET_OTHER(s)-1)
+
+#define TC_S_FORCE_TO_BALNAME(s) (S_SET_OTHER((s), N_BALNAME))
+#define TC_S_FORCE_TO_CALLNAME(s) (S_SET_OTHER((s), N_CALLNAME))
+#define TC_S_FORCE_TO_SYSPROC(s) {;}
+
+#else /* ! OBJ_A/BOUT */
+#ifdef OBJ_COFF
+
+#define TC_S_IS_SYSPROC(s) (S_GET_STORAGE_CLASS(s) == C_SCALL)
+#define TC_S_IS_BALNAME(s) (SF_GET_BALNAME(s))
+#define TC_S_IS_CALLNAME(s) (SF_GET_CALLNAME(s))
+#define TC_S_IS_BADPROC(s) (TC_S_IS_SYSPROC(s) && TC_S_GET_SYSPROC(s) < 0 && 31 < TC_S_GET_SYSPROC(s))
+
+#define TC_S_SET_SYSPROC(s, p) ((s)->sy_symbol.ost_auxent[1].x_sc.x_stindx = (p))
+#define TC_S_GET_SYSPROC(s) ((s)->sy_symbol.ost_auxent[1].x_sc.x_stindx)
+
+#define TC_S_FORCE_TO_BALNAME(s) (SF_SET_BALNAME(s))
+#define TC_S_FORCE_TO_CALLNAME(s) (SF_SET_CALLNAME(s))
+#define TC_S_FORCE_TO_SYSPROC(s) (S_SET_STORAGE_CLASS((s), C_SCALL))
+
+#else /* ! OBJ_COFF */
+you lose;
+#endif /* ! OBJ_COFF */
+#endif /* ! OBJ_A/BOUT */
+
+extern char *input_line_pointer;
+
+#if !defined (BFD_ASSEMBLER) && !defined (BFD)
+#ifdef OBJ_COFF
+const int md_reloc_size = sizeof (struct reloc);
+#else /* OBJ_COFF */
+const int md_reloc_size = sizeof (struct relocation_info);
+#endif /* OBJ_COFF */
+#endif
+
+/* Local i80960 routines. */
+
+static void brcnt_emit (); /* Emit branch-prediction instrumentation code */
+static char *brlab_next (); /* Return next branch local label */
+void brtab_emit (); /* Emit br-predict instrumentation table */
+static void cobr_fmt (); /* Generate COBR instruction */
+static void ctrl_fmt (); /* Generate CTRL instruction */
+static char *emit (); /* Emit (internally) binary */
+static int get_args (); /* Break arguments out of comma-separated list */
+static void get_cdisp (); /* Handle COBR or CTRL displacement */
+static char *get_ispec (); /* Find index specification string */
+static int get_regnum (); /* Translate text to register number */
+static int i_scan (); /* Lexical scan of instruction source */
+static void mem_fmt (); /* Generate MEMA or MEMB instruction */
+static void mema_to_memb (); /* Convert MEMA instruction to MEMB format */
+static void parse_expr (); /* Parse an expression */
+static int parse_ldconst (); /* Parse and replace a 'ldconst' pseudo-op */
+static void parse_memop (); /* Parse a memory operand */
+static void parse_po (); /* Parse machine-dependent pseudo-op */
+static void parse_regop (); /* Parse a register operand */
+static void reg_fmt (); /* Generate a REG format instruction */
+void reloc_callj (); /* Relocate a 'callj' instruction */
+static void relax_cobr (); /* "De-optimize" cobr into compare/branch */
+static void s_leafproc (); /* Process '.leafproc' pseudo-op */
+static void s_sysproc (); /* Process '.sysproc' pseudo-op */
+static int shift_ok (); /* Will a 'shlo' substiture for a 'ldconst'? */
+static void syntax (); /* Give syntax error */
+static int targ_has_sfr (); /* Target chip supports spec-func register? */
+static int targ_has_iclass (); /* Target chip supports instruction set? */
+
+/* See md_parse_option() for meanings of these options */
+static char norelax; /* True if -norelax switch seen */
+static char instrument_branches; /* True if -b switch seen */
+
+/* Characters that always start a comment.
+ If the pre-processor is disabled, these aren't very useful.
+ */
+const char comment_chars[] = "#";
+
+/* Characters that only start a comment at the beginning of
+ a line. If the line seems to have the form '# 123 filename'
+ .line and .file directives will appear in the pre-processed output.
+
+ Note that input_file.c hand checks for '#' at the beginning of the
+ first line of the input file. This is because the compiler outputs
+ #NO_APP at the beginning of its output.
+ */
+
+/* Also note that comments started like this one will always work. */
+
+const char line_comment_chars[1];
+
+const char line_separator_chars[1];
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant,
+ as in 0f12.456 or 0d1.2345e12
+ */
+const char FLT_CHARS[] = "fFdDtT";
+
+
+/* Table used by base assembler to relax addresses based on varying length
+ instructions. The fields are:
+ 1) most positive reach of this state,
+ 2) most negative reach of this state,
+ 3) how many bytes this mode will add to the size of the current frag
+ 4) which index into the table to try if we can't fit into this one.
+
+ For i80960, the only application is the (de-)optimization of cobr
+ instructions into separate compare and branch instructions when a 13-bit
+ displacement won't hack it.
+ */
+const relax_typeS md_relax_table[] =
+{
+ {0, 0, 0, 0}, /* State 0 => no more relaxation possible */
+ {4088, -4096, 0, 2}, /* State 1: conditional branch (cobr) */
+ {0x800000 - 8, -0x800000, 4, 0}, /* State 2: compare (reg) & branch (ctrl) */
+};
+
+static void s_endian PARAMS ((int));
+
+/* These are the machine dependent pseudo-ops.
+
+ This table describes all the machine specific pseudo-ops the assembler
+ has to support. The fields are:
+ pseudo-op name without dot
+ function to call to execute this pseudo-op
+ integer arg to pass to the function
+ */
+#define S_LEAFPROC 1
+#define S_SYSPROC 2
+
+const pseudo_typeS md_pseudo_table[] =
+{
+ {"bss", s_lcomm, 1},
+ {"endian", s_endian, 0},
+ {"extended", float_cons, 't'},
+ {"leafproc", parse_po, S_LEAFPROC},
+ {"sysproc", parse_po, S_SYSPROC},
+
+ {"word", cons, 4},
+ {"quad", cons, 16},
+
+ {0, 0, 0}
+};
+
+/* Macros to extract info from an 'expressionS' structure 'e' */
+#define adds(e) e.X_add_symbol
+#define offs(e) e.X_add_number
+
+
+/* Branch-prediction bits for CTRL/COBR format opcodes */
+#define BP_MASK 0x00000002 /* Mask for branch-prediction bit */
+#define BP_TAKEN 0x00000000 /* Value to OR in to predict branch */
+#define BP_NOT_TAKEN 0x00000002 /* Value to OR in to predict no branch */
+
+
+/* Some instruction opcodes that we need explicitly */
+#define BE 0x12000000
+#define BG 0x11000000
+#define BGE 0x13000000
+#define BL 0x14000000
+#define BLE 0x16000000
+#define BNE 0x15000000
+#define BNO 0x10000000
+#define BO 0x17000000
+#define CHKBIT 0x5a002700
+#define CMPI 0x5a002080
+#define CMPO 0x5a002000
+
+#define B 0x08000000
+#define BAL 0x0b000000
+#define CALL 0x09000000
+#define CALLS 0x66003800
+#define RET 0x0a000000
+
+
+/* These masks are used to build up a set of MEMB mode bits. */
+#define A_BIT 0x0400
+#define I_BIT 0x0800
+#define MEMB_BIT 0x1000
+#define D_BIT 0x2000
+
+
+/* Mask for the only mode bit in a MEMA instruction (if set, abase reg is
+ used). */
+#define MEMA_ABASE 0x2000
+
+/* Info from which a MEMA or MEMB format instruction can be generated */
+typedef struct
+ {
+ /* (First) 32 bits of instruction */
+ long opcode;
+ /* 0-(none), 12- or, 32-bit displacement needed */
+ int disp;
+ /* The expression in the source instruction from which the
+ displacement should be determined. */
+ char *e;
+ }
+
+memS;
+
+
+/* The two pieces of info we need to generate a register operand */
+struct regop
+ {
+ int mode; /* 0 =>local/global/spec reg; 1=> literal or fp reg */
+ int special; /* 0 =>not a sfr; 1=> is a sfr (not valid w/mode=0) */
+ int n; /* Register number or literal value */
+ };
+
+
+/* Number and assembler mnemonic for all registers that can appear in
+ operands. */
+static const struct
+ {
+ char *reg_name;
+ int reg_num;
+ }
+regnames[] =
+{
+ { "pfp", 0 },
+ { "sp", 1 },
+ { "rip", 2 },
+ { "r3", 3 },
+ { "r4", 4 },
+ { "r5", 5 },
+ { "r6", 6 },
+ { "r7", 7 },
+ { "r8", 8 },
+ { "r9", 9 },
+ { "r10", 10 },
+ { "r11", 11 },
+ { "r12", 12 },
+ { "r13", 13 },
+ { "r14", 14 },
+ { "r15", 15 },
+ { "g0", 16 },
+ { "g1", 17 },
+ { "g2", 18 },
+ { "g3", 19 },
+ { "g4", 20 },
+ { "g5", 21 },
+ { "g6", 22 },
+ { "g7", 23 },
+ { "g8", 24 },
+ { "g9", 25 },
+ { "g10", 26 },
+ { "g11", 27 },
+ { "g12", 28 },
+ { "g13", 29 },
+ { "g14", 30 },
+ { "fp", 31 },
+
+ /* Numbers for special-function registers are for assembler internal
+ use only: they are scaled back to range [0-31] for binary output. */
+#define SF0 32
+
+ { "sf0", 32 },
+ { "sf1", 33 },
+ { "sf2", 34 },
+ { "sf3", 35 },
+ { "sf4", 36 },
+ { "sf5", 37 },
+ { "sf6", 38 },
+ { "sf7", 39 },
+ { "sf8", 40 },
+ { "sf9", 41 },
+ { "sf10", 42 },
+ { "sf11", 43 },
+ { "sf12", 44 },
+ { "sf13", 45 },
+ { "sf14", 46 },
+ { "sf15", 47 },
+ { "sf16", 48 },
+ { "sf17", 49 },
+ { "sf18", 50 },
+ { "sf19", 51 },
+ { "sf20", 52 },
+ { "sf21", 53 },
+ { "sf22", 54 },
+ { "sf23", 55 },
+ { "sf24", 56 },
+ { "sf25", 57 },
+ { "sf26", 58 },
+ { "sf27", 59 },
+ { "sf28", 60 },
+ { "sf29", 61 },
+ { "sf30", 62 },
+ { "sf31", 63 },
+
+ /* Numbers for floating point registers are for assembler internal
+ use only: they are scaled back to [0-3] for binary output. */
+#define FP0 64
+
+ { "fp0", 64 },
+ { "fp1", 65 },
+ { "fp2", 66 },
+ { "fp3", 67 },
+
+ { NULL, 0 }, /* END OF LIST */
+};
+
+#define IS_RG_REG(n) ((0 <= (n)) && ((n) < SF0))
+#define IS_SF_REG(n) ((SF0 <= (n)) && ((n) < FP0))
+#define IS_FP_REG(n) ((n) >= FP0)
+
+/* Number and assembler mnemonic for all registers that can appear as
+ 'abase' (indirect addressing) registers. */
+static const struct
+ {
+ char *areg_name;
+ int areg_num;
+ }
+aregs[] =
+{
+ { "(pfp)", 0 },
+ { "(sp)", 1 },
+ { "(rip)", 2 },
+ { "(r3)", 3 },
+ { "(r4)", 4 },
+ { "(r5)", 5 },
+ { "(r6)", 6 },
+ { "(r7)", 7 },
+ { "(r8)", 8 },
+ { "(r9)", 9 },
+ { "(r10)", 10 },
+ { "(r11)", 11 },
+ { "(r12)", 12 },
+ { "(r13)", 13 },
+ { "(r14)", 14 },
+ { "(r15)", 15 },
+ { "(g0)", 16 },
+ { "(g1)", 17 },
+ { "(g2)", 18 },
+ { "(g3)", 19 },
+ { "(g4)", 20 },
+ { "(g5)", 21 },
+ { "(g6)", 22 },
+ { "(g7)", 23 },
+ { "(g8)", 24 },
+ { "(g9)", 25 },
+ { "(g10)", 26 },
+ { "(g11)", 27 },
+ { "(g12)", 28 },
+ { "(g13)", 29 },
+ { "(g14)", 30 },
+ { "(fp)", 31 },
+
+#define IPREL 32
+ /* For assembler internal use only: this number never appears in binary
+ output. */
+ { "(ip)", IPREL },
+
+ { NULL, 0 }, /* END OF LIST */
+};
+
+
+/* Hash tables */
+static struct hash_control *op_hash; /* Opcode mnemonics */
+static struct hash_control *reg_hash; /* Register name hash table */
+static struct hash_control *areg_hash; /* Abase register hash table */
+
+
+/* Architecture for which we are assembling */
+#define ARCH_ANY 0 /* Default: no architecture checking done */
+#define ARCH_KA 1
+#define ARCH_KB 2
+#define ARCH_MC 3
+#define ARCH_CA 4
+#define ARCH_JX 5
+#define ARCH_HX 6
+int architecture = ARCH_ANY; /* Architecture requested on invocation line */
+int iclasses_seen; /* OR of instruction classes (I_* constants)
+ * for which we've actually assembled
+ * instructions.
+ */
+
+
+/* BRANCH-PREDICTION INSTRUMENTATION
+
+ The following supports generation of branch-prediction instrumentation
+ (turned on by -b switch). The instrumentation collects counts
+ of branches taken/not-taken for later input to a utility that will
+ set the branch prediction bits of the instructions in accordance with
+ the behavior observed. (Note that the KX series does not have
+ brach-prediction.)
+
+ The instrumentation consists of:
+
+ (1) before and after each conditional branch, a call to an external
+ routine that increments and steps over an inline counter. The
+ counter itself, initialized to 0, immediately follows the call
+ instruction. For each branch, the counter following the branch
+ is the number of times the branch was not taken, and the difference
+ between the counters is the number of times it was taken. An
+ example of an instrumented conditional branch:
+
+ call BR_CNT_FUNC
+ .word 0
+ LBRANCH23: be label
+ call BR_CNT_FUNC
+ .word 0
+
+ (2) a table of pointers to the instrumented branches, so that an
+ external postprocessing routine can locate all of the counters.
+ the table begins with a 2-word header: a pointer to the next in
+ a linked list of such tables (initialized to 0); and a count
+ of the number of entries in the table (exclusive of the header.
+
+ Note that input source code is expected to already contain calls
+ an external routine that will link the branch local table into a
+ list of such tables.
+ */
+
+/* Number of branches instrumented so far. Also used to generate
+ unique local labels for each instrumented branch. */
+static int br_cnt;
+
+#define BR_LABEL_BASE "LBRANCH"
+/* Basename of local labels on instrumented branches, to avoid
+ conflict with compiler- generated local labels. */
+
+#define BR_CNT_FUNC "__inc_branch"
+/* Name of the external routine that will increment (and step over) an
+ inline counter. */
+
+#define BR_TAB_NAME "__BRANCH_TABLE__"
+/* Name of the table of pointers to branches. A local (i.e.,
+ non-external) symbol. */
+
+/*****************************************************************************
+ md_begin: One-time initialization.
+
+ Set up hash tables.
+
+ *************************************************************************** */
+void
+md_begin ()
+{
+ int i; /* Loop counter */
+ const struct i960_opcode *oP; /* Pointer into opcode table */
+ const char *retval; /* Value returned by hash functions */
+
+ op_hash = hash_new ();
+ reg_hash = hash_new ();
+ areg_hash = hash_new ();
+
+ /* For some reason, the base assembler uses an empty string for "no
+ error message", instead of a NULL pointer. */
+ retval = 0;
+
+ for (oP = i960_opcodes; oP->name && !retval; oP++)
+ retval = hash_insert (op_hash, oP->name, (PTR) oP);
+
+ for (i = 0; regnames[i].reg_name && !retval; i++)
+ retval = hash_insert (reg_hash, regnames[i].reg_name,
+ (char *) &regnames[i].reg_num);
+
+ for (i = 0; aregs[i].areg_name && !retval; i++)
+ retval = hash_insert (areg_hash, aregs[i].areg_name,
+ (char *) &aregs[i].areg_num);
+
+ if (retval)
+ as_fatal (_("Hashing returned \"%s\"."), retval);
+}
+
+/*****************************************************************************
+ md_assemble: Assemble an instruction
+
+ Assumptions about the passed-in text:
+ - all comments, labels removed
+ - text is an instruction
+ - all white space compressed to single blanks
+ - all character constants have been replaced with decimal
+
+ *************************************************************************** */
+void
+md_assemble (textP)
+ char *textP; /* Source text of instruction */
+{
+ /* Parsed instruction text, containing NO whitespace: arg[0]->opcode
+ mnemonic arg[1-3]->operands, with char constants replaced by
+ decimal numbers. */
+ char *args[4];
+
+ int n_ops; /* Number of instruction operands */
+ /* Pointer to instruction description */
+ struct i960_opcode *oP;
+ /* TRUE iff opcode mnemonic included branch-prediction suffix (".f"
+ or ".t"). */
+ int branch_predict;
+ /* Setting of branch-prediction bit(s) to be OR'd into instruction
+ opcode of CTRL/COBR format instructions. */
+ long bp_bits;
+
+ int n; /* Offset of last character in opcode mnemonic */
+
+ const char *bp_error_msg = _("branch prediction invalid on this opcode");
+
+
+ /* Parse instruction into opcode and operands */
+ memset (args, '\0', sizeof (args));
+ n_ops = i_scan (textP, args);
+ if (n_ops == -1)
+ {
+ return; /* Error message already issued */
+ }
+
+ /* Do "macro substitution" (sort of) on 'ldconst' pseudo-instruction */
+ if (!strcmp (args[0], "ldconst"))
+ {
+ n_ops = parse_ldconst (args);
+ if (n_ops == -1)
+ {
+ return;
+ }
+ }
+
+
+
+ /* Check for branch-prediction suffix on opcode mnemonic, strip it off */
+ n = strlen (args[0]) - 1;
+ branch_predict = 0;
+ bp_bits = 0;
+ if (args[0][n - 1] == '.' && (args[0][n] == 't' || args[0][n] == 'f'))
+ {
+ /* We could check here to see if the target architecture
+ supports branch prediction, but why bother? The bit will
+ just be ignored by processors that don't use it. */
+ branch_predict = 1;
+ bp_bits = (args[0][n] == 't') ? BP_TAKEN : BP_NOT_TAKEN;
+ args[0][n - 1] = '\0'; /* Strip suffix from opcode mnemonic */
+ }
+
+ /* Look up opcode mnemonic in table and check number of operands.
+ Check that opcode is legal for the target architecture. If all
+ looks good, assemble instruction. */
+ oP = (struct i960_opcode *) hash_find (op_hash, args[0]);
+ if (!oP || !targ_has_iclass (oP->iclass))
+ {
+ as_bad (_("invalid opcode, \"%s\"."), args[0]);
+
+ }
+ else if (n_ops != oP->num_ops)
+ {
+ as_bad (_("improper number of operands. expecting %d, got %d"),
+ oP->num_ops, n_ops);
+ }
+ else
+ {
+ switch (oP->format)
+ {
+ case FBRA:
+ case CTRL:
+ ctrl_fmt (args[1], oP->opcode | bp_bits, oP->num_ops);
+ if (oP->format == FBRA)
+ {
+ /* Now generate a 'bno' to same arg */
+ ctrl_fmt (args[1], BNO | bp_bits, 1);
+ }
+ break;
+ case COBR:
+ case COJ:
+ cobr_fmt (args, oP->opcode | bp_bits, oP);
+ break;
+ case REG:
+ if (branch_predict)
+ {
+ as_warn (bp_error_msg);
+ }
+ reg_fmt (args, oP);
+ break;
+ case MEM1:
+ if (args[0][0] == 'c' && args[0][1] == 'a')
+ {
+ if (branch_predict)
+ {
+ as_warn (bp_error_msg);
+ }
+ mem_fmt (args, oP, 1);
+ break;
+ }
+ case MEM2:
+ case MEM4:
+ case MEM8:
+ case MEM12:
+ case MEM16:
+ if (branch_predict)
+ {
+ as_warn (bp_error_msg);
+ }
+ mem_fmt (args, oP, 0);
+ break;
+ case CALLJ:
+ if (branch_predict)
+ {
+ as_warn (bp_error_msg);
+ }
+ /* Output opcode & set up "fixup" (relocation); flag
+ relocation as 'callj' type. */
+ know (oP->num_ops == 1);
+ get_cdisp (args[1], "CTRL", oP->opcode, 24, 0, 1);
+ break;
+ default:
+ BAD_CASE (oP->format);
+ break;
+ }
+ }
+} /* md_assemble() */
+
+/*****************************************************************************
+ md_number_to_chars: convert a number to target byte order
+
+ *************************************************************************** */
+void
+md_number_to_chars (buf, value, n)
+ char *buf;
+ valueT value;
+ int n;
+{
+ number_to_chars_littleendian (buf, value, n);
+}
+
+/*****************************************************************************
+ md_chars_to_number: convert from target byte order to host byte order.
+
+ *************************************************************************** */
+int
+md_chars_to_number (val, n)
+ unsigned char *val; /* Value in target byte order */
+ int n; /* Number of bytes in the input */
+{
+ int retval;
+
+ for (retval = 0; n--;)
+ {
+ retval <<= 8;
+ retval |= val[n];
+ }
+ return retval;
+}
+
+
+#define MAX_LITTLENUMS 6
+#define LNUM_SIZE sizeof(LITTLENUM_TYPE)
+
+/*****************************************************************************
+ md_atof: convert ascii to floating point
+
+ Turn a string at input_line_pointer into a floating point constant of type
+ 'type', and store the appropriate bytes at *litP. The number of LITTLENUMS
+ emitted is returned at 'sizeP'. An error message is returned, or a pointer
+ to an empty message if OK.
+
+ Note we call the i386 floating point routine, rather than complicating
+ things with more files or symbolic links.
+
+ *************************************************************************** */
+char *
+md_atof (type, litP, sizeP)
+ int type;
+ char *litP;
+ int *sizeP;
+{
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ int prec;
+ char *t;
+ char *atof_ieee ();
+
+ switch (type)
+ {
+ case 'f':
+ case 'F':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ prec = 4;
+ break;
+
+ case 't':
+ case 'T':
+ prec = 5;
+ type = 'x'; /* That's what atof_ieee() understands */
+ break;
+
+ default:
+ *sizeP = 0;
+ return _("Bad call to md_atof()");
+ }
+
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ {
+ input_line_pointer = t;
+ }
+
+ *sizeP = prec * LNUM_SIZE;
+
+ /* Output the LITTLENUMs in REVERSE order in accord with i80960
+ word-order. (Dunno why atof_ieee doesn't do it in the right
+ order in the first place -- probably because it's a hack of
+ atof_m68k.) */
+
+ for (wordP = words + prec - 1; prec--;)
+ {
+ md_number_to_chars (litP, (long) (*wordP--), LNUM_SIZE);
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+
+ return 0;
+}
+
+
+/*****************************************************************************
+ md_number_to_imm
+
+ *************************************************************************** */
+void
+md_number_to_imm (buf, val, n)
+ char *buf;
+ long val;
+ int n;
+{
+ md_number_to_chars (buf, val, n);
+}
+
+
+/*****************************************************************************
+ md_number_to_disp
+
+ *************************************************************************** */
+void
+md_number_to_disp (buf, val, n)
+ char *buf;
+ long val;
+ int n;
+{
+ md_number_to_chars (buf, val, n);
+}
+
+/*****************************************************************************
+ md_number_to_field:
+
+ Stick a value (an address fixup) into a bit field of
+ previously-generated instruction.
+
+ *************************************************************************** */
+void
+md_number_to_field (instrP, val, bfixP)
+ char *instrP; /* Pointer to instruction to be fixed */
+ long val; /* Address fixup value */
+ bit_fixS *bfixP; /* Description of bit field to be fixed up */
+{
+ int numbits; /* Length of bit field to be fixed */
+ long instr; /* 32-bit instruction to be fixed-up */
+ long sign; /* 0 or -1, according to sign bit of 'val' */
+
+ /* Convert instruction back to host byte order. */
+ instr = md_chars_to_number (instrP, 4);
+
+ /* Surprise! -- we stored the number of bits to be modified rather
+ than a pointer to a structure. */
+ numbits = (int) bfixP;
+ if (numbits == 1)
+ {
+ /* This is a no-op, stuck here by reloc_callj() */
+ return;
+ }
+
+ know ((numbits == 13) || (numbits == 24));
+
+ /* Propagate sign bit of 'val' for the given number of bits. Result
+ should be all 0 or all 1. */
+ sign = val >> ((int) numbits - 1);
+ if (((val < 0) && (sign != -1))
+ || ((val > 0) && (sign != 0)))
+ {
+ as_bad (_("Fixup of %ld too large for field width of %d"),
+ val, numbits);
+ }
+ else
+ {
+ /* Put bit field into instruction and write back in target
+ * byte order.
+ */
+ val &= ~(-1 << (int) numbits); /* Clear unused sign bits */
+ instr |= val;
+ md_number_to_chars (instrP, instr, 4);
+ }
+} /* md_number_to_field() */
+
+
+/*****************************************************************************
+ md_parse_option
+ Invocation line includes a switch not recognized by the base assembler.
+ See if it's a processor-specific option. For the 960, these are:
+
+ -norelax:
+ Conditional branch instructions that require displacements
+ greater than 13 bits (or that have external targets) should
+ generate errors. The default is to replace each such
+ instruction with the corresponding compare (or chkbit) and
+ branch instructions. Note that the Intel "j" cobr directives
+ are ALWAYS "de-optimized" in this way when necessary,
+ regardless of the setting of this option.
+
+ -b:
+ Add code to collect information about branches taken, for
+ later optimization of branch prediction bits by a separate
+ tool. COBR and CNTL format instructions have branch
+ prediction bits (in the CX architecture); if "BR" represents
+ an instruction in one of these classes, the following rep-
+ resents the code generated by the assembler:
+
+ call <increment routine>
+ .word 0 # pre-counter
+ Label: BR
+ call <increment routine>
+ .word 0 # post-counter
+
+ A table of all such "Labels" is also generated.
+
+
+ -AKA, -AKB, -AKC, -ASA, -ASB, -AMC, -ACA:
+ Select the 80960 architecture. Instructions or features not
+ supported by the selected architecture cause fatal errors.
+ The default is to generate code for any instruction or feature
+ that is supported by SOME version of the 960 (even if this
+ means mixing architectures!).
+
+ ****************************************************************************/
+
+CONST char *md_shortopts = "A:b";
+struct option md_longopts[] =
+{
+#define OPTION_LINKRELAX (OPTION_MD_BASE)
+ {"linkrelax", no_argument, NULL, OPTION_LINKRELAX},
+ {"link-relax", no_argument, NULL, OPTION_LINKRELAX},
+#define OPTION_NORELAX (OPTION_MD_BASE + 1)
+ {"norelax", no_argument, NULL, OPTION_NORELAX},
+ {"no-relax", no_argument, NULL, OPTION_NORELAX},
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof (md_longopts);
+
+struct tabentry
+ {
+ char *flag;
+ int arch;
+ };
+static const struct tabentry arch_tab[] =
+{
+ {"KA", ARCH_KA},
+ {"KB", ARCH_KB},
+ {"SA", ARCH_KA}, /* Synonym for KA */
+ {"SB", ARCH_KB}, /* Synonym for KB */
+ {"KC", ARCH_MC}, /* Synonym for MC */
+ {"MC", ARCH_MC},
+ {"CA", ARCH_CA},
+ {"JX", ARCH_JX},
+ {"HX", ARCH_HX},
+ {NULL, 0}
+};
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ switch (c)
+ {
+ case OPTION_LINKRELAX:
+ linkrelax = 1;
+ flag_keep_locals = 1;
+ break;
+
+ case OPTION_NORELAX:
+ norelax = 1;
+ break;
+
+ case 'b':
+ instrument_branches = 1;
+ break;
+
+ case 'A':
+ {
+ const struct tabentry *tp;
+ char *p = arg;
+
+ for (tp = arch_tab; tp->flag != NULL; tp++)
+ if (!strcmp (p, tp->flag))
+ break;
+
+ if (tp->flag == NULL)
+ {
+ as_bad (_("invalid architecture %s"), p);
+ return 0;
+ }
+ else
+ architecture = tp->arch;
+ }
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+ int i;
+ fprintf (stream, _("I960 options:\n"));
+ for (i = 0; arch_tab[i].flag; i++)
+ fprintf (stream, "%s-A%s", i ? " | " : "", arch_tab[i].flag);
+ fprintf (stream, _("\n\
+ specify variant of 960 architecture\n\
+-b add code to collect statistics about branches taken\n\
+-link-relax preserve individual alignment directives so linker\n\
+ can do relaxing (b.out format only)\n\
+-no-relax don't alter compare-and-branch instructions for\n\
+ long displacements\n"));
+}
+
+
+#ifndef BFD_ASSEMBLER
+/*****************************************************************************
+ md_convert_frag:
+ Called by base assembler after address relaxation is finished: modify
+ variable fragments according to how much relaxation was done.
+
+ If the fragment substate is still 1, a 13-bit displacement was enough
+ to reach the symbol in question. Set up an address fixup, but otherwise
+ leave the cobr instruction alone.
+
+ If the fragment substate is 2, a 13-bit displacement was not enough.
+ Replace the cobr with a two instructions (a compare and a branch).
+
+ *************************************************************************** */
+void
+md_convert_frag (headers, seg, fragP)
+ object_headers *headers;
+ segT seg;
+ fragS *fragP;
+{
+ fixS *fixP; /* Structure describing needed address fix */
+
+ switch (fragP->fr_subtype)
+ {
+ case 1:
+ /* LEAVE SINGLE COBR INSTRUCTION */
+ fixP = fix_new (fragP,
+ fragP->fr_opcode - fragP->fr_literal,
+ 4,
+ fragP->fr_symbol,
+ fragP->fr_offset,
+ 1,
+ NO_RELOC);
+
+ fixP->fx_bit_fixP = (bit_fixS *) 13; /* size of bit field */
+ break;
+ case 2:
+ /* REPLACE COBR WITH COMPARE/BRANCH INSTRUCTIONS */
+ relax_cobr (fragP);
+ break;
+ default:
+ BAD_CASE (fragP->fr_subtype);
+ break;
+ }
+}
+
+/*****************************************************************************
+ md_estimate_size_before_relax: How much does it look like *fragP will grow?
+
+ Called by base assembler just before address relaxation.
+ Return the amount by which the fragment will grow.
+
+ Any symbol that is now undefined will not become defined; cobr's
+ based on undefined symbols will have to be replaced with a compare
+ instruction and a branch instruction, and the code fragment will grow
+ by 4 bytes.
+
+ *************************************************************************** */
+int
+md_estimate_size_before_relax (fragP, segment_type)
+ register fragS *fragP;
+ register segT segment_type;
+{
+ /* If symbol is undefined in this segment, go to "relaxed" state
+ (compare and branch instructions instead of cobr) right now. */
+ if (S_GET_SEGMENT (fragP->fr_symbol) != segment_type)
+ {
+ relax_cobr (fragP);
+ return 4;
+ }
+ return 0;
+} /* md_estimate_size_before_relax() */
+
+
+/*****************************************************************************
+ md_ri_to_chars:
+ This routine exists in order to overcome machine byte-order problems
+ when dealing with bit-field entries in the relocation_info struct.
+
+ But relocation info will be used on the host machine only (only
+ executable code is actually downloaded to the i80960). Therefore,
+ we leave it in host byte order.
+
+ The above comment is no longer true. This routine now really
+ does do the reordering (Ian Taylor 28 Aug 92).
+
+ *************************************************************************** */
+void
+md_ri_to_chars (where, ri)
+ char *where;
+ struct relocation_info *ri;
+{
+ md_number_to_chars (where, ri->r_address,
+ sizeof (ri->r_address));
+ where[4] = ri->r_index & 0x0ff;
+ where[5] = (ri->r_index >> 8) & 0x0ff;
+ where[6] = (ri->r_index >> 16) & 0x0ff;
+ where[7] = ((ri->r_pcrel << 0)
+ | (ri->r_length << 1)
+ | (ri->r_extern << 3)
+ | (ri->r_bsr << 4)
+ | (ri->r_disp << 5)
+ | (ri->r_callj << 6));
+}
+
+#endif /* BFD_ASSEMBLER */
+
+/* FOLLOWING ARE THE LOCAL ROUTINES, IN ALPHABETICAL ORDER */
+
+/*****************************************************************************
+ brcnt_emit: Emit code to increment inline branch counter.
+
+ See the comments above the declaration of 'br_cnt' for details on
+ branch-prediction instrumentation.
+ *************************************************************************** */
+static void
+brcnt_emit ()
+{
+ ctrl_fmt (BR_CNT_FUNC, CALL, 1); /* Emit call to "increment" routine */
+ emit (0); /* Emit inline counter to be incremented */
+}
+
+/*****************************************************************************
+ brlab_next: generate the next branch local label
+
+ See the comments above the declaration of 'br_cnt' for details on
+ branch-prediction instrumentation.
+ *************************************************************************** */
+static char *
+brlab_next ()
+{
+ static char buf[20];
+
+ sprintf (buf, "%s%d", BR_LABEL_BASE, br_cnt++);
+ return buf;
+}
+
+/*****************************************************************************
+ brtab_emit: generate the fetch-prediction branch table.
+
+ See the comments above the declaration of 'br_cnt' for details on
+ branch-prediction instrumentation.
+
+ The code emitted here would be functionally equivalent to the following
+ example assembler source.
+
+ .data
+ .align 2
+ BR_TAB_NAME:
+ .word 0 # link to next table
+ .word 3 # length of table
+ .word LBRANCH0 # 1st entry in table proper
+ .word LBRANCH1
+ .word LBRANCH2
+ **************************************************************************** */
+void
+brtab_emit ()
+{
+ int i;
+ char buf[20];
+ char *p; /* Where the binary was output to */
+ /* Pointer to description of deferred address fixup. */
+ fixS *fixP;
+
+ if (!instrument_branches)
+ {
+ return;
+ }
+
+ subseg_set (data_section, 0); /* .data */
+ frag_align (2, 0, 0); /* .align 2 */
+ record_alignment (now_seg, 2);
+ colon (BR_TAB_NAME); /* BR_TAB_NAME: */
+ emit (0); /* .word 0 #link to next table */
+ emit (br_cnt); /* .word n #length of table */
+
+ for (i = 0; i < br_cnt; i++)
+ {
+ sprintf (buf, "%s%d", BR_LABEL_BASE, i);
+ p = emit (0);
+ fixP = fix_new (frag_now,
+ p - frag_now->fr_literal,
+ 4,
+ symbol_find (buf),
+ 0,
+ 0,
+ NO_RELOC);
+ }
+}
+
+/*****************************************************************************
+ cobr_fmt: generate a COBR-format instruction
+
+ *************************************************************************** */
+static
+void
+cobr_fmt (arg, opcode, oP)
+ /* arg[0]->opcode mnemonic, arg[1-3]->operands (ascii) */
+ char *arg[];
+ /* Opcode, with branch-prediction bits already set if necessary. */
+ long opcode;
+ /* Pointer to description of instruction. */
+ struct i960_opcode *oP;
+{
+ long instr; /* 32-bit instruction */
+ struct regop regop; /* Description of register operand */
+ int n; /* Number of operands */
+ int var_frag; /* 1 if varying length code fragment should
+ * be emitted; 0 if an address fix
+ * should be emitted.
+ */
+
+ instr = opcode;
+ n = oP->num_ops;
+
+ if (n >= 1)
+ {
+ /* First operand (if any) of a COBR is always a register
+ operand. Parse it. */
+ parse_regop (&regop, arg[1], oP->operand[0]);
+ instr |= (regop.n << 19) | (regop.mode << 13);
+ }
+ if (n >= 2)
+ {
+ /* Second operand (if any) of a COBR is always a register
+ operand. Parse it. */
+ parse_regop (&regop, arg[2], oP->operand[1]);
+ instr |= (regop.n << 14) | regop.special;
+ }
+
+
+ if (n < 3)
+ {
+ emit (instr);
+
+ }
+ else
+ {
+ if (instrument_branches)
+ {
+ brcnt_emit ();
+ colon (brlab_next ());
+ }
+
+ /* A third operand to a COBR is always a displacement. Parse
+ it; if it's relaxable (a cobr "j" directive, or any cobr
+ other than bbs/bbc when the "-norelax" option is not in use)
+ set up a variable code fragment; otherwise set up an address
+ fix. */
+ var_frag = !norelax || (oP->format == COJ); /* TRUE or FALSE */
+ get_cdisp (arg[3], "COBR", instr, 13, var_frag, 0);
+
+ if (instrument_branches)
+ {
+ brcnt_emit ();
+ }
+ }
+} /* cobr_fmt() */
+
+
+/*****************************************************************************
+ ctrl_fmt: generate a CTRL-format instruction
+
+ *************************************************************************** */
+static
+void
+ctrl_fmt (targP, opcode, num_ops)
+ char *targP; /* Pointer to text of lone operand (if any) */
+ long opcode; /* Template of instruction */
+ int num_ops; /* Number of operands */
+{
+ int instrument; /* TRUE iff we should add instrumentation to track
+ * how often the branch is taken
+ */
+
+
+ if (num_ops == 0)
+ {
+ emit (opcode); /* Output opcode */
+ }
+ else
+ {
+
+ instrument = instrument_branches && (opcode != CALL)
+ && (opcode != B) && (opcode != RET) && (opcode != BAL);
+
+ if (instrument)
+ {
+ brcnt_emit ();
+ colon (brlab_next ());
+ }
+
+ /* The operand MUST be an ip-relative displacment. Parse it
+ * and set up address fix for the instruction we just output.
+ */
+ get_cdisp (targP, "CTRL", opcode, 24, 0, 0);
+
+ if (instrument)
+ {
+ brcnt_emit ();
+ }
+ }
+
+}
+
+
+/*****************************************************************************
+ emit: output instruction binary
+
+ Output instruction binary, in target byte order, 4 bytes at a time.
+ Return pointer to where it was placed.
+
+ *************************************************************************** */
+static
+char *
+emit (instr)
+ long instr; /* Word to be output, host byte order */
+{
+ char *toP; /* Where to output it */
+
+ toP = frag_more (4); /* Allocate storage */
+ md_number_to_chars (toP, instr, 4); /* Convert to target byte order */
+ return toP;
+}
+
+
+/*****************************************************************************
+ get_args: break individual arguments out of comma-separated list
+
+ Input assumptions:
+ - all comments and labels have been removed
+ - all strings of whitespace have been collapsed to a single blank.
+ - all character constants ('x') have been replaced with decimal
+
+ Output:
+ args[0] is untouched. args[1] points to first operand, etc. All args:
+ - are NULL-terminated
+ - contain no whitespace
+
+ Return value:
+ Number of operands (0,1,2, or 3) or -1 on error.
+
+ *************************************************************************** */
+static int
+get_args (p, args)
+ /* Pointer to comma-separated operands; MUCKED BY US */
+ register char *p;
+ /* Output arg: pointers to operands placed in args[1-3]. MUST
+ ACCOMMODATE 4 ENTRIES (args[0-3]). */
+ char *args[];
+{
+ register int n; /* Number of operands */
+ register char *to;
+
+ /* Skip lead white space */
+ while (*p == ' ')
+ {
+ p++;
+ }
+
+ if (*p == '\0')
+ {
+ return 0;
+ }
+
+ n = 1;
+ args[1] = p;
+
+ /* Squeze blanks out by moving non-blanks toward start of string.
+ * Isolate operands, whenever comma is found.
+ */
+ to = p;
+ while (*p != '\0')
+ {
+
+ if (*p == ' '
+ && (! isalnum ((unsigned char) p[1])
+ || ! isalnum ((unsigned char) p[-1])))
+ {
+ p++;
+
+ }
+ else if (*p == ',')
+ {
+
+ /* Start of operand */
+ if (n == 3)
+ {
+ as_bad (_("too many operands"));
+ return -1;
+ }
+ *to++ = '\0'; /* Terminate argument */
+ args[++n] = to; /* Start next argument */
+ p++;
+
+ }
+ else
+ {
+ *to++ = *p++;
+ }
+ }
+ *to = '\0';
+ return n;
+}
+
+
+/*****************************************************************************
+ get_cdisp: handle displacement for a COBR or CTRL instruction.
+
+ Parse displacement for a COBR or CTRL instruction.
+
+ If successful, output the instruction opcode and set up for it,
+ depending on the arg 'var_frag', either:
+ o an address fixup to be done when all symbol values are known, or
+ o a varying length code fragment, with address fixup info. This
+ will be done for cobr instructions that may have to be relaxed
+ in to compare/branch instructions (8 bytes) if the final
+ address displacement is greater than 13 bits.
+
+ ****************************************************************************/
+static
+void
+get_cdisp (dispP, ifmtP, instr, numbits, var_frag, callj)
+ /* displacement as specified in source instruction */
+ char *dispP;
+ /* "COBR" or "CTRL" (for use in error message) */
+ char *ifmtP;
+ /* Instruction needing the displacement */
+ long instr;
+ /* # bits of displacement (13 for COBR, 24 for CTRL) */
+ int numbits;
+ /* 1 if varying length code fragment should be emitted;
+ * 0 if an address fix should be emitted.
+ */
+ int var_frag;
+ /* 1 if callj relocation should be done; else 0 */
+ int callj;
+{
+ expressionS e; /* Parsed expression */
+ fixS *fixP; /* Structure describing needed address fix */
+ char *outP; /* Where instruction binary is output to */
+
+ fixP = NULL;
+
+ parse_expr (dispP, &e);
+ switch (e.X_op)
+ {
+ case O_illegal:
+ as_bad (_("expression syntax error"));
+
+ case O_symbol:
+ if (S_GET_SEGMENT (e.X_add_symbol) == now_seg
+ || S_GET_SEGMENT (e.X_add_symbol) == undefined_section)
+ {
+ if (var_frag)
+ {
+ outP = frag_more (8); /* Allocate worst-case storage */
+ md_number_to_chars (outP, instr, 4);
+ frag_variant (rs_machine_dependent, 4, 4, 1,
+ adds (e), offs (e), outP);
+ }
+ else
+ {
+ /* Set up a new fix structure, so address can be updated
+ * when all symbol values are known.
+ */
+ outP = emit (instr);
+ fixP = fix_new (frag_now,
+ outP - frag_now->fr_literal,
+ 4,
+ adds (e),
+ offs (e),
+ 1,
+ NO_RELOC);
+
+ fixP->fx_tcbit = callj;
+
+ /* We want to modify a bit field when the address is
+ * known. But we don't need all the garbage in the
+ * bit_fix structure. So we're going to lie and store
+ * the number of bits affected instead of a pointer.
+ */
+ fixP->fx_bit_fixP = (bit_fixS *) numbits;
+ }
+ }
+ else
+ as_bad (_("attempt to branch into different segment"));
+ break;
+
+ default:
+ as_bad (_("target of %s instruction must be a label"), ifmtP);
+ break;
+ }
+}
+
+
+/*****************************************************************************
+ get_ispec: parse a memory operand for an index specification
+
+ Here, an "index specification" is taken to be anything surrounded
+ by square brackets and NOT followed by anything else.
+
+ If it's found, detach it from the input string, remove the surrounding
+ square brackets, and return a pointer to it. Otherwise, return NULL.
+
+ *************************************************************************** */
+static
+char *
+get_ispec (textP)
+ /* Pointer to memory operand from source instruction, no white space. */
+ char *textP;
+{
+ /* Points to start of index specification. */
+ char *start;
+ /* Points to end of index specification. */
+ char *end;
+
+ /* Find opening square bracket, if any. */
+ start = strchr (textP, '[');
+
+ if (start != NULL)
+ {
+
+ /* Eliminate '[', detach from rest of operand */
+ *start++ = '\0';
+
+ end = strchr (start, ']');
+
+ if (end == NULL)
+ {
+ as_bad (_("unmatched '['"));
+
+ }
+ else
+ {
+ /* Eliminate ']' and make sure it was the last thing
+ * in the string.
+ */
+ *end = '\0';
+ if (*(end + 1) != '\0')
+ {
+ as_bad (_("garbage after index spec ignored"));
+ }
+ }
+ }
+ return start;
+}
+
+/*****************************************************************************
+ get_regnum:
+
+ Look up a (suspected) register name in the register table and return the
+ associated register number (or -1 if not found).
+
+ *************************************************************************** */
+static
+int
+get_regnum (regname)
+ char *regname; /* Suspected register name */
+{
+ int *rP;
+
+ rP = (int *) hash_find (reg_hash, regname);
+ return (rP == NULL) ? -1 : *rP;
+}
+
+
+/*****************************************************************************
+ i_scan: perform lexical scan of ascii assembler instruction.
+
+ Input assumptions:
+ - input string is an i80960 instruction (not a pseudo-op)
+ - all comments and labels have been removed
+ - all strings of whitespace have been collapsed to a single blank.
+
+ Output:
+ args[0] points to opcode, other entries point to operands. All strings:
+ - are NULL-terminated
+ - contain no whitespace
+ - have character constants ('x') replaced with a decimal number
+
+ Return value:
+ Number of operands (0,1,2, or 3) or -1 on error.
+
+ *************************************************************************** */
+static int
+i_scan (iP, args)
+ /* Pointer to ascii instruction; MUCKED BY US. */
+ register char *iP;
+ /* Output arg: pointers to opcode and operands placed here. MUST
+ ACCOMMODATE 4 ENTRIES. */
+ char *args[];
+{
+
+ /* Isolate opcode */
+ if (*(iP) == ' ')
+ {
+ iP++;
+ } /* Skip lead space, if any */
+ args[0] = iP;
+ for (; *iP != ' '; iP++)
+ {
+ if (*iP == '\0')
+ {
+ /* There are no operands */
+ if (args[0] == iP)
+ {
+ /* We never moved: there was no opcode either! */
+ as_bad (_("missing opcode"));
+ return -1;
+ }
+ return 0;
+ }
+ }
+ *iP++ = '\0'; /* Terminate opcode */
+ return (get_args (iP, args));
+} /* i_scan() */
+
+
+/*****************************************************************************
+ mem_fmt: generate a MEMA- or MEMB-format instruction
+
+ *************************************************************************** */
+static void
+mem_fmt (args, oP, callx)
+ char *args[]; /* args[0]->opcode mnemonic, args[1-3]->operands */
+ struct i960_opcode *oP; /* Pointer to description of instruction */
+ int callx; /* Is this a callx opcode */
+{
+ int i; /* Loop counter */
+ struct regop regop; /* Description of register operand */
+ char opdesc; /* Operand descriptor byte */
+ memS instr; /* Description of binary to be output */
+ char *outP; /* Where the binary was output to */
+ expressionS expr; /* Parsed expression */
+ /* ->description of deferred address fixup */
+ fixS *fixP;
+
+#ifdef OBJ_COFF
+ /* COFF support isn't in place yet for callx relaxing. */
+ callx = 0;
+#endif
+
+ memset (&instr, '\0', sizeof (memS));
+ instr.opcode = oP->opcode;
+
+ /* Process operands. */
+ for (i = 1; i <= oP->num_ops; i++)
+ {
+ opdesc = oP->operand[i - 1];
+
+ if (MEMOP (opdesc))
+ {
+ parse_memop (&instr, args[i], oP->format);
+ }
+ else
+ {
+ parse_regop (&regop, args[i], opdesc);
+ instr.opcode |= regop.n << 19;
+ }
+ }
+
+ /* Parse the displacement; this must be done before emitting the
+ opcode, in case it is an expression using `.'. */
+ parse_expr (instr.e, &expr);
+
+ /* Output opcode */
+ outP = emit (instr.opcode);
+
+ if (instr.disp == 0)
+ {
+ return;
+ }
+
+ /* Process the displacement */
+ switch (expr.X_op)
+ {
+ case O_illegal:
+ as_bad (_("expression syntax error"));
+ break;
+
+ case O_constant:
+ if (instr.disp == 32)
+ {
+ (void) emit (offs (expr)); /* Output displacement */
+ }
+ else
+ {
+ /* 12-bit displacement */
+ if (offs (expr) & ~0xfff)
+ {
+ /* Won't fit in 12 bits: convert already-output
+ * instruction to MEMB format, output
+ * displacement.
+ */
+ mema_to_memb (outP);
+ (void) emit (offs (expr));
+ }
+ else
+ {
+ /* WILL fit in 12 bits: OR into opcode and
+ * overwrite the binary we already put out
+ */
+ instr.opcode |= offs (expr);
+ md_number_to_chars (outP, instr.opcode, 4);
+ }
+ }
+ break;
+
+ default:
+ if (instr.disp == 12)
+ {
+ /* Displacement is dependent on a symbol, whose value
+ * may change at link time. We HAVE to reserve 32 bits.
+ * Convert already-output opcode to MEMB format.
+ */
+ mema_to_memb (outP);
+ }
+
+ /* Output 0 displacement and set up address fixup for when
+ * this symbol's value becomes known.
+ */
+ outP = emit ((long) 0);
+ fixP = fix_new_exp (frag_now,
+ outP - frag_now->fr_literal,
+ 4,
+ &expr,
+ 0,
+ NO_RELOC);
+ /* Steve's linker relaxing hack. Mark this 32-bit relocation as
+ being in the instruction stream, specifically as part of a callx
+ instruction. */
+ fixP->fx_bsr = callx;
+ break;
+ }
+} /* memfmt() */
+
+
+/*****************************************************************************
+ mema_to_memb: convert a MEMA-format opcode to a MEMB-format opcode.
+
+ There are 2 possible MEMA formats:
+ - displacement only
+ - displacement + abase
+
+ They are distinguished by the setting of the MEMA_ABASE bit.
+
+ *************************************************************************** */
+static void
+mema_to_memb (opcodeP)
+ char *opcodeP; /* Where to find the opcode, in target byte order */
+{
+ long opcode; /* Opcode in host byte order */
+ long mode; /* Mode bits for MEMB instruction */
+
+ opcode = md_chars_to_number (opcodeP, 4);
+ know (!(opcode & MEMB_BIT));
+
+ mode = MEMB_BIT | D_BIT;
+ if (opcode & MEMA_ABASE)
+ {
+ mode |= A_BIT;
+ }
+
+ opcode &= 0xffffc000; /* Clear MEMA offset and mode bits */
+ opcode |= mode; /* Set MEMB mode bits */
+
+ md_number_to_chars (opcodeP, opcode, 4);
+} /* mema_to_memb() */
+
+
+/*****************************************************************************
+ parse_expr: parse an expression
+
+ Use base assembler's expression parser to parse an expression.
+ It, unfortunately, runs off a global which we have to save/restore
+ in order to make it work for us.
+
+ An empty expression string is treated as an absolute 0.
+
+ Sets O_illegal regardless of expression evaluation if entire input
+ string is not consumed in the evaluation -- tolerate no dangling junk!
+
+ *************************************************************************** */
+static void
+parse_expr (textP, expP)
+ char *textP; /* Text of expression to be parsed */
+ expressionS *expP; /* Where to put the results of parsing */
+{
+ char *save_in; /* Save global here */
+ symbolS *symP;
+
+ know (textP);
+
+ if (*textP == '\0')
+ {
+ /* Treat empty string as absolute 0 */
+ expP->X_add_symbol = expP->X_op_symbol = NULL;
+ expP->X_add_number = 0;
+ expP->X_op = O_constant;
+ }
+ else
+ {
+ save_in = input_line_pointer; /* Save global */
+ input_line_pointer = textP; /* Make parser work for us */
+
+ (void) expression (expP);
+ if ((size_t) (input_line_pointer - textP) != strlen (textP))
+ {
+ /* Did not consume all of the input */
+ expP->X_op = O_illegal;
+ }
+ symP = expP->X_add_symbol;
+ if (symP && (hash_find (reg_hash, S_GET_NAME (symP))))
+ {
+ /* Register name in an expression */
+ /* FIXME: this isn't much of a check any more. */
+ expP->X_op = O_illegal;
+ }
+
+ input_line_pointer = save_in; /* Restore global */
+ }
+}
+
+
+/*****************************************************************************
+ parse_ldcont:
+ Parse and replace a 'ldconst' pseudo-instruction with an appropriate
+ i80960 instruction.
+
+ Assumes the input consists of:
+ arg[0] opcode mnemonic ('ldconst')
+ arg[1] first operand (constant)
+ arg[2] name of register to be loaded
+
+ Replaces opcode and/or operands as appropriate.
+
+ Returns the new number of arguments, or -1 on failure.
+
+ *************************************************************************** */
+static
+int
+parse_ldconst (arg)
+ char *arg[]; /* See above */
+{
+ int n; /* Constant to be loaded */
+ int shift; /* Shift count for "shlo" instruction */
+ static char buf[5]; /* Literal for first operand */
+ static char buf2[5]; /* Literal for second operand */
+ expressionS e; /* Parsed expression */
+
+
+ arg[3] = NULL; /* So we can tell at the end if it got used or not */
+
+ parse_expr (arg[1], &e);
+ switch (e.X_op)
+ {
+ default:
+ /* We're dependent on one or more symbols -- use "lda" */
+ arg[0] = "lda";
+ break;
+
+ case O_constant:
+ /* Try the following mappings:
+ * ldconst 0,<reg> ->mov 0,<reg>
+ * ldconst 31,<reg> ->mov 31,<reg>
+ * ldconst 32,<reg> ->addo 1,31,<reg>
+ * ldconst 62,<reg> ->addo 31,31,<reg>
+ * ldconst 64,<reg> ->shlo 8,3,<reg>
+ * ldconst -1,<reg> ->subo 1,0,<reg>
+ * ldconst -31,<reg>->subo 31,0,<reg>
+ *
+ * anthing else becomes:
+ * lda xxx,<reg>
+ */
+ n = offs (e);
+ if ((0 <= n) && (n <= 31))
+ {
+ arg[0] = "mov";
+
+ }
+ else if ((-31 <= n) && (n <= -1))
+ {
+ arg[0] = "subo";
+ arg[3] = arg[2];
+ sprintf (buf, "%d", -n);
+ arg[1] = buf;
+ arg[2] = "0";
+
+ }
+ else if ((32 <= n) && (n <= 62))
+ {
+ arg[0] = "addo";
+ arg[3] = arg[2];
+ arg[1] = "31";
+ sprintf (buf, "%d", n - 31);
+ arg[2] = buf;
+
+ }
+ else if ((shift = shift_ok (n)) != 0)
+ {
+ arg[0] = "shlo";
+ arg[3] = arg[2];
+ sprintf (buf, "%d", shift);
+ arg[1] = buf;
+ sprintf (buf2, "%d", n >> shift);
+ arg[2] = buf2;
+
+ }
+ else
+ {
+ arg[0] = "lda";
+ }
+ break;
+
+ case O_illegal:
+ as_bad (_("invalid constant"));
+ return -1;
+ break;
+ }
+ return (arg[3] == 0) ? 2 : 3;
+}
+
+/*****************************************************************************
+ parse_memop: parse a memory operand
+
+ This routine is based on the observation that the 4 mode bits of the
+ MEMB format, taken individually, have fairly consistent meaning:
+
+ M3 (bit 13): 1 if displacement is present (D_BIT)
+ M2 (bit 12): 1 for MEMB instructions (MEMB_BIT)
+ M1 (bit 11): 1 if index is present (I_BIT)
+ M0 (bit 10): 1 if abase is present (A_BIT)
+
+ So we parse the memory operand and set bits in the mode as we find
+ things. Then at the end, if we go to MEMB format, we need only set
+ the MEMB bit (M2) and our mode is built for us.
+
+ Unfortunately, I said "fairly consistent". The exceptions:
+
+ DBIA
+ 0100 Would seem illegal, but means "abase-only".
+
+ 0101 Would seem to mean "abase-only" -- it means IP-relative.
+ Must be converted to 0100.
+
+ 0110 Would seem to mean "index-only", but is reserved.
+ We turn on the D bit and provide a 0 displacement.
+
+ The other thing to observe is that we parse from the right, peeling
+ things * off as we go: first any index spec, then any abase, then
+ the displacement.
+
+ *************************************************************************** */
+static
+void
+parse_memop (memP, argP, optype)
+ memS *memP; /* Where to put the results */
+ char *argP; /* Text of the operand to be parsed */
+ int optype; /* MEM1, MEM2, MEM4, MEM8, MEM12, or MEM16 */
+{
+ char *indexP; /* Pointer to index specification with "[]" removed */
+ char *p; /* Temp char pointer */
+ char iprel_flag; /* True if this is an IP-relative operand */
+ int regnum; /* Register number */
+ /* Scale factor: 1,2,4,8, or 16. Later converted to internal format
+ (0,1,2,3,4 respectively). */
+ int scale;
+ int mode; /* MEMB mode bits */
+ int *intP; /* Pointer to register number */
+
+ /* The following table contains the default scale factors for each
+ type of memory instruction. It is accessed using (optype-MEM1)
+ as an index -- thus it assumes the 'optype' constants are
+ assigned consecutive values, in the order they appear in this
+ table. */
+ static const int def_scale[] =
+ {
+ 1, /* MEM1 */
+ 2, /* MEM2 */
+ 4, /* MEM4 */
+ 8, /* MEM8 */
+ -1, /* MEM12 -- no valid default */
+ 16 /* MEM16 */
+ };
+
+
+ iprel_flag = mode = 0;
+
+ /* Any index present? */
+ indexP = get_ispec (argP);
+ if (indexP)
+ {
+ p = strchr (indexP, '*');
+ if (p == NULL)
+ {
+ /* No explicit scale -- use default for this instruction
+ type and assembler mode. */
+ if (flag_mri)
+ scale = 1;
+ else
+ /* GNU960 compatibility */
+ scale = def_scale[optype - MEM1];
+ }
+ else
+ {
+ *p++ = '\0'; /* Eliminate '*' */
+
+ /* Now indexP->a '\0'-terminated register name,
+ * and p->a scale factor.
+ */
+
+ if (!strcmp (p, "16"))
+ {
+ scale = 16;
+ }
+ else if (strchr ("1248", *p) && (p[1] == '\0'))
+ {
+ scale = *p - '0';
+ }
+ else
+ {
+ scale = -1;
+ }
+ }
+
+ regnum = get_regnum (indexP); /* Get index reg. # */
+ if (!IS_RG_REG (regnum))
+ {
+ as_bad (_("invalid index register"));
+ return;
+ }
+
+ /* Convert scale to its binary encoding */
+ switch (scale)
+ {
+ case 1:
+ scale = 0 << 7;
+ break;
+ case 2:
+ scale = 1 << 7;
+ break;
+ case 4:
+ scale = 2 << 7;
+ break;
+ case 8:
+ scale = 3 << 7;
+ break;
+ case 16:
+ scale = 4 << 7;
+ break;
+ default:
+ as_bad (_("invalid scale factor"));
+ return;
+ };
+
+ memP->opcode |= scale | regnum; /* Set index bits in opcode */
+ mode |= I_BIT; /* Found a valid index spec */
+ }
+
+ /* Any abase (Register Indirect) specification present? */
+ if ((p = strrchr (argP, '(')) != NULL)
+ {
+ /* "(" is there -- does it start a legal abase spec? If not, it
+ could be part of a displacement expression. */
+ intP = (int *) hash_find (areg_hash, p);
+ if (intP != NULL)
+ {
+ /* Got an abase here */
+ regnum = *intP;
+ *p = '\0'; /* discard register spec */
+ if (regnum == IPREL)
+ {
+ /* We have to specialcase ip-rel mode */
+ iprel_flag = 1;
+ }
+ else
+ {
+ memP->opcode |= regnum << 14;
+ mode |= A_BIT;
+ }
+ }
+ }
+
+ /* Any expression present? */
+ memP->e = argP;
+ if (*argP != '\0')
+ {
+ mode |= D_BIT;
+ }
+
+ /* Special-case ip-relative addressing */
+ if (iprel_flag)
+ {
+ if (mode & I_BIT)
+ {
+ syntax ();
+ }
+ else
+ {
+ memP->opcode |= 5 << 10; /* IP-relative mode */
+ memP->disp = 32;
+ }
+ return;
+ }
+
+ /* Handle all other modes */
+ switch (mode)
+ {
+ case D_BIT | A_BIT:
+ /* Go with MEMA instruction format for now (grow to MEMB later
+ if 12 bits is not enough for the displacement). MEMA format
+ has a single mode bit: set it to indicate that abase is
+ present. */
+ memP->opcode |= MEMA_ABASE;
+ memP->disp = 12;
+ break;
+
+ case D_BIT:
+ /* Go with MEMA instruction format for now (grow to MEMB later
+ if 12 bits is not enough for the displacement). */
+ memP->disp = 12;
+ break;
+
+ case A_BIT:
+ /* For some reason, the bit string for this mode is not
+ consistent: it should be 0 (exclusive of the MEMB bit), so we
+ set it "by hand" here. */
+ memP->opcode |= MEMB_BIT;
+ break;
+
+ case A_BIT | I_BIT:
+ /* set MEMB bit in mode, and OR in mode bits */
+ memP->opcode |= mode | MEMB_BIT;
+ break;
+
+ case I_BIT:
+ /* Treat missing displacement as displacement of 0. */
+ mode |= D_BIT;
+ /* Fall into next case. */
+ case D_BIT | A_BIT | I_BIT:
+ case D_BIT | I_BIT:
+ /* set MEMB bit in mode, and OR in mode bits */
+ memP->opcode |= mode | MEMB_BIT;
+ memP->disp = 32;
+ break;
+
+ default:
+ syntax ();
+ break;
+ }
+}
+
+/*****************************************************************************
+ parse_po: parse machine-dependent pseudo-op
+
+ This is a top-level routine for machine-dependent pseudo-ops. It slurps
+ up the rest of the input line, breaks out the individual arguments,
+ and dispatches them to the correct handler.
+ *************************************************************************** */
+static
+void
+parse_po (po_num)
+ int po_num; /* Pseudo-op number: currently S_LEAFPROC or S_SYSPROC */
+{
+ /* Pointers operands, with no embedded whitespace.
+ arg[0] unused, arg[1-3]->operands */
+ char *args[4];
+ int n_ops; /* Number of operands */
+ char *p; /* Pointer to beginning of unparsed argument string */
+ char eol; /* Character that indicated end of line */
+
+ extern char is_end_of_line[];
+
+ /* Advance input pointer to end of line. */
+ p = input_line_pointer;
+ while (!is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ input_line_pointer++;
+ }
+ eol = *input_line_pointer; /* Save end-of-line char */
+ *input_line_pointer = '\0'; /* Terminate argument list */
+
+ /* Parse out operands */
+ n_ops = get_args (p, args);
+ if (n_ops == -1)
+ {
+ return;
+ }
+
+ /* Dispatch to correct handler */
+ switch (po_num)
+ {
+ case S_SYSPROC:
+ s_sysproc (n_ops, args);
+ break;
+ case S_LEAFPROC:
+ s_leafproc (n_ops, args);
+ break;
+ default:
+ BAD_CASE (po_num);
+ break;
+ }
+
+ /* Restore eol, so line numbers get updated correctly. Base
+ assembler assumes we leave input pointer pointing at char
+ following the eol. */
+ *input_line_pointer++ = eol;
+}
+
+/*****************************************************************************
+ parse_regop: parse a register operand.
+
+ In case of illegal operand, issue a message and return some valid
+ information so instruction processing can continue.
+ *************************************************************************** */
+static
+void
+parse_regop (regopP, optext, opdesc)
+ struct regop *regopP; /* Where to put description of register operand */
+ char *optext; /* Text of operand */
+ char opdesc; /* Descriptor byte: what's legal for this operand */
+{
+ int n; /* Register number */
+ expressionS e; /* Parsed expression */
+
+ /* See if operand is a register */
+ n = get_regnum (optext);
+ if (n >= 0)
+ {
+ if (IS_RG_REG (n))
+ {
+ /* global or local register */
+ if (!REG_ALIGN (opdesc, n))
+ {
+ as_bad (_("unaligned register"));
+ }
+ regopP->n = n;
+ regopP->mode = 0;
+ regopP->special = 0;
+ return;
+ }
+ else if (IS_FP_REG (n) && FP_OK (opdesc))
+ {
+ /* Floating point register, and it's allowed */
+ regopP->n = n - FP0;
+ regopP->mode = 1;
+ regopP->special = 0;
+ return;
+ }
+ else if (IS_SF_REG (n) && SFR_OK (opdesc))
+ {
+ /* Special-function register, and it's allowed */
+ regopP->n = n - SF0;
+ regopP->mode = 0;
+ regopP->special = 1;
+ if (!targ_has_sfr (regopP->n))
+ {
+ as_bad (_("no such sfr in this architecture"));
+ }
+ return;
+ }
+ }
+ else if (LIT_OK (opdesc))
+ {
+ /* How about a literal? */
+ regopP->mode = 1;
+ regopP->special = 0;
+ if (FP_OK (opdesc))
+ { /* floating point literal acceptable */
+ /* Skip over 0f, 0d, or 0e prefix */
+ if ((optext[0] == '0')
+ && (optext[1] >= 'd')
+ && (optext[1] <= 'f'))
+ {
+ optext += 2;
+ }
+
+ if (!strcmp (optext, "0.0") || !strcmp (optext, "0"))
+ {
+ regopP->n = 0x10;
+ return;
+ }
+ if (!strcmp (optext, "1.0") || !strcmp (optext, "1"))
+ {
+ regopP->n = 0x16;
+ return;
+ }
+
+ }
+ else
+ { /* fixed point literal acceptable */
+ parse_expr (optext, &e);
+ if (e.X_op != O_constant
+ || (offs (e) < 0) || (offs (e) > 31))
+ {
+ as_bad (_("illegal literal"));
+ offs (e) = 0;
+ }
+ regopP->n = offs (e);
+ return;
+ }
+ }
+
+ /* Nothing worked */
+ syntax ();
+ regopP->mode = 0; /* Register r0 is always a good one */
+ regopP->n = 0;
+ regopP->special = 0;
+} /* parse_regop() */
+
+/*****************************************************************************
+ reg_fmt: generate a REG-format instruction
+
+ *************************************************************************** */
+static void
+reg_fmt (args, oP)
+ char *args[]; /* args[0]->opcode mnemonic, args[1-3]->operands */
+ struct i960_opcode *oP; /* Pointer to description of instruction */
+{
+ long instr; /* Binary to be output */
+ struct regop regop; /* Description of register operand */
+ int n_ops; /* Number of operands */
+
+
+ instr = oP->opcode;
+ n_ops = oP->num_ops;
+
+ if (n_ops >= 1)
+ {
+ parse_regop (&regop, args[1], oP->operand[0]);
+
+ if ((n_ops == 1) && !(instr & M3))
+ {
+ /* 1-operand instruction in which the dst field should
+ * be used (instead of src1).
+ */
+ regop.n <<= 19;
+ if (regop.special)
+ {
+ regop.mode = regop.special;
+ }
+ regop.mode <<= 13;
+ regop.special = 0;
+ }
+ else
+ {
+ /* regop.n goes in bit 0, needs no shifting */
+ regop.mode <<= 11;
+ regop.special <<= 5;
+ }
+ instr |= regop.n | regop.mode | regop.special;
+ }
+
+ if (n_ops >= 2)
+ {
+ parse_regop (&regop, args[2], oP->operand[1]);
+
+ if ((n_ops == 2) && !(instr & M3))
+ {
+ /* 2-operand instruction in which the dst field should
+ * be used instead of src2).
+ */
+ regop.n <<= 19;
+ if (regop.special)
+ {
+ regop.mode = regop.special;
+ }
+ regop.mode <<= 13;
+ regop.special = 0;
+ }
+ else
+ {
+ regop.n <<= 14;
+ regop.mode <<= 12;
+ regop.special <<= 6;
+ }
+ instr |= regop.n | regop.mode | regop.special;
+ }
+ if (n_ops == 3)
+ {
+ parse_regop (&regop, args[3], oP->operand[2]);
+ if (regop.special)
+ {
+ regop.mode = regop.special;
+ }
+ instr |= (regop.n <<= 19) | (regop.mode <<= 13);
+ }
+ emit (instr);
+}
+
+
+/*****************************************************************************
+ relax_cobr:
+ Replace cobr instruction in a code fragment with equivalent branch and
+ compare instructions, so it can reach beyond a 13-bit displacement.
+ Set up an address fix/relocation for the new branch instruction.
+
+ *************************************************************************** */
+
+/* This "conditional jump" table maps cobr instructions into
+ equivalent compare and branch opcodes. */
+static const
+struct
+{
+ long compare;
+ long branch;
+}
+
+coj[] =
+{ /* COBR OPCODE: */
+ { CHKBIT, BNO }, /* 0x30 - bbc */
+ { CMPO, BG }, /* 0x31 - cmpobg */
+ { CMPO, BE }, /* 0x32 - cmpobe */
+ { CMPO, BGE }, /* 0x33 - cmpobge */
+ { CMPO, BL }, /* 0x34 - cmpobl */
+ { CMPO, BNE }, /* 0x35 - cmpobne */
+ { CMPO, BLE }, /* 0x36 - cmpoble */
+ { CHKBIT, BO }, /* 0x37 - bbs */
+ { CMPI, BNO }, /* 0x38 - cmpibno */
+ { CMPI, BG }, /* 0x39 - cmpibg */
+ { CMPI, BE }, /* 0x3a - cmpibe */
+ { CMPI, BGE }, /* 0x3b - cmpibge */
+ { CMPI, BL }, /* 0x3c - cmpibl */
+ { CMPI, BNE }, /* 0x3d - cmpibne */
+ { CMPI, BLE }, /* 0x3e - cmpible */
+ { CMPI, BO }, /* 0x3f - cmpibo */
+};
+
+static
+void
+relax_cobr (fragP)
+ register fragS *fragP; /* fragP->fr_opcode is assumed to point to
+ * the cobr instruction, which comes at the
+ * end of the code fragment.
+ */
+{
+ int opcode, src1, src2, m1, s2;
+ /* Bit fields from cobr instruction */
+ long bp_bits; /* Branch prediction bits from cobr instruction */
+ long instr; /* A single i960 instruction */
+ /* ->instruction to be replaced */
+ char *iP;
+ fixS *fixP; /* Relocation that can be done at assembly time */
+
+ /* PICK UP & PARSE COBR INSTRUCTION */
+ iP = fragP->fr_opcode;
+ instr = md_chars_to_number (iP, 4);
+ opcode = ((instr >> 24) & 0xff) - 0x30; /* "-0x30" for table index */
+ src1 = (instr >> 19) & 0x1f;
+ m1 = (instr >> 13) & 1;
+ s2 = instr & 1;
+ src2 = (instr >> 14) & 0x1f;
+ bp_bits = instr & BP_MASK;
+
+ /* GENERATE AND OUTPUT COMPARE INSTRUCTION */
+ instr = coj[opcode].compare
+ | src1 | (m1 << 11) | (s2 << 6) | (src2 << 14);
+ md_number_to_chars (iP, instr, 4);
+
+ /* OUTPUT BRANCH INSTRUCTION */
+ md_number_to_chars (iP + 4, coj[opcode].branch | bp_bits, 4);
+
+ /* SET UP ADDRESS FIXUP/RELOCATION */
+ fixP = fix_new (fragP,
+ iP + 4 - fragP->fr_literal,
+ 4,
+ fragP->fr_symbol,
+ fragP->fr_offset,
+ 1,
+ NO_RELOC);
+
+ fixP->fx_bit_fixP = (bit_fixS *) 24; /* Store size of bit field */
+
+ fragP->fr_fix += 4;
+ frag_wane (fragP);
+}
+
+
+/*****************************************************************************
+ reloc_callj: Relocate a 'callj' instruction
+
+ This is a "non-(GNU)-standard" machine-dependent hook. The base
+ assembler calls it when it decides it can relocate an address at
+ assembly time instead of emitting a relocation directive.
+
+ Check to see if the relocation involves a 'callj' instruction to a:
+ sysproc: Replace the default 'call' instruction with a 'calls'
+ leafproc: Replace the default 'call' instruction with a 'bal'.
+ other proc: Do nothing.
+
+ See b.out.h for details on the 'n_other' field in a symbol structure.
+
+ IMPORTANT!:
+ Assumes the caller has already figured out, in the case of a leafproc,
+ to use the 'bal' entry point, and has substituted that symbol into the
+ passed fixup structure.
+
+ *************************************************************************** */
+void
+reloc_callj (fixP)
+ /* Relocation that can be done at assembly time */
+ fixS *fixP;
+{
+ /* Points to the binary for the instruction being relocated. */
+ char *where;
+
+ if (!fixP->fx_tcbit)
+ {
+ /* This wasn't a callj instruction in the first place */
+ return;
+ }
+
+ where = fixP->fx_frag->fr_literal + fixP->fx_where;
+
+ if (TC_S_IS_SYSPROC (fixP->fx_addsy))
+ {
+ /* Symbol is a .sysproc: replace 'call' with 'calls'. System
+ procedure number is (other-1). */
+ md_number_to_chars (where, CALLS | TC_S_GET_SYSPROC (fixP->fx_addsy), 4);
+
+ /* Nothing else needs to be done for this instruction. Make
+ sure 'md_number_to_field()' will perform a no-op. */
+ fixP->fx_bit_fixP = (bit_fixS *) 1;
+
+ }
+ else if (TC_S_IS_CALLNAME (fixP->fx_addsy))
+ {
+ /* Should not happen: see block comment above */
+ as_fatal (_("Trying to 'bal' to %s"), S_GET_NAME (fixP->fx_addsy));
+ }
+ else if (TC_S_IS_BALNAME (fixP->fx_addsy))
+ {
+ /* Replace 'call' with 'bal'; both instructions have the same
+ format, so calling code should complete relocation as if
+ nothing happened here. */
+ md_number_to_chars (where, BAL, 4);
+ }
+ else if (TC_S_IS_BADPROC (fixP->fx_addsy))
+ {
+ as_bad (_("Looks like a proc, but can't tell what kind.\n"));
+ } /* switch on proc type */
+
+ /* else Symbol is neither a sysproc nor a leafproc */
+}
+
+
+/*****************************************************************************
+ s_leafproc: process .leafproc pseudo-op
+
+ .leafproc takes two arguments, the second one is optional:
+ arg[1]: name of 'call' entry point to leaf procedure
+ arg[2]: name of 'bal' entry point to leaf procedure
+
+ If the two arguments are identical, or if the second one is missing,
+ the first argument is taken to be the 'bal' entry point.
+
+ If there are 2 distinct arguments, we must make sure that the 'bal'
+ entry point immediately follows the 'call' entry point in the linked
+ list of symbols.
+
+ *************************************************************************** */
+static void
+s_leafproc (n_ops, args)
+ int n_ops; /* Number of operands */
+ char *args[]; /* args[1]->1st operand, args[2]->2nd operand */
+{
+ symbolS *callP; /* Pointer to leafproc 'call' entry point symbol */
+ symbolS *balP; /* Pointer to leafproc 'bal' entry point symbol */
+
+ if ((n_ops != 1) && (n_ops != 2))
+ {
+ as_bad (_("should have 1 or 2 operands"));
+ return;
+ } /* Check number of arguments */
+
+ /* Find or create symbol for 'call' entry point. */
+ callP = symbol_find_or_make (args[1]);
+
+ if (TC_S_IS_CALLNAME (callP))
+ {
+ as_warn (_("Redefining leafproc %s"), S_GET_NAME (callP));
+ } /* is leafproc */
+
+ /* If that was the only argument, use it as the 'bal' entry point.
+ * Otherwise, mark it as the 'call' entry point and find or create
+ * another symbol for the 'bal' entry point.
+ */
+ if ((n_ops == 1) || !strcmp (args[1], args[2]))
+ {
+ TC_S_FORCE_TO_BALNAME (callP);
+
+ }
+ else
+ {
+ TC_S_FORCE_TO_CALLNAME (callP);
+
+ balP = symbol_find_or_make (args[2]);
+ if (TC_S_IS_CALLNAME (balP))
+ {
+ as_warn (_("Redefining leafproc %s"), S_GET_NAME (balP));
+ }
+ TC_S_FORCE_TO_BALNAME (balP);
+
+ tc_set_bal_of_call (callP, balP);
+ } /* if only one arg, or the args are the same */
+}
+
+
+/*
+ s_sysproc: process .sysproc pseudo-op
+
+ .sysproc takes two arguments:
+ arg[1]: name of entry point to system procedure
+ arg[2]: 'entry_num' (index) of system procedure in the range
+ [0,31] inclusive.
+
+ For [ab].out, we store the 'entrynum' in the 'n_other' field of
+ the symbol. Since that entry is normally 0, we bias 'entrynum'
+ by adding 1 to it. It must be unbiased before it is used. */
+static void
+s_sysproc (n_ops, args)
+ int n_ops; /* Number of operands */
+ char *args[]; /* args[1]->1st operand, args[2]->2nd operand */
+{
+ expressionS exp;
+ symbolS *symP;
+
+ if (n_ops != 2)
+ {
+ as_bad (_("should have two operands"));
+ return;
+ } /* bad arg count */
+
+ /* Parse "entry_num" argument and check it for validity. */
+ parse_expr (args[2], &exp);
+ if (exp.X_op != O_constant
+ || (offs (exp) < 0)
+ || (offs (exp) > 31))
+ {
+ as_bad (_("'entry_num' must be absolute number in [0,31]"));
+ return;
+ }
+
+ /* Find/make symbol and stick entry number (biased by +1) into it */
+ symP = symbol_find_or_make (args[1]);
+
+ if (TC_S_IS_SYSPROC (symP))
+ {
+ as_warn (_("Redefining entrynum for sysproc %s"), S_GET_NAME (symP));
+ } /* redefining */
+
+ TC_S_SET_SYSPROC (symP, offs (exp)); /* encode entry number */
+ TC_S_FORCE_TO_SYSPROC (symP);
+}
+
+
+/*****************************************************************************
+ shift_ok:
+ Determine if a "shlo" instruction can be used to implement a "ldconst".
+ This means that some number X < 32 can be shifted left to produce the
+ constant of interest.
+
+ Return the shift count, or 0 if we can't do it.
+ Caller calculates X by shifting original constant right 'shift' places.
+
+ *************************************************************************** */
+static
+int
+shift_ok (n)
+ int n; /* The constant of interest */
+{
+ int shift; /* The shift count */
+
+ if (n <= 0)
+ {
+ /* Can't do it for negative numbers */
+ return 0;
+ }
+
+ /* Shift 'n' right until a 1 is about to be lost */
+ for (shift = 0; (n & 1) == 0; shift++)
+ {
+ n >>= 1;
+ }
+
+ if (n >= 32)
+ {
+ return 0;
+ }
+ return shift;
+}
+
+
+/* syntax: issue syntax error */
+
+static void
+syntax ()
+{
+ as_bad (_("syntax error"));
+} /* syntax() */
+
+
+/* targ_has_sfr:
+
+ Return TRUE iff the target architecture supports the specified
+ special-function register (sfr). */
+
+static
+int
+targ_has_sfr (n)
+ int n; /* Number (0-31) of sfr */
+{
+ switch (architecture)
+ {
+ case ARCH_KA:
+ case ARCH_KB:
+ case ARCH_MC:
+ case ARCH_JX:
+ return 0;
+ case ARCH_HX:
+ return ((0 <= n) && (n <= 4));
+ case ARCH_CA:
+ default:
+ return ((0 <= n) && (n <= 2));
+ }
+}
+
+
+/* targ_has_iclass:
+
+ Return TRUE iff the target architecture supports the indicated
+ class of instructions. */
+static
+int
+targ_has_iclass (ic)
+ /* Instruction class; one of:
+ I_BASE, I_CX, I_DEC, I_KX, I_FP, I_MIL, I_CASIM, I_CX2, I_HX, I_HX2
+ */
+ int ic;
+{
+ iclasses_seen |= ic;
+ switch (architecture)
+ {
+ case ARCH_KA:
+ return ic & (I_BASE | I_KX);
+ case ARCH_KB:
+ return ic & (I_BASE | I_KX | I_FP | I_DEC);
+ case ARCH_MC:
+ return ic & (I_BASE | I_KX | I_FP | I_DEC | I_MIL);
+ case ARCH_CA:
+ return ic & (I_BASE | I_CX | I_CX2 | I_CASIM);
+ case ARCH_JX:
+ return ic & (I_BASE | I_CX2 | I_JX);
+ case ARCH_HX:
+ return ic & (I_BASE | I_CX2 | I_JX | I_HX);
+ default:
+ if ((iclasses_seen & (I_KX | I_FP | I_DEC | I_MIL))
+ && (iclasses_seen & (I_CX | I_CX2)))
+ {
+ as_warn (_("architecture of opcode conflicts with that of earlier instruction(s)"));
+ iclasses_seen &= ~ic;
+ }
+ return 1;
+ }
+}
+
+/* Handle the MRI .endian pseudo-op. */
+
+static void
+s_endian (ignore)
+ int ignore;
+{
+ char *name;
+ char c;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ if (strcasecmp (name, "little") == 0)
+ ;
+ else if (strcasecmp (name, "big") == 0)
+ as_bad (_("big endian mode is not supported"));
+ else
+ as_warn (_("ignoring unrecognized .endian type `%s'"), name);
+
+ *input_line_pointer = c;
+
+ demand_empty_rest_of_line ();
+}
+
+/* We have no need to default values of symbols. */
+
+/* ARGSUSED */
+symbolS *
+md_undefined_symbol (name)
+ char *name;
+{
+ return 0;
+}
+
+/* Exactly what point is a PC-relative offset relative TO?
+ On the i960, they're relative to the address of the instruction,
+ which we have set up as the address of the fixup too. */
+long
+md_pcrel_from (fixP)
+ fixS *fixP;
+{
+ return fixP->fx_where + fixP->fx_frag->fr_address;
+}
+
+void
+md_apply_fix (fixP, val)
+ fixS *fixP;
+ long val;
+{
+ char *place = fixP->fx_where + fixP->fx_frag->fr_literal;
+
+ if (!fixP->fx_bit_fixP)
+ {
+ /* For callx, we always want to write out zero, and emit a
+ symbolic relocation. */
+ if (fixP->fx_bsr)
+ val = 0;
+
+ fixP->fx_addnumber = val;
+ md_number_to_imm (place, val, fixP->fx_size, fixP);
+ }
+ else
+ md_number_to_field (place, val, fixP->fx_bit_fixP);
+}
+
+#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
+void
+tc_bout_fix_to_chars (where, fixP, segment_address_in_file)
+ char *where;
+ fixS *fixP;
+ relax_addressT segment_address_in_file;
+{
+ static const unsigned char nbytes_r_length[] = {42, 0, 1, 42, 2};
+ struct relocation_info ri;
+ symbolS *symbolP;
+
+ memset ((char *) &ri, '\0', sizeof (ri));
+ symbolP = fixP->fx_addsy;
+ know (symbolP != 0 || fixP->fx_r_type != NO_RELOC);
+ ri.r_bsr = fixP->fx_bsr; /*SAC LD RELAX HACK */
+ /* These two 'cuz of NS32K */
+ ri.r_callj = fixP->fx_tcbit;
+ if (fixP->fx_bit_fixP)
+ ri.r_length = 2;
+ else
+ ri.r_length = nbytes_r_length[fixP->fx_size];
+ ri.r_pcrel = fixP->fx_pcrel;
+ ri.r_address = fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file;
+
+ if (fixP->fx_r_type != NO_RELOC)
+ {
+ switch (fixP->fx_r_type)
+ {
+ case rs_align:
+ ri.r_index = -2;
+ ri.r_pcrel = 1;
+ ri.r_length = fixP->fx_size - 1;
+ break;
+ case rs_org:
+ ri.r_index = -2;
+ ri.r_pcrel = 0;
+ break;
+ case rs_fill:
+ ri.r_index = -1;
+ break;
+ default:
+ abort ();
+ }
+ ri.r_extern = 0;
+ }
+ else if (linkrelax || !S_IS_DEFINED (symbolP) || fixP->fx_bsr)
+ {
+ ri.r_extern = 1;
+ ri.r_index = symbolP->sy_number;
+ }
+ else
+ {
+ ri.r_extern = 0;
+ ri.r_index = S_GET_TYPE (symbolP);
+ }
+
+ /* Output the relocation information in machine-dependent form. */
+ md_ri_to_chars (where, &ri);
+}
+
+#endif /* OBJ_AOUT or OBJ_BOUT */
+
+#if defined (OBJ_COFF) && defined (BFD)
+short
+tc_coff_fix2rtype (fixP)
+ fixS *fixP;
+{
+ if (fixP->fx_bsr)
+ abort ();
+
+ if (fixP->fx_pcrel == 0 && fixP->fx_size == 4)
+ return R_RELLONG;
+
+ if (fixP->fx_pcrel != 0 && fixP->fx_size == 4)
+ return R_IPRMED;
+
+ abort ();
+ return 0;
+}
+
+int
+tc_coff_sizemachdep (frag)
+ fragS *frag;
+{
+ if (frag->fr_next)
+ return frag->fr_next->fr_address - frag->fr_address;
+ else
+ return 0;
+}
+#endif
+
+/* Align an address by rounding it up to the specified boundary. */
+valueT
+md_section_align (seg, addr)
+ segT seg;
+ valueT addr; /* Address to be rounded up */
+{
+ return ((addr + (1 << section_alignment[(int) seg]) - 1) & (-1 << section_alignment[(int) seg]));
+} /* md_section_align() */
+
+extern int coff_flags;
+
+#ifdef OBJ_COFF
+void
+tc_headers_hook (headers)
+ object_headers *headers;
+{
+ switch (architecture)
+ {
+ case ARCH_KA:
+ coff_flags |= F_I960KA;
+ break;
+
+ case ARCH_KB:
+ coff_flags |= F_I960KB;
+ break;
+
+ case ARCH_MC:
+ coff_flags |= F_I960MC;
+ break;
+
+ case ARCH_CA:
+ coff_flags |= F_I960CA;
+ break;
+
+ case ARCH_JX:
+ coff_flags |= F_I960JX;
+ break;
+
+ case ARCH_HX:
+ coff_flags |= F_I960HX;
+ break;
+
+ default:
+ if (iclasses_seen == I_BASE)
+ coff_flags |= F_I960CORE;
+ else if (iclasses_seen & I_CX)
+ coff_flags |= F_I960CA;
+ else if (iclasses_seen & I_HX)
+ coff_flags |= F_I960HX;
+ else if (iclasses_seen & I_JX)
+ coff_flags |= F_I960JX;
+ else if (iclasses_seen & I_CX2)
+ coff_flags |= F_I960CA;
+ else if (iclasses_seen & I_MIL)
+ coff_flags |= F_I960MC;
+ else if (iclasses_seen & (I_DEC | I_FP))
+ coff_flags |= F_I960KB;
+ else
+ coff_flags |= F_I960KA;
+ break;
+ }
+
+ if (flag_readonly_data_in_text)
+ {
+ headers->filehdr.f_magic = I960RWMAGIC;
+ headers->aouthdr.magic = OMAGIC;
+ }
+ else
+ {
+ headers->filehdr.f_magic = I960ROMAGIC;
+ headers->aouthdr.magic = NMAGIC;
+ } /* set magic numbers */
+}
+
+#endif /* OBJ_COFF */
+
+/* Things going on here:
+
+ For bout, We need to assure a couple of simplifying
+ assumptions about leafprocs for the linker: the leafproc
+ entry symbols will be defined in the same assembly in
+ which they're declared with the '.leafproc' directive;
+ and if a leafproc has both 'call' and 'bal' entry points
+ they are both global or both local.
+
+ For coff, the call symbol has a second aux entry that
+ contains the bal entry point. The bal symbol becomes a
+ label.
+
+ For coff representation, the call symbol has a second aux entry that
+ contains the bal entry point. The bal symbol becomes a label. */
+
+void
+tc_crawl_symbol_chain (headers)
+ object_headers *headers;
+{
+ symbolS *symbolP;
+
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
+ {
+#ifdef OBJ_COFF
+ if (TC_S_IS_SYSPROC (symbolP))
+ {
+ /* second aux entry already contains the sysproc number */
+ S_SET_NUMBER_AUXILIARY (symbolP, 2);
+ S_SET_STORAGE_CLASS (symbolP, C_SCALL);
+ S_SET_DATA_TYPE (symbolP, S_GET_DATA_TYPE (symbolP) | (DT_FCN << N_BTSHFT));
+ continue;
+ } /* rewrite sysproc */
+#endif /* OBJ_COFF */
+
+ if (!TC_S_IS_BALNAME (symbolP) && !TC_S_IS_CALLNAME (symbolP))
+ {
+ continue;
+ } /* Not a leafproc symbol */
+
+ if (!S_IS_DEFINED (symbolP))
+ {
+ as_bad (_("leafproc symbol '%s' undefined"), S_GET_NAME (symbolP));
+ } /* undefined leaf */
+
+ if (TC_S_IS_CALLNAME (symbolP))
+ {
+ symbolS *balP = tc_get_bal_of_call (symbolP);
+ if (S_IS_EXTERNAL (symbolP) != S_IS_EXTERNAL (balP))
+ {
+ S_SET_EXTERNAL (symbolP);
+ S_SET_EXTERNAL (balP);
+ as_warn (_("Warning: making leafproc entries %s and %s both global\n"),
+ S_GET_NAME (symbolP), S_GET_NAME (balP));
+ } /* externality mismatch */
+ } /* if callname */
+ } /* walk the symbol chain */
+}
+
+/* For aout or bout, the bal immediately follows the call.
+
+ For coff, we cheat and store a pointer to the bal symbol in the
+ second aux entry of the call. */
+
+#undef OBJ_ABOUT
+#ifdef OBJ_AOUT
+#define OBJ_ABOUT
+#endif
+#ifdef OBJ_BOUT
+#define OBJ_ABOUT
+#endif
+
+void
+tc_set_bal_of_call (callP, balP)
+ symbolS *callP;
+ symbolS *balP;
+{
+ know (TC_S_IS_CALLNAME (callP));
+ know (TC_S_IS_BALNAME (balP));
+
+#ifdef OBJ_COFF
+
+ callP->sy_tc = balP;
+ S_SET_NUMBER_AUXILIARY (callP, 2);
+
+#else /* ! OBJ_COFF */
+#ifdef OBJ_ABOUT
+
+ /* If the 'bal' entry doesn't immediately follow the 'call'
+ * symbol, unlink it from the symbol list and re-insert it.
+ */
+ if (symbol_next (callP) != balP)
+ {
+ symbol_remove (balP, &symbol_rootP, &symbol_lastP);
+ symbol_append (balP, callP, &symbol_rootP, &symbol_lastP);
+ } /* if not in order */
+
+#else /* ! OBJ_ABOUT */
+ (as yet unwritten.);
+#endif /* ! OBJ_ABOUT */
+#endif /* ! OBJ_COFF */
+}
+
+symbolS *
+tc_get_bal_of_call (callP)
+ symbolS *callP;
+{
+ symbolS *retval;
+
+ know (TC_S_IS_CALLNAME (callP));
+
+#ifdef OBJ_COFF
+ retval = callP->sy_tc;
+#else
+#ifdef OBJ_ABOUT
+ retval = symbol_next (callP);
+#else
+ (as yet unwritten.);
+#endif /* ! OBJ_ABOUT */
+#endif /* ! OBJ_COFF */
+
+ know (TC_S_IS_BALNAME (retval));
+ return retval;
+} /* _tc_get_bal_of_call() */
+
+void
+tc_coff_symbol_emit_hook (symbolP)
+ symbolS *symbolP;
+{
+ if (TC_S_IS_CALLNAME (symbolP))
+ {
+#ifdef OBJ_COFF
+ symbolS *balP = tc_get_bal_of_call (symbolP);
+
+#if 0
+ /* second aux entry contains the bal entry point */
+ S_SET_NUMBER_AUXILIARY (symbolP, 2);
+#endif
+ symbolP->sy_symbol.ost_auxent[1].x_bal.x_balntry = S_GET_VALUE (balP);
+ if (S_GET_STORAGE_CLASS (symbolP) == C_EXT)
+ S_SET_STORAGE_CLASS (symbolP, C_LEAFEXT);
+ else
+ S_SET_STORAGE_CLASS (symbolP, C_LEAFSTAT);
+ S_SET_DATA_TYPE (symbolP, S_GET_DATA_TYPE (symbolP) | (DT_FCN << N_BTSHFT));
+ /* fix up the bal symbol */
+ S_SET_STORAGE_CLASS (balP, C_LABEL);
+#endif /* OBJ_COFF */
+ } /* only on calls */
+}
+
+void
+i960_handle_align (fragp)
+ fragS *fragp;
+{
+ if (!linkrelax)
+ return;
+
+#ifndef OBJ_BOUT
+
+ as_bad (_("option --link-relax is only supported in b.out format"));
+ linkrelax = 0;
+ return;
+
+#else
+
+ /* The text section "ends" with another alignment reloc, to which we
+ aren't adding padding. */
+ if (fragp->fr_next == text_last_frag
+ || fragp->fr_next == data_last_frag)
+ return;
+
+ /* alignment directive */
+ fix_new (fragp, fragp->fr_fix, fragp->fr_offset, 0, 0, 0,
+ (int) fragp->fr_type);
+#endif /* OBJ_BOUT */
+}
+
+int
+i960_validate_fix (fixP, this_segment_type, add_symbolPP)
+ fixS *fixP;
+ segT this_segment_type;
+ symbolS **add_symbolPP;
+{
+#define add_symbolP (*add_symbolPP)
+ if (fixP->fx_tcbit && TC_S_IS_CALLNAME (add_symbolP))
+ {
+ /* Relocation should be done via the associated 'bal'
+ entry point symbol. */
+
+ if (!TC_S_IS_BALNAME (tc_get_bal_of_call (add_symbolP)))
+ {
+ as_bad (_("No 'bal' entry point for leafproc %s"),
+ S_GET_NAME (add_symbolP));
+ return 1;
+ }
+ fixP->fx_addsy = add_symbolP = tc_get_bal_of_call (add_symbolP);
+ }
+#if 0
+ /* Still have to work out other conditions for these tests. */
+ {
+ if (fixP->fx_tcbit)
+ {
+ as_bad (_("callj to difference of two symbols"));
+ return 1;
+ }
+ reloc_callj (fixP);
+ if ((int) fixP->fx_bit_fixP == 13)
+ {
+ /* This is a COBR instruction. They have only a 13-bit
+ displacement and are only to be used for local branches:
+ flag as error, don't generate relocation. */
+ as_bad (_("can't use COBR format with external label"));
+ fixP->fx_addsy = NULL; /* No relocations please. */
+ return 1;
+ }
+ }
+#endif
+#undef add_symbolP
+ return 0;
+}
+
+/* end of tc-i960.c */
diff --git a/gas/config/tc-i960.h b/gas/config/tc-i960.h
new file mode 100644
index 0000000000..f60696751f
--- /dev/null
+++ b/gas/config/tc-i960.h
@@ -0,0 +1,171 @@
+/* tc-i960.h - Basic 80960 instruction formats.
+ Copyright (C) 1989, 90, 91, 92, 93, 94, 95, 96, 97, 1998
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2,
+ or (at your option) any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#ifndef TC_I960
+#define TC_I960 1
+
+#define TARGET_BYTES_BIG_ENDIAN 0
+
+#define WORKING_DOT_WORD
+
+/*
+ * The 'COJ' instructions are actually COBR instructions with the 'b' in
+ * the mnemonic replaced by a 'j'; they are ALWAYS "de-optimized" if necessary:
+ * if the displacement will not fit in 13 bits, the assembler will replace them
+ * with the corresponding compare and branch instructions.
+ *
+ * All of the 'MEMn' instructions are the same format; the 'n' in the name
+ * indicates the default index scale factor (the size of the datum operated on).
+ *
+ * The FBRA formats are not actually an instruction format. They are the
+ * "convenience directives" for branching on floating-point comparisons,
+ * each of which generates 2 instructions (a 'bno' and one other branch).
+ *
+ * The CALLJ format is not actually an instruction format. It indicates that
+ * the instruction generated (a CTRL-format 'call') should have its relocation
+ * specially flagged for link-time replacement with a 'bal' or 'calls' if
+ * appropriate.
+ */
+
+/* tailor gas */
+#define SYMBOLS_NEED_BACKPOINTERS
+#define LOCAL_LABELS_FB 1
+#define BITFIELD_CONS_EXPRESSIONS
+
+/* tailor the coff format */
+#define BFD_ARCH bfd_arch_i960
+#define COFF_FLAGS F_AR32WR
+#define COFF_MAGIC I960ROMAGIC
+#define OBJ_COFF_SECTION_HEADER_HAS_ALIGNMENT
+#define OBJ_COFF_MAX_AUXENTRIES (2)
+#define TC_COUNT_RELOC(FIXP) (!(FIXP)->fx_done)
+#define TC_COFF_FIX2RTYPE(FIXP) tc_coff_fix2rtype(FIXP)
+#define TC_COFF_SIZEMACHDEP(FRAGP) tc_coff_sizemachdep(FRAGP)
+#define TC_COFF_SET_MACHINE(HDRS) tc_headers_hook (HDRS)
+extern void tc_headers_hook ();
+extern short tc_coff_fix2rtype ();
+extern int tc_coff_sizemachdep ();
+
+/* MEANING OF 'n_other' in the symbol record.
+ *
+ * If non-zero, the 'n_other' fields indicates either a leaf procedure or
+ * a system procedure, as follows:
+ *
+ * 1 <= n_other <= 32 :
+ * The symbol is the entry point to a system procedure.
+ * 'n_value' is the address of the entry, as for any other
+ * procedure. The system procedure number (which can be used in
+ * a 'calls' instruction) is (n_other-1). These entries come from
+ * '.sysproc' directives.
+ *
+ * n_other == N_CALLNAME
+ * the symbol is the 'call' entry point to a leaf procedure.
+ * The *next* symbol in the symbol table must be the corresponding
+ * 'bal' entry point to the procedure (see following). These
+ * entries come from '.leafproc' directives in which two different
+ * symbols are specified (the first one is represented here).
+ *
+ *
+ * n_other == N_BALNAME
+ * the symbol is the 'bal' entry point to a leaf procedure.
+ * These entries result from '.leafproc' directives in which only
+ * one symbol is specified, or in which the same symbol is
+ * specified twice.
+ *
+ * Note that an N_CALLNAME entry *must* have a corresponding N_BALNAME entry,
+ * but not every N_BALNAME entry must have an N_CALLNAME entry.
+ */
+#define N_CALLNAME ((char)-1)
+#define N_BALNAME ((char)-2)
+
+/* i960 uses a custom relocation record. */
+
+/* let obj-aout.h know */
+#define CUSTOM_RELOC_FORMAT 1
+/* let aout_gnu.h know */
+#define N_RELOCATION_INFO_DECLARED 1
+struct relocation_info
+ {
+ int r_address; /* File address of item to be relocated */
+ unsigned
+ r_index:24, /* Index of symbol on which relocation is based*/
+ r_pcrel:1, /* 1 => relocate PC-relative; else absolute
+ * On i960, pc-relative implies 24-bit
+ * address, absolute implies 32-bit.
+ */
+ r_length:2, /* Number of bytes to relocate:
+ * 0 => 1 byte
+ * 1 => 2 bytes
+ * 2 => 4 bytes -- only value used for i960
+ */
+ r_extern:1, r_bsr:1, /* Something for the GNU NS32K assembler */
+ r_disp:1, /* Something for the GNU NS32K assembler */
+ r_callj:1, /* 1 if relocation target is an i960 'callj' */
+ nuthin:1; /* Unused */
+ };
+
+#ifdef OBJ_COFF
+
+/* We store the bal information in the sy_tc field. */
+#define TC_SYMFIELD_TYPE struct symbol *
+
+#define TC_ADJUST_RELOC_COUNT(FIXP,COUNT) \
+ { fixS *tcfixp = (FIXP); \
+ for (;tcfixp;tcfixp=tcfixp->fx_next) \
+ if (tcfixp->fx_tcbit && tcfixp->fx_addsy != 0) \
+ ++(COUNT); \
+ }
+#endif
+
+extern int i960_validate_fix PARAMS ((struct fix *, segT, struct symbol **));
+#define TC_VALIDATE_FIX(FIXP,SEGTYPE,LABEL) \
+ if (i960_validate_fix (FIXP, SEGTYPE, &add_symbolP) != 0) goto LABEL
+
+#define tc_fix_adjustable(FIXP) ((FIXP)->fx_bsr == 0)
+
+extern void brtab_emit PARAMS ((void));
+#define md_end() brtab_emit ()
+
+extern void reloc_callj ();
+
+extern void tc_set_bal_of_call PARAMS ((struct symbol *, struct symbol *));
+
+extern struct symbol *tc_get_bal_of_call PARAMS ((struct symbol *));
+
+extern void i960_handle_align ();
+#define HANDLE_ALIGN(FRAG) i960_handle_align (FRAG)
+#define NEED_FX_R_TYPE
+#define NO_RELOC -1
+
+#define md_operand(x)
+
+extern const struct relax_type md_relax_table[];
+#define TC_GENERIC_RELAX_TABLE md_relax_table
+
+#define LINKER_RELAXING_SHRINKS_ONLY
+
+#define TC_FIX_TYPE struct { unsigned bsr : 1; }
+#define fx_bsr tc_fix_data.bsr
+#define TC_INIT_FIX_DATA(F) ((F)->tc_fix_data.bsr = 0)
+
+#endif
+
+/* end of tc-i960.h */
diff --git a/gas/config/tc-m32r.c b/gas/config/tc-m32r.c
new file mode 100644
index 0000000000..997e62316c
--- /dev/null
+++ b/gas/config/tc-m32r.c
@@ -0,0 +1,1300 @@
+/* tc-m32r.c -- Assembler for the Mitsubishi M32R.
+ Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "as.h"
+#include "subsegs.h"
+#include "symcat.h"
+#include "opcodes/m32r-desc.h"
+#include "opcodes/m32r-opc.h"
+#include "cgen.h"
+
+/* Linked list of symbols that are debugging symbols to be defined as the
+ beginning of the current instruction. */
+typedef struct sym_link
+{
+ struct sym_link *next;
+ symbolS *symbol;
+} sym_linkS;
+
+static sym_linkS *debug_sym_link = (sym_linkS *)0;
+
+/* Structure to hold all of the different components describing
+ an individual instruction. */
+typedef struct
+{
+ const CGEN_INSN * insn;
+ const CGEN_INSN * orig_insn;
+ CGEN_FIELDS fields;
+#if CGEN_INT_INSN_P
+ CGEN_INSN_INT buffer [1];
+#define INSN_VALUE(buf) (*(buf))
+#else
+ unsigned char buffer [CGEN_MAX_INSN_SIZE];
+#define INSN_VALUE(buf) (buf)
+#endif
+ char * addr;
+ fragS * frag;
+ int num_fixups;
+ fixS * fixups [GAS_CGEN_MAX_FIXUPS];
+ int indices [MAX_OPERAND_INSTANCES];
+ sym_linkS *debug_sym_link;
+}
+m32r_insn;
+
+/* prev_insn.insn is non-null if last insn was a 16 bit insn on a 32 bit
+ boundary (i.e. was the first of two 16 bit insns). */
+static m32r_insn prev_insn;
+
+/* Non-zero if we've seen a relaxable insn since the last 32 bit
+ alignment request. */
+static int seen_relaxable_p = 0;
+
+/* Non-zero if -relax specified, in which case sufficient relocs are output
+ for the linker to do relaxing.
+ We do simple forms of relaxing internally, but they are always done.
+ This flag does not apply to them. */
+static int m32r_relax;
+
+#if 0 /* not supported yet */
+/* If non-NULL, pointer to cpu description file to read.
+ This allows runtime additions to the assembler. */
+static const char * m32r_cpu_desc;
+#endif
+
+/* Non-zero if warn when a high/shigh reloc has no matching low reloc.
+ Each high/shigh reloc must be paired with it's low cousin in order to
+ properly calculate the addend in a relocatable link (since there is a
+ potential carry from the low to the high/shigh).
+ This option is off by default though for user-written assembler code it
+ might make sense to make the default be on (i.e. have gcc pass a flag
+ to turn it off). This warning must not be on for GCC created code as
+ optimization may delete the low but not the high/shigh (at least we
+ shouldn't assume or require it to). */
+static int warn_unmatched_high = 0;
+
+
+/* stuff for .scomm symbols. */
+static segT sbss_section;
+static asection scom_section;
+static asymbol scom_symbol;
+
+const char comment_chars[] = ";";
+const char line_comment_chars[] = "#";
+const char line_separator_chars[] = "";
+const char EXP_CHARS[] = "eE";
+const char FLT_CHARS[] = "dD";
+
+/* Relocations against symbols are done in two
+ parts, with a HI relocation and a LO relocation. Each relocation
+ has only 16 bits of space to store an addend. This means that in
+ order for the linker to handle carries correctly, it must be able
+ to locate both the HI and the LO relocation. This means that the
+ relocations must appear in order in the relocation table.
+
+ In order to implement this, we keep track of each unmatched HI
+ relocation. We then sort them so that they immediately precede the
+ corresponding LO relocation. */
+
+struct m32r_hi_fixup
+{
+ struct m32r_hi_fixup * next; /* Next HI fixup. */
+ fixS * fixp; /* This fixup. */
+ segT seg; /* The section this fixup is in. */
+
+};
+
+/* The list of unmatched HI relocs. */
+
+static struct m32r_hi_fixup * m32r_hi_fixup_list;
+
+
+
+#define M32R_SHORTOPTS ""
+const char * md_shortopts = M32R_SHORTOPTS;
+
+struct option md_longopts[] =
+{
+
+ /* Sigh. I guess all warnings must now have both variants. */
+#define OPTION_WARN_UNMATCHED (OPTION_MD_BASE + 4)
+ {"warn-unmatched-high", OPTION_WARN_UNMATCHED},
+ {"Wuh", OPTION_WARN_UNMATCHED},
+#define OPTION_NO_WARN_UNMATCHED (OPTION_MD_BASE + 5)
+ {"no-warn-unmatched-high", OPTION_WARN_UNMATCHED},
+ {"Wnuh", OPTION_WARN_UNMATCHED},
+
+#if 0 /* not supported yet */
+#define OPTION_RELAX (OPTION_MD_BASE + 6)
+ {"relax", no_argument, NULL, OPTION_RELAX},
+#define OPTION_CPU_DESC (OPTION_MD_BASE + 7)
+ {"cpu-desc", required_argument, NULL, OPTION_CPU_DESC},
+#endif
+
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof (md_longopts);
+
+int
+md_parse_option (c, arg)
+ int c;
+ char * arg;
+{
+ switch (c)
+ {
+
+ case OPTION_WARN_UNMATCHED:
+ warn_unmatched_high = 1;
+ break;
+
+ case OPTION_NO_WARN_UNMATCHED:
+ warn_unmatched_high = 0;
+ break;
+
+#if 0 /* not supported yet */
+ case OPTION_RELAX:
+ m32r_relax = 1;
+ break;
+ case OPTION_CPU_DESC:
+ m32r_cpu_desc = arg;
+ break;
+#endif
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+void
+md_show_usage (stream)
+ FILE * stream;
+{
+ fprintf (stream, _(" M32R specific command line options:\n"));
+
+
+ fprintf (stream, _("\
+ -warn-unmatched-high warn when an (s)high reloc has no matching low reloc\n"));
+ fprintf (stream, _("\
+ -no-warn-unmatched-high do not warn about missing low relocs\n"));
+ fprintf (stream, _("\
+ -Wuh synonym for -warn-unmatched-high\n"));
+ fprintf (stream, _("\
+ -Wnuh synonym for -no-warn-unmatched-high\n"));
+
+#if 0
+ fprintf (stream, _("\
+ -relax create linker relaxable code\n"));
+ fprintf (stream, _("\
+ -cpu-desc provide runtime cpu description file\n"));
+#endif
+}
+
+static void fill_insn PARAMS ((int));
+static void m32r_scomm PARAMS ((int));
+static void debug_sym PARAMS ((int));
+static void expand_debug_syms PARAMS ((sym_linkS *, int));
+
+/* Set by md_assemble for use by m32r_fill_insn. */
+static subsegT prev_subseg;
+static segT prev_seg;
+
+/* The target specific pseudo-ops which we support. */
+const pseudo_typeS md_pseudo_table[] =
+{
+ { "word", cons, 4 },
+ { "fillinsn", fill_insn, 0 },
+ { "scomm", m32r_scomm, 0 },
+ { "debugsym", debug_sym, 0 },
+ { NULL, NULL, 0 }
+};
+
+/* FIXME: Should be machine generated. */
+#define NOP_INSN 0x7000
+#define PAR_NOP_INSN 0xf000 /* can only be used in 2nd slot */
+
+/* When we align the .text section, insert the correct NOP pattern.
+ N is the power of 2 alignment. LEN is the length of pattern FILL.
+ MAX is the maximum number of characters to skip when doing the alignment,
+ or 0 if there is no maximum. */
+
+int
+m32r_do_align (n, fill, len, max)
+ int n;
+ const char * fill;
+ int len;
+ int max;
+{
+ /* Only do this if the fill pattern wasn't specified. */
+ if (fill == NULL
+ && (now_seg->flags & SEC_CODE) != 0
+ /* Only do this special handling if aligning to at least a
+ 4 byte boundary. */
+ && n > 1
+ /* Only do this special handling if we're allowed to emit at
+ least two bytes. */
+ && (max == 0 || max > 1))
+ {
+ static const unsigned char nop_pattern[] = { 0xf0, 0x00 };
+
+#if 0
+ /* First align to a 2 byte boundary, in case there is an odd .byte. */
+ /* FIXME: How much memory will cause gas to use when assembling a big
+ program? Perhaps we can avoid the frag_align call? */
+ frag_align (1, 0, 0);
+#endif
+ /* Next align to a 4 byte boundary (we know n >= 2) using a parallel
+ nop. */
+ frag_align_pattern (2, nop_pattern, sizeof nop_pattern, 0);
+ /* If doing larger alignments use a repeating sequence of appropriate
+ nops. */
+ if (n > 2)
+ {
+ static const unsigned char multi_nop_pattern[] =
+ { 0x70, 0x00, 0xf0, 0x00 };
+ frag_align_pattern (n, multi_nop_pattern, sizeof multi_nop_pattern,
+ max ? max - 2 : 0);
+ }
+
+ prev_insn.insn = NULL;
+ return 1;
+ }
+
+ return 0;
+}
+
+/* If the last instruction was the first of 2 16 bit insns,
+ output a nop to move the PC to a 32 bit boundary.
+
+ This is done via an alignment specification since branch relaxing
+ may make it unnecessary.
+
+ Internally, we need to output one of these each time a 32 bit insn is
+ seen after an insn that is relaxable. */
+
+static void
+fill_insn (ignore)
+ int ignore;
+{
+ (void) m32r_do_align (2, NULL, 0, 0);
+ prev_insn.insn = NULL;
+ seen_relaxable_p = 0;
+}
+
+/* Record the symbol so that when we output the insn, we can create
+ a symbol that is at the start of the instruction. This is used
+ to emit the label for the start of a breakpoint without causing
+ the assembler to emit a NOP if the previous instruction was a
+ 16 bit instruction. */
+
+static void
+debug_sym (ignore)
+ int ignore;
+{
+ register char *name;
+ register char delim;
+ register char *end_name;
+ register symbolS *symbolP;
+ register sym_linkS *link;
+
+ name = input_line_pointer;
+ delim = get_symbol_end ();
+ end_name = input_line_pointer;
+
+ if ((symbolP = symbol_find (name)) == NULL
+ && (symbolP = md_undefined_symbol (name)) == NULL)
+ {
+ symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
+ }
+
+ symbol_table_insert (symbolP);
+ if (S_IS_DEFINED (symbolP) && S_GET_SEGMENT (symbolP) != reg_section)
+ /* xgettext:c-format */
+ as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
+
+ else
+ {
+ link = (sym_linkS *) xmalloc (sizeof (sym_linkS));
+ link->symbol = symbolP;
+ link->next = debug_sym_link;
+ debug_sym_link = link;
+ symbolP->local = 1;
+ }
+
+ *end_name = delim;
+ demand_empty_rest_of_line ();
+}
+
+/* Second pass to expanding the debug symbols, go through linked
+ list of symbols and reassign the address. */
+
+static void
+expand_debug_syms (syms, align)
+ sym_linkS *syms;
+ int align;
+{
+ char *save_input_line = input_line_pointer;
+ sym_linkS *next_syms;
+
+ if (!syms)
+ return;
+
+ (void) m32r_do_align (align, NULL, 0, 0);
+ for (; syms != (sym_linkS *)0; syms = next_syms)
+ {
+ symbolS *symbolP = syms->symbol;
+ next_syms = syms->next;
+ input_line_pointer = ".\n";
+ pseudo_set (symbolP);
+ free ((char *)syms);
+ }
+
+ input_line_pointer = save_input_line;
+}
+
+/* Cover function to fill_insn called after a label and at end of assembly.
+ The result is always 1: we're called in a conditional to see if the
+ current line is a label. */
+
+int
+m32r_fill_insn (done)
+ int done;
+{
+ if (prev_seg != NULL)
+ {
+ segT seg = now_seg;
+ subsegT subseg = now_subseg;
+
+ subseg_set (prev_seg, prev_subseg);
+
+ fill_insn (0);
+
+ subseg_set (seg, subseg);
+ }
+
+ if (done && debug_sym_link)
+ {
+ expand_debug_syms (debug_sym_link, 1);
+ debug_sym_link = (sym_linkS *)0;
+ }
+
+ return 1;
+}
+
+void
+md_begin ()
+{
+ flagword applicable;
+ segT seg;
+ subsegT subseg;
+
+ /* Initialize the `cgen' interface. */
+
+ /* Set the machine number and endian. */
+ gas_cgen_cpu_desc = m32r_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0,
+ CGEN_CPU_OPEN_ENDIAN,
+ CGEN_ENDIAN_BIG,
+ CGEN_CPU_OPEN_END);
+ m32r_cgen_init_asm (gas_cgen_cpu_desc);
+
+ /* The operand instance table is used during optimization to determine
+ which insns can be executed in parallel. It is also used to give
+ warnings regarding operand interference in parallel insns. */
+ m32r_cgen_init_opinst_table (gas_cgen_cpu_desc);
+
+ /* This is a callback from cgen to gas to parse operands. */
+ cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
+
+#if 0 /* not supported yet */
+ /* If a runtime cpu description file was provided, parse it. */
+ if (m32r_cpu_desc != NULL)
+ {
+ const char * errmsg;
+
+ errmsg = cgen_read_cpu_file (gas_cgen_cpu_desc, m32r_cpu_desc);
+ if (errmsg != NULL)
+ as_bad ("%s: %s", m32r_cpu_desc, errmsg);
+ }
+#endif
+
+ /* Save the current subseg so we can restore it [it's the default one and
+ we don't want the initial section to be .sbss]. */
+ seg = now_seg;
+ subseg = now_subseg;
+
+ /* The sbss section is for local .scomm symbols. */
+ sbss_section = subseg_new (".sbss", 0);
+
+ /* This is copied from perform_an_assembly_pass. */
+ applicable = bfd_applicable_section_flags (stdoutput);
+ bfd_set_section_flags (stdoutput, sbss_section, applicable & SEC_ALLOC);
+
+#if 0 /* What does this do? [see perform_an_assembly_pass] */
+ seg_info (bss_section)->bss = 1;
+#endif
+
+ subseg_set (seg, subseg);
+
+ /* We must construct a fake section similar to bfd_com_section
+ but with the name .scommon. */
+ scom_section = bfd_com_section;
+ scom_section.name = ".scommon";
+ scom_section.output_section = & scom_section;
+ scom_section.symbol = & scom_symbol;
+ scom_section.symbol_ptr_ptr = & scom_section.symbol;
+ scom_symbol = * bfd_com_section.symbol;
+ scom_symbol.name = ".scommon";
+ scom_symbol.section = & scom_section;
+
+}
+
+
+
+void
+md_assemble (str)
+ char * str;
+{
+ m32r_insn insn;
+ char * errmsg;
+ char * str2 = NULL;
+
+ /* Initialize GAS's cgen interface for a new instruction. */
+ gas_cgen_init_parse ();
+
+
+ insn.debug_sym_link = debug_sym_link;
+ debug_sym_link = (sym_linkS *)0;
+
+ insn.insn = m32r_cgen_assemble_insn
+ (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
+
+ if (!insn.insn)
+ {
+ as_bad (errmsg);
+ return;
+ }
+
+
+ if (CGEN_INSN_BITSIZE (insn.insn) == 32)
+ {
+ /* 32 bit insns must live on 32 bit boundaries. */
+ if (prev_insn.insn || seen_relaxable_p)
+ {
+ /* ??? If calling fill_insn too many times turns us into a memory
+ pig, can we call a fn to assemble a nop instead of
+ !seen_relaxable_p? */
+ fill_insn (0);
+ }
+
+ expand_debug_syms (insn.debug_sym_link, 2);
+
+ /* Doesn't really matter what we pass for RELAX_P here. */
+ gas_cgen_finish_insn (insn.insn, insn.buffer,
+ CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);
+ }
+ else
+ {
+ int on_32bit_boundary_p;
+
+ if (CGEN_INSN_BITSIZE (insn.insn) != 16)
+ abort();
+
+ insn.orig_insn = insn.insn;
+
+ /* Compute whether we're on a 32 bit boundary or not.
+ prev_insn.insn is NULL when we're on a 32 bit boundary. */
+ on_32bit_boundary_p = prev_insn.insn == NULL;
+
+
+ expand_debug_syms (insn.debug_sym_link, 1);
+
+ {
+ int i;
+ finished_insnS fi;
+
+ /* Ensure each pair of 16 bit insns is in the same frag. */
+ frag_grow (4);
+
+ gas_cgen_finish_insn (insn.orig_insn, insn.buffer,
+ CGEN_FIELDS_BITSIZE (& insn.fields),
+ 1 /*relax_p*/, &fi);
+ insn.addr = fi.addr;
+ insn.frag = fi.frag;
+ insn.num_fixups = fi.num_fixups;
+ for (i = 0; i < fi.num_fixups; ++i)
+ insn.fixups[i] = fi.fixups[i];
+ }
+
+
+ /* Keep track of whether we've seen a pair of 16 bit insns.
+ prev_insn.insn is NULL when we're on a 32 bit boundary. */
+ if (on_32bit_boundary_p)
+ prev_insn = insn;
+ else
+ prev_insn.insn = NULL;
+
+ /* If the insn needs the following one to be on a 32 bit boundary
+ (e.g. subroutine calls), fill this insn's slot. */
+ if (on_32bit_boundary_p
+ && CGEN_INSN_ATTR_VALUE (insn.orig_insn, CGEN_INSN_FILL_SLOT) != 0)
+ fill_insn (0);
+
+ /* If this is a relaxable insn (can be replaced with a larger version)
+ mark the fact so that we can emit an alignment directive for a
+ following 32 bit insn if we see one. */
+ if (CGEN_INSN_ATTR_VALUE (insn.orig_insn, CGEN_INSN_RELAXABLE) != 0)
+ seen_relaxable_p = 1;
+ }
+
+ /* Set these so m32r_fill_insn can use them. */
+ prev_seg = now_seg;
+ prev_subseg = now_subseg;
+}
+
+/* The syntax in the manual says constants begin with '#'.
+ We just ignore it. */
+
+void
+md_operand (expressionP)
+ expressionS * expressionP;
+{
+ if (* input_line_pointer == '#')
+ {
+ input_line_pointer ++;
+ expression (expressionP);
+ }
+}
+
+valueT
+md_section_align (segment, size)
+ segT segment;
+ valueT size;
+{
+ int align = bfd_get_section_alignment (stdoutput, segment);
+ return ((size + (1 << align) - 1) & (-1 << align));
+}
+
+symbolS *
+md_undefined_symbol (name)
+ char * name;
+{
+ return 0;
+}
+
+/* .scomm pseudo-op handler.
+
+ This is a new pseudo-op to handle putting objects in .scommon.
+ By doing this the linker won't need to do any work and more importantly
+ it removes the implicit -G arg necessary to correctly link the object file.
+*/
+
+static void
+m32r_scomm (ignore)
+ int ignore;
+{
+ register char * name;
+ register char c;
+ register char * p;
+ offsetT size;
+ register symbolS * symbolP;
+ offsetT align;
+ int align2;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+
+ /* just after name is now '\0' */
+ p = input_line_pointer;
+ * p = c;
+ SKIP_WHITESPACE ();
+ if (* input_line_pointer != ',')
+ {
+ as_bad (_("Expected comma after symbol-name: rest of line ignored."));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ input_line_pointer ++; /* skip ',' */
+ if ((size = get_absolute_expression ()) < 0)
+ {
+ /* xgettext:c-format */
+ as_warn (_(".SCOMMon length (%ld.) <0! Ignored."), (long) size);
+ ignore_rest_of_line ();
+ return;
+ }
+
+ /* The third argument to .scomm is the alignment. */
+ if (* input_line_pointer != ',')
+ align = 8;
+ else
+ {
+ ++ input_line_pointer;
+ align = get_absolute_expression ();
+ if (align <= 0)
+ {
+ as_warn (_("ignoring bad alignment"));
+ align = 8;
+ }
+ }
+ /* Convert to a power of 2 alignment. */
+ if (align)
+ {
+ for (align2 = 0; (align & 1) == 0; align >>= 1, ++ align2)
+ continue;
+ if (align != 1)
+ {
+ as_bad (_("Common alignment not a power of 2"));
+ ignore_rest_of_line ();
+ return;
+ }
+ }
+ else
+ align2 = 0;
+
+ * p = 0;
+ symbolP = symbol_find_or_make (name);
+ * p = c;
+
+ if (S_IS_DEFINED (symbolP))
+ {
+ /* xgettext:c-format */
+ as_bad (_("Ignoring attempt to re-define symbol `%s'."),
+ S_GET_NAME (symbolP));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ if (S_GET_VALUE (symbolP) && S_GET_VALUE (symbolP) != (valueT) size)
+ {
+ /* xgettext:c-format */
+ as_bad (_("Length of .scomm \"%s\" is already %ld. Not changed to %ld."),
+ S_GET_NAME (symbolP),
+ (long) S_GET_VALUE (symbolP),
+ (long) size);
+
+ ignore_rest_of_line ();
+ return;
+ }
+
+ if (symbolP->local)
+ {
+ segT old_sec = now_seg;
+ int old_subsec = now_subseg;
+ char * pfrag;
+
+ record_alignment (sbss_section, align2);
+ subseg_set (sbss_section, 0);
+
+ if (align2)
+ frag_align (align2, 0, 0);
+
+ if (S_GET_SEGMENT (symbolP) == sbss_section)
+ symbolP->sy_frag->fr_symbol = 0;
+
+ symbolP->sy_frag = frag_now;
+
+ pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, size,
+ (char *) 0);
+ * pfrag = 0;
+ S_SET_SIZE (symbolP, size);
+ S_SET_SEGMENT (symbolP, sbss_section);
+ S_CLEAR_EXTERNAL (symbolP);
+ subseg_set (old_sec, old_subsec);
+ }
+ else
+ {
+ S_SET_VALUE (symbolP, (valueT) size);
+ S_SET_ALIGN (symbolP, align2);
+ S_SET_EXTERNAL (symbolP);
+ S_SET_SEGMENT (symbolP, & scom_section);
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* Interface to relax_segment. */
+
+/* FIXME: Build table by hand, get it working, then machine generate. */
+
+const relax_typeS md_relax_table[] =
+{
+/* The fields are:
+ 1) most positive reach of this state,
+ 2) most negative reach of this state,
+ 3) how many bytes this mode will add to the size of the current frag
+ 4) which index into the table to try if we can't fit into this one. */
+
+ /* The first entry must be unused because an `rlx_more' value of zero ends
+ each list. */
+ {1, 1, 0, 0},
+
+ /* The displacement used by GAS is from the end of the 2 byte insn,
+ so we subtract 2 from the following. */
+ /* 16 bit insn, 8 bit disp -> 10 bit range.
+ This doesn't handle a branch in the right slot at the border:
+ the "& -4" isn't taken into account. It's not important enough to
+ complicate things over it, so we subtract an extra 2 (or + 2 in -ve
+ case). */
+ {511 - 2 - 2, -512 - 2 + 2, 0, 2 },
+ /* 32 bit insn, 24 bit disp -> 26 bit range. */
+ {0x2000000 - 1 - 2, -0x2000000 - 2, 2, 0 },
+ /* Same thing, but with leading nop for alignment. */
+ {0x2000000 - 1 - 2, -0x2000000 - 2, 4, 0 }
+};
+
+long
+m32r_relax_frag (fragP, stretch)
+ fragS * fragP;
+ long stretch;
+{
+ /* Address of branch insn. */
+ long address = fragP->fr_address + fragP->fr_fix - 2;
+ long growth = 0;
+
+ /* Keep 32 bit insns aligned on 32 bit boundaries. */
+ if (fragP->fr_subtype == 2)
+ {
+ if ((address & 3) != 0)
+ {
+ fragP->fr_subtype = 3;
+ growth = 2;
+ }
+ }
+ else if (fragP->fr_subtype == 3)
+ {
+ if ((address & 3) == 0)
+ {
+ fragP->fr_subtype = 2;
+ growth = -2;
+ }
+ }
+ else
+ {
+ growth = relax_frag (fragP, stretch);
+
+ /* Long jump on odd halfword boundary? */
+ if (fragP->fr_subtype == 2 && (address & 3) != 0)
+ {
+ fragP->fr_subtype = 3;
+ growth += 2;
+ }
+ }
+
+ return growth;
+}
+
+/* Return an initial guess of the length by which a fragment must grow to
+ hold a branch to reach its destination.
+ Also updates fr_type/fr_subtype as necessary.
+
+ Called just before doing relaxation.
+ Any symbol that is now undefined will not become defined.
+ The guess for fr_var is ACTUALLY the growth beyond fr_fix.
+ Whatever we do to grow fr_fix or fr_var contributes to our returned value.
+ Although it may not be explicit in the frag, pretend fr_var starts with a
+ 0 value. */
+
+int
+md_estimate_size_before_relax (fragP, segment)
+ fragS * fragP;
+ segT segment;
+{
+ int old_fr_fix = fragP->fr_fix;
+
+ /* The only thing we have to handle here are symbols outside of the
+ current segment. They may be undefined or in a different segment in
+ which case linker scripts may place them anywhere.
+ However, we can't finish the fragment here and emit the reloc as insn
+ alignment requirements may move the insn about. */
+
+ if (S_GET_SEGMENT (fragP->fr_symbol) != segment)
+ {
+ /* The symbol is undefined in this segment.
+ Change the relaxation subtype to the max allowable and leave
+ all further handling to md_convert_frag. */
+ fragP->fr_subtype = 2;
+
+#if 0 /* Can't use this, but leave in for illustration. */
+ /* Change 16 bit insn to 32 bit insn. */
+ fragP->fr_opcode[0] |= 0x80;
+
+ /* Increase known (fixed) size of fragment. */
+ fragP->fr_fix += 2;
+
+ /* Create a relocation for it. */
+ fix_new (fragP, old_fr_fix, 4,
+ fragP->fr_symbol,
+ fragP->fr_offset, 1 /* pcrel */,
+ /* FIXME: Can't use a real BFD reloc here.
+ gas_cgen_md_apply_fix3 can't handle it. */
+ BFD_RELOC_M32R_26_PCREL);
+
+ /* Mark this fragment as finished. */
+ frag_wane (fragP);
+#else
+ {
+ const CGEN_INSN * insn;
+ int i;
+
+ /* Update the recorded insn.
+ Fortunately we don't have to look very far.
+ FIXME: Change this to record in the instruction the next higher
+ relaxable insn to use. */
+ for (i = 0, insn = fragP->fr_cgen.insn; i < 4; i++, insn++)
+ {
+ if ((strcmp (CGEN_INSN_MNEMONIC (insn),
+ CGEN_INSN_MNEMONIC (fragP->fr_cgen.insn))
+ == 0)
+ && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAX))
+ break;
+ }
+ if (i == 4)
+ abort ();
+
+ fragP->fr_cgen.insn = insn;
+ return 2;
+ }
+#endif
+ }
+
+ return (fragP->fr_var + fragP->fr_fix - old_fr_fix);
+}
+
+/* *fragP has been relaxed to its final size, and now needs to have
+ the bytes inside it modified to conform to the new size.
+
+ Called after relaxation is finished.
+ fragP->fr_type == rs_machine_dependent.
+ fragP->fr_subtype is the subtype of what the address relaxed to. */
+
+void
+md_convert_frag (abfd, sec, fragP)
+ bfd * abfd;
+ segT sec;
+ fragS * fragP;
+{
+ char * opcode;
+ char * displacement;
+ int target_address;
+ int opcode_address;
+ int extension;
+ int addend;
+
+ opcode = fragP->fr_opcode;
+
+ /* Address opcode resides at in file space. */
+ opcode_address = fragP->fr_address + fragP->fr_fix - 2;
+
+ switch (fragP->fr_subtype)
+ {
+ case 1 :
+ extension = 0;
+ displacement = & opcode[1];
+ break;
+ case 2 :
+ opcode[0] |= 0x80;
+ extension = 2;
+ displacement = & opcode[1];
+ break;
+ case 3 :
+ opcode[2] = opcode[0] | 0x80;
+ md_number_to_chars (opcode, PAR_NOP_INSN, 2);
+ opcode_address += 2;
+ extension = 4;
+ displacement = & opcode[3];
+ break;
+ default :
+ abort ();
+ }
+
+ if (S_GET_SEGMENT (fragP->fr_symbol) != sec)
+ {
+ /* symbol must be resolved by linker */
+ if (fragP->fr_offset & 3)
+ as_warn (_("Addend to unresolved symbol not on word boundary."));
+ addend = fragP->fr_offset >> 2;
+ }
+ else
+ {
+ /* Address we want to reach in file space. */
+ target_address = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset;
+ target_address += fragP->fr_symbol->sy_frag->fr_address;
+ addend = (target_address - (opcode_address & -4)) >> 2;
+ }
+
+ /* Create a relocation for symbols that must be resolved by the linker.
+ Otherwise output the completed insn. */
+
+ if (S_GET_SEGMENT (fragP->fr_symbol) != sec)
+ {
+ assert (fragP->fr_subtype != 1);
+ assert (fragP->fr_cgen.insn != 0);
+ gas_cgen_record_fixup (fragP,
+ /* Offset of branch insn in frag. */
+ fragP->fr_fix + extension - 4,
+ fragP->fr_cgen.insn,
+ 4 /*length*/,
+ /* FIXME: quick hack */
+#if 0
+ cgen_operand_lookup_by_num (gas_cgen_cpu_desc,
+ fragP->fr_cgen.opindex),
+#else
+ cgen_operand_lookup_by_num (gas_cgen_cpu_desc,
+ M32R_OPERAND_DISP24),
+#endif
+ fragP->fr_cgen.opinfo,
+ fragP->fr_symbol, fragP->fr_offset);
+ }
+
+#define SIZE_FROM_RELAX_STATE(n) ((n) == 1 ? 1 : 3)
+
+ md_number_to_chars (displacement, (valueT) addend,
+ SIZE_FROM_RELAX_STATE (fragP->fr_subtype));
+
+ fragP->fr_fix += extension;
+}
+
+/* Functions concerning relocs. */
+
+/* The location from which a PC relative jump should be calculated,
+ given a PC relative reloc. */
+
+long
+md_pcrel_from_section (fixP, sec)
+ fixS * fixP;
+ segT sec;
+{
+ if (fixP->fx_addsy != (symbolS *) NULL
+ && (! S_IS_DEFINED (fixP->fx_addsy)
+ || S_GET_SEGMENT (fixP->fx_addsy) != sec))
+ {
+ /* The symbol is undefined (or is defined but not in this section).
+ Let the linker figure it out. */
+ return 0;
+ }
+
+ return (fixP->fx_frag->fr_address + fixP->fx_where) & -4L;
+}
+
+/* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
+ Returns BFD_RELOC_NONE if no reloc type can be found.
+ *FIXP may be modified if desired. */
+
+bfd_reloc_code_real_type
+md_cgen_lookup_reloc (insn, operand, fixP)
+ const CGEN_INSN * insn;
+ const CGEN_OPERAND * operand;
+ fixS * fixP;
+{
+ switch (operand->type)
+ {
+ case M32R_OPERAND_DISP8 : return BFD_RELOC_M32R_10_PCREL;
+ case M32R_OPERAND_DISP16 : return BFD_RELOC_M32R_18_PCREL;
+ case M32R_OPERAND_DISP24 : return BFD_RELOC_M32R_26_PCREL;
+ case M32R_OPERAND_UIMM24 : return BFD_RELOC_M32R_24;
+ case M32R_OPERAND_HI16 :
+ case M32R_OPERAND_SLO16 :
+ case M32R_OPERAND_ULO16 :
+ /* If low/high/shigh/sda was used, it is recorded in `opinfo'. */
+ if (fixP->fx_cgen.opinfo != 0)
+ return fixP->fx_cgen.opinfo;
+ break;
+ default : /* avoid -Wall warning */
+ break;
+ }
+ return BFD_RELOC_NONE;
+}
+
+/* Record a HI16 reloc for later matching with its LO16 cousin. */
+
+static void
+m32r_record_hi16 (reloc_type, fixP, seg)
+ int reloc_type;
+ fixS * fixP;
+ segT seg;
+{
+ struct m32r_hi_fixup * hi_fixup;
+
+ assert (reloc_type == BFD_RELOC_M32R_HI16_SLO
+ || reloc_type == BFD_RELOC_M32R_HI16_ULO);
+
+ hi_fixup = ((struct m32r_hi_fixup *)
+ xmalloc (sizeof (struct m32r_hi_fixup)));
+ hi_fixup->fixp = fixP;
+ hi_fixup->seg = now_seg;
+ hi_fixup->next = m32r_hi_fixup_list;
+
+ m32r_hi_fixup_list = hi_fixup;
+}
+
+/* Called while parsing an instruction to create a fixup.
+ We need to check for HI16 relocs and queue them up for later sorting. */
+
+fixS *
+m32r_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp)
+ fragS * frag;
+ int where;
+ const CGEN_INSN * insn;
+ int length;
+ const CGEN_OPERAND * operand;
+ int opinfo;
+ expressionS * exp;
+{
+ fixS * fixP = gas_cgen_record_fixup_exp (frag, where, insn, length,
+ operand, opinfo, exp);
+
+ switch (operand->type)
+ {
+ case M32R_OPERAND_HI16 :
+ /* If low/high/shigh/sda was used, it is recorded in `opinfo'. */
+ if (fixP->fx_cgen.opinfo == BFD_RELOC_M32R_HI16_SLO
+ || fixP->fx_cgen.opinfo == BFD_RELOC_M32R_HI16_ULO)
+ m32r_record_hi16 (fixP->fx_cgen.opinfo, fixP, now_seg);
+ break;
+ default : /* avoid -Wall warning */
+ break;
+ }
+
+ return fixP;
+}
+
+/* Return BFD reloc type from opinfo field in a fixS.
+ It's tricky using fx_r_type in m32r_frob_file because the values
+ are BFD_RELOC_UNUSED + operand number. */
+#define FX_OPINFO_R_TYPE(f) ((f)->fx_cgen.opinfo)
+
+/* Sort any unmatched HI16 relocs so that they immediately precede
+ the corresponding LO16 reloc. This is called before md_apply_fix and
+ tc_gen_reloc. */
+
+void
+m32r_frob_file ()
+{
+ struct m32r_hi_fixup * l;
+
+ for (l = m32r_hi_fixup_list; l != NULL; l = l->next)
+ {
+ segment_info_type * seginfo;
+ int pass;
+
+ assert (FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_M32R_HI16_SLO
+ || FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_M32R_HI16_ULO);
+
+ /* Check quickly whether the next fixup happens to be a matching low. */
+ if (l->fixp->fx_next != NULL
+ && FX_OPINFO_R_TYPE (l->fixp->fx_next) == BFD_RELOC_M32R_LO16
+ && l->fixp->fx_addsy == l->fixp->fx_next->fx_addsy
+ && l->fixp->fx_offset == l->fixp->fx_next->fx_offset)
+ continue;
+
+ /* Look through the fixups for this segment for a matching `low'.
+ When we find one, move the high/shigh just in front of it. We do
+ this in two passes. In the first pass, we try to find a
+ unique `low'. In the second pass, we permit multiple high's
+ relocs for a single `low'. */
+ seginfo = seg_info (l->seg);
+ for (pass = 0; pass < 2; pass++)
+ {
+ fixS * f;
+ fixS * prev;
+
+ prev = NULL;
+ for (f = seginfo->fix_root; f != NULL; f = f->fx_next)
+ {
+ /* Check whether this is a `low' fixup which matches l->fixp. */
+ if (FX_OPINFO_R_TYPE (f) == BFD_RELOC_M32R_LO16
+ && f->fx_addsy == l->fixp->fx_addsy
+ && f->fx_offset == l->fixp->fx_offset
+ && (pass == 1
+ || prev == NULL
+ || (FX_OPINFO_R_TYPE (prev) != BFD_RELOC_M32R_HI16_SLO
+ && FX_OPINFO_R_TYPE (prev) != BFD_RELOC_M32R_HI16_ULO)
+ || prev->fx_addsy != f->fx_addsy
+ || prev->fx_offset != f->fx_offset))
+ {
+ fixS ** pf;
+
+ /* Move l->fixp before f. */
+ for (pf = &seginfo->fix_root;
+ * pf != l->fixp;
+ pf = & (* pf)->fx_next)
+ assert (* pf != NULL);
+
+ * pf = l->fixp->fx_next;
+
+ l->fixp->fx_next = f;
+ if (prev == NULL)
+ seginfo->fix_root = l->fixp;
+ else
+ prev->fx_next = l->fixp;
+
+ break;
+ }
+
+ prev = f;
+ }
+
+ if (f != NULL)
+ break;
+
+ if (pass == 1
+ && warn_unmatched_high)
+ as_warn_where (l->fixp->fx_file, l->fixp->fx_line,
+ _("Unmatched high/shigh reloc"));
+ }
+ }
+}
+
+/* See whether we need to force a relocation into the output file.
+ This is used to force out switch and PC relative relocations when
+ relaxing. */
+
+int
+m32r_force_relocation (fix)
+ fixS * fix;
+{
+ if (fix->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fix->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ return 1;
+
+ if (! m32r_relax)
+ return 0;
+
+ return (fix->fx_pcrel
+ || 0 /* ??? */);
+}
+
+/* Write a value out to the object file, using the appropriate endianness. */
+
+void
+md_number_to_chars (buf, val, n)
+ char * buf;
+ valueT val;
+ int n;
+{
+ if (target_big_endian)
+ number_to_chars_bigendian (buf, val, n);
+ else
+ number_to_chars_littleendian (buf, val, n);
+}
+
+/* Turn a string in input_line_pointer into a floating point constant of type
+ type, and store the appropriate bytes in *litP. The number of LITTLENUMS
+ emitted is stored in *sizeP . An error message is returned, or NULL on OK.
+*/
+
+/* Equal to MAX_PRECISION in atof-ieee.c */
+#define MAX_LITTLENUMS 6
+
+char *
+md_atof (type, litP, sizeP)
+ char type;
+ char *litP;
+ int *sizeP;
+{
+ int i;
+ int prec;
+ LITTLENUM_TYPE words [MAX_LITTLENUMS];
+ char * t;
+ char * atof_ieee ();
+
+ switch (type)
+ {
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ prec = 4;
+ break;
+
+ /* FIXME: Some targets allow other format chars for bigger sizes here. */
+
+ default:
+ * sizeP = 0;
+ return _("Bad call to md_atof()");
+ }
+
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+ * sizeP = prec * sizeof (LITTLENUM_TYPE);
+
+ if (target_big_endian)
+ {
+ for (i = 0; i < prec; i++)
+ {
+ md_number_to_chars (litP, (valueT) words[i],
+ sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+ }
+ else
+ {
+ for (i = prec - 1; i >= 0; i--)
+ {
+ md_number_to_chars (litP, (valueT) words[i],
+ sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+ }
+
+ return 0;
+}
+
+void
+m32r_elf_section_change_hook ()
+{
+ /* If we have reached the end of a section and we have just emitted a
+ 16 bit insn, then emit a nop to make sure that the section ends on
+ a 32 bit boundary. */
+
+ if (prev_insn.insn || seen_relaxable_p)
+ (void) m32r_fill_insn (0);
+}
+
+boolean
+m32r_fix_adjustable (fixP)
+ fixS *fixP;
+{
+
+ if (fixP->fx_addsy == NULL)
+ return 1;
+
+ /* Prevent all adjustments to global symbols. */
+ if (S_IS_EXTERN (fixP->fx_addsy))
+ return 0;
+ if (S_IS_WEAK (fixP->fx_addsy))
+ return 0;
+
+ /* We need the symbol name for the VTABLE entries */
+ if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ return 0;
+
+ return 1;
+}
diff --git a/gas/config/tc-m32r.h b/gas/config/tc-m32r.h
new file mode 100644
index 0000000000..ebcfca1c3f
--- /dev/null
+++ b/gas/config/tc-m32r.h
@@ -0,0 +1,102 @@
+/* tc-m32r.h -- Header file for tc-m32r.c.
+ Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#define TC_M32R
+
+#ifndef BFD_ASSEMBLER
+/* leading space so will compile with cc */
+ #error M32R support requires BFD_ASSEMBLER
+#endif
+
+#define LISTING_HEADER "M32R GAS "
+
+/* The target BFD architecture. */
+#define TARGET_ARCH bfd_arch_m32r
+
+#define TARGET_FORMAT "elf32-m32r"
+
+#define TARGET_BYTES_BIG_ENDIAN 1
+
+/* call md_pcrel_from_section, not md_pcrel_from */
+long md_pcrel_from_section PARAMS ((struct fix *, segT));
+#define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from_section(FIXP, SEC)
+
+/* Permit temporary numeric labels. */
+#define LOCAL_LABELS_FB 1
+
+#define DIFF_EXPR_OK /* .-foo gets turned into PC relative relocs */
+
+/* We don't need to handle .word strangely. */
+#define WORKING_DOT_WORD
+
+/* For 8 vs 16 vs 32 bit branch selection. */
+extern const struct relax_type md_relax_table[];
+#define TC_GENERIC_RELAX_TABLE md_relax_table
+#if 0
+extern void m32r_prepare_relax_scan ();
+#define md_prepare_relax_scan(fragP, address, aim, this_state, this_type) \
+m32r_prepare_relax_scan (fragP, address, aim, this_state, this_type)
+#else
+extern long m32r_relax_frag PARAMS ((fragS *, long));
+#define md_relax_frag(fragP, stretch) \
+m32r_relax_frag (fragP, stretch)
+#endif
+/* Account for nop if 32 bit insn falls on odd halfword boundary. */
+#define TC_CGEN_MAX_RELAX(insn, len) (6)
+
+/* Alignments are used to ensure 32 bit insns live on 32 bit boundaries, so
+ we use a special alignment function to insert the correct nop pattern. */
+extern int m32r_do_align PARAMS ((int, const char *, int, int));
+#define md_do_align(n, fill, len, max, l) \
+if (m32r_do_align (n, fill, len, max)) goto l
+
+#define MD_APPLY_FIX3
+#define md_apply_fix3 gas_cgen_md_apply_fix3
+
+#define obj_fix_adjustable(fixP) m32r_fix_adjustable(fixP)
+
+/* After creating a fixup for an instruction operand, we need to check for
+ HI16 relocs and queue them up for later sorting. */
+#define md_cgen_record_fixup_exp m32r_cgen_record_fixup_exp
+
+#define TC_HANDLES_FX_DONE
+
+#define tc_gen_reloc gas_cgen_tc_gen_reloc
+
+#define tc_frob_file() m32r_frob_file ()
+extern void m32r_frob_file PARAMS ((void));
+
+/* When relaxing, we need to emit various relocs we otherwise wouldn't. */
+#define TC_FORCE_RELOCATION(fix) m32r_force_relocation (fix)
+extern int m32r_force_relocation ();
+
+/* Ensure insns at labels are aligned to 32 bit boundaries. */
+int m32r_fill_insn PARAMS ((int));
+#define md_after_pass_hook() m32r_fill_insn (1)
+#define TC_START_LABEL(ch, ptr) (ch == ':' && m32r_fill_insn (0))
+
+/* Add extra M32R sections. */
+#define ELF_TC_SPECIAL_SECTIONS \
+ { ".sdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, \
+ { ".sbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
+
+#define md_cleanup m32r_elf_section_change_hook
+#define md_elf_section_change_hook m32r_elf_section_change_hook
+extern void m32r_elf_section_change_hook ();
diff --git a/gas/config/tc-m68851.h b/gas/config/tc-m68851.h
new file mode 100644
index 0000000000..0f6d741337
--- /dev/null
+++ b/gas/config/tc-m68851.h
@@ -0,0 +1,304 @@
+/* This file is tc-m68851.h
+
+ Copyright (C) 1987-1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * pmmu.h
+ */
+
+/* I suppose we have to copyright this file. Someone on the net sent it
+ to us as part of the changes for the m68851 Memory Management Unit */
+
+/* Copyright (C) 1987 Free Software Foundation, Inc.
+
+ This file is part of Gas, the GNU Assembler.
+
+ The GNU assembler is distributed in the hope that it will be
+ useful, but WITHOUT ANY WARRANTY. No author or distributor
+ accepts responsibility to anyone for the consequences of using it
+ or for whether it serves any particular purpose or works at all,
+ unless he says so in writing. Refer to the GNU Assembler General
+ Public License for full details.
+
+ Everyone is granted permission to copy, modify and redistribute
+ the GNU Assembler, but only under the conditions described in the
+ GNU Assembler General Public License. A copy of this license is
+ supposed to have been given to you along with the GNU Assembler
+ so you can know your rights and responsibilities. It should be
+ in a file named COPYING. Among other things, the copyright
+ notice and this notice must be preserved on all copies. */
+
+#ifdef m68851
+
+/*
+ I didn't use much imagination in choosing the
+ following codes, so many of them aren't very
+ mnemonic. -rab
+
+ P pmmu register
+ Possible values:
+ 000 TC Translation Control reg
+ 100 CAL Current Access Level
+ 101 VAL Validate Access Level
+ 110 SCC Stack Change Control
+ 111 AC Access Control
+
+ W wide pmmu registers
+ Possible values:
+ 001 DRP Dma Root Pointer
+ 010 SRP Supervisor Root Pointer
+ 011 CRP Cpu Root Pointer
+
+ f function code register
+ 0 SFC
+ 1 DFC
+
+ V VAL register only
+
+ X BADx, BACx
+ 100 BAD Breakpoint Acknowledge Data
+ 101 BAC Breakpoint Acknowledge Control
+
+ Y PSR
+ Z PCSR
+
+ | memory (modes 2-6, 7.*)
+
+ */
+
+/*
+ * these defines should be in m68k.c but
+ * i put them here to keep all the m68851 stuff
+ * together -rab
+ * JF--Make sure these #s don't clash with the ones in m68k.c
+ * That would be BAD.
+ */
+#define TC (FPS+1) /* 48 */
+#define DRP (TC+1) /* 49 */
+#define SRP (DRP+1) /* 50 */
+#define CRP (SRP+1) /* 51 */
+#define CAL (CRP+1) /* 52 */
+#define VAL (CAL+1) /* 53 */
+#define SCC (VAL+1) /* 54 */
+#define AC (SCC+1) /* 55 */
+#define BAD (AC+1) /* 56,57,58,59, 60,61,62,63 */
+#define BAC (BAD+8) /* 64,65,66,67, 68,69,70,71 */
+#define PSR (BAC+8) /* 72 */
+#define PCSR (PSR+1) /* 73 */
+
+/* name */ /* opcode */ /* match */ /* args */
+
+{"pbac", one(0xf0c7), one(0xffbf), "Bc"},
+{"pbacw", one(0xf087), one(0xffbf), "Bc"},
+{"pbas", one(0xf0c6), one(0xffbf), "Bc"},
+{"pbasw", one(0xf086), one(0xffbf), "Bc"},
+{"pbbc", one(0xf0c1), one(0xffbf), "Bc"},
+{"pbbcw", one(0xf081), one(0xffbf), "Bc"},
+{"pbbs", one(0xf0c0), one(0xffbf), "Bc"},
+{"pbbsw", one(0xf080), one(0xffbf), "Bc"},
+{"pbcc", one(0xf0cf), one(0xffbf), "Bc"},
+{"pbccw", one(0xf08f), one(0xffbf), "Bc"},
+{"pbcs", one(0xf0ce), one(0xffbf), "Bc"},
+{"pbcsw", one(0xf08e), one(0xffbf), "Bc"},
+{"pbgc", one(0xf0cd), one(0xffbf), "Bc"},
+{"pbgcw", one(0xf08d), one(0xffbf), "Bc"},
+{"pbgs", one(0xf0cc), one(0xffbf), "Bc"},
+{"pbgsw", one(0xf08c), one(0xffbf), "Bc"},
+{"pbic", one(0xf0cb), one(0xffbf), "Bc"},
+{"pbicw", one(0xf08b), one(0xffbf), "Bc"},
+{"pbis", one(0xf0ca), one(0xffbf), "Bc"},
+{"pbisw", one(0xf08a), one(0xffbf), "Bc"},
+{"pblc", one(0xf0c3), one(0xffbf), "Bc"},
+{"pblcw", one(0xf083), one(0xffbf), "Bc"},
+{"pbls", one(0xf0c2), one(0xffbf), "Bc"},
+{"pblsw", one(0xf082), one(0xffbf), "Bc"},
+{"pbsc", one(0xf0c5), one(0xffbf), "Bc"},
+{"pbscw", one(0xf085), one(0xffbf), "Bc"},
+{"pbss", one(0xf0c4), one(0xffbf), "Bc"},
+{"pbssw", one(0xf084), one(0xffbf), "Bc"},
+{"pbwc", one(0xf0c9), one(0xffbf), "Bc"},
+{"pbwcw", one(0xf089), one(0xffbf), "Bc"},
+{"pbws", one(0xf0c8), one(0xffbf), "Bc"},
+{"pbwsw", one(0xf088), one(0xffbf), "Bc"},
+
+
+{"pdbac", two(0xf048, 0x0007), two(0xfff8, 0xffff), "DsBw"},
+{"pdbas", two(0xf048, 0x0006), two(0xfff8, 0xffff), "DsBw"},
+{"pdbbc", two(0xf048, 0x0001), two(0xfff8, 0xffff), "DsBw"},
+{"pdbbs", two(0xf048, 0x0000), two(0xfff8, 0xffff), "DsBw"},
+{"pdbcc", two(0xf048, 0x000f), two(0xfff8, 0xffff), "DsBw"},
+{"pdbcs", two(0xf048, 0x000e), two(0xfff8, 0xffff), "DsBw"},
+{"pdbgc", two(0xf048, 0x000d), two(0xfff8, 0xffff), "DsBw"},
+{"pdbgs", two(0xf048, 0x000c), two(0xfff8, 0xffff), "DsBw"},
+{"pdbic", two(0xf048, 0x000b), two(0xfff8, 0xffff), "DsBw"},
+{"pdbis", two(0xf048, 0x000a), two(0xfff8, 0xffff), "DsBw"},
+{"pdblc", two(0xf048, 0x0003), two(0xfff8, 0xffff), "DsBw"},
+{"pdbls", two(0xf048, 0x0002), two(0xfff8, 0xffff), "DsBw"},
+{"pdbsc", two(0xf048, 0x0005), two(0xfff8, 0xffff), "DsBw"},
+{"pdbss", two(0xf048, 0x0004), two(0xfff8, 0xffff), "DsBw"},
+{"pdbwc", two(0xf048, 0x0009), two(0xfff8, 0xffff), "DsBw"},
+{"pdbws", two(0xf048, 0x0008), two(0xfff8, 0xffff), "DsBw"},
+
+{"pflusha", two(0xf000, 0x2400), two(0xffff, 0xffff), "" },
+
+{"pflush", two(0xf000, 0x3010), two(0xffc0, 0xfe10), "T3T9" },
+{"pflush", two(0xf000, 0x3810), two(0xffc0, 0xfe10), "T3T9&s" },
+{"pflush", two(0xf000, 0x3008), two(0xffc0, 0xfe18), "D3T9" },
+{"pflush", two(0xf000, 0x3808), two(0xffc0, 0xfe18), "D3T9&s" },
+{"pflush", two(0xf000, 0x3000), two(0xffc0, 0xfe1e), "f3T9" },
+{"pflush", two(0xf000, 0x3800), two(0xffc0, 0xfe1e), "f3T9&s" },
+
+{"pflushs", two(0xf000, 0x3410), two(0xfff8, 0xfe10), "T3T9" },
+{"pflushs", two(0xf000, 0x3c00), two(0xfff8, 0xfe00), "T3T9&s" },
+{"pflushs", two(0xf000, 0x3408), two(0xfff8, 0xfe18), "D3T9" },
+{"pflushs", two(0xf000, 0x3c08), two(0xfff8, 0xfe18), "D3T9&s" },
+{"pflushs", two(0xf000, 0x3400), two(0xfff8, 0xfe1e), "f3T9" },
+{"pflushs", two(0xf000, 0x3c00), two(0xfff8, 0xfe1e), "f3T9&s"},
+
+{"pflushr", two(0xf000, 0xa000), two(0xffc0, 0xffff), "|s" },
+
+{"ploadr", two(0xf000, 0x2210), two(0xffc0, 0xfff0), "T3&s" },
+{"ploadr", two(0xf000, 0x2208), two(0xffc0, 0xfff8), "D3&s" },
+{"ploadr", two(0xf000, 0x2200), two(0xffc0, 0xfffe), "f3&s" },
+{"ploadw", two(0xf000, 0x2010), two(0xffc0, 0xfff0), "T3&s" },
+{"ploadw", two(0xf000, 0x2008), two(0xffc0, 0xfff8), "D3&s" },
+{"ploadw", two(0xf000, 0x2000), two(0xffc0, 0xfffe), "f3&s" },
+
+ /* TC, CRP, DRP, SRP, CAL, VAL, SCC, AC */
+{"pmove", two(0xf000, 0x4000), two(0xffc0, 0xe3ff), "*sP8" },
+{"pmove", two(0xf000, 0x4200), two(0xffc0, 0xe3ff), "P8%s" },
+{"pmove", two(0xf000, 0x4000), two(0xffc0, 0xe3ff), "|sW8" },
+{"pmove", two(0xf000, 0x4200), two(0xffc0, 0xe3ff), "W8~s" },
+
+ /* BADx, BACx */
+{"pmove", two(0xf000, 0x6200), two(0xffc0, 0xe3e3), "*sX3" },
+{"pmove", two(0xf000, 0x6000), two(0xffc0, 0xe3e3), "X3%s" },
+
+ /* PSR, PCSR */
+ /* {"pmove", two(0xf000, 0x6100), two(oxffc0, oxffff), "*sZ8" }, */
+{"pmove", two(0xf000, 0x6000), two(0xffc0, 0xffff), "*sY8" },
+{"pmove", two(0xf000, 0x6200), two(0xffc0, 0xffff), "Y8%s" },
+{"pmove", two(0xf000, 0x6600), two(0xffc0, 0xffff), "Z8%s" },
+
+{"prestore", one(0xf140), one(0xffc0), "&s"},
+{"prestore", one(0xf158), one(0xfff8), "+s"},
+{"psave", one(0xf100), one(0xffc0), "&s"},
+{"psave", one(0xf100), one(0xffc0), "+s"},
+
+{"psac", two(0xf040, 0x0007), two(0xffc0, 0xffff), "@s"},
+{"psas", two(0xf040, 0x0006), two(0xffc0, 0xffff), "@s"},
+{"psbc", two(0xf040, 0x0001), two(0xffc0, 0xffff), "@s"},
+{"psbs", two(0xf040, 0x0000), two(0xffc0, 0xffff), "@s"},
+{"pscc", two(0xf040, 0x000f), two(0xffc0, 0xffff), "@s"},
+{"pscs", two(0xf040, 0x000e), two(0xffc0, 0xffff), "@s"},
+{"psgc", two(0xf040, 0x000d), two(0xffc0, 0xffff), "@s"},
+{"psgs", two(0xf040, 0x000c), two(0xffc0, 0xffff), "@s"},
+{"psic", two(0xf040, 0x000b), two(0xffc0, 0xffff), "@s"},
+{"psis", two(0xf040, 0x000a), two(0xffc0, 0xffff), "@s"},
+{"pslc", two(0xf040, 0x0003), two(0xffc0, 0xffff), "@s"},
+{"psls", two(0xf040, 0x0002), two(0xffc0, 0xffff), "@s"},
+{"pssc", two(0xf040, 0x0005), two(0xffc0, 0xffff), "@s"},
+{"psss", two(0xf040, 0x0004), two(0xffc0, 0xffff), "@s"},
+{"pswc", two(0xf040, 0x0009), two(0xffc0, 0xffff), "@s"},
+{"psws", two(0xf040, 0x0008), two(0xffc0, 0xffff), "@s"},
+
+{"ptestr", two(0xf000, 0x8210), two(0xffc0, 0xe3f0), "T3&sQ8" },
+{"ptestr", two(0xf000, 0x8310), two(0xffc0, 0xe310), "T3&sQ8A9" },
+{"ptestr", two(0xf000, 0x8208), two(0xffc0, 0xe3f8), "D3&sQ8" },
+{"ptestr", two(0xf000, 0x8308), two(0xffc0, 0xe318), "D3&sQ8A9" },
+{"ptestr", two(0xf000, 0x8200), two(0xffc0, 0xe3fe), "f3&sQ8" },
+{"ptestr", two(0xf000, 0x8300), two(0xffc0, 0xe31e), "f3&sQ8A9" },
+
+{"ptestw", two(0xf000, 0x8010), two(0xffc0, 0xe3f0), "T3&sQ8" },
+{"ptestw", two(0xf000, 0x8110), two(0xffc0, 0xe310), "T3&sQ8A9" },
+{"ptestw", two(0xf000, 0x8008), two(0xffc0, 0xe3f8), "D3&sQ8" },
+{"ptestw", two(0xf000, 0x8108), two(0xffc0, 0xe318), "D3&sQ8A9" },
+{"ptestw", two(0xf000, 0x8000), two(0xffc0, 0xe3fe), "f3&sQ8" },
+{"ptestw", two(0xf000, 0x8100), two(0xffc0, 0xe31e), "f3&sQ8A9" },
+
+{"ptrapacw", two(0xf07a, 0x0007), two(0xffff, 0xffff), "#w"},
+{"ptrapacl", two(0xf07b, 0x0007), two(0xffff, 0xffff), "#l"},
+{"ptrapac", two(0xf07c, 0x0007), two(0xffff, 0xffff), ""},
+
+{"ptrapasw", two(0xf07a, 0x0006), two(0xffff, 0xffff), "#w"},
+{"ptrapasl", two(0xf07b, 0x0006), two(0xffff, 0xffff), "#l"},
+{"ptrapas", two(0xf07c, 0x0006), two(0xffff, 0xffff), ""},
+
+{"ptrapbcw", two(0xf07a, 0x0001), two(0xffff, 0xffff), "#w"},
+{"ptrapbcl", two(0xf07b, 0x0001), two(0xffff, 0xffff), "#l"},
+{"ptrapbc", two(0xf07c, 0x0001), two(0xffff, 0xffff), ""},
+
+{"ptrapbsw", two(0xf07a, 0x0000), two(0xffff, 0xffff), "#w"},
+{"ptrapbsl", two(0xf07b, 0x0000), two(0xffff, 0xffff), "#l"},
+{"ptrapbs", two(0xf07c, 0x0000), two(0xffff, 0xffff), ""},
+
+{"ptrapccw", two(0xf07a, 0x000f), two(0xffff, 0xffff), "#w"},
+{"ptrapccl", two(0xf07b, 0x000f), two(0xffff, 0xffff), "#l"},
+{"ptrapcc", two(0xf07c, 0x000f), two(0xffff, 0xffff), ""},
+
+{"ptrapcsw", two(0xf07a, 0x000e), two(0xffff, 0xffff), "#w"},
+{"ptrapcsl", two(0xf07b, 0x000e), two(0xffff, 0xffff), "#l"},
+{"ptrapcs", two(0xf07c, 0x000e), two(0xffff, 0xffff), ""},
+
+{"ptrapgcw", two(0xf07a, 0x000d), two(0xffff, 0xffff), "#w"},
+{"ptrapgcl", two(0xf07b, 0x000d), two(0xffff, 0xffff), "#l"},
+{"ptrapgc", two(0xf07c, 0x000d), two(0xffff, 0xffff), ""},
+
+{"ptrapgsw", two(0xf07a, 0x000c), two(0xffff, 0xffff), "#w"},
+{"ptrapgsl", two(0xf07b, 0x000c), two(0xffff, 0xffff), "#l"},
+{"ptrapgs", two(0xf07c, 0x000c), two(0xffff, 0xffff), ""},
+
+{"ptrapicw", two(0xf07a, 0x000b), two(0xffff, 0xffff), "#w"},
+{"ptrapicl", two(0xf07b, 0x000b), two(0xffff, 0xffff), "#l"},
+{"ptrapic", two(0xf07c, 0x000b), two(0xffff, 0xffff), ""},
+
+{"ptrapisw", two(0xf07a, 0x000a), two(0xffff, 0xffff), "#w"},
+{"ptrapisl", two(0xf07b, 0x000a), two(0xffff, 0xffff), "#l"},
+{"ptrapis", two(0xf07c, 0x000a), two(0xffff, 0xffff), ""},
+
+{"ptraplcw", two(0xf07a, 0x0003), two(0xffff, 0xffff), "#w"},
+{"ptraplcl", two(0xf07b, 0x0003), two(0xffff, 0xffff), "#l"},
+{"ptraplc", two(0xf07c, 0x0003), two(0xffff, 0xffff), ""},
+
+{"ptraplsw", two(0xf07a, 0x0002), two(0xffff, 0xffff), "#w"},
+{"ptraplsl", two(0xf07b, 0x0002), two(0xffff, 0xffff), "#l"},
+{"ptrapls", two(0xf07c, 0x0002), two(0xffff, 0xffff), ""},
+
+{"ptrapscw", two(0xf07a, 0x0005), two(0xffff, 0xffff), "#w"},
+{"ptrapscl", two(0xf07b, 0x0005), two(0xffff, 0xffff), "#l"},
+{"ptrapsc", two(0xf07c, 0x0005), two(0xffff, 0xffff), ""},
+
+{"ptrapssw", two(0xf07a, 0x0004), two(0xffff, 0xffff), "#w"},
+{"ptrapssl", two(0xf07b, 0x0004), two(0xffff, 0xffff), "#l"},
+{"ptrapss", two(0xf07c, 0x0004), two(0xffff, 0xffff), ""},
+
+{"ptrapwcw", two(0xf07a, 0x0009), two(0xffff, 0xffff), "#w"},
+{"ptrapwcl", two(0xf07b, 0x0009), two(0xffff, 0xffff), "#l"},
+{"ptrapwc", two(0xf07c, 0x0009), two(0xffff, 0xffff), ""},
+
+{"ptrapwsw", two(0xf07a, 0x0008), two(0xffff, 0xffff), "#w"},
+{"ptrapwsl", two(0xf07b, 0x0008), two(0xffff, 0xffff), "#l"},
+{"ptrapws", two(0xf07c, 0x0008), two(0xffff, 0xffff), ""},
+
+{"pvalid", two(0xf000, 0x2800), two(0xffc0, 0xffff), "Vs&s"},
+{"pvalid", two(0xf000, 0x2c00), two(0xffc0, 0xfff8), "A3&s" },
+
+#endif /* m68851 */
+
+/* end of tc-m68851.h */
diff --git a/gas/config/tc-m68k.c b/gas/config/tc-m68k.c
new file mode 100644
index 0000000000..856dd4ec26
--- /dev/null
+++ b/gas/config/tc-m68k.c
@@ -0,0 +1,7009 @@
+/* tc-m68k.c -- Assemble for the m68k family
+ Copyright (C) 1987, 91, 92, 93, 94, 95, 96, 97, 1998
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include <ctype.h>
+#include "as.h"
+#include "obstack.h"
+#include "subsegs.h"
+
+#include "opcode/m68k.h"
+#include "m68k-parse.h"
+
+/* This string holds the chars that always start a comment. If the
+ pre-processor is disabled, these aren't very useful. The macro
+ tc_comment_chars points to this. We use this, rather than the
+ usual comment_chars, so that the --bitwise-or option will work. */
+#if defined (TE_SVR4) || defined (TE_DELTA)
+const char *m68k_comment_chars = "|#";
+#else
+const char *m68k_comment_chars = "|";
+#endif
+
+/* This array holds the chars that only start a comment at the beginning of
+ a line. If the line seems to have the form '# 123 filename'
+ .line and .file directives will appear in the pre-processed output */
+/* Note that input_file.c hand checks for '#' at the beginning of the
+ first line of the input file. This is because the compiler outputs
+ #NO_APP at the beginning of its output. */
+/* Also note that comments like this one will always work. */
+const char line_comment_chars[] = "#*";
+
+const char line_separator_chars[] = "";
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+CONST char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant, as
+ in "0f12.456" or "0d1.2345e12". */
+
+CONST char FLT_CHARS[] = "rRsSfFdDxXeEpP";
+
+/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
+ changed in read.c . Ideally it shouldn't have to know about it at all,
+ but nothing is ideal around here. */
+
+const int md_reloc_size = 8; /* Size of relocation record */
+
+/* Are we trying to generate PIC code? If so, absolute references
+ ought to be made into linkage table references or pc-relative
+ references. Not implemented. For ELF there are other means
+ to denote pic relocations. */
+int flag_want_pic;
+
+static int flag_short_refs; /* -l option */
+static int flag_long_jumps; /* -S option */
+
+#ifdef REGISTER_PREFIX_OPTIONAL
+int flag_reg_prefix_optional = REGISTER_PREFIX_OPTIONAL;
+#else
+int flag_reg_prefix_optional;
+#endif
+
+/* Whether --register-prefix-optional was used on the command line. */
+static int reg_prefix_optional_seen;
+
+/* The floating point coprocessor to use by default. */
+static enum m68k_register m68k_float_copnum = COP1;
+
+/* If this is non-zero, then references to number(%pc) will be taken
+ to refer to number, rather than to %pc + number. */
+static int m68k_abspcadd;
+
+/* If this is non-zero, then the quick forms of the move, add, and sub
+ instructions are used when possible. */
+static int m68k_quick = 1;
+
+/* If this is non-zero, then if the size is not specified for a base
+ or outer displacement, the assembler assumes that the size should
+ be 32 bits. */
+static int m68k_rel32 = 1;
+
+/* This is non-zero if m68k_rel32 was set from the command line. */
+static int m68k_rel32_from_cmdline;
+
+/* The default width to use for an index register when using a base
+ displacement. */
+static enum m68k_size m68k_index_width_default = SIZE_LONG;
+
+/* We want to warn if any text labels are misaligned. In order to get
+ the right line number, we need to record the line number for each
+ label. */
+
+struct label_line
+{
+ struct label_line *next;
+ symbolS *label;
+ char *file;
+ unsigned int line;
+ int text;
+};
+
+/* The list of labels. */
+
+static struct label_line *labels;
+
+/* The current label. */
+
+static struct label_line *current_label;
+
+/* Its an arbitrary name: This means I don't approve of it */
+/* See flames below */
+static struct obstack robyn;
+
+#define TAB(x,y) (((x)<<2)+(y))
+#define TABTYPE(xy) ((xy) >> 2)
+#define BYTE 0
+#define SHORT 1
+#define LONG 2
+#define SZ_UNDEF 3
+#undef BRANCH
+/* Case `g' except when BCC68000 is applicable. */
+#define ABRANCH 1
+/* Coprocessor branches. */
+#define FBRANCH 2
+/* Mode 7.2 -- program counter indirect with (16-bit) displacement,
+ supported on all cpus. Widens to 32-bit absolute. */
+#define PCREL 3
+/* For inserting an extra jmp instruction with long offset on 68000,
+ for expanding conditional branches. (Not bsr or bra.) Since the
+ 68000 doesn't support 32-bit displacements for conditional
+ branches, we fake it by reversing the condition and branching
+ around a jmp with an absolute long operand. */
+#define BCC68000 4
+/* For the DBcc "instructions". If the displacement requires 32 bits,
+ the branch-around-a-jump game is played here too. */
+#define DBCC 5
+/* Not currently used? */
+#define PCLEA 6
+/* Mode AINDX (apc-relative) using PC, with variable target, might fit
+ in 16 or 8 bits. */
+#define PCINDEX 7
+
+struct m68k_incant
+ {
+ const char *m_operands;
+ unsigned long m_opcode;
+ short m_opnum;
+ short m_codenum;
+ int m_arch;
+ struct m68k_incant *m_next;
+ };
+
+#define getone(x) ((((x)->m_opcode)>>16)&0xffff)
+#define gettwo(x) (((x)->m_opcode)&0xffff)
+
+static const enum m68k_register m68000_control_regs[] = { 0 };
+static const enum m68k_register m68010_control_regs[] = {
+ SFC, DFC, USP, VBR,
+ 0
+};
+static const enum m68k_register m68020_control_regs[] = {
+ SFC, DFC, USP, VBR, CACR, CAAR, MSP, ISP,
+ 0
+};
+static const enum m68k_register m68040_control_regs[] = {
+ SFC, DFC, CACR, TC, ITT0, ITT1, DTT0, DTT1,
+ USP, VBR, MSP, ISP, MMUSR, URP, SRP,
+ 0
+};
+static const enum m68k_register m68060_control_regs[] = {
+ SFC, DFC, CACR, TC, ITT0, ITT1, DTT0, DTT1, BUSCR,
+ USP, VBR, URP, SRP, PCR,
+ 0
+};
+static const enum m68k_register mcf5200_control_regs[] = {
+ CACR, TC, ITT0, ITT1, DTT0, DTT1, VBR, ROMBAR,
+ RAMBAR0, RAMBAR1, MBAR,
+ 0
+};
+#define cpu32_control_regs m68010_control_regs
+
+static const enum m68k_register *control_regs;
+
+/* internal form of a 68020 instruction */
+struct m68k_it
+{
+ const char *error;
+ const char *args; /* list of opcode info */
+ int numargs;
+
+ int numo; /* Number of shorts in opcode */
+ short opcode[11];
+
+ struct m68k_op operands[6];
+
+ int nexp; /* number of exprs in use */
+ struct m68k_exp exprs[4];
+
+ int nfrag; /* Number of frags we have to produce */
+ struct
+ {
+ int fragoff; /* Where in the current opcode the frag ends */
+ symbolS *fadd;
+ offsetT foff;
+ int fragty;
+ }
+ fragb[4];
+
+ int nrel; /* Num of reloc strucs in use */
+ struct
+ {
+ int n;
+ expressionS exp;
+ char wid;
+ char pcrel;
+ /* In a pc relative address the difference between the address
+ of the offset and the address that the offset is relative
+ to. This depends on the addressing mode. Basically this
+ is the value to put in the offset field to address the
+ first byte of the offset, without regarding the special
+ significance of some values (in the branch instruction, for
+ example). */
+ int pcrel_fix;
+#ifdef OBJ_ELF
+ /* Whether this expression needs special pic relocation, and if
+ so, which. */
+ enum pic_relocation pic_reloc;
+#endif
+ }
+ reloc[5]; /* Five is enough??? */
+};
+
+#define cpu_of_arch(x) ((x) & (m68000up|mcf5200))
+#define float_of_arch(x) ((x) & mfloat)
+#define mmu_of_arch(x) ((x) & mmmu)
+
+/* Macros for determining if cpu supports a specific addressing mode */
+#define HAVE_LONG_BRANCH(x) ((x) & (m68020|m68030|m68040|m68060|cpu32))
+
+static struct m68k_it the_ins; /* the instruction being assembled */
+
+#define op(ex) ((ex)->exp.X_op)
+#define adds(ex) ((ex)->exp.X_add_symbol)
+#define subs(ex) ((ex)->exp.X_op_symbol)
+#define offs(ex) ((ex)->exp.X_add_number)
+
+/* Macros for adding things to the m68k_it struct */
+
+#define addword(w) the_ins.opcode[the_ins.numo++]=(w)
+
+/* Static functions. */
+
+static void insop PARAMS ((int, const struct m68k_incant *));
+static void add_fix PARAMS ((int, struct m68k_exp *, int, int));
+static void add_frag PARAMS ((symbolS *, offsetT, int));
+
+/* Like addword, but goes BEFORE general operands */
+static void
+insop (w, opcode)
+ int w;
+ const struct m68k_incant *opcode;
+{
+ int z;
+ for(z=the_ins.numo;z>opcode->m_codenum;--z)
+ the_ins.opcode[z]=the_ins.opcode[z-1];
+ for(z=0;z<the_ins.nrel;z++)
+ the_ins.reloc[z].n+=2;
+ for (z = 0; z < the_ins.nfrag; z++)
+ the_ins.fragb[z].fragoff++;
+ the_ins.opcode[opcode->m_codenum]=w;
+ the_ins.numo++;
+}
+
+/* The numo+1 kludge is so we can hit the low order byte of the prev word.
+ Blecch. */
+static void
+add_fix (width, exp, pc_rel, pc_fix)
+ int width;
+ struct m68k_exp *exp;
+ int pc_rel;
+ int pc_fix;
+{
+ the_ins.reloc[the_ins.nrel].n = ((width == 'B' || width == '3')
+ ? (the_ins.numo*2-1)
+ : (((width)=='b')
+ ? (the_ins.numo*2+1)
+ : (the_ins.numo*2)));
+ the_ins.reloc[the_ins.nrel].exp = exp->exp;
+ the_ins.reloc[the_ins.nrel].wid = width;
+ the_ins.reloc[the_ins.nrel].pcrel_fix = pc_fix;
+#ifdef OBJ_ELF
+ the_ins.reloc[the_ins.nrel].pic_reloc = exp->pic_reloc;
+#endif
+ the_ins.reloc[the_ins.nrel++].pcrel = pc_rel;
+}
+
+/* Cause an extra frag to be generated here, inserting up to 10 bytes
+ (that value is chosen in the frag_var call in md_assemble). TYPE
+ is the subtype of the frag to be generated; its primary type is
+ rs_machine_dependent.
+
+ The TYPE parameter is also used by md_convert_frag_1 and
+ md_estimate_size_before_relax. The appropriate type of fixup will
+ be emitted by md_convert_frag_1.
+
+ ADD becomes the FR_SYMBOL field of the frag, and OFF the FR_OFFSET. */
+static void
+add_frag (add, off, type)
+ symbolS *add;
+ offsetT off;
+ int type;
+{
+ the_ins.fragb[the_ins.nfrag].fragoff=the_ins.numo;
+ the_ins.fragb[the_ins.nfrag].fadd=add;
+ the_ins.fragb[the_ins.nfrag].foff=off;
+ the_ins.fragb[the_ins.nfrag++].fragty=type;
+}
+
+#define isvar(ex) \
+ (op (ex) != O_constant && op (ex) != O_big)
+
+static char *crack_operand PARAMS ((char *str, struct m68k_op *opP));
+static int get_num PARAMS ((struct m68k_exp *exp, int ok));
+static void m68k_ip PARAMS ((char *));
+static void insert_reg PARAMS ((const char *, int));
+static void select_control_regs PARAMS ((void));
+static void init_regtable PARAMS ((void));
+static int reverse_16_bits PARAMS ((int in));
+static int reverse_8_bits PARAMS ((int in));
+static void install_gen_operand PARAMS ((int mode, int val));
+static void install_operand PARAMS ((int mode, int val));
+static void s_bss PARAMS ((int));
+static void s_data1 PARAMS ((int));
+static void s_data2 PARAMS ((int));
+static void s_even PARAMS ((int));
+static void s_proc PARAMS ((int));
+static void mri_chip PARAMS ((void));
+static void s_chip PARAMS ((int));
+static void s_fopt PARAMS ((int));
+static void s_opt PARAMS ((int));
+static void s_reg PARAMS ((int));
+static void s_restore PARAMS ((int));
+static void s_save PARAMS ((int));
+static void s_mri_if PARAMS ((int));
+static void s_mri_else PARAMS ((int));
+static void s_mri_endi PARAMS ((int));
+static void s_mri_break PARAMS ((int));
+static void s_mri_next PARAMS ((int));
+static void s_mri_for PARAMS ((int));
+static void s_mri_endf PARAMS ((int));
+static void s_mri_repeat PARAMS ((int));
+static void s_mri_until PARAMS ((int));
+static void s_mri_while PARAMS ((int));
+static void s_mri_endw PARAMS ((int));
+static void md_apply_fix_2 PARAMS ((fixS *, offsetT));
+static void md_convert_frag_1 PARAMS ((fragS *));
+
+static int current_architecture;
+
+struct m68k_cpu {
+ unsigned long arch;
+ const char *name;
+ int alias;
+};
+
+static const struct m68k_cpu archs[] = {
+ { m68000, "68000", 0 },
+ { m68010, "68010", 0 },
+ { m68020, "68020", 0 },
+ { m68030, "68030", 0 },
+ { m68040, "68040", 0 },
+ { m68060, "68060", 0 },
+ { cpu32, "cpu32", 0 },
+ { m68881, "68881", 0 },
+ { m68851, "68851", 0 },
+ { mcf5200, "5200", 0 },
+ /* Aliases (effectively, so far as gas is concerned) for the above
+ cpus. */
+ { m68020, "68k", 1 },
+ { m68000, "68008", 1 },
+ { m68000, "68302", 1 },
+ { m68000, "68306", 1 },
+ { m68000, "68307", 1 },
+ { m68000, "68322", 1 },
+ { m68000, "68356", 1 },
+ { m68000, "68ec000", 1 },
+ { m68000, "68hc000", 1 },
+ { m68000, "68hc001", 1 },
+ { m68020, "68ec020", 1 },
+ { m68030, "68ec030", 1 },
+ { m68040, "68ec040", 1 },
+ { m68060, "68ec060", 1 },
+ { cpu32, "68330", 1 },
+ { cpu32, "68331", 1 },
+ { cpu32, "68332", 1 },
+ { cpu32, "68333", 1 },
+ { cpu32, "68334", 1 },
+ { cpu32, "68336", 1 },
+ { cpu32, "68340", 1 },
+ { cpu32, "68341", 1 },
+ { cpu32, "68349", 1 },
+ { cpu32, "68360", 1 },
+ { m68881, "68882", 1 },
+};
+
+static const int n_archs = sizeof (archs) / sizeof (archs[0]);
+
+/* BCC68000 is for patching in an extra jmp instruction for long offsets
+ on the 68000. The 68000 doesn't support long branches with branchs */
+
+/* This table desribes how you change sizes for the various types of variable
+ size expressions. This version only supports two kinds. */
+
+/* Note that calls to frag_var need to specify the maximum expansion
+ needed; this is currently 10 bytes for DBCC. */
+
+/* The fields are:
+ How far Forward this mode will reach:
+ How far Backward this mode will reach:
+ How many bytes this mode will add to the size of the frag
+ Which mode to go to if the offset won't fit in this one
+ */
+relax_typeS md_relax_table[] =
+{
+ {1, 1, 0, 0}, /* First entries aren't used */
+ {1, 1, 0, 0}, /* For no good reason except */
+ {1, 1, 0, 0}, /* that the VAX doesn't either */
+ {1, 1, 0, 0},
+
+ {(127), (-128), 0, TAB (ABRANCH, SHORT)},
+ {(32767), (-32768), 2, TAB (ABRANCH, LONG)},
+ {0, 0, 4, 0},
+ {1, 1, 0, 0},
+
+ {1, 1, 0, 0}, /* FBRANCH doesn't come BYTE */
+ {(32767), (-32768), 2, TAB (FBRANCH, LONG)},
+ {0, 0, 4, 0},
+ {1, 1, 0, 0},
+
+ {1, 1, 0, 0}, /* PCREL doesn't come BYTE */
+ {(32767), (-32768), 2, TAB (PCREL, LONG)},
+ {0, 0, 4, 0},
+ {1, 1, 0, 0},
+
+ {(127), (-128), 0, TAB (BCC68000, SHORT)},
+ {(32767), (-32768), 2, TAB (BCC68000, LONG)},
+ {0, 0, 6, 0}, /* jmp long space */
+ {1, 1, 0, 0},
+
+ {1, 1, 0, 0}, /* DBCC doesn't come BYTE */
+ {(32767), (-32768), 2, TAB (DBCC, LONG)},
+ {0, 0, 10, 0}, /* bra/jmp long space */
+ {1, 1, 0, 0},
+
+ {1, 1, 0, 0}, /* PCLEA doesn't come BYTE */
+ {32767, -32768, 2, TAB (PCLEA, LONG)},
+ {0, 0, 6, 0},
+ {1, 1, 0, 0},
+
+ /* For, e.g., jmp pcrel indexed. */
+ {125, -130, 0, TAB (PCINDEX, SHORT)},
+ {32765, -32770, 2, TAB (PCINDEX, LONG)},
+ {0, 0, 4, 0},
+ {1, 1, 0, 0},
+};
+
+/* These are the machine dependent pseudo-ops. These are included so
+ the assembler can work on the output from the SUN C compiler, which
+ generates these.
+ */
+
+/* This table describes all the machine specific pseudo-ops the assembler
+ has to support. The fields are:
+ pseudo-op name without dot
+ function to call to execute this pseudo-op
+ Integer arg to pass to the function
+ */
+const pseudo_typeS md_pseudo_table[] =
+{
+ {"data1", s_data1, 0},
+ {"data2", s_data2, 0},
+ {"bss", s_bss, 0},
+ {"even", s_even, 0},
+ {"skip", s_space, 0},
+ {"proc", s_proc, 0},
+#if defined (TE_SUN3) || defined (OBJ_ELF)
+ {"align", s_align_bytes, 0},
+#endif
+#ifdef OBJ_ELF
+ {"swbeg", s_ignore, 0},
+#endif
+ {"extend", float_cons, 'x'},
+ {"ldouble", float_cons, 'x'},
+
+ /* The following pseudo-ops are supported for MRI compatibility. */
+ {"chip", s_chip, 0},
+ {"comline", s_space, 1},
+ {"fopt", s_fopt, 0},
+ {"mask2", s_ignore, 0},
+ {"opt", s_opt, 0},
+ {"reg", s_reg, 0},
+ {"restore", s_restore, 0},
+ {"save", s_save, 0},
+
+ {"if", s_mri_if, 0},
+ {"if.b", s_mri_if, 'b'},
+ {"if.w", s_mri_if, 'w'},
+ {"if.l", s_mri_if, 'l'},
+ {"else", s_mri_else, 0},
+ {"else.s", s_mri_else, 's'},
+ {"else.l", s_mri_else, 'l'},
+ {"endi", s_mri_endi, 0},
+ {"break", s_mri_break, 0},
+ {"break.s", s_mri_break, 's'},
+ {"break.l", s_mri_break, 'l'},
+ {"next", s_mri_next, 0},
+ {"next.s", s_mri_next, 's'},
+ {"next.l", s_mri_next, 'l'},
+ {"for", s_mri_for, 0},
+ {"for.b", s_mri_for, 'b'},
+ {"for.w", s_mri_for, 'w'},
+ {"for.l", s_mri_for, 'l'},
+ {"endf", s_mri_endf, 0},
+ {"repeat", s_mri_repeat, 0},
+ {"until", s_mri_until, 0},
+ {"until.b", s_mri_until, 'b'},
+ {"until.w", s_mri_until, 'w'},
+ {"until.l", s_mri_until, 'l'},
+ {"while", s_mri_while, 0},
+ {"while.b", s_mri_while, 'b'},
+ {"while.w", s_mri_while, 'w'},
+ {"while.l", s_mri_while, 'l'},
+ {"endw", s_mri_endw, 0},
+
+ {0, 0, 0}
+};
+
+
+/* The mote pseudo ops are put into the opcode table, since they
+ don't start with a . they look like opcodes to gas.
+ */
+
+#ifdef M68KCOFF
+extern void obj_coff_section PARAMS ((int));
+#endif
+
+CONST pseudo_typeS mote_pseudo_table[] =
+{
+
+ {"dcl", cons, 4},
+ {"dc", cons, 2},
+ {"dcw", cons, 2},
+ {"dcb", cons, 1},
+
+ {"dsl", s_space, 4},
+ {"ds", s_space, 2},
+ {"dsw", s_space, 2},
+ {"dsb", s_space, 1},
+
+ {"xdef", s_globl, 0},
+#ifdef OBJ_ELF
+ {"align", s_align_bytes, 0},
+#else
+ {"align", s_align_ptwo, 0},
+#endif
+#ifdef M68KCOFF
+ {"sect", obj_coff_section, 0},
+ {"section", obj_coff_section, 0},
+#endif
+ {0, 0, 0}
+};
+
+#define issbyte(x) ((x)>=-128 && (x)<=127)
+#define isubyte(x) ((x)>=0 && (x)<=255)
+#define issword(x) ((x)>=-32768 && (x)<=32767)
+#define isuword(x) ((x)>=0 && (x)<=65535)
+
+#define isbyte(x) ((x)>= -255 && (x)<=255)
+#define isword(x) ((x)>=-65536 && (x)<=65535)
+#define islong(x) (1)
+
+extern char *input_line_pointer;
+
+static char mklower_table[256];
+#define mklower(c) (mklower_table[(unsigned char)(c)])
+static char notend_table[256];
+static char alt_notend_table[256];
+#define notend(s) \
+ (! (notend_table[(unsigned char) *s] \
+ || (*s == ':' \
+ && alt_notend_table[(unsigned char) s[1]])))
+
+#if defined (M68KCOFF) && !defined (BFD_ASSEMBLER)
+
+#ifdef NO_PCREL_RELOCS
+
+int
+make_pcrel_absolute(fixP, add_number)
+ fixS *fixP;
+ long *add_number;
+{
+ register unsigned char *opcode = fixP->fx_frag->fr_opcode;
+
+ /* rewrite the PC relative instructions to absolute address ones.
+ * these are rumoured to be faster, and the apollo linker refuses
+ * to deal with the PC relative relocations.
+ */
+ if (opcode[0] == 0x60 && opcode[1] == 0xff) /* BRA -> JMP */
+ {
+ opcode[0] = 0x4e;
+ opcode[1] = 0xf9;
+ }
+ else if (opcode[0] == 0x61 && opcode[1] == 0xff) /* BSR -> JSR */
+ {
+ opcode[0] = 0x4e;
+ opcode[1] = 0xb9;
+ }
+ else
+ as_fatal (_("Unknown PC relative instruction"));
+ *add_number -= 4;
+ return 0;
+}
+
+#endif /* NO_PCREL_RELOCS */
+
+short
+tc_coff_fix2rtype (fixP)
+ fixS *fixP;
+{
+ if (fixP->fx_tcbit && fixP->fx_size == 4)
+ return R_RELLONG_NEG;
+#ifdef NO_PCREL_RELOCS
+ know (fixP->fx_pcrel == 0);
+ return (fixP->fx_size == 1 ? R_RELBYTE
+ : fixP->fx_size == 2 ? R_DIR16
+ : R_DIR32);
+#else
+ return (fixP->fx_pcrel ?
+ (fixP->fx_size == 1 ? R_PCRBYTE :
+ fixP->fx_size == 2 ? R_PCRWORD :
+ R_PCRLONG) :
+ (fixP->fx_size == 1 ? R_RELBYTE :
+ fixP->fx_size == 2 ? R_RELWORD :
+ R_RELLONG));
+#endif
+}
+
+#endif
+
+#ifdef OBJ_ELF
+
+/* Compute the relocation code for a fixup of SIZE bytes, using pc
+ relative relocation if PCREL is non-zero. PIC says whether a special
+ pic relocation was requested. */
+
+static bfd_reloc_code_real_type get_reloc_code
+ PARAMS ((int, int, enum pic_relocation));
+
+static bfd_reloc_code_real_type
+get_reloc_code (size, pcrel, pic)
+ int size;
+ int pcrel;
+ enum pic_relocation pic;
+{
+ switch (pic)
+ {
+ case pic_got_pcrel:
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_8_GOT_PCREL;
+ case 2:
+ return BFD_RELOC_16_GOT_PCREL;
+ case 4:
+ return BFD_RELOC_32_GOT_PCREL;
+ }
+ break;
+
+ case pic_got_off:
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_8_GOTOFF;
+ case 2:
+ return BFD_RELOC_16_GOTOFF;
+ case 4:
+ return BFD_RELOC_32_GOTOFF;
+ }
+ break;
+
+ case pic_plt_pcrel:
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_8_PLT_PCREL;
+ case 2:
+ return BFD_RELOC_16_PLT_PCREL;
+ case 4:
+ return BFD_RELOC_32_PLT_PCREL;
+ }
+ break;
+
+ case pic_plt_off:
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_8_PLTOFF;
+ case 2:
+ return BFD_RELOC_16_PLTOFF;
+ case 4:
+ return BFD_RELOC_32_PLTOFF;
+ }
+ break;
+
+ case pic_none:
+ if (pcrel)
+ {
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_8_PCREL;
+ case 2:
+ return BFD_RELOC_16_PCREL;
+ case 4:
+ return BFD_RELOC_32_PCREL;
+ }
+ }
+ else
+ {
+ switch (size)
+ {
+ case 1:
+ return BFD_RELOC_8;
+ case 2:
+ return BFD_RELOC_16;
+ case 4:
+ return BFD_RELOC_32;
+ }
+ }
+ }
+
+ if (pcrel)
+ {
+ if (pic == pic_none)
+ as_bad (_("Can not do %d byte pc-relative relocation"), size);
+ else
+ as_bad (_("Can not do %d byte pc-relative pic relocation"), size);
+ }
+ else
+ {
+ if (pic == pic_none)
+ as_bad (_("Can not do %d byte relocation"), size);
+ else
+ as_bad (_("Can not do %d byte pic relocation"), size);
+ }
+
+ return BFD_RELOC_NONE;
+}
+
+/* Here we decide which fixups can be adjusted to make them relative
+ to the beginning of the section instead of the symbol. Basically
+ we need to make sure that the dynamic relocations are done
+ correctly, so in some cases we force the original symbol to be
+ used. */
+int
+tc_m68k_fix_adjustable (fixP)
+ fixS *fixP;
+{
+ /* Prevent all adjustments to global symbols. */
+ if (S_IS_EXTERNAL (fixP->fx_addsy)
+ || S_IS_WEAK (fixP->fx_addsy))
+ return 0;
+
+ /* adjust_reloc_syms doesn't know about the GOT */
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_8_GOT_PCREL:
+ case BFD_RELOC_16_GOT_PCREL:
+ case BFD_RELOC_32_GOT_PCREL:
+ case BFD_RELOC_8_GOTOFF:
+ case BFD_RELOC_16_GOTOFF:
+ case BFD_RELOC_32_GOTOFF:
+ case BFD_RELOC_8_PLT_PCREL:
+ case BFD_RELOC_16_PLT_PCREL:
+ case BFD_RELOC_32_PLT_PCREL:
+ case BFD_RELOC_8_PLTOFF:
+ case BFD_RELOC_16_PLTOFF:
+ case BFD_RELOC_32_PLTOFF:
+ return 0;
+
+ case BFD_RELOC_VTABLE_INHERIT:
+ case BFD_RELOC_VTABLE_ENTRY:
+ return 0;
+
+ default:
+ return 1;
+ }
+}
+
+#else /* !OBJ_ELF */
+
+#define get_reloc_code(SIZE,PCREL,OTHER) NO_RELOC
+
+#endif /* OBJ_ELF */
+
+#ifdef BFD_ASSEMBLER
+
+arelent *
+tc_gen_reloc (section, fixp)
+ asection *section;
+ fixS *fixp;
+{
+ arelent *reloc;
+ bfd_reloc_code_real_type code;
+
+ if (fixp->fx_tcbit)
+ abort ();
+
+ if (fixp->fx_r_type != BFD_RELOC_NONE)
+ {
+ code = fixp->fx_r_type;
+
+ /* Since DIFF_EXPR_OK is defined in tc-m68k.h, it is possible
+ that fixup_segment converted a non-PC relative reloc into a
+ PC relative reloc. In such a case, we need to convert the
+ reloc code. */
+ if (fixp->fx_pcrel)
+ {
+ switch (code)
+ {
+ case BFD_RELOC_8:
+ code = BFD_RELOC_8_PCREL;
+ break;
+ case BFD_RELOC_16:
+ code = BFD_RELOC_16_PCREL;
+ break;
+ case BFD_RELOC_32:
+ code = BFD_RELOC_32_PCREL;
+ break;
+ case BFD_RELOC_8_PCREL:
+ case BFD_RELOC_16_PCREL:
+ case BFD_RELOC_32_PCREL:
+ case BFD_RELOC_8_GOT_PCREL:
+ case BFD_RELOC_16_GOT_PCREL:
+ case BFD_RELOC_32_GOT_PCREL:
+ case BFD_RELOC_8_GOTOFF:
+ case BFD_RELOC_16_GOTOFF:
+ case BFD_RELOC_32_GOTOFF:
+ case BFD_RELOC_8_PLT_PCREL:
+ case BFD_RELOC_16_PLT_PCREL:
+ case BFD_RELOC_32_PLT_PCREL:
+ case BFD_RELOC_8_PLTOFF:
+ case BFD_RELOC_16_PLTOFF:
+ case BFD_RELOC_32_PLTOFF:
+ break;
+ default:
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("Cannot make %s relocation PC relative"),
+ bfd_get_reloc_code_name (code));
+ }
+ }
+ }
+ else
+ {
+#define F(SZ,PCREL) (((SZ) << 1) + (PCREL))
+ switch (F (fixp->fx_size, fixp->fx_pcrel))
+ {
+#define MAP(SZ,PCREL,TYPE) case F(SZ,PCREL): code = (TYPE); break
+ MAP (1, 0, BFD_RELOC_8);
+ MAP (2, 0, BFD_RELOC_16);
+ MAP (4, 0, BFD_RELOC_32);
+ MAP (1, 1, BFD_RELOC_8_PCREL);
+ MAP (2, 1, BFD_RELOC_16_PCREL);
+ MAP (4, 1, BFD_RELOC_32_PCREL);
+ default:
+ abort ();
+ }
+ }
+#undef F
+#undef MAP
+
+ reloc = (arelent *) xmalloc (sizeof (arelent));
+ reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+ reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+#ifndef OBJ_ELF
+ if (fixp->fx_pcrel)
+ reloc->addend = fixp->fx_addnumber;
+ else
+ reloc->addend = 0;
+#else
+ if (!fixp->fx_pcrel)
+ reloc->addend = fixp->fx_addnumber;
+ else
+ reloc->addend = (section->vma
+ + (fixp->fx_pcrel_adjust == 64
+ ? -1 : fixp->fx_pcrel_adjust)
+ + fixp->fx_addnumber
+ + md_pcrel_from (fixp));
+#endif
+
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
+ assert (reloc->howto != 0);
+
+ return reloc;
+}
+
+#endif /* BFD_ASSEMBLER */
+
+/* Return zero if the reference to SYMBOL from within the same segment may
+ be relaxed. */
+#ifdef OBJ_ELF
+
+/* On an ELF system, we can't relax an externally visible symbol,
+ because it may be overridden by a shared library. However, if
+ TARGET_OS is "elf", then we presume that we are assembling for an
+ embedded system, in which case we don't have to worry about shared
+ libraries, and we can relax anything. */
+
+#define relaxable_symbol(symbol) \
+ (strcmp (TARGET_OS, "elf") == 0 \
+ || (! S_IS_EXTERNAL (symbol) \
+ && ! S_IS_WEAK (symbol)))
+
+#else
+
+#define relaxable_symbol(symbol) 1
+
+#endif
+
+/* Handle of the OPCODE hash table. NULL means any use before
+ m68k_ip_begin() will crash. */
+static struct hash_control *op_hash;
+
+/* Assemble an m68k instruction. */
+
+static void
+m68k_ip (instring)
+ char *instring;
+{
+ register char *p;
+ register struct m68k_op *opP;
+ register const struct m68k_incant *opcode;
+ register const char *s;
+ register int tmpreg = 0, baseo = 0, outro = 0, nextword;
+ char *pdot, *pdotmove;
+ enum m68k_size siz1, siz2;
+ char c;
+ int losing;
+ int opsfound;
+ LITTLENUM_TYPE words[6];
+ LITTLENUM_TYPE *wordp;
+ unsigned long ok_arch = 0;
+
+ if (*instring == ' ')
+ instring++; /* skip leading whitespace */
+
+ /* Scan up to end of operation-code, which MUST end in end-of-string
+ or exactly 1 space. */
+ pdot = 0;
+ for (p = instring; *p != '\0'; p++)
+ {
+ if (*p == ' ')
+ break;
+ if (*p == '.')
+ pdot = p;
+ }
+
+ if (p == instring)
+ {
+ the_ins.error = _("No operator");
+ return;
+ }
+
+ /* p now points to the end of the opcode name, probably whitespace.
+ Make sure the name is null terminated by clobbering the
+ whitespace, look it up in the hash table, then fix it back.
+ Remove a dot, first, since the opcode tables have none. */
+ if (pdot != NULL)
+ {
+ for (pdotmove = pdot; pdotmove < p; pdotmove++)
+ *pdotmove = pdotmove[1];
+ p--;
+ }
+
+ c = *p;
+ *p = '\0';
+ opcode = (const struct m68k_incant *) hash_find (op_hash, instring);
+ *p = c;
+
+ if (pdot != NULL)
+ {
+ for (pdotmove = p; pdotmove > pdot; pdotmove--)
+ *pdotmove = pdotmove[-1];
+ *pdot = '.';
+ ++p;
+ }
+
+ if (opcode == NULL)
+ {
+ the_ins.error = _("Unknown operator");
+ return;
+ }
+
+ /* found a legitimate opcode, start matching operands */
+ while (*p == ' ')
+ ++p;
+
+ if (opcode->m_operands == 0)
+ {
+ char *old = input_line_pointer;
+ *old = '\n';
+ input_line_pointer = p;
+ /* Ahh - it's a motorola style psuedo op */
+ mote_pseudo_table[opcode->m_opnum].poc_handler
+ (mote_pseudo_table[opcode->m_opnum].poc_val);
+ input_line_pointer = old;
+ *old = 0;
+
+ return;
+ }
+
+ if (flag_mri && opcode->m_opnum == 0)
+ {
+ /* In MRI mode, random garbage is allowed after an instruction
+ which accepts no operands. */
+ the_ins.args = opcode->m_operands;
+ the_ins.numargs = opcode->m_opnum;
+ the_ins.numo = opcode->m_codenum;
+ the_ins.opcode[0] = getone (opcode);
+ the_ins.opcode[1] = gettwo (opcode);
+ return;
+ }
+
+ for (opP = &the_ins.operands[0]; *p; opP++)
+ {
+ p = crack_operand (p, opP);
+
+ if (opP->error)
+ {
+ the_ins.error = opP->error;
+ return;
+ }
+ }
+
+ opsfound = opP - &the_ins.operands[0];
+
+ /* This ugly hack is to support the floating pt opcodes in their
+ standard form. Essentially, we fake a first enty of type COP#1 */
+ if (opcode->m_operands[0] == 'I')
+ {
+ int n;
+
+ for (n = opsfound; n > 0; --n)
+ the_ins.operands[n] = the_ins.operands[n - 1];
+
+ memset ((char *) (&the_ins.operands[0]), '\0',
+ sizeof (the_ins.operands[0]));
+ the_ins.operands[0].mode = CONTROL;
+ the_ins.operands[0].reg = m68k_float_copnum;
+ opsfound++;
+ }
+
+ /* We've got the operands. Find an opcode that'll accept them */
+ for (losing = 0;;)
+ {
+ /* If we didn't get the right number of ops, or we have no
+ common model with this pattern then reject this pattern. */
+
+ ok_arch |= opcode->m_arch;
+ if (opsfound != opcode->m_opnum
+ || ((opcode->m_arch & current_architecture) == 0))
+ ++losing;
+ else
+ {
+ for (s = opcode->m_operands, opP = &the_ins.operands[0];
+ *s && !losing;
+ s += 2, opP++)
+ {
+ /* Warning: this switch is huge! */
+ /* I've tried to organize the cases into this order:
+ non-alpha first, then alpha by letter. Lower-case
+ goes directly before uppercase counterpart. */
+ /* Code with multiple case ...: gets sorted by the lowest
+ case ... it belongs to. I hope this makes sense. */
+ switch (*s)
+ {
+ case '!':
+ switch (opP->mode)
+ {
+ case IMMED:
+ case DREG:
+ case AREG:
+ case FPREG:
+ case CONTROL:
+ case AINC:
+ case ADEC:
+ case REGLST:
+ losing++;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case '<':
+ switch (opP->mode)
+ {
+ case DREG:
+ case AREG:
+ case FPREG:
+ case CONTROL:
+ case IMMED:
+ case ADEC:
+ case REGLST:
+ losing++;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case '>':
+ switch (opP->mode)
+ {
+ case DREG:
+ case AREG:
+ case FPREG:
+ case CONTROL:
+ case IMMED:
+ case AINC:
+ case REGLST:
+ losing++;
+ break;
+ case ABSL:
+ break;
+ default:
+ if (opP->reg == PC
+ || opP->reg == ZPC)
+ losing++;
+ break;
+ }
+ break;
+
+ case 'm':
+ switch (opP->mode)
+ {
+ case DREG:
+ case AREG:
+ case AINDR:
+ case AINC:
+ case ADEC:
+ break;
+ default:
+ losing++;
+ }
+ break;
+
+ case 'n':
+ switch (opP->mode)
+ {
+ case DISP:
+ break;
+ default:
+ losing++;
+ }
+ break;
+
+ case 'o':
+ switch (opP->mode)
+ {
+ case BASE:
+ case ABSL:
+ case IMMED:
+ break;
+ default:
+ losing++;
+ }
+ break;
+
+ case 'p':
+ switch (opP->mode)
+ {
+ case DREG:
+ case AREG:
+ case AINDR:
+ case AINC:
+ case ADEC:
+ break;
+ case DISP:
+ if (opP->reg == PC || opP->reg == ZPC)
+ losing++;
+ break;
+ default:
+ losing++;
+ }
+ break;
+
+ case 'q':
+ switch (opP->mode)
+ {
+ case DREG:
+ case AINDR:
+ case AINC:
+ case ADEC:
+ break;
+ case DISP:
+ if (opP->reg == PC || opP->reg == ZPC)
+ losing++;
+ break;
+ default:
+ losing++;
+ break;
+ }
+ break;
+
+ case 'v':
+ switch (opP->mode)
+ {
+ case DREG:
+ case AINDR:
+ case AINC:
+ case ADEC:
+ case ABSL:
+ break;
+ case DISP:
+ if (opP->reg == PC || opP->reg == ZPC)
+ losing++;
+ break;
+ default:
+ losing++;
+ break;
+ }
+ break;
+
+ case '#':
+ if (opP->mode != IMMED)
+ losing++;
+ else if (s[1] == 'b'
+ && ! isvar (&opP->disp)
+ && (opP->disp.exp.X_op != O_constant
+ || ! isbyte (opP->disp.exp.X_add_number)))
+ losing++;
+ else if (s[1] == 'B'
+ && ! isvar (&opP->disp)
+ && (opP->disp.exp.X_op != O_constant
+ || ! issbyte (opP->disp.exp.X_add_number)))
+ losing++;
+ else if (s[1] == 'w'
+ && ! isvar (&opP->disp)
+ && (opP->disp.exp.X_op != O_constant
+ || ! isword (opP->disp.exp.X_add_number)))
+ losing++;
+ else if (s[1] == 'W'
+ && ! isvar (&opP->disp)
+ && (opP->disp.exp.X_op != O_constant
+ || ! issword (opP->disp.exp.X_add_number)))
+ losing++;
+ break;
+
+ case '^':
+ case 'T':
+ if (opP->mode != IMMED)
+ losing++;
+ break;
+
+ case '$':
+ if (opP->mode == AREG
+ || opP->mode == CONTROL
+ || opP->mode == FPREG
+ || opP->mode == IMMED
+ || opP->mode == REGLST
+ || (opP->mode != ABSL
+ && (opP->reg == PC
+ || opP->reg == ZPC)))
+ losing++;
+ break;
+
+ case '%':
+ if (opP->mode == CONTROL
+ || opP->mode == FPREG
+ || opP->mode == REGLST
+ || opP->mode == IMMED
+ || (opP->mode != ABSL
+ && (opP->reg == PC
+ || opP->reg == ZPC)))
+ losing++;
+ break;
+
+ case '&':
+ switch (opP->mode)
+ {
+ case DREG:
+ case AREG:
+ case FPREG:
+ case CONTROL:
+ case IMMED:
+ case AINC:
+ case ADEC:
+ case REGLST:
+ losing++;
+ break;
+ case ABSL:
+ break;
+ default:
+ if (opP->reg == PC
+ || opP->reg == ZPC)
+ losing++;
+ break;
+ }
+ break;
+
+ case '*':
+ if (opP->mode == CONTROL
+ || opP->mode == FPREG
+ || opP->mode == REGLST)
+ losing++;
+ break;
+
+ case '+':
+ if (opP->mode != AINC)
+ losing++;
+ break;
+
+ case '-':
+ if (opP->mode != ADEC)
+ losing++;
+ break;
+
+ case '/':
+ switch (opP->mode)
+ {
+ case AREG:
+ case CONTROL:
+ case FPREG:
+ case AINC:
+ case ADEC:
+ case IMMED:
+ case REGLST:
+ losing++;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case ';':
+ switch (opP->mode)
+ {
+ case AREG:
+ case CONTROL:
+ case FPREG:
+ case REGLST:
+ losing++;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case '?':
+ switch (opP->mode)
+ {
+ case AREG:
+ case CONTROL:
+ case FPREG:
+ case AINC:
+ case ADEC:
+ case IMMED:
+ case REGLST:
+ losing++;
+ break;
+ case ABSL:
+ break;
+ default:
+ if (opP->reg == PC || opP->reg == ZPC)
+ losing++;
+ break;
+ }
+ break;
+
+ case '@':
+ switch (opP->mode)
+ {
+ case AREG:
+ case CONTROL:
+ case FPREG:
+ case IMMED:
+ case REGLST:
+ losing++;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case '~': /* For now! (JF FOO is this right?) */
+ switch (opP->mode)
+ {
+ case DREG:
+ case AREG:
+ case CONTROL:
+ case FPREG:
+ case IMMED:
+ case REGLST:
+ losing++;
+ break;
+ case ABSL:
+ break;
+ default:
+ if (opP->reg == PC
+ || opP->reg == ZPC)
+ losing++;
+ break;
+ }
+ break;
+
+ case '3':
+ if (opP->mode != CONTROL
+ || (opP->reg != TT0 && opP->reg != TT1))
+ losing++;
+ break;
+
+ case 'A':
+ if (opP->mode != AREG)
+ losing++;
+ break;
+
+ case 'a':
+ if (opP->mode != AINDR)
+ ++losing;
+ break;
+
+ case 'B': /* FOO */
+ if (opP->mode != ABSL
+ || (flag_long_jumps
+ && strncmp (instring, "jbsr", 4) == 0))
+ losing++;
+ break;
+
+ case 'C':
+ if (opP->mode != CONTROL || opP->reg != CCR)
+ losing++;
+ break;
+
+ case 'd':
+ if (opP->mode != DISP
+ || opP->reg < ADDR0
+ || opP->reg > ADDR7)
+ losing++;
+ break;
+
+ case 'D':
+ if (opP->mode != DREG)
+ losing++;
+ break;
+
+ case 'F':
+ if (opP->mode != FPREG)
+ losing++;
+ break;
+
+ case 'I':
+ if (opP->mode != CONTROL
+ || opP->reg < COP0
+ || opP->reg > COP7)
+ losing++;
+ break;
+
+ case 'J':
+ if (opP->mode != CONTROL
+ || opP->reg < USP
+ || opP->reg > last_movec_reg)
+ losing++;
+ else
+ {
+ const enum m68k_register *rp;
+ for (rp = control_regs; *rp; rp++)
+ if (*rp == opP->reg)
+ break;
+ if (*rp == 0)
+ losing++;
+ }
+ break;
+
+ case 'k':
+ if (opP->mode != IMMED)
+ losing++;
+ break;
+
+ case 'l':
+ case 'L':
+ if (opP->mode == DREG
+ || opP->mode == AREG
+ || opP->mode == FPREG)
+ {
+ if (s[1] == '8')
+ losing++;
+ else
+ {
+ switch (opP->mode)
+ {
+ case DREG:
+ opP->mask = 1 << (opP->reg - DATA0);
+ break;
+ case AREG:
+ opP->mask = 1 << (opP->reg - ADDR0 + 8);
+ break;
+ case FPREG:
+ opP->mask = 1 << (opP->reg - FP0 + 16);
+ break;
+ default:
+ abort ();
+ }
+ opP->mode = REGLST;
+ }
+ }
+ else if (opP->mode == CONTROL)
+ {
+ if (s[1] != '8')
+ losing++;
+ else
+ {
+ switch (opP->reg)
+ {
+ case FPI:
+ opP->mask = 1 << 24;
+ break;
+ case FPS:
+ opP->mask = 1 << 25;
+ break;
+ case FPC:
+ opP->mask = 1 << 26;
+ break;
+ default:
+ losing++;
+ break;
+ }
+ opP->mode = REGLST;
+ }
+ }
+ else if (opP->mode != REGLST)
+ losing++;
+ else if (s[1] == '8' && (opP->mask & 0x0ffffff) != 0)
+ losing++;
+ else if (s[1] == '3' && (opP->mask & 0x7000000) != 0)
+ losing++;
+ break;
+
+ case 'M':
+ if (opP->mode != IMMED)
+ losing++;
+ else if (opP->disp.exp.X_op != O_constant
+ || ! issbyte (opP->disp.exp.X_add_number))
+ losing++;
+ else if (! m68k_quick
+ && instring[3] != 'q'
+ && instring[4] != 'q')
+ losing++;
+ break;
+
+ case 'O':
+ if (opP->mode != DREG
+ && opP->mode != IMMED
+ && opP->mode != ABSL)
+ losing++;
+ break;
+
+ case 'Q':
+ if (opP->mode != IMMED)
+ losing++;
+ else if (opP->disp.exp.X_op != O_constant
+ || opP->disp.exp.X_add_number < 1
+ || opP->disp.exp.X_add_number > 8)
+ losing++;
+ else if (! m68k_quick
+ && (strncmp (instring, "add", 3) == 0
+ || strncmp (instring, "sub", 3) == 0)
+ && instring[3] != 'q')
+ losing++;
+ break;
+
+ case 'R':
+ if (opP->mode != DREG && opP->mode != AREG)
+ losing++;
+ break;
+
+ case 'r':
+ if (opP->mode != AINDR
+ && (opP->mode != BASE
+ || (opP->reg != 0
+ && opP->reg != ZADDR0)
+ || opP->disp.exp.X_op != O_absent
+ || ((opP->index.reg < DATA0
+ || opP->index.reg > DATA7)
+ && (opP->index.reg < ADDR0
+ || opP->index.reg > ADDR7))
+ || opP->index.size != SIZE_UNSPEC
+ || opP->index.scale != 1))
+ losing++;
+ break;
+
+ case 's':
+ if (opP->mode != CONTROL
+ || ! (opP->reg == FPI
+ || opP->reg == FPS
+ || opP->reg == FPC))
+ losing++;
+ break;
+
+ case 'S':
+ if (opP->mode != CONTROL || opP->reg != SR)
+ losing++;
+ break;
+
+ case 't':
+ if (opP->mode != IMMED)
+ losing++;
+ else if (opP->disp.exp.X_op != O_constant
+ || opP->disp.exp.X_add_number < 0
+ || opP->disp.exp.X_add_number > 7)
+ losing++;
+ break;
+
+ case 'U':
+ if (opP->mode != CONTROL || opP->reg != USP)
+ losing++;
+ break;
+
+ /* JF these are out of order. We could put them
+ in order if we were willing to put up with
+ bunches of #ifdef m68851s in the code.
+
+ Don't forget that you need these operands
+ to use 68030 MMU instructions. */
+#ifndef NO_68851
+ /* Memory addressing mode used by pflushr */
+ case '|':
+ if (opP->mode == CONTROL
+ || opP->mode == FPREG
+ || opP->mode == DREG
+ || opP->mode == AREG
+ || opP->mode == REGLST)
+ losing++;
+ /* We should accept immediate operands, but they
+ supposedly have to be quad word, and we don't
+ handle that. I would like to see what a Motorola
+ assembler does before doing something here. */
+ if (opP->mode == IMMED)
+ losing++;
+ break;
+
+ case 'f':
+ if (opP->mode != CONTROL
+ || (opP->reg != SFC && opP->reg != DFC))
+ losing++;
+ break;
+
+ case '0':
+ if (opP->mode != CONTROL || opP->reg != TC)
+ losing++;
+ break;
+
+ case '1':
+ if (opP->mode != CONTROL || opP->reg != AC)
+ losing++;
+ break;
+
+ case '2':
+ if (opP->mode != CONTROL
+ || (opP->reg != CAL
+ && opP->reg != VAL
+ && opP->reg != SCC))
+ losing++;
+ break;
+
+ case 'V':
+ if (opP->mode != CONTROL
+ || opP->reg != VAL)
+ losing++;
+ break;
+
+ case 'W':
+ if (opP->mode != CONTROL
+ || (opP->reg != DRP
+ && opP->reg != SRP
+ && opP->reg != CRP))
+ losing++;
+ break;
+
+ case 'X':
+ if (opP->mode != CONTROL
+ || (!(opP->reg >= BAD && opP->reg <= BAD + 7)
+ && !(opP->reg >= BAC && opP->reg <= BAC + 7)))
+ losing++;
+ break;
+
+ case 'Y':
+ if (opP->mode != CONTROL || opP->reg != PSR)
+ losing++;
+ break;
+
+ case 'Z':
+ if (opP->mode != CONTROL || opP->reg != PCSR)
+ losing++;
+ break;
+#endif
+ case 'c':
+ if (opP->mode != CONTROL
+ || (opP->reg != NC
+ && opP->reg != IC
+ && opP->reg != DC
+ && opP->reg != BC))
+ {
+ losing++;
+ } /* not a cache specifier. */
+ break;
+
+ case '_':
+ if (opP->mode != ABSL)
+ ++losing;
+ break;
+
+ default:
+ abort ();
+ } /* switch on type of operand */
+
+ if (losing)
+ break;
+ } /* for each operand */
+ } /* if immediately wrong */
+
+ if (!losing)
+ {
+ break;
+ } /* got it. */
+
+ opcode = opcode->m_next;
+
+ if (!opcode)
+ {
+ if (ok_arch
+ && !(ok_arch & current_architecture))
+ {
+ char buf[200], *cp;
+
+ strcpy (buf,
+ _("invalid instruction for this architecture; needs "));
+ cp = buf + strlen (buf);
+ switch (ok_arch)
+ {
+ case mfloat:
+ strcpy (cp, _("fpu (68040, 68060 or 68881/68882)"));
+ break;
+ case mmmu:
+ strcpy (cp, _("mmu (68030 or 68851)"));
+ break;
+ case m68020up:
+ strcpy (cp, _("68020 or higher"));
+ break;
+ case m68000up:
+ strcpy (cp, _("68000 or higher"));
+ break;
+ case m68010up:
+ strcpy (cp, _("68010 or higher"));
+ break;
+ default:
+ {
+ int got_one = 0, idx;
+ for (idx = 0; idx < sizeof (archs) / sizeof (archs[0]);
+ idx++)
+ {
+ if ((archs[idx].arch & ok_arch)
+ && ! archs[idx].alias)
+ {
+ if (got_one)
+ {
+ strcpy (cp, " or ");
+ cp += strlen (cp);
+ }
+ got_one = 1;
+ strcpy (cp, archs[idx].name);
+ cp += strlen (cp);
+ }
+ }
+ }
+ }
+ cp = xmalloc (strlen (buf) + 1);
+ strcpy (cp, buf);
+ the_ins.error = cp;
+ }
+ else
+ the_ins.error = _("operands mismatch");
+ return;
+ } /* Fell off the end */
+
+ losing = 0;
+ }
+
+ /* now assemble it */
+
+ the_ins.args = opcode->m_operands;
+ the_ins.numargs = opcode->m_opnum;
+ the_ins.numo = opcode->m_codenum;
+ the_ins.opcode[0] = getone (opcode);
+ the_ins.opcode[1] = gettwo (opcode);
+
+ for (s = the_ins.args, opP = &the_ins.operands[0]; *s; s += 2, opP++)
+ {
+ /* This switch is a doozy.
+ Watch the first step; its a big one! */
+ switch (s[0])
+ {
+
+ case '*':
+ case '~':
+ case '%':
+ case ';':
+ case '@':
+ case '!':
+ case '&':
+ case '$':
+ case '?':
+ case '/':
+ case '<':
+ case '>':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'v':
+#ifndef NO_68851
+ case '|':
+#endif
+ switch (opP->mode)
+ {
+ case IMMED:
+ tmpreg = 0x3c; /* 7.4 */
+ if (strchr ("bwl", s[1]))
+ nextword = get_num (&opP->disp, 80);
+ else
+ nextword = get_num (&opP->disp, 0);
+ if (isvar (&opP->disp))
+ add_fix (s[1], &opP->disp, 0, 0);
+ switch (s[1])
+ {
+ case 'b':
+ if (!isbyte (nextword))
+ opP->error = _("operand out of range");
+ addword (nextword);
+ baseo = 0;
+ break;
+ case 'w':
+ if (!isword (nextword))
+ opP->error = _("operand out of range");
+ addword (nextword);
+ baseo = 0;
+ break;
+ case 'W':
+ if (!issword (nextword))
+ opP->error = _("operand out of range");
+ addword (nextword);
+ baseo = 0;
+ break;
+ case 'l':
+ addword (nextword >> 16);
+ addword (nextword);
+ baseo = 0;
+ break;
+
+ case 'f':
+ baseo = 2;
+ outro = 8;
+ break;
+ case 'F':
+ baseo = 4;
+ outro = 11;
+ break;
+ case 'x':
+ baseo = 6;
+ outro = 15;
+ break;
+ case 'p':
+ baseo = 6;
+ outro = -1;
+ break;
+ default:
+ abort ();
+ }
+ if (!baseo)
+ break;
+
+ /* We gotta put out some float */
+ if (op (&opP->disp) != O_big)
+ {
+ valueT val;
+ int gencnt;
+
+ /* Can other cases happen here? */
+ if (op (&opP->disp) != O_constant)
+ abort ();
+
+ val = (valueT) offs (&opP->disp);
+ gencnt = 0;
+ do
+ {
+ generic_bignum[gencnt] = (LITTLENUM_TYPE) val;
+ val >>= LITTLENUM_NUMBER_OF_BITS;
+ ++gencnt;
+ }
+ while (val != 0);
+ offs (&opP->disp) = gencnt;
+ }
+ if (offs (&opP->disp) > 0)
+ {
+ if (offs (&opP->disp) > baseo)
+ {
+ as_warn (_("Bignum too big for %c format; truncated"),
+ s[1]);
+ offs (&opP->disp) = baseo;
+ }
+ baseo -= offs (&opP->disp);
+ while (baseo--)
+ addword (0);
+ for (wordp = generic_bignum + offs (&opP->disp) - 1;
+ offs (&opP->disp)--;
+ --wordp)
+ addword (*wordp);
+ break;
+ }
+ gen_to_words (words, baseo, (long) outro);
+ for (wordp = words; baseo--; wordp++)
+ addword (*wordp);
+ break;
+ case DREG:
+ tmpreg = opP->reg - DATA; /* 0.dreg */
+ break;
+ case AREG:
+ tmpreg = 0x08 + opP->reg - ADDR; /* 1.areg */
+ break;
+ case AINDR:
+ tmpreg = 0x10 + opP->reg - ADDR; /* 2.areg */
+ break;
+ case ADEC:
+ tmpreg = 0x20 + opP->reg - ADDR; /* 4.areg */
+ break;
+ case AINC:
+ tmpreg = 0x18 + opP->reg - ADDR; /* 3.areg */
+ break;
+ case DISP:
+
+ nextword = get_num (&opP->disp, 80);
+
+ if (opP->reg == PC
+ && ! isvar (&opP->disp)
+ && m68k_abspcadd)
+ {
+ opP->disp.exp.X_op = O_symbol;
+#ifndef BFD_ASSEMBLER
+ opP->disp.exp.X_add_symbol = &abs_symbol;
+#else
+ opP->disp.exp.X_add_symbol =
+ section_symbol (absolute_section);
+#endif
+ }
+
+ /* Force into index mode. Hope this works */
+
+ /* We do the first bit for 32-bit displacements, and the
+ second bit for 16 bit ones. It is possible that we
+ should make the default be WORD instead of LONG, but
+ I think that'd break GCC, so we put up with a little
+ inefficiency for the sake of working output. */
+
+ if (!issword (nextword)
+ || (isvar (&opP->disp)
+ && ((opP->disp.size == SIZE_UNSPEC
+ && flag_short_refs == 0
+ && cpu_of_arch (current_architecture) >= m68020
+ && cpu_of_arch (current_architecture) != mcf5200)
+ || opP->disp.size == SIZE_LONG)))
+ {
+ if (cpu_of_arch (current_architecture) < m68020
+ || cpu_of_arch (current_architecture) == mcf5200)
+ opP->error =
+ _("displacement too large for this architecture; needs 68020 or higher");
+ if (opP->reg == PC)
+ tmpreg = 0x3B; /* 7.3 */
+ else
+ tmpreg = 0x30 + opP->reg - ADDR; /* 6.areg */
+ if (isvar (&opP->disp))
+ {
+ if (opP->reg == PC)
+ {
+ if (opP->disp.size == SIZE_LONG
+#ifdef OBJ_ELF
+ /* If the displacement needs pic
+ relocation it cannot be relaxed. */
+ || opP->disp.pic_reloc != pic_none
+#endif
+ )
+ {
+ addword (0x0170);
+ add_fix ('l', &opP->disp, 1, 2);
+ }
+ else
+ {
+ add_frag (adds (&opP->disp),
+ offs (&opP->disp),
+ TAB (PCLEA, SZ_UNDEF));
+ break;
+ }
+ }
+ else
+ {
+ addword (0x0170);
+ add_fix ('l', &opP->disp, 0, 0);
+ }
+ }
+ else
+ addword (0x0170);
+ addword (nextword >> 16);
+ }
+ else
+ {
+ if (opP->reg == PC)
+ tmpreg = 0x3A; /* 7.2 */
+ else
+ tmpreg = 0x28 + opP->reg - ADDR; /* 5.areg */
+
+ if (isvar (&opP->disp))
+ {
+ if (opP->reg == PC)
+ {
+ add_fix ('w', &opP->disp, 1, 0);
+ }
+ else
+ add_fix ('w', &opP->disp, 0, 0);
+ }
+ }
+ addword (nextword);
+ break;
+
+ case POST:
+ case PRE:
+ case BASE:
+ nextword = 0;
+ baseo = get_num (&opP->disp, 80);
+ if (opP->mode == POST || opP->mode == PRE)
+ outro = get_num (&opP->odisp, 80);
+ /* Figure out the `addressing mode'.
+ Also turn on the BASE_DISABLE bit, if needed. */
+ if (opP->reg == PC || opP->reg == ZPC)
+ {
+ tmpreg = 0x3b; /* 7.3 */
+ if (opP->reg == ZPC)
+ nextword |= 0x80;
+ }
+ else if (opP->reg == 0)
+ {
+ nextword |= 0x80;
+ tmpreg = 0x30; /* 6.garbage */
+ }
+ else if (opP->reg >= ZADDR0 && opP->reg <= ZADDR7)
+ {
+ nextword |= 0x80;
+ tmpreg = 0x30 + opP->reg - ZADDR0;
+ }
+ else
+ tmpreg = 0x30 + opP->reg - ADDR; /* 6.areg */
+
+ siz1 = opP->disp.size;
+ if (opP->mode == POST || opP->mode == PRE)
+ siz2 = opP->odisp.size;
+ else
+ siz2 = SIZE_UNSPEC;
+
+ /* Index register stuff */
+ if (opP->index.reg != 0
+ && opP->index.reg >= DATA
+ && opP->index.reg <= ADDR7)
+ {
+ nextword |= (opP->index.reg - DATA) << 12;
+
+ if (opP->index.size == SIZE_LONG
+ || (opP->index.size == SIZE_UNSPEC
+ && m68k_index_width_default == SIZE_LONG))
+ nextword |= 0x800;
+
+ if ((opP->index.scale != 1
+ && cpu_of_arch (current_architecture) < m68020)
+ || (opP->index.scale == 8
+ && current_architecture == mcf5200))
+ {
+ opP->error =
+ _("scale factor invalid on this architecture; needs cpu32 or 68020 or higher");
+ }
+
+ switch (opP->index.scale)
+ {
+ case 1:
+ break;
+ case 2:
+ nextword |= 0x200;
+ break;
+ case 4:
+ nextword |= 0x400;
+ break;
+ case 8:
+ nextword |= 0x600;
+ break;
+ default:
+ abort ();
+ }
+ /* IF its simple,
+ GET US OUT OF HERE! */
+
+ /* Must be INDEX, with an index register. Address
+ register cannot be ZERO-PC, and either :b was
+ forced, or we know it will fit. For a 68000 or
+ 68010, force this mode anyways, because the
+ larger modes aren't supported. */
+ if (opP->mode == BASE
+ && ((opP->reg >= ADDR0
+ && opP->reg <= ADDR7)
+ || opP->reg == PC))
+ {
+ if (siz1 == SIZE_BYTE
+ || cpu_of_arch (current_architecture) < m68020
+ || cpu_of_arch (current_architecture) == mcf5200
+ || (siz1 == SIZE_UNSPEC
+ && ! isvar (&opP->disp)
+ && issbyte (baseo)))
+ {
+ nextword += baseo & 0xff;
+ addword (nextword);
+ if (isvar (&opP->disp))
+ {
+ /* Do a byte relocation. If it doesn't
+ fit (possible on m68000) let the
+ fixup processing complain later. */
+ if (opP->reg == PC)
+ add_fix ('B', &opP->disp, 1, 1);
+ else
+ add_fix ('B', &opP->disp, 0, 0);
+ }
+ else if (siz1 != SIZE_BYTE)
+ {
+ if (siz1 != SIZE_UNSPEC)
+ as_warn (_("Forcing byte displacement"));
+ if (! issbyte (baseo))
+ opP->error = _("byte displacement out of range");
+ }
+
+ break;
+ }
+ else if (siz1 == SIZE_UNSPEC
+ && opP->reg == PC
+ && isvar (&opP->disp)
+ && subs (&opP->disp) == NULL
+#ifdef OBJ_ELF
+ /* If the displacement needs pic
+ relocation it cannot be relaxed. */
+ && opP->disp.pic_reloc == pic_none
+#endif
+ )
+ {
+ /* The code in md_convert_frag_1 needs to be
+ able to adjust nextword. Call frag_grow
+ to ensure that we have enough space in
+ the frag obstack to make all the bytes
+ contiguous. */
+ frag_grow (14);
+ nextword += baseo & 0xff;
+ addword (nextword);
+ add_frag (adds (&opP->disp), offs (&opP->disp),
+ TAB (PCINDEX, SZ_UNDEF));
+
+ break;
+ }
+ }
+ }
+ else
+ {
+ nextword |= 0x40; /* No index reg */
+ if (opP->index.reg >= ZDATA0
+ && opP->index.reg <= ZDATA7)
+ nextword |= (opP->index.reg - ZDATA0) << 12;
+ else if (opP->index.reg >= ZADDR0
+ || opP->index.reg <= ZADDR7)
+ nextword |= (opP->index.reg - ZADDR0 + 8) << 12;
+ }
+
+ /* It isn't simple. */
+
+ if (cpu_of_arch (current_architecture) < m68020
+ || cpu_of_arch (current_architecture) == mcf5200)
+ opP->error =
+ _("invalid operand mode for this architecture; needs 68020 or higher");
+
+ nextword |= 0x100;
+ /* If the guy specified a width, we assume that it is
+ wide enough. Maybe it isn't. If so, we lose. */
+ switch (siz1)
+ {
+ case SIZE_UNSPEC:
+ if (isvar (&opP->disp)
+ ? m68k_rel32
+ : ! issword (baseo))
+ {
+ siz1 = SIZE_LONG;
+ nextword |= 0x30;
+ }
+ else if (! isvar (&opP->disp) && baseo == 0)
+ nextword |= 0x10;
+ else
+ {
+ nextword |= 0x20;
+ siz1 = SIZE_WORD;
+ }
+ break;
+ case SIZE_BYTE:
+ as_warn (_(":b not permitted; defaulting to :w"));
+ /* Fall through. */
+ case SIZE_WORD:
+ nextword |= 0x20;
+ break;
+ case SIZE_LONG:
+ nextword |= 0x30;
+ break;
+ }
+
+ /* Figure out innner displacement stuff */
+ if (opP->mode == POST || opP->mode == PRE)
+ {
+ if (cpu_of_arch (current_architecture) & cpu32)
+ opP->error = _("invalid operand mode for this architecture; needs 68020 or higher");
+ switch (siz2)
+ {
+ case SIZE_UNSPEC:
+ if (isvar (&opP->odisp)
+ ? m68k_rel32
+ : ! issword (outro))
+ {
+ siz2 = SIZE_LONG;
+ nextword |= 0x3;
+ }
+ else if (! isvar (&opP->odisp) && outro == 0)
+ nextword |= 0x1;
+ else
+ {
+ nextword |= 0x2;
+ siz2 = SIZE_WORD;
+ }
+ break;
+ case 1:
+ as_warn (_(":b not permitted; defaulting to :w"));
+ /* Fall through. */
+ case 2:
+ nextword |= 0x2;
+ break;
+ case 3:
+ nextword |= 0x3;
+ break;
+ }
+ if (opP->mode == POST
+ && (nextword & 0x40) == 0)
+ nextword |= 0x04;
+ }
+ addword (nextword);
+
+ if (siz1 != SIZE_UNSPEC && isvar (&opP->disp))
+ {
+ if (opP->reg == PC || opP->reg == ZPC)
+ add_fix (siz1 == SIZE_LONG ? 'l' : 'w', &opP->disp, 1, 2);
+ else
+ add_fix (siz1 == SIZE_LONG ? 'l' : 'w', &opP->disp, 0, 0);
+ }
+ if (siz1 == SIZE_LONG)
+ addword (baseo >> 16);
+ if (siz1 != SIZE_UNSPEC)
+ addword (baseo);
+
+ if (siz2 != SIZE_UNSPEC && isvar (&opP->odisp))
+ add_fix (siz2 == SIZE_LONG ? 'l' : 'w', &opP->odisp, 0, 0);
+ if (siz2 == SIZE_LONG)
+ addword (outro >> 16);
+ if (siz2 != SIZE_UNSPEC)
+ addword (outro);
+
+ break;
+
+ case ABSL:
+ nextword = get_num (&opP->disp, 80);
+ switch (opP->disp.size)
+ {
+ default:
+ abort ();
+ case SIZE_UNSPEC:
+ if (!isvar (&opP->disp) && issword (offs (&opP->disp)))
+ {
+ tmpreg = 0x38; /* 7.0 */
+ addword (nextword);
+ break;
+ }
+ /* Don't generate pc relative code on 68010 and
+ 68000. */
+ if (isvar (&opP->disp)
+ && !subs (&opP->disp)
+ && adds (&opP->disp)
+#ifdef OBJ_ELF
+ /* If the displacement needs pic relocation it
+ cannot be relaxed. */
+ && opP->disp.pic_reloc == pic_none
+#endif
+ && S_GET_SEGMENT (adds (&opP->disp)) == now_seg
+ && relaxable_symbol (adds (&opP->disp))
+ && HAVE_LONG_BRANCH(current_architecture)
+ && !flag_long_jumps
+ && !strchr ("~%&$?", s[0]))
+ {
+ tmpreg = 0x3A; /* 7.2 */
+ add_frag (adds (&opP->disp),
+ offs (&opP->disp),
+ TAB (PCREL, SZ_UNDEF));
+ break;
+ }
+ /* Fall through into long */
+ case SIZE_LONG:
+ if (isvar (&opP->disp))
+ add_fix ('l', &opP->disp, 0, 0);
+
+ tmpreg = 0x39;/* 7.1 mode */
+ addword (nextword >> 16);
+ addword (nextword);
+ break;
+
+ case SIZE_BYTE:
+ as_bad (_("unsupported byte value; use a different suffix"));
+ /* Fall through. */
+ case SIZE_WORD: /* Word */
+ if (isvar (&opP->disp))
+ add_fix ('w', &opP->disp, 0, 0);
+
+ tmpreg = 0x38;/* 7.0 mode */
+ addword (nextword);
+ break;
+ }
+ break;
+ case CONTROL:
+ case FPREG:
+ default:
+ as_bad (_("unknown/incorrect operand"));
+ /* abort(); */
+ }
+ install_gen_operand (s[1], tmpreg);
+ break;
+
+ case '#':
+ case '^':
+ switch (s[1])
+ { /* JF: I hate floating point! */
+ case 'j':
+ tmpreg = 70;
+ break;
+ case '8':
+ tmpreg = 20;
+ break;
+ case 'C':
+ tmpreg = 50;
+ break;
+ case '3':
+ default:
+ tmpreg = 80;
+ break;
+ }
+ tmpreg = get_num (&opP->disp, tmpreg);
+ if (isvar (&opP->disp))
+ add_fix (s[1], &opP->disp, 0, 0);
+ switch (s[1])
+ {
+ case 'b': /* Danger: These do no check for
+ certain types of overflow.
+ user beware! */
+ if (!isbyte (tmpreg))
+ opP->error = _("out of range");
+ insop (tmpreg, opcode);
+ if (isvar (&opP->disp))
+ the_ins.reloc[the_ins.nrel - 1].n =
+ (opcode->m_codenum) * 2 + 1;
+ break;
+ case 'B':
+ if (!issbyte (tmpreg))
+ opP->error = _("out of range");
+ the_ins.opcode[the_ins.numo - 1] |= tmpreg & 0xff;
+ if (isvar (&opP->disp))
+ the_ins.reloc[the_ins.nrel - 1].n = opcode->m_codenum * 2 - 1;
+ break;
+ case 'w':
+ if (!isword (tmpreg))
+ opP->error = _("out of range");
+ insop (tmpreg, opcode);
+ if (isvar (&opP->disp))
+ the_ins.reloc[the_ins.nrel - 1].n = (opcode->m_codenum) * 2;
+ break;
+ case 'W':
+ if (!issword (tmpreg))
+ opP->error = _("out of range");
+ insop (tmpreg, opcode);
+ if (isvar (&opP->disp))
+ the_ins.reloc[the_ins.nrel - 1].n = (opcode->m_codenum) * 2;
+ break;
+ case 'l':
+ /* Because of the way insop works, we put these two out
+ backwards. */
+ insop (tmpreg, opcode);
+ insop (tmpreg >> 16, opcode);
+ if (isvar (&opP->disp))
+ the_ins.reloc[the_ins.nrel - 1].n = (opcode->m_codenum) * 2;
+ break;
+ case '3':
+ tmpreg &= 0xFF;
+ case '8':
+ case 'C':
+ case 'j':
+ install_operand (s[1], tmpreg);
+ break;
+ default:
+ abort ();
+ }
+ break;
+
+ case '+':
+ case '-':
+ case 'A':
+ case 'a':
+ install_operand (s[1], opP->reg - ADDR);
+ break;
+
+ case 'B':
+ tmpreg = get_num (&opP->disp, 80);
+ switch (s[1])
+ {
+ case 'B':
+ /* The pc_fix argument winds up in fx_pcrel_adjust,
+ which is a char, and may therefore be unsigned. We
+ want to pass -1, but we pass 64 instead, and convert
+ back in md_pcrel_from. */
+ add_fix ('B', &opP->disp, 1, 64);
+ break;
+ case 'W':
+ add_fix ('w', &opP->disp, 1, 0);
+ addword (0);
+ break;
+ case 'L':
+ long_branch:
+ if (!HAVE_LONG_BRANCH(current_architecture))
+ as_warn (_("Can't use long branches on 68000/68010/5200"));
+ the_ins.opcode[the_ins.numo - 1] |= 0xff;
+ add_fix ('l', &opP->disp, 1, 0);
+ addword (0);
+ addword (0);
+ break;
+ case 'g':
+ if (subs (&opP->disp)) /* We can't relax it */
+ goto long_branch;
+
+#ifdef OBJ_ELF
+ /* If the displacement needs pic relocation it cannot be
+ relaxed. */
+ if (opP->disp.pic_reloc != pic_none)
+ goto long_branch;
+#endif
+
+ /* This could either be a symbol, or an absolute
+ address. No matter, the frag hacking will finger it
+ out. Not quite: it can't switch from BRANCH to
+ BCC68000 for the case where opnd is absolute (it
+ needs to use the 68000 hack since no conditional abs
+ jumps). */
+ if (( !HAVE_LONG_BRANCH(current_architecture)
+ || (0 == adds (&opP->disp)))
+ && (the_ins.opcode[0] >= 0x6200)
+ && (the_ins.opcode[0] <= 0x6f00))
+ add_frag (adds (&opP->disp), offs (&opP->disp),
+ TAB (BCC68000, SZ_UNDEF));
+ else
+ add_frag (adds (&opP->disp), offs (&opP->disp),
+ TAB (ABRANCH, SZ_UNDEF));
+ break;
+ case 'w':
+ if (isvar (&opP->disp))
+ {
+#if 1
+ /* check for DBcc instruction */
+ if ((the_ins.opcode[0] & 0xf0f8) == 0x50c8)
+ {
+ /* size varies if patch */
+ /* needed for long form */
+ add_frag (adds (&opP->disp), offs (&opP->disp),
+ TAB (DBCC, SZ_UNDEF));
+ break;
+ }
+#endif
+ add_fix ('w', &opP->disp, 1, 0);
+ }
+ addword (0);
+ break;
+ case 'C': /* Fixed size LONG coproc branches */
+ add_fix ('l', &opP->disp, 1, 0);
+ addword (0);
+ addword (0);
+ break;
+ case 'c': /* Var size Coprocesssor branches */
+ if (subs (&opP->disp))
+ {
+ add_fix ('l', &opP->disp, 1, 0);
+ add_frag ((symbolS *) 0, (offsetT) 0, TAB (FBRANCH, LONG));
+ }
+ else if (adds (&opP->disp))
+ add_frag (adds (&opP->disp), offs (&opP->disp),
+ TAB (FBRANCH, SZ_UNDEF));
+ else
+ {
+ /* add_frag ((symbolS *) 0, offs (&opP->disp),
+ TAB(FBRANCH,SHORT)); */
+ the_ins.opcode[the_ins.numo - 1] |= 0x40;
+ add_fix ('l', &opP->disp, 1, 0);
+ addword (0);
+ addword (0);
+ }
+ break;
+ default:
+ abort ();
+ }
+ break;
+
+ case 'C': /* Ignore it */
+ break;
+
+ case 'd': /* JF this is a kludge */
+ install_operand ('s', opP->reg - ADDR);
+ tmpreg = get_num (&opP->disp, 80);
+ if (!issword (tmpreg))
+ {
+ as_warn (_("Expression out of range, using 0"));
+ tmpreg = 0;
+ }
+ addword (tmpreg);
+ break;
+
+ case 'D':
+ install_operand (s[1], opP->reg - DATA);
+ break;
+
+ case 'F':
+ install_operand (s[1], opP->reg - FP0);
+ break;
+
+ case 'I':
+ tmpreg = opP->reg - COP0;
+ install_operand (s[1], tmpreg);
+ break;
+
+ case 'J': /* JF foo */
+ switch (opP->reg)
+ {
+ case SFC:
+ tmpreg = 0x000;
+ break;
+ case DFC:
+ tmpreg = 0x001;
+ break;
+ case CACR:
+ tmpreg = 0x002;
+ break;
+ case TC:
+ tmpreg = 0x003;
+ break;
+ case ITT0:
+ tmpreg = 0x004;
+ break;
+ case ITT1:
+ tmpreg = 0x005;
+ break;
+ case DTT0:
+ tmpreg = 0x006;
+ break;
+ case DTT1:
+ tmpreg = 0x007;
+ break;
+ case BUSCR:
+ tmpreg = 0x008;
+ break;
+
+ case USP:
+ tmpreg = 0x800;
+ break;
+ case VBR:
+ tmpreg = 0x801;
+ break;
+ case CAAR:
+ tmpreg = 0x802;
+ break;
+ case MSP:
+ tmpreg = 0x803;
+ break;
+ case ISP:
+ tmpreg = 0x804;
+ break;
+ case MMUSR:
+ tmpreg = 0x805;
+ break;
+ case URP:
+ tmpreg = 0x806;
+ break;
+ case SRP:
+ tmpreg = 0x807;
+ break;
+ case PCR:
+ tmpreg = 0x808;
+ break;
+ case ROMBAR:
+ tmpreg = 0xC00;
+ break;
+ case RAMBAR0:
+ tmpreg = 0xC04;
+ break;
+ case RAMBAR1:
+ tmpreg = 0xC05;
+ break;
+ case MBAR:
+ tmpreg = 0xC0F;
+ break;
+ default:
+ abort ();
+ }
+ install_operand (s[1], tmpreg);
+ break;
+
+ case 'k':
+ tmpreg = get_num (&opP->disp, 55);
+ install_operand (s[1], tmpreg & 0x7f);
+ break;
+
+ case 'l':
+ tmpreg = opP->mask;
+ if (s[1] == 'w')
+ {
+ if (tmpreg & 0x7FF0000)
+ as_bad (_("Floating point register in register list"));
+ insop (reverse_16_bits (tmpreg), opcode);
+ }
+ else
+ {
+ if (tmpreg & 0x700FFFF)
+ as_bad (_("Wrong register in floating-point reglist"));
+ install_operand (s[1], reverse_8_bits (tmpreg >> 16));
+ }
+ break;
+
+ case 'L':
+ tmpreg = opP->mask;
+ if (s[1] == 'w')
+ {
+ if (tmpreg & 0x7FF0000)
+ as_bad (_("Floating point register in register list"));
+ insop (tmpreg, opcode);
+ }
+ else if (s[1] == '8')
+ {
+ if (tmpreg & 0x0FFFFFF)
+ as_bad (_("incorrect register in reglist"));
+ install_operand (s[1], tmpreg >> 24);
+ }
+ else
+ {
+ if (tmpreg & 0x700FFFF)
+ as_bad (_("wrong register in floating-point reglist"));
+ else
+ install_operand (s[1], tmpreg >> 16);
+ }
+ break;
+
+ case 'M':
+ install_operand (s[1], get_num (&opP->disp, 60));
+ break;
+
+ case 'O':
+ tmpreg = ((opP->mode == DREG)
+ ? 0x20 + opP->reg - DATA
+ : (get_num (&opP->disp, 40) & 0x1F));
+ install_operand (s[1], tmpreg);
+ break;
+
+ case 'Q':
+ tmpreg = get_num (&opP->disp, 10);
+ if (tmpreg == 8)
+ tmpreg = 0;
+ install_operand (s[1], tmpreg);
+ break;
+
+ case 'R':
+ /* This depends on the fact that ADDR registers are eight
+ more than their corresponding DATA regs, so the result
+ will have the ADDR_REG bit set */
+ install_operand (s[1], opP->reg - DATA);
+ break;
+
+ case 'r':
+ if (opP->mode == AINDR)
+ install_operand (s[1], opP->reg - DATA);
+ else
+ install_operand (s[1], opP->index.reg - DATA);
+ break;
+
+ case 's':
+ if (opP->reg == FPI)
+ tmpreg = 0x1;
+ else if (opP->reg == FPS)
+ tmpreg = 0x2;
+ else if (opP->reg == FPC)
+ tmpreg = 0x4;
+ else
+ abort ();
+ install_operand (s[1], tmpreg);
+ break;
+
+ case 'S': /* Ignore it */
+ break;
+
+ case 'T':
+ install_operand (s[1], get_num (&opP->disp, 30));
+ break;
+
+ case 'U': /* Ignore it */
+ break;
+
+ case 'c':
+ switch (opP->reg)
+ {
+ case NC:
+ tmpreg = 0;
+ break;
+ case DC:
+ tmpreg = 1;
+ break;
+ case IC:
+ tmpreg = 2;
+ break;
+ case BC:
+ tmpreg = 3;
+ break;
+ default:
+ as_fatal (_("failed sanity check"));
+ } /* switch on cache token */
+ install_operand (s[1], tmpreg);
+ break;
+#ifndef NO_68851
+ /* JF: These are out of order, I fear. */
+ case 'f':
+ switch (opP->reg)
+ {
+ case SFC:
+ tmpreg = 0;
+ break;
+ case DFC:
+ tmpreg = 1;
+ break;
+ default:
+ abort ();
+ }
+ install_operand (s[1], tmpreg);
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ switch (opP->reg)
+ {
+ case TC:
+ tmpreg = 0;
+ break;
+ case CAL:
+ tmpreg = 4;
+ break;
+ case VAL:
+ tmpreg = 5;
+ break;
+ case SCC:
+ tmpreg = 6;
+ break;
+ case AC:
+ tmpreg = 7;
+ break;
+ default:
+ abort ();
+ }
+ install_operand (s[1], tmpreg);
+ break;
+
+ case 'V':
+ if (opP->reg == VAL)
+ break;
+ abort ();
+
+ case 'W':
+ switch (opP->reg)
+ {
+ case DRP:
+ tmpreg = 1;
+ break;
+ case SRP:
+ tmpreg = 2;
+ break;
+ case CRP:
+ tmpreg = 3;
+ break;
+ default:
+ abort ();
+ }
+ install_operand (s[1], tmpreg);
+ break;
+
+ case 'X':
+ switch (opP->reg)
+ {
+ case BAD:
+ case BAD + 1:
+ case BAD + 2:
+ case BAD + 3:
+ case BAD + 4:
+ case BAD + 5:
+ case BAD + 6:
+ case BAD + 7:
+ tmpreg = (4 << 10) | ((opP->reg - BAD) << 2);
+ break;
+
+ case BAC:
+ case BAC + 1:
+ case BAC + 2:
+ case BAC + 3:
+ case BAC + 4:
+ case BAC + 5:
+ case BAC + 6:
+ case BAC + 7:
+ tmpreg = (5 << 10) | ((opP->reg - BAC) << 2);
+ break;
+
+ default:
+ abort ();
+ }
+ install_operand (s[1], tmpreg);
+ break;
+ case 'Y':
+ know (opP->reg == PSR);
+ break;
+ case 'Z':
+ know (opP->reg == PCSR);
+ break;
+#endif /* m68851 */
+ case '3':
+ switch (opP->reg)
+ {
+ case TT0:
+ tmpreg = 2;
+ break;
+ case TT1:
+ tmpreg = 3;
+ break;
+ default:
+ abort ();
+ }
+ install_operand (s[1], tmpreg);
+ break;
+ case 't':
+ tmpreg = get_num (&opP->disp, 20);
+ install_operand (s[1], tmpreg);
+ break;
+ case '_': /* used only for move16 absolute 32-bit address */
+ if (isvar (&opP->disp))
+ add_fix ('l', &opP->disp, 0, 0);
+ tmpreg = get_num (&opP->disp, 80);
+ addword (tmpreg >> 16);
+ addword (tmpreg & 0xFFFF);
+ break;
+ default:
+ abort ();
+ }
+ }
+
+ /* By the time whe get here (FINALLY) the_ins contains the complete
+ instruction, ready to be emitted. . . */
+}
+
+static int
+reverse_16_bits (in)
+ int in;
+{
+ int out = 0;
+ int n;
+
+ static int mask[16] =
+ {
+ 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
+ 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000
+ };
+ for (n = 0; n < 16; n++)
+ {
+ if (in & mask[n])
+ out |= mask[15 - n];
+ }
+ return out;
+} /* reverse_16_bits() */
+
+static int
+reverse_8_bits (in)
+ int in;
+{
+ int out = 0;
+ int n;
+
+ static int mask[8] =
+ {
+ 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
+ };
+
+ for (n = 0; n < 8; n++)
+ {
+ if (in & mask[n])
+ out |= mask[7 - n];
+ }
+ return out;
+} /* reverse_8_bits() */
+
+/* Cause an extra frag to be generated here, inserting up to 10 bytes
+ (that value is chosen in the frag_var call in md_assemble). TYPE
+ is the subtype of the frag to be generated; its primary type is
+ rs_machine_dependent.
+
+ The TYPE parameter is also used by md_convert_frag_1 and
+ md_estimate_size_before_relax. The appropriate type of fixup will
+ be emitted by md_convert_frag_1.
+
+ ADD becomes the FR_SYMBOL field of the frag, and OFF the FR_OFFSET. */
+static void
+install_operand (mode, val)
+ int mode;
+ int val;
+{
+ switch (mode)
+ {
+ case 's':
+ the_ins.opcode[0] |= val & 0xFF; /* JF FF is for M kludge */
+ break;
+ case 'd':
+ the_ins.opcode[0] |= val << 9;
+ break;
+ case '1':
+ the_ins.opcode[1] |= val << 12;
+ break;
+ case '2':
+ the_ins.opcode[1] |= val << 6;
+ break;
+ case '3':
+ the_ins.opcode[1] |= val;
+ break;
+ case '4':
+ the_ins.opcode[2] |= val << 12;
+ break;
+ case '5':
+ the_ins.opcode[2] |= val << 6;
+ break;
+ case '6':
+ /* DANGER! This is a hack to force cas2l and cas2w cmds to be
+ three words long! */
+ the_ins.numo++;
+ the_ins.opcode[2] |= val;
+ break;
+ case '7':
+ the_ins.opcode[1] |= val << 7;
+ break;
+ case '8':
+ the_ins.opcode[1] |= val << 10;
+ break;
+#ifndef NO_68851
+ case '9':
+ the_ins.opcode[1] |= val << 5;
+ break;
+#endif
+
+ case 't':
+ the_ins.opcode[1] |= (val << 10) | (val << 7);
+ break;
+ case 'D':
+ the_ins.opcode[1] |= (val << 12) | val;
+ break;
+ case 'g':
+ the_ins.opcode[0] |= val = 0xff;
+ break;
+ case 'i':
+ the_ins.opcode[0] |= val << 9;
+ break;
+ case 'C':
+ the_ins.opcode[1] |= val;
+ break;
+ case 'j':
+ the_ins.opcode[1] |= val;
+ the_ins.numo++; /* What a hack */
+ break;
+ case 'k':
+ the_ins.opcode[1] |= val << 4;
+ break;
+ case 'b':
+ case 'w':
+ case 'W':
+ case 'l':
+ break;
+ case 'e':
+ the_ins.opcode[0] |= (val << 6);
+ break;
+ case 'L':
+ the_ins.opcode[1] = (val >> 16);
+ the_ins.opcode[2] = val & 0xffff;
+ break;
+ case 'c':
+ default:
+ as_fatal (_("failed sanity check."));
+ }
+} /* install_operand() */
+
+static void
+install_gen_operand (mode, val)
+ int mode;
+ int val;
+{
+ switch (mode)
+ {
+ case 's':
+ the_ins.opcode[0] |= val;
+ break;
+ case 'd':
+ /* This is a kludge!!! */
+ the_ins.opcode[0] |= (val & 0x07) << 9 | (val & 0x38) << 3;
+ break;
+ case 'b':
+ case 'w':
+ case 'l':
+ case 'f':
+ case 'F':
+ case 'x':
+ case 'p':
+ the_ins.opcode[0] |= val;
+ break;
+ /* more stuff goes here */
+ default:
+ as_fatal (_("failed sanity check."));
+ }
+} /* install_gen_operand() */
+
+/*
+ * verify that we have some number of paren pairs, do m68k_ip_op(), and
+ * then deal with the bitfield hack.
+ */
+
+static char *
+crack_operand (str, opP)
+ register char *str;
+ register struct m68k_op *opP;
+{
+ register int parens;
+ register int c;
+ register char *beg_str;
+ int inquote = 0;
+
+ if (!str)
+ {
+ return str;
+ }
+ beg_str = str;
+ for (parens = 0; *str && (parens > 0 || inquote || notend (str)); str++)
+ {
+ if (! inquote)
+ {
+ if (*str == '(')
+ parens++;
+ else if (*str == ')')
+ {
+ if (!parens)
+ { /* ERROR */
+ opP->error = _("Extra )");
+ return str;
+ }
+ --parens;
+ }
+ }
+ if (flag_mri && *str == '\'')
+ inquote = ! inquote;
+ }
+ if (!*str && parens)
+ { /* ERROR */
+ opP->error = _("Missing )");
+ return str;
+ }
+ c = *str;
+ *str = '\0';
+ if (m68k_ip_op (beg_str, opP) != 0)
+ {
+ *str = c;
+ return str;
+ }
+ *str = c;
+ if (c == '}')
+ c = *++str; /* JF bitfield hack */
+ if (c)
+ {
+ c = *++str;
+ if (!c)
+ as_bad (_("Missing operand"));
+ }
+
+ /* Detect MRI REG symbols and convert them to REGLSTs. */
+ if (opP->mode == CONTROL && (int)opP->reg < 0)
+ {
+ opP->mode = REGLST;
+ opP->mask = ~(int)opP->reg;
+ opP->reg = 0;
+ }
+
+ return str;
+}
+
+/* This is the guts of the machine-dependent assembler. STR points to a
+ machine dependent instruction. This function is supposed to emit
+ the frags/bytes it assembles to.
+ */
+
+static void
+insert_reg (regname, regnum)
+ const char *regname;
+ int regnum;
+{
+ char buf[100];
+ int i;
+
+#ifdef REGISTER_PREFIX
+ if (!flag_reg_prefix_optional)
+ {
+ buf[0] = REGISTER_PREFIX;
+ strcpy (buf + 1, regname);
+ regname = buf;
+ }
+#endif
+
+ symbol_table_insert (symbol_new (regname, reg_section, regnum,
+ &zero_address_frag));
+
+ for (i = 0; regname[i]; i++)
+ buf[i] = islower (regname[i]) ? toupper (regname[i]) : regname[i];
+ buf[i] = '\0';
+
+ symbol_table_insert (symbol_new (buf, reg_section, regnum,
+ &zero_address_frag));
+}
+
+struct init_entry
+ {
+ const char *name;
+ int number;
+ };
+
+static const struct init_entry init_table[] =
+{
+ { "d0", DATA0 },
+ { "d1", DATA1 },
+ { "d2", DATA2 },
+ { "d3", DATA3 },
+ { "d4", DATA4 },
+ { "d5", DATA5 },
+ { "d6", DATA6 },
+ { "d7", DATA7 },
+ { "a0", ADDR0 },
+ { "a1", ADDR1 },
+ { "a2", ADDR2 },
+ { "a3", ADDR3 },
+ { "a4", ADDR4 },
+ { "a5", ADDR5 },
+ { "a6", ADDR6 },
+ { "fp", ADDR6 },
+ { "a7", ADDR7 },
+ { "sp", ADDR7 },
+ { "ssp", ADDR7 },
+ { "fp0", FP0 },
+ { "fp1", FP1 },
+ { "fp2", FP2 },
+ { "fp3", FP3 },
+ { "fp4", FP4 },
+ { "fp5", FP5 },
+ { "fp6", FP6 },
+ { "fp7", FP7 },
+ { "fpi", FPI },
+ { "fpiar", FPI },
+ { "fpc", FPI },
+ { "fps", FPS },
+ { "fpsr", FPS },
+ { "fpc", FPC },
+ { "fpcr", FPC },
+ { "control", FPC },
+ { "status", FPS },
+ { "iaddr", FPI },
+
+ { "cop0", COP0 },
+ { "cop1", COP1 },
+ { "cop2", COP2 },
+ { "cop3", COP3 },
+ { "cop4", COP4 },
+ { "cop5", COP5 },
+ { "cop6", COP6 },
+ { "cop7", COP7 },
+ { "pc", PC },
+ { "zpc", ZPC },
+ { "sr", SR },
+
+ { "ccr", CCR },
+ { "cc", CCR },
+
+ /* control registers */
+ { "sfc", SFC }, /* Source Function Code */
+ { "sfcr", SFC },
+ { "dfc", DFC }, /* Destination Function Code */
+ { "dfcr", DFC },
+ { "cacr", CACR }, /* Cache Control Register */
+ { "caar", CAAR }, /* Cache Address Register */
+
+ { "usp", USP }, /* User Stack Pointer */
+ { "vbr", VBR }, /* Vector Base Register */
+ { "msp", MSP }, /* Master Stack Pointer */
+ { "isp", ISP }, /* Interrupt Stack Pointer */
+
+ { "itt0", ITT0 }, /* Instruction Transparent Translation Reg 0 */
+ { "itt1", ITT1 }, /* Instruction Transparent Translation Reg 1 */
+ { "dtt0", DTT0 }, /* Data Transparent Translation Register 0 */
+ { "dtt1", DTT1 }, /* Data Transparent Translation Register 1 */
+
+ /* 68ec040 versions of same */
+ { "iacr0", ITT0 }, /* Instruction Access Control Register 0 */
+ { "iacr1", ITT1 }, /* Instruction Access Control Register 0 */
+ { "dacr0", DTT0 }, /* Data Access Control Register 0 */
+ { "dacr1", DTT1 }, /* Data Access Control Register 0 */
+
+ /* mcf5200 versions of same. The ColdFire programmer's reference
+ manual indicated that the order is 2,3,0,1, but Ken Rose
+ <rose@netcom.com> says that 0,1,2,3 is the correct order. */
+ { "acr0", ITT0 }, /* Access Control Unit 0 */
+ { "acr1", ITT1 }, /* Access Control Unit 1 */
+ { "acr2", DTT0 }, /* Access Control Unit 2 */
+ { "acr3", DTT1 }, /* Access Control Unit 3 */
+
+ { "tc", TC }, /* MMU Translation Control Register */
+ { "tcr", TC },
+
+ { "mmusr", MMUSR }, /* MMU Status Register */
+ { "srp", SRP }, /* User Root Pointer */
+ { "urp", URP }, /* Supervisor Root Pointer */
+
+ { "buscr", BUSCR },
+ { "pcr", PCR },
+
+ { "rombar", ROMBAR }, /* ROM Base Address Register */
+ { "rambar0", RAMBAR0 }, /* ROM Base Address Register */
+ { "rambar1", RAMBAR1 }, /* ROM Base Address Register */
+ { "mbar", MBAR }, /* Module Base Address Register */
+ /* end of control registers */
+
+ { "ac", AC },
+ { "bc", BC },
+ { "cal", CAL },
+ { "crp", CRP },
+ { "drp", DRP },
+ { "pcsr", PCSR },
+ { "psr", PSR },
+ { "scc", SCC },
+ { "val", VAL },
+ { "bad0", BAD0 },
+ { "bad1", BAD1 },
+ { "bad2", BAD2 },
+ { "bad3", BAD3 },
+ { "bad4", BAD4 },
+ { "bad5", BAD5 },
+ { "bad6", BAD6 },
+ { "bad7", BAD7 },
+ { "bac0", BAC0 },
+ { "bac1", BAC1 },
+ { "bac2", BAC2 },
+ { "bac3", BAC3 },
+ { "bac4", BAC4 },
+ { "bac5", BAC5 },
+ { "bac6", BAC6 },
+ { "bac7", BAC7 },
+
+ { "ic", IC },
+ { "dc", DC },
+ { "nc", NC },
+
+ { "tt0", TT0 },
+ { "tt1", TT1 },
+ /* 68ec030 versions of same */
+ { "ac0", TT0 },
+ { "ac1", TT1 },
+ /* 68ec030 access control unit, identical to 030 MMU status reg */
+ { "acusr", PSR },
+
+ /* Suppressed data and address registers. */
+ { "zd0", ZDATA0 },
+ { "zd1", ZDATA1 },
+ { "zd2", ZDATA2 },
+ { "zd3", ZDATA3 },
+ { "zd4", ZDATA4 },
+ { "zd5", ZDATA5 },
+ { "zd6", ZDATA6 },
+ { "zd7", ZDATA7 },
+ { "za0", ZADDR0 },
+ { "za1", ZADDR1 },
+ { "za2", ZADDR2 },
+ { "za3", ZADDR3 },
+ { "za4", ZADDR4 },
+ { "za5", ZADDR5 },
+ { "za6", ZADDR6 },
+ { "za7", ZADDR7 },
+
+ { 0, 0 }
+};
+
+static void
+init_regtable ()
+{
+ int i;
+ for (i = 0; init_table[i].name; i++)
+ insert_reg (init_table[i].name, init_table[i].number);
+}
+
+static int no_68851, no_68881;
+
+#ifdef OBJ_AOUT
+/* a.out machine type. Default to 68020. */
+int m68k_aout_machtype = 2;
+#endif
+
+void
+md_assemble (str)
+ char *str;
+{
+ const char *er;
+ short *fromP;
+ char *toP = NULL;
+ int m, n = 0;
+ char *to_beg_P;
+ int shorts_this_frag;
+ fixS *fixP;
+
+ /* In MRI mode, the instruction and operands are separated by a
+ space. Anything following the operands is a comment. The label
+ has already been removed. */
+ if (flag_mri)
+ {
+ char *s;
+ int fields = 0;
+ int infield = 0;
+ int inquote = 0;
+
+ for (s = str; *s != '\0'; s++)
+ {
+ if ((*s == ' ' || *s == '\t') && ! inquote)
+ {
+ if (infield)
+ {
+ ++fields;
+ if (fields >= 2)
+ {
+ *s = '\0';
+ break;
+ }
+ infield = 0;
+ }
+ }
+ else
+ {
+ if (! infield)
+ infield = 1;
+ if (*s == '\'')
+ inquote = ! inquote;
+ }
+ }
+ }
+
+ memset ((char *) (&the_ins), '\0', sizeof (the_ins));
+ m68k_ip (str);
+ er = the_ins.error;
+ if (!er)
+ {
+ for (n = 0; n < the_ins.numargs; n++)
+ if (the_ins.operands[n].error)
+ {
+ er = the_ins.operands[n].error;
+ break;
+ }
+ }
+ if (er)
+ {
+ as_bad (_("%s -- statement `%s' ignored"), er, str);
+ return;
+ }
+
+ /* If there is a current label, record that it marks an instruction. */
+ if (current_label != NULL)
+ {
+ current_label->text = 1;
+ current_label = NULL;
+ }
+
+ if (the_ins.nfrag == 0)
+ {
+ /* No frag hacking involved; just put it out */
+ toP = frag_more (2 * the_ins.numo);
+ fromP = &the_ins.opcode[0];
+ for (m = the_ins.numo; m; --m)
+ {
+ md_number_to_chars (toP, (long) (*fromP), 2);
+ toP += 2;
+ fromP++;
+ }
+ /* put out symbol-dependent info */
+ for (m = 0; m < the_ins.nrel; m++)
+ {
+ switch (the_ins.reloc[m].wid)
+ {
+ case 'B':
+ n = 1;
+ break;
+ case 'b':
+ n = 1;
+ break;
+ case '3':
+ n = 1;
+ break;
+ case 'w':
+ case 'W':
+ n = 2;
+ break;
+ case 'l':
+ n = 4;
+ break;
+ default:
+ as_fatal (_("Don't know how to figure width of %c in md_assemble()"),
+ the_ins.reloc[m].wid);
+ }
+
+ fixP = fix_new_exp (frag_now,
+ ((toP - frag_now->fr_literal)
+ - the_ins.numo * 2 + the_ins.reloc[m].n),
+ n,
+ &the_ins.reloc[m].exp,
+ the_ins.reloc[m].pcrel,
+ get_reloc_code (n, the_ins.reloc[m].pcrel,
+ the_ins.reloc[m].pic_reloc));
+ fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
+ if (the_ins.reloc[m].wid == 'B')
+ fixP->fx_signed = 1;
+ }
+ return;
+ }
+
+ /* There's some frag hacking */
+ for (n = 0, fromP = &the_ins.opcode[0]; n < the_ins.nfrag; n++)
+ {
+ int wid;
+
+ if (n == 0)
+ wid = 2 * the_ins.fragb[n].fragoff;
+ else
+ wid = 2 * (the_ins.numo - the_ins.fragb[n - 1].fragoff);
+ toP = frag_more (wid);
+ to_beg_P = toP;
+ shorts_this_frag = 0;
+ for (m = wid / 2; m; --m)
+ {
+ md_number_to_chars (toP, (long) (*fromP), 2);
+ toP += 2;
+ fromP++;
+ shorts_this_frag++;
+ }
+ for (m = 0; m < the_ins.nrel; m++)
+ {
+ if ((the_ins.reloc[m].n) >= 2 * shorts_this_frag)
+ {
+ the_ins.reloc[m].n -= 2 * shorts_this_frag;
+ break;
+ }
+ wid = the_ins.reloc[m].wid;
+ if (wid == 0)
+ continue;
+ the_ins.reloc[m].wid = 0;
+ wid = (wid == 'b') ? 1 : (wid == 'w') ? 2 : (wid == 'l') ? 4 : 4000;
+
+ fixP = fix_new_exp (frag_now,
+ ((toP - frag_now->fr_literal)
+ - the_ins.numo * 2 + the_ins.reloc[m].n),
+ wid,
+ &the_ins.reloc[m].exp,
+ the_ins.reloc[m].pcrel,
+ get_reloc_code (wid, the_ins.reloc[m].pcrel,
+ the_ins.reloc[m].pic_reloc));
+ fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
+ }
+ (void) frag_var (rs_machine_dependent, 10, 0,
+ (relax_substateT) (the_ins.fragb[n].fragty),
+ the_ins.fragb[n].fadd, the_ins.fragb[n].foff, to_beg_P);
+ }
+ n = (the_ins.numo - the_ins.fragb[n - 1].fragoff);
+ shorts_this_frag = 0;
+ if (n)
+ {
+ toP = frag_more (n * sizeof (short));
+ while (n--)
+ {
+ md_number_to_chars (toP, (long) (*fromP), 2);
+ toP += 2;
+ fromP++;
+ shorts_this_frag++;
+ }
+ }
+ for (m = 0; m < the_ins.nrel; m++)
+ {
+ int wid;
+
+ wid = the_ins.reloc[m].wid;
+ if (wid == 0)
+ continue;
+ the_ins.reloc[m].wid = 0;
+ wid = (wid == 'b') ? 1 : (wid == 'w') ? 2 : (wid == 'l') ? 4 : 4000;
+
+ fixP = fix_new_exp (frag_now,
+ ((the_ins.reloc[m].n + toP - frag_now->fr_literal)
+ - shorts_this_frag * 2),
+ wid,
+ &the_ins.reloc[m].exp,
+ the_ins.reloc[m].pcrel,
+ get_reloc_code (wid, the_ins.reloc[m].pcrel,
+ the_ins.reloc[m].pic_reloc));
+ fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
+ }
+}
+
+void
+md_begin ()
+{
+ /*
+ * md_begin -- set up hash tables with 68000 instructions.
+ * similar to what the vax assembler does. ---phr
+ */
+ /* RMS claims the thing to do is take the m68k-opcode.h table, and make
+ a copy of it at runtime, adding in the information we want but isn't
+ there. I think it'd be better to have an awk script hack the table
+ at compile time. Or even just xstr the table and use it as-is. But
+ my lord ghod hath spoken, so we do it this way. Excuse the ugly var
+ names. */
+
+ register const struct m68k_opcode *ins;
+ register struct m68k_incant *hack, *slak;
+ register const char *retval = 0; /* empty string, or error msg text */
+ register unsigned int i;
+ register char c;
+
+ if (flag_mri)
+ {
+ flag_reg_prefix_optional = 1;
+ m68k_abspcadd = 1;
+ if (! m68k_rel32_from_cmdline)
+ m68k_rel32 = 0;
+ }
+
+ op_hash = hash_new ();
+
+ obstack_begin (&robyn, 4000);
+ for (i = 0; i < m68k_numopcodes; i++)
+ {
+ hack = slak = (struct m68k_incant *) obstack_alloc (&robyn, sizeof (struct m68k_incant));
+ do
+ {
+ ins = &m68k_opcodes[i];
+ /* We *could* ignore insns that don't match our arch here
+ but just leaving them out of the hash. */
+ slak->m_operands = ins->args;
+ slak->m_opnum = strlen (slak->m_operands) / 2;
+ slak->m_arch = ins->arch;
+ slak->m_opcode = ins->opcode;
+ /* This is kludgey */
+ slak->m_codenum = ((ins->match) & 0xffffL) ? 2 : 1;
+ if (i + 1 != m68k_numopcodes
+ && !strcmp (ins->name, m68k_opcodes[i + 1].name))
+ {
+ slak->m_next = (struct m68k_incant *) obstack_alloc (&robyn, sizeof (struct m68k_incant));
+ i++;
+ }
+ else
+ slak->m_next = 0;
+ slak = slak->m_next;
+ }
+ while (slak);
+
+ retval = hash_insert (op_hash, ins->name, (char *) hack);
+ if (retval)
+ as_fatal (_("Internal Error: Can't hash %s: %s"), ins->name, retval);
+ }
+
+ for (i = 0; i < m68k_numaliases; i++)
+ {
+ const char *name = m68k_opcode_aliases[i].primary;
+ const char *alias = m68k_opcode_aliases[i].alias;
+ PTR val = hash_find (op_hash, name);
+ if (!val)
+ as_fatal (_("Internal Error: Can't find %s in hash table"), name);
+ retval = hash_insert (op_hash, alias, val);
+ if (retval)
+ as_fatal (_("Internal Error: Can't hash %s: %s"), alias, retval);
+ }
+
+ /* In MRI mode, all unsized branches are variable sized. Normally,
+ they are word sized. */
+ if (flag_mri)
+ {
+ static struct m68k_opcode_alias mri_aliases[] =
+ {
+ { "bhi", "jhi", },
+ { "bls", "jls", },
+ { "bcc", "jcc", },
+ { "bcs", "jcs", },
+ { "bne", "jne", },
+ { "beq", "jeq", },
+ { "bvc", "jvc", },
+ { "bvs", "jvs", },
+ { "bpl", "jpl", },
+ { "bmi", "jmi", },
+ { "bge", "jge", },
+ { "blt", "jlt", },
+ { "bgt", "jgt", },
+ { "ble", "jle", },
+ { "bra", "jra", },
+ { "bsr", "jbsr", },
+ };
+
+ for (i = 0; i < sizeof mri_aliases / sizeof mri_aliases[0]; i++)
+ {
+ const char *name = mri_aliases[i].primary;
+ const char *alias = mri_aliases[i].alias;
+ PTR val = hash_find (op_hash, name);
+ if (!val)
+ as_fatal (_("Internal Error: Can't find %s in hash table"), name);
+ retval = hash_jam (op_hash, alias, val);
+ if (retval)
+ as_fatal (_("Internal Error: Can't hash %s: %s"), alias, retval);
+ }
+ }
+
+ for (i = 0; i < sizeof (mklower_table); i++)
+ mklower_table[i] = (isupper (c = (char) i)) ? tolower (c) : c;
+
+ for (i = 0; i < sizeof (notend_table); i++)
+ {
+ notend_table[i] = 0;
+ alt_notend_table[i] = 0;
+ }
+ notend_table[','] = 1;
+ notend_table['{'] = 1;
+ notend_table['}'] = 1;
+ alt_notend_table['a'] = 1;
+ alt_notend_table['A'] = 1;
+ alt_notend_table['d'] = 1;
+ alt_notend_table['D'] = 1;
+ alt_notend_table['#'] = 1;
+ alt_notend_table['&'] = 1;
+ alt_notend_table['f'] = 1;
+ alt_notend_table['F'] = 1;
+#ifdef REGISTER_PREFIX
+ alt_notend_table[REGISTER_PREFIX] = 1;
+#endif
+
+ /* We need to put '(' in alt_notend_table to handle
+ cas2 %d0:%d2,%d3:%d4,(%a0):(%a1)
+ */
+ alt_notend_table['('] = 1;
+
+ /* We need to put '@' in alt_notend_table to handle
+ cas2 %d0:%d2,%d3:%d4,@(%d0):@(%d1)
+ */
+ alt_notend_table['@'] = 1;
+
+ /* We need to put digits in alt_notend_table to handle
+ bfextu %d0{24:1},%d0
+ */
+ alt_notend_table['0'] = 1;
+ alt_notend_table['1'] = 1;
+ alt_notend_table['2'] = 1;
+ alt_notend_table['3'] = 1;
+ alt_notend_table['4'] = 1;
+ alt_notend_table['5'] = 1;
+ alt_notend_table['6'] = 1;
+ alt_notend_table['7'] = 1;
+ alt_notend_table['8'] = 1;
+ alt_notend_table['9'] = 1;
+
+#ifndef MIT_SYNTAX_ONLY
+ /* Insert pseudo ops, these have to go into the opcode table since
+ gas expects pseudo ops to start with a dot */
+ {
+ int n = 0;
+ while (mote_pseudo_table[n].poc_name)
+ {
+ hack = (struct m68k_incant *)
+ obstack_alloc (&robyn, sizeof (struct m68k_incant));
+ hash_insert (op_hash,
+ mote_pseudo_table[n].poc_name, (char *) hack);
+ hack->m_operands = 0;
+ hack->m_opnum = n;
+ n++;
+ }
+ }
+#endif
+
+ init_regtable ();
+
+#ifdef OBJ_ELF
+ record_alignment (text_section, 2);
+ record_alignment (data_section, 2);
+ record_alignment (bss_section, 2);
+#endif
+}
+
+static void
+select_control_regs ()
+{
+ /* Note which set of "movec" control registers is available. */
+ switch (cpu_of_arch (current_architecture))
+ {
+ case m68000:
+ control_regs = m68000_control_regs;
+ break;
+ case m68010:
+ control_regs = m68010_control_regs;
+ break;
+ case m68020:
+ case m68030:
+ control_regs = m68020_control_regs;
+ break;
+ case m68040:
+ control_regs = m68040_control_regs;
+ break;
+ case m68060:
+ control_regs = m68060_control_regs;
+ break;
+ case cpu32:
+ control_regs = cpu32_control_regs;
+ break;
+ case mcf5200:
+ control_regs = mcf5200_control_regs;
+ break;
+ default:
+ abort ();
+ }
+}
+
+void
+m68k_init_after_args ()
+{
+ if (cpu_of_arch (current_architecture) == 0)
+ {
+ int i;
+ const char *default_cpu = TARGET_CPU;
+
+ if (*default_cpu == 'm')
+ default_cpu++;
+ for (i = 0; i < n_archs; i++)
+ if (strcasecmp (default_cpu, archs[i].name) == 0)
+ break;
+ if (i == n_archs)
+ {
+ as_bad (_("unrecognized default cpu `%s' ???"), TARGET_CPU);
+ current_architecture |= m68020;
+ }
+ else
+ current_architecture |= archs[i].arch;
+ }
+ /* Permit m68881 specification with all cpus; those that can't work
+ with a coprocessor could be doing emulation. */
+ if (current_architecture & m68851)
+ {
+ if (current_architecture & m68040)
+ {
+ as_warn (_("68040 and 68851 specified; mmu instructions may assemble incorrectly"));
+ }
+ }
+ /* What other incompatibilities could we check for? */
+
+ /* Toss in some default assumptions about coprocessors. */
+ if (!no_68881
+ && (cpu_of_arch (current_architecture)
+ /* Can CPU32 have a 68881 coprocessor?? */
+ & (m68020 | m68030 | cpu32)))
+ {
+ current_architecture |= m68881;
+ }
+ if (!no_68851
+ && (cpu_of_arch (current_architecture) & m68020up) != 0
+ && (cpu_of_arch (current_architecture) & m68040up) == 0)
+ {
+ current_architecture |= m68851;
+ }
+ if (no_68881 && (current_architecture & m68881))
+ as_bad (_("options for 68881 and no-68881 both given"));
+ if (no_68851 && (current_architecture & m68851))
+ as_bad (_("options for 68851 and no-68851 both given"));
+
+#ifdef OBJ_AOUT
+ /* Work out the magic number. This isn't very general. */
+ if (current_architecture & m68000)
+ m68k_aout_machtype = 0;
+ else if (current_architecture & m68010)
+ m68k_aout_machtype = 1;
+ else if (current_architecture & m68020)
+ m68k_aout_machtype = 2;
+ else
+ m68k_aout_machtype = 2;
+#endif
+
+ /* Note which set of "movec" control registers is available. */
+ select_control_regs ();
+
+ if (cpu_of_arch (current_architecture) < m68020
+ || cpu_of_arch (current_architecture) == mcf5200)
+ md_relax_table[TAB (PCINDEX, BYTE)].rlx_more = 0;
+}
+
+/* This is called when a label is defined. */
+
+void
+m68k_frob_label (sym)
+ symbolS *sym;
+{
+ struct label_line *n;
+
+ n = (struct label_line *) xmalloc (sizeof *n);
+ n->next = labels;
+ n->label = sym;
+ as_where (&n->file, &n->line);
+ n->text = 0;
+ labels = n;
+ current_label = n;
+}
+
+/* This is called when a value that is not an instruction is emitted. */
+
+void
+m68k_flush_pending_output ()
+{
+ current_label = NULL;
+}
+
+/* This is called at the end of the assembly, when the final value of
+ the label is known. We warn if this is a text symbol aligned at an
+ odd location. */
+
+void
+m68k_frob_symbol (sym)
+ symbolS *sym;
+{
+ if (S_GET_SEGMENT (sym) == reg_section
+ && (int) S_GET_VALUE (sym) < 0)
+ {
+ S_SET_SEGMENT (sym, absolute_section);
+ S_SET_VALUE (sym, ~(int)S_GET_VALUE (sym));
+ }
+ else if ((S_GET_VALUE (sym) & 1) != 0)
+ {
+ struct label_line *l;
+
+ for (l = labels; l != NULL; l = l->next)
+ {
+ if (l->label == sym)
+ {
+ if (l->text)
+ as_warn_where (l->file, l->line,
+ _("text label `%s' aligned to odd boundary"),
+ S_GET_NAME (sym));
+ break;
+ }
+ }
+ }
+}
+
+/* This is called if we go in or out of MRI mode because of the .mri
+ pseudo-op. */
+
+void
+m68k_mri_mode_change (on)
+ int on;
+{
+ if (on)
+ {
+ if (! flag_reg_prefix_optional)
+ {
+ flag_reg_prefix_optional = 1;
+#ifdef REGISTER_PREFIX
+ init_regtable ();
+#endif
+ }
+ m68k_abspcadd = 1;
+ if (! m68k_rel32_from_cmdline)
+ m68k_rel32 = 0;
+ }
+ else
+ {
+ if (! reg_prefix_optional_seen)
+ {
+#ifdef REGISTER_PREFIX_OPTIONAL
+ flag_reg_prefix_optional = REGISTER_PREFIX_OPTIONAL;
+#else
+ flag_reg_prefix_optional = 0;
+#endif
+#ifdef REGISTER_PREFIX
+ init_regtable ();
+#endif
+ }
+ m68k_abspcadd = 0;
+ if (! m68k_rel32_from_cmdline)
+ m68k_rel32 = 1;
+ }
+}
+
+/* Equal to MAX_PRECISION in atof-ieee.c */
+#define MAX_LITTLENUMS 6
+
+/* Turn a string in input_line_pointer into a floating point constant
+ of type type, and store the appropriate bytes in *litP. The number
+ of LITTLENUMS emitted is stored in *sizeP . An error message is
+ returned, or NULL on OK. */
+
+char *
+md_atof (type, litP, sizeP)
+ char type;
+ char *litP;
+ int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ char *t;
+
+ switch (type)
+ {
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ prec = 4;
+ break;
+
+ case 'x':
+ case 'X':
+ prec = 6;
+ break;
+
+ case 'p':
+ case 'P':
+ prec = 6;
+ break;
+
+ default:
+ *sizeP = 0;
+ return _("Bad call to MD_ATOF()");
+ }
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+
+ *sizeP = prec * sizeof (LITTLENUM_TYPE);
+ for (wordP = words; prec--;)
+ {
+ md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+ return 0;
+}
+
+void
+md_number_to_chars (buf, val, n)
+ char *buf;
+ valueT val;
+ int n;
+{
+ number_to_chars_bigendian (buf, val, n);
+}
+
+static void
+md_apply_fix_2 (fixP, val)
+ fixS *fixP;
+ offsetT val;
+{
+ addressT upper_limit;
+ offsetT lower_limit;
+
+ /* This is unnecessary but it convinces the native rs6000 compiler
+ to generate the code we want. */
+ char *buf = fixP->fx_frag->fr_literal;
+ buf += fixP->fx_where;
+ /* end ibm compiler workaround */
+
+ if (val & 0x80000000)
+ val |= ~(addressT)0x7fffffff;
+ else
+ val &= 0x7fffffff;
+
+#ifdef OBJ_ELF
+ if (fixP->fx_addsy)
+ {
+ memset (buf, 0, fixP->fx_size);
+ fixP->fx_addnumber = val; /* Remember value for emit_reloc */
+
+ if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ && !S_IS_DEFINED (fixP->fx_addsy)
+ && !S_IS_WEAK (fixP->fx_addsy))
+ S_SET_WEAK (fixP->fx_addsy);
+ return;
+ }
+#endif
+
+#ifdef BFD_ASSEMBLER
+ if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ return;
+#endif
+
+ switch (fixP->fx_size)
+ {
+ /* The cast to offsetT below are necessary to make code correct for
+ machines where ints are smaller than offsetT */
+ case 1:
+ *buf++ = val;
+ upper_limit = 0x7f;
+ lower_limit = - (offsetT) 0x80;
+ break;
+ case 2:
+ *buf++ = (val >> 8);
+ *buf++ = val;
+ upper_limit = 0x7fff;
+ lower_limit = - (offsetT) 0x8000;
+ break;
+ case 4:
+ *buf++ = (val >> 24);
+ *buf++ = (val >> 16);
+ *buf++ = (val >> 8);
+ *buf++ = val;
+ upper_limit = 0x7fffffff;
+ lower_limit = - (offsetT) 0x7fffffff - 1; /* avoid constant overflow */
+ break;
+ default:
+ BAD_CASE (fixP->fx_size);
+ }
+
+ /* Fix up a negative reloc. */
+ if (fixP->fx_addsy == NULL && fixP->fx_subsy != NULL)
+ {
+ fixP->fx_addsy = fixP->fx_subsy;
+ fixP->fx_subsy = NULL;
+ fixP->fx_tcbit = 1;
+ }
+
+ /* For non-pc-relative values, it's conceivable we might get something
+ like "0xff" for a byte field. So extend the upper part of the range
+ to accept such numbers. We arbitrarily disallow "-0xff" or "0xff+0xff",
+ so that we can do any range checking at all. */
+ if (! fixP->fx_pcrel && ! fixP->fx_signed)
+ upper_limit = upper_limit * 2 + 1;
+
+ if ((addressT) val > upper_limit
+ && (val > 0 || val < lower_limit))
+ as_bad_where (fixP->fx_file, fixP->fx_line, _("value out of range"));
+
+ /* A one byte PC-relative reloc means a short branch. We can't use
+ a short branch with a value of 0 or -1, because those indicate
+ different opcodes (branches with longer offsets). fixup_segment
+ in write.c may have clobbered fx_pcrel, so we need to examine the
+ reloc type. */
+ if ((fixP->fx_pcrel
+#ifdef BFD_ASSEMBLER
+ || fixP->fx_r_type == BFD_RELOC_8_PCREL
+#endif
+ )
+ && fixP->fx_size == 1
+ && (fixP->fx_addsy == NULL
+ || S_IS_DEFINED (fixP->fx_addsy))
+ && (val == 0 || val == -1))
+ as_bad_where (fixP->fx_file, fixP->fx_line, _("invalid byte branch offset"));
+}
+
+#ifdef BFD_ASSEMBLER
+int
+md_apply_fix (fixP, valp)
+ fixS *fixP;
+ valueT *valp;
+{
+ md_apply_fix_2 (fixP, (addressT) *valp);
+ return 1;
+}
+#else
+void md_apply_fix (fixP, val)
+ fixS *fixP;
+ long val;
+{
+ md_apply_fix_2 (fixP, (addressT) val);
+}
+#endif
+
+/* *fragP has been relaxed to its final size, and now needs to have
+ the bytes inside it modified to conform to the new size There is UGLY
+ MAGIC here. ..
+ */
+static void
+md_convert_frag_1 (fragP)
+ register fragS *fragP;
+{
+ long disp;
+ long ext = 0;
+ fixS *fixP;
+
+ /* Address in object code of the displacement. */
+ register int object_address = fragP->fr_fix + fragP->fr_address;
+
+ /* Address in gas core of the place to store the displacement. */
+ /* This convinces the native rs6000 compiler to generate the code we
+ want. */
+ register char *buffer_address = fragP->fr_literal;
+ buffer_address += fragP->fr_fix;
+ /* end ibm compiler workaround */
+
+ /* The displacement of the address, from current location. */
+ disp = fragP->fr_symbol ? S_GET_VALUE (fragP->fr_symbol) : 0;
+ disp = (disp + fragP->fr_offset) - object_address;
+
+#ifdef BFD_ASSEMBLER
+ disp += fragP->fr_symbol->sy_frag->fr_address;
+#endif
+
+ switch (fragP->fr_subtype)
+ {
+ case TAB (BCC68000, BYTE):
+ case TAB (ABRANCH, BYTE):
+ know (issbyte (disp));
+ if (disp == 0)
+ as_bad (_("short branch with zero offset: use :w"));
+ fragP->fr_opcode[1] = disp;
+ ext = 0;
+ break;
+ case TAB (DBCC, SHORT):
+ know (issword (disp));
+ ext = 2;
+ break;
+ case TAB (BCC68000, SHORT):
+ case TAB (ABRANCH, SHORT):
+ know (issword (disp));
+ fragP->fr_opcode[1] = 0x00;
+ ext = 2;
+ break;
+ case TAB (ABRANCH, LONG):
+ if (!HAVE_LONG_BRANCH(current_architecture))
+ {
+ if (fragP->fr_opcode[0] == 0x61)
+ /* BSR */
+ {
+ fragP->fr_opcode[0] = 0x4E;
+ fragP->fr_opcode[1] = (char) 0xB9; /* JBSR with ABSL LONG offset */
+
+ fix_new (fragP,
+ fragP->fr_fix,
+ 4,
+ fragP->fr_symbol,
+ fragP->fr_offset,
+ 0,
+ NO_RELOC);
+
+ fragP->fr_fix += 4;
+ ext = 0;
+ }
+ /* BRA */
+ else if (fragP->fr_opcode[0] == 0x60)
+ {
+ fragP->fr_opcode[0] = 0x4E;
+ fragP->fr_opcode[1] = (char) 0xF9; /* JMP with ABSL LONG offset */
+ fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
+ fragP->fr_offset, 0, NO_RELOC);
+ fragP->fr_fix += 4;
+ ext = 0;
+ }
+ else
+ {
+ as_bad (_("Long branch offset not supported."));
+ }
+ }
+ else
+ {
+ fragP->fr_opcode[1] = (char) 0xff;
+ ext = 4;
+ }
+ break;
+ case TAB (BCC68000, LONG):
+ /* only Bcc 68000 instructions can come here */
+ /* change bcc into b!cc/jmp absl long */
+ fragP->fr_opcode[0] ^= 0x01; /* invert bcc */
+ fragP->fr_opcode[1] = 0x6;/* branch offset = 6 */
+
+ /* JF: these used to be fr_opcode[2,3], but they may be in a
+ different frag, in which case refering to them is a no-no.
+ Only fr_opcode[0,1] are guaranteed to work. */
+ *buffer_address++ = 0x4e; /* put in jmp long (0x4ef9) */
+ *buffer_address++ = (char) 0xf9;
+ fragP->fr_fix += 2; /* account for jmp instruction */
+ fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
+ fragP->fr_offset, 0, NO_RELOC);
+ fragP->fr_fix += 4;
+ ext = 0;
+ break;
+ case TAB (DBCC, LONG):
+ /* only DBcc 68000 instructions can come here */
+ /* change dbcc into dbcc/jmp absl long */
+ /* JF: these used to be fr_opcode[2-7], but that's wrong */
+ *buffer_address++ = 0x00; /* branch offset = 4 */
+ *buffer_address++ = 0x04;
+ *buffer_address++ = 0x60; /* put in bra pc+6 */
+ *buffer_address++ = 0x06;
+ *buffer_address++ = 0x4e; /* put in jmp long (0x4ef9) */
+ *buffer_address++ = (char) 0xf9;
+
+ fragP->fr_fix += 6; /* account for bra/jmp instructions */
+ fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
+ fragP->fr_offset, 0, NO_RELOC);
+ fragP->fr_fix += 4;
+ ext = 0;
+ break;
+ case TAB (FBRANCH, SHORT):
+ know ((fragP->fr_opcode[1] & 0x40) == 0);
+ ext = 2;
+ break;
+ case TAB (FBRANCH, LONG):
+ fragP->fr_opcode[1] |= 0x40; /* Turn on LONG bit */
+ ext = 4;
+ break;
+ case TAB (PCREL, SHORT):
+ ext = 2;
+ break;
+ case TAB (PCREL, LONG):
+ /* The thing to do here is force it to ABSOLUTE LONG, since
+ PCREL is really trying to shorten an ABSOLUTE address anyway */
+ /* JF FOO This code has not been tested */
+ fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol, fragP->fr_offset,
+ 0, NO_RELOC);
+ if ((fragP->fr_opcode[1] & 0x3F) != 0x3A)
+ as_bad (_("Internal error (long PC-relative operand) for insn 0x%04x at 0x%lx"),
+ (unsigned) fragP->fr_opcode[0],
+ (unsigned long) fragP->fr_address);
+ fragP->fr_opcode[1] &= ~0x3F;
+ fragP->fr_opcode[1] |= 0x39; /* Mode 7.1 */
+ fragP->fr_fix += 4;
+ ext = 0;
+ break;
+ case TAB (PCLEA, SHORT):
+ fix_new (fragP, (int) (fragP->fr_fix), 2, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
+ fragP->fr_opcode[1] &= ~0x3F;
+ fragP->fr_opcode[1] |= 0x3A; /* 072 - mode 7.2 */
+ ext = 2;
+ break;
+ case TAB (PCLEA, LONG):
+ fixP = fix_new (fragP, (int) (fragP->fr_fix) + 2, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
+ fixP->fx_pcrel_adjust = 2;
+ /* Already set to mode 7.3; this indicates: PC indirect with
+ suppressed index, 32-bit displacement. */
+ *buffer_address++ = 0x01;
+ *buffer_address++ = 0x70;
+ fragP->fr_fix += 2;
+ ext = 4;
+ break;
+
+ case TAB (PCINDEX, BYTE):
+ disp += 2;
+ if (!issbyte (disp))
+ {
+ as_bad (_("displacement doesn't fit in one byte"));
+ disp = 0;
+ }
+ assert (fragP->fr_fix >= 2);
+ buffer_address[-2] &= ~1;
+ buffer_address[-1] = disp;
+ ext = 0;
+ break;
+ case TAB (PCINDEX, SHORT):
+ disp += 2;
+ assert (issword (disp));
+ assert (fragP->fr_fix >= 2);
+ buffer_address[-2] |= 0x1;
+ buffer_address[-1] = 0x20;
+ fixP = fix_new (fragP, (int) (fragP->fr_fix), 2, fragP->fr_symbol,
+ fragP->fr_offset, (fragP->fr_opcode[1] & 077) == 073,
+ NO_RELOC);
+ fixP->fx_pcrel_adjust = 2;
+ ext = 2;
+ break;
+ case TAB (PCINDEX, LONG):
+ disp += 2;
+ fixP = fix_new (fragP, (int) (fragP->fr_fix), 4, fragP->fr_symbol,
+ fragP->fr_offset, (fragP->fr_opcode[1] & 077) == 073,
+ NO_RELOC);
+ fixP->fx_pcrel_adjust = 2;
+ assert (fragP->fr_fix >= 2);
+ buffer_address[-2] |= 0x1;
+ buffer_address[-1] = 0x30;
+ ext = 4;
+ break;
+ }
+
+ if (ext)
+ {
+ md_number_to_chars (buffer_address, (long) disp, (int) ext);
+ fragP->fr_fix += ext;
+ }
+}
+
+#ifndef BFD_ASSEMBLER
+
+void
+md_convert_frag (headers, sec, fragP)
+ object_headers *headers;
+ segT sec;
+ fragS *fragP;
+{
+ md_convert_frag_1 (fragP);
+}
+
+#else
+
+void
+md_convert_frag (abfd, sec, fragP)
+ bfd *abfd;
+ segT sec;
+ fragS *fragP;
+{
+ md_convert_frag_1 (fragP);
+}
+#endif
+
+/* Force truly undefined symbols to their maximum size, and generally set up
+ the frag list to be relaxed
+ */
+int
+md_estimate_size_before_relax (fragP, segment)
+ register fragS *fragP;
+ segT segment;
+{
+ int old_fix;
+ register char *buffer_address = fragP->fr_fix + fragP->fr_literal;
+
+ old_fix = fragP->fr_fix;
+
+ /* handle SZ_UNDEF first, it can be changed to BYTE or SHORT */
+ switch (fragP->fr_subtype)
+ {
+
+ case TAB (ABRANCH, SZ_UNDEF):
+ {
+ if ((fragP->fr_symbol != NULL) /* Not absolute */
+ && S_GET_SEGMENT (fragP->fr_symbol) == segment
+ && relaxable_symbol (fragP->fr_symbol))
+ {
+ fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), BYTE);
+ break;
+ }
+ else if ((fragP->fr_symbol == 0) || !HAVE_LONG_BRANCH(current_architecture))
+ {
+ /* On 68000, or for absolute value, switch to abs long */
+ /* FIXME, we should check abs val, pick short or long */
+ if (fragP->fr_opcode[0] == 0x61)
+ {
+ fragP->fr_opcode[0] = 0x4E;
+ fragP->fr_opcode[1] = (char) 0xB9; /* JBSR with ABSL LONG offset */
+ fix_new (fragP, fragP->fr_fix, 4,
+ fragP->fr_symbol, fragP->fr_offset, 0, NO_RELOC);
+ fragP->fr_fix += 4;
+ frag_wane (fragP);
+ }
+ else if (fragP->fr_opcode[0] == 0x60)
+ {
+ fragP->fr_opcode[0] = 0x4E;
+ fragP->fr_opcode[1] = (char) 0xF9; /* JMP with ABSL LONG offset */
+ fix_new (fragP, fragP->fr_fix, 4,
+ fragP->fr_symbol, fragP->fr_offset, 0, NO_RELOC);
+ fragP->fr_fix += 4;
+ frag_wane (fragP);
+ }
+ else
+ {
+ as_warn (_("Long branch offset to extern symbol not supported."));
+ }
+ }
+ else
+ { /* Symbol is still undefined. Make it simple */
+ fix_new (fragP, (int) (fragP->fr_fix), 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
+ fragP->fr_fix += 4;
+ fragP->fr_opcode[1] = (char) 0xff;
+ frag_wane (fragP);
+ break;
+ }
+
+ break;
+ } /* case TAB(ABRANCH,SZ_UNDEF) */
+
+ case TAB (FBRANCH, SZ_UNDEF):
+ {
+ if ((S_GET_SEGMENT (fragP->fr_symbol) == segment
+ && relaxable_symbol (fragP->fr_symbol))
+ || flag_short_refs)
+ {
+ fragP->fr_subtype = TAB (FBRANCH, SHORT);
+ fragP->fr_var += 2;
+ }
+ else
+ {
+ fix_new (fragP, (int) fragP->fr_fix, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
+ fragP->fr_fix += 4;
+ fragP->fr_opcode[1] |= 0x40; /* Turn on LONG bit */
+ frag_wane (fragP);
+ }
+ break;
+ } /* TAB(FBRANCH,SZ_UNDEF) */
+
+ case TAB (PCREL, SZ_UNDEF):
+ {
+ if ((S_GET_SEGMENT (fragP->fr_symbol) == segment
+ && relaxable_symbol (fragP->fr_symbol))
+ || flag_short_refs
+ || cpu_of_arch (current_architecture) < m68020
+ || cpu_of_arch (current_architecture) == mcf5200)
+ {
+ fragP->fr_subtype = TAB (PCREL, SHORT);
+ fragP->fr_var += 2;
+ }
+ else
+ {
+ fragP->fr_subtype = TAB (PCREL, LONG);
+ fragP->fr_var += 4;
+ }
+ break;
+ } /* TAB(PCREL,SZ_UNDEF) */
+
+ case TAB (BCC68000, SZ_UNDEF):
+ {
+ if ((fragP->fr_symbol != NULL)
+ && S_GET_SEGMENT (fragP->fr_symbol) == segment
+ && relaxable_symbol (fragP->fr_symbol))
+ {
+ fragP->fr_subtype = TAB (BCC68000, BYTE);
+ break;
+ }
+ /* only Bcc 68000 instructions can come here */
+ /* change bcc into b!cc/jmp absl long */
+ fragP->fr_opcode[0] ^= 0x01; /* invert bcc */
+ if (flag_short_refs)
+ {
+ fragP->fr_opcode[1] = 0x04; /* branch offset = 6 */
+ /* JF: these were fr_opcode[2,3] */
+ buffer_address[0] = 0x4e; /* put in jmp long (0x4ef9) */
+ buffer_address[1] = (char) 0xf8;
+ fragP->fr_fix += 2; /* account for jmp instruction */
+ fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
+ fragP->fr_offset, 0, NO_RELOC);
+ fragP->fr_fix += 2;
+ }
+ else
+ {
+ fragP->fr_opcode[1] = 0x06; /* branch offset = 6 */
+ /* JF: these were fr_opcode[2,3] */
+ buffer_address[0] = 0x4e; /* put in jmp long (0x4ef9) */
+ buffer_address[1] = (char) 0xf9;
+ fragP->fr_fix += 2; /* account for jmp instruction */
+ fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
+ fragP->fr_offset, 0, NO_RELOC);
+ fragP->fr_fix += 4;
+ }
+ frag_wane (fragP);
+ break;
+ } /* case TAB(BCC68000,SZ_UNDEF) */
+
+ case TAB (DBCC, SZ_UNDEF):
+ {
+ if (fragP->fr_symbol != NULL
+ && S_GET_SEGMENT (fragP->fr_symbol) == segment
+ && relaxable_symbol (fragP->fr_symbol))
+ {
+ fragP->fr_subtype = TAB (DBCC, SHORT);
+ fragP->fr_var += 2;
+ break;
+ }
+ /* only DBcc 68000 instructions can come here */
+ /* change dbcc into dbcc/jmp absl long */
+ /* JF: these used to be fr_opcode[2-4], which is wrong. */
+ buffer_address[0] = 0x00; /* branch offset = 4 */
+ buffer_address[1] = 0x04;
+ buffer_address[2] = 0x60; /* put in bra pc + ... */
+
+ if (flag_short_refs)
+ {
+ /* JF: these were fr_opcode[5-7] */
+ buffer_address[3] = 0x04; /* plus 4 */
+ buffer_address[4] = 0x4e; /* Put in Jump Word */
+ buffer_address[5] = (char) 0xf8;
+ fragP->fr_fix += 6; /* account for bra/jmp instruction */
+ fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
+ fragP->fr_offset, 0, NO_RELOC);
+ fragP->fr_fix += 2;
+ }
+ else
+ {
+ /* JF: these were fr_opcode[5-7] */
+ buffer_address[3] = 0x06; /* Plus 6 */
+ buffer_address[4] = 0x4e; /* put in jmp long (0x4ef9) */
+ buffer_address[5] = (char) 0xf9;
+ fragP->fr_fix += 6; /* account for bra/jmp instruction */
+ fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
+ fragP->fr_offset, 0, NO_RELOC);
+ fragP->fr_fix += 4;
+ }
+
+ frag_wane (fragP);
+ break;
+ } /* case TAB(DBCC,SZ_UNDEF) */
+
+ case TAB (PCLEA, SZ_UNDEF):
+ {
+ if (((S_GET_SEGMENT (fragP->fr_symbol)) == segment
+ && relaxable_symbol (fragP->fr_symbol))
+ || flag_short_refs
+ || cpu_of_arch (current_architecture) < m68020
+ || cpu_of_arch (current_architecture) == mcf5200)
+ {
+ fragP->fr_subtype = TAB (PCLEA, SHORT);
+ fragP->fr_var += 2;
+ }
+ else
+ {
+ fragP->fr_subtype = TAB (PCLEA, LONG);
+ fragP->fr_var += 6;
+ }
+ break;
+ } /* TAB(PCLEA,SZ_UNDEF) */
+
+ case TAB (PCINDEX, SZ_UNDEF):
+ if ((S_GET_SEGMENT (fragP->fr_symbol) == segment
+ && relaxable_symbol (fragP->fr_symbol))
+ || cpu_of_arch (current_architecture) < m68020
+ || cpu_of_arch (current_architecture) == mcf5200)
+ {
+ fragP->fr_subtype = TAB (PCINDEX, BYTE);
+ }
+ else
+ {
+ fragP->fr_subtype = TAB (PCINDEX, LONG);
+ fragP->fr_var += 4;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* now that SZ_UNDEF are taken care of, check others */
+ switch (fragP->fr_subtype)
+ {
+ case TAB (BCC68000, BYTE):
+ case TAB (ABRANCH, BYTE):
+ /* We can't do a short jump to the next instruction, so in that
+ case we force word mode. At this point S_GET_VALUE should
+ return the offset of the symbol within its frag. If the
+ symbol is at the start of a frag, and it is the next frag
+ with any data in it (usually this is just the next frag, but
+ assembler listings may introduce empty frags), we must use
+ word mode. */
+ if (fragP->fr_symbol && S_GET_VALUE (fragP->fr_symbol) == 0)
+ {
+ fragS *l;
+
+ for (l = fragP->fr_next;
+ l != fragP->fr_symbol->sy_frag;
+ l = l->fr_next)
+ if (l->fr_fix + l->fr_var != 0)
+ break;
+ if (l == fragP->fr_symbol->sy_frag)
+ {
+ fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), SHORT);
+ fragP->fr_var += 2;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return fragP->fr_var + fragP->fr_fix - old_fix;
+}
+
+#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
+/* the bit-field entries in the relocation_info struct plays hell
+ with the byte-order problems of cross-assembly. So as a hack,
+ I added this mach. dependent ri twiddler. Ugly, but it gets
+ you there. -KWK */
+/* on m68k: first 4 bytes are normal unsigned long, next three bytes
+ are symbolnum, most sig. byte first. Last byte is broken up with
+ bit 7 as pcrel, bits 6 & 5 as length, bit 4 as pcrel, and the lower
+ nibble as nuthin. (on Sun 3 at least) */
+/* Translate the internal relocation information into target-specific
+ format. */
+#ifdef comment
+void
+md_ri_to_chars (the_bytes, ri)
+ char *the_bytes;
+ struct reloc_info_generic *ri;
+{
+ /* this is easy */
+ md_number_to_chars (the_bytes, ri->r_address, 4);
+ /* now the fun stuff */
+ the_bytes[4] = (ri->r_symbolnum >> 16) & 0x0ff;
+ the_bytes[5] = (ri->r_symbolnum >> 8) & 0x0ff;
+ the_bytes[6] = ri->r_symbolnum & 0x0ff;
+ the_bytes[7] = (((ri->r_pcrel << 7) & 0x80) | ((ri->r_length << 5) & 0x60) |
+ ((ri->r_extern << 4) & 0x10));
+}
+
+#endif /* comment */
+
+#ifndef BFD_ASSEMBLER
+void
+tc_aout_fix_to_chars (where, fixP, segment_address_in_file)
+ char *where;
+ fixS *fixP;
+ relax_addressT segment_address_in_file;
+{
+ /*
+ * In: length of relocation (or of address) in chars: 1, 2 or 4.
+ * Out: GNU LD relocation length code: 0, 1, or 2.
+ */
+
+ static CONST unsigned char nbytes_r_length[] = {42, 0, 1, 42, 2};
+ long r_symbolnum;
+
+ know (fixP->fx_addsy != NULL);
+
+ md_number_to_chars (where,
+ fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
+ 4);
+
+ r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy)
+ ? S_GET_TYPE (fixP->fx_addsy)
+ : fixP->fx_addsy->sy_number);
+
+ where[4] = (r_symbolnum >> 16) & 0x0ff;
+ where[5] = (r_symbolnum >> 8) & 0x0ff;
+ where[6] = r_symbolnum & 0x0ff;
+ where[7] = (((fixP->fx_pcrel << 7) & 0x80) | ((nbytes_r_length[fixP->fx_size] << 5) & 0x60) |
+ (((!S_IS_DEFINED (fixP->fx_addsy)) << 4) & 0x10));
+}
+#endif
+
+#endif /* OBJ_AOUT or OBJ_BOUT */
+
+#ifndef WORKING_DOT_WORD
+CONST int md_short_jump_size = 4;
+CONST int md_long_jump_size = 6;
+
+void
+md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
+ char *ptr;
+ addressT from_addr, to_addr;
+ fragS *frag;
+ symbolS *to_symbol;
+{
+ valueT offset;
+
+ offset = to_addr - (from_addr + 2);
+
+ md_number_to_chars (ptr, (valueT) 0x6000, 2);
+ md_number_to_chars (ptr + 2, (valueT) offset, 2);
+}
+
+void
+md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
+ char *ptr;
+ addressT from_addr, to_addr;
+ fragS *frag;
+ symbolS *to_symbol;
+{
+ valueT offset;
+
+ if (!HAVE_LONG_BRANCH(current_architecture))
+ {
+ offset = to_addr - S_GET_VALUE (to_symbol);
+ md_number_to_chars (ptr, (valueT) 0x4EF9, 2);
+ md_number_to_chars (ptr + 2, (valueT) offset, 4);
+ fix_new (frag, (ptr + 2) - frag->fr_literal, 4, to_symbol, (offsetT) 0,
+ 0, NO_RELOC);
+ }
+ else
+ {
+ offset = to_addr - (from_addr + 2);
+ md_number_to_chars (ptr, (valueT) 0x60ff, 2);
+ md_number_to_chars (ptr + 2, (valueT) offset, 4);
+ }
+}
+
+#endif
+
+/* Different values of OK tell what its OK to return. Things that
+ aren't OK are an error (what a shock, no?)
+
+ 0: Everything is OK
+ 10: Absolute 1:8 only
+ 20: Absolute 0:7 only
+ 30: absolute 0:15 only
+ 40: Absolute 0:31 only
+ 50: absolute 0:127 only
+ 55: absolute -64:63 only
+ 60: absolute -128:127 only
+ 70: absolute 0:4095 only
+ 80: No bignums
+
+ */
+
+static int
+get_num (exp, ok)
+ struct m68k_exp *exp;
+ int ok;
+{
+ if (exp->exp.X_op == O_absent)
+ {
+ /* Do the same thing the VAX asm does */
+ op (exp) = O_constant;
+ adds (exp) = 0;
+ subs (exp) = 0;
+ offs (exp) = 0;
+ if (ok == 10)
+ {
+ as_warn (_("expression out of range: defaulting to 1"));
+ offs (exp) = 1;
+ }
+ }
+ else if (exp->exp.X_op == O_constant)
+ {
+ switch (ok)
+ {
+ case 10:
+ if (offs (exp) < 1 || offs (exp) > 8)
+ {
+ as_warn (_("expression out of range: defaulting to 1"));
+ offs (exp) = 1;
+ }
+ break;
+ case 20:
+ if (offs (exp) < 0 || offs (exp) > 7)
+ goto outrange;
+ break;
+ case 30:
+ if (offs (exp) < 0 || offs (exp) > 15)
+ goto outrange;
+ break;
+ case 40:
+ if (offs (exp) < 0 || offs (exp) > 32)
+ goto outrange;
+ break;
+ case 50:
+ if (offs (exp) < 0 || offs (exp) > 127)
+ goto outrange;
+ break;
+ case 55:
+ if (offs (exp) < -64 || offs (exp) > 63)
+ goto outrange;
+ break;
+ case 60:
+ if (offs (exp) < -128 || offs (exp) > 127)
+ goto outrange;
+ break;
+ case 70:
+ if (offs (exp) < 0 || offs (exp) > 4095)
+ {
+ outrange:
+ as_warn (_("expression out of range: defaulting to 0"));
+ offs (exp) = 0;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ else if (exp->exp.X_op == O_big)
+ {
+ if (offs (exp) <= 0 /* flonum */
+ && (ok == 80 /* no bignums */
+ || (ok > 10 /* small-int ranges including 0 ok */
+ /* If we have a flonum zero, a zero integer should
+ do as well (e.g., in moveq). */
+ && generic_floating_point_number.exponent == 0
+ && generic_floating_point_number.low[0] == 0)))
+ {
+ /* HACK! Turn it into a long */
+ LITTLENUM_TYPE words[6];
+
+ gen_to_words (words, 2, 8L); /* These numbers are magic! */
+ op (exp) = O_constant;
+ adds (exp) = 0;
+ subs (exp) = 0;
+ offs (exp) = words[1] | (words[0] << 16);
+ }
+ else if (ok != 0)
+ {
+ op (exp) = O_constant;
+ adds (exp) = 0;
+ subs (exp) = 0;
+ offs (exp) = (ok == 10) ? 1 : 0;
+ as_warn (_("Can't deal with expression; defaulting to %ld"),
+ offs (exp));
+ }
+ }
+ else
+ {
+ if (ok >= 10 && ok <= 70)
+ {
+ op (exp) = O_constant;
+ adds (exp) = 0;
+ subs (exp) = 0;
+ offs (exp) = (ok == 10) ? 1 : 0;
+ as_warn (_("Can't deal with expression; defaulting to %ld"),
+ offs (exp));
+ }
+ }
+
+ if (exp->size != SIZE_UNSPEC)
+ {
+ switch (exp->size)
+ {
+ case SIZE_UNSPEC:
+ case SIZE_LONG:
+ break;
+ case SIZE_BYTE:
+ if (!isbyte (offs (exp)))
+ as_warn (_("expression doesn't fit in BYTE"));
+ break;
+ case SIZE_WORD:
+ if (!isword (offs (exp)))
+ as_warn (_("expression doesn't fit in WORD"));
+ break;
+ }
+ }
+
+ return offs (exp);
+}
+
+/* These are the back-ends for the various machine dependent pseudo-ops. */
+
+static void
+s_data1 (ignore)
+ int ignore;
+{
+ subseg_set (data_section, 1);
+ demand_empty_rest_of_line ();
+}
+
+static void
+s_data2 (ignore)
+ int ignore;
+{
+ subseg_set (data_section, 2);
+ demand_empty_rest_of_line ();
+}
+
+static void
+s_bss (ignore)
+ int ignore;
+{
+ /* We don't support putting frags in the BSS segment, we fake it
+ by marking in_bss, then looking at s_skip for clues. */
+
+ subseg_set (bss_section, 0);
+ demand_empty_rest_of_line ();
+}
+
+static void
+s_even (ignore)
+ int ignore;
+{
+ register int temp;
+ register long temp_fill;
+
+ temp = 1; /* JF should be 2? */
+ temp_fill = get_absolute_expression ();
+ if (!need_pass_2) /* Never make frag if expect extra pass. */
+ frag_align (temp, (int) temp_fill, 0);
+ demand_empty_rest_of_line ();
+ record_alignment (now_seg, temp);
+}
+
+static void
+s_proc (ignore)
+ int ignore;
+{
+ demand_empty_rest_of_line ();
+}
+
+/* Pseudo-ops handled for MRI compatibility. */
+
+/* This function returns non-zero if the argument is a conditional
+ pseudo-op. This is called when checking whether a pending
+ alignment is needed. */
+
+int
+m68k_conditional_pseudoop (pop)
+ pseudo_typeS *pop;
+{
+ return (pop->poc_handler == s_mri_if
+ || pop->poc_handler == s_mri_else);
+}
+
+/* Handle an MRI style chip specification. */
+
+static void
+mri_chip ()
+{
+ char *s;
+ char c;
+ int i;
+
+ s = input_line_pointer;
+ /* We can't use get_symbol_end since the processor names are not proper
+ symbols. */
+ while (is_part_of_name (c = *input_line_pointer++))
+ ;
+ *--input_line_pointer = 0;
+ for (i = 0; i < n_archs; i++)
+ if (strcasecmp (s, archs[i].name) == 0)
+ break;
+ if (i >= n_archs)
+ {
+ as_bad (_("%s: unrecognized processor name"), s);
+ *input_line_pointer = c;
+ ignore_rest_of_line ();
+ return;
+ }
+ *input_line_pointer = c;
+
+ if (*input_line_pointer == '/')
+ current_architecture = 0;
+ else
+ current_architecture &= m68881 | m68851;
+ current_architecture |= archs[i].arch;
+
+ while (*input_line_pointer == '/')
+ {
+ ++input_line_pointer;
+ s = input_line_pointer;
+ /* We can't use get_symbol_end since the processor names are not
+ proper symbols. */
+ while (is_part_of_name (c = *input_line_pointer++))
+ ;
+ *--input_line_pointer = 0;
+ if (strcmp (s, "68881") == 0)
+ current_architecture |= m68881;
+ else if (strcmp (s, "68851") == 0)
+ current_architecture |= m68851;
+ *input_line_pointer = c;
+ }
+
+ /* Update info about available control registers. */
+ select_control_regs ();
+}
+
+/* The MRI CHIP pseudo-op. */
+
+static void
+s_chip (ignore)
+ int ignore;
+{
+ char *stop = NULL;
+ char stopc;
+
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
+ mri_chip ();
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+ demand_empty_rest_of_line ();
+}
+
+/* The MRI FOPT pseudo-op. */
+
+static void
+s_fopt (ignore)
+ int ignore;
+{
+ SKIP_WHITESPACE ();
+
+ if (strncasecmp (input_line_pointer, "ID=", 3) == 0)
+ {
+ int temp;
+
+ input_line_pointer += 3;
+ temp = get_absolute_expression ();
+ if (temp < 0 || temp > 7)
+ as_bad (_("bad coprocessor id"));
+ else
+ m68k_float_copnum = COP0 + temp;
+ }
+ else
+ {
+ as_bad (_("unrecognized fopt option"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* The structure used to handle the MRI OPT pseudo-op. */
+
+struct opt_action
+{
+ /* The name of the option. */
+ const char *name;
+
+ /* If this is not NULL, just call this function. The first argument
+ is the ARG field of this structure, the second argument is
+ whether the option was negated. */
+ void (*pfn) PARAMS ((int arg, int on));
+
+ /* If this is not NULL, and the PFN field is NULL, set the variable
+ this points to. Set it to the ARG field if the option was not
+ negated, and the NOTARG field otherwise. */
+ int *pvar;
+
+ /* The value to pass to PFN or to assign to *PVAR. */
+ int arg;
+
+ /* The value to assign to *PVAR if the option is negated. If PFN is
+ NULL, and PVAR is not NULL, and ARG and NOTARG are the same, then
+ the option may not be negated. */
+ int notarg;
+};
+
+/* The table used to handle the MRI OPT pseudo-op. */
+
+static void skip_to_comma PARAMS ((int, int));
+static void opt_nest PARAMS ((int, int));
+static void opt_chip PARAMS ((int, int));
+static void opt_list PARAMS ((int, int));
+static void opt_list_symbols PARAMS ((int, int));
+
+static const struct opt_action opt_table[] =
+{
+ { "abspcadd", 0, &m68k_abspcadd, 1, 0 },
+
+ /* We do relaxing, so there is little use for these options. */
+ { "b", 0, 0, 0, 0 },
+ { "brs", 0, 0, 0, 0 },
+ { "brb", 0, 0, 0, 0 },
+ { "brl", 0, 0, 0, 0 },
+ { "brw", 0, 0, 0, 0 },
+
+ { "c", 0, 0, 0, 0 },
+ { "cex", 0, 0, 0, 0 },
+ { "case", 0, &symbols_case_sensitive, 1, 0 },
+ { "cl", 0, 0, 0, 0 },
+ { "cre", 0, 0, 0, 0 },
+ { "d", 0, &flag_keep_locals, 1, 0 },
+ { "e", 0, 0, 0, 0 },
+ { "f", 0, &flag_short_refs, 1, 0 },
+ { "frs", 0, &flag_short_refs, 1, 0 },
+ { "frl", 0, &flag_short_refs, 0, 1 },
+ { "g", 0, 0, 0, 0 },
+ { "i", 0, 0, 0, 0 },
+ { "m", 0, 0, 0, 0 },
+ { "mex", 0, 0, 0, 0 },
+ { "mc", 0, 0, 0, 0 },
+ { "md", 0, 0, 0, 0 },
+ { "nest", opt_nest, 0, 0, 0 },
+ { "next", skip_to_comma, 0, 0, 0 },
+ { "o", 0, 0, 0, 0 },
+ { "old", 0, 0, 0, 0 },
+ { "op", skip_to_comma, 0, 0, 0 },
+ { "pco", 0, 0, 0, 0 },
+ { "p", opt_chip, 0, 0, 0 },
+ { "pcr", 0, 0, 0, 0 },
+ { "pcs", 0, 0, 0, 0 },
+ { "r", 0, 0, 0, 0 },
+ { "quick", 0, &m68k_quick, 1, 0 },
+ { "rel32", 0, &m68k_rel32, 1, 0 },
+ { "s", opt_list, 0, 0, 0 },
+ { "t", opt_list_symbols, 0, 0, 0 },
+ { "w", 0, &flag_no_warnings, 0, 1 },
+ { "x", 0, 0, 0, 0 }
+};
+
+#define OPTCOUNT (sizeof opt_table / sizeof opt_table[0])
+
+/* The MRI OPT pseudo-op. */
+
+static void
+s_opt (ignore)
+ int ignore;
+{
+ do
+ {
+ int t;
+ char *s;
+ char c;
+ int i;
+ const struct opt_action *o;
+
+ SKIP_WHITESPACE ();
+
+ t = 1;
+ if (*input_line_pointer == '-')
+ {
+ ++input_line_pointer;
+ t = 0;
+ }
+ else if (strncasecmp (input_line_pointer, "NO", 2) == 0)
+ {
+ input_line_pointer += 2;
+ t = 0;
+ }
+
+ s = input_line_pointer;
+ c = get_symbol_end ();
+
+ for (i = 0, o = opt_table; i < OPTCOUNT; i++, o++)
+ {
+ if (strcasecmp (s, o->name) == 0)
+ {
+ if (o->pfn)
+ {
+ /* Restore input_line_pointer now in case the option
+ takes arguments. */
+ *input_line_pointer = c;
+ (*o->pfn) (o->arg, t);
+ }
+ else if (o->pvar != NULL)
+ {
+ if (! t && o->arg == o->notarg)
+ as_bad (_("option `%s' may not be negated"), s);
+ *input_line_pointer = c;
+ *o->pvar = t ? o->arg : o->notarg;
+ }
+ else
+ *input_line_pointer = c;
+ break;
+ }
+ }
+ if (i >= OPTCOUNT)
+ {
+ as_bad (_("option `%s' not recognized"), s);
+ *input_line_pointer = c;
+ }
+ }
+ while (*input_line_pointer++ == ',');
+
+ /* Move back to terminating character. */
+ --input_line_pointer;
+ demand_empty_rest_of_line ();
+}
+
+/* Skip ahead to a comma. This is used for OPT options which we do
+ not suppor tand which take arguments. */
+
+static void
+skip_to_comma (arg, on)
+ int arg;
+ int on;
+{
+ while (*input_line_pointer != ','
+ && ! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+}
+
+/* Handle the OPT NEST=depth option. */
+
+static void
+opt_nest (arg, on)
+ int arg;
+ int on;
+{
+ if (*input_line_pointer != '=')
+ {
+ as_bad (_("bad format of OPT NEST=depth"));
+ return;
+ }
+
+ ++input_line_pointer;
+ max_macro_nest = get_absolute_expression ();
+}
+
+/* Handle the OPT P=chip option. */
+
+static void
+opt_chip (arg, on)
+ int arg;
+ int on;
+{
+ if (*input_line_pointer != '=')
+ {
+ /* This is just OPT P, which we do not support. */
+ return;
+ }
+
+ ++input_line_pointer;
+ mri_chip ();
+}
+
+/* Handle the OPT S option. */
+
+static void
+opt_list (arg, on)
+ int arg;
+ int on;
+{
+ listing_list (on);
+}
+
+/* Handle the OPT T option. */
+
+static void
+opt_list_symbols (arg, on)
+ int arg;
+ int on;
+{
+ if (on)
+ listing |= LISTING_SYMBOLS;
+ else
+ listing &=~ LISTING_SYMBOLS;
+}
+
+/* Handle the MRI REG pseudo-op. */
+
+static void
+s_reg (ignore)
+ int ignore;
+{
+ char *s;
+ int c;
+ struct m68k_op rop;
+ int mask;
+ char *stop = NULL;
+ char stopc;
+
+ if (line_label == NULL)
+ {
+ as_bad (_("missing label"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
+
+ SKIP_WHITESPACE ();
+
+ s = input_line_pointer;
+ while (isalnum ((unsigned char) *input_line_pointer)
+#ifdef REGISTER_PREFIX
+ || *input_line_pointer == REGISTER_PREFIX
+#endif
+ || *input_line_pointer == '/'
+ || *input_line_pointer == '-')
+ ++input_line_pointer;
+ c = *input_line_pointer;
+ *input_line_pointer = '\0';
+
+ if (m68k_ip_op (s, &rop) != 0)
+ {
+ if (rop.error == NULL)
+ as_bad (_("bad register list"));
+ else
+ as_bad (_("bad register list: %s"), rop.error);
+ *input_line_pointer = c;
+ ignore_rest_of_line ();
+ return;
+ }
+
+ *input_line_pointer = c;
+
+ if (rop.mode == REGLST)
+ mask = rop.mask;
+ else if (rop.mode == DREG)
+ mask = 1 << (rop.reg - DATA0);
+ else if (rop.mode == AREG)
+ mask = 1 << (rop.reg - ADDR0 + 8);
+ else if (rop.mode == FPREG)
+ mask = 1 << (rop.reg - FP0 + 16);
+ else if (rop.mode == CONTROL
+ && rop.reg == FPI)
+ mask = 1 << 24;
+ else if (rop.mode == CONTROL
+ && rop.reg == FPS)
+ mask = 1 << 25;
+ else if (rop.mode == CONTROL
+ && rop.reg == FPC)
+ mask = 1 << 26;
+ else
+ {
+ as_bad (_("bad register list"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ S_SET_SEGMENT (line_label, reg_section);
+ S_SET_VALUE (line_label, ~mask);
+ line_label->sy_frag = &zero_address_frag;
+
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+
+ demand_empty_rest_of_line ();
+}
+
+/* This structure is used for the MRI SAVE and RESTORE pseudo-ops. */
+
+struct save_opts
+{
+ struct save_opts *next;
+ int abspcadd;
+ int symbols_case_sensitive;
+ int keep_locals;
+ int short_refs;
+ int architecture;
+ int quick;
+ int rel32;
+ int listing;
+ int no_warnings;
+ /* FIXME: We don't save OPT S. */
+};
+
+/* This variable holds the stack of saved options. */
+
+static struct save_opts *save_stack;
+
+/* The MRI SAVE pseudo-op. */
+
+static void
+s_save (ignore)
+ int ignore;
+{
+ struct save_opts *s;
+
+ s = (struct save_opts *) xmalloc (sizeof (struct save_opts));
+ s->abspcadd = m68k_abspcadd;
+ s->symbols_case_sensitive = symbols_case_sensitive;
+ s->keep_locals = flag_keep_locals;
+ s->short_refs = flag_short_refs;
+ s->architecture = current_architecture;
+ s->quick = m68k_quick;
+ s->rel32 = m68k_rel32;
+ s->listing = listing;
+ s->no_warnings = flag_no_warnings;
+
+ s->next = save_stack;
+ save_stack = s;
+
+ demand_empty_rest_of_line ();
+}
+
+/* The MRI RESTORE pseudo-op. */
+
+static void
+s_restore (ignore)
+ int ignore;
+{
+ struct save_opts *s;
+
+ if (save_stack == NULL)
+ {
+ as_bad (_("restore without save"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ s = save_stack;
+ save_stack = s->next;
+
+ m68k_abspcadd = s->abspcadd;
+ symbols_case_sensitive = s->symbols_case_sensitive;
+ flag_keep_locals = s->keep_locals;
+ flag_short_refs = s->short_refs;
+ current_architecture = s->architecture;
+ m68k_quick = s->quick;
+ m68k_rel32 = s->rel32;
+ listing = s->listing;
+ flag_no_warnings = s->no_warnings;
+
+ free (s);
+
+ demand_empty_rest_of_line ();
+}
+
+/* Types of MRI structured control directives. */
+
+enum mri_control_type
+{
+ mri_for,
+ mri_if,
+ mri_repeat,
+ mri_while
+};
+
+/* This structure is used to stack the MRI structured control
+ directives. */
+
+struct mri_control_info
+{
+ /* The directive within which this one is enclosed. */
+ struct mri_control_info *outer;
+
+ /* The type of directive. */
+ enum mri_control_type type;
+
+ /* Whether an ELSE has been in an IF. */
+ int else_seen;
+
+ /* The add or sub statement at the end of a FOR. */
+ char *incr;
+
+ /* The label of the top of a FOR or REPEAT loop. */
+ char *top;
+
+ /* The label to jump to for the next iteration, or the else
+ expression of a conditional. */
+ char *next;
+
+ /* The label to jump to to break out of the loop, or the label past
+ the end of a conditional. */
+ char *bottom;
+};
+
+/* The stack of MRI structured control directives. */
+
+static struct mri_control_info *mri_control_stack;
+
+/* The current MRI structured control directive index number, used to
+ generate label names. */
+
+static int mri_control_index;
+
+/* Some function prototypes. */
+
+static void mri_assemble PARAMS ((char *));
+static char *mri_control_label PARAMS ((void));
+static struct mri_control_info *push_mri_control
+ PARAMS ((enum mri_control_type));
+static void pop_mri_control PARAMS ((void));
+static int parse_mri_condition PARAMS ((int *));
+static int parse_mri_control_operand
+ PARAMS ((int *, char **, char **, char **, char **));
+static int swap_mri_condition PARAMS ((int));
+static int reverse_mri_condition PARAMS ((int));
+static void build_mri_control_operand
+ PARAMS ((int, int, char *, char *, char *, char *, const char *,
+ const char *, int));
+static void parse_mri_control_expression
+ PARAMS ((char *, int, const char *, const char *, int));
+
+/* Assemble an instruction for an MRI structured control directive. */
+
+static void
+mri_assemble (str)
+ char *str;
+{
+ char *s;
+
+ /* md_assemble expects the opcode to be in lower case. */
+ for (s = str; *s != ' ' && *s != '\0'; s++)
+ {
+ if (isupper ((unsigned char) *s))
+ *s = tolower ((unsigned char) *s);
+ }
+
+ md_assemble (str);
+}
+
+/* Generate a new MRI label structured control directive label name. */
+
+static char *
+mri_control_label ()
+{
+ char *n;
+
+ n = (char *) xmalloc (20);
+ sprintf (n, "%smc%d", FAKE_LABEL_NAME, mri_control_index);
+ ++mri_control_index;
+ return n;
+}
+
+/* Create a new MRI structured control directive. */
+
+static struct mri_control_info *
+push_mri_control (type)
+ enum mri_control_type type;
+{
+ struct mri_control_info *n;
+
+ n = (struct mri_control_info *) xmalloc (sizeof (struct mri_control_info));
+
+ n->type = type;
+ n->else_seen = 0;
+ if (type == mri_if || type == mri_while)
+ n->top = NULL;
+ else
+ n->top = mri_control_label ();
+ n->next = mri_control_label ();
+ n->bottom = mri_control_label ();
+
+ n->outer = mri_control_stack;
+ mri_control_stack = n;
+
+ return n;
+}
+
+/* Pop off the stack of MRI structured control directives. */
+
+static void
+pop_mri_control ()
+{
+ struct mri_control_info *n;
+
+ n = mri_control_stack;
+ mri_control_stack = n->outer;
+ if (n->top != NULL)
+ free (n->top);
+ free (n->next);
+ free (n->bottom);
+ free (n);
+}
+
+/* Recognize a condition code in an MRI structured control expression. */
+
+static int
+parse_mri_condition (pcc)
+ int *pcc;
+{
+ char c1, c2;
+
+ know (*input_line_pointer == '<');
+
+ ++input_line_pointer;
+ c1 = *input_line_pointer++;
+ c2 = *input_line_pointer++;
+
+ if (*input_line_pointer != '>')
+ {
+ as_bad (_("syntax error in structured control directive"));
+ return 0;
+ }
+
+ ++input_line_pointer;
+ SKIP_WHITESPACE ();
+
+ if (isupper (c1))
+ c1 = tolower (c1);
+ if (isupper (c2))
+ c2 = tolower (c2);
+
+ *pcc = (c1 << 8) | c2;
+
+ return 1;
+}
+
+/* Parse a single operand in an MRI structured control expression. */
+
+static int
+parse_mri_control_operand (pcc, leftstart, leftstop, rightstart, rightstop)
+ int *pcc;
+ char **leftstart;
+ char **leftstop;
+ char **rightstart;
+ char **rightstop;
+{
+ char *s;
+
+ SKIP_WHITESPACE ();
+
+ *pcc = -1;
+ *leftstart = NULL;
+ *leftstop = NULL;
+ *rightstart = NULL;
+ *rightstop = NULL;
+
+ if (*input_line_pointer == '<')
+ {
+ /* It's just a condition code. */
+ return parse_mri_condition (pcc);
+ }
+
+ /* Look ahead for the condition code. */
+ for (s = input_line_pointer; *s != '\0'; ++s)
+ {
+ if (*s == '<' && s[1] != '\0' && s[2] != '\0' && s[3] == '>')
+ break;
+ }
+ if (*s == '\0')
+ {
+ as_bad (_("missing condition code in structured control directive"));
+ return 0;
+ }
+
+ *leftstart = input_line_pointer;
+ *leftstop = s;
+ if (*leftstop > *leftstart
+ && ((*leftstop)[-1] == ' ' || (*leftstop)[-1] == '\t'))
+ --*leftstop;
+
+ input_line_pointer = s;
+ if (! parse_mri_condition (pcc))
+ return 0;
+
+ /* Look ahead for AND or OR or end of line. */
+ for (s = input_line_pointer; *s != '\0'; ++s)
+ {
+ if ((strncasecmp (s, "AND", 3) == 0
+ && (s[3] == '.' || ! is_part_of_name (s[3])))
+ || (strncasecmp (s, "OR", 2) == 0
+ && (s[2] == '.' || ! is_part_of_name (s[2]))))
+ break;
+ }
+
+ *rightstart = input_line_pointer;
+ *rightstop = s;
+ if (*rightstop > *rightstart
+ && ((*rightstop)[-1] == ' ' || (*rightstop)[-1] == '\t'))
+ --*rightstop;
+
+ input_line_pointer = s;
+
+ return 1;
+}
+
+#define MCC(b1, b2) (((b1) << 8) | (b2))
+
+/* Swap the sense of a condition. This changes the condition so that
+ it generates the same result when the operands are swapped. */
+
+static int
+swap_mri_condition (cc)
+ int cc;
+{
+ switch (cc)
+ {
+ case MCC ('h', 'i'): return MCC ('c', 's');
+ case MCC ('l', 's'): return MCC ('c', 'c');
+ case MCC ('c', 'c'): return MCC ('l', 's');
+ case MCC ('c', 's'): return MCC ('h', 'i');
+ case MCC ('p', 'l'): return MCC ('m', 'i');
+ case MCC ('m', 'i'): return MCC ('p', 'l');
+ case MCC ('g', 'e'): return MCC ('l', 'e');
+ case MCC ('l', 't'): return MCC ('g', 't');
+ case MCC ('g', 't'): return MCC ('l', 't');
+ case MCC ('l', 'e'): return MCC ('g', 'e');
+ }
+ return cc;
+}
+
+/* Reverse the sense of a condition. */
+
+static int
+reverse_mri_condition (cc)
+ int cc;
+{
+ switch (cc)
+ {
+ case MCC ('h', 'i'): return MCC ('l', 's');
+ case MCC ('l', 's'): return MCC ('h', 'i');
+ case MCC ('c', 'c'): return MCC ('c', 's');
+ case MCC ('c', 's'): return MCC ('c', 'c');
+ case MCC ('n', 'e'): return MCC ('e', 'q');
+ case MCC ('e', 'q'): return MCC ('n', 'e');
+ case MCC ('v', 'c'): return MCC ('v', 's');
+ case MCC ('v', 's'): return MCC ('v', 'c');
+ case MCC ('p', 'l'): return MCC ('m', 'i');
+ case MCC ('m', 'i'): return MCC ('p', 'l');
+ case MCC ('g', 'e'): return MCC ('l', 't');
+ case MCC ('l', 't'): return MCC ('g', 'e');
+ case MCC ('g', 't'): return MCC ('l', 'e');
+ case MCC ('l', 'e'): return MCC ('g', 't');
+ }
+ return cc;
+}
+
+/* Build an MRI structured control expression. This generates test
+ and branch instructions. It goes to TRUELAB if the condition is
+ true, and to FALSELAB if the condition is false. Exactly one of
+ TRUELAB and FALSELAB will be NULL, meaning to fall through. QUAL
+ is the size qualifier for the expression. EXTENT is the size to
+ use for the branch. */
+
+static void
+build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart,
+ rightstop, truelab, falselab, extent)
+ int qual;
+ int cc;
+ char *leftstart;
+ char *leftstop;
+ char *rightstart;
+ char *rightstop;
+ const char *truelab;
+ const char *falselab;
+ int extent;
+{
+ char *buf;
+ char *s;
+
+ if (leftstart != NULL)
+ {
+ struct m68k_op leftop, rightop;
+ char c;
+
+ /* Swap the compare operands, if necessary, to produce a legal
+ m68k compare instruction. Comparing a register operand with
+ a non-register operand requires the register to be on the
+ right (cmp, cmpa). Comparing an immediate value with
+ anything requires the immediate value to be on the left
+ (cmpi). */
+
+ c = *leftstop;
+ *leftstop = '\0';
+ (void) m68k_ip_op (leftstart, &leftop);
+ *leftstop = c;
+
+ c = *rightstop;
+ *rightstop = '\0';
+ (void) m68k_ip_op (rightstart, &rightop);
+ *rightstop = c;
+
+ if (rightop.mode == IMMED
+ || ((leftop.mode == DREG || leftop.mode == AREG)
+ && (rightop.mode != DREG && rightop.mode != AREG)))
+ {
+ char *temp;
+
+ cc = swap_mri_condition (cc);
+ temp = leftstart;
+ leftstart = rightstart;
+ rightstart = temp;
+ temp = leftstop;
+ leftstop = rightstop;
+ rightstop = temp;
+ }
+ }
+
+ if (truelab == NULL)
+ {
+ cc = reverse_mri_condition (cc);
+ truelab = falselab;
+ }
+
+ if (leftstart != NULL)
+ {
+ buf = (char *) xmalloc (20
+ + (leftstop - leftstart)
+ + (rightstop - rightstart));
+ s = buf;
+ *s++ = 'c';
+ *s++ = 'm';
+ *s++ = 'p';
+ if (qual != '\0')
+ *s++ = qual;
+ *s++ = ' ';
+ memcpy (s, leftstart, leftstop - leftstart);
+ s += leftstop - leftstart;
+ *s++ = ',';
+ memcpy (s, rightstart, rightstop - rightstart);
+ s += rightstop - rightstart;
+ *s = '\0';
+ mri_assemble (buf);
+ free (buf);
+ }
+
+ buf = (char *) xmalloc (20 + strlen (truelab));
+ s = buf;
+ *s++ = 'b';
+ *s++ = cc >> 8;
+ *s++ = cc & 0xff;
+ if (extent != '\0')
+ *s++ = extent;
+ *s++ = ' ';
+ strcpy (s, truelab);
+ mri_assemble (buf);
+ free (buf);
+}
+
+/* Parse an MRI structured control expression. This generates test
+ and branch instructions. STOP is where the expression ends. It
+ goes to TRUELAB if the condition is true, and to FALSELAB if the
+ condition is false. Exactly one of TRUELAB and FALSELAB will be
+ NULL, meaning to fall through. QUAL is the size qualifier for the
+ expression. EXTENT is the size to use for the branch. */
+
+static void
+parse_mri_control_expression (stop, qual, truelab, falselab, extent)
+ char *stop;
+ int qual;
+ const char *truelab;
+ const char *falselab;
+ int extent;
+{
+ int c;
+ int cc;
+ char *leftstart;
+ char *leftstop;
+ char *rightstart;
+ char *rightstop;
+
+ c = *stop;
+ *stop = '\0';
+
+ if (! parse_mri_control_operand (&cc, &leftstart, &leftstop,
+ &rightstart, &rightstop))
+ {
+ *stop = c;
+ return;
+ }
+
+ if (strncasecmp (input_line_pointer, "AND", 3) == 0)
+ {
+ const char *flab;
+
+ if (falselab != NULL)
+ flab = falselab;
+ else
+ flab = mri_control_label ();
+
+ build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart,
+ rightstop, (const char *) NULL, flab, extent);
+
+ input_line_pointer += 3;
+ if (*input_line_pointer != '.'
+ || input_line_pointer[1] == '\0')
+ qual = '\0';
+ else
+ {
+ qual = input_line_pointer[1];
+ input_line_pointer += 2;
+ }
+
+ if (! parse_mri_control_operand (&cc, &leftstart, &leftstop,
+ &rightstart, &rightstop))
+ {
+ *stop = c;
+ return;
+ }
+
+ build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart,
+ rightstop, truelab, falselab, extent);
+
+ if (falselab == NULL)
+ colon (flab);
+ }
+ else if (strncasecmp (input_line_pointer, "OR", 2) == 0)
+ {
+ const char *tlab;
+
+ if (truelab != NULL)
+ tlab = truelab;
+ else
+ tlab = mri_control_label ();
+
+ build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart,
+ rightstop, tlab, (const char *) NULL, extent);
+
+ input_line_pointer += 2;
+ if (*input_line_pointer != '.'
+ || input_line_pointer[1] == '\0')
+ qual = '\0';
+ else
+ {
+ qual = input_line_pointer[1];
+ input_line_pointer += 2;
+ }
+
+ if (! parse_mri_control_operand (&cc, &leftstart, &leftstop,
+ &rightstart, &rightstop))
+ {
+ *stop = c;
+ return;
+ }
+
+ build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart,
+ rightstop, truelab, falselab, extent);
+
+ if (truelab == NULL)
+ colon (tlab);
+ }
+ else
+ {
+ build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart,
+ rightstop, truelab, falselab, extent);
+ }
+
+ *stop = c;
+ if (input_line_pointer != stop)
+ as_bad (_("syntax error in structured control directive"));
+}
+
+/* Handle the MRI IF pseudo-op. This may be a structured control
+ directive, or it may be a regular assembler conditional, depending
+ on its operands. */
+
+static void
+s_mri_if (qual)
+ int qual;
+{
+ char *s;
+ int c;
+ struct mri_control_info *n;
+
+ /* A structured control directive must end with THEN with an
+ optional qualifier. */
+ s = input_line_pointer;
+ while (! is_end_of_line[(unsigned char) *s]
+ && (! flag_mri || *s != '*'))
+ ++s;
+ --s;
+ while (s > input_line_pointer && (*s == ' ' || *s == '\t'))
+ --s;
+
+ if (s - input_line_pointer > 1
+ && s[-1] == '.')
+ s -= 2;
+
+ if (s - input_line_pointer < 3
+ || strncasecmp (s - 3, "THEN", 4) != 0)
+ {
+ if (qual != '\0')
+ {
+ as_bad (_("missing then"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ /* It's a conditional. */
+ s_if (O_ne);
+ return;
+ }
+
+ /* Since this might be a conditional if, this pseudo-op will be
+ called even if we are supported to be ignoring input. Double
+ check now. Clobber *input_line_pointer so that ignore_input
+ thinks that this is not a special pseudo-op. */
+ c = *input_line_pointer;
+ *input_line_pointer = 0;
+ if (ignore_input ())
+ {
+ *input_line_pointer = c;
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ demand_empty_rest_of_line ();
+ return;
+ }
+ *input_line_pointer = c;
+
+ n = push_mri_control (mri_if);
+
+ parse_mri_control_expression (s - 3, qual, (const char *) NULL,
+ n->next, s[1] == '.' ? s[2] : '\0');
+
+ if (s[1] == '.')
+ input_line_pointer = s + 3;
+ else
+ input_line_pointer = s + 1;
+
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the MRI else pseudo-op. If we are currently doing an MRI
+ structured IF, associate the ELSE with the IF. Otherwise, assume
+ it is a conditional else. */
+
+static void
+s_mri_else (qual)
+ int qual;
+{
+ int c;
+ char *buf;
+ char q[2];
+
+ if (qual == '\0'
+ && (mri_control_stack == NULL
+ || mri_control_stack->type != mri_if
+ || mri_control_stack->else_seen))
+ {
+ s_else (0);
+ return;
+ }
+
+ c = *input_line_pointer;
+ *input_line_pointer = 0;
+ if (ignore_input ())
+ {
+ *input_line_pointer = c;
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ demand_empty_rest_of_line ();
+ return;
+ }
+ *input_line_pointer = c;
+
+ if (mri_control_stack == NULL
+ || mri_control_stack->type != mri_if
+ || mri_control_stack->else_seen)
+ {
+ as_bad (_("else without matching if"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ mri_control_stack->else_seen = 1;
+
+ buf = (char *) xmalloc (20 + strlen (mri_control_stack->bottom));
+ q[0] = qual;
+ q[1] = '\0';
+ sprintf (buf, "bra%s %s", q, mri_control_stack->bottom);
+ mri_assemble (buf);
+ free (buf);
+
+ colon (mri_control_stack->next);
+
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the MRI ENDI pseudo-op. */
+
+static void
+s_mri_endi (ignore)
+ int ignore;
+{
+ if (mri_control_stack == NULL
+ || mri_control_stack->type != mri_if)
+ {
+ as_bad (_("endi without matching if"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ /* ignore_input will not return true for ENDI, so we don't need to
+ worry about checking it again here. */
+
+ if (! mri_control_stack->else_seen)
+ colon (mri_control_stack->next);
+ colon (mri_control_stack->bottom);
+
+ pop_mri_control ();
+
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the MRI BREAK pseudo-op. */
+
+static void
+s_mri_break (extent)
+ int extent;
+{
+ struct mri_control_info *n;
+ char *buf;
+ char ex[2];
+
+ n = mri_control_stack;
+ while (n != NULL
+ && n->type != mri_for
+ && n->type != mri_repeat
+ && n->type != mri_while)
+ n = n->outer;
+ if (n == NULL)
+ {
+ as_bad (_("break outside of structured loop"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ buf = (char *) xmalloc (20 + strlen (n->bottom));
+ ex[0] = extent;
+ ex[1] = '\0';
+ sprintf (buf, "bra%s %s", ex, n->bottom);
+ mri_assemble (buf);
+ free (buf);
+
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the MRI NEXT pseudo-op. */
+
+static void
+s_mri_next (extent)
+ int extent;
+{
+ struct mri_control_info *n;
+ char *buf;
+ char ex[2];
+
+ n = mri_control_stack;
+ while (n != NULL
+ && n->type != mri_for
+ && n->type != mri_repeat
+ && n->type != mri_while)
+ n = n->outer;
+ if (n == NULL)
+ {
+ as_bad (_("next outside of structured loop"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ buf = (char *) xmalloc (20 + strlen (n->next));
+ ex[0] = extent;
+ ex[1] = '\0';
+ sprintf (buf, "bra%s %s", ex, n->next);
+ mri_assemble (buf);
+ free (buf);
+
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the MRI FOR pseudo-op. */
+
+static void
+s_mri_for (qual)
+ int qual;
+{
+ const char *varstart, *varstop;
+ const char *initstart, *initstop;
+ const char *endstart, *endstop;
+ const char *bystart, *bystop;
+ int up;
+ int by;
+ int extent;
+ struct mri_control_info *n;
+ char *buf;
+ char *s;
+ char ex[2];
+
+ /* The syntax is
+ FOR.q var = init { TO | DOWNTO } end [ BY by ] DO.e
+ */
+
+ SKIP_WHITESPACE ();
+ varstart = input_line_pointer;
+
+ /* Look for the '='. */
+ while (! is_end_of_line[(unsigned char) *input_line_pointer]
+ && *input_line_pointer != '=')
+ ++input_line_pointer;
+ if (*input_line_pointer != '=')
+ {
+ as_bad (_("missing ="));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ varstop = input_line_pointer;
+ if (varstop > varstart
+ && (varstop[-1] == ' ' || varstop[-1] == '\t'))
+ --varstop;
+
+ ++input_line_pointer;
+
+ initstart = input_line_pointer;
+
+ /* Look for TO or DOWNTO. */
+ up = 1;
+ initstop = NULL;
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ if (strncasecmp (input_line_pointer, "TO", 2) == 0
+ && ! is_part_of_name (input_line_pointer[2]))
+ {
+ initstop = input_line_pointer;
+ input_line_pointer += 2;
+ break;
+ }
+ if (strncasecmp (input_line_pointer, "DOWNTO", 6) == 0
+ && ! is_part_of_name (input_line_pointer[6]))
+ {
+ initstop = input_line_pointer;
+ up = 0;
+ input_line_pointer += 6;
+ break;
+ }
+ ++input_line_pointer;
+ }
+ if (initstop == NULL)
+ {
+ as_bad (_("missing to or downto"));
+ ignore_rest_of_line ();
+ return;
+ }
+ if (initstop > initstart
+ && (initstop[-1] == ' ' || initstop[-1] == '\t'))
+ --initstop;
+
+ SKIP_WHITESPACE ();
+ endstart = input_line_pointer;
+
+ /* Look for BY or DO. */
+ by = 0;
+ endstop = NULL;
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ if (strncasecmp (input_line_pointer, "BY", 2) == 0
+ && ! is_part_of_name (input_line_pointer[2]))
+ {
+ endstop = input_line_pointer;
+ by = 1;
+ input_line_pointer += 2;
+ break;
+ }
+ if (strncasecmp (input_line_pointer, "DO", 2) == 0
+ && (input_line_pointer[2] == '.'
+ || ! is_part_of_name (input_line_pointer[2])))
+ {
+ endstop = input_line_pointer;
+ input_line_pointer += 2;
+ break;
+ }
+ ++input_line_pointer;
+ }
+ if (endstop == NULL)
+ {
+ as_bad (_("missing do"));
+ ignore_rest_of_line ();
+ return;
+ }
+ if (endstop > endstart
+ && (endstop[-1] == ' ' || endstop[-1] == '\t'))
+ --endstop;
+
+ if (! by)
+ {
+ bystart = "#1";
+ bystop = bystart + 2;
+ }
+ else
+ {
+ SKIP_WHITESPACE ();
+ bystart = input_line_pointer;
+
+ /* Look for DO. */
+ bystop = NULL;
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ if (strncasecmp (input_line_pointer, "DO", 2) == 0
+ && (input_line_pointer[2] == '.'
+ || ! is_part_of_name (input_line_pointer[2])))
+ {
+ bystop = input_line_pointer;
+ input_line_pointer += 2;
+ break;
+ }
+ ++input_line_pointer;
+ }
+ if (bystop == NULL)
+ {
+ as_bad (_("missing do"));
+ ignore_rest_of_line ();
+ return;
+ }
+ if (bystop > bystart
+ && (bystop[-1] == ' ' || bystop[-1] == '\t'))
+ --bystop;
+ }
+
+ if (*input_line_pointer != '.')
+ extent = '\0';
+ else
+ {
+ extent = input_line_pointer[1];
+ input_line_pointer += 2;
+ }
+
+ /* We have fully parsed the FOR operands. Now build the loop. */
+
+ n = push_mri_control (mri_for);
+
+ buf = (char *) xmalloc (50 + (input_line_pointer - varstart));
+
+ /* move init,var */
+ s = buf;
+ *s++ = 'm';
+ *s++ = 'o';
+ *s++ = 'v';
+ *s++ = 'e';
+ if (qual != '\0')
+ *s++ = qual;
+ *s++ = ' ';
+ memcpy (s, initstart, initstop - initstart);
+ s += initstop - initstart;
+ *s++ = ',';
+ memcpy (s, varstart, varstop - varstart);
+ s += varstop - varstart;
+ *s = '\0';
+ mri_assemble (buf);
+
+ colon (n->top);
+
+ /* cmp end,var */
+ s = buf;
+ *s++ = 'c';
+ *s++ = 'm';
+ *s++ = 'p';
+ if (qual != '\0')
+ *s++ = qual;
+ *s++ = ' ';
+ memcpy (s, endstart, endstop - endstart);
+ s += endstop - endstart;
+ *s++ = ',';
+ memcpy (s, varstart, varstop - varstart);
+ s += varstop - varstart;
+ *s = '\0';
+ mri_assemble (buf);
+
+ /* bcc bottom */
+ ex[0] = extent;
+ ex[1] = '\0';
+ if (up)
+ sprintf (buf, "blt%s %s", ex, n->bottom);
+ else
+ sprintf (buf, "bgt%s %s", ex, n->bottom);
+ mri_assemble (buf);
+
+ /* Put together the add or sub instruction used by ENDF. */
+ s = buf;
+ if (up)
+ strcpy (s, "add");
+ else
+ strcpy (s, "sub");
+ s += 3;
+ if (qual != '\0')
+ *s++ = qual;
+ *s++ = ' ';
+ memcpy (s, bystart, bystop - bystart);
+ s += bystop - bystart;
+ *s++ = ',';
+ memcpy (s, varstart, varstop - varstart);
+ s += varstop - varstart;
+ *s = '\0';
+ n->incr = buf;
+
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the MRI ENDF pseudo-op. */
+
+static void
+s_mri_endf (ignore)
+ int ignore;
+{
+ if (mri_control_stack == NULL
+ || mri_control_stack->type != mri_for)
+ {
+ as_bad (_("endf without for"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ colon (mri_control_stack->next);
+
+ mri_assemble (mri_control_stack->incr);
+
+ sprintf (mri_control_stack->incr, "bra %s", mri_control_stack->top);
+ mri_assemble (mri_control_stack->incr);
+
+ free (mri_control_stack->incr);
+
+ colon (mri_control_stack->bottom);
+
+ pop_mri_control ();
+
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the MRI REPEAT pseudo-op. */
+
+static void
+s_mri_repeat (ignore)
+ int ignore;
+{
+ struct mri_control_info *n;
+
+ n = push_mri_control (mri_repeat);
+ colon (n->top);
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the MRI UNTIL pseudo-op. */
+
+static void
+s_mri_until (qual)
+ int qual;
+{
+ char *s;
+
+ if (mri_control_stack == NULL
+ || mri_control_stack->type != mri_repeat)
+ {
+ as_bad (_("until without repeat"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ colon (mri_control_stack->next);
+
+ for (s = input_line_pointer; ! is_end_of_line[(unsigned char) *s]; s++)
+ ;
+
+ parse_mri_control_expression (s, qual, (const char *) NULL,
+ mri_control_stack->top, '\0');
+
+ colon (mri_control_stack->bottom);
+
+ input_line_pointer = s;
+
+ pop_mri_control ();
+
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the MRI WHILE pseudo-op. */
+
+static void
+s_mri_while (qual)
+ int qual;
+{
+ char *s;
+
+ struct mri_control_info *n;
+
+ s = input_line_pointer;
+ while (! is_end_of_line[(unsigned char) *s]
+ && (! flag_mri || *s != '*'))
+ s++;
+ --s;
+ while (*s == ' ' || *s == '\t')
+ --s;
+ if (s - input_line_pointer > 1
+ && s[-1] == '.')
+ s -= 2;
+ if (s - input_line_pointer < 2
+ || strncasecmp (s - 1, "DO", 2) != 0)
+ {
+ as_bad (_("missing do"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ n = push_mri_control (mri_while);
+
+ colon (n->next);
+
+ parse_mri_control_expression (s - 1, qual, (const char *) NULL, n->bottom,
+ s[1] == '.' ? s[2] : '\0');
+
+ input_line_pointer = s + 1;
+ if (*input_line_pointer == '.')
+ input_line_pointer += 2;
+
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the MRI ENDW pseudo-op. */
+
+static void
+s_mri_endw (ignore)
+ int ignore;
+{
+ char *buf;
+
+ if (mri_control_stack == NULL
+ || mri_control_stack->type != mri_while)
+ {
+ as_bad (_("endw without while"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ buf = (char *) xmalloc (20 + strlen (mri_control_stack->next));
+ sprintf (buf, "bra %s", mri_control_stack->next);
+ mri_assemble (buf);
+ free (buf);
+
+ colon (mri_control_stack->bottom);
+
+ pop_mri_control ();
+
+ if (flag_mri)
+ {
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/*
+ * md_parse_option
+ * Invocation line includes a switch not recognized by the base assembler.
+ * See if it's a processor-specific option. These are:
+ *
+ * -[A]m[c]68000, -[A]m[c]68008, -[A]m[c]68010, -[A]m[c]68020, -[A]m[c]68030, -[A]m[c]68040
+ * -[A]m[c]68881, -[A]m[c]68882, -[A]m[c]68851
+ * Select the architecture. Instructions or features not
+ * supported by the selected architecture cause fatal
+ * errors. More than one may be specified. The default is
+ * -m68020 -m68851 -m68881. Note that -m68008 is a synonym
+ * for -m68000, and -m68882 is a synonym for -m68881.
+ * -[A]m[c]no-68851, -[A]m[c]no-68881
+ * Don't accept 688?1 instructions. (The "c" is kind of silly,
+ * so don't use or document it, but that's the way the parsing
+ * works).
+ *
+ * -pic Indicates PIC.
+ * -k Indicates PIC. (Sun 3 only.)
+ *
+ * --bitwise-or
+ * Permit `|' to be used in expressions.
+ *
+ */
+
+#ifdef OBJ_ELF
+CONST char *md_shortopts = "lSA:m:kQ:V";
+#else
+CONST char *md_shortopts = "lSA:m:k";
+#endif
+
+struct option md_longopts[] = {
+#define OPTION_PIC (OPTION_MD_BASE)
+ {"pic", no_argument, NULL, OPTION_PIC},
+#define OPTION_REGISTER_PREFIX_OPTIONAL (OPTION_MD_BASE + 1)
+ {"register-prefix-optional", no_argument, NULL,
+ OPTION_REGISTER_PREFIX_OPTIONAL},
+#define OPTION_BITWISE_OR (OPTION_MD_BASE + 2)
+ {"bitwise-or", no_argument, NULL, OPTION_BITWISE_OR},
+#define OPTION_BASE_SIZE_DEFAULT_16 (OPTION_MD_BASE + 3)
+ {"base-size-default-16", no_argument, NULL, OPTION_BASE_SIZE_DEFAULT_16},
+#define OPTION_BASE_SIZE_DEFAULT_32 (OPTION_MD_BASE + 4)
+ {"base-size-default-32", no_argument, NULL, OPTION_BASE_SIZE_DEFAULT_32},
+#define OPTION_DISP_SIZE_DEFAULT_16 (OPTION_MD_BASE + 5)
+ {"disp-size-default-16", no_argument, NULL, OPTION_DISP_SIZE_DEFAULT_16},
+#define OPTION_DISP_SIZE_DEFAULT_32 (OPTION_MD_BASE + 6)
+ {"disp-size-default-32", no_argument, NULL, OPTION_DISP_SIZE_DEFAULT_32},
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof(md_longopts);
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ switch (c)
+ {
+ case 'l': /* -l means keep external to 2 bit offset
+ rather than 16 bit one */
+ flag_short_refs = 1;
+ break;
+
+ case 'S': /* -S means that jbsr's always turn into
+ jsr's. */
+ flag_long_jumps = 1;
+ break;
+
+ case 'A':
+ if (*arg == 'm')
+ arg++;
+ /* intentional fall-through */
+ case 'm':
+
+ if (arg[0] == 'n' && arg[1] == 'o' && arg[2] == '-')
+ {
+ int i;
+ unsigned long arch;
+ const char *oarg = arg;
+
+ arg += 3;
+ if (*arg == 'm')
+ {
+ arg++;
+ if (arg[0] == 'c' && arg[1] == '6')
+ arg++;
+ }
+ for (i = 0; i < n_archs; i++)
+ if (!strcmp (arg, archs[i].name))
+ break;
+ if (i == n_archs)
+ {
+ unknown:
+ as_bad (_("unrecognized option `%s'"), oarg);
+ return 0;
+ }
+ arch = archs[i].arch;
+ if (arch == m68881)
+ no_68881 = 1;
+ else if (arch == m68851)
+ no_68851 = 1;
+ else
+ goto unknown;
+ }
+ else
+ {
+ int i;
+
+ if (arg[0] == 'c' && arg[1] == '6')
+ arg++;
+
+ for (i = 0; i < n_archs; i++)
+ if (!strcmp (arg, archs[i].name))
+ {
+ unsigned long arch = archs[i].arch;
+ if (cpu_of_arch (arch))
+ /* It's a cpu spec. */
+ {
+ current_architecture &= ~m68000up;
+ current_architecture |= arch;
+ }
+ else if (arch == m68881)
+ {
+ current_architecture |= m68881;
+ no_68881 = 0;
+ }
+ else if (arch == m68851)
+ {
+ current_architecture |= m68851;
+ no_68851 = 0;
+ }
+ else
+ /* ??? */
+ abort ();
+ break;
+ }
+ if (i == n_archs)
+ {
+ as_bad (_("unrecognized architecture specification `%s'"), arg);
+ return 0;
+ }
+ }
+ break;
+
+ case OPTION_PIC:
+ case 'k':
+ flag_want_pic = 1;
+ break; /* -pic, Position Independent Code */
+
+ case OPTION_REGISTER_PREFIX_OPTIONAL:
+ flag_reg_prefix_optional = 1;
+ reg_prefix_optional_seen = 1;
+ break;
+
+ /* -V: SVR4 argument to print version ID. */
+ case 'V':
+ print_version_id ();
+ break;
+
+ /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section
+ should be emitted or not. FIXME: Not implemented. */
+ case 'Q':
+ break;
+
+ case OPTION_BITWISE_OR:
+ {
+ char *n, *t;
+ const char *s;
+
+ n = (char *) xmalloc (strlen (m68k_comment_chars) + 1);
+ t = n;
+ for (s = m68k_comment_chars; *s != '\0'; s++)
+ if (*s != '|')
+ *t++ = *s;
+ *t = '\0';
+ m68k_comment_chars = n;
+ }
+ break;
+
+ case OPTION_BASE_SIZE_DEFAULT_16:
+ m68k_index_width_default = SIZE_WORD;
+ break;
+
+ case OPTION_BASE_SIZE_DEFAULT_32:
+ m68k_index_width_default = SIZE_LONG;
+ break;
+
+ case OPTION_DISP_SIZE_DEFAULT_16:
+ m68k_rel32 = 0;
+ m68k_rel32_from_cmdline = 1;
+ break;
+
+ case OPTION_DISP_SIZE_DEFAULT_32:
+ m68k_rel32 = 1;
+ m68k_rel32_from_cmdline = 1;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+ fprintf(stream, _("\
+680X0 options:\n\
+-l use 1 word for refs to undefined symbols [default 2]\n\
+-m68000 | -m68008 | -m68010 | -m68020 | -m68030 | -m68040 | -m68060\n\
+ | -m68302 | -m68331 | -m68332 | -m68333 | -m68340 | -m68360\n\
+ | -mcpu32 | -m5200\n\
+ specify variant of 680X0 architecture [default 68020]\n\
+-m68881 | -m68882 | -mno-68881 | -mno-68882\n\
+ target has/lacks floating-point coprocessor\n\
+ [default yes for 68020, 68030, and cpu32]\n"));
+ fprintf(stream, _("\
+-m68851 | -mno-68851\n\
+ target has/lacks memory-management unit coprocessor\n\
+ [default yes for 68020 and up]\n\
+-pic, -k generate position independent code\n\
+-S turn jbsr into jsr\n\
+--register-prefix-optional\n\
+ recognize register names without prefix character\n\
+--bitwise-or do not treat `|' as a comment character\n"));
+ fprintf (stream, _("\
+--base-size-default-16 base reg without size is 16 bits\n\
+--base-size-default-32 base reg without size is 32 bits (default)\n\
+--disp-size-default-16 displacement with unknown size is 16 bits\n\
+--disp-size-default-32 displacement with unknown size is 32 bits (default)\n"));
+}
+
+#ifdef TEST2
+
+/* TEST2: Test md_assemble() */
+/* Warning, this routine probably doesn't work anymore */
+
+main ()
+{
+ struct m68k_it the_ins;
+ char buf[120];
+ char *cp;
+ int n;
+
+ m68k_ip_begin ();
+ for (;;)
+ {
+ if (!gets (buf) || !*buf)
+ break;
+ if (buf[0] == '|' || buf[1] == '.')
+ continue;
+ for (cp = buf; *cp; cp++)
+ if (*cp == '\t')
+ *cp = ' ';
+ if (is_label (buf))
+ continue;
+ memset (&the_ins, '\0', sizeof (the_ins));
+ m68k_ip (&the_ins, buf);
+ if (the_ins.error)
+ {
+ printf (_("Error %s in %s\n"), the_ins.error, buf);
+ }
+ else
+ {
+ printf (_("Opcode(%d.%s): "), the_ins.numo, the_ins.args);
+ for (n = 0; n < the_ins.numo; n++)
+ printf (" 0x%x", the_ins.opcode[n] & 0xffff);
+ printf (" ");
+ print_the_insn (&the_ins.opcode[0], stdout);
+ (void) putchar ('\n');
+ }
+ for (n = 0; n < strlen (the_ins.args) / 2; n++)
+ {
+ if (the_ins.operands[n].error)
+ {
+ printf ("op%d Error %s in %s\n", n, the_ins.operands[n].error, buf);
+ continue;
+ }
+ printf ("mode %d, reg %d, ", the_ins.operands[n].mode, the_ins.operands[n].reg);
+ if (the_ins.operands[n].b_const)
+ printf ("Constant: '%.*s', ", 1 + the_ins.operands[n].e_const - the_ins.operands[n].b_const, the_ins.operands[n].b_const);
+ printf ("ireg %d, isiz %d, imul %d, ", the_ins.operands[n].ireg, the_ins.operands[n].isiz, the_ins.operands[n].imul);
+ if (the_ins.operands[n].b_iadd)
+ printf ("Iadd: '%.*s',", 1 + the_ins.operands[n].e_iadd - the_ins.operands[n].b_iadd, the_ins.operands[n].b_iadd);
+ (void) putchar ('\n');
+ }
+ }
+ m68k_ip_end ();
+ return 0;
+}
+
+is_label (str)
+ char *str;
+{
+ while (*str == ' ')
+ str++;
+ while (*str && *str != ' ')
+ str++;
+ if (str[-1] == ':' || str[1] == '=')
+ return 1;
+ return 0;
+}
+
+#endif
+
+/* Possible states for relaxation:
+
+ 0 0 branch offset byte (bra, etc)
+ 0 1 word
+ 0 2 long
+
+ 1 0 indexed offsets byte a0@(32,d4:w:1) etc
+ 1 1 word
+ 1 2 long
+
+ 2 0 two-offset index word-word a0@(32,d4)@(45) etc
+ 2 1 word-long
+ 2 2 long-word
+ 2 3 long-long
+
+ */
+
+/* We have no need to default values of symbols. */
+
+/* ARGSUSED */
+symbolS *
+md_undefined_symbol (name)
+ char *name;
+{
+ return 0;
+}
+
+/* Round up a section size to the appropriate boundary. */
+valueT
+md_section_align (segment, size)
+ segT segment;
+ valueT size;
+{
+#ifdef OBJ_AOUT
+#ifdef BFD_ASSEMBLER
+ /* For a.out, force the section size to be aligned. If we don't do
+ this, BFD will align it for us, but it will not write out the
+ final bytes of the section. This may be a bug in BFD, but it is
+ easier to fix it here since that is how the other a.out targets
+ work. */
+ int align;
+
+ align = bfd_get_section_alignment (stdoutput, segment);
+ size = ((size + (1 << align) - 1) & ((valueT) -1 << align));
+#endif
+#endif
+
+ return size;
+}
+
+/* Exactly what point is a PC-relative offset relative TO?
+ On the 68k, it is relative to the address of the first extension
+ word. The difference between the addresses of the offset and the
+ first extension word is stored in fx_pcrel_adjust. */
+long
+md_pcrel_from (fixP)
+ fixS *fixP;
+{
+ int adjust;
+
+ /* Because fx_pcrel_adjust is a char, and may be unsigned, we store
+ -1 as 64. */
+ adjust = fixP->fx_pcrel_adjust;
+ if (adjust == 64)
+ adjust = -1;
+ return fixP->fx_where + fixP->fx_frag->fr_address - adjust;
+}
+
+#ifndef BFD_ASSEMBLER
+#ifdef OBJ_COFF
+
+/*ARGSUSED*/
+void
+tc_coff_symbol_emit_hook (ignore)
+ symbolS *ignore;
+{
+}
+
+int
+tc_coff_sizemachdep (frag)
+ fragS *frag;
+{
+ switch (frag->fr_subtype & 0x3)
+ {
+ case BYTE:
+ return 1;
+ case SHORT:
+ return 2;
+ case LONG:
+ return 4;
+ default:
+ abort ();
+ return 0;
+ }
+}
+
+#endif
+#endif
+
+/* end of tc-m68k.c */
diff --git a/gas/config/tc-m68k.h b/gas/config/tc-m68k.h
new file mode 100644
index 0000000000..bc8308abca
--- /dev/null
+++ b/gas/config/tc-m68k.h
@@ -0,0 +1,216 @@
+/* This file is tc-m68k.h
+ Copyright (C) 1987, 89, 90, 91, 92, 93, 94, 95, 96, 97, 1998
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#define TC_M68K 1
+
+#ifdef ANSI_PROTOTYPES
+struct symbol;
+struct fix;
+#endif
+
+#define TARGET_BYTES_BIG_ENDIAN 1
+
+#ifdef OBJ_AOUT
+#ifdef TE_SUN3
+#define TARGET_FORMAT "a.out-sunos-big"
+#endif
+#ifdef TE_NetBSD
+#define TARGET_FORMAT "a.out-m68k-netbsd"
+#endif
+#ifdef TE_LINUX
+#define TARGET_FORMAT "a.out-m68k-linux"
+#endif
+#ifndef TARGET_FORMAT
+#define TARGET_FORMAT "a.out-zero-big"
+#endif
+#endif
+
+#ifdef OBJ_ELF
+#define TARGET_FORMAT "elf32-m68k"
+#endif
+
+#ifdef TE_APOLLO
+#define COFF_MAGIC APOLLOM68KMAGIC
+#define COFF_AOUTHDR_MAGIC APOLLO_COFF_VERSION_NUMBER
+#undef OBJ_COFF_OMIT_OPTIONAL_HEADER
+#endif
+
+#ifdef TE_LYNX
+#define TARGET_FORMAT "coff-m68k-lynx"
+#endif
+#ifdef TE_AUX
+#define TARGET_FORMAT "coff-m68k-aux"
+#endif
+#ifdef TE_DELTA
+#define TARGET_FORMAT "coff-m68k-sysv"
+#endif
+
+#ifndef COFF_MAGIC
+#define COFF_MAGIC MC68MAGIC
+#endif
+#define BFD_ARCH bfd_arch_m68k /* for non-BFD_ASSEMBLER */
+#define TARGET_ARCH bfd_arch_m68k /* BFD_ASSEMBLER */
+#define COFF_FLAGS F_AR32W
+#define TC_COUNT_RELOC(x) ((x)->fx_addsy||(x)->fx_subsy)
+
+#define TC_COFF_FIX2RTYPE(fixP) tc_coff_fix2rtype(fixP)
+#define TC_COFF_SIZEMACHDEP(frag) tc_coff_sizemachdep(frag)
+extern int tc_coff_sizemachdep PARAMS ((struct frag *));
+#ifdef TE_SUN3
+/* This variable contains the value to write out at the beginning of
+ the a.out file. The 2<<16 means that this is a 68020 file instead
+ of an old-style 68000 file */
+
+#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (2<<16|OMAGIC); /* Magic byte for file header */
+#endif /* TE_SUN3 */
+
+#ifndef AOUT_MACHTYPE
+#define AOUT_MACHTYPE m68k_aout_machtype
+extern int m68k_aout_machtype;
+#endif
+
+#define tc_comment_chars m68k_comment_chars
+extern const char *m68k_comment_chars;
+
+#define tc_crawl_symbol_chain(a) {;} /* not used */
+#define tc_headers_hook(a) {;} /* not used */
+#define tc_aout_pre_write_hook(x) {;} /* not used */
+
+#define LISTING_WORD_SIZE 2 /* A word is 2 bytes */
+#define LISTING_LHS_WIDTH 2 /* One word on the first line */
+#define LISTING_LHS_WIDTH_SECOND 2 /* One word on the second line */
+#define LISTING_LHS_CONT_LINES 4/* And 4 lines max */
+#define LISTING_HEADER "68K GAS "
+
+#ifndef REGISTER_PREFIX
+#define REGISTER_PREFIX '%'
+#endif
+
+#if !defined (REGISTER_PREFIX_OPTIONAL)
+#if defined (M68KCOFF) || defined (OBJ_ELF)
+#ifndef BFD_ASSEMBLER
+#define LOCAL_LABEL(name) (name[0] == '.' \
+ && (name[1] == 'L' || name[1] == '.'))
+#endif /* ! BFD_ASSEMBLER */
+#define REGISTER_PREFIX_OPTIONAL 0
+#else /* ! (COFF || ELF) */
+#define REGISTER_PREFIX_OPTIONAL 1
+#endif /* ! (COFF || ELF) */
+#endif /* not def REGISTER_PREFIX and not def OPTIONAL_REGISTER_PREFIX */
+
+#ifdef TE_DELTA
+/* On the Delta, `%' can occur within a label name, but not as the
+ initial character. */
+#define LEX_PCT LEX_NAME
+/* On the Delta, `~' can start a label name, but is converted to '.'. */
+#define LEX_TILDE LEX_BEGIN_NAME
+#define tc_canonicalize_symbol_name(s) ((*(s) == '~' ? *(s) = '.' : '.'), s)
+/* On the Delta, dots are not required before pseudo-ops. */
+#define NO_PSEUDO_DOT
+#ifndef BFD_ASSEMBLER
+#undef LOCAL_LABEL
+#define LOCAL_LABEL(name) \
+ (name[0] == '.' || (name[0] == 'L' && name[1] == '%'))
+#endif
+#endif
+
+extern void m68k_mri_mode_change PARAMS ((int));
+#define MRI_MODE_CHANGE(i) m68k_mri_mode_change (i)
+
+extern int m68k_conditional_pseudoop PARAMS ((pseudo_typeS *));
+#define tc_conditional_pseudoop(pop) m68k_conditional_pseudoop (pop)
+
+extern void m68k_frob_label PARAMS ((struct symbol *));
+#define tc_frob_label(sym) m68k_frob_label (sym)
+
+extern void m68k_flush_pending_output PARAMS ((void));
+#define md_flush_pending_output() m68k_flush_pending_output ()
+
+extern void m68k_frob_symbol PARAMS ((struct symbol *));
+
+#ifdef BFD_ASSEMBLER
+
+#define tc_frob_symbol(sym,punt) \
+do \
+ { \
+ if (S_GET_SEGMENT (sym) == reg_section) \
+ punt = 1; \
+ m68k_frob_symbol (sym); \
+ } \
+while (0)
+
+#define NO_RELOC BFD_RELOC_NONE
+
+#ifdef OBJ_ELF
+
+/* This expression evaluates to false if the relocation is for a local object
+ for which we still want to do the relocation at runtime. True if we
+ are willing to perform this relocation while building the .o file. If
+ the reloc is against an externally visible symbol, then the assembler
+ should never do the relocation. */
+
+#define TC_RELOC_RTSYM_LOC_FIXUP(FIX) \
+ ((FIX)->fx_addsy == NULL \
+ || (! S_IS_EXTERNAL ((FIX)->fx_addsy) \
+ && ! S_IS_WEAK ((FIX)->fx_addsy) \
+ && S_IS_DEFINED ((FIX)->fx_addsy) \
+ && ! S_IS_COMMON ((FIX)->fx_addsy)))
+
+#define tc_fix_adjustable(X) tc_m68k_fix_adjustable(X)
+extern int tc_m68k_fix_adjustable PARAMS ((struct fix *));
+#endif
+
+#define TC_FORCE_RELOCATION(FIX) \
+ ((FIX)->fx_r_type == BFD_RELOC_VTABLE_INHERIT \
+ || (FIX)->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+
+#else /* ! BFD_ASSEMBLER */
+
+#define tc_frob_coff_symbol(sym) m68k_frob_symbol (sym)
+
+#define NO_RELOC 0
+
+#endif /* ! BFD_ASSEMBLER */
+
+#define DIFF_EXPR_OK
+
+extern void m68k_init_after_args PARAMS ((void));
+#define tc_init_after_args m68k_init_after_args
+
+extern int m68k_parse_long_option PARAMS ((char *));
+#define md_parse_long_option m68k_parse_long_option
+
+#define md_operand(x)
+
+#define TARGET_WORD_SIZE 32
+#define TARGET_ARCH bfd_arch_m68k
+
+extern struct relax_type md_relax_table[];
+#define TC_GENERIC_RELAX_TABLE md_relax_table
+
+/* Copied from write.c */
+/* This was formerly called M68K_AIM_KLUDGE. */
+#define md_prepare_relax_scan(fragP, address, aim, this_state, this_type) \
+ if (aim==0 && this_state== 4) { /* hard encoded from tc-m68k.c */ \
+ aim=this_type->rlx_forward+1; /* Force relaxation into word mode */ \
+ }
+
+/* end of tc-m68k.h */
diff --git a/gas/config/tc-m88k.c b/gas/config/tc-m88k.c
new file mode 100644
index 0000000000..931a496a54
--- /dev/null
+++ b/gas/config/tc-m88k.c
@@ -0,0 +1,1452 @@
+/* m88k.c -- Assembler for the Motorola 88000
+ Contributed by Devon Bowen of Buffalo University
+ and Torbjorn Granlund of the Swedish Institute of Computer Science.
+ Copyright (C) 1989, 90, 91, 92, 93, 94, 95, 96, 1997
+ Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GAS 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 more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#include <ctype.h>
+#include "as.h"
+#include "subsegs.h"
+#include "m88k-opcode.h"
+
+struct field_val_assoc
+{
+ char *name;
+ unsigned val;
+};
+
+struct field_val_assoc cr_regs[] =
+{
+ {"PID", 0},
+ {"PSR", 1},
+ {"EPSR", 2},
+ {"SSBR", 3},
+ {"SXIP", 4},
+ {"SNIP", 5},
+ {"SFIP", 6},
+ {"VBR", 7},
+ {"DMT0", 8},
+ {"DMD0", 9},
+ {"DMA0", 10},
+ {"DMT1", 11},
+ {"DMD1", 12},
+ {"DMA1", 13},
+ {"DMT2", 14},
+ {"DMD2", 15},
+ {"DMA2", 16},
+ {"SR0", 17},
+ {"SR1", 18},
+ {"SR2", 19},
+ {"SR3", 20},
+
+ {NULL, 0},
+};
+
+struct field_val_assoc fcr_regs[] =
+{
+ {"FPECR", 0},
+ {"FPHS1", 1},
+ {"FPLS1", 2},
+ {"FPHS2", 3},
+ {"FPLS2", 4},
+ {"FPPT", 5},
+ {"FPRH", 6},
+ {"FPRL", 7},
+ {"FPIT", 8},
+
+ {"FPSR", 62},
+ {"FPCR", 63},
+
+ {NULL, 0},
+};
+
+struct field_val_assoc cmpslot[] =
+{
+/* Integer Floating point */
+ {"nc", 0},
+ {"cp", 1},
+ {"eq", 2},
+ {"ne", 3},
+ {"gt", 4},
+ {"le", 5},
+ {"lt", 6},
+ {"ge", 7},
+ {"hi", 8}, {"ou", 8},
+ {"ls", 9}, {"ib", 9},
+ {"lo", 10}, {"in", 10},
+ {"hs", 11}, {"ob", 11},
+ {"be", 12}, {"ue", 12},
+ {"nb", 13}, {"lg", 13},
+ {"he", 14}, {"ug", 14},
+ {"nh", 15}, {"ule", 15},
+ {"ul", 16},
+ {"uge", 17},
+
+ {NULL, 0},
+};
+
+struct field_val_assoc cndmsk[] =
+{
+ {"gt0", 1},
+ {"eq0", 2},
+ {"ge0", 3},
+ {"lt0", 12},
+ {"ne0", 13},
+ {"le0", 14},
+
+ {NULL, 0},
+};
+
+struct m88k_insn
+{
+ unsigned long opcode;
+ expressionS exp;
+ enum reloc_type reloc;
+};
+
+static char *get_bf PARAMS ((char *param, unsigned *valp));
+static char *get_cmp PARAMS ((char *param, unsigned *valp));
+static char *get_cnd PARAMS ((char *param, unsigned *valp));
+static char *get_cr PARAMS ((char *param, unsigned *regnop));
+static char *get_fcr PARAMS ((char *param, unsigned *regnop));
+static char *get_imm16 PARAMS ((char *param, struct m88k_insn *insn));
+static char *get_o6 PARAMS ((char *param, unsigned *valp));
+static char *get_reg PARAMS ((char *param, unsigned *regnop, int reg_prefix));
+static char *get_vec9 PARAMS ((char *param, unsigned *valp));
+static char *getval PARAMS ((char *param, unsigned int *valp));
+
+static char *get_pcr PARAMS ((char *param, struct m88k_insn *insn,
+ enum reloc_type reloc));
+
+static int calcop PARAMS ((struct m88k_opcode *format,
+ char *param, struct m88k_insn *insn));
+
+
+extern char *myname;
+static struct hash_control *op_hash = NULL;
+
+/* These bits should be turned off in the first address of every segment */
+int md_seg_align = 7;
+
+/* These chars start a comment anywhere in a source file (except inside
+ another comment */
+const char comment_chars[] = ";";
+
+/* These chars only start a comment at the beginning of a line. */
+const char line_comment_chars[] = "#";
+
+const char line_separator_chars[] = "";
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* as in 0f123.456 */
+/* or 0H1.234E-12 (see exp chars above) */
+const char FLT_CHARS[] = "dDfF";
+
+extern void float_cons (), cons (), s_globl (), s_space (),
+ s_set (), s_lcomm ();
+
+const pseudo_typeS md_pseudo_table[] =
+{
+ {"align", s_align_bytes, 4},
+ {"def", s_set, 0},
+ {"dfloat", float_cons, 'd'},
+ {"ffloat", float_cons, 'f'},
+ {"global", s_globl, 0},
+ {"half", cons, 2},
+ {"bss", s_lcomm, 1},
+ {"string", stringer, 0},
+ {"word", cons, 4},
+ /* Force set to be treated as an instruction. */
+ {"set", NULL, 0},
+ {".set", s_set, 0},
+ {0}
+};
+
+void
+md_begin ()
+{
+ const char *retval = NULL;
+ unsigned int i = 0;
+
+ /* initialize hash table */
+
+ op_hash = hash_new ();
+
+ /* loop until you see the end of the list */
+
+ while (*m88k_opcodes[i].name)
+ {
+ char *name = m88k_opcodes[i].name;
+
+ /* hash each mnemonic and record its position */
+
+ retval = hash_insert (op_hash, name, &m88k_opcodes[i]);
+
+ if (retval != NULL)
+ as_fatal (_("Can't hash instruction '%s':%s"),
+ m88k_opcodes[i].name, retval);
+
+ /* skip to next unique mnemonic or end of list */
+
+ for (i++; !strcmp (m88k_opcodes[i].name, name); i++)
+ ;
+ }
+}
+
+CONST char *md_shortopts = "";
+struct option md_longopts[] = {
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof(md_longopts);
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ return 0;
+}
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+}
+
+void
+md_assemble (op)
+ char *op;
+{
+ char *param, *thisfrag;
+ char c;
+ struct m88k_opcode *format;
+ struct m88k_insn insn;
+
+ assert (op);
+
+ /* skip over instruction to find parameters */
+
+ for (param = op; *param != 0 && !isspace (*param); param++)
+ ;
+ c = *param;
+ *param++ = '\0';
+
+ /* try to find the instruction in the hash table */
+
+ if ((format = (struct m88k_opcode *) hash_find (op_hash, op)) == NULL)
+ {
+ as_bad (_("Invalid mnemonic '%s'"), op);
+ return;
+ }
+
+ /* try parsing this instruction into insn */
+
+ insn.exp.X_add_symbol = 0;
+ insn.exp.X_op_symbol = 0;
+ insn.exp.X_add_number = 0;
+ insn.exp.X_op = O_illegal;
+ insn.reloc = NO_RELOC;
+
+ while (!calcop (format, param, &insn))
+ {
+ /* if it doesn't parse try the next instruction */
+
+ if (!strcmp (format[0].name, format[1].name))
+ format++;
+ else
+ {
+ as_fatal (_("Parameter syntax error"));
+ return;
+ }
+ }
+
+ /* grow the current frag and plop in the opcode */
+
+ thisfrag = frag_more (4);
+ md_number_to_chars (thisfrag, insn.opcode, 4);
+
+ /* if this instruction requires labels mark it for later */
+
+ switch (insn.reloc)
+ {
+ case NO_RELOC:
+ break;
+
+ case RELOC_LO16:
+ case RELOC_HI16:
+ fix_new_exp (frag_now,
+ thisfrag - frag_now->fr_literal + 2,
+ 2,
+ &insn.exp,
+ 0,
+ insn.reloc);
+ break;
+
+ case RELOC_IW16:
+ fix_new_exp (frag_now,
+ thisfrag - frag_now->fr_literal,
+ 4,
+ &insn.exp,
+ 0,
+ insn.reloc);
+ break;
+
+ case RELOC_PC16:
+ fix_new_exp (frag_now,
+ thisfrag - frag_now->fr_literal + 2,
+ 2,
+ &insn.exp,
+ 1,
+ insn.reloc);
+ break;
+
+ case RELOC_PC26:
+ fix_new_exp (frag_now,
+ thisfrag - frag_now->fr_literal,
+ 4,
+ &insn.exp,
+ 1,
+ insn.reloc);
+ break;
+
+ default:
+ as_fatal (_("Unknown relocation type"));
+ break;
+ }
+}
+
+static int
+calcop (format, param, insn)
+ struct m88k_opcode *format;
+ char *param;
+ struct m88k_insn *insn;
+{
+ char *fmt = format->op_spec;
+ int f;
+ unsigned val;
+ unsigned opcode;
+ int reg_prefix = 'r';
+
+ insn->opcode = format->opcode;
+ opcode = 0;
+
+ for (;;)
+ {
+ if (param == 0)
+ return 0;
+ f = *fmt++;
+ switch (f)
+ {
+ case 0:
+ insn->opcode |= opcode;
+ return (*param == 0 || *param == '\n');
+
+ default:
+ if (f != *param++)
+ return 0;
+ break;
+
+ case 'd':
+ param = get_reg (param, &val, reg_prefix);
+ reg_prefix = 'r';
+ opcode |= val << 21;
+ break;
+
+ case 'o':
+ param = get_o6 (param, &val);
+ opcode |= ((val >> 2) << 7);
+ break;
+
+ case 'x':
+ reg_prefix = 'x';
+ break;
+
+ case '1':
+ param = get_reg (param, &val, reg_prefix);
+ reg_prefix = 'r';
+ opcode |= val << 16;
+ break;
+
+ case '2':
+ param = get_reg (param, &val, reg_prefix);
+ reg_prefix = 'r';
+ opcode |= val;
+ break;
+
+ case '3':
+ param = get_reg (param, &val, 'r');
+ opcode |= (val << 16) | val;
+ break;
+
+ case 'I':
+ param = get_imm16 (param, insn);
+ break;
+
+ case 'b':
+ param = get_bf (param, &val);
+ opcode |= val;
+ break;
+
+ case 'p':
+ param = get_pcr (param, insn, RELOC_PC16);
+ break;
+
+ case 'P':
+ param = get_pcr (param, insn, RELOC_PC26);
+ break;
+
+ case 'B':
+ param = get_cmp (param, &val);
+ opcode |= val;
+ break;
+
+ case 'M':
+ param = get_cnd (param, &val);
+ opcode |= val;
+ break;
+
+ case 'c':
+ param = get_cr (param, &val);
+ opcode |= val << 5;
+ break;
+
+ case 'f':
+ param = get_fcr (param, &val);
+ opcode |= val << 5;
+ break;
+
+ case 'V':
+ param = get_vec9 (param, &val);
+ opcode |= val;
+ break;
+
+ case '?':
+ /* Having this here repeats the warning somtimes.
+ But can't we stand that? */
+ as_warn (_("Use of obsolete instruction"));
+ break;
+ }
+ }
+}
+
+static char *
+match_name (param, assoc_tab, valp)
+ char *param;
+ struct field_val_assoc *assoc_tab;
+ unsigned *valp;
+{
+ int i;
+ char *name;
+ int name_len;
+
+ for (i = 0;; i++)
+ {
+ name = assoc_tab[i].name;
+ if (name == NULL)
+ return NULL;
+ name_len = strlen (name);
+ if (!strncmp (param, name, name_len))
+ {
+ *valp = assoc_tab[i].val;
+ return param + name_len;
+ }
+ }
+}
+
+static char *
+get_reg (param, regnop, reg_prefix)
+ char *param;
+ unsigned *regnop;
+ int reg_prefix;
+{
+ unsigned c;
+ unsigned regno;
+
+ c = *param++;
+ if (c == reg_prefix)
+ {
+ regno = *param++ - '0';
+ if (regno < 10)
+ {
+ if (regno == 0)
+ {
+ *regnop = 0;
+ return param;
+ }
+ c = *param - '0';
+ if (c < 10)
+ {
+ regno = regno * 10 + c;
+ if (c < 32)
+ {
+ *regnop = regno;
+ return param + 1;
+ }
+ }
+ else
+ {
+ *regnop = regno;
+ return param;
+ }
+ }
+ return NULL;
+ }
+ else if (c == 's' && param[0] == 'p')
+ {
+ *regnop = 31;
+ return param + 1;
+ }
+
+ return 0;
+}
+
+static char *
+get_imm16 (param, insn)
+ char *param;
+ struct m88k_insn *insn;
+{
+ enum reloc_type reloc = NO_RELOC;
+ unsigned int val;
+ char *save_ptr;
+
+ if (!strncmp (param, "hi16", 4) && !isalnum (param[4]))
+ {
+ reloc = RELOC_HI16;
+ param += 4;
+ }
+ else if (!strncmp (param, "lo16", 4) && !isalnum (param[4]))
+ {
+ reloc = RELOC_LO16;
+ param += 4;
+ }
+ else if (!strncmp (param, "iw16", 4) && !isalnum (param[4]))
+ {
+ reloc = RELOC_IW16;
+ param += 4;
+ }
+
+ save_ptr = input_line_pointer;
+ input_line_pointer = param;
+ expression (&insn->exp);
+ param = input_line_pointer;
+ input_line_pointer = save_ptr;
+
+ val = insn->exp.X_add_number;
+
+ if (insn->exp.X_op == O_constant)
+ {
+ /* Insert the value now, and reset reloc to NO_RELOC. */
+ if (reloc == NO_RELOC)
+ {
+ /* Warn about too big expressions if not surrounded by xx16. */
+ if (val > 0xffff)
+ as_warn (_("Expression truncated to 16 bits"));
+ }
+
+ if (reloc == RELOC_HI16)
+ val >>= 16;
+
+ insn->opcode |= val & 0xffff;
+ reloc = NO_RELOC;
+ }
+ else if (reloc == NO_RELOC)
+ /* We accept a symbol even without lo16, hi16, etc, and assume
+ lo16 was intended. */
+ reloc = RELOC_LO16;
+
+ insn->reloc = reloc;
+
+ return param;
+}
+
+static char *
+get_pcr (param, insn, reloc)
+ char *param;
+ struct m88k_insn *insn;
+ enum reloc_type reloc;
+{
+ char *saveptr, *saveparam;
+
+ saveptr = input_line_pointer;
+ input_line_pointer = param;
+
+ expression (&insn->exp);
+
+ saveparam = input_line_pointer;
+ input_line_pointer = saveptr;
+
+ /* Botch: We should relocate now if O_constant. */
+ insn->reloc = reloc;
+
+ return saveparam;
+}
+
+static char *
+get_cmp (param, valp)
+ char *param;
+ unsigned *valp;
+{
+ unsigned int val;
+ char *save_ptr;
+
+ save_ptr = param;
+
+ param = match_name (param, cmpslot, valp);
+ val = *valp;
+
+ if (param == NULL)
+ {
+ param = save_ptr;
+
+ save_ptr = input_line_pointer;
+ input_line_pointer = param;
+ val = get_absolute_expression ();
+ param = input_line_pointer;
+ input_line_pointer = save_ptr;
+
+ if (val >= 32)
+ {
+ as_warn (_("Expression truncated to 5 bits"));
+ val %= 32;
+ }
+ }
+
+ *valp = val << 21;
+ return param;
+}
+
+static char *
+get_cnd (param, valp)
+ char *param;
+ unsigned *valp;
+{
+ unsigned int val;
+
+ if (isdigit (*param))
+ {
+ param = getval (param, &val);
+
+ if (val >= 32)
+ {
+ as_warn (_("Expression truncated to 5 bits"));
+ val %= 32;
+ }
+ }
+ else
+ {
+ if (isupper (*param))
+ *param = tolower (*param);
+
+ if (isupper (param[1]))
+ param[1] = tolower (param[1]);
+
+ param = match_name (param, cndmsk, valp);
+
+ if (param == NULL)
+ return NULL;
+
+ val = *valp;
+ }
+
+ *valp = val << 21;
+ return param;
+}
+
+static char *
+get_bf2 (param, bc)
+ char *param;
+ int bc;
+{
+ int depth = 0;
+ int c;
+
+ for (;;)
+ {
+ c = *param;
+ if (c == 0)
+ return param;
+ else if (c == '(')
+ depth++;
+ else if (c == ')')
+ depth--;
+ else if (c == bc && depth <= 0)
+ return param;
+ param++;
+ }
+}
+
+static char *
+get_bf_offset_expression (param, offsetp)
+ char *param;
+ unsigned *offsetp;
+{
+ unsigned offset;
+
+ if (isalpha (param[0]))
+ {
+ if (isupper (param[0]))
+ param[0] = tolower (param[0]);
+ if (isupper (param[1]))
+ param[1] = tolower (param[1]);
+
+ param = match_name (param, cmpslot, offsetp);
+
+ return param;
+ }
+ else
+ {
+ input_line_pointer = param;
+ offset = get_absolute_expression ();
+ param = input_line_pointer;
+ }
+
+ *offsetp = offset;
+ return param;
+}
+
+static char *
+get_bf (param, valp)
+ char *param;
+ unsigned *valp;
+{
+ unsigned offset = 0;
+ unsigned width = 0;
+ char *xp;
+ char *save_ptr;
+
+ xp = get_bf2 (param, '<');
+
+ save_ptr = input_line_pointer;
+ input_line_pointer = param;
+ if (*xp == 0)
+ {
+ /* We did not find '<'. We have an offset (width implicitly 32). */
+ param = get_bf_offset_expression (param, &offset);
+ input_line_pointer = save_ptr;
+ if (param == NULL)
+ return NULL;
+ }
+ else
+ {
+ *xp++ = 0; /* Overwrite the '<' */
+ param = get_bf2 (xp, '>');
+ if (*param == 0)
+ return NULL;
+ *param++ = 0; /* Overwrite the '>' */
+
+ width = get_absolute_expression ();
+ xp = get_bf_offset_expression (xp, &offset);
+ input_line_pointer = save_ptr;
+
+ if (xp + 1 != param)
+ return NULL;
+ }
+
+ *valp = ((width % 32) << 5) | (offset % 32);
+
+ return param;
+}
+
+static char *
+get_cr (param, regnop)
+ char *param;
+ unsigned *regnop;
+{
+ unsigned regno;
+ unsigned c;
+
+ if (!strncmp (param, "cr", 2))
+ {
+ param += 2;
+
+ regno = *param++ - '0';
+ if (regno < 10)
+ {
+ if (regno == 0)
+ {
+ *regnop = 0;
+ return param;
+ }
+ c = *param - '0';
+ if (c < 10)
+ {
+ regno = regno * 10 + c;
+ if (c < 64)
+ {
+ *regnop = regno;
+ return param + 1;
+ }
+ }
+ else
+ {
+ *regnop = regno;
+ return param;
+ }
+ }
+ return NULL;
+ }
+
+ param = match_name (param, cr_regs, regnop);
+
+ return param;
+}
+
+static char *
+get_fcr (param, regnop)
+ char *param;
+ unsigned *regnop;
+{
+ unsigned regno;
+ unsigned c;
+
+ if (!strncmp (param, "fcr", 3))
+ {
+ param += 3;
+
+ regno = *param++ - '0';
+ if (regno < 10)
+ {
+ if (regno == 0)
+ {
+ *regnop = 0;
+ return param;
+ }
+ c = *param - '0';
+ if (c < 10)
+ {
+ regno = regno * 10 + c;
+ if (c < 64)
+ {
+ *regnop = regno;
+ return param + 1;
+ }
+ }
+ else
+ {
+ *regnop = regno;
+ return param;
+ }
+ }
+ return NULL;
+ }
+
+ param = match_name (param, fcr_regs, regnop);
+
+ return param;
+}
+
+static char *
+get_vec9 (param, valp)
+ char *param;
+ unsigned *valp;
+{
+ unsigned val;
+ char *save_ptr;
+
+ save_ptr = input_line_pointer;
+ input_line_pointer = param;
+ val = get_absolute_expression ();
+ param = input_line_pointer;
+ input_line_pointer = save_ptr;
+
+ if (val >= 1 << 9)
+ as_warn (_("Expression truncated to 9 bits"));
+
+ *valp = val % (1 << 9);
+
+ return param;
+}
+
+static char *
+get_o6 (param, valp)
+ char *param;
+ unsigned *valp;
+{
+ unsigned val;
+ char *save_ptr;
+
+ save_ptr = input_line_pointer;
+ input_line_pointer = param;
+ val = get_absolute_expression ();
+ param = input_line_pointer;
+ input_line_pointer = save_ptr;
+
+ if (val & 0x3)
+ as_warn (_("Removed lower 2 bits of expression"));
+
+ *valp = val;
+
+ return(param);
+}
+
+#define hexval(z) \
+ (isdigit (z) ? (z) - '0' : \
+ islower (z) ? (z) - 'a' + 10 : \
+ isupper (z) ? (z) - 'A' + 10 : -1)
+
+static char *
+getval (param, valp)
+ char *param;
+ unsigned int *valp;
+{
+ unsigned int val = 0;
+ unsigned int c;
+
+ c = *param++;
+ if (c == '0')
+ {
+ c = *param++;
+ if (c == 'x' || c == 'X')
+ {
+ c = *param++;
+ c = hexval (c);
+ while (c < 16)
+ {
+ val = val * 16 + c;
+ c = *param++;
+ c = hexval (c);
+ }
+ }
+ else
+ {
+ c -= '0';
+ while (c < 8)
+ {
+ val = val * 8 + c;
+ c = *param++ - '0';
+ }
+ }
+ }
+ else
+ {
+ c -= '0';
+ while (c < 10)
+ {
+ val = val * 10 + c;
+ c = *param++ - '0';
+ }
+ }
+
+ *valp = val;
+ return param - 1;
+}
+
+void
+md_number_to_chars (buf, val, nbytes)
+ char *buf;
+ valueT val;
+ int nbytes;
+{
+ number_to_chars_bigendian (buf, val, nbytes);
+}
+
+#if 0
+
+/* This routine is never called. What is it for?
+ Ian Taylor, Cygnus Support 13 Jul 1993 */
+
+void
+md_number_to_imm (buf, val, nbytes, fixP, seg_type)
+ unsigned char *buf;
+ unsigned int val;
+ int nbytes;
+ fixS *fixP;
+ int seg_type;
+{
+ if (seg_type != N_TEXT || fixP->fx_r_type == NO_RELOC)
+ {
+ switch (nbytes)
+ {
+ case 4:
+ *buf++ = val >> 24;
+ *buf++ = val >> 16;
+ case 2:
+ *buf++ = val >> 8;
+ case 1:
+ *buf = val;
+ break;
+
+ default:
+ abort ();
+ }
+ return;
+ }
+
+ switch (fixP->fx_r_type)
+ {
+ case RELOC_IW16:
+ buf[2] = val >> 8;
+ buf[3] = val;
+ break;
+
+ case RELOC_LO16:
+ buf[0] = val >> 8;
+ buf[1] = val;
+ break;
+
+ case RELOC_HI16:
+ buf[0] = val >> 24;
+ buf[1] = val >> 16;
+ break;
+
+ case RELOC_PC16:
+ val += 4;
+ buf[0] = val >> 10;
+ buf[1] = val >> 2;
+ break;
+
+ case RELOC_PC26:
+ val += 4;
+ buf[0] |= (val >> 26) & 0x03;
+ buf[1] = val >> 18;
+ buf[2] = val >> 10;
+ buf[3] = val >> 2;
+ break;
+
+ case RELOC_32:
+ buf[0] = val >> 24;
+ buf[1] = val >> 16;
+ buf[2] = val >> 8;
+ buf[3] = val;
+ break;
+
+ default:
+ as_fatal (_("Bad relocation type"));
+ break;
+ }
+}
+
+#endif /* 0 */
+
+void
+md_number_to_disp (buf, val, nbytes)
+ char *buf;
+ int val;
+ int nbytes;
+{
+ as_fatal (_("md_number_to_disp not defined"));
+ md_number_to_chars (buf, val, nbytes);
+}
+
+void
+md_number_to_field (buf, val, nbytes)
+ char *buf;
+ int val;
+ int nbytes;
+{
+ as_fatal (_("md_number_to_field not defined"));
+ md_number_to_chars (buf, val, nbytes);
+}
+
+#define MAX_LITTLENUMS 6
+
+/* Turn a string in input_line_pointer into a floating point constant of type
+ type, and store the appropriate bytes in *litP. The number of LITTLENUMS
+ emitted is stored in *sizeP . An error message is returned, or NULL on OK.
+ */
+char *
+md_atof (type, litP, sizeP)
+ char type;
+ char *litP;
+ int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ char *t;
+
+ switch (type)
+ {
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ prec = 4;
+ break;
+
+ case 'x':
+ case 'X':
+ prec = 6;
+ break;
+
+ case 'p':
+ case 'P':
+ prec = 6;
+ break;
+
+ default:
+ *sizeP = 0;
+ return _("Bad call to MD_ATOF()");
+ }
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+
+ *sizeP = prec * sizeof (LITTLENUM_TYPE);
+ for (wordP = words; prec--;)
+ {
+ md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+ return 0;
+}
+
+int md_short_jump_size = 4;
+
+void
+md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
+ char *ptr;
+ addressT from_addr, to_addr;
+ fragS *frag;
+ symbolS *to_symbol;
+{
+ ptr[0] = (char) 0xc0;
+ ptr[1] = 0x00;
+ ptr[2] = 0x00;
+ ptr[3] = 0x00;
+ fix_new (frag,
+ ptr - frag->fr_literal,
+ 4,
+ to_symbol,
+ (offsetT) 0,
+ 0,
+ RELOC_PC26); /* Botch: Shouldn't this be RELOC_PC16? */
+}
+
+int md_long_jump_size = 4;
+
+void
+md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
+ char *ptr;
+ addressT from_addr, to_addr;
+ fragS *frag;
+ symbolS *to_symbol;
+{
+ ptr[0] = (char) 0xc0;
+ ptr[1] = 0x00;
+ ptr[2] = 0x00;
+ ptr[3] = 0x00;
+ fix_new (frag,
+ ptr - frag->fr_literal,
+ 4,
+ to_symbol,
+ (offsetT) 0,
+ 0,
+ RELOC_PC26);
+}
+
+int
+md_estimate_size_before_relax (fragP, segment_type)
+ fragS *fragP;
+ segT segment_type;
+{
+ as_fatal (_("Relaxation should never occur"));
+ return (-1);
+}
+
+#if 0
+
+/* As far as I can tell, this routine is never called. What is it
+ doing here?
+ Ian Taylor, Cygnus Support 13 Jul 1993 */
+
+
+/*
+ * Risc relocations are completely different, so it needs
+ * this machine dependent routine to emit them.
+ */
+void
+emit_relocations (fixP, segment_address_in_file)
+ fixS *fixP;
+ relax_addressT segment_address_in_file;
+{
+ struct reloc_info_m88k ri;
+ symbolS *symbolP;
+ extern char *next_object_file_charP;
+
+ bzero ((char *) &ri, sizeof (ri));
+ for (; fixP; fixP = fixP->fx_next)
+ {
+ if (fixP->fx_r_type >= NO_RELOC)
+ {
+ fprintf (stderr, "fixP->fx_r_type = %d\n", fixP->fx_r_type);
+ abort ();
+ }
+
+ if ((symbolP = fixP->fx_addsy) != NULL)
+ {
+ ri.r_address = fixP->fx_frag->fr_address +
+ fixP->fx_where - segment_address_in_file;
+ if ((symbolP->sy_type & N_TYPE) == N_UNDF)
+ {
+ ri.r_extern = 1;
+ ri.r_symbolnum = symbolP->sy_number;
+ }
+ else
+ {
+ ri.r_extern = 0;
+ ri.r_symbolnum = symbolP->sy_type & N_TYPE;
+ }
+ if (symbolP && symbolP->sy_frag)
+ {
+ ri.r_addend = symbolP->sy_frag->fr_address;
+ }
+ ri.r_type = fixP->fx_r_type;
+ if (fixP->fx_pcrel)
+ {
+ ri.r_addend -= ri.r_address;
+ }
+ else
+ {
+ ri.r_addend = fixP->fx_addnumber;
+ }
+
+ append (&next_object_file_charP, (char *) &ri, sizeof (ri));
+ }
+ }
+}
+
+#endif /* 0 */
+
+#if 0
+
+/* This routine can be subsumed by s_lcomm in read.c.
+ Ian Taylor, Cygnus Support 13 Jul 1993 */
+
+
+static void
+s_bss ()
+{
+ char *name;
+ char c;
+ char *p;
+ int temp, bss_align;
+ symbolS *symbolP;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
+ {
+ as_warn (_("Expected comma after name"));
+ ignore_rest_of_line ();
+ return;
+ }
+ input_line_pointer++;
+ if ((temp = get_absolute_expression ()) < 0)
+ {
+ as_warn (_("BSS length (%d.) <0! Ignored."), temp);
+ ignore_rest_of_line ();
+ return;
+ }
+ *p = 0;
+ symbolP = symbol_find_or_make (name);
+ *p = c;
+ if (*input_line_pointer == ',')
+ {
+ input_line_pointer++;
+ bss_align = get_absolute_expression ();
+ }
+ else
+ bss_align = 0;
+
+ if (!S_IS_DEFINED(symbolP)
+ || S_GET_SEGMENT(symbolP) == SEG_BSS)
+ {
+ if (! need_pass_2)
+ {
+ char *p;
+ segT current_seg = now_seg;
+ subsegT current_subseg = now_subseg;
+
+ subseg_set (SEG_BSS, 1); /* switch to bss */
+
+ if (bss_align)
+ frag_align (bss_align, 0, 0);
+
+ /* detach from old frag */
+ if (symbolP->sy_type == N_BSS && symbolP->sy_frag != NULL)
+ symbolP->sy_frag->fr_symbol = NULL;
+
+ symbolP->sy_frag = frag_now;
+ p = frag_var (rs_org, 1, 1, (relax_substateT)0, symbolP,
+ (offsetT) temp, (char *)0);
+ *p = 0;
+ S_SET_SEGMENT (symbolP, SEG_BSS);
+
+ subseg_set (current_seg, current_subseg);
+ }
+ }
+ else
+ {
+ as_warn (_("Ignoring attempt to re-define symbol %s."), name);
+ }
+
+ while (!is_end_of_line[*input_line_pointer])
+ {
+ input_line_pointer++;
+ }
+}
+
+#endif /* 0 */
+
+#ifdef M88KCOFF
+
+/* These functions are needed if we are linking with obj-coffbfd.c.
+ That file may be replaced by a more BFD oriented version at some
+ point. If that happens, these functions should be rexamined.
+
+ Ian Lance Taylor, Cygnus Support, 13 July 1993. */
+
+/* Given a fixS structure (created by a call to fix_new, above),
+ return the BFD relocation type to use for it. */
+
+short
+tc_coff_fix2rtype (fixp)
+ fixS *fixp;
+{
+ switch (fixp->fx_r_type)
+ {
+ case RELOC_LO16:
+ return R_LVRT16;
+ case RELOC_HI16:
+ return R_HVRT16;
+ case RELOC_PC16:
+ return R_PCR16L;
+ case RELOC_PC26:
+ return R_PCR26L;
+ case RELOC_32:
+ return R_VRT32;
+ case RELOC_IW16:
+ return R_VRT16;
+ default:
+ abort ();
+ }
+}
+
+/* Apply a fixS to the object file. Since COFF does not use addends
+ in relocs, the addend is actually stored directly in the object
+ file itself. */
+
+void
+md_apply_fix (fixp, val)
+ fixS *fixp;
+ long val;
+{
+ char *buf;
+
+ buf = fixp->fx_frag->fr_literal + fixp->fx_where;
+ fixp->fx_offset = 0;
+
+ switch (fixp->fx_r_type)
+ {
+ case RELOC_IW16:
+ fixp->fx_offset = val >> 16;
+ buf[2] = val >> 8;
+ buf[3] = val;
+ break;
+
+ case RELOC_LO16:
+ fixp->fx_offset = val >> 16;
+ buf[0] = val >> 8;
+ buf[1] = val;
+ break;
+
+ case RELOC_HI16:
+ fixp->fx_offset = val >> 16;
+ buf[0] = val >> 8;
+ buf[1] = val;
+ break;
+
+ case RELOC_PC16:
+ buf[0] = val >> 10;
+ buf[1] = val >> 2;
+ break;
+
+ case RELOC_PC26:
+ buf[0] |= (val >> 26) & 0x03;
+ buf[1] = val >> 18;
+ buf[2] = val >> 10;
+ buf[3] = val >> 2;
+ break;
+
+ case RELOC_32:
+ buf[0] = val >> 24;
+ buf[1] = val >> 16;
+ buf[2] = val >> 8;
+ buf[3] = val;
+ break;
+
+ default:
+ abort ();
+ }
+}
+
+/* Where a PC relative offset is calculated from. On the m88k they
+ are calculated from just after the instruction. */
+
+long
+md_pcrel_from (fixp)
+ fixS *fixp;
+{
+ switch (fixp->fx_r_type)
+ {
+ case RELOC_PC16:
+ return fixp->fx_frag->fr_address + fixp->fx_where - 2;
+ case RELOC_PC26:
+ return fixp->fx_frag->fr_address + fixp->fx_where;
+ default:
+ abort ();
+ }
+ /*NOTREACHED*/
+}
+
+/* When we align the .init section, insert the correct NOP pattern. */
+
+int
+m88k_do_align (n, fill, max, len)
+ int n;
+ const char *fill;
+ int len;
+ int max;
+{
+ if (fill == NULL
+ && strcmp (obj_segment_name (now_seg), ".init") == 0)
+ {
+ static const unsigned char nop_pattern[] = { 0xf4, 0x00, 0x58, 0x00 };
+ frag_align_pattern (n, nop_pattern, sizeof (nop_pattern), max);
+ return 1;
+ }
+ return 0;
+}
+
+#endif /* M88KCOFF */
diff --git a/gas/config/tc-m88k.h b/gas/config/tc-m88k.h
new file mode 100644
index 0000000000..426b697280
--- /dev/null
+++ b/gas/config/tc-m88k.h
@@ -0,0 +1,108 @@
+/* m88k.h -- Assembler for the Motorola 88000
+ Contributed by Devon Bowen of Buffalo University
+ and Torbjorn Granlund of the Swedish Institute of Computer Science.
+ Copyright (C) 1989, 90, 91, 92, 93, 94, 95, 96, 1997
+ Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GAS 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 more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#define TC_M88K
+
+#define TARGET_BYTES_BIG_ENDIAN 1
+
+#ifdef M88KCOFF
+#define COFF_MAGIC MC88OMAGIC
+#define BFD_ARCH bfd_arch_m88k
+#define COFF_FLAGS F_AR32W
+#endif
+
+#define NEED_FX_R_TYPE
+#define TC_KEEP_FX_OFFSET
+#define TC_CONS_RELOC RELOC_32
+
+/* different type of relocation available in the m88k */
+
+enum reloc_type
+{
+ RELOC_LO16, /* lo16(sym) */
+ RELOC_HI16, /* hi16(sym) */
+ RELOC_PC16, /* bb0, bb1, bcnd */
+ RELOC_PC26, /* br, bsr */
+ RELOC_32, /* jump tables, etc */
+ RELOC_IW16, /* global access through linker regs 28 */
+ NO_RELOC
+};
+
+struct reloc_info_m88k
+{
+ unsigned long int r_address;
+ unsigned int r_symbolnum:24;
+ unsigned int r_extern:1;
+ unsigned int r_pad:3;
+ enum reloc_type r_type:4;
+ long int r_addend;
+};
+
+#define relocation_info reloc_info_m88k
+
+/* The m88k uses '@' to start local labels. */
+#define LEX_AT (LEX_BEGIN_NAME | LEX_NAME)
+
+#ifndef BFD_ASSEMBLER
+#define LOCAL_LABEL(name) \
+ ((name[0] =='@' && (name [1] == 'L' || name [1] == '.')) \
+ || (name[0] == 'L' && name[1] == '0' && name[2] == '\001'))
+#endif
+
+/* The m88k uses pseudo-ops with no leading period. */
+#define NO_PSEUDO_DOT
+
+/* Don't warn on word overflow; it happens on %hi relocs. */
+#undef WARN_SIGNED_OVERFLOW_WORD
+
+#define md_convert_frag(b,s,f) {as_fatal (_("m88k convert_frag\n"));}
+
+/* We don't need to do anything special for undefined symbols. */
+#define md_undefined_symbol(s) 0
+
+/* We have no special operand handling. */
+#define md_operand(e)
+
+#ifdef M88KCOFF
+
+/* Whether a reloc should be output. */
+#define TC_COUNT_RELOC(fixp) ((fixp)->fx_addsy != NULL)
+
+/* Get the BFD reloc type to use for a gas fixS structure. */
+#define TC_COFF_FIX2RTYPE(fixp) tc_coff_fix2rtype (fixp)
+
+/* No special hook needed for symbols. */
+#define tc_coff_symbol_emit_hook(s)
+
+/* Align sections to a four byte boundary. */
+#ifndef max
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+#define SUB_SEGMENT_ALIGN(SEG) max (section_alignment[(int) (SEG)], 4)
+
+/* We use a special alignment function to insert the correct nop
+ pattern in .init. */
+extern int m88k_do_align PARAMS ((int, const char *, int, int));
+#define md_do_align(n,fill,len,max,l) if (m88k_do_align(n,fill,max,len)) goto l
+
+#endif /* M88KCOFF */
diff --git a/gas/config/tc-mcore.c b/gas/config/tc-mcore.c
new file mode 100644
index 0000000000..7e784354ea
--- /dev/null
+++ b/gas/config/tc-mcore.c
@@ -0,0 +1,2183 @@
+/* tc-mcore.c -- Assemble code for M*Core
+
+ Copyright (C) 1993,1994, 1999 Free Software Foundation.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "as.h"
+#include "bfd.h"
+#include "subsegs.h"
+#define DEFINE_TABLE
+#include "../opcodes/mcore-opc.h"
+#include <ctype.h>
+#include <string.h>
+
+#ifdef OBJ_ELF
+#include "elf/mcore.h"
+#endif
+
+#ifndef streq
+#define streq(a,b) (strcmp (a, b) == 0)
+#endif
+
+/* Forward declarations for dumb compilers. */
+static void mcore_s_literals PARAMS ((int));
+static void mcore_cons PARAMS ((int));
+static void mcore_float_cons PARAMS ((int));
+static void mcore_stringer PARAMS ((int));
+static int log2 PARAMS ((unsigned int));
+static char * parse_reg PARAMS ((char *, unsigned *));
+static char * parse_creg PARAMS ((char *, unsigned *));
+static char * parse_exp PARAMS ((char *, expressionS *));
+static void make_name PARAMS ((char *, char *, int));
+static int enter_literal PARAMS ((expressionS *, int));
+static char * parse_rt PARAMS ((char *, char **, int, expressionS *));
+static char * parse_imm PARAMS ((char *, unsigned *, unsigned, unsigned));
+static char * parse_mem PARAMS ((char *, unsigned *, unsigned *, unsigned));
+static void dump_literals PARAMS ((int));
+static void check_literals PARAMS ((int, int));
+static void mcore_s_text PARAMS ((int));
+static void mcore_s_data PARAMS ((int));
+#ifdef OBJ_ELF
+static void mcore_s_section PARAMS ((int));
+#endif
+
+/* Several places in this file insert raw instructions into the
+ object. They should use MCORE_INST_XXX macros to get the opcodes
+ and then use these two macros to crack the MCORE_INST value into
+ the appropriate byte values. */
+#define INST_BYTE0(x) (((x) >> 8) & 0xFF)
+#define INST_BYTE1(x) ((x) & 0xFF)
+
+const char comment_chars[] = "#/";
+const char line_separator_chars[] = ";";
+const char line_comment_chars[] = "#/";
+
+const int md_reloc_size = 8;
+
+static int relax; /* set if -relax seen */
+static int do_jsri2bsr = 0; /* change here from 1 by Cruess 19 August 97 */
+static int sifilter_mode = 0;
+
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* As in 0f12.456 */
+/* or 0d1.2345e12 */
+const char FLT_CHARS[] = "rRsSfFdDxXpP";
+
+#define C(what,length) (((what) << 2) + (length))
+#define GET_WHAT(x) ((x >> 2))
+
+/* These are the two types of relaxable instruction */
+#define COND_JUMP 1
+#define UNCD_JUMP 2
+
+#define UNDEF_DISP 0
+#define COND12 1
+#define COND32 2
+#define UNCD12 1
+#define UNCD32 2
+#define UNDEF_WORD_DISP 4
+#define END 5
+
+#define C12_LEN 2
+#define C32_LEN 10 /* allow for align */
+#define U12_LEN 2
+#define U32_LEN 8 /* allow for align */
+
+
+/* Initialize the relax table */
+const relax_typeS md_relax_table[] =
+{
+{ 1, 1, 0, 0 }, /* 0: unused */
+{ 1, 1, 0, 0 }, /* 1: unused */
+{ 1, 1, 0, 0 }, /* 2: unused */
+{ 1, 1, 0, 0 }, /* 3: unused */
+{ 1, 1, 0, 0 }, /* 4: unused */
+{ 2048, -2046, C12_LEN, C(COND_JUMP, COND32) }, /* 5: C(COND_JUMP, COND12) */
+{ 0, 0, C32_LEN, 0 }, /* 6: C(COND_JUMP, COND32) */
+{ 1, 1, 0, 0 }, /* 7: unused */
+{ 1, 1, 0, 0 }, /* 8: unused */
+{ 2048, -2046, U12_LEN, C(UNCD_JUMP, UNCD32) }, /* 9: C(UNCD_JUMP, UNCD12) */
+{ 0, 0, U32_LEN, 0 }, /*10: C(UNCD_JUMP, UNCD32) */
+{ 1, 1, 0, 0 }, /*11: unused */
+{ 0, 0, 0, 0 } /*12: unused */
+};
+
+/* LITERAL POOL DATA STRUCTURES */
+struct literal
+{
+ unsigned short refcnt;
+ unsigned char ispcrel;
+ unsigned char unused;
+ expressionS e;
+};
+
+#define MAX_POOL_SIZE (1024/4)
+static struct literal litpool [MAX_POOL_SIZE];
+static unsigned poolsize;
+static unsigned poolnumber;
+static unsigned long poolspan;
+
+/* SPANPANIC: the point at which we get too scared and force a dump
+ of the literal pool, and perhaps put a branch in place.
+ Calculated as:
+ 1024 span of lrw/jmpi/jsri insn (actually span+1)
+ -2 possible alignment at the insn.
+ -2 possible alignment to get the table aligned.
+ -2 an inserted branch around the table.
+ == 1018
+ at 1018, we might be in trouble.
+ -- so we have to be smaller than 1018 and since we deal with 2-byte
+ instructions, the next good choice is 1016.
+ -- Note we have a test case that fails when we've got 1018 here. */
+#define SPANPANIC (1016) /* 1024 - 1 entry - 2 byte rounding */
+#define SPANCLOSE (900)
+#define SPANEXIT (600)
+static symbolS * poolsym; /* label for current pool */
+static char poolname[8];
+static struct hash_control * opcode_hash_control; /* Opcode mnemonics */
+
+/* This table describes all the machine specific pseudo-ops the assembler
+ has to support. The fields are:
+ Pseudo-op name without dot
+ Function to call to execute this pseudo-op
+ Integer arg to pass to the function */
+const pseudo_typeS md_pseudo_table[] =
+{
+ { "export", s_globl, 0 },
+ { "import", s_ignore, 0 },
+ { "literals", mcore_s_literals, 0 },
+ { "page", listing_eject, 0 },
+ { "bss", s_lcomm_bytes, 1 },
+
+ /* The following are to intercept the placement of data into the text
+ section (eg addresses for a switch table), so that the space they
+ occupy can be taken into account when deciding whether or not to
+ dump the current literal pool.
+ XXX - currently we do not cope with the .space and .dcb.d directives. */
+ { "ascii", mcore_stringer, 0 },
+ { "asciz", mcore_stringer, 1 },
+ { "byte", mcore_cons, 1 },
+ { "dc", mcore_cons, 2 },
+ { "dc.b", mcore_cons, 1 },
+ { "dc.d", mcore_float_cons, 'd' },
+ { "dc.l", mcore_cons, 4 },
+ { "dc.s", mcore_float_cons, 'f' },
+ { "dc.w", mcore_cons, 2 },
+ { "dc.x", mcore_float_cons, 'x' },
+ { "double", mcore_float_cons, 'd'},
+ { "float", mcore_float_cons, 'f'},
+ { "hword", mcore_cons, 2 },
+ { "int", mcore_cons, 4 },
+ { "long", mcore_cons, 4 },
+ { "octa", mcore_cons, 16 },
+ { "quad", mcore_cons, 8 },
+ { "short", mcore_cons, 2 },
+ { "single", mcore_float_cons, 'f'},
+ { "string", mcore_stringer, 1 },
+ { "word", mcore_cons, 2 },
+
+ /* Allow for the effect of section changes. */
+ { "text", mcore_s_text, 0 },
+ { "data", mcore_s_data, 0 },
+
+#ifdef OBJ_ELF
+ { "section", mcore_s_section, 0 },
+ { "section.s", mcore_s_section, 0 },
+ { "sect", mcore_s_section, 0 },
+ { "sect.s", mcore_s_section, 0 },
+#endif
+ { 0, 0, 0 }
+};
+
+static void
+mcore_s_literals (ignore)
+ int ignore;
+{
+ dump_literals (0);
+ demand_empty_rest_of_line ();
+}
+
+
+static void
+mcore_cons (nbytes)
+ int nbytes;
+{
+ if (now_seg == text_section)
+ {
+ char * ptr = input_line_pointer;
+ int commas = 1;
+
+ /* Count the number of commas on the line. */
+ while (! is_end_of_line [* ptr])
+ commas += * ptr ++ == ',';
+
+ poolspan += nbytes * commas;
+ }
+
+ cons (nbytes);
+
+ /* In theory we ought to call check_literals (2,0) here in case
+ we need to dump the literal table. We cannot do this however,
+ as the directives that we are intercepting may be being used
+ to build a switch table, and we must not interfere with its
+ contents. Instead we cross our fingers and pray... */
+}
+
+static void
+mcore_float_cons (float_type)
+ int float_type;
+{
+ if (now_seg == text_section)
+ {
+ char * ptr = input_line_pointer;
+ int commas = 1;
+
+#ifdef REPEAT_CONS_EXPRESSIONS
+#error REPEAT_CONS_EXPRESSIONS not handled
+#endif
+
+ /* Count the number of commas on the line. */
+ while (! is_end_of_line [* ptr])
+ commas += * ptr ++ == ',';
+
+ /* We would like to compute "hex_float (float_type) * commas"
+ but hex_float is not exported from read.c */
+ float_type == 'f' ? 4 : (float_type == 'd' ? 8 : 12);
+ poolspan += float_type * commas;
+ }
+
+ float_cons (float_type);
+
+ /* See the comment in mcore_cons () about calling check_literals.
+ It is unlikely that a switch table will be constructed using
+ floating point values, but it is still likely that an indexed
+ table of floating point constants is being created by these
+ directives, so again we must not interfere with their placement. */
+}
+
+static void
+mcore_stringer (append_zero)
+ int append_zero;
+{
+ if (now_seg == text_section)
+ {
+ char * ptr = input_line_pointer;
+
+ /* In theory we should compute how many bytes are going to
+ be occupied by the string(s) and add this to the poolspan.
+ To keep things simple however, we just add the number of
+ bytes left on the current line. This will be an over-
+ estimate, which is OK, and automatically allows for the
+ appending a zero byte, since the real string(s) is/are
+ required to be enclosed in double quotes. */
+ while (! is_end_of_line [* ptr])
+ ptr ++;
+
+ poolspan += ptr - input_line_pointer;
+ }
+
+ stringer (append_zero);
+
+ /* We call check_literals here in case a large number of strings are
+ being placed into the text section with a sequence of stringer
+ directives. In theory we could be upsetting something if these
+ strings are actually in an indexed table instead of referenced by
+ individual labels. Let us hope that that never happens. */
+ check_literals (2, 0);
+}
+
+static void
+mcore_s_text (ignore)
+ int ignore;
+{
+ dump_literals (0);
+
+ s_text (ignore);
+}
+
+static void
+mcore_s_data (ignore)
+ int ignore;
+{
+ dump_literals (0);
+
+ s_data (ignore);
+}
+
+/* This function is called once, at assembler startup time. This should
+ set up all the tables, etc that the MD part of the assembler needs. */
+void
+md_begin ()
+{
+ mcore_opcode_info * opcode;
+ char * prev_name = "";
+
+ opcode_hash_control = hash_new ();
+
+ /* Insert unique names into hash table */
+ for (opcode = mcore_table; opcode->name; opcode ++)
+ {
+ if (streq (prev_name, opcode->name))
+ {
+ /* Make all the opcodes with the same name point to the same
+ string. */
+ opcode->name = prev_name;
+ }
+ else
+ {
+ prev_name = opcode->name;
+ hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
+ }
+ }
+}
+
+static int reg_m;
+static int reg_n;
+static expressionS immediate; /* absolute expression */
+
+/* Get a log2(val). */
+static int
+log2 (val)
+ unsigned int val;
+{
+ int log = -1;
+ while (val != 0)
+ {
+ log ++;
+ val >>= 1;
+ }
+
+ return log;
+}
+
+/* Try to parse a reg name. */
+static char *
+parse_reg (s, reg)
+ char * s;
+ unsigned * reg;
+{
+ /* Strip leading whitespace. */
+ while (isspace (* s))
+ ++ s;
+
+ if (tolower (s[0]) == 'r')
+ {
+ if (s[1] == '1' && s[2] >= '0' && s[2] <= '5')
+ {
+ *reg = 10 + s[2] - '0';
+ return s + 3;
+ }
+
+ if (s[1] >= '0' && s[1] <= '9')
+ {
+ *reg = s[1] - '0';
+ return s + 2;
+ }
+ }
+ else if ( tolower (s[0]) == 's'
+ && tolower (s[1]) == 'p'
+ && (isspace (s[2]) || s[2] == ','))
+ {
+ * reg = 0;
+ return s + 2;
+ }
+
+ as_bad (_("register expected, but saw '%.6s'"), s);
+ return s;
+}
+
+static struct Cregs
+{
+ char * name;
+ unsigned int crnum;
+}
+cregs[] =
+{
+ { "psr", 0},
+ { "vbr", 1},
+ { "epsr", 2},
+ { "fpsr", 3},
+ { "epc", 4},
+ { "fpc", 5},
+ { "ss0", 6},
+ { "ss1", 7},
+ { "ss2", 8},
+ { "ss3", 9},
+ { "ss4", 10},
+ { "gcr", 11},
+ { "gsr", 12},
+ { "", 0}
+};
+
+static char *
+parse_creg (s, reg)
+ char * s;
+ unsigned * reg;
+{
+ int i;
+
+ /* Strip leading whitespace. */
+ while (isspace (* s))
+ ++s;
+
+ if ((tolower (s[0]) == 'c' && tolower (s[1]) == 'r'))
+ {
+ if (s[2] == '3' && s[3] >= '0' && s[3] <= '1')
+ {
+ *reg = 30 + s[3] - '0';
+ return s + 4;
+ }
+
+ if (s[2] == '2' && s[3] >= '0' && s[3] <= '9')
+ {
+ *reg = 20 + s[3] - '0';
+ return s + 4;
+ }
+
+ if (s[2] == '1' && s[3] >= '0' && s[3] <= '9')
+ {
+ *reg = 10 + s[3] - '0';
+ return s + 4;
+ }
+
+ if (s[2] >= '0' && s[2] <= '9')
+ {
+ *reg = s[2] - '0';
+ return s + 3;
+ }
+ }
+
+ /* Look at alternate creg names before giving error. */
+ for (i = 0; cregs[i].name[0] != '\0'; i++)
+ {
+ char buf [10];
+ int length;
+ int j;
+
+ length = strlen (cregs[i].name);
+
+ for (j = 0; j < length; j++)
+ buf[j] = tolower (s[j]);
+
+ if (strncmp (cregs[i].name, buf, length) == 0)
+ {
+ *reg = cregs[i].crnum;
+ return s + length;
+ }
+ }
+
+ as_bad (_("control register expected, but saw '%.6s'"), s);
+
+ return s;
+}
+
+static char *
+parse_exp (s, e)
+ char * s;
+ expressionS * e;
+{
+ char * save;
+ char * new;
+
+ /* Skip whitespace. */
+ while (isspace (* s))
+ ++ s;
+
+ save = input_line_pointer;
+ input_line_pointer = s;
+
+ expression (e);
+
+ if (e->X_op == O_absent)
+ as_bad (_("missing operand"));
+
+ new = input_line_pointer;
+ input_line_pointer = save;
+
+ return new;
+}
+
+static void
+make_name (s, p, n)
+ char * s;
+ char * p;
+ int n;
+{
+ static const char hex[] = "0123456789ABCDEF";
+
+ s[0] = p[0];
+ s[1] = p[1];
+ s[2] = p[2];
+ s[3] = hex[(n >> 12) & 0xF];
+ s[4] = hex[(n >> 8) & 0xF];
+ s[5] = hex[(n >> 4) & 0xF];
+ s[6] = hex[(n) & 0xF];
+ s[7] = 0;
+}
+
+static void
+dump_literals (isforce)
+ int isforce;
+{
+ int i;
+ struct literal * p;
+ struct symbol * brarsym;
+
+ if (poolsize == 0)
+ return;
+
+ /* Must we branch around the literal table? */
+ if (isforce)
+ {
+ char * output;
+ char brarname[8];
+
+ make_name (brarname, ".YP.", poolnumber);
+
+ brarsym = symbol_make (brarname);
+
+ symbol_table_insert (brarsym);
+
+ output = frag_var (rs_machine_dependent,
+ md_relax_table[C (UNCD_JUMP, UNCD32)].rlx_length,
+ md_relax_table[C (UNCD_JUMP, UNCD12)].rlx_length,
+ C (UNCD_JUMP, 0), brarsym, 0, 0);
+ output[0] = INST_BYTE0 (MCORE_INST_BR); /* br .+xxx */
+ output[1] = INST_BYTE1 (MCORE_INST_BR);
+ }
+
+ /* Make sure that the section is sufficiently aligned and that
+ the literal table is aligned within it. */
+ record_alignment (now_seg, 2);
+ frag_align (2, 0, 0);
+
+ colon (S_GET_NAME (poolsym));
+
+ for (i = 0, p = litpool; i < poolsize; i++, p++)
+ emit_expr (& p->e, 4);
+
+ if (isforce)
+ colon (S_GET_NAME (brarsym));
+
+ poolsize = 0;
+}
+
+static void
+check_literals (kind, offset)
+ int kind;
+ int offset;
+{
+ poolspan += offset;
+
+ /* SPANCLOSE and SPANEXIT are smaller numbers than SPANPANIC.
+ SPANPANIC means that we must dump now.
+ kind == 0 is any old instruction.
+ kind > 0 means we just had a control transfer instruction.
+ kind == 1 means within a function
+ kind == 2 means we just left a function
+
+ The dump_literals (1) call inserts a branch around the table, so
+ we first look to see if its a situation where we won't have to
+ insert a branch (e.g., the previous instruction was an unconditional
+ branch).
+
+ SPANPANIC is the point where we must dump a single-entry pool.
+ it accounts for alignments and an inserted branch.
+ the 'poolsize*2' accounts for the scenario where we do:
+ lrw r1,lit1; lrw r2,lit2; lrw r3,lit3
+ Note that the 'lit2' reference is 2 bytes further along
+ but the literal it references will be 4 bytes further along,
+ so we must consider the poolsize into this equation.
+ This is slightly over-cautious, but guarantees that we won't
+ panic because a relocation is too distant. */
+
+ if (poolspan > SPANCLOSE && kind > 0)
+ dump_literals (0);
+ else if (poolspan > SPANEXIT && kind > 1)
+ dump_literals (0);
+ else if (poolspan >= (SPANPANIC - poolsize * 2))
+ dump_literals (1);
+}
+
+static int
+enter_literal (e, ispcrel)
+ expressionS * e;
+ int ispcrel;
+{
+ int i;
+ struct literal * p;
+
+ if (poolsize >= MAX_POOL_SIZE - 2)
+ {
+ /* The literal pool is as full as we can handle. We have
+ to be 2 entries shy of the 1024/4=256 entries because we
+ have to allow for the branch (2 bytes) and the alignment
+ (2 bytes before the first insn referencing the pool and
+ 2 bytes before the pool itself) == 6 bytes, rounds up
+ to 2 entries. */
+ dump_literals (1);
+ }
+
+ if (poolsize == 0)
+ {
+ /* Create new literal pool. */
+ if (++ poolnumber > 0xFFFF)
+ as_fatal (_("more than 65K literal pools"));
+
+ make_name (poolname, ".XP.", poolnumber);
+ poolsym = symbol_make (poolname);
+ symbol_table_insert (poolsym);
+ poolspan = 0;
+ }
+
+ /* Search pool for value so we don't have duplicates. */
+ for (p = litpool, i = 0; i < poolsize; i++, p++)
+ {
+ if (e->X_op == p->e.X_op
+ && e->X_add_symbol == p->e.X_add_symbol
+ && e->X_add_number == p->e.X_add_number
+ && ispcrel == p->ispcrel)
+ {
+ p->refcnt ++;
+ return i;
+ }
+ }
+
+ p->refcnt = 1;
+ p->ispcrel = ispcrel;
+ p->e = * e;
+
+ poolsize ++;
+
+ return i;
+}
+
+/* Parse a literal specification. -- either new or old syntax.
+ old syntax: the user supplies the label and places the literal.
+ new syntax: we put it into the literal pool. */
+static char *
+parse_rt (s, outputp, ispcrel, ep)
+ char * s;
+ char ** outputp;
+ int ispcrel;
+ expressionS * ep;
+{
+ expressionS e;
+ int n;
+
+ if (ep)
+ /* Indicate nothing there. */
+ ep->X_op = O_absent;
+
+ if (*s == '[')
+ {
+ s = parse_exp (s + 1, & e);
+
+ if (*s == ']')
+ s++;
+ else
+ as_bad (_("missing ']'"));
+ }
+ else
+ {
+ s = parse_exp (s, & e);
+
+ n = enter_literal (& e, ispcrel);
+
+ if (ep)
+ *ep = e;
+
+ /* Create a reference to pool entry. */
+ e.X_op = O_symbol;
+ e.X_add_symbol = poolsym;
+ e.X_add_number = n << 2;
+ }
+
+ * outputp = frag_more (2);
+
+ fix_new_exp (frag_now, (*outputp) - frag_now->fr_literal, 2, & e, 1,
+ BFD_RELOC_MCORE_PCREL_IMM8BY4);
+
+ return s;
+}
+
+static char *
+parse_imm (s, val, min, max)
+ char * s;
+ unsigned * val;
+ unsigned min;
+ unsigned max;
+{
+ char * new;
+ expressionS e;
+
+ new = parse_exp (s, & e);
+
+ if (e.X_op == O_absent)
+ ; /* An error message has already been emitted. */
+ else if (e.X_op != O_constant)
+ as_bad (_("operand must be a constant"));
+ else if (e.X_add_number < min || e.X_add_number > max)
+ as_bad (_("operand must be absolute in range %d..%d, not %d"),
+ min, max, e.X_add_number);
+
+ * val = e.X_add_number;
+
+ return new;
+}
+
+static char *
+parse_mem (s, reg, off, siz)
+ char * s;
+ unsigned * reg;
+ unsigned * off;
+ unsigned siz;
+{
+ char * new;
+
+ * off = 0;
+
+ while (isspace (* s))
+ ++ s;
+
+ if (* s == '(')
+ {
+ s = parse_reg (s + 1, reg);
+
+ while (isspace (* s))
+ ++ s;
+
+ if (* s == ',')
+ {
+ s = parse_imm (s + 1, off, 0, 63);
+
+ if (siz > 1)
+ {
+ if (siz > 2)
+ {
+ if (* off & 0x3)
+ as_bad (_("operand must be a multiple of 4"));
+
+ * off >>= 2;
+ }
+ else
+ {
+ if (* off & 0x1)
+ as_bad (_("operand must be a multiple of 2"));
+
+ * off >>= 1;
+ }
+ }
+ }
+
+ while (isspace (* s))
+ ++ s;
+
+ if (* s == ')')
+ s ++;
+ }
+ else
+ as_bad (_("base register expected"));
+
+ return s;
+}
+
+/* This is the guts of the machine-dependent assembler. STR points to a
+ machine dependent instruction. This function is supposed to emit
+ the frags/bytes it assembles to. */
+
+void
+md_assemble (str)
+ char * str;
+{
+ char * op_start;
+ char * op_end;
+ mcore_opcode_info * opcode;
+ char * output;
+ int nlen = 0;
+ unsigned short inst;
+ unsigned reg;
+ unsigned off;
+ unsigned isize;
+ expressionS e;
+ char name[20];
+
+ /* Drop leading whitespace. */
+ while (isspace (* str))
+ str ++;
+
+ /* Find the op code end. */
+ for (op_start = op_end = str;
+ * op_end && nlen < 20 && !is_end_of_line [*op_end] && *op_end != ' ';
+ op_end++)
+ {
+ name[nlen] = op_start[nlen];
+ nlen++;
+ }
+
+ name [nlen] = 0;
+
+ if (nlen == 0)
+ {
+ as_bad (_("can't find opcode "));
+ return;
+ }
+
+ opcode = (mcore_opcode_info *) hash_find (opcode_hash_control, name);
+ if (opcode == NULL)
+ {
+ as_bad (_("unknown opcode \"%s\""), name);
+ return;
+ }
+
+ inst = opcode->inst;
+ isize = 2;
+
+ switch (opcode->opclass)
+ {
+ case O0:
+ output = frag_more (2);
+ break;
+
+ case OT:
+ op_end = parse_imm (op_end + 1, & reg, 0, 3);
+ inst |= reg;
+ output = frag_more (2);
+ break;
+
+ case O1:
+ op_end = parse_reg (op_end + 1, & reg);
+ inst |= reg;
+ output = frag_more (2);
+ break;
+
+ case JMP:
+ op_end = parse_reg (op_end + 1, & reg);
+ inst |= reg;
+ output = frag_more (2);
+ /* In a sifilter mode, we emit this insn 2 times,
+ fixes problem of an interrupt during a jmp.. */
+ if (sifilter_mode)
+ {
+ output[0] = (inst >> 8);
+ output[1] = (inst);
+ output = frag_more (2);
+ }
+ break;
+
+ case JSR:
+ op_end = parse_reg (op_end + 1, & reg);
+
+ if (reg == 15)
+ as_bad (_("invalid register: r15 illegal"));
+
+ inst |= reg;
+ output = frag_more (2);
+
+ if (sifilter_mode)
+ {
+ /* Replace with: bsr .+2 ; addi r15,6; jmp rx ; jmp rx */
+ inst = MCORE_INST_BSR; /* with 0 displacement */
+ output[0] = (inst >> 8);
+ output[1] = (inst);
+
+ output = frag_more (2);
+ inst = MCORE_INST_ADDI;
+ inst |= 15; /* addi r15,6 */
+ inst |= (6 - 1) << 4; /* over the jmp's */
+ output[0] = (inst >> 8);
+ output[1] = (inst);
+
+ output = frag_more (2);
+ inst = MCORE_INST_JMP | reg;
+ output[0] = (inst >> 8);
+ output[1] = (inst);
+
+ output = frag_more (2); /* 2nd emitted in fallthru */
+ }
+ break;
+
+ case OC:
+ op_end = parse_reg (op_end + 1, & reg);
+ inst |= reg;
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+
+ if (*op_end == ',')
+ {
+ op_end = parse_creg (op_end + 1, & reg);
+ inst |= reg << 4;
+ }
+
+ output = frag_more (2);
+ break;
+
+ case O2:
+ op_end = parse_reg (op_end + 1, & reg);
+ inst |= reg;
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+
+ if (* op_end == ',')
+ {
+ op_end = parse_reg (op_end + 1, & reg);
+ inst |= reg << 4;
+ }
+ else
+ as_bad (_("second operand missing"));
+
+ output = frag_more (2);
+ break;
+
+ case X1: /* Handle both syntax-> xtrb- r1,rx OR xtrb- rx */
+ op_end = parse_reg (op_end + 1, & reg);
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+
+ if (* op_end == ',') /* xtrb- r1,rx */
+ {
+ if (reg != 1)
+ as_bad (_("destination register must be r1"));
+
+ op_end = parse_reg (op_end + 1, & reg);
+ }
+
+ inst |= reg;
+ output = frag_more (2);
+ break;
+
+ case O1R1: /* div- rx,r1 */
+ op_end = parse_reg (op_end + 1, & reg);
+ inst |= reg;
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+
+ if (* op_end == ',')
+ {
+ op_end = parse_reg (op_end + 1, & reg);
+ if (reg != 1)
+ as_bad (_("source register must be r1"));
+ }
+ else
+ as_bad (_("second operand missing"));
+
+ output = frag_more (2);
+ break;
+
+ case OI:
+ op_end = parse_reg (op_end + 1, & reg);
+ inst |= reg;
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+
+ if (* op_end == ',')
+ {
+ op_end = parse_imm (op_end + 1, & reg, 1, 32);
+ inst |= (reg - 1) << 4;
+ }
+ else
+ as_bad (_("second operand missing"));
+
+ output = frag_more (2);
+ break;
+
+ case OB:
+ op_end = parse_reg (op_end + 1, & reg);
+ inst |= reg;
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+
+ if (* op_end == ',')
+ {
+ op_end = parse_imm (op_end + 1, & reg, 0, 31);
+ inst |= reg << 4;
+ }
+ else
+ as_bad (_("second operand missing"));
+
+ output = frag_more (2);
+ break;
+
+ case OB2: /* like OB, but arg is 2^n instead of n */
+ op_end = parse_reg (op_end + 1, & reg);
+ inst |= reg;
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+
+ if (* op_end == ',')
+ {
+ op_end = parse_imm (op_end + 1, & reg, 1, 1 << 31);
+ /* Further restrict the immediate to a power of two. */
+ if ((reg & (reg - 1)) == 0)
+ reg = log2 (reg);
+ else
+ {
+ reg = 0;
+ as_bad (_("immediate is not a power of two"));
+ }
+ inst |= (reg) << 4;
+ }
+ else
+ as_bad (_("second operand missing"));
+
+ output = frag_more (2);
+ break;
+
+ case OBRa: /* Specific for bgeni: imm of 0->6 translate to movi. */
+ case OBRb:
+ case OBRc:
+ op_end = parse_reg (op_end + 1, & reg);
+ inst |= reg;
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+
+ if (* op_end == ',')
+ {
+ op_end = parse_imm (op_end + 1, & reg, 0, 31);
+ /* immediate values of 0 -> 6 translate to movi */
+ if (reg <= 6)
+ {
+ inst = (inst & 0xF) | MCORE_INST_BGENI_ALT;
+ reg = 0x1 << reg;
+ as_warn (_("translating bgeni to movi"));
+ }
+ inst &= ~ 0x01f0;
+ inst |= reg << 4;
+ }
+ else
+ as_bad (_("second operand missing"));
+
+ output = frag_more (2);
+ break;
+
+ case OBR2: /* like OBR, but arg is 2^n instead of n */
+ op_end = parse_reg (op_end + 1, & reg);
+ inst |= reg;
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+
+ if (* op_end == ',')
+ {
+ op_end = parse_imm (op_end + 1, & reg, 1, 1 << 31);
+
+ /* Further restrict the immediate to a power of two. */
+ if ((reg & (reg - 1)) == 0)
+ reg = log2 (reg);
+ else
+ {
+ reg = 0;
+ as_bad (_("immediate is not a power of two"));
+ }
+
+ /* Immediate values of 0 -> 6 translate to movi. */
+ if (reg <= 6)
+ {
+ inst = (inst & 0xF) | MCORE_INST_BGENI_ALT;
+ reg = 0x1 << reg;
+ as_warn (_("translating mgeni to movi"));
+ }
+
+ inst |= reg << 4;
+ }
+ else
+ as_bad (_("second operand missing"));
+
+ output = frag_more (2);
+ break;
+
+ case OMa: /* Specific for bmaski: imm 1->7 translate to movi. */
+ case OMb:
+ case OMc:
+ op_end = parse_reg (op_end + 1, & reg);
+ inst |= reg;
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+
+ if (* op_end == ',')
+ {
+ op_end = parse_imm (op_end + 1, & reg, 1, 32);
+
+ /* Immediate values of 1 -> 7 translate to movi. */
+ if (reg <= 7)
+ {
+ inst = (inst & 0xF) | MCORE_INST_BMASKI_ALT;
+ reg = (0x1 << reg) - 1;
+ inst |= reg << 4;
+
+ as_warn (_("translating bmaski to movi"));
+ }
+ else
+ {
+ inst &= ~ 0x01F0;
+ inst |= (reg & 0x1F) << 4;
+ }
+ }
+ else
+ as_bad (_("second operand missing"));
+
+ output = frag_more (2);
+ break;
+
+ case SI:
+ op_end = parse_reg (op_end + 1, & reg);
+ inst |= reg;
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+
+ if (* op_end == ',')
+ {
+ op_end = parse_imm (op_end + 1, & reg, 1, 31);
+ inst |= reg << 4;
+ }
+ else
+ as_bad (_("second operand missing"));
+
+ output = frag_more (2);
+ break;
+
+ case I7:
+ op_end = parse_reg (op_end + 1, & reg);
+ inst |= reg;
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+
+ if (* op_end == ',')
+ {
+ op_end = parse_imm (op_end + 1, & reg, 0, 0x7F);
+ inst |= reg << 4;
+ }
+ else
+ as_bad (_("second operand missing"));
+
+ output = frag_more (2);
+ break;
+
+ case LS:
+ op_end = parse_reg (op_end + 1, & reg);
+ inst |= reg << 8;
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+
+ if (* op_end == ',')
+ {
+ int size;
+
+ if ((inst & 0x6000) == 0)
+ size = 4;
+ else if ((inst & 0x6000) == 0x4000)
+ size = 2;
+ else if ((inst & 0x6000) == 0x2000)
+ size = 1;
+
+ op_end = parse_mem (op_end + 1, & reg, & off, size);
+
+ if (off > 16)
+ as_bad (_("displacement too large (%d)"), off);
+ else
+ inst |= (reg) | (off << 4);
+ }
+ else
+ as_bad (_("second operand missing"));
+
+ output = frag_more (2);
+ break;
+
+ case LR:
+ op_end = parse_reg (op_end + 1, & reg);
+
+ if (reg == 0 || reg == 15)
+ as_bad (_("Invalid register: r0 and r15 illegal"));
+
+ inst |= (reg << 8);
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+
+ if (* op_end == ',')
+ /* parse_rt calls frag_more() for us. */
+ input_line_pointer = parse_rt (op_end + 1, & output, 0, 0);
+ else
+ {
+ as_bad (_("second operand missing"));
+ output = frag_more (2); /* save its space */
+ }
+ break;
+
+ case LJ:
+ input_line_pointer = parse_rt (op_end + 1, & output, 1, 0);
+ /* parse_rt() calls frag_more() for us. */
+ break;
+
+ case RM:
+ op_end = parse_reg (op_end + 1, & reg);
+
+ if (reg == 0 || reg == 15)
+ as_bad (_("bad starting register: r0 and r15 invalid"));
+
+ inst |= reg;
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+
+ if (* op_end == '-')
+ {
+ op_end = parse_reg (op_end + 1, & reg);
+
+ if (reg != 15)
+ as_bad (_("ending register must be r15"));
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+ }
+
+ if (* op_end == ',')
+ {
+ op_end ++;
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+
+ if (* op_end == '(')
+ {
+ op_end = parse_reg (op_end + 1, & reg);
+
+ if (reg != 0)
+ as_bad (_("bad base register: must be r0"));
+
+ if (* op_end == ')')
+ op_end ++;
+ }
+ else
+ as_bad (_("base register expected"));
+ }
+ else
+ as_bad (_("second operand missing"));
+
+ output = frag_more (2);
+ break;
+
+ case RQ:
+ op_end = parse_reg (op_end + 1, & reg);
+
+ if (reg != 4)
+ as_fatal (_("first register must be r4"));
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+
+ if (* op_end == '-')
+ {
+ op_end = parse_reg (op_end + 1, & reg);
+
+ if (reg != 7)
+ as_fatal (_("last register must be r7"));
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+
+ if (* op_end == ',')
+ {
+ op_end ++;
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+
+ if (* op_end == '(')
+ {
+ op_end = parse_reg (op_end + 1, & reg);
+
+ if (reg >= 4 && reg <= 7)
+ as_fatal ("base register cannot be r4, r5, r6, or r7");
+
+ inst |= reg;
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+
+ if (* op_end == ')')
+ op_end ++;
+ }
+ else
+ as_bad (_("base register expected"));
+ }
+ else
+ as_bad (_("second operand missing"));
+ }
+ else
+ as_bad (_("reg-reg expected"));
+
+ output = frag_more (2);
+ break;
+
+ case BR:
+ input_line_pointer = parse_exp (op_end + 1, & e);
+
+ output = frag_more (2);
+
+ fix_new_exp (frag_now, output-frag_now->fr_literal,
+ 2, & e, 1, BFD_RELOC_MCORE_PCREL_IMM11BY2);
+ break;
+
+ case BL:
+ op_end = parse_reg (op_end + 1, & reg);
+ inst |= reg << 4;
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+
+ if (* op_end == ',')
+ {
+ op_end = parse_exp (op_end + 1, & e);
+ output = frag_more (2);
+
+ fix_new_exp (frag_now, output-frag_now->fr_literal,
+ 2, & e, 1, BFD_RELOC_MCORE_PCREL_IMM4BY2);
+ }
+ else
+ {
+ as_bad (_("second operand missing"));
+ output = frag_more (2);
+ }
+ break;
+
+ case JC:
+ input_line_pointer = parse_exp (op_end + 1, & e);
+
+ output = frag_var (rs_machine_dependent,
+ md_relax_table[C (COND_JUMP, COND32)].rlx_length,
+ md_relax_table[C (COND_JUMP, COND12)].rlx_length,
+ C (COND_JUMP, 0), e.X_add_symbol, e.X_add_number, 0);
+ isize = C32_LEN;
+ break;
+
+ case JU:
+ input_line_pointer = parse_exp (op_end + 1, & e);
+ output = frag_var (rs_machine_dependent,
+ md_relax_table[C (UNCD_JUMP, UNCD32)].rlx_length,
+ md_relax_table[C (UNCD_JUMP, UNCD12)].rlx_length,
+ C (UNCD_JUMP, 0), e.X_add_symbol, e.X_add_number, 0);
+ isize = U32_LEN;
+ break;
+
+ case JL:
+ inst = MCORE_INST_JSRI; /* jsri */
+ input_line_pointer = parse_rt (op_end + 1, & output, 1, & e);
+ /* parse_rt() calls frag_more for us */
+
+ /* Only do this if we know how to do it ... */
+ if (e.X_op != O_absent && do_jsri2bsr)
+ {
+ /* Look at adding the R_PCREL_JSRIMM11BY2. */
+ fix_new_exp (frag_now, output-frag_now->fr_literal,
+ 2, & e, 1, BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2);
+ }
+ break;
+
+ case RSI: /* SI, but imm becomes 32-imm */
+ op_end = parse_reg (op_end + 1, & reg);
+ inst |= reg;
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+
+ if (* op_end == ',')
+ {
+ op_end = parse_imm (op_end + 1, & reg, 1, 31);
+
+ reg = 32 - reg;
+ inst |= reg << 4;
+ }
+ else
+ as_bad (_("second operand missing"));
+
+ output = frag_more (2);
+ break;
+
+ case DO21: /* O2, dup rd, lit must be 1 */
+ op_end = parse_reg (op_end + 1, & reg);
+ inst |= reg;
+ inst |= reg << 4;
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+
+ if (* op_end == ',')
+ {
+ op_end = parse_imm (op_end + 1, & reg, 1, 31);
+
+ if (reg != 1)
+ as_bad (_("second operand must be 1"));
+ }
+ else
+ as_bad (_("second operand missing"));
+
+ output = frag_more (2);
+ break;
+
+ case SIa:
+ op_end = parse_reg (op_end + 1, & reg);
+ inst |= reg;
+
+ /* Skip whitespace. */
+ while (isspace (* op_end))
+ ++ op_end;
+
+ if (* op_end == ',')
+ {
+ op_end = parse_imm (op_end + 1, & reg, 1, 31);
+
+ if (reg == 0)
+ as_bad (_("zero used as immediate value"));
+
+ inst |= reg << 4;
+ }
+ else
+ as_bad (_("second operand missing"));
+
+ output = frag_more (2);
+ break;
+
+ default:
+ as_bad (_("unimplemented opcode \"%s\""), name);
+ }
+
+ output[0] = inst >> 8;
+ output[1] = inst;
+
+ check_literals (opcode->transfer, isize);
+}
+
+symbolS *
+md_undefined_symbol (name)
+ char * name;
+{
+ return 0;
+}
+
+void
+md_mcore_end ()
+{
+ dump_literals (0);
+ subseg_set (text_section, 0);
+}
+
+/* Various routines to kill one day. */
+/* Equal to MAX_PRECISION in atof-ieee.c */
+#define MAX_LITTLENUMS 6
+
+/* Turn a string in input_line_pointer into a floating point constant of type
+ type, and store the appropriate bytes in *litP. The number of LITTLENUMS
+ emitted is stored in *sizeP. An error message is returned, or NULL on OK.*/
+char *
+md_atof (type, litP, sizeP)
+ int type;
+ char * litP;
+ int * sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE * wordP;
+ char * t;
+ char * atof_ieee ();
+
+ switch (type)
+ {
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ prec = 4;
+ break;
+
+ case 'x':
+ case 'X':
+ prec = 6;
+ break;
+
+ case 'p':
+ case 'P':
+ prec = 6;
+ break;
+
+ default:
+ *sizeP = 0;
+ return _("Bad call to MD_NTOF()");
+ }
+
+ t = atof_ieee (input_line_pointer, type, words);
+
+ if (t)
+ input_line_pointer = t;
+
+ *sizeP = prec * sizeof (LITTLENUM_TYPE);
+
+ for (wordP = words; prec--;)
+ {
+ md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+
+ return 0;
+}
+
+CONST char * md_shortopts = "";
+
+#define OPTION_RELAX (OPTION_MD_BASE)
+#define OPTION_JSRI2BSR_ON (OPTION_MD_BASE + 1)
+#define OPTION_JSRI2BSR_OFF (OPTION_MD_BASE + 2)
+#define OPTION_SIFILTER_ON (OPTION_MD_BASE + 3)
+#define OPTION_SIFILTER_OFF (OPTION_MD_BASE + 4)
+
+struct option md_longopts[] =
+{
+ { "relax", no_argument, NULL, OPTION_RELAX},
+ { "no-jsri2bsr", no_argument, NULL, OPTION_JSRI2BSR_OFF},
+ { "jsri2bsr", no_argument, NULL, OPTION_JSRI2BSR_ON},
+ { "sifilter", no_argument, NULL, OPTION_SIFILTER_ON},
+ { "no-sifilter", no_argument, NULL, OPTION_SIFILTER_OFF},
+ { NULL, no_argument, NULL, 0}
+};
+
+size_t md_longopts_size = sizeof (md_longopts);
+
+int
+md_parse_option (c, arg)
+ int c;
+ char * arg;
+{
+ int i;
+ char * p;
+
+ switch (c)
+ {
+
+ case OPTION_RELAX: relax = 1; break;
+ case OPTION_JSRI2BSR_ON: do_jsri2bsr = 1; break;
+ case OPTION_JSRI2BSR_OFF: do_jsri2bsr = 0; break;
+ case OPTION_SIFILTER_ON: sifilter_mode = 1; break;
+ case OPTION_SIFILTER_OFF: sifilter_mode = 0; break;
+ default: return 0;
+ }
+
+ return 1;
+}
+
+void
+md_show_usage (stream)
+ FILE * stream;
+{
+ fprintf (stream, _("\
+MCORE specific options:\n\
+ -{no-}jsri2bsr {dis}able jsri to bsr transformation (def: off)\n\
+ -{no-}sifilter {dis}able silicon filter behavior (def: off)\n\
+ -relax alter jump instructions for long displacements\n"));
+}
+
+int md_short_jump_size;
+
+void
+md_create_short_jump (ptr, from_Nddr, to_Nddr, frag, to_symbol)
+ char * ptr;
+ addressT from_Nddr;
+ addressT to_Nddr;
+ fragS * frag;
+ symbolS * to_symbol;
+{
+ as_fatal (_("failed sanity check: short_jump"));
+}
+
+void
+md_create_long_jump (ptr, from_Nddr, to_Nddr, frag, to_symbol)
+ char * ptr;
+ addressT from_Nddr;
+ addressT to_Nddr;
+ fragS * frag;
+ symbolS * to_symbol;
+{
+ as_fatal (_("failed sanity check: long_jump"));
+}
+
+/* Called after relaxing, change the frags so they know how big they are. */
+void
+md_convert_frag (abfd, sec, fragP)
+ bfd * abfd;
+ segT sec;
+ register fragS * fragP;
+{
+ unsigned char * buffer;
+ int targ_addr = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset;
+
+ buffer = (unsigned char *) (fragP->fr_fix + fragP->fr_literal);
+ targ_addr += fragP->fr_symbol->sy_frag->fr_address;
+
+ switch (fragP->fr_subtype)
+ {
+ case C (COND_JUMP, COND12):
+ case C (UNCD_JUMP, UNCD12):
+ {
+ /* Get the address of the end of the instruction */
+ int next_inst = fragP->fr_fix + fragP->fr_address + 2;
+ unsigned char t0;
+ int disp = targ_addr - next_inst;
+
+ if (disp & 1)
+ as_bad (_("odd displacement at %x"), next_inst - 2);
+
+ disp >>= 1;
+ t0 = buffer[0] & 0xF8;
+
+ md_number_to_chars (buffer, disp, 2);
+
+ buffer[0] = (buffer[0] & 0x07) | t0;
+ fragP->fr_fix += 2;
+ fragP->fr_var = 0;
+ }
+ break;
+
+ case C (COND_JUMP, COND32):
+ case C (COND_JUMP, UNDEF_WORD_DISP):
+ {
+ /* A conditional branch wont fit into 12 bits so:
+ * b!cond 1f
+ * jmpi 0f
+ * .align 2
+ * 0: .long disp
+ * 1:
+ *
+ * if the b!cond is 4 byte aligned, the literal which would
+ * go at x+4 will also be aligned.
+ */
+ int first_inst = fragP->fr_fix + fragP->fr_address;
+ int needpad = (first_inst & 3);
+
+ buffer[0] ^= 0x08; /* Toggle T/F bit */
+
+ buffer[2] = INST_BYTE0 (MCORE_INST_JMPI); /* Build jmpi */
+ buffer[3] = INST_BYTE1 (MCORE_INST_JMPI);
+
+ if (needpad)
+ {
+ buffer[1] = 4; /* branch over jmpi, pad, and ptr */
+ buffer[3] = 1; /* jmpi offset of 1 gets the pointer */
+ buffer[4] = 0; /* alignment/pad */
+ buffer[5] = 0;
+ buffer[6] = 0; /* space for 32 bit address */
+ buffer[7] = 0;
+ buffer[8] = 0;
+ buffer[9] = 0;
+
+ /* Make reloc for the long disp */
+ fix_new (fragP, fragP->fr_fix + 6, 4,
+ fragP->fr_symbol, fragP->fr_offset, 0, BFD_RELOC_32);
+
+ fragP->fr_fix += C32_LEN;
+ }
+ else
+ {
+ /* See comment below about this given gas' limitations for
+ shrinking the fragment. '3' is the amount of code that
+ we inserted here, but '4' is right for the space we reserved
+ for this fragment. */
+ buffer[1] = 3; /* branch over jmpi, and ptr */
+ buffer[3] = 0; /* jmpi offset of 0 gets the pointer */
+ buffer[4] = 0; /* space for 32 bit address */
+ buffer[5] = 0;
+ buffer[6] = 0;
+ buffer[7] = 0;
+
+ /* Make reloc for the long disp. */
+ fix_new (fragP, fragP->fr_fix + 4, 4,
+ fragP->fr_symbol, fragP->fr_offset, 0, BFD_RELOC_32);
+ fragP->fr_fix += C32_LEN;
+
+ /* frag is actually shorter (see the other side of this ifdef)
+ but gas isn't prepared for that. We have to re-adjust
+ the branch displacement so that it goes beyond the
+ full length of the fragment, not just what we actually
+ filled in. */
+ buffer[1] = 4; /* jmpi, ptr, and the 'tail pad' */
+ }
+
+ fragP->fr_var = 0;
+ }
+ break;
+
+ case C (UNCD_JUMP, UNCD32):
+ case C (UNCD_JUMP, UNDEF_WORD_DISP):
+ {
+ /* An unconditional branch will not fit in 12 bits, make code which
+ looks like:
+ jmpi 0f
+ .align 2
+ 0: .long disp
+ we need a pad if "first_inst" is 4 byte aligned.
+ [because the natural literal place is x + 2] */
+ int first_inst = fragP->fr_fix + fragP->fr_address;
+ int needpad = !(first_inst & 3);
+
+ buffer[0] = INST_BYTE0 (MCORE_INST_JMPI); /* Build jmpi */
+ buffer[1] = INST_BYTE1 (MCORE_INST_JMPI);
+
+ if (needpad)
+ {
+ buffer[1] = 1; /* jmpi offset of 1 since padded */
+ buffer[2] = 0; /* alignment */
+ buffer[3] = 0;
+ buffer[4] = 0; /* space for 32 bit address */
+ buffer[5] = 0;
+ buffer[6] = 0;
+ buffer[7] = 0;
+
+ /* Make reloc for the long disp */
+ fix_new (fragP, fragP->fr_fix + 4, 4,
+ fragP->fr_symbol, fragP->fr_offset, 0, BFD_RELOC_32);
+
+ fragP->fr_fix += U32_LEN;
+ }
+ else
+ {
+ buffer[1] = 0; /* jmpi offset of 0 if no pad */
+ buffer[2] = 0; /* space for 32 bit address */
+ buffer[3] = 0;
+ buffer[4] = 0;
+ buffer[5] = 0;
+
+ /* Make reloc for the long disp */
+ fix_new (fragP, fragP->fr_fix + 2, 4,
+ fragP->fr_symbol, fragP->fr_offset, 0, BFD_RELOC_32);
+ fragP->fr_fix += U32_LEN;
+ }
+
+ fragP->fr_var = 0;
+ }
+ break;
+
+ default:
+ abort ();
+ }
+}
+
+/* Applies the desired value to the specified location.
+ Also sets up addends for 'rela' type relocations. */
+int
+md_apply_fix3 (fixP, valp, segment)
+ fixS * fixP;
+ valueT * valp;
+ segT segment;
+{
+ char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
+ char * file = fixP->fx_file ? fixP->fx_file : _("unknown");
+ const char * symname;
+ /* Note: use offsetT because it is signed, valueT is unsigned. */
+ offsetT val = (offsetT) * valp;
+
+ symname = fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : _("<unknown>");
+ /* Save this for the addend in the relocation record. */
+ fixP->fx_addnumber = val;
+
+ /* If the fix is relative to a symbol which is not defined, or not
+ in the same segment as the fix, we cannot resolve it here. */
+ if (fixP->fx_addsy != NULL
+ && ( ! S_IS_DEFINED (fixP->fx_addsy)
+ || (S_GET_SEGMENT (fixP->fx_addsy) != segment)))
+ {
+ fixP->fx_done = 0;
+#ifdef OBJ_ELF
+ /* For ELF we can just return and let the reloc that will be generated
+ take care of everything. For COFF we still have to insert 'val'
+ into the insn since the addend field will be ignored. */
+ return 0;
+#endif
+ }
+ else
+ fixP->fx_done = 1;
+
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_MCORE_PCREL_IMM11BY2: /* second byte of 2 byte opcode */
+ if ((val & 1) != 0)
+ as_bad_where (file, fixP->fx_line,
+ _("odd distance branch (0x%x bytes)"), val);
+ val /= 2;
+ if (((val & ~0x3ff) != 0) && ((val | 0x3ff) != -1))
+ as_bad_where (file, fixP->fx_line,
+ _("pcrel for branch to %s too far (0x%x)"),
+ symname, val);
+ buf[0] |= ((val >> 8) & 0x7);
+ buf[1] |= (val & 0xff);
+ break;
+
+ case BFD_RELOC_MCORE_PCREL_IMM8BY4: /* lower 8 bits of 2 byte opcode */
+ val += 3;
+ val /= 4;
+ if (val & ~0xff)
+ as_bad_where (file, fixP->fx_line,
+ _("pcrel for lrw/jmpi/jsri to %s too far (0x%x)"),
+ symname, val);
+ else
+ buf[1] |= (val & 0xff);
+ break;
+
+ case BFD_RELOC_MCORE_PCREL_IMM4BY2: /* loopt instruction */
+ if ((val < -32) || (val > -2))
+ as_bad_where (file, fixP->fx_line,
+ _("pcrel for loopt too far (0x%x)"), val);
+ val /= 2;
+ buf[1] |= (val & 0xf);
+ break;
+
+ case BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2:
+ /* Conditional linker map jsri to bsr. */
+ /* If its a local target and close enough, fix it.
+ NB: >= -2k for backwards bsr; < 2k for forwards... */
+ if (fixP->fx_addsy == 0 && val >= -2048 && val < 2048)
+ {
+ long nval = (val / 2) & 0x7ff;
+ nval |= MCORE_INST_BSR;
+
+ /* REPLACE the instruction, don't just modify it. */
+ buf[0] = ((nval >> 8) & 0xff);
+ buf[1] = (nval & 0xff);
+ }
+ else
+ fixP->fx_done = 0;
+ break;
+
+ case BFD_RELOC_MCORE_PCREL_32:
+ case BFD_RELOC_VTABLE_INHERIT:
+ case BFD_RELOC_VTABLE_ENTRY:
+ fixP->fx_done = 0;
+ break;
+
+ default:
+ if (fixP->fx_addsy != NULL)
+ {
+ /* If the fix is an absolute reloc based on a symbol's
+ address, then it cannot be resolved until the final link. */
+ fixP->fx_done = 0;
+ }
+#ifdef OBJ_ELF
+ else
+#endif
+ {
+ if (fixP->fx_size == 4)
+ {
+ *buf++ = val >> 24;
+ *buf++ = val >> 16;
+ *buf++ = val >> 8;
+ *buf = val;
+ }
+ else if (fixP->fx_size == 2 && val >= -32768 && val <= 32767)
+ {
+ *buf++ = val >> 8;
+ *buf = val;
+ }
+ else if (fixP->fx_size == 1 && val >= -256 && val <= 255)
+ *buf = val;
+ else
+ abort ();
+ }
+ break;
+ }
+
+ return 0; /* Return value is ignored. */
+}
+
+void
+md_operand (expressionP)
+ expressionS * expressionP;
+{
+ /* Ignore leading hash symbol, if poresent. */
+ if (* input_line_pointer == '#')
+ {
+ input_line_pointer ++;
+ expression (expressionP);
+ }
+}
+
+int md_long_jump_size;
+
+/* Called just before address relaxation, return the length
+ by which a fragment must grow to reach it's destination. */
+int
+md_estimate_size_before_relax (fragP, segment_type)
+ register fragS * fragP;
+ register segT segment_type;
+{
+ switch (fragP->fr_subtype)
+ {
+ case C (UNCD_JUMP, UNDEF_DISP):
+ /* Used to be a branch to somewhere which was unknown. */
+ if (!fragP->fr_symbol)
+ {
+ fragP->fr_subtype = C (UNCD_JUMP, UNCD12);
+ fragP->fr_var = md_relax_table[C (UNCD_JUMP, UNCD12)].rlx_length;
+ }
+ else if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type)
+ {
+ fragP->fr_subtype = C (UNCD_JUMP, UNCD12);
+ fragP->fr_var = md_relax_table[C (UNCD_JUMP, UNCD12)].rlx_length;
+ }
+ else
+ {
+ fragP->fr_subtype = C (UNCD_JUMP, UNDEF_WORD_DISP);
+ fragP->fr_var = md_relax_table[C (UNCD_JUMP, UNCD32)].rlx_length;
+ return md_relax_table[C (UNCD_JUMP, UNCD32)].rlx_length;
+ }
+ break;
+
+ default:
+ abort ();
+
+ case C (COND_JUMP, UNDEF_DISP):
+ /* Used to be a branch to somewhere which was unknown. */
+ if (fragP->fr_symbol
+ && S_GET_SEGMENT (fragP->fr_symbol) == segment_type)
+ {
+ /* Got a symbol and it's defined in this segment, become byte
+ sized - maybe it will fix up */
+ fragP->fr_subtype = C (COND_JUMP, COND12);
+ fragP->fr_var = md_relax_table[C (COND_JUMP, COND12)].rlx_length;
+ }
+ else if (fragP->fr_symbol)
+ {
+ /* Its got a segment, but its not ours, so it will always be long. */
+ fragP->fr_subtype = C (COND_JUMP, UNDEF_WORD_DISP);
+ fragP->fr_var = md_relax_table[C (COND_JUMP, COND32)].rlx_length;
+ return md_relax_table[C (COND_JUMP, COND32)].rlx_length;
+ }
+ else
+ {
+ /* We know the abs value. */
+ fragP->fr_subtype = C (COND_JUMP, COND12);
+ fragP->fr_var = md_relax_table[C (COND_JUMP, COND12)].rlx_length;
+ }
+
+ break;
+ }
+
+ return fragP->fr_var;
+}
+
+/* Put number into target byte order */
+
+void
+md_number_to_chars (ptr, use, nbytes)
+ char * ptr;
+ valueT use;
+ int nbytes;
+{
+ switch (nbytes)
+ {
+ case 4: *ptr++ = (use >> 24) & 0xff; /* fall through */
+ case 3: *ptr++ = (use >> 16) & 0xff; /* fall through */
+ case 2: *ptr++ = (use >> 8) & 0xff; /* fall through */
+ case 1: *ptr++ = (use >> 0) & 0xff; break;
+ default: abort ();
+ }
+}
+
+/* Round up a section size to the appropriate boundary. */
+valueT
+md_section_align (segment, size)
+ segT segment;
+ valueT size;
+{
+ return size; /* Byte alignment is fine */
+}
+
+
+/* The location from which a PC relative jump should be calculated,
+ given a PC relative reloc. */
+long
+md_pcrel_from_section (fixp, sec)
+ fixS * fixp;
+ segT sec;
+{
+#ifdef OBJ_ELF
+ /* If the symbol is undefined or defined in another section
+ we leave the add number alone for the linker to fix it later.
+ Only account for the PC pre-bump (which is 2 bytes on the MCore). */
+ if (fixp->fx_addsy != (symbolS *) NULL
+ && (! S_IS_DEFINED (fixp->fx_addsy)
+ || (S_GET_SEGMENT (fixp->fx_addsy) != sec)))
+
+ {
+ assert (fixp->fx_size == 2); /* must be an insn */
+ return fixp->fx_size;
+ }
+#endif
+
+ /* The case where we are going to resolve things... */
+ return fixp->fx_size + fixp->fx_where + fixp->fx_frag->fr_address;
+}
+
+#define F(SZ,PCREL) (((SZ) << 1) + (PCREL))
+#define MAP(SZ,PCREL,TYPE) case F (SZ, PCREL): code = (TYPE); break
+
+arelent *
+tc_gen_reloc (section, fixp)
+ asection * section;
+ fixS * fixp;
+{
+ arelent * rel;
+ bfd_reloc_code_real_type code;
+ int handled = 0;
+
+ switch (fixp->fx_r_type)
+ {
+ /* These confuse the size/pcrel macro approach. */
+ case BFD_RELOC_VTABLE_INHERIT:
+ case BFD_RELOC_VTABLE_ENTRY:
+ case BFD_RELOC_MCORE_PCREL_IMM4BY2:
+ case BFD_RELOC_MCORE_PCREL_IMM8BY4:
+ case BFD_RELOC_MCORE_PCREL_IMM11BY2:
+ case BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2:
+ code = fixp->fx_r_type;
+ break;
+
+ default:
+ switch (F (fixp->fx_size, fixp->fx_pcrel))
+ {
+ MAP (1, 0, BFD_RELOC_8);
+ MAP (2, 0, BFD_RELOC_16);
+ MAP (4, 0, BFD_RELOC_32);
+ MAP (1, 1, BFD_RELOC_8_PCREL);
+ MAP (2, 1, BFD_RELOC_16_PCREL);
+ MAP (4, 1, BFD_RELOC_32_PCREL);
+ default:
+ code = fixp->fx_r_type;
+ as_bad (_("Can not do %d byte %srelocation"),
+ fixp->fx_size,
+ fixp->fx_pcrel ? _("pc-relative") : "");
+ }
+ break;
+ }
+
+ rel = (arelent *) xmalloc (sizeof (arelent));
+ rel->sym_ptr_ptr = & fixp->fx_addsy->bsym;
+ rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
+ /* Always pass the addend along! */
+ rel->addend = fixp->fx_addnumber;
+
+ rel->howto = bfd_reloc_type_lookup (stdoutput, code);
+
+ if (rel->howto == NULL)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("Cannot represent relocation type %s"),
+ bfd_get_reloc_code_name (code));
+
+ /* Set howto to a garbage value so that we can keep going. */
+ rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
+ assert (rel->howto != NULL);
+ }
+
+ return rel;
+}
+
+#ifdef OBJ_ELF
+/* See whether we need to force a relocation into the output file.
+ This is used to force out switch and PC relative relocations when
+ relaxing. */
+int
+mcore_force_relocation (fix)
+ fixS * fix;
+{
+ if ( fix->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fix->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ return 1;
+
+ return 0;
+}
+
+/* Return true if the fix can be handled by GAS, false if it must
+ be passed through to the linker. */
+boolean
+mcore_fix_adjustable (fixP)
+ fixS * fixP;
+{
+ if (fixP->fx_addsy == NULL)
+ return 1;
+
+ /* We need the symbol name for the VTABLE entries. */
+ if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ return 0;
+
+ return 1;
+}
+
+/* Handle the .section pseudo-op. This is like the usual one, but it
+ dumps the literal pool before changing the section. */
+static void
+mcore_s_section (ignore)
+ int ignore;
+{
+ dump_literals (0);
+
+ obj_elf_section (ignore);
+}
+#endif /* OBJ_ELF */
diff --git a/gas/config/tc-mcore.h b/gas/config/tc-mcore.h
new file mode 100644
index 0000000000..9e487c92a3
--- /dev/null
+++ b/gas/config/tc-mcore.h
@@ -0,0 +1,119 @@
+/* This file is tc-mcore.h
+
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef TC_MCORE
+#define TC_MCORE 1
+
+#ifndef BFD_ASSEMBLER
+ #error MCORE support requires BFD_ASSEMBLER
+#endif
+
+#define TARGET_ARCH bfd_arch_mcore
+#define TARGET_BYTES_BIG_ENDIAN 1
+
+/* Don't write out relocs for pcrel stuff. */
+#define TC_COUNT_RELOC(x) (((x)->fx_addsy || (x)->fx_subsy) && \
+ (x)->fx_r_type < BFD_RELOC_MCORE_PCREL_IMM8BY4)
+
+#define IGNORE_NONSTANDARD_ESCAPES
+
+#define TC_RELOC_MANGLE(a,b,c) tc_reloc_mangle (a, b, c)
+
+/* Some pseudo-op semantic extensions. */
+#define PSEUDO_LCOMM_OPTIONAL_ALIGN
+
+#define LISTING_HEADER "M.CORE GAS Version 2.9.4"
+#define LISTING_LHS_CONT_LINES 4
+
+#define NEED_FX_R_TYPE 1
+#define COFF_FLAGS 1
+
+/* We want local label support. */
+#define LOCAL_LABELS_FB 1
+
+#define TC_COFF_SIZEMACHDEP(frag) tc_coff_sizemachdep (frag)
+
+extern const struct relax_type md_relax_table[];
+#define TC_GENERIC_RELAX_TABLE md_relax_table
+#define md_end md_mcore_end
+
+/* Want the section information too... */
+#define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from_section (FIXP, SEC)
+
+#define MD_APPLY_FIX3 /* We want the segment as well. */
+
+
+
+#ifdef OBJ_COFF
+
+#define TARGET_FORMAT (target_big_endian ? "pe-mcore-big" : "pe-mcore-little")
+
+#define TARGET_SYMBOL_FIELDS int sy_flags ;
+
+#endif /* OBJ_COFF */
+
+
+#ifdef OBJ_ELF
+
+#define TARGET_FORMAT (target_big_endian ? "elf32-mcore-big" : "elf32-mcore-little")
+
+#define ELF_TC_SPECIAL_SECTIONS \
+ { ".ctors", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, \
+ { ".dtors", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, \
+/* Other special sections not generated by the assembler: .reginfo,
+ .liblist, .conflict, .gptab, .got, .dynamic, .rel.dyn. */
+
+/* When relaxing, we need to emit various relocs we otherwise wouldn't. */
+#define TC_FORCE_RELOCATION(fix) mcore_force_relocation (fix)
+extern int mcore_force_relocation PARAMS ((struct fix *));
+
+#define obj_fix_adjustable(fixP) mcore_fix_adjustable (fixP)
+extern boolean mcore_fix_adjustable PARAMS ((struct fix *));
+
+#endif /* OBJ_ELF */
+
+#ifndef TARGET_FORMAT
+# error No target format specified.
+#endif
+
+#include "struc-symbol.h" /* For definition of symbolS */
+#include "write.h" /* For definition of fixS */
+
+extern void md_begin PARAMS ((void));
+extern void md_assemble PARAMS ((char *));
+extern symbolS * md_undefined_symbol PARAMS ((char *));
+extern void md_mcore_end PARAMS ((void));
+extern char * md_atof PARAMS ((int, char *, int *));
+extern int md_parse_option PARAMS ((int, char *));
+extern void md_show_usage PARAMS ((FILE *));
+extern void md_create_short_jump
+ PARAMS ((char *, addressT, addressT, fragS *, symbolS *));
+extern void md_create_long_jump
+ PARAMS ((char *, addressT, addressT, fragS *, symbolS *));
+extern void md_convert_frag PARAMS ((bfd *, segT, fragS *));
+extern int md_apply_fix3 PARAMS ((fixS *, valueT *, segT));
+extern void md_operand PARAMS ((expressionS *));
+extern int md_estimate_size_before_relax PARAMS ((fragS *, segT));
+extern void md_number_to_chars PARAMS ((char *, valueT, int));
+extern valueT md_section_align PARAMS ((segT, valueT));
+extern long md_pcrel_from_section PARAMS ((fixS *, segT));
+extern arelent * tc_gen_reloc PARAMS ((asection *, fixS *));
+
+#endif /* TC_MCORE */
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
new file mode 100644
index 0000000000..3d865fd977
--- /dev/null
+++ b/gas/config/tc-mips.c
@@ -0,0 +1,11783 @@
+/* tc-mips.c -- assemble code for a MIPS chip.
+ Copyright (C) 1993, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+ Contributed by the OSF and Ralph Campbell.
+ Written by Keith Knowles and Ralph Campbell, working independently.
+ Modified for ECOFF and R4000 support by Ian Lance Taylor of Cygnus
+ Support.
+
+ This file is part of GAS.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include "as.h"
+#include "config.h"
+#include "subsegs.h"
+
+#include <ctype.h>
+
+#ifdef USE_STDARG
+#include <stdarg.h>
+#endif
+#ifdef USE_VARARGS
+#include <varargs.h>
+#endif
+
+#include "opcode/mips.h"
+#include "itbl-ops.h"
+
+#ifdef DEBUG
+#define DBG(x) printf x
+#else
+#define DBG(x)
+#endif
+
+#ifdef OBJ_MAYBE_ELF
+/* Clean up namespace so we can include obj-elf.h too. */
+static int mips_output_flavor PARAMS ((void));
+static int mips_output_flavor () { return OUTPUT_FLAVOR; }
+#undef OBJ_PROCESS_STAB
+#undef OUTPUT_FLAVOR
+#undef S_GET_ALIGN
+#undef S_GET_SIZE
+#undef S_SET_ALIGN
+#undef S_SET_SIZE
+#undef TARGET_SYMBOL_FIELDS
+#undef obj_frob_file
+#undef obj_frob_file_after_relocs
+#undef obj_frob_symbol
+#undef obj_pop_insert
+#undef obj_sec_sym_ok_for_reloc
+#undef OBJ_COPY_SYMBOL_ATTRIBUTES
+
+#include "obj-elf.h"
+/* Fix any of them that we actually care about. */
+#undef OUTPUT_FLAVOR
+#define OUTPUT_FLAVOR mips_output_flavor()
+#endif
+
+#if defined (OBJ_ELF)
+#include "elf/mips.h"
+#endif
+
+#ifndef ECOFF_DEBUGGING
+#define NO_ECOFF_DEBUGGING
+#define ECOFF_DEBUGGING 0
+#endif
+
+#include "ecoff.h"
+
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+static char *mips_regmask_frag;
+#endif
+
+#define AT 1
+#define TREG 24
+#define PIC_CALL_REG 25
+#define KT0 26
+#define KT1 27
+#define GP 28
+#define SP 29
+#define FP 30
+#define RA 31
+
+#define ILLEGAL_REG (32)
+
+/* Allow override of standard little-endian ECOFF format. */
+
+#ifndef ECOFF_LITTLE_FORMAT
+#define ECOFF_LITTLE_FORMAT "ecoff-littlemips"
+#endif
+
+extern int target_big_endian;
+
+/* 1 is we should use the 64 bit MIPS ELF ABI, 0 if we should use the
+ 32 bit ABI. This has no meaning for ECOFF.
+ Note that the default is always 32 bit, even if "configured" for
+ 64 bit [e.g. --target=mips64-elf]. */
+static int mips_64;
+
+/* The default target format to use. */
+const char *
+mips_target_format ()
+{
+ switch (OUTPUT_FLAVOR)
+ {
+ case bfd_target_aout_flavour:
+ return target_big_endian ? "a.out-mips-big" : "a.out-mips-little";
+ case bfd_target_ecoff_flavour:
+ return target_big_endian ? "ecoff-bigmips" : ECOFF_LITTLE_FORMAT;
+ case bfd_target_elf_flavour:
+ return (target_big_endian
+ ? (mips_64 ? "elf64-bigmips" : "elf32-bigmips")
+ : (mips_64 ? "elf64-littlemips" : "elf32-littlemips"));
+ default:
+ abort ();
+ return NULL;
+ }
+}
+
+/* The name of the readonly data section. */
+#define RDATA_SECTION_NAME (OUTPUT_FLAVOR == bfd_target_aout_flavour \
+ ? ".data" \
+ : OUTPUT_FLAVOR == bfd_target_ecoff_flavour \
+ ? ".rdata" \
+ : OUTPUT_FLAVOR == bfd_target_elf_flavour \
+ ? ".rodata" \
+ : (abort (), ""))
+
+/* This is the set of options which may be modified by the .set
+ pseudo-op. We use a struct so that .set push and .set pop are more
+ reliable. */
+
+struct mips_set_options
+{
+ /* MIPS ISA (Instruction Set Architecture) level. This is set to -1
+ if it has not been initialized. Changed by `.set mipsN', and the
+ -mipsN command line option, and the default CPU. */
+ int isa;
+ /* Whether we are assembling for the mips16 processor. 0 if we are
+ not, 1 if we are, and -1 if the value has not been initialized.
+ Changed by `.set mips16' and `.set nomips16', and the -mips16 and
+ -nomips16 command line options, and the default CPU. */
+ int mips16;
+ /* Non-zero if we should not reorder instructions. Changed by `.set
+ reorder' and `.set noreorder'. */
+ int noreorder;
+ /* Non-zero if we should not permit the $at ($1) register to be used
+ in instructions. Changed by `.set at' and `.set noat'. */
+ int noat;
+ /* Non-zero if we should warn when a macro instruction expands into
+ more than one machine instruction. Changed by `.set nomacro' and
+ `.set macro'. */
+ int warn_about_macros;
+ /* Non-zero if we should not move instructions. Changed by `.set
+ move', `.set volatile', `.set nomove', and `.set novolatile'. */
+ int nomove;
+ /* Non-zero if we should not optimize branches by moving the target
+ of the branch into the delay slot. Actually, we don't perform
+ this optimization anyhow. Changed by `.set bopt' and `.set
+ nobopt'. */
+ int nobopt;
+ /* Non-zero if we should not autoextend mips16 instructions.
+ Changed by `.set autoextend' and `.set noautoextend'. */
+ int noautoextend;
+};
+
+/* This is the struct we use to hold the current set of options. Note
+ that we must set the isa and mips16 fields to -1 to indicate that
+ they have not been initialized. */
+
+static struct mips_set_options mips_opts = { -1, -1 };
+
+/* These variables are filled in with the masks of registers used.
+ The object format code reads them and puts them in the appropriate
+ place. */
+unsigned long mips_gprmask;
+unsigned long mips_cprmask[4];
+
+/* MIPS ISA we are using for this output file. */
+static int file_mips_isa;
+
+/* The CPU type as a number: 2000, 3000, 4000, 4400, etc. */
+static int mips_cpu = -1;
+
+/* The argument of the -mabi= flag. */
+static char* mips_abi_string = 0;
+
+/* Wether we should mark the file EABI64 or EABI32. */
+static int mips_eabi64 = 0;
+
+/* If they asked for mips1 or mips2 and a cpu that is
+ mips3 or greater, then mark the object file 32BITMODE. */
+static int mips_32bitmode = 0;
+
+/* Whether the processor uses hardware interlocks to protect
+ reads from the HI and LO registers, and thus does not
+ require nops to be inserted.
+
+ FIXME: GCC makes a distinction between -mcpu=FOO and -mFOO:
+ -mcpu=FOO schedules for FOO, but still produces code that meets the
+ requirements of MIPS ISA I. For example, it won't generate any
+ FOO-specific instructions, and it will still assume that any
+ scheduling hazards described in MIPS ISA I are there, even if FOO
+ has interlocks. -mFOO gives GCC permission to generate code that
+ will only run on a FOO; it will generate FOO-specific instructions,
+ and assume interlocks provided by a FOO.
+
+ However, GAS currently doesn't make this distinction; before Jan 28
+ 1999, GAS's -mcpu=FOO implied -mFOO, which violates GCC's
+ assumptions. The GCC driver passes these flags through to GAS, so
+ if GAS actually does anything that doesn't meet MIPS ISA I with
+ -mFOO, then GCC's -mcpu=FOO flag isn't going to work.
+
+ And furthermore, it did not assume that -mFOO implied -mcpu=FOO,
+ which seems senseless --- why generate code which will only run on
+ a FOO, but schedule for something else?
+
+ So now, at least, -mcpu=FOO and -mFOO are exactly equivalent.
+
+ -- Jim Blandy <jimb@cygnus.com> */
+
+#define hilo_interlocks (mips_cpu == 4010 \
+ )
+
+/* Whether the processor uses hardware interlocks to protect reads
+ from the GPRs, and thus does not require nops to be inserted. */
+#define gpr_interlocks \
+ (mips_opts.isa >= 2 \
+ || mips_cpu == 3900)
+
+/* As with other "interlocks" this is used by hardware that has FP
+ (co-processor) interlocks. */
+/* Itbl support may require additional care here. */
+#define cop_interlocks (mips_cpu == 4300 \
+ )
+
+/* MIPS PIC level. */
+
+enum mips_pic_level
+{
+ /* Do not generate PIC code. */
+ NO_PIC,
+
+ /* Generate PIC code as in Irix 4. This is not implemented, and I'm
+ not sure what it is supposed to do. */
+ IRIX4_PIC,
+
+ /* Generate PIC code as in the SVR4 MIPS ABI. */
+ SVR4_PIC,
+
+ /* Generate PIC code without using a global offset table: the data
+ segment has a maximum size of 64K, all data references are off
+ the $gp register, and all text references are PC relative. This
+ is used on some embedded systems. */
+ EMBEDDED_PIC
+};
+
+static enum mips_pic_level mips_pic;
+
+/* 1 if we should generate 32 bit offsets from the GP register in
+ SVR4_PIC mode. Currently has no meaning in other modes. */
+static int mips_big_got;
+
+/* 1 if trap instructions should used for overflow rather than break
+ instructions. */
+static int mips_trap;
+
+/* Non-zero if any .set noreorder directives were used. */
+
+static int mips_any_noreorder;
+
+/* The size of the small data section. */
+static int g_switch_value = 8;
+/* Whether the -G option was used. */
+static int g_switch_seen = 0;
+
+#define N_RMASK 0xc4
+#define N_VFP 0xd4
+
+/* If we can determine in advance that GP optimization won't be
+ possible, we can skip the relaxation stuff that tries to produce
+ GP-relative references. This makes delay slot optimization work
+ better.
+
+ This function can only provide a guess, but it seems to work for
+ gcc output. If it guesses wrong, the only loss should be in
+ efficiency; it shouldn't introduce any bugs.
+
+ I don't know if a fix is needed for the SVR4_PIC mode. I've only
+ fixed it for the non-PIC mode. KR 95/04/07 */
+static int nopic_need_relax PARAMS ((symbolS *, int));
+
+/* handle of the OPCODE hash table */
+static struct hash_control *op_hash = NULL;
+
+/* The opcode hash table we use for the mips16. */
+static struct hash_control *mips16_op_hash = NULL;
+
+/* This array holds the chars that always start a comment. If the
+ pre-processor is disabled, these aren't very useful */
+const char comment_chars[] = "#";
+
+/* This array holds the chars that only start a comment at the beginning of
+ a line. If the line seems to have the form '# 123 filename'
+ .line and .file directives will appear in the pre-processed output */
+/* Note that input_file.c hand checks for '#' at the beginning of the
+ first line of the input file. This is because the compiler outputs
+ #NO_APP at the beginning of its output. */
+/* Also note that C style comments are always supported. */
+const char line_comment_chars[] = "#";
+
+/* This array holds machine specific line separator characters. */
+const char line_separator_chars[] = "";
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* As in 0f12.456 */
+/* or 0d1.2345e12 */
+const char FLT_CHARS[] = "rRsSfFdDxXpP";
+
+/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
+ changed in read.c . Ideally it shouldn't have to know about it at all,
+ but nothing is ideal around here.
+ */
+
+static char *insn_error;
+
+static int auto_align = 1;
+
+/* When outputting SVR4 PIC code, the assembler needs to know the
+ offset in the stack frame from which to restore the $gp register.
+ This is set by the .cprestore pseudo-op, and saved in this
+ variable. */
+static offsetT mips_cprestore_offset = -1;
+
+/* This is the register which holds the stack frame, as set by the
+ .frame pseudo-op. This is needed to implement .cprestore. */
+static int mips_frame_reg = SP;
+
+/* To output NOP instructions correctly, we need to keep information
+ about the previous two instructions. */
+
+/* Whether we are optimizing. The default value of 2 means to remove
+ unneeded NOPs and swap branch instructions when possible. A value
+ of 1 means to not swap branches. A value of 0 means to always
+ insert NOPs. */
+static int mips_optimize = 2;
+
+/* Debugging level. -g sets this to 2. -gN sets this to N. -g0 is
+ equivalent to seeing no -g option at all. */
+static int mips_debug = 0;
+
+/* The previous instruction. */
+static struct mips_cl_insn prev_insn;
+
+/* The instruction before prev_insn. */
+static struct mips_cl_insn prev_prev_insn;
+
+/* If we don't want information for prev_insn or prev_prev_insn, we
+ point the insn_mo field at this dummy integer. */
+static const struct mips_opcode dummy_opcode = { 0 };
+
+/* Non-zero if prev_insn is valid. */
+static int prev_insn_valid;
+
+/* The frag for the previous instruction. */
+static struct frag *prev_insn_frag;
+
+/* The offset into prev_insn_frag for the previous instruction. */
+static long prev_insn_where;
+
+/* The reloc type for the previous instruction, if any. */
+static bfd_reloc_code_real_type prev_insn_reloc_type;
+
+/* The reloc for the previous instruction, if any. */
+static fixS *prev_insn_fixp;
+
+/* Non-zero if the previous instruction was in a delay slot. */
+static int prev_insn_is_delay_slot;
+
+/* Non-zero if the previous instruction was in a .set noreorder. */
+static int prev_insn_unreordered;
+
+/* Non-zero if the previous instruction uses an extend opcode (if
+ mips16). */
+static int prev_insn_extended;
+
+/* Non-zero if the previous previous instruction was in a .set
+ noreorder. */
+static int prev_prev_insn_unreordered;
+
+/* If this is set, it points to a frag holding nop instructions which
+ were inserted before the start of a noreorder section. If those
+ nops turn out to be unnecessary, the size of the frag can be
+ decreased. */
+static fragS *prev_nop_frag;
+
+/* The number of nop instructions we created in prev_nop_frag. */
+static int prev_nop_frag_holds;
+
+/* The number of nop instructions that we know we need in
+ prev_nop_frag. */
+static int prev_nop_frag_required;
+
+/* The number of instructions we've seen since prev_nop_frag. */
+static int prev_nop_frag_since;
+
+/* For ECOFF and ELF, relocations against symbols are done in two
+ parts, with a HI relocation and a LO relocation. Each relocation
+ has only 16 bits of space to store an addend. This means that in
+ order for the linker to handle carries correctly, it must be able
+ to locate both the HI and the LO relocation. This means that the
+ relocations must appear in order in the relocation table.
+
+ In order to implement this, we keep track of each unmatched HI
+ relocation. We then sort them so that they immediately precede the
+ corresponding LO relocation. */
+
+struct mips_hi_fixup
+{
+ /* Next HI fixup. */
+ struct mips_hi_fixup *next;
+ /* This fixup. */
+ fixS *fixp;
+ /* The section this fixup is in. */
+ segT seg;
+};
+
+/* The list of unmatched HI relocs. */
+
+static struct mips_hi_fixup *mips_hi_fixup_list;
+
+/* Map normal MIPS register numbers to mips16 register numbers. */
+
+#define X ILLEGAL_REG
+static const int mips32_to_16_reg_map[] =
+{
+ X, X, 2, 3, 4, 5, 6, 7,
+ X, X, X, X, X, X, X, X,
+ 0, 1, X, X, X, X, X, X,
+ X, X, X, X, X, X, X, X
+};
+#undef X
+
+/* Map mips16 register numbers to normal MIPS register numbers. */
+
+static const int mips16_to_32_reg_map[] =
+{
+ 16, 17, 2, 3, 4, 5, 6, 7
+};
+
+/* Since the MIPS does not have multiple forms of PC relative
+ instructions, we do not have to do relaxing as is done on other
+ platforms. However, we do have to handle GP relative addressing
+ correctly, which turns out to be a similar problem.
+
+ Every macro that refers to a symbol can occur in (at least) two
+ forms, one with GP relative addressing and one without. For
+ example, loading a global variable into a register generally uses
+ a macro instruction like this:
+ lw $4,i
+ If i can be addressed off the GP register (this is true if it is in
+ the .sbss or .sdata section, or if it is known to be smaller than
+ the -G argument) this will generate the following instruction:
+ lw $4,i($gp)
+ This instruction will use a GPREL reloc. If i can not be addressed
+ off the GP register, the following instruction sequence will be used:
+ lui $at,i
+ lw $4,i($at)
+ In this case the first instruction will have a HI16 reloc, and the
+ second reloc will have a LO16 reloc. Both relocs will be against
+ the symbol i.
+
+ The issue here is that we may not know whether i is GP addressable
+ until after we see the instruction that uses it. Therefore, we
+ want to be able to choose the final instruction sequence only at
+ the end of the assembly. This is similar to the way other
+ platforms choose the size of a PC relative instruction only at the
+ end of assembly.
+
+ When generating position independent code we do not use GP
+ addressing in quite the same way, but the issue still arises as
+ external symbols and local symbols must be handled differently.
+
+ We handle these issues by actually generating both possible
+ instruction sequences. The longer one is put in a frag_var with
+ type rs_machine_dependent. We encode what to do with the frag in
+ the subtype field. We encode (1) the number of existing bytes to
+ replace, (2) the number of new bytes to use, (3) the offset from
+ the start of the existing bytes to the first reloc we must generate
+ (that is, the offset is applied from the start of the existing
+ bytes after they are replaced by the new bytes, if any), (4) the
+ offset from the start of the existing bytes to the second reloc,
+ (5) whether a third reloc is needed (the third reloc is always four
+ bytes after the second reloc), and (6) whether to warn if this
+ variant is used (this is sometimes needed if .set nomacro or .set
+ noat is in effect). All these numbers are reasonably small.
+
+ Generating two instruction sequences must be handled carefully to
+ ensure that delay slots are handled correctly. Fortunately, there
+ are a limited number of cases. When the second instruction
+ sequence is generated, append_insn is directed to maintain the
+ existing delay slot information, so it continues to apply to any
+ code after the second instruction sequence. This means that the
+ second instruction sequence must not impose any requirements not
+ required by the first instruction sequence.
+
+ These variant frags are then handled in functions called by the
+ machine independent code. md_estimate_size_before_relax returns
+ the final size of the frag. md_convert_frag sets up the final form
+ of the frag. tc_gen_reloc adjust the first reloc and adds a second
+ one if needed. */
+#define RELAX_ENCODE(old, new, reloc1, reloc2, reloc3, warn) \
+ ((relax_substateT) \
+ (((old) << 23) \
+ | ((new) << 16) \
+ | (((reloc1) + 64) << 9) \
+ | (((reloc2) + 64) << 2) \
+ | ((reloc3) ? (1 << 1) : 0) \
+ | ((warn) ? 1 : 0)))
+#define RELAX_OLD(i) (((i) >> 23) & 0x7f)
+#define RELAX_NEW(i) (((i) >> 16) & 0x7f)
+#define RELAX_RELOC1(i) ((bfd_vma)(((i) >> 9) & 0x7f) - 64)
+#define RELAX_RELOC2(i) ((bfd_vma)(((i) >> 2) & 0x7f) - 64)
+#define RELAX_RELOC3(i) (((i) >> 1) & 1)
+#define RELAX_WARN(i) ((i) & 1)
+
+/* For mips16 code, we use an entirely different form of relaxation.
+ mips16 supports two versions of most instructions which take
+ immediate values: a small one which takes some small value, and a
+ larger one which takes a 16 bit value. Since branches also follow
+ this pattern, relaxing these values is required.
+
+ We can assemble both mips16 and normal MIPS code in a single
+ object. Therefore, we need to support this type of relaxation at
+ the same time that we support the relaxation described above. We
+ use the high bit of the subtype field to distinguish these cases.
+
+ The information we store for this type of relaxation is the
+ argument code found in the opcode file for this relocation, whether
+ the user explicitly requested a small or extended form, and whether
+ the relocation is in a jump or jal delay slot. That tells us the
+ size of the value, and how it should be stored. We also store
+ whether the fragment is considered to be extended or not. We also
+ store whether this is known to be a branch to a different section,
+ whether we have tried to relax this frag yet, and whether we have
+ ever extended a PC relative fragment because of a shift count. */
+#define RELAX_MIPS16_ENCODE(type, small, ext, dslot, jal_dslot) \
+ (0x80000000 \
+ | ((type) & 0xff) \
+ | ((small) ? 0x100 : 0) \
+ | ((ext) ? 0x200 : 0) \
+ | ((dslot) ? 0x400 : 0) \
+ | ((jal_dslot) ? 0x800 : 0))
+#define RELAX_MIPS16_P(i) (((i) & 0x80000000) != 0)
+#define RELAX_MIPS16_TYPE(i) ((i) & 0xff)
+#define RELAX_MIPS16_USER_SMALL(i) (((i) & 0x100) != 0)
+#define RELAX_MIPS16_USER_EXT(i) (((i) & 0x200) != 0)
+#define RELAX_MIPS16_DSLOT(i) (((i) & 0x400) != 0)
+#define RELAX_MIPS16_JAL_DSLOT(i) (((i) & 0x800) != 0)
+#define RELAX_MIPS16_EXTENDED(i) (((i) & 0x1000) != 0)
+#define RELAX_MIPS16_MARK_EXTENDED(i) ((i) | 0x1000)
+#define RELAX_MIPS16_CLEAR_EXTENDED(i) ((i) &~ 0x1000)
+#define RELAX_MIPS16_LONG_BRANCH(i) (((i) & 0x2000) != 0)
+#define RELAX_MIPS16_MARK_LONG_BRANCH(i) ((i) | 0x2000)
+#define RELAX_MIPS16_CLEAR_LONG_BRANCH(i) ((i) &~ 0x2000)
+
+/* Prototypes for static functions. */
+
+#ifdef __STDC__
+#define internalError() \
+ as_fatal (_("internal Error, line %d, %s"), __LINE__, __FILE__)
+#else
+#define internalError() as_fatal (_("MIPS internal Error"));
+#endif
+
+enum mips_regclass { MIPS_GR_REG, MIPS_FP_REG, MIPS16_REG };
+
+static int insn_uses_reg PARAMS ((struct mips_cl_insn *ip,
+ unsigned int reg, enum mips_regclass class));
+static int reg_needs_delay PARAMS ((int));
+static void mips16_mark_labels PARAMS ((void));
+static void append_insn PARAMS ((char *place,
+ struct mips_cl_insn * ip,
+ expressionS * p,
+ bfd_reloc_code_real_type r,
+ boolean));
+static void mips_no_prev_insn PARAMS ((int));
+static void mips_emit_delays PARAMS ((boolean));
+#ifdef USE_STDARG
+static void macro_build PARAMS ((char *place, int *counter, expressionS * ep,
+ const char *name, const char *fmt,
+ ...));
+#else
+static void macro_build ();
+#endif
+static void mips16_macro_build PARAMS ((char *, int *, expressionS *,
+ const char *, const char *,
+ va_list));
+static void macro_build_lui PARAMS ((char *place, int *counter,
+ expressionS * ep, int regnum));
+static void set_at PARAMS ((int *counter, int reg, int unsignedp));
+static void check_absolute_expr PARAMS ((struct mips_cl_insn * ip,
+ expressionS *));
+static void load_register PARAMS ((int *, int, expressionS *, int));
+static void load_address PARAMS ((int *counter, int reg, expressionS *ep));
+static void macro PARAMS ((struct mips_cl_insn * ip));
+static void mips16_macro PARAMS ((struct mips_cl_insn * ip));
+#ifdef LOSING_COMPILER
+static void macro2 PARAMS ((struct mips_cl_insn * ip));
+#endif
+static void mips_ip PARAMS ((char *str, struct mips_cl_insn * ip));
+static void mips16_ip PARAMS ((char *str, struct mips_cl_insn * ip));
+static void mips16_immed PARAMS ((char *, unsigned int, int, offsetT, boolean,
+ boolean, boolean, unsigned long *,
+ boolean *, unsigned short *));
+static int my_getSmallExpression PARAMS ((expressionS * ep, char *str));
+static void my_getExpression PARAMS ((expressionS * ep, char *str));
+static symbolS *get_symbol PARAMS ((void));
+static void mips_align PARAMS ((int to, int fill, symbolS *label));
+static void s_align PARAMS ((int));
+static void s_change_sec PARAMS ((int));
+static void s_cons PARAMS ((int));
+static void s_float_cons PARAMS ((int));
+static void s_mips_globl PARAMS ((int));
+static void s_option PARAMS ((int));
+static void s_mipsset PARAMS ((int));
+static void s_abicalls PARAMS ((int));
+static void s_cpload PARAMS ((int));
+static void s_cprestore PARAMS ((int));
+static void s_gpword PARAMS ((int));
+static void s_cpadd PARAMS ((int));
+static void s_insn PARAMS ((int));
+static void md_obj_begin PARAMS ((void));
+static void md_obj_end PARAMS ((void));
+static long get_number PARAMS ((void));
+static void s_mips_ent PARAMS ((int));
+static void s_mips_end PARAMS ((int));
+static void s_mips_frame PARAMS ((int));
+static void s_mips_mask PARAMS ((int));
+static void s_mips_stab PARAMS ((int));
+static void s_mips_weakext PARAMS ((int));
+static void s_file PARAMS ((int));
+static int mips16_extended_frag PARAMS ((fragS *, asection *, long));
+
+
+static int validate_mips_insn PARAMS ((const struct mips_opcode *));
+
+/* Pseudo-op table.
+
+ The following pseudo-ops from the Kane and Heinrich MIPS book
+ should be defined here, but are currently unsupported: .alias,
+ .galive, .gjaldef, .gjrlive, .livereg, .noalias.
+
+ The following pseudo-ops from the Kane and Heinrich MIPS book are
+ specific to the type of debugging information being generated, and
+ should be defined by the object format: .aent, .begin, .bend,
+ .bgnb, .end, .endb, .ent, .fmask, .frame, .loc, .mask, .verstamp,
+ .vreg.
+
+ The following pseudo-ops from the Kane and Heinrich MIPS book are
+ not MIPS CPU specific, but are also not specific to the object file
+ format. This file is probably the best place to define them, but
+ they are not currently supported: .asm0, .endr, .lab, .repeat,
+ .struct. */
+
+static const pseudo_typeS mips_pseudo_table[] =
+{
+ /* MIPS specific pseudo-ops. */
+ {"option", s_option, 0},
+ {"set", s_mipsset, 0},
+ {"rdata", s_change_sec, 'r'},
+ {"sdata", s_change_sec, 's'},
+ {"livereg", s_ignore, 0},
+ {"abicalls", s_abicalls, 0},
+ {"cpload", s_cpload, 0},
+ {"cprestore", s_cprestore, 0},
+ {"gpword", s_gpword, 0},
+ {"cpadd", s_cpadd, 0},
+ {"insn", s_insn, 0},
+
+ /* Relatively generic pseudo-ops that happen to be used on MIPS
+ chips. */
+ {"asciiz", stringer, 1},
+ {"bss", s_change_sec, 'b'},
+ {"err", s_err, 0},
+ {"half", s_cons, 1},
+ {"dword", s_cons, 3},
+ {"weakext", s_mips_weakext, 0},
+
+ /* These pseudo-ops are defined in read.c, but must be overridden
+ here for one reason or another. */
+ {"align", s_align, 0},
+ {"byte", s_cons, 0},
+ {"data", s_change_sec, 'd'},
+ {"double", s_float_cons, 'd'},
+ {"float", s_float_cons, 'f'},
+ {"globl", s_mips_globl, 0},
+ {"global", s_mips_globl, 0},
+ {"hword", s_cons, 1},
+ {"int", s_cons, 2},
+ {"long", s_cons, 2},
+ {"octa", s_cons, 4},
+ {"quad", s_cons, 3},
+ {"short", s_cons, 1},
+ {"single", s_float_cons, 'f'},
+ {"stabn", s_mips_stab, 'n'},
+ {"text", s_change_sec, 't'},
+ {"word", s_cons, 2},
+ { 0 },
+};
+
+static const pseudo_typeS mips_nonecoff_pseudo_table[] = {
+ /* These pseudo-ops should be defined by the object file format.
+ However, a.out doesn't support them, so we have versions here. */
+ {"aent", s_mips_ent, 1},
+ {"bgnb", s_ignore, 0},
+ {"end", s_mips_end, 0},
+ {"endb", s_ignore, 0},
+ {"ent", s_mips_ent, 0},
+ {"file", s_file, 0},
+ {"fmask", s_mips_mask, 'F'},
+ {"frame", s_mips_frame, 0},
+ {"loc", s_ignore, 0},
+ {"mask", s_mips_mask, 'R'},
+ {"verstamp", s_ignore, 0},
+ { 0 },
+};
+
+extern void pop_insert PARAMS ((const pseudo_typeS *));
+
+void
+mips_pop_insert ()
+{
+ pop_insert (mips_pseudo_table);
+ if (! ECOFF_DEBUGGING)
+ pop_insert (mips_nonecoff_pseudo_table);
+}
+
+/* Symbols labelling the current insn. */
+
+struct insn_label_list
+{
+ struct insn_label_list *next;
+ symbolS *label;
+};
+
+static struct insn_label_list *insn_labels;
+static struct insn_label_list *free_insn_labels;
+
+static void mips_clear_insn_labels PARAMS ((void));
+
+static inline void
+mips_clear_insn_labels ()
+{
+ register struct insn_label_list **pl;
+
+ for (pl = &free_insn_labels; *pl != NULL; pl = &(*pl)->next)
+ ;
+ *pl = insn_labels;
+ insn_labels = NULL;
+}
+
+static char *expr_end;
+
+/* Expressions which appear in instructions. These are set by
+ mips_ip. */
+
+static expressionS imm_expr;
+static expressionS offset_expr;
+
+/* Relocs associated with imm_expr and offset_expr. */
+
+static bfd_reloc_code_real_type imm_reloc;
+static bfd_reloc_code_real_type offset_reloc;
+
+/* This is set by mips_ip if imm_reloc is an unmatched HI16_S reloc. */
+
+static boolean imm_unmatched_hi;
+
+/* These are set by mips16_ip if an explicit extension is used. */
+
+static boolean mips16_small, mips16_ext;
+
+#ifdef MIPS_STABS_ELF
+/* The pdr segment for per procedure frame/regmask info */
+
+static segT pdr_seg;
+#endif
+
+/*
+ * This function is called once, at assembler startup time. It should
+ * set up all the tables, etc. that the MD part of the assembler will need.
+ */
+void
+md_begin ()
+{
+ boolean ok = false;
+ register const char *retval = NULL;
+ register unsigned int i = 0;
+ const char *cpu;
+ char *a = NULL;
+ int broken = 0;
+ int mips_isa_from_cpu;
+
+ cpu = TARGET_CPU;
+ if (strcmp (cpu + (sizeof TARGET_CPU) - 3, "el") == 0)
+ {
+ a = xmalloc (sizeof TARGET_CPU);
+ strcpy (a, TARGET_CPU);
+ a[(sizeof TARGET_CPU) - 3] = '\0';
+ cpu = a;
+ }
+
+ if (mips_cpu < 0)
+ {
+ /* Set mips_cpu based on TARGET_CPU, unless TARGET_CPU is
+ just the generic 'mips', in which case set mips_cpu based
+ on the given ISA, if any. */
+
+ if (strcmp (cpu, "mips") == 0)
+ {
+ if (mips_opts.isa < 0)
+ mips_cpu = 3000;
+
+ else if (mips_opts.isa == 2)
+ mips_cpu = 6000;
+
+ else if (mips_opts.isa == 3)
+ mips_cpu = 4000;
+
+ else if (mips_opts.isa == 4)
+ mips_cpu = 8000;
+
+ else
+ mips_cpu = 3000;
+ }
+
+ else if (strcmp (cpu, "r3900") == 0
+ || strcmp (cpu, "mipstx39") == 0
+ )
+ mips_cpu = 3900;
+
+ else if (strcmp (cpu, "r6000") == 0
+ || strcmp (cpu, "mips2") == 0)
+ mips_cpu = 6000;
+
+ else if (strcmp (cpu, "mips64") == 0
+ || strcmp (cpu, "r4000") == 0
+ || strcmp (cpu, "mips3") == 0)
+ mips_cpu = 4000;
+
+ else if (strcmp (cpu, "r4400") == 0)
+ mips_cpu = 4400;
+
+ else if (strcmp (cpu, "mips64orion") == 0
+ || strcmp (cpu, "r4600") == 0)
+ mips_cpu = 4600;
+
+ else if (strcmp (cpu, "r4650") == 0)
+ mips_cpu = 4650;
+
+ else if (strcmp (cpu, "mips64vr4300") == 0)
+ mips_cpu = 4300;
+
+ else if (strcmp (cpu, "mips64vr4111") == 0)
+ mips_cpu = 4111;
+
+ else if (strcmp (cpu, "mips64vr4100") == 0)
+ mips_cpu = 4100;
+
+ else if (strcmp (cpu, "r4010") == 0)
+ mips_cpu = 4010;
+
+
+ else if (strcmp (cpu, "r5000") == 0
+ || strcmp (cpu, "mips64vr5000") == 0)
+ mips_cpu = 5000;
+
+
+
+ else if (strcmp (cpu, "r8000") == 0
+ || strcmp (cpu, "mips4") == 0)
+ mips_cpu = 8000;
+
+ else if (strcmp (cpu, "r10000") == 0)
+ mips_cpu = 10000;
+
+ else if (strcmp (cpu, "mips16") == 0)
+ mips_cpu = 0; /* FIXME */
+
+ else
+ mips_cpu = 3000;
+ }
+
+ if (mips_cpu == 3000
+ || mips_cpu == 3900)
+ mips_isa_from_cpu = 1;
+
+ else if (mips_cpu == 6000
+ || mips_cpu == 4010)
+ mips_isa_from_cpu = 2;
+
+ else if (mips_cpu == 4000
+ || mips_cpu == 4100
+ || mips_cpu == 4111
+ || mips_cpu == 4400
+ || mips_cpu == 4300
+ || mips_cpu == 4600
+ || mips_cpu == 4650)
+ mips_isa_from_cpu = 3;
+
+ else if (mips_cpu == 5000
+ || mips_cpu == 8000
+ || mips_cpu == 10000)
+ mips_isa_from_cpu = 4;
+
+ else
+ mips_isa_from_cpu = -1;
+
+ if (mips_opts.isa == -1)
+ {
+ if (mips_isa_from_cpu != -1)
+ mips_opts.isa = mips_isa_from_cpu;
+ else
+ mips_opts.isa = 1;
+ }
+
+ if (mips_opts.mips16 < 0)
+ {
+ if (strncmp (TARGET_CPU, "mips16", sizeof "mips16" - 1) == 0)
+ mips_opts.mips16 = 1;
+ else
+ mips_opts.mips16 = 0;
+ }
+
+ /* End of TARGET_CPU processing, get rid of malloced memory
+ if necessary. */
+ cpu = NULL;
+ if (a != NULL)
+ {
+ free (a);
+ a = NULL;
+ }
+
+ if (mips_opts.isa < 2 && mips_trap)
+ as_bad (_("trap exception not supported at ISA 1"));
+
+ /* Set the EABI kind based on the ISA before the user gets
+ to change the ISA with directives. This isn't really
+ the best, but then neither is basing the abi on the isa. */
+ if (mips_opts.isa > 2
+ && mips_abi_string
+ && 0 == strcmp (mips_abi_string,"eabi"))
+ mips_eabi64 = 1;
+
+ if (mips_cpu != 0 && mips_cpu != -1)
+ {
+ ok = bfd_set_arch_mach (stdoutput, bfd_arch_mips, mips_cpu);
+
+ /* If they asked for mips1 or mips2 and a cpu that is
+ mips3 or greater, then mark the object file 32BITMODE. */
+ if (mips_isa_from_cpu != -1
+ && mips_opts.isa <= 2 && mips_isa_from_cpu > 2)
+ mips_32bitmode = 1;
+ }
+ else
+ {
+ switch (mips_opts.isa)
+ {
+ case 1:
+ ok = bfd_set_arch_mach (stdoutput, bfd_arch_mips, 3000);
+ break;
+ case 2:
+ ok = bfd_set_arch_mach (stdoutput, bfd_arch_mips, 6000);
+ break;
+ case 3:
+ ok = bfd_set_arch_mach (stdoutput, bfd_arch_mips, 4000);
+ break;
+ case 4:
+ ok = bfd_set_arch_mach (stdoutput, bfd_arch_mips, 8000);
+ break;
+ }
+ }
+
+ if (! ok)
+ as_warn (_("Could not set architecture and machine"));
+
+ file_mips_isa = mips_opts.isa;
+
+ op_hash = hash_new ();
+
+ for (i = 0; i < NUMOPCODES;)
+ {
+ const char *name = mips_opcodes[i].name;
+
+ retval = hash_insert (op_hash, name, (PTR) &mips_opcodes[i]);
+ if (retval != NULL)
+ {
+ fprintf (stderr, _("internal error: can't hash `%s': %s\n"),
+ mips_opcodes[i].name, retval);
+ /* Probably a memory allocation problem? Give up now. */
+ as_fatal (_("Broken assembler. No assembly attempted."));
+ }
+ do
+ {
+ if (mips_opcodes[i].pinfo != INSN_MACRO)
+ {
+ if (!validate_mips_insn (&mips_opcodes[i]))
+ broken = 1;
+ }
+ ++i;
+ }
+ while ((i < NUMOPCODES) && !strcmp (mips_opcodes[i].name, name));
+ }
+
+ mips16_op_hash = hash_new ();
+
+ i = 0;
+ while (i < bfd_mips16_num_opcodes)
+ {
+ const char *name = mips16_opcodes[i].name;
+
+ retval = hash_insert (mips16_op_hash, name, (PTR) &mips16_opcodes[i]);
+ if (retval != NULL)
+ as_fatal (_("internal: can't hash `%s': %s"),
+ mips16_opcodes[i].name, retval);
+ do
+ {
+ if (mips16_opcodes[i].pinfo != INSN_MACRO
+ && ((mips16_opcodes[i].match & mips16_opcodes[i].mask)
+ != mips16_opcodes[i].match))
+ {
+ fprintf (stderr, _("internal error: bad mips16 opcode: %s %s\n"),
+ mips16_opcodes[i].name, mips16_opcodes[i].args);
+ broken = 1;
+ }
+ ++i;
+ }
+ while (i < bfd_mips16_num_opcodes
+ && strcmp (mips16_opcodes[i].name, name) == 0);
+ }
+
+ if (broken)
+ as_fatal (_("Broken assembler. No assembly attempted."));
+
+ /* We add all the general register names to the symbol table. This
+ helps us detect invalid uses of them. */
+ for (i = 0; i < 32; i++)
+ {
+ char buf[5];
+
+ sprintf (buf, "$%d", i);
+ symbol_table_insert (symbol_new (buf, reg_section, i,
+ &zero_address_frag));
+ }
+ symbol_table_insert (symbol_new ("$fp", reg_section, FP,
+ &zero_address_frag));
+ symbol_table_insert (symbol_new ("$sp", reg_section, SP,
+ &zero_address_frag));
+ symbol_table_insert (symbol_new ("$gp", reg_section, GP,
+ &zero_address_frag));
+ symbol_table_insert (symbol_new ("$at", reg_section, AT,
+ &zero_address_frag));
+ symbol_table_insert (symbol_new ("$kt0", reg_section, KT0,
+ &zero_address_frag));
+ symbol_table_insert (symbol_new ("$kt1", reg_section, KT1,
+ &zero_address_frag));
+ symbol_table_insert (symbol_new ("$pc", reg_section, -1,
+ &zero_address_frag));
+
+ mips_no_prev_insn (false);
+
+ mips_gprmask = 0;
+ mips_cprmask[0] = 0;
+ mips_cprmask[1] = 0;
+ mips_cprmask[2] = 0;
+ mips_cprmask[3] = 0;
+
+ /* set the default alignment for the text section (2**2) */
+ record_alignment (text_section, 2);
+
+ if (USE_GLOBAL_POINTER_OPT)
+ bfd_set_gp_size (stdoutput, g_switch_value);
+
+ if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
+ {
+ /* On a native system, sections must be aligned to 16 byte
+ boundaries. When configured for an embedded ELF target, we
+ don't bother. */
+ if (strcmp (TARGET_OS, "elf") != 0)
+ {
+ (void) bfd_set_section_alignment (stdoutput, text_section, 4);
+ (void) bfd_set_section_alignment (stdoutput, data_section, 4);
+ (void) bfd_set_section_alignment (stdoutput, bss_section, 4);
+ }
+
+ /* Create a .reginfo section for register masks and a .mdebug
+ section for debugging information. */
+ {
+ segT seg;
+ subsegT subseg;
+ flagword flags;
+ segT sec;
+
+ seg = now_seg;
+ subseg = now_subseg;
+
+ /* The ABI says this section should be loaded so that the
+ running program can access it. However, we don't load it
+ if we are configured for an embedded target */
+ flags = SEC_READONLY | SEC_DATA;
+ if (strcmp (TARGET_OS, "elf") != 0)
+ flags |= SEC_ALLOC | SEC_LOAD;
+
+ if (! mips_64)
+ {
+ sec = subseg_new (".reginfo", (subsegT) 0);
+
+
+ (void) bfd_set_section_flags (stdoutput, sec, flags);
+ (void) bfd_set_section_alignment (stdoutput, sec, 2);
+
+#ifdef OBJ_ELF
+ mips_regmask_frag = frag_more (sizeof (Elf32_External_RegInfo));
+#endif
+ }
+ else
+ {
+ /* The 64-bit ABI uses a .MIPS.options section rather than
+ .reginfo section. */
+ sec = subseg_new (".MIPS.options", (subsegT) 0);
+ (void) bfd_set_section_flags (stdoutput, sec, flags);
+ (void) bfd_set_section_alignment (stdoutput, sec, 3);
+
+#ifdef OBJ_ELF
+ /* Set up the option header. */
+ {
+ Elf_Internal_Options opthdr;
+ char *f;
+
+ opthdr.kind = ODK_REGINFO;
+ opthdr.size = (sizeof (Elf_External_Options)
+ + sizeof (Elf64_External_RegInfo));
+ opthdr.section = 0;
+ opthdr.info = 0;
+ f = frag_more (sizeof (Elf_External_Options));
+ bfd_mips_elf_swap_options_out (stdoutput, &opthdr,
+ (Elf_External_Options *) f);
+
+ mips_regmask_frag = frag_more (sizeof (Elf64_External_RegInfo));
+ }
+#endif
+ }
+
+ if (ECOFF_DEBUGGING)
+ {
+ sec = subseg_new (".mdebug", (subsegT) 0);
+ (void) bfd_set_section_flags (stdoutput, sec,
+ SEC_HAS_CONTENTS | SEC_READONLY);
+ (void) bfd_set_section_alignment (stdoutput, sec, 2);
+ }
+
+#ifdef MIPS_STABS_ELF
+ pdr_seg = subseg_new (".pdr", (subsegT) 0);
+ (void) bfd_set_section_flags (stdoutput, pdr_seg,
+ SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
+ (void) bfd_set_section_alignment (stdoutput, pdr_seg, 2);
+#endif
+
+ subseg_set (seg, subseg);
+ }
+ }
+
+ if (! ECOFF_DEBUGGING)
+ md_obj_begin ();
+}
+
+void
+md_mips_end ()
+{
+ if (! ECOFF_DEBUGGING)
+ md_obj_end ();
+}
+
+void
+md_assemble (str)
+ char *str;
+{
+ struct mips_cl_insn insn;
+
+ imm_expr.X_op = O_absent;
+ imm_reloc = BFD_RELOC_UNUSED;
+ imm_unmatched_hi = false;
+ offset_expr.X_op = O_absent;
+ offset_reloc = BFD_RELOC_UNUSED;
+
+ if (mips_opts.mips16)
+ mips16_ip (str, &insn);
+ else
+ {
+ mips_ip (str, &insn);
+ DBG((_("returned from mips_ip(%s) insn_opcode = 0x%x\n"),
+ str, insn.insn_opcode));
+ }
+
+ if (insn_error)
+ {
+ as_bad ("%s `%s'", insn_error, str);
+ return;
+ }
+
+ if (insn.insn_mo->pinfo == INSN_MACRO)
+ {
+ if (mips_opts.mips16)
+ mips16_macro (&insn);
+ else
+ macro (&insn);
+ }
+ else
+ {
+ if (imm_expr.X_op != O_absent)
+ append_insn ((char *) NULL, &insn, &imm_expr, imm_reloc,
+ imm_unmatched_hi);
+ else if (offset_expr.X_op != O_absent)
+ append_insn ((char *) NULL, &insn, &offset_expr, offset_reloc, false);
+ else
+ append_insn ((char *) NULL, &insn, NULL, BFD_RELOC_UNUSED, false);
+ }
+}
+
+/* See whether instruction IP reads register REG. CLASS is the type
+ of register. */
+
+static int
+insn_uses_reg (ip, reg, class)
+ struct mips_cl_insn *ip;
+ unsigned int reg;
+ enum mips_regclass class;
+{
+ if (class == MIPS16_REG)
+ {
+ assert (mips_opts.mips16);
+ reg = mips16_to_32_reg_map[reg];
+ class = MIPS_GR_REG;
+ }
+
+ /* Don't report on general register 0, since it never changes. */
+ if (class == MIPS_GR_REG && reg == 0)
+ return 0;
+
+ if (class == MIPS_FP_REG)
+ {
+ assert (! mips_opts.mips16);
+ /* If we are called with either $f0 or $f1, we must check $f0.
+ This is not optimal, because it will introduce an unnecessary
+ NOP between "lwc1 $f0" and "swc1 $f1". To fix this we would
+ need to distinguish reading both $f0 and $f1 or just one of
+ them. Note that we don't have to check the other way,
+ because there is no instruction that sets both $f0 and $f1
+ and requires a delay. */
+ if ((ip->insn_mo->pinfo & INSN_READ_FPR_S)
+ && ((((ip->insn_opcode >> OP_SH_FS) & OP_MASK_FS) &~(unsigned)1)
+ == (reg &~ (unsigned) 1)))
+ return 1;
+ if ((ip->insn_mo->pinfo & INSN_READ_FPR_T)
+ && ((((ip->insn_opcode >> OP_SH_FT) & OP_MASK_FT) &~(unsigned)1)
+ == (reg &~ (unsigned) 1)))
+ return 1;
+ }
+ else if (! mips_opts.mips16)
+ {
+ if ((ip->insn_mo->pinfo & INSN_READ_GPR_S)
+ && ((ip->insn_opcode >> OP_SH_RS) & OP_MASK_RS) == reg)
+ return 1;
+ if ((ip->insn_mo->pinfo & INSN_READ_GPR_T)
+ && ((ip->insn_opcode >> OP_SH_RT) & OP_MASK_RT) == reg)
+ return 1;
+ }
+ else
+ {
+ if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_X)
+ && (mips16_to_32_reg_map[((ip->insn_opcode >> MIPS16OP_SH_RX)
+ & MIPS16OP_MASK_RX)]
+ == reg))
+ return 1;
+ if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_Y)
+ && (mips16_to_32_reg_map[((ip->insn_opcode >> MIPS16OP_SH_RY)
+ & MIPS16OP_MASK_RY)]
+ == reg))
+ return 1;
+ if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_Z)
+ && (mips16_to_32_reg_map[((ip->insn_opcode >> MIPS16OP_SH_MOVE32Z)
+ & MIPS16OP_MASK_MOVE32Z)]
+ == reg))
+ return 1;
+ if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_T) && reg == TREG)
+ return 1;
+ if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_SP) && reg == SP)
+ return 1;
+ if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_31) && reg == RA)
+ return 1;
+ if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_GPR_X)
+ && ((ip->insn_opcode >> MIPS16OP_SH_REGR32)
+ & MIPS16OP_MASK_REGR32) == reg)
+ return 1;
+ }
+
+ return 0;
+}
+
+/* This function returns true if modifying a register requires a
+ delay. */
+
+static int
+reg_needs_delay (reg)
+ int reg;
+{
+ unsigned long prev_pinfo;
+
+ prev_pinfo = prev_insn.insn_mo->pinfo;
+ if (! mips_opts.noreorder
+ && mips_opts.isa < 4
+ && ((prev_pinfo & INSN_LOAD_COPROC_DELAY)
+ || (! gpr_interlocks
+ && (prev_pinfo & INSN_LOAD_MEMORY_DELAY))))
+ {
+ /* A load from a coprocessor or from memory. All load
+ delays delay the use of general register rt for one
+ instruction on the r3000. The r6000 and r4000 use
+ interlocks. */
+ /* Itbl support may require additional care here. */
+ know (prev_pinfo & INSN_WRITE_GPR_T);
+ if (reg == ((prev_insn.insn_opcode >> OP_SH_RT) & OP_MASK_RT))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Mark instruction labels in mips16 mode. This permits the linker to
+ handle them specially, such as generating jalx instructions when
+ needed. We also make them odd for the duration of the assembly, in
+ order to generate the right sort of code. We will make them even
+ in the adjust_symtab routine, while leaving them marked. This is
+ convenient for the debugger and the disassembler. The linker knows
+ to make them odd again. */
+
+static void
+mips16_mark_labels ()
+{
+ if (mips_opts.mips16)
+ {
+ struct insn_label_list *l;
+
+ for (l = insn_labels; l != NULL; l = l->next)
+ {
+#ifdef OBJ_ELF
+ if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
+ S_SET_OTHER (l->label, STO_MIPS16);
+#endif
+ if ((l->label->sy_value.X_add_number & 1) == 0)
+ ++l->label->sy_value.X_add_number;
+ }
+ }
+}
+
+/* Output an instruction. PLACE is where to put the instruction; if
+ it is NULL, this uses frag_more to get room. IP is the instruction
+ information. ADDRESS_EXPR is an operand of the instruction to be
+ used with RELOC_TYPE. */
+
+static void
+append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
+ char *place;
+ struct mips_cl_insn *ip;
+ expressionS *address_expr;
+ bfd_reloc_code_real_type reloc_type;
+ boolean unmatched_hi;
+{
+ register unsigned long prev_pinfo, pinfo;
+ char *f;
+ fixS *fixp;
+ int nops = 0;
+
+ /* Mark instruction labels in mips16 mode. */
+ if (mips_opts.mips16)
+ mips16_mark_labels ();
+
+ prev_pinfo = prev_insn.insn_mo->pinfo;
+ pinfo = ip->insn_mo->pinfo;
+
+ if (place == NULL && (! mips_opts.noreorder || prev_nop_frag != NULL))
+ {
+ int prev_prev_nop;
+
+ /* If the previous insn required any delay slots, see if we need
+ to insert a NOP or two. There are eight kinds of possible
+ hazards, of which an instruction can have at most one type.
+ (1) a load from memory delay
+ (2) a load from a coprocessor delay
+ (3) an unconditional branch delay
+ (4) a conditional branch delay
+ (5) a move to coprocessor register delay
+ (6) a load coprocessor register from memory delay
+ (7) a coprocessor condition code delay
+ (8) a HI/LO special register delay
+
+ There are a lot of optimizations we could do that we don't.
+ In particular, we do not, in general, reorder instructions.
+ If you use gcc with optimization, it will reorder
+ instructions and generally do much more optimization then we
+ do here; repeating all that work in the assembler would only
+ benefit hand written assembly code, and does not seem worth
+ it. */
+
+ /* This is how a NOP is emitted. */
+#define emit_nop() \
+ (mips_opts.mips16 \
+ ? md_number_to_chars (frag_more (2), 0x6500, 2) \
+ : md_number_to_chars (frag_more (4), 0, 4))
+
+ /* The previous insn might require a delay slot, depending upon
+ the contents of the current insn. */
+ if (! mips_opts.mips16
+ && mips_opts.isa < 4
+ && (((prev_pinfo & INSN_LOAD_COPROC_DELAY)
+ && ! cop_interlocks)
+ || (! gpr_interlocks
+ && (prev_pinfo & INSN_LOAD_MEMORY_DELAY))))
+ {
+ /* A load from a coprocessor or from memory. All load
+ delays delay the use of general register rt for one
+ instruction on the r3000. The r6000 and r4000 use
+ interlocks. */
+ /* Itbl support may require additional care here. */
+ know (prev_pinfo & INSN_WRITE_GPR_T);
+ if (mips_optimize == 0
+ || insn_uses_reg (ip,
+ ((prev_insn.insn_opcode >> OP_SH_RT)
+ & OP_MASK_RT),
+ MIPS_GR_REG))
+ ++nops;
+ }
+ else if (! mips_opts.mips16
+ && mips_opts.isa < 4
+ && (((prev_pinfo & INSN_COPROC_MOVE_DELAY)
+ && ! cop_interlocks)
+ || (mips_opts.isa < 2
+ && (prev_pinfo & INSN_COPROC_MEMORY_DELAY))))
+ {
+ /* A generic coprocessor delay. The previous instruction
+ modified a coprocessor general or control register. If
+ it modified a control register, we need to avoid any
+ coprocessor instruction (this is probably not always
+ required, but it sometimes is). If it modified a general
+ register, we avoid using that register.
+
+ On the r6000 and r4000 loading a coprocessor register
+ from memory is interlocked, and does not require a delay.
+
+ This case is not handled very well. There is no special
+ knowledge of CP0 handling, and the coprocessors other
+ than the floating point unit are not distinguished at
+ all. */
+ /* Itbl support may require additional care here. FIXME!
+ Need to modify this to include knowledge about
+ user specified delays! */
+ if (prev_pinfo & INSN_WRITE_FPR_T)
+ {
+ if (mips_optimize == 0
+ || insn_uses_reg (ip,
+ ((prev_insn.insn_opcode >> OP_SH_FT)
+ & OP_MASK_FT),
+ MIPS_FP_REG))
+ ++nops;
+ }
+ else if (prev_pinfo & INSN_WRITE_FPR_S)
+ {
+ if (mips_optimize == 0
+ || insn_uses_reg (ip,
+ ((prev_insn.insn_opcode >> OP_SH_FS)
+ & OP_MASK_FS),
+ MIPS_FP_REG))
+ ++nops;
+ }
+ else
+ {
+ /* We don't know exactly what the previous instruction
+ does. If the current instruction uses a coprocessor
+ register, we must insert a NOP. If previous
+ instruction may set the condition codes, and the
+ current instruction uses them, we must insert two
+ NOPS. */
+ /* Itbl support may require additional care here. */
+ if (mips_optimize == 0
+ || ((prev_pinfo & INSN_WRITE_COND_CODE)
+ && (pinfo & INSN_READ_COND_CODE)))
+ nops += 2;
+ else if (pinfo & INSN_COP)
+ ++nops;
+ }
+ }
+ else if (! mips_opts.mips16
+ && mips_opts.isa < 4
+ && (prev_pinfo & INSN_WRITE_COND_CODE)
+ && ! cop_interlocks)
+ {
+ /* The previous instruction sets the coprocessor condition
+ codes, but does not require a general coprocessor delay
+ (this means it is a floating point comparison
+ instruction). If this instruction uses the condition
+ codes, we need to insert a single NOP. */
+ /* Itbl support may require additional care here. */
+ if (mips_optimize == 0
+ || (pinfo & INSN_READ_COND_CODE))
+ ++nops;
+ }
+ else if (prev_pinfo & INSN_READ_LO)
+ {
+ /* The previous instruction reads the LO register; if the
+ current instruction writes to the LO register, we must
+ insert two NOPS. Some newer processors have interlocks.
+ Also the tx39's multiply instructions can be exectuted
+ immediatly after a read from HI/LO (without the delay),
+ though the tx39's divide insns still do require the
+ delay. */
+ if (! (hilo_interlocks
+ || (mips_cpu == 3900 && (pinfo & INSN_MULT)))
+ && (mips_optimize == 0
+ || (pinfo & INSN_WRITE_LO)))
+ nops += 2;
+ /* Most mips16 branch insns don't have a delay slot.
+ If a read from LO is immediately followed by a branch
+ to a write to LO we have a read followed by a write
+ less than 2 insns away. We assume the target of
+ a branch might be a write to LO, and insert a nop
+ between a read and an immediately following branch. */
+ else if (mips_opts.mips16
+ && (mips_optimize == 0
+ || (pinfo & MIPS16_INSN_BRANCH)))
+ nops += 1;
+ }
+ else if (prev_insn.insn_mo->pinfo & INSN_READ_HI)
+ {
+ /* The previous instruction reads the HI register; if the
+ current instruction writes to the HI register, we must
+ insert a NOP. Some newer processors have interlocks.
+ Also the note tx39's multiply above. */
+ if (! (hilo_interlocks
+ || (mips_cpu == 3900 && (pinfo & INSN_MULT)))
+ && (mips_optimize == 0
+ || (pinfo & INSN_WRITE_HI)))
+ nops += 2;
+ /* Most mips16 branch insns don't have a delay slot.
+ If a read from HI is immediately followed by a branch
+ to a write to HI we have a read followed by a write
+ less than 2 insns away. We assume the target of
+ a branch might be a write to HI, and insert a nop
+ between a read and an immediately following branch. */
+ else if (mips_opts.mips16
+ && (mips_optimize == 0
+ || (pinfo & MIPS16_INSN_BRANCH)))
+ nops += 1;
+ }
+
+ /* If the previous instruction was in a noreorder section, then
+ we don't want to insert the nop after all. */
+ /* Itbl support may require additional care here. */
+ if (prev_insn_unreordered)
+ nops = 0;
+
+ /* There are two cases which require two intervening
+ instructions: 1) setting the condition codes using a move to
+ coprocessor instruction which requires a general coprocessor
+ delay and then reading the condition codes 2) reading the HI
+ or LO register and then writing to it (except on processors
+ which have interlocks). If we are not already emitting a NOP
+ instruction, we must check for these cases compared to the
+ instruction previous to the previous instruction. */
+ if ((! mips_opts.mips16
+ && mips_opts.isa < 4
+ && (prev_prev_insn.insn_mo->pinfo & INSN_COPROC_MOVE_DELAY)
+ && (prev_prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE)
+ && (pinfo & INSN_READ_COND_CODE)
+ && ! cop_interlocks)
+ || ((prev_prev_insn.insn_mo->pinfo & INSN_READ_LO)
+ && (pinfo & INSN_WRITE_LO)
+ && ! (hilo_interlocks
+ || (mips_cpu == 3900 && (pinfo & INSN_MULT))))
+ || ((prev_prev_insn.insn_mo->pinfo & INSN_READ_HI)
+ && (pinfo & INSN_WRITE_HI)
+ && ! (hilo_interlocks
+ || (mips_cpu == 3900 && (pinfo & INSN_MULT)))))
+ prev_prev_nop = 1;
+ else
+ prev_prev_nop = 0;
+
+ if (prev_prev_insn_unreordered)
+ prev_prev_nop = 0;
+
+ if (prev_prev_nop && nops == 0)
+ ++nops;
+
+ /* If we are being given a nop instruction, don't bother with
+ one of the nops we would otherwise output. This will only
+ happen when a nop instruction is used with mips_optimize set
+ to 0. */
+ if (nops > 0
+ && ! mips_opts.noreorder
+ && ip->insn_opcode == (mips_opts.mips16 ? 0x6500 : 0))
+ --nops;
+
+ /* Now emit the right number of NOP instructions. */
+ if (nops > 0 && ! mips_opts.noreorder)
+ {
+ fragS *old_frag;
+ unsigned long old_frag_offset;
+ int i;
+ struct insn_label_list *l;
+
+ old_frag = frag_now;
+ old_frag_offset = frag_now_fix ();
+
+ for (i = 0; i < nops; i++)
+ emit_nop ();
+
+ if (listing)
+ {
+ listing_prev_line ();
+ /* We may be at the start of a variant frag. In case we
+ are, make sure there is enough space for the frag
+ after the frags created by listing_prev_line. The
+ argument to frag_grow here must be at least as large
+ as the argument to all other calls to frag_grow in
+ this file. We don't have to worry about being in the
+ middle of a variant frag, because the variants insert
+ all needed nop instructions themselves. */
+ frag_grow (40);
+ }
+
+ for (l = insn_labels; l != NULL; l = l->next)
+ {
+ assert (S_GET_SEGMENT (l->label) == now_seg);
+ l->label->sy_frag = frag_now;
+ S_SET_VALUE (l->label, (valueT) frag_now_fix ());
+ /* mips16 text labels are stored as odd. */
+ if (mips_opts.mips16)
+ ++l->label->sy_value.X_add_number;
+ }
+
+#ifndef NO_ECOFF_DEBUGGING
+ if (ECOFF_DEBUGGING)
+ ecoff_fix_loc (old_frag, old_frag_offset);
+#endif
+ }
+ else if (prev_nop_frag != NULL)
+ {
+ /* We have a frag holding nops we may be able to remove. If
+ we don't need any nops, we can decrease the size of
+ prev_nop_frag by the size of one instruction. If we do
+ need some nops, we count them in prev_nops_required. */
+ if (prev_nop_frag_since == 0)
+ {
+ if (nops == 0)
+ {
+ prev_nop_frag->fr_fix -= mips_opts.mips16 ? 2 : 4;
+ --prev_nop_frag_holds;
+ }
+ else
+ prev_nop_frag_required += nops;
+ }
+ else
+ {
+ if (prev_prev_nop == 0)
+ {
+ prev_nop_frag->fr_fix -= mips_opts.mips16 ? 2 : 4;
+ --prev_nop_frag_holds;
+ }
+ else
+ ++prev_nop_frag_required;
+ }
+
+ if (prev_nop_frag_holds <= prev_nop_frag_required)
+ prev_nop_frag = NULL;
+
+ ++prev_nop_frag_since;
+
+ /* Sanity check: by the time we reach the second instruction
+ after prev_nop_frag, we should have used up all the nops
+ one way or another. */
+ assert (prev_nop_frag_since <= 1 || prev_nop_frag == NULL);
+ }
+ }
+
+ if (reloc_type > BFD_RELOC_UNUSED)
+ {
+ /* We need to set up a variant frag. */
+ assert (mips_opts.mips16 && address_expr != NULL);
+ f = frag_var (rs_machine_dependent, 4, 0,
+ RELAX_MIPS16_ENCODE (reloc_type - BFD_RELOC_UNUSED,
+ mips16_small, mips16_ext,
+ (prev_pinfo
+ & INSN_UNCOND_BRANCH_DELAY),
+ (prev_insn_reloc_type
+ == BFD_RELOC_MIPS16_JMP)),
+ make_expr_symbol (address_expr), (offsetT) 0,
+ (char *) NULL);
+ }
+ else if (place != NULL)
+ f = place;
+ else if (mips_opts.mips16
+ && ! ip->use_extend
+ && reloc_type != BFD_RELOC_MIPS16_JMP)
+ {
+ /* Make sure there is enough room to swap this instruction with
+ a following jump instruction. */
+ frag_grow (6);
+ f = frag_more (2);
+ }
+ else
+ {
+ if (mips_opts.mips16
+ && mips_opts.noreorder
+ && (prev_pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
+ as_warn (_("extended instruction in delay slot"));
+
+ f = frag_more (4);
+ }
+
+ fixp = NULL;
+ if (address_expr != NULL && reloc_type < BFD_RELOC_UNUSED)
+ {
+ if (address_expr->X_op == O_constant)
+ {
+ switch (reloc_type)
+ {
+ case BFD_RELOC_32:
+ ip->insn_opcode |= address_expr->X_add_number;
+ break;
+
+ case BFD_RELOC_LO16:
+ ip->insn_opcode |= address_expr->X_add_number & 0xffff;
+ break;
+
+ case BFD_RELOC_MIPS_JMP:
+ if ((address_expr->X_add_number & 3) != 0)
+ as_bad (_("jump to misaligned address (0x%lx)"),
+ (unsigned long) address_expr->X_add_number);
+ ip->insn_opcode |= (address_expr->X_add_number >> 2) & 0x3ffffff;
+ break;
+
+ case BFD_RELOC_MIPS16_JMP:
+ if ((address_expr->X_add_number & 3) != 0)
+ as_bad (_("jump to misaligned address (0x%lx)"),
+ (unsigned long) address_expr->X_add_number);
+ ip->insn_opcode |=
+ (((address_expr->X_add_number & 0x7c0000) << 3)
+ | ((address_expr->X_add_number & 0xf800000) >> 7)
+ | ((address_expr->X_add_number & 0x3fffc) >> 2));
+ break;
+
+
+ case BFD_RELOC_16_PCREL_S2:
+ goto need_reloc;
+
+ default:
+ internalError ();
+ }
+ }
+ else
+ {
+ need_reloc:
+ /* Don't generate a reloc if we are writing into a variant
+ frag. */
+ if (place == NULL)
+ {
+ fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 4,
+ address_expr,
+ reloc_type == BFD_RELOC_16_PCREL_S2,
+ reloc_type);
+ if (unmatched_hi)
+ {
+ struct mips_hi_fixup *hi_fixup;
+
+ assert (reloc_type == BFD_RELOC_HI16_S);
+ hi_fixup = ((struct mips_hi_fixup *)
+ xmalloc (sizeof (struct mips_hi_fixup)));
+ hi_fixup->fixp = fixp;
+ hi_fixup->seg = now_seg;
+ hi_fixup->next = mips_hi_fixup_list;
+ mips_hi_fixup_list = hi_fixup;
+ }
+ }
+ }
+ }
+
+ if (! mips_opts.mips16)
+ md_number_to_chars (f, ip->insn_opcode, 4);
+ else if (reloc_type == BFD_RELOC_MIPS16_JMP)
+ {
+ md_number_to_chars (f, ip->insn_opcode >> 16, 2);
+ md_number_to_chars (f + 2, ip->insn_opcode & 0xffff, 2);
+ }
+ else
+ {
+ if (ip->use_extend)
+ {
+ md_number_to_chars (f, 0xf000 | ip->extend, 2);
+ f += 2;
+ }
+ md_number_to_chars (f, ip->insn_opcode, 2);
+ }
+
+ /* Update the register mask information. */
+ if (! mips_opts.mips16)
+ {
+ if (pinfo & INSN_WRITE_GPR_D)
+ mips_gprmask |= 1 << ((ip->insn_opcode >> OP_SH_RD) & OP_MASK_RD);
+ if ((pinfo & (INSN_WRITE_GPR_T | INSN_READ_GPR_T)) != 0)
+ mips_gprmask |= 1 << ((ip->insn_opcode >> OP_SH_RT) & OP_MASK_RT);
+ if (pinfo & INSN_READ_GPR_S)
+ mips_gprmask |= 1 << ((ip->insn_opcode >> OP_SH_RS) & OP_MASK_RS);
+ if (pinfo & INSN_WRITE_GPR_31)
+ mips_gprmask |= 1 << 31;
+ if (pinfo & INSN_WRITE_FPR_D)
+ mips_cprmask[1] |= 1 << ((ip->insn_opcode >> OP_SH_FD) & OP_MASK_FD);
+ if ((pinfo & (INSN_WRITE_FPR_S | INSN_READ_FPR_S)) != 0)
+ mips_cprmask[1] |= 1 << ((ip->insn_opcode >> OP_SH_FS) & OP_MASK_FS);
+ if ((pinfo & (INSN_WRITE_FPR_T | INSN_READ_FPR_T)) != 0)
+ mips_cprmask[1] |= 1 << ((ip->insn_opcode >> OP_SH_FT) & OP_MASK_FT);
+ if ((pinfo & INSN_READ_FPR_R) != 0)
+ mips_cprmask[1] |= 1 << ((ip->insn_opcode >> OP_SH_FR) & OP_MASK_FR);
+ if (pinfo & INSN_COP)
+ {
+ /* We don't keep enough information to sort these cases out.
+ The itbl support does keep this information however, although
+ we currently don't support itbl fprmats as part of the cop
+ instruction. May want to add this support in the future. */
+ }
+ /* Never set the bit for $0, which is always zero. */
+ mips_gprmask &=~ 1 << 0;
+ }
+ else
+ {
+ if (pinfo & (MIPS16_INSN_WRITE_X | MIPS16_INSN_READ_X))
+ mips_gprmask |= 1 << ((ip->insn_opcode >> MIPS16OP_SH_RX)
+ & MIPS16OP_MASK_RX);
+ if (pinfo & (MIPS16_INSN_WRITE_Y | MIPS16_INSN_READ_Y))
+ mips_gprmask |= 1 << ((ip->insn_opcode >> MIPS16OP_SH_RY)
+ & MIPS16OP_MASK_RY);
+ if (pinfo & MIPS16_INSN_WRITE_Z)
+ mips_gprmask |= 1 << ((ip->insn_opcode >> MIPS16OP_SH_RZ)
+ & MIPS16OP_MASK_RZ);
+ if (pinfo & (MIPS16_INSN_WRITE_T | MIPS16_INSN_READ_T))
+ mips_gprmask |= 1 << TREG;
+ if (pinfo & (MIPS16_INSN_WRITE_SP | MIPS16_INSN_READ_SP))
+ mips_gprmask |= 1 << SP;
+ if (pinfo & (MIPS16_INSN_WRITE_31 | MIPS16_INSN_READ_31))
+ mips_gprmask |= 1 << RA;
+ if (pinfo & MIPS16_INSN_WRITE_GPR_Y)
+ mips_gprmask |= 1 << MIPS16OP_EXTRACT_REG32R (ip->insn_opcode);
+ if (pinfo & MIPS16_INSN_READ_Z)
+ mips_gprmask |= 1 << ((ip->insn_opcode >> MIPS16OP_SH_MOVE32Z)
+ & MIPS16OP_MASK_MOVE32Z);
+ if (pinfo & MIPS16_INSN_READ_GPR_X)
+ mips_gprmask |= 1 << ((ip->insn_opcode >> MIPS16OP_SH_REGR32)
+ & MIPS16OP_MASK_REGR32);
+ }
+
+ if (place == NULL && ! mips_opts.noreorder)
+ {
+ /* Filling the branch delay slot is more complex. We try to
+ switch the branch with the previous instruction, which we can
+ do if the previous instruction does not set up a condition
+ that the branch tests and if the branch is not itself the
+ target of any branch. */
+ if ((pinfo & INSN_UNCOND_BRANCH_DELAY)
+ || (pinfo & INSN_COND_BRANCH_DELAY))
+ {
+ if (mips_optimize < 2
+ /* If we have seen .set volatile or .set nomove, don't
+ optimize. */
+ || mips_opts.nomove != 0
+ /* If we had to emit any NOP instructions, then we
+ already know we can not swap. */
+ || nops != 0
+ /* If we don't even know the previous insn, we can not
+ swap. */
+ || ! prev_insn_valid
+ /* If the previous insn is already in a branch delay
+ slot, then we can not swap. */
+ || prev_insn_is_delay_slot
+ /* If the previous previous insn was in a .set
+ noreorder, we can't swap. Actually, the MIPS
+ assembler will swap in this situation. However, gcc
+ configured -with-gnu-as will generate code like
+ .set noreorder
+ lw $4,XXX
+ .set reorder
+ INSN
+ bne $4,$0,foo
+ in which we can not swap the bne and INSN. If gcc is
+ not configured -with-gnu-as, it does not output the
+ .set pseudo-ops. We don't have to check
+ prev_insn_unreordered, because prev_insn_valid will
+ be 0 in that case. We don't want to use
+ prev_prev_insn_valid, because we do want to be able
+ to swap at the start of a function. */
+ || prev_prev_insn_unreordered
+ /* If the branch is itself the target of a branch, we
+ can not swap. We cheat on this; all we check for is
+ whether there is a label on this instruction. If
+ there are any branches to anything other than a
+ label, users must use .set noreorder. */
+ || insn_labels != NULL
+ /* If the previous instruction is in a variant frag, we
+ can not do the swap. This does not apply to the
+ mips16, which uses variant frags for different
+ purposes. */
+ || (! mips_opts.mips16
+ && prev_insn_frag->fr_type == rs_machine_dependent)
+ /* If the branch reads the condition codes, we don't
+ even try to swap, because in the sequence
+ ctc1 $X,$31
+ INSN
+ INSN
+ bc1t LABEL
+ we can not swap, and I don't feel like handling that
+ case. */
+ || (! mips_opts.mips16
+ && mips_opts.isa < 4
+ && (pinfo & INSN_READ_COND_CODE))
+ /* We can not swap with an instruction that requires a
+ delay slot, becase the target of the branch might
+ interfere with that instruction. */
+ || (! mips_opts.mips16
+ && mips_opts.isa < 4
+ && (prev_pinfo
+ /* Itbl support may require additional care here. */
+ & (INSN_LOAD_COPROC_DELAY
+ | INSN_COPROC_MOVE_DELAY
+ | INSN_WRITE_COND_CODE)))
+ || (! (hilo_interlocks
+ || (mips_cpu == 3900 && (pinfo & INSN_MULT)))
+ && (prev_pinfo
+ & (INSN_READ_LO
+ | INSN_READ_HI)))
+ || (! mips_opts.mips16
+ && ! gpr_interlocks
+ && (prev_pinfo & INSN_LOAD_MEMORY_DELAY))
+ || (! mips_opts.mips16
+ && mips_opts.isa < 2
+ /* Itbl support may require additional care here. */
+ && (prev_pinfo & INSN_COPROC_MEMORY_DELAY))
+ /* We can not swap with a branch instruction. */
+ || (prev_pinfo
+ & (INSN_UNCOND_BRANCH_DELAY
+ | INSN_COND_BRANCH_DELAY
+ | INSN_COND_BRANCH_LIKELY))
+ /* We do not swap with a trap instruction, since it
+ complicates trap handlers to have the trap
+ instruction be in a delay slot. */
+ || (prev_pinfo & INSN_TRAP)
+ /* If the branch reads a register that the previous
+ instruction sets, we can not swap. */
+ || (! mips_opts.mips16
+ && (prev_pinfo & INSN_WRITE_GPR_T)
+ && insn_uses_reg (ip,
+ ((prev_insn.insn_opcode >> OP_SH_RT)
+ & OP_MASK_RT),
+ MIPS_GR_REG))
+ || (! mips_opts.mips16
+ && (prev_pinfo & INSN_WRITE_GPR_D)
+ && insn_uses_reg (ip,
+ ((prev_insn.insn_opcode >> OP_SH_RD)
+ & OP_MASK_RD),
+ MIPS_GR_REG))
+ || (mips_opts.mips16
+ && (((prev_pinfo & MIPS16_INSN_WRITE_X)
+ && insn_uses_reg (ip,
+ ((prev_insn.insn_opcode
+ >> MIPS16OP_SH_RX)
+ & MIPS16OP_MASK_RX),
+ MIPS16_REG))
+ || ((prev_pinfo & MIPS16_INSN_WRITE_Y)
+ && insn_uses_reg (ip,
+ ((prev_insn.insn_opcode
+ >> MIPS16OP_SH_RY)
+ & MIPS16OP_MASK_RY),
+ MIPS16_REG))
+ || ((prev_pinfo & MIPS16_INSN_WRITE_Z)
+ && insn_uses_reg (ip,
+ ((prev_insn.insn_opcode
+ >> MIPS16OP_SH_RZ)
+ & MIPS16OP_MASK_RZ),
+ MIPS16_REG))
+ || ((prev_pinfo & MIPS16_INSN_WRITE_T)
+ && insn_uses_reg (ip, TREG, MIPS_GR_REG))
+ || ((prev_pinfo & MIPS16_INSN_WRITE_31)
+ && insn_uses_reg (ip, RA, MIPS_GR_REG))
+ || ((prev_pinfo & MIPS16_INSN_WRITE_GPR_Y)
+ && insn_uses_reg (ip,
+ MIPS16OP_EXTRACT_REG32R (prev_insn.
+ insn_opcode),
+ MIPS_GR_REG))))
+ /* If the branch writes a register that the previous
+ instruction sets, we can not swap (we know that
+ branches write only to RD or to $31). */
+ || (! mips_opts.mips16
+ && (prev_pinfo & INSN_WRITE_GPR_T)
+ && (((pinfo & INSN_WRITE_GPR_D)
+ && (((prev_insn.insn_opcode >> OP_SH_RT) & OP_MASK_RT)
+ == ((ip->insn_opcode >> OP_SH_RD) & OP_MASK_RD)))
+ || ((pinfo & INSN_WRITE_GPR_31)
+ && (((prev_insn.insn_opcode >> OP_SH_RT)
+ & OP_MASK_RT)
+ == 31))))
+ || (! mips_opts.mips16
+ && (prev_pinfo & INSN_WRITE_GPR_D)
+ && (((pinfo & INSN_WRITE_GPR_D)
+ && (((prev_insn.insn_opcode >> OP_SH_RD) & OP_MASK_RD)
+ == ((ip->insn_opcode >> OP_SH_RD) & OP_MASK_RD)))
+ || ((pinfo & INSN_WRITE_GPR_31)
+ && (((prev_insn.insn_opcode >> OP_SH_RD)
+ & OP_MASK_RD)
+ == 31))))
+ || (mips_opts.mips16
+ && (pinfo & MIPS16_INSN_WRITE_31)
+ && ((prev_pinfo & MIPS16_INSN_WRITE_31)
+ || ((prev_pinfo & MIPS16_INSN_WRITE_GPR_Y)
+ && (MIPS16OP_EXTRACT_REG32R (prev_insn.insn_opcode)
+ == RA))))
+ /* If the branch writes a register that the previous
+ instruction reads, we can not swap (we know that
+ branches only write to RD or to $31). */
+ || (! mips_opts.mips16
+ && (pinfo & INSN_WRITE_GPR_D)
+ && insn_uses_reg (&prev_insn,
+ ((ip->insn_opcode >> OP_SH_RD)
+ & OP_MASK_RD),
+ MIPS_GR_REG))
+ || (! mips_opts.mips16
+ && (pinfo & INSN_WRITE_GPR_31)
+ && insn_uses_reg (&prev_insn, 31, MIPS_GR_REG))
+ || (mips_opts.mips16
+ && (pinfo & MIPS16_INSN_WRITE_31)
+ && insn_uses_reg (&prev_insn, RA, MIPS_GR_REG))
+ /* If we are generating embedded PIC code, the branch
+ might be expanded into a sequence which uses $at, so
+ we can't swap with an instruction which reads it. */
+ || (mips_pic == EMBEDDED_PIC
+ && insn_uses_reg (&prev_insn, AT, MIPS_GR_REG))
+ /* If the previous previous instruction has a load
+ delay, and sets a register that the branch reads, we
+ can not swap. */
+ || (! mips_opts.mips16
+ && mips_opts.isa < 4
+ /* Itbl support may require additional care here. */
+ && ((prev_prev_insn.insn_mo->pinfo & INSN_LOAD_COPROC_DELAY)
+ || (! gpr_interlocks
+ && (prev_prev_insn.insn_mo->pinfo
+ & INSN_LOAD_MEMORY_DELAY)))
+ && insn_uses_reg (ip,
+ ((prev_prev_insn.insn_opcode >> OP_SH_RT)
+ & OP_MASK_RT),
+ MIPS_GR_REG))
+ /* If one instruction sets a condition code and the
+ other one uses a condition code, we can not swap. */
+ || ((pinfo & INSN_READ_COND_CODE)
+ && (prev_pinfo & INSN_WRITE_COND_CODE))
+ || ((pinfo & INSN_WRITE_COND_CODE)
+ && (prev_pinfo & INSN_READ_COND_CODE))
+ /* If the previous instruction uses the PC, we can not
+ swap. */
+ || (mips_opts.mips16
+ && (prev_pinfo & MIPS16_INSN_READ_PC))
+ /* If the previous instruction was extended, we can not
+ swap. */
+ || (mips_opts.mips16 && prev_insn_extended)
+ /* If the previous instruction had a fixup in mips16
+ mode, we can not swap. This normally means that the
+ previous instruction was a 4 byte branch anyhow. */
+ || (mips_opts.mips16 && prev_insn_fixp)
+ /* If the previous instruction is a sync, sync.l, or
+ sync.p, we can not swap. */
+ || (prev_pinfo && INSN_SYNC))
+ {
+ /* We could do even better for unconditional branches to
+ portions of this object file; we could pick up the
+ instruction at the destination, put it in the delay
+ slot, and bump the destination address. */
+ emit_nop ();
+ /* Update the previous insn information. */
+ prev_prev_insn = *ip;
+ prev_insn.insn_mo = &dummy_opcode;
+ }
+ else
+ {
+ /* It looks like we can actually do the swap. */
+ if (! mips_opts.mips16)
+ {
+ char *prev_f;
+ char temp[4];
+
+ prev_f = prev_insn_frag->fr_literal + prev_insn_where;
+ memcpy (temp, prev_f, 4);
+ memcpy (prev_f, f, 4);
+ memcpy (f, temp, 4);
+ if (prev_insn_fixp)
+ {
+ prev_insn_fixp->fx_frag = frag_now;
+ prev_insn_fixp->fx_where = f - frag_now->fr_literal;
+ }
+ if (fixp)
+ {
+ fixp->fx_frag = prev_insn_frag;
+ fixp->fx_where = prev_insn_where;
+ }
+ }
+ else
+ {
+ char *prev_f;
+ char temp[2];
+
+ assert (prev_insn_fixp == NULL);
+ prev_f = prev_insn_frag->fr_literal + prev_insn_where;
+ memcpy (temp, prev_f, 2);
+ memcpy (prev_f, f, 2);
+ if (reloc_type != BFD_RELOC_MIPS16_JMP)
+ {
+ assert (reloc_type == BFD_RELOC_UNUSED);
+ memcpy (f, temp, 2);
+ }
+ else
+ {
+ memcpy (f, f + 2, 2);
+ memcpy (f + 2, temp, 2);
+ }
+ if (fixp)
+ {
+ fixp->fx_frag = prev_insn_frag;
+ fixp->fx_where = prev_insn_where;
+ }
+ }
+
+ /* Update the previous insn information; leave prev_insn
+ unchanged. */
+ prev_prev_insn = *ip;
+ }
+ prev_insn_is_delay_slot = 1;
+
+ /* If that was an unconditional branch, forget the previous
+ insn information. */
+ if (pinfo & INSN_UNCOND_BRANCH_DELAY)
+ {
+ prev_prev_insn.insn_mo = &dummy_opcode;
+ prev_insn.insn_mo = &dummy_opcode;
+ }
+
+ prev_insn_fixp = NULL;
+ prev_insn_reloc_type = BFD_RELOC_UNUSED;
+ prev_insn_extended = 0;
+ }
+ else if (pinfo & INSN_COND_BRANCH_LIKELY)
+ {
+ /* We don't yet optimize a branch likely. What we should do
+ is look at the target, copy the instruction found there
+ into the delay slot, and increment the branch to jump to
+ the next instruction. */
+ emit_nop ();
+ /* Update the previous insn information. */
+ prev_prev_insn = *ip;
+ prev_insn.insn_mo = &dummy_opcode;
+ prev_insn_fixp = NULL;
+ prev_insn_reloc_type = BFD_RELOC_UNUSED;
+ prev_insn_extended = 0;
+ }
+ else
+ {
+ /* Update the previous insn information. */
+ if (nops > 0)
+ prev_prev_insn.insn_mo = &dummy_opcode;
+ else
+ prev_prev_insn = prev_insn;
+ prev_insn = *ip;
+
+ /* Any time we see a branch, we always fill the delay slot
+ immediately; since this insn is not a branch, we know it
+ is not in a delay slot. */
+ prev_insn_is_delay_slot = 0;
+
+ prev_insn_fixp = fixp;
+ prev_insn_reloc_type = reloc_type;
+ if (mips_opts.mips16)
+ prev_insn_extended = (ip->use_extend
+ || reloc_type > BFD_RELOC_UNUSED);
+ }
+
+ prev_prev_insn_unreordered = prev_insn_unreordered;
+ prev_insn_unreordered = 0;
+ prev_insn_frag = frag_now;
+ prev_insn_where = f - frag_now->fr_literal;
+ prev_insn_valid = 1;
+ }
+ else if (place == NULL)
+ {
+ /* We need to record a bit of information even when we are not
+ reordering, in order to determine the base address for mips16
+ PC relative relocs. */
+ prev_prev_insn = prev_insn;
+ prev_insn = *ip;
+ prev_insn_reloc_type = reloc_type;
+ prev_prev_insn_unreordered = prev_insn_unreordered;
+ prev_insn_unreordered = 1;
+ }
+
+ /* We just output an insn, so the next one doesn't have a label. */
+ mips_clear_insn_labels ();
+
+ /* We must ensure that a fixup associated with an unmatched %hi
+ reloc does not become a variant frag. Otherwise, the
+ rearrangement of %hi relocs in frob_file may confuse
+ tc_gen_reloc. */
+ if (unmatched_hi)
+ {
+ frag_wane (frag_now);
+ frag_new (0);
+ }
+}
+
+/* This function forgets that there was any previous instruction or
+ label. If PRESERVE is non-zero, it remembers enough information to
+ know whether nops are needed before a noreorder section. */
+
+static void
+mips_no_prev_insn (preserve)
+ int preserve;
+{
+ if (! preserve)
+ {
+ prev_insn.insn_mo = &dummy_opcode;
+ prev_prev_insn.insn_mo = &dummy_opcode;
+ prev_nop_frag = NULL;
+ prev_nop_frag_holds = 0;
+ prev_nop_frag_required = 0;
+ prev_nop_frag_since = 0;
+ }
+ prev_insn_valid = 0;
+ prev_insn_is_delay_slot = 0;
+ prev_insn_unreordered = 0;
+ prev_insn_extended = 0;
+ prev_insn_reloc_type = BFD_RELOC_UNUSED;
+ prev_prev_insn_unreordered = 0;
+ mips_clear_insn_labels ();
+}
+
+/* This function must be called whenever we turn on noreorder or emit
+ something other than instructions. It inserts any NOPS which might
+ be needed by the previous instruction, and clears the information
+ kept for the previous instructions. The INSNS parameter is true if
+ instructions are to follow. */
+
+static void
+mips_emit_delays (insns)
+ boolean insns;
+{
+ if (! mips_opts.noreorder)
+ {
+ int nops;
+
+ nops = 0;
+ if ((! mips_opts.mips16
+ && mips_opts.isa < 4
+ && (! cop_interlocks
+ && (prev_insn.insn_mo->pinfo
+ & (INSN_LOAD_COPROC_DELAY
+ | INSN_COPROC_MOVE_DELAY
+ | INSN_WRITE_COND_CODE))))
+ || (! hilo_interlocks
+ && (prev_insn.insn_mo->pinfo
+ & (INSN_READ_LO
+ | INSN_READ_HI)))
+ || (! mips_opts.mips16
+ && ! gpr_interlocks
+ && (prev_insn.insn_mo->pinfo
+ & INSN_LOAD_MEMORY_DELAY))
+ || (! mips_opts.mips16
+ && mips_opts.isa < 2
+ && (prev_insn.insn_mo->pinfo
+ & INSN_COPROC_MEMORY_DELAY)))
+ {
+ /* Itbl support may require additional care here. */
+ ++nops;
+ if ((! mips_opts.mips16
+ && mips_opts.isa < 4
+ && (! cop_interlocks
+ && prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE))
+ || (! hilo_interlocks
+ && ((prev_insn.insn_mo->pinfo & INSN_READ_HI)
+ || (prev_insn.insn_mo->pinfo & INSN_READ_LO))))
+ ++nops;
+
+ if (prev_insn_unreordered)
+ nops = 0;
+ }
+ else if ((! mips_opts.mips16
+ && mips_opts.isa < 4
+ && (! cop_interlocks
+ && prev_prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE))
+ || (! hilo_interlocks
+ && ((prev_prev_insn.insn_mo->pinfo & INSN_READ_HI)
+ || (prev_prev_insn.insn_mo->pinfo & INSN_READ_LO))))
+ {
+ /* Itbl support may require additional care here. */
+ if (! prev_prev_insn_unreordered)
+ ++nops;
+ }
+
+ if (nops > 0)
+ {
+ struct insn_label_list *l;
+
+ if (insns)
+ {
+ /* Record the frag which holds the nop instructions, so
+ that we can remove them if we don't need them. */
+ frag_grow (mips_opts.mips16 ? nops * 2 : nops * 4);
+ prev_nop_frag = frag_now;
+ prev_nop_frag_holds = nops;
+ prev_nop_frag_required = 0;
+ prev_nop_frag_since = 0;
+ }
+
+ for (; nops > 0; --nops)
+ emit_nop ();
+
+ if (insns)
+ {
+ /* Move on to a new frag, so that it is safe to simply
+ decrease the size of prev_nop_frag. */
+ frag_wane (frag_now);
+ frag_new (0);
+ }
+
+ for (l = insn_labels; l != NULL; l = l->next)
+ {
+ assert (S_GET_SEGMENT (l->label) == now_seg);
+ l->label->sy_frag = frag_now;
+ S_SET_VALUE (l->label, (valueT) frag_now_fix ());
+ /* mips16 text labels are stored as odd. */
+ if (mips_opts.mips16)
+ ++l->label->sy_value.X_add_number;
+ }
+ }
+ }
+
+ /* Mark instruction labels in mips16 mode. */
+ if (mips_opts.mips16 && insns)
+ mips16_mark_labels ();
+
+ mips_no_prev_insn (insns);
+}
+
+/* Build an instruction created by a macro expansion. This is passed
+ a pointer to the count of instructions created so far, an
+ expression, the name of the instruction to build, an operand format
+ string, and corresponding arguments. */
+
+#ifdef USE_STDARG
+static void
+macro_build (char *place,
+ int *counter,
+ expressionS * ep,
+ const char *name,
+ const char *fmt,
+ ...)
+#else
+static void
+macro_build (place, counter, ep, name, fmt, va_alist)
+ char *place;
+ int *counter;
+ expressionS *ep;
+ const char *name;
+ const char *fmt;
+ va_dcl
+#endif
+{
+ struct mips_cl_insn insn;
+ bfd_reloc_code_real_type r;
+ va_list args;
+ int insn_isa;
+
+#ifdef USE_STDARG
+ va_start (args, fmt);
+#else
+ va_start (args);
+#endif
+
+ /*
+ * If the macro is about to expand into a second instruction,
+ * print a warning if needed. We need to pass ip as a parameter
+ * to generate a better warning message here...
+ */
+ if (mips_opts.warn_about_macros && place == NULL && *counter == 1)
+ as_warn (_("Macro instruction expanded into multiple instructions"));
+
+ if (place == NULL)
+ *counter += 1; /* bump instruction counter */
+
+ if (mips_opts.mips16)
+ {
+ mips16_macro_build (place, counter, ep, name, fmt, args);
+ va_end (args);
+ return;
+ }
+
+ r = BFD_RELOC_UNUSED;
+ insn.insn_mo = (struct mips_opcode *) hash_find (op_hash, name);
+ assert (insn.insn_mo);
+ assert (strcmp (name, insn.insn_mo->name) == 0);
+
+ /* Search until we get a match for NAME. */
+ while (1)
+ {
+ if ((insn.insn_mo->membership & INSN_ISA) == INSN_ISA1)
+ insn_isa = 1;
+ else if ((insn.insn_mo->membership & INSN_ISA) == INSN_ISA2)
+ insn_isa = 2;
+ else if ((insn.insn_mo->membership & INSN_ISA) == INSN_ISA3)
+ insn_isa = 3;
+ else if ((insn.insn_mo->membership & INSN_ISA) == INSN_ISA4)
+ insn_isa = 4;
+ else
+ insn_isa = 15;
+
+ if (strcmp (fmt, insn.insn_mo->args) == 0
+ && insn.insn_mo->pinfo != INSN_MACRO
+ && (insn_isa <= mips_opts.isa
+ || (mips_cpu == 4650
+ && (insn.insn_mo->membership & INSN_4650) != 0)
+ || (mips_cpu == 4010
+ && (insn.insn_mo->membership & INSN_4010) != 0)
+ || ((mips_cpu == 4100
+ || mips_cpu == 4111
+ )
+ && (insn.insn_mo->membership & INSN_4100) != 0)
+ || (mips_cpu == 3900
+ && (insn.insn_mo->membership & INSN_3900) != 0))
+ && (mips_cpu != 4650 || (insn.insn_mo->pinfo & FP_D) == 0))
+ break;
+
+ ++insn.insn_mo;
+ assert (insn.insn_mo->name);
+ assert (strcmp (name, insn.insn_mo->name) == 0);
+ }
+
+ insn.insn_opcode = insn.insn_mo->match;
+ for (;;)
+ {
+ switch (*fmt++)
+ {
+ case '\0':
+ break;
+
+ case ',':
+ case '(':
+ case ')':
+ continue;
+
+ case 't':
+ case 'w':
+ case 'E':
+ insn.insn_opcode |= va_arg (args, int) << 16;
+ continue;
+
+ case 'c':
+ case 'T':
+ case 'W':
+ insn.insn_opcode |= va_arg (args, int) << 16;
+ continue;
+
+ case 'd':
+ case 'G':
+ insn.insn_opcode |= va_arg (args, int) << 11;
+ continue;
+
+ case 'V':
+ case 'S':
+ insn.insn_opcode |= va_arg (args, int) << 11;
+ continue;
+
+ case 'z':
+ continue;
+
+ case '<':
+ insn.insn_opcode |= va_arg (args, int) << 6;
+ continue;
+
+ case 'D':
+ insn.insn_opcode |= va_arg (args, int) << 6;
+ continue;
+
+ case 'B':
+ insn.insn_opcode |= va_arg (args, int) << 6;
+ continue;
+
+ case 'q':
+ insn.insn_opcode |= va_arg (args, int) << 6;
+ continue;
+
+ case 'b':
+ case 's':
+ case 'r':
+ case 'v':
+ insn.insn_opcode |= va_arg (args, int) << 21;
+ continue;
+
+ case 'i':
+ case 'j':
+ case 'o':
+ r = (bfd_reloc_code_real_type) va_arg (args, int);
+ assert (r == BFD_RELOC_MIPS_GPREL
+ || r == BFD_RELOC_MIPS_LITERAL
+ || r == BFD_RELOC_LO16
+ || r == BFD_RELOC_MIPS_GOT16
+ || r == BFD_RELOC_MIPS_CALL16
+ || r == BFD_RELOC_MIPS_GOT_LO16
+ || r == BFD_RELOC_MIPS_CALL_LO16
+ || (ep->X_op == O_subtract
+ && now_seg == text_section
+ && r == BFD_RELOC_PCREL_LO16));
+ continue;
+
+ case 'u':
+ r = (bfd_reloc_code_real_type) va_arg (args, int);
+ assert (ep != NULL
+ && (ep->X_op == O_constant
+ || (ep->X_op == O_symbol
+ && (r == BFD_RELOC_HI16_S
+ || r == BFD_RELOC_HI16
+ || r == BFD_RELOC_MIPS_GOT_HI16
+ || r == BFD_RELOC_MIPS_CALL_HI16))
+ || (ep->X_op == O_subtract
+ && now_seg == text_section
+ && r == BFD_RELOC_PCREL_HI16_S)));
+ if (ep->X_op == O_constant)
+ {
+ insn.insn_opcode |= (ep->X_add_number >> 16) & 0xffff;
+ ep = NULL;
+ r = BFD_RELOC_UNUSED;
+ }
+ continue;
+
+ case 'p':
+ assert (ep != NULL);
+ /*
+ * This allows macro() to pass an immediate expression for
+ * creating short branches without creating a symbol.
+ * Note that the expression still might come from the assembly
+ * input, in which case the value is not checked for range nor
+ * is a relocation entry generated (yuck).
+ */
+ if (ep->X_op == O_constant)
+ {
+ insn.insn_opcode |= (ep->X_add_number >> 2) & 0xffff;
+ ep = NULL;
+ }
+ else
+ r = BFD_RELOC_16_PCREL_S2;
+ continue;
+
+ case 'a':
+ assert (ep != NULL);
+ r = BFD_RELOC_MIPS_JMP;
+ continue;
+
+ case 'C':
+ insn.insn_opcode |= va_arg (args, unsigned long);
+ continue;
+
+ default:
+ internalError ();
+ }
+ break;
+ }
+ va_end (args);
+ assert (r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL);
+
+ append_insn (place, &insn, ep, r, false);
+}
+
+static void
+mips16_macro_build (place, counter, ep, name, fmt, args)
+ char *place;
+ int *counter;
+ expressionS *ep;
+ const char *name;
+ const char *fmt;
+ va_list args;
+{
+ struct mips_cl_insn insn;
+ bfd_reloc_code_real_type r;
+
+ r = BFD_RELOC_UNUSED;
+ insn.insn_mo = (struct mips_opcode *) hash_find (mips16_op_hash, name);
+ assert (insn.insn_mo);
+ assert (strcmp (name, insn.insn_mo->name) == 0);
+
+ while (strcmp (fmt, insn.insn_mo->args) != 0
+ || insn.insn_mo->pinfo == INSN_MACRO)
+ {
+ ++insn.insn_mo;
+ assert (insn.insn_mo->name);
+ assert (strcmp (name, insn.insn_mo->name) == 0);
+ }
+
+ insn.insn_opcode = insn.insn_mo->match;
+ insn.use_extend = false;
+
+ for (;;)
+ {
+ int c;
+
+ c = *fmt++;
+ switch (c)
+ {
+ case '\0':
+ break;
+
+ case ',':
+ case '(':
+ case ')':
+ continue;
+
+ case 'y':
+ case 'w':
+ insn.insn_opcode |= va_arg (args, int) << MIPS16OP_SH_RY;
+ continue;
+
+ case 'x':
+ case 'v':
+ insn.insn_opcode |= va_arg (args, int) << MIPS16OP_SH_RX;
+ continue;
+
+ case 'z':
+ insn.insn_opcode |= va_arg (args, int) << MIPS16OP_SH_RZ;
+ continue;
+
+ case 'Z':
+ insn.insn_opcode |= va_arg (args, int) << MIPS16OP_SH_MOVE32Z;
+ continue;
+
+ case '0':
+ case 'S':
+ case 'P':
+ case 'R':
+ continue;
+
+ case 'X':
+ insn.insn_opcode |= va_arg (args, int) << MIPS16OP_SH_REGR32;
+ continue;
+
+ case 'Y':
+ {
+ int regno;
+
+ regno = va_arg (args, int);
+ regno = ((regno & 7) << 2) | ((regno & 0x18) >> 3);
+ insn.insn_opcode |= regno << MIPS16OP_SH_REG32R;
+ }
+ continue;
+
+ case '<':
+ case '>':
+ case '4':
+ case '5':
+ case 'H':
+ case 'W':
+ case 'D':
+ case 'j':
+ case '8':
+ case 'V':
+ case 'C':
+ case 'U':
+ case 'k':
+ case 'K':
+ case 'p':
+ case 'q':
+ {
+ assert (ep != NULL);
+
+ if (ep->X_op != O_constant)
+ r = BFD_RELOC_UNUSED + c;
+ else
+ {
+ mips16_immed ((char *) NULL, 0, c, ep->X_add_number, false,
+ false, false, &insn.insn_opcode,
+ &insn.use_extend, &insn.extend);
+ ep = NULL;
+ r = BFD_RELOC_UNUSED;
+ }
+ }
+ continue;
+
+ case '6':
+ insn.insn_opcode |= va_arg (args, int) << MIPS16OP_SH_IMM6;
+ continue;
+ }
+
+ break;
+ }
+
+ assert (r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL);
+
+ append_insn (place, &insn, ep, r, false);
+}
+
+/*
+ * Generate a "lui" instruction.
+ */
+static void
+macro_build_lui (place, counter, ep, regnum)
+ char *place;
+ int *counter;
+ expressionS *ep;
+ int regnum;
+{
+ expressionS high_expr;
+ struct mips_cl_insn insn;
+ bfd_reloc_code_real_type r;
+ CONST char *name = "lui";
+ CONST char *fmt = "t,u";
+
+ assert (! mips_opts.mips16);
+
+ if (place == NULL)
+ high_expr = *ep;
+ else
+ {
+ high_expr.X_op = O_constant;
+ high_expr.X_add_number = ep->X_add_number;
+ }
+
+ if (high_expr.X_op == O_constant)
+ {
+ /* we can compute the instruction now without a relocation entry */
+ if (high_expr.X_add_number & 0x8000)
+ high_expr.X_add_number += 0x10000;
+ high_expr.X_add_number =
+ ((unsigned long) high_expr.X_add_number >> 16) & 0xffff;
+ r = BFD_RELOC_UNUSED;
+ }
+ else
+ {
+ assert (ep->X_op == O_symbol);
+ /* _gp_disp is a special case, used from s_cpload. */
+ assert (mips_pic == NO_PIC
+ || strcmp (S_GET_NAME (ep->X_add_symbol), "_gp_disp") == 0);
+ r = BFD_RELOC_HI16_S;
+ }
+
+ /*
+ * If the macro is about to expand into a second instruction,
+ * print a warning if needed. We need to pass ip as a parameter
+ * to generate a better warning message here...
+ */
+ if (mips_opts.warn_about_macros && place == NULL && *counter == 1)
+ as_warn (_("Macro instruction expanded into multiple instructions"));
+
+ if (place == NULL)
+ *counter += 1; /* bump instruction counter */
+
+ insn.insn_mo = (struct mips_opcode *) hash_find (op_hash, name);
+ assert (insn.insn_mo);
+ assert (strcmp (name, insn.insn_mo->name) == 0);
+ assert (strcmp (fmt, insn.insn_mo->args) == 0);
+
+ insn.insn_opcode = insn.insn_mo->match | (regnum << OP_SH_RT);
+ if (r == BFD_RELOC_UNUSED)
+ {
+ insn.insn_opcode |= high_expr.X_add_number;
+ append_insn (place, &insn, NULL, r, false);
+ }
+ else
+ append_insn (place, &insn, &high_expr, r, false);
+}
+
+/* set_at()
+ * Generates code to set the $at register to true (one)
+ * if reg is less than the immediate expression.
+ */
+static void
+set_at (counter, reg, unsignedp)
+ int *counter;
+ int reg;
+ int unsignedp;
+{
+ if (imm_expr.X_op == O_constant
+ && imm_expr.X_add_number >= -0x8000
+ && imm_expr.X_add_number < 0x8000)
+ macro_build ((char *) NULL, counter, &imm_expr,
+ unsignedp ? "sltiu" : "slti",
+ "t,r,j", AT, reg, (int) BFD_RELOC_LO16);
+ else
+ {
+ load_register (counter, AT, &imm_expr, 0);
+ macro_build ((char *) NULL, counter, NULL,
+ unsignedp ? "sltu" : "slt",
+ "d,v,t", AT, reg, AT);
+ }
+}
+
+/* Warn if an expression is not a constant. */
+
+static void
+check_absolute_expr (ip, ex)
+ struct mips_cl_insn *ip;
+ expressionS *ex;
+{
+ if (ex->X_op == O_big)
+ as_bad (_("unsupported large constant"));
+ else if (ex->X_op != O_constant)
+ as_bad (_("Instruction %s requires absolute expression"), ip->insn_mo->name);
+}
+
+/* Count the leading zeroes by performing a binary chop. This is a
+ bulky bit of source, but performance is a LOT better for the
+ majority of values than a simple loop to count the bits:
+ for (lcnt = 0; (lcnt < 32); lcnt++)
+ if ((v) & (1 << (31 - lcnt)))
+ break;
+ However it is not code size friendly, and the gain will drop a bit
+ on certain cached systems.
+*/
+#define COUNT_TOP_ZEROES(v) \
+ (((v) & ~0xffff) == 0 \
+ ? ((v) & ~0xff) == 0 \
+ ? ((v) & ~0xf) == 0 \
+ ? ((v) & ~0x3) == 0 \
+ ? ((v) & ~0x1) == 0 \
+ ? !(v) \
+ ? 32 \
+ : 31 \
+ : 30 \
+ : ((v) & ~0x7) == 0 \
+ ? 29 \
+ : 28 \
+ : ((v) & ~0x3f) == 0 \
+ ? ((v) & ~0x1f) == 0 \
+ ? 27 \
+ : 26 \
+ : ((v) & ~0x7f) == 0 \
+ ? 25 \
+ : 24 \
+ : ((v) & ~0xfff) == 0 \
+ ? ((v) & ~0x3ff) == 0 \
+ ? ((v) & ~0x1ff) == 0 \
+ ? 23 \
+ : 22 \
+ : ((v) & ~0x7ff) == 0 \
+ ? 21 \
+ : 20 \
+ : ((v) & ~0x3fff) == 0 \
+ ? ((v) & ~0x1fff) == 0 \
+ ? 19 \
+ : 18 \
+ : ((v) & ~0x7fff) == 0 \
+ ? 17 \
+ : 16 \
+ : ((v) & ~0xffffff) == 0 \
+ ? ((v) & ~0xfffff) == 0 \
+ ? ((v) & ~0x3ffff) == 0 \
+ ? ((v) & ~0x1ffff) == 0 \
+ ? 15 \
+ : 14 \
+ : ((v) & ~0x7ffff) == 0 \
+ ? 13 \
+ : 12 \
+ : ((v) & ~0x3fffff) == 0 \
+ ? ((v) & ~0x1fffff) == 0 \
+ ? 11 \
+ : 10 \
+ : ((v) & ~0x7fffff) == 0 \
+ ? 9 \
+ : 8 \
+ : ((v) & ~0xfffffff) == 0 \
+ ? ((v) & ~0x3ffffff) == 0 \
+ ? ((v) & ~0x1ffffff) == 0 \
+ ? 7 \
+ : 6 \
+ : ((v) & ~0x7ffffff) == 0 \
+ ? 5 \
+ : 4 \
+ : ((v) & ~0x3fffffff) == 0 \
+ ? ((v) & ~0x1fffffff) == 0 \
+ ? 3 \
+ : 2 \
+ : ((v) & ~0x7fffffff) == 0 \
+ ? 1 \
+ : 0)
+
+/* load_register()
+ * This routine generates the least number of instructions neccessary to load
+ * an absolute expression value into a register.
+ */
+static void
+load_register (counter, reg, ep, dbl)
+ int *counter;
+ int reg;
+ expressionS *ep;
+ int dbl;
+{
+ int freg;
+ expressionS hi32, lo32;
+
+ if (ep->X_op != O_big)
+ {
+ assert (ep->X_op == O_constant);
+ if (ep->X_add_number < 0x8000
+ && (ep->X_add_number >= 0
+ || (ep->X_add_number >= -0x8000
+ && (! dbl
+ || ! ep->X_unsigned
+ || sizeof (ep->X_add_number) > 4))))
+ {
+ /* We can handle 16 bit signed values with an addiu to
+ $zero. No need to ever use daddiu here, since $zero and
+ the result are always correct in 32 bit mode. */
+ macro_build ((char *) NULL, counter, ep, "addiu", "t,r,j", reg, 0,
+ (int) BFD_RELOC_LO16);
+ return;
+ }
+ else if (ep->X_add_number >= 0 && ep->X_add_number < 0x10000)
+ {
+ /* We can handle 16 bit unsigned values with an ori to
+ $zero. */
+ macro_build ((char *) NULL, counter, ep, "ori", "t,r,i", reg, 0,
+ (int) BFD_RELOC_LO16);
+ return;
+ }
+ else if ((((ep->X_add_number &~ (offsetT) 0x7fffffff) == 0
+ || ((ep->X_add_number &~ (offsetT) 0x7fffffff)
+ == ~ (offsetT) 0x7fffffff))
+ && (! dbl
+ || ! ep->X_unsigned
+ || sizeof (ep->X_add_number) > 4
+ || (ep->X_add_number & 0x80000000) == 0))
+ || ((mips_opts.isa < 3 || ! dbl)
+ && (ep->X_add_number &~ (offsetT) 0xffffffff) == 0)
+ || (mips_opts.isa < 3
+ && ! dbl
+ && ((ep->X_add_number &~ (offsetT) 0xffffffff)
+ == ~ (offsetT) 0xffffffff)))
+ {
+ /* 32 bit values require an lui. */
+ macro_build ((char *) NULL, counter, ep, "lui", "t,u", reg,
+ (int) BFD_RELOC_HI16);
+ if ((ep->X_add_number & 0xffff) != 0)
+ macro_build ((char *) NULL, counter, ep, "ori", "t,r,i", reg, reg,
+ (int) BFD_RELOC_LO16);
+ return;
+ }
+ }
+
+ /* The value is larger than 32 bits. */
+
+ if (mips_opts.isa < 3)
+ {
+ as_bad (_("Number larger than 32 bits"));
+ macro_build ((char *) NULL, counter, ep, "addiu", "t,r,j", reg, 0,
+ (int) BFD_RELOC_LO16);
+ return;
+ }
+
+ if (ep->X_op != O_big)
+ {
+ hi32 = *ep;
+ hi32.X_add_number = (valueT) hi32.X_add_number >> 16;
+ hi32.X_add_number = (valueT) hi32.X_add_number >> 16;
+ hi32.X_add_number &= 0xffffffff;
+ lo32 = *ep;
+ lo32.X_add_number &= 0xffffffff;
+ }
+ else
+ {
+ assert (ep->X_add_number > 2);
+ if (ep->X_add_number == 3)
+ generic_bignum[3] = 0;
+ else if (ep->X_add_number > 4)
+ as_bad (_("Number larger than 64 bits"));
+ lo32.X_op = O_constant;
+ lo32.X_add_number = generic_bignum[0] + (generic_bignum[1] << 16);
+ hi32.X_op = O_constant;
+ hi32.X_add_number = generic_bignum[2] + (generic_bignum[3] << 16);
+ }
+
+ if (hi32.X_add_number == 0)
+ freg = 0;
+ else
+ {
+ int shift, bit;
+ unsigned long hi, lo;
+
+ if (hi32.X_add_number == 0xffffffff)
+ {
+ if ((lo32.X_add_number & 0xffff8000) == 0xffff8000)
+ {
+ macro_build ((char *) NULL, counter, &lo32, "addiu", "t,r,j",
+ reg, 0, (int) BFD_RELOC_LO16);
+ return;
+ }
+ if (lo32.X_add_number & 0x80000000)
+ {
+ macro_build ((char *) NULL, counter, &lo32, "lui", "t,u", reg,
+ (int) BFD_RELOC_HI16);
+ if (lo32.X_add_number & 0xffff)
+ macro_build ((char *) NULL, counter, &lo32, "ori", "t,r,i",
+ reg, reg, (int) BFD_RELOC_LO16);
+ return;
+ }
+ }
+
+ /* Check for 16bit shifted constant. We know that hi32 is
+ non-zero, so start the mask on the first bit of the hi32
+ value. */
+ shift = 17;
+ do
+ {
+ unsigned long himask, lomask;
+
+ if (shift < 32)
+ {
+ himask = 0xffff >> (32 - shift);
+ lomask = (0xffff << shift) & 0xffffffff;
+ }
+ else
+ {
+ himask = 0xffff << (shift - 32);
+ lomask = 0;
+ }
+ if ((hi32.X_add_number & ~ (offsetT) himask) == 0
+ && (lo32.X_add_number & ~ (offsetT) lomask) == 0)
+ {
+ expressionS tmp;
+
+ tmp.X_op = O_constant;
+ if (shift < 32)
+ tmp.X_add_number = ((hi32.X_add_number << (32 - shift))
+ | (lo32.X_add_number >> shift));
+ else
+ tmp.X_add_number = hi32.X_add_number >> (shift - 32);
+ macro_build ((char *) NULL, counter, &tmp, "ori", "t,r,i", reg, 0,
+ (int) BFD_RELOC_LO16);
+ macro_build ((char *) NULL, counter, NULL,
+ (shift >= 32) ? "dsll32" : "dsll",
+ "d,w,<", reg, reg,
+ (shift >= 32) ? shift - 32 : shift);
+ return;
+ }
+ shift++;
+ } while (shift <= (64 - 16));
+
+ /* Find the bit number of the lowest one bit, and store the
+ shifted value in hi/lo. */
+ hi = (unsigned long) (hi32.X_add_number & 0xffffffff);
+ lo = (unsigned long) (lo32.X_add_number & 0xffffffff);
+ if (lo != 0)
+ {
+ bit = 0;
+ while ((lo & 1) == 0)
+ {
+ lo >>= 1;
+ ++bit;
+ }
+ lo |= (hi & (((unsigned long) 1 << bit) - 1)) << (32 - bit);
+ hi >>= bit;
+ }
+ else
+ {
+ bit = 32;
+ while ((hi & 1) == 0)
+ {
+ hi >>= 1;
+ ++bit;
+ }
+ lo = hi;
+ hi = 0;
+ }
+
+ /* Optimize if the shifted value is a (power of 2) - 1. */
+ if ((hi == 0 && ((lo + 1) & lo) == 0)
+ || (lo == 0xffffffff && ((hi + 1) & hi) == 0))
+ {
+ shift = COUNT_TOP_ZEROES ((unsigned int) hi32.X_add_number);
+ if (shift != 0)
+ {
+ expressionS tmp;
+
+ /* This instruction will set the register to be all
+ ones. */
+ tmp.X_op = O_constant;
+ tmp.X_add_number = (offsetT) -1;
+ macro_build ((char *) NULL, counter, &tmp, "addiu", "t,r,j",
+ reg, 0, (int) BFD_RELOC_LO16);
+ if (bit != 0)
+ {
+ bit += shift;
+ macro_build ((char *) NULL, counter, NULL,
+ (bit >= 32) ? "dsll32" : "dsll",
+ "d,w,<", reg, reg,
+ (bit >= 32) ? bit - 32 : bit);
+ }
+ macro_build ((char *) NULL, counter, NULL,
+ (shift >= 32) ? "dsrl32" : "dsrl",
+ "d,w,<", reg, reg,
+ (shift >= 32) ? shift - 32 : shift);
+ return;
+ }
+ }
+
+ /* Sign extend hi32 before calling load_register, because we can
+ generally get better code when we load a sign extended value. */
+ if ((hi32.X_add_number & 0x80000000) != 0)
+ hi32.X_add_number |= ~ (offsetT) 0xffffffff;
+ load_register (counter, reg, &hi32, 0);
+ freg = reg;
+ }
+ if ((lo32.X_add_number & 0xffff0000) == 0)
+ {
+ if (freg != 0)
+ {
+ macro_build ((char *) NULL, counter, NULL, "dsll32", "d,w,<", reg,
+ freg, 0);
+ freg = reg;
+ }
+ }
+ else
+ {
+ expressionS mid16;
+
+ if ((freg == 0) && (lo32.X_add_number == 0xffffffff))
+ {
+ macro_build ((char *) NULL, counter, &lo32, "lui", "t,u", reg,
+ (int) BFD_RELOC_HI16);
+ macro_build ((char *) NULL, counter, NULL, "dsrl32", "d,w,<", reg,
+ reg, 0);
+ return;
+ }
+
+ if (freg != 0)
+ {
+ macro_build ((char *) NULL, counter, NULL, "dsll", "d,w,<", reg,
+ freg, 16);
+ freg = reg;
+ }
+ mid16 = lo32;
+ mid16.X_add_number >>= 16;
+ macro_build ((char *) NULL, counter, &mid16, "ori", "t,r,i", reg,
+ freg, (int) BFD_RELOC_LO16);
+ macro_build ((char *) NULL, counter, NULL, "dsll", "d,w,<", reg,
+ reg, 16);
+ freg = reg;
+ }
+ if ((lo32.X_add_number & 0xffff) != 0)
+ macro_build ((char *) NULL, counter, &lo32, "ori", "t,r,i", reg, freg,
+ (int) BFD_RELOC_LO16);
+}
+
+/* Load an address into a register. */
+
+static void
+load_address (counter, reg, ep)
+ int *counter;
+ int reg;
+ expressionS *ep;
+{
+ char *p;
+
+ if (ep->X_op != O_constant
+ && ep->X_op != O_symbol)
+ {
+ as_bad (_("expression too complex"));
+ ep->X_op = O_constant;
+ }
+
+ if (ep->X_op == O_constant)
+ {
+ load_register (counter, reg, ep, 0);
+ return;
+ }
+
+ if (mips_pic == NO_PIC)
+ {
+ /* If this is a reference to a GP relative symbol, we want
+ addiu $reg,$gp,<sym> (BFD_RELOC_MIPS_GPREL)
+ Otherwise we want
+ lui $reg,<sym> (BFD_RELOC_HI16_S)
+ addiu $reg,$reg,<sym> (BFD_RELOC_LO16)
+ If we have an addend, we always use the latter form. */
+ if ((valueT) ep->X_add_number >= MAX_GPREL_OFFSET
+ || nopic_need_relax (ep->X_add_symbol, 1))
+ p = NULL;
+ else
+ {
+ frag_grow (20);
+ macro_build ((char *) NULL, counter, ep,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", reg, GP, (int) BFD_RELOC_MIPS_GPREL);
+ p = frag_var (rs_machine_dependent, 8, 0,
+ RELAX_ENCODE (4, 8, 0, 4, 0,
+ mips_opts.warn_about_macros),
+ ep->X_add_symbol, (offsetT) 0, (char *) NULL);
+ }
+ macro_build_lui (p, counter, ep, reg);
+ if (p != NULL)
+ p += 4;
+ macro_build (p, counter, ep,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
+ }
+ else if (mips_pic == SVR4_PIC && ! mips_big_got)
+ {
+ expressionS ex;
+
+ /* If this is a reference to an external symbol, we want
+ lw $reg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
+ Otherwise we want
+ lw $reg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
+ nop
+ addiu $reg,$reg,<sym> (BFD_RELOC_LO16)
+ If there is a constant, it must be added in after. */
+ ex.X_add_number = ep->X_add_number;
+ ep->X_add_number = 0;
+ frag_grow (20);
+ macro_build ((char *) NULL, counter, ep,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "lw" : "ld"),
+ "t,o(b)", reg, (int) BFD_RELOC_MIPS_GOT16, GP);
+ macro_build ((char *) NULL, counter, (expressionS *) NULL, "nop", "");
+ p = frag_var (rs_machine_dependent, 4, 0,
+ RELAX_ENCODE (0, 4, -8, 0, 0, mips_opts.warn_about_macros),
+ ep->X_add_symbol, (offsetT) 0, (char *) NULL);
+ macro_build (p, counter, ep,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
+ if (ex.X_add_number != 0)
+ {
+ if (ex.X_add_number < -0x8000 || ex.X_add_number >= 0x8000)
+ as_bad (_("PIC code offset overflow (max 16 signed bits)"));
+ ex.X_op = O_constant;
+ macro_build ((char *) NULL, counter, &ex,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
+ }
+ }
+ else if (mips_pic == SVR4_PIC)
+ {
+ expressionS ex;
+ int off;
+
+ /* This is the large GOT case. If this is a reference to an
+ external symbol, we want
+ lui $reg,<sym> (BFD_RELOC_MIPS_GOT_HI16)
+ addu $reg,$reg,$gp
+ lw $reg,<sym>($reg) (BFD_RELOC_MIPS_GOT_LO16)
+ Otherwise, for a reference to a local symbol, we want
+ lw $reg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
+ nop
+ addiu $reg,$reg,<sym> (BFD_RELOC_LO16)
+ If there is a constant, it must be added in after. */
+ ex.X_add_number = ep->X_add_number;
+ ep->X_add_number = 0;
+ if (reg_needs_delay (GP))
+ off = 4;
+ else
+ off = 0;
+ frag_grow (32);
+ macro_build ((char *) NULL, counter, ep, "lui", "t,u", reg,
+ (int) BFD_RELOC_MIPS_GOT_HI16);
+ macro_build ((char *) NULL, counter, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", reg, reg, GP);
+ macro_build ((char *) NULL, counter, ep,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "lw" : "ld"),
+ "t,o(b)", reg, (int) BFD_RELOC_MIPS_GOT_LO16, reg);
+ p = frag_var (rs_machine_dependent, 12 + off, 0,
+ RELAX_ENCODE (12, 12 + off, off, 8 + off, 0,
+ mips_opts.warn_about_macros),
+ ep->X_add_symbol, (offsetT) 0, (char *) NULL);
+ if (off > 0)
+ {
+ /* We need a nop before loading from $gp. This special
+ check is required because the lui which starts the main
+ instruction stream does not refer to $gp, and so will not
+ insert the nop which may be required. */
+ macro_build (p, counter, (expressionS *) NULL, "nop", "");
+ p += 4;
+ }
+ macro_build (p, counter, ep,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "lw" : "ld"),
+ "t,o(b)", reg, (int) BFD_RELOC_MIPS_GOT16, GP);
+ p += 4;
+ macro_build (p, counter, (expressionS *) NULL, "nop", "");
+ p += 4;
+ macro_build (p, counter, ep,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
+ if (ex.X_add_number != 0)
+ {
+ if (ex.X_add_number < -0x8000 || ex.X_add_number >= 0x8000)
+ as_bad (_("PIC code offset overflow (max 16 signed bits)"));
+ ex.X_op = O_constant;
+ macro_build ((char *) NULL, counter, &ex,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", reg, reg, (int) BFD_RELOC_LO16);
+ }
+ }
+ else if (mips_pic == EMBEDDED_PIC)
+ {
+ /* We always do
+ addiu $reg,$gp,<sym> (BFD_RELOC_MIPS_GPREL)
+ */
+ macro_build ((char *) NULL, counter, ep,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", reg, GP, (int) BFD_RELOC_MIPS_GPREL);
+ }
+ else
+ abort ();
+}
+
+/*
+ * Build macros
+ * This routine implements the seemingly endless macro or synthesized
+ * instructions and addressing modes in the mips assembly language. Many
+ * of these macros are simple and are similar to each other. These could
+ * probably be handled by some kind of table or grammer aproach instead of
+ * this verbose method. Others are not simple macros but are more like
+ * optimizing code generation.
+ * One interesting optimization is when several store macros appear
+ * consecutivly that would load AT with the upper half of the same address.
+ * The ensuing load upper instructions are ommited. This implies some kind
+ * of global optimization. We currently only optimize within a single macro.
+ * For many of the load and store macros if the address is specified as a
+ * constant expression in the first 64k of memory (ie ld $2,0x4000c) we
+ * first load register 'at' with zero and use it as the base register. The
+ * mips assembler simply uses register $zero. Just one tiny optimization
+ * we're missing.
+ */
+static void
+macro (ip)
+ struct mips_cl_insn *ip;
+{
+ register int treg, sreg, dreg, breg;
+ int tempreg;
+ int mask;
+ int icnt = 0;
+ int used_at;
+ expressionS expr1;
+ const char *s;
+ const char *s2;
+ const char *fmt;
+ int likely = 0;
+ int dbl = 0;
+ int coproc = 0;
+ int lr = 0;
+ int imm = 0;
+ offsetT maxnum;
+ int off;
+ bfd_reloc_code_real_type r;
+ char *p;
+ int hold_mips_optimize;
+
+ assert (! mips_opts.mips16);
+
+ treg = (ip->insn_opcode >> 16) & 0x1f;
+ dreg = (ip->insn_opcode >> 11) & 0x1f;
+ sreg = breg = (ip->insn_opcode >> 21) & 0x1f;
+ mask = ip->insn_mo->mask;
+
+ expr1.X_op = O_constant;
+ expr1.X_op_symbol = NULL;
+ expr1.X_add_symbol = NULL;
+ expr1.X_add_number = 1;
+
+ switch (mask)
+ {
+ case M_DABS:
+ dbl = 1;
+ case M_ABS:
+ /* bgez $a0,.+12
+ move v0,$a0
+ sub v0,$zero,$a0
+ */
+
+ mips_emit_delays (true);
+ ++mips_opts.noreorder;
+ mips_any_noreorder = 1;
+
+ expr1.X_add_number = 8;
+ macro_build ((char *) NULL, &icnt, &expr1, "bgez", "s,p", sreg);
+ if (dreg == sreg)
+ macro_build ((char *) NULL, &icnt, NULL, "nop", "", 0);
+ else
+ macro_build ((char *) NULL, &icnt, NULL, "move", "d,s", dreg, sreg, 0);
+ macro_build ((char *) NULL, &icnt, NULL,
+ dbl ? "dsub" : "sub",
+ "d,v,t", dreg, 0, sreg);
+
+ --mips_opts.noreorder;
+ return;
+
+ case M_ADD_I:
+ s = "addi";
+ s2 = "add";
+ goto do_addi;
+ case M_ADDU_I:
+ s = "addiu";
+ s2 = "addu";
+ goto do_addi;
+ case M_DADD_I:
+ dbl = 1;
+ s = "daddi";
+ s2 = "dadd";
+ goto do_addi;
+ case M_DADDU_I:
+ dbl = 1;
+ s = "daddiu";
+ s2 = "daddu";
+ do_addi:
+ if (imm_expr.X_op == O_constant
+ && imm_expr.X_add_number >= -0x8000
+ && imm_expr.X_add_number < 0x8000)
+ {
+ macro_build ((char *) NULL, &icnt, &imm_expr, s, "t,r,j", treg, sreg,
+ (int) BFD_RELOC_LO16);
+ return;
+ }
+ load_register (&icnt, AT, &imm_expr, dbl);
+ macro_build ((char *) NULL, &icnt, NULL, s2, "d,v,t", treg, sreg, AT);
+ break;
+
+ case M_AND_I:
+ s = "andi";
+ s2 = "and";
+ goto do_bit;
+ case M_OR_I:
+ s = "ori";
+ s2 = "or";
+ goto do_bit;
+ case M_NOR_I:
+ s = "";
+ s2 = "nor";
+ goto do_bit;
+ case M_XOR_I:
+ s = "xori";
+ s2 = "xor";
+ do_bit:
+ if (imm_expr.X_op == O_constant
+ && imm_expr.X_add_number >= 0
+ && imm_expr.X_add_number < 0x10000)
+ {
+ if (mask != M_NOR_I)
+ macro_build ((char *) NULL, &icnt, &imm_expr, s, "t,r,i", treg,
+ sreg, (int) BFD_RELOC_LO16);
+ else
+ {
+ macro_build ((char *) NULL, &icnt, &imm_expr, "ori", "t,r,i",
+ treg, sreg, (int) BFD_RELOC_LO16);
+ macro_build ((char *) NULL, &icnt, NULL, "nor", "d,v,t",
+ treg, treg, 0);
+ }
+ return;
+ }
+
+ load_register (&icnt, AT, &imm_expr, 0);
+ macro_build ((char *) NULL, &icnt, NULL, s2, "d,v,t", treg, sreg, AT);
+ break;
+
+ case M_BEQ_I:
+ s = "beq";
+ goto beq_i;
+ case M_BEQL_I:
+ s = "beql";
+ likely = 1;
+ goto beq_i;
+ case M_BNE_I:
+ s = "bne";
+ goto beq_i;
+ case M_BNEL_I:
+ s = "bnel";
+ likely = 1;
+ beq_i:
+ if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 0)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr, s, "s,t,p", sreg,
+ 0);
+ return;
+ }
+ load_register (&icnt, AT, &imm_expr, 0);
+ macro_build ((char *) NULL, &icnt, &offset_expr, s, "s,t,p", sreg, AT);
+ break;
+
+ case M_BGEL:
+ likely = 1;
+ case M_BGE:
+ if (treg == 0)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "bgezl" : "bgez",
+ "s,p", sreg);
+ return;
+ }
+ if (sreg == 0)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "blezl" : "blez",
+ "s,p", treg);
+ return;
+ }
+ macro_build ((char *) NULL, &icnt, NULL, "slt", "d,v,t", AT, sreg, treg);
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "beql" : "beq",
+ "s,t,p", AT, 0);
+ break;
+
+ case M_BGTL_I:
+ likely = 1;
+ case M_BGT_I:
+ /* check for > max integer */
+ maxnum = 0x7fffffff;
+ if (mips_opts.isa >= 3 && sizeof (maxnum) > 4)
+ {
+ maxnum <<= 16;
+ maxnum |= 0xffff;
+ maxnum <<= 16;
+ maxnum |= 0xffff;
+ }
+ if (imm_expr.X_op == O_constant
+ && imm_expr.X_add_number >= maxnum
+ && (mips_opts.isa < 3 || sizeof (maxnum) > 4))
+ {
+ do_false:
+ /* result is always false */
+ if (! likely)
+ {
+ as_warn (_("Branch %s is always false (nop)"), ip->insn_mo->name);
+ macro_build ((char *) NULL, &icnt, NULL, "nop", "", 0);
+ }
+ else
+ {
+ as_warn (_("Branch likely %s is always false"), ip->insn_mo->name);
+ macro_build ((char *) NULL, &icnt, &offset_expr, "bnel",
+ "s,t,p", 0, 0);
+ }
+ return;
+ }
+ if (imm_expr.X_op != O_constant)
+ as_bad (_("Unsupported large constant"));
+ imm_expr.X_add_number++;
+ /* FALLTHROUGH */
+ case M_BGE_I:
+ case M_BGEL_I:
+ if (mask == M_BGEL_I)
+ likely = 1;
+ if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 0)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "bgezl" : "bgez",
+ "s,p", sreg);
+ return;
+ }
+ if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 1)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "bgtzl" : "bgtz",
+ "s,p", sreg);
+ return;
+ }
+ maxnum = 0x7fffffff;
+ if (mips_opts.isa >= 3 && sizeof (maxnum) > 4)
+ {
+ maxnum <<= 16;
+ maxnum |= 0xffff;
+ maxnum <<= 16;
+ maxnum |= 0xffff;
+ }
+ maxnum = - maxnum - 1;
+ if (imm_expr.X_op == O_constant
+ && imm_expr.X_add_number <= maxnum
+ && (mips_opts.isa < 3 || sizeof (maxnum) > 4))
+ {
+ do_true:
+ /* result is always true */
+ as_warn (_("Branch %s is always true"), ip->insn_mo->name);
+ macro_build ((char *) NULL, &icnt, &offset_expr, "b", "p");
+ return;
+ }
+ set_at (&icnt, sreg, 0);
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "beql" : "beq",
+ "s,t,p", AT, 0);
+ break;
+
+ case M_BGEUL:
+ likely = 1;
+ case M_BGEU:
+ if (treg == 0)
+ goto do_true;
+ if (sreg == 0)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "beql" : "beq",
+ "s,t,p", 0, treg);
+ return;
+ }
+ macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", AT, sreg,
+ treg);
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "beql" : "beq",
+ "s,t,p", AT, 0);
+ break;
+
+ case M_BGTUL_I:
+ likely = 1;
+ case M_BGTU_I:
+ if (sreg == 0
+ || (mips_opts.isa < 3
+ && imm_expr.X_op == O_constant
+ && imm_expr.X_add_number == 0xffffffff))
+ goto do_false;
+ if (imm_expr.X_op != O_constant)
+ as_bad (_("Unsupported large constant"));
+ imm_expr.X_add_number++;
+ /* FALLTHROUGH */
+ case M_BGEU_I:
+ case M_BGEUL_I:
+ if (mask == M_BGEUL_I)
+ likely = 1;
+ if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 0)
+ goto do_true;
+ if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 1)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "bnel" : "bne",
+ "s,t,p", sreg, 0);
+ return;
+ }
+ set_at (&icnt, sreg, 1);
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "beql" : "beq",
+ "s,t,p", AT, 0);
+ break;
+
+ case M_BGTL:
+ likely = 1;
+ case M_BGT:
+ if (treg == 0)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "bgtzl" : "bgtz",
+ "s,p", sreg);
+ return;
+ }
+ if (sreg == 0)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "bltzl" : "bltz",
+ "s,p", treg);
+ return;
+ }
+ macro_build ((char *) NULL, &icnt, NULL, "slt", "d,v,t", AT, treg, sreg);
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "bnel" : "bne",
+ "s,t,p", AT, 0);
+ break;
+
+ case M_BGTUL:
+ likely = 1;
+ case M_BGTU:
+ if (treg == 0)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "bnel" : "bne",
+ "s,t,p", sreg, 0);
+ return;
+ }
+ if (sreg == 0)
+ goto do_false;
+ macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", AT, treg,
+ sreg);
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "bnel" : "bne",
+ "s,t,p", AT, 0);
+ break;
+
+ case M_BLEL:
+ likely = 1;
+ case M_BLE:
+ if (treg == 0)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "blezl" : "blez",
+ "s,p", sreg);
+ return;
+ }
+ if (sreg == 0)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "bgezl" : "bgez",
+ "s,p", treg);
+ return;
+ }
+ macro_build ((char *) NULL, &icnt, NULL, "slt", "d,v,t", AT, treg, sreg);
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "beql" : "beq",
+ "s,t,p", AT, 0);
+ break;
+
+ case M_BLEL_I:
+ likely = 1;
+ case M_BLE_I:
+ maxnum = 0x7fffffff;
+ if (mips_opts.isa >= 3 && sizeof (maxnum) > 4)
+ {
+ maxnum <<= 16;
+ maxnum |= 0xffff;
+ maxnum <<= 16;
+ maxnum |= 0xffff;
+ }
+ if (imm_expr.X_op == O_constant
+ && imm_expr.X_add_number >= maxnum
+ && (mips_opts.isa < 3 || sizeof (maxnum) > 4))
+ goto do_true;
+ if (imm_expr.X_op != O_constant)
+ as_bad (_("Unsupported large constant"));
+ imm_expr.X_add_number++;
+ /* FALLTHROUGH */
+ case M_BLT_I:
+ case M_BLTL_I:
+ if (mask == M_BLTL_I)
+ likely = 1;
+ if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 0)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "bltzl" : "bltz",
+ "s,p", sreg);
+ return;
+ }
+ if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 1)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "blezl" : "blez",
+ "s,p", sreg);
+ return;
+ }
+ set_at (&icnt, sreg, 0);
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "bnel" : "bne",
+ "s,t,p", AT, 0);
+ break;
+
+ case M_BLEUL:
+ likely = 1;
+ case M_BLEU:
+ if (treg == 0)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "beql" : "beq",
+ "s,t,p", sreg, 0);
+ return;
+ }
+ if (sreg == 0)
+ goto do_true;
+ macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", AT, treg,
+ sreg);
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "beql" : "beq",
+ "s,t,p", AT, 0);
+ break;
+
+ case M_BLEUL_I:
+ likely = 1;
+ case M_BLEU_I:
+ if (sreg == 0
+ || (mips_opts.isa < 3
+ && imm_expr.X_op == O_constant
+ && imm_expr.X_add_number == 0xffffffff))
+ goto do_true;
+ if (imm_expr.X_op != O_constant)
+ as_bad (_("Unsupported large constant"));
+ imm_expr.X_add_number++;
+ /* FALLTHROUGH */
+ case M_BLTU_I:
+ case M_BLTUL_I:
+ if (mask == M_BLTUL_I)
+ likely = 1;
+ if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 0)
+ goto do_false;
+ if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 1)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "beql" : "beq",
+ "s,t,p", sreg, 0);
+ return;
+ }
+ set_at (&icnt, sreg, 1);
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "bnel" : "bne",
+ "s,t,p", AT, 0);
+ break;
+
+ case M_BLTL:
+ likely = 1;
+ case M_BLT:
+ if (treg == 0)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "bltzl" : "bltz",
+ "s,p", sreg);
+ return;
+ }
+ if (sreg == 0)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "bgtzl" : "bgtz",
+ "s,p", treg);
+ return;
+ }
+ macro_build ((char *) NULL, &icnt, NULL, "slt", "d,v,t", AT, sreg, treg);
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "bnel" : "bne",
+ "s,t,p", AT, 0);
+ break;
+
+ case M_BLTUL:
+ likely = 1;
+ case M_BLTU:
+ if (treg == 0)
+ goto do_false;
+ if (sreg == 0)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "bnel" : "bne",
+ "s,t,p", 0, treg);
+ return;
+ }
+ macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", AT, sreg,
+ treg);
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ likely ? "bnel" : "bne",
+ "s,t,p", AT, 0);
+ break;
+
+ case M_DDIV_3:
+ dbl = 1;
+ case M_DIV_3:
+ s = "mflo";
+ goto do_div3;
+ case M_DREM_3:
+ dbl = 1;
+ case M_REM_3:
+ s = "mfhi";
+ do_div3:
+ if (treg == 0)
+ {
+ as_warn (_("Divide by zero."));
+ if (mips_trap)
+ macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", 0, 0);
+ else
+ macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
+ return;
+ }
+
+ mips_emit_delays (true);
+ ++mips_opts.noreorder;
+ mips_any_noreorder = 1;
+ if (mips_trap)
+ {
+ macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", treg, 0);
+ macro_build ((char *) NULL, &icnt, NULL,
+ dbl ? "ddiv" : "div",
+ "z,s,t", sreg, treg);
+ }
+ else
+ {
+ expr1.X_add_number = 8;
+ macro_build ((char *) NULL, &icnt, &expr1, "bne", "s,t,p", treg, 0);
+ macro_build ((char *) NULL, &icnt, NULL,
+ dbl ? "ddiv" : "div",
+ "z,s,t", sreg, treg);
+ macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
+ }
+ expr1.X_add_number = -1;
+ macro_build ((char *) NULL, &icnt, &expr1,
+ dbl ? "daddiu" : "addiu",
+ "t,r,j", AT, 0, (int) BFD_RELOC_LO16);
+ expr1.X_add_number = mips_trap ? (dbl ? 12 : 8) : (dbl ? 20 : 16);
+ macro_build ((char *) NULL, &icnt, &expr1, "bne", "s,t,p", treg, AT);
+ if (dbl)
+ {
+ expr1.X_add_number = 1;
+ macro_build ((char *) NULL, &icnt, &expr1, "daddiu", "t,r,j", AT, 0,
+ (int) BFD_RELOC_LO16);
+ macro_build ((char *) NULL, &icnt, NULL, "dsll32", "d,w,<", AT, AT,
+ 31);
+ }
+ else
+ {
+ expr1.X_add_number = 0x80000000;
+ macro_build ((char *) NULL, &icnt, &expr1, "lui", "t,u", AT,
+ (int) BFD_RELOC_HI16);
+ }
+ if (mips_trap)
+ {
+ macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", sreg, AT);
+ /* We want to close the noreorder block as soon as possible, so
+ that later insns are available for delay slot filling. */
+ --mips_opts.noreorder;
+ }
+ else
+ {
+ expr1.X_add_number = 8;
+ macro_build ((char *) NULL, &icnt, &expr1, "bne", "s,t,p", sreg, AT);
+ macro_build ((char *) NULL, &icnt, NULL, "nop", "", 0);
+
+ /* We want to close the noreorder block as soon as possible, so
+ that later insns are available for delay slot filling. */
+ --mips_opts.noreorder;
+
+ macro_build ((char *) NULL, &icnt, NULL, "break", "c", 6);
+ }
+ macro_build ((char *) NULL, &icnt, NULL, s, "d", dreg);
+ break;
+
+ case M_DIV_3I:
+ s = "div";
+ s2 = "mflo";
+ goto do_divi;
+ case M_DIVU_3I:
+ s = "divu";
+ s2 = "mflo";
+ goto do_divi;
+ case M_REM_3I:
+ s = "div";
+ s2 = "mfhi";
+ goto do_divi;
+ case M_REMU_3I:
+ s = "divu";
+ s2 = "mfhi";
+ goto do_divi;
+ case M_DDIV_3I:
+ dbl = 1;
+ s = "ddiv";
+ s2 = "mflo";
+ goto do_divi;
+ case M_DDIVU_3I:
+ dbl = 1;
+ s = "ddivu";
+ s2 = "mflo";
+ goto do_divi;
+ case M_DREM_3I:
+ dbl = 1;
+ s = "ddiv";
+ s2 = "mfhi";
+ goto do_divi;
+ case M_DREMU_3I:
+ dbl = 1;
+ s = "ddivu";
+ s2 = "mfhi";
+ do_divi:
+ if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 0)
+ {
+ as_warn (_("Divide by zero."));
+ if (mips_trap)
+ macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", 0, 0);
+ else
+ macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
+ return;
+ }
+ if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 1)
+ {
+ if (strcmp (s2, "mflo") == 0)
+ macro_build ((char *) NULL, &icnt, NULL, "move", "d,s", dreg,
+ sreg);
+ else
+ macro_build ((char *) NULL, &icnt, NULL, "move", "d,s", dreg, 0);
+ return;
+ }
+ if (imm_expr.X_op == O_constant
+ && imm_expr.X_add_number == -1
+ && s[strlen (s) - 1] != 'u')
+ {
+ if (strcmp (s2, "mflo") == 0)
+ {
+ if (dbl)
+ macro_build ((char *) NULL, &icnt, NULL, "dneg", "d,w", dreg,
+ sreg);
+ else
+ macro_build ((char *) NULL, &icnt, NULL, "neg", "d,w", dreg,
+ sreg);
+ }
+ else
+ macro_build ((char *) NULL, &icnt, NULL, "move", "d,s", dreg, 0);
+ return;
+ }
+
+ load_register (&icnt, AT, &imm_expr, dbl);
+ macro_build ((char *) NULL, &icnt, NULL, s, "z,s,t", sreg, AT);
+ macro_build ((char *) NULL, &icnt, NULL, s2, "d", dreg);
+ break;
+
+ case M_DIVU_3:
+ s = "divu";
+ s2 = "mflo";
+ goto do_divu3;
+ case M_REMU_3:
+ s = "divu";
+ s2 = "mfhi";
+ goto do_divu3;
+ case M_DDIVU_3:
+ s = "ddivu";
+ s2 = "mflo";
+ goto do_divu3;
+ case M_DREMU_3:
+ s = "ddivu";
+ s2 = "mfhi";
+ do_divu3:
+ mips_emit_delays (true);
+ ++mips_opts.noreorder;
+ mips_any_noreorder = 1;
+ if (mips_trap)
+ {
+ macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", treg, 0);
+ macro_build ((char *) NULL, &icnt, NULL, s, "z,s,t", sreg, treg);
+ /* We want to close the noreorder block as soon as possible, so
+ that later insns are available for delay slot filling. */
+ --mips_opts.noreorder;
+ }
+ else
+ {
+ expr1.X_add_number = 8;
+ macro_build ((char *) NULL, &icnt, &expr1, "bne", "s,t,p", treg, 0);
+ macro_build ((char *) NULL, &icnt, NULL, s, "z,s,t", sreg, treg);
+
+ /* We want to close the noreorder block as soon as possible, so
+ that later insns are available for delay slot filling. */
+ --mips_opts.noreorder;
+ macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
+ }
+ macro_build ((char *) NULL, &icnt, NULL, s2, "d", dreg);
+ return;
+
+ case M_DLA_AB:
+ dbl = 1;
+ case M_LA_AB:
+ /* Load the address of a symbol into a register. If breg is not
+ zero, we then add a base register to it. */
+
+ /* When generating embedded PIC code, we permit expressions of
+ the form
+ la $4,foo-bar
+ where bar is an address in the .text section. These are used
+ when getting the addresses of functions. We don't permit
+ X_add_number to be non-zero, because if the symbol is
+ external the relaxing code needs to know that any addend is
+ purely the offset to X_op_symbol. */
+ if (mips_pic == EMBEDDED_PIC
+ && offset_expr.X_op == O_subtract
+ && now_seg == text_section
+ && (offset_expr.X_op_symbol->sy_value.X_op == O_constant
+ ? S_GET_SEGMENT (offset_expr.X_op_symbol) == text_section
+ : (offset_expr.X_op_symbol->sy_value.X_op == O_symbol
+ && (S_GET_SEGMENT (offset_expr.X_op_symbol
+ ->sy_value.X_add_symbol)
+ == text_section)))
+ && breg == 0
+ && offset_expr.X_add_number == 0)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
+ treg, (int) BFD_RELOC_PCREL_HI16_S);
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", treg, treg, (int) BFD_RELOC_PCREL_LO16);
+ return;
+ }
+
+ if (offset_expr.X_op != O_symbol
+ && offset_expr.X_op != O_constant)
+ {
+ as_bad (_("expression too complex"));
+ offset_expr.X_op = O_constant;
+ }
+
+ if (treg == breg)
+ {
+ tempreg = AT;
+ used_at = 1;
+ }
+ else
+ {
+ tempreg = treg;
+ used_at = 0;
+ }
+
+ if (offset_expr.X_op == O_constant)
+ load_register (&icnt, tempreg, &offset_expr, dbl);
+ else if (mips_pic == NO_PIC)
+ {
+ /* If this is a reference to an GP relative symbol, we want
+ addiu $tempreg,$gp,<sym> (BFD_RELOC_MIPS_GPREL)
+ Otherwise we want
+ lui $tempreg,<sym> (BFD_RELOC_HI16_S)
+ addiu $tempreg,$tempreg,<sym> (BFD_RELOC_LO16)
+ If we have a constant, we need two instructions anyhow,
+ so we may as well always use the latter form. */
+ if ((valueT) offset_expr.X_add_number >= MAX_GPREL_OFFSET
+ || nopic_need_relax (offset_expr.X_add_symbol, 1))
+ p = NULL;
+ else
+ {
+ frag_grow (20);
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", tempreg, GP, (int) BFD_RELOC_MIPS_GPREL);
+ p = frag_var (rs_machine_dependent, 8, 0,
+ RELAX_ENCODE (4, 8, 0, 4, 0,
+ mips_opts.warn_about_macros),
+ offset_expr.X_add_symbol, (offsetT) 0,
+ (char *) NULL);
+ }
+ macro_build_lui (p, &icnt, &offset_expr, tempreg);
+ if (p != NULL)
+ p += 4;
+ macro_build (p, &icnt, &offset_expr,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
+ }
+ else if (mips_pic == SVR4_PIC && ! mips_big_got)
+ {
+ /* If this is a reference to an external symbol, and there
+ is no constant, we want
+ lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
+ For a local symbol, we want
+ lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
+ nop
+ addiu $tempreg,$tempreg,<sym> (BFD_RELOC_LO16)
+
+ If we have a small constant, and this is a reference to
+ an external symbol, we want
+ lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
+ nop
+ addiu $tempreg,$tempreg,<constant>
+ For a local symbol, we want the same instruction
+ sequence, but we output a BFD_RELOC_LO16 reloc on the
+ addiu instruction.
+
+ If we have a large constant, and this is a reference to
+ an external symbol, we want
+ lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
+ lui $at,<hiconstant>
+ addiu $at,$at,<loconstant>
+ addu $tempreg,$tempreg,$at
+ For a local symbol, we want the same instruction
+ sequence, but we output a BFD_RELOC_LO16 reloc on the
+ addiu instruction. */
+ expr1.X_add_number = offset_expr.X_add_number;
+ offset_expr.X_add_number = 0;
+ frag_grow (32);
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ dbl ? "ld" : "lw",
+ "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT16, GP);
+ if (expr1.X_add_number == 0)
+ {
+ int off;
+
+ if (breg == 0)
+ off = 0;
+ else
+ {
+ /* We're going to put in an addu instruction using
+ tempreg, so we may as well insert the nop right
+ now. */
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ "nop", "");
+ off = 4;
+ }
+ p = frag_var (rs_machine_dependent, 8 - off, 0,
+ RELAX_ENCODE (0, 8 - off, -4 - off, 4 - off, 0,
+ (breg == 0
+ ? mips_opts.warn_about_macros
+ : 0)),
+ offset_expr.X_add_symbol, (offsetT) 0,
+ (char *) NULL);
+ if (breg == 0)
+ {
+ macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
+ p += 4;
+ }
+ macro_build (p, &icnt, &expr1,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
+ /* FIXME: If breg == 0, and the next instruction uses
+ $tempreg, then if this variant case is used an extra
+ nop will be generated. */
+ }
+ else if (expr1.X_add_number >= -0x8000
+ && expr1.X_add_number < 0x8000)
+ {
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ "nop", "");
+ macro_build ((char *) NULL, &icnt, &expr1,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
+ (void) frag_var (rs_machine_dependent, 0, 0,
+ RELAX_ENCODE (0, 0, -12, -4, 0, 0),
+ offset_expr.X_add_symbol, (offsetT) 0,
+ (char *) NULL);
+ }
+ else
+ {
+ int off1;
+
+ /* If we are going to add in a base register, and the
+ target register and the base register are the same,
+ then we are using AT as a temporary register. Since
+ we want to load the constant into AT, we add our
+ current AT (from the global offset table) and the
+ register into the register now, and pretend we were
+ not using a base register. */
+ if (breg != treg)
+ off1 = 0;
+ else
+ {
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ "nop", "");
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", treg, AT, breg);
+ breg = 0;
+ tempreg = treg;
+ off1 = -8;
+ }
+
+ /* Set mips_optimize around the lui instruction to avoid
+ inserting an unnecessary nop after the lw. */
+ hold_mips_optimize = mips_optimize;
+ mips_optimize = 2;
+ macro_build_lui ((char *) NULL, &icnt, &expr1, AT);
+ mips_optimize = hold_mips_optimize;
+
+ macro_build ((char *) NULL, &icnt, &expr1,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", AT, AT, (int) BFD_RELOC_LO16);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", tempreg, tempreg, AT);
+ (void) frag_var (rs_machine_dependent, 0, 0,
+ RELAX_ENCODE (0, 0, -16 + off1, -8, 0, 0),
+ offset_expr.X_add_symbol, (offsetT) 0,
+ (char *) NULL);
+ used_at = 1;
+ }
+ }
+ else if (mips_pic == SVR4_PIC)
+ {
+ int gpdel;
+
+ /* This is the large GOT case. If this is a reference to an
+ external symbol, and there is no constant, we want
+ lui $tempreg,<sym> (BFD_RELOC_MIPS_GOT_HI16)
+ addu $tempreg,$tempreg,$gp
+ lw $tempreg,<sym>($tempreg) (BFD_RELOC_MIPS_GOT_LO16)
+ For a local symbol, we want
+ lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
+ nop
+ addiu $tempreg,$tempreg,<sym> (BFD_RELOC_LO16)
+
+ If we have a small constant, and this is a reference to
+ an external symbol, we want
+ lui $tempreg,<sym> (BFD_RELOC_MIPS_GOT_HI16)
+ addu $tempreg,$tempreg,$gp
+ lw $tempreg,<sym>($tempreg) (BFD_RELOC_MIPS_GOT_LO16)
+ nop
+ addiu $tempreg,$tempreg,<constant>
+ For a local symbol, we want
+ lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
+ nop
+ addiu $tempreg,$tempreg,<constant> (BFD_RELOC_LO16)
+
+ If we have a large constant, and this is a reference to
+ an external symbol, we want
+ lui $tempreg,<sym> (BFD_RELOC_MIPS_GOT_HI16)
+ addu $tempreg,$tempreg,$gp
+ lw $tempreg,<sym>($tempreg) (BFD_RELOC_MIPS_GOT_LO16)
+ lui $at,<hiconstant>
+ addiu $at,$at,<loconstant>
+ addu $tempreg,$tempreg,$at
+ For a local symbol, we want
+ lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
+ lui $at,<hiconstant>
+ addiu $at,$at,<loconstant> (BFD_RELOC_LO16)
+ addu $tempreg,$tempreg,$at
+ */
+ expr1.X_add_number = offset_expr.X_add_number;
+ offset_expr.X_add_number = 0;
+ frag_grow (52);
+ if (reg_needs_delay (GP))
+ gpdel = 4;
+ else
+ gpdel = 0;
+ macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
+ tempreg, (int) BFD_RELOC_MIPS_GOT_HI16);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", tempreg, tempreg, GP);
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ dbl ? "ld" : "lw",
+ "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT_LO16,
+ tempreg);
+ if (expr1.X_add_number == 0)
+ {
+ int off;
+
+ if (breg == 0)
+ off = 0;
+ else
+ {
+ /* We're going to put in an addu instruction using
+ tempreg, so we may as well insert the nop right
+ now. */
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ "nop", "");
+ off = 4;
+ }
+
+ p = frag_var (rs_machine_dependent, 12 + gpdel, 0,
+ RELAX_ENCODE (12 + off, 12 + gpdel, gpdel,
+ 8 + gpdel, 0,
+ (breg == 0
+ ? mips_opts.warn_about_macros
+ : 0)),
+ offset_expr.X_add_symbol, (offsetT) 0,
+ (char *) NULL);
+ }
+ else if (expr1.X_add_number >= -0x8000
+ && expr1.X_add_number < 0x8000)
+ {
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ "nop", "");
+ macro_build ((char *) NULL, &icnt, &expr1,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
+
+ p = frag_var (rs_machine_dependent, 12 + gpdel, 0,
+ RELAX_ENCODE (20, 12 + gpdel, gpdel, 8 + gpdel, 0,
+ (breg == 0
+ ? mips_opts.warn_about_macros
+ : 0)),
+ offset_expr.X_add_symbol, (offsetT) 0,
+ (char *) NULL);
+ }
+ else
+ {
+ int adj, dreg;
+
+ /* If we are going to add in a base register, and the
+ target register and the base register are the same,
+ then we are using AT as a temporary register. Since
+ we want to load the constant into AT, we add our
+ current AT (from the global offset table) and the
+ register into the register now, and pretend we were
+ not using a base register. */
+ if (breg != treg)
+ {
+ adj = 0;
+ dreg = tempreg;
+ }
+ else
+ {
+ assert (tempreg == AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ "nop", "");
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", treg, AT, breg);
+ dreg = treg;
+ adj = 8;
+ }
+
+ /* Set mips_optimize around the lui instruction to avoid
+ inserting an unnecessary nop after the lw. */
+ hold_mips_optimize = mips_optimize;
+ mips_optimize = 2;
+ macro_build_lui ((char *) NULL, &icnt, &expr1, AT);
+ mips_optimize = hold_mips_optimize;
+
+ macro_build ((char *) NULL, &icnt, &expr1,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", AT, AT, (int) BFD_RELOC_LO16);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", dreg, dreg, AT);
+
+ p = frag_var (rs_machine_dependent, 16 + gpdel + adj, 0,
+ RELAX_ENCODE (24 + adj, 16 + gpdel + adj, gpdel,
+ 8 + gpdel, 0,
+ (breg == 0
+ ? mips_opts.warn_about_macros
+ : 0)),
+ offset_expr.X_add_symbol, (offsetT) 0,
+ (char *) NULL);
+
+ used_at = 1;
+ }
+
+ if (gpdel > 0)
+ {
+ /* This is needed because this instruction uses $gp, but
+ the first instruction on the main stream does not. */
+ macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
+ p += 4;
+ }
+ macro_build (p, &icnt, &offset_expr,
+ dbl ? "ld" : "lw",
+ "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT16, GP);
+ p += 4;
+ if (expr1.X_add_number >= -0x8000
+ && expr1.X_add_number < 0x8000)
+ {
+ macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
+ p += 4;
+ macro_build (p, &icnt, &expr1,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
+ /* FIXME: If add_number is 0, and there was no base
+ register, the external symbol case ended with a load,
+ so if the symbol turns out to not be external, and
+ the next instruction uses tempreg, an unnecessary nop
+ will be inserted. */
+ }
+ else
+ {
+ if (breg == treg)
+ {
+ /* We must add in the base register now, as in the
+ external symbol case. */
+ assert (tempreg == AT);
+ macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
+ p += 4;
+ macro_build (p, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", treg, AT, breg);
+ p += 4;
+ tempreg = treg;
+ /* We set breg to 0 because we have arranged to add
+ it in in both cases. */
+ breg = 0;
+ }
+
+ macro_build_lui (p, &icnt, &expr1, AT);
+ p += 4;
+ macro_build (p, &icnt, &expr1,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", AT, AT, (int) BFD_RELOC_LO16);
+ p += 4;
+ macro_build (p, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", tempreg, tempreg, AT);
+ p += 4;
+ }
+ }
+ else if (mips_pic == EMBEDDED_PIC)
+ {
+ /* We use
+ addiu $tempreg,$gp,<sym> (BFD_RELOC_MIPS_GPREL)
+ */
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", tempreg, GP, (int) BFD_RELOC_MIPS_GPREL);
+ }
+ else
+ abort ();
+
+ if (breg != 0)
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", treg, tempreg, breg);
+
+ if (! used_at)
+ return;
+
+ break;
+
+ case M_J_A:
+ /* The j instruction may not be used in PIC code, since it
+ requires an absolute address. We convert it to a b
+ instruction. */
+ if (mips_pic == NO_PIC)
+ macro_build ((char *) NULL, &icnt, &offset_expr, "j", "a");
+ else
+ macro_build ((char *) NULL, &icnt, &offset_expr, "b", "p");
+ return;
+
+ /* The jal instructions must be handled as macros because when
+ generating PIC code they expand to multi-instruction
+ sequences. Normally they are simple instructions. */
+ case M_JAL_1:
+ dreg = RA;
+ /* Fall through. */
+ case M_JAL_2:
+ if (mips_pic == NO_PIC
+ || mips_pic == EMBEDDED_PIC)
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "jalr",
+ "d,s", dreg, sreg);
+ else if (mips_pic == SVR4_PIC)
+ {
+ if (sreg != PIC_CALL_REG)
+ as_warn (_("MIPS PIC call to register other than $25"));
+
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "jalr",
+ "d,s", dreg, sreg);
+ if (mips_cprestore_offset < 0)
+ as_warn (_("No .cprestore pseudo-op used in PIC code"));
+ else
+ {
+ expr1.X_add_number = mips_cprestore_offset;
+ macro_build ((char *) NULL, &icnt, &expr1,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "lw" : "ld"),
+ "t,o(b)", GP, (int) BFD_RELOC_LO16, mips_frame_reg);
+ }
+ }
+ else
+ abort ();
+
+ return;
+
+ case M_JAL_A:
+ if (mips_pic == NO_PIC)
+ macro_build ((char *) NULL, &icnt, &offset_expr, "jal", "a");
+ else if (mips_pic == SVR4_PIC)
+ {
+ /* If this is a reference to an external symbol, and we are
+ using a small GOT, we want
+ lw $25,<sym>($gp) (BFD_RELOC_MIPS_CALL16)
+ nop
+ jalr $25
+ nop
+ lw $gp,cprestore($sp)
+ The cprestore value is set using the .cprestore
+ pseudo-op. If we are using a big GOT, we want
+ lui $25,<sym> (BFD_RELOC_MIPS_CALL_HI16)
+ addu $25,$25,$gp
+ lw $25,<sym>($25) (BFD_RELOC_MIPS_CALL_LO16)
+ nop
+ jalr $25
+ nop
+ lw $gp,cprestore($sp)
+ If the symbol is not external, we want
+ lw $25,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
+ nop
+ addiu $25,$25,<sym> (BFD_RELOC_LO16)
+ jalr $25
+ nop
+ lw $gp,cprestore($sp) */
+ frag_grow (40);
+ if (! mips_big_got)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "lw" : "ld"),
+ "t,o(b)", PIC_CALL_REG,
+ (int) BFD_RELOC_MIPS_CALL16, GP);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ "nop", "");
+ p = frag_var (rs_machine_dependent, 4, 0,
+ RELAX_ENCODE (0, 4, -8, 0, 0, 0),
+ offset_expr.X_add_symbol, (offsetT) 0,
+ (char *) NULL);
+ }
+ else
+ {
+ int gpdel;
+
+ if (reg_needs_delay (GP))
+ gpdel = 4;
+ else
+ gpdel = 0;
+ macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
+ PIC_CALL_REG, (int) BFD_RELOC_MIPS_CALL_HI16);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", PIC_CALL_REG, PIC_CALL_REG, GP);
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "lw" : "ld"),
+ "t,o(b)", PIC_CALL_REG,
+ (int) BFD_RELOC_MIPS_CALL_LO16, PIC_CALL_REG);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ "nop", "");
+ p = frag_var (rs_machine_dependent, 12 + gpdel, 0,
+ RELAX_ENCODE (16, 12 + gpdel, gpdel, 8 + gpdel,
+ 0, 0),
+ offset_expr.X_add_symbol, (offsetT) 0,
+ (char *) NULL);
+ if (gpdel > 0)
+ {
+ macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
+ p += 4;
+ }
+ macro_build (p, &icnt, &offset_expr,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "lw" : "ld"),
+ "t,o(b)", PIC_CALL_REG,
+ (int) BFD_RELOC_MIPS_GOT16, GP);
+ p += 4;
+ macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
+ p += 4;
+ }
+ macro_build (p, &icnt, &offset_expr,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", PIC_CALL_REG, PIC_CALL_REG,
+ (int) BFD_RELOC_LO16);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ "jalr", "s", PIC_CALL_REG);
+ if (mips_cprestore_offset < 0)
+ as_warn (_("No .cprestore pseudo-op used in PIC code"));
+ else
+ {
+ if (mips_opts.noreorder)
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ "nop", "");
+ expr1.X_add_number = mips_cprestore_offset;
+ macro_build ((char *) NULL, &icnt, &expr1,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "lw" : "ld"),
+ "t,o(b)", GP, (int) BFD_RELOC_LO16,
+ mips_frame_reg);
+ }
+ }
+ else if (mips_pic == EMBEDDED_PIC)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr, "bal", "p");
+ /* The linker may expand the call to a longer sequence which
+ uses $at, so we must break rather than return. */
+ break;
+ }
+ else
+ abort ();
+
+ return;
+
+ case M_LB_AB:
+ s = "lb";
+ goto ld;
+ case M_LBU_AB:
+ s = "lbu";
+ goto ld;
+ case M_LH_AB:
+ s = "lh";
+ goto ld;
+ case M_LHU_AB:
+ s = "lhu";
+ goto ld;
+ case M_LW_AB:
+ s = "lw";
+ goto ld;
+ case M_LWC0_AB:
+ s = "lwc0";
+ /* Itbl support may require additional care here. */
+ coproc = 1;
+ goto ld;
+ case M_LWC1_AB:
+ s = "lwc1";
+ /* Itbl support may require additional care here. */
+ coproc = 1;
+ goto ld;
+ case M_LWC2_AB:
+ s = "lwc2";
+ /* Itbl support may require additional care here. */
+ coproc = 1;
+ goto ld;
+ case M_LWC3_AB:
+ s = "lwc3";
+ /* Itbl support may require additional care here. */
+ coproc = 1;
+ goto ld;
+ case M_LWL_AB:
+ s = "lwl";
+ lr = 1;
+ goto ld;
+ case M_LWR_AB:
+ s = "lwr";
+ lr = 1;
+ goto ld;
+ case M_LDC1_AB:
+ if (mips_cpu == 4650)
+ {
+ as_bad (_("opcode not supported on this processor"));
+ return;
+ }
+ s = "ldc1";
+ /* Itbl support may require additional care here. */
+ coproc = 1;
+ goto ld;
+ case M_LDC2_AB:
+ s = "ldc2";
+ /* Itbl support may require additional care here. */
+ coproc = 1;
+ goto ld;
+ case M_LDC3_AB:
+ s = "ldc3";
+ /* Itbl support may require additional care here. */
+ coproc = 1;
+ goto ld;
+ case M_LDL_AB:
+ s = "ldl";
+ lr = 1;
+ goto ld;
+ case M_LDR_AB:
+ s = "ldr";
+ lr = 1;
+ goto ld;
+ case M_LL_AB:
+ s = "ll";
+ goto ld;
+ case M_LLD_AB:
+ s = "lld";
+ goto ld;
+ case M_LWU_AB:
+ s = "lwu";
+ ld:
+ if (breg == treg || coproc || lr)
+ {
+ tempreg = AT;
+ used_at = 1;
+ }
+ else
+ {
+ tempreg = treg;
+ used_at = 0;
+ }
+ goto ld_st;
+ case M_SB_AB:
+ s = "sb";
+ goto st;
+ case M_SH_AB:
+ s = "sh";
+ goto st;
+ case M_SW_AB:
+ s = "sw";
+ goto st;
+ case M_SWC0_AB:
+ s = "swc0";
+ /* Itbl support may require additional care here. */
+ coproc = 1;
+ goto st;
+ case M_SWC1_AB:
+ s = "swc1";
+ /* Itbl support may require additional care here. */
+ coproc = 1;
+ goto st;
+ case M_SWC2_AB:
+ s = "swc2";
+ /* Itbl support may require additional care here. */
+ coproc = 1;
+ goto st;
+ case M_SWC3_AB:
+ s = "swc3";
+ /* Itbl support may require additional care here. */
+ coproc = 1;
+ goto st;
+ case M_SWL_AB:
+ s = "swl";
+ goto st;
+ case M_SWR_AB:
+ s = "swr";
+ goto st;
+ case M_SC_AB:
+ s = "sc";
+ goto st;
+ case M_SCD_AB:
+ s = "scd";
+ goto st;
+ case M_SDC1_AB:
+ if (mips_cpu == 4650)
+ {
+ as_bad (_("opcode not supported on this processor"));
+ return;
+ }
+ s = "sdc1";
+ coproc = 1;
+ /* Itbl support may require additional care here. */
+ goto st;
+ case M_SDC2_AB:
+ s = "sdc2";
+ /* Itbl support may require additional care here. */
+ coproc = 1;
+ goto st;
+ case M_SDC3_AB:
+ s = "sdc3";
+ /* Itbl support may require additional care here. */
+ coproc = 1;
+ goto st;
+ case M_SDL_AB:
+ s = "sdl";
+ goto st;
+ case M_SDR_AB:
+ s = "sdr";
+ st:
+ tempreg = AT;
+ used_at = 1;
+ ld_st:
+ /* Itbl support may require additional care here. */
+ if (mask == M_LWC1_AB
+ || mask == M_SWC1_AB
+ || mask == M_LDC1_AB
+ || mask == M_SDC1_AB
+ || mask == M_L_DAB
+ || mask == M_S_DAB)
+ fmt = "T,o(b)";
+ else if (coproc)
+ fmt = "E,o(b)";
+ else
+ fmt = "t,o(b)";
+
+ if (offset_expr.X_op != O_constant
+ && offset_expr.X_op != O_symbol)
+ {
+ as_bad (_("expression too complex"));
+ offset_expr.X_op = O_constant;
+ }
+
+ /* A constant expression in PIC code can be handled just as it
+ is in non PIC code. */
+ if (mips_pic == NO_PIC
+ || offset_expr.X_op == O_constant)
+ {
+ /* If this is a reference to a GP relative symbol, and there
+ is no base register, we want
+ <op> $treg,<sym>($gp) (BFD_RELOC_MIPS_GPREL)
+ Otherwise, if there is no base register, we want
+ lui $tempreg,<sym> (BFD_RELOC_HI16_S)
+ <op> $treg,<sym>($tempreg) (BFD_RELOC_LO16)
+ If we have a constant, we need two instructions anyhow,
+ so we always use the latter form.
+
+ If we have a base register, and this is a reference to a
+ GP relative symbol, we want
+ addu $tempreg,$breg,$gp
+ <op> $treg,<sym>($tempreg) (BFD_RELOC_MIPS_GPREL)
+ Otherwise we want
+ lui $tempreg,<sym> (BFD_RELOC_HI16_S)
+ addu $tempreg,$tempreg,$breg
+ <op> $treg,<sym>($tempreg) (BFD_RELOC_LO16)
+ With a constant we always use the latter case. */
+ if (breg == 0)
+ {
+ if ((valueT) offset_expr.X_add_number >= MAX_GPREL_OFFSET
+ || nopic_need_relax (offset_expr.X_add_symbol, 1))
+ p = NULL;
+ else
+ {
+ frag_grow (20);
+ macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
+ treg, (int) BFD_RELOC_MIPS_GPREL, GP);
+ p = frag_var (rs_machine_dependent, 8, 0,
+ RELAX_ENCODE (4, 8, 0, 4, 0,
+ (mips_opts.warn_about_macros
+ || (used_at
+ && mips_opts.noat))),
+ offset_expr.X_add_symbol, (offsetT) 0,
+ (char *) NULL);
+ used_at = 0;
+ }
+ macro_build_lui (p, &icnt, &offset_expr, tempreg);
+ if (p != NULL)
+ p += 4;
+ macro_build (p, &icnt, &offset_expr, s, fmt, treg,
+ (int) BFD_RELOC_LO16, tempreg);
+ }
+ else
+ {
+ if ((valueT) offset_expr.X_add_number >= MAX_GPREL_OFFSET
+ || nopic_need_relax (offset_expr.X_add_symbol, 1))
+ p = NULL;
+ else
+ {
+ frag_grow (28);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", tempreg, breg, GP);
+ macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
+ treg, (int) BFD_RELOC_MIPS_GPREL, tempreg);
+ p = frag_var (rs_machine_dependent, 12, 0,
+ RELAX_ENCODE (8, 12, 0, 8, 0, 0),
+ offset_expr.X_add_symbol, (offsetT) 0,
+ (char *) NULL);
+ }
+ macro_build_lui (p, &icnt, &offset_expr, tempreg);
+ if (p != NULL)
+ p += 4;
+ macro_build (p, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", tempreg, tempreg, breg);
+ if (p != NULL)
+ p += 4;
+ macro_build (p, &icnt, &offset_expr, s, fmt, treg,
+ (int) BFD_RELOC_LO16, tempreg);
+ }
+ }
+ else if (mips_pic == SVR4_PIC && ! mips_big_got)
+ {
+ /* If this is a reference to an external symbol, we want
+ lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
+ nop
+ <op> $treg,0($tempreg)
+ Otherwise we want
+ lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
+ nop
+ addiu $tempreg,$tempreg,<sym> (BFD_RELOC_LO16)
+ <op> $treg,0($tempreg)
+ If there is a base register, we add it to $tempreg before
+ the <op>. If there is a constant, we stick it in the
+ <op> instruction. We don't handle constants larger than
+ 16 bits, because we have no way to load the upper 16 bits
+ (actually, we could handle them for the subset of cases
+ in which we are not using $at). */
+ assert (offset_expr.X_op == O_symbol);
+ expr1.X_add_number = offset_expr.X_add_number;
+ offset_expr.X_add_number = 0;
+ if (expr1.X_add_number < -0x8000
+ || expr1.X_add_number >= 0x8000)
+ as_bad (_("PIC code offset overflow (max 16 signed bits)"));
+ frag_grow (20);
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "lw" : "ld"),
+ "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT16, GP);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");
+ p = frag_var (rs_machine_dependent, 4, 0,
+ RELAX_ENCODE (0, 4, -8, 0, 0, 0),
+ offset_expr.X_add_symbol, (offsetT) 0,
+ (char *) NULL);
+ macro_build (p, &icnt, &offset_expr,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
+ if (breg != 0)
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", tempreg, tempreg, breg);
+ macro_build ((char *) NULL, &icnt, &expr1, s, fmt, treg,
+ (int) BFD_RELOC_LO16, tempreg);
+ }
+ else if (mips_pic == SVR4_PIC)
+ {
+ int gpdel;
+
+ /* If this is a reference to an external symbol, we want
+ lui $tempreg,<sym> (BFD_RELOC_MIPS_GOT_HI16)
+ addu $tempreg,$tempreg,$gp
+ lw $tempreg,<sym>($tempreg) (BFD_RELOC_MIPS_GOT_LO16)
+ <op> $treg,0($tempreg)
+ Otherwise we want
+ lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
+ nop
+ addiu $tempreg,$tempreg,<sym> (BFD_RELOC_LO16)
+ <op> $treg,0($tempreg)
+ If there is a base register, we add it to $tempreg before
+ the <op>. If there is a constant, we stick it in the
+ <op> instruction. We don't handle constants larger than
+ 16 bits, because we have no way to load the upper 16 bits
+ (actually, we could handle them for the subset of cases
+ in which we are not using $at). */
+ assert (offset_expr.X_op == O_symbol);
+ expr1.X_add_number = offset_expr.X_add_number;
+ offset_expr.X_add_number = 0;
+ if (expr1.X_add_number < -0x8000
+ || expr1.X_add_number >= 0x8000)
+ as_bad (_("PIC code offset overflow (max 16 signed bits)"));
+ if (reg_needs_delay (GP))
+ gpdel = 4;
+ else
+ gpdel = 0;
+ frag_grow (36);
+ macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
+ tempreg, (int) BFD_RELOC_MIPS_GOT_HI16);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", tempreg, tempreg, GP);
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "lw" : "ld"),
+ "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT_LO16,
+ tempreg);
+ p = frag_var (rs_machine_dependent, 12 + gpdel, 0,
+ RELAX_ENCODE (12, 12 + gpdel, gpdel, 8 + gpdel, 0, 0),
+ offset_expr.X_add_symbol, (offsetT) 0, (char *) NULL);
+ if (gpdel > 0)
+ {
+ macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
+ p += 4;
+ }
+ macro_build (p, &icnt, &offset_expr,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "lw" : "ld"),
+ "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT16, GP);
+ p += 4;
+ macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
+ p += 4;
+ macro_build (p, &icnt, &offset_expr,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);
+ if (breg != 0)
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", tempreg, tempreg, breg);
+ macro_build ((char *) NULL, &icnt, &expr1, s, fmt, treg,
+ (int) BFD_RELOC_LO16, tempreg);
+ }
+ else if (mips_pic == EMBEDDED_PIC)
+ {
+ /* If there is no base register, we want
+ <op> $treg,<sym>($gp) (BFD_RELOC_MIPS_GPREL)
+ If there is a base register, we want
+ addu $tempreg,$breg,$gp
+ <op> $treg,<sym>($tempreg) (BFD_RELOC_MIPS_GPREL)
+ */
+ assert (offset_expr.X_op == O_symbol);
+ if (breg == 0)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
+ treg, (int) BFD_RELOC_MIPS_GPREL, GP);
+ used_at = 0;
+ }
+ else
+ {
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", tempreg, breg, GP);
+ macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
+ treg, (int) BFD_RELOC_MIPS_GPREL, tempreg);
+ }
+ }
+ else
+ abort ();
+
+ if (! used_at)
+ return;
+
+ break;
+
+ case M_LI:
+ case M_LI_S:
+ load_register (&icnt, treg, &imm_expr, 0);
+ return;
+
+ case M_DLI:
+ load_register (&icnt, treg, &imm_expr, 1);
+ return;
+
+ case M_LI_SS:
+ if (imm_expr.X_op == O_constant)
+ {
+ load_register (&icnt, AT, &imm_expr, 0);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ "mtc1", "t,G", AT, treg);
+ break;
+ }
+ else
+ {
+ assert (offset_expr.X_op == O_symbol
+ && strcmp (segment_name (S_GET_SEGMENT
+ (offset_expr.X_add_symbol)),
+ ".lit4") == 0
+ && offset_expr.X_add_number == 0);
+ macro_build ((char *) NULL, &icnt, &offset_expr, "lwc1", "T,o(b)",
+ treg, (int) BFD_RELOC_MIPS_LITERAL, GP);
+ return;
+ }
+
+ case M_LI_D:
+ /* If we have a constant in IMM_EXPR, then in mips3 mode it is
+ the entire value, and in mips1 mode it is the high order 32
+ bits of the value and the low order 32 bits are either zero
+ or in offset_expr. */
+ if (imm_expr.X_op == O_constant || imm_expr.X_op == O_big)
+ {
+ if (mips_opts.isa >= 3)
+ load_register (&icnt, treg, &imm_expr, 1);
+ else
+ {
+ int hreg, lreg;
+
+ if (target_big_endian)
+ {
+ hreg = treg;
+ lreg = treg + 1;
+ }
+ else
+ {
+ hreg = treg + 1;
+ lreg = treg;
+ }
+
+ if (hreg <= 31)
+ load_register (&icnt, hreg, &imm_expr, 0);
+ if (lreg <= 31)
+ {
+ if (offset_expr.X_op == O_absent)
+ macro_build ((char *) NULL, &icnt, NULL, "move", "d,s",
+ lreg, 0);
+ else
+ {
+ assert (offset_expr.X_op == O_constant);
+ load_register (&icnt, lreg, &offset_expr, 0);
+ }
+ }
+ }
+ return;
+ }
+
+ /* We know that sym is in the .rdata section. First we get the
+ upper 16 bits of the address. */
+ if (mips_pic == NO_PIC)
+ {
+ /* FIXME: This won't work for a 64 bit address. */
+ macro_build_lui ((char *) NULL, &icnt, &offset_expr, AT);
+ }
+ else if (mips_pic == SVR4_PIC)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "lw" : "ld"),
+ "t,o(b)", AT, (int) BFD_RELOC_MIPS_GOT16, GP);
+ }
+ else if (mips_pic == EMBEDDED_PIC)
+ {
+ /* For embedded PIC we pick up the entire address off $gp in
+ a single instruction. */
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", AT, GP, (int) BFD_RELOC_MIPS_GPREL);
+ offset_expr.X_op = O_constant;
+ offset_expr.X_add_number = 0;
+ }
+ else
+ abort ();
+
+ /* Now we load the register(s). */
+ if (mips_opts.isa >= 3)
+ macro_build ((char *) NULL, &icnt, &offset_expr, "ld", "t,o(b)",
+ treg, (int) BFD_RELOC_LO16, AT);
+ else
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr, "lw", "t,o(b)",
+ treg, (int) BFD_RELOC_LO16, AT);
+ if (treg != 31)
+ {
+ /* FIXME: How in the world do we deal with the possible
+ overflow here? */
+ offset_expr.X_add_number += 4;
+ macro_build ((char *) NULL, &icnt, &offset_expr, "lw", "t,o(b)",
+ treg + 1, (int) BFD_RELOC_LO16, AT);
+ }
+ }
+
+ /* To avoid confusion in tc_gen_reloc, we must ensure that this
+ does not become a variant frag. */
+ frag_wane (frag_now);
+ frag_new (0);
+
+ break;
+
+ case M_LI_DD:
+ /* If we have a constant in IMM_EXPR, then in mips3 mode it is
+ the entire value, and in mips1 mode it is the high order 32
+ bits of the value and the low order 32 bits are either zero
+ or in offset_expr. */
+ if (imm_expr.X_op == O_constant || imm_expr.X_op == O_big)
+ {
+ load_register (&icnt, AT, &imm_expr, mips_opts.isa >= 3);
+ if (mips_opts.isa >= 3)
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ "dmtc1", "t,S", AT, treg);
+ else
+ {
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ "mtc1", "t,G", AT, treg + 1);
+ if (offset_expr.X_op == O_absent)
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ "mtc1", "t,G", 0, treg);
+ else
+ {
+ assert (offset_expr.X_op == O_constant);
+ load_register (&icnt, AT, &offset_expr, 0);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ "mtc1", "t,G", AT, treg);
+ }
+ }
+ break;
+ }
+
+ assert (offset_expr.X_op == O_symbol
+ && offset_expr.X_add_number == 0);
+ s = segment_name (S_GET_SEGMENT (offset_expr.X_add_symbol));
+ if (strcmp (s, ".lit8") == 0)
+ {
+ if (mips_opts.isa >= 2)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr, "ldc1",
+ "T,o(b)", treg, (int) BFD_RELOC_MIPS_LITERAL, GP);
+ return;
+ }
+ breg = GP;
+ r = BFD_RELOC_MIPS_LITERAL;
+ goto dob;
+ }
+ else
+ {
+ assert (strcmp (s, RDATA_SECTION_NAME) == 0);
+ if (mips_pic == SVR4_PIC)
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "lw" : "ld"),
+ "t,o(b)", AT, (int) BFD_RELOC_MIPS_GOT16, GP);
+ else
+ {
+ /* FIXME: This won't work for a 64 bit address. */
+ macro_build_lui ((char *) NULL, &icnt, &offset_expr, AT);
+ }
+
+ if (mips_opts.isa >= 2)
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr, "ldc1",
+ "T,o(b)", treg, (int) BFD_RELOC_LO16, AT);
+
+ /* To avoid confusion in tc_gen_reloc, we must ensure
+ that this does not become a variant frag. */
+ frag_wane (frag_now);
+ frag_new (0);
+
+ break;
+ }
+ breg = AT;
+ r = BFD_RELOC_LO16;
+ goto dob;
+ }
+
+ case M_L_DOB:
+ if (mips_cpu == 4650)
+ {
+ as_bad (_("opcode not supported on this processor"));
+ return;
+ }
+ /* Even on a big endian machine $fn comes before $fn+1. We have
+ to adjust when loading from memory. */
+ r = BFD_RELOC_LO16;
+ dob:
+ assert (mips_opts.isa < 2);
+ macro_build ((char *) NULL, &icnt, &offset_expr, "lwc1", "T,o(b)",
+ target_big_endian ? treg + 1 : treg,
+ (int) r, breg);
+ /* FIXME: A possible overflow which I don't know how to deal
+ with. */
+ offset_expr.X_add_number += 4;
+ macro_build ((char *) NULL, &icnt, &offset_expr, "lwc1", "T,o(b)",
+ target_big_endian ? treg : treg + 1,
+ (int) r, breg);
+
+ /* To avoid confusion in tc_gen_reloc, we must ensure that this
+ does not become a variant frag. */
+ frag_wane (frag_now);
+ frag_new (0);
+
+ if (breg != AT)
+ return;
+ break;
+
+ case M_L_DAB:
+ /*
+ * The MIPS assembler seems to check for X_add_number not
+ * being double aligned and generating:
+ * lui at,%hi(foo+1)
+ * addu at,at,v1
+ * addiu at,at,%lo(foo+1)
+ * lwc1 f2,0(at)
+ * lwc1 f3,4(at)
+ * But, the resulting address is the same after relocation so why
+ * generate the extra instruction?
+ */
+ if (mips_cpu == 4650)
+ {
+ as_bad (_("opcode not supported on this processor"));
+ return;
+ }
+ /* Itbl support may require additional care here. */
+ coproc = 1;
+ if (mips_opts.isa >= 2)
+ {
+ s = "ldc1";
+ goto ld;
+ }
+
+ s = "lwc1";
+ fmt = "T,o(b)";
+ goto ldd_std;
+
+ case M_S_DAB:
+ if (mips_cpu == 4650)
+ {
+ as_bad (_("opcode not supported on this processor"));
+ return;
+ }
+
+ if (mips_opts.isa >= 2)
+ {
+ s = "sdc1";
+ goto st;
+ }
+
+ s = "swc1";
+ fmt = "T,o(b)";
+ /* Itbl support may require additional care here. */
+ coproc = 1;
+ goto ldd_std;
+
+ case M_LD_AB:
+ if (mips_opts.isa >= 3)
+ {
+ s = "ld";
+ goto ld;
+ }
+
+ s = "lw";
+ fmt = "t,o(b)";
+ goto ldd_std;
+
+ case M_SD_AB:
+ if (mips_opts.isa >= 3)
+ {
+ s = "sd";
+ goto st;
+ }
+
+ s = "sw";
+ fmt = "t,o(b)";
+
+ ldd_std:
+ if (offset_expr.X_op != O_symbol
+ && offset_expr.X_op != O_constant)
+ {
+ as_bad (_("expression too complex"));
+ offset_expr.X_op = O_constant;
+ }
+
+ /* Even on a big endian machine $fn comes before $fn+1. We have
+ to adjust when loading from memory. We set coproc if we must
+ load $fn+1 first. */
+ /* Itbl support may require additional care here. */
+ if (! target_big_endian)
+ coproc = 0;
+
+ if (mips_pic == NO_PIC
+ || offset_expr.X_op == O_constant)
+ {
+ /* If this is a reference to a GP relative symbol, we want
+ <op> $treg,<sym>($gp) (BFD_RELOC_MIPS_GPREL)
+ <op> $treg+1,<sym>+4($gp) (BFD_RELOC_MIPS_GPREL)
+ If we have a base register, we use this
+ addu $at,$breg,$gp
+ <op> $treg,<sym>($at) (BFD_RELOC_MIPS_GPREL)
+ <op> $treg+1,<sym>+4($at) (BFD_RELOC_MIPS_GPREL)
+ If this is not a GP relative symbol, we want
+ lui $at,<sym> (BFD_RELOC_HI16_S)
+ <op> $treg,<sym>($at) (BFD_RELOC_LO16)
+ <op> $treg+1,<sym>+4($at) (BFD_RELOC_LO16)
+ If there is a base register, we add it to $at after the
+ lui instruction. If there is a constant, we always use
+ the last case. */
+ if ((valueT) offset_expr.X_add_number >= MAX_GPREL_OFFSET
+ || nopic_need_relax (offset_expr.X_add_symbol, 1))
+ {
+ p = NULL;
+ used_at = 1;
+ }
+ else
+ {
+ int off;
+
+ if (breg == 0)
+ {
+ frag_grow (28);
+ tempreg = GP;
+ off = 0;
+ used_at = 0;
+ }
+ else
+ {
+ frag_grow (36);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", AT, breg, GP);
+ tempreg = AT;
+ off = 4;
+ used_at = 1;
+ }
+
+ /* Itbl support may require additional care here. */
+ macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
+ coproc ? treg + 1 : treg,
+ (int) BFD_RELOC_MIPS_GPREL, tempreg);
+ offset_expr.X_add_number += 4;
+
+ /* Set mips_optimize to 2 to avoid inserting an
+ undesired nop. */
+ hold_mips_optimize = mips_optimize;
+ mips_optimize = 2;
+ /* Itbl support may require additional care here. */
+ macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
+ coproc ? treg : treg + 1,
+ (int) BFD_RELOC_MIPS_GPREL, tempreg);
+ mips_optimize = hold_mips_optimize;
+
+ p = frag_var (rs_machine_dependent, 12 + off, 0,
+ RELAX_ENCODE (8 + off, 12 + off, 0, 4 + off, 1,
+ used_at && mips_opts.noat),
+ offset_expr.X_add_symbol, (offsetT) 0,
+ (char *) NULL);
+
+ /* We just generated two relocs. When tc_gen_reloc
+ handles this case, it will skip the first reloc and
+ handle the second. The second reloc already has an
+ extra addend of 4, which we added above. We must
+ subtract it out, and then subtract another 4 to make
+ the first reloc come out right. The second reloc
+ will come out right because we are going to add 4 to
+ offset_expr when we build its instruction below.
+
+ If we have a symbol, then we don't want to include
+ the offset, because it will wind up being included
+ when we generate the reloc. */
+
+ if (offset_expr.X_op == O_constant)
+ offset_expr.X_add_number -= 8;
+ else
+ {
+ offset_expr.X_add_number = -4;
+ offset_expr.X_op = O_constant;
+ }
+ }
+ macro_build_lui (p, &icnt, &offset_expr, AT);
+ if (p != NULL)
+ p += 4;
+ if (breg != 0)
+ {
+ macro_build (p, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", AT, breg, AT);
+ if (p != NULL)
+ p += 4;
+ }
+ /* Itbl support may require additional care here. */
+ macro_build (p, &icnt, &offset_expr, s, fmt,
+ coproc ? treg + 1 : treg,
+ (int) BFD_RELOC_LO16, AT);
+ if (p != NULL)
+ p += 4;
+ /* FIXME: How do we handle overflow here? */
+ offset_expr.X_add_number += 4;
+ /* Itbl support may require additional care here. */
+ macro_build (p, &icnt, &offset_expr, s, fmt,
+ coproc ? treg : treg + 1,
+ (int) BFD_RELOC_LO16, AT);
+ }
+ else if (mips_pic == SVR4_PIC && ! mips_big_got)
+ {
+ int off;
+
+ /* If this is a reference to an external symbol, we want
+ lw $at,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
+ nop
+ <op> $treg,0($at)
+ <op> $treg+1,4($at)
+ Otherwise we want
+ lw $at,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
+ nop
+ <op> $treg,<sym>($at) (BFD_RELOC_LO16)
+ <op> $treg+1,<sym>+4($at) (BFD_RELOC_LO16)
+ If there is a base register we add it to $at before the
+ lwc1 instructions. If there is a constant we include it
+ in the lwc1 instructions. */
+ used_at = 1;
+ expr1.X_add_number = offset_expr.X_add_number;
+ offset_expr.X_add_number = 0;
+ if (expr1.X_add_number < -0x8000
+ || expr1.X_add_number >= 0x8000 - 4)
+ as_bad (_("PIC code offset overflow (max 16 signed bits)"));
+ if (breg == 0)
+ off = 0;
+ else
+ off = 4;
+ frag_grow (24 + off);
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "lw" : "ld"),
+ "t,o(b)", AT, (int) BFD_RELOC_MIPS_GOT16, GP);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");
+ if (breg != 0)
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", AT, breg, AT);
+ /* Itbl support may require additional care here. */
+ macro_build ((char *) NULL, &icnt, &expr1, s, fmt,
+ coproc ? treg + 1 : treg,
+ (int) BFD_RELOC_LO16, AT);
+ expr1.X_add_number += 4;
+
+ /* Set mips_optimize to 2 to avoid inserting an undesired
+ nop. */
+ hold_mips_optimize = mips_optimize;
+ mips_optimize = 2;
+ /* Itbl support may require additional care here. */
+ macro_build ((char *) NULL, &icnt, &expr1, s, fmt,
+ coproc ? treg : treg + 1,
+ (int) BFD_RELOC_LO16, AT);
+ mips_optimize = hold_mips_optimize;
+
+ (void) frag_var (rs_machine_dependent, 0, 0,
+ RELAX_ENCODE (0, 0, -16 - off, -8, 1, 0),
+ offset_expr.X_add_symbol, (offsetT) 0,
+ (char *) NULL);
+ }
+ else if (mips_pic == SVR4_PIC)
+ {
+ int gpdel, off;
+
+ /* If this is a reference to an external symbol, we want
+ lui $at,<sym> (BFD_RELOC_MIPS_GOT_HI16)
+ addu $at,$at,$gp
+ lw $at,<sym>($at) (BFD_RELOC_MIPS_GOT_LO16)
+ nop
+ <op> $treg,0($at)
+ <op> $treg+1,4($at)
+ Otherwise we want
+ lw $at,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
+ nop
+ <op> $treg,<sym>($at) (BFD_RELOC_LO16)
+ <op> $treg+1,<sym>+4($at) (BFD_RELOC_LO16)
+ If there is a base register we add it to $at before the
+ lwc1 instructions. If there is a constant we include it
+ in the lwc1 instructions. */
+ used_at = 1;
+ expr1.X_add_number = offset_expr.X_add_number;
+ offset_expr.X_add_number = 0;
+ if (expr1.X_add_number < -0x8000
+ || expr1.X_add_number >= 0x8000 - 4)
+ as_bad (_("PIC code offset overflow (max 16 signed bits)"));
+ if (reg_needs_delay (GP))
+ gpdel = 4;
+ else
+ gpdel = 0;
+ if (breg == 0)
+ off = 0;
+ else
+ off = 4;
+ frag_grow (56);
+ macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
+ AT, (int) BFD_RELOC_MIPS_GOT_HI16);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", AT, AT, GP);
+ macro_build ((char *) NULL, &icnt, &offset_expr,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "lw" : "ld"),
+ "t,o(b)", AT, (int) BFD_RELOC_MIPS_GOT_LO16, AT);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");
+ if (breg != 0)
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", AT, breg, AT);
+ /* Itbl support may require additional care here. */
+ macro_build ((char *) NULL, &icnt, &expr1, s, fmt,
+ coproc ? treg + 1 : treg,
+ (int) BFD_RELOC_LO16, AT);
+ expr1.X_add_number += 4;
+
+ /* Set mips_optimize to 2 to avoid inserting an undesired
+ nop. */
+ hold_mips_optimize = mips_optimize;
+ mips_optimize = 2;
+ /* Itbl support may require additional care here. */
+ macro_build ((char *) NULL, &icnt, &expr1, s, fmt,
+ coproc ? treg : treg + 1,
+ (int) BFD_RELOC_LO16, AT);
+ mips_optimize = hold_mips_optimize;
+ expr1.X_add_number -= 4;
+
+ p = frag_var (rs_machine_dependent, 16 + gpdel + off, 0,
+ RELAX_ENCODE (24 + off, 16 + gpdel + off, gpdel,
+ 8 + gpdel + off, 1, 0),
+ offset_expr.X_add_symbol, (offsetT) 0,
+ (char *) NULL);
+ if (gpdel > 0)
+ {
+ macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
+ p += 4;
+ }
+ macro_build (p, &icnt, &offset_expr,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "lw" : "ld"),
+ "t,o(b)", AT, (int) BFD_RELOC_MIPS_GOT16, GP);
+ p += 4;
+ macro_build (p, &icnt, (expressionS *) NULL, "nop", "");
+ p += 4;
+ if (breg != 0)
+ {
+ macro_build (p, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", AT, breg, AT);
+ p += 4;
+ }
+ /* Itbl support may require additional care here. */
+ macro_build (p, &icnt, &expr1, s, fmt,
+ coproc ? treg + 1 : treg,
+ (int) BFD_RELOC_LO16, AT);
+ p += 4;
+ expr1.X_add_number += 4;
+
+ /* Set mips_optimize to 2 to avoid inserting an undesired
+ nop. */
+ hold_mips_optimize = mips_optimize;
+ mips_optimize = 2;
+ /* Itbl support may require additional care here. */
+ macro_build (p, &icnt, &expr1, s, fmt,
+ coproc ? treg : treg + 1,
+ (int) BFD_RELOC_LO16, AT);
+ mips_optimize = hold_mips_optimize;
+ }
+ else if (mips_pic == EMBEDDED_PIC)
+ {
+ /* If there is no base register, we use
+ <op> $treg,<sym>($gp) (BFD_RELOC_MIPS_GPREL)
+ <op> $treg+1,<sym>+4($gp) (BFD_RELOC_MIPS_GPREL)
+ If we have a base register, we use
+ addu $at,$breg,$gp
+ <op> $treg,<sym>($at) (BFD_RELOC_MIPS_GPREL)
+ <op> $treg+1,<sym>+4($at) (BFD_RELOC_MIPS_GPREL)
+ */
+ if (breg == 0)
+ {
+ tempreg = GP;
+ used_at = 0;
+ }
+ else
+ {
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", AT, breg, GP);
+ tempreg = AT;
+ used_at = 1;
+ }
+
+ /* Itbl support may require additional care here. */
+ macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
+ coproc ? treg + 1 : treg,
+ (int) BFD_RELOC_MIPS_GPREL, tempreg);
+ offset_expr.X_add_number += 4;
+ /* Itbl support may require additional care here. */
+ macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,
+ coproc ? treg : treg + 1,
+ (int) BFD_RELOC_MIPS_GPREL, tempreg);
+ }
+ else
+ abort ();
+
+ if (! used_at)
+ return;
+
+ break;
+
+ case M_LD_OB:
+ s = "lw";
+ goto sd_ob;
+ case M_SD_OB:
+ s = "sw";
+ sd_ob:
+ assert (bfd_arch_bits_per_address (stdoutput) == 32 || mips_opts.isa < 3);
+ macro_build ((char *) NULL, &icnt, &offset_expr, s, "t,o(b)", treg,
+ (int) BFD_RELOC_LO16, breg);
+ offset_expr.X_add_number += 4;
+ macro_build ((char *) NULL, &icnt, &offset_expr, s, "t,o(b)", treg + 1,
+ (int) BFD_RELOC_LO16, breg);
+ return;
+
+ /* New code added to support COPZ instructions.
+ This code builds table entries out of the macros in mip_opcodes.
+ R4000 uses interlocks to handle coproc delays.
+ Other chips (like the R3000) require nops to be inserted for delays.
+
+ FIXME: Currently, we require that the user handle delays.
+ In order to fill delay slots for non-interlocked chips,
+ we must have a way to specify delays based on the coprocessor.
+ Eg. 4 cycles if load coproc reg from memory, 1 if in cache, etc.
+ What are the side-effects of the cop instruction?
+ What cache support might we have and what are its effects?
+ Both coprocessor & memory require delays. how long???
+ What registers are read/set/modified?
+
+ If an itbl is provided to interpret cop instructions,
+ this knowledge can be encoded in the itbl spec. */
+
+ case M_COP0:
+ s = "c0";
+ goto copz;
+ case M_COP1:
+ s = "c1";
+ goto copz;
+ case M_COP2:
+ s = "c2";
+ goto copz;
+ case M_COP3:
+ s = "c3";
+ copz:
+ /* For now we just do C (same as Cz). The parameter will be
+ stored in insn_opcode by mips_ip. */
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "C",
+ ip->insn_opcode);
+ return;
+
+#ifdef LOSING_COMPILER
+ default:
+ /* Try and see if this is a new itbl instruction.
+ This code builds table entries out of the macros in mip_opcodes.
+ FIXME: For now we just assemble the expression and pass it's
+ value along as a 32-bit immediate.
+ We may want to have the assembler assemble this value,
+ so that we gain the assembler's knowledge of delay slots,
+ symbols, etc.
+ Would it be more efficient to use mask (id) here? */
+ if (itbl_have_entries
+ && (immed_expr = itbl_assemble (ip->insn_mo->name, "")))
+ {
+ s = ip->insn_mo->name;
+ s2 = "cop3";
+ coproc = ITBL_DECODE_PNUM (immed_expr);;
+ macro_build ((char *) NULL, &icnt, &immed_expr, s, "C");
+ return;
+ }
+ macro2 (ip);
+ return;
+ }
+ if (mips_opts.noat)
+ as_warn (_("Macro used $at after \".set noat\""));
+}
+
+static void
+macro2 (ip)
+ struct mips_cl_insn *ip;
+{
+ register int treg, sreg, dreg, breg;
+ int tempreg;
+ int mask;
+ int icnt = 0;
+ int used_at;
+ expressionS expr1;
+ const char *s;
+ const char *s2;
+ const char *fmt;
+ int likely = 0;
+ int dbl = 0;
+ int coproc = 0;
+ int lr = 0;
+ int imm = 0;
+ int off;
+ offsetT maxnum;
+ bfd_reloc_code_real_type r;
+ char *p;
+
+ treg = (ip->insn_opcode >> 16) & 0x1f;
+ dreg = (ip->insn_opcode >> 11) & 0x1f;
+ sreg = breg = (ip->insn_opcode >> 21) & 0x1f;
+ mask = ip->insn_mo->mask;
+
+ expr1.X_op = O_constant;
+ expr1.X_op_symbol = NULL;
+ expr1.X_add_symbol = NULL;
+ expr1.X_add_number = 1;
+
+ switch (mask)
+ {
+#endif /* LOSING_COMPILER */
+
+ case M_DMUL:
+ dbl = 1;
+ case M_MUL:
+ macro_build ((char *) NULL, &icnt, NULL,
+ dbl ? "dmultu" : "multu",
+ "s,t", sreg, treg);
+ macro_build ((char *) NULL, &icnt, NULL, "mflo", "d", dreg);
+ return;
+
+ case M_DMUL_I:
+ dbl = 1;
+ case M_MUL_I:
+ /* The MIPS assembler some times generates shifts and adds. I'm
+ not trying to be that fancy. GCC should do this for us
+ anyway. */
+ load_register (&icnt, AT, &imm_expr, dbl);
+ macro_build ((char *) NULL, &icnt, NULL,
+ dbl ? "dmult" : "mult",
+ "s,t", sreg, AT);
+ macro_build ((char *) NULL, &icnt, NULL, "mflo", "d", dreg);
+ break;
+
+ case M_DMULO_I:
+ dbl = 1;
+ case M_MULO_I:
+ imm = 1;
+ goto do_mulo;
+
+ case M_DMULO:
+ dbl = 1;
+ case M_MULO:
+ do_mulo:
+ mips_emit_delays (true);
+ ++mips_opts.noreorder;
+ mips_any_noreorder = 1;
+ if (imm)
+ load_register (&icnt, AT, &imm_expr, dbl);
+ macro_build ((char *) NULL, &icnt, NULL,
+ dbl ? "dmult" : "mult",
+ "s,t", sreg, imm ? AT : treg);
+ macro_build ((char *) NULL, &icnt, NULL, "mflo", "d", dreg);
+ macro_build ((char *) NULL, &icnt, NULL,
+ dbl ? "dsra32" : "sra",
+ "d,w,<", dreg, dreg, 31);
+ macro_build ((char *) NULL, &icnt, NULL, "mfhi", "d", AT);
+ if (mips_trap)
+ macro_build ((char *) NULL, &icnt, NULL, "tne", "s,t", dreg, AT);
+ else
+ {
+ expr1.X_add_number = 8;
+ macro_build ((char *) NULL, &icnt, &expr1, "beq", "s,t,p", dreg, AT);
+ macro_build ((char *) NULL, &icnt, NULL, "nop", "", 0);
+ macro_build ((char *) NULL, &icnt, NULL, "break", "c", 6);
+ }
+ --mips_opts.noreorder;
+ macro_build ((char *) NULL, &icnt, NULL, "mflo", "d", dreg);
+ break;
+
+ case M_DMULOU_I:
+ dbl = 1;
+ case M_MULOU_I:
+ imm = 1;
+ goto do_mulou;
+
+ case M_DMULOU:
+ dbl = 1;
+ case M_MULOU:
+ do_mulou:
+ mips_emit_delays (true);
+ ++mips_opts.noreorder;
+ mips_any_noreorder = 1;
+ if (imm)
+ load_register (&icnt, AT, &imm_expr, dbl);
+ macro_build ((char *) NULL, &icnt, NULL,
+ dbl ? "dmultu" : "multu",
+ "s,t", sreg, imm ? AT : treg);
+ macro_build ((char *) NULL, &icnt, NULL, "mfhi", "d", AT);
+ macro_build ((char *) NULL, &icnt, NULL, "mflo", "d", dreg);
+ if (mips_trap)
+ macro_build ((char *) NULL, &icnt, NULL, "tne", "s,t", AT, 0);
+ else
+ {
+ expr1.X_add_number = 8;
+ macro_build ((char *) NULL, &icnt, &expr1, "beq", "s,t,p", AT, 0);
+ macro_build ((char *) NULL, &icnt, NULL, "nop", "", 0);
+ macro_build ((char *) NULL, &icnt, NULL, "break", "c", 6);
+ }
+ --mips_opts.noreorder;
+ break;
+
+ case M_ROL:
+ macro_build ((char *) NULL, &icnt, NULL, "subu", "d,v,t", AT, 0, treg);
+ macro_build ((char *) NULL, &icnt, NULL, "srlv", "d,t,s", AT, sreg, AT);
+ macro_build ((char *) NULL, &icnt, NULL, "sllv", "d,t,s", dreg, sreg,
+ treg);
+ macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", dreg, dreg, AT);
+ break;
+
+ case M_ROL_I:
+ if (imm_expr.X_op != O_constant)
+ as_bad (_("rotate count too large"));
+ macro_build ((char *) NULL, &icnt, NULL, "sll", "d,w,<", AT, sreg,
+ (int) (imm_expr.X_add_number & 0x1f));
+ macro_build ((char *) NULL, &icnt, NULL, "srl", "d,w,<", dreg, sreg,
+ (int) ((0 - imm_expr.X_add_number) & 0x1f));
+ macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", dreg, dreg, AT);
+ break;
+
+ case M_ROR:
+ macro_build ((char *) NULL, &icnt, NULL, "subu", "d,v,t", AT, 0, treg);
+ macro_build ((char *) NULL, &icnt, NULL, "sllv", "d,t,s", AT, sreg, AT);
+ macro_build ((char *) NULL, &icnt, NULL, "srlv", "d,t,s", dreg, sreg,
+ treg);
+ macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", dreg, dreg, AT);
+ break;
+
+ case M_ROR_I:
+ if (imm_expr.X_op != O_constant)
+ as_bad (_("rotate count too large"));
+ macro_build ((char *) NULL, &icnt, NULL, "srl", "d,w,<", AT, sreg,
+ (int) (imm_expr.X_add_number & 0x1f));
+ macro_build ((char *) NULL, &icnt, NULL, "sll", "d,w,<", dreg, sreg,
+ (int) ((0 - imm_expr.X_add_number) & 0x1f));
+ macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", dreg, dreg, AT);
+ break;
+
+ case M_S_DOB:
+ if (mips_cpu == 4650)
+ {
+ as_bad (_("opcode not supported on this processor"));
+ return;
+ }
+ assert (mips_opts.isa < 2);
+ /* Even on a big endian machine $fn comes before $fn+1. We have
+ to adjust when storing to memory. */
+ macro_build ((char *) NULL, &icnt, &offset_expr, "swc1", "T,o(b)",
+ target_big_endian ? treg + 1 : treg,
+ (int) BFD_RELOC_LO16, breg);
+ offset_expr.X_add_number += 4;
+ macro_build ((char *) NULL, &icnt, &offset_expr, "swc1", "T,o(b)",
+ target_big_endian ? treg : treg + 1,
+ (int) BFD_RELOC_LO16, breg);
+ return;
+
+ case M_SEQ:
+ if (sreg == 0)
+ macro_build ((char *) NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg,
+ treg, (int) BFD_RELOC_LO16);
+ else if (treg == 0)
+ macro_build ((char *) NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg,
+ sreg, (int) BFD_RELOC_LO16);
+ else
+ {
+ macro_build ((char *) NULL, &icnt, NULL, "xor", "d,v,t", dreg,
+ sreg, treg);
+ macro_build ((char *) NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg,
+ dreg, (int) BFD_RELOC_LO16);
+ }
+ return;
+
+ case M_SEQ_I:
+ if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 0)
+ {
+ macro_build ((char *) NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg,
+ sreg, (int) BFD_RELOC_LO16);
+ return;
+ }
+ if (sreg == 0)
+ {
+ as_warn (_("Instruction %s: result is always false"),
+ ip->insn_mo->name);
+ macro_build ((char *) NULL, &icnt, NULL, "move", "d,s", dreg, 0);
+ return;
+ }
+ if (imm_expr.X_op == O_constant
+ && imm_expr.X_add_number >= 0
+ && imm_expr.X_add_number < 0x10000)
+ {
+ macro_build ((char *) NULL, &icnt, &imm_expr, "xori", "t,r,i", dreg,
+ sreg, (int) BFD_RELOC_LO16);
+ used_at = 0;
+ }
+ else if (imm_expr.X_op == O_constant
+ && imm_expr.X_add_number > -0x8000
+ && imm_expr.X_add_number < 0)
+ {
+ imm_expr.X_add_number = -imm_expr.X_add_number;
+ macro_build ((char *) NULL, &icnt, &imm_expr,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", dreg, sreg,
+ (int) BFD_RELOC_LO16);
+ used_at = 0;
+ }
+ else
+ {
+ load_register (&icnt, AT, &imm_expr, 0);
+ macro_build ((char *) NULL, &icnt, NULL, "xor", "d,v,t", dreg,
+ sreg, AT);
+ used_at = 1;
+ }
+ macro_build ((char *) NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg, dreg,
+ (int) BFD_RELOC_LO16);
+ if (used_at)
+ break;
+ return;
+
+ case M_SGE: /* sreg >= treg <==> not (sreg < treg) */
+ s = "slt";
+ goto sge;
+ case M_SGEU:
+ s = "sltu";
+ sge:
+ macro_build ((char *) NULL, &icnt, NULL, s, "d,v,t", dreg, sreg, treg);
+ macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg,
+ (int) BFD_RELOC_LO16);
+ return;
+
+ case M_SGE_I: /* sreg >= I <==> not (sreg < I) */
+ case M_SGEU_I:
+ if (imm_expr.X_op == O_constant
+ && imm_expr.X_add_number >= -0x8000
+ && imm_expr.X_add_number < 0x8000)
+ {
+ macro_build ((char *) NULL, &icnt, &imm_expr,
+ mask == M_SGE_I ? "slti" : "sltiu",
+ "t,r,j", dreg, sreg, (int) BFD_RELOC_LO16);
+ used_at = 0;
+ }
+ else
+ {
+ load_register (&icnt, AT, &imm_expr, 0);
+ macro_build ((char *) NULL, &icnt, NULL,
+ mask == M_SGE_I ? "slt" : "sltu",
+ "d,v,t", dreg, sreg, AT);
+ used_at = 1;
+ }
+ macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg,
+ (int) BFD_RELOC_LO16);
+ if (used_at)
+ break;
+ return;
+
+ case M_SGT: /* sreg > treg <==> treg < sreg */
+ s = "slt";
+ goto sgt;
+ case M_SGTU:
+ s = "sltu";
+ sgt:
+ macro_build ((char *) NULL, &icnt, NULL, s, "d,v,t", dreg, treg, sreg);
+ return;
+
+ case M_SGT_I: /* sreg > I <==> I < sreg */
+ s = "slt";
+ goto sgti;
+ case M_SGTU_I:
+ s = "sltu";
+ sgti:
+ load_register (&icnt, AT, &imm_expr, 0);
+ macro_build ((char *) NULL, &icnt, NULL, s, "d,v,t", dreg, AT, sreg);
+ break;
+
+ case M_SLE: /* sreg <= treg <==> treg >= sreg <==> not (treg < sreg) */
+ s = "slt";
+ goto sle;
+ case M_SLEU:
+ s = "sltu";
+ sle:
+ macro_build ((char *) NULL, &icnt, NULL, s, "d,v,t", dreg, treg, sreg);
+ macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg,
+ (int) BFD_RELOC_LO16);
+ return;
+
+ case M_SLE_I: /* sreg <= I <==> I >= sreg <==> not (I < sreg) */
+ s = "slt";
+ goto slei;
+ case M_SLEU_I:
+ s = "sltu";
+ slei:
+ load_register (&icnt, AT, &imm_expr, 0);
+ macro_build ((char *) NULL, &icnt, NULL, s, "d,v,t", dreg, AT, sreg);
+ macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg,
+ (int) BFD_RELOC_LO16);
+ break;
+
+ case M_SLT_I:
+ if (imm_expr.X_op == O_constant
+ && imm_expr.X_add_number >= -0x8000
+ && imm_expr.X_add_number < 0x8000)
+ {
+ macro_build ((char *) NULL, &icnt, &imm_expr, "slti", "t,r,j",
+ dreg, sreg, (int) BFD_RELOC_LO16);
+ return;
+ }
+ load_register (&icnt, AT, &imm_expr, 0);
+ macro_build ((char *) NULL, &icnt, NULL, "slt", "d,v,t", dreg, sreg, AT);
+ break;
+
+ case M_SLTU_I:
+ if (imm_expr.X_op == O_constant
+ && imm_expr.X_add_number >= -0x8000
+ && imm_expr.X_add_number < 0x8000)
+ {
+ macro_build ((char *) NULL, &icnt, &imm_expr, "sltiu", "t,r,j",
+ dreg, sreg, (int) BFD_RELOC_LO16);
+ return;
+ }
+ load_register (&icnt, AT, &imm_expr, 0);
+ macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, sreg,
+ AT);
+ break;
+
+ case M_SNE:
+ if (sreg == 0)
+ macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0,
+ treg);
+ else if (treg == 0)
+ macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0,
+ sreg);
+ else
+ {
+ macro_build ((char *) NULL, &icnt, NULL, "xor", "d,v,t", dreg,
+ sreg, treg);
+ macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0,
+ dreg);
+ }
+ return;
+
+ case M_SNE_I:
+ if (imm_expr.X_op == O_constant && imm_expr.X_add_number == 0)
+ {
+ macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0,
+ sreg);
+ return;
+ }
+ if (sreg == 0)
+ {
+ as_warn (_("Instruction %s: result is always true"),
+ ip->insn_mo->name);
+ macro_build ((char *) NULL, &icnt, &expr1,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", dreg, 0, (int) BFD_RELOC_LO16);
+ return;
+ }
+ if (imm_expr.X_op == O_constant
+ && imm_expr.X_add_number >= 0
+ && imm_expr.X_add_number < 0x10000)
+ {
+ macro_build ((char *) NULL, &icnt, &imm_expr, "xori", "t,r,i",
+ dreg, sreg, (int) BFD_RELOC_LO16);
+ used_at = 0;
+ }
+ else if (imm_expr.X_op == O_constant
+ && imm_expr.X_add_number > -0x8000
+ && imm_expr.X_add_number < 0)
+ {
+ imm_expr.X_add_number = -imm_expr.X_add_number;
+ macro_build ((char *) NULL, &icnt, &imm_expr,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addiu" : "daddiu"),
+ "t,r,j", dreg, sreg, (int) BFD_RELOC_LO16);
+ used_at = 0;
+ }
+ else
+ {
+ load_register (&icnt, AT, &imm_expr, 0);
+ macro_build ((char *) NULL, &icnt, NULL, "xor", "d,v,t", dreg,
+ sreg, AT);
+ used_at = 1;
+ }
+ macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0, dreg);
+ if (used_at)
+ break;
+ return;
+
+ case M_DSUB_I:
+ dbl = 1;
+ case M_SUB_I:
+ if (imm_expr.X_op == O_constant
+ && imm_expr.X_add_number > -0x8000
+ && imm_expr.X_add_number <= 0x8000)
+ {
+ imm_expr.X_add_number = -imm_expr.X_add_number;
+ macro_build ((char *) NULL, &icnt, &imm_expr,
+ dbl ? "daddi" : "addi",
+ "t,r,j", dreg, sreg, (int) BFD_RELOC_LO16);
+ return;
+ }
+ load_register (&icnt, AT, &imm_expr, dbl);
+ macro_build ((char *) NULL, &icnt, NULL,
+ dbl ? "dsub" : "sub",
+ "d,v,t", dreg, sreg, AT);
+ break;
+
+ case M_DSUBU_I:
+ dbl = 1;
+ case M_SUBU_I:
+ if (imm_expr.X_op == O_constant
+ && imm_expr.X_add_number > -0x8000
+ && imm_expr.X_add_number <= 0x8000)
+ {
+ imm_expr.X_add_number = -imm_expr.X_add_number;
+ macro_build ((char *) NULL, &icnt, &imm_expr,
+ dbl ? "daddiu" : "addiu",
+ "t,r,j", dreg, sreg, (int) BFD_RELOC_LO16);
+ return;
+ }
+ load_register (&icnt, AT, &imm_expr, dbl);
+ macro_build ((char *) NULL, &icnt, NULL,
+ dbl ? "dsubu" : "subu",
+ "d,v,t", dreg, sreg, AT);
+ break;
+
+ case M_TEQ_I:
+ s = "teq";
+ goto trap;
+ case M_TGE_I:
+ s = "tge";
+ goto trap;
+ case M_TGEU_I:
+ s = "tgeu";
+ goto trap;
+ case M_TLT_I:
+ s = "tlt";
+ goto trap;
+ case M_TLTU_I:
+ s = "tltu";
+ goto trap;
+ case M_TNE_I:
+ s = "tne";
+ trap:
+ load_register (&icnt, AT, &imm_expr, 0);
+ macro_build ((char *) NULL, &icnt, NULL, s, "s,t", sreg, AT);
+ break;
+
+ case M_TRUNCWD:
+ case M_TRUNCWS:
+ assert (mips_opts.isa < 2);
+ sreg = (ip->insn_opcode >> 11) & 0x1f; /* floating reg */
+ dreg = (ip->insn_opcode >> 06) & 0x1f; /* floating reg */
+
+ /*
+ * Is the double cfc1 instruction a bug in the mips assembler;
+ * or is there a reason for it?
+ */
+ mips_emit_delays (true);
+ ++mips_opts.noreorder;
+ mips_any_noreorder = 1;
+ macro_build ((char *) NULL, &icnt, NULL, "cfc1", "t,G", treg, 31);
+ macro_build ((char *) NULL, &icnt, NULL, "cfc1", "t,G", treg, 31);
+ macro_build ((char *) NULL, &icnt, NULL, "nop", "");
+ expr1.X_add_number = 3;
+ macro_build ((char *) NULL, &icnt, &expr1, "ori", "t,r,i", AT, treg,
+ (int) BFD_RELOC_LO16);
+ expr1.X_add_number = 2;
+ macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", AT, AT,
+ (int) BFD_RELOC_LO16);
+ macro_build ((char *) NULL, &icnt, NULL, "ctc1", "t,G", AT, 31);
+ macro_build ((char *) NULL, &icnt, NULL, "nop", "");
+ macro_build ((char *) NULL, &icnt, NULL,
+ mask == M_TRUNCWD ? "cvt.w.d" : "cvt.w.s", "D,S", dreg, sreg);
+ macro_build ((char *) NULL, &icnt, NULL, "ctc1", "t,G", treg, 31);
+ macro_build ((char *) NULL, &icnt, NULL, "nop", "");
+ --mips_opts.noreorder;
+ break;
+
+ case M_ULH:
+ s = "lb";
+ goto ulh;
+ case M_ULHU:
+ s = "lbu";
+ ulh:
+ if (offset_expr.X_add_number >= 0x7fff)
+ as_bad (_("operand overflow"));
+ /* avoid load delay */
+ if (! target_big_endian)
+ offset_expr.X_add_number += 1;
+ macro_build ((char *) NULL, &icnt, &offset_expr, s, "t,o(b)", treg,
+ (int) BFD_RELOC_LO16, breg);
+ if (! target_big_endian)
+ offset_expr.X_add_number -= 1;
+ else
+ offset_expr.X_add_number += 1;
+ macro_build ((char *) NULL, &icnt, &offset_expr, "lbu", "t,o(b)", AT,
+ (int) BFD_RELOC_LO16, breg);
+ macro_build ((char *) NULL, &icnt, NULL, "sll", "d,w,<", treg, treg, 8);
+ macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", treg, treg, AT);
+ break;
+
+ case M_ULD:
+ s = "ldl";
+ s2 = "ldr";
+ off = 7;
+ goto ulw;
+ case M_ULW:
+ s = "lwl";
+ s2 = "lwr";
+ off = 3;
+ ulw:
+ if (offset_expr.X_add_number >= 0x8000 - off)
+ as_bad (_("operand overflow"));
+ if (! target_big_endian)
+ offset_expr.X_add_number += off;
+ macro_build ((char *) NULL, &icnt, &offset_expr, s, "t,o(b)", treg,
+ (int) BFD_RELOC_LO16, breg);
+ if (! target_big_endian)
+ offset_expr.X_add_number -= off;
+ else
+ offset_expr.X_add_number += off;
+ macro_build ((char *) NULL, &icnt, &offset_expr, s2, "t,o(b)", treg,
+ (int) BFD_RELOC_LO16, breg);
+ return;
+
+ case M_ULD_A:
+ s = "ldl";
+ s2 = "ldr";
+ off = 7;
+ goto ulwa;
+ case M_ULW_A:
+ s = "lwl";
+ s2 = "lwr";
+ off = 3;
+ ulwa:
+ load_address (&icnt, AT, &offset_expr);
+ if (breg != 0)
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", AT, AT, breg);
+ if (! target_big_endian)
+ expr1.X_add_number = off;
+ else
+ expr1.X_add_number = 0;
+ macro_build ((char *) NULL, &icnt, &expr1, s, "t,o(b)", treg,
+ (int) BFD_RELOC_LO16, AT);
+ if (! target_big_endian)
+ expr1.X_add_number = 0;
+ else
+ expr1.X_add_number = off;
+ macro_build ((char *) NULL, &icnt, &expr1, s2, "t,o(b)", treg,
+ (int) BFD_RELOC_LO16, AT);
+ break;
+
+ case M_ULH_A:
+ case M_ULHU_A:
+ load_address (&icnt, AT, &offset_expr);
+ if (breg != 0)
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", AT, AT, breg);
+ if (target_big_endian)
+ expr1.X_add_number = 0;
+ macro_build ((char *) NULL, &icnt, &expr1,
+ mask == M_ULH_A ? "lb" : "lbu", "t,o(b)", treg,
+ (int) BFD_RELOC_LO16, AT);
+ if (target_big_endian)
+ expr1.X_add_number = 1;
+ else
+ expr1.X_add_number = 0;
+ macro_build ((char *) NULL, &icnt, &expr1, "lbu", "t,o(b)", AT,
+ (int) BFD_RELOC_LO16, AT);
+ macro_build ((char *) NULL, &icnt, NULL, "sll", "d,w,<", treg,
+ treg, 8);
+ macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", treg,
+ treg, AT);
+ break;
+
+ case M_USH:
+ if (offset_expr.X_add_number >= 0x7fff)
+ as_bad (_("operand overflow"));
+ if (target_big_endian)
+ offset_expr.X_add_number += 1;
+ macro_build ((char *) NULL, &icnt, &offset_expr, "sb", "t,o(b)", treg,
+ (int) BFD_RELOC_LO16, breg);
+ macro_build ((char *) NULL, &icnt, NULL, "srl", "d,w,<", AT, treg, 8);
+ if (target_big_endian)
+ offset_expr.X_add_number -= 1;
+ else
+ offset_expr.X_add_number += 1;
+ macro_build ((char *) NULL, &icnt, &offset_expr, "sb", "t,o(b)", AT,
+ (int) BFD_RELOC_LO16, breg);
+ break;
+
+ case M_USD:
+ s = "sdl";
+ s2 = "sdr";
+ off = 7;
+ goto usw;
+ case M_USW:
+ s = "swl";
+ s2 = "swr";
+ off = 3;
+ usw:
+ if (offset_expr.X_add_number >= 0x8000 - off)
+ as_bad (_("operand overflow"));
+ if (! target_big_endian)
+ offset_expr.X_add_number += off;
+ macro_build ((char *) NULL, &icnt, &offset_expr, s, "t,o(b)", treg,
+ (int) BFD_RELOC_LO16, breg);
+ if (! target_big_endian)
+ offset_expr.X_add_number -= off;
+ else
+ offset_expr.X_add_number += off;
+ macro_build ((char *) NULL, &icnt, &offset_expr, s2, "t,o(b)", treg,
+ (int) BFD_RELOC_LO16, breg);
+ return;
+
+ case M_USD_A:
+ s = "sdl";
+ s2 = "sdr";
+ off = 7;
+ goto uswa;
+ case M_USW_A:
+ s = "swl";
+ s2 = "swr";
+ off = 3;
+ uswa:
+ load_address (&icnt, AT, &offset_expr);
+ if (breg != 0)
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", AT, AT, breg);
+ if (! target_big_endian)
+ expr1.X_add_number = off;
+ else
+ expr1.X_add_number = 0;
+ macro_build ((char *) NULL, &icnt, &expr1, s, "t,o(b)", treg,
+ (int) BFD_RELOC_LO16, AT);
+ if (! target_big_endian)
+ expr1.X_add_number = 0;
+ else
+ expr1.X_add_number = off;
+ macro_build ((char *) NULL, &icnt, &expr1, s2, "t,o(b)", treg,
+ (int) BFD_RELOC_LO16, AT);
+ break;
+
+ case M_USH_A:
+ load_address (&icnt, AT, &offset_expr);
+ if (breg != 0)
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", AT, AT, breg);
+ if (! target_big_endian)
+ expr1.X_add_number = 0;
+ macro_build ((char *) NULL, &icnt, &expr1, "sb", "t,o(b)", treg,
+ (int) BFD_RELOC_LO16, AT);
+ macro_build ((char *) NULL, &icnt, NULL, "srl", "d,w,<", treg,
+ treg, 8);
+ if (! target_big_endian)
+ expr1.X_add_number = 1;
+ else
+ expr1.X_add_number = 0;
+ macro_build ((char *) NULL, &icnt, &expr1, "sb", "t,o(b)", treg,
+ (int) BFD_RELOC_LO16, AT);
+ if (! target_big_endian)
+ expr1.X_add_number = 0;
+ else
+ expr1.X_add_number = 1;
+ macro_build ((char *) NULL, &icnt, &expr1, "lbu", "t,o(b)", AT,
+ (int) BFD_RELOC_LO16, AT);
+ macro_build ((char *) NULL, &icnt, NULL, "sll", "d,w,<", treg,
+ treg, 8);
+ macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", treg,
+ treg, AT);
+ break;
+
+ default:
+ /* FIXME: Check if this is one of the itbl macros, since they
+ are added dynamically. */
+ as_bad (_("Macro %s not implemented yet"), ip->insn_mo->name);
+ break;
+ }
+ if (mips_opts.noat)
+ as_warn (_("Macro used $at after \".set noat\""));
+}
+
+/* Implement macros in mips16 mode. */
+
+static void
+mips16_macro (ip)
+ struct mips_cl_insn *ip;
+{
+ int mask;
+ int xreg, yreg, zreg, tmp;
+ int icnt;
+ expressionS expr1;
+ int dbl;
+ const char *s, *s2, *s3;
+
+ mask = ip->insn_mo->mask;
+
+ xreg = (ip->insn_opcode >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
+ yreg = (ip->insn_opcode >> MIPS16OP_SH_RY) & MIPS16OP_MASK_RY;
+ zreg = (ip->insn_opcode >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
+
+ icnt = 0;
+
+ expr1.X_op = O_constant;
+ expr1.X_op_symbol = NULL;
+ expr1.X_add_symbol = NULL;
+ expr1.X_add_number = 1;
+
+ dbl = 0;
+
+ switch (mask)
+ {
+ default:
+ internalError ();
+
+ case M_DDIV_3:
+ dbl = 1;
+ case M_DIV_3:
+ s = "mflo";
+ goto do_div3;
+ case M_DREM_3:
+ dbl = 1;
+ case M_REM_3:
+ s = "mfhi";
+ do_div3:
+ mips_emit_delays (true);
+ ++mips_opts.noreorder;
+ mips_any_noreorder = 1;
+ macro_build ((char *) NULL, &icnt, NULL,
+ dbl ? "ddiv" : "div",
+ "0,x,y", xreg, yreg);
+ expr1.X_add_number = 2;
+ macro_build ((char *) NULL, &icnt, &expr1, "bnez", "x,p", yreg);
+ macro_build ((char *) NULL, &icnt, NULL, "break", "6", 7);
+
+ /* FIXME: The normal code checks for of -1 / -0x80000000 here,
+ since that causes an overflow. We should do that as well,
+ but I don't see how to do the comparisons without a temporary
+ register. */
+ --mips_opts.noreorder;
+ macro_build ((char *) NULL, &icnt, NULL, s, "x", zreg);
+ break;
+
+ case M_DIVU_3:
+ s = "divu";
+ s2 = "mflo";
+ goto do_divu3;
+ case M_REMU_3:
+ s = "divu";
+ s2 = "mfhi";
+ goto do_divu3;
+ case M_DDIVU_3:
+ s = "ddivu";
+ s2 = "mflo";
+ goto do_divu3;
+ case M_DREMU_3:
+ s = "ddivu";
+ s2 = "mfhi";
+ do_divu3:
+ mips_emit_delays (true);
+ ++mips_opts.noreorder;
+ mips_any_noreorder = 1;
+ macro_build ((char *) NULL, &icnt, NULL, s, "0,x,y", xreg, yreg);
+ expr1.X_add_number = 2;
+ macro_build ((char *) NULL, &icnt, &expr1, "bnez", "x,p", yreg);
+ macro_build ((char *) NULL, &icnt, NULL, "break", "6", 7);
+ --mips_opts.noreorder;
+ macro_build ((char *) NULL, &icnt, NULL, s2, "x", zreg);
+ break;
+
+ case M_DMUL:
+ dbl = 1;
+ case M_MUL:
+ macro_build ((char *) NULL, &icnt, NULL,
+ dbl ? "dmultu" : "multu",
+ "x,y", xreg, yreg);
+ macro_build ((char *) NULL, &icnt, NULL, "mflo", "x", zreg);
+ return;
+
+ case M_DSUBU_I:
+ dbl = 1;
+ goto do_subu;
+ case M_SUBU_I:
+ do_subu:
+ if (imm_expr.X_op != O_constant)
+ as_bad (_("Unsupported large constant"));
+ imm_expr.X_add_number = -imm_expr.X_add_number;
+ macro_build ((char *) NULL, &icnt, &imm_expr,
+ dbl ? "daddiu" : "addiu",
+ "y,x,4", yreg, xreg);
+ break;
+
+ case M_SUBU_I_2:
+ if (imm_expr.X_op != O_constant)
+ as_bad (_("Unsupported large constant"));
+ imm_expr.X_add_number = -imm_expr.X_add_number;
+ macro_build ((char *) NULL, &icnt, &imm_expr, "addiu",
+ "x,k", xreg);
+ break;
+
+ case M_DSUBU_I_2:
+ if (imm_expr.X_op != O_constant)
+ as_bad (_("Unsupported large constant"));
+ imm_expr.X_add_number = -imm_expr.X_add_number;
+ macro_build ((char *) NULL, &icnt, &imm_expr, "daddiu",
+ "y,j", yreg);
+ break;
+
+ case M_BEQ:
+ s = "cmp";
+ s2 = "bteqz";
+ goto do_branch;
+ case M_BNE:
+ s = "cmp";
+ s2 = "btnez";
+ goto do_branch;
+ case M_BLT:
+ s = "slt";
+ s2 = "btnez";
+ goto do_branch;
+ case M_BLTU:
+ s = "sltu";
+ s2 = "btnez";
+ goto do_branch;
+ case M_BLE:
+ s = "slt";
+ s2 = "bteqz";
+ goto do_reverse_branch;
+ case M_BLEU:
+ s = "sltu";
+ s2 = "bteqz";
+ goto do_reverse_branch;
+ case M_BGE:
+ s = "slt";
+ s2 = "bteqz";
+ goto do_branch;
+ case M_BGEU:
+ s = "sltu";
+ s2 = "bteqz";
+ goto do_branch;
+ case M_BGT:
+ s = "slt";
+ s2 = "btnez";
+ goto do_reverse_branch;
+ case M_BGTU:
+ s = "sltu";
+ s2 = "btnez";
+
+ do_reverse_branch:
+ tmp = xreg;
+ xreg = yreg;
+ yreg = tmp;
+
+ do_branch:
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, s, "x,y",
+ xreg, yreg);
+ macro_build ((char *) NULL, &icnt, &offset_expr, s2, "p");
+ break;
+
+ case M_BEQ_I:
+ s = "cmpi";
+ s2 = "bteqz";
+ s3 = "x,U";
+ goto do_branch_i;
+ case M_BNE_I:
+ s = "cmpi";
+ s2 = "btnez";
+ s3 = "x,U";
+ goto do_branch_i;
+ case M_BLT_I:
+ s = "slti";
+ s2 = "btnez";
+ s3 = "x,8";
+ goto do_branch_i;
+ case M_BLTU_I:
+ s = "sltiu";
+ s2 = "btnez";
+ s3 = "x,8";
+ goto do_branch_i;
+ case M_BLE_I:
+ s = "slti";
+ s2 = "btnez";
+ s3 = "x,8";
+ goto do_addone_branch_i;
+ case M_BLEU_I:
+ s = "sltiu";
+ s2 = "btnez";
+ s3 = "x,8";
+ goto do_addone_branch_i;
+ case M_BGE_I:
+ s = "slti";
+ s2 = "bteqz";
+ s3 = "x,8";
+ goto do_branch_i;
+ case M_BGEU_I:
+ s = "sltiu";
+ s2 = "bteqz";
+ s3 = "x,8";
+ goto do_branch_i;
+ case M_BGT_I:
+ s = "slti";
+ s2 = "bteqz";
+ s3 = "x,8";
+ goto do_addone_branch_i;
+ case M_BGTU_I:
+ s = "sltiu";
+ s2 = "bteqz";
+ s3 = "x,8";
+
+ do_addone_branch_i:
+ if (imm_expr.X_op != O_constant)
+ as_bad (_("Unsupported large constant"));
+ ++imm_expr.X_add_number;
+
+ do_branch_i:
+ macro_build ((char *) NULL, &icnt, &imm_expr, s, s3, xreg);
+ macro_build ((char *) NULL, &icnt, &offset_expr, s2, "p");
+ break;
+
+ case M_ABS:
+ expr1.X_add_number = 0;
+ macro_build ((char *) NULL, &icnt, &expr1, "slti", "x,8", yreg);
+ if (xreg != yreg)
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ "move", "y,X", xreg, yreg);
+ expr1.X_add_number = 2;
+ macro_build ((char *) NULL, &icnt, &expr1, "bteqz", "p");
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ "neg", "x,w", xreg, xreg);
+ }
+}
+
+/* For consistency checking, verify that all bits are specified either
+ by the match/mask part of the instruction definition, or by the
+ operand list. */
+static int
+validate_mips_insn (opc)
+ const struct mips_opcode *opc;
+{
+ const char *p = opc->args;
+ char c;
+ unsigned long used_bits = opc->mask;
+
+ if ((used_bits & opc->match) != opc->match)
+ {
+ as_bad (_("internal: bad mips opcode (mask error): %s %s"),
+ opc->name, opc->args);
+ return 0;
+ }
+#define USE_BITS(mask,shift) (used_bits |= ((mask) << (shift)))
+ while (*p)
+ switch (c = *p++)
+ {
+ case ',': break;
+ case '(': break;
+ case ')': break;
+ case '<': USE_BITS (OP_MASK_SHAMT, OP_SH_SHAMT); break;
+ case '>': USE_BITS (OP_MASK_SHAMT, OP_SH_SHAMT); break;
+ case 'A': break;
+ case 'B': USE_BITS (OP_MASK_SYSCALL, OP_SH_SYSCALL); break;
+ case 'C': USE_BITS (OP_MASK_COPZ, OP_SH_COPZ); break;
+ case 'D': USE_BITS (OP_MASK_FD, OP_SH_FD); break;
+ case 'E': USE_BITS (OP_MASK_RT, OP_SH_RT); break;
+ case 'F': break;
+ case 'G': USE_BITS (OP_MASK_RD, OP_SH_RD); break;
+ case 'I': break;
+ case 'L': break;
+ case 'M': USE_BITS (OP_MASK_CCC, OP_SH_CCC); break;
+ case 'N': USE_BITS (OP_MASK_BCC, OP_SH_BCC); break;
+ case 'R': USE_BITS (OP_MASK_FR, OP_SH_FR); break;
+ case 'S': USE_BITS (OP_MASK_FS, OP_SH_FS); break;
+ case 'T': USE_BITS (OP_MASK_FT, OP_SH_FT); break;
+ case 'V': USE_BITS (OP_MASK_FS, OP_SH_FS); break;
+ case 'W': USE_BITS (OP_MASK_FT, OP_SH_FT); break;
+ case 'a': USE_BITS (OP_MASK_TARGET, OP_SH_TARGET); break;
+ case 'b': USE_BITS (OP_MASK_RS, OP_SH_RS); break;
+ case 'c': USE_BITS (OP_MASK_CODE, OP_SH_CODE); break;
+ case 'd': USE_BITS (OP_MASK_RD, OP_SH_RD); break;
+ case 'f': break;
+ case 'h': USE_BITS (OP_MASK_PREFX, OP_SH_PREFX); break;
+ case 'i': USE_BITS (OP_MASK_IMMEDIATE, OP_SH_IMMEDIATE); break;
+ case 'j': USE_BITS (OP_MASK_DELTA, OP_SH_DELTA); break;
+ case 'k': USE_BITS (OP_MASK_CACHE, OP_SH_CACHE); break;
+ case 'l': break;
+ case 'o': USE_BITS (OP_MASK_DELTA, OP_SH_DELTA); break;
+ case 'p': USE_BITS (OP_MASK_DELTA, OP_SH_DELTA); break;
+ case 'q': USE_BITS (OP_MASK_CODE2, OP_SH_CODE2); break;
+ case 'r': USE_BITS (OP_MASK_RS, OP_SH_RS); break;
+ case 's': USE_BITS (OP_MASK_RS, OP_SH_RS); break;
+ case 't': USE_BITS (OP_MASK_RT, OP_SH_RT); break;
+ case 'u': USE_BITS (OP_MASK_IMMEDIATE, OP_SH_IMMEDIATE); break;
+ case 'v': USE_BITS (OP_MASK_RS, OP_SH_RS); break;
+ case 'w': USE_BITS (OP_MASK_RT, OP_SH_RT); break;
+ case 'x': break;
+ case 'z': break;
+ case 'P': USE_BITS (OP_MASK_PERFREG, OP_SH_PERFREG); break;
+ default:
+ as_bad (_("internal: bad mips opcode (unknown operand type `%c'): %s %s"),
+ c, opc->name, opc->args);
+ return 0;
+ }
+#undef USE_BITS
+ if (used_bits != 0xffffffff)
+ {
+ as_bad (_("internal: bad mips opcode (bits 0x%lx undefined): %s %s"),
+ ~used_bits & 0xffffffff, opc->name, opc->args);
+ return 0;
+ }
+ return 1;
+}
+
+/* This routine assembles an instruction into its binary format. As a
+ side effect, it sets one of the global variables imm_reloc or
+ offset_reloc to the type of relocation to do if one of the operands
+ is an address expression. */
+
+static void
+mips_ip (str, ip)
+ char *str;
+ struct mips_cl_insn *ip;
+{
+ char *s;
+ const char *args;
+ char c;
+ struct mips_opcode *insn;
+ char *argsStart;
+ unsigned int regno;
+ unsigned int lastregno = 0;
+ char *s_reset;
+ char save_c = 0;
+ int full_opcode_match = 1;
+
+ insn_error = NULL;
+
+ /* If the instruction contains a '.', we first try to match an instruction
+ including the '.'. Then we try again without the '.'. */
+ insn = NULL;
+ for (s = str; *s != '\0' && !isspace(*s); ++s)
+ continue;
+
+ /* If we stopped on whitespace, then replace the whitespace with null for
+ the call to hash_find. Save the character we replaced just in case we
+ have to re-parse the instruction. */
+ if (isspace (*s))
+ {
+ save_c = *s;
+ *s++ = '\0';
+ }
+
+ insn = (struct mips_opcode *) hash_find (op_hash, str);
+
+ /* If we didn't find the instruction in the opcode table, try again, but
+ this time with just the instruction up to, but not including the
+ first '.'. */
+ if (insn == NULL)
+ {
+ /* Restore the character we overwrite above (if any). */
+ if (save_c)
+ *(--s) = save_c;
+
+ /* Scan up to the first '.' or whitespace. */
+ for (s = str; *s != '\0' && *s != '.' && !isspace (*s); ++s)
+ continue;
+
+ /* If we did not find a '.', then we can quit now. */
+ if (*s != '.')
+ {
+ insn_error = "unrecognized opcode";
+ return;
+ }
+
+ /* Lookup the instruction in the hash table. */
+ *s++ = '\0';
+ if ((insn = (struct mips_opcode *) hash_find (op_hash, str)) == NULL)
+ {
+ insn_error = "unrecognized opcode";
+ return;
+ }
+
+ full_opcode_match = 0;
+ }
+
+ argsStart = s;
+ for (;;)
+ {
+ int insn_isa;
+ boolean ok;
+
+ assert (strcmp (insn->name, str) == 0);
+
+ if ((insn->membership & INSN_ISA) == INSN_ISA1)
+ insn_isa = 1;
+ else if ((insn->membership & INSN_ISA) == INSN_ISA2)
+ insn_isa = 2;
+ else if ((insn->membership & INSN_ISA) == INSN_ISA3)
+ insn_isa = 3;
+ else if ((insn->membership & INSN_ISA) == INSN_ISA4)
+ insn_isa = 4;
+ else
+ insn_isa = 15;
+
+ if (insn_isa <= mips_opts.isa)
+ ok = true;
+ else if (insn->pinfo == INSN_MACRO)
+ ok = false;
+ else if ((mips_cpu == 4650 && (insn->membership & INSN_4650) != 0)
+ || (mips_cpu == 4010 && (insn->membership & INSN_4010) != 0)
+ || ((mips_cpu == 4100
+ || mips_cpu == 4111
+ )
+ && (insn->membership & INSN_4100) != 0)
+ || (mips_cpu == 3900 && (insn->membership & INSN_3900) != 0))
+ ok = true;
+ else
+ ok = false;
+
+ if (insn->pinfo != INSN_MACRO)
+ {
+ if (mips_cpu == 4650 && (insn->pinfo & FP_D) != 0)
+ ok = false;
+ }
+
+ if (! ok)
+ {
+ if (insn + 1 < &mips_opcodes[NUMOPCODES]
+ && strcmp (insn->name, insn[1].name) == 0)
+ {
+ ++insn;
+ continue;
+ }
+ if (insn_isa == 15
+ || insn_isa <= mips_opts.isa)
+ insn_error = _("opcode not supported on this processor");
+ else
+ {
+ static char buf[100];
+
+ sprintf (buf, _("opcode requires -mips%d or greater"), insn_isa);
+ insn_error = buf;
+ }
+ return;
+ }
+
+ ip->insn_mo = insn;
+ ip->insn_opcode = insn->match;
+ for (args = insn->args;; ++args)
+ {
+ if (*s == ' ')
+ ++s;
+ switch (*args)
+ {
+ case '\0': /* end of args */
+ if (*s == '\0')
+ return;
+ break;
+
+ case ',':
+ if (*s++ == *args)
+ continue;
+ s--;
+ switch (*++args)
+ {
+ case 'r':
+ case 'v':
+ ip->insn_opcode |= lastregno << 21;
+ continue;
+
+ case 'w':
+ case 'W':
+ ip->insn_opcode |= lastregno << 16;
+ continue;
+
+ case 'V':
+ ip->insn_opcode |= lastregno << 11;
+ continue;
+ }
+ break;
+
+ case '(':
+ /* Handle optional base register.
+ Either the base register is omitted or
+ we must have a left paren. */
+ /* This is dependent on the next operand specifier
+ is a base register specification. */
+ assert (args[1] == 'b' || args[1] == '5'
+ || args[1] == '-' || args[1] == '4');
+ if (*s == '\0')
+ return;
+
+ case ')': /* these must match exactly */
+ if (*s++ == *args)
+ continue;
+ break;
+
+ case '<': /* must be at least one digit */
+ /*
+ * According to the manual, if the shift amount is greater
+ * than 31 or less than 0 the the shift amount should be
+ * mod 32. In reality the mips assembler issues an error.
+ * We issue a warning and mask out all but the low 5 bits.
+ */
+ my_getExpression (&imm_expr, s);
+ check_absolute_expr (ip, &imm_expr);
+ if ((unsigned long) imm_expr.X_add_number > 31)
+ {
+ as_warn (_("Improper shift amount (%ld)"),
+ (long) imm_expr.X_add_number);
+ imm_expr.X_add_number = imm_expr.X_add_number & 0x1f;
+ }
+ ip->insn_opcode |= imm_expr.X_add_number << 6;
+ imm_expr.X_op = O_absent;
+ s = expr_end;
+ continue;
+
+ case '>': /* shift amount minus 32 */
+ my_getExpression (&imm_expr, s);
+ check_absolute_expr (ip, &imm_expr);
+ if ((unsigned long) imm_expr.X_add_number < 32
+ || (unsigned long) imm_expr.X_add_number > 63)
+ break;
+ ip->insn_opcode |= (imm_expr.X_add_number - 32) << 6;
+ imm_expr.X_op = O_absent;
+ s = expr_end;
+ continue;
+
+
+ case 'k': /* cache code */
+ case 'h': /* prefx code */
+ my_getExpression (&imm_expr, s);
+ check_absolute_expr (ip, &imm_expr);
+ if ((unsigned long) imm_expr.X_add_number > 31)
+ {
+ as_warn (_("Invalid value for `%s' (%lu)"),
+ ip->insn_mo->name,
+ (unsigned long) imm_expr.X_add_number);
+ imm_expr.X_add_number &= 0x1f;
+ }
+ if (*args == 'k')
+ ip->insn_opcode |= imm_expr.X_add_number << OP_SH_CACHE;
+ else
+ ip->insn_opcode |= imm_expr.X_add_number << OP_SH_PREFX;
+ imm_expr.X_op = O_absent;
+ s = expr_end;
+ continue;
+
+ case 'c': /* break code */
+ my_getExpression (&imm_expr, s);
+ check_absolute_expr (ip, &imm_expr);
+ if ((unsigned) imm_expr.X_add_number > 1023)
+ {
+ as_warn (_("Illegal break code (%ld)"),
+ (long) imm_expr.X_add_number);
+ imm_expr.X_add_number &= 0x3ff;
+ }
+ ip->insn_opcode |= imm_expr.X_add_number << 16;
+ imm_expr.X_op = O_absent;
+ s = expr_end;
+ continue;
+
+ case 'q': /* lower break code */
+ my_getExpression (&imm_expr, s);
+ check_absolute_expr (ip, &imm_expr);
+ if ((unsigned) imm_expr.X_add_number > 1023)
+ {
+ as_warn (_("Illegal lower break code (%ld)"),
+ (long) imm_expr.X_add_number);
+ imm_expr.X_add_number &= 0x3ff;
+ }
+ ip->insn_opcode |= imm_expr.X_add_number << 6;
+ imm_expr.X_op = O_absent;
+ s = expr_end;
+ continue;
+
+ case 'B': /* syscall code */
+ my_getExpression (&imm_expr, s);
+ check_absolute_expr (ip, &imm_expr);
+ if ((unsigned) imm_expr.X_add_number > 0xfffff)
+ as_warn (_("Illegal syscall code (%ld)"),
+ (long) imm_expr.X_add_number);
+ ip->insn_opcode |= imm_expr.X_add_number << 6;
+ imm_expr.X_op = O_absent;
+ s = expr_end;
+ continue;
+
+ case 'C': /* Coprocessor code */
+ my_getExpression (&imm_expr, s);
+ check_absolute_expr (ip, &imm_expr);
+ if ((unsigned long) imm_expr.X_add_number >= (1<<25))
+ {
+ as_warn (_("Coproccesor code > 25 bits (%ld)"),
+ (long) imm_expr.X_add_number);
+ imm_expr.X_add_number &= ((1<<25) - 1);
+ }
+ ip->insn_opcode |= imm_expr.X_add_number;
+ imm_expr.X_op = O_absent;
+ s = expr_end;
+ continue;
+
+ case 'P': /* Performance register */
+ my_getExpression (&imm_expr, s);
+ check_absolute_expr (ip, &imm_expr);
+ if (imm_expr.X_add_number != 0 && imm_expr.X_add_number != 1)
+ {
+ as_warn (_("Invalidate performance regster (%ld)"),
+ (long) imm_expr.X_add_number);
+ imm_expr.X_add_number &= 1;
+ }
+ ip->insn_opcode |= (imm_expr.X_add_number << 1);
+ imm_expr.X_op = O_absent;
+ s = expr_end;
+ continue;
+
+ case 'b': /* base register */
+ case 'd': /* destination register */
+ case 's': /* source register */
+ case 't': /* target register */
+ case 'r': /* both target and source */
+ case 'v': /* both dest and source */
+ case 'w': /* both dest and target */
+ case 'E': /* coprocessor target register */
+ case 'G': /* coprocessor destination register */
+ case 'x': /* ignore register name */
+ case 'z': /* must be zero register */
+ s_reset = s;
+ if (s[0] == '$')
+ {
+
+ if (isdigit (s[1]))
+ {
+ ++s;
+ regno = 0;
+ do
+ {
+ regno *= 10;
+ regno += *s - '0';
+ ++s;
+ }
+ while (isdigit (*s));
+ if (regno > 31)
+ as_bad (_("Invalid register number (%d)"), regno);
+ }
+ else if (*args == 'E' || *args == 'G')
+ goto notreg;
+ else
+ {
+ if (s[1] == 'f' && s[2] == 'p')
+ {
+ s += 3;
+ regno = FP;
+ }
+ else if (s[1] == 's' && s[2] == 'p')
+ {
+ s += 3;
+ regno = SP;
+ }
+ else if (s[1] == 'g' && s[2] == 'p')
+ {
+ s += 3;
+ regno = GP;
+ }
+ else if (s[1] == 'a' && s[2] == 't')
+ {
+ s += 3;
+ regno = AT;
+ }
+ else if (s[1] == 'k' && s[2] == 't' && s[3] == '0')
+ {
+ s += 4;
+ regno = KT0;
+ }
+ else if (s[1] == 'k' && s[2] == 't' && s[3] == '1')
+ {
+ s += 4;
+ regno = KT1;
+ }
+ else if (itbl_have_entries)
+ {
+ char *p, *n;
+ int r;
+
+ p = s+1; /* advance past '$' */
+ n = itbl_get_field (&p); /* n is name */
+
+ /* See if this is a register defined in an
+ itbl entry */
+ r = itbl_get_reg_val (n);
+ if (r)
+ {
+ /* Get_field advances to the start of
+ the next field, so we need to back
+ rack to the end of the last field. */
+ if (p)
+ s = p - 1;
+ else
+ s = strchr (s,'\0');
+ regno = r;
+ }
+ else
+ goto notreg;
+ }
+ else
+ goto notreg;
+ }
+ if (regno == AT
+ && ! mips_opts.noat
+ && *args != 'E'
+ && *args != 'G')
+ as_warn (_("Used $at without \".set noat\""));
+ c = *args;
+ if (*s == ' ')
+ s++;
+ if (args[1] != *s)
+ {
+ if (c == 'r' || c == 'v' || c == 'w')
+ {
+ regno = lastregno;
+ s = s_reset;
+ args++;
+ }
+ }
+ /* 'z' only matches $0. */
+ if (c == 'z' && regno != 0)
+ break;
+
+ /* Now that we have assembled one operand, we use the args string
+ * to figure out where it goes in the instruction. */
+ switch (c)
+ {
+ case 'r':
+ case 's':
+ case 'v':
+ case 'b':
+ ip->insn_opcode |= regno << 21;
+ break;
+ case 'd':
+ case 'G':
+ ip->insn_opcode |= regno << 11;
+ break;
+ case 'w':
+ case 't':
+ case 'E':
+ ip->insn_opcode |= regno << 16;
+ break;
+ case 'x':
+ /* This case exists because on the r3000 trunc
+ expands into a macro which requires a gp
+ register. On the r6000 or r4000 it is
+ assembled into a single instruction which
+ ignores the register. Thus the insn version
+ is MIPS_ISA2 and uses 'x', and the macro
+ version is MIPS_ISA1 and uses 't'. */
+ break;
+ case 'z':
+ /* This case is for the div instruction, which
+ acts differently if the destination argument
+ is $0. This only matches $0, and is checked
+ outside the switch. */
+ break;
+ case 'D':
+ /* Itbl operand; not yet implemented. FIXME ?? */
+ break;
+ /* What about all other operands like 'i', which
+ can be specified in the opcode table? */
+ }
+ lastregno = regno;
+ continue;
+ }
+ notreg:
+ switch (*args++)
+ {
+ case 'r':
+ case 'v':
+ ip->insn_opcode |= lastregno << 21;
+ continue;
+ case 'w':
+ ip->insn_opcode |= lastregno << 16;
+ continue;
+ }
+ break;
+
+ case 'D': /* floating point destination register */
+ case 'S': /* floating point source register */
+ case 'T': /* floating point target register */
+ case 'R': /* floating point source register */
+ case 'V':
+ case 'W':
+ s_reset = s;
+ if (s[0] == '$' && s[1] == 'f' && isdigit (s[2]))
+ {
+ s += 2;
+ regno = 0;
+ do
+ {
+ regno *= 10;
+ regno += *s - '0';
+ ++s;
+ }
+ while (isdigit (*s));
+
+ if (regno > 31)
+ as_bad (_("Invalid float register number (%d)"), regno);
+
+ if ((regno & 1) != 0
+ && mips_opts.isa < 3
+ && ! (strcmp (str, "mtc1") == 0
+ || strcmp (str, "mfc1") == 0
+ || strcmp (str, "lwc1") == 0
+ || strcmp (str, "swc1") == 0
+ || strcmp (str, "l.s") == 0
+ || strcmp (str, "s.s") == 0))
+ as_warn (_("Float register should be even, was %d"),
+ regno);
+
+ c = *args;
+ if (*s == ' ')
+ s++;
+ if (args[1] != *s)
+ {
+ if (c == 'V' || c == 'W')
+ {
+ regno = lastregno;
+ s = s_reset;
+ args++;
+ }
+ }
+ switch (c)
+ {
+ case 'D':
+ ip->insn_opcode |= regno << 6;
+ break;
+ case 'V':
+ case 'S':
+ ip->insn_opcode |= regno << 11;
+ break;
+ case 'W':
+ case 'T':
+ ip->insn_opcode |= regno << 16;
+ break;
+ case 'R':
+ ip->insn_opcode |= regno << 21;
+ break;
+ }
+ lastregno = regno;
+ continue;
+ }
+
+
+ switch (*args++)
+ {
+ case 'V':
+ ip->insn_opcode |= lastregno << 11;
+ continue;
+ case 'W':
+ ip->insn_opcode |= lastregno << 16;
+ continue;
+ }
+ break;
+
+ case 'I':
+ my_getExpression (&imm_expr, s);
+ if (imm_expr.X_op != O_big
+ && imm_expr.X_op != O_constant)
+ insn_error = _("absolute expression required");
+ s = expr_end;
+ continue;
+
+ case 'A':
+ my_getExpression (&offset_expr, s);
+ imm_reloc = BFD_RELOC_32;
+ s = expr_end;
+ continue;
+
+ case 'F':
+ case 'L':
+ case 'f':
+ case 'l':
+ {
+ int f64;
+ char *save_in;
+ char *err;
+ unsigned char temp[8];
+ int len;
+ unsigned int length;
+ segT seg;
+ subsegT subseg;
+ char *p;
+
+ /* These only appear as the last operand in an
+ instruction, and every instruction that accepts
+ them in any variant accepts them in all variants.
+ This means we don't have to worry about backing out
+ any changes if the instruction does not match.
+
+ The difference between them is the size of the
+ floating point constant and where it goes. For 'F'
+ and 'L' the constant is 64 bits; for 'f' and 'l' it
+ is 32 bits. Where the constant is placed is based
+ on how the MIPS assembler does things:
+ F -- .rdata
+ L -- .lit8
+ f -- immediate value
+ l -- .lit4
+
+ The .lit4 and .lit8 sections are only used if
+ permitted by the -G argument.
+
+ When generating embedded PIC code, we use the
+ .lit8 section but not the .lit4 section (we can do
+ .lit4 inline easily; we need to put .lit8
+ somewhere in the data segment, and using .lit8
+ permits the linker to eventually combine identical
+ .lit8 entries). */
+
+ f64 = *args == 'F' || *args == 'L';
+
+ save_in = input_line_pointer;
+ input_line_pointer = s;
+ err = md_atof (f64 ? 'd' : 'f', (char *) temp, &len);
+ length = len;
+ s = input_line_pointer;
+ input_line_pointer = save_in;
+ if (err != NULL && *err != '\0')
+ {
+ as_bad (_("Bad floating point constant: %s"), err);
+ memset (temp, '\0', sizeof temp);
+ length = f64 ? 8 : 4;
+ }
+
+ assert (length == (f64 ? 8 : 4));
+
+ if (*args == 'f'
+ || (*args == 'l'
+ && (! USE_GLOBAL_POINTER_OPT
+ || mips_pic == EMBEDDED_PIC
+ || g_switch_value < 4
+ || (temp[0] == 0 && temp[1] == 0)
+ || (temp[2] == 0 && temp[3] == 0))))
+ {
+ imm_expr.X_op = O_constant;
+ if (! target_big_endian)
+ imm_expr.X_add_number = bfd_getl32 (temp);
+ else
+ imm_expr.X_add_number = bfd_getb32 (temp);
+ }
+ else if (length > 4
+ && ((temp[0] == 0 && temp[1] == 0)
+ || (temp[2] == 0 && temp[3] == 0))
+ && ((temp[4] == 0 && temp[5] == 0)
+ || (temp[6] == 0 && temp[7] == 0)))
+ {
+ /* The value is simple enough to load with a
+ couple of instructions. In mips1 mode, set
+ imm_expr to the high order 32 bits and
+ offset_expr to the low order 32 bits.
+ Otherwise, set imm_expr to the entire 64 bit
+ constant. */
+ if (mips_opts.isa < 3)
+ {
+ imm_expr.X_op = O_constant;
+ offset_expr.X_op = O_constant;
+ if (! target_big_endian)
+ {
+ imm_expr.X_add_number = bfd_getl32 (temp + 4);
+ offset_expr.X_add_number = bfd_getl32 (temp);
+ }
+ else
+ {
+ imm_expr.X_add_number = bfd_getb32 (temp);
+ offset_expr.X_add_number = bfd_getb32 (temp + 4);
+ }
+ if (offset_expr.X_add_number == 0)
+ offset_expr.X_op = O_absent;
+ }
+ else if (sizeof (imm_expr.X_add_number) > 4)
+ {
+ imm_expr.X_op = O_constant;
+ if (! target_big_endian)
+ imm_expr.X_add_number = bfd_getl64 (temp);
+ else
+ imm_expr.X_add_number = bfd_getb64 (temp);
+ }
+ else
+ {
+ imm_expr.X_op = O_big;
+ imm_expr.X_add_number = 4;
+ if (! target_big_endian)
+ {
+ generic_bignum[0] = bfd_getl16 (temp);
+ generic_bignum[1] = bfd_getl16 (temp + 2);
+ generic_bignum[2] = bfd_getl16 (temp + 4);
+ generic_bignum[3] = bfd_getl16 (temp + 6);
+ }
+ else
+ {
+ generic_bignum[0] = bfd_getb16 (temp + 6);
+ generic_bignum[1] = bfd_getb16 (temp + 4);
+ generic_bignum[2] = bfd_getb16 (temp + 2);
+ generic_bignum[3] = bfd_getb16 (temp);
+ }
+ }
+ }
+ else
+ {
+ const char *newname;
+ segT new_seg;
+
+ /* Switch to the right section. */
+ seg = now_seg;
+ subseg = now_subseg;
+ switch (*args)
+ {
+ default: /* unused default case avoids warnings. */
+ case 'L':
+ newname = RDATA_SECTION_NAME;
+ if (USE_GLOBAL_POINTER_OPT && g_switch_value >= 8)
+ newname = ".lit8";
+ break;
+ case 'F':
+ newname = RDATA_SECTION_NAME;
+ break;
+ case 'l':
+ assert (!USE_GLOBAL_POINTER_OPT
+ || g_switch_value >= 4);
+ newname = ".lit4";
+ break;
+ }
+ new_seg = subseg_new (newname, (subsegT) 0);
+ if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
+ bfd_set_section_flags (stdoutput, new_seg,
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_READONLY
+ | SEC_DATA));
+ frag_align (*args == 'l' ? 2 : 3, 0, 0);
+ if (OUTPUT_FLAVOR == bfd_target_elf_flavour
+ && strcmp (TARGET_OS, "elf") != 0)
+ record_alignment (new_seg, 4);
+ else
+ record_alignment (new_seg, *args == 'l' ? 2 : 3);
+ if (seg == now_seg)
+ as_bad (_("Can't use floating point insn in this section"));
+
+ /* Set the argument to the current address in the
+ section. */
+ offset_expr.X_op = O_symbol;
+ offset_expr.X_add_symbol =
+ symbol_new ("L0\001", now_seg,
+ (valueT) frag_now_fix (), frag_now);
+ offset_expr.X_add_number = 0;
+
+ /* Put the floating point number into the section. */
+ p = frag_more ((int) length);
+ memcpy (p, temp, length);
+
+ /* Switch back to the original section. */
+ subseg_set (seg, subseg);
+ }
+ }
+ continue;
+
+ case 'i': /* 16 bit unsigned immediate */
+ case 'j': /* 16 bit signed immediate */
+ imm_reloc = BFD_RELOC_LO16;
+ c = my_getSmallExpression (&imm_expr, s);
+ if (c != '\0')
+ {
+ if (c != 'l')
+ {
+ if (imm_expr.X_op == O_constant)
+ imm_expr.X_add_number =
+ (imm_expr.X_add_number >> 16) & 0xffff;
+ else if (c == 'h')
+ {
+ imm_reloc = BFD_RELOC_HI16_S;
+ imm_unmatched_hi = true;
+ }
+ else
+ imm_reloc = BFD_RELOC_HI16;
+ }
+ else if (imm_expr.X_op == O_constant)
+ imm_expr.X_add_number &= 0xffff;
+ }
+ if (*args == 'i')
+ {
+ if ((c == '\0' && imm_expr.X_op != O_constant)
+ || ((imm_expr.X_add_number < 0
+ || imm_expr.X_add_number >= 0x10000)
+ && imm_expr.X_op == O_constant))
+ {
+ if (insn + 1 < &mips_opcodes[NUMOPCODES] &&
+ !strcmp (insn->name, insn[1].name))
+ break;
+ if (imm_expr.X_op != O_constant
+ && imm_expr.X_op != O_big)
+ insn_error = _("absolute expression required");
+ else
+ as_bad (_("16 bit expression not in range 0..65535"));
+ }
+ }
+ else
+ {
+ int more;
+ offsetT max;
+
+ /* The upper bound should be 0x8000, but
+ unfortunately the MIPS assembler accepts numbers
+ from 0x8000 to 0xffff and sign extends them, and
+ we want to be compatible. We only permit this
+ extended range for an instruction which does not
+ provide any further alternates, since those
+ alternates may handle other cases. People should
+ use the numbers they mean, rather than relying on
+ a mysterious sign extension. */
+ more = (insn + 1 < &mips_opcodes[NUMOPCODES] &&
+ strcmp (insn->name, insn[1].name) == 0);
+ if (more)
+ max = 0x8000;
+ else
+ max = 0x10000;
+ if ((c == '\0' && imm_expr.X_op != O_constant)
+ || ((imm_expr.X_add_number < -0x8000
+ || imm_expr.X_add_number >= max)
+ && imm_expr.X_op == O_constant)
+ || (more
+ && imm_expr.X_add_number < 0
+ && mips_opts.isa >= 3
+ && imm_expr.X_unsigned
+ && sizeof (imm_expr.X_add_number) <= 4))
+ {
+ if (more)
+ break;
+ if (imm_expr.X_op != O_constant
+ && imm_expr.X_op != O_big)
+ insn_error = _("absolute expression required");
+ else
+ as_bad (_("16 bit expression not in range -32768..32767"));
+ }
+ }
+ s = expr_end;
+ continue;
+
+ case 'o': /* 16 bit offset */
+ c = my_getSmallExpression (&offset_expr, s);
+
+ /* If this value won't fit into a 16 bit offset, then go
+ find a macro that will generate the 32 bit offset
+ code pattern. As a special hack, we accept the
+ difference of two local symbols as a constant. This
+ is required to suppose embedded PIC switches, which
+ use an instruction which looks like
+ lw $4,$L12-$LS12($4)
+ The problem with handling this in a more general
+ fashion is that the macro function doesn't expect to
+ see anything which can be handled in a single
+ constant instruction. */
+ if (c == 0
+ && (offset_expr.X_op != O_constant
+ || offset_expr.X_add_number >= 0x8000
+ || offset_expr.X_add_number < -0x8000)
+ && (mips_pic != EMBEDDED_PIC
+ || offset_expr.X_op != O_subtract
+ || now_seg != text_section
+ || (S_GET_SEGMENT (offset_expr.X_op_symbol)
+ != text_section)))
+ break;
+
+ if (c == 'h' || c == 'H')
+ {
+ if (offset_expr.X_op != O_constant)
+ break;
+ offset_expr.X_add_number =
+ (offset_expr.X_add_number >> 16) & 0xffff;
+ }
+ offset_reloc = BFD_RELOC_LO16;
+ s = expr_end;
+ continue;
+
+ case 'p': /* pc relative offset */
+ offset_reloc = BFD_RELOC_16_PCREL_S2;
+ my_getExpression (&offset_expr, s);
+ s = expr_end;
+ continue;
+
+ case 'u': /* upper 16 bits */
+ c = my_getSmallExpression (&imm_expr, s);
+ imm_reloc = BFD_RELOC_LO16;
+ if (c)
+ {
+ if (c != 'l')
+ {
+ if (imm_expr.X_op == O_constant)
+ imm_expr.X_add_number =
+ (imm_expr.X_add_number >> 16) & 0xffff;
+ else if (c == 'h')
+ {
+ imm_reloc = BFD_RELOC_HI16_S;
+ imm_unmatched_hi = true;
+ }
+ else
+ imm_reloc = BFD_RELOC_HI16;
+ }
+ else if (imm_expr.X_op == O_constant)
+ imm_expr.X_add_number &= 0xffff;
+ }
+ if (imm_expr.X_op == O_constant
+ && (imm_expr.X_add_number < 0
+ || imm_expr.X_add_number >= 0x10000))
+ as_bad (_("lui expression not in range 0..65535"));
+ s = expr_end;
+ continue;
+
+ case 'a': /* 26 bit address */
+ my_getExpression (&offset_expr, s);
+ s = expr_end;
+ offset_reloc = BFD_RELOC_MIPS_JMP;
+ continue;
+
+ case 'N': /* 3 bit branch condition code */
+ case 'M': /* 3 bit compare condition code */
+ if (strncmp (s, "$fcc", 4) != 0)
+ break;
+ s += 4;
+ regno = 0;
+ do
+ {
+ regno *= 10;
+ regno += *s - '0';
+ ++s;
+ }
+ while (isdigit (*s));
+ if (regno > 7)
+ as_bad (_("invalid condition code register $fcc%d"), regno);
+ if (*args == 'N')
+ ip->insn_opcode |= regno << OP_SH_BCC;
+ else
+ ip->insn_opcode |= regno << OP_SH_CCC;
+ continue;
+
+ default:
+ as_bad (_("bad char = '%c'\n"), *args);
+ internalError ();
+ }
+ break;
+ }
+ /* Args don't match. */
+ if (insn + 1 < &mips_opcodes[NUMOPCODES] &&
+ !strcmp (insn->name, insn[1].name))
+ {
+ ++insn;
+ s = argsStart;
+ continue;
+ }
+ insn_error = _("illegal operands");
+ return;
+ }
+}
+
+/* This routine assembles an instruction into its binary format when
+ assembling for the mips16. As a side effect, it sets one of the
+ global variables imm_reloc or offset_reloc to the type of
+ relocation to do if one of the operands is an address expression.
+ It also sets mips16_small and mips16_ext if the user explicitly
+ requested a small or extended instruction. */
+
+static void
+mips16_ip (str, ip)
+ char *str;
+ struct mips_cl_insn *ip;
+{
+ char *s;
+ const char *args;
+ struct mips_opcode *insn;
+ char *argsstart;
+ unsigned int regno;
+ unsigned int lastregno = 0;
+ char *s_reset;
+
+ insn_error = NULL;
+
+ mips16_small = false;
+ mips16_ext = false;
+
+ for (s = str; islower (*s); ++s)
+ ;
+ switch (*s)
+ {
+ case '\0':
+ break;
+
+ case ' ':
+ *s++ = '\0';
+ break;
+
+ case '.':
+ if (s[1] == 't' && s[2] == ' ')
+ {
+ *s = '\0';
+ mips16_small = true;
+ s += 3;
+ break;
+ }
+ else if (s[1] == 'e' && s[2] == ' ')
+ {
+ *s = '\0';
+ mips16_ext = true;
+ s += 3;
+ break;
+ }
+ /* Fall through. */
+ default:
+ insn_error = _("unknown opcode");
+ return;
+ }
+
+ if (mips_opts.noautoextend && ! mips16_ext)
+ mips16_small = true;
+
+ if ((insn = (struct mips_opcode *) hash_find (mips16_op_hash, str)) == NULL)
+ {
+ insn_error = _("unrecognized opcode");
+ return;
+ }
+
+ argsstart = s;
+ for (;;)
+ {
+ assert (strcmp (insn->name, str) == 0);
+
+ ip->insn_mo = insn;
+ ip->insn_opcode = insn->match;
+ ip->use_extend = false;
+ imm_expr.X_op = O_absent;
+ imm_reloc = BFD_RELOC_UNUSED;
+ offset_expr.X_op = O_absent;
+ offset_reloc = BFD_RELOC_UNUSED;
+ for (args = insn->args; 1; ++args)
+ {
+ int c;
+
+ if (*s == ' ')
+ ++s;
+
+ /* In this switch statement we call break if we did not find
+ a match, continue if we did find a match, or return if we
+ are done. */
+
+ c = *args;
+ switch (c)
+ {
+ case '\0':
+ if (*s == '\0')
+ {
+ /* Stuff the immediate value in now, if we can. */
+ if (imm_expr.X_op == O_constant
+ && imm_reloc > BFD_RELOC_UNUSED
+ && insn->pinfo != INSN_MACRO)
+ {
+ mips16_immed ((char *) NULL, 0,
+ imm_reloc - BFD_RELOC_UNUSED,
+ imm_expr.X_add_number, true, mips16_small,
+ mips16_ext, &ip->insn_opcode,
+ &ip->use_extend, &ip->extend);
+ imm_expr.X_op = O_absent;
+ imm_reloc = BFD_RELOC_UNUSED;
+ }
+
+ return;
+ }
+ break;
+
+ case ',':
+ if (*s++ == c)
+ continue;
+ s--;
+ switch (*++args)
+ {
+ case 'v':
+ ip->insn_opcode |= lastregno << MIPS16OP_SH_RX;
+ continue;
+ case 'w':
+ ip->insn_opcode |= lastregno << MIPS16OP_SH_RY;
+ continue;
+ }
+ break;
+
+ case '(':
+ case ')':
+ if (*s++ == c)
+ continue;
+ break;
+
+ case 'v':
+ case 'w':
+ if (s[0] != '$')
+ {
+ if (c == 'v')
+ ip->insn_opcode |= lastregno << MIPS16OP_SH_RX;
+ else
+ ip->insn_opcode |= lastregno << MIPS16OP_SH_RY;
+ ++args;
+ continue;
+ }
+ /* Fall through. */
+ case 'x':
+ case 'y':
+ case 'z':
+ case 'Z':
+ case '0':
+ case 'S':
+ case 'R':
+ case 'X':
+ case 'Y':
+ if (s[0] != '$')
+ break;
+ s_reset = s;
+ if (isdigit (s[1]))
+ {
+ ++s;
+ regno = 0;
+ do
+ {
+ regno *= 10;
+ regno += *s - '0';
+ ++s;
+ }
+ while (isdigit (*s));
+ if (regno > 31)
+ {
+ as_bad (_("invalid register number (%d)"), regno);
+ regno = 2;
+ }
+ }
+ else
+ {
+ if (s[1] == 'f' && s[2] == 'p')
+ {
+ s += 3;
+ regno = FP;
+ }
+ else if (s[1] == 's' && s[2] == 'p')
+ {
+ s += 3;
+ regno = SP;
+ }
+ else if (s[1] == 'g' && s[2] == 'p')
+ {
+ s += 3;
+ regno = GP;
+ }
+ else if (s[1] == 'a' && s[2] == 't')
+ {
+ s += 3;
+ regno = AT;
+ }
+ else if (s[1] == 'k' && s[2] == 't' && s[3] == '0')
+ {
+ s += 4;
+ regno = KT0;
+ }
+ else if (s[1] == 'k' && s[2] == 't' && s[3] == '1')
+ {
+ s += 4;
+ regno = KT1;
+ }
+ else
+ break;
+ }
+
+ if (*s == ' ')
+ ++s;
+ if (args[1] != *s)
+ {
+ if (c == 'v' || c == 'w')
+ {
+ regno = mips16_to_32_reg_map[lastregno];
+ s = s_reset;
+ args++;
+ }
+ }
+
+ switch (c)
+ {
+ case 'x':
+ case 'y':
+ case 'z':
+ case 'v':
+ case 'w':
+ case 'Z':
+ regno = mips32_to_16_reg_map[regno];
+ break;
+
+ case '0':
+ if (regno != 0)
+ regno = ILLEGAL_REG;
+ break;
+
+ case 'S':
+ if (regno != SP)
+ regno = ILLEGAL_REG;
+ break;
+
+ case 'R':
+ if (regno != RA)
+ regno = ILLEGAL_REG;
+ break;
+
+ case 'X':
+ case 'Y':
+ if (regno == AT && ! mips_opts.noat)
+ as_warn (_("used $at without \".set noat\""));
+ break;
+
+ default:
+ internalError ();
+ }
+
+ if (regno == ILLEGAL_REG)
+ break;
+
+ switch (c)
+ {
+ case 'x':
+ case 'v':
+ ip->insn_opcode |= regno << MIPS16OP_SH_RX;
+ break;
+ case 'y':
+ case 'w':
+ ip->insn_opcode |= regno << MIPS16OP_SH_RY;
+ break;
+ case 'z':
+ ip->insn_opcode |= regno << MIPS16OP_SH_RZ;
+ break;
+ case 'Z':
+ ip->insn_opcode |= regno << MIPS16OP_SH_MOVE32Z;
+ case '0':
+ case 'S':
+ case 'R':
+ break;
+ case 'X':
+ ip->insn_opcode |= regno << MIPS16OP_SH_REGR32;
+ break;
+ case 'Y':
+ regno = ((regno & 7) << 2) | ((regno & 0x18) >> 3);
+ ip->insn_opcode |= regno << MIPS16OP_SH_REG32R;
+ break;
+ default:
+ internalError ();
+ }
+
+ lastregno = regno;
+ continue;
+
+ case 'P':
+ if (strncmp (s, "$pc", 3) == 0)
+ {
+ s += 3;
+ continue;
+ }
+ break;
+
+ case '<':
+ case '>':
+ case '[':
+ case ']':
+ case '4':
+ case '5':
+ case 'H':
+ case 'W':
+ case 'D':
+ case 'j':
+ case '8':
+ case 'V':
+ case 'C':
+ case 'U':
+ case 'k':
+ case 'K':
+ if (s[0] == '%'
+ && strncmp (s + 1, "gprel(", sizeof "gprel(" - 1) == 0)
+ {
+ /* This is %gprel(SYMBOL). We need to read SYMBOL,
+ and generate the appropriate reloc. If the text
+ inside %gprel is not a symbol name with an
+ optional offset, then we generate a normal reloc
+ and will probably fail later. */
+ my_getExpression (&imm_expr, s + sizeof "%gprel" - 1);
+ if (imm_expr.X_op == O_symbol)
+ {
+ mips16_ext = true;
+ imm_reloc = BFD_RELOC_MIPS16_GPREL;
+ s = expr_end;
+ ip->use_extend = true;
+ ip->extend = 0;
+ continue;
+ }
+ }
+ else
+ {
+ /* Just pick up a normal expression. */
+ my_getExpression (&imm_expr, s);
+ }
+
+ if (imm_expr.X_op == O_register)
+ {
+ /* What we thought was an expression turned out to
+ be a register. */
+
+ if (s[0] == '(' && args[1] == '(')
+ {
+ /* It looks like the expression was omitted
+ before a register indirection, which means
+ that the expression is implicitly zero. We
+ still set up imm_expr, so that we handle
+ explicit extensions correctly. */
+ imm_expr.X_op = O_constant;
+ imm_expr.X_add_number = 0;
+ imm_reloc = (int) BFD_RELOC_UNUSED + c;
+ continue;
+ }
+
+ break;
+ }
+
+ /* We need to relax this instruction. */
+ imm_reloc = (int) BFD_RELOC_UNUSED + c;
+ s = expr_end;
+ continue;
+
+ case 'p':
+ case 'q':
+ case 'A':
+ case 'B':
+ case 'E':
+ /* We use offset_reloc rather than imm_reloc for the PC
+ relative operands. This lets macros with both
+ immediate and address operands work correctly. */
+ my_getExpression (&offset_expr, s);
+
+ if (offset_expr.X_op == O_register)
+ break;
+
+ /* We need to relax this instruction. */
+ offset_reloc = (int) BFD_RELOC_UNUSED + c;
+ s = expr_end;
+ continue;
+
+ case '6': /* break code */
+ my_getExpression (&imm_expr, s);
+ check_absolute_expr (ip, &imm_expr);
+ if ((unsigned long) imm_expr.X_add_number > 63)
+ {
+ as_warn (_("Invalid value for `%s' (%lu)"),
+ ip->insn_mo->name,
+ (unsigned long) imm_expr.X_add_number);
+ imm_expr.X_add_number &= 0x3f;
+ }
+ ip->insn_opcode |= imm_expr.X_add_number << MIPS16OP_SH_IMM6;
+ imm_expr.X_op = O_absent;
+ s = expr_end;
+ continue;
+
+ case 'a': /* 26 bit address */
+ my_getExpression (&offset_expr, s);
+ s = expr_end;
+ offset_reloc = BFD_RELOC_MIPS16_JMP;
+ ip->insn_opcode <<= 16;
+ continue;
+
+ case 'l': /* register list for entry macro */
+ case 'L': /* register list for exit macro */
+ {
+ int mask;
+
+ if (c == 'l')
+ mask = 0;
+ else
+ mask = 7 << 3;
+ while (*s != '\0')
+ {
+ int freg, reg1, reg2;
+
+ while (*s == ' ' || *s == ',')
+ ++s;
+ if (*s != '$')
+ {
+ as_bad (_("can't parse register list"));
+ break;
+ }
+ ++s;
+ if (*s != 'f')
+ freg = 0;
+ else
+ {
+ freg = 1;
+ ++s;
+ }
+ reg1 = 0;
+ while (isdigit (*s))
+ {
+ reg1 *= 10;
+ reg1 += *s - '0';
+ ++s;
+ }
+ if (*s == ' ')
+ ++s;
+ if (*s != '-')
+ reg2 = reg1;
+ else
+ {
+ ++s;
+ if (*s != '$')
+ break;
+ ++s;
+ if (freg)
+ {
+ if (*s == 'f')
+ ++s;
+ else
+ {
+ as_bad (_("invalid register list"));
+ break;
+ }
+ }
+ reg2 = 0;
+ while (isdigit (*s))
+ {
+ reg2 *= 10;
+ reg2 += *s - '0';
+ ++s;
+ }
+ }
+ if (freg && reg1 == 0 && reg2 == 0 && c == 'L')
+ {
+ mask &= ~ (7 << 3);
+ mask |= 5 << 3;
+ }
+ else if (freg && reg1 == 0 && reg2 == 1 && c == 'L')
+ {
+ mask &= ~ (7 << 3);
+ mask |= 6 << 3;
+ }
+ else if (reg1 == 4 && reg2 >= 4 && reg2 <= 7 && c != 'L')
+ mask |= (reg2 - 3) << 3;
+ else if (reg1 == 16 && reg2 >= 16 && reg2 <= 17)
+ mask |= (reg2 - 15) << 1;
+ else if (reg1 == 31 && reg2 == 31)
+ mask |= 1;
+ else
+ {
+ as_bad (_("invalid register list"));
+ break;
+ }
+ }
+ /* The mask is filled in in the opcode table for the
+ benefit of the disassembler. We remove it before
+ applying the actual mask. */
+ ip->insn_opcode &= ~ ((7 << 3) << MIPS16OP_SH_IMM6);
+ ip->insn_opcode |= mask << MIPS16OP_SH_IMM6;
+ }
+ continue;
+
+ case 'e': /* extend code */
+ my_getExpression (&imm_expr, s);
+ check_absolute_expr (ip, &imm_expr);
+ if ((unsigned long) imm_expr.X_add_number > 0x7ff)
+ {
+ as_warn (_("Invalid value for `%s' (%lu)"),
+ ip->insn_mo->name,
+ (unsigned long) imm_expr.X_add_number);
+ imm_expr.X_add_number &= 0x7ff;
+ }
+ ip->insn_opcode |= imm_expr.X_add_number;
+ imm_expr.X_op = O_absent;
+ s = expr_end;
+ continue;
+
+ default:
+ internalError ();
+ }
+ break;
+ }
+
+ /* Args don't match. */
+ if (insn + 1 < &mips16_opcodes[bfd_mips16_num_opcodes] &&
+ strcmp (insn->name, insn[1].name) == 0)
+ {
+ ++insn;
+ s = argsstart;
+ continue;
+ }
+
+ insn_error = _("illegal operands");
+
+ return;
+ }
+}
+
+/* This structure holds information we know about a mips16 immediate
+ argument type. */
+
+struct mips16_immed_operand
+{
+ /* The type code used in the argument string in the opcode table. */
+ int type;
+ /* The number of bits in the short form of the opcode. */
+ int nbits;
+ /* The number of bits in the extended form of the opcode. */
+ int extbits;
+ /* The amount by which the short form is shifted when it is used;
+ for example, the sw instruction has a shift count of 2. */
+ int shift;
+ /* The amount by which the short form is shifted when it is stored
+ into the instruction code. */
+ int op_shift;
+ /* Non-zero if the short form is unsigned. */
+ int unsp;
+ /* Non-zero if the extended form is unsigned. */
+ int extu;
+ /* Non-zero if the value is PC relative. */
+ int pcrel;
+};
+
+/* The mips16 immediate operand types. */
+
+static const struct mips16_immed_operand mips16_immed_operands[] =
+{
+ { '<', 3, 5, 0, MIPS16OP_SH_RZ, 1, 1, 0 },
+ { '>', 3, 5, 0, MIPS16OP_SH_RX, 1, 1, 0 },
+ { '[', 3, 6, 0, MIPS16OP_SH_RZ, 1, 1, 0 },
+ { ']', 3, 6, 0, MIPS16OP_SH_RX, 1, 1, 0 },
+ { '4', 4, 15, 0, MIPS16OP_SH_IMM4, 0, 0, 0 },
+ { '5', 5, 16, 0, MIPS16OP_SH_IMM5, 1, 0, 0 },
+ { 'H', 5, 16, 1, MIPS16OP_SH_IMM5, 1, 0, 0 },
+ { 'W', 5, 16, 2, MIPS16OP_SH_IMM5, 1, 0, 0 },
+ { 'D', 5, 16, 3, MIPS16OP_SH_IMM5, 1, 0, 0 },
+ { 'j', 5, 16, 0, MIPS16OP_SH_IMM5, 0, 0, 0 },
+ { '8', 8, 16, 0, MIPS16OP_SH_IMM8, 1, 0, 0 },
+ { 'V', 8, 16, 2, MIPS16OP_SH_IMM8, 1, 0, 0 },
+ { 'C', 8, 16, 3, MIPS16OP_SH_IMM8, 1, 0, 0 },
+ { 'U', 8, 16, 0, MIPS16OP_SH_IMM8, 1, 1, 0 },
+ { 'k', 8, 16, 0, MIPS16OP_SH_IMM8, 0, 0, 0 },
+ { 'K', 8, 16, 3, MIPS16OP_SH_IMM8, 0, 0, 0 },
+ { 'p', 8, 16, 0, MIPS16OP_SH_IMM8, 0, 0, 1 },
+ { 'q', 11, 16, 0, MIPS16OP_SH_IMM8, 0, 0, 1 },
+ { 'A', 8, 16, 2, MIPS16OP_SH_IMM8, 1, 0, 1 },
+ { 'B', 5, 16, 3, MIPS16OP_SH_IMM5, 1, 0, 1 },
+ { 'E', 5, 16, 2, MIPS16OP_SH_IMM5, 1, 0, 1 }
+};
+
+#define MIPS16_NUM_IMMED \
+ (sizeof mips16_immed_operands / sizeof mips16_immed_operands[0])
+
+/* Handle a mips16 instruction with an immediate value. This or's the
+ small immediate value into *INSN. It sets *USE_EXTEND to indicate
+ whether an extended value is needed; if one is needed, it sets
+ *EXTEND to the value. The argument type is TYPE. The value is VAL.
+ If SMALL is true, an unextended opcode was explicitly requested.
+ If EXT is true, an extended opcode was explicitly requested. If
+ WARN is true, warn if EXT does not match reality. */
+
+static void
+mips16_immed (file, line, type, val, warn, small, ext, insn, use_extend,
+ extend)
+ char *file;
+ unsigned int line;
+ int type;
+ offsetT val;
+ boolean warn;
+ boolean small;
+ boolean ext;
+ unsigned long *insn;
+ boolean *use_extend;
+ unsigned short *extend;
+{
+ register const struct mips16_immed_operand *op;
+ int mintiny, maxtiny;
+ boolean needext;
+
+ op = mips16_immed_operands;
+ while (op->type != type)
+ {
+ ++op;
+ assert (op < mips16_immed_operands + MIPS16_NUM_IMMED);
+ }
+
+ if (op->unsp)
+ {
+ if (type == '<' || type == '>' || type == '[' || type == ']')
+ {
+ mintiny = 1;
+ maxtiny = 1 << op->nbits;
+ }
+ else
+ {
+ mintiny = 0;
+ maxtiny = (1 << op->nbits) - 1;
+ }
+ }
+ else
+ {
+ mintiny = - (1 << (op->nbits - 1));
+ maxtiny = (1 << (op->nbits - 1)) - 1;
+ }
+
+ /* Branch offsets have an implicit 0 in the lowest bit. */
+ if (type == 'p' || type == 'q')
+ val /= 2;
+
+ if ((val & ((1 << op->shift) - 1)) != 0
+ || val < (mintiny << op->shift)
+ || val > (maxtiny << op->shift))
+ needext = true;
+ else
+ needext = false;
+
+ if (warn && ext && ! needext)
+ as_warn_where (file, line, _("extended operand requested but not required"));
+ if (small && needext)
+ as_bad_where (file, line, _("invalid unextended operand value"));
+
+ if (small || (! ext && ! needext))
+ {
+ int insnval;
+
+ *use_extend = false;
+ insnval = ((val >> op->shift) & ((1 << op->nbits) - 1));
+ insnval <<= op->op_shift;
+ *insn |= insnval;
+ }
+ else
+ {
+ long minext, maxext;
+ int extval;
+
+ if (op->extu)
+ {
+ minext = 0;
+ maxext = (1 << op->extbits) - 1;
+ }
+ else
+ {
+ minext = - (1 << (op->extbits - 1));
+ maxext = (1 << (op->extbits - 1)) - 1;
+ }
+ if (val < minext || val > maxext)
+ as_bad_where (file, line,
+ _("operand value out of range for instruction"));
+
+ *use_extend = true;
+ if (op->extbits == 16)
+ {
+ extval = ((val >> 11) & 0x1f) | (val & 0x7e0);
+ val &= 0x1f;
+ }
+ else if (op->extbits == 15)
+ {
+ extval = ((val >> 11) & 0xf) | (val & 0x7f0);
+ val &= 0xf;
+ }
+ else
+ {
+ extval = ((val & 0x1f) << 6) | (val & 0x20);
+ val = 0;
+ }
+
+ *extend = (unsigned short) extval;
+ *insn |= val;
+ }
+}
+
+#define LP '('
+#define RP ')'
+
+static int
+my_getSmallExpression (ep, str)
+ expressionS *ep;
+ char *str;
+{
+ char *sp;
+ int c = 0;
+
+ if (*str == ' ')
+ str++;
+ if (*str == LP
+ || (*str == '%' &&
+ ((str[1] == 'h' && str[2] == 'i')
+ || (str[1] == 'H' && str[2] == 'I')
+ || (str[1] == 'l' && str[2] == 'o'))
+ && str[3] == LP))
+ {
+ if (*str == LP)
+ c = 0;
+ else
+ {
+ c = str[1];
+ str += 3;
+ }
+
+ /*
+ * A small expression may be followed by a base register.
+ * Scan to the end of this operand, and then back over a possible
+ * base register. Then scan the small expression up to that
+ * point. (Based on code in sparc.c...)
+ */
+ for (sp = str; *sp && *sp != ','; sp++)
+ ;
+ if (sp - 4 >= str && sp[-1] == RP)
+ {
+ if (isdigit (sp[-2]))
+ {
+ for (sp -= 3; sp >= str && isdigit (*sp); sp--)
+ ;
+ if (*sp == '$' && sp > str && sp[-1] == LP)
+ {
+ sp--;
+ goto do_it;
+ }
+ }
+ else if (sp - 5 >= str
+ && sp[-5] == LP
+ && sp[-4] == '$'
+ && ((sp[-3] == 'f' && sp[-2] == 'p')
+ || (sp[-3] == 's' && sp[-2] == 'p')
+ || (sp[-3] == 'g' && sp[-2] == 'p')
+ || (sp[-3] == 'a' && sp[-2] == 't')))
+ {
+ sp -= 5;
+ do_it:
+ if (sp == str)
+ {
+ /* no expression means zero offset */
+ if (c)
+ {
+ /* %xx(reg) is an error */
+ ep->X_op = O_absent;
+ expr_end = str - 3;
+ }
+ else
+ {
+ ep->X_op = O_constant;
+ expr_end = sp;
+ }
+ ep->X_add_symbol = NULL;
+ ep->X_op_symbol = NULL;
+ ep->X_add_number = 0;
+ }
+ else
+ {
+ *sp = '\0';
+ my_getExpression (ep, str);
+ *sp = LP;
+ }
+ return c;
+ }
+ }
+ }
+ my_getExpression (ep, str);
+ return c; /* => %hi or %lo encountered */
+}
+
+static void
+my_getExpression (ep, str)
+ expressionS *ep;
+ char *str;
+{
+ char *save_in;
+
+ save_in = input_line_pointer;
+ input_line_pointer = str;
+ expression (ep);
+ expr_end = input_line_pointer;
+ input_line_pointer = save_in;
+
+ /* If we are in mips16 mode, and this is an expression based on `.',
+ then we bump the value of the symbol by 1 since that is how other
+ text symbols are handled. We don't bother to handle complex
+ expressions, just `.' plus or minus a constant. */
+ if (mips_opts.mips16
+ && ep->X_op == O_symbol
+ && strcmp (S_GET_NAME (ep->X_add_symbol), FAKE_LABEL_NAME) == 0
+ && S_GET_SEGMENT (ep->X_add_symbol) == now_seg
+ && ep->X_add_symbol->sy_frag == frag_now
+ && ep->X_add_symbol->sy_value.X_op == O_constant
+ && ep->X_add_symbol->sy_value.X_add_number == frag_now_fix ())
+ ++ep->X_add_symbol->sy_value.X_add_number;
+}
+
+/* Turn a string in input_line_pointer into a floating point constant
+ of type type, and store the appropriate bytes in *litP. The number
+ of LITTLENUMS emitted is stored in *sizeP . An error message is
+ returned, or NULL on OK. */
+
+char *
+md_atof (type, litP, sizeP)
+ int type;
+ char *litP;
+ int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[4];
+ char *t;
+ int i;
+
+ switch (type)
+ {
+ case 'f':
+ prec = 2;
+ break;
+
+ case 'd':
+ prec = 4;
+ break;
+
+ default:
+ *sizeP = 0;
+ return _("bad call to md_atof");
+ }
+
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+
+ *sizeP = prec * 2;
+
+ if (! target_big_endian)
+ {
+ for (i = prec - 1; i >= 0; i--)
+ {
+ md_number_to_chars (litP, (valueT) words[i], 2);
+ litP += 2;
+ }
+ }
+ else
+ {
+ for (i = 0; i < prec; i++)
+ {
+ md_number_to_chars (litP, (valueT) words[i], 2);
+ litP += 2;
+ }
+ }
+
+ return NULL;
+}
+
+void
+md_number_to_chars (buf, val, n)
+ char *buf;
+ valueT val;
+ int n;
+{
+ if (target_big_endian)
+ number_to_chars_bigendian (buf, val, n);
+ else
+ number_to_chars_littleendian (buf, val, n);
+}
+
+CONST char *md_shortopts = "O::g::G:";
+
+struct option md_longopts[] = {
+#define OPTION_MIPS1 (OPTION_MD_BASE + 1)
+ {"mips0", no_argument, NULL, OPTION_MIPS1},
+ {"mips1", no_argument, NULL, OPTION_MIPS1},
+#define OPTION_MIPS2 (OPTION_MD_BASE + 2)
+ {"mips2", no_argument, NULL, OPTION_MIPS2},
+#define OPTION_MIPS3 (OPTION_MD_BASE + 3)
+ {"mips3", no_argument, NULL, OPTION_MIPS3},
+#define OPTION_MIPS4 (OPTION_MD_BASE + 4)
+ {"mips4", no_argument, NULL, OPTION_MIPS4},
+#define OPTION_MCPU (OPTION_MD_BASE + 5)
+ {"mcpu", required_argument, NULL, OPTION_MCPU},
+#define OPTION_MEMBEDDED_PIC (OPTION_MD_BASE + 6)
+ {"membedded-pic", no_argument, NULL, OPTION_MEMBEDDED_PIC},
+#define OPTION_TRAP (OPTION_MD_BASE + 9)
+ {"trap", no_argument, NULL, OPTION_TRAP},
+ {"no-break", no_argument, NULL, OPTION_TRAP},
+#define OPTION_BREAK (OPTION_MD_BASE + 10)
+ {"break", no_argument, NULL, OPTION_BREAK},
+ {"no-trap", no_argument, NULL, OPTION_BREAK},
+#define OPTION_EB (OPTION_MD_BASE + 11)
+ {"EB", no_argument, NULL, OPTION_EB},
+#define OPTION_EL (OPTION_MD_BASE + 12)
+ {"EL", no_argument, NULL, OPTION_EL},
+#define OPTION_M4650 (OPTION_MD_BASE + 13)
+ {"m4650", no_argument, NULL, OPTION_M4650},
+#define OPTION_NO_M4650 (OPTION_MD_BASE + 14)
+ {"no-m4650", no_argument, NULL, OPTION_NO_M4650},
+#define OPTION_M4010 (OPTION_MD_BASE + 15)
+ {"m4010", no_argument, NULL, OPTION_M4010},
+#define OPTION_NO_M4010 (OPTION_MD_BASE + 16)
+ {"no-m4010", no_argument, NULL, OPTION_NO_M4010},
+#define OPTION_M4100 (OPTION_MD_BASE + 17)
+ {"m4100", no_argument, NULL, OPTION_M4100},
+#define OPTION_NO_M4100 (OPTION_MD_BASE + 18)
+ {"no-m4100", no_argument, NULL, OPTION_NO_M4100},
+#define OPTION_MIPS16 (OPTION_MD_BASE + 22)
+ {"mips16", no_argument, NULL, OPTION_MIPS16},
+#define OPTION_NO_MIPS16 (OPTION_MD_BASE + 23)
+ {"no-mips16", no_argument, NULL, OPTION_NO_MIPS16},
+#define OPTION_M3900 (OPTION_MD_BASE + 26)
+ {"m3900", no_argument, NULL, OPTION_M3900},
+#define OPTION_NO_M3900 (OPTION_MD_BASE + 27)
+ {"no-m3900", no_argument, NULL, OPTION_NO_M3900},
+
+
+#define OPTION_MABI (OPTION_MD_BASE + 38)
+ {"mabi", required_argument, NULL, OPTION_MABI},
+
+#define OPTION_CALL_SHARED (OPTION_MD_BASE + 7)
+#define OPTION_NON_SHARED (OPTION_MD_BASE + 8)
+#define OPTION_XGOT (OPTION_MD_BASE + 19)
+#define OPTION_32 (OPTION_MD_BASE + 20)
+#define OPTION_64 (OPTION_MD_BASE + 21)
+#ifdef OBJ_ELF
+ {"KPIC", no_argument, NULL, OPTION_CALL_SHARED},
+ {"xgot", no_argument, NULL, OPTION_XGOT},
+ {"call_shared", no_argument, NULL, OPTION_CALL_SHARED},
+ {"non_shared", no_argument, NULL, OPTION_NON_SHARED},
+ {"32", no_argument, NULL, OPTION_32},
+ {"64", no_argument, NULL, OPTION_64},
+#endif
+
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof(md_longopts);
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ switch (c)
+ {
+ case OPTION_TRAP:
+ mips_trap = 1;
+ break;
+
+ case OPTION_BREAK:
+ mips_trap = 0;
+ break;
+
+ case OPTION_EB:
+ target_big_endian = 1;
+ break;
+
+ case OPTION_EL:
+ target_big_endian = 0;
+ break;
+
+ case 'O':
+ if (arg && arg[1] == '0')
+ mips_optimize = 1;
+ else
+ mips_optimize = 2;
+ break;
+
+ case 'g':
+ if (arg == NULL)
+ mips_debug = 2;
+ else
+ mips_debug = atoi (arg);
+ /* When the MIPS assembler sees -g or -g2, it does not do
+ optimizations which limit full symbolic debugging. We take
+ that to be equivalent to -O0. */
+ if (mips_debug == 2)
+ mips_optimize = 1;
+ break;
+
+ case OPTION_MIPS1:
+ mips_opts.isa = 1;
+ break;
+
+ case OPTION_MIPS2:
+ mips_opts.isa = 2;
+ break;
+
+ case OPTION_MIPS3:
+ mips_opts.isa = 3;
+ break;
+
+ case OPTION_MIPS4:
+ mips_opts.isa = 4;
+ break;
+
+ case OPTION_MCPU:
+ {
+ char *p;
+
+ /* Identify the processor type */
+ p = arg;
+ if (strcmp (p, "default") == 0
+ || strcmp (p, "DEFAULT") == 0)
+ mips_cpu = -1;
+ else
+ {
+ int sv = 0;
+
+ /* We need to cope with the various "vr" prefixes for the 4300
+ processor. */
+ if (*p == 'v' || *p == 'V')
+ {
+ sv = 1;
+ p++;
+ }
+
+ if (*p == 'r' || *p == 'R')
+ p++;
+
+ mips_cpu = -1;
+ switch (*p)
+ {
+ case '1':
+ if (strcmp (p, "10000") == 0
+ || strcmp (p, "10k") == 0
+ || strcmp (p, "10K") == 0)
+ mips_cpu = 10000;
+ break;
+
+ case '2':
+ if (strcmp (p, "2000") == 0
+ || strcmp (p, "2k") == 0
+ || strcmp (p, "2K") == 0)
+ mips_cpu = 2000;
+ break;
+
+ case '3':
+ if (strcmp (p, "3000") == 0
+ || strcmp (p, "3k") == 0
+ || strcmp (p, "3K") == 0)
+ mips_cpu = 3000;
+ else if (strcmp (p, "3900") == 0)
+ mips_cpu = 3900;
+ break;
+
+ case '4':
+ if (strcmp (p, "4000") == 0
+ || strcmp (p, "4k") == 0
+ || strcmp (p, "4K") == 0)
+ mips_cpu = 4000;
+ else if (strcmp (p, "4100") == 0)
+ mips_cpu = 4100;
+ else if (strcmp (p, "4111") == 0)
+ mips_cpu = 4111;
+ else if (strcmp (p, "4300") == 0)
+ mips_cpu = 4300;
+ else if (strcmp (p, "4400") == 0)
+ mips_cpu = 4400;
+ else if (strcmp (p, "4600") == 0)
+ mips_cpu = 4600;
+ else if (strcmp (p, "4650") == 0)
+ mips_cpu = 4650;
+ else if (strcmp (p, "4010") == 0)
+ mips_cpu = 4010;
+ break;
+
+ case '5':
+ if (strcmp (p, "5000") == 0
+ || strcmp (p, "5k") == 0
+ || strcmp (p, "5K") == 0)
+ mips_cpu = 5000;
+ break;
+
+ case '6':
+ if (strcmp (p, "6000") == 0
+ || strcmp (p, "6k") == 0
+ || strcmp (p, "6K") == 0)
+ mips_cpu = 6000;
+ break;
+
+ case '8':
+ if (strcmp (p, "8000") == 0
+ || strcmp (p, "8k") == 0
+ || strcmp (p, "8K") == 0)
+ mips_cpu = 8000;
+ break;
+
+ case 'o':
+ if (strcmp (p, "orion") == 0)
+ mips_cpu = 4600;
+ break;
+ }
+
+ if (sv
+ && (mips_cpu != 4300
+ && mips_cpu != 4100
+ && mips_cpu != 4111
+ && mips_cpu != 5000))
+ {
+ as_bad (_("ignoring invalid leading 'v' in -mcpu=%s switch"), arg);
+ return 0;
+ }
+
+ if (mips_cpu == -1)
+ {
+ as_bad (_("invalid architecture -mcpu=%s"), arg);
+ return 0;
+ }
+ }
+ }
+ break;
+
+ case OPTION_M4650:
+ mips_cpu = 4650;
+ break;
+
+ case OPTION_NO_M4650:
+ break;
+
+ case OPTION_M4010:
+ mips_cpu = 4010;
+ break;
+
+ case OPTION_NO_M4010:
+ break;
+
+ case OPTION_M4100:
+ mips_cpu = 4100;
+ break;
+
+ case OPTION_NO_M4100:
+ break;
+
+
+ case OPTION_M3900:
+ mips_cpu = 3900;
+ break;
+
+ case OPTION_NO_M3900:
+ break;
+
+ case OPTION_MIPS16:
+ mips_opts.mips16 = 1;
+ mips_no_prev_insn (false);
+ break;
+
+ case OPTION_NO_MIPS16:
+ mips_opts.mips16 = 0;
+ mips_no_prev_insn (false);
+ break;
+
+ case OPTION_MEMBEDDED_PIC:
+ mips_pic = EMBEDDED_PIC;
+ if (USE_GLOBAL_POINTER_OPT && g_switch_seen)
+ {
+ as_bad (_("-G may not be used with embedded PIC code"));
+ return 0;
+ }
+ g_switch_value = 0x7fffffff;
+ break;
+
+ /* When generating ELF code, we permit -KPIC and -call_shared to
+ select SVR4_PIC, and -non_shared to select no PIC. This is
+ intended to be compatible with Irix 5. */
+ case OPTION_CALL_SHARED:
+ if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
+ {
+ as_bad (_("-call_shared is supported only for ELF format"));
+ return 0;
+ }
+ mips_pic = SVR4_PIC;
+ if (g_switch_seen && g_switch_value != 0)
+ {
+ as_bad (_("-G may not be used with SVR4 PIC code"));
+ return 0;
+ }
+ g_switch_value = 0;
+ break;
+
+ case OPTION_NON_SHARED:
+ if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
+ {
+ as_bad (_("-non_shared is supported only for ELF format"));
+ return 0;
+ }
+ mips_pic = NO_PIC;
+ break;
+
+ /* The -xgot option tells the assembler to use 32 offsets when
+ accessing the got in SVR4_PIC mode. It is for Irix
+ compatibility. */
+ case OPTION_XGOT:
+ mips_big_got = 1;
+ break;
+
+ case 'G':
+ if (! USE_GLOBAL_POINTER_OPT)
+ {
+ as_bad (_("-G is not supported for this configuration"));
+ return 0;
+ }
+ else if (mips_pic == SVR4_PIC || mips_pic == EMBEDDED_PIC)
+ {
+ as_bad (_("-G may not be used with SVR4 or embedded PIC code"));
+ return 0;
+ }
+ else
+ g_switch_value = atoi (arg);
+ g_switch_seen = 1;
+ break;
+
+ /* The -32 and -64 options tell the assembler to output the 32
+ bit or the 64 bit MIPS ELF format. */
+ case OPTION_32:
+ mips_64 = 0;
+ break;
+
+ case OPTION_64:
+ {
+ const char **list, **l;
+
+ list = bfd_target_list ();
+ for (l = list; *l != NULL; l++)
+ if (strcmp (*l, "elf64-bigmips") == 0
+ || strcmp (*l, "elf64-littlemips") == 0)
+ break;
+ if (*l == NULL)
+ as_fatal (_("No compiled in support for 64 bit object file format"));
+ free (list);
+ mips_64 = 1;
+ }
+ break;
+
+
+ case OPTION_MABI:
+ if (strcmp (arg,"32") == 0
+ || strcmp (arg,"n32") == 0
+ || strcmp (arg,"64") == 0
+ || strcmp (arg,"o64") == 0
+ || strcmp (arg,"eabi") == 0)
+ mips_abi_string = arg;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+
+static void
+show (stream, string, col_p, first_p)
+ FILE *stream;
+ char *string;
+ int *col_p;
+ int *first_p;
+{
+ if (*first_p)
+ {
+ fprintf (stream, "%24s", "");
+ *col_p = 24;
+ }
+ else
+ {
+ fprintf (stream, ", ");
+ *col_p += 2;
+ }
+
+ if (*col_p + strlen (string) > 72)
+ {
+ fprintf (stream, "\n%24s", "");
+ *col_p = 24;
+ }
+
+ fprintf (stream, "%s", string);
+ *col_p += strlen (string);
+
+ *first_p = 0;
+}
+
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+ int column, first;
+
+ fprintf(stream, _("\
+MIPS options:\n\
+-membedded-pic generate embedded position independent code\n\
+-EB generate big endian output\n\
+-EL generate little endian output\n\
+-g, -g2 do not remove uneeded NOPs or swap branches\n\
+-G NUM allow referencing objects up to NUM bytes\n\
+ implicitly with the gp register [default 8]\n"));
+ fprintf(stream, _("\
+-mips1 generate MIPS ISA I instructions\n\
+-mips2 generate MIPS ISA II instructions\n\
+-mips3 generate MIPS ISA III instructions\n\
+-mips4 generate MIPS ISA IV instructions\n\
+-mcpu=CPU generate code for CPU, where CPU is one of:\n"));
+
+ first = 1;
+
+ show (stream, "2000", &column, &first);
+ show (stream, "3000", &column, &first);
+ show (stream, "3900", &column, &first);
+ show (stream, "4000", &column, &first);
+ show (stream, "4010", &column, &first);
+ show (stream, "4100", &column, &first);
+ show (stream, "4111", &column, &first);
+ show (stream, "4300", &column, &first);
+ show (stream, "4400", &column, &first);
+ show (stream, "4600", &column, &first);
+ show (stream, "4650", &column, &first);
+ show (stream, "5000", &column, &first);
+ show (stream, "6000", &column, &first);
+ show (stream, "8000", &column, &first);
+ show (stream, "10000", &column, &first);
+ fputc ('\n', stream);
+
+ fprintf (stream, _("\
+-mCPU equivalent to -mcpu=CPU.\n\
+-no-mCPU don't generate code specific to CPU.\n\
+ For -mCPU and -no-mCPU, CPU must be one of:\n"));
+
+ first = 1;
+
+ show (stream, "3900", &column, &first);
+ show (stream, "4010", &column, &first);
+ show (stream, "4100", &column, &first);
+ show (stream, "4650", &column, &first);
+ fputc ('\n', stream);
+
+ fprintf(stream, _("\
+-mips16 generate mips16 instructions\n\
+-no-mips16 do not generate mips16 instructions\n"));
+ fprintf(stream, _("\
+-O0 remove unneeded NOPs, do not swap branches\n\
+-O remove unneeded NOPs and swap branches\n\
+--trap, --no-break trap exception on div by 0 and mult overflow\n\
+--break, --no-trap break exception on div by 0 and mult overflow\n"));
+#ifdef OBJ_ELF
+ fprintf(stream, _("\
+-KPIC, -call_shared generate SVR4 position independent code\n\
+-non_shared do not generate position independent code\n\
+-xgot assume a 32 bit GOT\n\
+-32 create 32 bit object file (default)\n\
+-64 create 64 bit object file\n"));
+#endif
+}
+
+void
+mips_init_after_args ()
+{
+ /* initialize opcodes */
+ bfd_mips_num_opcodes = bfd_mips_num_builtin_opcodes;
+ mips_opcodes = (struct mips_opcode*) mips_builtin_opcodes;
+}
+
+long
+md_pcrel_from (fixP)
+ fixS *fixP;
+{
+ if (OUTPUT_FLAVOR != bfd_target_aout_flavour
+ && fixP->fx_addsy != (symbolS *) NULL
+ && ! S_IS_DEFINED (fixP->fx_addsy))
+ {
+ /* This makes a branch to an undefined symbol be a branch to the
+ current location. */
+ return 4;
+ }
+
+ /* return the address of the delay slot */
+ return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
+}
+
+/* This is called by emit_expr via TC_CONS_FIX_NEW when creating a
+ reloc for a cons. We could use the definition there, except that
+ we want to handle 64 bit relocs specially. */
+
+void
+cons_fix_new_mips (frag, where, nbytes, exp)
+ fragS *frag;
+ int where;
+ unsigned int nbytes;
+ expressionS *exp;
+{
+#ifndef OBJ_ELF
+ /* If we are assembling in 32 bit mode, turn an 8 byte reloc into a
+ 4 byte reloc. */
+ if (nbytes == 8 && ! mips_64)
+ {
+ if (target_big_endian)
+ where += 4;
+ nbytes = 4;
+ }
+#endif
+
+ if (nbytes != 2 && nbytes != 4 && nbytes != 8)
+ as_bad (_("Unsupported reloc size %d"), nbytes);
+
+ fix_new_exp (frag_now, where, (int) nbytes, exp, 0,
+ (nbytes == 2
+ ? BFD_RELOC_16
+ : (nbytes == 4 ? BFD_RELOC_32 : BFD_RELOC_64)));
+}
+
+/* This is called before the symbol table is processed. In order to
+ work with gcc when using mips-tfile, we must keep all local labels.
+ However, in other cases, we want to discard them. If we were
+ called with -g, but we didn't see any debugging information, it may
+ mean that gcc is smuggling debugging information through to
+ mips-tfile, in which case we must generate all local labels. */
+
+void
+mips_frob_file_before_adjust ()
+{
+#ifndef NO_ECOFF_DEBUGGING
+ if (ECOFF_DEBUGGING
+ && mips_debug != 0
+ && ! ecoff_debugging_seen)
+ flag_keep_locals = 1;
+#endif
+}
+
+/* Sort any unmatched HI16_S relocs so that they immediately precede
+ the corresponding LO reloc. This is called before md_apply_fix and
+ tc_gen_reloc. Unmatched HI16_S relocs can only be generated by
+ explicit use of the %hi modifier. */
+
+void
+mips_frob_file ()
+{
+ struct mips_hi_fixup *l;
+
+ for (l = mips_hi_fixup_list; l != NULL; l = l->next)
+ {
+ segment_info_type *seginfo;
+ int pass;
+
+ assert (l->fixp->fx_r_type == BFD_RELOC_HI16_S);
+
+ /* Check quickly whether the next fixup happens to be a matching
+ %lo. */
+ if (l->fixp->fx_next != NULL
+ && l->fixp->fx_next->fx_r_type == BFD_RELOC_LO16
+ && l->fixp->fx_addsy == l->fixp->fx_next->fx_addsy
+ && l->fixp->fx_offset == l->fixp->fx_next->fx_offset)
+ continue;
+
+ /* Look through the fixups for this segment for a matching %lo.
+ When we find one, move the %hi just in front of it. We do
+ this in two passes. In the first pass, we try to find a
+ unique %lo. In the second pass, we permit multiple %hi
+ relocs for a single %lo (this is a GNU extension). */
+ seginfo = seg_info (l->seg);
+ for (pass = 0; pass < 2; pass++)
+ {
+ fixS *f, *prev;
+
+ prev = NULL;
+ for (f = seginfo->fix_root; f != NULL; f = f->fx_next)
+ {
+ /* Check whether this is a %lo fixup which matches l->fixp. */
+ if (f->fx_r_type == BFD_RELOC_LO16
+ && f->fx_addsy == l->fixp->fx_addsy
+ && f->fx_offset == l->fixp->fx_offset
+ && (pass == 1
+ || prev == NULL
+ || prev->fx_r_type != BFD_RELOC_HI16_S
+ || prev->fx_addsy != f->fx_addsy
+ || prev->fx_offset != f->fx_offset))
+ {
+ fixS **pf;
+
+ /* Move l->fixp before f. */
+ for (pf = &seginfo->fix_root;
+ *pf != l->fixp;
+ pf = &(*pf)->fx_next)
+ assert (*pf != NULL);
+
+ *pf = l->fixp->fx_next;
+
+ l->fixp->fx_next = f;
+ if (prev == NULL)
+ seginfo->fix_root = l->fixp;
+ else
+ prev->fx_next = l->fixp;
+
+ break;
+ }
+
+ prev = f;
+ }
+
+ if (f != NULL)
+ break;
+
+#if 0 /* GCC code motion plus incomplete dead code elimination
+ can leave a %hi without a %lo. */
+ if (pass == 1)
+ as_warn_where (l->fixp->fx_file, l->fixp->fx_line,
+ _("Unmatched %%hi reloc"));
+#endif
+ }
+ }
+}
+
+/* When generating embedded PIC code we need to use a special
+ relocation to represent the difference of two symbols in the .text
+ section (switch tables use a difference of this sort). See
+ include/coff/mips.h for details. This macro checks whether this
+ fixup requires the special reloc. */
+#define SWITCH_TABLE(fixp) \
+ ((fixp)->fx_r_type == BFD_RELOC_32 \
+ && (fixp)->fx_addsy != NULL \
+ && (fixp)->fx_subsy != NULL \
+ && S_GET_SEGMENT ((fixp)->fx_addsy) == text_section \
+ && S_GET_SEGMENT ((fixp)->fx_subsy) == text_section)
+
+/* When generating embedded PIC code we must keep all PC relative
+ relocations, in case the linker has to relax a call. We also need
+ to keep relocations for switch table entries. */
+
+/*ARGSUSED*/
+int
+mips_force_relocation (fixp)
+ fixS *fixp;
+{
+ if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ return 1;
+
+ return (mips_pic == EMBEDDED_PIC
+ && (fixp->fx_pcrel
+ || SWITCH_TABLE (fixp)
+ || fixp->fx_r_type == BFD_RELOC_PCREL_HI16_S
+ || fixp->fx_r_type == BFD_RELOC_PCREL_LO16));
+}
+
+/* Apply a fixup to the object file. */
+
+int
+md_apply_fix (fixP, valueP)
+ fixS *fixP;
+ valueT *valueP;
+{
+ unsigned char *buf;
+ long insn, value;
+
+ assert (fixP->fx_size == 4
+ || fixP->fx_r_type == BFD_RELOC_16
+ || fixP->fx_r_type == BFD_RELOC_64
+ || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY);
+
+ value = *valueP;
+
+ /* If we aren't adjusting this fixup to be against the section
+ symbol, we need to adjust the value. */
+#ifdef OBJ_ELF
+ if (fixP->fx_addsy != NULL && OUTPUT_FLAVOR == bfd_target_elf_flavour)
+ if (S_GET_OTHER (fixP->fx_addsy) == STO_MIPS16
+ || S_IS_WEAK (fixP->fx_addsy)
+ || (fixP->fx_addsy->sy_used_in_reloc
+ && (bfd_get_section_flags (stdoutput,
+ S_GET_SEGMENT (fixP->fx_addsy))
+ & SEC_LINK_ONCE != 0)
+ || !strncmp (segment_name (S_GET_SEGMENT (fixP->fx_addsy)),
+ ".gnu.linkonce",
+ sizeof (".gnu.linkonce") - 1)))
+
+ {
+ value -= S_GET_VALUE (fixP->fx_addsy);
+ if (value != 0 && ! fixP->fx_pcrel)
+ {
+ /* In this case, the bfd_install_relocation routine will
+ incorrectly add the symbol value back in. We just want
+ the addend to appear in the object file. */
+ value -= S_GET_VALUE (fixP->fx_addsy);
+ }
+ }
+#endif
+
+
+ fixP->fx_addnumber = value; /* Remember value for tc_gen_reloc */
+
+ if (fixP->fx_addsy == NULL && ! fixP->fx_pcrel)
+ fixP->fx_done = 1;
+
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_MIPS_JMP:
+ case BFD_RELOC_HI16:
+ case BFD_RELOC_HI16_S:
+ case BFD_RELOC_MIPS_GPREL:
+ case BFD_RELOC_MIPS_LITERAL:
+ case BFD_RELOC_MIPS_CALL16:
+ case BFD_RELOC_MIPS_GOT16:
+ case BFD_RELOC_MIPS_GPREL32:
+ case BFD_RELOC_MIPS_GOT_HI16:
+ case BFD_RELOC_MIPS_GOT_LO16:
+ case BFD_RELOC_MIPS_CALL_HI16:
+ case BFD_RELOC_MIPS_CALL_LO16:
+ case BFD_RELOC_MIPS16_GPREL:
+ if (fixP->fx_pcrel)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Invalid PC relative reloc"));
+ /* Nothing needed to do. The value comes from the reloc entry */
+ break;
+
+ case BFD_RELOC_MIPS16_JMP:
+ /* We currently always generate a reloc against a symbol, which
+ means that we don't want an addend even if the symbol is
+ defined. */
+ fixP->fx_addnumber = 0;
+ break;
+
+ case BFD_RELOC_PCREL_HI16_S:
+ /* The addend for this is tricky if it is internal, so we just
+ do everything here rather than in bfd_install_relocation. */
+ if ((fixP->fx_addsy->bsym->flags & BSF_SECTION_SYM) == 0)
+ {
+ /* For an external symbol adjust by the address to make it
+ pcrel_offset. We use the address of the RELLO reloc
+ which follows this one. */
+ value += (fixP->fx_next->fx_frag->fr_address
+ + fixP->fx_next->fx_where);
+ }
+ if (value & 0x8000)
+ value += 0x10000;
+ value >>= 16;
+ buf = (unsigned char *) fixP->fx_frag->fr_literal + fixP->fx_where;
+ if (target_big_endian)
+ buf += 2;
+ md_number_to_chars (buf, value, 2);
+ break;
+
+ case BFD_RELOC_PCREL_LO16:
+ /* The addend for this is tricky if it is internal, so we just
+ do everything here rather than in bfd_install_relocation. */
+ if ((fixP->fx_addsy->bsym->flags & BSF_SECTION_SYM) == 0)
+ value += fixP->fx_frag->fr_address + fixP->fx_where;
+ buf = (unsigned char *) fixP->fx_frag->fr_literal + fixP->fx_where;
+ if (target_big_endian)
+ buf += 2;
+ md_number_to_chars (buf, value, 2);
+ break;
+
+ case BFD_RELOC_64:
+ /* This is handled like BFD_RELOC_32, but we output a sign
+ extended value if we are only 32 bits. */
+ if (fixP->fx_done
+ || (mips_pic == EMBEDDED_PIC && SWITCH_TABLE (fixP)))
+ {
+ if (8 <= sizeof (valueT))
+ md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
+ value, 8);
+ else
+ {
+ long w1, w2;
+ long hiv;
+
+ w1 = w2 = fixP->fx_where;
+ if (target_big_endian)
+ w1 += 4;
+ else
+ w2 += 4;
+ md_number_to_chars (fixP->fx_frag->fr_literal + w1, value, 4);
+ if ((value & 0x80000000) != 0)
+ hiv = 0xffffffff;
+ else
+ hiv = 0;
+ md_number_to_chars (fixP->fx_frag->fr_literal + w2, hiv, 4);
+ }
+ }
+ break;
+
+ case BFD_RELOC_32:
+ /* If we are deleting this reloc entry, we must fill in the
+ value now. This can happen if we have a .word which is not
+ resolved when it appears but is later defined. We also need
+ to fill in the value if this is an embedded PIC switch table
+ entry. */
+ if (fixP->fx_done
+ || (mips_pic == EMBEDDED_PIC && SWITCH_TABLE (fixP)))
+ md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
+ value, 4);
+ break;
+
+ case BFD_RELOC_16:
+ /* If we are deleting this reloc entry, we must fill in the
+ value now. */
+ assert (fixP->fx_size == 2);
+ if (fixP->fx_done)
+ md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
+ value, 2);
+ break;
+
+ case BFD_RELOC_LO16:
+ /* When handling an embedded PIC switch statement, we can wind
+ up deleting a LO16 reloc. See the 'o' case in mips_ip. */
+ if (fixP->fx_done)
+ {
+ if (value < -0x8000 || value > 0x7fff)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("relocation overflow"));
+ buf = (unsigned char *) fixP->fx_frag->fr_literal + fixP->fx_where;
+ if (target_big_endian)
+ buf += 2;
+ md_number_to_chars (buf, value, 2);
+ }
+ break;
+
+ case BFD_RELOC_16_PCREL_S2:
+ /*
+ * We need to save the bits in the instruction since fixup_segment()
+ * might be deleting the relocation entry (i.e., a branch within
+ * the current segment).
+ */
+ if ((value & 0x3) != 0)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Branch to odd address (%lx)"), value);
+ value >>= 2;
+
+ /* update old instruction data */
+ buf = (unsigned char *) (fixP->fx_where + fixP->fx_frag->fr_literal);
+ if (target_big_endian)
+ insn = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+ else
+ insn = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
+
+ if (value >= -0x8000 && value < 0x8000)
+ insn |= value & 0xffff;
+ else
+ {
+ /* The branch offset is too large. If this is an
+ unconditional branch, and we are not generating PIC code,
+ we can convert it to an absolute jump instruction. */
+ if (mips_pic == NO_PIC
+ && fixP->fx_done
+ && fixP->fx_frag->fr_address >= text_section->vma
+ && (fixP->fx_frag->fr_address
+ < text_section->vma + text_section->_raw_size)
+ && ((insn & 0xffff0000) == 0x10000000 /* beq $0,$0 */
+ || (insn & 0xffff0000) == 0x04010000 /* bgez $0 */
+ || (insn & 0xffff0000) == 0x04110000)) /* bgezal $0 */
+ {
+ if ((insn & 0xffff0000) == 0x04110000) /* bgezal $0 */
+ insn = 0x0c000000; /* jal */
+ else
+ insn = 0x08000000; /* j */
+ fixP->fx_r_type = BFD_RELOC_MIPS_JMP;
+ fixP->fx_done = 0;
+ fixP->fx_addsy = section_symbol (text_section);
+ fixP->fx_addnumber = (value << 2) + md_pcrel_from (fixP);
+ }
+ else
+ {
+ /* FIXME. It would be possible in principle to handle
+ conditional branches which overflow. They could be
+ transformed into a branch around a jump. This would
+ require setting up variant frags for each different
+ branch type. The native MIPS assembler attempts to
+ handle these cases, but it appears to do it
+ incorrectly. */
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Branch out of range"));
+ }
+ }
+
+ md_number_to_chars ((char *) buf, (valueT) insn, 4);
+ break;
+
+ case BFD_RELOC_VTABLE_INHERIT:
+ fixP->fx_done = 0;
+ if (fixP->fx_addsy
+ && !S_IS_DEFINED (fixP->fx_addsy)
+ && !S_IS_WEAK (fixP->fx_addsy))
+ S_SET_WEAK (fixP->fx_addsy);
+ break;
+
+ case BFD_RELOC_VTABLE_ENTRY:
+ fixP->fx_done = 0;
+ break;
+
+ default:
+ internalError ();
+ }
+
+ return 1;
+}
+
+#if 0
+void
+printInsn (oc)
+ unsigned long oc;
+{
+ const struct mips_opcode *p;
+ int treg, sreg, dreg, shamt;
+ short imm;
+ const char *args;
+ int i;
+
+ for (i = 0; i < NUMOPCODES; ++i)
+ {
+ p = &mips_opcodes[i];
+ if (((oc & p->mask) == p->match) && (p->pinfo != INSN_MACRO))
+ {
+ printf ("%08lx %s\t", oc, p->name);
+ treg = (oc >> 16) & 0x1f;
+ sreg = (oc >> 21) & 0x1f;
+ dreg = (oc >> 11) & 0x1f;
+ shamt = (oc >> 6) & 0x1f;
+ imm = oc;
+ for (args = p->args;; ++args)
+ {
+ switch (*args)
+ {
+ case '\0':
+ printf ("\n");
+ break;
+
+ case ',':
+ case '(':
+ case ')':
+ printf ("%c", *args);
+ continue;
+
+ case 'r':
+ assert (treg == sreg);
+ printf ("$%d,$%d", treg, sreg);
+ continue;
+
+ case 'd':
+ case 'G':
+ printf ("$%d", dreg);
+ continue;
+
+ case 't':
+ case 'E':
+ printf ("$%d", treg);
+ continue;
+
+ case 'k':
+ printf ("0x%x", treg);
+ continue;
+
+ case 'b':
+ case 's':
+ printf ("$%d", sreg);
+ continue;
+
+ case 'a':
+ printf ("0x%08lx", oc & 0x1ffffff);
+ continue;
+
+ case 'i':
+ case 'j':
+ case 'o':
+ case 'u':
+ printf ("%d", imm);
+ continue;
+
+ case '<':
+ case '>':
+ printf ("$%d", shamt);
+ continue;
+
+ default:
+ internalError ();
+ }
+ break;
+ }
+ return;
+ }
+ }
+ printf (_("%08lx UNDEFINED\n"), oc);
+}
+#endif
+
+static symbolS *
+get_symbol ()
+{
+ int c;
+ char *name;
+ symbolS *p;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ p = (symbolS *) symbol_find_or_make (name);
+ *input_line_pointer = c;
+ return p;
+}
+
+/* Align the current frag to a given power of two. The MIPS assembler
+ also automatically adjusts any preceding label. */
+
+static void
+mips_align (to, fill, label)
+ int to;
+ int fill;
+ symbolS *label;
+{
+ mips_emit_delays (false);
+ frag_align (to, fill, 0);
+ record_alignment (now_seg, to);
+ if (label != NULL)
+ {
+ assert (S_GET_SEGMENT (label) == now_seg);
+ label->sy_frag = frag_now;
+ S_SET_VALUE (label, (valueT) frag_now_fix ());
+ }
+}
+
+/* Align to a given power of two. .align 0 turns off the automatic
+ alignment used by the data creating pseudo-ops. */
+
+static void
+s_align (x)
+ int x;
+{
+ register int temp;
+ register long temp_fill;
+ long max_alignment = 15;
+
+ /*
+
+ o Note that the assembler pulls down any immediately preceeding label
+ to the aligned address.
+ o It's not documented but auto alignment is reinstated by
+ a .align pseudo instruction.
+ o Note also that after auto alignment is turned off the mips assembler
+ issues an error on attempt to assemble an improperly aligned data item.
+ We don't.
+
+ */
+
+ temp = get_absolute_expression ();
+ if (temp > max_alignment)
+ as_bad (_("Alignment too large: %d. assumed."), temp = max_alignment);
+ else if (temp < 0)
+ {
+ as_warn (_("Alignment negative: 0 assumed."));
+ temp = 0;
+ }
+ if (*input_line_pointer == ',')
+ {
+ input_line_pointer++;
+ temp_fill = get_absolute_expression ();
+ }
+ else
+ temp_fill = 0;
+ if (temp)
+ {
+ auto_align = 1;
+ mips_align (temp, (int) temp_fill,
+ insn_labels != NULL ? insn_labels->label : NULL);
+ }
+ else
+ {
+ auto_align = 0;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+void
+mips_flush_pending_output ()
+{
+ mips_emit_delays (false);
+ mips_clear_insn_labels ();
+}
+
+static void
+s_change_sec (sec)
+ int sec;
+{
+ segT seg;
+
+ /* When generating embedded PIC code, we only use the .text, .lit8,
+ .sdata and .sbss sections. We change the .data and .rdata
+ pseudo-ops to use .sdata. */
+ if (mips_pic == EMBEDDED_PIC
+ && (sec == 'd' || sec == 'r'))
+ sec = 's';
+
+#ifdef OBJ_ELF
+ /* The ELF backend needs to know that we are changing sections, so
+ that .previous works correctly. We could do something like check
+ for a obj_section_change_hook macro, but that might be confusing
+ as it would not be appropriate to use it in the section changing
+ functions in read.c, since obj-elf.c intercepts those. FIXME:
+ This should be cleaner, somehow. */
+ obj_elf_section_change_hook ();
+#endif
+
+ mips_emit_delays (false);
+ switch (sec)
+ {
+ case 't':
+ s_text (0);
+ break;
+ case 'd':
+ s_data (0);
+ break;
+ case 'b':
+ subseg_set (bss_section, (subsegT) get_absolute_expression ());
+ demand_empty_rest_of_line ();
+ break;
+
+ case 'r':
+ if (USE_GLOBAL_POINTER_OPT)
+ {
+ seg = subseg_new (RDATA_SECTION_NAME,
+ (subsegT) get_absolute_expression ());
+ if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
+ {
+ bfd_set_section_flags (stdoutput, seg,
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_READONLY
+ | SEC_RELOC
+ | SEC_DATA));
+ if (strcmp (TARGET_OS, "elf") != 0)
+ bfd_set_section_alignment (stdoutput, seg, 4);
+ }
+ demand_empty_rest_of_line ();
+ }
+ else
+ {
+ as_bad (_("No read only data section in this object file format"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+ break;
+
+ case 's':
+ if (USE_GLOBAL_POINTER_OPT)
+ {
+ seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
+ if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
+ {
+ bfd_set_section_flags (stdoutput, seg,
+ SEC_ALLOC | SEC_LOAD | SEC_RELOC
+ | SEC_DATA);
+ if (strcmp (TARGET_OS, "elf") != 0)
+ bfd_set_section_alignment (stdoutput, seg, 4);
+ }
+ demand_empty_rest_of_line ();
+ break;
+ }
+ else
+ {
+ as_bad (_("Global pointers not supported; recompile -G 0"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+ }
+
+ auto_align = 1;
+}
+
+void
+mips_enable_auto_align ()
+{
+ auto_align = 1;
+}
+
+static void
+s_cons (log_size)
+ int log_size;
+{
+ symbolS *label;
+
+ label = insn_labels != NULL ? insn_labels->label : NULL;
+ mips_emit_delays (false);
+ if (log_size > 0 && auto_align)
+ mips_align (log_size, 0, label);
+ mips_clear_insn_labels ();
+ cons (1 << log_size);
+}
+
+static void
+s_float_cons (type)
+ int type;
+{
+ symbolS *label;
+
+ label = insn_labels != NULL ? insn_labels->label : NULL;
+
+ mips_emit_delays (false);
+
+ if (auto_align)
+ if (type == 'd')
+ mips_align (3, 0, label);
+ else
+ mips_align (2, 0, label);
+
+ mips_clear_insn_labels ();
+
+ float_cons (type);
+}
+
+/* Handle .globl. We need to override it because on Irix 5 you are
+ permitted to say
+ .globl foo .text
+ where foo is an undefined symbol, to mean that foo should be
+ considered to be the address of a function. */
+
+static void
+s_mips_globl (x)
+ int x;
+{
+ char *name;
+ int c;
+ symbolS *symbolP;
+ flagword flag;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ symbolP = symbol_find_or_make (name);
+ *input_line_pointer = c;
+ SKIP_WHITESPACE ();
+
+ /* On Irix 5, every global symbol that is not explicitly labelled as
+ being a function is apparently labelled as being an object. */
+ flag = BSF_OBJECT;
+
+ if (! is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ char *secname;
+ asection *sec;
+
+ secname = input_line_pointer;
+ c = get_symbol_end ();
+ sec = bfd_get_section_by_name (stdoutput, secname);
+ if (sec == NULL)
+ as_bad (_("%s: no such section"), secname);
+ *input_line_pointer = c;
+
+ if (sec != NULL && (sec->flags & SEC_CODE) != 0)
+ flag = BSF_FUNCTION;
+ }
+
+ symbolP->bsym->flags |= flag;
+
+ S_SET_EXTERNAL (symbolP);
+ demand_empty_rest_of_line ();
+}
+
+static void
+s_option (x)
+ int x;
+{
+ char *opt;
+ char c;
+
+ opt = input_line_pointer;
+ c = get_symbol_end ();
+
+ if (*opt == 'O')
+ {
+ /* FIXME: What does this mean? */
+ }
+ else if (strncmp (opt, "pic", 3) == 0)
+ {
+ int i;
+
+ i = atoi (opt + 3);
+ if (i == 0)
+ mips_pic = NO_PIC;
+ else if (i == 2)
+ mips_pic = SVR4_PIC;
+ else
+ as_bad (_(".option pic%d not supported"), i);
+
+ if (USE_GLOBAL_POINTER_OPT && mips_pic == SVR4_PIC)
+ {
+ if (g_switch_seen && g_switch_value != 0)
+ as_warn (_("-G may not be used with SVR4 PIC code"));
+ g_switch_value = 0;
+ bfd_set_gp_size (stdoutput, 0);
+ }
+ }
+ else
+ as_warn (_("Unrecognized option \"%s\""), opt);
+
+ *input_line_pointer = c;
+ demand_empty_rest_of_line ();
+}
+
+/* This structure is used to hold a stack of .set values. */
+
+struct mips_option_stack
+{
+ struct mips_option_stack *next;
+ struct mips_set_options options;
+};
+
+static struct mips_option_stack *mips_opts_stack;
+
+/* Handle the .set pseudo-op. */
+
+static void
+s_mipsset (x)
+ int x;
+{
+ char *name = input_line_pointer, ch;
+
+ while (!is_end_of_line[(unsigned char) *input_line_pointer])
+ input_line_pointer++;
+ ch = *input_line_pointer;
+ *input_line_pointer = '\0';
+
+ if (strcmp (name, "reorder") == 0)
+ {
+ if (mips_opts.noreorder && prev_nop_frag != NULL)
+ {
+ /* If we still have pending nops, we can discard them. The
+ usual nop handling will insert any that are still
+ needed. */
+ prev_nop_frag->fr_fix -= (prev_nop_frag_holds
+ * (mips_opts.mips16 ? 2 : 4));
+ prev_nop_frag = NULL;
+ }
+ mips_opts.noreorder = 0;
+ }
+ else if (strcmp (name, "noreorder") == 0)
+ {
+ mips_emit_delays (true);
+ mips_opts.noreorder = 1;
+ mips_any_noreorder = 1;
+ }
+ else if (strcmp (name, "at") == 0)
+ {
+ mips_opts.noat = 0;
+ }
+ else if (strcmp (name, "noat") == 0)
+ {
+ mips_opts.noat = 1;
+ }
+ else if (strcmp (name, "macro") == 0)
+ {
+ mips_opts.warn_about_macros = 0;
+ }
+ else if (strcmp (name, "nomacro") == 0)
+ {
+ if (mips_opts.noreorder == 0)
+ as_bad (_("`noreorder' must be set before `nomacro'"));
+ mips_opts.warn_about_macros = 1;
+ }
+ else if (strcmp (name, "move") == 0 || strcmp (name, "novolatile") == 0)
+ {
+ mips_opts.nomove = 0;
+ }
+ else if (strcmp (name, "nomove") == 0 || strcmp (name, "volatile") == 0)
+ {
+ mips_opts.nomove = 1;
+ }
+ else if (strcmp (name, "bopt") == 0)
+ {
+ mips_opts.nobopt = 0;
+ }
+ else if (strcmp (name, "nobopt") == 0)
+ {
+ mips_opts.nobopt = 1;
+ }
+ else if (strcmp (name, "mips16") == 0
+ || strcmp (name, "MIPS-16") == 0)
+ mips_opts.mips16 = 1;
+ else if (strcmp (name, "nomips16") == 0
+ || strcmp (name, "noMIPS-16") == 0)
+ mips_opts.mips16 = 0;
+ else if (strncmp (name, "mips", 4) == 0)
+ {
+ int isa;
+
+ /* Permit the user to change the ISA on the fly. Needless to
+ say, misuse can cause serious problems. */
+ isa = atoi (name + 4);
+ if (isa == 0)
+ mips_opts.isa = file_mips_isa;
+ else if (isa < 1 || isa > 4)
+ as_bad (_("unknown ISA level"));
+ else
+ mips_opts.isa = isa;
+ }
+ else if (strcmp (name, "autoextend") == 0)
+ mips_opts.noautoextend = 0;
+ else if (strcmp (name, "noautoextend") == 0)
+ mips_opts.noautoextend = 1;
+ else if (strcmp (name, "push") == 0)
+ {
+ struct mips_option_stack *s;
+
+ s = (struct mips_option_stack *) xmalloc (sizeof *s);
+ s->next = mips_opts_stack;
+ s->options = mips_opts;
+ mips_opts_stack = s;
+ }
+ else if (strcmp (name, "pop") == 0)
+ {
+ struct mips_option_stack *s;
+
+ s = mips_opts_stack;
+ if (s == NULL)
+ as_bad (_(".set pop with no .set push"));
+ else
+ {
+ /* If we're changing the reorder mode we need to handle
+ delay slots correctly. */
+ if (s->options.noreorder && ! mips_opts.noreorder)
+ mips_emit_delays (true);
+ else if (! s->options.noreorder && mips_opts.noreorder)
+ {
+ if (prev_nop_frag != NULL)
+ {
+ prev_nop_frag->fr_fix -= (prev_nop_frag_holds
+ * (mips_opts.mips16 ? 2 : 4));
+ prev_nop_frag = NULL;
+ }
+ }
+
+ mips_opts = s->options;
+ mips_opts_stack = s->next;
+ free (s);
+ }
+ }
+ else
+ {
+ as_warn (_("Tried to set unrecognized symbol: %s\n"), name);
+ }
+ *input_line_pointer = ch;
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the .abicalls pseudo-op. I believe this is equivalent to
+ .option pic2. It means to generate SVR4 PIC calls. */
+
+static void
+s_abicalls (ignore)
+ int ignore;
+{
+ mips_pic = SVR4_PIC;
+ if (USE_GLOBAL_POINTER_OPT)
+ {
+ if (g_switch_seen && g_switch_value != 0)
+ as_warn (_("-G may not be used with SVR4 PIC code"));
+ g_switch_value = 0;
+ }
+ bfd_set_gp_size (stdoutput, 0);
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the .cpload pseudo-op. This is used when generating SVR4
+ PIC code. It sets the $gp register for the function based on the
+ function address, which is in the register named in the argument.
+ This uses a relocation against _gp_disp, which is handled specially
+ by the linker. The result is:
+ lui $gp,%hi(_gp_disp)
+ addiu $gp,$gp,%lo(_gp_disp)
+ addu $gp,$gp,.cpload argument
+ The .cpload argument is normally $25 == $t9. */
+
+static void
+s_cpload (ignore)
+ int ignore;
+{
+ expressionS ex;
+ int icnt = 0;
+
+ /* If we are not generating SVR4 PIC code, .cpload is ignored. */
+ if (mips_pic != SVR4_PIC)
+ {
+ s_ignore (0);
+ return;
+ }
+
+ /* .cpload should be a in .set noreorder section. */
+ if (mips_opts.noreorder == 0)
+ as_warn (_(".cpload not in noreorder section"));
+
+ ex.X_op = O_symbol;
+ ex.X_add_symbol = symbol_find_or_make ("_gp_disp");
+ ex.X_op_symbol = NULL;
+ ex.X_add_number = 0;
+
+ /* In ELF, this symbol is implicitly an STT_OBJECT symbol. */
+ ex.X_add_symbol->bsym->flags |= BSF_OBJECT;
+
+ macro_build_lui ((char *) NULL, &icnt, &ex, GP);
+ macro_build ((char *) NULL, &icnt, &ex, "addiu", "t,r,j", GP, GP,
+ (int) BFD_RELOC_LO16);
+
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "addu", "d,v,t",
+ GP, GP, tc_get_register (0));
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the .cprestore pseudo-op. This stores $gp into a given
+ offset from $sp. The offset is remembered, and after making a PIC
+ call $gp is restored from that location. */
+
+static void
+s_cprestore (ignore)
+ int ignore;
+{
+ expressionS ex;
+ int icnt = 0;
+
+ /* If we are not generating SVR4 PIC code, .cprestore is ignored. */
+ if (mips_pic != SVR4_PIC)
+ {
+ s_ignore (0);
+ return;
+ }
+
+ mips_cprestore_offset = get_absolute_expression ();
+
+ ex.X_op = O_constant;
+ ex.X_add_symbol = NULL;
+ ex.X_op_symbol = NULL;
+ ex.X_add_number = mips_cprestore_offset;
+
+ macro_build ((char *) NULL, &icnt, &ex,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "sw" : "sd"),
+ "t,o(b)", GP, (int) BFD_RELOC_LO16, SP);
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the .gpword pseudo-op. This is used when generating PIC
+ code. It generates a 32 bit GP relative reloc. */
+
+static void
+s_gpword (ignore)
+ int ignore;
+{
+ symbolS *label;
+ expressionS ex;
+ char *p;
+
+ /* When not generating PIC code, this is treated as .word. */
+ if (mips_pic != SVR4_PIC)
+ {
+ s_cons (2);
+ return;
+ }
+
+ label = insn_labels != NULL ? insn_labels->label : NULL;
+ mips_emit_delays (true);
+ if (auto_align)
+ mips_align (2, 0, label);
+ mips_clear_insn_labels ();
+
+ expression (&ex);
+
+ if (ex.X_op != O_symbol || ex.X_add_number != 0)
+ {
+ as_bad (_("Unsupported use of .gpword"));
+ ignore_rest_of_line ();
+ }
+
+ p = frag_more (4);
+ md_number_to_chars (p, (valueT) 0, 4);
+ fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, 0,
+ BFD_RELOC_MIPS_GPREL32);
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the .cpadd pseudo-op. This is used when dealing with switch
+ tables in SVR4 PIC code. */
+
+static void
+s_cpadd (ignore)
+ int ignore;
+{
+ int icnt = 0;
+ int reg;
+
+ /* This is ignored when not generating SVR4 PIC code. */
+ if (mips_pic != SVR4_PIC)
+ {
+ s_ignore (0);
+ return;
+ }
+
+ /* Add $gp to the register named as an argument. */
+ reg = tc_get_register (0);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || mips_opts.isa < 3)
+ ? "addu" : "daddu"),
+ "d,v,t", reg, reg, GP);
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the .insn pseudo-op. This marks instruction labels in
+ mips16 mode. This permits the linker to handle them specially,
+ such as generating jalx instructions when needed. We also make
+ them odd for the duration of the assembly, in order to generate the
+ right sort of code. We will make them even in the adjust_symtab
+ routine, while leaving them marked. This is convenient for the
+ debugger and the disassembler. The linker knows to make them odd
+ again. */
+
+static void
+s_insn (ignore)
+ int ignore;
+{
+ if (mips_opts.mips16)
+ mips16_mark_labels ();
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle a .stabn directive. We need these in order to mark a label
+ as being a mips16 text label correctly. Sometimes the compiler
+ will emit a label, followed by a .stabn, and then switch sections.
+ If the label and .stabn are in mips16 mode, then the label is
+ really a mips16 text label. */
+
+static void
+s_mips_stab (type)
+ int type;
+{
+ if (type == 'n' && mips_opts.mips16)
+ mips16_mark_labels ();
+
+ s_stab (type);
+}
+
+/* Handle the .weakext pseudo-op as defined in Kane and Heinrich.
+ */
+
+static void
+s_mips_weakext (ignore)
+ int ignore;
+{
+ char *name;
+ int c;
+ symbolS *symbolP;
+ expressionS exp;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ symbolP = symbol_find_or_make (name);
+ S_SET_WEAK (symbolP);
+ *input_line_pointer = c;
+
+ SKIP_WHITESPACE ();
+
+ if (! is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ if (S_IS_DEFINED (symbolP))
+ {
+ as_bad ("Ignoring attempt to redefine symbol `%s'.",
+ S_GET_NAME (symbolP));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ if (*input_line_pointer == ',')
+ {
+ ++input_line_pointer;
+ SKIP_WHITESPACE ();
+ }
+
+ expression (&exp);
+ if (exp.X_op != O_symbol)
+ {
+ as_bad ("bad .weakext directive");
+ ignore_rest_of_line();
+ return;
+ }
+ symbolP->sy_value = exp;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* Parse a register string into a number. Called from the ECOFF code
+ to parse .frame. The argument is non-zero if this is the frame
+ register, so that we can record it in mips_frame_reg. */
+
+int
+tc_get_register (frame)
+ int frame;
+{
+ int reg;
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer++ != '$')
+ {
+ as_warn (_("expected `$'"));
+ reg = 0;
+ }
+ else if (isdigit ((unsigned char) *input_line_pointer))
+ {
+ reg = get_absolute_expression ();
+ if (reg < 0 || reg >= 32)
+ {
+ as_warn (_("Bad register number"));
+ reg = 0;
+ }
+ }
+ else
+ {
+ if (strncmp (input_line_pointer, "fp", 2) == 0)
+ reg = FP;
+ else if (strncmp (input_line_pointer, "sp", 2) == 0)
+ reg = SP;
+ else if (strncmp (input_line_pointer, "gp", 2) == 0)
+ reg = GP;
+ else if (strncmp (input_line_pointer, "at", 2) == 0)
+ reg = AT;
+ else
+ {
+ as_warn (_("Unrecognized register name"));
+ reg = 0;
+ }
+ input_line_pointer += 2;
+ }
+ if (frame)
+ mips_frame_reg = reg != 0 ? reg : SP;
+ return reg;
+}
+
+valueT
+md_section_align (seg, addr)
+ asection *seg;
+ valueT addr;
+{
+ int align = bfd_get_section_alignment (stdoutput, seg);
+
+#ifdef OBJ_ELF
+ /* We don't need to align ELF sections to the full alignment.
+ However, Irix 5 may prefer that we align them at least to a 16
+ byte boundary. We don't bother to align the sections if we are
+ targeted for an embedded system. */
+ if (strcmp (TARGET_OS, "elf") == 0)
+ return addr;
+ if (align > 4)
+ align = 4;
+#endif
+
+ return ((addr + (1 << align) - 1) & (-1 << align));
+}
+
+/* Utility routine, called from above as well. If called while the
+ input file is still being read, it's only an approximation. (For
+ example, a symbol may later become defined which appeared to be
+ undefined earlier.) */
+
+static int
+nopic_need_relax (sym, before_relaxing)
+ symbolS *sym;
+ int before_relaxing;
+{
+ if (sym == 0)
+ return 0;
+
+ if (USE_GLOBAL_POINTER_OPT)
+ {
+ const char *symname;
+ int change;
+
+ /* Find out whether this symbol can be referenced off the GP
+ register. It can be if it is smaller than the -G size or if
+ it is in the .sdata or .sbss section. Certain symbols can
+ not be referenced off the GP, although it appears as though
+ they can. */
+ symname = S_GET_NAME (sym);
+ if (symname != (const char *) NULL
+ && (strcmp (symname, "eprol") == 0
+ || strcmp (symname, "etext") == 0
+ || strcmp (symname, "_gp") == 0
+ || strcmp (symname, "edata") == 0
+ || strcmp (symname, "_fbss") == 0
+ || strcmp (symname, "_fdata") == 0
+ || strcmp (symname, "_ftext") == 0
+ || strcmp (symname, "end") == 0
+ || strcmp (symname, "_gp_disp") == 0))
+ change = 1;
+ else if ((! S_IS_DEFINED (sym) || S_IS_COMMON (sym))
+ && (0
+#ifndef NO_ECOFF_DEBUGGING
+ || (sym->ecoff_extern_size != 0
+ && sym->ecoff_extern_size <= g_switch_value)
+#endif
+ /* We must defer this decision until after the whole
+ file has been read, since there might be a .extern
+ after the first use of this symbol. */
+ || (before_relaxing
+#ifndef NO_ECOFF_DEBUGGING
+ && sym->ecoff_extern_size == 0
+#endif
+ && S_GET_VALUE (sym) == 0)
+ || (S_GET_VALUE (sym) != 0
+ && S_GET_VALUE (sym) <= g_switch_value)))
+ change = 0;
+ else
+ {
+ const char *segname;
+
+ segname = segment_name (S_GET_SEGMENT (sym));
+ assert (strcmp (segname, ".lit8") != 0
+ && strcmp (segname, ".lit4") != 0);
+ change = (strcmp (segname, ".sdata") != 0
+ && strcmp (segname, ".sbss") != 0);
+ }
+ return change;
+ }
+ else
+ /* We are not optimizing for the GP register. */
+ return 1;
+}
+
+/* Given a mips16 variant frag FRAGP, return non-zero if it needs an
+ extended opcode. SEC is the section the frag is in. */
+
+static int
+mips16_extended_frag (fragp, sec, stretch)
+ fragS *fragp;
+ asection *sec;
+ long stretch;
+{
+ int type;
+ register const struct mips16_immed_operand *op;
+ offsetT val;
+ int mintiny, maxtiny;
+ segT symsec;
+
+ if (RELAX_MIPS16_USER_SMALL (fragp->fr_subtype))
+ return 0;
+ if (RELAX_MIPS16_USER_EXT (fragp->fr_subtype))
+ return 1;
+
+ type = RELAX_MIPS16_TYPE (fragp->fr_subtype);
+ op = mips16_immed_operands;
+ while (op->type != type)
+ {
+ ++op;
+ assert (op < mips16_immed_operands + MIPS16_NUM_IMMED);
+ }
+
+ if (op->unsp)
+ {
+ if (type == '<' || type == '>' || type == '[' || type == ']')
+ {
+ mintiny = 1;
+ maxtiny = 1 << op->nbits;
+ }
+ else
+ {
+ mintiny = 0;
+ maxtiny = (1 << op->nbits) - 1;
+ }
+ }
+ else
+ {
+ mintiny = - (1 << (op->nbits - 1));
+ maxtiny = (1 << (op->nbits - 1)) - 1;
+ }
+
+ /* We can't call S_GET_VALUE here, because we don't want to lock in
+ a particular frag address. */
+ if (fragp->fr_symbol->sy_value.X_op == O_constant)
+ {
+ val = (fragp->fr_symbol->sy_value.X_add_number
+ + fragp->fr_symbol->sy_frag->fr_address);
+ symsec = S_GET_SEGMENT (fragp->fr_symbol);
+ }
+ else if (fragp->fr_symbol->sy_value.X_op == O_symbol
+ && (fragp->fr_symbol->sy_value.X_add_symbol->sy_value.X_op
+ == O_constant))
+ {
+ val = (fragp->fr_symbol->sy_value.X_add_symbol->sy_value.X_add_number
+ + fragp->fr_symbol->sy_value.X_add_symbol->sy_frag->fr_address
+ + fragp->fr_symbol->sy_value.X_add_number
+ + fragp->fr_symbol->sy_frag->fr_address);
+ symsec = S_GET_SEGMENT (fragp->fr_symbol->sy_value.X_add_symbol);
+ }
+ else
+ return 1;
+
+ if (op->pcrel)
+ {
+ addressT addr;
+
+ /* We won't have the section when we are called from
+ mips_relax_frag. However, we will always have been called
+ from md_estimate_size_before_relax first. If this is a
+ branch to a different section, we mark it as such. If SEC is
+ NULL, and the frag is not marked, then it must be a branch to
+ the same section. */
+ if (sec == NULL)
+ {
+ if (RELAX_MIPS16_LONG_BRANCH (fragp->fr_subtype))
+ return 1;
+ }
+ else
+ {
+ if (symsec != sec)
+ {
+ fragp->fr_subtype =
+ RELAX_MIPS16_MARK_LONG_BRANCH (fragp->fr_subtype);
+
+ /* FIXME: We should support this, and let the linker
+ catch branches and loads that are out of range. */
+ as_bad_where (fragp->fr_file, fragp->fr_line,
+ _("unsupported PC relative reference to different section"));
+
+ return 1;
+ }
+ }
+
+ /* In this case, we know for sure that the symbol fragment is in
+ the same section. If the fr_address of the symbol fragment
+ is greater then the address of this fragment we want to add
+ in STRETCH in order to get a better estimate of the address.
+ This particularly matters because of the shift bits. */
+ if (stretch != 0
+ && fragp->fr_symbol->sy_frag->fr_address >= fragp->fr_address)
+ {
+ fragS *f;
+
+ /* Adjust stretch for any alignment frag. Note that if have
+ been expanding the earlier code, the symbol may be
+ defined in what appears to be an earlier frag. FIXME:
+ This doesn't handle the fr_subtype field, which specifies
+ a maximum number of bytes to skip when doing an
+ alignment. */
+ for (f = fragp;
+ f != NULL && f != fragp->fr_symbol->sy_frag;
+ f = f->fr_next)
+ {
+ if (f->fr_type == rs_align || f->fr_type == rs_align_code)
+ {
+ if (stretch < 0)
+ stretch = - ((- stretch)
+ & ~ ((1 << (int) f->fr_offset) - 1));
+ else
+ stretch &= ~ ((1 << (int) f->fr_offset) - 1);
+ if (stretch == 0)
+ break;
+ }
+ }
+ if (f != NULL)
+ val += stretch;
+ }
+
+ addr = fragp->fr_address + fragp->fr_fix;
+
+ /* The base address rules are complicated. The base address of
+ a branch is the following instruction. The base address of a
+ PC relative load or add is the instruction itself, but if it
+ is in a delay slot (in which case it can not be extended) use
+ the address of the instruction whose delay slot it is in. */
+ if (type == 'p' || type == 'q')
+ {
+ addr += 2;
+
+ /* If we are currently assuming that this frag should be
+ extended, then, the current address is two bytes
+ higher. */
+ if (RELAX_MIPS16_EXTENDED (fragp->fr_subtype))
+ addr += 2;
+
+ /* Ignore the low bit in the target, since it will be set
+ for a text label. */
+ if ((val & 1) != 0)
+ --val;
+ }
+ else if (RELAX_MIPS16_JAL_DSLOT (fragp->fr_subtype))
+ addr -= 4;
+ else if (RELAX_MIPS16_DSLOT (fragp->fr_subtype))
+ addr -= 2;
+
+ val -= addr & ~ ((1 << op->shift) - 1);
+
+ /* Branch offsets have an implicit 0 in the lowest bit. */
+ if (type == 'p' || type == 'q')
+ val /= 2;
+
+ /* If any of the shifted bits are set, we must use an extended
+ opcode. If the address depends on the size of this
+ instruction, this can lead to a loop, so we arrange to always
+ use an extended opcode. We only check this when we are in
+ the main relaxation loop, when SEC is NULL. */
+ if ((val & ((1 << op->shift) - 1)) != 0 && sec == NULL)
+ {
+ fragp->fr_subtype =
+ RELAX_MIPS16_MARK_LONG_BRANCH (fragp->fr_subtype);
+ return 1;
+ }
+
+ /* If we are about to mark a frag as extended because the value
+ is precisely maxtiny + 1, then there is a chance of an
+ infinite loop as in the following code:
+ la $4,foo
+ .skip 1020
+ .align 2
+ foo:
+ In this case when the la is extended, foo is 0x3fc bytes
+ away, so the la can be shrunk, but then foo is 0x400 away, so
+ the la must be extended. To avoid this loop, we mark the
+ frag as extended if it was small, and is about to become
+ extended with a value of maxtiny + 1. */
+ if (val == ((maxtiny + 1) << op->shift)
+ && ! RELAX_MIPS16_EXTENDED (fragp->fr_subtype)
+ && sec == NULL)
+ {
+ fragp->fr_subtype =
+ RELAX_MIPS16_MARK_LONG_BRANCH (fragp->fr_subtype);
+ return 1;
+ }
+ }
+ else if (symsec != absolute_section && sec != NULL)
+ as_bad_where (fragp->fr_file, fragp->fr_line, _("unsupported relocation"));
+
+ if ((val & ((1 << op->shift) - 1)) != 0
+ || val < (mintiny << op->shift)
+ || val > (maxtiny << op->shift))
+ return 1;
+ else
+ return 0;
+}
+
+/* Estimate the size of a frag before relaxing. Unless this is the
+ mips16, we are not really relaxing here, and the final size is
+ encoded in the subtype information. For the mips16, we have to
+ decide whether we are using an extended opcode or not. */
+
+/*ARGSUSED*/
+int
+md_estimate_size_before_relax (fragp, segtype)
+ fragS *fragp;
+ asection *segtype;
+{
+ int change;
+
+ if (RELAX_MIPS16_P (fragp->fr_subtype))
+ {
+ if (mips16_extended_frag (fragp, segtype, 0))
+ {
+ fragp->fr_subtype = RELAX_MIPS16_MARK_EXTENDED (fragp->fr_subtype);
+ return 4;
+ }
+ else
+ {
+ fragp->fr_subtype = RELAX_MIPS16_CLEAR_EXTENDED (fragp->fr_subtype);
+ return 2;
+ }
+ }
+
+ if (mips_pic == NO_PIC)
+ {
+ change = nopic_need_relax (fragp->fr_symbol, 0);
+ }
+ else if (mips_pic == SVR4_PIC)
+ {
+ symbolS *sym;
+ asection *symsec;
+
+ sym = fragp->fr_symbol;
+
+ /* Handle the case of a symbol equated to another symbol. */
+ while (sym->sy_value.X_op == O_symbol
+ && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
+ {
+ symbolS *n;
+
+ /* It's possible to get a loop here in a badly written
+ program. */
+ n = sym->sy_value.X_add_symbol;
+ if (n == sym)
+ break;
+ sym = n;
+ }
+
+ symsec = S_GET_SEGMENT (sym);
+
+ /* This must duplicate the test in adjust_reloc_syms. */
+ change = (symsec != &bfd_und_section
+ && symsec != &bfd_abs_section
+ && ! bfd_is_com_section (symsec));
+ }
+ else
+ abort ();
+
+ if (change)
+ {
+ /* Record the offset to the first reloc in the fr_opcode field.
+ This lets md_convert_frag and tc_gen_reloc know that the code
+ must be expanded. */
+ fragp->fr_opcode = (fragp->fr_literal
+ + fragp->fr_fix
+ - RELAX_OLD (fragp->fr_subtype)
+ + RELAX_RELOC1 (fragp->fr_subtype));
+ /* FIXME: This really needs as_warn_where. */
+ if (RELAX_WARN (fragp->fr_subtype))
+ as_warn (_("AT used after \".set noat\" or macro used after \".set nomacro\""));
+ }
+
+ if (! change)
+ return 0;
+ else
+ return RELAX_NEW (fragp->fr_subtype) - RELAX_OLD (fragp->fr_subtype);
+}
+
+/* This is called to see whether a reloc against a defined symbol
+ should be converted into a reloc against a section. Don't adjust
+ MIPS16 jump relocations, so we don't have to worry about the format
+ of the offset in the .o file. Don't adjust relocations against
+ mips16 symbols, so that the linker can find them if it needs to set
+ up a stub. */
+
+int
+mips_fix_adjustable (fixp)
+ fixS *fixp;
+{
+ if (fixp->fx_r_type == BFD_RELOC_MIPS16_JMP)
+ return 0;
+ if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ return 0;
+ if (fixp->fx_addsy == NULL)
+ return 1;
+#ifdef OBJ_ELF
+ if (OUTPUT_FLAVOR == bfd_target_elf_flavour
+ && S_GET_OTHER (fixp->fx_addsy) == STO_MIPS16
+ && fixp->fx_subsy == NULL)
+ return 0;
+#endif
+ return 1;
+}
+
+/* Translate internal representation of relocation info to BFD target
+ format. */
+
+arelent **
+tc_gen_reloc (section, fixp)
+ asection *section;
+ fixS *fixp;
+{
+ static arelent *retval[4];
+ arelent *reloc;
+ bfd_reloc_code_real_type code;
+
+ reloc = retval[0] = (arelent *) xmalloc (sizeof (arelent));
+ retval[1] = NULL;
+
+ reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+ reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+
+ if (mips_pic == EMBEDDED_PIC
+ && SWITCH_TABLE (fixp))
+ {
+ /* For a switch table entry we use a special reloc. The addend
+ is actually the difference between the reloc address and the
+ subtrahend. */
+ reloc->addend = reloc->address - S_GET_VALUE (fixp->fx_subsy);
+ if (OUTPUT_FLAVOR != bfd_target_ecoff_flavour)
+ as_fatal (_("Double check fx_r_type in tc-mips.c:tc_gen_reloc"));
+ fixp->fx_r_type = BFD_RELOC_GPREL32;
+ }
+ else if (fixp->fx_r_type == BFD_RELOC_PCREL_LO16)
+ {
+ /* We use a special addend for an internal RELLO reloc. */
+ if (fixp->fx_addsy->bsym->flags & BSF_SECTION_SYM)
+ reloc->addend = reloc->address - S_GET_VALUE (fixp->fx_subsy);
+ else
+ reloc->addend = fixp->fx_addnumber + reloc->address;
+ }
+ else if (fixp->fx_r_type == BFD_RELOC_PCREL_HI16_S)
+ {
+ assert (fixp->fx_next != NULL
+ && fixp->fx_next->fx_r_type == BFD_RELOC_PCREL_LO16);
+ /* We use a special addend for an internal RELHI reloc. The
+ reloc is relative to the RELLO; adjust the addend
+ accordingly. */
+ if (fixp->fx_addsy->bsym->flags & BSF_SECTION_SYM)
+ reloc->addend = (fixp->fx_next->fx_frag->fr_address
+ + fixp->fx_next->fx_where
+ - S_GET_VALUE (fixp->fx_subsy));
+ else
+ reloc->addend = (fixp->fx_addnumber
+ + fixp->fx_next->fx_frag->fr_address
+ + fixp->fx_next->fx_where);
+ }
+ else if (fixp->fx_pcrel == 0)
+ reloc->addend = fixp->fx_addnumber;
+ else
+ {
+ if (OUTPUT_FLAVOR != bfd_target_aout_flavour)
+ /* A gruesome hack which is a result of the gruesome gas reloc
+ handling. */
+ reloc->addend = reloc->address;
+ else
+ reloc->addend = -reloc->address;
+ }
+
+ /* If this is a variant frag, we may need to adjust the existing
+ reloc and generate a new one. */
+ if (fixp->fx_frag->fr_opcode != NULL
+ && (fixp->fx_r_type == BFD_RELOC_MIPS_GPREL
+ || fixp->fx_r_type == BFD_RELOC_MIPS_GOT16
+ || fixp->fx_r_type == BFD_RELOC_MIPS_CALL16
+ || fixp->fx_r_type == BFD_RELOC_MIPS_GOT_HI16
+ || fixp->fx_r_type == BFD_RELOC_MIPS_GOT_LO16
+ || fixp->fx_r_type == BFD_RELOC_MIPS_CALL_HI16
+ || fixp->fx_r_type == BFD_RELOC_MIPS_CALL_LO16))
+ {
+ arelent *reloc2;
+
+ assert (! RELAX_MIPS16_P (fixp->fx_frag->fr_subtype));
+
+ /* If this is not the last reloc in this frag, then we have two
+ GPREL relocs, or a GOT_HI16/GOT_LO16 pair, or a
+ CALL_HI16/CALL_LO16, both of which are being replaced. Let
+ the second one handle all of them. */
+ if (fixp->fx_next != NULL
+ && fixp->fx_frag == fixp->fx_next->fx_frag)
+ {
+ assert ((fixp->fx_r_type == BFD_RELOC_MIPS_GPREL
+ && fixp->fx_next->fx_r_type == BFD_RELOC_MIPS_GPREL)
+ || (fixp->fx_r_type == BFD_RELOC_MIPS_GOT_HI16
+ && (fixp->fx_next->fx_r_type
+ == BFD_RELOC_MIPS_GOT_LO16))
+ || (fixp->fx_r_type == BFD_RELOC_MIPS_CALL_HI16
+ && (fixp->fx_next->fx_r_type
+ == BFD_RELOC_MIPS_CALL_LO16)));
+ retval[0] = NULL;
+ return retval;
+ }
+
+ fixp->fx_where = fixp->fx_frag->fr_opcode - fixp->fx_frag->fr_literal;
+ reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+ reloc2 = retval[1] = (arelent *) xmalloc (sizeof (arelent));
+ retval[2] = NULL;
+ reloc2->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+ reloc2->address = (reloc->address
+ + (RELAX_RELOC2 (fixp->fx_frag->fr_subtype)
+ - RELAX_RELOC1 (fixp->fx_frag->fr_subtype)));
+ reloc2->addend = fixp->fx_addnumber;
+ reloc2->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
+ assert (reloc2->howto != NULL);
+
+ if (RELAX_RELOC3 (fixp->fx_frag->fr_subtype))
+ {
+ arelent *reloc3;
+
+ reloc3 = retval[2] = (arelent *) xmalloc (sizeof (arelent));
+ retval[3] = NULL;
+ *reloc3 = *reloc2;
+ reloc3->address += 4;
+ }
+
+ if (mips_pic == NO_PIC)
+ {
+ assert (fixp->fx_r_type == BFD_RELOC_MIPS_GPREL);
+ fixp->fx_r_type = BFD_RELOC_HI16_S;
+ }
+ else if (mips_pic == SVR4_PIC)
+ {
+ switch (fixp->fx_r_type)
+ {
+ default:
+ abort ();
+ case BFD_RELOC_MIPS_GOT16:
+ break;
+ case BFD_RELOC_MIPS_CALL16:
+ case BFD_RELOC_MIPS_GOT_LO16:
+ case BFD_RELOC_MIPS_CALL_LO16:
+ fixp->fx_r_type = BFD_RELOC_MIPS_GOT16;
+ break;
+ }
+ }
+ else
+ abort ();
+ }
+
+ /* Since MIPS ELF uses Rel instead of Rela, encode the vtable entry
+ to be used in the relocation's section offset. */
+ if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ {
+ reloc->address = reloc->addend;
+ reloc->addend = 0;
+ }
+
+ /* Since DIFF_EXPR_OK is defined in tc-mips.h, it is possible that
+ fixup_segment converted a non-PC relative reloc into a PC
+ relative reloc. In such a case, we need to convert the reloc
+ code. */
+ code = fixp->fx_r_type;
+ if (fixp->fx_pcrel)
+ {
+ switch (code)
+ {
+ case BFD_RELOC_8:
+ code = BFD_RELOC_8_PCREL;
+ break;
+ case BFD_RELOC_16:
+ code = BFD_RELOC_16_PCREL;
+ break;
+ case BFD_RELOC_32:
+ code = BFD_RELOC_32_PCREL;
+ break;
+ case BFD_RELOC_64:
+ code = BFD_RELOC_64_PCREL;
+ break;
+ case BFD_RELOC_8_PCREL:
+ case BFD_RELOC_16_PCREL:
+ case BFD_RELOC_32_PCREL:
+ case BFD_RELOC_64_PCREL:
+ case BFD_RELOC_16_PCREL_S2:
+ case BFD_RELOC_PCREL_HI16_S:
+ case BFD_RELOC_PCREL_LO16:
+ break;
+ default:
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("Cannot make %s relocation PC relative"),
+ bfd_get_reloc_code_name (code));
+ }
+ }
+
+ /* To support a PC relative reloc when generating embedded PIC code
+ for ECOFF, we use a Cygnus extension. We check for that here to
+ make sure that we don't let such a reloc escape normally. */
+ if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour
+ && code == BFD_RELOC_16_PCREL_S2
+ && mips_pic != EMBEDDED_PIC)
+ reloc->howto = NULL;
+ else
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
+
+ if (reloc->howto == NULL)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("Can not represent %s relocation in this object file format"),
+ bfd_get_reloc_code_name (code));
+ retval[0] = NULL;
+ }
+
+ return retval;
+}
+
+/* Relax a machine dependent frag. This returns the amount by which
+ the current size of the frag should change. */
+
+int
+mips_relax_frag (fragp, stretch)
+ fragS *fragp;
+ long stretch;
+{
+ if (! RELAX_MIPS16_P (fragp->fr_subtype))
+ return 0;
+
+ if (mips16_extended_frag (fragp, (asection *) NULL, stretch))
+ {
+ if (RELAX_MIPS16_EXTENDED (fragp->fr_subtype))
+ return 0;
+ fragp->fr_subtype = RELAX_MIPS16_MARK_EXTENDED (fragp->fr_subtype);
+ return 2;
+ }
+ else
+ {
+ if (! RELAX_MIPS16_EXTENDED (fragp->fr_subtype))
+ return 0;
+ fragp->fr_subtype = RELAX_MIPS16_CLEAR_EXTENDED (fragp->fr_subtype);
+ return -2;
+ }
+
+ return 0;
+}
+
+/* Convert a machine dependent frag. */
+
+void
+md_convert_frag (abfd, asec, fragp)
+ bfd *abfd;
+ segT asec;
+ fragS *fragp;
+{
+ int old, new;
+ char *fixptr;
+
+ if (RELAX_MIPS16_P (fragp->fr_subtype))
+ {
+ int type;
+ register const struct mips16_immed_operand *op;
+ boolean small, ext;
+ offsetT val;
+ bfd_byte *buf;
+ unsigned long insn;
+ boolean use_extend;
+ unsigned short extend;
+
+ type = RELAX_MIPS16_TYPE (fragp->fr_subtype);
+ op = mips16_immed_operands;
+ while (op->type != type)
+ ++op;
+
+ if (RELAX_MIPS16_EXTENDED (fragp->fr_subtype))
+ {
+ small = false;
+ ext = true;
+ }
+ else
+ {
+ small = true;
+ ext = false;
+ }
+
+ resolve_symbol_value (fragp->fr_symbol, 1);
+ val = S_GET_VALUE (fragp->fr_symbol);
+ if (op->pcrel)
+ {
+ addressT addr;
+
+ addr = fragp->fr_address + fragp->fr_fix;
+
+ /* The rules for the base address of a PC relative reloc are
+ complicated; see mips16_extended_frag. */
+ if (type == 'p' || type == 'q')
+ {
+ addr += 2;
+ if (ext)
+ addr += 2;
+ /* Ignore the low bit in the target, since it will be
+ set for a text label. */
+ if ((val & 1) != 0)
+ --val;
+ }
+ else if (RELAX_MIPS16_JAL_DSLOT (fragp->fr_subtype))
+ addr -= 4;
+ else if (RELAX_MIPS16_DSLOT (fragp->fr_subtype))
+ addr -= 2;
+
+ addr &= ~ (addressT) ((1 << op->shift) - 1);
+ val -= addr;
+
+ /* Make sure the section winds up with the alignment we have
+ assumed. */
+ if (op->shift > 0)
+ record_alignment (asec, op->shift);
+ }
+
+ if (ext
+ && (RELAX_MIPS16_JAL_DSLOT (fragp->fr_subtype)
+ || RELAX_MIPS16_DSLOT (fragp->fr_subtype)))
+ as_warn_where (fragp->fr_file, fragp->fr_line,
+ _("extended instruction in delay slot"));
+
+ buf = (bfd_byte *) (fragp->fr_literal + fragp->fr_fix);
+
+ if (target_big_endian)
+ insn = bfd_getb16 (buf);
+ else
+ insn = bfd_getl16 (buf);
+
+ mips16_immed (fragp->fr_file, fragp->fr_line, type, val,
+ RELAX_MIPS16_USER_EXT (fragp->fr_subtype),
+ small, ext, &insn, &use_extend, &extend);
+
+ if (use_extend)
+ {
+ md_number_to_chars (buf, 0xf000 | extend, 2);
+ fragp->fr_fix += 2;
+ buf += 2;
+ }
+
+ md_number_to_chars (buf, insn, 2);
+ fragp->fr_fix += 2;
+ buf += 2;
+ }
+ else
+ {
+ if (fragp->fr_opcode == NULL)
+ return;
+
+ old = RELAX_OLD (fragp->fr_subtype);
+ new = RELAX_NEW (fragp->fr_subtype);
+ fixptr = fragp->fr_literal + fragp->fr_fix;
+
+ if (new > 0)
+ memcpy (fixptr - old, fixptr, new);
+
+ fragp->fr_fix += new - old;
+ }
+}
+
+#ifdef OBJ_ELF
+
+/* This function is called after the relocs have been generated.
+ We've been storing mips16 text labels as odd. Here we convert them
+ back to even for the convenience of the debugger. */
+
+void
+mips_frob_file_after_relocs ()
+{
+ asymbol **syms;
+ unsigned int count, i;
+
+ if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
+ return;
+
+ syms = bfd_get_outsymbols (stdoutput);
+ count = bfd_get_symcount (stdoutput);
+ for (i = 0; i < count; i++, syms++)
+ {
+ if (elf_symbol (*syms)->internal_elf_sym.st_other == STO_MIPS16
+ && ((*syms)->value & 1) != 0)
+ {
+ (*syms)->value &= ~1;
+ /* If the symbol has an odd size, it was probably computed
+ incorrectly, so adjust that as well. */
+ if ((elf_symbol (*syms)->internal_elf_sym.st_size & 1) != 0)
+ ++elf_symbol (*syms)->internal_elf_sym.st_size;
+ }
+ }
+}
+
+#endif
+
+/* This function is called whenever a label is defined. It is used
+ when handling branch delays; if a branch has a label, we assume we
+ can not move it. */
+
+void
+mips_define_label (sym)
+ symbolS *sym;
+{
+ struct insn_label_list *l;
+
+ if (free_insn_labels == NULL)
+ l = (struct insn_label_list *) xmalloc (sizeof *l);
+ else
+ {
+ l = free_insn_labels;
+ free_insn_labels = l->next;
+ }
+
+ l->label = sym;
+ l->next = insn_labels;
+ insn_labels = l;
+}
+
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+
+/* Some special processing for a MIPS ELF file. */
+
+void
+mips_elf_final_processing ()
+{
+ /* Write out the register information. */
+ if (! mips_64)
+ {
+ Elf32_RegInfo s;
+
+ s.ri_gprmask = mips_gprmask;
+ s.ri_cprmask[0] = mips_cprmask[0];
+ s.ri_cprmask[1] = mips_cprmask[1];
+ s.ri_cprmask[2] = mips_cprmask[2];
+ s.ri_cprmask[3] = mips_cprmask[3];
+ /* The gp_value field is set by the MIPS ELF backend. */
+
+ bfd_mips_elf32_swap_reginfo_out (stdoutput, &s,
+ ((Elf32_External_RegInfo *)
+ mips_regmask_frag));
+ }
+ else
+ {
+ Elf64_Internal_RegInfo s;
+
+ s.ri_gprmask = mips_gprmask;
+ s.ri_pad = 0;
+ s.ri_cprmask[0] = mips_cprmask[0];
+ s.ri_cprmask[1] = mips_cprmask[1];
+ s.ri_cprmask[2] = mips_cprmask[2];
+ s.ri_cprmask[3] = mips_cprmask[3];
+ /* The gp_value field is set by the MIPS ELF backend. */
+
+ bfd_mips_elf64_swap_reginfo_out (stdoutput, &s,
+ ((Elf64_External_RegInfo *)
+ mips_regmask_frag));
+ }
+
+ /* Set the MIPS ELF flag bits. FIXME: There should probably be some
+ sort of BFD interface for this. */
+ if (mips_any_noreorder)
+ elf_elfheader (stdoutput)->e_flags |= EF_MIPS_NOREORDER;
+ if (mips_pic != NO_PIC)
+ elf_elfheader (stdoutput)->e_flags |= EF_MIPS_PIC;
+
+ /* Set the MIPS ELF ABI flags. */
+ if (mips_abi_string == 0)
+ ;
+ else if (strcmp (mips_abi_string,"32") == 0)
+ elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_O32;
+ else if (strcmp (mips_abi_string,"o64") == 0)
+ elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_O64;
+ else if (strcmp (mips_abi_string,"eabi") == 0)
+ {
+ if (mips_eabi64)
+ elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_EABI64;
+ else
+ elf_elfheader (stdoutput)->e_flags |= E_MIPS_ABI_EABI32;
+ }
+
+ if (mips_32bitmode)
+ elf_elfheader (stdoutput)->e_flags |= EF_MIPS_32BITMODE;
+}
+
+#endif /* OBJ_ELF || OBJ_MAYBE_ELF */
+
+typedef struct proc
+ {
+ struct symbol *isym;
+ unsigned long reg_mask;
+ unsigned long reg_offset;
+ unsigned long fpreg_mask;
+ unsigned long fpreg_offset;
+ unsigned long frame_offset;
+ unsigned long frame_reg;
+ unsigned long pc_reg;
+ }
+procS;
+
+static procS cur_proc;
+static procS *cur_proc_ptr;
+static int numprocs;
+
+static void
+md_obj_begin ()
+{
+}
+
+static void
+md_obj_end ()
+{
+ /* check for premature end, nesting errors, etc */
+ if (cur_proc_ptr)
+ as_warn (_("missing `.end' at end of assembly"));
+}
+
+static long
+get_number ()
+{
+ int negative = 0;
+ long val = 0;
+
+ if (*input_line_pointer == '-')
+ {
+ ++input_line_pointer;
+ negative = 1;
+ }
+ if (!isdigit (*input_line_pointer))
+ as_bad (_("Expected simple number."));
+ if (input_line_pointer[0] == '0')
+ {
+ if (input_line_pointer[1] == 'x')
+ {
+ input_line_pointer += 2;
+ while (isxdigit (*input_line_pointer))
+ {
+ val <<= 4;
+ val |= hex_value (*input_line_pointer++);
+ }
+ return negative ? -val : val;
+ }
+ else
+ {
+ ++input_line_pointer;
+ while (isdigit (*input_line_pointer))
+ {
+ val <<= 3;
+ val |= *input_line_pointer++ - '0';
+ }
+ return negative ? -val : val;
+ }
+ }
+ if (!isdigit (*input_line_pointer))
+ {
+ printf (_(" *input_line_pointer == '%c' 0x%02x\n"),
+ *input_line_pointer, *input_line_pointer);
+ as_warn (_("Invalid number"));
+ return -1;
+ }
+ while (isdigit (*input_line_pointer))
+ {
+ val *= 10;
+ val += *input_line_pointer++ - '0';
+ }
+ return negative ? -val : val;
+}
+
+/* The .file directive; just like the usual .file directive, but there
+ is an initial number which is the ECOFF file index. */
+
+static void
+s_file (x)
+ int x;
+{
+ int line;
+
+ line = get_number ();
+ s_app_file (0);
+}
+
+
+/* The .end directive. */
+
+static void
+s_mips_end (x)
+ int x;
+{
+ symbolS *p;
+ int maybe_text;
+
+ if (!is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ p = get_symbol ();
+ demand_empty_rest_of_line ();
+ }
+ else
+ p = NULL;
+
+#ifdef BFD_ASSEMBLER
+ if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
+ maybe_text = 1;
+ else
+ maybe_text = 0;
+#else
+ if (now_seg != data_section && now_seg != bss_section)
+ maybe_text = 1;
+ else
+ maybe_text = 0;
+#endif
+
+ if (!maybe_text)
+ as_warn (_(".end not in text section"));
+
+ if (!cur_proc_ptr)
+ {
+ as_warn (_(".end directive without a preceding .ent directive."));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ if (p != NULL)
+ {
+ assert (S_GET_NAME (p));
+ if (strcmp (S_GET_NAME (p), S_GET_NAME (cur_proc_ptr->isym)))
+ as_warn (_(".end symbol does not match .ent symbol."));
+ }
+ else
+ as_warn (_(".end directive missing or unknown symbol"));
+
+#ifdef MIPS_STABS_ELF
+ {
+ segT saved_seg = now_seg;
+ subsegT saved_subseg = now_subseg;
+ fragS *saved_frag = frag_now;
+ valueT dot;
+ segT seg;
+ expressionS exp;
+ char *fragp;
+
+ dot = frag_now_fix ();
+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+ assert (pdr_seg);
+ subseg_set (pdr_seg, 0);
+
+ /* Write the symbol */
+ exp.X_op = O_symbol;
+ exp.X_add_symbol = p;
+ exp.X_add_number = 0;
+ emit_expr (&exp, 4);
+
+ fragp = frag_more (7*4);
+
+ md_number_to_chars (fragp, (valueT) cur_proc_ptr->reg_mask, 4);
+ md_number_to_chars (fragp + 4, (valueT) cur_proc_ptr->reg_offset, 4);
+ md_number_to_chars (fragp + 8, (valueT) cur_proc_ptr->fpreg_mask, 4);
+ md_number_to_chars (fragp +12, (valueT) cur_proc_ptr->fpreg_offset, 4);
+ md_number_to_chars (fragp +16, (valueT) cur_proc_ptr->frame_offset, 4);
+ md_number_to_chars (fragp +20, (valueT) cur_proc_ptr->frame_reg, 4);
+ md_number_to_chars (fragp +24, (valueT) cur_proc_ptr->pc_reg, 4);
+
+ subseg_set (saved_seg, saved_subseg);
+ }
+#endif
+
+ cur_proc_ptr = NULL;
+}
+
+/* The .aent and .ent directives. */
+
+static void
+s_mips_ent (aent)
+ int aent;
+{
+ int number = 0;
+ symbolS *symbolP;
+ int maybe_text;
+
+ symbolP = get_symbol ();
+ if (*input_line_pointer == ',')
+ input_line_pointer++;
+ SKIP_WHITESPACE ();
+ if (isdigit (*input_line_pointer) || *input_line_pointer == '-')
+ number = get_number ();
+
+#ifdef BFD_ASSEMBLER
+ if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
+ maybe_text = 1;
+ else
+ maybe_text = 0;
+#else
+ if (now_seg != data_section && now_seg != bss_section)
+ maybe_text = 1;
+ else
+ maybe_text = 0;
+#endif
+
+ if (!maybe_text)
+ as_warn (_(".ent or .aent not in text section."));
+
+ if (!aent && cur_proc_ptr)
+ as_warn (_("missing `.end'"));
+
+ if (!aent)
+ {
+ cur_proc_ptr = &cur_proc;
+ memset (cur_proc_ptr, '\0', sizeof (procS));
+
+ cur_proc_ptr->isym = symbolP;
+
+ symbolP->bsym->flags |= BSF_FUNCTION;
+
+ numprocs++;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* The .frame directive. If the mdebug section is present (IRIX 5 native)
+ then ecoff.c (ecoff_directive_frame) is used. For embedded targets,
+ s_mips_frame is used so that we can set the PDR information correctly.
+ We can't use the ecoff routines because they make reference to the ecoff
+ symbol table (in the mdebug section). */
+
+static void
+s_mips_frame (ignore)
+ int ignore;
+{
+#ifdef MIPS_STABS_ELF
+
+ long val;
+
+ if (cur_proc_ptr == (procS *) NULL)
+ {
+ as_warn (_(".frame outside of .ent"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ cur_proc_ptr->frame_reg = tc_get_register (1);
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer++ != ','
+ || get_absolute_expression_and_terminator (&val) != ',')
+ {
+ as_warn (_("Bad .frame directive"));
+ --input_line_pointer;
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ cur_proc_ptr->frame_offset = val;
+ cur_proc_ptr->pc_reg = tc_get_register (0);
+
+ demand_empty_rest_of_line ();
+#else
+ s_ignore (ignore);
+#endif /* MIPS_STABS_ELF */
+}
+
+/* The .fmask and .mask directives. If the mdebug section is present
+ (IRIX 5 native) then ecoff.c (ecoff_directive_mask) is used. For
+ embedded targets, s_mips_mask is used so that we can set the PDR
+ information correctly. We can't use the ecoff routines because they
+ make reference to the ecoff symbol table (in the mdebug section). */
+
+static void
+s_mips_mask (reg_type)
+ char reg_type;
+{
+#ifdef MIPS_STABS_ELF
+ long mask, off;
+
+ if (cur_proc_ptr == (procS *) NULL)
+ {
+ as_warn (_(".mask/.fmask outside of .ent"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ if (get_absolute_expression_and_terminator (&mask) != ',')
+ {
+ as_warn (_("Bad .mask/.fmask directive"));
+ --input_line_pointer;
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ off = get_absolute_expression ();
+
+ if (reg_type == 'F')
+ {
+ cur_proc_ptr->fpreg_mask = mask;
+ cur_proc_ptr->fpreg_offset = off;
+ }
+ else
+ {
+ cur_proc_ptr->reg_mask = mask;
+ cur_proc_ptr->reg_offset = off;
+ }
+
+ demand_empty_rest_of_line ();
+#else
+ s_ignore (reg_type);
+#endif /* MIPS_STABS_ELF */
+}
+
+/* The .loc directive. */
+
+#if 0
+static void
+s_loc (x)
+ int x;
+{
+ symbolS *symbolP;
+ int lineno;
+ int addroff;
+
+ assert (now_seg == text_section);
+
+ lineno = get_number ();
+ addroff = frag_now_fix ();
+
+ symbolP = symbol_new ("", N_SLINE, addroff, frag_now);
+ S_SET_TYPE (symbolP, N_SLINE);
+ S_SET_OTHER (symbolP, 0);
+ S_SET_DESC (symbolP, lineno);
+ symbolP->sy_segment = now_seg;
+}
+#endif
+
+
+
diff --git a/gas/config/tc-mips.h b/gas/config/tc-mips.h
new file mode 100644
index 0000000000..868aedea6a
--- /dev/null
+++ b/gas/config/tc-mips.h
@@ -0,0 +1,153 @@
+/* tc-mips.h -- header file for tc-mips.c.
+ Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+ Contributed by the OSF and Ralph Campbell.
+ Written by Keith Knowles and Ralph Campbell, working independently.
+ Modified for ECOFF support by Ian Lance Taylor of Cygnus Support.
+
+ This file is part of GAS.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#ifndef TC_MIPS
+
+#define TC_MIPS
+
+#ifdef ANSI_PROTOTYPES
+struct frag;
+struct expressionS;
+#endif
+
+/* Default to big endian. */
+#ifndef TARGET_BYTES_BIG_ENDIAN
+#define TARGET_BYTES_BIG_ENDIAN 1
+#endif
+
+#define TARGET_ARCH bfd_arch_mips
+
+#define ONLY_STANDARD_ESCAPES
+#define WORKING_DOT_WORD 1
+#define OLD_FLOAT_READS
+#define REPEAT_CONS_EXPRESSIONS
+#define RELOC_EXPANSION_POSSIBLE
+#define MAX_RELOC_EXPANSION 3
+#define LOCAL_LABELS_FB 1
+
+/* Maximum symbol offset that can be encoded in a BFD_RELOC_MIPS_GPREL
+ relocation: */
+#define MAX_GPREL_OFFSET (0x7FF4)
+
+#define md_relax_frag(fragp, stretch) mips_relax_frag(fragp, stretch)
+extern int mips_relax_frag PARAMS ((struct frag *, long));
+
+#define md_undefined_symbol(name) (0)
+#define md_operand(x)
+
+/* We permit PC relative difference expressions when generating
+ embedded PIC code. */
+#define DIFF_EXPR_OK
+
+/* Tell assembler that we have an itbl_mips.h header file to include. */
+#define HAVE_ITBL_CPU
+
+/* The endianness of the target format may change based on command
+ line arguments. */
+#define TARGET_FORMAT mips_target_format()
+extern const char *mips_target_format PARAMS ((void));
+
+struct mips_cl_insn
+{
+ unsigned long insn_opcode;
+ const struct mips_opcode *insn_mo;
+ /* The next two fields are used when generating mips16 code. */
+ boolean use_extend;
+ unsigned short extend;
+};
+
+extern int tc_get_register PARAMS ((int frame));
+
+#define tc_init_after_args() mips_init_after_args()
+extern void mips_init_after_args PARAMS ((void));
+
+#define md_parse_long_option(arg) mips_parse_long_option (arg)
+extern int mips_parse_long_option PARAMS ((const char *));
+
+#define tc_frob_label(sym) mips_define_label (sym)
+extern void mips_define_label PARAMS ((struct symbol *));
+
+#define tc_frob_file_before_adjust() mips_frob_file_before_adjust ()
+extern void mips_frob_file_before_adjust PARAMS ((void));
+
+#define tc_frob_file() mips_frob_file ()
+extern void mips_frob_file PARAMS ((void));
+
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+#define tc_frob_file_after_relocs mips_frob_file_after_relocs
+extern void mips_frob_file_after_relocs PARAMS ((void));
+#endif
+
+#define TC_CONS_FIX_NEW cons_fix_new_mips
+extern void cons_fix_new_mips
+ PARAMS ((struct frag *, int, unsigned int, struct expressionS *));
+
+#define tc_fix_adjustable(fixp) mips_fix_adjustable (fixp)
+extern int mips_fix_adjustable PARAMS ((struct fix *));
+
+/* When generating embedded PIC code we must keep PC relative
+ relocations. */
+#define TC_FORCE_RELOCATION(fixp) mips_force_relocation (fixp)
+extern int mips_force_relocation PARAMS ((struct fix *));
+
+/* md_apply_fix sets fx_done correctly. */
+#define TC_HANDLE_FX_DONE 1
+
+/* Register mask variables. These are set by the MIPS assembly code
+ and used by ECOFF and possibly other object file formats. */
+extern unsigned long mips_gprmask;
+extern unsigned long mips_cprmask[4];
+
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+
+#define elf_tc_final_processing mips_elf_final_processing
+extern void mips_elf_final_processing PARAMS ((void));
+
+#define ELF_TC_SPECIAL_SECTIONS \
+ { ".sdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL }, \
+ { ".sbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL }, \
+ { ".lit4", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL }, \
+ { ".lit8", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL }, \
+ { ".ucode", SHT_MIPS_UCODE, 0 }, \
+ { ".mdebug", SHT_MIPS_DEBUG, 0 },
+/* Other special sections not generated by the assembler: .reginfo,
+ .liblist, .conflict, .gptab, .got, .dynamic, .rel.dyn. */
+
+#endif
+
+extern void md_mips_end PARAMS ((void));
+#define md_end() md_mips_end()
+
+#define USE_GLOBAL_POINTER_OPT (OUTPUT_FLAVOR == bfd_target_ecoff_flavour \
+ || OUTPUT_FLAVOR == bfd_target_elf_flavour)
+
+extern void mips_pop_insert PARAMS ((void));
+#define md_pop_insert() mips_pop_insert()
+
+extern void mips_flush_pending_output PARAMS ((void));
+#define md_flush_pending_output mips_flush_pending_output
+
+extern void mips_enable_auto_align PARAMS ((void));
+#define md_elf_section_change_hook() mips_enable_auto_align()
+
+#endif /* TC_MIPS */
diff --git a/gas/config/tc-mn10200.c b/gas/config/tc-mn10200.c
new file mode 100644
index 0000000000..2380915910
--- /dev/null
+++ b/gas/config/tc-mn10200.c
@@ -0,0 +1,1414 @@
+/* tc-mn10200.c -- Assembler code for the Matsushita 10200
+
+ Copyright (C) 1996, 1997, 1998 Free Software Foundation.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "as.h"
+#include "subsegs.h"
+#include "opcode/mn10200.h"
+
+/* Structure to hold information about predefined registers. */
+struct reg_name
+{
+ const char *name;
+ int value;
+};
+
+/* Generic assembler global variables which must be defined by all targets. */
+
+/* Characters which always start a comment. */
+const char comment_chars[] = "#";
+
+/* Characters which start a comment at the beginning of a line. */
+const char line_comment_chars[] = ";#";
+
+/* Characters which may be used to separate multiple commands on a
+ single line. */
+const char line_separator_chars[] = ";";
+
+/* Characters which are used to indicate an exponent in a floating
+ point number. */
+const char EXP_CHARS[] = "eE";
+
+/* Characters which mean that a number is a floating point constant,
+ as in 0d1.0. */
+const char FLT_CHARS[] = "dD";
+
+
+const relax_typeS md_relax_table[] = {
+ /* bCC relaxing */
+ {0x81, -0x7e, 2, 1},
+ {0x8004, -0x7ffb, 5, 2},
+ {0x800006, -0x7ffff9, 7, 0},
+ /* bCCx relaxing */
+ {0x81, -0x7e, 3, 4},
+ {0x8004, -0x7ffb, 6, 5},
+ {0x800006, -0x7ffff9, 8, 0},
+ /* jsr relaxing */
+ {0x8004, -0x7ffb, 3, 7},
+ {0x800006, -0x7ffff9, 5, 0},
+ /* jmp relaxing */
+ {0x81, -0x7e, 2, 9},
+ {0x8004, -0x7ffb, 3, 10},
+ {0x800006, -0x7ffff9, 5, 0},
+
+};
+/* local functions */
+static void mn10200_insert_operand PARAMS ((unsigned long *, unsigned long *,
+ const struct mn10200_operand *,
+ offsetT, char *, unsigned,
+ unsigned));
+static unsigned long check_operand PARAMS ((unsigned long,
+ const struct mn10200_operand *,
+ offsetT));
+static int reg_name_search PARAMS ((const struct reg_name *, int, const char *));
+static boolean data_register_name PARAMS ((expressionS *expressionP));
+static boolean address_register_name PARAMS ((expressionS *expressionP));
+static boolean other_register_name PARAMS ((expressionS *expressionP));
+
+
+/* fixups */
+#define MAX_INSN_FIXUPS (5)
+struct mn10200_fixup
+{
+ expressionS exp;
+ int opindex;
+ bfd_reloc_code_real_type reloc;
+};
+struct mn10200_fixup fixups[MAX_INSN_FIXUPS];
+static int fc;
+
+const char *md_shortopts = "";
+struct option md_longopts[] = {
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof(md_longopts);
+
+/* The target specific pseudo-ops which we support. */
+const pseudo_typeS md_pseudo_table[] =
+{
+ { NULL, NULL, 0 }
+};
+
+/* Opcode hash table. */
+static struct hash_control *mn10200_hash;
+
+/* This table is sorted. Suitable for searching by a binary search. */
+static const struct reg_name data_registers[] =
+{
+ { "d0", 0 },
+ { "d1", 1 },
+ { "d2", 2 },
+ { "d3", 3 },
+};
+#define DATA_REG_NAME_CNT (sizeof(data_registers) / sizeof(struct reg_name))
+
+static const struct reg_name address_registers[] =
+{
+ { "a0", 0 },
+ { "a1", 1 },
+ { "a2", 2 },
+ { "a3", 3 },
+};
+#define ADDRESS_REG_NAME_CNT (sizeof(address_registers) / sizeof(struct reg_name))
+
+static const struct reg_name other_registers[] =
+{
+ { "mdr", 0 },
+ { "psw", 0 },
+};
+#define OTHER_REG_NAME_CNT (sizeof(other_registers) / sizeof(struct reg_name))
+
+/* reg_name_search does a binary search of the given register table
+ to see if "name" is a valid regiter name. Returns the register
+ number from the array on success, or -1 on failure. */
+
+static int
+reg_name_search (regs, regcount, name)
+ const struct reg_name *regs;
+ int regcount;
+ const char *name;
+{
+ int middle, low, high;
+ int cmp;
+
+ low = 0;
+ high = regcount - 1;
+
+ do
+ {
+ middle = (low + high) / 2;
+ cmp = strcasecmp (name, regs[middle].name);
+ if (cmp < 0)
+ high = middle - 1;
+ else if (cmp > 0)
+ low = middle + 1;
+ else
+ return regs[middle].value;
+ }
+ while (low <= high);
+ return -1;
+}
+
+
+/* Summary of register_name().
+ *
+ * in: Input_line_pointer points to 1st char of operand.
+ *
+ * out: A expressionS.
+ * The operand may have been a register: in this case, X_op == O_register,
+ * X_add_number is set to the register number, and truth is returned.
+ * Input_line_pointer->(next non-blank) char after operand, or is in
+ * its original state.
+ */
+static boolean
+data_register_name (expressionP)
+ expressionS *expressionP;
+{
+ int reg_number;
+ char *name;
+ char *start;
+ char c;
+
+ /* Find the spelling of the operand */
+ start = name = input_line_pointer;
+
+ c = get_symbol_end ();
+ reg_number = reg_name_search (data_registers, DATA_REG_NAME_CNT, name);
+
+ /* look to see if it's in the register table */
+ if (reg_number >= 0)
+ {
+ expressionP->X_op = O_register;
+ expressionP->X_add_number = reg_number;
+
+ /* make the rest nice */
+ expressionP->X_add_symbol = NULL;
+ expressionP->X_op_symbol = NULL;
+ *input_line_pointer = c; /* put back the delimiting char */
+ return true;
+ }
+ else
+ {
+ /* reset the line as if we had not done anything */
+ *input_line_pointer = c; /* put back the delimiting char */
+ input_line_pointer = start; /* reset input_line pointer */
+ return false;
+ }
+}
+
+/* Summary of register_name().
+ *
+ * in: Input_line_pointer points to 1st char of operand.
+ *
+ * out: A expressionS.
+ * The operand may have been a register: in this case, X_op == O_register,
+ * X_add_number is set to the register number, and truth is returned.
+ * Input_line_pointer->(next non-blank) char after operand, or is in
+ * its original state.
+ */
+static boolean
+address_register_name (expressionP)
+ expressionS *expressionP;
+{
+ int reg_number;
+ char *name;
+ char *start;
+ char c;
+
+ /* Find the spelling of the operand */
+ start = name = input_line_pointer;
+
+ c = get_symbol_end ();
+ reg_number = reg_name_search (address_registers, ADDRESS_REG_NAME_CNT, name);
+
+ /* look to see if it's in the register table */
+ if (reg_number >= 0)
+ {
+ expressionP->X_op = O_register;
+ expressionP->X_add_number = reg_number;
+
+ /* make the rest nice */
+ expressionP->X_add_symbol = NULL;
+ expressionP->X_op_symbol = NULL;
+ *input_line_pointer = c; /* put back the delimiting char */
+ return true;
+ }
+ else
+ {
+ /* reset the line as if we had not done anything */
+ *input_line_pointer = c; /* put back the delimiting char */
+ input_line_pointer = start; /* reset input_line pointer */
+ return false;
+ }
+}
+
+/* Summary of register_name().
+ *
+ * in: Input_line_pointer points to 1st char of operand.
+ *
+ * out: A expressionS.
+ * The operand may have been a register: in this case, X_op == O_register,
+ * X_add_number is set to the register number, and truth is returned.
+ * Input_line_pointer->(next non-blank) char after operand, or is in
+ * its original state.
+ */
+static boolean
+other_register_name (expressionP)
+ expressionS *expressionP;
+{
+ int reg_number;
+ char *name;
+ char *start;
+ char c;
+
+ /* Find the spelling of the operand */
+ start = name = input_line_pointer;
+
+ c = get_symbol_end ();
+ reg_number = reg_name_search (other_registers, OTHER_REG_NAME_CNT, name);
+
+ /* look to see if it's in the register table */
+ if (reg_number >= 0)
+ {
+ expressionP->X_op = O_register;
+ expressionP->X_add_number = reg_number;
+
+ /* make the rest nice */
+ expressionP->X_add_symbol = NULL;
+ expressionP->X_op_symbol = NULL;
+ *input_line_pointer = c; /* put back the delimiting char */
+ return true;
+ }
+ else
+ {
+ /* reset the line as if we had not done anything */
+ *input_line_pointer = c; /* put back the delimiting char */
+ input_line_pointer = start; /* reset input_line pointer */
+ return false;
+ }
+}
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+ fprintf(stream, _("MN10200 options:\n\
+none yet\n"));
+}
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ return 0;
+}
+
+symbolS *
+md_undefined_symbol (name)
+ char *name;
+{
+ return 0;
+}
+
+char *
+md_atof (type, litp, sizep)
+ int type;
+ char *litp;
+ int *sizep;
+{
+ int prec;
+ LITTLENUM_TYPE words[4];
+ char *t;
+ int i;
+
+ switch (type)
+ {
+ case 'f':
+ prec = 2;
+ break;
+
+ case 'd':
+ prec = 4;
+ break;
+
+ default:
+ *sizep = 0;
+ return _("bad call to md_atof");
+ }
+
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+
+ *sizep = prec * 2;
+
+ for (i = prec - 1; i >= 0; i--)
+ {
+ md_number_to_chars (litp, (valueT) words[i], 2);
+ litp += 2;
+ }
+
+ return NULL;
+}
+
+
+void
+md_convert_frag (abfd, sec, fragP)
+ bfd *abfd;
+ asection *sec;
+ fragS *fragP;
+{
+ static unsigned long label_count = 0;
+ char buf[40];
+
+ subseg_change (sec, 0);
+ if (fragP->fr_subtype == 0)
+ {
+ fix_new (fragP, fragP->fr_fix + 1, 1, fragP->fr_symbol,
+ fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 2;
+ }
+ else if (fragP->fr_subtype == 1)
+ {
+ /* Reverse the condition of the first branch. */
+ int offset = fragP->fr_fix;
+ int opcode = fragP->fr_literal[offset] & 0xff;
+
+ switch (opcode)
+ {
+ case 0xe8:
+ opcode = 0xe9;
+ break;
+ case 0xe9:
+ opcode = 0xe8;
+ break;
+ case 0xe0:
+ opcode = 0xe2;
+ break;
+ case 0xe2:
+ opcode = 0xe0;
+ break;
+ case 0xe3:
+ opcode = 0xe1;
+ break;
+ case 0xe1:
+ opcode = 0xe3;
+ break;
+ case 0xe4:
+ opcode = 0xe6;
+ break;
+ case 0xe6:
+ opcode = 0xe4;
+ break;
+ case 0xe7:
+ opcode = 0xe5;
+ break;
+ case 0xe5:
+ opcode = 0xe7;
+ break;
+ default:
+ abort ();
+ }
+ fragP->fr_literal[offset] = opcode;
+
+ /* Create a fixup for the reversed conditional branch. */
+ sprintf (buf, ".%s_%d", FAKE_LABEL_NAME, label_count++);
+ fix_new (fragP, fragP->fr_fix + 1, 1,
+ symbol_new (buf, sec, 0, fragP->fr_next),
+ fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
+
+ /* Now create the unconditional branch + fixup to the
+ final target. */
+ fragP->fr_literal[offset + 2] = 0xfc;
+ fix_new (fragP, fragP->fr_fix + 3, 2, fragP->fr_symbol,
+ fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 5;
+ }
+ else if (fragP->fr_subtype == 2)
+ {
+ /* Reverse the condition of the first branch. */
+ int offset = fragP->fr_fix;
+ int opcode = fragP->fr_literal[offset] & 0xff;
+
+ switch (opcode)
+ {
+ case 0xe8:
+ opcode = 0xe9;
+ break;
+ case 0xe9:
+ opcode = 0xe8;
+ break;
+ case 0xe0:
+ opcode = 0xe2;
+ break;
+ case 0xe2:
+ opcode = 0xe0;
+ break;
+ case 0xe3:
+ opcode = 0xe1;
+ break;
+ case 0xe1:
+ opcode = 0xe3;
+ break;
+ case 0xe4:
+ opcode = 0xe6;
+ break;
+ case 0xe6:
+ opcode = 0xe4;
+ break;
+ case 0xe7:
+ opcode = 0xe5;
+ break;
+ case 0xe5:
+ opcode = 0xe7;
+ break;
+ default:
+ abort ();
+ }
+ fragP->fr_literal[offset] = opcode;
+
+ /* Create a fixup for the reversed conditional branch. */
+ sprintf (buf, ".%s_%d", FAKE_LABEL_NAME, label_count++);
+ fix_new (fragP, fragP->fr_fix + 1, 1,
+ symbol_new (buf, sec, 0, fragP->fr_next),
+ fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
+
+ /* Now create the unconditional branch + fixup to the
+ final target. */
+ fragP->fr_literal[offset + 2] = 0xf4;
+ fragP->fr_literal[offset + 3] = 0xe0;
+ fix_new (fragP, fragP->fr_fix + 4, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, BFD_RELOC_24_PCREL);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 7;
+ }
+ else if (fragP->fr_subtype == 3)
+ {
+ fix_new (fragP, fragP->fr_fix + 2, 1, fragP->fr_symbol,
+ fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 3;
+ }
+ else if (fragP->fr_subtype == 4)
+ {
+ /* Reverse the condition of the first branch. */
+ int offset = fragP->fr_fix;
+ int opcode = fragP->fr_literal[offset + 1] & 0xff;
+
+ switch (opcode)
+ {
+ case 0xfc:
+ opcode = 0xfd;
+ break;
+ case 0xfd:
+ opcode = 0xfc;
+ break;
+ case 0xfe:
+ opcode = 0xff;
+ break;
+ case 0xff:
+ opcode = 0xfe;
+ case 0xe8:
+ opcode = 0xe9;
+ break;
+ case 0xe9:
+ opcode = 0xe8;
+ break;
+ case 0xe0:
+ opcode = 0xe2;
+ break;
+ case 0xe2:
+ opcode = 0xe0;
+ break;
+ case 0xe3:
+ opcode = 0xe1;
+ break;
+ case 0xe1:
+ opcode = 0xe3;
+ break;
+ case 0xe4:
+ opcode = 0xe6;
+ break;
+ case 0xe6:
+ opcode = 0xe4;
+ break;
+ case 0xe7:
+ opcode = 0xe5;
+ break;
+ case 0xe5:
+ opcode = 0xe7;
+ break;
+ case 0xec:
+ opcode = 0xed;
+ break;
+ case 0xed:
+ opcode = 0xec;
+ break;
+ case 0xee:
+ opcode = 0xef;
+ break;
+ case 0xef:
+ opcode = 0xee;
+ break;
+ default:
+ abort ();
+ }
+ fragP->fr_literal[offset + 1] = opcode;
+
+ /* Create a fixup for the reversed conditional branch. */
+ sprintf (buf, ".%s_%d", FAKE_LABEL_NAME, label_count++);
+ fix_new (fragP, fragP->fr_fix + 2, 1,
+ symbol_new (buf, sec, 0, fragP->fr_next),
+ fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
+
+ /* Now create the unconditional branch + fixup to the
+ final target. */
+ fragP->fr_literal[offset + 3] = 0xfc;
+ fix_new (fragP, fragP->fr_fix + 4, 2, fragP->fr_symbol,
+ fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 6;
+ }
+ else if (fragP->fr_subtype == 5)
+ {
+ /* Reverse the condition of the first branch. */
+ int offset = fragP->fr_fix;
+ int opcode = fragP->fr_literal[offset + 1] & 0xff;
+
+ switch (opcode)
+ {
+ case 0xfc:
+ opcode = 0xfd;
+ break;
+ case 0xfd:
+ opcode = 0xfc;
+ break;
+ case 0xfe:
+ opcode = 0xff;
+ break;
+ case 0xff:
+ opcode = 0xfe;
+ case 0xe8:
+ opcode = 0xe9;
+ break;
+ case 0xe9:
+ opcode = 0xe8;
+ break;
+ case 0xe0:
+ opcode = 0xe2;
+ break;
+ case 0xe2:
+ opcode = 0xe0;
+ break;
+ case 0xe3:
+ opcode = 0xe1;
+ break;
+ case 0xe1:
+ opcode = 0xe3;
+ break;
+ case 0xe4:
+ opcode = 0xe6;
+ break;
+ case 0xe6:
+ opcode = 0xe4;
+ break;
+ case 0xe7:
+ opcode = 0xe5;
+ break;
+ case 0xe5:
+ opcode = 0xe7;
+ break;
+ case 0xec:
+ opcode = 0xed;
+ break;
+ case 0xed:
+ opcode = 0xec;
+ break;
+ case 0xee:
+ opcode = 0xef;
+ break;
+ case 0xef:
+ opcode = 0xee;
+ break;
+ default:
+ abort ();
+ }
+ fragP->fr_literal[offset + 1] = opcode;
+
+ /* Create a fixup for the reversed conditional branch. */
+ sprintf (buf, ".%s_%d", FAKE_LABEL_NAME, label_count++);
+ fix_new (fragP, fragP->fr_fix + 2, 1,
+ symbol_new (buf, sec, 0, fragP->fr_next),
+ fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
+
+ /* Now create the unconditional branch + fixup to the
+ final target. */
+ fragP->fr_literal[offset + 3] = 0xf4;
+ fragP->fr_literal[offset + 4] = 0xe0;
+ fix_new (fragP, fragP->fr_fix + 5, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, BFD_RELOC_24_PCREL);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 8;
+ }
+ else if (fragP->fr_subtype == 6)
+ {
+ fix_new (fragP, fragP->fr_fix + 1, 2, fragP->fr_symbol,
+ fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 3;
+ }
+ else if (fragP->fr_subtype == 7)
+ {
+ int offset = fragP->fr_fix;
+ fragP->fr_literal[offset] = 0xf4;
+ fragP->fr_literal[offset + 1] = 0xe1;
+
+ fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, BFD_RELOC_24_PCREL);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 5;
+ }
+ else if (fragP->fr_subtype == 8)
+ {
+ fragP->fr_literal[fragP->fr_fix] = 0xea;
+ fix_new (fragP, fragP->fr_fix + 1, 1, fragP->fr_symbol,
+ fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 2;
+ }
+ else if (fragP->fr_subtype == 9)
+ {
+ int offset = fragP->fr_fix;
+ fragP->fr_literal[offset] = 0xfc;
+
+ fix_new (fragP, fragP->fr_fix + 1, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 3;
+ }
+ else if (fragP->fr_subtype == 10)
+ {
+ int offset = fragP->fr_fix;
+ fragP->fr_literal[offset] = 0xf4;
+ fragP->fr_literal[offset + 1] = 0xe0;
+
+ fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, BFD_RELOC_24_PCREL);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 5;
+ }
+ else
+ abort ();
+}
+
+valueT
+md_section_align (seg, addr)
+ asection *seg;
+ valueT addr;
+{
+ int align = bfd_get_section_alignment (stdoutput, seg);
+ return ((addr + (1 << align) - 1) & (-1 << align));
+}
+
+void
+md_begin ()
+{
+ char *prev_name = "";
+ register const struct mn10200_opcode *op;
+
+ mn10200_hash = hash_new();
+
+ /* Insert unique names into hash table. The MN10200 instruction set
+ has many identical opcode names that have different opcodes based
+ on the operands. This hash table then provides a quick index to
+ the first opcode with a particular name in the opcode table. */
+
+ op = mn10200_opcodes;
+ while (op->name)
+ {
+ if (strcmp (prev_name, op->name))
+ {
+ prev_name = (char *) op->name;
+ hash_insert (mn10200_hash, op->name, (char *) op);
+ }
+ op++;
+ }
+
+ /* This is both a simplification (we don't have to write md_apply_fix)
+ and support for future optimizations (branch shortening and similar
+ stuff in the linker. */
+ linkrelax = 1;
+}
+
+void
+md_assemble (str)
+ char *str;
+{
+ char *s;
+ struct mn10200_opcode *opcode;
+ struct mn10200_opcode *next_opcode;
+ const unsigned char *opindex_ptr;
+ int next_opindex, relaxable;
+ unsigned long insn, extension, size = 0;
+ char *f;
+ int i;
+ int match;
+
+ /* Get the opcode. */
+ for (s = str; *s != '\0' && ! isspace (*s); s++)
+ ;
+ if (*s != '\0')
+ *s++ = '\0';
+
+ /* find the first opcode with the proper name */
+ opcode = (struct mn10200_opcode *)hash_find (mn10200_hash, str);
+ if (opcode == NULL)
+ {
+ as_bad (_("Unrecognized opcode: `%s'"), str);
+ return;
+ }
+
+ str = s;
+ while (isspace (*str))
+ ++str;
+
+ input_line_pointer = str;
+
+ for(;;)
+ {
+ const char *errmsg = NULL;
+ int op_idx;
+ char *hold;
+ int extra_shift = 0;
+
+ relaxable = 0;
+ fc = 0;
+ match = 0;
+ next_opindex = 0;
+ insn = opcode->opcode;
+ extension = 0;
+ for (op_idx = 1, opindex_ptr = opcode->operands;
+ *opindex_ptr != 0;
+ opindex_ptr++, op_idx++)
+ {
+ const struct mn10200_operand *operand;
+ expressionS ex;
+
+ if (next_opindex == 0)
+ {
+ operand = &mn10200_operands[*opindex_ptr];
+ }
+ else
+ {
+ operand = &mn10200_operands[next_opindex];
+ next_opindex = 0;
+ }
+
+ errmsg = NULL;
+
+ while (*str == ' ' || *str == ',')
+ ++str;
+
+ if (operand->flags & MN10200_OPERAND_RELAX)
+ relaxable = 1;
+
+ /* Gather the operand. */
+ hold = input_line_pointer;
+ input_line_pointer = str;
+
+ if (operand->flags & MN10200_OPERAND_PAREN)
+ {
+ if (*input_line_pointer != ')' && *input_line_pointer != '(')
+ {
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+ input_line_pointer++;
+ goto keep_going;
+ }
+ /* See if we can match the operands. */
+ else if (operand->flags & MN10200_OPERAND_DREG)
+ {
+ if (!data_register_name (&ex))
+ {
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+ }
+ else if (operand->flags & MN10200_OPERAND_AREG)
+ {
+ if (!address_register_name (&ex))
+ {
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+ }
+ else if (operand->flags & MN10200_OPERAND_PSW)
+ {
+ char *start = input_line_pointer;
+ char c = get_symbol_end ();
+
+ if (strcmp (start, "psw") != 0)
+ {
+ *input_line_pointer = c;
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+ *input_line_pointer = c;
+ goto keep_going;
+ }
+ else if (operand->flags & MN10200_OPERAND_MDR)
+ {
+ char *start = input_line_pointer;
+ char c = get_symbol_end ();
+
+ if (strcmp (start, "mdr") != 0)
+ {
+ *input_line_pointer = c;
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+ *input_line_pointer = c;
+ goto keep_going;
+ }
+ else if (data_register_name (&ex))
+ {
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+ else if (address_register_name (&ex))
+ {
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+ else if (other_register_name (&ex))
+ {
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+ else if (*str == ')' || *str == '(')
+ {
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+ else
+ {
+ expression (&ex);
+ }
+
+ switch (ex.X_op)
+ {
+ case O_illegal:
+ errmsg = _("illegal operand");
+ goto error;
+ case O_absent:
+ errmsg = _("missing operand");
+ goto error;
+ case O_register:
+ if ((operand->flags
+ & (MN10200_OPERAND_DREG | MN10200_OPERAND_AREG)) == 0)
+ {
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+
+ if (opcode->format == FMT_2 || opcode->format == FMT_5)
+ extra_shift = 8;
+ else if (opcode->format == FMT_3 || opcode->format == FMT_6
+ || opcode->format == FMT_7)
+ extra_shift = 16;
+ else
+ extra_shift = 0;
+
+ mn10200_insert_operand (&insn, &extension, operand,
+ ex.X_add_number, (char *) NULL,
+ 0, extra_shift);
+
+ break;
+
+ case O_constant:
+ /* If this operand can be promoted, and it doesn't
+ fit into the allocated bitfield for this insn,
+ then promote it (ie this opcode does not match). */
+ if (operand->flags
+ & (MN10200_OPERAND_PROMOTE | MN10200_OPERAND_RELAX)
+ && ! check_operand (insn, operand, ex.X_add_number))
+ {
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+
+ mn10200_insert_operand (&insn, &extension, operand,
+ ex.X_add_number, (char *) NULL,
+ 0, 0);
+ break;
+
+ default:
+ /* If this operand can be promoted, then this opcode didn't
+ match since we can't know if it needed promotion! */
+ if (operand->flags & MN10200_OPERAND_PROMOTE)
+ {
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+
+ /* We need to generate a fixup for this expression. */
+ if (fc >= MAX_INSN_FIXUPS)
+ as_fatal (_("too many fixups"));
+ fixups[fc].exp = ex;
+ fixups[fc].opindex = *opindex_ptr;
+ fixups[fc].reloc = BFD_RELOC_UNUSED;
+ ++fc;
+ break;
+ }
+
+keep_going:
+ str = input_line_pointer;
+ input_line_pointer = hold;
+
+ while (*str == ' ' || *str == ',')
+ ++str;
+
+ }
+
+ /* Make sure we used all the operands! */
+ if (*str != ',')
+ match = 1;
+
+ error:
+ if (match == 0)
+ {
+ next_opcode = opcode + 1;
+ if (!strcmp(next_opcode->name, opcode->name))
+ {
+ opcode = next_opcode;
+ continue;
+ }
+
+ as_bad ("%s", errmsg);
+ return;
+ }
+ break;
+ }
+
+ while (isspace (*str))
+ ++str;
+
+ if (*str != '\0')
+ as_bad (_("junk at end of line: `%s'"), str);
+
+ input_line_pointer = str;
+
+ if (opcode->format == FMT_1)
+ size = 1;
+ else if (opcode->format == FMT_2 || opcode->format == FMT_4)
+ size = 2;
+ else if (opcode->format == FMT_3 || opcode->format == FMT_5)
+ size = 3;
+ else if (opcode->format == FMT_6)
+ size = 4;
+ else if (opcode->format == FMT_7)
+ size = 5;
+ else
+ abort ();
+
+ /* Write out the instruction. */
+
+ if (relaxable && fc > 0)
+ {
+ int type;
+
+ /* bCC */
+ if (size == 2 && opcode->opcode != 0xfc0000)
+ {
+ /* Handle bra specially. Basically treat it like jmp so
+ that we automatically handle 8, 16 and 32 bit offsets
+ correctly as well as jumps to an undefined address.
+
+ It is also important to not treat it like other bCC
+ instructions since the long forms of bra is different
+ from other bCC instructions. */
+ if (opcode->opcode == 0xea00)
+ type = 8;
+ else
+ type = 0;
+ }
+ /* jsr */
+ else if (size == 3 && opcode->opcode == 0xfd0000)
+ type = 6;
+ /* jmp */
+ else if (size == 3 && opcode->opcode == 0xfc0000)
+ type = 8;
+ /* bCCx */
+ else
+ type = 3;
+
+ f = frag_var (rs_machine_dependent, 8, 8 - size, type,
+ fixups[0].exp.X_add_symbol,
+ fixups[0].exp.X_add_number,
+ (char *)fixups[0].opindex);
+ number_to_chars_bigendian (f, insn, size);
+ if (8 - size > 4)
+ {
+ number_to_chars_bigendian (f + size, 0, 4);
+ number_to_chars_bigendian (f + size + 4, 0, 8 - size - 4);
+ }
+ else
+ number_to_chars_bigendian (f + size, 0, 8 - size);
+ }
+
+ else
+ {
+ f = frag_more (size);
+
+ /* Oh, what a mess. The instruction is in big endian format, but
+ 16 and 24bit immediates are little endian! */
+ if (opcode->format == FMT_3)
+ {
+ number_to_chars_bigendian (f, (insn >> 16) & 0xff, 1);
+ number_to_chars_littleendian (f + 1, insn & 0xffff, 2);
+ }
+ else if (opcode->format == FMT_6)
+ {
+ number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);
+ number_to_chars_littleendian (f + 2, insn & 0xffff, 2);
+ }
+ else if (opcode->format == FMT_7)
+ {
+ number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);
+ number_to_chars_littleendian (f + 2, insn & 0xffff, 2);
+ number_to_chars_littleendian (f + 4, extension & 0xff, 1);
+ }
+ else
+ {
+ number_to_chars_bigendian (f, insn, size > 4 ? 4 : size);
+ }
+
+ /* Create any fixups. */
+ for (i = 0; i < fc; i++)
+ {
+ const struct mn10200_operand *operand;
+
+ operand = &mn10200_operands[fixups[i].opindex];
+ if (fixups[i].reloc != BFD_RELOC_UNUSED)
+ {
+ reloc_howto_type *reloc_howto;
+ int size;
+ int offset;
+ fixS *fixP;
+
+ reloc_howto = bfd_reloc_type_lookup (stdoutput, fixups[i].reloc);
+
+ if (!reloc_howto)
+ abort();
+
+ size = bfd_get_reloc_size (reloc_howto);
+
+ if (size < 1 || size > 4)
+ abort();
+
+ offset = 4 - size;
+ fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset,
+ size,
+ &fixups[i].exp,
+ reloc_howto->pc_relative,
+ fixups[i].reloc);
+
+ /* PC-relative offsets are from the first byte of the next
+ instruction, not from the start of the current instruction. */
+ if (reloc_howto->pc_relative)
+ fixP->fx_offset += size;
+ }
+ else
+ {
+ int reloc, pcrel, reloc_size, offset;
+ fixS *fixP;
+
+ reloc = BFD_RELOC_NONE;
+ /* How big is the reloc? Remember SPLIT relocs are
+ implicitly 32bits. */
+ reloc_size = operand->bits;
+
+ offset = size - reloc_size / 8;
+
+ /* Is the reloc pc-relative? */
+ pcrel = (operand->flags & MN10200_OPERAND_PCREL) != 0;
+
+
+ /* Choose a proper BFD relocation type. */
+ if (pcrel)
+ {
+ if (reloc_size == 8)
+ reloc = BFD_RELOC_8_PCREL;
+ else if (reloc_size == 24)
+ reloc = BFD_RELOC_24_PCREL;
+ else
+ abort ();
+ }
+ else
+ {
+ if (reloc_size == 32)
+ reloc = BFD_RELOC_32;
+ else if (reloc_size == 16)
+ reloc = BFD_RELOC_16;
+ else if (reloc_size == 8)
+ reloc = BFD_RELOC_8;
+ else if (reloc_size == 24)
+ reloc = BFD_RELOC_24;
+ else
+ abort ();
+ }
+
+ /* Convert the size of the reloc into what fix_new_exp wants. */
+ reloc_size = reloc_size / 8;
+ if (reloc_size == 8)
+ reloc_size = 0;
+ else if (reloc_size == 16)
+ reloc_size = 1;
+ else if (reloc_size == 32 || reloc_size == 24)
+ reloc_size = 2;
+
+ fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset,
+ reloc_size, &fixups[i].exp, pcrel,
+ ((bfd_reloc_code_real_type) reloc));
+
+ /* PC-relative offsets are from the first byte of the next
+ instruction, not from the start of the current instruction. */
+ if (pcrel)
+ fixP->fx_offset += size;
+ }
+ }
+ }
+}
+
+
+/* if while processing a fixup, a reloc really needs to be created */
+/* then it is done here */
+
+arelent *
+tc_gen_reloc (seg, fixp)
+ asection *seg;
+ fixS *fixp;
+{
+ arelent *reloc;
+ reloc = (arelent *) xmalloc (sizeof (arelent));
+
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
+ if (reloc->howto == (reloc_howto_type *) NULL)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("reloc %d not supported by object file format"),
+ (int)fixp->fx_r_type);
+ return NULL;
+ }
+ reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+
+ if (fixp->fx_addsy && fixp->fx_subsy)
+ {
+ if ((S_GET_SEGMENT (fixp->fx_addsy) != S_GET_SEGMENT (fixp->fx_subsy))
+ || S_GET_SEGMENT (fixp->fx_addsy) == undefined_section)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ "Difference of symbols in different sections is not supported");
+ return NULL;
+ }
+ reloc->sym_ptr_ptr = &bfd_abs_symbol;
+ reloc->addend = (S_GET_VALUE (fixp->fx_addsy)
+ - S_GET_VALUE (fixp->fx_subsy) + fixp->fx_offset);
+ }
+ else
+ {
+ reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+ reloc->addend = fixp->fx_offset;
+ }
+ return reloc;
+}
+
+int
+md_estimate_size_before_relax (fragp, seg)
+ fragS *fragp;
+ asection *seg;
+{
+ if (fragp->fr_subtype == 0)
+ return 2;
+ if (fragp->fr_subtype == 3)
+ return 3;
+ if (fragp->fr_subtype == 6)
+ {
+ if (!S_IS_DEFINED (fragp->fr_symbol)
+ || seg != S_GET_SEGMENT (fragp->fr_symbol))
+ {
+ fragp->fr_subtype = 7;
+ return 5;
+ }
+ return 3;
+ }
+ if (fragp->fr_subtype == 8)
+ {
+ if (!S_IS_DEFINED (fragp->fr_symbol))
+ {
+ fragp->fr_subtype = 10;
+ return 5;
+ }
+ return 2;
+ }
+}
+
+long
+md_pcrel_from (fixp)
+ fixS *fixp;
+{
+ return fixp->fx_frag->fr_address;
+#if 0
+ if (fixp->fx_addsy != (symbolS *) NULL && ! S_IS_DEFINED (fixp->fx_addsy))
+ {
+ /* The symbol is undefined. Let the linker figure it out. */
+ return 0;
+ }
+ return fixp->fx_frag->fr_address + fixp->fx_where;
+#endif
+}
+
+int
+md_apply_fix3 (fixp, valuep, seg)
+ fixS *fixp;
+ valueT *valuep;
+ segT seg;
+{
+ /* We shouldn't ever get here because linkrelax is nonzero. */
+ abort ();
+ fixp->fx_done = 1;
+ return 0;
+}
+
+/* Insert an operand value into an instruction. */
+
+static void
+mn10200_insert_operand (insnp, extensionp, operand, val, file, line, shift)
+ unsigned long *insnp;
+ unsigned long *extensionp;
+ const struct mn10200_operand *operand;
+ offsetT val;
+ char *file;
+ unsigned int line;
+ unsigned int shift;
+{
+ /* No need to check 24 or 32bit operands for a bit. */
+ if (operand->bits < 24
+ && (operand->flags & MN10200_OPERAND_NOCHECK) == 0)
+ {
+ long min, max;
+ offsetT test;
+
+ if ((operand->flags & MN10200_OPERAND_SIGNED) != 0)
+ {
+ max = (1 << (operand->bits - 1)) - 1;
+ min = - (1 << (operand->bits - 1));
+ }
+ else
+ {
+ max = (1 << operand->bits) - 1;
+ min = 0;
+ }
+
+ test = val;
+
+
+ if (test < (offsetT) min || test > (offsetT) max)
+ {
+ const char *err =
+ _("operand out of range (%s not between %ld and %ld)");
+ char buf[100];
+
+ sprint_value (buf, test);
+ if (file == (char *) NULL)
+ as_warn (err, buf, min, max);
+ else
+ as_warn_where (file, line, err, buf, min, max);
+ }
+ }
+
+ if ((operand->flags & MN10200_OPERAND_EXTENDED) == 0)
+ {
+ *insnp |= (((long) val & ((1 << operand->bits) - 1))
+ << (operand->shift + shift));
+
+ if ((operand->flags & MN10200_OPERAND_REPEATED) != 0)
+ *insnp |= (((long) val & ((1 << operand->bits) - 1))
+ << (operand->shift + shift + 2));
+ }
+ else
+ {
+ *extensionp |= (val >> 16) & 0xff;
+ *insnp |= val & 0xffff;
+ }
+}
+
+static unsigned long
+check_operand (insn, operand, val)
+ unsigned long insn;
+ const struct mn10200_operand *operand;
+ offsetT val;
+{
+ /* No need to check 24bit or 32bit operands for a bit. */
+ if (operand->bits < 24
+ && (operand->flags & MN10200_OPERAND_NOCHECK) == 0)
+ {
+ long min, max;
+ offsetT test;
+
+ if ((operand->flags & MN10200_OPERAND_SIGNED) != 0)
+ {
+ max = (1 << (operand->bits - 1)) - 1;
+ min = - (1 << (operand->bits - 1));
+ }
+ else
+ {
+ max = (1 << operand->bits) - 1;
+ min = 0;
+ }
+
+ test = val;
+
+
+ if (test < (offsetT) min || test > (offsetT) max)
+ return 0;
+ else
+ return 1;
+ }
+ return 1;
+}
diff --git a/gas/config/tc-mn10200.h b/gas/config/tc-mn10200.h
new file mode 100644
index 0000000000..e53e569c09
--- /dev/null
+++ b/gas/config/tc-mn10200.h
@@ -0,0 +1,51 @@
+/* tc-mn10200.h -- Header file for tc-mn10200.c.
+ Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#define TC_MN10200
+
+#define TARGET_BYTES_BIG_ENDIAN 0
+
+#ifndef BFD_ASSEMBLER
+ #error MN10200 support requires BFD_ASSEMBLER
+#endif
+
+/* The target BFD architecture. */
+#define TARGET_ARCH bfd_arch_mn10200
+
+#define TARGET_FORMAT "elf32-mn10200"
+
+#define MD_APPLY_FIX3
+#define md_operand(x)
+
+/* Permit temporary numeric labels. */
+#define LOCAL_LABELS_FB 1
+
+/* We don't need to handle .word strangely. */
+#define WORKING_DOT_WORD
+
+#define md_number_to_chars number_to_chars_littleendian
+
+/* Don't bother to adjust relocs. */
+#define tc_fix_adjustable(FIX) 0
+
+/* We do relaxing in the assembler as well as the linker. */
+extern const struct relax_type md_relax_table[];
+#define TC_GENERIC_RELAX_TABLE md_relax_table
+
diff --git a/gas/config/tc-mn10300.c b/gas/config/tc-mn10300.c
new file mode 100644
index 0000000000..3f9e9cee7d
--- /dev/null
+++ b/gas/config/tc-mn10300.c
@@ -0,0 +1,1649 @@
+/* tc-mn10300.c -- Assembler code for the Matsushita 10300
+
+ Copyright (C) 1996, 1997, 1998 Free Software Foundation.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "as.h"
+#include "subsegs.h"
+#include "opcode/mn10300.h"
+
+/* Structure to hold information about predefined registers. */
+struct reg_name
+{
+ const char *name;
+ int value;
+};
+
+/* Generic assembler global variables which must be defined by all targets. */
+
+/* Characters which always start a comment. */
+const char comment_chars[] = "#";
+
+/* Characters which start a comment at the beginning of a line. */
+const char line_comment_chars[] = ";#";
+
+/* Characters which may be used to separate multiple commands on a
+ single line. */
+const char line_separator_chars[] = ";";
+
+/* Characters which are used to indicate an exponent in a floating
+ point number. */
+const char EXP_CHARS[] = "eE";
+
+/* Characters which mean that a number is a floating point constant,
+ as in 0d1.0. */
+const char FLT_CHARS[] = "dD";
+
+
+const relax_typeS md_relax_table[] = {
+ /* bCC relaxing */
+ {0x7f, -0x80, 2, 1},
+ {0x7fff, -0x8000, 5, 2},
+ {0x7fffffff, -0x80000000, 7, 0},
+
+ /* bCC relaxing (uncommon cases) */
+ {0x7f, -0x80, 3, 4},
+ {0x7fff, -0x8000, 6, 5},
+ {0x7fffffff, -0x80000000, 8, 0},
+
+ /* call relaxing */
+ {0x7fff, -0x8000, 5, 7},
+ {0x7fffffff, -0x80000000, 7, 0},
+
+ /* calls relaxing */
+ {0x7fff, -0x8000, 4, 9},
+ {0x7fffffff, -0x80000000, 6, 0},
+
+ /* jmp relaxing */
+ {0x7f, -0x80, 2, 11},
+ {0x7fff, -0x8000, 3, 12},
+ {0x7fffffff, -0x80000000, 5, 0},
+
+};
+
+/* local functions */
+static void mn10300_insert_operand PARAMS ((unsigned long *, unsigned long *,
+ const struct mn10300_operand *,
+ offsetT, char *, unsigned,
+ unsigned));
+static unsigned long check_operand PARAMS ((unsigned long,
+ const struct mn10300_operand *,
+ offsetT));
+static int reg_name_search PARAMS ((const struct reg_name *, int, const char *));
+static boolean data_register_name PARAMS ((expressionS *expressionP));
+static boolean address_register_name PARAMS ((expressionS *expressionP));
+static boolean other_register_name PARAMS ((expressionS *expressionP));
+static void set_arch_mach PARAMS ((int));
+
+static int current_machine;
+
+/* fixups */
+#define MAX_INSN_FIXUPS (5)
+struct mn10300_fixup
+{
+ expressionS exp;
+ int opindex;
+ bfd_reloc_code_real_type reloc;
+};
+struct mn10300_fixup fixups[MAX_INSN_FIXUPS];
+static int fc;
+
+/* We must store the value of each register operand so that we can
+ verify that certain registers do not match. */
+int mn10300_reg_operands[MN10300_MAX_OPERANDS];
+
+const char *md_shortopts = "";
+struct option md_longopts[] = {
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof(md_longopts);
+
+/* The target specific pseudo-ops which we support. */
+const pseudo_typeS md_pseudo_table[] =
+{
+ { "am30", set_arch_mach, 300 },
+ { "mn10300", set_arch_mach, 300 },
+ {NULL, 0, 0}
+};
+
+/* Opcode hash table. */
+static struct hash_control *mn10300_hash;
+
+/* This table is sorted. Suitable for searching by a binary search. */
+static const struct reg_name data_registers[] =
+{
+ { "d0", 0 },
+ { "d1", 1 },
+ { "d2", 2 },
+ { "d3", 3 },
+};
+#define DATA_REG_NAME_CNT (sizeof(data_registers) / sizeof(struct reg_name))
+
+static const struct reg_name address_registers[] =
+{
+ { "a0", 0 },
+ { "a1", 1 },
+ { "a2", 2 },
+ { "a3", 3 },
+};
+#define ADDRESS_REG_NAME_CNT (sizeof(address_registers) / sizeof(struct reg_name))
+
+
+static const struct reg_name other_registers[] =
+{
+ { "mdr", 0 },
+ { "psw", 0 },
+ { "sp", 0 },
+};
+#define OTHER_REG_NAME_CNT (sizeof(other_registers) / sizeof(struct reg_name))
+
+/* reg_name_search does a binary search of the given register table
+ to see if "name" is a valid regiter name. Returns the register
+ number from the array on success, or -1 on failure. */
+
+static int
+reg_name_search (regs, regcount, name)
+ const struct reg_name *regs;
+ int regcount;
+ const char *name;
+{
+ int middle, low, high;
+ int cmp;
+
+ low = 0;
+ high = regcount - 1;
+
+ do
+ {
+ middle = (low + high) / 2;
+ cmp = strcasecmp (name, regs[middle].name);
+ if (cmp < 0)
+ high = middle - 1;
+ else if (cmp > 0)
+ low = middle + 1;
+ else
+ return regs[middle].value;
+ }
+ while (low <= high);
+ return -1;
+}
+
+
+
+/* Summary of register_name().
+ *
+ * in: Input_line_pointer points to 1st char of operand.
+ *
+ * out: A expressionS.
+ * The operand may have been a register: in this case, X_op == O_register,
+ * X_add_number is set to the register number, and truth is returned.
+ * Input_line_pointer->(next non-blank) char after operand, or is in
+ * its original state.
+ */
+static boolean
+data_register_name (expressionP)
+ expressionS *expressionP;
+{
+ int reg_number;
+ char *name;
+ char *start;
+ char c;
+
+ /* Find the spelling of the operand */
+ start = name = input_line_pointer;
+
+ c = get_symbol_end ();
+ reg_number = reg_name_search (data_registers, DATA_REG_NAME_CNT, name);
+
+ /* look to see if it's in the register table */
+ if (reg_number >= 0)
+ {
+ expressionP->X_op = O_register;
+ expressionP->X_add_number = reg_number;
+
+ /* make the rest nice */
+ expressionP->X_add_symbol = NULL;
+ expressionP->X_op_symbol = NULL;
+ *input_line_pointer = c; /* put back the delimiting char */
+ return true;
+ }
+ else
+ {
+ /* reset the line as if we had not done anything */
+ *input_line_pointer = c; /* put back the delimiting char */
+ input_line_pointer = start; /* reset input_line pointer */
+ return false;
+ }
+}
+
+/* Summary of register_name().
+ *
+ * in: Input_line_pointer points to 1st char of operand.
+ *
+ * out: A expressionS.
+ * The operand may have been a register: in this case, X_op == O_register,
+ * X_add_number is set to the register number, and truth is returned.
+ * Input_line_pointer->(next non-blank) char after operand, or is in
+ * its original state.
+ */
+static boolean
+address_register_name (expressionP)
+ expressionS *expressionP;
+{
+ int reg_number;
+ char *name;
+ char *start;
+ char c;
+
+ /* Find the spelling of the operand */
+ start = name = input_line_pointer;
+
+ c = get_symbol_end ();
+ reg_number = reg_name_search (address_registers, ADDRESS_REG_NAME_CNT, name);
+
+ /* look to see if it's in the register table */
+ if (reg_number >= 0)
+ {
+ expressionP->X_op = O_register;
+ expressionP->X_add_number = reg_number;
+
+ /* make the rest nice */
+ expressionP->X_add_symbol = NULL;
+ expressionP->X_op_symbol = NULL;
+ *input_line_pointer = c; /* put back the delimiting char */
+ return true;
+ }
+ else
+ {
+ /* reset the line as if we had not done anything */
+ *input_line_pointer = c; /* put back the delimiting char */
+ input_line_pointer = start; /* reset input_line pointer */
+ return false;
+ }
+}
+
+/* Summary of register_name().
+ *
+ * in: Input_line_pointer points to 1st char of operand.
+ *
+ * out: A expressionS.
+ * The operand may have been a register: in this case, X_op == O_register,
+ * X_add_number is set to the register number, and truth is returned.
+ * Input_line_pointer->(next non-blank) char after operand, or is in
+ * its original state.
+ */
+static boolean
+other_register_name (expressionP)
+ expressionS *expressionP;
+{
+ int reg_number;
+ char *name;
+ char *start;
+ char c;
+
+ /* Find the spelling of the operand */
+ start = name = input_line_pointer;
+
+ c = get_symbol_end ();
+ reg_number = reg_name_search (other_registers, OTHER_REG_NAME_CNT, name);
+
+ /* look to see if it's in the register table */
+ if (reg_number >= 0)
+ {
+ expressionP->X_op = O_register;
+ expressionP->X_add_number = reg_number;
+
+ /* make the rest nice */
+ expressionP->X_add_symbol = NULL;
+ expressionP->X_op_symbol = NULL;
+ *input_line_pointer = c; /* put back the delimiting char */
+ return true;
+ }
+ else
+ {
+ /* reset the line as if we had not done anything */
+ *input_line_pointer = c; /* put back the delimiting char */
+ input_line_pointer = start; /* reset input_line pointer */
+ return false;
+ }
+}
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+ fprintf(stream, _("MN10300 options:\n\
+none yet\n"));
+}
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ return 0;
+}
+
+symbolS *
+md_undefined_symbol (name)
+ char *name;
+{
+ return 0;
+}
+
+char *
+md_atof (type, litp, sizep)
+ int type;
+ char *litp;
+ int *sizep;
+{
+ int prec;
+ LITTLENUM_TYPE words[4];
+ char *t;
+ int i;
+
+ switch (type)
+ {
+ case 'f':
+ prec = 2;
+ break;
+
+ case 'd':
+ prec = 4;
+ break;
+
+ default:
+ *sizep = 0;
+ return "bad call to md_atof";
+ }
+
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+
+ *sizep = prec * 2;
+
+ for (i = prec - 1; i >= 0; i--)
+ {
+ md_number_to_chars (litp, (valueT) words[i], 2);
+ litp += 2;
+ }
+
+ return NULL;
+}
+
+
+void
+md_convert_frag (abfd, sec, fragP)
+ bfd *abfd;
+ asection *sec;
+ fragS *fragP;
+{
+ static unsigned long label_count = 0;
+ char buf[40];
+
+ subseg_change (sec, 0);
+ if (fragP->fr_subtype == 0)
+ {
+ fix_new (fragP, fragP->fr_fix + 1, 1, fragP->fr_symbol,
+ fragP->fr_offset + 1, 1, BFD_RELOC_8_PCREL);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 2;
+ }
+ else if (fragP->fr_subtype == 1)
+ {
+ /* Reverse the condition of the first branch. */
+ int offset = fragP->fr_fix;
+ int opcode = fragP->fr_literal[offset] & 0xff;
+
+ switch (opcode)
+ {
+ case 0xc8:
+ opcode = 0xc9;
+ break;
+ case 0xc9:
+ opcode = 0xc8;
+ break;
+ case 0xc0:
+ opcode = 0xc2;
+ break;
+ case 0xc2:
+ opcode = 0xc0;
+ break;
+ case 0xc3:
+ opcode = 0xc1;
+ break;
+ case 0xc1:
+ opcode = 0xc3;
+ break;
+ case 0xc4:
+ opcode = 0xc6;
+ break;
+ case 0xc6:
+ opcode = 0xc4;
+ break;
+ case 0xc7:
+ opcode = 0xc5;
+ break;
+ case 0xc5:
+ opcode = 0xc7;
+ break;
+ default:
+ abort ();
+ }
+ fragP->fr_literal[offset] = opcode;
+
+ /* Create a fixup for the reversed conditional branch. */
+ sprintf (buf, ".%s_%d", FAKE_LABEL_NAME, label_count++);
+ fix_new (fragP, fragP->fr_fix + 1, 1,
+ symbol_new (buf, sec, 0, fragP->fr_next),
+ fragP->fr_offset + 1, 1, BFD_RELOC_8_PCREL);
+
+ /* Now create the unconditional branch + fixup to the
+ final target. */
+ fragP->fr_literal[offset + 2] = 0xcc;
+ fix_new (fragP, fragP->fr_fix + 3, 2, fragP->fr_symbol,
+ fragP->fr_offset + 1, 1, BFD_RELOC_16_PCREL);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 5;
+ }
+ else if (fragP->fr_subtype == 2)
+ {
+ /* Reverse the condition of the first branch. */
+ int offset = fragP->fr_fix;
+ int opcode = fragP->fr_literal[offset] & 0xff;
+
+ switch (opcode)
+ {
+ case 0xc8:
+ opcode = 0xc9;
+ break;
+ case 0xc9:
+ opcode = 0xc8;
+ break;
+ case 0xc0:
+ opcode = 0xc2;
+ break;
+ case 0xc2:
+ opcode = 0xc0;
+ break;
+ case 0xc3:
+ opcode = 0xc1;
+ break;
+ case 0xc1:
+ opcode = 0xc3;
+ break;
+ case 0xc4:
+ opcode = 0xc6;
+ break;
+ case 0xc6:
+ opcode = 0xc4;
+ break;
+ case 0xc7:
+ opcode = 0xc5;
+ break;
+ case 0xc5:
+ opcode = 0xc7;
+ break;
+ default:
+ abort ();
+ }
+ fragP->fr_literal[offset] = opcode;
+
+ /* Create a fixup for the reversed conditional branch. */
+ sprintf (buf, ".%s_%d", FAKE_LABEL_NAME, label_count++);
+ fix_new (fragP, fragP->fr_fix + 1, 1,
+ symbol_new (buf, sec, 0, fragP->fr_next),
+ fragP->fr_offset + 1, 1, BFD_RELOC_8_PCREL);
+
+ /* Now create the unconditional branch + fixup to the
+ final target. */
+ fragP->fr_literal[offset + 2] = 0xdc;
+ fix_new (fragP, fragP->fr_fix + 3, 4, fragP->fr_symbol,
+ fragP->fr_offset + 1, 1, BFD_RELOC_32_PCREL);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 7;
+ }
+ else if (fragP->fr_subtype == 3)
+ {
+ fix_new (fragP, fragP->fr_fix + 2, 1, fragP->fr_symbol,
+ fragP->fr_offset + 2, 1, BFD_RELOC_8_PCREL);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 3;
+ }
+ else if (fragP->fr_subtype == 4)
+ {
+ /* Reverse the condition of the first branch. */
+ int offset = fragP->fr_fix;
+ int opcode = fragP->fr_literal[offset + 1] & 0xff;
+
+ switch (opcode)
+ {
+ case 0xe8:
+ opcode = 0xe9;
+ break;
+ case 0xe9:
+ opcode = 0xe8;
+ break;
+ case 0xea:
+ opcode = 0xeb;
+ break;
+ case 0xeb:
+ opcode = 0xea;
+ break;
+ default:
+ abort ();
+ }
+ fragP->fr_literal[offset + 1] = opcode;
+
+ /* Create a fixup for the reversed conditional branch. */
+ sprintf (buf, ".%s_%d", FAKE_LABEL_NAME, label_count++);
+ fix_new (fragP, fragP->fr_fix + 2, 1,
+ symbol_new (buf, sec, 0, fragP->fr_next),
+ fragP->fr_offset + 2, 1, BFD_RELOC_8_PCREL);
+
+ /* Now create the unconditional branch + fixup to the
+ final target. */
+ fragP->fr_literal[offset + 3] = 0xcc;
+ fix_new (fragP, fragP->fr_fix + 4, 2, fragP->fr_symbol,
+ fragP->fr_offset + 1, 1, BFD_RELOC_16_PCREL);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 6;
+ }
+ else if (fragP->fr_subtype == 5)
+ {
+ /* Reverse the condition of the first branch. */
+ int offset = fragP->fr_fix;
+ int opcode = fragP->fr_literal[offset + 1] & 0xff;
+
+ switch (opcode)
+ {
+ case 0xe8:
+ opcode = 0xe9;
+ break;
+ case 0xea:
+ opcode = 0xeb;
+ break;
+ case 0xeb:
+ opcode = 0xea;
+ break;
+ default:
+ abort ();
+ }
+ fragP->fr_literal[offset + 1] = opcode;
+
+ /* Create a fixup for the reversed conditional branch. */
+ sprintf (buf, ".%s_%d", FAKE_LABEL_NAME, label_count++);
+ fix_new (fragP, fragP->fr_fix + 2, 1,
+ symbol_new (buf, sec, 0, fragP->fr_next),
+ fragP->fr_offset + 2, 1, BFD_RELOC_8_PCREL);
+
+ /* Now create the unconditional branch + fixup to the
+ final target. */
+ fragP->fr_literal[offset + 3] = 0xdc;
+ fix_new (fragP, fragP->fr_fix + 4, 4, fragP->fr_symbol,
+ fragP->fr_offset + 1, 1, BFD_RELOC_32_PCREL);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 8;
+ }
+ else if (fragP->fr_subtype == 6)
+ {
+ int offset = fragP->fr_fix;
+ fragP->fr_literal[offset] = 0xcd;
+ fix_new (fragP, fragP->fr_fix + 1, 2, fragP->fr_symbol,
+ fragP->fr_offset + 1, 1, BFD_RELOC_16_PCREL);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 5;
+ }
+ else if (fragP->fr_subtype == 7)
+ {
+ int offset = fragP->fr_fix;
+ fragP->fr_literal[offset] = 0xdd;
+ fragP->fr_literal[offset + 5] = fragP->fr_literal[offset + 3];
+ fragP->fr_literal[offset + 6] = fragP->fr_literal[offset + 4];
+
+ fix_new (fragP, fragP->fr_fix + 1, 4, fragP->fr_symbol,
+ fragP->fr_offset + 1, 1, BFD_RELOC_32_PCREL);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 7;
+ }
+ else if (fragP->fr_subtype == 8)
+ {
+ int offset = fragP->fr_fix;
+ fragP->fr_literal[offset] = 0xfa;
+ fragP->fr_literal[offset + 1] = 0xff;
+ fix_new (fragP, fragP->fr_fix + 2, 2, fragP->fr_symbol,
+ fragP->fr_offset + 2, 1, BFD_RELOC_16_PCREL);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 4;
+ }
+ else if (fragP->fr_subtype == 9)
+ {
+ int offset = fragP->fr_fix;
+ fragP->fr_literal[offset] = 0xfc;
+ fragP->fr_literal[offset + 1] = 0xff;
+
+ fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol,
+ fragP->fr_offset + 2, 1, BFD_RELOC_32_PCREL);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 6;
+ }
+ else if (fragP->fr_subtype == 10)
+ {
+ fragP->fr_literal[fragP->fr_fix] = 0xca;
+ fix_new (fragP, fragP->fr_fix + 1, 1, fragP->fr_symbol,
+ fragP->fr_offset + 1, 1, BFD_RELOC_8_PCREL);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 2;
+ }
+ else if (fragP->fr_subtype == 11)
+ {
+ int offset = fragP->fr_fix;
+ fragP->fr_literal[offset] = 0xcc;
+
+ fix_new (fragP, fragP->fr_fix + 1, 4, fragP->fr_symbol,
+ fragP->fr_offset + 1, 1, BFD_RELOC_16_PCREL);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 3;
+ }
+ else if (fragP->fr_subtype == 12)
+ {
+ int offset = fragP->fr_fix;
+ fragP->fr_literal[offset] = 0xdc;
+
+ fix_new (fragP, fragP->fr_fix + 1, 4, fragP->fr_symbol,
+ fragP->fr_offset + 1, 1, BFD_RELOC_32_PCREL);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 5;
+ }
+ else
+ abort ();
+}
+
+valueT
+md_section_align (seg, addr)
+ asection *seg;
+ valueT addr;
+{
+ int align = bfd_get_section_alignment (stdoutput, seg);
+ return ((addr + (1 << align) - 1) & (-1 << align));
+}
+
+void
+md_begin ()
+{
+ char *prev_name = "";
+ register const struct mn10300_opcode *op;
+
+ mn10300_hash = hash_new();
+
+ /* Insert unique names into hash table. The MN10300 instruction set
+ has many identical opcode names that have different opcodes based
+ on the operands. This hash table then provides a quick index to
+ the first opcode with a particular name in the opcode table. */
+
+ op = mn10300_opcodes;
+ while (op->name)
+ {
+ if (strcmp (prev_name, op->name))
+ {
+ prev_name = (char *) op->name;
+ hash_insert (mn10300_hash, op->name, (char *) op);
+ }
+ op++;
+ }
+
+ /* This is both a simplification (we don't have to write md_apply_fix)
+ and support for future optimizations (branch shortening and similar
+ stuff in the linker). */
+ linkrelax = 1;
+
+ /* Set the default machine type. */
+ if (!bfd_set_arch_mach (stdoutput, bfd_arch_mn10300, 300))
+ as_warn (_("could not set architecture and machine"));
+
+ current_machine = 300;
+}
+
+void
+md_assemble (str)
+ char *str;
+{
+ char *s;
+ struct mn10300_opcode *opcode;
+ struct mn10300_opcode *next_opcode;
+ const unsigned char *opindex_ptr;
+ int next_opindex, relaxable;
+ unsigned long insn, extension, size = 0;
+ char *f;
+ int i;
+ int match;
+
+ /* Get the opcode. */
+ for (s = str; *s != '\0' && ! isspace (*s); s++)
+ ;
+ if (*s != '\0')
+ *s++ = '\0';
+
+ /* find the first opcode with the proper name */
+ opcode = (struct mn10300_opcode *)hash_find (mn10300_hash, str);
+ if (opcode == NULL)
+ {
+ as_bad (_("Unrecognized opcode: `%s'"), str);
+ return;
+ }
+
+ str = s;
+ while (isspace (*str))
+ ++str;
+
+ input_line_pointer = str;
+
+ for(;;)
+ {
+ const char *errmsg;
+ int op_idx;
+ char *hold;
+ int extra_shift = 0;
+
+
+ errmsg = _("Invalid opcode/operands");
+
+ /* Reset the array of register operands. */
+ memset (mn10300_reg_operands, -1, sizeof (mn10300_reg_operands));
+
+ relaxable = 0;
+ fc = 0;
+ match = 0;
+ next_opindex = 0;
+ insn = opcode->opcode;
+ extension = 0;
+
+ /* If the instruction is not available on the current machine
+ then it can not possibly match. */
+ if (opcode->machine
+ && (opcode->machine != current_machine))
+ goto error;
+
+ for (op_idx = 1, opindex_ptr = opcode->operands;
+ *opindex_ptr != 0;
+ opindex_ptr++, op_idx++)
+ {
+ const struct mn10300_operand *operand;
+ expressionS ex;
+
+ if (next_opindex == 0)
+ {
+ operand = &mn10300_operands[*opindex_ptr];
+ }
+ else
+ {
+ operand = &mn10300_operands[next_opindex];
+ next_opindex = 0;
+ }
+
+ while (*str == ' ' || *str == ',')
+ ++str;
+
+ if (operand->flags & MN10300_OPERAND_RELAX)
+ relaxable = 1;
+
+ /* Gather the operand. */
+ hold = input_line_pointer;
+ input_line_pointer = str;
+
+ if (operand->flags & MN10300_OPERAND_PAREN)
+ {
+ if (*input_line_pointer != ')' && *input_line_pointer != '(')
+ {
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+ input_line_pointer++;
+ goto keep_going;
+ }
+ /* See if we can match the operands. */
+ else if (operand->flags & MN10300_OPERAND_DREG)
+ {
+ if (!data_register_name (&ex))
+ {
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+ }
+ else if (operand->flags & MN10300_OPERAND_AREG)
+ {
+ if (!address_register_name (&ex))
+ {
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+ }
+ else if (operand->flags & MN10300_OPERAND_SP)
+ {
+ char *start = input_line_pointer;
+ char c = get_symbol_end ();
+
+ if (strcasecmp (start, "sp") != 0)
+ {
+ *input_line_pointer = c;
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+ *input_line_pointer = c;
+ goto keep_going;
+ }
+ else if (operand->flags & MN10300_OPERAND_PSW)
+ {
+ char *start = input_line_pointer;
+ char c = get_symbol_end ();
+
+ if (strcasecmp (start, "psw") != 0)
+ {
+ *input_line_pointer = c;
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+ *input_line_pointer = c;
+ goto keep_going;
+ }
+ else if (operand->flags & MN10300_OPERAND_MDR)
+ {
+ char *start = input_line_pointer;
+ char c = get_symbol_end ();
+
+ if (strcasecmp (start, "mdr") != 0)
+ {
+ *input_line_pointer = c;
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+ *input_line_pointer = c;
+ goto keep_going;
+ }
+ else if (operand->flags & MN10300_OPERAND_REG_LIST)
+ {
+ unsigned int value = 0;
+ if (*input_line_pointer != '[')
+ {
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+
+ /* Eat the '['. */
+ input_line_pointer++;
+
+ /* We used to reject a null register list here; however,
+ we accept it now so the compiler can emit "call" instructions
+ for all calls to named functions.
+
+ The linker can then fill in the appropriate bits for the
+ register list and stack size or change the instruction
+ into a "calls" if using "call" is not profitable. */
+ while (*input_line_pointer != ']')
+ {
+ char *start;
+ char c;
+
+ if (*input_line_pointer == ',')
+ input_line_pointer++;
+
+ start = input_line_pointer;
+ c = get_symbol_end ();
+
+ if (strcasecmp (start, "d2") == 0)
+ {
+ value |= 0x80;
+ *input_line_pointer = c;
+ }
+ else if (strcasecmp (start, "d3") == 0)
+ {
+ value |= 0x40;
+ *input_line_pointer = c;
+ }
+ else if (strcasecmp (start, "a2") == 0)
+ {
+ value |= 0x20;
+ *input_line_pointer = c;
+ }
+ else if (strcasecmp (start, "a3") == 0)
+ {
+ value |= 0x10;
+ *input_line_pointer = c;
+ }
+ else if (strcasecmp (start, "other") == 0)
+ {
+ value |= 0x08;
+ *input_line_pointer = c;
+ }
+ else
+ {
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+ }
+ input_line_pointer++;
+ mn10300_insert_operand (&insn, &extension, operand,
+ value, (char *) NULL, 0, 0);
+ goto keep_going;
+
+ }
+ else if (data_register_name (&ex))
+ {
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+ else if (address_register_name (&ex))
+ {
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+ else if (other_register_name (&ex))
+ {
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+ else if (*str == ')' || *str == '(')
+ {
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+ else
+ {
+ expression (&ex);
+ }
+
+ switch (ex.X_op)
+ {
+ case O_illegal:
+ errmsg = _("illegal operand");
+ goto error;
+ case O_absent:
+ errmsg = _("missing operand");
+ goto error;
+ case O_register:
+ {
+ int mask;
+
+ mask = MN10300_OPERAND_DREG | MN10300_OPERAND_AREG;
+ if ((operand->flags & mask) == 0)
+ {
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+
+ if (opcode->format == FMT_D1 || opcode->format == FMT_S1)
+ extra_shift = 8;
+ else if (opcode->format == FMT_D2
+ || opcode->format == FMT_D4
+ || opcode->format == FMT_S2
+ || opcode->format == FMT_S4
+ || opcode->format == FMT_S6
+ || opcode->format == FMT_D5)
+ extra_shift = 16;
+ else
+ extra_shift = 0;
+
+ mn10300_insert_operand (&insn, &extension, operand,
+ ex.X_add_number, (char *) NULL,
+ 0, extra_shift);
+
+
+ /* And note the register number in the register array. */
+ mn10300_reg_operands[op_idx - 1] = ex.X_add_number;
+ break;
+ }
+
+ case O_constant:
+ /* If this operand can be promoted, and it doesn't
+ fit into the allocated bitfield for this insn,
+ then promote it (ie this opcode does not match). */
+ if (operand->flags
+ & (MN10300_OPERAND_PROMOTE | MN10300_OPERAND_RELAX)
+ && ! check_operand (insn, operand, ex.X_add_number))
+ {
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+
+ mn10300_insert_operand (&insn, &extension, operand,
+ ex.X_add_number, (char *) NULL,
+ 0, 0);
+ break;
+
+ default:
+ /* If this operand can be promoted, then this opcode didn't
+ match since we can't know if it needed promotion! */
+ if (operand->flags & MN10300_OPERAND_PROMOTE)
+ {
+ input_line_pointer = hold;
+ str = hold;
+ goto error;
+ }
+
+ /* We need to generate a fixup for this expression. */
+ if (fc >= MAX_INSN_FIXUPS)
+ as_fatal (_("too many fixups"));
+ fixups[fc].exp = ex;
+ fixups[fc].opindex = *opindex_ptr;
+ fixups[fc].reloc = BFD_RELOC_UNUSED;
+ ++fc;
+ break;
+ }
+
+keep_going:
+ str = input_line_pointer;
+ input_line_pointer = hold;
+
+ while (*str == ' ' || *str == ',')
+ ++str;
+
+ }
+
+ /* Make sure we used all the operands! */
+ if (*str != ',')
+ match = 1;
+
+ /* If this instruction has registers that must not match, verify
+ that they do indeed not match. */
+ if (opcode->no_match_operands)
+ {
+ int i;
+
+ /* Look at each operand to see if it's marked. */
+ for (i = 0; i < MN10300_MAX_OPERANDS; i++)
+ {
+ if ((1 << i) & opcode->no_match_operands)
+ {
+ int j;
+
+ /* operand I is marked. Check that it does not match any
+ operands > I which are marked. */
+ for (j = i + 1; j < MN10300_MAX_OPERANDS; j++)
+ {
+ if (((1 << j) & opcode->no_match_operands)
+ && mn10300_reg_operands[i] == mn10300_reg_operands[j])
+ {
+ errmsg = _("Invalid register specification.");
+ match = 0;
+ goto error;
+ }
+ }
+ }
+ }
+ }
+
+ error:
+ if (match == 0)
+ {
+ next_opcode = opcode + 1;
+ if (!strcmp(next_opcode->name, opcode->name))
+ {
+ opcode = next_opcode;
+ continue;
+ }
+
+ as_bad ("%s", errmsg);
+ return;
+ }
+ break;
+ }
+
+ while (isspace (*str))
+ ++str;
+
+ if (*str != '\0')
+ as_bad (_("junk at end of line: `%s'"), str);
+
+ input_line_pointer = str;
+
+ /* Determine the size of the instruction. */
+ if (opcode->format == FMT_S0)
+ size = 1;
+
+ if (opcode->format == FMT_S1 || opcode->format == FMT_D0)
+ size = 2;
+
+ if (opcode->format == FMT_S2 || opcode->format == FMT_D1)
+ size = 3;
+
+
+ if (opcode->format == FMT_S4)
+ size = 5;
+
+ if (opcode->format == FMT_S6 || opcode->format == FMT_D5)
+ size = 7;
+
+ if (opcode->format == FMT_D2)
+ size = 4;
+
+ if (opcode->format == FMT_D4)
+ size = 6;
+
+ if (relaxable && fc > 0)
+ {
+ int type;
+
+ /* bCC */
+ if (size == 2)
+ {
+ /* Handle bra specially. Basically treat it like jmp so
+ that we automatically handle 8, 16 and 32 bit offsets
+ correctly as well as jumps to an undefined address.
+
+ It is also important to not treat it like other bCC
+ instructions since the long forms of bra is different
+ from other bCC instructions. */
+ if (opcode->opcode == 0xca00)
+ type = 10;
+ else
+ type = 0;
+ }
+ /* call */
+ else if (size == 5)
+ type = 6;
+ /* calls */
+ else if (size == 4)
+ type = 8;
+ /* jmp */
+ else if (size == 3 && opcode->opcode == 0xcc0000)
+ type = 10;
+ /* bCC (uncommon cases) */
+ else
+ type = 3;
+
+ f = frag_var (rs_machine_dependent, 8, 8 - size, type,
+ fixups[0].exp.X_add_symbol,
+ fixups[0].exp.X_add_number,
+ (char *)fixups[0].opindex);
+
+ /* This is pretty hokey. We basically just care about the
+ opcode, so we have to write out the first word big endian.
+
+ The exception is "call", which has two operands that we
+ care about.
+
+ The first operand (the register list) happens to be in the
+ first instruction word, and will be in the right place if
+ we output the first word in big endian mode.
+
+ The second operand (stack size) is in the extension word,
+ and we want it to appear as the first character in the extension
+ word (as it appears in memory). Luckily, writing the extension
+ word in big endian format will do what we want. */
+ number_to_chars_bigendian (f, insn, size > 4 ? 4 : size);
+ if (size > 8)
+ {
+ number_to_chars_bigendian (f + 4, extension, 4);
+ number_to_chars_bigendian (f + 8, 0, size - 8);
+ }
+ else if (size > 4)
+ number_to_chars_bigendian (f + 4, extension, size - 4);
+ }
+ else
+ {
+ /* Allocate space for the instruction. */
+ f = frag_more (size);
+
+ /* Fill in bytes for the instruction. Note that opcode fields
+ are written big-endian, 16 & 32bit immediates are written
+ little endian. Egad. */
+ if (opcode->format == FMT_S0
+ || opcode->format == FMT_S1
+ || opcode->format == FMT_D0
+ || opcode->format == FMT_D1)
+ {
+ number_to_chars_bigendian (f, insn, size);
+ }
+ else if (opcode->format == FMT_S2
+ && opcode->opcode != 0xdf0000
+ && opcode->opcode != 0xde0000)
+ {
+ /* A format S2 instruction that is _not_ "ret" and "retf". */
+ number_to_chars_bigendian (f, (insn >> 16) & 0xff, 1);
+ number_to_chars_littleendian (f + 1, insn & 0xffff, 2);
+ }
+ else if (opcode->format == FMT_S2)
+ {
+ /* This must be a ret or retf, which is written entirely in
+ big-endian format. */
+ number_to_chars_bigendian (f, insn, 3);
+ }
+ else if (opcode->format == FMT_S4
+ && opcode->opcode != 0xdc000000)
+ {
+ /* This must be a format S4 "call" instruction. What a pain. */
+ unsigned long temp = (insn >> 8) & 0xffff;
+ number_to_chars_bigendian (f, (insn >> 24) & 0xff, 1);
+ number_to_chars_littleendian (f + 1, temp, 2);
+ number_to_chars_bigendian (f + 3, insn & 0xff, 1);
+ number_to_chars_bigendian (f + 4, extension & 0xff, 1);
+ }
+ else if (opcode->format == FMT_S4)
+ {
+ /* This must be a format S4 "jmp" instruction. */
+ unsigned long temp = ((insn & 0xffffff) << 8) | (extension & 0xff);
+ number_to_chars_bigendian (f, (insn >> 24) & 0xff, 1);
+ number_to_chars_littleendian (f + 1, temp, 4);
+ }
+ else if (opcode->format == FMT_S6)
+ {
+ unsigned long temp = ((insn & 0xffffff) << 8)
+ | ((extension >> 16) & 0xff);
+ number_to_chars_bigendian (f, (insn >> 24) & 0xff, 1);
+ number_to_chars_littleendian (f + 1, temp, 4);
+ number_to_chars_bigendian (f + 5, (extension >> 8) & 0xff, 1);
+ number_to_chars_bigendian (f + 6, extension & 0xff, 1);
+ }
+ else if (opcode->format == FMT_D2
+ && opcode->opcode != 0xfaf80000
+ && opcode->opcode != 0xfaf00000
+ && opcode->opcode != 0xfaf40000)
+ {
+ /* A format D2 instruction where the 16bit immediate is
+ really a single 16bit value, not two 8bit values. */
+ number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);
+ number_to_chars_littleendian (f + 2, insn & 0xffff, 2);
+ }
+ else if (opcode->format == FMT_D2)
+ {
+ /* A format D2 instruction where the 16bit immediate
+ is really two 8bit immediates. */
+ number_to_chars_bigendian (f, insn, 4);
+ }
+ else if (opcode->format == FMT_D4)
+ {
+ unsigned long temp = ((insn & 0xffff) << 16) | (extension & 0xffff);
+ number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);
+ number_to_chars_littleendian (f + 2, temp, 4);
+ }
+ else if (opcode->format == FMT_D5)
+ {
+ unsigned long temp = ((insn & 0xffff) << 16)
+ | ((extension >> 8) & 0xffff);
+ number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);
+ number_to_chars_littleendian (f + 2, temp, 4);
+ number_to_chars_bigendian (f + 6, extension & 0xff, 1);
+ }
+
+ /* Create any fixups. */
+ for (i = 0; i < fc; i++)
+ {
+ const struct mn10300_operand *operand;
+
+ operand = &mn10300_operands[fixups[i].opindex];
+ if (fixups[i].reloc != BFD_RELOC_UNUSED)
+ {
+ reloc_howto_type *reloc_howto;
+ int size;
+ int offset;
+ fixS *fixP;
+
+ reloc_howto = bfd_reloc_type_lookup (stdoutput, fixups[i].reloc);
+
+ if (!reloc_howto)
+ abort();
+
+ size = bfd_get_reloc_size (reloc_howto);
+
+ if (size < 1 || size > 4)
+ abort();
+
+ offset = 4 - size;
+ fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset,
+ size, &fixups[i].exp,
+ reloc_howto->pc_relative,
+ fixups[i].reloc);
+ }
+ else
+ {
+ int reloc, pcrel, reloc_size, offset;
+ fixS *fixP;
+
+ reloc = BFD_RELOC_NONE;
+ /* How big is the reloc? Remember SPLIT relocs are
+ implicitly 32bits. */
+ if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
+ reloc_size = 32;
+ else
+ reloc_size = operand->bits;
+
+ /* Is the reloc pc-relative? */
+ pcrel = (operand->flags & MN10300_OPERAND_PCREL) != 0;
+
+ /* Gross. This disgusting hack is to make sure we
+ get the right offset for the 16/32 bit reloc in
+ "call" instructions. Basically they're a pain
+ because the reloc isn't at the end of the instruction. */
+ if ((size == 5 || size == 7)
+ && (((insn >> 24) & 0xff) == 0xcd
+ || ((insn >> 24) & 0xff) == 0xdd))
+ size -= 2;
+
+ /* Similarly for certain bit instructions which don't
+ hav their 32bit reloc at the tail of the instruction. */
+ if (size == 7
+ && (((insn >> 16) & 0xffff) == 0xfe00
+ || ((insn >> 16) & 0xffff) == 0xfe01
+ || ((insn >> 16) & 0xffff) == 0xfe02))
+ size -= 1;
+
+ offset = size - reloc_size / 8;
+
+ /* Choose a proper BFD relocation type. */
+ if (pcrel)
+ {
+ if (reloc_size == 32)
+ reloc = BFD_RELOC_32_PCREL;
+ else if (reloc_size == 16)
+ reloc = BFD_RELOC_16_PCREL;
+ else if (reloc_size == 8)
+ reloc = BFD_RELOC_8_PCREL;
+ else
+ abort ();
+ }
+ else
+ {
+ if (reloc_size == 32)
+ reloc = BFD_RELOC_32;
+ else if (reloc_size == 16)
+ reloc = BFD_RELOC_16;
+ else if (reloc_size == 8)
+ reloc = BFD_RELOC_8;
+ else
+ abort ();
+ }
+
+ /* Convert the size of the reloc into what fix_new_exp wants. */
+ reloc_size = reloc_size / 8;
+ if (reloc_size == 8)
+ reloc_size = 0;
+ else if (reloc_size == 16)
+ reloc_size = 1;
+ else if (reloc_size == 32)
+ reloc_size = 2;
+
+ fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset,
+ reloc_size, &fixups[i].exp, pcrel,
+ ((bfd_reloc_code_real_type) reloc));
+
+ if (pcrel)
+ fixP->fx_offset += offset;
+ }
+ }
+ }
+}
+
+
+/* if while processing a fixup, a reloc really needs to be created */
+/* then it is done here */
+
+arelent *
+tc_gen_reloc (seg, fixp)
+ asection *seg;
+ fixS *fixp;
+{
+ arelent *reloc;
+ reloc = (arelent *) xmalloc (sizeof (arelent));
+
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
+ if (reloc->howto == (reloc_howto_type *) NULL)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("reloc %d not supported by object file format"),
+ (int)fixp->fx_r_type);
+ return NULL;
+ }
+ reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+
+ if (fixp->fx_addsy && fixp->fx_subsy)
+ {
+
+ if ((S_GET_SEGMENT (fixp->fx_addsy) != S_GET_SEGMENT (fixp->fx_subsy))
+ || S_GET_SEGMENT (fixp->fx_addsy) == undefined_section)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ "Difference of symbols in different sections is not supported");
+ return NULL;
+ }
+
+ reloc->sym_ptr_ptr = &bfd_abs_symbol;
+ reloc->addend = (S_GET_VALUE (fixp->fx_addsy)
+ - S_GET_VALUE (fixp->fx_subsy) + fixp->fx_offset);
+ }
+ else
+ {
+ reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+ reloc->addend = fixp->fx_offset;
+ }
+ return reloc;
+}
+
+int
+md_estimate_size_before_relax (fragp, seg)
+ fragS *fragp;
+ asection *seg;
+{
+ if (fragp->fr_subtype == 0)
+ return 2;
+ if (fragp->fr_subtype == 3)
+ return 3;
+ if (fragp->fr_subtype == 6)
+ {
+ if (!S_IS_DEFINED (fragp->fr_symbol)
+ || seg != S_GET_SEGMENT (fragp->fr_symbol))
+ {
+ fragp->fr_subtype = 7;
+ return 7;
+ }
+ else
+ return 5;
+ }
+ if (fragp->fr_subtype == 8)
+ {
+ if (!S_IS_DEFINED (fragp->fr_symbol)
+ || seg != S_GET_SEGMENT (fragp->fr_symbol))
+ {
+ fragp->fr_subtype = 9;
+ return 6;
+ }
+ else
+ return 4;
+ }
+ if (fragp->fr_subtype == 10)
+ {
+ if (!S_IS_DEFINED (fragp->fr_symbol)
+ || seg != S_GET_SEGMENT (fragp->fr_symbol))
+ {
+ fragp->fr_subtype = 12;
+ return 5;
+ }
+ else
+ return 2;
+ }
+}
+
+long
+md_pcrel_from (fixp)
+ fixS *fixp;
+{
+ return fixp->fx_frag->fr_address;
+#if 0
+ if (fixp->fx_addsy != (symbolS *) NULL && ! S_IS_DEFINED (fixp->fx_addsy))
+ {
+ /* The symbol is undefined. Let the linker figure it out. */
+ return 0;
+ }
+ return fixp->fx_frag->fr_address + fixp->fx_where;
+#endif
+}
+
+int
+md_apply_fix3 (fixp, valuep, seg)
+ fixS *fixp;
+ valueT *valuep;
+ segT seg;
+{
+ /* We shouldn't ever get here because linkrelax is nonzero. */
+ abort ();
+ fixp->fx_done = 1;
+ return 0;
+}
+
+/* Insert an operand value into an instruction. */
+
+static void
+mn10300_insert_operand (insnp, extensionp, operand, val, file, line, shift)
+ unsigned long *insnp;
+ unsigned long *extensionp;
+ const struct mn10300_operand *operand;
+ offsetT val;
+ char *file;
+ unsigned int line;
+ unsigned int shift;
+{
+ /* No need to check 32bit operands for a bit. Note that
+ MN10300_OPERAND_SPLIT is an implicit 32bit operand. */
+ if (operand->bits != 32
+ && (operand->flags & MN10300_OPERAND_SPLIT) == 0)
+ {
+ long min, max;
+ offsetT test;
+ int bits;
+
+ bits = operand->bits;
+
+ if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
+ {
+ max = (1 << (bits - 1)) - 1;
+ min = - (1 << (bits - 1));
+ }
+ else
+ {
+ max = (1 << bits) - 1;
+ min = 0;
+ }
+
+ test = val;
+
+
+ if (test < (offsetT) min || test > (offsetT) max)
+ {
+ const char *err =
+ _("operand out of range (%s not between %ld and %ld)");
+ char buf[100];
+
+ sprint_value (buf, test);
+ if (file == (char *) NULL)
+ as_warn (err, buf, min, max);
+ else
+ as_warn_where (file, line, err, buf, min, max);
+ }
+ }
+
+ if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
+ {
+ *insnp |= (val >> (32 - operand->bits)) & ((1 << operand->bits) - 1);
+ *extensionp |= ((val & ((1 << (32 - operand->bits)) - 1))
+ << operand->shift);
+ }
+ else if ((operand->flags & MN10300_OPERAND_EXTENDED) == 0)
+ {
+ *insnp |= (((long) val & ((1 << operand->bits) - 1))
+ << (operand->shift + shift));
+
+ if ((operand->flags & MN10300_OPERAND_REPEATED) != 0)
+ *insnp |= (((long) val & ((1 << operand->bits) - 1))
+ << (operand->shift + shift + operand->bits));
+ }
+ else
+ {
+ *extensionp |= (((long) val & ((1 << operand->bits) - 1))
+ << (operand->shift + shift));
+
+ if ((operand->flags & MN10300_OPERAND_REPEATED) != 0)
+ *extensionp |= (((long) val & ((1 << operand->bits) - 1))
+ << (operand->shift + shift + operand->bits));
+ }
+}
+
+static unsigned long
+check_operand (insn, operand, val)
+ unsigned long insn;
+ const struct mn10300_operand *operand;
+ offsetT val;
+{
+ /* No need to check 32bit operands for a bit. Note that
+ MN10300_OPERAND_SPLIT is an implicit 32bit operand. */
+ if (operand->bits != 32
+ && (operand->flags & MN10300_OPERAND_SPLIT) == 0)
+ {
+ long min, max;
+ offsetT test;
+ int bits;
+
+ bits = operand->bits;
+
+ if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
+ {
+ max = (1 << (bits - 1)) - 1;
+ min = - (1 << (bits - 1));
+ }
+ else
+ {
+ max = (1 << bits) - 1;
+ min = 0;
+ }
+
+ test = val;
+
+
+ if (test < (offsetT) min || test > (offsetT) max)
+ return 0;
+ else
+ return 1;
+ }
+ return 1;
+}
+
+static void
+set_arch_mach (mach)
+ int mach;
+{
+ if (!bfd_set_arch_mach (stdoutput, bfd_arch_mn10300, mach))
+ as_warn (_("could not set architecture and machine"));
+
+ current_machine = mach;
+}
diff --git a/gas/config/tc-mn10300.h b/gas/config/tc-mn10300.h
new file mode 100644
index 0000000000..ffcb227b0e
--- /dev/null
+++ b/gas/config/tc-mn10300.h
@@ -0,0 +1,50 @@
+/* tc-mn10300.h -- Header file for tc-mn10300.c.
+ Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#define TC_MN10300
+
+#define TARGET_BYTES_BIG_ENDIAN 0
+
+#ifndef BFD_ASSEMBLER
+ #error MN10300 support requires BFD_ASSEMBLER
+#endif
+
+/* The target BFD architecture. */
+#define TARGET_ARCH bfd_arch_mn10300
+
+#define TARGET_FORMAT "elf32-mn10300"
+
+#define MD_APPLY_FIX3
+#define md_operand(x)
+
+/* Permit temporary numeric labels. */
+#define LOCAL_LABELS_FB 1
+
+/* We don't need to handle .word strangely. */
+#define WORKING_DOT_WORD
+
+#define md_number_to_chars number_to_chars_littleendian
+
+/* Don't bother to adjust relocs. */
+#define tc_fix_adjustable(FIX) 0
+
+/* We do relaxing in the assembler as well as the linker. */
+extern const struct relax_type md_relax_table[];
+#define TC_GENERIC_RELAX_TABLE md_relax_table
diff --git a/gas/config/tc-ns32k.c b/gas/config/tc-ns32k.c
new file mode 100644
index 0000000000..42dc528388
--- /dev/null
+++ b/gas/config/tc-ns32k.c
@@ -0,0 +1,2328 @@
+/* ns32k.c -- Assemble on the National Semiconductor 32k series
+ Copyright (C) 1987, 92, 93, 94, 95, 96, 1997, 1998 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/*#define SHOW_NUM 1*//* uncomment for debugging */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include "as.h"
+#include "opcode/ns32k.h"
+
+#include "obstack.h"
+
+/* Macros */
+#define IIF_ENTRIES 13 /* number of entries in iif */
+#define PRIVATE_SIZE 256 /* size of my garbage memory */
+#define MAX_ARGS 4
+#define DEFAULT -1 /* addr_mode returns this value when
+ plain constant or label is
+ encountered */
+
+#define IIF(ptr,a1,c1,e1,g1,i1,k1,m1,o1,q1,s1,u1) \
+ iif.iifP[ptr].type= a1; \
+ iif.iifP[ptr].size= c1; \
+ iif.iifP[ptr].object= e1; \
+ iif.iifP[ptr].object_adjust= g1; \
+ iif.iifP[ptr].pcrel= i1; \
+ iif.iifP[ptr].pcrel_adjust= k1; \
+ iif.iifP[ptr].im_disp= m1; \
+ iif.iifP[ptr].relax_substate= o1; \
+ iif.iifP[ptr].bit_fixP= q1; \
+ iif.iifP[ptr].addr_mode= s1; \
+ iif.iifP[ptr].bsr= u1;
+
+#ifdef SEQUENT_COMPATABILITY
+#define LINE_COMMENT_CHARS "|"
+#define ABSOLUTE_PREFIX '@'
+#define IMMEDIATE_PREFIX '#'
+#endif
+
+#ifndef LINE_COMMENT_CHARS
+#define LINE_COMMENT_CHARS "#"
+#endif
+
+const char comment_chars[] = "#";
+const char line_comment_chars[] = LINE_COMMENT_CHARS;
+const char line_separator_chars[] = "";
+#if !defined(ABSOLUTE_PREFIX) && !defined(IMMEDIATE_PREFIX)
+#define ABSOLUTE_PREFIX '@' /* One or the other MUST be defined */
+#endif
+
+struct addr_mode
+ {
+ char mode; /* addressing mode of operand (0-31) */
+ char scaled_mode; /* mode combined with scaled mode */
+ char scaled_reg; /* register used in scaled+1 (1-8) */
+ char float_flag; /* set if R0..R7 was F0..F7 ie a
+ floating-point-register */
+ char am_size; /* estimated max size of general addr-mode
+ parts */
+ char im_disp; /* if im_disp==1 we have a displacement */
+ char pcrel; /* 1 if pcrel, this is really redundant info */
+ char disp_suffix[2]; /* length of displacement(s), 0=undefined */
+ char *disp[2]; /* pointer(s) at displacement(s)
+ or immediates(s) (ascii) */
+ char index_byte; /* index byte */
+ };
+typedef struct addr_mode addr_modeS;
+
+
+char *freeptr, *freeptr_static; /* points at some number of free bytes */
+struct hash_control *inst_hash_handle;
+
+struct ns32k_opcode *desc; /* pointer at description of instruction */
+addr_modeS addr_modeP;
+const char EXP_CHARS[] = "eE";
+const char FLT_CHARS[] = "fd"; /* we don't want to support lowercase, do we */
+
+/* UPPERCASE denotes live names when an instruction is built, IIF is
+ * used as an intermediate form to store the actual parts of the
+ * instruction. A ns32k machine instruction can be divided into a
+ * couple of sub PARTs. When an instruction is assembled the
+ * appropriate PART get an assignment. When an IIF has been completed
+ * it is converted to a FRAGment as specified in AS.H */
+
+/* internal structs */
+struct ns32k_option
+ {
+ char *pattern;
+ unsigned long or;
+ unsigned long and;
+ };
+
+typedef struct
+ {
+ int type; /* how to interpret object */
+ int size; /* Estimated max size of object */
+ unsigned long object; /* binary data */
+ int object_adjust; /* number added to object */
+ int pcrel; /* True if object is pcrel */
+ int pcrel_adjust; /* length in bytes from the
+ instruction start to the
+ displacement */
+ int im_disp; /* True if the object is a displacement */
+ relax_substateT relax_substate; /* Initial relaxsubstate */
+ bit_fixS *bit_fixP; /* Pointer at bit_fix struct */
+ int addr_mode; /* What addrmode do we associate with this
+ iif-entry */
+ char bsr; /* Sequent hack */
+ } iif_entryT; /* Internal Instruction Format */
+
+struct int_ins_form
+ {
+ int instr_size; /* Max size of instruction in bytes. */
+ iif_entryT iifP[IIF_ENTRIES + 1];
+ };
+struct int_ins_form iif;
+expressionS exprP;
+char *input_line_pointer;
+/* description of the PARTs in IIF
+ *object[n]:
+ * 0 total length in bytes of entries in iif
+ * 1 opcode
+ * 2 index_byte_a
+ * 3 index_byte_b
+ * 4 disp_a_1
+ * 5 disp_a_2
+ * 6 disp_b_1
+ * 7 disp_b_2
+ * 8 imm_a
+ * 9 imm_b
+ * 10 implied1
+ * 11 implied2
+ *
+ * For every entry there is a datalength in bytes. This is stored in size[n].
+ * 0, the objectlength is not explicitly given by the instruction
+ * and the operand is undefined. This is a case for relaxation.
+ * Reserve 4 bytes for the final object.
+ *
+ * 1, the entry contains one byte
+ * 2, the entry contains two bytes
+ * 3, the entry contains three bytes
+ * 4, the entry contains four bytes
+ * etc
+ *
+ * Furthermore, every entry has a data type identifier in type[n].
+ *
+ * 0, the entry is void, ignore it.
+ * 1, the entry is a binary number.
+ * 2, the entry is a pointer at an expression.
+ * Where expression may be as simple as a single '1',
+ * and as complicated as foo-bar+12,
+ * foo and bar may be undefined but suffixed by :{b|w|d} to
+ * control the length of the object.
+ *
+ * 3, the entry is a pointer at a bignum struct
+ *
+ *
+ * The low-order-byte coresponds to low physical memory.
+ * Obviously a FRAGment must be created for each valid disp in PART whose
+ * datalength is undefined (to bad) .
+ * The case where just the expression is undefined is less severe and is
+ * handled by fix. Here the number of bytes in the objectfile is known.
+ * With this representation we simplify the assembly and separates the
+ * machine dependent/independent parts in a more clean way (said OE)
+ */
+
+struct ns32k_option opt1[] = /* restore, exit */
+{
+ {"r0", 0x80, 0xff},
+ {"r1", 0x40, 0xff},
+ {"r2", 0x20, 0xff},
+ {"r3", 0x10, 0xff},
+ {"r4", 0x08, 0xff},
+ {"r5", 0x04, 0xff},
+ {"r6", 0x02, 0xff},
+ {"r7", 0x01, 0xff},
+ {0, 0x00, 0xff}
+};
+struct ns32k_option opt2[] = /* save, enter */
+{
+ {"r0", 0x01, 0xff},
+ {"r1", 0x02, 0xff},
+ {"r2", 0x04, 0xff},
+ {"r3", 0x08, 0xff},
+ {"r4", 0x10, 0xff},
+ {"r5", 0x20, 0xff},
+ {"r6", 0x40, 0xff},
+ {"r7", 0x80, 0xff},
+ {0, 0x00, 0xff}
+};
+struct ns32k_option opt3[] = /* setcfg */
+{
+ {"c", 0x8, 0xff},
+ {"m", 0x4, 0xff},
+ {"f", 0x2, 0xff},
+ {"i", 0x1, 0xff},
+ {0, 0x0, 0xff}
+};
+struct ns32k_option opt4[] = /* cinv */
+{
+ {"a", 0x4, 0xff},
+ {"i", 0x2, 0xff},
+ {"d", 0x1, 0xff},
+ {0, 0x0, 0xff}
+};
+struct ns32k_option opt5[] = /* string inst */
+{
+ {"b", 0x2, 0xff},
+ {"u", 0xc, 0xff},
+ {"w", 0x4, 0xff},
+ {0, 0x0, 0xff}
+};
+struct ns32k_option opt6[] = /* plain reg ext,cvtp etc */
+{
+ {"r0", 0x00, 0xff},
+ {"r1", 0x01, 0xff},
+ {"r2", 0x02, 0xff},
+ {"r3", 0x03, 0xff},
+ {"r4", 0x04, 0xff},
+ {"r5", 0x05, 0xff},
+ {"r6", 0x06, 0xff},
+ {"r7", 0x07, 0xff},
+ {0, 0x00, 0xff}
+};
+
+#if !defined(NS32032) && !defined(NS32532)
+#define NS32532
+#endif
+
+struct ns32k_option cpureg_532[] = /* lpr spr */
+{
+ {"us", 0x0, 0xff},
+ {"dcr", 0x1, 0xff},
+ {"bpc", 0x2, 0xff},
+ {"dsr", 0x3, 0xff},
+ {"car", 0x4, 0xff},
+ {"fp", 0x8, 0xff},
+ {"sp", 0x9, 0xff},
+ {"sb", 0xa, 0xff},
+ {"usp", 0xb, 0xff},
+ {"cfg", 0xc, 0xff},
+ {"psr", 0xd, 0xff},
+ {"intbase", 0xe, 0xff},
+ {"mod", 0xf, 0xff},
+ {0, 0x00, 0xff}
+};
+struct ns32k_option mmureg_532[] = /* lmr smr */
+{
+ {"mcr", 0x9, 0xff},
+ {"msr", 0xa, 0xff},
+ {"tear", 0xb, 0xff},
+ {"ptb0", 0xc, 0xff},
+ {"ptb1", 0xd, 0xff},
+ {"ivar0", 0xe, 0xff},
+ {"ivar1", 0xf, 0xff},
+ {0, 0x0, 0xff}
+};
+
+struct ns32k_option cpureg_032[] = /* lpr spr */
+{
+ {"upsr", 0x0, 0xff},
+ {"fp", 0x8, 0xff},
+ {"sp", 0x9, 0xff},
+ {"sb", 0xa, 0xff},
+ {"psr", 0xd, 0xff},
+ {"intbase", 0xe, 0xff},
+ {"mod", 0xf, 0xff},
+ {0, 0x0, 0xff}
+};
+struct ns32k_option mmureg_032[] = /* lmr smr */
+{
+ {"bpr0", 0x0, 0xff},
+ {"bpr1", 0x1, 0xff},
+ {"pf0", 0x4, 0xff},
+ {"pf1", 0x5, 0xff},
+ {"sc", 0x8, 0xff},
+ {"msr", 0xa, 0xff},
+ {"bcnt", 0xb, 0xff},
+ {"ptb0", 0xc, 0xff},
+ {"ptb1", 0xd, 0xff},
+ {"eia", 0xf, 0xff},
+ {0, 0x0, 0xff}
+};
+
+#if defined(NS32532)
+struct ns32k_option *cpureg = cpureg_532;
+struct ns32k_option *mmureg = mmureg_532;
+#else
+struct ns32k_option *cpureg = cpureg_032;
+struct ns32k_option *mmureg = mmureg_032;
+#endif
+
+
+const pseudo_typeS md_pseudo_table[] =
+{ /* so far empty */
+ {0, 0, 0}
+};
+
+#define IND(x,y) (((x)<<2)+(y))
+
+/* those are index's to relax groups in md_relax_table ie it must be
+ multiplied by 4 to point at a group start. Viz IND(x,y) Se function
+ relax_segment in write.c for more info */
+
+#define BRANCH 1
+#define PCREL 2
+
+/* those are index's to entries in a relax group */
+
+#define BYTE 0
+#define WORD 1
+#define DOUBLE 2
+#define UNDEF 3
+/* Those limits are calculated from the displacement start in memory.
+ The ns32k uses the begining of the instruction as displacement
+ base. This type of displacements could be handled here by moving
+ the limit window up or down. I choose to use an internal
+ displacement base-adjust as there are other routines that must
+ consider this. Also, as we have two various offset-adjusts in the
+ ns32k (acb versus br/brs/jsr/bcond), two set of limits would have
+ had to be used. Now we dont have to think about that. */
+
+
+const relax_typeS md_relax_table[] =
+{
+ {1, 1, 0, 0},
+ {1, 1, 0, 0},
+ {1, 1, 0, 0},
+ {1, 1, 0, 0},
+
+ {(63), (-64), 1, IND (BRANCH, WORD)},
+ {(8192), (-8192), 2, IND (BRANCH, DOUBLE)},
+ {0, 0, 4, 0},
+ {1, 1, 0, 0}
+};
+
+/* Array used to test if mode contains displacements.
+ Value is true if mode contains displacement. */
+
+char disp_test[] =
+{0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 0, 0, 1, 1, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1};
+
+/* Array used to calculate max size of displacements */
+
+char disp_size[] =
+{4, 1, 2, 0, 4};
+
+static void evaluate_expr PARAMS ((expressionS * resultP, char *ptr));
+static void md_number_to_disp PARAMS ((char *buf, long val, int n));
+static void md_number_to_imm PARAMS ((char *buf, long val, int n));
+
+/* Parses a general operand into an addressingmode struct
+
+ in: pointer at operand in ascii form
+ pointer at addr_mode struct for result
+ the level of recursion. (always 0 or 1)
+
+ out: data in addr_mode struct
+ */
+int
+addr_mode (operand, addr_modeP, recursive_level)
+ char *operand;
+ register addr_modeS *addr_modeP;
+ int recursive_level;
+{
+ register char *str;
+ register int i;
+ register int strl;
+ register int mode;
+ int j;
+ mode = DEFAULT; /* default */
+ addr_modeP->scaled_mode = 0; /* why not */
+ addr_modeP->scaled_reg = 0; /* if 0, not scaled index */
+ addr_modeP->float_flag = 0;
+ addr_modeP->am_size = 0;
+ addr_modeP->im_disp = 0;
+ addr_modeP->pcrel = 0; /* not set in this function */
+ addr_modeP->disp_suffix[0] = 0;
+ addr_modeP->disp_suffix[1] = 0;
+ addr_modeP->disp[0] = NULL;
+ addr_modeP->disp[1] = NULL;
+ str = operand;
+ if (str[0] == 0)
+ {
+ return (0);
+ } /* we don't want this */
+ strl = strlen (str);
+ switch (str[0])
+ {
+ /* the following three case statements controls the mode-chars
+ this is the place to ed if you want to change them */
+#ifdef ABSOLUTE_PREFIX
+ case ABSOLUTE_PREFIX:
+ if (str[strl - 1] == ']')
+ break;
+ addr_modeP->mode = 21; /* absolute */
+ addr_modeP->disp[0] = str + 1;
+ return (-1);
+#endif
+#ifdef IMMEDIATE_PREFIX
+ case IMMEDIATE_PREFIX:
+ if (str[strl - 1] == ']')
+ break;
+ addr_modeP->mode = 20; /* immediate */
+ addr_modeP->disp[0] = str + 1;
+ return (-1);
+#endif
+ case '.':
+ if (str[strl - 1] != ']')
+ {
+ switch (str[1])
+ {
+ case '-':
+ case '+':
+ if (str[2] != '\000')
+ {
+ addr_modeP->mode = 27; /* pc-relativ */
+ addr_modeP->disp[0] = str + 2;
+ return (-1);
+ }
+ default:
+ as_warn (_("Invalid syntax in PC-relative addressing mode"));
+ return (0);
+ }
+ }
+ break;
+ case 'e':
+ if (str[strl - 1] != ']')
+ {
+ if ((!strncmp (str, "ext(", 4)) && strl > 7)
+ { /* external */
+ addr_modeP->disp[0] = str + 4;
+ i = 0;
+ j = 2;
+ do
+ { /* disp[0]'s termination point */
+ j += 1;
+ if (str[j] == '(')
+ i++;
+ if (str[j] == ')')
+ i--;
+ }
+ while (j < strl && i != 0);
+ if (i != 0 || !(str[j + 1] == '-' || str[j + 1] == '+'))
+ {
+ as_warn (_("Invalid syntax in External addressing mode"));
+ return (0);
+ }
+ str[j] = '\000'; /* null terminate disp[0] */
+ addr_modeP->disp[1] = str + j + 2;
+ addr_modeP->mode = 22;
+ return (-1);
+ }
+ }
+ break;
+ default:;
+ }
+ strl = strlen (str);
+ switch (strl)
+ {
+ case 2:
+ switch (str[0])
+ {
+ case 'f':
+ addr_modeP->float_flag = 1;
+ case 'r':
+ if (str[1] >= '0' && str[1] < '8')
+ {
+ addr_modeP->mode = str[1] - '0';
+ return (-1);
+ }
+ }
+ case 3:
+ if (!strncmp (str, "tos", 3))
+ {
+ addr_modeP->mode = 23; /* TopOfStack */
+ return (-1);
+ }
+ default:;
+ }
+ if (strl > 4)
+ {
+ if (str[strl - 1] == ')')
+ {
+ if (str[strl - 2] == ')')
+ {
+ if (!strncmp (&str[strl - 5], "(fp", 3))
+ {
+ mode = 16; /* Memory Relative */
+ }
+ if (!strncmp (&str[strl - 5], "(sp", 3))
+ {
+ mode = 17;
+ }
+ if (!strncmp (&str[strl - 5], "(sb", 3))
+ {
+ mode = 18;
+ }
+ if (mode != DEFAULT)
+ { /* memory relative */
+ addr_modeP->mode = mode;
+ j = strl - 5; /* temp for end of disp[0] */
+ i = 0;
+ do
+ {
+ strl -= 1;
+ if (str[strl] == ')')
+ i++;
+ if (str[strl] == '(')
+ i--;
+ }
+ while (strl > -1 && i != 0);
+ if (i != 0)
+ {
+ as_warn (_("Invalid syntax in Memory Relative addressing mode"));
+ return (0);
+ }
+ addr_modeP->disp[1] = str;
+ addr_modeP->disp[0] = str + strl + 1;
+ str[j] = '\000'; /* null terminate disp[0] */
+ str[strl] = '\000'; /* null terminate disp[1] */
+ return (-1);
+ }
+ }
+ switch (str[strl - 3])
+ {
+ case 'r':
+ case 'R':
+ if (str[strl - 2] >= '0'
+ && str[strl - 2] < '8'
+ && str[strl - 4] == '(')
+ {
+ addr_modeP->mode = str[strl - 2] - '0' + 8;
+ addr_modeP->disp[0] = str;
+ str[strl - 4] = 0;
+ return (-1); /* reg rel */
+ }
+ default:
+ if (!strncmp (&str[strl - 4], "(fp", 3))
+ {
+ mode = 24;
+ }
+ if (!strncmp (&str[strl - 4], "(sp", 3))
+ {
+ mode = 25;
+ }
+ if (!strncmp (&str[strl - 4], "(sb", 3))
+ {
+ mode = 26;
+ }
+ if (!strncmp (&str[strl - 4], "(pc", 3))
+ {
+ mode = 27;
+ }
+ if (mode != DEFAULT)
+ {
+ addr_modeP->mode = mode;
+ addr_modeP->disp[0] = str;
+ str[strl - 4] = '\0';
+ return (-1); /* memory space */
+ }
+ }
+ }
+ /* no trailing ')' do we have a ']' ? */
+ if (str[strl - 1] == ']')
+ {
+ switch (str[strl - 2])
+ {
+ case 'b':
+ mode = 28;
+ break;
+ case 'w':
+ mode = 29;
+ break;
+ case 'd':
+ mode = 30;
+ break;
+ case 'q':
+ mode = 31;
+ break;
+ default:;
+ as_warn (_("Invalid scaled-indexed mode, use (b,w,d,q)"));
+ if (str[strl - 3] != ':' || str[strl - 6] != '['
+ || str[strl - 5] == 'r' || str[strl - 4] < '0'
+ || str[strl - 4] > '7')
+ {
+ as_warn (_("Syntax in scaled-indexed mode, use [Rn:m] where n=[0..7] m={b,w,d,q}"));
+ }
+ } /* scaled index */
+ {
+ if (recursive_level > 0)
+ {
+ as_warn (_("Scaled-indexed addressing mode combined with scaled-index"));
+ return (0);
+ }
+ addr_modeP->am_size += 1; /* scaled index byte */
+ j = str[strl - 4] - '0'; /* store temporary */
+ str[strl - 6] = '\000'; /* nullterminate for recursive call */
+ i = addr_mode (str, addr_modeP, 1);
+ if (!i || addr_modeP->mode == 20)
+ {
+ as_warn (_("Invalid or illegal addressing mode combined with scaled-index"));
+ return (0);
+ }
+ addr_modeP->scaled_mode = addr_modeP->mode; /* store the inferior
+ mode */
+ addr_modeP->mode = mode;
+ addr_modeP->scaled_reg = j + 1;
+ return (-1);
+ }
+ }
+ }
+ addr_modeP->mode = DEFAULT; /* default to whatever */
+ addr_modeP->disp[0] = str;
+ return (-1);
+}
+
+/* ptr points at string addr_modeP points at struct with result This
+ routine calls addr_mode to determine the general addr.mode of the
+ operand. When this is ready it parses the displacements for size
+ specifying suffixes and determines size of immediate mode via
+ ns32k-opcode. Also builds index bytes if needed. */
+int
+get_addr_mode (ptr, addr_modeP)
+ char *ptr;
+ addr_modeS *addr_modeP;
+{
+ int tmp;
+ addr_mode (ptr, addr_modeP, 0);
+ if (addr_modeP->mode == DEFAULT || addr_modeP->scaled_mode == -1)
+ {
+ /* resolve ambigious operands, this shouldn't be necessary if
+ one uses standard NSC operand syntax. But the sequent
+ compiler doesn't!!! This finds a proper addressinging mode
+ if it is implicitly stated. See ns32k-opcode.h */
+ (void) evaluate_expr (&exprP, ptr); /* this call takes time Sigh! */
+ if (addr_modeP->mode == DEFAULT)
+ {
+ if (exprP.X_add_symbol || exprP.X_op_symbol)
+ {
+ addr_modeP->mode = desc->default_model; /* we have a label */
+ }
+ else
+ {
+ addr_modeP->mode = desc->default_modec; /* we have a constant */
+ }
+ }
+ else
+ {
+ if (exprP.X_add_symbol || exprP.X_op_symbol)
+ {
+ addr_modeP->scaled_mode = desc->default_model;
+ }
+ else
+ {
+ addr_modeP->scaled_mode = desc->default_modec;
+ }
+ }
+ /* must put this mess down in addr_mode to handle the scaled
+ case better */
+ }
+ /* It appears as the sequent compiler wants an absolute when we have
+ a label without @. Constants becomes immediates besides the addr
+ case. Think it does so with local labels too, not optimum, pcrel
+ is better. When I have time I will make gas check this and
+ select pcrel when possible Actually that is trivial. */
+ if (tmp = addr_modeP->scaled_reg)
+ { /* build indexbyte */
+ tmp--; /* remember regnumber comes incremented for
+ flagpurpose */
+ tmp |= addr_modeP->scaled_mode << 3;
+ addr_modeP->index_byte = (char) tmp;
+ addr_modeP->am_size += 1;
+ }
+ if (disp_test[addr_modeP->mode])
+ { /* there was a displacement, probe for length
+ specifying suffix */
+ {
+ register char c;
+ register char suffix;
+ register char suffix_sub;
+ register int i;
+ register char *toP;
+ register char *fromP;
+
+ addr_modeP->pcrel = 0;
+ if (disp_test[addr_modeP->mode])
+ { /* there is a displacement */
+ if (addr_modeP->mode == 27 || addr_modeP->scaled_mode == 27)
+ { /* do we have pcrel. mode */
+ addr_modeP->pcrel = 1;
+ }
+ addr_modeP->im_disp = 1;
+ for (i = 0; i < 2; i++)
+ {
+ suffix_sub = suffix = 0;
+ if (toP = addr_modeP->disp[i])
+ { /* suffix of expression, the largest size
+ rules */
+ fromP = toP;
+ while (c = *fromP++)
+ {
+ *toP++ = c;
+ if (c == ':')
+ {
+ switch (*fromP)
+ {
+ case '\0':
+ as_warn (_("Premature end of suffix -- Defaulting to d"));
+ suffix = 4;
+ continue;
+ case 'b':
+ suffix_sub = 1;
+ break;
+ case 'w':
+ suffix_sub = 2;
+ break;
+ case 'd':
+ suffix_sub = 4;
+ break;
+ default:
+ as_warn (_("Bad suffix after ':' use {b|w|d} Defaulting to d"));
+ suffix = 4;
+ }
+ fromP++;
+ toP--; /* So we write over the ':' */
+ if (suffix < suffix_sub)
+ suffix = suffix_sub;
+ }
+ }
+ *toP = '\0';/* terminate properly */
+ addr_modeP->disp_suffix[i] = suffix;
+ addr_modeP->am_size += suffix ? suffix : 4;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (addr_modeP->mode == 20)
+ { /* look in ns32k_opcode for size */
+ addr_modeP->disp_suffix[0] = addr_modeP->am_size = desc->im_size;
+ addr_modeP->im_disp = 0;
+ }
+ }
+ return addr_modeP->mode;
+}
+
+
+/* read an optionlist */
+void
+optlist (str, optionP, default_map)
+ char *str; /* the string to extract options from */
+ struct ns32k_option *optionP; /* how to search the string */
+ unsigned long *default_map; /* default pattern and output */
+{
+ register int i, j, k, strlen1, strlen2;
+ register char *patternP, *strP;
+ strlen1 = strlen (str);
+ if (strlen1 < 1)
+ {
+ as_fatal (_("Very short instr to option, ie you can't do it on a NULLstr"));
+ }
+ for (i = 0; optionP[i].pattern != 0; i++)
+ {
+ strlen2 = strlen (optionP[i].pattern);
+ for (j = 0; j < strlen1; j++)
+ {
+ patternP = optionP[i].pattern;
+ strP = &str[j];
+ for (k = 0; k < strlen2; k++)
+ {
+ if (*(strP++) != *(patternP++))
+ break;
+ }
+ if (k == strlen2)
+ { /* match */
+ *default_map |= optionP[i].or;
+ *default_map &= optionP[i].and;
+ }
+ }
+ }
+}
+
+/* search struct for symbols
+ This function is used to get the short integer form of reg names in
+ the instructions lmr, smr, lpr, spr return true if str is found in
+ list */
+
+int
+list_search (str, optionP, default_map)
+ char *str; /* the string to match */
+ struct ns32k_option *optionP; /* list to search */
+ unsigned long *default_map; /* default pattern and output */
+{
+ register int i;
+ for (i = 0; optionP[i].pattern != 0; i++)
+ {
+ if (!strncmp (optionP[i].pattern, str, 20))
+ { /* use strncmp to be safe */
+ *default_map |= optionP[i].or;
+ *default_map &= optionP[i].and;
+ return -1;
+ }
+ }
+ as_warn (_("No such entry in list. (cpu/mmu register)"));
+ return 0;
+}
+
+static void
+evaluate_expr (resultP, ptr)
+ expressionS *resultP;
+ char *ptr;
+{
+ register char *tmp_line;
+
+ tmp_line = input_line_pointer;
+ input_line_pointer = ptr;
+ expression (&exprP);
+ input_line_pointer = tmp_line;
+}
+
+/* Convert operands to iif-format and adds bitfields to the opcode.
+ Operands are parsed in such an order that the opcode is updated from
+ its most significant bit, that is when the operand need to alter the
+ opcode.
+ Be carefull not to put to objects in the same iif-slot.
+ */
+
+void
+encode_operand (argc, argv, operandsP, suffixP, im_size, opcode_bit_ptr)
+ int argc;
+ char **argv;
+ char *operandsP;
+ char *suffixP;
+ char im_size;
+ char opcode_bit_ptr;
+{
+ register int i, j;
+ char d;
+ int pcrel, tmp, b, loop, pcrel_adjust;
+ for (loop = 0; loop < argc; loop++)
+ {
+ i = operandsP[loop << 1] - '1'; /* what operand are we supposed
+ to work on */
+ if (i > 3)
+ as_fatal (_("Internal consistency error. check ns32k-opcode.h"));
+ pcrel = 0;
+ pcrel_adjust = 0;
+ tmp = 0;
+ switch ((d = operandsP[(loop << 1) + 1]))
+ {
+ case 'f': /* operand of sfsr turns out to be a nasty
+ specialcase */
+ opcode_bit_ptr -= 5;
+ case 'Z': /* float not immediate */
+ case 'F': /* 32 bit float general form */
+ case 'L': /* 64 bit float */
+ case 'I': /* integer not immediate */
+ case 'B': /* byte */
+ case 'W': /* word */
+ case 'D': /* double-word */
+ case 'A': /* double-word gen-address-form ie no regs
+ allowed */
+ get_addr_mode (argv[i], &addr_modeP);
+ if((addr_modeP.mode == 20) &&
+ (d == 'I' || d == 'Z' || d == 'A')) {
+ as_fatal(d == 'A'? _("Address of immediate operand"):
+ _("Invalid immediate write operand."));
+ }
+
+ if (opcode_bit_ptr == desc->opcode_size)
+ b = 4;
+ else
+ b = 6;
+ for (j = b; j < (b + 2); j++)
+ {
+ if (addr_modeP.disp[j - b])
+ {
+ IIF (j,
+ 2,
+ addr_modeP.disp_suffix[j - b],
+ (unsigned long) addr_modeP.disp[j - b],
+ 0,
+ addr_modeP.pcrel,
+ iif.instr_size,
+ addr_modeP.im_disp,
+ IND (BRANCH, BYTE),
+ NULL,
+ (addr_modeP.scaled_reg ? addr_modeP.scaled_mode
+ : addr_modeP.mode),
+ 0);
+ }
+ }
+ opcode_bit_ptr -= 5;
+ iif.iifP[1].object |= ((long) addr_modeP.mode) << opcode_bit_ptr;
+ if (addr_modeP.scaled_reg)
+ {
+ j = b / 2;
+ IIF (j, 1, 1, (unsigned long) addr_modeP.index_byte,
+ 0, 0, 0, 0, 0, NULL, -1, 0);
+ }
+ break;
+ case 'b': /* multiple instruction disp */
+ freeptr++; /* OVE:this is an useful hack */
+ sprintf (freeptr, "((%s-1)*%d)\000", argv[i], desc->im_size);
+ argv[i] = freeptr;
+ pcrel -= 1; /* make pcrel 0 inspite of what case 'p':
+ wants */
+ /* fall thru */
+ case 'p': /* displacement - pc relative addressing */
+ pcrel += 1;
+ /* fall thru */
+ case 'd': /* displacement */
+ iif.instr_size += suffixP[i] ? suffixP[i] : 4;
+ IIF (12, 2, suffixP[i], (unsigned long) argv[i], 0,
+ pcrel, pcrel_adjust, 1, IND (BRANCH, BYTE), NULL, -1, 0);
+ break;
+ case 'H': /* sequent-hack: the linker wants a bit set
+ when bsr */
+ pcrel = 1;
+ iif.instr_size += suffixP[i] ? suffixP[i] : 4;
+ IIF (12, 2, suffixP[i], (unsigned long) argv[i], 0,
+ pcrel, pcrel_adjust, 1, IND (BRANCH, BYTE), NULL, -1, 1);
+ break;
+ case 'q': /* quick */
+ opcode_bit_ptr -= 4;
+ IIF (11, 2, 42, (unsigned long) argv[i], 0, 0, 0, 0, 0,
+ bit_fix_new (4, opcode_bit_ptr, -8, 7, 0, 1, 0), -1, 0);
+ break;
+ case 'r': /* register number (3 bits) */
+ list_search (argv[i], opt6, &tmp);
+ opcode_bit_ptr -= 3;
+ iif.iifP[1].object |= tmp << opcode_bit_ptr;
+ break;
+ case 'O': /* setcfg instruction optionslist */
+ optlist (argv[i], opt3, &tmp);
+ opcode_bit_ptr -= 4;
+ iif.iifP[1].object |= tmp << 15;
+ break;
+ case 'C': /* cinv instruction optionslist */
+ optlist (argv[i], opt4, &tmp);
+ opcode_bit_ptr -= 4;
+ iif.iifP[1].object |= tmp << 15; /* insert the regtype in opcode */
+ break;
+ case 'S': /* stringinstruction optionslist */
+ optlist (argv[i], opt5, &tmp);
+ opcode_bit_ptr -= 4;
+ iif.iifP[1].object |= tmp << 15;
+ break;
+ case 'u':
+ case 'U': /* registerlist */
+ IIF (10, 1, 1, 0, 0, 0, 0, 0, 0, NULL, -1, 0);
+ switch (operandsP[(i << 1) + 1])
+ {
+ case 'u': /* restore, exit */
+ optlist (argv[i], opt1, &iif.iifP[10].object);
+ break;
+ case 'U': /* save,enter */
+ optlist (argv[i], opt2, &iif.iifP[10].object);
+ break;
+ }
+ iif.instr_size += 1;
+ break;
+ case 'M': /* mmu register */
+ list_search (argv[i], mmureg, &tmp);
+ opcode_bit_ptr -= 4;
+ iif.iifP[1].object |= tmp << opcode_bit_ptr;
+ break;
+ case 'P': /* cpu register */
+ list_search (argv[i], cpureg, &tmp);
+ opcode_bit_ptr -= 4;
+ iif.iifP[1].object |= tmp << opcode_bit_ptr;
+ break;
+ case 'g': /* inss exts */
+ iif.instr_size += 1; /* 1 byte is allocated after the opcode */
+ IIF (10, 2, 1,
+ (unsigned long) argv[i], /* i always 2 here */
+ 0, 0, 0, 0, 0,
+ bit_fix_new (3, 5, 0, 7, 0, 0, 0), /* a bit_fix is targeted to
+ the byte */
+ -1, 0);
+ break;
+ case 'G':
+ IIF (11, 2, 42,
+ (unsigned long) argv[i], /* i always 3 here */
+ 0, 0, 0, 0, 0,
+ bit_fix_new (5, 0, 1, 32, -1, 0, -1), -1, 0);
+ break;
+ case 'i':
+ iif.instr_size += 1;
+ b = 2 + i; /* put the extension byte after opcode */
+ IIF (b, 2, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0);
+ break;
+ default:
+ as_fatal (_("Bad opcode-table-option, check in file ns32k-opcode.h"));
+ }
+ }
+}
+
+/* in: instruction line
+ out: internal structure of instruction
+ that has been prepared for direct conversion to fragment(s) and
+ fixes in a systematical fashion
+ Return-value = recursive_level
+ */
+/* build iif of one assembly text line */
+int
+parse (line, recursive_level)
+ char *line;
+ int recursive_level;
+{
+ register char *lineptr, c, suffix_separator;
+ register int i;
+ int argc, arg_type;
+ char sqr, sep;
+ char suffix[MAX_ARGS], *argv[MAX_ARGS]; /* no more than 4 operands */
+ if (recursive_level <= 0)
+ { /* called from md_assemble */
+ for (lineptr = line; (*lineptr) != '\0' && (*lineptr) != ' '; lineptr++);
+ c = *lineptr;
+ *lineptr = '\0';
+ if (!(desc = (struct ns32k_opcode *) hash_find (inst_hash_handle, line)))
+ {
+ as_fatal (_("No such opcode"));
+ }
+ *lineptr = c;
+ }
+ else
+ {
+ lineptr = line;
+ }
+ argc = 0;
+ if (*desc->operands)
+ {
+ if (*lineptr++ != '\0')
+ {
+ sqr = '[';
+ sep = ',';
+ while (*lineptr != '\0')
+ {
+ if (desc->operands[argc << 1])
+ {
+ suffix[argc] = 0;
+ arg_type = desc->operands[(argc << 1) + 1];
+ switch (arg_type)
+ {
+ case 'd':
+ case 'b':
+ case 'p':
+ case 'H': /* the operand is supposed to be a
+ displacement */
+ /* Hackwarning: do not forget to update the 4
+ cases above when editing ns32k-opcode.h */
+ suffix_separator = ':';
+ break;
+ default:
+ suffix_separator = '\255'; /* if this char occurs we
+ loose */
+ }
+ suffix[argc] = 0; /* 0 when no ':' is encountered */
+ argv[argc] = freeptr;
+ *freeptr = '\0';
+ while ((c = *lineptr) != '\0' && c != sep)
+ {
+ if (c == sqr)
+ {
+ if (sqr == '[')
+ {
+ sqr = ']';
+ sep = '\0';
+ }
+ else
+ {
+ sqr = '[';
+ sep = ',';
+ }
+ }
+ if (c == suffix_separator)
+ { /* ':' - label/suffix separator */
+ switch (lineptr[1])
+ {
+ case 'b':
+ suffix[argc] = 1;
+ break;
+ case 'w':
+ suffix[argc] = 2;
+ break;
+ case 'd':
+ suffix[argc] = 4;
+ break;
+ default:
+ as_warn (_("Bad suffix, defaulting to d"));
+ suffix[argc] = 4;
+ if (lineptr[1] == '\0' || lineptr[1] == sep)
+ {
+ lineptr += 1;
+ continue;
+ }
+ }
+ lineptr += 2;
+ continue;
+ }
+ *freeptr++ = c;
+ lineptr++;
+ }
+ *freeptr++ = '\0';
+ argc += 1;
+ if (*lineptr == '\0')
+ continue;
+ lineptr += 1;
+ }
+ else
+ {
+ as_fatal (_("Too many operands passed to instruction"));
+ }
+ }
+ }
+ }
+ if (argc != strlen (desc->operands) / 2)
+ {
+ if (strlen (desc->default_args))
+ { /* we can apply default, dont goof */
+ if (parse (desc->default_args, 1) != 1)
+ { /* check error in default */
+ as_fatal (_("Wrong numbers of operands in default, check ns32k-opcodes.h"));
+ }
+ }
+ else
+ {
+ as_fatal (_("Wrong number of operands"));
+ }
+
+ }
+ for (i = 0; i < IIF_ENTRIES; i++)
+ {
+ iif.iifP[i].type = 0; /* mark all entries as void*/
+ }
+
+ /* build opcode iif-entry */
+ iif.instr_size = desc->opcode_size / 8;
+ IIF (1, 1, iif.instr_size, desc->opcode_seed, 0, 0, 0, 0, 0, 0, -1, 0);
+
+ /* this call encodes operands to iif format */
+ if (argc)
+ {
+ encode_operand (argc,
+ argv,
+ &desc->operands[0],
+ &suffix[0],
+ desc->im_size,
+ desc->opcode_size);
+ }
+ return recursive_level;
+}
+
+
+/* Convert iif to fragments. From this point we start to dribble with
+ * functions in other files than this one.(Except hash.c) So, if it's
+ * possible to make an iif for an other CPU, you don't need to know
+ * what frags, relax, obstacks, etc is in order to port this
+ * assembler. You only need to know if it's possible to reduce your
+ * cpu-instruction to iif-format (takes some work) and adopt the other
+ * md_? parts according to given instructions Note that iif was
+ * invented for the clean ns32k`s architecure.
+ */
+
+/* GAS for the ns32k has a problem. PC relative displacements are
+ * relative to the address of the opcode, not the address of the
+ * operand. We used to keep track of the offset between the operand
+ * and the opcode in pcrel_adjust for each frag and each fix. However,
+ * we get into trouble where there are two or more pc-relative
+ * operands and the size of the first one can't be determined. Then in
+ * the relax phase, the size of the first operand will change and
+ * pcrel_adjust will no longer be correct. The current solution is
+ * keep a pointer to the frag with the opcode in it and the offset in
+ * that frag for each frag and each fix. Then, when needed, we can
+ * always figure out how far it is between the opcode and the pcrel
+ * object. See also md_pcrel_adjust and md_fix_pcrel_adjust. For
+ * objects not part of an instruction, the pointer to the opcode frag
+ * is always zero. */
+
+void
+convert_iif ()
+{
+ int i;
+ bit_fixS *j;
+ fragS *inst_frag;
+ unsigned int inst_offset;
+ char *inst_opcode;
+ char *memP;
+ int l;
+ int k;
+ char type;
+ char size = 0;
+ int size_so_far;
+
+ memP = frag_more (0);
+ inst_opcode = memP;
+ inst_offset = (memP - frag_now->fr_literal);
+ inst_frag = frag_now;
+
+ for (i = 0; i < IIF_ENTRIES; i++)
+ {
+ if (type = iif.iifP[i].type)
+ { /* the object exist, so handle it */
+ switch (size = iif.iifP[i].size)
+ {
+ case 42:
+ size = 0; /* it's a bitfix that operates on an existing
+ object*/
+ if (iif.iifP[i].bit_fixP->fx_bit_base)
+ { /* expand fx_bit_base to point at opcode */
+ iif.iifP[i].bit_fixP->fx_bit_base = (long) inst_opcode;
+ }
+ case 8: /* bignum or doublefloat */
+ case 1:
+ case 2:
+ case 3:
+ case 4: /* the final size in objectmemory is known */
+ memP = frag_more(size);
+ j = iif.iifP[i].bit_fixP;
+ switch (type)
+ {
+ case 1: /* the object is pure binary */
+ if (j || iif.iifP[i].pcrel)
+ {
+ fix_new_ns32k (frag_now,
+ (long) (memP - frag_now->fr_literal),
+ size,
+ 0,
+ iif.iifP[i].object,
+ iif.iifP[i].pcrel,
+ iif.iifP[i].im_disp,
+ j,
+ iif.iifP[i].bsr, /* sequent hack */
+ inst_frag, inst_offset);
+ }
+ else
+ { /* good, just put them bytes out */
+ switch (iif.iifP[i].im_disp)
+ {
+ case 0:
+ md_number_to_chars (memP, iif.iifP[i].object, size);
+ break;
+ case 1:
+ md_number_to_disp (memP, iif.iifP[i].object, size);
+ break;
+ default:
+ as_fatal (_("iif convert internal pcrel/binary"));
+ }
+ }
+ break;
+ case 2:
+ /* the object is a pointer at an expression, so
+ unpack it, note that bignums may result from the
+ expression */
+ evaluate_expr (&exprP, (char *) iif.iifP[i].object);
+ if (exprP.X_op == O_big || size == 8)
+ {
+ if ((k = exprP.X_add_number) > 0)
+ {
+ /* we have a bignum ie a quad. This can only
+ happens in a long suffixed instruction */
+ if (k * 2 > size)
+ as_warn (_("Bignum too big for long"));
+ if (k == 3)
+ memP += 2;
+ for (l = 0; k > 0; k--, l += 2)
+ {
+ md_number_to_chars (memP + l,
+ generic_bignum[l >> 1],
+ sizeof (LITTLENUM_TYPE));
+ }
+ }
+ else
+ { /* flonum */
+ LITTLENUM_TYPE words[4];
+
+ switch (size)
+ {
+ case 4:
+ gen_to_words (words, 2, 8);
+ md_number_to_imm (memP, (long) words[0],
+ sizeof (LITTLENUM_TYPE));
+ md_number_to_imm (memP + sizeof (LITTLENUM_TYPE),
+ (long) words[1],
+ sizeof (LITTLENUM_TYPE));
+ break;
+ case 8:
+ gen_to_words (words, 4, 11);
+ md_number_to_imm (memP, (long) words[0],
+ sizeof (LITTLENUM_TYPE));
+ md_number_to_imm (memP + sizeof (LITTLENUM_TYPE),
+ (long) words[1],
+ sizeof (LITTLENUM_TYPE));
+ md_number_to_imm ((memP + 2
+ * sizeof (LITTLENUM_TYPE)),
+ (long) words[2],
+ sizeof (LITTLENUM_TYPE));
+ md_number_to_imm ((memP + 3
+ * sizeof (LITTLENUM_TYPE)),
+ (long) words[3],
+ sizeof (LITTLENUM_TYPE));
+ break;
+ }
+ }
+ break;
+ }
+ if (j ||
+ exprP.X_add_symbol ||
+ exprP.X_op_symbol ||
+ iif.iifP[i].pcrel)
+ {
+ /* The expression was undefined due to an
+ undefined label. Create a fix so we can fix
+ the object later. */
+ exprP.X_add_number += iif.iifP[i].object_adjust;
+ fix_new_ns32k_exp (frag_now,
+ (long) (memP - frag_now->fr_literal),
+ size,
+ &exprP,
+ iif.iifP[i].pcrel,
+ iif.iifP[i].im_disp,
+ j,
+ iif.iifP[i].bsr,
+ inst_frag, inst_offset);
+ }
+ else
+ {
+ /* good, just put them bytes out */
+ switch (iif.iifP[i].im_disp)
+ {
+ case 0:
+ md_number_to_imm (memP, exprP.X_add_number, size);
+ break;
+ case 1:
+ md_number_to_disp (memP, exprP.X_add_number, size);
+ break;
+ default:
+ as_fatal (_("iif convert internal pcrel/pointer"));
+ }
+ }
+ break;
+ default:
+ as_fatal (_("Internal logic error in iif.iifP[n].type"));
+ }
+ break;
+ case 0:
+ /* To bad, the object may be undefined as far as its
+ final nsize in object memory is concerned. The size
+ of the object in objectmemory is not explicitly
+ given. If the object is defined its length can be
+ determined and a fix can replace the frag. */
+ {
+ evaluate_expr (&exprP, (char *) iif.iifP[i].object);
+ if ((exprP.X_add_symbol || exprP.X_op_symbol) &&
+ !iif.iifP[i].pcrel)
+ {
+ /* Size is unknown until link time so have to
+ allow 4 bytes. */
+ size = 4;
+ memP = frag_more(size);
+ fix_new_ns32k_exp (frag_now,
+ (long) (memP - frag_now->fr_literal),
+ size,
+ &exprP,
+ 0, /* never iif.iifP[i].pcrel, */
+ 1, /* always iif.iifP[i].im_disp */
+ (bit_fixS *) 0, 0,
+ inst_frag,
+ inst_offset);
+ break; /* exit this absolute hack */
+ }
+
+ if (exprP.X_add_symbol || exprP.X_op_symbol)
+ { /* frag it */
+ if (exprP.X_op_symbol)
+ { /* We cant relax this case */
+ as_fatal (_("Can't relax difference"));
+ }
+ else
+ {
+
+ /* Size is not important. This gets fixed by relax,
+ * but we assume 0 in what follows
+ */
+ memP = frag_more(4); /* Max size */
+ size = 0;
+
+ {
+ fragS *old_frag = frag_now;
+ frag_variant (rs_machine_dependent,
+ 4, /* Max size */
+ 0, /* size */
+ IND (BRANCH, UNDEF), /* expecting the worst */
+ exprP.X_add_symbol,
+ exprP.X_add_number,
+ inst_opcode);
+ frag_opcode_frag(old_frag) = inst_frag;
+ frag_opcode_offset(old_frag) = inst_offset;
+ frag_bsr(old_frag) = iif.iifP[i].bsr;
+ }
+ }
+ }
+ else
+ {
+ /* This duplicates code in md_number_to_disp */
+ if (-64 <= exprP.X_add_number && exprP.X_add_number <= 63)
+ {
+ size = 1;
+ }
+ else
+ {
+ if (-8192 <= exprP.X_add_number
+ && exprP.X_add_number <= 8191)
+ {
+ size = 2;
+ }
+ else
+ {
+ if (-0x20000000<=exprP.X_add_number &&
+ exprP.X_add_number<=0x1fffffff)
+ {
+ size = 4;
+ }
+ else
+ {
+ as_warn (_("Displacement to large for :d"));
+ size = 4;
+ }
+ }
+ }
+ memP = frag_more(size);
+ md_number_to_disp (memP, exprP.X_add_number, size);
+ }
+ }
+ break;
+ default:
+ as_fatal (_("Internal logic error in iif.iifP[].type"));
+ }
+ }
+ }
+}
+
+#ifdef BFD_ASSEMBLER
+/* This functionality should really be in the bfd library */
+static bfd_reloc_code_real_type
+reloc (int size, int pcrel, int type)
+{
+ int length, index;
+ bfd_reloc_code_real_type relocs[] = {
+ BFD_RELOC_NS32K_IMM_8,
+ BFD_RELOC_NS32K_IMM_16,
+ BFD_RELOC_NS32K_IMM_32,
+ BFD_RELOC_NS32K_IMM_8_PCREL,
+ BFD_RELOC_NS32K_IMM_16_PCREL,
+ BFD_RELOC_NS32K_IMM_32_PCREL,
+
+ /* ns32k displacements */
+ BFD_RELOC_NS32K_DISP_8,
+ BFD_RELOC_NS32K_DISP_16,
+ BFD_RELOC_NS32K_DISP_32,
+ BFD_RELOC_NS32K_DISP_8_PCREL,
+ BFD_RELOC_NS32K_DISP_16_PCREL,
+ BFD_RELOC_NS32K_DISP_32_PCREL,
+
+ /* Normal 2's complement */
+ BFD_RELOC_8,
+ BFD_RELOC_16,
+ BFD_RELOC_32,
+ BFD_RELOC_8_PCREL,
+ BFD_RELOC_16_PCREL,
+ BFD_RELOC_32_PCREL
+ };
+ switch (size)
+ {
+ case 1:
+ length = 0;
+ break;
+ case 2:
+ length = 1;
+ break;
+ case 4:
+ length = 2;
+ break;
+ default:
+ length = -1;
+ break;
+ }
+ index = length + 3 * pcrel + 6 * type;
+ if (index >= 0 && index < sizeof(relocs)/sizeof(relocs[0]))
+ return relocs[index];
+ if (pcrel)
+ as_bad (_("Can not do %d byte pc-relative relocation for storage type %d"),
+ size, type);
+ else
+ as_bad (_("Can not do %d byte relocation for storage type %d"),
+ size, type);
+ return BFD_RELOC_NONE;
+
+}
+
+#endif
+
+void
+md_assemble (line)
+ char *line;
+{
+ freeptr = freeptr_static;
+ parse (line, 0); /* explode line to more fix form in iif */
+ convert_iif (); /* convert iif to frags, fix's etc */
+#ifdef SHOW_NUM
+ printf (" \t\t\t%s\n", line);
+#endif
+}
+
+
+void
+md_begin ()
+{
+ /* build a hashtable of the instructions */
+ const struct ns32k_opcode *ptr;
+ const char *stat;
+ inst_hash_handle = hash_new ();
+ for (ptr = ns32k_opcodes; ptr < endop; ptr++)
+ {
+ if ((stat = hash_insert (inst_hash_handle, ptr->name, (char *) ptr)))
+ {
+ as_fatal (_("Can't hash %s: %s"), ptr->name, stat); /*fatal*/
+ }
+ }
+ freeptr_static = (char *) malloc (PRIVATE_SIZE); /* some private space
+ please! */
+}
+
+/* Must be equal to MAX_PRECISON in atof-ieee.c */
+#define MAX_LITTLENUMS 6
+
+/* Turn the string pointed to by litP into a floating point constant
+ of type type, and emit the appropriate bytes. The number of
+ LITTLENUMS emitted is stored in *sizeP . An error message is
+ returned, or NULL on OK. */
+char *
+md_atof (type, litP, sizeP)
+ char type;
+ char *litP;
+ int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ char *t;
+
+ switch (type)
+ {
+ case 'f':
+ prec = 2;
+ break;
+
+ case 'd':
+ prec = 4;
+ break;
+ default:
+ *sizeP = 0;
+ return _("Bad call to MD_ATOF()");
+ }
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+
+ *sizeP = prec * sizeof (LITTLENUM_TYPE);
+ for (wordP = words + prec; prec--;)
+ {
+ md_number_to_chars (litP, (long) (*--wordP), sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+ return 0;
+}
+
+/* Convert number to chars in correct order */
+
+void
+md_number_to_chars (buf, value, nbytes)
+ char *buf;
+ valueT value;
+ int nbytes;
+{
+ number_to_chars_littleendian (buf, value, nbytes);
+}
+
+
+/* This is a variant of md_numbers_to_chars. The reason for its'
+ existence is the fact that ns32k uses Huffman coded
+ displacements. This implies that the bit order is reversed in
+ displacements and that they are prefixed with a size-tag.
+
+ binary: msb -> lsb
+ 0xxxxxxx byte
+ 10xxxxxx xxxxxxxx word
+ 11xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx double word
+
+ This must be taken care of and we do it here! */
+static void
+md_number_to_disp (buf, val, n)
+ char *buf;
+ long val;
+ char n;
+{
+ switch (n)
+ {
+ case 1:
+ if (val < -64 || val > 63)
+ as_warn (_("Byte displacement out of range. line number not valid"));
+ val &= 0x7f;
+#ifdef SHOW_NUM
+ printf ("%x ", val & 0xff);
+#endif
+ *buf++ = val;
+ break;
+ case 2:
+ if (val < -8192 || val > 8191)
+ as_warn (_("Word displacement out of range. line number not valid"));
+ val &= 0x3fff;
+ val |= 0x8000;
+#ifdef SHOW_NUM
+ printf ("%x ", val >> 8 & 0xff);
+#endif
+ *buf++ = (val >> 8);
+#ifdef SHOW_NUM
+ printf ("%x ", val & 0xff);
+#endif
+ *buf++ = val;
+ break;
+ case 4:
+ if (val < -0x20000000 || val >= 0x20000000)
+ as_warn (_("Double word displacement out of range"));
+ val |= 0xc0000000;
+#ifdef SHOW_NUM
+ printf ("%x ", val >> 24 & 0xff);
+#endif
+ *buf++ = (val >> 24);
+#ifdef SHOW_NUM
+ printf ("%x ", val >> 16 & 0xff);
+#endif
+ *buf++ = (val >> 16);
+#ifdef SHOW_NUM
+ printf ("%x ", val >> 8 & 0xff);
+#endif
+ *buf++ = (val >> 8);
+#ifdef SHOW_NUM
+ printf ("%x ", val & 0xff);
+#endif
+ *buf++ = val;
+ break;
+ default:
+ as_fatal (_("Internal logic error. line %s, file \"%s\""),
+ __LINE__, __FILE__);
+ }
+}
+
+static void
+md_number_to_imm (buf, val, n)
+ char *buf;
+ long val;
+ char n;
+{
+ switch (n)
+ {
+ case 1:
+#ifdef SHOW_NUM
+ printf ("%x ", val & 0xff);
+#endif
+ *buf++ = val;
+ break;
+ case 2:
+#ifdef SHOW_NUM
+ printf ("%x ", val >> 8 & 0xff);
+#endif
+ *buf++ = (val >> 8);
+#ifdef SHOW_NUM
+ printf ("%x ", val & 0xff);
+#endif
+ *buf++ = val;
+ break;
+ case 4:
+#ifdef SHOW_NUM
+ printf ("%x ", val >> 24 & 0xff);
+#endif
+ *buf++ = (val >> 24);
+#ifdef SHOW_NUM
+ printf ("%x ", val >> 16 & 0xff);
+#endif
+ *buf++ = (val >> 16);
+#ifdef SHOW_NUM
+ printf ("%x ", val >> 8 & 0xff);
+#endif
+ *buf++ = (val >> 8);
+#ifdef SHOW_NUM
+ printf ("%x ", val & 0xff);
+#endif
+ *buf++ = val;
+ break;
+ default:
+ as_fatal (_("Internal logic error. line %s, file \"%s\""),
+ __LINE__, __FILE__);
+ }
+}
+
+
+/* fast bitfiddling support */
+/* mask used to zero bitfield before oring in the true field */
+
+static unsigned long l_mask[] =
+{
+ 0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8,
+ 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80,
+ 0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800,
+ 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000,
+ 0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000,
+ 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000,
+ 0xff000000, 0xfe000000, 0xfc000000, 0xf8000000,
+ 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000,
+};
+static unsigned long r_mask[] =
+{
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007,
+ 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
+ 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
+ 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
+ 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
+ 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
+ 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
+ 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
+};
+#define MASK_BITS 31
+/* Insert bitfield described by field_ptr and val at buf
+ This routine is written for modification of the first 4 bytes pointed
+ to by buf, to yield speed.
+ The ifdef stuff is for selection between a ns32k-dependent routine
+ and a general version. (My advice: use the general version!)
+ */
+
+static void
+md_number_to_field (buf, val, field_ptr)
+ register char *buf;
+ register long val;
+ register bit_fixS *field_ptr;
+{
+ register unsigned long object;
+ register unsigned long mask;
+ /* define ENDIAN on a ns32k machine */
+#ifdef ENDIAN
+ register unsigned long *mem_ptr;
+#else
+ register char *mem_ptr;
+#endif
+ if (field_ptr->fx_bit_min <= val && val <= field_ptr->fx_bit_max)
+ {
+#ifdef ENDIAN
+ if (field_ptr->fx_bit_base)
+ { /* override buf */
+ mem_ptr = (unsigned long *) field_ptr->fx_bit_base;
+ }
+ else
+ {
+ mem_ptr = (unsigned long *) buf;
+ }
+ mem_ptr = ((unsigned long *)
+ ((char *) mem_ptr + field_ptr->fx_bit_base_adj));
+#else
+ if (field_ptr->fx_bit_base)
+ { /* override buf */
+ mem_ptr = (char *) field_ptr->fx_bit_base;
+ }
+ else
+ {
+ mem_ptr = buf;
+ }
+ mem_ptr += field_ptr->fx_bit_base_adj;
+#endif
+#ifdef ENDIAN /* we have a nice ns32k machine with lowbyte
+ at low-physical mem */
+ object = *mem_ptr; /* get some bytes */
+#else /* OVE Goof! the machine is a m68k or dito */
+ /* That takes more byte fiddling */
+ object = 0;
+ object |= mem_ptr[3] & 0xff;
+ object <<= 8;
+ object |= mem_ptr[2] & 0xff;
+ object <<= 8;
+ object |= mem_ptr[1] & 0xff;
+ object <<= 8;
+ object |= mem_ptr[0] & 0xff;
+#endif
+ mask = 0;
+ mask |= (r_mask[field_ptr->fx_bit_offset]);
+ mask |= (l_mask[field_ptr->fx_bit_offset + field_ptr->fx_bit_size]);
+ object &= mask;
+ val += field_ptr->fx_bit_add;
+ object |= ((val << field_ptr->fx_bit_offset) & (mask ^ 0xffffffff));
+#ifdef ENDIAN
+ *mem_ptr = object;
+#else
+ mem_ptr[0] = (char) object;
+ object >>= 8;
+ mem_ptr[1] = (char) object;
+ object >>= 8;
+ mem_ptr[2] = (char) object;
+ object >>= 8;
+ mem_ptr[3] = (char) object;
+#endif
+ }
+ else
+ {
+ as_warn (_("Bit field out of range"));
+ }
+}
+
+int md_pcrel_adjust (fragS *fragP)
+{
+ fragS *opcode_frag;
+ addressT opcode_address;
+ unsigned int offset;
+ opcode_frag = frag_opcode_frag(fragP);
+ if (opcode_frag == 0)
+ return 0;
+ offset = frag_opcode_offset(fragP);
+ opcode_address = offset + opcode_frag->fr_address;
+ return fragP->fr_address + fragP->fr_fix - opcode_address;
+}
+
+int md_fix_pcrel_adjust (fixS *fixP)
+{
+ fragS *fragP = fixP->fx_frag;
+ fragS *opcode_frag;
+ addressT opcode_address;
+ unsigned int offset;
+ opcode_frag = fix_opcode_frag(fixP);
+ if (opcode_frag == 0)
+ return 0;
+ offset = fix_opcode_offset(fixP);
+ opcode_address = offset + opcode_frag->fr_address;
+ return fixP->fx_where + fixP->fx_frag->fr_address - opcode_address;
+}
+
+/* Apply a fixS (fixup of an instruction or data that we didn't have
+ enough info to complete immediately) to the data in a frag.
+
+ On the ns32k, everything is in a different format, so we have broken
+ out separate functions for each kind of thing we could be fixing.
+ They all get called from here. */
+
+#ifdef BFD_ASSEMBLER
+int
+md_apply_fix (fixP, valp)
+ fixS *fixP;
+ valueT *valp;
+#else
+void
+md_apply_fix (fixP, val)
+ fixS *fixP;
+ long val;
+#endif
+{
+#ifdef BFD_ASSEMBLER
+ long val = *valp;
+#endif
+ fragS *fragP = fixP->fx_frag;
+
+ char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
+
+ if (fix_bit_fixP(fixP))
+ { /* Bitfields to fix, sigh */
+ md_number_to_field (buf, val, fix_bit_fixP(fixP));
+ }
+ else
+ switch (fix_im_disp(fixP))
+ {
+
+ case 0: /* Immediate field */
+ md_number_to_imm (buf, val, fixP->fx_size);
+ break;
+
+ case 1: /* Displacement field */
+ /* Calculate offset */
+ {
+ md_number_to_disp (buf,
+ (fixP->fx_pcrel ? val + md_fix_pcrel_adjust(fixP)
+ : val), fixP->fx_size);
+ }
+ break;
+
+ case 2: /* Pointer in a data object */
+ md_number_to_chars (buf, val, fixP->fx_size);
+ break;
+ }
+#ifdef BSD_ASSEMBLER
+ return 1;
+#endif
+}
+
+/* Convert a relaxed displacement to ditto in final output */
+
+#ifndef BFD_ASSEMBLER
+void
+md_convert_frag (headers, sec, fragP)
+ object_headers *headers;
+ segT sec;
+ register fragS *fragP;
+#else
+void
+md_convert_frag (abfd, sec, fragP)
+ bfd *abfd;
+ segT sec;
+ register fragS *fragP;
+#endif
+{
+ long disp;
+ long ext = 0;
+
+ /* Address in gas core of the place to store the displacement. */
+ register char *buffer_address = fragP->fr_fix + fragP->fr_literal;
+ /* Address in object code of the displacement. */
+ int object_address;
+
+ fragS *opcode_frag;
+
+ switch (fragP->fr_subtype)
+ {
+ case IND (BRANCH, BYTE):
+ ext = 1;
+ break;
+ case IND (BRANCH, WORD):
+ ext = 2;
+ break;
+ case IND (BRANCH, DOUBLE):
+ ext = 4;
+ break;
+ }
+
+ if(ext == 0)
+ return;
+
+ know (fragP->fr_symbol);
+
+ object_address = fragP->fr_fix + fragP->fr_address;
+ /* The displacement of the address, from current location. */
+ disp = (S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset) - object_address;
+#ifdef BFD_ASSEMBLER
+ disp += fragP->fr_symbol->sy_frag->fr_address;
+#endif
+ disp += md_pcrel_adjust(fragP);
+
+ md_number_to_disp (buffer_address, (long) disp, (int) ext);
+ fragP->fr_fix += ext;
+}
+
+/* This function returns the estimated size a variable object will occupy,
+ one can say that we tries to guess the size of the objects before we
+ actually know it */
+
+int
+md_estimate_size_before_relax (fragP, segment)
+ register fragS *fragP;
+ segT segment;
+{
+ int old_fix;
+ old_fix = fragP->fr_fix;
+ switch (fragP->fr_subtype)
+ {
+ case IND (BRANCH, UNDEF):
+ if (S_GET_SEGMENT (fragP->fr_symbol) == segment)
+ {
+ /* the symbol has been assigned a value */
+ fragP->fr_subtype = IND (BRANCH, BYTE);
+ }
+ else
+ {
+ /* we don't relax symbols defined in an other segment the
+ thing to do is to assume the object will occupy 4 bytes */
+ fix_new_ns32k (fragP,
+ (int) (fragP->fr_fix),
+ 4,
+ fragP->fr_symbol,
+ fragP->fr_offset,
+ 1,
+ 1,
+ 0,
+ frag_bsr(fragP), /*sequent hack */
+ frag_opcode_frag(fragP),
+ frag_opcode_offset(fragP));
+ fragP->fr_fix += 4;
+ /* fragP->fr_opcode[1]=0xff; */
+ frag_wane (fragP);
+ break;
+ }
+ case IND (BRANCH, BYTE):
+ fragP->fr_var += 1;
+ break;
+ default:
+ break;
+ }
+ return fragP->fr_var + fragP->fr_fix - old_fix;
+}
+
+int md_short_jump_size = 3;
+int md_long_jump_size = 5;
+const int md_reloc_size = 8; /* Size of relocation record */
+
+void
+md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
+ char *ptr;
+ addressT from_addr, to_addr;
+ fragS *frag;
+ symbolS *to_symbol;
+{
+ valueT offset;
+
+ offset = to_addr - from_addr;
+ md_number_to_chars (ptr, (valueT) 0xEA, 1);
+ md_number_to_disp (ptr + 1, (valueT) offset, 2);
+}
+
+void
+md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
+ char *ptr;
+ addressT from_addr, to_addr;
+ fragS *frag;
+ symbolS *to_symbol;
+{
+ valueT offset;
+
+ offset = to_addr - from_addr;
+ md_number_to_chars (ptr, (valueT) 0xEA, 1);
+ md_number_to_disp (ptr + 1, (valueT) offset, 4);
+}
+
+CONST char *md_shortopts = "m:";
+struct option md_longopts[] = {
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof(md_longopts);
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ switch (c)
+ {
+ case 'm':
+ if (!strcmp (arg, "32032"))
+ {
+ cpureg = cpureg_032;
+ mmureg = mmureg_032;
+ }
+ else if (!strcmp (arg, "32532"))
+ {
+ cpureg = cpureg_532;
+ mmureg = mmureg_532;
+ }
+ else
+ {
+ as_bad (_("invalid architecture option -m%s"), arg);
+ return 0;
+ }
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+ fprintf(stream, _("\
+NS32K options:\n\
+-m32032 | -m32532 select variant of NS32K architecture\n"));
+}
+
+
+/*
+ * bit_fix_new()
+ *
+ * Create a bit_fixS in obstack 'notes'.
+ * This struct is used to profile the normal fix. If the bit_fixP is a
+ * valid pointer (not NULL) the bit_fix data will be used to format the fix.
+ */
+bit_fixS *
+bit_fix_new (size, offset, min, max, add, base_type, base_adj)
+ char size; /* Length of bitfield */
+ char offset; /* Bit offset to bitfield */
+ long min; /* Signextended min for bitfield */
+ long max; /* Signextended max for bitfield */
+ long add; /* Add mask, used for huffman prefix */
+ long base_type; /* 0 or 1, if 1 it's exploded to opcode ptr */
+ long base_adj;
+{
+ register bit_fixS *bit_fixP;
+
+ bit_fixP = (bit_fixS *) obstack_alloc (&notes, sizeof (bit_fixS));
+
+ bit_fixP->fx_bit_size = size;
+ bit_fixP->fx_bit_offset = offset;
+ bit_fixP->fx_bit_base = base_type;
+ bit_fixP->fx_bit_base_adj = base_adj;
+ bit_fixP->fx_bit_max = max;
+ bit_fixP->fx_bit_min = min;
+ bit_fixP->fx_bit_add = add;
+
+ return (bit_fixP);
+}
+
+void
+fix_new_ns32k (frag, where, size, add_symbol, offset, pcrel,
+ im_disp, bit_fixP, bsr, opcode_frag, opcode_offset)
+ fragS *frag; /* Which frag? */
+ int where; /* Where in that frag? */
+ int size; /* 1, 2 or 4 usually. */
+ symbolS *add_symbol; /* X_add_symbol. */
+ long offset; /* X_add_number. */
+ int pcrel; /* TRUE if PC-relative relocation. */
+ char im_disp; /* true if the value to write is a
+ displacement */
+ bit_fixS *bit_fixP; /* pointer at struct of bit_fix's, ignored if
+ NULL */
+ char bsr; /* sequent-linker-hack: 1 when relocobject is
+ a bsr */
+ fragS *opcode_frag;
+ unsigned int opcode_offset;
+
+{
+ fixS *fixP = fix_new (frag, where, size, add_symbol,
+ offset, pcrel,
+#ifdef BFD_ASSEMBLER
+ bit_fixP? NO_RELOC: reloc(size, pcrel, im_disp)
+#else
+ NO_RELOC
+#endif
+ );
+
+ fix_opcode_frag(fixP) = opcode_frag;
+ fix_opcode_offset(fixP) = opcode_offset;
+ fix_im_disp(fixP) = im_disp;
+ fix_bsr(fixP) = bsr;
+ fix_bit_fixP(fixP) = bit_fixP;
+} /* fix_new_ns32k() */
+
+void
+fix_new_ns32k_exp (frag, where, size, exp, pcrel,
+ im_disp, bit_fixP, bsr, opcode_frag, opcode_offset)
+ fragS *frag; /* Which frag? */
+ int where; /* Where in that frag? */
+ int size; /* 1, 2 or 4 usually. */
+ expressionS *exp; /* Expression. */
+ int pcrel; /* TRUE if PC-relative relocation. */
+ char im_disp; /* true if the value to write is a
+ displacement */
+ bit_fixS *bit_fixP; /* pointer at struct of bit_fix's, ignored if
+ NULL */
+ char bsr; /* sequent-linker-hack: 1 when relocobject is
+ a bsr */
+ fragS *opcode_frag;
+ unsigned int opcode_offset;
+{
+ fixS *fixP = fix_new_exp (frag, where, size, exp, pcrel,
+#ifdef BFD_ASSEMBLER
+ bit_fixP? NO_RELOC: reloc(size, pcrel, im_disp)
+#else
+ NO_RELOC
+#endif
+ );
+
+ fix_opcode_frag(fixP) = opcode_frag;
+ fix_opcode_offset(fixP) = opcode_offset;
+ fix_im_disp(fixP) = im_disp;
+ fix_bsr(fixP) = bsr;
+ fix_bit_fixP(fixP) = bit_fixP;
+} /* fix_new_ns32k() */
+
+/* This is TC_CONS_FIX_NEW, called by emit_expr in read.c. */
+
+void
+cons_fix_new_ns32k (frag, where, size, exp)
+ fragS *frag; /* Which frag? */
+ int where; /* Where in that frag? */
+ int size; /* 1, 2 or 4 usually. */
+ expressionS *exp; /* Expression. */
+{
+ fix_new_ns32k_exp (frag, where, size, exp,
+ 0, 2, 0, 0, 0, 0);
+}
+
+/* We have no need to default values of symbols. */
+
+symbolS *
+md_undefined_symbol (name)
+ char *name;
+{
+ return 0;
+}
+
+/* Round up a section size to the appropriate boundary. */
+valueT
+md_section_align (segment, size)
+ segT segment;
+ valueT size;
+{
+ return size; /* Byte alignment is fine */
+}
+
+/* Exactly what point is a PC-relative offset relative TO? On the
+ ns32k, they're relative to the start of the instruction. */
+long
+md_pcrel_from (fixP)
+ fixS *fixP;
+{
+ long res;
+ res = fixP->fx_where + fixP->fx_frag->fr_address;
+#ifdef SEQUENT_COMPATABILITY
+ if (frag_bsr(fixP->fx_frag))
+ res += 0x12 /* FOO Kludge alert! */
+#endif
+ return res;
+}
+
+#ifdef BFD_ASSEMBLER
+
+arelent *
+tc_gen_reloc (section, fixp)
+ asection *section;
+ fixS *fixp;
+{
+ arelent *rel;
+ bfd_reloc_code_real_type code;
+
+ code = reloc(fixp->fx_size, fixp->fx_pcrel, fix_im_disp(fixp));
+
+ rel = (arelent *) xmalloc (sizeof (arelent));
+ rel->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+ rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
+ if (fixp->fx_pcrel)
+ rel->addend = fixp->fx_addnumber;
+ else
+ rel->addend = 0;
+
+ rel->howto = bfd_reloc_type_lookup (stdoutput, code);
+ if (!rel->howto)
+ {
+ const char *name;
+
+ name = S_GET_NAME (fixp->fx_addsy);
+ if (name == NULL)
+ name = _("<unknown>");
+ as_fatal (_("Cannot find relocation type for symbol %s, code %d"),
+ name, (int) code);
+ }
+
+ return rel;
+}
+#else /* BFD_ASSEMBLER */
+
+#ifdef OBJ_AOUT
+void
+cons_fix_new_ns32k (where, fixP, segment_address_in_file)
+ char *where;
+ struct fix *fixP;
+ relax_addressT segment_address_in_file;
+{
+ /*
+ * In: length of relocation (or of address) in chars: 1, 2 or 4.
+ * Out: GNU LD relocation length code: 0, 1, or 2.
+ */
+
+ static unsigned char nbytes_r_length[] = {42, 0, 1, 42, 2};
+ long r_symbolnum;
+
+ know (fixP->fx_addsy != NULL);
+
+ md_number_to_chars (where,
+ fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
+ 4);
+
+ r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy)
+ ? S_GET_TYPE (fixP->fx_addsy)
+ : fixP->fx_addsy->sy_number);
+
+ md_number_to_chars (where + 4,
+ ((long) (r_symbolnum)
+ | (long) (fixP->fx_pcrel << 24)
+ | (long) (nbytes_r_length[fixP->fx_size] << 25)
+ | (long) ((!S_IS_DEFINED (fixP->fx_addsy)) << 27)
+ | (long) (fix_bsr(fixP) << 28)
+ | (long) (fix_im_disp(fixP) << 29)),
+ 4);
+}
+
+#endif /* OBJ_AOUT */
+#endif /* BFD_ASSMEBLER */
+
+/* end of tc-ns32k.c */
diff --git a/gas/config/tc-ns32k.h b/gas/config/tc-ns32k.h
new file mode 100644
index 0000000000..4b038ebc6a
--- /dev/null
+++ b/gas/config/tc-ns32k.h
@@ -0,0 +1,155 @@
+/* tc-ns32k.h -- Opcode table for National Semi 32k processor
+ Copyright (C) 1987, 92, 93, 94, 95, 1997 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#define TC_NS32K
+
+#define TARGET_BYTES_BIG_ENDIAN 0
+
+#define TC_PCREL_ADJUST(F) md_pcrel_adjust(F)
+
+#ifdef BFD_ASSEMBLER
+#define NO_RELOC BFD_RELOC_NONE
+
+#define TARGET_ARCH bfd_arch_ns32k
+
+#ifndef TARGET_FORMAT /* Maybe defined in te-*.h */
+#define TARGET_FORMAT "a.out-pc532-mach"
+#endif
+#else
+#define NO_RELOC 0
+#endif
+
+#define LOCAL_LABELS_FB 1
+
+#include "bit_fix.h"
+
+#define tc_aout_pre_write_hook(x) {;} /* not used */
+#define tc_crawl_symbol_chain(a) {;} /* not used */
+#define tc_headers_hook(a) {;} /* not used */
+
+#ifdef SEQUENT_COMPATABILITY
+#define DEF_MODEC 20
+#define DEF_MODEL 21
+#endif
+
+#ifndef DEF_MODEC
+#define DEF_MODEC 20
+#endif
+
+#ifndef DEF_MODEL
+#define DEF_MODEL 20
+#endif
+
+#define MAX_ARGS 4
+#define ARG_LEN 50
+
+#define TC_CONS_FIX_NEW cons_fix_new_ns32k
+extern void fix_new_ns32k_exp PARAMS((fragS *frag,
+ int where,
+ int size,
+ expressionS *exp,
+ int pcrel,
+ int im_disp,
+ bit_fixS *bit_fixP, /* really bit_fixS */
+ int bsr,
+ fragS *opcode_frag,
+ unsigned int opcode_offset));
+
+
+extern void fix_new_ns32k PARAMS ((fragS *frag,
+ int where,
+ int size,
+ struct symbol *add_symbol,
+ long offset,
+ int pcrel,
+ int im_disp,
+ bit_fixS *bit_fixP, /* really bit_fixS */
+ int bsr,
+ fragS *opcode_frag,
+ unsigned int opcode_offset));
+
+extern void cons_fix_new_ns32k PARAMS ((fragS *frag,
+ int where,
+ int size,
+ expressionS *exp));
+
+/* the NS32x32 has a non 0 nop instruction which should be used in aligns */
+#define NOP_OPCODE 0xa2
+
+#define md_operand(x)
+
+extern const struct relax_type md_relax_table[];
+#define TC_GENERIC_RELAX_TABLE md_relax_table
+
+#define TC_FRAG_TYPE \
+struct { \
+ fragS *fr_opcode_fragP; \
+ unsigned int fr_opcode_offset; \
+ char fr_bsr; \
+}
+
+#define TC_FRAG_INIT(X) \
+ do \
+ { \
+ frag_opcode_frag (X) = NULL; \
+ frag_opcode_offset (X) = 0; \
+ frag_bsr (X) = 0; \
+ } \
+ while(0)
+
+/* Accessor macros for things which may move around */
+#define frag_opcode_frag(X) (X)->tc_frag_data.fr_opcode_fragP
+#define frag_opcode_offset(X) (X)->tc_frag_data.fr_opcode_offset
+#define frag_bsr(X) (X)->tc_frag_data.fr_bsr
+
+#define TC_FIX_TYPE \
+struct \
+{ \
+ fragS *opcode_fragP; \
+ unsigned int opcode_offset; \
+ unsigned int bsr : 1; \
+}
+
+/* Accessor macros for things which may move around.
+ See comments in write.h. */
+#define fix_im_disp(X) (X)->fx_im_disp
+#define fix_bit_fixP(X) (X)->fx_bit_fixP
+#define fix_opcode_frag(X) (X)->tc_fix_data.opcode_fragP
+#define fix_opcode_offset(X) (X)->tc_fix_data.opcode_offset
+#define fix_bsr(X) (X)->tc_fix_data.bsr
+
+#define TC_INIT_FIX_DATA(X) \
+ do \
+ { \
+ fix_opcode_frag(X) = NULL; \
+ fix_opcode_offset(X) = 0; \
+ fix_bsr(X) = 0; \
+ } \
+ while(0)
+
+#define TC_FIX_DATA_PRINT(FILE, FIXP) \
+ do \
+ { \
+ fprintf((FILE), "opcode_frag=%ld, operand offset=%d, bsr=%d\n", \
+ (unsigned long) fix_opcode_frag (FIXP), \
+ fix_opcode_offset (FIXP), \
+ fix_bsr (FIXP)); \
+ } \
+ while(0)
diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c
new file mode 100644
index 0000000000..8c31ba6415
--- /dev/null
+++ b/gas/config/tc-ppc.c
@@ -0,0 +1,5003 @@
+/* tc-ppc.c -- Assemble for the PowerPC or POWER (RS/6000)
+ Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor, Cygnus Support.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "as.h"
+#include "subsegs.h"
+
+#include "opcode/ppc.h"
+
+#ifdef OBJ_ELF
+#include "elf/ppc.h"
+#endif
+
+#ifdef TE_PE
+#include "coff/pe.h"
+#endif
+
+/* This is the assembler for the PowerPC or POWER (RS/6000) chips. */
+
+/* Tell the main code what the endianness is. */
+extern int target_big_endian;
+
+/* Whether or not, we've set target_big_endian. */
+static int set_target_endian = 0;
+
+/* Whether to use user friendly register names. */
+#ifndef TARGET_REG_NAMES_P
+#ifdef TE_PE
+#define TARGET_REG_NAMES_P true
+#else
+#define TARGET_REG_NAMES_P false
+#endif
+#endif
+
+static boolean reg_names_p = TARGET_REG_NAMES_P;
+
+static boolean register_name PARAMS ((expressionS *));
+static void ppc_set_cpu PARAMS ((void));
+static unsigned long ppc_insert_operand
+ PARAMS ((unsigned long insn, const struct powerpc_operand *operand,
+ offsetT val, char *file, unsigned int line));
+static void ppc_macro PARAMS ((char *str, const struct powerpc_macro *macro));
+static void ppc_byte PARAMS ((int));
+static int ppc_is_toc_sym PARAMS ((symbolS *sym));
+static void ppc_tc PARAMS ((int));
+
+#ifdef OBJ_XCOFF
+static void ppc_comm PARAMS ((int));
+static void ppc_bb PARAMS ((int));
+static void ppc_bc PARAMS ((int));
+static void ppc_bf PARAMS ((int));
+static void ppc_biei PARAMS ((int));
+static void ppc_bs PARAMS ((int));
+static void ppc_eb PARAMS ((int));
+static void ppc_ec PARAMS ((int));
+static void ppc_ef PARAMS ((int));
+static void ppc_es PARAMS ((int));
+static void ppc_csect PARAMS ((int));
+static void ppc_change_csect PARAMS ((symbolS *));
+static void ppc_function PARAMS ((int));
+static void ppc_extern PARAMS ((int));
+static void ppc_lglobl PARAMS ((int));
+static void ppc_section PARAMS ((int));
+static void ppc_named_section PARAMS ((int));
+static void ppc_stabx PARAMS ((int));
+static void ppc_rename PARAMS ((int));
+static void ppc_toc PARAMS ((int));
+static void ppc_xcoff_cons PARAMS ((int));
+static void ppc_vbyte PARAMS ((int));
+#endif
+
+#ifdef OBJ_ELF
+static bfd_reloc_code_real_type ppc_elf_suffix PARAMS ((char **, expressionS *));
+static void ppc_elf_cons PARAMS ((int));
+static void ppc_elf_rdata PARAMS ((int));
+static void ppc_elf_lcomm PARAMS ((int));
+static void ppc_elf_validate_fix PARAMS ((fixS *, segT));
+#endif
+
+#ifdef TE_PE
+static void ppc_set_current_section PARAMS ((segT));
+static void ppc_previous PARAMS ((int));
+static void ppc_pdata PARAMS ((int));
+static void ppc_ydata PARAMS ((int));
+static void ppc_reldata PARAMS ((int));
+static void ppc_rdata PARAMS ((int));
+static void ppc_ualong PARAMS ((int));
+static void ppc_znop PARAMS ((int));
+static void ppc_pe_comm PARAMS ((int));
+static void ppc_pe_section PARAMS ((int));
+static void ppc_pe_function PARAMS ((int));
+static void ppc_pe_tocd PARAMS ((int));
+#endif
+
+/* Generic assembler global variables which must be defined by all
+ targets. */
+
+#ifdef OBJ_ELF
+/* This string holds the chars that always start a comment. If the
+ pre-processor is disabled, these aren't very useful. The macro
+ tc_comment_chars points to this. We use this, rather than the
+ usual comment_chars, so that we can switch for Solaris conventions. */
+static const char ppc_solaris_comment_chars[] = "#!";
+static const char ppc_eabi_comment_chars[] = "#";
+
+#ifdef TARGET_SOLARIS_COMMENT
+const char *ppc_comment_chars = ppc_solaris_comment_chars;
+#else
+const char *ppc_comment_chars = ppc_eabi_comment_chars;
+#endif
+#else
+const char comment_chars[] = "#";
+#endif
+
+/* Characters which start a comment at the beginning of a line. */
+const char line_comment_chars[] = "#";
+
+/* Characters which may be used to separate multiple commands on a
+ single line. */
+const char line_separator_chars[] = ";";
+
+/* Characters which are used to indicate an exponent in a floating
+ point number. */
+const char EXP_CHARS[] = "eE";
+
+/* Characters which mean that a number is a floating point constant,
+ as in 0d1.0. */
+const char FLT_CHARS[] = "dD";
+
+/* The target specific pseudo-ops which we support. */
+
+const pseudo_typeS md_pseudo_table[] =
+{
+ /* Pseudo-ops which must be overridden. */
+ { "byte", ppc_byte, 0 },
+
+#ifdef OBJ_XCOFF
+ /* Pseudo-ops specific to the RS/6000 XCOFF format. Some of these
+ legitimately belong in the obj-*.c file. However, XCOFF is based
+ on COFF, and is only implemented for the RS/6000. We just use
+ obj-coff.c, and add what we need here. */
+ { "comm", ppc_comm, 0 },
+ { "lcomm", ppc_comm, 1 },
+ { "bb", ppc_bb, 0 },
+ { "bc", ppc_bc, 0 },
+ { "bf", ppc_bf, 0 },
+ { "bi", ppc_biei, 0 },
+ { "bs", ppc_bs, 0 },
+ { "csect", ppc_csect, 0 },
+ { "data", ppc_section, 'd' },
+ { "eb", ppc_eb, 0 },
+ { "ec", ppc_ec, 0 },
+ { "ef", ppc_ef, 0 },
+ { "ei", ppc_biei, 1 },
+ { "es", ppc_es, 0 },
+ { "extern", ppc_extern, 0 },
+ { "function", ppc_function, 0 },
+ { "lglobl", ppc_lglobl, 0 },
+ { "rename", ppc_rename, 0 },
+ { "section", ppc_named_section, 0 },
+ { "stabx", ppc_stabx, 0 },
+ { "text", ppc_section, 't' },
+ { "toc", ppc_toc, 0 },
+ { "long", ppc_xcoff_cons, 2 },
+ { "word", ppc_xcoff_cons, 1 },
+ { "short", ppc_xcoff_cons, 1 },
+ { "vbyte", ppc_vbyte, 0 },
+#endif
+
+#ifdef OBJ_ELF
+ { "long", ppc_elf_cons, 4 },
+ { "word", ppc_elf_cons, 2 },
+ { "short", ppc_elf_cons, 2 },
+ { "rdata", ppc_elf_rdata, 0 },
+ { "rodata", ppc_elf_rdata, 0 },
+ { "lcomm", ppc_elf_lcomm, 0 },
+#endif
+
+#ifdef TE_PE
+ /* Pseudo-ops specific to the Windows NT PowerPC PE (coff) format */
+ { "previous", ppc_previous, 0 },
+ { "pdata", ppc_pdata, 0 },
+ { "ydata", ppc_ydata, 0 },
+ { "reldata", ppc_reldata, 0 },
+ { "rdata", ppc_rdata, 0 },
+ { "ualong", ppc_ualong, 0 },
+ { "znop", ppc_znop, 0 },
+ { "comm", ppc_pe_comm, 0 },
+ { "lcomm", ppc_pe_comm, 1 },
+ { "section", ppc_pe_section, 0 },
+ { "function", ppc_pe_function,0 },
+ { "tocd", ppc_pe_tocd, 0 },
+#endif
+
+ /* This pseudo-op is used even when not generating XCOFF output. */
+ { "tc", ppc_tc, 0 },
+
+ { NULL, NULL, 0 }
+};
+
+
+/* Predefined register names if -mregnames (or default for Windows NT). */
+/* In general, there are lots of them, in an attempt to be compatible */
+/* with a number of other Windows NT assemblers. */
+
+/* Structure to hold information about predefined registers. */
+struct pd_reg
+ {
+ char *name;
+ int value;
+ };
+
+/* List of registers that are pre-defined:
+
+ Each general register has predefined names of the form:
+ 1. r<reg_num> which has the value <reg_num>.
+ 2. r.<reg_num> which has the value <reg_num>.
+
+
+ Each floating point register has predefined names of the form:
+ 1. f<reg_num> which has the value <reg_num>.
+ 2. f.<reg_num> which has the value <reg_num>.
+
+ Each condition register has predefined names of the form:
+ 1. cr<reg_num> which has the value <reg_num>.
+ 2. cr.<reg_num> which has the value <reg_num>.
+
+ There are individual registers as well:
+ sp or r.sp has the value 1
+ rtoc or r.toc has the value 2
+ fpscr has the value 0
+ xer has the value 1
+ lr has the value 8
+ ctr has the value 9
+ pmr has the value 0
+ dar has the value 19
+ dsisr has the value 18
+ dec has the value 22
+ sdr1 has the value 25
+ srr0 has the value 26
+ srr1 has the value 27
+
+ The table is sorted. Suitable for searching by a binary search. */
+
+static const struct pd_reg pre_defined_registers[] =
+{
+ { "cr.0", 0 }, /* Condition Registers */
+ { "cr.1", 1 },
+ { "cr.2", 2 },
+ { "cr.3", 3 },
+ { "cr.4", 4 },
+ { "cr.5", 5 },
+ { "cr.6", 6 },
+ { "cr.7", 7 },
+
+ { "cr0", 0 },
+ { "cr1", 1 },
+ { "cr2", 2 },
+ { "cr3", 3 },
+ { "cr4", 4 },
+ { "cr5", 5 },
+ { "cr6", 6 },
+ { "cr7", 7 },
+
+ { "ctr", 9 },
+
+ { "dar", 19 }, /* Data Access Register */
+ { "dec", 22 }, /* Decrementer */
+ { "dsisr", 18 }, /* Data Storage Interrupt Status Register */
+
+ { "f.0", 0 }, /* Floating point registers */
+ { "f.1", 1 },
+ { "f.10", 10 },
+ { "f.11", 11 },
+ { "f.12", 12 },
+ { "f.13", 13 },
+ { "f.14", 14 },
+ { "f.15", 15 },
+ { "f.16", 16 },
+ { "f.17", 17 },
+ { "f.18", 18 },
+ { "f.19", 19 },
+ { "f.2", 2 },
+ { "f.20", 20 },
+ { "f.21", 21 },
+ { "f.22", 22 },
+ { "f.23", 23 },
+ { "f.24", 24 },
+ { "f.25", 25 },
+ { "f.26", 26 },
+ { "f.27", 27 },
+ { "f.28", 28 },
+ { "f.29", 29 },
+ { "f.3", 3 },
+ { "f.30", 30 },
+ { "f.31", 31 },
+ { "f.4", 4 },
+ { "f.5", 5 },
+ { "f.6", 6 },
+ { "f.7", 7 },
+ { "f.8", 8 },
+ { "f.9", 9 },
+
+ { "f0", 0 },
+ { "f1", 1 },
+ { "f10", 10 },
+ { "f11", 11 },
+ { "f12", 12 },
+ { "f13", 13 },
+ { "f14", 14 },
+ { "f15", 15 },
+ { "f16", 16 },
+ { "f17", 17 },
+ { "f18", 18 },
+ { "f19", 19 },
+ { "f2", 2 },
+ { "f20", 20 },
+ { "f21", 21 },
+ { "f22", 22 },
+ { "f23", 23 },
+ { "f24", 24 },
+ { "f25", 25 },
+ { "f26", 26 },
+ { "f27", 27 },
+ { "f28", 28 },
+ { "f29", 29 },
+ { "f3", 3 },
+ { "f30", 30 },
+ { "f31", 31 },
+ { "f4", 4 },
+ { "f5", 5 },
+ { "f6", 6 },
+ { "f7", 7 },
+ { "f8", 8 },
+ { "f9", 9 },
+
+ { "fpscr", 0 },
+
+ { "lr", 8 }, /* Link Register */
+
+ { "pmr", 0 },
+
+ { "r.0", 0 }, /* General Purpose Registers */
+ { "r.1", 1 },
+ { "r.10", 10 },
+ { "r.11", 11 },
+ { "r.12", 12 },
+ { "r.13", 13 },
+ { "r.14", 14 },
+ { "r.15", 15 },
+ { "r.16", 16 },
+ { "r.17", 17 },
+ { "r.18", 18 },
+ { "r.19", 19 },
+ { "r.2", 2 },
+ { "r.20", 20 },
+ { "r.21", 21 },
+ { "r.22", 22 },
+ { "r.23", 23 },
+ { "r.24", 24 },
+ { "r.25", 25 },
+ { "r.26", 26 },
+ { "r.27", 27 },
+ { "r.28", 28 },
+ { "r.29", 29 },
+ { "r.3", 3 },
+ { "r.30", 30 },
+ { "r.31", 31 },
+ { "r.4", 4 },
+ { "r.5", 5 },
+ { "r.6", 6 },
+ { "r.7", 7 },
+ { "r.8", 8 },
+ { "r.9", 9 },
+
+ { "r.sp", 1 }, /* Stack Pointer */
+
+ { "r.toc", 2 }, /* Pointer to the table of contents */
+
+ { "r0", 0 }, /* More general purpose registers */
+ { "r1", 1 },
+ { "r10", 10 },
+ { "r11", 11 },
+ { "r12", 12 },
+ { "r13", 13 },
+ { "r14", 14 },
+ { "r15", 15 },
+ { "r16", 16 },
+ { "r17", 17 },
+ { "r18", 18 },
+ { "r19", 19 },
+ { "r2", 2 },
+ { "r20", 20 },
+ { "r21", 21 },
+ { "r22", 22 },
+ { "r23", 23 },
+ { "r24", 24 },
+ { "r25", 25 },
+ { "r26", 26 },
+ { "r27", 27 },
+ { "r28", 28 },
+ { "r29", 29 },
+ { "r3", 3 },
+ { "r30", 30 },
+ { "r31", 31 },
+ { "r4", 4 },
+ { "r5", 5 },
+ { "r6", 6 },
+ { "r7", 7 },
+ { "r8", 8 },
+ { "r9", 9 },
+
+ { "rtoc", 2 }, /* Table of contents */
+
+ { "sdr1", 25 }, /* Storage Description Register 1 */
+
+ { "sp", 1 },
+
+ { "srr0", 26 }, /* Machine Status Save/Restore Register 0 */
+ { "srr1", 27 }, /* Machine Status Save/Restore Register 1 */
+
+ { "xer", 1 },
+
+};
+
+#define REG_NAME_CNT (sizeof(pre_defined_registers) / sizeof(struct pd_reg))
+
+/* Given NAME, find the register number associated with that name, return
+ the integer value associated with the given name or -1 on failure. */
+
+static int reg_name_search
+ PARAMS ((const struct pd_reg *, int, const char * name));
+
+static int
+reg_name_search (regs, regcount, name)
+ const struct pd_reg *regs;
+ int regcount;
+ const char *name;
+{
+ int middle, low, high;
+ int cmp;
+
+ low = 0;
+ high = regcount - 1;
+
+ do
+ {
+ middle = (low + high) / 2;
+ cmp = strcasecmp (name, regs[middle].name);
+ if (cmp < 0)
+ high = middle - 1;
+ else if (cmp > 0)
+ low = middle + 1;
+ else
+ return regs[middle].value;
+ }
+ while (low <= high);
+
+ return -1;
+}
+
+/*
+ * Summary of register_name().
+ *
+ * in: Input_line_pointer points to 1st char of operand.
+ *
+ * out: A expressionS.
+ * The operand may have been a register: in this case, X_op == O_register,
+ * X_add_number is set to the register number, and truth is returned.
+ * Input_line_pointer->(next non-blank) char after operand, or is in its
+ * original state.
+ */
+
+static boolean
+register_name (expressionP)
+ expressionS *expressionP;
+{
+ int reg_number;
+ char *name;
+ char *start;
+ char c;
+
+ /* Find the spelling of the operand */
+ start = name = input_line_pointer;
+ if (name[0] == '%' && isalpha (name[1]))
+ name = ++input_line_pointer;
+
+ else if (!reg_names_p || !isalpha (name[0]))
+ return false;
+
+ c = get_symbol_end ();
+ reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT, name);
+
+ /* look to see if it's in the register table */
+ if (reg_number >= 0)
+ {
+ expressionP->X_op = O_register;
+ expressionP->X_add_number = reg_number;
+
+ /* make the rest nice */
+ expressionP->X_add_symbol = NULL;
+ expressionP->X_op_symbol = NULL;
+ *input_line_pointer = c; /* put back the delimiting char */
+ return true;
+ }
+ else
+ {
+ /* reset the line as if we had not done anything */
+ *input_line_pointer = c; /* put back the delimiting char */
+ input_line_pointer = start; /* reset input_line pointer */
+ return false;
+ }
+}
+
+/* This function is called for each symbol seen in an expression. It
+ handles the special parsing which PowerPC assemblers are supposed
+ to use for condition codes. */
+
+/* Whether to do the special parsing. */
+static boolean cr_operand;
+
+/* Names to recognize in a condition code. This table is sorted. */
+static const struct pd_reg cr_names[] =
+{
+ { "cr0", 0 },
+ { "cr1", 1 },
+ { "cr2", 2 },
+ { "cr3", 3 },
+ { "cr4", 4 },
+ { "cr5", 5 },
+ { "cr6", 6 },
+ { "cr7", 7 },
+ { "eq", 2 },
+ { "gt", 1 },
+ { "lt", 0 },
+ { "so", 3 },
+ { "un", 3 }
+};
+
+/* Parsing function. This returns non-zero if it recognized an
+ expression. */
+
+int
+ppc_parse_name (name, expr)
+ const char *name;
+ expressionS *expr;
+{
+ int val;
+
+ if (! cr_operand)
+ return 0;
+
+ val = reg_name_search (cr_names, sizeof cr_names / sizeof cr_names[0],
+ name);
+ if (val < 0)
+ return 0;
+
+ expr->X_op = O_constant;
+ expr->X_add_number = val;
+
+ return 1;
+}
+
+/* Local variables. */
+
+/* The type of processor we are assembling for. This is one or more
+ of the PPC_OPCODE flags defined in opcode/ppc.h. */
+static int ppc_cpu = 0;
+
+/* The size of the processor we are assembling for. This is either
+ PPC_OPCODE_32 or PPC_OPCODE_64. */
+static int ppc_size = PPC_OPCODE_32;
+
+/* Opcode hash table. */
+static struct hash_control *ppc_hash;
+
+/* Macro hash table. */
+static struct hash_control *ppc_macro_hash;
+
+#ifdef OBJ_ELF
+/* What type of shared library support to use */
+static enum { SHLIB_NONE, SHLIB_PIC, SHILB_MRELOCATABLE } shlib = SHLIB_NONE;
+
+/* Flags to set in the elf header */
+static flagword ppc_flags = 0;
+
+/* Whether this is Solaris or not. */
+#ifdef TARGET_SOLARIS_COMMENT
+#define SOLARIS_P true
+#else
+#define SOLARIS_P false
+#endif
+
+static boolean msolaris = SOLARIS_P;
+#endif
+
+#ifdef OBJ_XCOFF
+
+/* The RS/6000 assembler uses the .csect pseudo-op to generate code
+ using a bunch of different sections. These assembler sections,
+ however, are all encompassed within the .text or .data sections of
+ the final output file. We handle this by using different
+ subsegments within these main segments. */
+
+/* Next subsegment to allocate within the .text segment. */
+static subsegT ppc_text_subsegment = 2;
+
+/* Linked list of csects in the text section. */
+static symbolS *ppc_text_csects;
+
+/* Next subsegment to allocate within the .data segment. */
+static subsegT ppc_data_subsegment = 2;
+
+/* Linked list of csects in the data section. */
+static symbolS *ppc_data_csects;
+
+/* The current csect. */
+static symbolS *ppc_current_csect;
+
+/* The RS/6000 assembler uses a TOC which holds addresses of functions
+ and variables. Symbols are put in the TOC with the .tc pseudo-op.
+ A special relocation is used when accessing TOC entries. We handle
+ the TOC as a subsegment within the .data segment. We set it up if
+ we see a .toc pseudo-op, and save the csect symbol here. */
+static symbolS *ppc_toc_csect;
+
+/* The first frag in the TOC subsegment. */
+static fragS *ppc_toc_frag;
+
+/* The first frag in the first subsegment after the TOC in the .data
+ segment. NULL if there are no subsegments after the TOC. */
+static fragS *ppc_after_toc_frag;
+
+/* The current static block. */
+static symbolS *ppc_current_block;
+
+/* The COFF debugging section; set by md_begin. This is not the
+ .debug section, but is instead the secret BFD section which will
+ cause BFD to set the section number of a symbol to N_DEBUG. */
+static asection *ppc_coff_debug_section;
+
+#endif /* OBJ_XCOFF */
+
+#ifdef TE_PE
+
+/* Various sections that we need for PE coff support. */
+static segT ydata_section;
+static segT pdata_section;
+static segT reldata_section;
+static segT rdata_section;
+static segT tocdata_section;
+
+/* The current section and the previous section. See ppc_previous. */
+static segT ppc_previous_section;
+static segT ppc_current_section;
+
+#endif /* TE_PE */
+
+#ifdef OBJ_ELF
+symbolS *GOT_symbol; /* Pre-defined "_GLOBAL_OFFSET_TABLE" */
+#endif /* OBJ_ELF */
+
+#ifdef OBJ_ELF
+CONST char *md_shortopts = "b:l:usm:K:VQ:";
+#else
+CONST char *md_shortopts = "um:";
+#endif
+struct option md_longopts[] = {
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof(md_longopts);
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ switch (c)
+ {
+ case 'u':
+ /* -u means that any undefined symbols should be treated as
+ external, which is the default for gas anyhow. */
+ break;
+
+#ifdef OBJ_ELF
+ case 'l':
+ /* Solaris as takes -le (presumably for little endian). For completeness
+ sake, recognize -be also. */
+ if (strcmp (arg, "e") == 0)
+ {
+ target_big_endian = 0;
+ set_target_endian = 1;
+ }
+ else
+ return 0;
+
+ break;
+
+ case 'b':
+ if (strcmp (arg, "e") == 0)
+ {
+ target_big_endian = 1;
+ set_target_endian = 1;
+ }
+ else
+ return 0;
+
+ break;
+
+ case 'K':
+ /* Recognize -K PIC */
+ if (strcmp (arg, "PIC") == 0 || strcmp (arg, "pic") == 0)
+ {
+ shlib = SHLIB_PIC;
+ ppc_flags |= EF_PPC_RELOCATABLE_LIB;
+ }
+ else
+ return 0;
+
+ break;
+#endif
+
+ case 'm':
+ /* -mpwrx and -mpwr2 mean to assemble for the IBM POWER/2
+ (RIOS2). */
+ if (strcmp (arg, "pwrx") == 0 || strcmp (arg, "pwr2") == 0)
+ ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_POWER2;
+ /* -mpwr means to assemble for the IBM POWER (RIOS1). */
+ else if (strcmp (arg, "pwr") == 0)
+ ppc_cpu = PPC_OPCODE_POWER;
+ /* -m601 means to assemble for the Motorola PowerPC 601, which includes
+ instructions that are holdovers from the Power. */
+ else if (strcmp (arg, "601") == 0)
+ ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_601;
+ /* -mppc, -mppc32, -m603, and -m604 mean to assemble for the
+ Motorola PowerPC 603/604. */
+ else if (strcmp (arg, "ppc") == 0
+ || strcmp (arg, "ppc32") == 0
+ || strcmp (arg, "403") == 0
+ || strcmp (arg, "603") == 0
+ || strcmp (arg, "604") == 0)
+ ppc_cpu = PPC_OPCODE_PPC;
+ /* -mppc64 and -m620 mean to assemble for the 64-bit PowerPC
+ 620. */
+ else if (strcmp (arg, "ppc64") == 0 || strcmp (arg, "620") == 0)
+ {
+ ppc_cpu = PPC_OPCODE_PPC;
+ ppc_size = PPC_OPCODE_64;
+ }
+ /* -mcom means assemble for the common intersection between Power
+ and PowerPC. At present, we just allow the union, rather
+ than the intersection. */
+ else if (strcmp (arg, "com") == 0)
+ ppc_cpu = PPC_OPCODE_COMMON;
+ /* -many means to assemble for any architecture (PWR/PWRX/PPC). */
+ else if (strcmp (arg, "any") == 0)
+ ppc_cpu = PPC_OPCODE_ANY;
+
+ else if (strcmp (arg, "regnames") == 0)
+ reg_names_p = true;
+
+ else if (strcmp (arg, "no-regnames") == 0)
+ reg_names_p = false;
+
+#ifdef OBJ_ELF
+ /* -mrelocatable/-mrelocatable-lib -- warn about initializations that require relocation */
+ else if (strcmp (arg, "relocatable") == 0)
+ {
+ shlib = SHILB_MRELOCATABLE;
+ ppc_flags |= EF_PPC_RELOCATABLE;
+ }
+
+ else if (strcmp (arg, "relocatable-lib") == 0)
+ {
+ shlib = SHILB_MRELOCATABLE;
+ ppc_flags |= EF_PPC_RELOCATABLE_LIB;
+ }
+
+ /* -memb, set embedded bit */
+ else if (strcmp (arg, "emb") == 0)
+ ppc_flags |= EF_PPC_EMB;
+
+ /* -mlittle/-mbig set the endianess */
+ else if (strcmp (arg, "little") == 0 || strcmp (arg, "little-endian") == 0)
+ {
+ target_big_endian = 0;
+ set_target_endian = 1;
+ }
+
+ else if (strcmp (arg, "big") == 0 || strcmp (arg, "big-endian") == 0)
+ {
+ target_big_endian = 1;
+ set_target_endian = 1;
+ }
+
+ else if (strcmp (arg, "solaris") == 0)
+ {
+ msolaris = true;
+ ppc_comment_chars = ppc_solaris_comment_chars;
+ }
+
+ else if (strcmp (arg, "no-solaris") == 0)
+ {
+ msolaris = false;
+ ppc_comment_chars = ppc_eabi_comment_chars;
+ }
+#endif
+ else
+ {
+ as_bad (_("invalid switch -m%s"), arg);
+ return 0;
+ }
+ break;
+
+#ifdef OBJ_ELF
+ /* -V: SVR4 argument to print version ID. */
+ case 'V':
+ print_version_id ();
+ break;
+
+ /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section
+ should be emitted or not. FIXME: Not implemented. */
+ case 'Q':
+ break;
+
+ /* Solaris takes -s to specify that .stabs go in a .stabs section,
+ rather than .stabs.excl, which is ignored by the linker.
+ FIXME: Not implemented. */
+ case 's':
+ if (arg)
+ return 0;
+
+ break;
+#endif
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+ fprintf(stream, _("\
+PowerPC options:\n\
+-u ignored\n\
+-mpwrx, -mpwr2 generate code for IBM POWER/2 (RIOS2)\n\
+-mpwr generate code for IBM POWER (RIOS1)\n\
+-m601 generate code for Motorola PowerPC 601\n\
+-mppc, -mppc32, -m403, -m603, -m604\n\
+ generate code for Motorola PowerPC 603/604\n\
+-mppc64, -m620 generate code for Motorola PowerPC 620\n\
+-mcom generate code Power/PowerPC common instructions\n\
+-many generate code for any architecture (PWR/PWRX/PPC)\n\
+-mregnames Allow symbolic names for registers\n\
+-mno-regnames Do not allow symbolic names for registers\n"));
+#ifdef OBJ_ELF
+ fprintf(stream, _("\
+-mrelocatable support for GCC's -mrelocatble option\n\
+-mrelocatable-lib support for GCC's -mrelocatble-lib option\n\
+-memb set PPC_EMB bit in ELF flags\n\
+-mlittle, -mlittle-endian\n\
+ generate code for a little endian machine\n\
+-mbig, -mbig-endian generate code for a big endian machine\n\
+-msolaris generate code for Solaris\n\
+-mno-solaris do not generate code for Solaris\n\
+-V print assembler version number\n\
+-Qy, -Qn ignored\n"));
+#endif
+}
+
+/* Set ppc_cpu if it is not already set. */
+
+static void
+ppc_set_cpu ()
+{
+ const char *default_os = TARGET_OS;
+ const char *default_cpu = TARGET_CPU;
+
+ if (ppc_cpu == 0)
+ {
+ if (strncmp (default_os, "aix", 3) == 0
+ && default_os[3] >= '4' && default_os[3] <= '9')
+ ppc_cpu = PPC_OPCODE_COMMON;
+ else if (strncmp (default_os, "aix3", 4) == 0)
+ ppc_cpu = PPC_OPCODE_POWER;
+ else if (strcmp (default_cpu, "rs6000") == 0)
+ ppc_cpu = PPC_OPCODE_POWER;
+ else if (strcmp (default_cpu, "powerpc") == 0
+ || strcmp (default_cpu, "powerpcle") == 0)
+ ppc_cpu = PPC_OPCODE_PPC;
+ else
+ as_fatal (_("Unknown default cpu = %s, os = %s"), default_cpu, default_os);
+ }
+}
+
+/* Figure out the BFD architecture to use. */
+
+enum bfd_architecture
+ppc_arch ()
+{
+ const char *default_cpu = TARGET_CPU;
+ ppc_set_cpu ();
+
+ if ((ppc_cpu & PPC_OPCODE_PPC) != 0)
+ return bfd_arch_powerpc;
+ else if ((ppc_cpu & PPC_OPCODE_POWER) != 0)
+ return bfd_arch_rs6000;
+ else if ((ppc_cpu & (PPC_OPCODE_COMMON | PPC_OPCODE_ANY)) != 0)
+ {
+ if (strcmp (default_cpu, "rs6000") == 0)
+ return bfd_arch_rs6000;
+ else if (strcmp (default_cpu, "powerpc") == 0
+ || strcmp (default_cpu, "powerpcle") == 0)
+ return bfd_arch_powerpc;
+ }
+
+ as_fatal (_("Neither Power nor PowerPC opcodes were selected."));
+ return bfd_arch_unknown;
+}
+
+/* This function is called when the assembler starts up. It is called
+ after the options have been parsed and the output file has been
+ opened. */
+
+void
+md_begin ()
+{
+ register const struct powerpc_opcode *op;
+ const struct powerpc_opcode *op_end;
+ const struct powerpc_macro *macro;
+ const struct powerpc_macro *macro_end;
+ boolean dup_insn = false;
+
+ ppc_set_cpu ();
+
+#ifdef OBJ_ELF
+ /* Set the ELF flags if desired. */
+ if (ppc_flags && !msolaris)
+ bfd_set_private_flags (stdoutput, ppc_flags);
+#endif
+
+ /* Insert the opcodes into a hash table. */
+ ppc_hash = hash_new ();
+
+ op_end = powerpc_opcodes + powerpc_num_opcodes;
+ for (op = powerpc_opcodes; op < op_end; op++)
+ {
+ know ((op->opcode & op->mask) == op->opcode);
+
+ if ((op->flags & ppc_cpu) != 0
+ && ((op->flags & (PPC_OPCODE_32 | PPC_OPCODE_64)) == 0
+ || (op->flags & (PPC_OPCODE_32 | PPC_OPCODE_64)) == ppc_size))
+ {
+ const char *retval;
+
+ retval = hash_insert (ppc_hash, op->name, (PTR) op);
+ if (retval != (const char *) NULL)
+ {
+ /* Ignore Power duplicates for -m601 */
+ if ((ppc_cpu & PPC_OPCODE_601) != 0
+ && (op->flags & PPC_OPCODE_POWER) != 0)
+ continue;
+
+ as_bad (_("Internal assembler error for instruction %s"), op->name);
+ dup_insn = true;
+ }
+ }
+ }
+
+ /* Insert the macros into a hash table. */
+ ppc_macro_hash = hash_new ();
+
+ macro_end = powerpc_macros + powerpc_num_macros;
+ for (macro = powerpc_macros; macro < macro_end; macro++)
+ {
+ if ((macro->flags & ppc_cpu) != 0)
+ {
+ const char *retval;
+
+ retval = hash_insert (ppc_macro_hash, macro->name, (PTR) macro);
+ if (retval != (const char *) NULL)
+ {
+ as_bad (_("Internal assembler error for macro %s"), macro->name);
+ dup_insn = true;
+ }
+ }
+ }
+
+ if (dup_insn)
+ abort ();
+
+ /* Tell the main code what the endianness is if it is not overidden by the user. */
+ if (!set_target_endian)
+ {
+ set_target_endian = 1;
+ target_big_endian = PPC_BIG_ENDIAN;
+ }
+
+#ifdef OBJ_XCOFF
+ ppc_coff_debug_section = coff_section_from_bfd_index (stdoutput, N_DEBUG);
+
+ /* Create dummy symbols to serve as initial csects. This forces the
+ text csects to precede the data csects. These symbols will not
+ be output. */
+ ppc_text_csects = symbol_make ("dummy\001");
+ ppc_text_csects->sy_tc.within = ppc_text_csects;
+ ppc_data_csects = symbol_make ("dummy\001");
+ ppc_data_csects->sy_tc.within = ppc_data_csects;
+#endif
+
+#ifdef TE_PE
+
+ ppc_current_section = text_section;
+ ppc_previous_section = 0;
+
+#endif
+}
+
+/* Insert an operand value into an instruction. */
+
+static unsigned long
+ppc_insert_operand (insn, operand, val, file, line)
+ unsigned long insn;
+ const struct powerpc_operand *operand;
+ offsetT val;
+ char *file;
+ unsigned int line;
+{
+ if (operand->bits != 32)
+ {
+ long min, max;
+ offsetT test;
+
+ if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
+ {
+ if ((operand->flags & PPC_OPERAND_SIGNOPT) != 0
+ && ppc_size == PPC_OPCODE_32)
+ max = (1 << operand->bits) - 1;
+ else
+ max = (1 << (operand->bits - 1)) - 1;
+ min = - (1 << (operand->bits - 1));
+
+ if (ppc_size == PPC_OPCODE_32)
+ {
+ /* Some people write 32 bit hex constants with the sign
+ extension done by hand. This shouldn't really be
+ valid, but, to permit this code to assemble on a 64
+ bit host, we sign extend the 32 bit value. */
+ if (val > 0
+ && (val & 0x80000000) != 0
+ && (val & 0xffffffff) == val)
+ {
+ val -= 0x80000000;
+ val -= 0x80000000;
+ }
+ }
+ }
+ else
+ {
+ max = (1 << operand->bits) - 1;
+ min = 0;
+ }
+
+ if ((operand->flags & PPC_OPERAND_NEGATIVE) != 0)
+ test = - val;
+ else
+ test = val;
+
+ if (test < (offsetT) min || test > (offsetT) max)
+ {
+ const char *err =
+ _("operand out of range (%s not between %ld and %ld)");
+ char buf[100];
+
+ sprint_value (buf, test);
+ if (file == (char *) NULL)
+ as_bad (err, buf, min, max);
+ else
+ as_bad_where (file, line, err, buf, min, max);
+ }
+ }
+
+ if (operand->insert)
+ {
+ const char *errmsg;
+
+ errmsg = NULL;
+ insn = (*operand->insert) (insn, (long) val, &errmsg);
+ if (errmsg != (const char *) NULL)
+ as_bad (errmsg);
+ }
+ else
+ insn |= (((long) val & ((1 << operand->bits) - 1))
+ << operand->shift);
+
+ return insn;
+}
+
+
+#ifdef OBJ_ELF
+/* Parse @got, etc. and return the desired relocation. */
+static bfd_reloc_code_real_type
+ppc_elf_suffix (str_p, exp_p)
+ char **str_p;
+ expressionS *exp_p;
+{
+ struct map_bfd {
+ char *string;
+ int length;
+ bfd_reloc_code_real_type reloc;
+ };
+
+ char ident[20];
+ char *str = *str_p;
+ char *str2;
+ int ch;
+ int len;
+ struct map_bfd *ptr;
+
+#define MAP(str,reloc) { str, sizeof(str)-1, reloc }
+
+ static struct map_bfd mapping[] = {
+ MAP ("l", BFD_RELOC_LO16),
+ MAP ("h", BFD_RELOC_HI16),
+ MAP ("ha", BFD_RELOC_HI16_S),
+ MAP ("brtaken", BFD_RELOC_PPC_B16_BRTAKEN),
+ MAP ("brntaken", BFD_RELOC_PPC_B16_BRNTAKEN),
+ MAP ("got", BFD_RELOC_16_GOTOFF),
+ MAP ("got@l", BFD_RELOC_LO16_GOTOFF),
+ MAP ("got@h", BFD_RELOC_HI16_GOTOFF),
+ MAP ("got@ha", BFD_RELOC_HI16_S_GOTOFF),
+ MAP ("fixup", BFD_RELOC_CTOR), /* warnings with -mrelocatable */
+ MAP ("plt", BFD_RELOC_24_PLT_PCREL),
+ MAP ("pltrel24", BFD_RELOC_24_PLT_PCREL),
+ MAP ("copy", BFD_RELOC_PPC_COPY),
+ MAP ("globdat", BFD_RELOC_PPC_GLOB_DAT),
+ MAP ("local24pc", BFD_RELOC_PPC_LOCAL24PC),
+ MAP ("local", BFD_RELOC_PPC_LOCAL24PC),
+ MAP ("pltrel", BFD_RELOC_32_PLT_PCREL),
+ MAP ("plt@l", BFD_RELOC_LO16_PLTOFF),
+ MAP ("plt@h", BFD_RELOC_HI16_PLTOFF),
+ MAP ("plt@ha", BFD_RELOC_HI16_S_PLTOFF),
+ MAP ("sdarel", BFD_RELOC_GPREL16),
+ MAP ("sectoff", BFD_RELOC_32_BASEREL),
+ MAP ("sectoff@l", BFD_RELOC_LO16_BASEREL),
+ MAP ("sectoff@h", BFD_RELOC_HI16_BASEREL),
+ MAP ("sectoff@ha", BFD_RELOC_HI16_S_BASEREL),
+ MAP ("naddr", BFD_RELOC_PPC_EMB_NADDR32),
+ MAP ("naddr16", BFD_RELOC_PPC_EMB_NADDR16),
+ MAP ("naddr@l", BFD_RELOC_PPC_EMB_NADDR16_LO),
+ MAP ("naddr@h", BFD_RELOC_PPC_EMB_NADDR16_HI),
+ MAP ("naddr@ha", BFD_RELOC_PPC_EMB_NADDR16_HA),
+ MAP ("sdai16", BFD_RELOC_PPC_EMB_SDAI16),
+ MAP ("sda2rel", BFD_RELOC_PPC_EMB_SDA2REL),
+ MAP ("sda2i16", BFD_RELOC_PPC_EMB_SDA2I16),
+ MAP ("sda21", BFD_RELOC_PPC_EMB_SDA21),
+ MAP ("mrkref", BFD_RELOC_PPC_EMB_MRKREF),
+ MAP ("relsect", BFD_RELOC_PPC_EMB_RELSEC16),
+ MAP ("relsect@l", BFD_RELOC_PPC_EMB_RELST_LO),
+ MAP ("relsect@h", BFD_RELOC_PPC_EMB_RELST_HI),
+ MAP ("relsect@ha", BFD_RELOC_PPC_EMB_RELST_HA),
+ MAP ("bitfld", BFD_RELOC_PPC_EMB_BIT_FLD),
+ MAP ("relsda", BFD_RELOC_PPC_EMB_RELSDA),
+ MAP ("xgot", BFD_RELOC_PPC_TOC16),
+
+ { (char *)0, 0, BFD_RELOC_UNUSED }
+ };
+
+ if (*str++ != '@')
+ return BFD_RELOC_UNUSED;
+
+ for (ch = *str, str2 = ident;
+ (str2 < ident + sizeof (ident) - 1
+ && (isalnum (ch) || ch == '@'));
+ ch = *++str)
+ {
+ *str2++ = (islower (ch)) ? ch : tolower (ch);
+ }
+
+ *str2 = '\0';
+ len = str2 - ident;
+
+ ch = ident[0];
+ for (ptr = &mapping[0]; ptr->length > 0; ptr++)
+ if (ch == ptr->string[0]
+ && len == ptr->length
+ && memcmp (ident, ptr->string, ptr->length) == 0)
+ {
+ if (exp_p->X_add_number != 0
+ && (ptr->reloc == BFD_RELOC_16_GOTOFF
+ || ptr->reloc == BFD_RELOC_LO16_GOTOFF
+ || ptr->reloc == BFD_RELOC_HI16_GOTOFF
+ || ptr->reloc == BFD_RELOC_HI16_S_GOTOFF))
+ as_warn (_("identifier+constant@got means identifier@got+constant"));
+
+ /* Now check for identifier@suffix+constant */
+ if (*str == '-' || *str == '+')
+ {
+ char *orig_line = input_line_pointer;
+ expressionS new_exp;
+
+ input_line_pointer = str;
+ expression (&new_exp);
+ if (new_exp.X_op == O_constant)
+ {
+ exp_p->X_add_number += new_exp.X_add_number;
+ str = input_line_pointer;
+ }
+
+ if (&input_line_pointer != str_p)
+ input_line_pointer = orig_line;
+ }
+
+ *str_p = str;
+ return ptr->reloc;
+ }
+
+ return BFD_RELOC_UNUSED;
+}
+
+/* Like normal .long/.short/.word, except support @got, etc. */
+/* clobbers input_line_pointer, checks */
+/* end-of-line. */
+static void
+ppc_elf_cons (nbytes)
+ register int nbytes; /* 1=.byte, 2=.word, 4=.long */
+{
+ expressionS exp;
+ bfd_reloc_code_real_type reloc;
+
+ if (is_it_end_of_statement ())
+ {
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ do
+ {
+ expression (&exp);
+ if (exp.X_op == O_symbol
+ && *input_line_pointer == '@'
+ && (reloc = ppc_elf_suffix (&input_line_pointer, &exp)) != BFD_RELOC_UNUSED)
+ {
+ reloc_howto_type *reloc_howto = bfd_reloc_type_lookup (stdoutput, reloc);
+ int size = bfd_get_reloc_size (reloc_howto);
+
+ if (size > nbytes)
+ as_bad (_("%s relocations do not fit in %d bytes\n"), reloc_howto->name, nbytes);
+
+ else
+ {
+ register char *p = frag_more ((int) nbytes);
+ int offset = nbytes - size;
+
+ fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size, &exp, 0, reloc);
+ }
+ }
+ else
+ emit_expr (&exp, (unsigned int) nbytes);
+ }
+ while (*input_line_pointer++ == ',');
+
+ input_line_pointer--; /* Put terminator back into stream. */
+ demand_empty_rest_of_line ();
+}
+
+/* Solaris pseduo op to change to the .rodata section. */
+static void
+ppc_elf_rdata (xxx)
+ int xxx;
+{
+ char *save_line = input_line_pointer;
+ static char section[] = ".rodata\n";
+
+ /* Just pretend this is .section .rodata */
+ input_line_pointer = section;
+ obj_elf_section (xxx);
+
+ input_line_pointer = save_line;
+}
+
+/* Pseudo op to make file scope bss items */
+static void
+ppc_elf_lcomm(xxx)
+ int xxx;
+{
+ register char *name;
+ register char c;
+ register char *p;
+ offsetT size;
+ register symbolS *symbolP;
+ offsetT align;
+ segT old_sec;
+ int old_subsec;
+ char *pfrag;
+ int align2;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+
+ /* just after name is now '\0' */
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("Expected comma after symbol-name: rest of line ignored."));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ input_line_pointer++; /* skip ',' */
+ if ((size = get_absolute_expression ()) < 0)
+ {
+ as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) size);
+ ignore_rest_of_line ();
+ return;
+ }
+
+ /* The third argument to .lcomm is the alignment. */
+ if (*input_line_pointer != ',')
+ align = 8;
+ else
+ {
+ ++input_line_pointer;
+ align = get_absolute_expression ();
+ if (align <= 0)
+ {
+ as_warn (_("ignoring bad alignment"));
+ align = 8;
+ }
+ }
+
+ *p = 0;
+ symbolP = symbol_find_or_make (name);
+ *p = c;
+
+ if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
+ {
+ as_bad (_("Ignoring attempt to re-define symbol `%s'."),
+ S_GET_NAME (symbolP));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ if (S_GET_VALUE (symbolP) && S_GET_VALUE (symbolP) != (valueT) size)
+ {
+ as_bad (_("Length of .lcomm \"%s\" is already %ld. Not changed to %ld."),
+ S_GET_NAME (symbolP),
+ (long) S_GET_VALUE (symbolP),
+ (long) size);
+
+ ignore_rest_of_line ();
+ return;
+ }
+
+ /* allocate_bss: */
+ old_sec = now_seg;
+ old_subsec = now_subseg;
+ if (align)
+ {
+ /* convert to a power of 2 alignment */
+ for (align2 = 0; (align & 1) == 0; align >>= 1, ++align2);
+ if (align != 1)
+ {
+ as_bad (_("Common alignment not a power of 2"));
+ ignore_rest_of_line ();
+ return;
+ }
+ }
+ else
+ align2 = 0;
+
+ record_alignment (bss_section, align2);
+ subseg_set (bss_section, 0);
+ if (align2)
+ frag_align (align2, 0, 0);
+ if (S_GET_SEGMENT (symbolP) == bss_section)
+ symbolP->sy_frag->fr_symbol = 0;
+ symbolP->sy_frag = frag_now;
+ pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, size,
+ (char *) 0);
+ *pfrag = 0;
+ S_SET_SIZE (symbolP, size);
+ S_SET_SEGMENT (symbolP, bss_section);
+ subseg_set (old_sec, old_subsec);
+ demand_empty_rest_of_line ();
+}
+
+/* Validate any relocations emitted for -mrelocatable, possibly adding
+ fixups for word relocations in writable segments, so we can adjust
+ them at runtime. */
+static void
+ppc_elf_validate_fix (fixp, seg)
+ fixS *fixp;
+ segT seg;
+{
+ if (fixp->fx_done || fixp->fx_pcrel)
+ return;
+
+ switch (shlib)
+ {
+ case SHLIB_NONE:
+ case SHLIB_PIC:
+ return;
+
+ case SHILB_MRELOCATABLE:
+ if (fixp->fx_r_type <= BFD_RELOC_UNUSED
+ && fixp->fx_r_type != BFD_RELOC_16_GOTOFF
+ && fixp->fx_r_type != BFD_RELOC_HI16_GOTOFF
+ && fixp->fx_r_type != BFD_RELOC_LO16_GOTOFF
+ && fixp->fx_r_type != BFD_RELOC_HI16_S_GOTOFF
+ && fixp->fx_r_type != BFD_RELOC_32_BASEREL
+ && fixp->fx_r_type != BFD_RELOC_LO16_BASEREL
+ && fixp->fx_r_type != BFD_RELOC_HI16_BASEREL
+ && fixp->fx_r_type != BFD_RELOC_HI16_S_BASEREL
+ && strcmp (segment_name (seg), ".got2") != 0
+ && strcmp (segment_name (seg), ".dtors") != 0
+ && strcmp (segment_name (seg), ".ctors") != 0
+ && strcmp (segment_name (seg), ".fixup") != 0
+ && strcmp (segment_name (seg), ".stab") != 0
+ && strcmp (segment_name (seg), ".gcc_except_table") != 0
+ && strcmp (segment_name (seg), ".eh_frame") != 0
+ && strcmp (segment_name (seg), ".ex_shared") != 0)
+ {
+ if ((seg->flags & (SEC_READONLY | SEC_CODE)) != 0
+ || fixp->fx_r_type != BFD_RELOC_CTOR)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("Relocation cannot be done when using -mrelocatable"));
+ }
+ }
+ return;
+ }
+}
+#endif /* OBJ_ELF */
+
+#ifdef TE_PE
+
+/*
+ * Summary of parse_toc_entry().
+ *
+ * in: Input_line_pointer points to the '[' in one of:
+ *
+ * [toc] [tocv] [toc32] [toc64]
+ *
+ * Anything else is an error of one kind or another.
+ *
+ * out:
+ * return value: success or failure
+ * toc_kind: kind of toc reference
+ * input_line_pointer:
+ * success: first char after the ']'
+ * failure: unchanged
+ *
+ * settings:
+ *
+ * [toc] - rv == success, toc_kind = default_toc
+ * [tocv] - rv == success, toc_kind = data_in_toc
+ * [toc32] - rv == success, toc_kind = must_be_32
+ * [toc64] - rv == success, toc_kind = must_be_64
+ *
+ */
+
+enum toc_size_qualifier
+{
+ default_toc, /* The toc cell constructed should be the system default size */
+ data_in_toc, /* This is a direct reference to a toc cell */
+ must_be_32, /* The toc cell constructed must be 32 bits wide */
+ must_be_64 /* The toc cell constructed must be 64 bits wide */
+};
+
+static int
+parse_toc_entry(toc_kind)
+ enum toc_size_qualifier *toc_kind;
+{
+ char *start;
+ char *toc_spec;
+ char c;
+ enum toc_size_qualifier t;
+
+ /* save the input_line_pointer */
+ start = input_line_pointer;
+
+ /* skip over the '[' , and whitespace */
+ ++input_line_pointer;
+ SKIP_WHITESPACE ();
+
+ /* find the spelling of the operand */
+ toc_spec = input_line_pointer;
+ c = get_symbol_end ();
+
+ if (strcmp(toc_spec, "toc") == 0)
+ {
+ t = default_toc;
+ }
+ else if (strcmp(toc_spec, "tocv") == 0)
+ {
+ t = data_in_toc;
+ }
+ else if (strcmp(toc_spec, "toc32") == 0)
+ {
+ t = must_be_32;
+ }
+ else if (strcmp(toc_spec, "toc64") == 0)
+ {
+ t = must_be_64;
+ }
+ else
+ {
+ as_bad (_("syntax error: invalid toc specifier `%s'"), toc_spec);
+ *input_line_pointer = c; /* put back the delimiting char */
+ input_line_pointer = start; /* reset input_line pointer */
+ return 0;
+ }
+
+ /* now find the ']' */
+ *input_line_pointer = c; /* put back the delimiting char */
+
+ SKIP_WHITESPACE (); /* leading whitespace could be there. */
+ c = *input_line_pointer++; /* input_line_pointer->past char in c. */
+
+ if (c != ']')
+ {
+ as_bad (_("syntax error: expected `]', found `%c'"), c);
+ input_line_pointer = start; /* reset input_line pointer */
+ return 0;
+ }
+
+ *toc_kind = t; /* set return value */
+ return 1;
+}
+#endif
+
+
+/* We need to keep a list of fixups. We can't simply generate them as
+ we go, because that would require us to first create the frag, and
+ that would screw up references to ``.''. */
+
+struct ppc_fixup
+{
+ expressionS exp;
+ int opindex;
+ bfd_reloc_code_real_type reloc;
+};
+
+#define MAX_INSN_FIXUPS (5)
+
+/* This routine is called for each instruction to be assembled. */
+
+void
+md_assemble (str)
+ char *str;
+{
+ char *s;
+ const struct powerpc_opcode *opcode;
+ unsigned long insn;
+ const unsigned char *opindex_ptr;
+ int skip_optional;
+ int need_paren;
+ int next_opindex;
+ struct ppc_fixup fixups[MAX_INSN_FIXUPS];
+ int fc;
+ char *f;
+ int i;
+#ifdef OBJ_ELF
+ bfd_reloc_code_real_type reloc;
+#endif
+
+ /* Get the opcode. */
+ for (s = str; *s != '\0' && ! isspace (*s); s++)
+ ;
+ if (*s != '\0')
+ *s++ = '\0';
+
+ /* Look up the opcode in the hash table. */
+ opcode = (const struct powerpc_opcode *) hash_find (ppc_hash, str);
+ if (opcode == (const struct powerpc_opcode *) NULL)
+ {
+ const struct powerpc_macro *macro;
+
+ macro = (const struct powerpc_macro *) hash_find (ppc_macro_hash, str);
+ if (macro == (const struct powerpc_macro *) NULL)
+ as_bad (_("Unrecognized opcode: `%s'"), str);
+ else
+ ppc_macro (s, macro);
+
+ return;
+ }
+
+ insn = opcode->opcode;
+
+ str = s;
+ while (isspace (*str))
+ ++str;
+
+ /* PowerPC operands are just expressions. The only real issue is
+ that a few operand types are optional. All cases which might use
+ an optional operand separate the operands only with commas (in
+ some cases parentheses are used, as in ``lwz 1,0(1)'' but such
+ cases never have optional operands). There is never more than
+ one optional operand for an instruction. So, before we start
+ seriously parsing the operands, we check to see if we have an
+ optional operand, and, if we do, we count the number of commas to
+ see whether the operand should be omitted. */
+ skip_optional = 0;
+ for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)
+ {
+ const struct powerpc_operand *operand;
+
+ operand = &powerpc_operands[*opindex_ptr];
+ if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
+ {
+ unsigned int opcount;
+
+ /* There is an optional operand. Count the number of
+ commas in the input line. */
+ if (*str == '\0')
+ opcount = 0;
+ else
+ {
+ opcount = 1;
+ s = str;
+ while ((s = strchr (s, ',')) != (char *) NULL)
+ {
+ ++opcount;
+ ++s;
+ }
+ }
+
+ /* If there are fewer operands in the line then are called
+ for by the instruction, we want to skip the optional
+ operand. */
+ if (opcount < strlen (opcode->operands))
+ skip_optional = 1;
+
+ break;
+ }
+ }
+
+ /* Gather the operands. */
+ need_paren = 0;
+ next_opindex = 0;
+ fc = 0;
+ for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)
+ {
+ const struct powerpc_operand *operand;
+ const char *errmsg;
+ char *hold;
+ expressionS ex;
+ char endc;
+
+ if (next_opindex == 0)
+ operand = &powerpc_operands[*opindex_ptr];
+ else
+ {
+ operand = &powerpc_operands[next_opindex];
+ next_opindex = 0;
+ }
+
+ errmsg = NULL;
+
+ /* If this is a fake operand, then we do not expect anything
+ from the input. */
+ if ((operand->flags & PPC_OPERAND_FAKE) != 0)
+ {
+ insn = (*operand->insert) (insn, 0L, &errmsg);
+ if (errmsg != (const char *) NULL)
+ as_bad (errmsg);
+ continue;
+ }
+
+ /* If this is an optional operand, and we are skipping it, just
+ insert a zero. */
+ if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
+ && skip_optional)
+ {
+ if (operand->insert)
+ {
+ insn = (*operand->insert) (insn, 0L, &errmsg);
+ if (errmsg != (const char *) NULL)
+ as_bad (errmsg);
+ }
+ if ((operand->flags & PPC_OPERAND_NEXT) != 0)
+ next_opindex = *opindex_ptr + 1;
+ continue;
+ }
+
+ /* Gather the operand. */
+ hold = input_line_pointer;
+ input_line_pointer = str;
+
+#ifdef TE_PE
+ if (*input_line_pointer == '[')
+ {
+ /* We are expecting something like the second argument here:
+
+ lwz r4,[toc].GS.0.static_int(rtoc)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ The argument following the `]' must be a symbol name, and the
+ register must be the toc register: 'rtoc' or '2'
+
+ The effect is to 0 as the displacement field
+ in the instruction, and issue an IMAGE_REL_PPC_TOCREL16 (or
+ the appropriate variation) reloc against it based on the symbol.
+ The linker will build the toc, and insert the resolved toc offset.
+
+ Note:
+ o The size of the toc entry is currently assumed to be
+ 32 bits. This should not be assumed to be a hard coded
+ number.
+ o In an effort to cope with a change from 32 to 64 bits,
+ there are also toc entries that are specified to be
+ either 32 or 64 bits:
+ lwz r4,[toc32].GS.0.static_int(rtoc)
+ lwz r4,[toc64].GS.0.static_int(rtoc)
+ These demand toc entries of the specified size, and the
+ instruction probably requires it.
+ */
+
+ int valid_toc;
+ enum toc_size_qualifier toc_kind;
+ bfd_reloc_code_real_type toc_reloc;
+
+ /* go parse off the [tocXX] part */
+ valid_toc = parse_toc_entry(&toc_kind);
+
+ if (!valid_toc)
+ {
+ /* Note: message has already been issued. */
+ /* FIXME: what sort of recovery should we do? */
+ /* demand_rest_of_line(); return; ? */
+ }
+
+ /* Now get the symbol following the ']' */
+ expression(&ex);
+
+ switch (toc_kind)
+ {
+ case default_toc:
+ /* In this case, we may not have seen the symbol yet, since */
+ /* it is allowed to appear on a .extern or .globl or just be */
+ /* a label in the .data section. */
+ toc_reloc = BFD_RELOC_PPC_TOC16;
+ break;
+ case data_in_toc:
+ /* 1. The symbol must be defined and either in the toc */
+ /* section, or a global. */
+ /* 2. The reloc generated must have the TOCDEFN flag set in */
+ /* upper bit mess of the reloc type. */
+ /* FIXME: It's a little confusing what the tocv qualifier can */
+ /* be used for. At the very least, I've seen three */
+ /* uses, only one of which I'm sure I can explain. */
+ if (ex.X_op == O_symbol)
+ {
+ assert (ex.X_add_symbol != NULL);
+ if (ex.X_add_symbol->bsym->section != tocdata_section)
+ {
+ as_bad(_("[tocv] symbol is not a toc symbol"));
+ }
+ }
+
+ toc_reloc = BFD_RELOC_PPC_TOC16;
+ break;
+ case must_be_32:
+ /* FIXME: these next two specifically specify 32/64 bit toc */
+ /* entries. We don't support them today. Is this the */
+ /* right way to say that? */
+ toc_reloc = BFD_RELOC_UNUSED;
+ as_bad (_("Unimplemented toc32 expression modifier"));
+ break;
+ case must_be_64:
+ /* FIXME: see above */
+ toc_reloc = BFD_RELOC_UNUSED;
+ as_bad (_("Unimplemented toc64 expression modifier"));
+ break;
+ default:
+ fprintf(stderr,
+ _("Unexpected return value [%d] from parse_toc_entry!\n"),
+ toc_kind);
+ abort();
+ break;
+ }
+
+ /* We need to generate a fixup for this expression. */
+ if (fc >= MAX_INSN_FIXUPS)
+ as_fatal (_("too many fixups"));
+
+ fixups[fc].reloc = toc_reloc;
+ fixups[fc].exp = ex;
+ fixups[fc].opindex = *opindex_ptr;
+ ++fc;
+
+ /* Ok. We've set up the fixup for the instruction. Now make it
+ look like the constant 0 was found here */
+ ex.X_unsigned = 1;
+ ex.X_op = O_constant;
+ ex.X_add_number = 0;
+ ex.X_add_symbol = NULL;
+ ex.X_op_symbol = NULL;
+ }
+
+ else
+#endif /* TE_PE */
+ {
+ if (! register_name (&ex))
+ {
+ if ((operand->flags & PPC_OPERAND_CR) != 0)
+ cr_operand = true;
+ expression (&ex);
+ cr_operand = false;
+ }
+ }
+
+ str = input_line_pointer;
+ input_line_pointer = hold;
+
+ if (ex.X_op == O_illegal)
+ as_bad (_("illegal operand"));
+ else if (ex.X_op == O_absent)
+ as_bad (_("missing operand"));
+ else if (ex.X_op == O_register)
+ {
+ insn = ppc_insert_operand (insn, operand, ex.X_add_number,
+ (char *) NULL, 0);
+ }
+ else if (ex.X_op == O_constant)
+ {
+#ifdef OBJ_ELF
+ /* Allow @HA, @L, @H on constants. */
+ char *orig_str = str;
+
+ if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
+ switch (reloc)
+ {
+ default:
+ str = orig_str;
+ break;
+
+ case BFD_RELOC_LO16:
+ /* X_unsigned is the default, so if the user has done
+ something which cleared it, we always produce a
+ signed value. */
+ if (ex.X_unsigned
+ && (operand->flags & PPC_OPERAND_SIGNED) == 0)
+ ex.X_add_number &= 0xffff;
+ else
+ ex.X_add_number = (((ex.X_add_number & 0xffff)
+ ^ 0x8000)
+ - 0x8000);
+ break;
+
+ case BFD_RELOC_HI16:
+ ex.X_add_number = (ex.X_add_number >> 16) & 0xffff;
+ break;
+
+ case BFD_RELOC_HI16_S:
+ ex.X_add_number = (((ex.X_add_number >> 16) & 0xffff)
+ + ((ex.X_add_number >> 15) & 1));
+ break;
+ }
+#endif
+ insn = ppc_insert_operand (insn, operand, ex.X_add_number,
+ (char *) NULL, 0);
+ }
+#ifdef OBJ_ELF
+ else if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
+ {
+ /* For the absoulte forms of branchs, convert the PC relative form back into
+ the absolute. */
+ if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
+ {
+ switch (reloc)
+ {
+ case BFD_RELOC_PPC_B26:
+ reloc = BFD_RELOC_PPC_BA26;
+ break;
+ case BFD_RELOC_PPC_B16:
+ reloc = BFD_RELOC_PPC_BA16;
+ break;
+ case BFD_RELOC_PPC_B16_BRTAKEN:
+ reloc = BFD_RELOC_PPC_BA16_BRTAKEN;
+ break;
+ case BFD_RELOC_PPC_B16_BRNTAKEN:
+ reloc = BFD_RELOC_PPC_BA16_BRNTAKEN;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* We need to generate a fixup for this expression. */
+ if (fc >= MAX_INSN_FIXUPS)
+ as_fatal (_("too many fixups"));
+ fixups[fc].exp = ex;
+ fixups[fc].opindex = 0;
+ fixups[fc].reloc = reloc;
+ ++fc;
+ }
+#endif /* OBJ_ELF */
+
+ else
+ {
+ /* We need to generate a fixup for this expression. */
+ if (fc >= MAX_INSN_FIXUPS)
+ as_fatal (_("too many fixups"));
+ fixups[fc].exp = ex;
+ fixups[fc].opindex = *opindex_ptr;
+ fixups[fc].reloc = BFD_RELOC_UNUSED;
+ ++fc;
+ }
+
+ if (need_paren)
+ {
+ endc = ')';
+ need_paren = 0;
+ }
+ else if ((operand->flags & PPC_OPERAND_PARENS) != 0)
+ {
+ endc = '(';
+ need_paren = 1;
+ }
+ else
+ endc = ',';
+
+ /* The call to expression should have advanced str past any
+ whitespace. */
+ if (*str != endc
+ && (endc != ',' || *str != '\0'))
+ {
+ as_bad (_("syntax error; found `%c' but expected `%c'"), *str, endc);
+ break;
+ }
+
+ if (*str != '\0')
+ ++str;
+ }
+
+ while (isspace (*str))
+ ++str;
+
+ if (*str != '\0')
+ as_bad (_("junk at end of line: `%s'"), str);
+
+ /* Write out the instruction. */
+ f = frag_more (4);
+ md_number_to_chars (f, insn, 4);
+
+ /* Create any fixups. At this point we do not use a
+ bfd_reloc_code_real_type, but instead just use the
+ BFD_RELOC_UNUSED plus the operand index. This lets us easily
+ handle fixups for any operand type, although that is admittedly
+ not a very exciting feature. We pick a BFD reloc type in
+ md_apply_fix. */
+ for (i = 0; i < fc; i++)
+ {
+ const struct powerpc_operand *operand;
+
+ operand = &powerpc_operands[fixups[i].opindex];
+ if (fixups[i].reloc != BFD_RELOC_UNUSED)
+ {
+ reloc_howto_type *reloc_howto = bfd_reloc_type_lookup (stdoutput, fixups[i].reloc);
+ int size;
+ int offset;
+ fixS *fixP;
+
+ if (!reloc_howto)
+ abort ();
+
+ size = bfd_get_reloc_size (reloc_howto);
+ offset = target_big_endian ? (4 - size) : 0;
+
+ if (size < 1 || size > 4)
+ abort();
+
+ fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset, size,
+ &fixups[i].exp, reloc_howto->pc_relative,
+ fixups[i].reloc);
+
+ /* Turn off complaints that the addend is too large for things like
+ foo+100000@ha. */
+ switch (fixups[i].reloc)
+ {
+ case BFD_RELOC_16_GOTOFF:
+ case BFD_RELOC_PPC_TOC16:
+ case BFD_RELOC_LO16:
+ case BFD_RELOC_HI16:
+ case BFD_RELOC_HI16_S:
+ fixP->fx_no_overflow = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ fix_new_exp (frag_now, f - frag_now->fr_literal, 4,
+ &fixups[i].exp,
+ (operand->flags & PPC_OPERAND_RELATIVE) != 0,
+ ((bfd_reloc_code_real_type)
+ (fixups[i].opindex + (int) BFD_RELOC_UNUSED)));
+ }
+}
+
+/* Handle a macro. Gather all the operands, transform them as
+ described by the macro, and call md_assemble recursively. All the
+ operands are separated by commas; we don't accept parentheses
+ around operands here. */
+
+static void
+ppc_macro (str, macro)
+ char *str;
+ const struct powerpc_macro *macro;
+{
+ char *operands[10];
+ unsigned int count;
+ char *s;
+ unsigned int len;
+ const char *format;
+ int arg;
+ char *send;
+ char *complete;
+
+ /* Gather the users operands into the operands array. */
+ count = 0;
+ s = str;
+ while (1)
+ {
+ if (count >= sizeof operands / sizeof operands[0])
+ break;
+ operands[count++] = s;
+ s = strchr (s, ',');
+ if (s == (char *) NULL)
+ break;
+ *s++ = '\0';
+ }
+
+ if (count != macro->operands)
+ {
+ as_bad (_("wrong number of operands"));
+ return;
+ }
+
+ /* Work out how large the string must be (the size is unbounded
+ because it includes user input). */
+ len = 0;
+ format = macro->format;
+ while (*format != '\0')
+ {
+ if (*format != '%')
+ {
+ ++len;
+ ++format;
+ }
+ else
+ {
+ arg = strtol (format + 1, &send, 10);
+ know (send != format && arg >= 0 && arg < count);
+ len += strlen (operands[arg]);
+ format = send;
+ }
+ }
+
+ /* Put the string together. */
+ complete = s = (char *) alloca (len + 1);
+ format = macro->format;
+ while (*format != '\0')
+ {
+ if (*format != '%')
+ *s++ = *format++;
+ else
+ {
+ arg = strtol (format + 1, &send, 10);
+ strcpy (s, operands[arg]);
+ s += strlen (s);
+ format = send;
+ }
+ }
+ *s = '\0';
+
+ /* Assemble the constructed instruction. */
+ md_assemble (complete);
+}
+
+#ifdef OBJ_ELF
+/* For ELF, add support for SHF_EXCLUDE and SHT_ORDERED */
+
+int
+ppc_section_letter (letter, ptr_msg)
+ int letter;
+ char **ptr_msg;
+{
+ if (letter == 'e')
+ return SHF_EXCLUDE;
+
+ *ptr_msg = _("Bad .section directive: want a,w,x,e in string");
+ return 0;
+}
+
+int
+ppc_section_word (ptr_str)
+ char **ptr_str;
+{
+ if (strncmp (*ptr_str, "exclude", sizeof ("exclude")-1) == 0)
+ {
+ *ptr_str += sizeof ("exclude")-1;
+ return SHF_EXCLUDE;
+ }
+
+ return 0;
+}
+
+int
+ppc_section_type (ptr_str)
+ char **ptr_str;
+{
+ if (strncmp (*ptr_str, "ordered", sizeof ("ordered")-1) == 0)
+ {
+ *ptr_str += sizeof ("ordered")-1;
+ return SHT_ORDERED;
+ }
+
+ return 0;
+}
+
+int
+ppc_section_flags (flags, attr, type)
+ int flags;
+ int attr;
+ int type;
+{
+ if (type == SHT_ORDERED)
+ flags |= SEC_ALLOC | SEC_LOAD | SEC_SORT_ENTRIES;
+
+ if (attr & SHF_EXCLUDE)
+ flags |= SEC_EXCLUDE;
+
+ return flags;
+}
+#endif /* OBJ_ELF */
+
+
+/* Pseudo-op handling. */
+
+/* The .byte pseudo-op. This is similar to the normal .byte
+ pseudo-op, but it can also take a single ASCII string. */
+
+static void
+ppc_byte (ignore)
+ int ignore;
+{
+ if (*input_line_pointer != '\"')
+ {
+ cons (1);
+ return;
+ }
+
+ /* Gather characters. A real double quote is doubled. Unusual
+ characters are not permitted. */
+ ++input_line_pointer;
+ while (1)
+ {
+ char c;
+
+ c = *input_line_pointer++;
+
+ if (c == '\"')
+ {
+ if (*input_line_pointer != '\"')
+ break;
+ ++input_line_pointer;
+ }
+
+ FRAG_APPEND_1_CHAR (c);
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+#ifdef OBJ_XCOFF
+
+/* XCOFF specific pseudo-op handling. */
+
+/* This is set if we are creating a .stabx symbol, since we don't want
+ to handle symbol suffixes for such symbols. */
+static boolean ppc_stab_symbol;
+
+/* The .comm and .lcomm pseudo-ops for XCOFF. XCOFF puts common
+ symbols in the .bss segment as though they were local common
+ symbols, and uses a different smclas. */
+
+static void
+ppc_comm (lcomm)
+ int lcomm;
+{
+ asection *current_seg = now_seg;
+ subsegT current_subseg = now_subseg;
+ char *name;
+ char endc;
+ char *end_name;
+ offsetT size;
+ offsetT align;
+ symbolS *lcomm_sym = NULL;
+ symbolS *sym;
+ char *pfrag;
+
+ name = input_line_pointer;
+ endc = get_symbol_end ();
+ end_name = input_line_pointer;
+ *end_name = endc;
+
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("missing size"));
+ ignore_rest_of_line ();
+ return;
+ }
+ ++input_line_pointer;
+
+ size = get_absolute_expression ();
+ if (size < 0)
+ {
+ as_bad (_("negative size"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ if (! lcomm)
+ {
+ /* The third argument to .comm is the alignment. */
+ if (*input_line_pointer != ',')
+ align = 3;
+ else
+ {
+ ++input_line_pointer;
+ align = get_absolute_expression ();
+ if (align <= 0)
+ {
+ as_warn (_("ignoring bad alignment"));
+ align = 3;
+ }
+ }
+ }
+ else
+ {
+ char *lcomm_name;
+ char lcomm_endc;
+
+ if (size <= 1)
+ align = 0;
+ else if (size <= 2)
+ align = 1;
+ else if (size <= 4)
+ align = 2;
+ else
+ align = 3;
+
+ /* The third argument to .lcomm appears to be the real local
+ common symbol to create. References to the symbol named in
+ the first argument are turned into references to the third
+ argument. */
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("missing real symbol name"));
+ ignore_rest_of_line ();
+ return;
+ }
+ ++input_line_pointer;
+
+ lcomm_name = input_line_pointer;
+ lcomm_endc = get_symbol_end ();
+
+ lcomm_sym = symbol_find_or_make (lcomm_name);
+
+ *input_line_pointer = lcomm_endc;
+ }
+
+ *end_name = '\0';
+ sym = symbol_find_or_make (name);
+ *end_name = endc;
+
+ if (S_IS_DEFINED (sym)
+ || S_GET_VALUE (sym) != 0)
+ {
+ as_bad (_("attempt to redefine symbol"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ record_alignment (bss_section, align);
+
+ if (! lcomm
+ || ! S_IS_DEFINED (lcomm_sym))
+ {
+ symbolS *def_sym;
+ offsetT def_size;
+
+ if (! lcomm)
+ {
+ def_sym = sym;
+ def_size = size;
+ S_SET_EXTERNAL (sym);
+ }
+ else
+ {
+ lcomm_sym->sy_tc.output = 1;
+ def_sym = lcomm_sym;
+ def_size = 0;
+ }
+
+ subseg_set (bss_section, 1);
+ frag_align (align, 0, 0);
+
+ def_sym->sy_frag = frag_now;
+ pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, def_sym,
+ def_size, (char *) NULL);
+ *pfrag = 0;
+ S_SET_SEGMENT (def_sym, bss_section);
+ def_sym->sy_tc.align = align;
+ }
+ else if (lcomm)
+ {
+ /* Align the size of lcomm_sym. */
+ lcomm_sym->sy_frag->fr_offset =
+ ((lcomm_sym->sy_frag->fr_offset + (1 << align) - 1)
+ &~ ((1 << align) - 1));
+ if (align > lcomm_sym->sy_tc.align)
+ lcomm_sym->sy_tc.align = align;
+ }
+
+ if (lcomm)
+ {
+ /* Make sym an offset from lcomm_sym. */
+ S_SET_SEGMENT (sym, bss_section);
+ sym->sy_frag = lcomm_sym->sy_frag;
+ S_SET_VALUE (sym, lcomm_sym->sy_frag->fr_offset);
+ lcomm_sym->sy_frag->fr_offset += size;
+ }
+
+ subseg_set (current_seg, current_subseg);
+
+ demand_empty_rest_of_line ();
+}
+
+/* The .csect pseudo-op. This switches us into a different
+ subsegment. The first argument is a symbol whose value is the
+ start of the .csect. In COFF, csect symbols get special aux
+ entries defined by the x_csect field of union internal_auxent. The
+ optional second argument is the alignment (the default is 2). */
+
+static void
+ppc_csect (ignore)
+ int ignore;
+{
+ char *name;
+ char endc;
+ symbolS *sym;
+
+ name = input_line_pointer;
+ endc = get_symbol_end ();
+
+ sym = symbol_find_or_make (name);
+
+ *input_line_pointer = endc;
+
+ if (S_GET_NAME (sym)[0] == '\0')
+ {
+ /* An unnamed csect is assumed to be [PR]. */
+ sym->sy_tc.class = XMC_PR;
+ }
+
+ ppc_change_csect (sym);
+
+ if (*input_line_pointer == ',')
+ {
+ ++input_line_pointer;
+ sym->sy_tc.align = get_absolute_expression ();
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* Change to a different csect. */
+
+static void
+ppc_change_csect (sym)
+ symbolS *sym;
+{
+ if (S_IS_DEFINED (sym))
+ subseg_set (S_GET_SEGMENT (sym), sym->sy_tc.subseg);
+ else
+ {
+ symbolS **list_ptr;
+ int after_toc;
+ int hold_chunksize;
+ symbolS *list;
+
+ /* This is a new csect. We need to look at the symbol class to
+ figure out whether it should go in the text section or the
+ data section. */
+ after_toc = 0;
+ switch (sym->sy_tc.class)
+ {
+ case XMC_PR:
+ case XMC_RO:
+ case XMC_DB:
+ case XMC_GL:
+ case XMC_XO:
+ case XMC_SV:
+ case XMC_TI:
+ case XMC_TB:
+ S_SET_SEGMENT (sym, text_section);
+ sym->sy_tc.subseg = ppc_text_subsegment;
+ ++ppc_text_subsegment;
+ list_ptr = &ppc_text_csects;
+ break;
+ case XMC_RW:
+ case XMC_TC0:
+ case XMC_TC:
+ case XMC_DS:
+ case XMC_UA:
+ case XMC_BS:
+ case XMC_UC:
+ if (ppc_toc_csect != NULL
+ && ppc_toc_csect->sy_tc.subseg + 1 == ppc_data_subsegment)
+ after_toc = 1;
+ S_SET_SEGMENT (sym, data_section);
+ sym->sy_tc.subseg = ppc_data_subsegment;
+ ++ppc_data_subsegment;
+ list_ptr = &ppc_data_csects;
+ break;
+ default:
+ abort ();
+ }
+
+ /* We set the obstack chunk size to a small value before
+ changing subsegments, so that we don't use a lot of memory
+ space for what may be a small section. */
+ hold_chunksize = chunksize;
+ chunksize = 64;
+
+ subseg_new (segment_name (S_GET_SEGMENT (sym)), sym->sy_tc.subseg);
+
+ chunksize = hold_chunksize;
+
+ if (after_toc)
+ ppc_after_toc_frag = frag_now;
+
+ sym->sy_frag = frag_now;
+ S_SET_VALUE (sym, (valueT) frag_now_fix ());
+
+ sym->sy_tc.align = 2;
+ sym->sy_tc.output = 1;
+ sym->sy_tc.within = sym;
+
+ for (list = *list_ptr;
+ list->sy_tc.next != (symbolS *) NULL;
+ list = list->sy_tc.next)
+ ;
+ list->sy_tc.next = sym;
+
+ symbol_remove (sym, &symbol_rootP, &symbol_lastP);
+ symbol_append (sym, list->sy_tc.within, &symbol_rootP, &symbol_lastP);
+ }
+
+ ppc_current_csect = sym;
+}
+
+/* This function handles the .text and .data pseudo-ops. These
+ pseudo-ops aren't really used by XCOFF; we implement them for the
+ convenience of people who aren't used to XCOFF. */
+
+static void
+ppc_section (type)
+ int type;
+{
+ const char *name;
+ symbolS *sym;
+
+ if (type == 't')
+ name = ".text[PR]";
+ else if (type == 'd')
+ name = ".data[RW]";
+ else
+ abort ();
+
+ sym = symbol_find_or_make (name);
+
+ ppc_change_csect (sym);
+
+ demand_empty_rest_of_line ();
+}
+
+/* This function handles the .section pseudo-op. This is mostly to
+ give an error, since XCOFF only supports .text, .data and .bss, but
+ we do permit the user to name the text or data section. */
+
+static void
+ppc_named_section (ignore)
+ int ignore;
+{
+ char *user_name;
+ const char *real_name;
+ char c;
+ symbolS *sym;
+
+ user_name = input_line_pointer;
+ c = get_symbol_end ();
+
+ if (strcmp (user_name, ".text") == 0)
+ real_name = ".text[PR]";
+ else if (strcmp (user_name, ".data") == 0)
+ real_name = ".data[RW]";
+ else
+ {
+ as_bad (_("The XCOFF file format does not support arbitrary sections"));
+ *input_line_pointer = c;
+ ignore_rest_of_line ();
+ return;
+ }
+
+ *input_line_pointer = c;
+
+ sym = symbol_find_or_make (real_name);
+
+ ppc_change_csect (sym);
+
+ demand_empty_rest_of_line ();
+}
+
+/* The .extern pseudo-op. We create an undefined symbol. */
+
+static void
+ppc_extern (ignore)
+ int ignore;
+{
+ char *name;
+ char endc;
+
+ name = input_line_pointer;
+ endc = get_symbol_end ();
+
+ (void) symbol_find_or_make (name);
+
+ *input_line_pointer = endc;
+
+ demand_empty_rest_of_line ();
+}
+
+/* The .lglobl pseudo-op. Keep the symbol in the symbol table. */
+
+static void
+ppc_lglobl (ignore)
+ int ignore;
+{
+ char *name;
+ char endc;
+ symbolS *sym;
+
+ name = input_line_pointer;
+ endc = get_symbol_end ();
+
+ sym = symbol_find_or_make (name);
+
+ *input_line_pointer = endc;
+
+ sym->sy_tc.output = 1;
+
+ demand_empty_rest_of_line ();
+}
+
+/* The .rename pseudo-op. The RS/6000 assembler can rename symbols,
+ although I don't know why it bothers. */
+
+static void
+ppc_rename (ignore)
+ int ignore;
+{
+ char *name;
+ char endc;
+ symbolS *sym;
+ int len;
+
+ name = input_line_pointer;
+ endc = get_symbol_end ();
+
+ sym = symbol_find_or_make (name);
+
+ *input_line_pointer = endc;
+
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("missing rename string"));
+ ignore_rest_of_line ();
+ return;
+ }
+ ++input_line_pointer;
+
+ sym->sy_tc.real_name = demand_copy_C_string (&len);
+
+ demand_empty_rest_of_line ();
+}
+
+/* The .stabx pseudo-op. This is similar to a normal .stabs
+ pseudo-op, but slightly different. A sample is
+ .stabx "main:F-1",.main,142,0
+ The first argument is the symbol name to create. The second is the
+ value, and the third is the storage class. The fourth seems to be
+ always zero, and I am assuming it is the type. */
+
+static void
+ppc_stabx (ignore)
+ int ignore;
+{
+ char *name;
+ int len;
+ symbolS *sym;
+ expressionS exp;
+
+ name = demand_copy_C_string (&len);
+
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("missing value"));
+ return;
+ }
+ ++input_line_pointer;
+
+ ppc_stab_symbol = true;
+ sym = symbol_make (name);
+ ppc_stab_symbol = false;
+
+ sym->sy_tc.real_name = name;
+
+ (void) expression (&exp);
+
+ switch (exp.X_op)
+ {
+ case O_illegal:
+ case O_absent:
+ case O_big:
+ as_bad (_("illegal .stabx expression; zero assumed"));
+ exp.X_add_number = 0;
+ /* Fall through. */
+ case O_constant:
+ S_SET_VALUE (sym, (valueT) exp.X_add_number);
+ sym->sy_frag = &zero_address_frag;
+ break;
+
+ case O_symbol:
+ if (S_GET_SEGMENT (exp.X_add_symbol) == undefined_section)
+ sym->sy_value = exp;
+ else
+ {
+ S_SET_VALUE (sym,
+ exp.X_add_number + S_GET_VALUE (exp.X_add_symbol));
+ sym->sy_frag = exp.X_add_symbol->sy_frag;
+ }
+ break;
+
+ default:
+ /* The value is some complex expression. This will probably
+ fail at some later point, but this is probably the right
+ thing to do here. */
+ sym->sy_value = exp;
+ break;
+ }
+
+ S_SET_SEGMENT (sym, ppc_coff_debug_section);
+ sym->bsym->flags |= BSF_DEBUGGING;
+
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("missing class"));
+ return;
+ }
+ ++input_line_pointer;
+
+ S_SET_STORAGE_CLASS (sym, get_absolute_expression ());
+
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("missing type"));
+ return;
+ }
+ ++input_line_pointer;
+
+ S_SET_DATA_TYPE (sym, get_absolute_expression ());
+
+ sym->sy_tc.output = 1;
+
+ if (S_GET_STORAGE_CLASS (sym) == C_STSYM)
+ sym->sy_tc.within = ppc_current_block;
+
+ if (exp.X_op != O_symbol
+ || ! S_IS_EXTERNAL (exp.X_add_symbol)
+ || S_GET_SEGMENT (exp.X_add_symbol) != bss_section)
+ ppc_frob_label (sym);
+ else
+ {
+ symbol_remove (sym, &symbol_rootP, &symbol_lastP);
+ symbol_append (sym, exp.X_add_symbol, &symbol_rootP, &symbol_lastP);
+ if (ppc_current_csect->sy_tc.within == exp.X_add_symbol)
+ ppc_current_csect->sy_tc.within = sym;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* The .function pseudo-op. This takes several arguments. The first
+ argument seems to be the external name of the symbol. The second
+ argment seems to be the label for the start of the function. gcc
+ uses the same name for both. I have no idea what the third and
+ fourth arguments are meant to be. The optional fifth argument is
+ an expression for the size of the function. In COFF this symbol
+ gets an aux entry like that used for a csect. */
+
+static void
+ppc_function (ignore)
+ int ignore;
+{
+ char *name;
+ char endc;
+ char *s;
+ symbolS *ext_sym;
+ symbolS *lab_sym;
+
+ name = input_line_pointer;
+ endc = get_symbol_end ();
+
+ /* Ignore any [PR] suffix. */
+ name = ppc_canonicalize_symbol_name (name);
+ s = strchr (name, '[');
+ if (s != (char *) NULL
+ && strcmp (s + 1, "PR]") == 0)
+ *s = '\0';
+
+ ext_sym = symbol_find_or_make (name);
+
+ *input_line_pointer = endc;
+
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("missing symbol name"));
+ ignore_rest_of_line ();
+ return;
+ }
+ ++input_line_pointer;
+
+ name = input_line_pointer;
+ endc = get_symbol_end ();
+
+ lab_sym = symbol_find_or_make (name);
+
+ *input_line_pointer = endc;
+
+ if (ext_sym != lab_sym)
+ {
+ ext_sym->sy_value.X_op = O_symbol;
+ ext_sym->sy_value.X_add_symbol = lab_sym;
+ ext_sym->sy_value.X_op_symbol = NULL;
+ ext_sym->sy_value.X_add_number = 0;
+ }
+
+ if (ext_sym->sy_tc.class == -1)
+ ext_sym->sy_tc.class = XMC_PR;
+ ext_sym->sy_tc.output = 1;
+
+ if (*input_line_pointer == ',')
+ {
+ expressionS ignore;
+
+ /* Ignore the third argument. */
+ ++input_line_pointer;
+ expression (&ignore);
+ if (*input_line_pointer == ',')
+ {
+ /* Ignore the fourth argument. */
+ ++input_line_pointer;
+ expression (&ignore);
+ if (*input_line_pointer == ',')
+ {
+ /* The fifth argument is the function size. */
+ ++input_line_pointer;
+ ext_sym->sy_tc.size = symbol_new ("L0\001",
+ absolute_section,
+ (valueT) 0,
+ &zero_address_frag);
+ pseudo_set (ext_sym->sy_tc.size);
+ }
+ }
+ }
+
+ S_SET_DATA_TYPE (ext_sym, DT_FCN << N_BTSHFT);
+ SF_SET_FUNCTION (ext_sym);
+ SF_SET_PROCESS (ext_sym);
+ coff_add_linesym (ext_sym);
+
+ demand_empty_rest_of_line ();
+}
+
+/* The .bf pseudo-op. This is just like a COFF C_FCN symbol named
+ ".bf". */
+
+static void
+ppc_bf (ignore)
+ int ignore;
+{
+ symbolS *sym;
+
+ sym = symbol_make (".bf");
+ S_SET_SEGMENT (sym, text_section);
+ sym->sy_frag = frag_now;
+ S_SET_VALUE (sym, frag_now_fix ());
+ S_SET_STORAGE_CLASS (sym, C_FCN);
+
+ coff_line_base = get_absolute_expression ();
+
+ S_SET_NUMBER_AUXILIARY (sym, 1);
+ SA_SET_SYM_LNNO (sym, coff_line_base);
+
+ sym->sy_tc.output = 1;
+
+ ppc_frob_label (sym);
+
+ demand_empty_rest_of_line ();
+}
+
+/* The .ef pseudo-op. This is just like a COFF C_FCN symbol named
+ ".ef", except that the line number is absolute, not relative to the
+ most recent ".bf" symbol. */
+
+static void
+ppc_ef (ignore)
+ int ignore;
+{
+ symbolS *sym;
+
+ sym = symbol_make (".ef");
+ S_SET_SEGMENT (sym, text_section);
+ sym->sy_frag = frag_now;
+ S_SET_VALUE (sym, frag_now_fix ());
+ S_SET_STORAGE_CLASS (sym, C_FCN);
+ S_SET_NUMBER_AUXILIARY (sym, 1);
+ SA_SET_SYM_LNNO (sym, get_absolute_expression ());
+ sym->sy_tc.output = 1;
+
+ ppc_frob_label (sym);
+
+ demand_empty_rest_of_line ();
+}
+
+/* The .bi and .ei pseudo-ops. These take a string argument and
+ generates a C_BINCL or C_EINCL symbol, which goes at the start of
+ the symbol list. */
+
+static void
+ppc_biei (ei)
+ int ei;
+{
+ static symbolS *last_biei;
+
+ char *name;
+ int len;
+ symbolS *sym;
+ symbolS *look;
+
+ name = demand_copy_C_string (&len);
+
+ /* The value of these symbols is actually file offset. Here we set
+ the value to the index into the line number entries. In
+ ppc_frob_symbols we set the fix_line field, which will cause BFD
+ to do the right thing. */
+
+ sym = symbol_make (name);
+ /* obj-coff.c currently only handles line numbers correctly in the
+ .text section. */
+ S_SET_SEGMENT (sym, text_section);
+ S_SET_VALUE (sym, coff_n_line_nos);
+ sym->bsym->flags |= BSF_DEBUGGING;
+
+ S_SET_STORAGE_CLASS (sym, ei ? C_EINCL : C_BINCL);
+ sym->sy_tc.output = 1;
+
+ for (look = last_biei ? last_biei : symbol_rootP;
+ (look != (symbolS *) NULL
+ && (S_GET_STORAGE_CLASS (look) == C_FILE
+ || S_GET_STORAGE_CLASS (look) == C_BINCL
+ || S_GET_STORAGE_CLASS (look) == C_EINCL));
+ look = symbol_next (look))
+ ;
+ if (look != (symbolS *) NULL)
+ {
+ symbol_remove (sym, &symbol_rootP, &symbol_lastP);
+ symbol_insert (sym, look, &symbol_rootP, &symbol_lastP);
+ last_biei = sym;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* The .bs pseudo-op. This generates a C_BSTAT symbol named ".bs".
+ There is one argument, which is a csect symbol. The value of the
+ .bs symbol is the index of this csect symbol. */
+
+static void
+ppc_bs (ignore)
+ int ignore;
+{
+ char *name;
+ char endc;
+ symbolS *csect;
+ symbolS *sym;
+
+ if (ppc_current_block != NULL)
+ as_bad (_("nested .bs blocks"));
+
+ name = input_line_pointer;
+ endc = get_symbol_end ();
+
+ csect = symbol_find_or_make (name);
+
+ *input_line_pointer = endc;
+
+ sym = symbol_make (".bs");
+ S_SET_SEGMENT (sym, now_seg);
+ S_SET_STORAGE_CLASS (sym, C_BSTAT);
+ sym->bsym->flags |= BSF_DEBUGGING;
+ sym->sy_tc.output = 1;
+
+ sym->sy_tc.within = csect;
+
+ ppc_frob_label (sym);
+
+ ppc_current_block = sym;
+
+ demand_empty_rest_of_line ();
+}
+
+/* The .es pseudo-op. Generate a C_ESTART symbol named .es. */
+
+static void
+ppc_es (ignore)
+ int ignore;
+{
+ symbolS *sym;
+
+ if (ppc_current_block == NULL)
+ as_bad (_(".es without preceding .bs"));
+
+ sym = symbol_make (".es");
+ S_SET_SEGMENT (sym, now_seg);
+ S_SET_STORAGE_CLASS (sym, C_ESTAT);
+ sym->bsym->flags |= BSF_DEBUGGING;
+ sym->sy_tc.output = 1;
+
+ ppc_frob_label (sym);
+
+ ppc_current_block = NULL;
+
+ demand_empty_rest_of_line ();
+}
+
+/* The .bb pseudo-op. Generate a C_BLOCK symbol named .bb, with a
+ line number. */
+
+static void
+ppc_bb (ignore)
+ int ignore;
+{
+ symbolS *sym;
+
+ sym = symbol_make (".bb");
+ S_SET_SEGMENT (sym, text_section);
+ sym->sy_frag = frag_now;
+ S_SET_VALUE (sym, frag_now_fix ());
+ S_SET_STORAGE_CLASS (sym, C_BLOCK);
+
+ S_SET_NUMBER_AUXILIARY (sym, 1);
+ SA_SET_SYM_LNNO (sym, get_absolute_expression ());
+
+ sym->sy_tc.output = 1;
+
+ SF_SET_PROCESS (sym);
+
+ ppc_frob_label (sym);
+
+ demand_empty_rest_of_line ();
+}
+
+/* The .eb pseudo-op. Generate a C_BLOCK symbol named .eb, with a
+ line number. */
+
+static void
+ppc_eb (ignore)
+ int ignore;
+{
+ symbolS *sym;
+
+ sym = symbol_make (".eb");
+ S_SET_SEGMENT (sym, text_section);
+ sym->sy_frag = frag_now;
+ S_SET_VALUE (sym, frag_now_fix ());
+ S_SET_STORAGE_CLASS (sym, C_BLOCK);
+ S_SET_NUMBER_AUXILIARY (sym, 1);
+ SA_SET_SYM_LNNO (sym, get_absolute_expression ());
+ sym->sy_tc.output = 1;
+
+ SF_SET_PROCESS (sym);
+
+ ppc_frob_label (sym);
+
+ demand_empty_rest_of_line ();
+}
+
+/* The .bc pseudo-op. This just creates a C_BCOMM symbol with a
+ specified name. */
+
+static void
+ppc_bc (ignore)
+ int ignore;
+{
+ char *name;
+ int len;
+ symbolS *sym;
+
+ name = demand_copy_C_string (&len);
+ sym = symbol_make (name);
+ S_SET_SEGMENT (sym, ppc_coff_debug_section);
+ sym->bsym->flags |= BSF_DEBUGGING;
+ S_SET_STORAGE_CLASS (sym, C_BCOMM);
+ S_SET_VALUE (sym, 0);
+ sym->sy_tc.output = 1;
+
+ ppc_frob_label (sym);
+
+ demand_empty_rest_of_line ();
+}
+
+/* The .ec pseudo-op. This just creates a C_ECOMM symbol. */
+
+static void
+ppc_ec (ignore)
+ int ignore;
+{
+ symbolS *sym;
+
+ sym = symbol_make (".ec");
+ S_SET_SEGMENT (sym, ppc_coff_debug_section);
+ sym->bsym->flags |= BSF_DEBUGGING;
+ S_SET_STORAGE_CLASS (sym, C_ECOMM);
+ S_SET_VALUE (sym, 0);
+ sym->sy_tc.output = 1;
+
+ ppc_frob_label (sym);
+
+ demand_empty_rest_of_line ();
+}
+
+/* The .toc pseudo-op. Switch to the .toc subsegment. */
+
+static void
+ppc_toc (ignore)
+ int ignore;
+{
+ if (ppc_toc_csect != (symbolS *) NULL)
+ subseg_set (data_section, ppc_toc_csect->sy_tc.subseg);
+ else
+ {
+ subsegT subseg;
+ symbolS *sym;
+ symbolS *list;
+
+ subseg = ppc_data_subsegment;
+ ++ppc_data_subsegment;
+
+ subseg_new (segment_name (data_section), subseg);
+ ppc_toc_frag = frag_now;
+
+ sym = symbol_find_or_make ("TOC[TC0]");
+ sym->sy_frag = frag_now;
+ S_SET_SEGMENT (sym, data_section);
+ S_SET_VALUE (sym, (valueT) frag_now_fix ());
+ sym->sy_tc.subseg = subseg;
+ sym->sy_tc.output = 1;
+ sym->sy_tc.within = sym;
+
+ ppc_toc_csect = sym;
+
+ for (list = ppc_data_csects;
+ list->sy_tc.next != (symbolS *) NULL;
+ list = list->sy_tc.next)
+ ;
+ list->sy_tc.next = sym;
+
+ symbol_remove (sym, &symbol_rootP, &symbol_lastP);
+ symbol_append (sym, list->sy_tc.within, &symbol_rootP, &symbol_lastP);
+ }
+
+ ppc_current_csect = ppc_toc_csect;
+
+ demand_empty_rest_of_line ();
+}
+
+/* The AIX assembler automatically aligns the operands of a .long or
+ .short pseudo-op, and we want to be compatible. */
+
+static void
+ppc_xcoff_cons (log_size)
+ int log_size;
+{
+ frag_align (log_size, 0, 0);
+ record_alignment (now_seg, log_size);
+ cons (1 << log_size);
+}
+
+static void
+ppc_vbyte (dummy)
+ int dummy;
+{
+ expressionS exp;
+ int byte_count;
+
+ (void) expression (&exp);
+
+ if (exp.X_op != O_constant)
+ {
+ as_bad (_("non-constant byte count"));
+ return;
+ }
+
+ byte_count = exp.X_add_number;
+
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("missing value"));
+ return;
+ }
+
+ ++input_line_pointer;
+ cons (byte_count);
+}
+
+#endif /* OBJ_XCOFF */
+
+/* The .tc pseudo-op. This is used when generating either XCOFF or
+ ELF. This takes two or more arguments.
+
+ When generating XCOFF output, the first argument is the name to
+ give to this location in the toc; this will be a symbol with class
+ TC. The rest of the arguments are 4 byte values to actually put at
+ this location in the TOC; often there is just one more argument, a
+ relocateable symbol reference.
+
+ When not generating XCOFF output, the arguments are the same, but
+ the first argument is simply ignored. */
+
+static void
+ppc_tc (ignore)
+ int ignore;
+{
+#ifdef OBJ_XCOFF
+
+ /* Define the TOC symbol name. */
+ {
+ char *name;
+ char endc;
+ symbolS *sym;
+
+ if (ppc_toc_csect == (symbolS *) NULL
+ || ppc_toc_csect != ppc_current_csect)
+ {
+ as_bad (_(".tc not in .toc section"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ name = input_line_pointer;
+ endc = get_symbol_end ();
+
+ sym = symbol_find_or_make (name);
+
+ *input_line_pointer = endc;
+
+ if (S_IS_DEFINED (sym))
+ {
+ symbolS *label;
+
+ label = ppc_current_csect->sy_tc.within;
+ if (label->sy_tc.class != XMC_TC0)
+ {
+ as_bad (_(".tc with no label"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ S_SET_SEGMENT (label, S_GET_SEGMENT (sym));
+ label->sy_frag = sym->sy_frag;
+ S_SET_VALUE (label, S_GET_VALUE (sym));
+
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+
+ return;
+ }
+
+ S_SET_SEGMENT (sym, now_seg);
+ sym->sy_frag = frag_now;
+ S_SET_VALUE (sym, (valueT) frag_now_fix ());
+ sym->sy_tc.class = XMC_TC;
+ sym->sy_tc.output = 1;
+
+ ppc_frob_label (sym);
+ }
+
+#else /* ! defined (OBJ_XCOFF) */
+
+ /* Skip the TOC symbol name. */
+ while (is_part_of_name (*input_line_pointer)
+ || *input_line_pointer == '['
+ || *input_line_pointer == ']'
+ || *input_line_pointer == '{'
+ || *input_line_pointer == '}')
+ ++input_line_pointer;
+
+ /* Align to a four byte boundary. */
+ frag_align (2, 0, 0);
+ record_alignment (now_seg, 2);
+
+#endif /* ! defined (OBJ_XCOFF) */
+
+ if (*input_line_pointer != ',')
+ demand_empty_rest_of_line ();
+ else
+ {
+ ++input_line_pointer;
+ cons (4);
+ }
+}
+
+#ifdef TE_PE
+
+/* Pseudo-ops specific to the Windows NT PowerPC PE (coff) format */
+
+/* Set the current section. */
+static void
+ppc_set_current_section (new)
+ segT new;
+{
+ ppc_previous_section = ppc_current_section;
+ ppc_current_section = new;
+}
+
+/* pseudo-op: .previous
+ behaviour: toggles the current section with the previous section.
+ errors: None
+ warnings: "No previous section"
+*/
+static void
+ppc_previous(ignore)
+ int ignore;
+{
+ symbolS *tmp;
+
+ if (ppc_previous_section == NULL)
+ {
+ as_warn(_("No previous section to return to. Directive ignored."));
+ return;
+ }
+
+ subseg_set(ppc_previous_section, 0);
+
+ ppc_set_current_section(ppc_previous_section);
+}
+
+/* pseudo-op: .pdata
+ behaviour: predefined read only data section
+ double word aligned
+ errors: None
+ warnings: None
+ initial: .section .pdata "adr3"
+ a - don't know -- maybe a misprint
+ d - initialized data
+ r - readable
+ 3 - double word aligned (that would be 4 byte boundary)
+
+ commentary:
+ Tag index tables (also known as the function table) for exception
+ handling, debugging, etc.
+
+*/
+static void
+ppc_pdata(ignore)
+ int ignore;
+{
+ if (pdata_section == 0)
+ {
+ pdata_section = subseg_new (".pdata", 0);
+
+ bfd_set_section_flags (stdoutput, pdata_section,
+ (SEC_ALLOC | SEC_LOAD | SEC_RELOC
+ | SEC_READONLY | SEC_DATA ));
+
+ bfd_set_section_alignment (stdoutput, pdata_section, 2);
+ }
+ else
+ {
+ pdata_section = subseg_new(".pdata", 0);
+ }
+ ppc_set_current_section(pdata_section);
+}
+
+/* pseudo-op: .ydata
+ behaviour: predefined read only data section
+ double word aligned
+ errors: None
+ warnings: None
+ initial: .section .ydata "drw3"
+ a - don't know -- maybe a misprint
+ d - initialized data
+ r - readable
+ 3 - double word aligned (that would be 4 byte boundary)
+ commentary:
+ Tag tables (also known as the scope table) for exception handling,
+ debugging, etc.
+*/
+static void
+ppc_ydata(ignore)
+ int ignore;
+{
+ if (ydata_section == 0)
+ {
+ ydata_section = subseg_new (".ydata", 0);
+ bfd_set_section_flags (stdoutput, ydata_section,
+ (SEC_ALLOC | SEC_LOAD | SEC_RELOC
+ | SEC_READONLY | SEC_DATA ));
+
+ bfd_set_section_alignment (stdoutput, ydata_section, 3);
+ }
+ else
+ {
+ ydata_section = subseg_new (".ydata", 0);
+ }
+ ppc_set_current_section(ydata_section);
+}
+
+/* pseudo-op: .reldata
+ behaviour: predefined read write data section
+ double word aligned (4-byte)
+ FIXME: relocation is applied to it
+ FIXME: what's the difference between this and .data?
+ errors: None
+ warnings: None
+ initial: .section .reldata "drw3"
+ d - initialized data
+ r - readable
+ w - writeable
+ 3 - double word aligned (that would be 8 byte boundary)
+
+ commentary:
+ Like .data, but intended to hold data subject to relocation, such as
+ function descriptors, etc.
+*/
+static void
+ppc_reldata(ignore)
+ int ignore;
+{
+ if (reldata_section == 0)
+ {
+ reldata_section = subseg_new (".reldata", 0);
+
+ bfd_set_section_flags (stdoutput, reldata_section,
+ ( SEC_ALLOC | SEC_LOAD | SEC_RELOC
+ | SEC_DATA ));
+
+ bfd_set_section_alignment (stdoutput, reldata_section, 2);
+ }
+ else
+ {
+ reldata_section = subseg_new (".reldata", 0);
+ }
+ ppc_set_current_section(reldata_section);
+}
+
+/* pseudo-op: .rdata
+ behaviour: predefined read only data section
+ double word aligned
+ errors: None
+ warnings: None
+ initial: .section .rdata "dr3"
+ d - initialized data
+ r - readable
+ 3 - double word aligned (that would be 4 byte boundary)
+*/
+static void
+ppc_rdata(ignore)
+ int ignore;
+{
+ if (rdata_section == 0)
+ {
+ rdata_section = subseg_new (".rdata", 0);
+ bfd_set_section_flags (stdoutput, rdata_section,
+ (SEC_ALLOC | SEC_LOAD | SEC_RELOC
+ | SEC_READONLY | SEC_DATA ));
+
+ bfd_set_section_alignment (stdoutput, rdata_section, 2);
+ }
+ else
+ {
+ rdata_section = subseg_new (".rdata", 0);
+ }
+ ppc_set_current_section(rdata_section);
+}
+
+/* pseudo-op: .ualong
+ behaviour: much like .int, with the exception that no alignment is
+ performed.
+ FIXME: test the alignment statement
+ errors: None
+ warnings: None
+*/
+static void
+ppc_ualong(ignore)
+ int ignore;
+{
+ /* try for long */
+ cons ( 4 );
+}
+
+/* pseudo-op: .znop <symbol name>
+ behaviour: Issue a nop instruction
+ Issue a IMAGE_REL_PPC_IFGLUE relocation against it, using
+ the supplied symbol name.
+ errors: None
+ warnings: Missing symbol name
+*/
+static void
+ppc_znop(ignore)
+ int ignore;
+{
+ unsigned long insn;
+ const struct powerpc_opcode *opcode;
+ expressionS ex;
+ char *f;
+
+ symbolS *sym;
+
+ /* Strip out the symbol name */
+ char *symbol_name;
+ char c;
+ char *name;
+ unsigned int exp;
+ flagword flags;
+ asection *sec;
+
+ symbol_name = input_line_pointer;
+ c = get_symbol_end ();
+
+ name = xmalloc (input_line_pointer - symbol_name + 1);
+ strcpy (name, symbol_name);
+
+ sym = symbol_find_or_make (name);
+
+ *input_line_pointer = c;
+
+ SKIP_WHITESPACE ();
+
+ /* Look up the opcode in the hash table. */
+ opcode = (const struct powerpc_opcode *) hash_find (ppc_hash, "nop");
+
+ /* stick in the nop */
+ insn = opcode->opcode;
+
+ /* Write out the instruction. */
+ f = frag_more (4);
+ md_number_to_chars (f, insn, 4);
+ fix_new (frag_now,
+ f - frag_now->fr_literal,
+ 4,
+ sym,
+ 0,
+ 0,
+ BFD_RELOC_16_GOT_PCREL);
+
+}
+
+/* pseudo-op:
+ behaviour:
+ errors:
+ warnings:
+*/
+static void
+ppc_pe_comm(lcomm)
+ int lcomm;
+{
+ register char *name;
+ register char c;
+ register char *p;
+ offsetT temp;
+ register symbolS *symbolP;
+ offsetT align;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+
+ /* just after name is now '\0' */
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("Expected comma after symbol-name: rest of line ignored."));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ input_line_pointer++; /* skip ',' */
+ if ((temp = get_absolute_expression ()) < 0)
+ {
+ as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) temp);
+ ignore_rest_of_line ();
+ return;
+ }
+
+ if (! lcomm)
+ {
+ /* The third argument to .comm is the alignment. */
+ if (*input_line_pointer != ',')
+ align = 3;
+ else
+ {
+ ++input_line_pointer;
+ align = get_absolute_expression ();
+ if (align <= 0)
+ {
+ as_warn (_("ignoring bad alignment"));
+ align = 3;
+ }
+ }
+ }
+
+ *p = 0;
+ symbolP = symbol_find_or_make (name);
+
+ *p = c;
+ if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
+ {
+ as_bad (_("Ignoring attempt to re-define symbol `%s'."),
+ S_GET_NAME (symbolP));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ if (S_GET_VALUE (symbolP))
+ {
+ if (S_GET_VALUE (symbolP) != (valueT) temp)
+ as_bad (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."),
+ S_GET_NAME (symbolP),
+ (long) S_GET_VALUE (symbolP),
+ (long) temp);
+ }
+ else
+ {
+ S_SET_VALUE (symbolP, (valueT) temp);
+ S_SET_EXTERNAL (symbolP);
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/*
+ * implement the .section pseudo op:
+ * .section name {, "flags"}
+ * ^ ^
+ * | +--- optional flags: 'b' for bss
+ * | 'i' for info
+ * +-- section name 'l' for lib
+ * 'n' for noload
+ * 'o' for over
+ * 'w' for data
+ * 'd' (apparently m88k for data)
+ * 'x' for text
+ * But if the argument is not a quoted string, treat it as a
+ * subsegment number.
+ *
+ * FIXME: this is a copy of the section processing from obj-coff.c, with
+ * additions/changes for the moto-pas assembler support. There are three
+ * categories:
+ *
+ * FIXME: I just noticed this. This doesn't work at all really. It it
+ * setting bits that bfd probably neither understands or uses. The
+ * correct approach (?) will have to incorporate extra fields attached
+ * to the section to hold the system specific stuff. (krk)
+ *
+ * Section Contents:
+ * 'a' - unknown - referred to in documentation, but no definition supplied
+ * 'c' - section has code
+ * 'd' - section has initialized data
+ * 'u' - section has uninitialized data
+ * 'i' - section contains directives (info)
+ * 'n' - section can be discarded
+ * 'R' - remove section at link time
+ *
+ * Section Protection:
+ * 'r' - section is readable
+ * 'w' - section is writeable
+ * 'x' - section is executable
+ * 's' - section is sharable
+ *
+ * Section Alignment:
+ * '0' - align to byte boundary
+ * '1' - align to halfword undary
+ * '2' - align to word boundary
+ * '3' - align to doubleword boundary
+ * '4' - align to quadword boundary
+ * '5' - align to 32 byte boundary
+ * '6' - align to 64 byte boundary
+ *
+ */
+
+void
+ppc_pe_section (ignore)
+ int ignore;
+{
+ /* Strip out the section name */
+ char *section_name;
+ char c;
+ char *name;
+ unsigned int exp;
+ flagword flags;
+ segT sec;
+ int align;
+
+ section_name = input_line_pointer;
+ c = get_symbol_end ();
+
+ name = xmalloc (input_line_pointer - section_name + 1);
+ strcpy (name, section_name);
+
+ *input_line_pointer = c;
+
+ SKIP_WHITESPACE ();
+
+ exp = 0;
+ flags = SEC_NO_FLAGS;
+
+ if (strcmp (name, ".idata$2") == 0)
+ {
+ align = 0;
+ }
+ else if (strcmp (name, ".idata$3") == 0)
+ {
+ align = 0;
+ }
+ else if (strcmp (name, ".idata$4") == 0)
+ {
+ align = 2;
+ }
+ else if (strcmp (name, ".idata$5") == 0)
+ {
+ align = 2;
+ }
+ else if (strcmp (name, ".idata$6") == 0)
+ {
+ align = 1;
+ }
+ else
+ align = 4; /* default alignment to 16 byte boundary */
+
+ if (*input_line_pointer == ',')
+ {
+ ++input_line_pointer;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != '"')
+ exp = get_absolute_expression ();
+ else
+ {
+ ++input_line_pointer;
+ while (*input_line_pointer != '"'
+ && ! is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ switch (*input_line_pointer)
+ {
+ /* Section Contents */
+ case 'a': /* unknown */
+ as_bad (_("Unsupported section attribute -- 'a'"));
+ break;
+ case 'c': /* code section */
+ flags |= SEC_CODE;
+ break;
+ case 'd': /* section has initialized data */
+ flags |= SEC_DATA;
+ break;
+ case 'u': /* section has uninitialized data */
+ /* FIXME: This is IMAGE_SCN_CNT_UNINITIALIZED_DATA
+ in winnt.h */
+ flags |= SEC_ROM;
+ break;
+ case 'i': /* section contains directives (info) */
+ /* FIXME: This is IMAGE_SCN_LNK_INFO
+ in winnt.h */
+ flags |= SEC_HAS_CONTENTS;
+ break;
+ case 'n': /* section can be discarded */
+ flags &=~ SEC_LOAD;
+ break;
+ case 'R': /* Remove section at link time */
+ flags |= SEC_NEVER_LOAD;
+ break;
+
+ /* Section Protection */
+ case 'r': /* section is readable */
+ flags |= IMAGE_SCN_MEM_READ;
+ break;
+ case 'w': /* section is writeable */
+ flags |= IMAGE_SCN_MEM_WRITE;
+ break;
+ case 'x': /* section is executable */
+ flags |= IMAGE_SCN_MEM_EXECUTE;
+ break;
+ case 's': /* section is sharable */
+ flags |= IMAGE_SCN_MEM_SHARED;
+ break;
+
+ /* Section Alignment */
+ case '0': /* align to byte boundary */
+ flags |= IMAGE_SCN_ALIGN_1BYTES;
+ align = 0;
+ break;
+ case '1': /* align to halfword boundary */
+ flags |= IMAGE_SCN_ALIGN_2BYTES;
+ align = 1;
+ break;
+ case '2': /* align to word boundary */
+ flags |= IMAGE_SCN_ALIGN_4BYTES;
+ align = 2;
+ break;
+ case '3': /* align to doubleword boundary */
+ flags |= IMAGE_SCN_ALIGN_8BYTES;
+ align = 3;
+ break;
+ case '4': /* align to quadword boundary */
+ flags |= IMAGE_SCN_ALIGN_16BYTES;
+ align = 4;
+ break;
+ case '5': /* align to 32 byte boundary */
+ flags |= IMAGE_SCN_ALIGN_32BYTES;
+ align = 5;
+ break;
+ case '6': /* align to 64 byte boundary */
+ flags |= IMAGE_SCN_ALIGN_64BYTES;
+ align = 6;
+ break;
+
+ default:
+ as_bad(_("unknown section attribute '%c'"),
+ *input_line_pointer);
+ break;
+ }
+ ++input_line_pointer;
+ }
+ if (*input_line_pointer == '"')
+ ++input_line_pointer;
+ }
+ }
+
+ sec = subseg_new (name, (subsegT) exp);
+
+ ppc_set_current_section(sec);
+
+ if (flags != SEC_NO_FLAGS)
+ {
+ if (! bfd_set_section_flags (stdoutput, sec, flags))
+ as_bad (_("error setting flags for \"%s\": %s"),
+ bfd_section_name (stdoutput, sec),
+ bfd_errmsg (bfd_get_error ()));
+ }
+
+ bfd_set_section_alignment(stdoutput, sec, align);
+
+}
+
+static void
+ppc_pe_function (ignore)
+ int ignore;
+{
+ char *name;
+ char endc;
+ symbolS *ext_sym;
+
+ name = input_line_pointer;
+ endc = get_symbol_end ();
+
+ ext_sym = symbol_find_or_make (name);
+
+ *input_line_pointer = endc;
+
+ S_SET_DATA_TYPE (ext_sym, DT_FCN << N_BTSHFT);
+ SF_SET_FUNCTION (ext_sym);
+ SF_SET_PROCESS (ext_sym);
+ coff_add_linesym (ext_sym);
+
+ demand_empty_rest_of_line ();
+}
+
+static void
+ppc_pe_tocd (ignore)
+ int ignore;
+{
+ if (tocdata_section == 0)
+ {
+ tocdata_section = subseg_new (".tocd", 0);
+ /* FIXME: section flags won't work */
+ bfd_set_section_flags (stdoutput, tocdata_section,
+ (SEC_ALLOC | SEC_LOAD | SEC_RELOC
+ | SEC_READONLY | SEC_DATA ));
+
+ bfd_set_section_alignment (stdoutput, tocdata_section, 2);
+ }
+ else
+ {
+ rdata_section = subseg_new (".tocd", 0);
+ }
+
+ ppc_set_current_section(tocdata_section);
+
+ demand_empty_rest_of_line ();
+}
+
+/* Don't adjust TOC relocs to use the section symbol. */
+
+int
+ppc_pe_fix_adjustable (fix)
+ fixS *fix;
+{
+ return fix->fx_r_type != BFD_RELOC_PPC_TOC16;
+}
+
+#endif
+
+#ifdef OBJ_XCOFF
+
+/* XCOFF specific symbol and file handling. */
+
+/* Canonicalize the symbol name. We use the to force the suffix, if
+ any, to use square brackets, and to be in upper case. */
+
+char *
+ppc_canonicalize_symbol_name (name)
+ char *name;
+{
+ char *s;
+
+ if (ppc_stab_symbol)
+ return name;
+
+ for (s = name; *s != '\0' && *s != '{' && *s != '['; s++)
+ ;
+ if (*s != '\0')
+ {
+ char brac;
+
+ if (*s == '[')
+ brac = ']';
+ else
+ {
+ *s = '[';
+ brac = '}';
+ }
+
+ for (s++; *s != '\0' && *s != brac; s++)
+ if (islower (*s))
+ *s = toupper (*s);
+
+ if (*s == '\0' || s[1] != '\0')
+ as_bad (_("bad symbol suffix"));
+
+ *s = ']';
+ }
+
+ return name;
+}
+
+/* Set the class of a symbol based on the suffix, if any. This is
+ called whenever a new symbol is created. */
+
+void
+ppc_symbol_new_hook (sym)
+ symbolS *sym;
+{
+ const char *s;
+
+ sym->sy_tc.next = NULL;
+ sym->sy_tc.output = 0;
+ sym->sy_tc.class = -1;
+ sym->sy_tc.real_name = NULL;
+ sym->sy_tc.subseg = 0;
+ sym->sy_tc.align = 0;
+ sym->sy_tc.size = NULL;
+ sym->sy_tc.within = NULL;
+
+ if (ppc_stab_symbol)
+ return;
+
+ s = strchr (S_GET_NAME (sym), '[');
+ if (s == (const char *) NULL)
+ {
+ /* There is no suffix. */
+ return;
+ }
+
+ ++s;
+
+ switch (s[0])
+ {
+ case 'B':
+ if (strcmp (s, "BS]") == 0)
+ sym->sy_tc.class = XMC_BS;
+ break;
+ case 'D':
+ if (strcmp (s, "DB]") == 0)
+ sym->sy_tc.class = XMC_DB;
+ else if (strcmp (s, "DS]") == 0)
+ sym->sy_tc.class = XMC_DS;
+ break;
+ case 'G':
+ if (strcmp (s, "GL]") == 0)
+ sym->sy_tc.class = XMC_GL;
+ break;
+ case 'P':
+ if (strcmp (s, "PR]") == 0)
+ sym->sy_tc.class = XMC_PR;
+ break;
+ case 'R':
+ if (strcmp (s, "RO]") == 0)
+ sym->sy_tc.class = XMC_RO;
+ else if (strcmp (s, "RW]") == 0)
+ sym->sy_tc.class = XMC_RW;
+ break;
+ case 'S':
+ if (strcmp (s, "SV]") == 0)
+ sym->sy_tc.class = XMC_SV;
+ break;
+ case 'T':
+ if (strcmp (s, "TC]") == 0)
+ sym->sy_tc.class = XMC_TC;
+ else if (strcmp (s, "TI]") == 0)
+ sym->sy_tc.class = XMC_TI;
+ else if (strcmp (s, "TB]") == 0)
+ sym->sy_tc.class = XMC_TB;
+ else if (strcmp (s, "TC0]") == 0 || strcmp (s, "T0]") == 0)
+ sym->sy_tc.class = XMC_TC0;
+ break;
+ case 'U':
+ if (strcmp (s, "UA]") == 0)
+ sym->sy_tc.class = XMC_UA;
+ else if (strcmp (s, "UC]") == 0)
+ sym->sy_tc.class = XMC_UC;
+ break;
+ case 'X':
+ if (strcmp (s, "XO]") == 0)
+ sym->sy_tc.class = XMC_XO;
+ break;
+ }
+
+ if (sym->sy_tc.class == -1)
+ as_bad (_("Unrecognized symbol suffix"));
+}
+
+/* Set the class of a label based on where it is defined. This
+ handles symbols without suffixes. Also, move the symbol so that it
+ follows the csect symbol. */
+
+void
+ppc_frob_label (sym)
+ symbolS *sym;
+{
+ if (ppc_current_csect != (symbolS *) NULL)
+ {
+ if (sym->sy_tc.class == -1)
+ sym->sy_tc.class = ppc_current_csect->sy_tc.class;
+
+ symbol_remove (sym, &symbol_rootP, &symbol_lastP);
+ symbol_append (sym, ppc_current_csect->sy_tc.within, &symbol_rootP,
+ &symbol_lastP);
+ ppc_current_csect->sy_tc.within = sym;
+ }
+}
+
+/* This variable is set by ppc_frob_symbol if any absolute symbols are
+ seen. It tells ppc_adjust_symtab whether it needs to look through
+ the symbols. */
+
+static boolean ppc_saw_abs;
+
+/* Change the name of a symbol just before writing it out. Set the
+ real name if the .rename pseudo-op was used. Otherwise, remove any
+ class suffix. Return 1 if the symbol should not be included in the
+ symbol table. */
+
+int
+ppc_frob_symbol (sym)
+ symbolS *sym;
+{
+ static symbolS *ppc_last_function;
+ static symbolS *set_end;
+
+ /* Discard symbols that should not be included in the output symbol
+ table. */
+ if (! sym->sy_used_in_reloc
+ && ((sym->bsym->flags & BSF_SECTION_SYM) != 0
+ || (! S_IS_EXTERNAL (sym)
+ && ! sym->sy_tc.output
+ && S_GET_STORAGE_CLASS (sym) != C_FILE)))
+ return 1;
+
+ if (sym->sy_tc.real_name != (char *) NULL)
+ S_SET_NAME (sym, sym->sy_tc.real_name);
+ else
+ {
+ const char *name;
+ const char *s;
+
+ name = S_GET_NAME (sym);
+ s = strchr (name, '[');
+ if (s != (char *) NULL)
+ {
+ unsigned int len;
+ char *snew;
+
+ len = s - name;
+ snew = xmalloc (len + 1);
+ memcpy (snew, name, len);
+ snew[len] = '\0';
+
+ S_SET_NAME (sym, snew);
+ }
+ }
+
+ if (set_end != (symbolS *) NULL)
+ {
+ SA_SET_SYM_ENDNDX (set_end, sym);
+ set_end = NULL;
+ }
+
+ if (SF_GET_FUNCTION (sym))
+ {
+ if (ppc_last_function != (symbolS *) NULL)
+ as_bad (_("two .function pseudo-ops with no intervening .ef"));
+ ppc_last_function = sym;
+ if (sym->sy_tc.size != (symbolS *) NULL)
+ {
+ resolve_symbol_value (sym->sy_tc.size, 1);
+ SA_SET_SYM_FSIZE (sym, (long) S_GET_VALUE (sym->sy_tc.size));
+ }
+ }
+ else if (S_GET_STORAGE_CLASS (sym) == C_FCN
+ && strcmp (S_GET_NAME (sym), ".ef") == 0)
+ {
+ if (ppc_last_function == (symbolS *) NULL)
+ as_bad (_(".ef with no preceding .function"));
+ else
+ {
+ set_end = ppc_last_function;
+ ppc_last_function = NULL;
+
+ /* We don't have a C_EFCN symbol, but we need to force the
+ COFF backend to believe that it has seen one. */
+ coff_last_function = NULL;
+ }
+ }
+
+ if (! S_IS_EXTERNAL (sym)
+ && (sym->bsym->flags & BSF_SECTION_SYM) == 0
+ && S_GET_STORAGE_CLASS (sym) != C_FILE
+ && S_GET_STORAGE_CLASS (sym) != C_FCN
+ && S_GET_STORAGE_CLASS (sym) != C_BLOCK
+ && S_GET_STORAGE_CLASS (sym) != C_BSTAT
+ && S_GET_STORAGE_CLASS (sym) != C_ESTAT
+ && S_GET_STORAGE_CLASS (sym) != C_BINCL
+ && S_GET_STORAGE_CLASS (sym) != C_EINCL
+ && S_GET_SEGMENT (sym) != ppc_coff_debug_section)
+ S_SET_STORAGE_CLASS (sym, C_HIDEXT);
+
+ if (S_GET_STORAGE_CLASS (sym) == C_EXT
+ || S_GET_STORAGE_CLASS (sym) == C_HIDEXT)
+ {
+ int i;
+ union internal_auxent *a;
+
+ /* Create a csect aux. */
+ i = S_GET_NUMBER_AUXILIARY (sym);
+ S_SET_NUMBER_AUXILIARY (sym, i + 1);
+ a = &coffsymbol (sym->bsym)->native[i + 1].u.auxent;
+ if (sym->sy_tc.class == XMC_TC0)
+ {
+ /* This is the TOC table. */
+ know (strcmp (S_GET_NAME (sym), "TOC") == 0);
+ a->x_csect.x_scnlen.l = 0;
+ a->x_csect.x_smtyp = (2 << 3) | XTY_SD;
+ }
+ else if (sym->sy_tc.subseg != 0)
+ {
+ /* This is a csect symbol. x_scnlen is the size of the
+ csect. */
+ if (sym->sy_tc.next == (symbolS *) NULL)
+ a->x_csect.x_scnlen.l = (bfd_section_size (stdoutput,
+ S_GET_SEGMENT (sym))
+ - S_GET_VALUE (sym));
+ else
+ {
+ resolve_symbol_value (sym->sy_tc.next, 1);
+ a->x_csect.x_scnlen.l = (S_GET_VALUE (sym->sy_tc.next)
+ - S_GET_VALUE (sym));
+ }
+ a->x_csect.x_smtyp = (sym->sy_tc.align << 3) | XTY_SD;
+ }
+ else if (S_GET_SEGMENT (sym) == bss_section)
+ {
+ /* This is a common symbol. */
+ a->x_csect.x_scnlen.l = sym->sy_frag->fr_offset;
+ a->x_csect.x_smtyp = (sym->sy_tc.align << 3) | XTY_CM;
+ if (S_IS_EXTERNAL (sym))
+ sym->sy_tc.class = XMC_RW;
+ else
+ sym->sy_tc.class = XMC_BS;
+ }
+ else if (S_GET_SEGMENT (sym) == absolute_section)
+ {
+ /* This is an absolute symbol. The csect will be created by
+ ppc_adjust_symtab. */
+ ppc_saw_abs = true;
+ a->x_csect.x_smtyp = XTY_LD;
+ if (sym->sy_tc.class == -1)
+ sym->sy_tc.class = XMC_XO;
+ }
+ else if (! S_IS_DEFINED (sym))
+ {
+ /* This is an external symbol. */
+ a->x_csect.x_scnlen.l = 0;
+ a->x_csect.x_smtyp = XTY_ER;
+ }
+ else if (sym->sy_tc.class == XMC_TC)
+ {
+ symbolS *next;
+
+ /* This is a TOC definition. x_scnlen is the size of the
+ TOC entry. */
+ next = symbol_next (sym);
+ while (next->sy_tc.class == XMC_TC0)
+ next = symbol_next (next);
+ if (next == (symbolS *) NULL
+ || next->sy_tc.class != XMC_TC)
+ {
+ if (ppc_after_toc_frag == (fragS *) NULL)
+ a->x_csect.x_scnlen.l = (bfd_section_size (stdoutput,
+ data_section)
+ - S_GET_VALUE (sym));
+ else
+ a->x_csect.x_scnlen.l = (ppc_after_toc_frag->fr_address
+ - S_GET_VALUE (sym));
+ }
+ else
+ {
+ resolve_symbol_value (next, 1);
+ a->x_csect.x_scnlen.l = (S_GET_VALUE (next)
+ - S_GET_VALUE (sym));
+ }
+ a->x_csect.x_smtyp = (2 << 3) | XTY_SD;
+ }
+ else
+ {
+ symbolS *csect;
+
+ /* This is a normal symbol definition. x_scnlen is the
+ symbol index of the containing csect. */
+ if (S_GET_SEGMENT (sym) == text_section)
+ csect = ppc_text_csects;
+ else if (S_GET_SEGMENT (sym) == data_section)
+ csect = ppc_data_csects;
+ else
+ abort ();
+
+ /* Skip the initial dummy symbol. */
+ csect = csect->sy_tc.next;
+
+ if (csect == (symbolS *) NULL)
+ {
+ as_warn (_("warning: symbol %s has no csect"), S_GET_NAME (sym));
+ a->x_csect.x_scnlen.l = 0;
+ }
+ else
+ {
+ while (csect->sy_tc.next != (symbolS *) NULL)
+ {
+ resolve_symbol_value (csect->sy_tc.next, 1);
+ if (S_GET_VALUE (csect->sy_tc.next) > S_GET_VALUE (sym))
+ break;
+ csect = csect->sy_tc.next;
+ }
+
+ a->x_csect.x_scnlen.p = coffsymbol (csect->bsym)->native;
+ coffsymbol (sym->bsym)->native[i + 1].fix_scnlen = 1;
+ }
+ a->x_csect.x_smtyp = XTY_LD;
+ }
+
+ a->x_csect.x_parmhash = 0;
+ a->x_csect.x_snhash = 0;
+ if (sym->sy_tc.class == -1)
+ a->x_csect.x_smclas = XMC_PR;
+ else
+ a->x_csect.x_smclas = sym->sy_tc.class;
+ a->x_csect.x_stab = 0;
+ a->x_csect.x_snstab = 0;
+
+ /* Don't let the COFF backend resort these symbols. */
+ sym->bsym->flags |= BSF_NOT_AT_END;
+ }
+ else if (S_GET_STORAGE_CLASS (sym) == C_BSTAT)
+ {
+ /* We want the value to be the symbol index of the referenced
+ csect symbol. BFD will do that for us if we set the right
+ flags. */
+ S_SET_VALUE (sym,
+ (valueT) coffsymbol (sym->sy_tc.within->bsym)->native);
+ coffsymbol (sym->bsym)->native->fix_value = 1;
+ }
+ else if (S_GET_STORAGE_CLASS (sym) == C_STSYM)
+ {
+ symbolS *block;
+ symbolS *csect;
+
+ /* The value is the offset from the enclosing csect. */
+ block = sym->sy_tc.within;
+ csect = block->sy_tc.within;
+ resolve_symbol_value (csect, 1);
+ S_SET_VALUE (sym, S_GET_VALUE (sym) - S_GET_VALUE (csect));
+ }
+ else if (S_GET_STORAGE_CLASS (sym) == C_BINCL
+ || S_GET_STORAGE_CLASS (sym) == C_EINCL)
+ {
+ /* We want the value to be a file offset into the line numbers.
+ BFD will do that for us if we set the right flags. We have
+ already set the value correctly. */
+ coffsymbol (sym->bsym)->native->fix_line = 1;
+ }
+
+ return 0;
+}
+
+/* Adjust the symbol table. This creates csect symbols for all
+ absolute symbols. */
+
+void
+ppc_adjust_symtab ()
+{
+ symbolS *sym;
+
+ if (! ppc_saw_abs)
+ return;
+
+ for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
+ {
+ symbolS *csect;
+ int i;
+ union internal_auxent *a;
+
+ if (S_GET_SEGMENT (sym) != absolute_section)
+ continue;
+
+ csect = symbol_create (".abs[XO]", absolute_section,
+ S_GET_VALUE (sym), &zero_address_frag);
+ csect->bsym->value = S_GET_VALUE (sym);
+ S_SET_STORAGE_CLASS (csect, C_HIDEXT);
+ i = S_GET_NUMBER_AUXILIARY (csect);
+ S_SET_NUMBER_AUXILIARY (csect, i + 1);
+ a = &coffsymbol (csect->bsym)->native[i + 1].u.auxent;
+ a->x_csect.x_scnlen.l = 0;
+ a->x_csect.x_smtyp = XTY_SD;
+ a->x_csect.x_parmhash = 0;
+ a->x_csect.x_snhash = 0;
+ a->x_csect.x_smclas = XMC_XO;
+ a->x_csect.x_stab = 0;
+ a->x_csect.x_snstab = 0;
+
+ symbol_insert (csect, sym, &symbol_rootP, &symbol_lastP);
+
+ i = S_GET_NUMBER_AUXILIARY (sym);
+ a = &coffsymbol (sym->bsym)->native[i].u.auxent;
+ a->x_csect.x_scnlen.p = coffsymbol (csect->bsym)->native;
+ coffsymbol (sym->bsym)->native[i].fix_scnlen = 1;
+ }
+
+ ppc_saw_abs = false;
+}
+
+/* Set the VMA for a section. This is called on all the sections in
+ turn. */
+
+void
+ppc_frob_section (sec)
+ asection *sec;
+{
+ static bfd_size_type vma = 0;
+
+ bfd_set_section_vma (stdoutput, sec, vma);
+ vma += bfd_section_size (stdoutput, sec);
+}
+
+#endif /* OBJ_XCOFF */
+
+/* Turn a string in input_line_pointer into a floating point constant
+ of type type, and store the appropriate bytes in *litp. The number
+ of LITTLENUMS emitted is stored in *sizep . An error message is
+ returned, or NULL on OK. */
+
+char *
+md_atof (type, litp, sizep)
+ int type;
+ char *litp;
+ int *sizep;
+{
+ int prec;
+ LITTLENUM_TYPE words[4];
+ char *t;
+ int i;
+
+ switch (type)
+ {
+ case 'f':
+ prec = 2;
+ break;
+
+ case 'd':
+ prec = 4;
+ break;
+
+ default:
+ *sizep = 0;
+ return _("bad call to md_atof");
+ }
+
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+
+ *sizep = prec * 2;
+
+ if (target_big_endian)
+ {
+ for (i = 0; i < prec; i++)
+ {
+ md_number_to_chars (litp, (valueT) words[i], 2);
+ litp += 2;
+ }
+ }
+ else
+ {
+ for (i = prec - 1; i >= 0; i--)
+ {
+ md_number_to_chars (litp, (valueT) words[i], 2);
+ litp += 2;
+ }
+ }
+
+ return NULL;
+}
+
+/* Write a value out to the object file, using the appropriate
+ endianness. */
+
+void
+md_number_to_chars (buf, val, n)
+ char *buf;
+ valueT val;
+ int n;
+{
+ if (target_big_endian)
+ number_to_chars_bigendian (buf, val, n);
+ else
+ number_to_chars_littleendian (buf, val, n);
+}
+
+/* Align a section (I don't know why this is machine dependent). */
+
+valueT
+md_section_align (seg, addr)
+ asection *seg;
+ valueT addr;
+{
+ int align = bfd_get_section_alignment (stdoutput, seg);
+
+ return ((addr + (1 << align) - 1) & (-1 << align));
+}
+
+/* We don't have any form of relaxing. */
+
+int
+md_estimate_size_before_relax (fragp, seg)
+ fragS *fragp;
+ asection *seg;
+{
+ abort ();
+ return 0;
+}
+
+/* Convert a machine dependent frag. We never generate these. */
+
+void
+md_convert_frag (abfd, sec, fragp)
+ bfd *abfd;
+ asection *sec;
+ fragS *fragp;
+{
+ abort ();
+}
+
+/* We have no need to default values of symbols. */
+
+/*ARGSUSED*/
+symbolS *
+md_undefined_symbol (name)
+ char *name;
+{
+ return 0;
+}
+
+/* Functions concerning relocs. */
+
+/* The location from which a PC relative jump should be calculated,
+ given a PC relative reloc. */
+
+long
+md_pcrel_from_section (fixp, sec)
+ fixS *fixp;
+ segT sec;
+{
+ return fixp->fx_frag->fr_address + fixp->fx_where;
+}
+
+#ifdef OBJ_XCOFF
+
+/* This is called to see whether a fixup should be adjusted to use a
+ section symbol. We take the opportunity to change a fixup against
+ a symbol in the TOC subsegment into a reloc against the
+ corresponding .tc symbol. */
+
+int
+ppc_fix_adjustable (fix)
+ fixS *fix;
+{
+ valueT val;
+
+ resolve_symbol_value (fix->fx_addsy, 1);
+ val = S_GET_VALUE (fix->fx_addsy);
+ if (ppc_toc_csect != (symbolS *) NULL
+ && fix->fx_addsy != (symbolS *) NULL
+ && fix->fx_addsy != ppc_toc_csect
+ && S_GET_SEGMENT (fix->fx_addsy) == data_section
+ && val >= ppc_toc_frag->fr_address
+ && (ppc_after_toc_frag == (fragS *) NULL
+ || val < ppc_after_toc_frag->fr_address))
+ {
+ symbolS *sy;
+
+ for (sy = symbol_next (ppc_toc_csect);
+ sy != (symbolS *) NULL;
+ sy = symbol_next (sy))
+ {
+ if (sy->sy_tc.class == XMC_TC0)
+ continue;
+ if (sy->sy_tc.class != XMC_TC)
+ break;
+ resolve_symbol_value (sy, 1);
+ if (val == S_GET_VALUE (sy))
+ {
+ fix->fx_addsy = sy;
+ fix->fx_addnumber = val - ppc_toc_frag->fr_address;
+ return 0;
+ }
+ }
+
+ as_bad_where (fix->fx_file, fix->fx_line,
+ _("symbol in .toc does not match any .tc"));
+ }
+
+ /* Possibly adjust the reloc to be against the csect. */
+ if (fix->fx_addsy != (symbolS *) NULL
+ && fix->fx_addsy->sy_tc.subseg == 0
+ && fix->fx_addsy->sy_tc.class != XMC_TC0
+ && fix->fx_addsy->sy_tc.class != XMC_TC
+ && S_GET_SEGMENT (fix->fx_addsy) != bss_section
+ /* Don't adjust if this is a reloc in the toc section. */
+ && (S_GET_SEGMENT (fix->fx_addsy) != data_section
+ || ppc_toc_csect == NULL
+ || val < ppc_toc_frag->fr_address
+ || (ppc_after_toc_frag != NULL
+ && val >= ppc_after_toc_frag->fr_address)))
+ {
+ symbolS *csect;
+
+ if (S_GET_SEGMENT (fix->fx_addsy) == text_section)
+ csect = ppc_text_csects;
+ else if (S_GET_SEGMENT (fix->fx_addsy) == data_section)
+ csect = ppc_data_csects;
+ else
+ abort ();
+
+ /* Skip the initial dummy symbol. */
+ csect = csect->sy_tc.next;
+
+ if (csect != (symbolS *) NULL)
+ {
+ while (csect->sy_tc.next != (symbolS *) NULL
+ && (csect->sy_tc.next->sy_frag->fr_address
+ <= fix->fx_addsy->sy_frag->fr_address))
+ {
+ /* If the csect address equals the symbol value, then we
+ have to look through the full symbol table to see
+ whether this is the csect we want. Note that we will
+ only get here if the csect has zero length. */
+ if ((csect->sy_frag->fr_address
+ == fix->fx_addsy->sy_frag->fr_address)
+ && S_GET_VALUE (csect) == S_GET_VALUE (fix->fx_addsy))
+ {
+ symbolS *scan;
+
+ for (scan = csect->sy_next;
+ scan != NULL;
+ scan = scan->sy_next)
+ {
+ if (scan->sy_tc.subseg != 0)
+ break;
+ if (scan == fix->fx_addsy)
+ break;
+ }
+
+ /* If we found the symbol before the next csect
+ symbol, then this is the csect we want. */
+ if (scan == fix->fx_addsy)
+ break;
+ }
+
+ csect = csect->sy_tc.next;
+ }
+
+ fix->fx_offset += (S_GET_VALUE (fix->fx_addsy)
+ - csect->sy_frag->fr_address);
+ fix->fx_addsy = csect;
+ }
+ }
+
+ /* Adjust a reloc against a .lcomm symbol to be against the base
+ .lcomm. */
+ if (fix->fx_addsy != (symbolS *) NULL
+ && S_GET_SEGMENT (fix->fx_addsy) == bss_section
+ && ! S_IS_EXTERNAL (fix->fx_addsy))
+ {
+ resolve_symbol_value (fix->fx_addsy->sy_frag->fr_symbol, 1);
+ fix->fx_offset += (S_GET_VALUE (fix->fx_addsy)
+ - S_GET_VALUE (fix->fx_addsy->sy_frag->fr_symbol));
+ fix->fx_addsy = fix->fx_addsy->sy_frag->fr_symbol;
+ }
+
+ return 0;
+}
+
+/* A reloc from one csect to another must be kept. The assembler
+ will, of course, keep relocs between sections, and it will keep
+ absolute relocs, but we need to force it to keep PC relative relocs
+ between two csects in the same section. */
+
+int
+ppc_force_relocation (fix)
+ fixS *fix;
+{
+ /* At this point fix->fx_addsy should already have been converted to
+ a csect symbol. If the csect does not include the fragment, then
+ we need to force the relocation. */
+ if (fix->fx_pcrel
+ && fix->fx_addsy != NULL
+ && fix->fx_addsy->sy_tc.subseg != 0
+ && (fix->fx_addsy->sy_frag->fr_address > fix->fx_frag->fr_address
+ || (fix->fx_addsy->sy_tc.next != NULL
+ && (fix->fx_addsy->sy_tc.next->sy_frag->fr_address
+ <= fix->fx_frag->fr_address))))
+ return 1;
+
+ return 0;
+}
+
+#endif /* OBJ_XCOFF */
+
+/* See whether a symbol is in the TOC section. */
+
+static int
+ppc_is_toc_sym (sym)
+ symbolS *sym;
+{
+#ifdef OBJ_XCOFF
+ return sym->sy_tc.class == XMC_TC;
+#else
+ return strcmp (segment_name (S_GET_SEGMENT (sym)), ".got") == 0;
+#endif
+}
+
+/* Apply a fixup to the object code. This is called for all the
+ fixups we generated by the call to fix_new_exp, above. In the call
+ above we used a reloc code which was the largest legal reloc code
+ plus the operand index. Here we undo that to recover the operand
+ index. At this point all symbol values should be fully resolved,
+ and we attempt to completely resolve the reloc. If we can not do
+ that, we determine the correct reloc code and put it back in the
+ fixup. */
+
+int
+md_apply_fix3 (fixp, valuep, seg)
+ fixS *fixp;
+ valueT *valuep;
+ segT seg;
+{
+ valueT value;
+
+#ifdef OBJ_ELF
+ value = *valuep;
+ if (fixp->fx_addsy != NULL)
+ {
+ /* `*valuep' may contain the value of the symbol on which the reloc
+ will be based; we have to remove it. */
+ if (fixp->fx_addsy->sy_used_in_reloc
+ && S_GET_SEGMENT (fixp->fx_addsy) != absolute_section
+ && S_GET_SEGMENT (fixp->fx_addsy) != undefined_section
+ && ! bfd_is_com_section (S_GET_SEGMENT (fixp->fx_addsy)))
+ value -= S_GET_VALUE (fixp->fx_addsy);
+
+ /* FIXME: Why '+'? Better yet, what exactly is '*valuep'
+ supposed to be? I think this is related to various similar
+ FIXMEs in tc-i386.c and tc-sparc.c. */
+ if (fixp->fx_pcrel)
+ value += fixp->fx_frag->fr_address + fixp->fx_where;
+ }
+ else
+ {
+ fixp->fx_done = 1;
+ }
+#else
+ /* FIXME FIXME FIXME: The value we are passed in *valuep includes
+ the symbol values. Since we are using BFD_ASSEMBLER, if we are
+ doing this relocation the code in write.c is going to call
+ bfd_install_relocation, which is also going to use the symbol
+ value. That means that if the reloc is fully resolved we want to
+ use *valuep since bfd_install_relocation is not being used.
+ However, if the reloc is not fully resolved we do not want to use
+ *valuep, and must use fx_offset instead. However, if the reloc
+ is PC relative, we do want to use *valuep since it includes the
+ result of md_pcrel_from. This is confusing. */
+ if (fixp->fx_addsy == (symbolS *) NULL)
+ {
+ value = *valuep;
+ fixp->fx_done = 1;
+ }
+ else if (fixp->fx_pcrel)
+ value = *valuep;
+ else
+ {
+ value = fixp->fx_offset;
+ if (fixp->fx_subsy != (symbolS *) NULL)
+ {
+ if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
+ value -= S_GET_VALUE (fixp->fx_subsy);
+ else
+ {
+ /* We can't actually support subtracting a symbol. */
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("expression too complex"));
+ }
+ }
+ }
+#endif
+
+ if ((int) fixp->fx_r_type >= (int) BFD_RELOC_UNUSED)
+ {
+ int opindex;
+ const struct powerpc_operand *operand;
+ char *where;
+ unsigned long insn;
+
+ opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
+
+ operand = &powerpc_operands[opindex];
+
+#ifdef OBJ_XCOFF
+ /* It appears that an instruction like
+ l 9,LC..1(30)
+ when LC..1 is not a TOC symbol does not generate a reloc. It
+ uses the offset of LC..1 within its csect. However, .long
+ LC..1 will generate a reloc. I can't find any documentation
+ on how these cases are to be distinguished, so this is a wild
+ guess. These cases are generated by gcc -mminimal-toc. */
+ if ((operand->flags & PPC_OPERAND_PARENS) != 0
+ && operand->bits == 16
+ && operand->shift == 0
+ && operand->insert == NULL
+ && fixp->fx_addsy != NULL
+ && fixp->fx_addsy->sy_tc.subseg != 0
+ && fixp->fx_addsy->sy_tc.class != XMC_TC
+ && fixp->fx_addsy->sy_tc.class != XMC_TC0
+ && S_GET_SEGMENT (fixp->fx_addsy) != bss_section)
+ {
+ value = fixp->fx_offset;
+ fixp->fx_done = 1;
+ }
+#endif
+
+ /* Fetch the instruction, insert the fully resolved operand
+ value, and stuff the instruction back again. */
+ where = fixp->fx_frag->fr_literal + fixp->fx_where;
+ if (target_big_endian)
+ insn = bfd_getb32 ((unsigned char *) where);
+ else
+ insn = bfd_getl32 ((unsigned char *) where);
+ insn = ppc_insert_operand (insn, operand, (offsetT) value,
+ fixp->fx_file, fixp->fx_line);
+ if (target_big_endian)
+ bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
+ else
+ bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
+
+ if (fixp->fx_done)
+ {
+ /* Nothing else to do here. */
+ return 1;
+ }
+
+ /* Determine a BFD reloc value based on the operand information.
+ We are only prepared to turn a few of the operands into
+ relocs.
+ FIXME: We need to handle the DS field at the very least.
+ FIXME: Selecting the reloc type is a bit haphazard; perhaps
+ there should be a new field in the operand table. */
+ if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
+ && operand->bits == 26
+ && operand->shift == 0)
+ fixp->fx_r_type = BFD_RELOC_PPC_B26;
+ else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
+ && operand->bits == 16
+ && operand->shift == 0)
+ fixp->fx_r_type = BFD_RELOC_PPC_B16;
+ else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0
+ && operand->bits == 26
+ && operand->shift == 0)
+ fixp->fx_r_type = BFD_RELOC_PPC_BA26;
+ else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0
+ && operand->bits == 16
+ && operand->shift == 0)
+ fixp->fx_r_type = BFD_RELOC_PPC_BA16;
+ else if ((operand->flags & PPC_OPERAND_PARENS) != 0
+ && operand->bits == 16
+ && operand->shift == 0
+ && operand->insert == NULL
+ && fixp->fx_addsy != NULL
+ && ppc_is_toc_sym (fixp->fx_addsy))
+ {
+ fixp->fx_size = 2;
+ if (target_big_endian)
+ fixp->fx_where += 2;
+ fixp->fx_r_type = BFD_RELOC_PPC_TOC16;
+ }
+ else
+ {
+ char *sfile;
+ unsigned int sline;
+
+ /* Use expr_symbol_where to see if this is an expression
+ symbol. */
+ if (expr_symbol_where (fixp->fx_addsy, &sfile, &sline))
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("unresolved expression that must be resolved"));
+ else
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("unsupported relocation type"));
+ fixp->fx_done = 1;
+ return 1;
+ }
+ }
+ else
+ {
+#ifdef OBJ_ELF
+ ppc_elf_validate_fix (fixp, seg);
+#endif
+ switch (fixp->fx_r_type)
+ {
+ case BFD_RELOC_32:
+ case BFD_RELOC_CTOR:
+ if (fixp->fx_pcrel)
+ fixp->fx_r_type = BFD_RELOC_32_PCREL;
+ /* fall through */
+
+ case BFD_RELOC_RVA:
+ case BFD_RELOC_32_PCREL:
+ case BFD_RELOC_32_BASEREL:
+ case BFD_RELOC_PPC_EMB_NADDR32:
+ md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
+ value, 4);
+ break;
+
+ case BFD_RELOC_LO16:
+ case BFD_RELOC_16:
+ case BFD_RELOC_GPREL16:
+ case BFD_RELOC_16_GOT_PCREL:
+ case BFD_RELOC_16_GOTOFF:
+ case BFD_RELOC_LO16_GOTOFF:
+ case BFD_RELOC_HI16_GOTOFF:
+ case BFD_RELOC_HI16_S_GOTOFF:
+ case BFD_RELOC_LO16_BASEREL:
+ case BFD_RELOC_HI16_BASEREL:
+ case BFD_RELOC_HI16_S_BASEREL:
+ case BFD_RELOC_PPC_EMB_NADDR16:
+ case BFD_RELOC_PPC_EMB_NADDR16_LO:
+ case BFD_RELOC_PPC_EMB_NADDR16_HI:
+ case BFD_RELOC_PPC_EMB_NADDR16_HA:
+ case BFD_RELOC_PPC_EMB_SDAI16:
+ case BFD_RELOC_PPC_EMB_SDA2REL:
+ case BFD_RELOC_PPC_EMB_SDA2I16:
+ case BFD_RELOC_PPC_EMB_RELSEC16:
+ case BFD_RELOC_PPC_EMB_RELST_LO:
+ case BFD_RELOC_PPC_EMB_RELST_HI:
+ case BFD_RELOC_PPC_EMB_RELST_HA:
+ case BFD_RELOC_PPC_EMB_RELSDA:
+ case BFD_RELOC_PPC_TOC16:
+ if (fixp->fx_pcrel)
+ {
+ if (fixp->fx_addsy != NULL)
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("cannot emit PC relative %s relocation against %s"),
+ bfd_get_reloc_code_name (fixp->fx_r_type),
+ S_GET_NAME (fixp->fx_addsy));
+ else
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("cannot emit PC relative %s relocation"),
+ bfd_get_reloc_code_name (fixp->fx_r_type));
+ }
+
+ md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
+ value, 2);
+ break;
+
+ /* This case happens when you write, for example,
+ lis %r3,(L1-L2)@ha
+ where L1 and L2 are defined later. */
+ case BFD_RELOC_HI16:
+ if (fixp->fx_pcrel)
+ abort ();
+ md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
+ value >> 16, 2);
+ break;
+ case BFD_RELOC_HI16_S:
+ if (fixp->fx_pcrel)
+ abort ();
+ md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
+ value + 0x8000 >> 16, 2);
+ break;
+
+ /* Because SDA21 modifies the register field, the size is set to 4
+ bytes, rather than 2, so offset it here appropriately */
+ case BFD_RELOC_PPC_EMB_SDA21:
+ if (fixp->fx_pcrel)
+ abort ();
+
+ md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where
+ + ((target_big_endian) ? 2 : 0),
+ value, 2);
+ break;
+
+ case BFD_RELOC_8:
+ if (fixp->fx_pcrel)
+ abort ();
+
+ md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
+ value, 1);
+ break;
+
+ case BFD_RELOC_24_PLT_PCREL:
+ case BFD_RELOC_PPC_LOCAL24PC:
+ if (!fixp->fx_pcrel && !fixp->fx_done)
+ abort ();
+
+ if (fixp->fx_done)
+ {
+ char *where;
+ unsigned long insn;
+
+ /* Fetch the instruction, insert the fully resolved operand
+ value, and stuff the instruction back again. */
+ where = fixp->fx_frag->fr_literal + fixp->fx_where;
+ if (target_big_endian)
+ insn = bfd_getb32 ((unsigned char *) where);
+ else
+ insn = bfd_getl32 ((unsigned char *) where);
+ if ((value & 3) != 0)
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("must branch to an address a multiple of 4"));
+ if ((offsetT) value < -0x40000000
+ || (offsetT) value >= 0x40000000)
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("@local or @plt branch destination is too far away, %ld bytes"),
+ value);
+ insn = insn | (value & 0x03fffffc);
+ if (target_big_endian)
+ bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
+ else
+ bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
+ }
+ break;
+
+ case BFD_RELOC_VTABLE_INHERIT:
+ fixp->fx_done = 0;
+ if (fixp->fx_addsy
+ && !S_IS_DEFINED (fixp->fx_addsy)
+ && !S_IS_WEAK (fixp->fx_addsy))
+ S_SET_WEAK (fixp->fx_addsy);
+ break;
+
+ case BFD_RELOC_VTABLE_ENTRY:
+ fixp->fx_done = 0;
+ break;
+
+ default:
+ fprintf(stderr,
+ _("Gas failure, reloc value %d\n"), fixp->fx_r_type);
+ fflush(stderr);
+ abort ();
+ }
+ }
+
+#ifdef OBJ_ELF
+ fixp->fx_addnumber = value;
+#else
+ if (fixp->fx_r_type != BFD_RELOC_PPC_TOC16)
+ fixp->fx_addnumber = 0;
+ else
+ {
+#ifdef TE_PE
+ fixp->fx_addnumber = 0;
+#else
+ /* We want to use the offset within the data segment of the
+ symbol, not the actual VMA of the symbol. */
+ fixp->fx_addnumber =
+ - bfd_get_section_vma (stdoutput, S_GET_SEGMENT (fixp->fx_addsy));
+#endif
+ }
+#endif
+
+ return 1;
+}
+
+/* Generate a reloc for a fixup. */
+
+arelent *
+tc_gen_reloc (seg, fixp)
+ asection *seg;
+ fixS *fixp;
+{
+ arelent *reloc;
+
+ reloc = (arelent *) xmalloc (sizeof (arelent));
+
+ reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+ reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
+ if (reloc->howto == (reloc_howto_type *) NULL)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("reloc %d not supported by object file format"), (int)fixp->fx_r_type);
+ return NULL;
+ }
+ reloc->addend = fixp->fx_addnumber;
+
+ return reloc;
+}
diff --git a/gas/config/tc-ppc.h b/gas/config/tc-ppc.h
new file mode 100644
index 0000000000..0871d130d6
--- /dev/null
+++ b/gas/config/tc-ppc.h
@@ -0,0 +1,276 @@
+/* tc-ppc.h -- Header file for tc-ppc.c.
+ Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor, Cygnus Support.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#define TC_PPC
+
+#ifdef ANSI_PROTOTYPES
+struct fix;
+#endif
+
+/* Set the endianness we are using. Default to big endian. */
+#ifndef TARGET_BYTES_BIG_ENDIAN
+#define TARGET_BYTES_BIG_ENDIAN 1
+#endif
+
+#ifndef BFD_ASSEMBLER
+ #error PowerPC support requires BFD_ASSEMBLER
+#endif
+
+/* If OBJ_COFF is defined, and TE_PE is not defined, we are assembling
+ XCOFF for AIX or PowerMac. If TE_PE is defined, we are assembling
+ COFF for Windows NT. */
+
+#ifdef OBJ_COFF
+#ifndef TE_PE
+#define OBJ_XCOFF
+#endif
+#endif
+
+/* The target BFD architecture. */
+#define TARGET_ARCH (ppc_arch ())
+extern enum bfd_architecture ppc_arch PARAMS ((void));
+
+/* Whether or not the target is big endian */
+extern int target_big_endian;
+
+/* The target BFD format. */
+#ifdef OBJ_COFF
+#ifdef TE_PE
+#define TARGET_FORMAT (target_big_endian ? "pe-powerpc" : "pe-powerpcle")
+#else
+#define TARGET_FORMAT "aixcoff-rs6000"
+#endif
+#endif
+
+/* PowerMac has a BFD slightly different from AIX's. */
+#ifdef TE_POWERMAC
+#ifdef TARGET_FORMAT
+#undef TARGET_FORMAT
+#endif
+#define TARGET_FORMAT "xcoff-powermac"
+#endif
+
+#ifdef OBJ_ELF
+#define TARGET_FORMAT (target_big_endian ? "elf32-powerpc" : "elf32-powerpcle")
+#endif
+
+/* Permit temporary numeric labels. */
+#define LOCAL_LABELS_FB 1
+
+/* $ is used to refer to the current location. */
+#define DOLLAR_DOT
+
+/* Strings do not use backslash escapes under COFF. */
+#ifdef OBJ_COFF
+#define NO_STRING_ESCAPES
+#endif
+
+#ifdef OBJ_ELF
+#define DIFF_EXPR_OK /* foo-. gets turned into PC relative relocs */
+#endif
+
+#if TARGET_BYTES_BIG_ENDIAN
+#define PPC_BIG_ENDIAN 1
+#else
+#define PPC_BIG_ENDIAN 0
+#endif
+
+/* We don't need to handle .word strangely. */
+#define WORKING_DOT_WORD
+
+/* We set the fx_done field appropriately in md_apply_fix. */
+#define TC_HANDLES_FX_DONE
+
+#ifdef TE_PE
+
+/* Question marks are permitted in symbol names. */
+#define LEX_QM 1
+
+/* Don't adjust TOC relocs. */
+#define tc_fix_adjustable(fixp) ppc_pe_fix_adjustable (fixp)
+extern int ppc_pe_fix_adjustable PARAMS ((struct fix *));
+
+#endif
+
+#ifdef OBJ_XCOFF
+
+/* Declarations needed when generating XCOFF code. XCOFF is an
+ extension of COFF, used only on the RS/6000. Rather than create an
+ obj-xcoff, we just use obj-coff, and handle the extensions here in
+ tc-ppc. */
+
+/* We need to keep some information for symbols. */
+struct ppc_tc_sy
+{
+ /* We keep a few linked lists of symbols. */
+ struct symbol *next;
+ /* Non-zero if the symbol should be output. The RS/6000 assembler
+ only outputs symbols that are external or are mentioned in a
+ .globl or .lglobl statement. */
+ int output;
+ /* The symbol class. */
+ int class;
+ /* The real name, if the symbol was renamed. */
+ char *real_name;
+ /* For a csect symbol, the subsegment we are using. This is zero
+ for symbols that are not csects. */
+ subsegT subseg;
+ /* For a csect or common symbol, the alignment to use. */
+ int align;
+ /* For a function symbol, a symbol whose value is the size. The
+ field is NULL if there is no size. */
+ struct symbol *size;
+ /* For a csect symbol, the last symbol which has been defined in
+ this csect, or NULL if none have been defined so far. For a .bs
+ symbol, the referenced csect symbol. */
+ struct symbol *within;
+};
+
+#define TC_SYMFIELD_TYPE struct ppc_tc_sy
+
+/* We need an additional auxent for function symbols. */
+#define OBJ_COFF_MAX_AUXENTRIES 2
+
+/* Square and curly brackets are permitted in symbol names. */
+#define LEX_BR 3
+
+/* Canonicalize the symbol name. */
+#define tc_canonicalize_symbol_name(name) ppc_canonicalize_symbol_name (name)
+extern char *ppc_canonicalize_symbol_name PARAMS ((char *));
+
+/* Get the symbol class from the name. */
+#define tc_symbol_new_hook(sym) ppc_symbol_new_hook (sym)
+extern void ppc_symbol_new_hook PARAMS ((struct symbol *));
+
+/* Set the symbol class of a label based on the csect. */
+#define tc_frob_label(sym) ppc_frob_label (sym)
+extern void ppc_frob_label PARAMS ((struct symbol *));
+
+/* TOC relocs requires special handling. */
+#define tc_fix_adjustable(fixp) ppc_fix_adjustable (fixp)
+extern int ppc_fix_adjustable PARAMS ((struct fix *));
+
+/* A relocation from one csect to another must be kept. */
+#define TC_FORCE_RELOCATION(FIXP) ppc_force_relocation (FIXP)
+extern int ppc_force_relocation PARAMS ((struct fix *));
+
+/* We need to set the section VMA. */
+#define tc_frob_section(sec) ppc_frob_section (sec)
+extern void ppc_frob_section PARAMS ((asection *));
+
+/* Finish up the symbol. */
+#define tc_frob_symbol(sym, punt) punt = ppc_frob_symbol (sym)
+extern int ppc_frob_symbol PARAMS ((struct symbol *));
+
+/* Finish up the entire symtab. */
+#define tc_adjust_symtab() ppc_adjust_symtab ()
+extern void ppc_adjust_symtab PARAMS ((void));
+
+/* Niclas Andersson <nican@ida.liu.se> says this is needed. */
+#define SUB_SEGMENT_ALIGN(SEG) 2
+
+#endif /* OBJ_XCOFF */
+
+#ifdef OBJ_ELF
+
+/* Branch prediction relocations must force relocation, as must
+ the vtable description relocs. */
+#define TC_FORCE_RELOCATION(FIXP) \
+((FIXP)->fx_r_type == BFD_RELOC_PPC_B16_BRTAKEN \
+ || (FIXP)->fx_r_type == BFD_RELOC_PPC_B16_BRNTAKEN \
+ || (FIXP)->fx_r_type == BFD_RELOC_PPC_BA16_BRTAKEN \
+ || (FIXP)->fx_r_type == BFD_RELOC_PPC_BA16_BRNTAKEN \
+ || (FIXP)->fx_r_type == BFD_RELOC_VTABLE_INHERIT \
+ || (FIXP)->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+
+#define TC_FORCE_RELOCATION_SECTION(FIXP,SEC) \
+(TC_FORCE_RELOCATION (FIXP) \
+ || ((FIXP)->fx_addsy && !(FIXP)->fx_subsy && (FIXP)->fx_addsy->bsym \
+ && (FIXP)->fx_addsy->bsym->section != SEC))
+
+/* Support for SHF_EXCLUDE and SHT_ORDERED */
+extern int ppc_section_letter PARAMS ((int, char **));
+extern int ppc_section_type PARAMS ((char **));
+extern int ppc_section_word PARAMS ((char **));
+extern int ppc_section_flags PARAMS ((int, int, int));
+
+#define md_elf_section_letter(LETTER, PTR_MSG) ppc_section_letter (LETTER, PTR_MSG)
+#define md_elf_section_type(PTR_STR) ppc_section_type (PTR_STR)
+#define md_elf_section_word(PTR_STR) ppc_section_word (PTR_STR)
+#define md_elf_section_flags(FLAGS, ATTR, TYPE) ppc_section_flags (FLAGS, ATTR, TYPE)
+
+/* Add extra PPC sections -- Note, for now, make .sbss2 and .PPC.EMB.sbss0 a
+ normal section, and not a bss section so that the linker doesn't crater
+ when trying to make more than 2 sections. */
+#define ELF_TC_SPECIAL_SECTIONS \
+ { ".tags", SHT_ORDERED, SHF_ALLOC }, \
+ { ".sdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, \
+ { ".sbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, \
+ { ".sdata2", SHT_PROGBITS, SHF_ALLOC }, \
+ { ".sbss2", SHT_PROGBITS, SHF_ALLOC }, \
+ { ".PPC.EMB.sdata0", SHT_PROGBITS, SHF_ALLOC }, \
+ { ".PPC.EMB.sbss0", SHT_PROGBITS, SHF_ALLOC },
+
+#define tc_comment_chars ppc_comment_chars
+extern const char *ppc_comment_chars;
+
+/* Keep relocations relative to the GOT, or non-PC relative. */
+#define tc_fix_adjustable(FIX) \
+ ((FIX)->fx_r_type != BFD_RELOC_16_GOTOFF \
+ && (FIX)->fx_r_type != BFD_RELOC_LO16_GOTOFF \
+ && (FIX)->fx_r_type != BFD_RELOC_HI16_GOTOFF \
+ && (FIX)->fx_r_type != BFD_RELOC_HI16_S_GOTOFF \
+ && (FIX)->fx_r_type != BFD_RELOC_GPREL16 \
+ && (FIX)->fx_r_type != BFD_RELOC_VTABLE_INHERIT \
+ && (FIX)->fx_r_type != BFD_RELOC_VTABLE_ENTRY \
+ && ! S_IS_EXTERNAL ((FIX)->fx_addsy) \
+ && ! S_IS_WEAK ((FIX)->fx_addsy) \
+ && ((FIX)->fx_pcrel \
+ || ((FIX)->fx_subsy != NULL \
+ && (S_GET_SEGMENT ((FIX)->fx_subsy) \
+ == S_GET_SEGMENT ((FIX)->fx_addsy))) \
+ || strchr (S_GET_NAME ((FIX)->fx_addsy), '\001') != NULL \
+ || strchr (S_GET_NAME ((FIX)->fx_addsy), '\002') != NULL))
+
+/* We must never ever try to resolve references to externally visible
+ symbols in the assembler, because the .o file might go into a shared
+ library, and some other shared library might override that symbol. */
+#define TC_RELOC_RTSYM_LOC_FIXUP(FIX) \
+ ((FIX)->fx_addsy == NULL \
+ || (! S_IS_EXTERNAL ((FIX)->fx_addsy) \
+ && ! S_IS_WEAK ((FIX)->fx_addsy) \
+ && S_IS_DEFINED ((FIX)->fx_addsy) \
+ && ! S_IS_COMMON ((FIX)->fx_addsy)))
+
+#endif /* OBJ_ELF */
+
+/* call md_apply_fix3 with segment instead of md_apply_fix */
+#define MD_APPLY_FIX3
+
+/* call md_pcrel_from_section, not md_pcrel_from */
+#define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from_section(FIXP, SEC)
+extern long md_pcrel_from_section PARAMS ((struct fix *, segT));
+
+#define md_parse_name(name, exp) ppc_parse_name (name, exp)
+extern int ppc_parse_name PARAMS ((const char *, struct expressionS *));
+
+#define md_operand(x)
+
diff --git a/gas/config/tc-sh.c b/gas/config/tc-sh.c
new file mode 100644
index 0000000000..6d8ca81643
--- /dev/null
+++ b/gas/config/tc-sh.c
@@ -0,0 +1,2425 @@
+/* tc-sh.c -- Assemble code for the Hitachi Super-H
+ Copyright (C) 1993, 94, 95, 96, 97, 1998 Free Software Foundation.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/*
+ Written By Steve Chamberlain
+ sac@cygnus.com
+ */
+
+#include <stdio.h>
+#include "as.h"
+#include "bfd.h"
+#include "subsegs.h"
+#define DEFINE_TABLE
+#include "opcodes/sh-opc.h"
+#include <ctype.h>
+const char comment_chars[] = "!";
+const char line_separator_chars[] = ";";
+const char line_comment_chars[] = "!#";
+
+static void s_uses PARAMS ((int));
+
+static void sh_count_relocs PARAMS ((bfd *, segT, PTR));
+static void sh_frob_section PARAMS ((bfd *, segT, PTR));
+
+/* This table describes all the machine specific pseudo-ops the assembler
+ has to support. The fields are:
+ pseudo-op name without dot
+ function to call to execute this pseudo-op
+ Integer arg to pass to the function
+ */
+
+void cons ();
+void s_align_bytes ();
+static void s_uacons PARAMS ((int));
+
+int shl = 0;
+
+static void
+little (ignore)
+ int ignore;
+{
+ shl = 1;
+ target_big_endian = 0;
+}
+
+const pseudo_typeS md_pseudo_table[] =
+{
+ {"int", cons, 4},
+ {"word", cons, 2},
+ {"form", listing_psize, 0},
+ {"little", little, 0},
+ {"heading", listing_title, 0},
+ {"import", s_ignore, 0},
+ {"page", listing_eject, 0},
+ {"program", s_ignore, 0},
+ {"uses", s_uses, 0},
+ {"uaword", s_uacons, 2},
+ {"ualong", s_uacons, 4},
+ {0, 0, 0}
+};
+
+/*int md_reloc_size; */
+
+int sh_relax; /* set if -relax seen */
+
+/* Whether -small was seen. */
+
+int sh_small;
+
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* As in 0f12.456 */
+/* or 0d1.2345e12 */
+const char FLT_CHARS[] = "rRsSfFdDxXpP";
+
+#define C(a,b) ENCODE_RELAX(a,b)
+
+#define JREG 14 /* Register used as a temp when relaxing */
+#define ENCODE_RELAX(what,length) (((what) << 4) + (length))
+#define GET_WHAT(x) ((x>>4))
+
+/* These are the three types of relaxable instrction */
+#define COND_JUMP 1
+#define COND_JUMP_DELAY 2
+#define UNCOND_JUMP 3
+#define END 4
+
+#define UNDEF_DISP 0
+#define COND8 1
+#define COND12 2
+#define COND32 3
+#define UNCOND12 1
+#define UNCOND32 2
+#define UNDEF_WORD_DISP 4
+
+#define UNCOND12 1
+#define UNCOND32 2
+
+/* Branch displacements are from the address of the branch plus
+ four, thus all minimum and maximum values have 4 added to them. */
+#define COND8_F 258
+#define COND8_M -252
+#define COND8_LENGTH 2
+
+/* There is one extra instruction before the branch, so we must add
+ two more bytes to account for it. */
+#define COND12_F 4100
+#define COND12_M -4090
+#define COND12_LENGTH 6
+
+#define COND12_DELAY_LENGTH 4
+
+/* ??? The minimum and maximum values are wrong, but this does not matter
+ since this relocation type is not supported yet. */
+#define COND32_F (1<<30)
+#define COND32_M -(1<<30)
+#define COND32_LENGTH 14
+
+#define UNCOND12_F 4098
+#define UNCOND12_M -4092
+#define UNCOND12_LENGTH 2
+
+/* ??? The minimum and maximum values are wrong, but this does not matter
+ since this relocation type is not supported yet. */
+#define UNCOND32_F (1<<30)
+#define UNCOND32_M -(1<<30)
+#define UNCOND32_LENGTH 14
+
+const relax_typeS md_relax_table[C (END, 0)] = {
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { 0 },
+ /* C (COND_JUMP, COND8) */
+ { COND8_F, COND8_M, COND8_LENGTH, C (COND_JUMP, COND12) },
+ /* C (COND_JUMP, COND12) */
+ { COND12_F, COND12_M, COND12_LENGTH, C (COND_JUMP, COND32), },
+ /* C (COND_JUMP, COND32) */
+ { COND32_F, COND32_M, COND32_LENGTH, 0, },
+ { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { 0 },
+ /* C (COND_JUMP_DELAY, COND8) */
+ { COND8_F, COND8_M, COND8_LENGTH, C (COND_JUMP_DELAY, COND12) },
+ /* C (COND_JUMP_DELAY, COND12) */
+ { COND12_F, COND12_M, COND12_DELAY_LENGTH, C (COND_JUMP_DELAY, COND32), },
+ /* C (COND_JUMP_DELAY, COND32) */
+ { COND32_F, COND32_M, COND32_LENGTH, 0, },
+ { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { 0 },
+ /* C (UNCOND_JUMP, UNCOND12) */
+ { UNCOND12_F, UNCOND12_M, UNCOND12_LENGTH, C (UNCOND_JUMP, UNCOND32), },
+ /* C (UNCOND_JUMP, UNCOND32) */
+ { UNCOND32_F, UNCOND32_M, UNCOND32_LENGTH, 0, },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+};
+
+static struct hash_control *opcode_hash_control; /* Opcode mnemonics */
+
+/*
+ This function is called once, at assembler startup time. This should
+ set up all the tables, etc that the MD part of the assembler needs
+ */
+
+void
+md_begin ()
+{
+ sh_opcode_info *opcode;
+ char *prev_name = "";
+
+ if (! shl)
+ target_big_endian = 1;
+
+ opcode_hash_control = hash_new ();
+
+ /* Insert unique names into hash table */
+ for (opcode = sh_table; opcode->name; opcode++)
+ {
+ if (strcmp (prev_name, opcode->name))
+ {
+ prev_name = opcode->name;
+ hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
+ }
+ else
+ {
+ /* Make all the opcodes with the same name point to the same
+ string */
+ opcode->name = prev_name;
+ }
+ }
+}
+
+static int reg_m;
+static int reg_n;
+static int reg_b;
+
+static expressionS immediate; /* absolute expression */
+
+typedef struct
+ {
+ sh_arg_type type;
+ int reg;
+ }
+
+sh_operand_info;
+
+/* try and parse a reg name, returns number of chars consumed */
+static int
+parse_reg (src, mode, reg)
+ char *src;
+ int *mode;
+ int *reg;
+{
+ /* We use !isalnum for the next character after the register name, to
+ make sure that we won't accidentally recognize a symbol name such as
+ 'sram' as being a reference to the register 'sr'. */
+
+ if (src[0] == 'r')
+ {
+ if (src[1] >= '0' && src[1] <= '7' && strncmp(&src[2], "_bank", 5) == 0
+ && ! isalnum ((unsigned char) src[7]))
+ {
+ *mode = A_REG_B;
+ *reg = (src[1] - '0');
+ return 7;
+ }
+ }
+
+ if (src[0] == 'r')
+ {
+ if (src[1] == '1')
+ {
+ if (src[2] >= '0' && src[2] <= '5'
+ && ! isalnum ((unsigned char) src[3]))
+ {
+ *mode = A_REG_N;
+ *reg = 10 + src[2] - '0';
+ return 3;
+ }
+ }
+ if (src[1] >= '0' && src[1] <= '9'
+ && ! isalnum ((unsigned char) src[2]))
+ {
+ *mode = A_REG_N;
+ *reg = (src[1] - '0');
+ return 2;
+ }
+ }
+
+ if (src[0] == 's'
+ && src[1] == 's'
+ && src[2] == 'r' && ! isalnum ((unsigned char) src[3]))
+ {
+ *mode = A_SSR;
+ return 3;
+ }
+
+ if (src[0] == 's' && src[1] == 'p' && src[2] == 'c'
+ && ! isalnum ((unsigned char) src[3]))
+ {
+ *mode = A_SPC;
+ return 3;
+ }
+
+ if (src[0] == 's' && src[1] == 'g' && src[2] == 'r'
+ && ! isalnum ((unsigned char) src[3]))
+ {
+ *mode = A_SGR;
+ return 3;
+ }
+
+ if (src[0] == 'd' && src[1] == 'b' && src[2] == 'r'
+ && ! isalnum ((unsigned char) src[3]))
+ {
+ *mode = A_DBR;
+ return 3;
+ }
+
+ if (src[0] == 's' && src[1] == 'r' && ! isalnum ((unsigned char) src[2]))
+ {
+ *mode = A_SR;
+ return 2;
+ }
+
+ if (src[0] == 's' && src[1] == 'p' && ! isalnum ((unsigned char) src[2]))
+ {
+ *mode = A_REG_N;
+ *reg = 15;
+ return 2;
+ }
+
+ if (src[0] == 'p' && src[1] == 'r' && ! isalnum ((unsigned char) src[2]))
+ {
+ *mode = A_PR;
+ return 2;
+ }
+ if (src[0] == 'p' && src[1] == 'c' && ! isalnum ((unsigned char) src[2]))
+ {
+ *mode = A_DISP_PC;
+ return 2;
+ }
+ if (src[0] == 'g' && src[1] == 'b' && src[2] == 'r'
+ && ! isalnum ((unsigned char) src[3]))
+ {
+ *mode = A_GBR;
+ return 3;
+ }
+ if (src[0] == 'v' && src[1] == 'b' && src[2] == 'r'
+ && ! isalnum ((unsigned char) src[3]))
+ {
+ *mode = A_VBR;
+ return 3;
+ }
+
+ if (src[0] == 'm' && src[1] == 'a' && src[2] == 'c'
+ && ! isalnum ((unsigned char) src[4]))
+ {
+ if (src[3] == 'l')
+ {
+ *mode = A_MACL;
+ return 4;
+ }
+ if (src[3] == 'h')
+ {
+ *mode = A_MACH;
+ return 4;
+ }
+ }
+ if (src[0] == 'f' && src[1] == 'r')
+ {
+ if (src[2] == '1')
+ {
+ if (src[3] >= '0' && src[3] <= '5'
+ && ! isalnum ((unsigned char) src[4]))
+ {
+ *mode = F_REG_N;
+ *reg = 10 + src[3] - '0';
+ return 4;
+ }
+ }
+ if (src[2] >= '0' && src[2] <= '9'
+ && ! isalnum ((unsigned char) src[3]))
+ {
+ *mode = F_REG_N;
+ *reg = (src[2] - '0');
+ return 3;
+ }
+ }
+ if (src[0] == 'd' && src[1] == 'r')
+ {
+ if (src[2] == '1')
+ {
+ if (src[3] >= '0' && src[3] <= '4' && ! ((src[3] - '0') & 1)
+ && ! isalnum ((unsigned char) src[4]))
+ {
+ *mode = D_REG_N;
+ *reg = 10 + src[3] - '0';
+ return 4;
+ }
+ }
+ if (src[2] >= '0' && src[2] <= '8' && ! ((src[2] - '0') & 1)
+ && ! isalnum ((unsigned char) src[3]))
+ {
+ *mode = D_REG_N;
+ *reg = (src[2] - '0');
+ return 3;
+ }
+ }
+ if (src[0] == 'x' && src[1] == 'd')
+ {
+ if (src[2] == '1')
+ {
+ if (src[3] >= '0' && src[3] <= '4' && ! ((src[3] - '0') & 1)
+ && ! isalnum ((unsigned char) src[4]))
+ {
+ *mode = X_REG_N;
+ *reg = 11 + src[3] - '0';
+ return 4;
+ }
+ }
+ if (src[2] >= '0' && src[2] <= '8' && ! ((src[2] - '0') & 1)
+ && ! isalnum ((unsigned char) src[3]))
+ {
+ *mode = X_REG_N;
+ *reg = (src[2] - '0') + 1;
+ return 3;
+ }
+ }
+ if (src[0] == 'f' && src[1] == 'v')
+ {
+ if (src[2] == '1'&& src[3] == '2' && ! isalnum ((unsigned char) src[4]))
+ {
+ *mode = V_REG_N;
+ *reg = 12;
+ return 4;
+ }
+ if ((src[2] == '0' || src[2] == '4' || src[2] == '8')
+ && ! isalnum ((unsigned char) src[3]))
+ {
+ *mode = V_REG_N;
+ *reg = (src[2] - '0');
+ return 3;
+ }
+ }
+ if (src[0] == 'f' && src[1] == 'p' && src[2] == 'u' && src[3] == 'l'
+ && ! isalnum ((unsigned char) src[4]))
+ {
+ *mode = FPUL_N;
+ return 4;
+ }
+
+ if (src[0] == 'f' && src[1] == 'p' && src[2] == 's' && src[3] == 'c'
+ && src[4] == 'r' && ! isalnum ((unsigned char) src[5]))
+ {
+ *mode = FPSCR_N;
+ return 5;
+ }
+
+ if (src[0] == 'x' && src[1] == 'm' && src[2] == 't' && src[3] == 'r'
+ && src[4] == 'x' && ! isalnum ((unsigned char) src[5]))
+ {
+ *mode = XMTRX_M4;
+ return 5;
+ }
+
+ return 0;
+}
+
+static symbolS *dot()
+{
+ const char *fake;
+
+ /* JF: '.' is pseudo symbol with value of current location
+ in current segment. */
+ fake = FAKE_LABEL_NAME;
+ return symbol_new (fake,
+ now_seg,
+ (valueT) frag_now_fix (),
+ frag_now);
+
+}
+
+
+static
+char *
+parse_exp (s)
+ char *s;
+{
+ char *save;
+ char *new;
+
+ save = input_line_pointer;
+ input_line_pointer = s;
+ expression (&immediate);
+ if (immediate.X_op == O_absent)
+ as_bad (_("missing operand"));
+ new = input_line_pointer;
+ input_line_pointer = save;
+ return new;
+}
+
+
+/* The many forms of operand:
+
+ Rn Register direct
+ @Rn Register indirect
+ @Rn+ Autoincrement
+ @-Rn Autodecrement
+ @(disp:4,Rn)
+ @(disp:8,GBR)
+ @(disp:8,PC)
+
+ @(R0,Rn)
+ @(R0,GBR)
+
+ disp:8
+ disp:12
+ #imm8
+ pr, gbr, vbr, macl, mach
+
+ */
+
+static
+char *
+parse_at (src, op)
+ char *src;
+ sh_operand_info *op;
+{
+ int len;
+ int mode;
+ src++;
+ if (src[0] == '-')
+ {
+ /* Must be predecrement */
+ src++;
+
+ len = parse_reg (src, &mode, &(op->reg));
+ if (mode != A_REG_N)
+ as_bad (_("illegal register after @-"));
+
+ op->type = A_DEC_N;
+ src += len;
+ }
+ else if (src[0] == '(')
+ {
+ /* Could be @(disp, rn), @(disp, gbr), @(disp, pc), @(r0, gbr) or
+ @(r0, rn) */
+ src++;
+ len = parse_reg (src, &mode, &(op->reg));
+ if (len && mode == A_REG_N)
+ {
+ src += len;
+ if (op->reg != 0)
+ {
+ as_bad (_("must be @(r0,...)"));
+ }
+ if (src[0] == ',')
+ src++;
+ /* Now can be rn or gbr */
+ len = parse_reg (src, &mode, &(op->reg));
+ if (mode == A_GBR)
+ {
+ op->type = A_R0_GBR;
+ }
+ else if (mode == A_REG_N)
+ {
+ op->type = A_IND_R0_REG_N;
+ }
+ else
+ {
+ as_bad (_("syntax error in @(r0,...)"));
+ }
+ }
+ else
+ {
+ /* Must be an @(disp,.. thing) */
+ src = parse_exp (src);
+ if (src[0] == ',')
+ src++;
+ /* Now can be rn, gbr or pc */
+ len = parse_reg (src, &mode, &op->reg);
+ if (len)
+ {
+ if (mode == A_REG_N)
+ {
+ op->type = A_DISP_REG_N;
+ }
+ else if (mode == A_GBR)
+ {
+ op->type = A_DISP_GBR;
+ }
+ else if (mode == A_DISP_PC)
+ {
+ /* Turn a plain @(4,pc) into @(.+4,pc) */
+ if (immediate.X_op == O_constant) {
+ immediate.X_add_symbol = dot();
+ immediate.X_op = O_symbol;
+ }
+ op->type = A_DISP_PC;
+ }
+ else
+ {
+ as_bad (_("syntax error in @(disp,[Rn, gbr, pc])"));
+ }
+ }
+ else
+ {
+ as_bad (_("syntax error in @(disp,[Rn, gbr, pc])"));
+ }
+ }
+ src += len;
+ if (src[0] != ')')
+ as_bad (_("expecting )"));
+ else
+ src++;
+ }
+ else
+ {
+ src += parse_reg (src, &mode, &(op->reg));
+ if (mode != A_REG_N)
+ {
+ as_bad (_("illegal register after @"));
+ }
+ if (src[0] == '+')
+ {
+ op->type = A_INC_N;
+ src++;
+ }
+ else
+ {
+ op->type = A_IND_N;
+ }
+ }
+ return src;
+}
+
+static void
+get_operand (ptr, op)
+ char **ptr;
+ sh_operand_info *op;
+{
+ char *src = *ptr;
+ int mode = -1;
+ unsigned int len;
+
+ if (src[0] == '#')
+ {
+ src++;
+ *ptr = parse_exp (src);
+ op->type = A_IMM;
+ return;
+ }
+
+ else if (src[0] == '@')
+ {
+ *ptr = parse_at (src, op);
+ return;
+ }
+ len = parse_reg (src, &mode, &(op->reg));
+ if (len)
+ {
+ *ptr = src + len;
+ op->type = mode;
+ return;
+ }
+ else
+ {
+ /* Not a reg, the only thing left is a displacement */
+ *ptr = parse_exp (src);
+ op->type = A_DISP_PC;
+ return;
+ }
+}
+
+static
+char *
+get_operands (info, args, operand)
+ sh_opcode_info *info;
+ char *args;
+ sh_operand_info *operand;
+
+{
+ char *ptr = args;
+ if (info->arg[0])
+ {
+ ptr++;
+
+ get_operand (&ptr, operand + 0);
+ if (info->arg[1])
+ {
+ if (*ptr == ',')
+ {
+ ptr++;
+ }
+ get_operand (&ptr, operand + 1);
+ if (info->arg[2])
+ {
+ if (*ptr == ',')
+ {
+ ptr++;
+ }
+ get_operand (&ptr, operand + 2);
+ }
+ else
+ {
+ operand[2].type = 0;
+ }
+ }
+ else
+ {
+ operand[1].type = 0;
+ operand[2].type = 0;
+ }
+ }
+ else
+ {
+ operand[0].type = 0;
+ operand[1].type = 0;
+ operand[2].type = 0;
+ }
+ return ptr;
+}
+
+/* Passed a pointer to a list of opcodes which use different
+ addressing modes, return the opcode which matches the opcodes
+ provided
+ */
+
+static
+sh_opcode_info *
+get_specific (opcode, operands)
+ sh_opcode_info *opcode;
+ sh_operand_info *operands;
+{
+ sh_opcode_info *this_try = opcode;
+ char *name = opcode->name;
+ int n = 0;
+ while (opcode->name)
+ {
+ this_try = opcode++;
+ if (this_try->name != name)
+ {
+ /* We've looked so far down the table that we've run out of
+ opcodes with the same name */
+ return 0;
+ }
+ /* look at both operands needed by the opcodes and provided by
+ the user - since an arg test will often fail on the same arg
+ again and again, we'll try and test the last failing arg the
+ first on each opcode try */
+
+ for (n = 0; this_try->arg[n]; n++)
+ {
+ sh_operand_info *user = operands + n;
+ sh_arg_type arg = this_try->arg[n];
+ switch (arg)
+ {
+ case A_IMM:
+ case A_BDISP12:
+ case A_BDISP8:
+ case A_DISP_GBR:
+ case A_DISP_PC:
+ case A_MACH:
+ case A_PR:
+ case A_MACL:
+ if (user->type != arg)
+ goto fail;
+ break;
+ case A_R0:
+ /* opcode needs r0 */
+ if (user->type != A_REG_N || user->reg != 0)
+ goto fail;
+ break;
+ case A_R0_GBR:
+ if (user->type != A_R0_GBR || user->reg != 0)
+ goto fail;
+ break;
+ case F_FR0:
+ if (user->type != F_REG_N || user->reg != 0)
+ goto fail;
+ break;
+
+ case A_REG_N:
+ case A_INC_N:
+ case A_DEC_N:
+ case A_IND_N:
+ case A_IND_R0_REG_N:
+ case A_DISP_REG_N:
+ case F_REG_N:
+ case D_REG_N:
+ case X_REG_N:
+ case V_REG_N:
+ case FPUL_N:
+ case FPSCR_N:
+ /* Opcode needs rn */
+ if (user->type != arg)
+ goto fail;
+ reg_n = user->reg;
+ break;
+ case FD_REG_N:
+ if (user->type != F_REG_N && user->type != D_REG_N)
+ goto fail;
+ reg_n = user->reg;
+ break;
+ case DX_REG_N:
+ if (user->type != D_REG_N && user->type != X_REG_N)
+ goto fail;
+ reg_n = user->reg;
+ break;
+ case A_GBR:
+ case A_SR:
+ case A_VBR:
+ case A_SSR:
+ case A_SPC:
+ case A_SGR:
+ case A_DBR:
+ if (user->type != arg)
+ goto fail;
+ break;
+
+ case A_REG_B:
+ if (user->type != arg)
+ goto fail;
+ reg_b = user->reg;
+ break;
+
+ case A_REG_M:
+ case A_INC_M:
+ case A_DEC_M:
+ case A_IND_M:
+ case A_IND_R0_REG_M:
+ case A_DISP_REG_M:
+ /* Opcode needs rn */
+ if (user->type != arg - A_REG_M + A_REG_N)
+ goto fail;
+ reg_m = user->reg;
+ break;
+
+ case F_REG_M:
+ case D_REG_M:
+ case X_REG_M:
+ case V_REG_M:
+ case FPUL_M:
+ case FPSCR_M:
+ /* Opcode needs rn */
+ if (user->type != arg - F_REG_M + F_REG_N)
+ goto fail;
+ reg_m = user->reg;
+ break;
+ case DX_REG_M:
+ if (user->type != D_REG_N && user->type != X_REG_N)
+ goto fail;
+ reg_m = user->reg;
+ break;
+ case XMTRX_M4:
+ if (user->type != XMTRX_M4)
+ goto fail;
+ reg_m = 4;
+ break;
+
+ default:
+ printf (_("unhandled %d\n"), arg);
+ goto fail;
+ }
+ }
+ return this_try;
+ fail:;
+ }
+
+ return 0;
+}
+
+int
+check (operand, low, high)
+ expressionS *operand;
+ int low;
+ int high;
+{
+ if (operand->X_op != O_constant
+ || operand->X_add_number < low
+ || operand->X_add_number > high)
+ {
+ as_bad (_("operand must be absolute in range %d..%d"), low, high);
+ }
+ return operand->X_add_number;
+}
+
+
+static void
+insert (where, how, pcrel)
+ char *where;
+ int how;
+ int pcrel;
+{
+ fix_new_exp (frag_now,
+ where - frag_now->fr_literal,
+ 2,
+ &immediate,
+ pcrel,
+ how);
+}
+
+static void
+build_relax (opcode)
+ sh_opcode_info *opcode;
+{
+ int high_byte = target_big_endian ? 0 : 1;
+ char *p;
+
+ if (opcode->arg[0] == A_BDISP8)
+ {
+ int what = (opcode->nibbles[1] & 4) ? COND_JUMP_DELAY : COND_JUMP;
+ p = frag_var (rs_machine_dependent,
+ md_relax_table[C (what, COND32)].rlx_length,
+ md_relax_table[C (what, COND8)].rlx_length,
+ C (what, 0),
+ immediate.X_add_symbol,
+ immediate.X_add_number,
+ 0);
+ p[high_byte] = (opcode->nibbles[0] << 4) | (opcode->nibbles[1]);
+ }
+ else if (opcode->arg[0] == A_BDISP12)
+ {
+ p = frag_var (rs_machine_dependent,
+ md_relax_table[C (UNCOND_JUMP, UNCOND32)].rlx_length,
+ md_relax_table[C (UNCOND_JUMP, UNCOND12)].rlx_length,
+ C (UNCOND_JUMP, 0),
+ immediate.X_add_symbol,
+ immediate.X_add_number,
+ 0);
+ p[high_byte] = (opcode->nibbles[0] << 4);
+ }
+
+}
+
+/* Now we know what sort of opcodes it is, lets build the bytes -
+ */
+static void
+build_Mytes (opcode, operand)
+ sh_opcode_info *opcode;
+ sh_operand_info *operand;
+
+{
+ int index;
+ char nbuf[4];
+ char *output = frag_more (2);
+ int low_byte = target_big_endian ? 1 : 0;
+ nbuf[0] = 0;
+ nbuf[1] = 0;
+ nbuf[2] = 0;
+ nbuf[3] = 0;
+
+ for (index = 0; index < 4; index++)
+ {
+ sh_nibble_type i = opcode->nibbles[index];
+ if (i < 16)
+ {
+ nbuf[index] = i;
+ }
+ else
+ {
+ switch (i)
+ {
+ case REG_N:
+ nbuf[index] = reg_n;
+ break;
+ case REG_M:
+ nbuf[index] = reg_m;
+ break;
+ case REG_NM:
+ nbuf[index] = reg_n | (reg_m >> 2);
+ break;
+ case REG_B:
+ nbuf[index] = reg_b | 0x08;
+ break;
+ case DISP_4:
+ insert (output + low_byte, BFD_RELOC_SH_IMM4, 0);
+ break;
+ case IMM_4BY4:
+ insert (output + low_byte, BFD_RELOC_SH_IMM4BY4, 0);
+ break;
+ case IMM_4BY2:
+ insert (output + low_byte, BFD_RELOC_SH_IMM4BY2, 0);
+ break;
+ case IMM_4:
+ insert (output + low_byte, BFD_RELOC_SH_IMM4, 0);
+ break;
+ case IMM_8BY4:
+ insert (output + low_byte, BFD_RELOC_SH_IMM8BY4, 0);
+ break;
+ case IMM_8BY2:
+ insert (output + low_byte, BFD_RELOC_SH_IMM8BY2, 0);
+ break;
+ case IMM_8:
+ insert (output + low_byte, BFD_RELOC_SH_IMM8, 0);
+ break;
+ case PCRELIMM_8BY4:
+ insert (output, BFD_RELOC_SH_PCRELIMM8BY4, 1);
+ break;
+ case PCRELIMM_8BY2:
+ insert (output, BFD_RELOC_SH_PCRELIMM8BY2, 1);
+ break;
+ default:
+ printf (_("failed for %d\n"), i);
+ }
+ }
+ }
+ if (! target_big_endian) {
+ output[1] = (nbuf[0] << 4) | (nbuf[1]);
+ output[0] = (nbuf[2] << 4) | (nbuf[3]);
+ }
+ else {
+ output[0] = (nbuf[0] << 4) | (nbuf[1]);
+ output[1] = (nbuf[2] << 4) | (nbuf[3]);
+ }
+}
+
+/* This is the guts of the machine-dependent assembler. STR points to a
+ machine dependent instruction. This function is supposed to emit
+ the frags/bytes it assembles to.
+ */
+
+void
+md_assemble (str)
+ char *str;
+{
+ unsigned char *op_start;
+ unsigned char *op_end;
+ sh_operand_info operand[3];
+ sh_opcode_info *opcode;
+ char name[20];
+ int nlen = 0;
+ /* Drop leading whitespace */
+ while (*str == ' ')
+ str++;
+
+ /* find the op code end */
+ for (op_start = op_end = (unsigned char *) (str);
+ *op_end
+ && nlen < 20
+ && !is_end_of_line[*op_end] && *op_end != ' ';
+ op_end++)
+ {
+ unsigned char c = op_start[nlen];
+
+ /* The machine independent code will convert CMP/EQ into cmp/EQ
+ because it thinks the '/' is the end of the symbol. Instead of
+ hacking up the machine independent code, we just deal with it
+ here. */
+ c = isupper (c) ? tolower (c) : c;
+ name[nlen] = c;
+ nlen++;
+ }
+ name[nlen] = 0;
+
+ if (nlen == 0)
+ {
+ as_bad (_("can't find opcode "));
+ }
+
+ opcode = (sh_opcode_info *) hash_find (opcode_hash_control, name);
+
+ if (opcode == NULL)
+ {
+ as_bad (_("unknown opcode"));
+ return;
+ }
+
+ if (sh_relax
+ && ! seg_info (now_seg)->tc_segment_info_data.in_code)
+ {
+ /* Output a CODE reloc to tell the linker that the following
+ bytes are instructions, not data. */
+ fix_new (frag_now, frag_now_fix (), 2, &abs_symbol, 0, 0,
+ BFD_RELOC_SH_CODE);
+ seg_info (now_seg)->tc_segment_info_data.in_code = 1;
+ }
+
+ if (opcode->arg[0] == A_BDISP12
+ || opcode->arg[0] == A_BDISP8)
+ {
+ parse_exp (op_end + 1);
+ build_relax (opcode);
+ }
+ else
+ {
+ if (opcode->arg[0] != A_END)
+ {
+ get_operands (opcode, op_end, operand);
+ }
+ opcode = get_specific (opcode, operand);
+
+ if (opcode == 0)
+ {
+ /* Couldn't find an opcode which matched the operands */
+ char *where = frag_more (2);
+
+ where[0] = 0x0;
+ where[1] = 0x0;
+ as_bad (_("invalid operands for opcode"));
+ return;
+ }
+
+ build_Mytes (opcode, operand);
+ }
+
+}
+
+/* This routine is called each time a label definition is seen. It
+ emits a BFD_RELOC_SH_LABEL reloc if necessary. */
+
+void
+sh_frob_label ()
+{
+ static fragS *last_label_frag;
+ static int last_label_offset;
+
+ if (sh_relax
+ && seg_info (now_seg)->tc_segment_info_data.in_code)
+ {
+ int offset;
+
+ offset = frag_now_fix ();
+ if (frag_now != last_label_frag
+ || offset != last_label_offset)
+ {
+ fix_new (frag_now, offset, 2, &abs_symbol, 0, 0, BFD_RELOC_SH_LABEL);
+ last_label_frag = frag_now;
+ last_label_offset = offset;
+ }
+ }
+}
+
+/* This routine is called when the assembler is about to output some
+ data. It emits a BFD_RELOC_SH_DATA reloc if necessary. */
+
+void
+sh_flush_pending_output ()
+{
+ if (sh_relax
+ && seg_info (now_seg)->tc_segment_info_data.in_code)
+ {
+ fix_new (frag_now, frag_now_fix (), 2, &abs_symbol, 0, 0,
+ BFD_RELOC_SH_DATA);
+ seg_info (now_seg)->tc_segment_info_data.in_code = 0;
+ }
+}
+
+symbolS *
+DEFUN (md_undefined_symbol, (name),
+ char *name)
+{
+ return 0;
+}
+
+#ifdef OBJ_COFF
+
+void
+DEFUN (tc_crawl_symbol_chain, (headers),
+ object_headers * headers)
+{
+ printf (_("call to tc_crawl_symbol_chain \n"));
+}
+
+void
+DEFUN (tc_headers_hook, (headers),
+ object_headers * headers)
+{
+ printf (_("call to tc_headers_hook \n"));
+}
+
+#endif
+
+/* Various routines to kill one day */
+/* Equal to MAX_PRECISION in atof-ieee.c */
+#define MAX_LITTLENUMS 6
+
+/* Turn a string in input_line_pointer into a floating point constant of type
+ type, and store the appropriate bytes in *litP. The number of LITTLENUMS
+ emitted is stored in *sizeP . An error message is returned, or NULL on OK.
+ */
+char *
+md_atof (type, litP, sizeP)
+ int type;
+ char *litP;
+ int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[4];
+ char *t;
+ int i;
+
+ switch (type)
+ {
+ case 'f':
+ prec = 2;
+ break;
+
+ case 'd':
+ prec = 4;
+ break;
+
+ default:
+ *sizeP = 0;
+ return _("bad call to md_atof");
+ }
+
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+
+ *sizeP = prec * 2;
+
+ if (! target_big_endian)
+ {
+ for (i = prec - 1; i >= 0; i--)
+ {
+ md_number_to_chars (litP, (valueT) words[i], 2);
+ litP += 2;
+ }
+ }
+ else
+ {
+ for (i = 0; i < prec; i++)
+ {
+ md_number_to_chars (litP, (valueT) words[i], 2);
+ litP += 2;
+ }
+ }
+
+ return NULL;
+}
+
+/* Handle the .uses pseudo-op. This pseudo-op is used just before a
+ call instruction. It refers to a label of the instruction which
+ loads the register which the call uses. We use it to generate a
+ special reloc for the linker. */
+
+static void
+s_uses (ignore)
+ int ignore;
+{
+ expressionS ex;
+
+ if (! sh_relax)
+ as_warn (_(".uses pseudo-op seen when not relaxing"));
+
+ expression (&ex);
+
+ if (ex.X_op != O_symbol || ex.X_add_number != 0)
+ {
+ as_bad (_("bad .uses format"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ fix_new_exp (frag_now, frag_now_fix (), 2, &ex, 1, BFD_RELOC_SH_USES);
+
+ demand_empty_rest_of_line ();
+}
+
+CONST char *md_shortopts = "";
+struct option md_longopts[] = {
+
+#define OPTION_RELAX (OPTION_MD_BASE)
+#define OPTION_LITTLE (OPTION_MD_BASE + 1)
+#define OPTION_SMALL (OPTION_LITTLE + 1)
+
+ {"relax", no_argument, NULL, OPTION_RELAX},
+ {"little", no_argument, NULL, OPTION_LITTLE},
+ {"small", no_argument, NULL, OPTION_SMALL},
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof(md_longopts);
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ switch (c)
+ {
+ case OPTION_RELAX:
+ sh_relax = 1;
+ break;
+
+ case OPTION_LITTLE:
+ shl = 1;
+ target_big_endian = 0;
+ break;
+
+ case OPTION_SMALL:
+ sh_small = 1;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+ fprintf(stream, _("\
+SH options:\n\
+-little generate little endian code\n\
+-relax alter jump instructions for long displacements\n\
+-small align sections to 4 byte boundaries, not 16\n"));
+}
+
+void
+tc_Nout_fix_to_chars ()
+{
+ printf (_("call to tc_Nout_fix_to_chars \n"));
+ abort ();
+}
+
+/* This struct is used to pass arguments to sh_count_relocs through
+ bfd_map_over_sections. */
+
+struct sh_count_relocs
+{
+ /* Symbol we are looking for. */
+ symbolS *sym;
+ /* Count of relocs found. */
+ int count;
+};
+
+/* Count the number of fixups in a section which refer to a particular
+ symbol. When using BFD_ASSEMBLER, this is called via
+ bfd_map_over_sections. */
+
+/*ARGSUSED*/
+static void
+sh_count_relocs (abfd, sec, data)
+ bfd *abfd;
+ segT sec;
+ PTR data;
+{
+ struct sh_count_relocs *info = (struct sh_count_relocs *) data;
+ segment_info_type *seginfo;
+ symbolS *sym;
+ fixS *fix;
+
+ seginfo = seg_info (sec);
+ if (seginfo == NULL)
+ return;
+
+ sym = info->sym;
+ for (fix = seginfo->fix_root; fix != NULL; fix = fix->fx_next)
+ {
+ if (fix->fx_addsy == sym)
+ {
+ ++info->count;
+ fix->fx_tcbit = 1;
+ }
+ }
+}
+
+/* Handle the count relocs for a particular section. When using
+ BFD_ASSEMBLER, this is called via bfd_map_over_sections. */
+
+/*ARGSUSED*/
+static void
+sh_frob_section (abfd, sec, ignore)
+ bfd *abfd;
+ segT sec;
+ PTR ignore;
+{
+ segment_info_type *seginfo;
+ fixS *fix;
+
+ seginfo = seg_info (sec);
+ if (seginfo == NULL)
+ return;
+
+ for (fix = seginfo->fix_root; fix != NULL; fix = fix->fx_next)
+ {
+ symbolS *sym;
+ bfd_vma val;
+ fixS *fscan;
+ struct sh_count_relocs info;
+
+ if (fix->fx_r_type != BFD_RELOC_SH_USES)
+ continue;
+
+ /* The BFD_RELOC_SH_USES reloc should refer to a defined local
+ symbol in the same section. */
+ sym = fix->fx_addsy;
+ if (sym == NULL
+ || fix->fx_subsy != NULL
+ || fix->fx_addnumber != 0
+ || S_GET_SEGMENT (sym) != sec
+#if ! defined (BFD_ASSEMBLER) && defined (OBJ_COFF)
+ || S_GET_STORAGE_CLASS (sym) == C_EXT
+#endif
+ || S_IS_EXTERNAL (sym))
+ {
+ as_warn_where (fix->fx_file, fix->fx_line,
+ _(".uses does not refer to a local symbol in the same section"));
+ continue;
+ }
+
+ /* Look through the fixups again, this time looking for one
+ at the same location as sym. */
+ val = S_GET_VALUE (sym);
+ for (fscan = seginfo->fix_root;
+ fscan != NULL;
+ fscan = fscan->fx_next)
+ if (val == fscan->fx_frag->fr_address + fscan->fx_where
+ && fscan->fx_r_type != BFD_RELOC_SH_ALIGN
+ && fscan->fx_r_type != BFD_RELOC_SH_CODE
+ && fscan->fx_r_type != BFD_RELOC_SH_DATA
+ && fscan->fx_r_type != BFD_RELOC_SH_LABEL)
+ break;
+ if (fscan == NULL)
+ {
+ as_warn_where (fix->fx_file, fix->fx_line,
+ _("can't find fixup pointed to by .uses"));
+ continue;
+ }
+
+ if (fscan->fx_tcbit)
+ {
+ /* We've already done this one. */
+ continue;
+ }
+
+ /* fscan should also be a fixup to a local symbol in the same
+ section. */
+ sym = fscan->fx_addsy;
+ if (sym == NULL
+ || fscan->fx_subsy != NULL
+ || fscan->fx_addnumber != 0
+ || S_GET_SEGMENT (sym) != sec
+#if ! defined (BFD_ASSEMBLER) && defined (OBJ_COFF)
+ || S_GET_STORAGE_CLASS (sym) == C_EXT
+#endif
+ || S_IS_EXTERNAL (sym))
+ {
+ as_warn_where (fix->fx_file, fix->fx_line,
+ _(".uses target does not refer to a local symbol in the same section"));
+ continue;
+ }
+
+ /* Now we look through all the fixups of all the sections,
+ counting the number of times we find a reference to sym. */
+ info.sym = sym;
+ info.count = 0;
+#ifdef BFD_ASSEMBLER
+ bfd_map_over_sections (stdoutput, sh_count_relocs, (PTR) &info);
+#else
+ {
+ int iscan;
+
+ for (iscan = SEG_E0; iscan < SEG_UNKNOWN; iscan++)
+ sh_count_relocs ((bfd *) NULL, iscan, (PTR) &info);
+ }
+#endif
+
+ if (info.count < 1)
+ abort ();
+
+ /* Generate a BFD_RELOC_SH_COUNT fixup at the location of sym.
+ We have already adjusted the value of sym to include the
+ fragment address, so we undo that adjustment here. */
+ subseg_change (sec, 0);
+ fix_new (sym->sy_frag, S_GET_VALUE (sym) - sym->sy_frag->fr_address,
+ 4, &abs_symbol, info.count, 0, BFD_RELOC_SH_COUNT);
+ }
+}
+
+/* This function is called after the symbol table has been completed,
+ but before the relocs or section contents have been written out.
+ If we have seen any .uses pseudo-ops, they point to an instruction
+ which loads a register with the address of a function. We look
+ through the fixups to find where the function address is being
+ loaded from. We then generate a COUNT reloc giving the number of
+ times that function address is referred to. The linker uses this
+ information when doing relaxing, to decide when it can eliminate
+ the stored function address entirely. */
+
+void
+sh_frob_file ()
+{
+ if (! sh_relax)
+ return;
+
+#ifdef BFD_ASSEMBLER
+ bfd_map_over_sections (stdoutput, sh_frob_section, (PTR) NULL);
+#else
+ {
+ int iseg;
+
+ for (iseg = SEG_E0; iseg < SEG_UNKNOWN; iseg++)
+ sh_frob_section ((bfd *) NULL, iseg, (PTR) NULL);
+ }
+#endif
+}
+
+/* Called after relaxing. Set the correct sizes of the fragments, and
+ create relocs so that md_apply_fix will fill in the correct values. */
+
+void
+md_convert_frag (headers, seg, fragP)
+#ifdef BFD_ASSEMBLER
+ bfd *headers;
+#else
+ object_headers *headers;
+#endif
+ segT seg;
+ fragS *fragP;
+{
+ int donerelax = 0;
+
+ switch (fragP->fr_subtype)
+ {
+ case C (COND_JUMP, COND8):
+ case C (COND_JUMP_DELAY, COND8):
+ subseg_change (seg, 0);
+ fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, fragP->fr_offset,
+ 1, BFD_RELOC_SH_PCDISP8BY2);
+ fragP->fr_fix += 2;
+ fragP->fr_var = 0;
+ break;
+
+ case C (UNCOND_JUMP, UNCOND12):
+ subseg_change (seg, 0);
+ fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, fragP->fr_offset,
+ 1, BFD_RELOC_SH_PCDISP12BY2);
+ fragP->fr_fix += 2;
+ fragP->fr_var = 0;
+ break;
+
+ case C (UNCOND_JUMP, UNCOND32):
+ case C (UNCOND_JUMP, UNDEF_WORD_DISP):
+ if (fragP->fr_symbol == NULL)
+ as_bad (_("at 0x%lx, displacement overflows 12-bit field"),
+ (unsigned long) fragP->fr_address);
+ else if (S_IS_DEFINED (fragP->fr_symbol))
+ as_bad (_("at 0x%lx, displacement to defined symbol %s overflows 12-bit field"),
+ (unsigned long) fragP->fr_address,
+ S_GET_NAME (fragP->fr_symbol));
+ else
+ as_bad (_("at 0x%lx, displacement to undefined symbol %s overflows 12-bit field"),
+ (unsigned long) fragP->fr_address,
+ S_GET_NAME (fragP->fr_symbol));
+
+#if 0 /* This code works, but generates poor code and the compiler
+ should never produce a sequence that requires it to be used. */
+
+ /* A jump wont fit in 12 bits, make code which looks like
+ bra foo
+ mov.w @(0, PC), r14
+ .long disp
+ foo: bra @r14
+ */
+ int t = buffer[0] & 0x10;
+
+ buffer[highbyte] = 0xa0; /* branch over move and disp */
+ buffer[lowbyte] = 3;
+ buffer[highbyte+2] = 0xd0 | JREG; /* Build mov insn */
+ buffer[lowbyte+2] = 0x00;
+
+ buffer[highbyte+4] = 0; /* space for 32 bit jump disp */
+ buffer[lowbyte+4] = 0;
+ buffer[highbyte+6] = 0;
+ buffer[lowbyte+6] = 0;
+
+ buffer[highbyte+8] = 0x40 | JREG; /* Build jmp @JREG */
+ buffer[lowbyte+8] = t ? 0xb : 0x2b;
+
+ buffer[highbyte+10] = 0x20; /* build nop */
+ buffer[lowbyte+10] = 0x0b;
+
+ /* Make reloc for the long disp */
+ fix_new (fragP,
+ fragP->fr_fix + 4,
+ 4,
+ fragP->fr_symbol,
+ fragP->fr_offset,
+ 0,
+ BFD_RELOC_32);
+ fragP->fr_fix += UNCOND32_LENGTH;
+ fragP->fr_var = 0;
+ donerelax = 1;
+#endif
+
+ break;
+
+ case C (COND_JUMP, COND12):
+ case C (COND_JUMP_DELAY, COND12):
+ /* A bcond won't fit, so turn it into a b!cond; bra disp; nop */
+ /* I found that a relax failure for gcc.c-torture/execute/930628-1.c
+ was due to gas incorrectly relaxing an out-of-range conditional
+ branch with delay slot. It turned:
+ bf.s L6 (slot mov.l r12,@(44,r0))
+ into:
+
+2c: 8f 01 a0 8b bf.s 32 <_main+32> (slot bra L6)
+30: 00 09 nop
+32: 10 cb mov.l r12,@(44,r0)
+ Therefore, branches with delay slots have to be handled
+ differently from ones without delay slots. */
+ {
+ unsigned char *buffer =
+ (unsigned char *) (fragP->fr_fix + fragP->fr_literal);
+ int highbyte = target_big_endian ? 0 : 1;
+ int lowbyte = target_big_endian ? 1 : 0;
+ int delay = fragP->fr_subtype == C (COND_JUMP_DELAY, COND12);
+
+ /* Toggle the true/false bit of the bcond. */
+ buffer[highbyte] ^= 0x2;
+
+ /* If this is a dalayed branch, we may not put the the bra in the
+ slot. So we change it to a non-delayed branch, like that:
+ b! cond slot_label; bra disp; slot_label: slot_insn
+ ??? We should try if swapping the conditional branch and
+ its delay-slot insn already makes the branch reach. */
+
+ /* Build a relocation to six / four bytes farther on. */
+ subseg_change (seg, 0);
+ fix_new (fragP, fragP->fr_fix, 2,
+#ifdef BFD_ASSEMBLER
+ section_symbol (seg),
+#else
+ seg_info (seg)->dot,
+#endif
+ fragP->fr_address + fragP->fr_fix + (delay ? 4 : 6),
+ 1, BFD_RELOC_SH_PCDISP8BY2);
+
+ /* Set up a jump instruction. */
+ buffer[highbyte + 2] = 0xa0;
+ buffer[lowbyte + 2] = 0;
+ fix_new (fragP, fragP->fr_fix + 2, 2, fragP->fr_symbol,
+ fragP->fr_offset, 1, BFD_RELOC_SH_PCDISP12BY2);
+
+ if (delay)
+ {
+ buffer[highbyte] &= ~0x4; /* Removes delay slot from branch. */
+ fragP->fr_fix += 4;
+ }
+ else
+ {
+ /* Fill in a NOP instruction. */
+ buffer[highbyte + 4] = 0x0;
+ buffer[lowbyte + 4] = 0x9;
+
+ fragP->fr_fix += 6;
+ }
+ fragP->fr_var = 0;
+ donerelax = 1;
+ }
+ break;
+
+ case C (COND_JUMP, COND32):
+ case C (COND_JUMP_DELAY, COND32):
+ case C (COND_JUMP, UNDEF_WORD_DISP):
+ case C (COND_JUMP_DELAY, UNDEF_WORD_DISP):
+ if (fragP->fr_symbol == NULL)
+ as_bad (_("at 0x%lx, displacement overflows 8-bit field"),
+ (unsigned long) fragP->fr_address);
+ else if (S_IS_DEFINED (fragP->fr_symbol))
+ as_bad (_("at 0x%lx, displacement to defined symbol %s overflows 8-bit field "),
+ (unsigned long) fragP->fr_address,
+ S_GET_NAME (fragP->fr_symbol));
+ else
+ as_bad (_("at 0x%lx, displacement to undefined symbol %s overflows 8-bit field "),
+ (unsigned long) fragP->fr_address,
+ S_GET_NAME (fragP->fr_symbol));
+
+#if 0 /* This code works, but generates poor code, and the compiler
+ should never produce a sequence that requires it to be used. */
+
+ /* A bcond won't fit and it won't go into a 12 bit
+ displacement either, the code sequence looks like:
+ b!cond foop
+ mov.w @(n, PC), r14
+ jmp @r14
+ nop
+ .long where
+ foop:
+ */
+
+ buffer[0] ^= 0x2; /* Toggle T/F bit */
+#define JREG 14
+ buffer[1] = 5; /* branch over mov, jump, nop and ptr */
+ buffer[2] = 0xd0 | JREG; /* Build mov insn */
+ buffer[3] = 0x2;
+ buffer[4] = 0x40 | JREG; /* Build jmp @JREG */
+ buffer[5] = 0x0b;
+ buffer[6] = 0x20; /* build nop */
+ buffer[7] = 0x0b;
+ buffer[8] = 0; /* space for 32 bit jump disp */
+ buffer[9] = 0;
+ buffer[10] = 0;
+ buffer[11] = 0;
+ buffer[12] = 0;
+ buffer[13] = 0;
+ /* Make reloc for the long disp */
+ fix_new (fragP,
+ fragP->fr_fix + 8,
+ 4,
+ fragP->fr_symbol,
+ fragP->fr_offset,
+ 0,
+ BFD_RELOC_32);
+ fragP->fr_fix += COND32_LENGTH;
+ fragP->fr_var = 0;
+ donerelax = 1;
+#endif
+
+ break;
+
+ default:
+ abort ();
+ }
+
+ if (donerelax && !sh_relax)
+ as_warn_where (fragP->fr_file, fragP->fr_line,
+ _("overflow in branch to %s; converted into longer instruction sequence"),
+ (fragP->fr_symbol != NULL
+ ? S_GET_NAME (fragP->fr_symbol)
+ : ""));
+}
+
+valueT
+DEFUN (md_section_align, (seg, size),
+ segT seg AND
+ valueT size)
+{
+#ifdef BFD_ASSEMBLER
+#ifdef OBJ_ELF
+ return size;
+#else /* ! OBJ_ELF */
+ return ((size + (1 << bfd_get_section_alignment (stdoutput, seg)) - 1)
+ & (-1 << bfd_get_section_alignment (stdoutput, seg)));
+#endif /* ! OBJ_ELF */
+#else /* ! BFD_ASSEMBLER */
+ return ((size + (1 << section_alignment[(int) seg]) - 1)
+ & (-1 << section_alignment[(int) seg]));
+#endif /* ! BFD_ASSEMBLER */
+}
+
+/* This static variable is set by s_uacons to tell sh_cons_align that
+ the expession does not need to be aligned. */
+
+static int sh_no_align_cons = 0;
+
+/* This handles the unaligned space allocation pseudo-ops, such as
+ .uaword. .uaword is just like .word, but the value does not need
+ to be aligned. */
+
+static void
+s_uacons (bytes)
+ int bytes;
+{
+ /* Tell sh_cons_align not to align this value. */
+ sh_no_align_cons = 1;
+ cons (bytes);
+}
+
+/* If a .word, et. al., pseud-op is seen, warn if the value is not
+ aligned correctly. Note that this can cause warnings to be issued
+ when assembling initialized structured which were declared with the
+ packed attribute. FIXME: Perhaps we should require an option to
+ enable this warning? */
+
+void
+sh_cons_align (nbytes)
+ int nbytes;
+{
+ int nalign;
+ char *p;
+
+ if (sh_no_align_cons)
+ {
+ /* This is an unaligned pseudo-op. */
+ sh_no_align_cons = 0;
+ return;
+ }
+
+ nalign = 0;
+ while ((nbytes & 1) == 0)
+ {
+ ++nalign;
+ nbytes >>= 1;
+ }
+
+ if (nalign == 0)
+ return;
+
+ if (now_seg == absolute_section)
+ {
+ if ((abs_section_offset & ((1 << nalign) - 1)) != 0)
+ as_warn (_("misaligned data"));
+ return;
+ }
+
+ p = frag_var (rs_align_code, 1, 1, (relax_substateT) 0,
+ (symbolS *) NULL, (offsetT) nalign, (char *) NULL);
+
+ record_alignment (now_seg, nalign);
+}
+
+/* When relaxing, we need to output a reloc for any .align directive
+ that requests alignment to a four byte boundary or larger. This is
+ also where we check for misaligned data. */
+
+void
+sh_handle_align (frag)
+ fragS *frag;
+{
+ if (sh_relax
+ && frag->fr_type == rs_align
+ && frag->fr_address + frag->fr_fix > 0
+ && frag->fr_offset > 1
+ && now_seg != bss_section)
+ fix_new (frag, frag->fr_fix, 2, &abs_symbol, frag->fr_offset, 0,
+ BFD_RELOC_SH_ALIGN);
+
+ if (frag->fr_type == rs_align_code
+ && frag->fr_next->fr_address - frag->fr_address - frag->fr_fix != 0)
+ as_warn_where (frag->fr_file, frag->fr_line, _("misaligned data"));
+}
+
+/* This macro decides whether a particular reloc is an entry in a
+ switch table. It is used when relaxing, because the linker needs
+ to know about all such entries so that it can adjust them if
+ necessary. */
+
+#ifdef BFD_ASSEMBLER
+#define SWITCH_TABLE_CONS(fix) (0)
+#else
+#define SWITCH_TABLE_CONS(fix) \
+ ((fix)->fx_r_type == 0 \
+ && ((fix)->fx_size == 2 \
+ || (fix)->fx_size == 1 \
+ || (fix)->fx_size == 4))
+#endif
+
+#define SWITCH_TABLE(fix) \
+ ((fix)->fx_addsy != NULL \
+ && (fix)->fx_subsy != NULL \
+ && S_GET_SEGMENT ((fix)->fx_addsy) == text_section \
+ && S_GET_SEGMENT ((fix)->fx_subsy) == text_section \
+ && ((fix)->fx_r_type == BFD_RELOC_32 \
+ || (fix)->fx_r_type == BFD_RELOC_16 \
+ || (fix)->fx_r_type == BFD_RELOC_8 \
+ || SWITCH_TABLE_CONS (fix)))
+
+/* See whether we need to force a relocation into the output file.
+ This is used to force out switch and PC relative relocations when
+ relaxing. */
+
+int
+sh_force_relocation (fix)
+ fixS *fix;
+{
+
+ if (fix->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fix->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ return 1;
+
+ if (! sh_relax)
+ return 0;
+
+ return (fix->fx_pcrel
+ || SWITCH_TABLE (fix)
+ || fix->fx_r_type == BFD_RELOC_SH_COUNT
+ || fix->fx_r_type == BFD_RELOC_SH_ALIGN
+ || fix->fx_r_type == BFD_RELOC_SH_CODE
+ || fix->fx_r_type == BFD_RELOC_SH_DATA
+ || fix->fx_r_type == BFD_RELOC_SH_LABEL);
+}
+
+#ifdef OBJ_ELF
+boolean
+sh_fix_adjustable (fixP)
+ fixS *fixP;
+{
+
+ if (fixP->fx_addsy == NULL)
+ return 1;
+
+ /* We need the symbol name for the VTABLE entries */
+ if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ return 0;
+
+ return 1;
+}
+#endif
+
+/* Apply a fixup to the object file. */
+
+#ifdef BFD_ASSEMBLER
+int
+md_apply_fix (fixP, valp)
+ fixS *fixP;
+ valueT *valp;
+#else
+void
+md_apply_fix (fixP, val)
+ fixS *fixP;
+ long val;
+#endif
+{
+ char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
+ int lowbyte = target_big_endian ? 1 : 0;
+ int highbyte = target_big_endian ? 0 : 1;
+#ifdef BFD_ASSEMBLER
+ long val = *valp;
+#endif
+ long max, min;
+ int shift;
+
+#ifdef BFD_ASSEMBLER
+ /* adjust_reloc_syms won't convert a reloc against a weak symbol
+ into a reloc against a section, but bfd_install_relocation will
+ screw up if the symbol is defined, so we have to adjust val here
+ to avoid the screw up later. */
+ if (fixP->fx_addsy != NULL
+ && S_IS_WEAK (fixP->fx_addsy))
+ val -= S_GET_VALUE (fixP->fx_addsy);
+#endif
+
+#ifndef BFD_ASSEMBLER
+ if (fixP->fx_r_type == 0)
+ {
+ if (fixP->fx_size == 2)
+ fixP->fx_r_type = BFD_RELOC_16;
+ else if (fixP->fx_size == 4)
+ fixP->fx_r_type = BFD_RELOC_32;
+ else if (fixP->fx_size == 1)
+ fixP->fx_r_type = BFD_RELOC_8;
+ else
+ abort ();
+ }
+#endif
+
+ max = min = 0;
+ shift = 0;
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_SH_IMM4:
+ max = 0xf;
+ *buf = (*buf & 0xf0) | (val & 0xf);
+ break;
+
+ case BFD_RELOC_SH_IMM4BY2:
+ max = 0xf;
+ shift = 1;
+ *buf = (*buf & 0xf0) | ((val >> 1) & 0xf);
+ break;
+
+ case BFD_RELOC_SH_IMM4BY4:
+ max = 0xf;
+ shift = 2;
+ *buf = (*buf & 0xf0) | ((val >> 2) & 0xf);
+ break;
+
+ case BFD_RELOC_SH_IMM8BY2:
+ max = 0xff;
+ shift = 1;
+ *buf = val >> 1;
+ break;
+
+ case BFD_RELOC_SH_IMM8BY4:
+ max = 0xff;
+ shift = 2;
+ *buf = val >> 2;
+ break;
+
+ case BFD_RELOC_8:
+ case BFD_RELOC_SH_IMM8:
+ /* Sometimes the 8 bit value is sign extended (e.g., add) and
+ sometimes it is not (e.g., and). We permit any 8 bit value.
+ Note that adding further restrictions may invalidate
+ reasonable looking assembly code, such as ``and -0x1,r0''. */
+ max = 0xff;
+ min = - 0xff;
+ *buf++ = val;
+ break;
+
+ case BFD_RELOC_SH_PCRELIMM8BY4:
+ /* The lower two bits of the PC are cleared before the
+ displacement is added in. We can assume that the destination
+ is on a 4 byte bounday. If this instruction is also on a 4
+ byte boundary, then we want
+ (target - here) / 4
+ and target - here is a multiple of 4.
+ Otherwise, we are on a 2 byte boundary, and we want
+ (target - (here - 2)) / 4
+ and target - here is not a multiple of 4. Computing
+ (target - (here - 2)) / 4 == (target - here + 2) / 4
+ works for both cases, since in the first case the addition of
+ 2 will be removed by the division. target - here is in the
+ variable val. */
+ val = (val + 2) / 4;
+ if (val & ~0xff)
+ as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far"));
+ buf[lowbyte] = val;
+ break;
+
+ case BFD_RELOC_SH_PCRELIMM8BY2:
+ val /= 2;
+ if (val & ~0xff)
+ as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far"));
+ buf[lowbyte] = val;
+ break;
+
+ case BFD_RELOC_SH_PCDISP8BY2:
+ val /= 2;
+ if (val < -0x80 || val > 0x7f)
+ as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far"));
+ buf[lowbyte] = val;
+ break;
+
+ case BFD_RELOC_SH_PCDISP12BY2:
+ val /= 2;
+ if (val < -0x800 || val >= 0x7ff)
+ as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far"));
+ buf[lowbyte] = val & 0xff;
+ buf[highbyte] |= (val >> 8) & 0xf;
+ break;
+
+ case BFD_RELOC_32:
+ if (! target_big_endian)
+ {
+ *buf++ = val >> 0;
+ *buf++ = val >> 8;
+ *buf++ = val >> 16;
+ *buf++ = val >> 24;
+ }
+ else
+ {
+ *buf++ = val >> 24;
+ *buf++ = val >> 16;
+ *buf++ = val >> 8;
+ *buf++ = val >> 0;
+ }
+ break;
+
+ case BFD_RELOC_16:
+ if (! target_big_endian)
+ {
+ *buf++ = val >> 0;
+ *buf++ = val >> 8;
+ }
+ else
+ {
+ *buf++ = val >> 8;
+ *buf++ = val >> 0;
+ }
+ break;
+
+ case BFD_RELOC_SH_USES:
+ /* Pass the value into sh_coff_reloc_mangle. */
+ fixP->fx_addnumber = val;
+ break;
+
+ case BFD_RELOC_SH_COUNT:
+ case BFD_RELOC_SH_ALIGN:
+ case BFD_RELOC_SH_CODE:
+ case BFD_RELOC_SH_DATA:
+ case BFD_RELOC_SH_LABEL:
+ /* Nothing to do here. */
+ break;
+
+ case BFD_RELOC_VTABLE_INHERIT:
+ case BFD_RELOC_VTABLE_ENTRY:
+ fixP->fx_done = 0;
+ return;
+
+ default:
+ abort ();
+ }
+
+ if (shift != 0)
+ {
+ if ((val & ((1 << shift) - 1)) != 0)
+ as_bad_where (fixP->fx_file, fixP->fx_line, _("misaligned offset"));
+ if (val >= 0)
+ val >>= shift;
+ else
+ val = ((val >> shift)
+ | ((long) -1 & ~ ((long) -1 >> shift)));
+ }
+ if (max != 0 && (val < min || val > max))
+ as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range"));
+
+#ifdef BFD_ASSEMBLER
+ return 0;
+#endif
+}
+
+/* Called just before address relaxation. Return the length
+ by which a fragment must grow to reach it's destination. */
+
+int
+md_estimate_size_before_relax (fragP, segment_type)
+ register fragS *fragP;
+ register segT segment_type;
+{
+ switch (fragP->fr_subtype)
+ {
+ case C (UNCOND_JUMP, UNDEF_DISP):
+ /* used to be a branch to somewhere which was unknown */
+ if (!fragP->fr_symbol)
+ {
+ fragP->fr_subtype = C (UNCOND_JUMP, UNCOND12);
+ fragP->fr_var = md_relax_table[C (UNCOND_JUMP, UNCOND12)].rlx_length;
+ }
+ else if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type)
+ {
+ fragP->fr_subtype = C (UNCOND_JUMP, UNCOND12);
+ fragP->fr_var = md_relax_table[C (UNCOND_JUMP, UNCOND12)].rlx_length;
+ }
+ else
+ {
+ fragP->fr_subtype = C (UNCOND_JUMP, UNDEF_WORD_DISP);
+ fragP->fr_var = md_relax_table[C (UNCOND_JUMP, UNCOND32)].rlx_length;
+ return md_relax_table[C (UNCOND_JUMP, UNCOND32)].rlx_length;
+ }
+ break;
+
+ default:
+ abort ();
+ case C (COND_JUMP, UNDEF_DISP):
+ case C (COND_JUMP_DELAY, UNDEF_DISP):
+ /* used to be a branch to somewhere which was unknown */
+ if (fragP->fr_symbol
+ && S_GET_SEGMENT (fragP->fr_symbol) == segment_type)
+ {
+ int what = GET_WHAT (fragP->fr_subtype);
+ /* Got a symbol and it's defined in this segment, become byte
+ sized - maybe it will fix up */
+ fragP->fr_subtype = C (what, COND8);
+ fragP->fr_var = md_relax_table[C (what, COND8)].rlx_length;
+ }
+ else if (fragP->fr_symbol)
+ {
+ int what = GET_WHAT (fragP->fr_subtype);
+ /* Its got a segment, but its not ours, so it will always be long */
+ fragP->fr_subtype = C (what, UNDEF_WORD_DISP);
+ fragP->fr_var = md_relax_table[C (what, COND32)].rlx_length;
+ return md_relax_table[C (what, COND32)].rlx_length;
+ }
+ else
+ {
+ int what = GET_WHAT (fragP->fr_subtype);
+ /* We know the abs value */
+ fragP->fr_subtype = C (what, COND8);
+ fragP->fr_var = md_relax_table[C (what, COND8)].rlx_length;
+ }
+
+ break;
+ }
+ return fragP->fr_var;
+}
+
+/* Put number into target byte order */
+
+void
+md_number_to_chars (ptr, use, nbytes)
+ char *ptr;
+ valueT use;
+ int nbytes;
+{
+ if (! target_big_endian)
+ number_to_chars_littleendian (ptr, use, nbytes);
+ else
+ number_to_chars_bigendian (ptr, use, nbytes);
+}
+
+long
+md_pcrel_from (fixP)
+ fixS *fixP;
+{
+ return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address + 2;
+}
+
+#ifdef OBJ_COFF
+
+int
+tc_coff_sizemachdep (frag)
+ fragS *frag;
+{
+ return md_relax_table[frag->fr_subtype].rlx_length;
+}
+
+#endif /* OBJ_COFF */
+
+/* When we align the .text section, insert the correct NOP pattern. */
+
+int
+sh_do_align (n, fill, len, max)
+ int n;
+ const char *fill;
+ int len;
+ int max;
+{
+ if (fill == NULL
+#ifdef BFD_ASSEMBLER
+ && (now_seg->flags & SEC_CODE) != 0
+#else
+ && now_seg != data_section
+ && now_seg != bss_section
+#endif
+ && n > 1)
+ {
+ static const unsigned char big_nop_pattern[] = { 0x00, 0x09 };
+ static const unsigned char little_nop_pattern[] = { 0x09, 0x00 };
+
+ /* First align to a 2 byte boundary, in case there is an odd
+ .byte. */
+ frag_align (1, 0, 0);
+ if (target_big_endian)
+ frag_align_pattern (n, big_nop_pattern, sizeof big_nop_pattern, max);
+ else
+ frag_align_pattern (n, little_nop_pattern, sizeof little_nop_pattern,
+ max);
+ return 1;
+ }
+
+ return 0;
+}
+
+#ifndef BFD_ASSEMBLER
+#ifdef OBJ_COFF
+
+/* Map BFD relocs to SH COFF relocs. */
+
+struct reloc_map
+{
+ bfd_reloc_code_real_type bfd_reloc;
+ int sh_reloc;
+};
+
+static const struct reloc_map coff_reloc_map[] =
+{
+ { BFD_RELOC_32, R_SH_IMM32 },
+ { BFD_RELOC_16, R_SH_IMM16 },
+ { BFD_RELOC_8, R_SH_IMM8 },
+ { BFD_RELOC_SH_PCDISP8BY2, R_SH_PCDISP8BY2 },
+ { BFD_RELOC_SH_PCDISP12BY2, R_SH_PCDISP },
+ { BFD_RELOC_SH_IMM4, R_SH_IMM4 },
+ { BFD_RELOC_SH_IMM4BY2, R_SH_IMM4BY2 },
+ { BFD_RELOC_SH_IMM4BY4, R_SH_IMM4BY4 },
+ { BFD_RELOC_SH_IMM8, R_SH_IMM8 },
+ { BFD_RELOC_SH_IMM8BY2, R_SH_IMM8BY2 },
+ { BFD_RELOC_SH_IMM8BY4, R_SH_IMM8BY4 },
+ { BFD_RELOC_SH_PCRELIMM8BY2, R_SH_PCRELIMM8BY2 },
+ { BFD_RELOC_SH_PCRELIMM8BY4, R_SH_PCRELIMM8BY4 },
+ { BFD_RELOC_8_PCREL, R_SH_SWITCH8 },
+ { BFD_RELOC_SH_SWITCH16, R_SH_SWITCH16 },
+ { BFD_RELOC_SH_SWITCH32, R_SH_SWITCH32 },
+ { BFD_RELOC_SH_USES, R_SH_USES },
+ { BFD_RELOC_SH_COUNT, R_SH_COUNT },
+ { BFD_RELOC_SH_ALIGN, R_SH_ALIGN },
+ { BFD_RELOC_SH_CODE, R_SH_CODE },
+ { BFD_RELOC_SH_DATA, R_SH_DATA },
+ { BFD_RELOC_SH_LABEL, R_SH_LABEL },
+ { BFD_RELOC_UNUSED, 0 }
+};
+
+/* Adjust a reloc for the SH. This is similar to the generic code,
+ but does some minor tweaking. */
+
+void
+sh_coff_reloc_mangle (seg, fix, intr, paddr)
+ segment_info_type *seg;
+ fixS *fix;
+ struct internal_reloc *intr;
+ unsigned int paddr;
+{
+ symbolS *symbol_ptr = fix->fx_addsy;
+ symbolS *dot;
+
+ intr->r_vaddr = paddr + fix->fx_frag->fr_address + fix->fx_where;
+
+ if (! SWITCH_TABLE (fix))
+ {
+ const struct reloc_map *rm;
+
+ for (rm = coff_reloc_map; rm->bfd_reloc != BFD_RELOC_UNUSED; rm++)
+ if (rm->bfd_reloc == (bfd_reloc_code_real_type) fix->fx_r_type)
+ break;
+ if (rm->bfd_reloc == BFD_RELOC_UNUSED)
+ as_bad_where (fix->fx_file, fix->fx_line,
+ _("Can not represent %s relocation in this object file format"),
+ bfd_get_reloc_code_name (fix->fx_r_type));
+ intr->r_type = rm->sh_reloc;
+ intr->r_offset = 0;
+ }
+ else
+ {
+ know (sh_relax);
+
+ if (fix->fx_r_type == BFD_RELOC_16)
+ intr->r_type = R_SH_SWITCH16;
+ else if (fix->fx_r_type == BFD_RELOC_8)
+ intr->r_type = R_SH_SWITCH8;
+ else if (fix->fx_r_type == BFD_RELOC_32)
+ intr->r_type = R_SH_SWITCH32;
+ else
+ abort ();
+
+ /* For a switch reloc, we set r_offset to the difference between
+ the reloc address and the subtrahend. When the linker is
+ doing relaxing, it can use the determine the starting and
+ ending points of the switch difference expression. */
+ intr->r_offset = intr->r_vaddr - S_GET_VALUE (fix->fx_subsy);
+ }
+
+ /* PC relative relocs are always against the current section. */
+ if (symbol_ptr == NULL)
+ {
+ switch (fix->fx_r_type)
+ {
+ case BFD_RELOC_SH_PCRELIMM8BY2:
+ case BFD_RELOC_SH_PCRELIMM8BY4:
+ case BFD_RELOC_SH_PCDISP8BY2:
+ case BFD_RELOC_SH_PCDISP12BY2:
+ case BFD_RELOC_SH_USES:
+ symbol_ptr = seg->dot;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (fix->fx_r_type == BFD_RELOC_SH_USES)
+ {
+ /* We can't store the offset in the object file, since this
+ reloc does not take up any space, so we store it in r_offset.
+ The fx_addnumber field was set in md_apply_fix. */
+ intr->r_offset = fix->fx_addnumber;
+ }
+ else if (fix->fx_r_type == BFD_RELOC_SH_COUNT)
+ {
+ /* We can't store the count in the object file, since this reloc
+ does not take up any space, so we store it in r_offset. The
+ fx_offset field was set when the fixup was created in
+ sh_coff_frob_file. */
+ intr->r_offset = fix->fx_offset;
+ /* This reloc is always absolute. */
+ symbol_ptr = NULL;
+ }
+ else if (fix->fx_r_type == BFD_RELOC_SH_ALIGN)
+ {
+ /* Store the alignment in the r_offset field. */
+ intr->r_offset = fix->fx_offset;
+ /* This reloc is always absolute. */
+ symbol_ptr = NULL;
+ }
+ else if (fix->fx_r_type == BFD_RELOC_SH_CODE
+ || fix->fx_r_type == BFD_RELOC_SH_DATA
+ || fix->fx_r_type == BFD_RELOC_SH_LABEL)
+ {
+ /* These relocs are always absolute. */
+ symbol_ptr = NULL;
+ }
+
+ /* Turn the segment of the symbol into an offset. */
+ if (symbol_ptr != NULL)
+ {
+ dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot;
+ if (dot != NULL)
+ intr->r_symndx = dot->sy_number;
+ else
+ intr->r_symndx = symbol_ptr->sy_number;
+ }
+ else
+ intr->r_symndx = -1;
+}
+
+#endif /* OBJ_COFF */
+#endif /* ! BFD_ASSEMBLER */
+
+#ifdef BFD_ASSEMBLER
+
+/* Create a reloc. */
+
+arelent *
+tc_gen_reloc (section, fixp)
+ asection *section;
+ fixS *fixp;
+{
+ arelent *rel;
+ bfd_reloc_code_real_type r_type;
+
+ rel = (arelent *) xmalloc (sizeof (arelent));
+ rel->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+ rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
+
+ r_type = fixp->fx_r_type;
+
+ if (SWITCH_TABLE (fixp))
+ {
+ rel->addend = rel->address - S_GET_VALUE (fixp->fx_subsy);
+ if (r_type == BFD_RELOC_16)
+ r_type = BFD_RELOC_SH_SWITCH16;
+ else if (r_type == BFD_RELOC_8)
+ r_type = BFD_RELOC_8_PCREL;
+ else if (r_type == BFD_RELOC_32)
+ r_type = BFD_RELOC_SH_SWITCH32;
+ else
+ abort ();
+ }
+ else if (r_type == BFD_RELOC_SH_USES)
+ rel->addend = fixp->fx_addnumber;
+ else if (r_type == BFD_RELOC_SH_COUNT)
+ rel->addend = fixp->fx_offset;
+ else if (r_type == BFD_RELOC_SH_ALIGN)
+ rel->addend = fixp->fx_offset;
+ else if (r_type == BFD_RELOC_VTABLE_INHERIT
+ || r_type == BFD_RELOC_VTABLE_ENTRY)
+ rel->addend = fixp->fx_offset;
+ else if (fixp->fx_pcrel)
+ rel->addend = fixp->fx_addnumber;
+ else
+ rel->addend = 0;
+
+ rel->howto = bfd_reloc_type_lookup (stdoutput, r_type);
+ if (rel->howto == NULL)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("Cannot represent relocation type %s"),
+ bfd_get_reloc_code_name (r_type));
+ /* Set howto to a garbage value so that we can keep going. */
+ rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
+ assert (rel->howto != NULL);
+ }
+
+ return rel;
+}
+
+#endif /* BFD_ASSEMBLER */
diff --git a/gas/config/tc-sh.h b/gas/config/tc-sh.h
new file mode 100644
index 0000000000..cc02eab72c
--- /dev/null
+++ b/gas/config/tc-sh.h
@@ -0,0 +1,152 @@
+/* This file is tc-sh.h
+ Copyright (C) 1993, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#define TC_SH
+
+#define TARGET_BYTES_BIG_ENDIAN 0
+
+#define TARGET_ARCH bfd_arch_sh
+
+#if ANSI_PROTOTYPES
+struct segment_info_struct;
+struct internal_reloc;
+#endif
+
+/* Whether in little endian mode. */
+extern int shl;
+
+/* Whether -relax was used. */
+extern int sh_relax;
+
+/* Whether -small was used. */
+extern int sh_small;
+
+/* Don't try to break words. */
+#define WORKING_DOT_WORD
+
+/* We require .long, et. al., to be aligned correctly. */
+#define md_cons_align(nbytes) sh_cons_align (nbytes)
+extern void sh_cons_align PARAMS ((int));
+
+/* When relaxing, we need to generate relocations for alignment
+ directives. */
+#define HANDLE_ALIGN(frag) sh_handle_align (frag)
+extern void sh_handle_align PARAMS ((fragS *));
+
+/* We need to force out some relocations when relaxing. */
+#define TC_FORCE_RELOCATION(fix) sh_force_relocation (fix)
+extern int sh_force_relocation ();
+
+#ifdef OBJ_ELF
+#define obj_fix_adjustable(fixP) sh_fix_adjustable(fixP)
+#endif
+
+#define IGNORE_NONSTANDARD_ESCAPES
+
+#define LISTING_HEADER (shl ? "Hitachi Super-H GAS Little Endian" : "Hitachi Super-H GAS Big Endian")
+
+#define md_operand(x)
+
+extern const struct relax_type md_relax_table[];
+#define TC_GENERIC_RELAX_TABLE md_relax_table
+
+/* We use a special alignment function to insert the correct nop
+ pattern. */
+extern int sh_do_align PARAMS ((int, const char *, int, int));
+#define md_do_align(n,fill,len,max,l) if (sh_do_align (n,fill,len,max)) goto l
+
+/* We record, for each section, whether we have most recently output a
+ CODE reloc or a DATA reloc. */
+struct sh_segment_info_type
+{
+ int in_code : 1;
+};
+#define TC_SEGMENT_INFO_TYPE struct sh_segment_info_type
+
+/* We call a routine to emit a reloc for a label, so that the linker
+ can align loads and stores without crossing a label. */
+extern void sh_frob_label PARAMS ((void));
+#define tc_frob_label(sym) sh_frob_label ()
+
+/* We call a routine to flush pending output in order to output a DATA
+ reloc when required. */
+extern void sh_flush_pending_output PARAMS ((void));
+#define md_flush_pending_output() sh_flush_pending_output ()
+
+#ifdef BFD_ASSEMBLER
+#define tc_frob_file_before_adjust sh_frob_file
+#else
+#define tc_frob_file sh_frob_file
+#endif
+extern void sh_frob_file PARAMS ((void));
+
+#ifdef OBJ_COFF
+/* COFF specific definitions. */
+
+#define DO_NOT_STRIP 0
+
+/* This macro translates between an internal fix and an coff reloc type */
+#define TC_COFF_FIX2RTYPE(fix) ((fix)->fx_r_type)
+
+#define BFD_ARCH TARGET_ARCH
+
+#define COFF_MAGIC (shl ? SH_ARCH_MAGIC_LITTLE : SH_ARCH_MAGIC_BIG)
+
+/* We need to write out relocs which have not been completed. */
+#define TC_COUNT_RELOC(fix) ((fix)->fx_addsy != NULL)
+
+#define TC_RELOC_MANGLE(seg, fix, int, paddr) \
+ sh_coff_reloc_mangle ((seg), (fix), (int), (paddr))
+extern void sh_coff_reloc_mangle
+ PARAMS ((struct segment_info_struct *, struct fix *,
+ struct internal_reloc *, unsigned int));
+
+#define tc_coff_symbol_emit_hook(a) ; /* not used */
+
+#define NEED_FX_R_TYPE 1
+
+#define TC_KEEP_FX_OFFSET 1
+
+#define TC_COFF_SIZEMACHDEP(frag) tc_coff_sizemachdep(frag)
+extern int tc_coff_sizemachdep PARAMS ((fragS *));
+
+/* We align most sections to a 16 byte boundary. */
+#define SUB_SEGMENT_ALIGN(SEG) \
+ (strncmp (obj_segment_name (SEG), ".stabstr", 8) == 0 \
+ ? 0 \
+ : ((strncmp (obj_segment_name (SEG), ".stab", 5) == 0 \
+ || strcmp (obj_segment_name (SEG), ".ctors") == 0 \
+ || strcmp (obj_segment_name (SEG), ".dtors") == 0) \
+ ? 2 \
+ : (sh_small ? 2 : 4)))
+
+#endif /* OBJ_COFF */
+
+#ifdef OBJ_ELF
+/* ELF specific definitions. */
+
+/* Whether or not the target is big endian */
+extern int target_big_endian;
+
+#define TARGET_FORMAT (shl ? "elf32-shl" : "elf32-sh")
+
+#endif /* OBJ_ELF */
+
+/* end of tc-sh.h */
diff --git a/gas/config/tc-sparc.c b/gas/config/tc-sparc.c
new file mode 100644
index 0000000000..1518a8a34c
--- /dev/null
+++ b/gas/config/tc-sparc.c
@@ -0,0 +1,3551 @@
+/* tc-sparc.c -- Assemble for the SPARC
+ Copyright (C) 1989, 90-96, 97, 1998 Free Software Foundation, Inc.
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public
+ License along with GAS; see the file COPYING. If not, write
+ to the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include "as.h"
+#include "subsegs.h"
+
+#include "opcode/sparc.h"
+
+#ifdef OBJ_ELF
+#include "elf/sparc.h"
+#endif
+
+static struct sparc_arch *lookup_arch PARAMS ((char *));
+static void init_default_arch PARAMS ((void));
+static void sparc_ip PARAMS ((char *, const struct sparc_opcode **));
+static int in_signed_range PARAMS ((bfd_signed_vma, bfd_signed_vma));
+static int in_unsigned_range PARAMS ((bfd_vma, bfd_vma));
+static int in_bitfield_range PARAMS ((bfd_signed_vma, bfd_signed_vma));
+static int sparc_ffs PARAMS ((unsigned int));
+static bfd_vma BSR PARAMS ((bfd_vma, int));
+static int cmp_reg_entry PARAMS ((const PTR, const PTR));
+static int parse_keyword_arg PARAMS ((int (*) (const char *), char **, int *));
+static int parse_const_expr_arg PARAMS ((char **, int *));
+static int get_expression PARAMS ((char *str));
+
+/* Default architecture. */
+/* ??? The default value should be V8, but sparclite support was added
+ by making it the default. GCC now passes -Asparclite, so maybe sometime in
+ the future we can set this to V8. */
+#ifndef DEFAULT_ARCH
+#define DEFAULT_ARCH "sparclite"
+#endif
+static char *default_arch = DEFAULT_ARCH;
+
+/* Non-zero if the initial values of `max_architecture' and `sparc_arch_size'
+ have been set. */
+static int default_init_p;
+
+/* Current architecture. We don't bump up unless necessary. */
+static enum sparc_opcode_arch_val current_architecture = SPARC_OPCODE_ARCH_V6;
+
+/* The maximum architecture level we can bump up to.
+ In a 32 bit environment, don't allow bumping up to v9 by default.
+ The native assembler works this way. The user is required to pass
+ an explicit argument before we'll create v9 object files. However, if
+ we don't see any v9 insns, a v8plus object file is not created. */
+static enum sparc_opcode_arch_val max_architecture;
+
+/* Either 32 or 64, selects file format. */
+static int sparc_arch_size;
+/* Initial (default) value, recorded separately in case a user option
+ changes the value before md_show_usage is called. */
+static int default_arch_size;
+
+#ifdef OBJ_ELF
+/* The currently selected v9 memory model. Currently only used for
+ ELF. */
+static enum { MM_TSO, MM_PSO, MM_RMO } sparc_memory_model = MM_RMO;
+#endif
+
+static int architecture_requested;
+static int warn_on_bump;
+
+/* If warn_on_bump and the needed architecture is higher than this
+ architecture, issue a warning. */
+static enum sparc_opcode_arch_val warn_after_architecture;
+
+/* Non-zero if we are generating PIC code. */
+int sparc_pic_code;
+
+/* Non-zero if we should give an error when misaligned data is seen. */
+static int enforce_aligned_data;
+
+extern int target_big_endian;
+
+static int target_little_endian_data;
+
+/* V9 and 86x have big and little endian data, but instructions are always big
+ endian. The sparclet has bi-endian support but both data and insns have
+ the same endianness. Global `target_big_endian' is used for data.
+ The following macro is used for instructions. */
+#ifndef INSN_BIG_ENDIAN
+#define INSN_BIG_ENDIAN (target_big_endian \
+ || default_arch_type == sparc86x \
+ || SPARC_OPCODE_ARCH_V9_P (max_architecture))
+#endif
+
+/* handle of the OPCODE hash table */
+static struct hash_control *op_hash;
+
+static int log2 PARAMS ((int));
+static void s_data1 PARAMS ((void));
+static void s_seg PARAMS ((int));
+static void s_proc PARAMS ((int));
+static void s_reserve PARAMS ((int));
+static void s_common PARAMS ((int));
+static void s_empty PARAMS ((int));
+static void s_uacons PARAMS ((int));
+
+const pseudo_typeS md_pseudo_table[] =
+{
+ {"align", s_align_bytes, 0}, /* Defaulting is invalid (0) */
+ {"common", s_common, 0},
+ {"empty", s_empty, 0},
+ {"global", s_globl, 0},
+ {"half", cons, 2},
+ {"optim", s_ignore, 0},
+ {"proc", s_proc, 0},
+ {"reserve", s_reserve, 0},
+ {"seg", s_seg, 0},
+ {"skip", s_space, 0},
+ {"word", cons, 4},
+ {"xword", cons, 8},
+ {"uahalf", s_uacons, 2},
+ {"uaword", s_uacons, 4},
+ {"uaxword", s_uacons, 8},
+#ifdef OBJ_ELF
+ /* these are specific to sparc/svr4 */
+ {"pushsection", obj_elf_section, 0},
+ {"popsection", obj_elf_previous, 0},
+ {"2byte", s_uacons, 2},
+ {"4byte", s_uacons, 4},
+ {"8byte", s_uacons, 8},
+#endif
+ {NULL, 0, 0},
+};
+
+const int md_reloc_size = 12; /* Size of relocation record */
+
+/* This array holds the chars that always start a comment. If the
+ pre-processor is disabled, these aren't very useful */
+const char comment_chars[] = "!"; /* JF removed '|' from comment_chars */
+
+/* This array holds the chars that only start a comment at the beginning of
+ a line. If the line seems to have the form '# 123 filename'
+ .line and .file directives will appear in the pre-processed output */
+/* Note that input_file.c hand checks for '#' at the beginning of the
+ first line of the input file. This is because the compiler outputs
+ #NO_APP at the beginning of its output. */
+/* Also note that comments started like this one will always
+ work if '/' isn't otherwise defined. */
+const char line_comment_chars[] = "#";
+
+const char line_separator_chars[] = "";
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* As in 0f12.456 */
+/* or 0d1.2345e12 */
+const char FLT_CHARS[] = "rRsSfFdDxXpP";
+
+/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
+ changed in read.c. Ideally it shouldn't have to know about it at all,
+ but nothing is ideal around here. */
+
+static unsigned char octal[256];
+#define isoctal(c) octal[(unsigned char) (c)]
+static unsigned char toHex[256];
+
+struct sparc_it
+ {
+ char *error;
+ unsigned long opcode;
+ struct nlist *nlistp;
+ expressionS exp;
+ int pcrel;
+ bfd_reloc_code_real_type reloc;
+ };
+
+struct sparc_it the_insn, set_insn;
+
+static void output_insn
+ PARAMS ((const struct sparc_opcode *, struct sparc_it *));
+
+/* Table of arguments to -A.
+ The sparc_opcode_arch table in sparc-opc.c is insufficient and incorrect
+ for this use. That table is for opcodes only. This table is for opcodes
+ and file formats. */
+
+enum sparc_arch_types {v6, v7, v8, sparclet, sparclite, sparc86x, v8plus,
+ v8plusa, v9, v9a, v9_64};
+
+static struct sparc_arch {
+ char *name;
+ char *opcode_arch;
+ enum sparc_arch_types arch_type;
+ /* Default word size, as specified during configuration.
+ A value of zero means can't be used to specify default architecture. */
+ int default_arch_size;
+ /* Allowable arg to -A? */
+ int user_option_p;
+} sparc_arch_table[] = {
+ { "v6", "v6", v6, 0, 1 },
+ { "v7", "v7", v7, 0, 1 },
+ { "v8", "v8", v8, 32, 1 },
+ { "sparclet", "sparclet", sparclet, 32, 1 },
+ { "sparclite", "sparclite", sparclite, 32, 1 },
+ { "sparc86x", "sparclite", sparc86x, 32, 1 },
+ { "v8plus", "v9", v9, 0, 1 },
+ { "v8plusa", "v9a", v9, 0, 1 },
+ { "v9", "v9", v9, 0, 1 },
+ { "v9a", "v9a", v9, 0, 1 },
+ /* This exists to allow configure.in/Makefile.in to pass one
+ value to specify both the default machine and default word size. */
+ { "v9-64", "v9", v9, 64, 0 },
+ { NULL, NULL, v8, 0, 0 }
+};
+
+/* Variant of default_arch */
+static enum sparc_arch_types default_arch_type;
+
+static struct sparc_arch *
+lookup_arch (name)
+ char *name;
+{
+ struct sparc_arch *sa;
+
+ for (sa = &sparc_arch_table[0]; sa->name != NULL; sa++)
+ if (strcmp (sa->name, name) == 0)
+ break;
+ if (sa->name == NULL)
+ return NULL;
+ return sa;
+}
+
+/* Initialize the default opcode arch and word size from the default
+ architecture name. */
+
+static void
+init_default_arch ()
+{
+ struct sparc_arch *sa = lookup_arch (default_arch);
+
+ if (sa == NULL
+ || sa->default_arch_size == 0)
+ as_fatal (_("Invalid default architecture, broken assembler."));
+
+ max_architecture = sparc_opcode_lookup_arch (sa->opcode_arch);
+ if (max_architecture == SPARC_OPCODE_ARCH_BAD)
+ as_fatal (_("Bad opcode table, broken assembler."));
+ default_arch_size = sparc_arch_size = sa->default_arch_size;
+ default_init_p = 1;
+ default_arch_type = sa->arch_type;
+}
+
+/* Called by TARGET_FORMAT. */
+
+const char *
+sparc_target_format ()
+{
+ /* We don't get a chance to initialize anything before we're called,
+ so handle that now. */
+ if (! default_init_p)
+ init_default_arch ();
+
+#ifdef OBJ_AOUT
+#ifdef TE_NetBSD
+ return "a.out-sparc-netbsd";
+#else
+#ifdef TE_SPARCAOUT
+ if (target_big_endian)
+ return "a.out-sunos-big";
+ else if (default_arch_type == sparc86x && target_little_endian_data)
+ return "a.out-sunos-big";
+ else return "a.out-sparc-little";
+#else
+ return "a.out-sunos-big";
+#endif
+#endif
+#endif
+
+#ifdef OBJ_BOUT
+ return "b.out.big";
+#endif
+
+#ifdef OBJ_COFF
+#ifdef TE_LYNX
+ return "coff-sparc-lynx";
+#else
+ return "coff-sparc";
+#endif
+#endif
+
+#ifdef OBJ_ELF
+ return sparc_arch_size == 64 ? "elf64-sparc" : "elf32-sparc";
+#endif
+
+ abort ();
+}
+
+/*
+ * md_parse_option
+ * Invocation line includes a switch not recognized by the base assembler.
+ * See if it's a processor-specific option. These are:
+ *
+ * -bump
+ * Warn on architecture bumps. See also -A.
+ *
+ * -Av6, -Av7, -Av8, -Asparclite, -Asparclet
+ * Standard 32 bit architectures.
+ * -Av8plus, -Av8plusa
+ * Sparc64 in a 32 bit world.
+ * -Av9, -Av9a
+ * Sparc64 in either a 32 or 64 bit world (-32/-64 says which).
+ * This used to only mean 64 bits, but properly specifying it
+ * complicated gcc's ASM_SPECs, so now opcode selection is
+ * specified orthogonally to word size (except when specifying
+ * the default, but that is an internal implementation detail).
+ * -xarch=v8plus, -xarch=v8plusa
+ * Same as -Av8plus{,a}, for compatibility with Sun's assembler.
+ *
+ * Select the architecture and possibly the file format.
+ * Instructions or features not supported by the selected
+ * architecture cause fatal errors.
+ *
+ * The default is to start at v6, and bump the architecture up
+ * whenever an instruction is seen at a higher level. In 32 bit
+ * environments, v9 is not bumped up to, the user must pass
+ * -Av8plus{,a}.
+ *
+ * If -bump is specified, a warning is printing when bumping to
+ * higher levels.
+ *
+ * If an architecture is specified, all instructions must match
+ * that architecture. Any higher level instructions are flagged
+ * as errors. Note that in the 32 bit environment specifying
+ * -Av8plus does not automatically create a v8plus object file, a
+ * v9 insn must be seen.
+ *
+ * If both an architecture and -bump are specified, the
+ * architecture starts at the specified level, but bumps are
+ * warnings. Note that we can't set `current_architecture' to
+ * the requested level in this case: in the 32 bit environment,
+ * we still must avoid creating v8plus object files unless v9
+ * insns are seen.
+ *
+ * Note:
+ * Bumping between incompatible architectures is always an
+ * error. For example, from sparclite to v9.
+ */
+
+#ifdef OBJ_ELF
+CONST char *md_shortopts = "A:K:VQ:sq";
+#else
+#ifdef OBJ_AOUT
+CONST char *md_shortopts = "A:k";
+#else
+CONST char *md_shortopts = "A:";
+#endif
+#endif
+struct option md_longopts[] = {
+#define OPTION_BUMP (OPTION_MD_BASE)
+ {"bump", no_argument, NULL, OPTION_BUMP},
+#define OPTION_SPARC (OPTION_MD_BASE + 1)
+ {"sparc", no_argument, NULL, OPTION_SPARC},
+#define OPTION_XARCH (OPTION_MD_BASE + 2)
+ {"xarch", required_argument, NULL, OPTION_XARCH},
+#ifdef OBJ_ELF
+#define OPTION_32 (OPTION_MD_BASE + 3)
+ {"32", no_argument, NULL, OPTION_32},
+#define OPTION_64 (OPTION_MD_BASE + 4)
+ {"64", no_argument, NULL, OPTION_64},
+#define OPTION_TSO (OPTION_MD_BASE + 5)
+ {"TSO", no_argument, NULL, OPTION_TSO},
+#define OPTION_PSO (OPTION_MD_BASE + 6)
+ {"PSO", no_argument, NULL, OPTION_PSO},
+#define OPTION_RMO (OPTION_MD_BASE + 7)
+ {"RMO", no_argument, NULL, OPTION_RMO},
+#endif
+#ifdef SPARC_BIENDIAN
+#define OPTION_LITTLE_ENDIAN (OPTION_MD_BASE + 8)
+ {"EL", no_argument, NULL, OPTION_LITTLE_ENDIAN},
+#define OPTION_BIG_ENDIAN (OPTION_MD_BASE + 9)
+ {"EB", no_argument, NULL, OPTION_BIG_ENDIAN},
+#endif
+#define OPTION_ENFORCE_ALIGNED_DATA (OPTION_MD_BASE + 10)
+ {"enforce-aligned-data", no_argument, NULL, OPTION_ENFORCE_ALIGNED_DATA},
+#define OPTION_LITTLE_ENDIAN_DATA (OPTION_MD_BASE + 11)
+ {"little-endian-data", no_argument, NULL, OPTION_LITTLE_ENDIAN_DATA},
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof(md_longopts);
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ /* We don't get a chance to initialize anything before we're called,
+ so handle that now. */
+ if (! default_init_p)
+ init_default_arch ();
+
+ switch (c)
+ {
+ case OPTION_BUMP:
+ warn_on_bump = 1;
+ warn_after_architecture = SPARC_OPCODE_ARCH_V6;
+ break;
+
+ case OPTION_XARCH:
+ /* This is for compatibility with Sun's assembler. */
+ if (strcmp (arg, "v8plus") != 0
+ && strcmp (arg, "v8plusa") != 0)
+ {
+ as_bad (_("invalid architecture -xarch=%s"), arg);
+ return 0;
+ }
+
+ /* fall through */
+
+ case 'A':
+ {
+ struct sparc_arch *sa;
+ enum sparc_opcode_arch_val opcode_arch;
+
+ sa = lookup_arch (arg);
+ if (sa == NULL
+ || ! sa->user_option_p)
+ {
+ as_bad (_("invalid architecture -A%s"), arg);
+ return 0;
+ }
+
+ opcode_arch = sparc_opcode_lookup_arch (sa->opcode_arch);
+ if (opcode_arch == SPARC_OPCODE_ARCH_BAD)
+ as_fatal (_("Bad opcode table, broken assembler."));
+
+ max_architecture = opcode_arch;
+ architecture_requested = 1;
+ }
+ break;
+
+ case OPTION_SPARC:
+ /* Ignore -sparc, used by SunOS make default .s.o rule. */
+ break;
+
+ case OPTION_ENFORCE_ALIGNED_DATA:
+ enforce_aligned_data = 1;
+ break;
+
+#ifdef SPARC_BIENDIAN
+ case OPTION_LITTLE_ENDIAN:
+ target_big_endian = 0;
+ if (default_arch_type != sparclet)
+ as_fatal ("This target does not support -EL");
+ break;
+ case OPTION_LITTLE_ENDIAN_DATA:
+ target_little_endian_data = 1;
+ target_big_endian = 0;
+ if (default_arch_type != sparc86x
+ && default_arch_type != v9)
+ as_fatal ("This target does not support --little-endian-data");
+ break;
+ case OPTION_BIG_ENDIAN:
+ target_big_endian = 1;
+ break;
+#endif
+
+#ifdef OBJ_AOUT
+ case 'k':
+ sparc_pic_code = 1;
+ break;
+#endif
+
+#ifdef OBJ_ELF
+ case OPTION_32:
+ case OPTION_64:
+ {
+ const char **list, **l;
+
+ sparc_arch_size = c == OPTION_32 ? 32 : 64;
+ list = bfd_target_list ();
+ for (l = list; *l != NULL; l++)
+ {
+ if (sparc_arch_size == 32)
+ {
+ if (strcmp (*l, "elf32-sparc") == 0)
+ break;
+ }
+ else
+ {
+ if (strcmp (*l, "elf64-sparc") == 0)
+ break;
+ }
+ }
+ if (*l == NULL)
+ as_fatal (_("No compiled in support for %d bit object file format"),
+ sparc_arch_size);
+ free (list);
+ }
+ break;
+
+ case OPTION_TSO:
+ sparc_memory_model = MM_TSO;
+ break;
+
+ case OPTION_PSO:
+ sparc_memory_model = MM_PSO;
+ break;
+
+ case OPTION_RMO:
+ sparc_memory_model = MM_RMO;
+ break;
+
+ case 'V':
+ print_version_id ();
+ break;
+
+ case 'Q':
+ /* Qy - do emit .comment
+ Qn - do not emit .comment */
+ break;
+
+ case 's':
+ /* use .stab instead of .stab.excl */
+ break;
+
+ case 'q':
+ /* quick -- native assembler does fewer checks */
+ break;
+
+ case 'K':
+ if (strcmp (arg, "PIC") != 0)
+ as_warn (_("Unrecognized option following -K"));
+ else
+ sparc_pic_code = 1;
+ break;
+#endif
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+ const struct sparc_arch *arch;
+
+ /* We don't get a chance to initialize anything before we're called,
+ so handle that now. */
+ if (! default_init_p)
+ init_default_arch ();
+
+ fprintf(stream, _("SPARC options:\n"));
+ for (arch = &sparc_arch_table[0]; arch->name; arch++)
+ {
+ if (arch != &sparc_arch_table[0])
+ fprintf (stream, " | ");
+ if (arch->user_option_p)
+ fprintf (stream, "-A%s", arch->name);
+ }
+ fprintf (stream, _("\n-xarch=v8plus | -xarch=v8plusa\n"));
+ fprintf (stream, _("\
+ specify variant of SPARC architecture\n\
+-bump warn when assembler switches architectures\n\
+-sparc ignored\n\
+--enforce-aligned-data force .long, etc., to be aligned correctly\n"));
+#ifdef OBJ_AOUT
+ fprintf (stream, _("\
+-k generate PIC\n"));
+#endif
+#ifdef OBJ_ELF
+ fprintf (stream, _("\
+-32 create 32 bit object file\n\
+-64 create 64 bit object file\n"));
+ fprintf (stream, _("\
+ [default is %d]\n"), default_arch_size);
+ fprintf (stream, _("\
+-TSO use Total Store Ordering\n\
+-PSO use Partial Store Ordering\n\
+-RMO use Relaxed Memory Ordering\n"));
+ fprintf (stream, _("\
+ [default is %s]\n"), (default_arch_size == 64) ? "RMO" : "TSO");
+ fprintf (stream, _("\
+-KPIC generate PIC\n\
+-V print assembler version number\n\
+-q ignored\n\
+-Qy, -Qn ignored\n\
+-s ignored\n"));
+#endif
+#ifdef SPARC_BIENDIAN
+ fprintf (stream, _("\
+-EL generate code for a little endian machine\n\
+-EB generate code for a big endian machine\n\
+--little-endian-data generate code for a machine having big endian\n\
+ instructions and little endian data."));
+#endif
+}
+
+/* sparc64 priviledged registers */
+
+struct priv_reg_entry
+ {
+ char *name;
+ int regnum;
+ };
+
+struct priv_reg_entry priv_reg_table[] =
+{
+ {"tpc", 0},
+ {"tnpc", 1},
+ {"tstate", 2},
+ {"tt", 3},
+ {"tick", 4},
+ {"tba", 5},
+ {"pstate", 6},
+ {"tl", 7},
+ {"pil", 8},
+ {"cwp", 9},
+ {"cansave", 10},
+ {"canrestore", 11},
+ {"cleanwin", 12},
+ {"otherwin", 13},
+ {"wstate", 14},
+ {"fq", 15},
+ {"ver", 31},
+ {"", -1}, /* end marker */
+};
+
+/* v9a specific asrs */
+
+struct priv_reg_entry v9a_asr_table[] =
+{
+ {"tick_cmpr", 23},
+ {"softint", 22},
+ {"set_softint", 20},
+ {"pic", 17},
+ {"pcr", 16},
+ {"gsr", 19},
+ {"dcr", 18},
+ {"clear_softint", 21},
+ {"", -1}, /* end marker */
+};
+
+static int
+cmp_reg_entry (parg, qarg)
+ const PTR parg;
+ const PTR qarg;
+{
+ const struct priv_reg_entry *p = (const struct priv_reg_entry *) parg;
+ const struct priv_reg_entry *q = (const struct priv_reg_entry *) qarg;
+
+ return strcmp (q->name, p->name);
+}
+
+/* This function is called once, at assembler startup time. It should
+ set up all the tables, etc. that the MD part of the assembler will need. */
+
+void
+md_begin ()
+{
+ register const char *retval = NULL;
+ int lose = 0;
+ register unsigned int i = 0;
+
+ /* We don't get a chance to initialize anything before md_parse_option
+ is called, and it may not be called, so handle default initialization
+ now if not already done. */
+ if (! default_init_p)
+ init_default_arch ();
+
+ op_hash = hash_new ();
+
+ while (i < (unsigned int) sparc_num_opcodes)
+ {
+ const char *name = sparc_opcodes[i].name;
+ retval = hash_insert (op_hash, name, (PTR) &sparc_opcodes[i]);
+ if (retval != NULL)
+ {
+ fprintf (stderr, _("internal error: can't hash `%s': %s\n"),
+ sparc_opcodes[i].name, retval);
+ lose = 1;
+ }
+ do
+ {
+ if (sparc_opcodes[i].match & sparc_opcodes[i].lose)
+ {
+ fprintf (stderr, _("internal error: losing opcode: `%s' \"%s\"\n"),
+ sparc_opcodes[i].name, sparc_opcodes[i].args);
+ lose = 1;
+ }
+ ++i;
+ }
+ while (i < (unsigned int) sparc_num_opcodes
+ && !strcmp (sparc_opcodes[i].name, name));
+ }
+
+ if (lose)
+ as_fatal (_("Broken assembler. No assembly attempted."));
+
+ for (i = '0'; i < '8'; ++i)
+ octal[i] = 1;
+ for (i = '0'; i <= '9'; ++i)
+ toHex[i] = i - '0';
+ for (i = 'a'; i <= 'f'; ++i)
+ toHex[i] = i + 10 - 'a';
+ for (i = 'A'; i <= 'F'; ++i)
+ toHex[i] = i + 10 - 'A';
+
+ qsort (priv_reg_table, sizeof (priv_reg_table) / sizeof (priv_reg_table[0]),
+ sizeof (priv_reg_table[0]), cmp_reg_entry);
+
+ /* If -bump, record the architecture level at which we start issuing
+ warnings. The behaviour is different depending upon whether an
+ architecture was explicitly specified. If it wasn't, we issue warnings
+ for all upwards bumps. If it was, we don't start issuing warnings until
+ we need to bump beyond the requested architecture or when we bump between
+ conflicting architectures. */
+
+ if (warn_on_bump
+ && architecture_requested)
+ {
+ /* `max_architecture' records the requested architecture.
+ Issue warnings if we go above it. */
+ warn_after_architecture = max_architecture;
+
+ /* Find the highest architecture level that doesn't conflict with
+ the requested one. */
+ for (max_architecture = SPARC_OPCODE_ARCH_MAX;
+ max_architecture > warn_after_architecture;
+ --max_architecture)
+ if (! SPARC_OPCODE_CONFLICT_P (max_architecture,
+ warn_after_architecture))
+ break;
+ }
+}
+
+/* Called after all assembly has been done. */
+
+void
+sparc_md_end ()
+{
+ if (sparc_arch_size == 64)
+ {
+ if (current_architecture == SPARC_OPCODE_ARCH_V9A)
+ bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v9a);
+ else
+ bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v9);
+ }
+ else
+ {
+ if (current_architecture == SPARC_OPCODE_ARCH_V9)
+ bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v8plus);
+ else if (current_architecture == SPARC_OPCODE_ARCH_V9A)
+ bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v8plusa);
+ else if (current_architecture == SPARC_OPCODE_ARCH_SPARCLET)
+ bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_sparclet);
+ else if (default_arch_type == sparc86x && target_little_endian_data)
+ bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_sparclite_le);
+ else
+ {
+ /* The sparclite is treated like a normal sparc. Perhaps it shouldn't
+ be but for now it is (since that's the way it's always been
+ treated). */
+ bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc);
+ }
+ }
+}
+
+/* Return non-zero if VAL is in the range -(MAX+1) to MAX. */
+
+static INLINE int
+in_signed_range (val, max)
+ bfd_signed_vma val, max;
+{
+ if (max <= 0)
+ abort ();
+ /* Sign-extend the value from the architecture word size, so that
+ 0xffffffff is always considered -1 on sparc32. */
+ if (sparc_arch_size == 32)
+ {
+ bfd_signed_vma sign = (bfd_signed_vma)1 << 31;
+ val = ((val & 0xffffffff) ^ sign) - sign;
+ }
+ if (val > max)
+ return 0;
+ if (val < ~max)
+ return 0;
+ return 1;
+}
+
+/* Return non-zero if VAL is in the range 0 to MAX. */
+
+static INLINE int
+in_unsigned_range (val, max)
+ bfd_vma val, max;
+{
+ if (val > max)
+ return 0;
+ return 1;
+}
+
+/* Return non-zero if VAL is in the range -(MAX/2+1) to MAX.
+ (e.g. -15 to +31). */
+
+static INLINE int
+in_bitfield_range (val, max)
+ bfd_signed_vma val, max;
+{
+ if (max <= 0)
+ abort ();
+ if (val > max)
+ return 0;
+ if (val < ~(max >> 1))
+ return 0;
+ return 1;
+}
+
+static int
+sparc_ffs (mask)
+ unsigned int mask;
+{
+ int i;
+
+ if (mask == 0)
+ return -1;
+
+ for (i = 0; (mask & 1) == 0; ++i)
+ mask >>= 1;
+ return i;
+}
+
+/* Implement big shift right. */
+static bfd_vma
+BSR (val, amount)
+ bfd_vma val;
+ int amount;
+{
+ if (sizeof (bfd_vma) <= 4 && amount >= 32)
+ as_fatal (_("Support for 64-bit arithmetic not compiled in."));
+ return val >> amount;
+}
+
+/* For communication between sparc_ip and get_expression. */
+static char *expr_end;
+
+/* For communication between md_assemble and sparc_ip. */
+static int special_case;
+
+/* Values for `special_case'.
+ Instructions that require wierd handling because they're longer than
+ 4 bytes. */
+#define SPECIAL_CASE_NONE 0
+#define SPECIAL_CASE_SET 1
+#define SPECIAL_CASE_SETSW 2
+#define SPECIAL_CASE_SETX 3
+/* FIXME: sparc-opc.c doesn't have necessary "S" trigger to enable this. */
+#define SPECIAL_CASE_FDIV 4
+
+/* Bit masks of various insns. */
+#define NOP_INSN 0x01000000
+#define OR_INSN 0x80100000
+#define FMOVS_INSN 0x81A00020
+#define SETHI_INSN 0x01000000
+#define SLLX_INSN 0x81281000
+#define SRA_INSN 0x81380000
+
+/* The last instruction to be assembled. */
+static const struct sparc_opcode *last_insn;
+/* The assembled opcode of `last_insn'. */
+static unsigned long last_opcode;
+
+/* Main entry point to assemble one instruction. */
+
+void
+md_assemble (str)
+ char *str;
+{
+ const struct sparc_opcode *insn;
+
+ know (str);
+ special_case = SPECIAL_CASE_NONE;
+ sparc_ip (str, &insn);
+
+ /* We warn about attempts to put a floating point branch in a delay slot,
+ unless the delay slot has been annulled. */
+ if (insn != NULL
+ && last_insn != NULL
+ && (insn->flags & F_FBR) != 0
+ && (last_insn->flags & F_DELAYED) != 0
+ /* ??? This test isn't completely accurate. We assume anything with
+ F_{UNBR,CONDBR,FBR} set is annullable. */
+ && ((last_insn->flags & (F_UNBR | F_CONDBR | F_FBR)) == 0
+ || (last_opcode & ANNUL) == 0))
+ as_warn (_("FP branch in delay slot"));
+
+ /* SPARC before v9 requires a nop instruction between a floating
+ point instruction and a floating point branch. We insert one
+ automatically, with a warning. */
+ if (max_architecture < SPARC_OPCODE_ARCH_V9
+ && insn != NULL
+ && last_insn != NULL
+ && (insn->flags & F_FBR) != 0
+ && (last_insn->flags & F_FLOAT) != 0)
+ {
+ struct sparc_it nop_insn;
+
+ nop_insn.opcode = NOP_INSN;
+ nop_insn.reloc = BFD_RELOC_NONE;
+ output_insn (insn, &nop_insn);
+ as_warn (_("FP branch preceded by FP instruction; NOP inserted"));
+ }
+
+ switch (special_case)
+ {
+ case SPECIAL_CASE_NONE:
+ /* normal insn */
+ output_insn (insn, &the_insn);
+ break;
+
+ case SPECIAL_CASE_SET:
+ {
+ int need_hi22_p = 0;
+
+ /* "set" is not defined for negative numbers in v9: it doesn't yield
+ what you expect it to. */
+ if (SPARC_OPCODE_ARCH_V9_P (max_architecture)
+ && the_insn.exp.X_op == O_constant)
+ {
+ if (the_insn.exp.X_add_number < 0)
+ as_warn (_("set: used with negative number"));
+ else if (the_insn.exp.X_add_number > (offsetT) 0xffffffff)
+ as_warn (_("set: number larger than 4294967295"));
+ }
+
+ /* See if operand is absolute and small; skip sethi if so. */
+ if (the_insn.exp.X_op != O_constant
+ || the_insn.exp.X_add_number >= (1 << 12)
+ || the_insn.exp.X_add_number < -(1 << 12))
+ {
+ output_insn (insn, &the_insn);
+ need_hi22_p = 1;
+ }
+ /* See if operand has no low-order bits; skip OR if so. */
+ if (the_insn.exp.X_op != O_constant
+ || (need_hi22_p && (the_insn.exp.X_add_number & 0x3FF) != 0)
+ || ! need_hi22_p)
+ {
+ int rd = (the_insn.opcode & RD (~0)) >> 25;
+ the_insn.opcode = (OR_INSN | (need_hi22_p ? RS1 (rd) : 0)
+ | RD (rd)
+ | IMMED
+ | (the_insn.exp.X_add_number
+ & (need_hi22_p ? 0x3ff : 0x1fff)));
+ the_insn.reloc = (the_insn.exp.X_op != O_constant
+ ? BFD_RELOC_LO10
+ : BFD_RELOC_NONE);
+ output_insn (insn, &the_insn);
+ }
+ break;
+ }
+
+ case SPECIAL_CASE_SETSW:
+ {
+ /* FIXME: Not finished. */
+ break;
+ }
+
+ case SPECIAL_CASE_SETX:
+ {
+#define SIGNEXT32(x) ((((x) & 0xffffffff) ^ 0x80000000) - 0x80000000)
+ int upper32 = SIGNEXT32 (BSR (the_insn.exp.X_add_number, 32));
+ int lower32 = SIGNEXT32 (the_insn.exp.X_add_number);
+#undef SIGNEXT32
+ int tmpreg = (the_insn.opcode & RS1 (~0)) >> 14;
+ int dstreg = (the_insn.opcode & RD (~0)) >> 25;
+ /* Output directly to dst reg if lower 32 bits are all zero. */
+ int upper_dstreg = (the_insn.exp.X_op == O_constant
+ && lower32 == 0) ? dstreg : tmpreg;
+ int need_hh22_p = 0, need_hm10_p = 0, need_hi22_p = 0, need_lo10_p = 0;
+
+ /* The tmp reg should not be the dst reg. */
+ if (tmpreg == dstreg)
+ as_warn (_("setx: temporary register same as destination register"));
+
+ /* Reset X_add_number, we've extracted it as upper32/lower32.
+ Otherwise fixup_segment will complain about not being able to
+ write an 8 byte number in a 4 byte field. */
+ the_insn.exp.X_add_number = 0;
+
+ /* ??? Obviously there are other optimizations we can do
+ (e.g. sethi+shift for 0x1f0000000) and perhaps we shouldn't be
+ doing some of these. Later. If you do change things, try to
+ change all of this to be table driven as well. */
+
+ /* What to output depends on the number if it's constant.
+ Compute that first, then output what we've decided upon. */
+ if (the_insn.exp.X_op != O_constant)
+ need_hh22_p = need_hm10_p = need_hi22_p = need_lo10_p = 1;
+ else
+ {
+ /* Only need hh22 if `or' insn can't handle constant. */
+ if (upper32 < -(1 << 12) || upper32 >= (1 << 12))
+ need_hh22_p = 1;
+
+ /* Does bottom part (after sethi) have bits? */
+ if ((need_hh22_p && (upper32 & 0x3ff) != 0)
+ /* No hh22, but does upper32 still have bits we can't set
+ from lower32? */
+ || (! need_hh22_p
+ && upper32 != 0
+ && (upper32 != -1 || lower32 >= 0)))
+ need_hm10_p = 1;
+
+ /* If the lower half is all zero, we build the upper half directly
+ into the dst reg. */
+ if (lower32 != 0
+ /* Need lower half if number is zero. */
+ || (! need_hh22_p && ! need_hm10_p))
+ {
+ /* No need for sethi if `or' insn can handle constant. */
+ if (lower32 < -(1 << 12) || lower32 >= (1 << 12)
+ /* Note that we can't use a negative constant in the `or'
+ insn unless the upper 32 bits are all ones. */
+ || (lower32 < 0 && upper32 != -1))
+ need_hi22_p = 1;
+
+ /* Does bottom part (after sethi) have bits? */
+ if ((need_hi22_p && (lower32 & 0x3ff) != 0)
+ /* No sethi. */
+ || (! need_hi22_p && (lower32 & 0x1fff) != 0)
+ /* Need `or' if we didn't set anything else. */
+ || (! need_hi22_p && ! need_hh22_p && ! need_hm10_p))
+ need_lo10_p = 1;
+ }
+ }
+
+ if (need_hh22_p)
+ {
+ the_insn.opcode = (SETHI_INSN | RD (upper_dstreg)
+ | ((upper32 >> 10) & 0x3fffff));
+ the_insn.reloc = (the_insn.exp.X_op != O_constant
+ ? BFD_RELOC_SPARC_HH22 : BFD_RELOC_NONE);
+ output_insn (insn, &the_insn);
+ }
+
+ if (need_hm10_p)
+ {
+ the_insn.opcode = (OR_INSN
+ | (need_hh22_p ? RS1 (upper_dstreg) : 0)
+ | RD (upper_dstreg)
+ | IMMED
+ | (upper32
+ & (need_hh22_p ? 0x3ff : 0x1fff)));
+ the_insn.reloc = (the_insn.exp.X_op != O_constant
+ ? BFD_RELOC_SPARC_HM10 : BFD_RELOC_NONE);
+ output_insn (insn, &the_insn);
+ }
+
+ if (need_hi22_p)
+ {
+ the_insn.opcode = (SETHI_INSN | RD (dstreg)
+ | ((lower32 >> 10) & 0x3fffff));
+ the_insn.reloc = BFD_RELOC_HI22;
+ output_insn (insn, &the_insn);
+ }
+
+ if (need_lo10_p)
+ {
+ /* FIXME: One nice optimization to do here is to OR the low part
+ with the highpart if hi22 isn't needed and the low part is
+ positive. */
+ the_insn.opcode = (OR_INSN | (need_hi22_p ? RS1 (dstreg) : 0)
+ | RD (dstreg)
+ | IMMED
+ | (lower32
+ & (need_hi22_p ? 0x3ff : 0x1fff)));
+ the_insn.reloc = BFD_RELOC_LO10;
+ output_insn (insn, &the_insn);
+ }
+
+ /* If we needed to build the upper part, shift it into place. */
+ if (need_hh22_p || need_hm10_p)
+ {
+ the_insn.opcode = (SLLX_INSN | RS1 (upper_dstreg) | RD (upper_dstreg)
+ | IMMED | 32);
+ the_insn.reloc = BFD_RELOC_NONE;
+ output_insn (insn, &the_insn);
+ }
+
+ /* If we needed to build both upper and lower parts, OR them together. */
+ if ((need_hh22_p || need_hm10_p)
+ && (need_hi22_p || need_lo10_p))
+ {
+ the_insn.opcode = (OR_INSN | RS1 (dstreg) | RS2 (upper_dstreg)
+ | RD (dstreg));
+ the_insn.reloc = BFD_RELOC_NONE;
+ output_insn (insn, &the_insn);
+ }
+ /* We didn't need both regs, but we may have to sign extend lower32. */
+ else if (need_hi22_p && upper32 == -1)
+ {
+ the_insn.opcode = (SRA_INSN | RS1 (dstreg) | RD (dstreg)
+ | IMMED | 0);
+ the_insn.reloc = BFD_RELOC_NONE;
+ output_insn (insn, &the_insn);
+ }
+ break;
+ }
+
+ case SPECIAL_CASE_FDIV:
+ {
+ int rd = (the_insn.opcode >> 25) & 0x1f;
+
+ output_insn (insn, &the_insn);
+
+ /* According to information leaked from Sun, the "fdiv" instructions
+ on early SPARC machines would produce incorrect results sometimes.
+ The workaround is to add an fmovs of the destination register to
+ itself just after the instruction. This was true on machines
+ with Weitek 1165 float chips, such as the Sun-4/260 and /280. */
+ assert (the_insn.reloc == BFD_RELOC_NONE);
+ the_insn.opcode = FMOVS_INSN | rd | RD (rd);
+ output_insn (insn, &the_insn);
+ break;
+ }
+
+ default:
+ as_fatal (_("failed special case insn sanity check"));
+ }
+}
+
+/* Subroutine of md_assemble to do the actual parsing. */
+
+static void
+sparc_ip (str, pinsn)
+ char *str;
+ const struct sparc_opcode **pinsn;
+{
+ char *error_message = "";
+ char *s;
+ const char *args;
+ char c;
+ const struct sparc_opcode *insn;
+ char *argsStart;
+ unsigned long opcode;
+ unsigned int mask = 0;
+ int match = 0;
+ int comma = 0;
+ int v9_arg_p;
+
+ s = str;
+ if (islower ((unsigned char) *s))
+ {
+ do
+ ++s;
+ while (islower ((unsigned char) *s) || isdigit ((unsigned char) *s));
+ }
+
+ switch (*s)
+ {
+ case '\0':
+ break;
+
+ case ',':
+ comma = 1;
+
+ /*FALLTHROUGH */
+
+ case ' ':
+ *s++ = '\0';
+ break;
+
+ default:
+ as_fatal (_("Unknown opcode: `%s'"), str);
+ }
+ insn = (struct sparc_opcode *) hash_find (op_hash, str);
+ *pinsn = insn;
+ if (insn == NULL)
+ {
+ as_bad (_("Unknown opcode: `%s'"), str);
+ return;
+ }
+ if (comma)
+ {
+ *--s = ',';
+ }
+
+ argsStart = s;
+ for (;;)
+ {
+ opcode = insn->match;
+ memset (&the_insn, '\0', sizeof (the_insn));
+ the_insn.reloc = BFD_RELOC_NONE;
+ v9_arg_p = 0;
+
+ /*
+ * Build the opcode, checking as we go to make
+ * sure that the operands match
+ */
+ for (args = insn->args;; ++args)
+ {
+ switch (*args)
+ {
+ case 'K':
+ {
+ int kmask = 0;
+
+ /* Parse a series of masks. */
+ if (*s == '#')
+ {
+ while (*s == '#')
+ {
+ int mask;
+
+ if (! parse_keyword_arg (sparc_encode_membar, &s,
+ &mask))
+ {
+ error_message = _(": invalid membar mask name");
+ goto error;
+ }
+ kmask |= mask;
+ while (*s == ' ') { ++s; continue; }
+ if (*s == '|' || *s == '+')
+ ++s;
+ while (*s == ' ') { ++s; continue; }
+ }
+ }
+ else
+ {
+ if (! parse_const_expr_arg (&s, &kmask))
+ {
+ error_message = _(": invalid membar mask expression");
+ goto error;
+ }
+ if (kmask < 0 || kmask > 127)
+ {
+ error_message = _(": invalid membar mask number");
+ goto error;
+ }
+ }
+
+ opcode |= MEMBAR (kmask);
+ continue;
+ }
+
+ case '*':
+ {
+ int fcn = 0;
+
+ /* Parse a prefetch function. */
+ if (*s == '#')
+ {
+ if (! parse_keyword_arg (sparc_encode_prefetch, &s, &fcn))
+ {
+ error_message = _(": invalid prefetch function name");
+ goto error;
+ }
+ }
+ else
+ {
+ if (! parse_const_expr_arg (&s, &fcn))
+ {
+ error_message = _(": invalid prefetch function expression");
+ goto error;
+ }
+ if (fcn < 0 || fcn > 31)
+ {
+ error_message = _(": invalid prefetch function number");
+ goto error;
+ }
+ }
+ opcode |= RD (fcn);
+ continue;
+ }
+
+ case '!':
+ case '?':
+ /* Parse a sparc64 privileged register. */
+ if (*s == '%')
+ {
+ struct priv_reg_entry *p = priv_reg_table;
+ unsigned int len = 9999999; /* init to make gcc happy */
+
+ s += 1;
+ while (p->name[0] > s[0])
+ p++;
+ while (p->name[0] == s[0])
+ {
+ len = strlen (p->name);
+ if (strncmp (p->name, s, len) == 0)
+ break;
+ p++;
+ }
+ if (p->name[0] != s[0])
+ {
+ error_message = _(": unrecognizable privileged register");
+ goto error;
+ }
+ if (*args == '?')
+ opcode |= (p->regnum << 14);
+ else
+ opcode |= (p->regnum << 25);
+ s += len;
+ continue;
+ }
+ else
+ {
+ error_message = _(": unrecognizable privileged register");
+ goto error;
+ }
+
+ case '_':
+ case '/':
+ /* Parse a v9a ancillary state register. */
+ if (*s == '%')
+ {
+ struct priv_reg_entry *p = v9a_asr_table;
+ unsigned int len = 9999999; /* init to make gcc happy */
+
+ s += 1;
+ while (p->name[0] > s[0])
+ p++;
+ while (p->name[0] == s[0])
+ {
+ len = strlen (p->name);
+ if (strncmp (p->name, s, len) == 0)
+ break;
+ p++;
+ }
+ if (p->name[0] != s[0])
+ {
+ error_message = _(": unrecognizable v9a ancillary state register");
+ goto error;
+ }
+ if (*args == '/' && (p->regnum == 20 || p->regnum == 21))
+ {
+ error_message = _(": rd on write only ancillary state register");
+ goto error;
+ }
+ if (*args == '/')
+ opcode |= (p->regnum << 14);
+ else
+ opcode |= (p->regnum << 25);
+ s += len;
+ continue;
+ }
+ else
+ {
+ error_message = _(": unrecognizable v9a ancillary state register");
+ goto error;
+ }
+
+ case 'M':
+ case 'm':
+ if (strncmp (s, "%asr", 4) == 0)
+ {
+ s += 4;
+
+ if (isdigit ((unsigned char) *s))
+ {
+ long num = 0;
+
+ while (isdigit ((unsigned char) *s))
+ {
+ num = num * 10 + *s - '0';
+ ++s;
+ }
+
+ if (current_architecture >= SPARC_OPCODE_ARCH_V9)
+ {
+ if (num < 16 || 31 < num)
+ {
+ error_message = _(": asr number must be between 16 and 31");
+ goto error;
+ }
+ }
+ else
+ {
+ if (num < 0 || 31 < num)
+ {
+ error_message = _(": asr number must be between 0 and 31");
+ goto error;
+ }
+ }
+
+ opcode |= (*args == 'M' ? RS1 (num) : RD (num));
+ continue;
+ }
+ else
+ {
+ error_message = _(": expecting %asrN");
+ goto error;
+ }
+ } /* if %asr */
+ break;
+
+ case 'I':
+ the_insn.reloc = BFD_RELOC_SPARC_11;
+ goto immediate;
+
+ case 'j':
+ the_insn.reloc = BFD_RELOC_SPARC_10;
+ goto immediate;
+
+ case 'X':
+ /* V8 systems don't understand BFD_RELOC_SPARC_5. */
+ if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
+ the_insn.reloc = BFD_RELOC_SPARC_5;
+ else
+ the_insn.reloc = BFD_RELOC_SPARC13;
+ /* These fields are unsigned, but for upward compatibility,
+ allow negative values as well. */
+ goto immediate;
+
+ case 'Y':
+ /* V8 systems don't understand BFD_RELOC_SPARC_6. */
+ if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
+ the_insn.reloc = BFD_RELOC_SPARC_6;
+ else
+ the_insn.reloc = BFD_RELOC_SPARC13;
+ /* These fields are unsigned, but for upward compatibility,
+ allow negative values as well. */
+ goto immediate;
+
+ case 'k':
+ the_insn.reloc = /* RELOC_WDISP2_14 */ BFD_RELOC_SPARC_WDISP16;
+ the_insn.pcrel = 1;
+ goto immediate;
+
+ case 'G':
+ the_insn.reloc = BFD_RELOC_SPARC_WDISP19;
+ the_insn.pcrel = 1;
+ goto immediate;
+
+ case 'N':
+ if (*s == 'p' && s[1] == 'n')
+ {
+ s += 2;
+ continue;
+ }
+ break;
+
+ case 'T':
+ if (*s == 'p' && s[1] == 't')
+ {
+ s += 2;
+ continue;
+ }
+ break;
+
+ case 'z':
+ if (*s == ' ')
+ {
+ ++s;
+ }
+ if (strncmp (s, "%icc", 4) == 0)
+ {
+ s += 4;
+ continue;
+ }
+ break;
+
+ case 'Z':
+ if (*s == ' ')
+ {
+ ++s;
+ }
+ if (strncmp (s, "%xcc", 4) == 0)
+ {
+ s += 4;
+ continue;
+ }
+ break;
+
+ case '6':
+ if (*s == ' ')
+ {
+ ++s;
+ }
+ if (strncmp (s, "%fcc0", 5) == 0)
+ {
+ s += 5;
+ continue;
+ }
+ break;
+
+ case '7':
+ if (*s == ' ')
+ {
+ ++s;
+ }
+ if (strncmp (s, "%fcc1", 5) == 0)
+ {
+ s += 5;
+ continue;
+ }
+ break;
+
+ case '8':
+ if (*s == ' ')
+ {
+ ++s;
+ }
+ if (strncmp (s, "%fcc2", 5) == 0)
+ {
+ s += 5;
+ continue;
+ }
+ break;
+
+ case '9':
+ if (*s == ' ')
+ {
+ ++s;
+ }
+ if (strncmp (s, "%fcc3", 5) == 0)
+ {
+ s += 5;
+ continue;
+ }
+ break;
+
+ case 'P':
+ if (strncmp (s, "%pc", 3) == 0)
+ {
+ s += 3;
+ continue;
+ }
+ break;
+
+ case 'W':
+ if (strncmp (s, "%tick", 5) == 0)
+ {
+ s += 5;
+ continue;
+ }
+ break;
+
+ case '\0': /* end of args */
+ if (*s == '\0')
+ {
+ match = 1;
+ }
+ break;
+
+ case '+':
+ if (*s == '+')
+ {
+ ++s;
+ continue;
+ }
+ if (*s == '-')
+ {
+ continue;
+ }
+ break;
+
+ case '[': /* these must match exactly */
+ case ']':
+ case ',':
+ case ' ':
+ if (*s++ == *args)
+ continue;
+ break;
+
+ case '#': /* must be at least one digit */
+ if (isdigit ((unsigned char) *s++))
+ {
+ while (isdigit ((unsigned char) *s))
+ {
+ ++s;
+ }
+ continue;
+ }
+ break;
+
+ case 'C': /* coprocessor state register */
+ if (strncmp (s, "%csr", 4) == 0)
+ {
+ s += 4;
+ continue;
+ }
+ break;
+
+ case 'b': /* next operand is a coprocessor register */
+ case 'c':
+ case 'D':
+ if (*s++ == '%' && *s++ == 'c' && isdigit ((unsigned char) *s))
+ {
+ mask = *s++;
+ if (isdigit ((unsigned char) *s))
+ {
+ mask = 10 * (mask - '0') + (*s++ - '0');
+ if (mask >= 32)
+ {
+ break;
+ }
+ }
+ else
+ {
+ mask -= '0';
+ }
+ switch (*args)
+ {
+
+ case 'b':
+ opcode |= mask << 14;
+ continue;
+
+ case 'c':
+ opcode |= mask;
+ continue;
+
+ case 'D':
+ opcode |= mask << 25;
+ continue;
+ }
+ }
+ break;
+
+ case 'r': /* next operand must be a register */
+ case 'O':
+ case '1':
+ case '2':
+ case 'd':
+ if (*s++ == '%')
+ {
+ switch (c = *s++)
+ {
+
+ case 'f': /* frame pointer */
+ if (*s++ == 'p')
+ {
+ mask = 0x1e;
+ break;
+ }
+ goto error;
+
+ case 'g': /* global register */
+ if (isoctal (c = *s++))
+ {
+ mask = c - '0';
+ break;
+ }
+ goto error;
+
+ case 'i': /* in register */
+ if (isoctal (c = *s++))
+ {
+ mask = c - '0' + 24;
+ break;
+ }
+ goto error;
+
+ case 'l': /* local register */
+ if (isoctal (c = *s++))
+ {
+ mask = (c - '0' + 16);
+ break;
+ }
+ goto error;
+
+ case 'o': /* out register */
+ if (isoctal (c = *s++))
+ {
+ mask = (c - '0' + 8);
+ break;
+ }
+ goto error;
+
+ case 's': /* stack pointer */
+ if (*s++ == 'p')
+ {
+ mask = 0xe;
+ break;
+ }
+ goto error;
+
+ case 'r': /* any register */
+ if (!isdigit ((unsigned char) (c = *s++)))
+ {
+ goto error;
+ }
+ /* FALLTHROUGH */
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (isdigit ((unsigned char) *s))
+ {
+ if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32)
+ {
+ goto error;
+ }
+ }
+ else
+ {
+ c -= '0';
+ }
+ mask = c;
+ break;
+
+ default:
+ goto error;
+ }
+
+ /* Got the register, now figure out where
+ it goes in the opcode. */
+ switch (*args)
+ {
+ case '1':
+ opcode |= mask << 14;
+ continue;
+
+ case '2':
+ opcode |= mask;
+ continue;
+
+ case 'd':
+ opcode |= mask << 25;
+ continue;
+
+ case 'r':
+ opcode |= (mask << 25) | (mask << 14);
+ continue;
+
+ case 'O':
+ opcode |= (mask << 25) | (mask << 0);
+ continue;
+ }
+ }
+ break;
+
+ case 'e': /* next operand is a floating point register */
+ case 'v':
+ case 'V':
+
+ case 'f':
+ case 'B':
+ case 'R':
+
+ case 'g':
+ case 'H':
+ case 'J':
+ {
+ char format;
+
+ if (*s++ == '%'
+ && ((format = *s) == 'f')
+ && isdigit ((unsigned char) *++s))
+ {
+ for (mask = 0; isdigit ((unsigned char) *s); ++s)
+ {
+ mask = 10 * mask + (*s - '0');
+ } /* read the number */
+
+ if ((*args == 'v'
+ || *args == 'B'
+ || *args == 'H')
+ && (mask & 1))
+ {
+ break;
+ } /* register must be even numbered */
+
+ if ((*args == 'V'
+ || *args == 'R'
+ || *args == 'J')
+ && (mask & 3))
+ {
+ break;
+ } /* register must be multiple of 4 */
+
+ if (mask >= 64)
+ {
+ if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
+ error_message = _(": There are only 64 f registers; [0-63]");
+ else
+ error_message = _(": There are only 32 f registers; [0-31]");
+ goto error;
+ } /* on error */
+ else if (mask >= 32)
+ {
+ if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
+ {
+ v9_arg_p = 1;
+ mask -= 31; /* wrap high bit */
+ }
+ else
+ {
+ error_message = _(": There are only 32 f registers; [0-31]");
+ goto error;
+ }
+ }
+ }
+ else
+ {
+ break;
+ } /* if not an 'f' register. */
+
+ switch (*args)
+ {
+ case 'v':
+ case 'V':
+ case 'e':
+ opcode |= RS1 (mask);
+ continue;
+
+
+ case 'f':
+ case 'B':
+ case 'R':
+ opcode |= RS2 (mask);
+ continue;
+
+ case 'g':
+ case 'H':
+ case 'J':
+ opcode |= RD (mask);
+ continue;
+ } /* pack it in. */
+
+ know (0);
+ break;
+ } /* float arg */
+
+ case 'F':
+ if (strncmp (s, "%fsr", 4) == 0)
+ {
+ s += 4;
+ continue;
+ }
+ break;
+
+ case '0': /* 64 bit immediate (setx insn) */
+ the_insn.reloc = BFD_RELOC_NONE; /* reloc handled elsewhere */
+ goto immediate;
+
+ case 'h': /* high 22 bits */
+ the_insn.reloc = BFD_RELOC_HI22;
+ goto immediate;
+
+ case 'l': /* 22 bit PC relative immediate */
+ the_insn.reloc = BFD_RELOC_SPARC_WDISP22;
+ the_insn.pcrel = 1;
+ goto immediate;
+
+ case 'L': /* 30 bit immediate */
+ the_insn.reloc = BFD_RELOC_32_PCREL_S2;
+ the_insn.pcrel = 1;
+ goto immediate;
+
+ case 'n': /* 22 bit immediate */
+ the_insn.reloc = BFD_RELOC_SPARC22;
+ goto immediate;
+
+ case 'i': /* 13 bit immediate */
+ the_insn.reloc = BFD_RELOC_SPARC13;
+
+ /* fallthrough */
+
+ immediate:
+ if (*s == ' ')
+ s++;
+
+ /* Check for %hi, etc. */
+ if (*s == '%')
+ {
+ static struct ops {
+ /* The name as it appears in assembler. */
+ char *name;
+ /* strlen (name), precomputed for speed */
+ int len;
+ /* The reloc this pseudo-op translates to. */
+ int reloc;
+ /* Non-zero if for v9 only. */
+ int v9_p;
+ /* Non-zero if can be used in pc-relative contexts. */
+ int pcrel_p;/*FIXME:wip*/
+ } ops[] = {
+ /* hix/lox must appear before hi/lo so %hix won't be
+ mistaken for %hi. */
+ { "hix", 3, BFD_RELOC_SPARC_HIX22, 1, 0 },
+ { "lox", 3, BFD_RELOC_SPARC_LOX10, 1, 0 },
+ { "hi", 2, BFD_RELOC_HI22, 0, 1 },
+ { "lo", 2, BFD_RELOC_LO10, 0, 1 },
+ { "hh", 2, BFD_RELOC_SPARC_HH22, 1, 1 },
+ { "hm", 2, BFD_RELOC_SPARC_HM10, 1, 1 },
+ { "lm", 2, BFD_RELOC_SPARC_LM22, 1, 1 },
+ { "h44", 3, BFD_RELOC_SPARC_H44, 1, 0 },
+ { "m44", 3, BFD_RELOC_SPARC_M44, 1, 0 },
+ { "l44", 3, BFD_RELOC_SPARC_L44, 1, 0 },
+ { "uhi", 3, BFD_RELOC_SPARC_HH22, 1, 0 },
+ { "ulo", 3, BFD_RELOC_SPARC_HM10, 1, 0 },
+ { NULL }
+ };
+ struct ops *o;
+
+ for (o = ops; o->name; o++)
+ if (strncmp (s + 1, o->name, o->len) == 0)
+ break;
+ if (o->name == NULL)
+ break;
+
+ the_insn.reloc = o->reloc;
+ s += o->len + 1;
+ v9_arg_p = o->v9_p;
+ }
+
+ /* Note that if the get_expression() fails, we will still
+ have created U entries in the symbol table for the
+ 'symbols' in the input string. Try not to create U
+ symbols for registers, etc. */
+ {
+ /* This stuff checks to see if the expression ends in
+ +%reg. If it does, it removes the register from
+ the expression, and re-sets 's' to point to the
+ right place. */
+
+ char *s1;
+
+ for (s1 = s; *s1 && *s1 != ',' && *s1 != ']'; s1++) ;
+
+ if (s1 != s && isdigit ((unsigned char) s1[-1]))
+ {
+ if (s1[-2] == '%' && s1[-3] == '+')
+ {
+ s1 -= 3;
+ *s1 = '\0';
+ (void) get_expression (s);
+ *s1 = '+';
+ s = s1;
+ continue;
+ }
+ else if (strchr ("goli0123456789", s1[-2]) && s1[-3] == '%' && s1[-4] == '+')
+ {
+ s1 -= 4;
+ *s1 = '\0';
+ (void) get_expression (s);
+ *s1 = '+';
+ s = s1;
+ continue;
+ }
+ }
+ }
+ (void) get_expression (s);
+ s = expr_end;
+
+ /* Check for constants that don't require emitting a reloc. */
+ if (the_insn.exp.X_op == O_constant
+ && the_insn.exp.X_add_symbol == 0
+ && the_insn.exp.X_op_symbol == 0)
+ {
+ /* For pc-relative call instructions, we reject
+ constants to get better code. */
+ if (the_insn.pcrel
+ && the_insn.reloc == BFD_RELOC_32_PCREL_S2
+ && in_signed_range (the_insn.exp.X_add_number, 0x3fff))
+ {
+ error_message = _(": PC-relative operand can't be a constant");
+ goto error;
+ }
+
+ /* Constants that won't fit are checked in md_apply_fix3
+ and bfd_install_relocation.
+ ??? It would be preferable to install the constants
+ into the insn here and save having to create a fixS
+ for each one. There already exists code to handle
+ all the various cases (e.g. in md_apply_fix3 and
+ bfd_install_relocation) so duplicating all that code
+ here isn't right. */
+ }
+
+ continue;
+
+ case 'a':
+ if (*s++ == 'a')
+ {
+ opcode |= ANNUL;
+ continue;
+ }
+ break;
+
+ case 'A':
+ {
+ int asi = 0;
+
+ /* Parse an asi. */
+ if (*s == '#')
+ {
+ if (! parse_keyword_arg (sparc_encode_asi, &s, &asi))
+ {
+ error_message = _(": invalid ASI name");
+ goto error;
+ }
+ }
+ else
+ {
+ if (! parse_const_expr_arg (&s, &asi))
+ {
+ error_message = _(": invalid ASI expression");
+ goto error;
+ }
+ if (asi < 0 || asi > 255)
+ {
+ error_message = _(": invalid ASI number");
+ goto error;
+ }
+ }
+ opcode |= ASI (asi);
+ continue;
+ } /* alternate space */
+
+ case 'p':
+ if (strncmp (s, "%psr", 4) == 0)
+ {
+ s += 4;
+ continue;
+ }
+ break;
+
+ case 'q': /* floating point queue */
+ if (strncmp (s, "%fq", 3) == 0)
+ {
+ s += 3;
+ continue;
+ }
+ break;
+
+ case 'Q': /* coprocessor queue */
+ if (strncmp (s, "%cq", 3) == 0)
+ {
+ s += 3;
+ continue;
+ }
+ break;
+
+ case 'S':
+ if (strcmp (str, "set") == 0
+ || strcmp (str, "setuw") == 0)
+ {
+ special_case = SPECIAL_CASE_SET;
+ continue;
+ }
+ else if (strcmp (str, "setsw") == 0)
+ {
+ special_case = SPECIAL_CASE_SETSW;
+ continue;
+ }
+ else if (strcmp (str, "setx") == 0)
+ {
+ special_case = SPECIAL_CASE_SETX;
+ continue;
+ }
+ else if (strncmp (str, "fdiv", 4) == 0)
+ {
+ special_case = SPECIAL_CASE_FDIV;
+ continue;
+ }
+ break;
+
+ case 'o':
+ if (strncmp (s, "%asi", 4) != 0)
+ break;
+ s += 4;
+ continue;
+
+ case 's':
+ if (strncmp (s, "%fprs", 5) != 0)
+ break;
+ s += 5;
+ continue;
+
+ case 'E':
+ if (strncmp (s, "%ccr", 4) != 0)
+ break;
+ s += 4;
+ continue;
+
+ case 't':
+ if (strncmp (s, "%tbr", 4) != 0)
+ break;
+ s += 4;
+ continue;
+
+ case 'w':
+ if (strncmp (s, "%wim", 4) != 0)
+ break;
+ s += 4;
+ continue;
+
+ case 'x':
+ {
+ char *push = input_line_pointer;
+ expressionS e;
+
+ input_line_pointer = s;
+ expression (&e);
+ if (e.X_op == O_constant)
+ {
+ int n = e.X_add_number;
+ if (n != e.X_add_number || (n & ~0x1ff) != 0)
+ as_bad (_("OPF immediate operand out of range (0-0x1ff)"));
+ else
+ opcode |= e.X_add_number << 5;
+ }
+ else
+ as_bad (_("non-immediate OPF operand, ignored"));
+ s = input_line_pointer;
+ input_line_pointer = push;
+ continue;
+ }
+
+ case 'y':
+ if (strncmp (s, "%y", 2) != 0)
+ break;
+ s += 2;
+ continue;
+
+ case 'u':
+ case 'U':
+ {
+ /* Parse a sparclet cpreg. */
+ int cpreg;
+ if (! parse_keyword_arg (sparc_encode_sparclet_cpreg, &s, &cpreg))
+ {
+ error_message = _(": invalid cpreg name");
+ goto error;
+ }
+ opcode |= (*args == 'U' ? RS1 (cpreg) : RD (cpreg));
+ continue;
+ }
+
+ default:
+ as_fatal (_("failed sanity check."));
+ } /* switch on arg code */
+
+ /* Break out of for() loop. */
+ break;
+ } /* for each arg that we expect */
+
+ error:
+ if (match == 0)
+ {
+ /* Args don't match. */
+ if (&insn[1] - sparc_opcodes < sparc_num_opcodes
+ && (insn->name == insn[1].name
+ || !strcmp (insn->name, insn[1].name)))
+ {
+ ++insn;
+ s = argsStart;
+ continue;
+ }
+ else
+ {
+ as_bad (_("Illegal operands%s"), error_message);
+ return;
+ }
+ }
+ else
+ {
+ /* We have a match. Now see if the architecture is ok. */
+ int needed_arch_mask = insn->architecture;
+
+ if (v9_arg_p)
+ {
+ needed_arch_mask &= ~ ((1 << SPARC_OPCODE_ARCH_V9)
+ | (1 << SPARC_OPCODE_ARCH_V9A));
+ needed_arch_mask |= (1 << SPARC_OPCODE_ARCH_V9);
+ }
+
+ if (needed_arch_mask & SPARC_OPCODE_SUPPORTED (current_architecture))
+ ; /* ok */
+ /* Can we bump up the architecture? */
+ else if (needed_arch_mask & SPARC_OPCODE_SUPPORTED (max_architecture))
+ {
+ enum sparc_opcode_arch_val needed_architecture =
+ sparc_ffs (SPARC_OPCODE_SUPPORTED (max_architecture)
+ & needed_arch_mask);
+
+ assert (needed_architecture <= SPARC_OPCODE_ARCH_MAX);
+ if (warn_on_bump
+ && needed_architecture > warn_after_architecture)
+ {
+ as_warn (_("architecture bumped from \"%s\" to \"%s\" on \"%s\""),
+ sparc_opcode_archs[current_architecture].name,
+ sparc_opcode_archs[needed_architecture].name,
+ str);
+ warn_after_architecture = needed_architecture;
+ }
+ current_architecture = needed_architecture;
+ }
+ /* Conflict. */
+ /* ??? This seems to be a bit fragile. What if the next entry in
+ the opcode table is the one we want and it is supported?
+ It is possible to arrange the table today so that this can't
+ happen but what about tomorrow? */
+ else
+ {
+ int arch,printed_one_p = 0;
+ char *p;
+ char required_archs[SPARC_OPCODE_ARCH_MAX * 16];
+
+ /* Create a list of the architectures that support the insn. */
+ needed_arch_mask &= ~ SPARC_OPCODE_SUPPORTED (max_architecture);
+ p = required_archs;
+ arch = sparc_ffs (needed_arch_mask);
+ while ((1 << arch) <= needed_arch_mask)
+ {
+ if ((1 << arch) & needed_arch_mask)
+ {
+ if (printed_one_p)
+ *p++ = '|';
+ strcpy (p, sparc_opcode_archs[arch].name);
+ p += strlen (p);
+ printed_one_p = 1;
+ }
+ ++arch;
+ }
+
+ as_bad (_("Architecture mismatch on \"%s\"."), str);
+ as_tsktsk (_(" (Requires %s; requested architecture is %s.)"),
+ required_archs,
+ sparc_opcode_archs[max_architecture].name);
+ return;
+ }
+ } /* if no match */
+
+ break;
+ } /* forever looking for a match */
+
+ the_insn.opcode = opcode;
+}
+
+/* Parse an argument that can be expressed as a keyword.
+ (eg: #StoreStore or %ccfr).
+ The result is a boolean indicating success.
+ If successful, INPUT_POINTER is updated. */
+
+static int
+parse_keyword_arg (lookup_fn, input_pointerP, valueP)
+ int (*lookup_fn) PARAMS ((const char *));
+ char **input_pointerP;
+ int *valueP;
+{
+ int value;
+ char c, *p, *q;
+
+ p = *input_pointerP;
+ for (q = p + (*p == '#' || *p == '%');
+ isalnum ((unsigned char) *q) || *q == '_';
+ ++q)
+ continue;
+ c = *q;
+ *q = 0;
+ value = (*lookup_fn) (p);
+ *q = c;
+ if (value == -1)
+ return 0;
+ *valueP = value;
+ *input_pointerP = q;
+ return 1;
+}
+
+/* Parse an argument that is a constant expression.
+ The result is a boolean indicating success. */
+
+static int
+parse_const_expr_arg (input_pointerP, valueP)
+ char **input_pointerP;
+ int *valueP;
+{
+ char *save = input_line_pointer;
+ expressionS exp;
+
+ input_line_pointer = *input_pointerP;
+ /* The next expression may be something other than a constant
+ (say if we're not processing the right variant of the insn).
+ Don't call expression unless we're sure it will succeed as it will
+ signal an error (which we want to defer until later). */
+ /* FIXME: It might be better to define md_operand and have it recognize
+ things like %asi, etc. but continuing that route through to the end
+ is a lot of work. */
+ if (*input_line_pointer == '%')
+ {
+ input_line_pointer = save;
+ return 0;
+ }
+ expression (&exp);
+ *input_pointerP = input_line_pointer;
+ input_line_pointer = save;
+ if (exp.X_op != O_constant)
+ return 0;
+ *valueP = exp.X_add_number;
+ return 1;
+}
+
+/* Subroutine of sparc_ip to parse an expression. */
+
+static int
+get_expression (str)
+ char *str;
+{
+ char *save_in;
+ segT seg;
+
+ save_in = input_line_pointer;
+ input_line_pointer = str;
+ seg = expression (&the_insn.exp);
+ if (seg != absolute_section
+ && seg != text_section
+ && seg != data_section
+ && seg != bss_section
+ && seg != undefined_section)
+ {
+ the_insn.error = _("bad segment");
+ expr_end = input_line_pointer;
+ input_line_pointer = save_in;
+ return 1;
+ }
+ expr_end = input_line_pointer;
+ input_line_pointer = save_in;
+ return 0;
+}
+
+/* Subroutine of md_assemble to output one insn. */
+
+static void
+output_insn (insn, the_insn)
+ const struct sparc_opcode *insn;
+ struct sparc_it *the_insn;
+{
+ char *toP = frag_more (4);
+
+ /* put out the opcode */
+ if (INSN_BIG_ENDIAN)
+ number_to_chars_bigendian (toP, (valueT) the_insn->opcode, 4);
+ else
+ number_to_chars_littleendian (toP, (valueT) the_insn->opcode, 4);
+
+ /* put out the symbol-dependent stuff */
+ if (the_insn->reloc != BFD_RELOC_NONE)
+ {
+ fixS *fixP = fix_new_exp (frag_now, /* which frag */
+ (toP - frag_now->fr_literal), /* where */
+ 4, /* size */
+ &the_insn->exp,
+ the_insn->pcrel,
+ the_insn->reloc);
+ /* Turn off overflow checking in fixup_segment. We'll do our
+ own overflow checking in md_apply_fix3. This is necessary because
+ the insn size is 4 and fixup_segment will signal an overflow for
+ large 8 byte quantities. */
+ fixP->fx_no_overflow = 1;
+ }
+
+ last_insn = insn;
+ last_opcode = the_insn->opcode;
+}
+
+/*
+ This is identical to the md_atof in m68k.c. I think this is right,
+ but I'm not sure.
+
+ Turn a string in input_line_pointer into a floating point constant of type
+ type, and store the appropriate bytes in *litP. The number of LITTLENUMS
+ emitted is stored in *sizeP . An error message is returned, or NULL on OK.
+ */
+
+/* Equal to MAX_PRECISION in atof-ieee.c */
+#define MAX_LITTLENUMS 6
+
+char *
+md_atof (type, litP, sizeP)
+ char type;
+ char *litP;
+ int *sizeP;
+{
+ int i,prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ char *t;
+
+ switch (type)
+ {
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ prec = 4;
+ break;
+
+ case 'x':
+ case 'X':
+ prec = 6;
+ break;
+
+ case 'p':
+ case 'P':
+ prec = 6;
+ break;
+
+ default:
+ *sizeP = 0;
+ return _("Bad call to MD_ATOF()");
+ }
+
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+ *sizeP = prec * sizeof (LITTLENUM_TYPE);
+
+ if (target_big_endian)
+ {
+ for (i = 0; i < prec; i++)
+ {
+ md_number_to_chars (litP, (valueT) words[i], sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+ }
+ else
+ {
+ for (i = prec - 1; i >= 0; i--)
+ {
+ md_number_to_chars (litP, (valueT) words[i], sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+ }
+
+ return 0;
+}
+
+/* Write a value out to the object file, using the appropriate
+ endianness. */
+
+void
+md_number_to_chars (buf, val, n)
+ char *buf;
+ valueT val;
+ int n;
+{
+ if (target_big_endian)
+ number_to_chars_bigendian (buf, val, n);
+ else if (target_little_endian_data
+ && ((n == 4 || n == 2) && ~now_seg->flags & SEC_ALLOC))
+ /* Output debug words, which are not in allocated sections, as big endian */
+ number_to_chars_bigendian (buf, val, n);
+ else if (target_little_endian_data || ! target_big_endian)
+ number_to_chars_littleendian (buf, val, n);
+}
+
+/* Apply a fixS to the frags, now that we know the value it ought to
+ hold. */
+
+int
+md_apply_fix3 (fixP, value, segment)
+ fixS *fixP;
+ valueT *value;
+ segT segment;
+{
+ char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
+ offsetT val;
+ long insn;
+
+ val = *value;
+
+ assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
+
+ fixP->fx_addnumber = val; /* Remember value for emit_reloc */
+
+#ifdef OBJ_ELF
+ /* FIXME: SPARC ELF relocations don't use an addend in the data
+ field itself. This whole approach should be somehow combined
+ with the calls to bfd_install_relocation. Also, the value passed
+ in by fixup_segment includes the value of a defined symbol. We
+ don't want to include the value of an externally visible symbol. */
+ if (fixP->fx_addsy != NULL)
+ {
+ if (fixP->fx_addsy->sy_used_in_reloc
+ && (S_IS_EXTERNAL (fixP->fx_addsy)
+ || S_IS_WEAK (fixP->fx_addsy)
+ || (sparc_pic_code && ! fixP->fx_pcrel)
+ || (S_GET_SEGMENT (fixP->fx_addsy) != segment
+ && ((bfd_get_section_flags (stdoutput,
+ S_GET_SEGMENT (fixP->fx_addsy))
+ & SEC_LINK_ONCE) != 0
+ || strncmp (segment_name (S_GET_SEGMENT (fixP->fx_addsy)),
+ ".gnu.linkonce",
+ sizeof ".gnu.linkonce" - 1) == 0)))
+ && S_GET_SEGMENT (fixP->fx_addsy) != absolute_section
+ && S_GET_SEGMENT (fixP->fx_addsy) != undefined_section
+ && ! bfd_is_com_section (S_GET_SEGMENT (fixP->fx_addsy)))
+ fixP->fx_addnumber -= S_GET_VALUE (fixP->fx_addsy);
+ return 1;
+ }
+#endif
+
+ /* This is a hack. There should be a better way to
+ handle this. Probably in terms of howto fields, once
+ we can look at these fixups in terms of howtos. */
+ if (fixP->fx_r_type == BFD_RELOC_32_PCREL_S2 && fixP->fx_addsy)
+ val += fixP->fx_where + fixP->fx_frag->fr_address;
+
+#ifdef OBJ_AOUT
+ /* FIXME: More ridiculous gas reloc hacking. If we are going to
+ generate a reloc, then we just want to let the reloc addend set
+ the value. We do not want to also stuff the addend into the
+ object file. Including the addend in the object file works when
+ doing a static link, because the linker will ignore the object
+ file contents. However, the dynamic linker does not ignore the
+ object file contents. */
+ if (fixP->fx_addsy != NULL
+ && fixP->fx_r_type != BFD_RELOC_32_PCREL_S2)
+ val = 0;
+
+ /* When generating PIC code, we do not want an addend for a reloc
+ against a local symbol. We adjust fx_addnumber to cancel out the
+ value already included in val, and to also cancel out the
+ adjustment which bfd_install_relocation will create. */
+ if (sparc_pic_code
+ && fixP->fx_r_type != BFD_RELOC_32_PCREL_S2
+ && fixP->fx_addsy != NULL
+ && ! S_IS_COMMON (fixP->fx_addsy)
+ && (fixP->fx_addsy->bsym->flags & BSF_SECTION_SYM) == 0)
+ fixP->fx_addnumber -= 2 * S_GET_VALUE (fixP->fx_addsy);
+
+ /* When generating PIC code, we need to fiddle to get
+ bfd_install_relocation to do the right thing for a PC relative
+ reloc against a local symbol which we are going to keep. */
+ if (sparc_pic_code
+ && fixP->fx_r_type == BFD_RELOC_32_PCREL_S2
+ && fixP->fx_addsy != NULL
+ && (S_IS_EXTERNAL (fixP->fx_addsy)
+ || S_IS_WEAK (fixP->fx_addsy))
+ && S_IS_DEFINED (fixP->fx_addsy)
+ && ! S_IS_COMMON (fixP->fx_addsy))
+ {
+ val = 0;
+ fixP->fx_addnumber -= 2 * S_GET_VALUE (fixP->fx_addsy);
+ }
+#endif
+
+ /* If this is a data relocation, just output VAL. */
+
+ if (fixP->fx_r_type == BFD_RELOC_16)
+ {
+ md_number_to_chars (buf, val, 2);
+ }
+ else if (fixP->fx_r_type == BFD_RELOC_32
+ || fixP->fx_r_type == BFD_RELOC_SPARC_REV32)
+ {
+ md_number_to_chars (buf, val, 4);
+ }
+ else if (fixP->fx_r_type == BFD_RELOC_64)
+ {
+ md_number_to_chars (buf, val, 8);
+ }
+ else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ {
+ fixP->fx_done = 0;
+ return 1;
+ }
+ else
+ {
+ /* It's a relocation against an instruction. */
+
+ if (INSN_BIG_ENDIAN)
+ insn = bfd_getb32 ((unsigned char *) buf);
+ else
+ insn = bfd_getl32 ((unsigned char *) buf);
+
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_32_PCREL_S2:
+ val = val >> 2;
+ /* FIXME: This increment-by-one deserves a comment of why it's
+ being done! */
+ if (! sparc_pic_code
+ || fixP->fx_addsy == NULL
+ || (fixP->fx_addsy->bsym->flags & BSF_SECTION_SYM) != 0)
+ ++val;
+ insn |= val & 0x3fffffff;
+ break;
+
+ case BFD_RELOC_SPARC_11:
+ if (! in_signed_range (val, 0x7ff))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("relocation overflow"));
+ insn |= val & 0x7ff;
+ break;
+
+ case BFD_RELOC_SPARC_10:
+ if (! in_signed_range (val, 0x3ff))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("relocation overflow"));
+ insn |= val & 0x3ff;
+ break;
+
+ case BFD_RELOC_SPARC_7:
+ if (! in_bitfield_range (val, 0x7f))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("relocation overflow"));
+ insn |= val & 0x7f;
+ break;
+
+ case BFD_RELOC_SPARC_6:
+ if (! in_bitfield_range (val, 0x3f))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("relocation overflow"));
+ insn |= val & 0x3f;
+ break;
+
+ case BFD_RELOC_SPARC_5:
+ if (! in_bitfield_range (val, 0x1f))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("relocation overflow"));
+ insn |= val & 0x1f;
+ break;
+
+ case BFD_RELOC_SPARC_WDISP16:
+ /* FIXME: simplify */
+ if (((val > 0) && (val & ~0x3fffc))
+ || ((val < 0) && (~(val - 1) & ~0x3fffc)))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("relocation overflow"));
+ /* FIXME: The +1 deserves a comment. */
+ val = (val >> 2) + 1;
+ insn |= ((val & 0xc000) << 6) | (val & 0x3fff);
+ break;
+
+ case BFD_RELOC_SPARC_WDISP19:
+ /* FIXME: simplify */
+ if (((val > 0) && (val & ~0x1ffffc))
+ || ((val < 0) && (~(val - 1) & ~0x1ffffc)))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("relocation overflow"));
+ /* FIXME: The +1 deserves a comment. */
+ val = (val >> 2) + 1;
+ insn |= val & 0x7ffff;
+ break;
+
+ case BFD_RELOC_SPARC_HH22:
+ val = BSR (val, 32);
+ /* intentional fallthrough */
+
+ case BFD_RELOC_SPARC_LM22:
+ case BFD_RELOC_HI22:
+ if (!fixP->fx_addsy)
+ {
+ insn |= (val >> 10) & 0x3fffff;
+ }
+ else
+ {
+ /* FIXME: Need comment explaining why we do this. */
+ insn &= ~0xffff;
+ }
+ break;
+
+ case BFD_RELOC_SPARC22:
+ if (val & ~0x003fffff)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("relocation overflow"));
+ insn |= (val & 0x3fffff);
+ break;
+
+ case BFD_RELOC_SPARC_HM10:
+ val = BSR (val, 32);
+ /* intentional fallthrough */
+
+ case BFD_RELOC_LO10:
+ if (!fixP->fx_addsy)
+ {
+ insn |= val & 0x3ff;
+ }
+ else
+ {
+ /* FIXME: Need comment explaining why we do this. */
+ insn &= ~0xff;
+ }
+ break;
+
+ case BFD_RELOC_SPARC13:
+ if (! in_signed_range (val, 0x1fff))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("relocation overflow"));
+ insn |= val & 0x1fff;
+ break;
+
+ case BFD_RELOC_SPARC_WDISP22:
+ val = (val >> 2) + 1;
+ /* FALLTHROUGH */
+ case BFD_RELOC_SPARC_BASE22:
+ insn |= val & 0x3fffff;
+ break;
+
+ case BFD_RELOC_SPARC_H44:
+ if (!fixP->fx_addsy)
+ {
+ bfd_vma tval = val;
+ tval >>= 22;
+ insn |= tval & 0x3fffff;
+ }
+ break;
+
+ case BFD_RELOC_SPARC_M44:
+ if (!fixP->fx_addsy)
+ insn |= (val >> 12) & 0x3ff;
+ break;
+
+ case BFD_RELOC_SPARC_L44:
+ if (!fixP->fx_addsy)
+ insn |= val & 0xfff;
+ break;
+
+ case BFD_RELOC_SPARC_HIX22:
+ if (!fixP->fx_addsy)
+ {
+ val ^= ~ (offsetT) 0;
+ insn |= (val >> 10) & 0x3fffff;
+ }
+ break;
+
+ case BFD_RELOC_SPARC_LOX10:
+ if (!fixP->fx_addsy)
+ insn |= 0x1c00 | (val & 0x3ff);
+ break;
+
+ case BFD_RELOC_NONE:
+ default:
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("bad or unhandled relocation type: 0x%02x"),
+ fixP->fx_r_type);
+ break;
+ }
+
+ if (INSN_BIG_ENDIAN)
+ bfd_putb32 (insn, (unsigned char *) buf);
+ else
+ bfd_putl32 (insn, (unsigned char *) buf);
+ }
+
+ /* Are we finished with this relocation now? */
+ if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
+ fixP->fx_done = 1;
+
+ return 1;
+}
+
+/* Translate internal representation of relocation info to BFD target
+ format. */
+arelent *
+tc_gen_reloc (section, fixp)
+ asection *section;
+ fixS *fixp;
+{
+ arelent *reloc;
+ bfd_reloc_code_real_type code;
+
+ reloc = (arelent *) xmalloc (sizeof (arelent));
+
+ reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+ reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+
+ switch (fixp->fx_r_type)
+ {
+ case BFD_RELOC_16:
+ case BFD_RELOC_32:
+ case BFD_RELOC_HI22:
+ case BFD_RELOC_LO10:
+ case BFD_RELOC_32_PCREL_S2:
+ case BFD_RELOC_SPARC13:
+ case BFD_RELOC_SPARC_BASE13:
+ case BFD_RELOC_SPARC_WDISP16:
+ case BFD_RELOC_SPARC_WDISP19:
+ case BFD_RELOC_SPARC_WDISP22:
+ case BFD_RELOC_64:
+ case BFD_RELOC_SPARC_5:
+ case BFD_RELOC_SPARC_6:
+ case BFD_RELOC_SPARC_7:
+ case BFD_RELOC_SPARC_10:
+ case BFD_RELOC_SPARC_11:
+ case BFD_RELOC_SPARC_HH22:
+ case BFD_RELOC_SPARC_HM10:
+ case BFD_RELOC_SPARC_LM22:
+ case BFD_RELOC_SPARC_PC_HH22:
+ case BFD_RELOC_SPARC_PC_HM10:
+ case BFD_RELOC_SPARC_PC_LM22:
+ case BFD_RELOC_SPARC_H44:
+ case BFD_RELOC_SPARC_M44:
+ case BFD_RELOC_SPARC_L44:
+ case BFD_RELOC_SPARC_HIX22:
+ case BFD_RELOC_SPARC_LOX10:
+ case BFD_RELOC_SPARC_REV32:
+ case BFD_RELOC_VTABLE_ENTRY:
+ case BFD_RELOC_VTABLE_INHERIT:
+ code = fixp->fx_r_type;
+ break;
+ default:
+ abort ();
+ return NULL;
+ }
+
+#if defined (OBJ_ELF) || defined (OBJ_AOUT)
+ /* If we are generating PIC code, we need to generate a different
+ set of relocs. */
+
+#ifdef OBJ_ELF
+#define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
+#else
+#define GOT_NAME "__GLOBAL_OFFSET_TABLE_"
+#endif
+
+ if (sparc_pic_code)
+ {
+ switch (code)
+ {
+ case BFD_RELOC_32_PCREL_S2:
+ if (! S_IS_DEFINED (fixp->fx_addsy)
+ || S_IS_COMMON (fixp->fx_addsy)
+ || S_IS_EXTERNAL (fixp->fx_addsy)
+ || S_IS_WEAK (fixp->fx_addsy))
+ code = BFD_RELOC_SPARC_WPLT30;
+ break;
+ case BFD_RELOC_HI22:
+ if (fixp->fx_addsy != NULL
+ && strcmp (S_GET_NAME (fixp->fx_addsy), GOT_NAME) == 0)
+ code = BFD_RELOC_SPARC_PC22;
+ else
+ code = BFD_RELOC_SPARC_GOT22;
+ break;
+ case BFD_RELOC_LO10:
+ if (fixp->fx_addsy != NULL
+ && strcmp (S_GET_NAME (fixp->fx_addsy), GOT_NAME) == 0)
+ code = BFD_RELOC_SPARC_PC10;
+ else
+ code = BFD_RELOC_SPARC_GOT10;
+ break;
+ case BFD_RELOC_SPARC13:
+ code = BFD_RELOC_SPARC_GOT13;
+ break;
+ default:
+ break;
+ }
+ }
+#endif /* defined (OBJ_ELF) || defined (OBJ_AOUT) */
+
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
+ if (reloc->howto == 0)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("internal error: can't export reloc type %d (`%s')"),
+ fixp->fx_r_type, bfd_get_reloc_code_name (code));
+ return 0;
+ }
+
+ /* @@ Why fx_addnumber sometimes and fx_offset other times? */
+#ifdef OBJ_AOUT
+
+ if (reloc->howto->pc_relative == 0
+ || code == BFD_RELOC_SPARC_PC10
+ || code == BFD_RELOC_SPARC_PC22)
+ reloc->addend = fixp->fx_addnumber;
+ else if (sparc_pic_code
+ && fixp->fx_r_type == BFD_RELOC_32_PCREL_S2
+ && fixp->fx_addsy != NULL
+ && (S_IS_EXTERNAL (fixp->fx_addsy)
+ || S_IS_WEAK (fixp->fx_addsy))
+ && S_IS_DEFINED (fixp->fx_addsy)
+ && ! S_IS_COMMON (fixp->fx_addsy))
+ reloc->addend = fixp->fx_addnumber;
+ else
+ reloc->addend = fixp->fx_offset - reloc->address;
+
+#else /* elf or coff */
+
+ if (reloc->howto->pc_relative == 0
+ || code == BFD_RELOC_SPARC_PC10
+ || code == BFD_RELOC_SPARC_PC22)
+ reloc->addend = fixp->fx_addnumber;
+ else if ((fixp->fx_addsy->bsym->flags & BSF_SECTION_SYM) != 0)
+ reloc->addend = (section->vma
+ + fixp->fx_addnumber
+ + md_pcrel_from (fixp));
+ else
+ reloc->addend = fixp->fx_offset;
+#endif
+
+ return reloc;
+}
+
+/* We have no need to default values of symbols. */
+
+/* ARGSUSED */
+symbolS *
+md_undefined_symbol (name)
+ char *name;
+{
+ return 0;
+} /* md_undefined_symbol() */
+
+/* Round up a section size to the appropriate boundary. */
+valueT
+md_section_align (segment, size)
+ segT segment;
+ valueT size;
+{
+#ifndef OBJ_ELF
+ /* This is not right for ELF; a.out wants it, and COFF will force
+ the alignment anyways. */
+ valueT align = ((valueT) 1
+ << (valueT) bfd_get_section_alignment (stdoutput, segment));
+ valueT newsize;
+ /* turn alignment value into a mask */
+ align--;
+ newsize = (size + align) & ~align;
+ return newsize;
+#else
+ return size;
+#endif
+}
+
+/* Exactly what point is a PC-relative offset relative TO?
+ On the sparc, they're relative to the address of the offset, plus
+ its size. This gets us to the following instruction.
+ (??? Is this right? FIXME-SOON) */
+long
+md_pcrel_from (fixP)
+ fixS *fixP;
+{
+ long ret;
+
+ ret = fixP->fx_where + fixP->fx_frag->fr_address;
+ if (! sparc_pic_code
+ || fixP->fx_addsy == NULL
+ || (fixP->fx_addsy->bsym->flags & BSF_SECTION_SYM) != 0)
+ ret += fixP->fx_size;
+ return ret;
+}
+
+/* Return log2 (VALUE), or -1 if VALUE is not an exact positive power
+ of two. */
+
+static int
+log2 (value)
+ int value;
+{
+ int shift;
+
+ if (value <= 0)
+ return -1;
+
+ for (shift = 0; (value & 1) == 0; value >>= 1)
+ ++shift;
+
+ return (value == 1) ? shift : -1;
+}
+
+/*
+ * sort of like s_lcomm
+ */
+
+#ifndef OBJ_ELF
+static int max_alignment = 15;
+#endif
+
+static void
+s_reserve (ignore)
+ int ignore;
+{
+ char *name;
+ char *p;
+ char c;
+ int align;
+ int size;
+ int temp;
+ symbolS *symbolP;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE ();
+
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("Expected comma after name"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ ++input_line_pointer;
+
+ if ((size = get_absolute_expression ()) < 0)
+ {
+ as_bad (_("BSS length (%d.) <0! Ignored."), size);
+ ignore_rest_of_line ();
+ return;
+ } /* bad length */
+
+ *p = 0;
+ symbolP = symbol_find_or_make (name);
+ *p = c;
+
+ if (strncmp (input_line_pointer, ",\"bss\"", 6) != 0
+ && strncmp (input_line_pointer, ",\".bss\"", 7) != 0)
+ {
+ as_bad (_("bad .reserve segment -- expected BSS segment"));
+ return;
+ }
+
+ if (input_line_pointer[2] == '.')
+ input_line_pointer += 7;
+ else
+ input_line_pointer += 6;
+ SKIP_WHITESPACE ();
+
+ if (*input_line_pointer == ',')
+ {
+ ++input_line_pointer;
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '\n')
+ {
+ as_bad (_("missing alignment"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ align = (int) get_absolute_expression ();
+
+#ifndef OBJ_ELF
+ if (align > max_alignment)
+ {
+ align = max_alignment;
+ as_warn (_("alignment too large; assuming %d"), align);
+ }
+#endif
+
+ if (align < 0)
+ {
+ as_bad (_("negative alignment"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ if (align != 0)
+ {
+ temp = log2 (align);
+ if (temp < 0)
+ {
+ as_bad (_("alignment not a power of 2"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ align = temp;
+ }
+
+ record_alignment (bss_section, align);
+ }
+ else
+ align = 0;
+
+ if (!S_IS_DEFINED (symbolP)
+#ifdef OBJ_AOUT
+ && S_GET_OTHER (symbolP) == 0
+ && S_GET_DESC (symbolP) == 0
+#endif
+ )
+ {
+ if (! need_pass_2)
+ {
+ char *pfrag;
+ segT current_seg = now_seg;
+ subsegT current_subseg = now_subseg;
+
+ subseg_set (bss_section, 1); /* switch to bss */
+
+ if (align)
+ frag_align (align, 0, 0); /* do alignment */
+
+ /* detach from old frag */
+ if (S_GET_SEGMENT(symbolP) == bss_section)
+ symbolP->sy_frag->fr_symbol = NULL;
+
+ symbolP->sy_frag = frag_now;
+ pfrag = frag_var (rs_org, 1, 1, (relax_substateT)0, symbolP,
+ (offsetT) size, (char *)0);
+ *pfrag = 0;
+
+ S_SET_SEGMENT (symbolP, bss_section);
+
+ subseg_set (current_seg, current_subseg);
+
+#ifdef OBJ_ELF
+ S_SET_SIZE (symbolP, size);
+#endif
+ }
+ }
+ else
+ {
+ as_warn("Ignoring attempt to re-define symbol %s",
+ S_GET_NAME (symbolP));
+ } /* if not redefining */
+
+ demand_empty_rest_of_line ();
+}
+
+static void
+s_common (ignore)
+ int ignore;
+{
+ char *name;
+ char c;
+ char *p;
+ int temp, size;
+ symbolS *symbolP;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ /* just after name is now '\0' */
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("Expected comma after symbol-name"));
+ ignore_rest_of_line ();
+ return;
+ }
+ input_line_pointer++; /* skip ',' */
+ if ((temp = get_absolute_expression ()) < 0)
+ {
+ as_bad (_(".COMMon length (%d.) <0! Ignored."), temp);
+ ignore_rest_of_line ();
+ return;
+ }
+ size = temp;
+ *p = 0;
+ symbolP = symbol_find_or_make (name);
+ *p = c;
+ if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
+ {
+ as_bad (_("Ignoring attempt to re-define symbol"));
+ ignore_rest_of_line ();
+ return;
+ }
+ if (S_GET_VALUE (symbolP) != 0)
+ {
+ if (S_GET_VALUE (symbolP) != (valueT) size)
+ {
+ as_warn (_("Length of .comm \"%s\" is already %ld. Not changed to %d."),
+ S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size);
+ }
+ }
+ else
+ {
+#ifndef OBJ_ELF
+ S_SET_VALUE (symbolP, (valueT) size);
+ S_SET_EXTERNAL (symbolP);
+#endif
+ }
+ know (symbolP->sy_frag == &zero_address_frag);
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("Expected comma after common length"));
+ ignore_rest_of_line ();
+ return;
+ }
+ input_line_pointer++;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != '"')
+ {
+ temp = get_absolute_expression ();
+
+#ifndef OBJ_ELF
+ if (temp > max_alignment)
+ {
+ temp = max_alignment;
+ as_warn (_("alignment too large; assuming %d"), temp);
+ }
+#endif
+
+ if (temp < 0)
+ {
+ as_bad (_("negative alignment"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+#ifdef OBJ_ELF
+ if (symbolP->local)
+ {
+ segT old_sec;
+ int old_subsec;
+ char *p;
+ int align;
+
+ old_sec = now_seg;
+ old_subsec = now_subseg;
+
+ if (temp == 0)
+ align = 0;
+ else
+ align = log2 (temp);
+
+ if (align < 0)
+ {
+ as_bad (_("alignment not a power of 2"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ record_alignment (bss_section, align);
+ subseg_set (bss_section, 0);
+ if (align)
+ frag_align (align, 0, 0);
+ if (S_GET_SEGMENT (symbolP) == bss_section)
+ symbolP->sy_frag->fr_symbol = 0;
+ symbolP->sy_frag = frag_now;
+ p = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
+ (offsetT) size, (char *) 0);
+ *p = 0;
+ S_SET_SEGMENT (symbolP, bss_section);
+ S_CLEAR_EXTERNAL (symbolP);
+ S_SET_SIZE (symbolP, size);
+ subseg_set (old_sec, old_subsec);
+ }
+ else
+#endif /* OBJ_ELF */
+ {
+ allocate_common:
+ S_SET_VALUE (symbolP, (valueT) size);
+#ifdef OBJ_ELF
+ S_SET_ALIGN (symbolP, temp);
+ S_SET_SIZE (symbolP, size);
+#endif
+ S_SET_EXTERNAL (symbolP);
+ S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
+ }
+ }
+ else
+ {
+ input_line_pointer++;
+ /* @@ Some use the dot, some don't. Can we get some consistency?? */
+ if (*input_line_pointer == '.')
+ input_line_pointer++;
+ /* @@ Some say data, some say bss. */
+ if (strncmp (input_line_pointer, "bss\"", 4)
+ && strncmp (input_line_pointer, "data\"", 5))
+ {
+ while (*--input_line_pointer != '"')
+ ;
+ input_line_pointer--;
+ goto bad_common_segment;
+ }
+ while (*input_line_pointer++ != '"')
+ ;
+ goto allocate_common;
+ }
+
+#ifdef BFD_ASSEMBLER
+ symbolP->bsym->flags |= BSF_OBJECT;
+#endif
+
+ demand_empty_rest_of_line ();
+ return;
+
+ {
+ bad_common_segment:
+ p = input_line_pointer;
+ while (*p && *p != '\n')
+ p++;
+ c = *p;
+ *p = '\0';
+ as_bad (_("bad .common segment %s"), input_line_pointer + 1);
+ *p = c;
+ input_line_pointer = p;
+ ignore_rest_of_line ();
+ return;
+ }
+}
+
+/* Handle the .empty pseudo-op. This supresses the warnings about
+ invalid delay slot usage. */
+
+static void
+s_empty (ignore)
+ int ignore;
+{
+ /* The easy way to implement is to just forget about the last
+ instruction. */
+ last_insn = NULL;
+}
+
+static void
+s_seg (ignore)
+ int ignore;
+{
+
+ if (strncmp (input_line_pointer, "\"text\"", 6) == 0)
+ {
+ input_line_pointer += 6;
+ s_text (0);
+ return;
+ }
+ if (strncmp (input_line_pointer, "\"data\"", 6) == 0)
+ {
+ input_line_pointer += 6;
+ s_data (0);
+ return;
+ }
+ if (strncmp (input_line_pointer, "\"data1\"", 7) == 0)
+ {
+ input_line_pointer += 7;
+ s_data1 ();
+ return;
+ }
+ if (strncmp (input_line_pointer, "\"bss\"", 5) == 0)
+ {
+ input_line_pointer += 5;
+ /* We only support 2 segments -- text and data -- for now, so
+ things in the "bss segment" will have to go into data for now.
+ You can still allocate SEG_BSS stuff with .lcomm or .reserve. */
+ subseg_set (data_section, 255); /* FIXME-SOMEDAY */
+ return;
+ }
+ as_bad (_("Unknown segment type"));
+ demand_empty_rest_of_line ();
+}
+
+static void
+s_data1 ()
+{
+ subseg_set (data_section, 1);
+ demand_empty_rest_of_line ();
+}
+
+static void
+s_proc (ignore)
+ int ignore;
+{
+ while (!is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ ++input_line_pointer;
+ }
+ ++input_line_pointer;
+}
+
+/* This static variable is set by s_uacons to tell sparc_cons_align
+ that the expession does not need to be aligned. */
+
+static int sparc_no_align_cons = 0;
+
+/* This handles the unaligned space allocation pseudo-ops, such as
+ .uaword. .uaword is just like .word, but the value does not need
+ to be aligned. */
+
+static void
+s_uacons (bytes)
+ int bytes;
+{
+ /* Tell sparc_cons_align not to align this value. */
+ sparc_no_align_cons = 1;
+ cons (bytes);
+}
+
+/* If the --enforce-aligned-data option is used, we require .word,
+ et. al., to be aligned correctly. We do it by setting up an
+ rs_align_code frag, and checking in HANDLE_ALIGN to make sure that
+ no unexpected alignment was introduced.
+
+ The SunOS and Solaris native assemblers enforce aligned data by
+ default. We don't want to do that, because gcc can deliberately
+ generate misaligned data if the packed attribute is used. Instead,
+ we permit misaligned data by default, and permit the user to set an
+ option to check for it. */
+
+void
+sparc_cons_align (nbytes)
+ int nbytes;
+{
+ int nalign;
+ char *p;
+
+ /* Only do this if we are enforcing aligned data. */
+ if (! enforce_aligned_data)
+ return;
+
+ if (sparc_no_align_cons)
+ {
+ /* This is an unaligned pseudo-op. */
+ sparc_no_align_cons = 0;
+ return;
+ }
+
+ nalign = log2 (nbytes);
+ if (nalign == 0)
+ return;
+
+ assert (nalign > 0);
+
+ if (now_seg == absolute_section)
+ {
+ if ((abs_section_offset & ((1 << nalign) - 1)) != 0)
+ as_bad (_("misaligned data"));
+ return;
+ }
+
+ p = frag_var (rs_align_code, 1, 1, (relax_substateT) 0,
+ (symbolS *) NULL, (offsetT) nalign, (char *) NULL);
+
+ record_alignment (now_seg, nalign);
+}
+
+/* This is where we do the unexpected alignment check.
+ This is called from HANDLE_ALIGN in tc-sparc.h. */
+
+void
+sparc_handle_align (fragp)
+ fragS *fragp;
+{
+ if (fragp->fr_type == rs_align_code && !fragp->fr_subtype
+ && fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix != 0)
+ as_bad_where (fragp->fr_file, fragp->fr_line, _("misaligned data"));
+ if (fragp->fr_type == rs_align_code && fragp->fr_subtype == 1024)
+ {
+ int count = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
+
+ if (count >= 4
+ && !(count & 3)
+ && count <= 1024
+ && !((long)(fragp->fr_literal + fragp->fr_fix) & 3))
+ {
+ unsigned *p = (unsigned *)(fragp->fr_literal + fragp->fr_fix);
+ int i;
+
+ for (i = 0; i < count; i += 4, p++)
+ if (INSN_BIG_ENDIAN)
+ number_to_chars_bigendian ((char *)p, 0x01000000, 4); /* emit nops */
+ else
+ number_to_chars_littleendian ((char *)p, 0x10000000, 4);
+
+ if (SPARC_OPCODE_ARCH_V9_P (max_architecture) && count > 8)
+ {
+ char *waddr = &fragp->fr_literal[fragp->fr_fix];
+ unsigned wval = (0x30680000 | count >> 2); /* ba,a,pt %xcc, 1f */
+ if (INSN_BIG_ENDIAN)
+ number_to_chars_bigendian (waddr, wval, 4);
+ else
+ number_to_chars_littleendian (waddr, wval, 4);
+ }
+ fragp->fr_var = count;
+ }
+ }
+}
+
+#ifdef OBJ_ELF
+/* Some special processing for a Sparc ELF file. */
+
+void
+sparc_elf_final_processing ()
+{
+ /* Set the Sparc ELF flag bits. FIXME: There should probably be some
+ sort of BFD interface for this. */
+ if (sparc_arch_size == 64)
+ {
+ switch (sparc_memory_model)
+ {
+ case MM_RMO:
+ elf_elfheader (stdoutput)->e_flags |= EF_SPARCV9_RMO;
+ break;
+ case MM_PSO:
+ elf_elfheader (stdoutput)->e_flags |= EF_SPARCV9_PSO;
+ break;
+ default:
+ break;
+ }
+ }
+ else if (current_architecture >= SPARC_OPCODE_ARCH_V9)
+ elf_elfheader (stdoutput)->e_flags |= EF_SPARC_32PLUS;
+ if (current_architecture == SPARC_OPCODE_ARCH_V9A)
+ elf_elfheader (stdoutput)->e_flags |= EF_SPARC_SUN_US1;
+}
+#endif
+
+/* This is called by emit_expr via TC_CONS_FIX_NEW when creating a
+ reloc for a cons. We could use the definition there, except that
+ we want to handle little endian relocs specially. */
+
+void
+cons_fix_new_sparc (frag, where, nbytes, exp)
+ fragS *frag;
+ int where;
+ unsigned int nbytes;
+ expressionS *exp;
+{
+ bfd_reloc_code_real_type r;
+
+ r = (nbytes == 1 ? BFD_RELOC_8 :
+ (nbytes == 2 ? BFD_RELOC_16 :
+ (nbytes == 4 ? BFD_RELOC_32 : BFD_RELOC_64)));
+
+ if (target_little_endian_data && nbytes == 4
+ && now_seg->flags & SEC_ALLOC)
+ r = BFD_RELOC_SPARC_REV32;
+ fix_new_exp (frag, where, (int) nbytes, exp, 0, r);
+}
+
+#ifdef OBJ_ELF
+int
+elf32_sparc_force_relocation (fixp)
+ struct fix *fixp;
+{
+ if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ return 1;
+
+ return 0;
+}
+#endif
+
diff --git a/gas/config/tc-sparc.h b/gas/config/tc-sparc.h
new file mode 100644
index 0000000000..2a057642be
--- /dev/null
+++ b/gas/config/tc-sparc.h
@@ -0,0 +1,164 @@
+/* tc-sparc.h - Macros and type defines for the sparc.
+ Copyright (C) 1989, 90-96, 97, 98, 1999 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2,
+ or (at your option) any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public
+ License along with GAS; see the file COPYING. If not, write
+ to the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef TC_SPARC
+#define TC_SPARC 1
+
+#ifdef ANSI_PROTOTYPES
+struct frag;
+#endif
+
+/* This is used to set the default value for `target_big_endian'. */
+#define TARGET_BYTES_BIG_ENDIAN 1
+
+#define LOCAL_LABELS_FB 1
+
+#define TARGET_ARCH bfd_arch_sparc
+
+extern const char *sparc_target_format PARAMS ((void));
+#define TARGET_FORMAT sparc_target_format ()
+
+#if 0
+#ifdef TE_SPARCAOUT
+/* Bi-endian support may eventually be unconditional, but until things are
+ working well it's only provided for targets that need it. */
+#define SPARC_BIENDIAN
+#endif
+#endif
+/* Make it unconditional and check if -EL is valid after option parsing */
+#define SPARC_BIENDIAN
+
+#define WORKING_DOT_WORD
+
+#define md_convert_frag(b,s,f) {as_fatal (_("sparc convert_frag\n"));}
+#define md_estimate_size_before_relax(f,s) \
+ (as_fatal(_("estimate_size_before_relax called")),1)
+
+#define LISTING_HEADER "SPARC GAS "
+
+extern int sparc_pic_code;
+
+#define md_do_align(n, fill, len, max, around) \
+if ((n) && (n) <= 10 && !need_pass_2 && !(fill) \
+ && now_seg != data_section && now_seg != bss_section) \
+ { \
+ char *p; \
+ p = frag_var (rs_align_code, 1 << n, 1, (relax_substateT) 1024, \
+ (symbolS *) 0, (offsetT) (n), (char *) 0); \
+ *p = 0x00; \
+ goto around; \
+ }
+
+/* We require .word, et. al., to be aligned correctly. */
+#define md_cons_align(nbytes) sparc_cons_align (nbytes)
+extern void sparc_cons_align PARAMS ((int));
+#define HANDLE_ALIGN(fragp) sparc_handle_align (fragp)
+extern void sparc_handle_align PARAMS ((struct frag *));
+
+#if defined (OBJ_ELF) || defined (OBJ_AOUT)
+
+/* This expression evaluates to false if the relocation is for a local
+ object for which we still want to do the relocation at runtime.
+ True if we are willing to perform this relocation while building
+ the .o file.
+
+ If the reloc is against an externally visible symbol, then the
+ a.out assembler should not do the relocation if generating PIC, and
+ the ELF assembler should never do the relocation. */
+
+#ifdef OBJ_ELF
+#define obj_relocate_extern 0
+#else
+#define obj_relocate_extern (! sparc_pic_code)
+#endif
+
+#define TC_RELOC_RTSYM_LOC_FIXUP(FIX) \
+ (obj_relocate_extern \
+ || (FIX)->fx_addsy == NULL \
+ || (! S_IS_EXTERNAL ((FIX)->fx_addsy) \
+ && ! S_IS_WEAK ((FIX)->fx_addsy) \
+ && S_IS_DEFINED ((FIX)->fx_addsy) \
+ && ! S_IS_COMMON ((FIX)->fx_addsy)))
+#endif
+
+/* I know that "call 0" fails in sparc-coff if this doesn't return 1. I
+ don't know about other relocation types, or other formats, yet. */
+#ifdef OBJ_COFF
+#define TC_FORCE_RELOCATION(FIXP) \
+ ((FIXP)->fx_r_type == BFD_RELOC_32_PCREL_S2 \
+ && ((FIXP)->fx_addsy == 0 \
+ || S_GET_SEGMENT ((FIXP)->fx_addsy) == absolute_section))
+#define RELOC_REQUIRES_SYMBOL
+#endif
+
+#ifdef OBJ_ELF
+#define TC_FORCE_RELOCATION(fixp) elf32_sparc_force_relocation(fixp)
+extern int elf32_sparc_force_relocation PARAMS ((struct fix *));
+#endif
+
+#define MD_APPLY_FIX3
+#define TC_HANDLES_FX_DONE
+
+#ifdef OBJ_ELF
+/* Keep relocations against global symbols. Don't turn them into
+ relocations against sections. This is required for the dynamic
+ linker to operate properly. When generating PIC, we need to keep
+ any non PC relative reloc. */
+#define tc_fix_adjustable(FIX) \
+ (! S_IS_EXTERNAL ((FIX)->fx_addsy) \
+ && ! S_IS_WEAK ((FIX)->fx_addsy) \
+ && (! sparc_pic_code \
+ || (FIX)->fx_pcrel \
+ || ((FIX)->fx_subsy != NULL \
+ && (S_GET_SEGMENT ((FIX)->fx_subsy) \
+ == S_GET_SEGMENT ((FIX)->fx_addsy))) \
+ || strchr (S_GET_NAME ((FIX)->fx_addsy), '\001') != NULL \
+ || strchr (S_GET_NAME ((FIX)->fx_addsy), '\002') != NULL))
+#endif
+
+#ifdef OBJ_AOUT
+/* When generating PIC code, we must not adjust any reloc which will
+ turn into a reloc against the global offset table, nor any reloc
+ which we will need if a symbol is overridden. */
+#define tc_fix_adjustable(FIX) \
+ (! sparc_pic_code \
+ || ((FIX)->fx_pcrel \
+ && ((FIX)->fx_addsy == NULL \
+ || (! S_IS_EXTERNAL ((FIX)->fx_addsy) \
+ && ! S_IS_WEAK ((FIX)->fx_addsy)))) \
+ || (FIX)->fx_r_type == BFD_RELOC_16 \
+ || (FIX)->fx_r_type == BFD_RELOC_32)
+#endif
+
+#define elf_tc_final_processing sparc_elf_final_processing
+extern void sparc_elf_final_processing PARAMS ((void));
+
+#define md_operand(x)
+
+extern void sparc_md_end PARAMS ((void));
+#define md_end() sparc_md_end ()
+
+#endif
+
+#define TC_CONS_FIX_NEW cons_fix_new_sparc
+extern void cons_fix_new_sparc
+ PARAMS ((struct frag *, int, unsigned int, struct expressionS *));
+
+/* end of tc-sparc.h */
diff --git a/gas/config/tc-tahoe.c b/gas/config/tc-tahoe.c
new file mode 100644
index 0000000000..2bd63ca7b1
--- /dev/null
+++ b/gas/config/tc-tahoe.c
@@ -0,0 +1,2027 @@
+/* tc-tahoe.c
+ Not part of GAS yet. */
+
+#include "as.h"
+#include "obstack.h"
+
+/* this bit glommed from tahoe-inst.h */
+
+typedef unsigned char byte;
+typedef byte tahoe_opcodeT;
+
+/*
+ * This is part of tahoe-ins-parse.c & friends.
+ * We want to parse a tahoe instruction text into a tree defined here.
+ */
+
+#define TIT_MAX_OPERANDS (4) /* maximum number of operands in one
+ single tahoe instruction */
+
+struct top /* tahoe instruction operand */
+{
+ int top_ndx; /* -1, or index register. eg 7=[R7] */
+ int top_reg; /* -1, or register number. eg 7 = R7 or (R7) */
+ byte top_mode; /* Addressing mode byte. This byte, defines
+ which of the 11 modes opcode is. */
+
+ char top_access; /* Access type wanted for this opperand
+ 'b'branch ' 'no-instruction 'amrvw' */
+ char top_width; /* Operand width expected, one of "bwlq?-:!" */
+
+ char *top_error; /* Say if operand is inappropriate */
+
+ segT seg_of_operand; /* segment as returned by expression()*/
+
+ expressionS exp_of_operand; /* The expression as parsed by expression()*/
+
+ byte top_dispsize; /* Number of bytes in the displacement if we
+ can figure it out */
+};
+
+/* The addressing modes for an operand. These numbers are the acutal values
+ for certain modes, so be carefull if you screw with them. */
+#define TAHOE_DIRECT_REG (0x50)
+#define TAHOE_REG_DEFERRED (0x60)
+
+#define TAHOE_REG_DISP (0xE0)
+#define TAHOE_REG_DISP_DEFERRED (0xF0)
+
+#define TAHOE_IMMEDIATE (0x8F)
+#define TAHOE_IMMEDIATE_BYTE (0x88)
+#define TAHOE_IMMEDIATE_WORD (0x89)
+#define TAHOE_IMMEDIATE_LONGWORD (0x8F)
+#define TAHOE_ABSOLUTE_ADDR (0x9F)
+
+#define TAHOE_DISPLACED_RELATIVE (0xEF)
+#define TAHOE_DISP_REL_DEFERRED (0xFF)
+
+#define TAHOE_AUTO_DEC (0x7E)
+#define TAHOE_AUTO_INC (0x8E)
+#define TAHOE_AUTO_INC_DEFERRED (0x9E)
+/* INDEXED_REG is decided by the existance or lack of a [reg] */
+
+/* These are encoded into top_width when top_access=='b'
+ and it's a psuedo op.*/
+#define TAHOE_WIDTH_ALWAYS_JUMP '-'
+#define TAHOE_WIDTH_CONDITIONAL_JUMP '?'
+#define TAHOE_WIDTH_BIG_REV_JUMP '!'
+#define TAHOE_WIDTH_BIG_NON_REV_JUMP ':'
+
+/* The hex code for certain tahoe commands and modes.
+ This is just for readability. */
+#define TAHOE_JMP (0x71)
+#define TAHOE_PC_REL_LONG (0xEF)
+#define TAHOE_BRB (0x11)
+#define TAHOE_BRW (0x13)
+/* These, when 'ored' with, or added to, a register number,
+ set up the number for the displacement mode. */
+#define TAHOE_PC_OR_BYTE (0xA0)
+#define TAHOE_PC_OR_WORD (0xC0)
+#define TAHOE_PC_OR_LONG (0xE0)
+
+struct tit /* get it out of the sewer, it stands for
+ tahoe instruction tree (Geeze!) */
+{
+ tahoe_opcodeT tit_opcode; /* The opcode. */
+ byte tit_operands; /* How many operands are here. */
+ struct top tit_operand[TIT_MAX_OPERANDS]; /* Operands */
+ char *tit_error; /* "" or fatal error text */
+};
+
+/* end: tahoe-inst.h */
+
+/* tahoe.c - tahoe-specific -
+ Not part of gas yet.
+ */
+
+#include "opcode/tahoe.h"
+
+/* This is the number to put at the beginning of the a.out file */
+long omagic = OMAGIC;
+
+/* These chars start a comment anywhere in a source file (except inside
+ another comment or a quoted string. */
+const char comment_chars[] = "#;";
+
+/* These chars only start a comment at the beginning of a line. */
+const char line_comment_chars[] = "#";
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant
+ as in 0f123.456
+ or 0d1.234E-12 (see exp chars above)
+ Note: The Tahoe port doesn't support floating point constants. This is
+ consistant with 'as' If it's needed, I can always add it later. */
+const char FLT_CHARS[] = "df";
+
+/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
+ changed in read.c . Ideally it shouldn't have to know about it at all,
+ but nothing is ideal around here.
+ (The tahoe has plenty of room, so the change currently isn't needed.)
+ */
+
+static struct tit t; /* A tahoe instruction after decoding. */
+
+void float_cons ();
+/* A table of pseudo ops (sans .), the function called, and an integer op
+ that the function is called with. */
+
+const pseudo_typeS md_pseudo_table[] =
+{
+ {"dfloat", float_cons, 'd'},
+ {"ffloat", float_cons, 'f'},
+ {0}
+};
+
+/*
+ * For Tahoe, relative addresses of "just the right length" are pretty easy.
+ * The branch displacement is always the last operand, even in
+ * synthetic instructions.
+ * For Tahoe, we encode the relax_substateTs (in e.g. fr_substate) as:
+ *
+ * 4 3 2 1 0 bit number
+ * ---/ /--+-------+-------+-------+-------+-------+
+ * | what state ? | how long ? |
+ * ---/ /--+-------+-------+-------+-------+-------+
+ *
+ * The "how long" bits are 00=byte, 01=word, 10=long.
+ * This is a Un*x convention.
+ * Not all lengths are legit for a given value of (what state).
+ * The four states are listed below.
+ * The "how long" refers merely to the displacement length.
+ * The address usually has some constant bytes in it as well.
+ *
+
+States for Tahoe address relaxing.
+1. TAHOE_WIDTH_ALWAYS_JUMP (-)
+ Format: "b-"
+ Tahoe opcodes are: (Hex)
+ jr 11
+ jbr 11
+ Simple branch.
+ Always, 1 byte opcode, then displacement/absolute.
+ If word or longword, change opcode to brw or jmp.
+
+
+2. TAHOE_WIDTH_CONDITIONAL_JUMP (?)
+ J<cond> where <cond> is a simple flag test.
+ Format: "b?"
+ Tahoe opcodes are: (Hex)
+ jneq/jnequ 21
+ jeql/jeqlu 31
+ jgtr 41
+ jleq 51
+ jgeq 81
+ jlss 91
+ jgtru a1
+ jlequ b1
+ jvc c1
+ jvs d1
+ jlssu/jcs e1
+ jgequ/jcc f1
+ Always, you complement 4th bit to reverse the condition.
+ Always, 1-byte opcode, then 1-byte displacement.
+
+3. TAHOE_WIDTH_BIG_REV_JUMP (!)
+ Jbc/Jbs where cond tests a memory bit.
+ Format: "rlvlb!"
+ Tahoe opcodes are: (Hex)
+ jbs 0e
+ jbc 1e
+ Always, you complement 4th bit to reverse the condition.
+ Always, 1-byte opcde, longword, longword-address, 1-word-displacement
+
+4. TAHOE_WIDTH_BIG_NON_REV_JUMP (:)
+ JaoblXX/Jbssi
+ Format: "rlmlb:"
+ Tahoe opcodes are: (Hex)
+ aojlss 2f
+ jaoblss 2f
+ aojleq 3f
+ jaobleq 3f
+ jbssi 5f
+ Always, we cannot reverse the sense of the branch; we have a word
+ displacement.
+
+We need to modify the opcode is for class 1, 2 and 3 instructions.
+After relax() we may complement the 4th bit of 2 or 3 to reverse sense of
+branch.
+
+We sometimes store context in the operand literal. This way we can figure out
+after relax() what the original addressing mode was. (Was is pc_rel, or
+pc_rel_disp? That sort of thing.) */
+
+/* These displacements are relative to the START address of the
+ displacement which is at the start of the displacement, not the end of
+ the instruction. The hardware pc_rel is at the end of the instructions.
+ That's why all the displacements have the length of the displacement added
+ to them. (WF + length(word))
+
+ The first letter is Byte, Word.
+ 2nd letter is Forward, Backward. */
+#define BF (1+ 127)
+#define BB (1+-128)
+#define WF (2+ 32767)
+#define WB (2+-32768)
+/* Dont need LF, LB because they always reach. [They are coded as 0.] */
+
+#define C(a,b) ENCODE_RELAX(a,b)
+/* This macro has no side-effects. */
+#define ENCODE_RELAX(what,length) (((what) << 2) + (length))
+#define RELAX_STATE(what) ((what) >> 2)
+#define RELAX_LENGTH(length) ((length) && 3)
+
+#define STATE_ALWAYS_BRANCH (1)
+#define STATE_CONDITIONAL_BRANCH (2)
+#define STATE_BIG_REV_BRANCH (3)
+#define STATE_BIG_NON_REV_BRANCH (4)
+#define STATE_PC_RELATIVE (5)
+
+#define STATE_BYTE (0)
+#define STATE_WORD (1)
+#define STATE_LONG (2)
+#define STATE_UNDF (3) /* Symbol undefined in pass1 */
+
+/* This is the table used by gas to figure out relaxing modes. The fields are
+ forward_branch reach, backward_branch reach, number of bytes it would take,
+ where the next biggest branch is. */
+const relax_typeS md_relax_table[] =
+{
+ {
+ 1, 1, 0, 0
+ }, /* error sentinel 0,0 */
+ {
+ 1, 1, 0, 0
+ }, /* unused 0,1 */
+ {
+ 1, 1, 0, 0
+ }, /* unused 0,2 */
+ {
+ 1, 1, 0, 0
+ }, /* unused 0,3 */
+/* Unconditional branch cases "jrb"
+ The relax part is the actual displacement */
+ {
+ BF, BB, 1, C (1, 1)
+ }, /* brb B`foo 1,0 */
+ {
+ WF, WB, 2, C (1, 2)
+ }, /* brw W`foo 1,1 */
+ {
+ 0, 0, 5, 0
+ }, /* Jmp L`foo 1,2 */
+ {
+ 1, 1, 0, 0
+ }, /* unused 1,3 */
+/* Reversible Conditional Branch. If the branch won't reach, reverse
+ it, and jump over a brw or a jmp that will reach. The relax part is the
+ actual address. */
+ {
+ BF, BB, 1, C (2, 1)
+ }, /* b<cond> B`foo 2,0 */
+ {
+ WF + 2, WB + 2, 4, C (2, 2)
+ }, /* brev over, brw W`foo, over: 2,1 */
+ {
+ 0, 0, 7, 0
+ }, /* brev over, jmp L`foo, over: 2,2 */
+ {
+ 1, 1, 0, 0
+ }, /* unused 2,3 */
+/* Another type of reversable branch. But this only has a word
+ displacement. */
+ {
+ 1, 1, 0, 0
+ }, /* unused 3,0 */
+ {
+ WF, WB, 2, C (3, 2)
+ }, /* jbX W`foo 3,1 */
+ {
+ 0, 0, 8, 0
+ }, /* jrevX over, jmp L`foo, over: 3,2 */
+ {
+ 1, 1, 0, 0
+ }, /* unused 3,3 */
+/* These are the non reversable branches, all of which have a word
+ displacement. If I can't reach, branch over a byte branch, to a
+ jump that will reach. The jumped branch jumps over the reaching
+ branch, to continue with the flow of the program. It's like playing
+ leap frog. */
+ {
+ 1, 1, 0, 0
+ }, /* unused 4,0 */
+ {
+ WF, WB, 2, C (4, 2)
+ }, /* aobl_ W`foo 4,1 */
+ {
+ 0, 0, 10, 0
+ }, /*aobl_ W`hop,br over,hop: jmp L^foo,over 4,2*/
+ {
+ 1, 1, 0, 0
+ }, /* unused 4,3 */
+/* Normal displacement mode, no jumping or anything like that.
+ The relax points to one byte before the address, thats why all
+ the numbers are up by one. */
+ {
+ BF + 1, BB + 1, 2, C (5, 1)
+ }, /* B^"foo" 5,0 */
+ {
+ WF + 1, WB + 1, 3, C (5, 2)
+ }, /* W^"foo" 5,1 */
+ {
+ 0, 0, 5, 0
+ }, /* L^"foo" 5,2 */
+ {
+ 1, 1, 0, 0
+ }, /* unused 5,3 */
+};
+
+#undef C
+#undef BF
+#undef BB
+#undef WF
+#undef WB
+/* End relax stuff */
+
+/* Handle of the OPCODE hash table. NULL means any use before
+ md_begin() will crash. */
+static struct hash_control *op_hash;
+
+/* Init function. Build the hash table. */
+void
+md_begin ()
+{
+ struct tot *tP;
+ char *errorval = 0;
+ int synthetic_too = 1; /* If 0, just use real opcodes. */
+
+ op_hash = hash_new ();
+
+ for (tP = totstrs; *tP->name && !errorval; tP++)
+ errorval = hash_insert (op_hash, tP->name, &tP->detail);
+
+ if (synthetic_too)
+ for (tP = synthetic_totstrs; *tP->name && !errorval; tP++)
+ errorval = hash_insert (op_hash, tP->name, &tP->detail);
+
+ if (errorval)
+ as_fatal (errorval);
+}
+
+CONST char *md_shortopts = "ad:STt:V";
+struct option md_longopts[] = {
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof(md_longopts);
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ switch (c)
+ {
+ case 'a':
+ as_warn (_("The -a option doesn't exist. (Despite what the man page says!"));
+ break;
+
+ case 'd':
+ as_warn (_("Displacement length %s ignored!"), arg);
+ break;
+
+ case 'S':
+ as_warn (_("SYMBOL TABLE not implemented"));
+ break;
+
+ case 'T':
+ as_warn (_("TOKEN TRACE not implemented"));
+ break;
+
+ case 't':
+ as_warn (_("I don't need or use temp. file \"%s\"."), arg);
+ break;
+
+ case 'V':
+ as_warn (_("I don't use an interpass file! -V ignored"));
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+ fprintf(stream, _("\
+Tahoe options:\n\
+-a ignored\n\
+-d LENGTH ignored\n\
+-J ignored\n\
+-S ignored\n\
+-t FILE ignored\n\
+-T ignored\n\
+-V ignored\n"));
+}
+
+/* The functions in this section take numbers in the machine format, and
+ munges them into Tahoe byte order.
+ They exist primarily for cross assembly purpose. */
+void /* Knows about order of bytes in address. */
+md_number_to_chars (con, value, nbytes)
+ char con[]; /* Return 'nbytes' of chars here. */
+ valueT value; /* The value of the bits. */
+ int nbytes; /* Number of bytes in the output. */
+{
+ number_to_chars_bigendian (con, value, nbytes);
+}
+
+#ifdef comment
+void /* Knows about order of bytes in address. */
+md_number_to_imm (con, value, nbytes)
+ char con[]; /* Return 'nbytes' of chars here. */
+ long int value; /* The value of the bits. */
+ int nbytes; /* Number of bytes in the output. */
+{
+ md_number_to_chars (con, value, nbytes);
+}
+
+#endif /* comment */
+
+void
+tc_apply_fix (fixP, val)
+ fixS *fixP;
+ long val;
+{
+ /* should never be called */
+ know (0);
+}
+
+void /* Knows about order of bytes in address. */
+md_number_to_disp (con, value, nbytes)
+ char con[]; /* Return 'nbytes' of chars here. */
+ long int value; /* The value of the bits. */
+ int nbytes; /* Number of bytes in the output. */
+{
+ md_number_to_chars (con, value, nbytes);
+}
+
+void /* Knows about order of bytes in address. */
+md_number_to_field (con, value, nbytes)
+ char con[]; /* Return 'nbytes' of chars here. */
+ long int value; /* The value of the bits. */
+ int nbytes; /* Number of bytes in the output. */
+{
+ md_number_to_chars (con, value, nbytes);
+}
+
+/* Put the bits in an order that a tahoe will understand, despite the ordering
+ of the native machine.
+ On Tahoe: first 4 bytes are normal unsigned big endian long,
+ next three bytes are symbolnum, in kind of 3 byte big endian (least sig. byte last).
+ The last byte is broken up with bit 7 as pcrel,
+ bits 6 & 5 as length,
+ bit 4 as extern and the last nibble as 'undefined'. */
+
+#if comment
+void
+md_ri_to_chars (ri_p, ri)
+ struct relocation_info *ri_p, ri;
+{
+ byte the_bytes[sizeof (struct relocation_info)];
+ /* The reason I can't just encode these directly into ri_p is that
+ ri_p may point to ri. */
+
+ /* This is easy */
+ md_number_to_chars (the_bytes, ri.r_address, sizeof (ri.r_address));
+
+ /* now the fun stuff */
+ the_bytes[4] = (ri.r_symbolnum >> 16) & 0x0ff;
+ the_bytes[5] = (ri.r_symbolnum >> 8) & 0x0ff;
+ the_bytes[6] = ri.r_symbolnum & 0x0ff;
+ the_bytes[7] = (((ri.r_extern << 4) & 0x10) | ((ri.r_length << 5) & 0x60) |
+ ((ri.r_pcrel << 7) & 0x80)) & 0xf0;
+
+ bcopy (the_bytes, (char *) ri_p, sizeof (struct relocation_info));
+}
+
+#endif /* comment */
+
+/* Put the bits in an order that a tahoe will understand, despite the ordering
+ of the native machine.
+ On Tahoe: first 4 bytes are normal unsigned big endian long,
+ next three bytes are symbolnum, in kind of 3 byte big endian (least sig. byte last).
+ The last byte is broken up with bit 7 as pcrel,
+ bits 6 & 5 as length,
+ bit 4 as extern and the last nibble as 'undefined'. */
+
+void
+tc_aout_fix_to_chars (where, fixP, segment_address_in_file)
+ char *where;
+ fixS *fixP;
+ relax_addressT segment_address_in_file;
+{
+ long r_symbolnum;
+
+ know (fixP->fx_addsy != NULL);
+
+ md_number_to_chars (where,
+ fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
+ 4);
+
+ r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy)
+ ? S_GET_TYPE (fixP->fx_addsy)
+ : fixP->fx_addsy->sy_number);
+
+ where[4] = (r_symbolnum >> 16) & 0x0ff;
+ where[5] = (r_symbolnum >> 8) & 0x0ff;
+ where[6] = r_symbolnum & 0x0ff;
+ where[7] = (((is_pcrel (fixP) << 7) & 0x80)
+ | ((((fixP->fx_type == FX_8 || fixP->fx_type == FX_PCREL8
+ ? 0
+ : (fixP->fx_type == FX_16 || fixP->fx_type == FX_PCREL16
+ ? 1
+ : (fixP->fx_type == FX_32 || fixP->fx_type == FX_PCREL32
+ ? 2
+ : 42)))) << 5) & 0x60)
+ | ((!S_IS_DEFINED (fixP->fx_addsy) << 4) & 0x10));
+}
+
+/* Relocate byte stuff */
+
+/* This is for broken word. */
+const int md_short_jump_size = 3;
+
+void
+md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
+ char *ptr;
+ addressT from_addr, to_addr;
+ fragS *frag;
+ symbolS *to_symbol;
+{
+ valueT offset;
+
+ offset = to_addr - (from_addr + 1);
+ *ptr++ = TAHOE_BRW;
+ md_number_to_chars (ptr, offset, 2);
+}
+
+const int md_long_jump_size = 6;
+const int md_reloc_size = 8; /* Size of relocation record */
+
+void
+md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
+ char *ptr;
+ addressT from_addr, to_addr;
+ fragS *frag;
+ symbolS *to_symbol;
+{
+ valueT offset;
+
+ offset = to_addr - (from_addr + 4);
+ *ptr++ = TAHOE_JMP;
+ *ptr++ = TAHOE_PC_REL_LONG;
+ md_number_to_chars (ptr, offset, 4);
+}
+
+/*
+ * md_estimate_size_before_relax()
+ *
+ * Called just before relax().
+ * Any symbol that is now undefined will not become defined, so we assumed
+ * that it will be resolved by the linker.
+ * Return the correct fr_subtype in the frag, for relax()
+ * Return the initial "guess for fr_var" to caller. (How big I think this
+ * will be.)
+ * The guess for fr_var is ACTUALLY the growth beyond fr_fix.
+ * Whatever we do to grow fr_fix or fr_var contributes to our returned value.
+ * Although it may not be explicit in the frag, pretend fr_var starts with a
+ * 0 value.
+ */
+int
+md_estimate_size_before_relax (fragP, segment_type)
+ register fragS *fragP;
+ segT segment_type; /* N_DATA or N_TEXT. */
+{
+ register char *p;
+ register int old_fr_fix;
+ /* int pc_rel; FIXME: remove this */
+
+ old_fr_fix = fragP->fr_fix;
+ switch (fragP->fr_subtype)
+ {
+ case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_UNDF):
+ if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type)
+ {
+ /* The symbol was in the same segment as the opcode, and it's
+ a real pc_rel case so it's a relaxable case. */
+ fragP->fr_subtype = ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE);
+ }
+ else
+ {
+ /* This case is still undefined, so asume it's a long word for the
+ linker to fix. */
+ p = fragP->fr_literal + old_fr_fix;
+ *p |= TAHOE_PC_OR_LONG;
+ /* We now know how big it will be, one long word. */
+ fragP->fr_fix += 1 + 4;
+ fix_new (fragP, old_fr_fix + 1, fragP->fr_symbol,
+ fragP->fr_offset, FX_PCREL32, NULL);
+ frag_wane (fragP);
+ }
+ break;
+
+ case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_UNDF):
+ if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type)
+ {
+ fragP->fr_subtype = ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_BYTE);
+ }
+ else
+ {
+ p = fragP->fr_literal + old_fr_fix;
+ *fragP->fr_opcode ^= 0x10; /* Reverse sense of branch. */
+ *p++ = 6;
+ *p++ = TAHOE_JMP;
+ *p++ = TAHOE_PC_REL_LONG;
+ fragP->fr_fix += 1 + 1 + 1 + 4;
+ fix_new (fragP, old_fr_fix + 3, fragP->fr_symbol,
+ fragP->fr_offset, FX_PCREL32, NULL);
+ frag_wane (fragP);
+ }
+ break;
+
+ case ENCODE_RELAX (STATE_BIG_REV_BRANCH, STATE_UNDF):
+ if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type)
+ {
+ fragP->fr_subtype =
+ ENCODE_RELAX (STATE_BIG_REV_BRANCH, STATE_WORD);
+ }
+ else
+ {
+ p = fragP->fr_literal + old_fr_fix;
+ *fragP->fr_opcode ^= 0x10; /* Reverse sense of branch. */
+ *p++ = 0;
+ *p++ = 6;
+ *p++ = TAHOE_JMP;
+ *p++ = TAHOE_PC_REL_LONG;
+ fragP->fr_fix += 2 + 2 + 4;
+ fix_new (fragP, old_fr_fix + 4, fragP->fr_symbol,
+ fragP->fr_offset, FX_PCREL32, NULL);
+ frag_wane (fragP);
+ }
+ break;
+
+ case ENCODE_RELAX (STATE_BIG_NON_REV_BRANCH, STATE_UNDF):
+ if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type)
+ {
+ fragP->fr_subtype = ENCODE_RELAX (STATE_BIG_NON_REV_BRANCH, STATE_WORD);
+ }
+ else
+ {
+ p = fragP->fr_literal + old_fr_fix;
+ *p++ = 2;
+ *p++ = 0;
+ *p++ = TAHOE_BRB;
+ *p++ = 6;
+ *p++ = TAHOE_JMP;
+ *p++ = TAHOE_PC_REL_LONG;
+ fragP->fr_fix += 2 + 2 + 2 + 4;
+ fix_new (fragP, old_fr_fix + 6, fragP->fr_symbol,
+ fragP->fr_offset, FX_PCREL32, NULL);
+ frag_wane (fragP);
+ }
+ break;
+
+ case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_UNDF):
+ if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type)
+ {
+ fragP->fr_subtype = ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_BYTE);
+ }
+ else
+ {
+ p = fragP->fr_literal + old_fr_fix;
+ *fragP->fr_opcode = TAHOE_JMP;
+ *p++ = TAHOE_PC_REL_LONG;
+ fragP->fr_fix += 1 + 4;
+ fix_new (fragP, old_fr_fix + 1, fragP->fr_symbol,
+ fragP->fr_offset, FX_PCREL32, NULL);
+ frag_wane (fragP);
+ }
+ break;
+
+ default:
+ break;
+ }
+ return (fragP->fr_var + fragP->fr_fix - old_fr_fix);
+} /* md_estimate_size_before_relax() */
+
+/*
+ * md_convert_frag();
+ *
+ * Called after relax() is finished.
+ * In: Address of frag.
+ * fr_type == rs_machine_dependent.
+ * fr_subtype is what the address relaxed to.
+ *
+ * Out: Any fixSs and constants are set up.
+ * Caller will turn frag into a ".space 0".
+ */
+void
+md_convert_frag (headers, seg, fragP)
+ object_headers *headers;
+ segT seg;
+ register fragS *fragP;
+{
+ register char *addressP; /* -> _var to change. */
+ register char *opcodeP; /* -> opcode char(s) to change. */
+ register short int length_code; /* 2=long 1=word 0=byte */
+ register short int extension = 0; /* Size of relaxed address.
+ Added to fr_fix: incl. ALL var chars. */
+ register symbolS *symbolP;
+ register long int where;
+ register long int address_of_var;
+ /* Where, in file space, is _var of *fragP? */
+ register long int target_address;
+ /* Where, in file space, does addr point? */
+
+ know (fragP->fr_type == rs_machine_dependent);
+ length_code = RELAX_LENGTH (fragP->fr_subtype);
+ know (length_code >= 0 && length_code < 3);
+ where = fragP->fr_fix;
+ addressP = fragP->fr_literal + where;
+ opcodeP = fragP->fr_opcode;
+ symbolP = fragP->fr_symbol;
+ know (symbolP);
+ target_address = S_GET_VALUE (symbolP) + fragP->fr_offset;
+ address_of_var = fragP->fr_address + where;
+ switch (fragP->fr_subtype)
+ {
+ case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE):
+ /* *addressP holds the registers number, plus 0x10, if it's deferred
+ mode. To set up the right mode, just OR the size of this displacement */
+ /* Byte displacement. */
+ *addressP++ |= TAHOE_PC_OR_BYTE;
+ *addressP = target_address - (address_of_var + 2);
+ extension = 2;
+ break;
+
+ case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_WORD):
+ /* Word displacement. */
+ *addressP++ |= TAHOE_PC_OR_WORD;
+ md_number_to_chars (addressP, target_address - (address_of_var + 3), 2);
+ extension = 3;
+ break;
+
+ case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_LONG):
+ /* Long word displacement. */
+ *addressP++ |= TAHOE_PC_OR_LONG;
+ md_number_to_chars (addressP, target_address - (address_of_var + 5), 4);
+ extension = 5;
+ break;
+
+ case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_BYTE):
+ *addressP = target_address - (address_of_var + 1);
+ extension = 1;
+ break;
+
+ case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_WORD):
+ *opcodeP ^= 0x10; /* Reverse sense of test. */
+ *addressP++ = 3; /* Jump over word branch */
+ *addressP++ = TAHOE_BRW;
+ md_number_to_chars (addressP, target_address - (address_of_var + 4), 2);
+ extension = 4;
+ break;
+
+ case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_LONG):
+ *opcodeP ^= 0x10; /* Reverse sense of test. */
+ *addressP++ = 6;
+ *addressP++ = TAHOE_JMP;
+ *addressP++ = TAHOE_PC_REL_LONG;
+ md_number_to_chars (addressP, target_address, 4);
+ extension = 7;
+ break;
+
+ case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_BYTE):
+ *addressP = target_address - (address_of_var + 1);
+ extension = 1;
+ break;
+
+ case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_WORD):
+ *opcodeP = TAHOE_BRW;
+ md_number_to_chars (addressP, target_address - (address_of_var + 2), 2);
+ extension = 2;
+ break;
+
+ case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_LONG):
+ *opcodeP = TAHOE_JMP;
+ *addressP++ = TAHOE_PC_REL_LONG;
+ md_number_to_chars (addressP, target_address - (address_of_var + 5), 4);
+ extension = 5;
+ break;
+
+ case ENCODE_RELAX (STATE_BIG_REV_BRANCH, STATE_WORD):
+ md_number_to_chars (addressP, target_address - (address_of_var + 2), 2);
+ extension = 2;
+ break;
+
+ case ENCODE_RELAX (STATE_BIG_REV_BRANCH, STATE_LONG):
+ *opcodeP ^= 0x10;
+ *addressP++ = 0;
+ *addressP++ = 6;
+ *addressP++ = TAHOE_JMP;
+ *addressP++ = TAHOE_PC_REL_LONG;
+ md_number_to_chars (addressP, target_address, 4);
+ extension = 8;
+ break;
+
+ case ENCODE_RELAX (STATE_BIG_NON_REV_BRANCH, STATE_WORD):
+ md_number_to_chars (addressP, target_address - (address_of_var + 2), 2);
+ extension = 2;
+ break;
+
+ case ENCODE_RELAX (STATE_BIG_NON_REV_BRANCH, STATE_LONG):
+ *addressP++ = 0;
+ *addressP++ = 2;
+ *addressP++ = TAHOE_BRB;
+ *addressP++ = 6;
+ *addressP++ = TAHOE_JMP;
+ *addressP++ = TAHOE_PC_REL_LONG;
+ md_number_to_chars (addressP, target_address, 4);
+ extension = 10;
+ break;
+
+ default:
+ BAD_CASE (fragP->fr_subtype);
+ break;
+ }
+ fragP->fr_fix += extension;
+} /* md_convert_frag */
+
+
+/* This is the stuff for md_assemble. */
+#define FP_REG 13
+#define SP_REG 14
+#define PC_REG 15
+#define BIGGESTREG PC_REG
+
+/*
+ * Parse the string pointed to by START
+ * If it represents a valid register, point START to the character after
+ * the last valid register char, and return the register number (0-15).
+ * If invalid, leave START alone, return -1.
+ * The format has to be exact. I don't do things like eat leading zeros
+ * or the like.
+ * Note: This doesn't check for the next character in the string making
+ * this invalid. Ex: R123 would return 12, it's the callers job to check
+ * what start is point to apon return.
+ *
+ * Valid registers are R1-R15, %1-%15, FP (13), SP (14), PC (15)
+ * Case doesn't matter.
+ */
+int
+tahoe_reg_parse (start)
+ char **start; /* A pointer to the string to parse. */
+{
+ register char *regpoint = *start;
+ register int regnum = -1;
+
+ switch (*regpoint++)
+ {
+ case '%': /* Registers can start with a %,
+ R or r, and then a number. */
+ case 'R':
+ case 'r':
+ if (isdigit (*regpoint))
+ {
+ /* Got the first digit. */
+ regnum = *regpoint++ - '0';
+ if ((regnum == 1) && isdigit (*regpoint))
+ {
+ /* Its a two digit number. */
+ regnum = 10 + (*regpoint++ - '0');
+ if (regnum > BIGGESTREG)
+ { /* Number too big? */
+ regnum = -1;
+ }
+ }
+ }
+ break;
+ case 'F': /* Is it the FP */
+ case 'f':
+ switch (*regpoint++)
+ {
+ case 'p':
+ case 'P':
+ regnum = FP_REG;
+ }
+ break;
+ case 's': /* How about the SP */
+ case 'S':
+ switch (*regpoint++)
+ {
+ case 'p':
+ case 'P':
+ regnum = SP_REG;
+ }
+ break;
+ case 'p': /* OR the PC even */
+ case 'P':
+ switch (*regpoint++)
+ {
+ case 'c':
+ case 'C':
+ regnum = PC_REG;
+ }
+ break;
+ }
+
+ if (regnum != -1)
+ { /* No error, so move string pointer */
+ *start = regpoint;
+ }
+ return regnum; /* Return results */
+} /* tahoe_reg_parse */
+
+/*
+ * This chops up an operand and figures out its modes and stuff.
+ * It's a little touchy about extra characters.
+ * Optex to start with one extra character so it can be overwritten for
+ * the backward part of the parsing.
+ * You can't put a bunch of extra characters in side to
+ * make the command look cute. ie: * foo ( r1 ) [ r0 ]
+ * If you like doing a lot of typing, try COBOL!
+ * Actually, this parser is a little weak all around. It's designed to be
+ * used with compliers, so I emphisise correct decoding of valid code quickly
+ * rather that catching every possable error.
+ * Note: This uses the expression function, so save input_line_pointer before
+ * calling.
+ *
+ * Sperry defines the semantics of address modes (and values)
+ * by a two-letter code, explained here.
+ *
+ * letter 1: access type
+ *
+ * a address calculation - no data access, registers forbidden
+ * b branch displacement
+ * m read - let go of bus - write back "modify"
+ * r read
+ * w write
+ * v bit field address: like 'a' but registers are OK
+ *
+ * letter 2: data type (i.e. width, alignment)
+ *
+ * b byte
+ * w word
+ * l longword
+ * q quadword (Even regs < 14 allowed) (if 12, you get a warning)
+ * - unconditional synthetic jbr operand
+ * ? simple synthetic reversable branch operand
+ * ! complex synthetic reversable branch operand
+ * : complex synthetic non-reversable branch operand
+ *
+ * The '-?!:' letter 2's are not for external consumption. They are used
+ * by GAS for psuedo ops relaxing code.
+ *
+ * After parsing topP has:
+ *
+ * top_ndx: -1, or the index register. eg 7=[R7]
+ * top_reg: -1, or register number. eg 7 = R7 or (R7)
+ * top_mode: The addressing mode byte. This byte, defines which of
+ * the 11 modes opcode is.
+ * top_access: Access type wanted for this opperand 'b'branch ' '
+ * no-instruction 'amrvw'
+ * top_width: Operand width expected, one of "bwlq?-:!"
+ * exp_of_operand: The expression as parsed by expression()
+ * top_dispsize: Number of bytes in the displacement if we can figure it
+ * out and it's relavent.
+ *
+ * Need syntax checks built.
+ */
+
+void
+tip_op (optex, topP)
+ char *optex; /* The users text input, with one leading character */
+ struct top *topP; /* The tahoe instruction with some fields already set:
+ in: access, width
+ out: ndx, reg, mode, error, dispsize */
+
+{
+ int mode = 0; /* This operand's mode. */
+ char segfault = *optex; /* To keep the back parsing from freaking. */
+ char *point = optex + 1; /* Parsing from front to back. */
+ char *end; /* Parsing from back to front. */
+ int reg = -1; /* major register, -1 means absent */
+ int imreg = -1; /* Major register in immediate mode */
+ int ndx = -1; /* index register number, -1 means absent */
+ char dec_inc = ' '; /* Is the SP auto-incremented '+' or
+ auto-decremented '-' or neither ' '. */
+ int immediate = 0; /* 1 if '$' immediate mode */
+ int call_width = 0; /* If the caller casts the displacement */
+ int abs_width = 0; /* The width of the absolute displacment */
+ int com_width = 0; /* Displacement width required by branch */
+ int deferred = 0; /* 1 if '*' deferral is used */
+ byte disp_size = 0; /* How big is this operand. 0 == don't know */
+ char *op_bad = ""; /* Bad operand error */
+
+ char *tp, *temp, c; /* Temporary holders */
+
+ char access = topP->top_access; /* Save on a deref. */
+ char width = topP->top_width;
+
+ int really_none = 0; /* Empty expressions evaluate to 0
+ but I need to know if it's there or not */
+ expressionS *expP; /* -> expression values for this operand */
+
+ /* Does this command restrict the displacement size. */
+ if (access == 'b')
+ com_width = (width == 'b' ? 1 :
+ (width == 'w' ? 2 :
+ (width == 'l' ? 4 : 0)));
+
+ *optex = '\0'; /* This is kind of a back stop for all
+ the searches to fail on if needed.*/
+ if (*point == '*')
+ { /* A dereference? */
+ deferred = 1;
+ point++;
+ }
+
+ /* Force words into a certain mode */
+ /* Bitch, Bitch, Bitch! */
+ /*
+ * Using the ^ operator is ambigous. If I have an absolute label
+ * called 'w' set to, say 2, and I have the expression 'w^1', do I get
+ * 1, forced to be in word displacement mode, or do I get the value of
+ * 'w' or'ed with 1 (3 in this case).
+ * The default is 'w' as an offset, so that's what I use.
+ * Stick with `, it does the same, and isn't ambig.
+ */
+
+ if (*point != '\0' && ((point[1] == '^') || (point[1] == '`')))
+ switch (*point)
+ {
+ case 'b':
+ case 'B':
+ case 'w':
+ case 'W':
+ case 'l':
+ case 'L':
+ if (com_width)
+ as_warn (_("Casting a branch displacement is bad form, and is ignored."));
+ else
+ {
+ c = (isupper (*point) ? tolower (*point) : *point);
+ call_width = ((c == 'b') ? 1 :
+ ((c == 'w') ? 2 : 4));
+ }
+ point += 2;
+ break;
+ }
+
+ /* Setting immediate mode */
+ if (*point == '$')
+ {
+ immediate = 1;
+ point++;
+ }
+
+ /*
+ * I've pulled off all the easy stuff off the front, move to the end and
+ * yank.
+ */
+
+ for (end = point; *end != '\0'; end++) /* Move to the end. */
+ ;
+
+ if (end != point) /* Null string? */
+ end--;
+
+ if (end > point && *end == ' ' && end[-1] != '\'')
+ end--; /* Hop white space */
+
+ /* Is this an index reg. */
+ if ((*end == ']') && (end[-1] != '\''))
+ {
+ temp = end;
+
+ /* Find opening brace. */
+ for (--end; (*end != '[' && end != point); end--)
+ ;
+
+ /* If I found the opening brace, get the index register number. */
+ if (*end == '[')
+ {
+ tp = end + 1; /* tp should point to the start of a reg. */
+ ndx = tahoe_reg_parse (&tp);
+ if (tp != temp)
+ { /* Reg. parse error. */
+ ndx = -1;
+ }
+ else
+ {
+ end--; /* Found it, move past brace. */
+ }
+ if (ndx == -1)
+ {
+ op_bad = _("Couldn't parse the [index] in this operand.");
+ end = point; /* Force all the rest of the tests to fail. */
+ }
+ }
+ else
+ {
+ op_bad = _("Couldn't find the opening '[' for the index of this operand.");
+ end = point; /* Force all the rest of the tests to fail. */
+ }
+ }
+
+ /* Post increment? */
+ if (*end == '+')
+ {
+ dec_inc = '+';
+ /* was: *end--; */
+ end--;
+ }
+
+ /* register in parens? */
+ if ((*end == ')') && (end[-1] != '\''))
+ {
+ temp = end;
+
+ /* Find opening paren. */
+ for (--end; (*end != '(' && end != point); end--)
+ ;
+
+ /* If I found the opening paren, get the register number. */
+ if (*end == '(')
+ {
+ tp = end + 1;
+ reg = tahoe_reg_parse (&tp);
+ if (tp != temp)
+ {
+ /* Not a register, but could be part of the expression. */
+ reg = -1;
+ end = temp; /* Rest the pointer back */
+ }
+ else
+ {
+ end--; /* Found the reg. move before opening paren. */
+ }
+ }
+ else
+ {
+ op_bad = _("Couldn't find the opening '(' for the deref of this operand.");
+ end = point; /* Force all the rest of the tests to fail. */
+ }
+ }
+
+ /* Pre decrement? */
+ if (*end == '-')
+ {
+ if (dec_inc != ' ')
+ {
+ op_bad = _("Operand can't be both pre-inc and post-dec.");
+ end = point;
+ }
+ else
+ {
+ dec_inc = '-';
+ /* was: *end--; */
+ end--;
+ }
+ }
+
+ /*
+ * Everything between point and end is the 'expression', unless it's
+ * a register name.
+ */
+
+ c = end[1];
+ end[1] = '\0';
+
+ tp = point;
+ imreg = tahoe_reg_parse (&point); /* Get the immediate register
+ if it is there.*/
+ if (*point != '\0')
+ {
+ /* If there is junk after point, then the it's not immediate reg. */
+ point = tp;
+ imreg = -1;
+ }
+
+ if (imreg != -1 && reg != -1)
+ op_bad = _("I parsed 2 registers in this operand.");
+
+ /*
+ * Evaluate whats left of the expression to see if it's valid.
+ * Note again: This assumes that the calling expression has saved
+ * input_line_pointer. (Nag, nag, nag!)
+ */
+
+ if (*op_bad == '\0')
+ {
+ /* statement has no syntax goofs yet: lets sniff the expression */
+ input_line_pointer = point;
+ expP = &(topP->exp_of_operand);
+ topP->seg_of_operand = expression (expP);
+ switch (expP->X_op)
+ {
+ case O_absent:
+ /* No expression. For BSD4.2 compatibility, missing expression is
+ absolute 0 */
+ expP->X_op = O_constant;
+ expP->X_add_number = 0;
+ really_none = 1;
+ case O_constant:
+ /* for SEG_ABSOLUTE, we shouldnt need to set X_op_symbol,
+ X_add_symbol to any particular value. */
+ /* But, we will program defensively. Since this situation occurs
+ rarely so it costs us little to do so. */
+ expP->X_add_symbol = NULL;
+ expP->X_op_symbol = NULL;
+ /* How many bytes are needed to express this abs value? */
+ abs_width =
+ ((((expP->X_add_number & 0xFFFFFF80) == 0) ||
+ ((expP->X_add_number & 0xFFFFFF80) == 0xFFFFFF80)) ? 1 :
+ (((expP->X_add_number & 0xFFFF8000) == 0) ||
+ ((expP->X_add_number & 0xFFFF8000) == 0xFFFF8000)) ? 2 : 4);
+
+ case O_symbol:
+ break;
+
+ default:
+ /*
+ * Major bug. We can't handle the case of a operator
+ * expression in a synthetic opcode variable-length
+ * instruction. We don't have a frag type that is smart
+ * enough to relax a operator, and so we just force all
+ * operators to behave like SEG_PASS1s. Clearly, if there is
+ * a demand we can invent a new or modified frag type and
+ * then coding up a frag for this case will be easy.
+ */
+ need_pass_2 = 1;
+ op_bad = _("Can't relocate expression error.");
+ break;
+
+ case O_big:
+ /* This is an error. Tahoe doesn't allow any expressions
+ bigger that a 32 bit long word. Any bigger has to be referenced
+ by address. */
+ op_bad = _("Expression is too large for a 32 bits.");
+ break;
+ }
+ if (*input_line_pointer != '\0')
+ {
+ op_bad = _("Junk at end of expression.");
+ }
+ }
+
+ end[1] = c;
+
+ /* I'm done, so restore optex */
+ *optex = segfault;
+
+
+ /*
+ * At this point in the game, we (in theory) have all the components of
+ * the operand at least parsed. Now it's time to check for syntax/semantic
+ * errors, and build the mode.
+ * This is what I have:
+ * deferred = 1 if '*'
+ * call_width = 0,1,2,4
+ * abs_width = 0,1,2,4
+ * com_width = 0,1,2,4
+ * immediate = 1 if '$'
+ * ndx = -1 or reg num
+ * dec_inc = '-' or '+' or ' '
+ * reg = -1 or reg num
+ * imreg = -1 or reg num
+ * topP->exp_of_operand
+ * really_none
+ */
+ /* Is there a displacement size? */
+ disp_size = (call_width ? call_width :
+ (com_width ? com_width :
+ abs_width ? abs_width : 0));
+
+ if (*op_bad == '\0')
+ {
+ if (imreg != -1)
+ {
+ /* Rn */
+ mode = TAHOE_DIRECT_REG;
+ if (deferred || immediate || (dec_inc != ' ') ||
+ (reg != -1) || !really_none)
+ op_bad = _("Syntax error in direct register mode.");
+ else if (ndx != -1)
+ op_bad = _("You can't index a register in direct register mode.");
+ else if (imreg == SP_REG && access == 'r')
+ op_bad =
+ _("SP can't be the source operand with direct register addressing.");
+ else if (access == 'a')
+ op_bad = _("Can't take the address of a register.");
+ else if (access == 'b')
+ op_bad = _("Direct Register can't be used in a branch.");
+ else if (width == 'q' && ((imreg % 2) || (imreg > 13)))
+ op_bad = _("For quad access, the register must be even and < 14.");
+ else if (call_width)
+ op_bad = _("You can't cast a direct register.");
+
+ if (*op_bad == '\0')
+ {
+ /* No errors, check for warnings */
+ if (width == 'q' && imreg == 12)
+ as_warn (_("Using reg 14 for quadwords can tromp the FP register."));
+
+ reg = imreg;
+ }
+
+ /* We know: imm = -1 */
+ }
+ else if (dec_inc == '-')
+ {
+ /* -(SP) */
+ mode = TAHOE_AUTO_DEC;
+ if (deferred || immediate || !really_none)
+ op_bad = _("Syntax error in auto-dec mode.");
+ else if (ndx != -1)
+ op_bad = _("You can't have an index auto dec mode.");
+ else if (access == 'r')
+ op_bad = _("Auto dec mode cant be used for reading.");
+ else if (reg != SP_REG)
+ op_bad = _("Auto dec only works of the SP register.");
+ else if (access == 'b')
+ op_bad = _("Auto dec can't be used in a branch.");
+ else if (width == 'q')
+ op_bad = _("Auto dec won't work with quadwords.");
+
+ /* We know: imm = -1, dec_inc != '-' */
+ }
+ else if (dec_inc == '+')
+ {
+ if (immediate || !really_none)
+ op_bad = _("Syntax error in one of the auto-inc modes.");
+ else if (deferred)
+ {
+ /* *(SP)+ */
+ mode = TAHOE_AUTO_INC_DEFERRED;
+ if (reg != SP_REG)
+ op_bad = _("Auto inc deferred only works of the SP register.");
+ else if (ndx != -1)
+ op_bad = _("You can't have an index auto inc deferred mode.");
+ else if (access == 'b')
+ op_bad = _("Auto inc can't be used in a branch.");
+ }
+ else
+ {
+ /* (SP)+ */
+ mode = TAHOE_AUTO_INC;
+ if (access == 'm' || access == 'w')
+ op_bad = _("You can't write to an auto inc register.");
+ else if (reg != SP_REG)
+ op_bad = _("Auto inc only works of the SP register.");
+ else if (access == 'b')
+ op_bad = _("Auto inc can't be used in a branch.");
+ else if (width == 'q')
+ op_bad = _("Auto inc won't work with quadwords.");
+ else if (ndx != -1)
+ op_bad = _("You can't have an index in auto inc mode.");
+ }
+
+ /* We know: imm = -1, dec_inc == ' ' */
+ }
+ else if (reg != -1)
+ {
+ if ((ndx != -1) && (reg == SP_REG))
+ op_bad = _("You can't index the sp register.");
+ if (deferred)
+ {
+ /* *<disp>(Rn) */
+ mode = TAHOE_REG_DISP_DEFERRED;
+ if (immediate)
+ op_bad = _("Syntax error in register displaced mode.");
+ }
+ else if (really_none)
+ {
+ /* (Rn) */
+ mode = TAHOE_REG_DEFERRED;
+ /* if reg = SP then cant be indexed */
+ }
+ else
+ {
+ /* <disp>(Rn) */
+ mode = TAHOE_REG_DISP;
+ }
+
+ /* We know: imm = -1, dec_inc == ' ', Reg = -1 */
+ }
+ else
+ {
+ if (really_none)
+ op_bad = _("An offest is needed for this operand.");
+ if (deferred && immediate)
+ {
+ /* *$<ADDR> */
+ mode = TAHOE_ABSOLUTE_ADDR;
+ disp_size = 4;
+ }
+ else if (immediate)
+ {
+ /* $<disp> */
+ mode = TAHOE_IMMEDIATE;
+ if (ndx != -1)
+ op_bad = _("You can't index a register in immediate mode.");
+ if (access == 'a')
+ op_bad = _("Immediate access can't be used as an address.");
+ /* ponder the wisdom of a cast because it doesn't do any good. */
+ }
+ else if (deferred)
+ {
+ /* *<disp> */
+ mode = TAHOE_DISP_REL_DEFERRED;
+ }
+ else
+ {
+ /* <disp> */
+ mode = TAHOE_DISPLACED_RELATIVE;
+ }
+ }
+ }
+
+ /*
+ * At this point, all the errors we can do have be checked for.
+ * We can build the 'top'. */
+
+ topP->top_ndx = ndx;
+ topP->top_reg = reg;
+ topP->top_mode = mode;
+ topP->top_error = op_bad;
+ topP->top_dispsize = disp_size;
+} /* tip_op */
+
+/*
+ * t i p ( )
+ *
+ * This converts a string into a tahoe instruction.
+ * The string must be a bare single instruction in tahoe (with BSD4 frobs)
+ * format.
+ * It provides at most one fatal error message (which stops the scan)
+ * some warning messages as it finds them.
+ * The tahoe instruction is returned in exploded form.
+ *
+ * The exploded instruction is returned to a struct tit of your choice.
+ * #include "tahoe-inst.h" to know what a struct tit is.
+ *
+ */
+
+static void
+tip (titP, instring)
+ struct tit *titP; /* We build an exploded instruction here. */
+ char *instring; /* Text of a vax instruction: we modify. */
+{
+ register struct tot_wot *twP = NULL; /* How to bit-encode this opcode. */
+ register char *p; /* 1/skip whitespace.2/scan vot_how */
+ register char *q; /* */
+ register unsigned char count; /* counts number of operands seen */
+ register struct top *operandp;/* scan operands in struct tit */
+ register char *alloperr = ""; /* error over all operands */
+ register char c; /* Remember char, (we clobber it
+ with '\0' temporarily). */
+ char *save_input_line_pointer;
+
+ if (*instring == ' ')
+ ++instring; /* Skip leading whitespace. */
+ for (p = instring; *p && *p != ' '; p++)
+ ; /* MUST end in end-of-string or
+ exactly 1 space. */
+ /* Scanned up to end of operation-code. */
+ /* Operation-code is ended with whitespace. */
+ if (p == instring)
+ {
+ titP->tit_error = _("No operator");
+ count = 0;
+ titP->tit_opcode = 0;
+ }
+ else
+ {
+ c = *p;
+ *p = '\0';
+ /*
+ * Here with instring pointing to what better be an op-name, and p
+ * pointing to character just past that.
+ * We trust instring points to an op-name, with no whitespace.
+ */
+ twP = (struct tot_wot *) hash_find (op_hash, instring);
+ *p = c; /* Restore char after op-code. */
+ if (twP == 0)
+ {
+ titP->tit_error = _("Unknown operator");
+ count = 0;
+ titP->tit_opcode = 0;
+ }
+ else
+ {
+ /*
+ * We found a match! So lets pick up as many operands as the
+ * instruction wants, and even gripe if there are too many.
+ * We expect comma to seperate each operand.
+ * We let instring track the text, while p tracks a part of the
+ * struct tot.
+ */
+
+ count = 0; /* no operands seen yet */
+ instring = p + (*p != '\0'); /* point past the operation code */
+ /* tip_op() screws with the input_line_pointer, so save it before
+ I jump in */
+ save_input_line_pointer = input_line_pointer;
+ for (p = twP->args, operandp = titP->tit_operand;
+ !*alloperr && *p;
+ operandp++, p += 2)
+ {
+ /*
+ * Here to parse one operand. Leave instring pointing just
+ * past any one ',' that marks the end of this operand.
+ */
+ if (!p[1])
+ as_fatal (_("Compiler bug: ODD number of bytes in arg structure %s."),
+ twP->args);
+ else if (*instring)
+ {
+ for (q = instring; (*q != ',' && *q != '\0'); q++)
+ {
+ if (*q == '\'' && q[1] != '\0') /* Jump quoted characters */
+ q++;
+ }
+ c = *q;
+ /*
+ * Q points to ',' or '\0' that ends argument. C is that
+ * character.
+ */
+ *q = '\0';
+ operandp->top_access = p[0];
+ operandp->top_width = p[1];
+ tip_op (instring - 1, operandp);
+ *q = c; /* Restore input text. */
+ if (*(operandp->top_error))
+ {
+ alloperr = operandp->top_error;
+ }
+ instring = q + (c ? 1 : 0); /* next operand (if any) */
+ count++; /* won another argument, may have an operr */
+ }
+ else
+ alloperr = _("Not enough operands");
+ }
+ /* Restore the pointer. */
+ input_line_pointer = save_input_line_pointer;
+
+ if (!*alloperr)
+ {
+ if (*instring == ' ')
+ instring++; /* Skip whitespace. */
+ if (*instring)
+ alloperr = _("Too many operands");
+ }
+ titP->tit_error = alloperr;
+ }
+ }
+
+ titP->tit_opcode = twP->code; /* The op-code. */
+ titP->tit_operands = count;
+} /* tip */
+
+/* md_assemble() emit frags for 1 instruction */
+void
+md_assemble (instruction_string)
+ char *instruction_string; /* A string: assemble 1 instruction. */
+{
+ char *p;
+ register struct top *operandP;/* An operand. Scans all operands. */
+ /* char c_save; fixme: remove this line *//* What used to live after an expression. */
+ /* struct frag *fragP; fixme: remove this line *//* Fragment of code we just made. */
+ /* register struct top *end_operandP; fixme: remove this line *//* -> slot just after last operand
+ Limit of the for (each operand). */
+ register expressionS *expP; /* -> expression values for this operand */
+
+ /* These refer to an instruction operand expression. */
+ segT to_seg; /* Target segment of the address. */
+
+ register valueT this_add_number;
+ register struct symbol *this_add_symbol; /* +ve (minuend) symbol. */
+
+ /* tahoe_opcodeT opcode_as_number; fixme: remove this line *//* The opcode as a number. */
+ char *opcodeP; /* Where it is in a frag. */
+ /* char *opmodeP; fixme: remove this line *//* Where opcode type is, in a frag. */
+
+ int dispsize; /* From top_dispsize: tahoe_operand_width
+ (in bytes) */
+ int is_undefined; /* 1 if operand expression's
+ segment not known yet. */
+ int pc_rel; /* Is this operand pc relative? */
+
+ /* Decode the operand. */
+ tip (&t, instruction_string);
+
+ /*
+ * Check to see if this operand decode properly.
+ * Notice that we haven't made any frags yet.
+ * If it goofed, then this instruction will wedge in any pass,
+ * and we can safely flush it, without causing interpass symbol phase
+ * errors. That is, without changing label values in different passes.
+ */
+ if (*t.tit_error)
+ {
+ as_warn (_("Ignoring statement due to \"%s\""), t.tit_error);
+ }
+ else
+ {
+ /* We saw no errors in any operands - try to make frag(s) */
+ /* Emit op-code. */
+ /* Remember where it is, in case we want to modify the op-code later. */
+ opcodeP = frag_more (1);
+ *opcodeP = t.tit_opcode;
+ /* Now do each operand. */
+ for (operandP = t.tit_operand;
+ operandP < t.tit_operand + t.tit_operands;
+ operandP++)
+ { /* for each operand */
+ expP = &(operandP->exp_of_operand);
+ if (operandP->top_ndx >= 0)
+ {
+ /* Indexed addressing byte
+ Legality of indexed mode already checked: it is OK */
+ FRAG_APPEND_1_CHAR (0x40 + operandP->top_ndx);
+ } /* if(top_ndx>=0) */
+
+ /* Here to make main operand frag(s). */
+ this_add_number = expP->X_add_number;
+ this_add_symbol = expP->X_add_symbol;
+ to_seg = operandP->seg_of_operand;
+ know (to_seg == SEG_UNKNOWN || \
+ to_seg == SEG_ABSOLUTE || \
+ to_seg == SEG_DATA || \
+ to_seg == SEG_TEXT || \
+ to_seg == SEG_BSS);
+ is_undefined = (to_seg == SEG_UNKNOWN);
+ /* Do we know how big this opperand is? */
+ dispsize = operandP->top_dispsize;
+ pc_rel = 0;
+ /* Deal with the branch possabilities. (Note, this doesn't include
+ jumps.)*/
+ if (operandP->top_access == 'b')
+ {
+ /* Branches must be expressions. A psuedo branch can also jump to
+ an absolute address. */
+ if (to_seg == now_seg || is_undefined)
+ {
+ /* If is_undefined, then it might BECOME now_seg by relax time. */
+ if (dispsize)
+ {
+ /* I know how big the branch is supposed to be (it's a normal
+ branch), so I set up the frag, and let GAS do the rest. */
+ p = frag_more (dispsize);
+ fix_new (frag_now, p - frag_now->fr_literal,
+ this_add_symbol, this_add_number,
+ size_to_fx (dispsize, 1),
+ NULL);
+ }
+ else
+ {
+ /* (to_seg==now_seg || to_seg == SEG_UNKNOWN) && dispsize==0 */
+ /* If we don't know how big it is, then its a synthetic branch,
+ so we set up a simple relax state. */
+ switch (operandP->top_width)
+ {
+ case TAHOE_WIDTH_CONDITIONAL_JUMP:
+ /* Simple (conditional) jump. I may have to reverse the
+ condition of opcodeP, and then jump to my destination.
+ I set 1 byte aside for the branch off set, and could need 6
+ more bytes for the pc_rel jump */
+ frag_var (rs_machine_dependent, 7, 1,
+ ENCODE_RELAX (STATE_CONDITIONAL_BRANCH,
+ is_undefined ? STATE_UNDF : STATE_BYTE),
+ this_add_symbol, this_add_number, opcodeP);
+ break;
+ case TAHOE_WIDTH_ALWAYS_JUMP:
+ /* Simple (unconditional) jump. I may have to convert this to
+ a word branch, or an absolute jump. */
+ frag_var (rs_machine_dependent, 5, 1,
+ ENCODE_RELAX (STATE_ALWAYS_BRANCH,
+ is_undefined ? STATE_UNDF : STATE_BYTE),
+ this_add_symbol, this_add_number, opcodeP);
+ break;
+ /* The smallest size for the next 2 cases is word. */
+ case TAHOE_WIDTH_BIG_REV_JUMP:
+ frag_var (rs_machine_dependent, 8, 2,
+ ENCODE_RELAX (STATE_BIG_REV_BRANCH,
+ is_undefined ? STATE_UNDF : STATE_WORD),
+ this_add_symbol, this_add_number,
+ opcodeP);
+ break;
+ case TAHOE_WIDTH_BIG_NON_REV_JUMP:
+ frag_var (rs_machine_dependent, 10, 2,
+ ENCODE_RELAX (STATE_BIG_NON_REV_BRANCH,
+ is_undefined ? STATE_UNDF : STATE_WORD),
+ this_add_symbol, this_add_number,
+ opcodeP);
+ break;
+ default:
+ as_fatal (_("Compliler bug: Got a case (%d) I wasn't expecting."),
+ operandP->top_width);
+ }
+ }
+ }
+ else
+ {
+ /* to_seg != now_seg && to_seg != seg_unknown (still in branch)
+ In other words, I'm jumping out of my segment so extend the
+ branches to jumps, and let GAS fix them. */
+
+ /* These are "branches" what will always be branches around a jump
+ to the correct addresss in real life.
+ If to_seg is SEG_ABSOLUTE, just encode the branch in,
+ else let GAS fix the address. */
+
+ switch (operandP->top_width)
+ {
+ /* The theory:
+ For SEG_ABSOLUTE, then mode is ABSOLUTE_ADDR, jump
+ to that addresss (not pc_rel).
+ For other segs, address is a long word PC rel jump. */
+ case TAHOE_WIDTH_CONDITIONAL_JUMP:
+ /* b<cond> */
+ /* To reverse the condition in a TAHOE branch,
+ complement bit 4 */
+ *opcodeP ^= 0x10;
+ p = frag_more (7);
+ *p++ = 6;
+ *p++ = TAHOE_JMP;
+ *p++ = (operandP->top_mode ==
+ TAHOE_ABSOLUTE_ADDR ? TAHOE_ABSOLUTE_ADDR :
+ TAHOE_PC_REL_LONG);
+ fix_new (frag_now, p - frag_now->fr_literal,
+ this_add_symbol, this_add_number,
+ (to_seg != SEG_ABSOLUTE) ? FX_PCREL32 : FX_32, NULL);
+ /*
+ * Now (eg) BLEQ 1f
+ * JMP foo
+ * 1:
+ */
+ break;
+ case TAHOE_WIDTH_ALWAYS_JUMP:
+ /* br, just turn it into a jump */
+ *opcodeP = TAHOE_JMP;
+ p = frag_more (5);
+ *p++ = (operandP->top_mode ==
+ TAHOE_ABSOLUTE_ADDR ? TAHOE_ABSOLUTE_ADDR :
+ TAHOE_PC_REL_LONG);
+ fix_new (frag_now, p - frag_now->fr_literal,
+ this_add_symbol, this_add_number,
+ (to_seg != SEG_ABSOLUTE) ? FX_PCREL32 : FX_32, NULL);
+ /* Now (eg) JMP foo */
+ break;
+ case TAHOE_WIDTH_BIG_REV_JUMP:
+ p = frag_more (8);
+ *opcodeP ^= 0x10;
+ *p++ = 0;
+ *p++ = 6;
+ *p++ = TAHOE_JMP;
+ *p++ = (operandP->top_mode ==
+ TAHOE_ABSOLUTE_ADDR ? TAHOE_ABSOLUTE_ADDR :
+ TAHOE_PC_REL_LONG);
+ fix_new (frag_now, p - frag_now->fr_literal,
+ this_add_symbol, this_add_number,
+ (to_seg != SEG_ABSOLUTE) ? FX_PCREL32 : FX_32, NULL);
+ /*
+ * Now (eg) ACBx 1f
+ * JMP foo
+ * 1:
+ */
+ break;
+ case TAHOE_WIDTH_BIG_NON_REV_JUMP:
+ p = frag_more (10);
+ *p++ = 0;
+ *p++ = 2;
+ *p++ = TAHOE_BRB;
+ *p++ = 6;
+ *p++ = TAHOE_JMP;
+ *p++ = (operandP->top_mode ==
+ TAHOE_ABSOLUTE_ADDR ? TAHOE_ABSOLUTE_ADDR :
+ TAHOE_PC_REL_LONG);
+ fix_new (frag_now, p - frag_now->fr_literal,
+ this_add_symbol, this_add_number,
+ (to_seg != SEG_ABSOLUTE) ? FX_PCREL32 : FX_32, NULL);
+ /*
+ * Now (eg) xOBxxx 1f
+ * BRB 2f
+ * 1: JMP @#foo
+ * 2:
+ */
+ break;
+ case 'b':
+ case 'w':
+ as_warn (_("Real branch displacements must be expressions."));
+ break;
+ default:
+ as_fatal (_("Complier error: I got an unknown synthetic branch :%c"),
+ operandP->top_width);
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* It ain't a branch operand. */
+ switch (operandP->top_mode)
+ {
+ /* Auto-foo access, only works for one reg (SP)
+ so the only thing needed is the mode. */
+ case TAHOE_AUTO_DEC:
+ case TAHOE_AUTO_INC:
+ case TAHOE_AUTO_INC_DEFERRED:
+ FRAG_APPEND_1_CHAR (operandP->top_mode);
+ break;
+
+ /* Numbered Register only access. Only thing needed is the
+ mode + Register number */
+ case TAHOE_DIRECT_REG:
+ case TAHOE_REG_DEFERRED:
+ FRAG_APPEND_1_CHAR (operandP->top_mode + operandP->top_reg);
+ break;
+
+ /* An absolute address. It's size is always 5 bytes.
+ (mode_type + 4 byte address). */
+ case TAHOE_ABSOLUTE_ADDR:
+ know ((this_add_symbol == NULL));
+ p = frag_more (5);
+ *p = TAHOE_ABSOLUTE_ADDR;
+ md_number_to_chars (p + 1, this_add_number, 4);
+ break;
+
+ /* Immediate data. If the size isn't known, then it's an address
+ + and offset, which is 4 bytes big. */
+ case TAHOE_IMMEDIATE:
+ if (this_add_symbol != NULL)
+ {
+ p = frag_more (5);
+ *p++ = TAHOE_IMMEDIATE_LONGWORD;
+ fix_new (frag_now, p - frag_now->fr_literal,
+ this_add_symbol, this_add_number,
+ FX_32, NULL);
+ }
+ else
+ {
+ /* It's a integer, and I know it's size. */
+ if ((unsigned) this_add_number < 0x40)
+ {
+ /* Will it fit in a literal? */
+ FRAG_APPEND_1_CHAR ((byte) this_add_number);
+ }
+ else
+ {
+ p = frag_more (dispsize + 1);
+ switch (dispsize)
+ {
+ case 1:
+ *p++ = TAHOE_IMMEDIATE_BYTE;
+ *p = (byte) this_add_number;
+ break;
+ case 2:
+ *p++ = TAHOE_IMMEDIATE_WORD;
+ md_number_to_chars (p, this_add_number, 2);
+ break;
+ case 4:
+ *p++ = TAHOE_IMMEDIATE_LONGWORD;
+ md_number_to_chars (p, this_add_number, 4);
+ break;
+ }
+ }
+ }
+ break;
+
+ /* Distance from the PC. If the size isn't known, we have to relax
+ into it. The difference between this and disp(sp) is that
+ this offset is pc_rel, and disp(sp) isn't.
+ Note the drop through code. */
+
+ case TAHOE_DISPLACED_RELATIVE:
+ case TAHOE_DISP_REL_DEFERRED:
+ operandP->top_reg = PC_REG;
+ pc_rel = 1;
+
+ /* Register, plus a displacement mode. Save the register number,
+ and weather its deffered or not, and relax the size if it isn't
+ known. */
+ case TAHOE_REG_DISP:
+ case TAHOE_REG_DISP_DEFERRED:
+ if (operandP->top_mode == TAHOE_DISP_REL_DEFERRED ||
+ operandP->top_mode == TAHOE_REG_DISP_DEFERRED)
+ operandP->top_reg += 0x10; /* deffered mode is always 0x10 higher
+ than it's non-deffered sibling. */
+
+ /* Is this a value out of this segment?
+ The first part of this conditional is a cludge to make gas
+ produce the same output as 'as' when there is a lable, in
+ the current segment, displaceing a register. It's strange,
+ and no one in their right mind would do it, but it's easy
+ to cludge. */
+ if ((dispsize == 0 && !pc_rel) ||
+ (to_seg != now_seg && !is_undefined && to_seg != SEG_ABSOLUTE))
+ dispsize = 4;
+
+ if (dispsize == 0)
+ {
+ /*
+ * We have a SEG_UNKNOWN symbol, or the size isn't cast.
+ * It might turn out to be in the same segment as
+ * the instruction, permitting relaxation.
+ */
+ p = frag_var (rs_machine_dependent, 5, 2,
+ ENCODE_RELAX (STATE_PC_RELATIVE,
+ is_undefined ? STATE_UNDF : STATE_BYTE),
+ this_add_symbol, this_add_number, 0);
+ *p = operandP->top_reg;
+ }
+ else
+ {
+ /* Either this is an abs, or a cast. */
+ p = frag_more (dispsize + 1);
+ switch (dispsize)
+ {
+ case 1:
+ *p = TAHOE_PC_OR_BYTE + operandP->top_reg;
+ break;
+ case 2:
+ *p = TAHOE_PC_OR_WORD + operandP->top_reg;
+ break;
+ case 4:
+ *p = TAHOE_PC_OR_LONG + operandP->top_reg;
+ break;
+ };
+ fix_new (frag_now, p + 1 - frag_now->fr_literal,
+ this_add_symbol, this_add_number,
+ size_to_fx (dispsize, pc_rel), NULL);
+ }
+ break;
+ default:
+ as_fatal (_("Barf, bad mode %x\n"), operandP->top_mode);
+ }
+ }
+ } /* for(operandP) */
+ } /* if(!need_pass_2 && !goofed) */
+} /* tahoe_assemble() */
+
+
+/* We have no need to default values of symbols. */
+
+/* ARGSUSED */
+symbolS *
+md_undefined_symbol (name)
+ char *name;
+{
+ return 0;
+} /* md_undefined_symbol() */
+
+/* Round up a section size to the appropriate boundary. */
+valueT
+md_section_align (segment, size)
+ segT segment;
+ valueT size;
+{
+ return ((size + 7) & ~7); /* Round all sects to multiple of 8 */
+} /* md_section_align() */
+
+/* Exactly what point is a PC-relative offset relative TO?
+ On the sparc, they're relative to the address of the offset, plus
+ its size. This gets us to the following instruction.
+ (??? Is this right? FIXME-SOON) */
+long
+md_pcrel_from (fixP)
+ fixS *fixP;
+{
+ return (((fixP->fx_type == FX_8
+ || fixP->fx_type == FX_PCREL8)
+ ? 1
+ : ((fixP->fx_type == FX_16
+ || fixP->fx_type == FX_PCREL16)
+ ? 2
+ : ((fixP->fx_type == FX_32
+ || fixP->fx_type == FX_PCREL32)
+ ? 4
+ : 0))) + fixP->fx_where + fixP->fx_frag->fr_address);
+} /* md_pcrel_from() */
+
+int
+tc_is_pcrel (fixP)
+ fixS *fixP;
+{
+ /* should never be called */
+ know (0);
+ return (0);
+} /* tc_is_pcrel() */
+
+/* end of tc-tahoe.c */
diff --git a/gas/config/tc-tahoe.h b/gas/config/tc-tahoe.h
new file mode 100644
index 0000000000..be8a5bea8e
--- /dev/null
+++ b/gas/config/tc-tahoe.h
@@ -0,0 +1,43 @@
+/* This file is tc-tahoe.h
+
+ Copyright (C) 1987-1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TC_TAHOE 1
+
+#define TARGET_BYTES_BIG_ENDIAN 1
+
+#define NO_LISTING
+
+#define tc_headers_hook(a) {;} /* don't need it. */
+#define tc_crawl_symbol_chain(a) {;} /* don't need it. */
+#define tc_aout_pre_write_hook(a) {;}
+
+#define md_operand(x)
+
+extern const struct relax_type md_relax_table[];
+#define TC_GENERIC_RELAX_TABLE md_relax_table
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of tc-tahoe.h */
diff --git a/gas/config/tc-tic30.c b/gas/config/tc-tic30.c
new file mode 100644
index 0000000000..61ed905e47
--- /dev/null
+++ b/gas/config/tc-tic30.c
@@ -0,0 +1,1887 @@
+/* tc-c30.c -- Assembly code for the Texas Instruments TMS320C30
+ Copyright (C) 1998 Free Software Foundation.
+ Contributed by Steven Haworth (steve@pm.cse.rmit.edu.au)
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/*
+ Texas Instruments TMS320C30 machine specific gas.
+ Written by Steven Haworth (steve@pm.cse.rmit.edu.au).
+ Bugs & suggestions are completely welcome. This is free software.
+ Please help us make it better.
+ */
+
+#include "as.h"
+#include "opcode/tic30.h"
+
+/* put here all non-digit non-letter charcters that may occur in an operand */
+static char operand_special_chars[] = "%$-+(,)*._~/<>&^!:[@]";
+static char *ordinal_names[] =
+{"first", "second", "third", "fourth", "fifth"};
+
+const int md_reloc_size = 0;
+
+const char comment_chars[] = ";";
+const char line_comment_chars[] = "*";
+const char line_separator_chars[] = "";
+
+const char *md_shortopts = "";
+struct option md_longopts[] =
+{
+ {NULL, no_argument, NULL, 0}
+};
+
+size_t md_longopts_size = sizeof (md_longopts);
+
+/* Chars that mean this number is a floating point constant */
+/* As in 0f12.456 */
+/* or 0d1.2345e12 */
+const char FLT_CHARS[] = "fFdDxX";
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+const char EXP_CHARS[] = "eE";
+
+/* tables for lexical analysis */
+static char opcode_chars[256];
+static char register_chars[256];
+static char operand_chars[256];
+static char space_chars[256];
+static char identifier_chars[256];
+static char digit_chars[256];
+
+/* lexical macros */
+#define is_opcode_char(x) (opcode_chars[(unsigned char) x])
+#define is_operand_char(x) (operand_chars[(unsigned char) x])
+#define is_register_char(x) (register_chars[(unsigned char) x])
+#define is_space_char(x) (space_chars[(unsigned char) x])
+#define is_identifier_char(x) (identifier_chars[(unsigned char) x])
+#define is_digit_char(x) (digit_chars[(unsigned char) x])
+
+const pseudo_typeS md_pseudo_table[] =
+{
+ {0, 0, 0}
+};
+
+#undef USE_STDOUT
+#define USE_STDOUT 1
+
+#ifdef USE_STDARG
+
+#include <stdarg.h>
+
+int
+debug (const char *string,...)
+{
+ if (flag_debug)
+ {
+ va_list argptr;
+ char str[100];
+
+ va_start (argptr, string);
+ vsprintf (str, string, argptr);
+ if (str[0] == '\0')
+ return (0);
+ va_end (argptr);
+ fputs (str, USE_STDOUT ? stdout : stderr);
+ return strlen (str);
+ }
+ else
+ return 0;
+}
+#else
+int
+debug (string, va_alist)
+ const char *string;
+ va_dcl
+{
+ if (flag_debug)
+ {
+ va_list argptr;
+ char str[100];
+ int cnt;
+
+ va_start (argptr, string);
+ cnt = vsprintf (str, string, argptr);
+ if (str[0] == NULL)
+ return (0);
+ va_end (argptr);
+ fputs (str, USE_STDOUT ? stdout : stderr);
+ return (cnt);
+ }
+ else
+ return 0;
+}
+#endif
+
+/* hash table for opcode lookup */
+static struct hash_control *op_hash;
+/* hash table for parallel opcode lookup */
+static struct hash_control *parop_hash;
+/* hash table for register lookup */
+static struct hash_control *reg_hash;
+/* hash table for indirect addressing lookup */
+static struct hash_control *ind_hash;
+
+void
+md_begin ()
+{
+ const char *hash_err;
+ debug ("In md_begin()\n");
+ op_hash = hash_new ();
+ {
+ const template *current_optab = tic30_optab;
+ for (; current_optab < tic30_optab_end; current_optab++)
+ {
+ hash_err = hash_insert (op_hash, current_optab->name, (char *) current_optab);
+ if (hash_err)
+ as_fatal ("Internal Error: Can't Hash %s: %s", current_optab->name, hash_err);
+ }
+ }
+ parop_hash = hash_new ();
+ {
+ const partemplate *current_parop = tic30_paroptab;
+ for (; current_parop < tic30_paroptab_end; current_parop++)
+ {
+ hash_err = hash_insert (parop_hash, current_parop->name, (char *) current_parop);
+ if (hash_err)
+ as_fatal ("Internal Error: Can't Hash %s: %s", current_parop->name, hash_err);
+ }
+ }
+ reg_hash = hash_new ();
+ {
+ const reg *current_reg = tic30_regtab;
+ for (; current_reg < tic30_regtab_end; current_reg++)
+ {
+ hash_err = hash_insert (reg_hash, current_reg->name, (char *) current_reg);
+ if (hash_err)
+ as_fatal ("Internal Error: Can't Hash %s: %s", current_reg->name, hash_err);
+ }
+ }
+ ind_hash = hash_new ();
+ {
+ const ind_addr_type *current_ind = tic30_indaddr_tab;
+ for (; current_ind < tic30_indaddrtab_end; current_ind++)
+ {
+ hash_err = hash_insert (ind_hash, current_ind->syntax, (char *) current_ind);
+ if (hash_err)
+ as_fatal ("Internal Error: Can't Hash %s: %s", current_ind->syntax, hash_err);
+ }
+ }
+ /* fill in lexical tables: opcode_chars, operand_chars, space_chars */
+ {
+ register int c;
+ register char *p;
+
+ for (c = 0; c < 256; c++)
+ {
+ if (islower (c) || isdigit (c))
+ {
+ opcode_chars[c] = c;
+ register_chars[c] = c;
+ }
+ else if (isupper (c))
+ {
+ opcode_chars[c] = tolower (c);
+ register_chars[c] = opcode_chars[c];
+ }
+ else if (c == ')' || c == '(')
+ {
+ register_chars[c] = c;
+ }
+ if (isupper (c) || islower (c) || isdigit (c))
+ operand_chars[c] = c;
+ if (isdigit (c) || c == '-')
+ digit_chars[c] = c;
+ if (isalpha (c) || c == '_' || c == '.' || isdigit (c))
+ identifier_chars[c] = c;
+ if (c == ' ' || c == '\t')
+ space_chars[c] = c;
+ if (c == '_')
+ opcode_chars[c] = c;
+ }
+ for (p = operand_special_chars; *p != '\0'; p++)
+ operand_chars[(unsigned char) *p] = *p;
+ }
+}
+
+/* Address Mode OR values */
+#define AM_Register 0x00000000
+#define AM_Direct 0x00200000
+#define AM_Indirect 0x00400000
+#define AM_Immediate 0x00600000
+#define AM_NotReq 0xFFFFFFFF
+
+/* PC Relative OR values */
+#define PC_Register 0x00000000
+#define PC_Relative 0x02000000
+
+typedef struct
+{
+ unsigned op_type;
+ struct
+ {
+ int resolved;
+ unsigned address;
+ char *label;
+ expressionS direct_expr;
+ }
+ direct;
+ struct
+ {
+ unsigned mod;
+ int ARnum;
+ unsigned char disp;
+ }
+ indirect;
+ struct
+ {
+ unsigned opcode;
+ }
+ reg;
+ struct
+ {
+ int resolved;
+ int decimal_found;
+ float f_number;
+ int s_number;
+ unsigned int u_number;
+ char *label;
+ expressionS imm_expr;
+ }
+ immediate;
+}
+operand;
+
+int tic30_parallel_insn PARAMS ((char *));
+operand *tic30_operand PARAMS ((char *));
+char *tic30_find_parallel_insn PARAMS ((char *, char *));
+
+template *opcode;
+
+struct tic30_insn
+ {
+ template *tm; /* Template of current instruction */
+ unsigned opcode; /* Final opcode */
+ int operands; /* Number of given operands */
+ /* Type of operand given in instruction */
+ operand *operand_type[MAX_OPERANDS];
+ unsigned addressing_mode; /* Final addressing mode of instruction */
+ };
+
+struct tic30_insn insn;
+static int found_parallel_insn;
+
+void
+md_assemble (line)
+ char *line;
+{
+ template *opcode;
+ char *current_posn;
+ char *token_start;
+ char save_char;
+ int count;
+
+ debug ("In md_assemble() with argument %s\n", line);
+ memset (&insn, '\0', sizeof (insn));
+ if (found_parallel_insn)
+ {
+ debug ("Line is second part of parallel instruction\n\n");
+ found_parallel_insn = 0;
+ return;
+ }
+ if ((current_posn = tic30_find_parallel_insn (line, input_line_pointer + 1)) == NULL)
+ current_posn = line;
+ else
+ found_parallel_insn = 1;
+ while (is_space_char (*current_posn))
+ current_posn++;
+ token_start = current_posn;
+ if (!is_opcode_char (*current_posn))
+ {
+ as_bad ("Invalid character %s in opcode", output_invalid (*current_posn));
+ return;
+ }
+ /* Check if instruction is a parallel instruction by seeing if the first
+ character is a q. */
+ if (*token_start == 'q')
+ {
+ if (tic30_parallel_insn (token_start))
+ {
+ if (found_parallel_insn)
+ free (token_start);
+ return;
+ }
+ }
+ while (is_opcode_char (*current_posn))
+ current_posn++;
+ { /* Find instruction */
+ save_char = *current_posn;
+ *current_posn = '\0';
+ opcode = (template *) hash_find (op_hash, token_start);
+ if (opcode)
+ {
+ debug ("Found instruction %s\n", opcode->name);
+ insn.tm = opcode;
+ }
+ else
+ {
+ debug ("Didn't find insn\n");
+ as_bad ("Unknown TMS320C30 instruction: %s", token_start);
+ return;
+ }
+ *current_posn = save_char;
+ }
+ if (*current_posn != END_OF_INSN)
+ { /* Find operands */
+ int paren_not_balanced;
+ int expecting_operand = 0;
+ int this_operand;
+ do
+ {
+ /* skip optional white space before operand */
+ while (!is_operand_char (*current_posn) && *current_posn != END_OF_INSN)
+ {
+ if (!is_space_char (*current_posn))
+ {
+ as_bad ("Invalid character %s before %s operand",
+ output_invalid (*current_posn),
+ ordinal_names[insn.operands]);
+ return;
+ }
+ current_posn++;
+ }
+ token_start = current_posn; /* after white space */
+ paren_not_balanced = 0;
+ while (paren_not_balanced || *current_posn != ',')
+ {
+ if (*current_posn == END_OF_INSN)
+ {
+ if (paren_not_balanced)
+ {
+ as_bad ("Unbalanced parenthesis in %s operand.",
+ ordinal_names[insn.operands]);
+ return;
+ }
+ else
+ break; /* we are done */
+ }
+ else if (!is_operand_char (*current_posn) && !is_space_char (*current_posn))
+ {
+ as_bad ("Invalid character %s in %s operand",
+ output_invalid (*current_posn),
+ ordinal_names[insn.operands]);
+ return;
+ }
+ if (*current_posn == '(')
+ ++paren_not_balanced;
+ if (*current_posn == ')')
+ --paren_not_balanced;
+ current_posn++;
+ }
+ if (current_posn != token_start)
+ { /* yes, we've read in another operand */
+ this_operand = insn.operands++;
+ if (insn.operands > MAX_OPERANDS)
+ {
+ as_bad ("Spurious operands; (%d operands/instruction max)",
+ MAX_OPERANDS);
+ return;
+ }
+ /* now parse operand adding info to 'insn' as we go along */
+ save_char = *current_posn;
+ *current_posn = '\0';
+ insn.operand_type[this_operand] = tic30_operand (token_start);
+ *current_posn = save_char;
+ if (insn.operand_type[this_operand] == NULL)
+ return;
+ }
+ else
+ {
+ if (expecting_operand)
+ {
+ as_bad ("Expecting operand after ','; got nothing");
+ return;
+ }
+ if (*current_posn == ',')
+ {
+ as_bad ("Expecting operand before ','; got nothing");
+ return;
+ }
+ }
+ /* now *current_posn must be either ',' or END_OF_INSN */
+ if (*current_posn == ',')
+ {
+ if (*++current_posn == END_OF_INSN)
+ { /* just skip it, if it's \n complain */
+ as_bad ("Expecting operand after ','; got nothing");
+ return;
+ }
+ expecting_operand = 1;
+ }
+ }
+ while (*current_posn != END_OF_INSN); /* until we get end of insn */
+ }
+ debug ("Number of operands found: %d\n", insn.operands);
+ /* Check that number of operands is correct */
+ if (insn.operands != insn.tm->operands)
+ {
+ int i;
+ int numops = insn.tm->operands;
+ /* If operands are not the same, then see if any of the operands are not
+ required. Then recheck with number of given operands. If they are still not
+ the same, then give an error, otherwise carry on. */
+ for (i = 0; i < insn.tm->operands; i++)
+ if (insn.tm->operand_types[i] & NotReq)
+ numops--;
+ if (insn.operands != numops)
+ {
+ as_bad ("Incorrect number of operands given");
+ return;
+ }
+ }
+ insn.addressing_mode = AM_NotReq;
+ for (count = 0; count < insn.operands; count++)
+ {
+ if (insn.operand_type[count]->op_type & insn.tm->operand_types[count])
+ {
+ debug ("Operand %d matches\n", count + 1);
+ /* If instruction has two operands and has an AddressMode modifier then set
+ addressing mode type for instruction */
+ if (insn.tm->opcode_modifier == AddressMode)
+ {
+ int addr_insn = 0;
+ /* Store instruction uses the second operand for the address mode. */
+ if ((insn.tm->operand_types[1] & (Indirect | Direct)) == (Indirect | Direct))
+ addr_insn = 1;
+ if (insn.operand_type[addr_insn]->op_type & (AllReg))
+ insn.addressing_mode = AM_Register;
+ else if (insn.operand_type[addr_insn]->op_type & Direct)
+ insn.addressing_mode = AM_Direct;
+ else if (insn.operand_type[addr_insn]->op_type & Indirect)
+ insn.addressing_mode = AM_Indirect;
+ else
+ insn.addressing_mode = AM_Immediate;
+ }
+ }
+ else
+ {
+ as_bad ("The %s operand doesn't match", ordinal_names[count]);
+ return;
+ }
+ }
+ /* Now set the addressing mode for 3 operand instructions. */
+ if ((insn.tm->operand_types[0] & op3T1) && (insn.tm->operand_types[1] & op3T2))
+ {
+ /* Set the addressing mode to the values used for 2 operand instructions in the
+ G addressing field of the opcode. */
+ char *p;
+ switch (insn.operand_type[0]->op_type)
+ {
+ case Rn:
+ case ARn:
+ case DPReg:
+ case OtherReg:
+ if (insn.operand_type[1]->op_type & (AllReg))
+ insn.addressing_mode = AM_Register;
+ else if (insn.operand_type[1]->op_type & Indirect)
+ insn.addressing_mode = AM_Direct;
+ else
+ {
+ /* Shouldn't make it to this stage */
+ as_bad ("Incompatible first and second operands in instruction");
+ return;
+ }
+ break;
+ case Indirect:
+ if (insn.operand_type[1]->op_type & (AllReg))
+ insn.addressing_mode = AM_Indirect;
+ else if (insn.operand_type[1]->op_type & Indirect)
+ insn.addressing_mode = AM_Immediate;
+ else
+ {
+ /* Shouldn't make it to this stage */
+ as_bad ("Incompatible first and second operands in instruction");
+ return;
+ }
+ break;
+ }
+ /* Now make up the opcode for the 3 operand instructions. As in parallel
+ instructions, there will be no unresolved values, so they can be fully formed
+ and added to the frag table. */
+ insn.opcode = insn.tm->base_opcode;
+ if (insn.operand_type[0]->op_type & Indirect)
+ {
+ insn.opcode |= (insn.operand_type[0]->indirect.ARnum);
+ insn.opcode |= (insn.operand_type[0]->indirect.mod << 3);
+ }
+ else
+ insn.opcode |= (insn.operand_type[0]->reg.opcode);
+ if (insn.operand_type[1]->op_type & Indirect)
+ {
+ insn.opcode |= (insn.operand_type[1]->indirect.ARnum << 8);
+ insn.opcode |= (insn.operand_type[1]->indirect.mod << 11);
+ }
+ else
+ insn.opcode |= (insn.operand_type[1]->reg.opcode << 8);
+ if (insn.operands == 3)
+ insn.opcode |= (insn.operand_type[2]->reg.opcode << 16);
+ insn.opcode |= insn.addressing_mode;
+ p = frag_more (INSN_SIZE);
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ }
+ else
+ { /* Not a three operand instruction */
+ char *p;
+ int am_insn = -1;
+ insn.opcode = insn.tm->base_opcode;
+ /* Create frag for instruction - all instructions are 4 bytes long. */
+ p = frag_more (INSN_SIZE);
+ if ((insn.operands > 0) && (insn.tm->opcode_modifier == AddressMode))
+ {
+ insn.opcode |= insn.addressing_mode;
+ if (insn.addressing_mode == AM_Indirect)
+ {
+ /* Determine which operand gives the addressing mode */
+ if (insn.operand_type[0]->op_type & Indirect)
+ am_insn = 0;
+ if ((insn.operands > 1) && (insn.operand_type[1]->op_type & Indirect))
+ am_insn = 1;
+ insn.opcode |= (insn.operand_type[am_insn]->indirect.disp);
+ insn.opcode |= (insn.operand_type[am_insn]->indirect.ARnum << 8);
+ insn.opcode |= (insn.operand_type[am_insn]->indirect.mod << 11);
+ if (insn.operands > 1)
+ insn.opcode |= (insn.operand_type[!am_insn]->reg.opcode << 16);
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ }
+ else if (insn.addressing_mode == AM_Register)
+ {
+ insn.opcode |= (insn.operand_type[0]->reg.opcode);
+ if (insn.operands > 1)
+ insn.opcode |= (insn.operand_type[1]->reg.opcode << 16);
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ }
+ else if (insn.addressing_mode == AM_Direct)
+ {
+ if (insn.operand_type[0]->op_type & Direct)
+ am_insn = 0;
+ if ((insn.operands > 1) && (insn.operand_type[1]->op_type & Direct))
+ am_insn = 1;
+ if (insn.operands > 1)
+ insn.opcode |= (insn.operand_type[!am_insn]->reg.opcode << 16);
+ if (insn.operand_type[am_insn]->direct.resolved == 1)
+ {
+ /* Resolved values can be placed straight into instruction word, and output */
+ insn.opcode |= (insn.operand_type[am_insn]->direct.address & 0x0000FFFF);
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ }
+ else
+ { /* Unresolved direct addressing mode instruction */
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ fix_new_exp (frag_now, p + 2 - (frag_now->fr_literal), 2, &insn.operand_type[am_insn]->direct.direct_expr, 0, 0);
+ }
+ }
+ else if (insn.addressing_mode == AM_Immediate)
+ {
+ if (insn.operand_type[0]->immediate.resolved == 1)
+ {
+ char *keeploc;
+ int size;
+ if (insn.operands > 1)
+ insn.opcode |= (insn.operand_type[1]->reg.opcode << 16);
+ switch (insn.tm->imm_arg_type)
+ {
+ case Imm_Float:
+ debug ("Floating point first operand\n");
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ keeploc = input_line_pointer;
+ input_line_pointer = insn.operand_type[0]->immediate.label;
+ if (md_atof ('f', p + 2, &size) != 0)
+ {
+ as_bad ("invalid short form floating point immediate operand");
+ return;
+ }
+ input_line_pointer = keeploc;
+ break;
+ case Imm_UInt:
+ debug ("Unsigned int first operand\n");
+ if (insn.operand_type[0]->immediate.decimal_found)
+ as_warn ("rounding down first operand float to unsigned int");
+ if (insn.operand_type[0]->immediate.u_number > 0xFFFF)
+ as_warn ("only lower 16-bits of first operand are used");
+ insn.opcode |= (insn.operand_type[0]->immediate.u_number & 0x0000FFFFL);
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ break;
+ case Imm_SInt:
+ debug ("Int first operand\n");
+ if (insn.operand_type[0]->immediate.decimal_found)
+ as_warn ("rounding down first operand float to signed int");
+ if (insn.operand_type[0]->immediate.s_number < -32768 ||
+ insn.operand_type[0]->immediate.s_number > 32767)
+ {
+ as_bad ("first operand is too large for 16-bit signed int");
+ return;
+ }
+ insn.opcode |= (insn.operand_type[0]->immediate.s_number & 0x0000FFFFL);
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ break;
+ }
+ }
+ else
+ { /* Unresolved immediate label */
+ if (insn.operands > 1)
+ insn.opcode |= (insn.operand_type[1]->reg.opcode << 16);
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ fix_new_exp (frag_now, p + 2 - (frag_now->fr_literal), 2, &insn.operand_type[0]->immediate.imm_expr, 0, 0);
+ }
+ }
+ }
+ else if (insn.tm->opcode_modifier == PCRel)
+ {
+ /* Conditional Branch and Call instructions */
+ if ((insn.tm->operand_types[0] & (AllReg | Disp)) == (AllReg | Disp))
+ {
+ if (insn.operand_type[0]->op_type & (AllReg))
+ {
+ insn.opcode |= (insn.operand_type[0]->reg.opcode);
+ insn.opcode |= PC_Register;
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ }
+ else
+ {
+ insn.opcode |= PC_Relative;
+ if (insn.operand_type[0]->immediate.resolved == 1)
+ {
+ insn.opcode |= (insn.operand_type[0]->immediate.s_number & 0x0000FFFF);
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ }
+ else
+ {
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ fix_new_exp (frag_now, p + 2 - (frag_now->fr_literal), 2, &insn.operand_type[0]->immediate.imm_expr, 1, 0);
+ }
+ }
+ }
+ else if ((insn.tm->operand_types[0] & ARn) == ARn)
+ {
+ /* Decrement and Branch instructions */
+ insn.opcode |= ((insn.operand_type[0]->reg.opcode - 0x08) << 22);
+ if (insn.operand_type[1]->op_type & (AllReg))
+ {
+ insn.opcode |= (insn.operand_type[1]->reg.opcode);
+ insn.opcode |= PC_Register;
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ }
+ else if (insn.operand_type[1]->immediate.resolved == 1)
+ {
+ if (insn.operand_type[0]->immediate.decimal_found)
+ {
+ as_bad ("first operand is floating point");
+ return;
+ }
+ if (insn.operand_type[0]->immediate.s_number < -32768 ||
+ insn.operand_type[0]->immediate.s_number > 32767)
+ {
+ as_bad ("first operand is too large for 16-bit signed int");
+ return;
+ }
+ insn.opcode |= (insn.operand_type[1]->immediate.s_number);
+ insn.opcode |= PC_Relative;
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ }
+ else
+ {
+ insn.opcode |= PC_Relative;
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ fix_new_exp (frag_now, p + 2 - frag_now->fr_literal, 2, &insn.operand_type[1]->immediate.imm_expr, 1, 0);
+ }
+ }
+ }
+ else if (insn.tm->operand_types[0] == IVector)
+ {
+ /* Trap instructions */
+ if (insn.operand_type[0]->op_type & IVector)
+ insn.opcode |= (insn.operand_type[0]->immediate.u_number);
+ else
+ { /* Shouldn't get here */
+ as_bad ("interrupt vector for trap instruction out of range");
+ return;
+ }
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ }
+ else if (insn.tm->opcode_modifier == StackOp || insn.tm->opcode_modifier == Rotate)
+ {
+ /* Push, Pop and Rotate instructions */
+ insn.opcode |= (insn.operand_type[0]->reg.opcode << 16);
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ }
+ else if ((insn.tm->operand_types[0] & (Abs24 | Direct)) == (Abs24 | Direct))
+ {
+ /* LDP Instruction needs to be tested for before the next section */
+ if (insn.operand_type[0]->op_type & Direct)
+ {
+ if (insn.operand_type[0]->direct.resolved == 1)
+ {
+ /* Direct addressing uses lower 8 bits of direct address */
+ insn.opcode |= (insn.operand_type[0]->direct.address & 0x00FF0000) >> 16;
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ }
+ else
+ {
+ fixS *fix;
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ fix = fix_new_exp (frag_now, p + 3 - (frag_now->fr_literal), 1, &insn.operand_type[0]->direct.direct_expr, 0, 0);
+ /* Ensure that the assembler doesn't complain about fitting a 24-bit
+ address into 8 bits. */
+ fix->fx_no_overflow = 1;
+ }
+ }
+ else
+ {
+ if (insn.operand_type[0]->immediate.resolved == 1)
+ {
+ /* Immediate addressing uses upper 8 bits of address */
+ if (insn.operand_type[0]->immediate.u_number > 0x00FFFFFF)
+ {
+ as_bad ("LDP instruction needs a 24-bit operand");
+ return;
+ }
+ insn.opcode |= ((insn.operand_type[0]->immediate.u_number & 0x00FF0000) >> 16);
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ }
+ else
+ {
+ fixS *fix;
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ fix = fix_new_exp (frag_now, p + 3 - (frag_now->fr_literal), 1, &insn.operand_type[0]->immediate.imm_expr, 0, 0);
+ fix->fx_no_overflow = 1;
+ }
+ }
+ }
+ else if (insn.tm->operand_types[0] & (Imm24))
+ {
+ /* Unconditional Branch and Call instructions */
+ if (insn.operand_type[0]->immediate.resolved == 1)
+ {
+ if (insn.operand_type[0]->immediate.u_number > 0x00FFFFFF)
+ as_warn ("first operand is too large for a 24-bit displacement");
+ insn.opcode |= (insn.operand_type[0]->immediate.u_number & 0x00FFFFFF);
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ }
+ else
+ {
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ fix_new_exp (frag_now, p + 1 - (frag_now->fr_literal), 3, &insn.operand_type[0]->immediate.imm_expr, 0, 0);
+ }
+ }
+ else if (insn.tm->operand_types[0] & NotReq)
+ {
+ /* Check for NOP instruction without arguments. */
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ }
+ else if (insn.tm->operands == 0)
+ {
+ /* Check for instructions without operands. */
+ md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE);
+ }
+ }
+ debug ("Addressing mode: %08X\n", insn.addressing_mode);
+ {
+ int i;
+ for (i = 0; i < insn.operands; i++)
+ {
+ if (insn.operand_type[i]->immediate.label)
+ free (insn.operand_type[i]->immediate.label);
+ free (insn.operand_type[i]);
+ }
+ }
+ debug ("Final opcode: %08X\n", insn.opcode);
+ debug ("\n");
+}
+
+struct tic30_par_insn
+{
+ partemplate *tm; /* Template of current parallel instruction */
+ int operands[2]; /* Number of given operands for each insn */
+ /* Type of operand given in instruction */
+ operand *operand_type[2][MAX_OPERANDS];
+ int swap_operands; /* Whether to swap operands around. */
+ unsigned p_field; /* Value of p field in multiply add/sub instructions */
+ unsigned opcode; /* Final opcode */
+};
+
+struct tic30_par_insn p_insn;
+
+int
+tic30_parallel_insn (char *token)
+{
+ static partemplate *p_opcode;
+ char *current_posn = token;
+ char *token_start;
+ char save_char;
+
+ debug ("In tic30_parallel_insn with %s\n", token);
+ memset (&p_insn, '\0', sizeof (p_insn));
+ while (is_opcode_char (*current_posn))
+ current_posn++;
+ { /* Find instruction */
+ save_char = *current_posn;
+ *current_posn = '\0';
+ p_opcode = (partemplate *) hash_find (parop_hash, token);
+ if (p_opcode)
+ {
+ debug ("Found instruction %s\n", p_opcode->name);
+ p_insn.tm = p_opcode;
+ }
+ else
+ {
+ char first_opcode[6] =
+ {0};
+ char second_opcode[6] =
+ {0};
+ int i;
+ int current_opcode = -1;
+ int char_ptr = 0;
+
+ for (i = 0; i < strlen (token); i++)
+ {
+ char ch = *(token + i);
+ if (ch == '_' && current_opcode == -1)
+ {
+ current_opcode = 0;
+ continue;
+ }
+ if (ch == '_' && current_opcode == 0)
+ {
+ current_opcode = 1;
+ char_ptr = 0;
+ continue;
+ }
+ switch (current_opcode)
+ {
+ case 0:
+ first_opcode[char_ptr++] = ch;
+ break;
+ case 1:
+ second_opcode[char_ptr++] = ch;
+ break;
+ }
+ }
+ debug ("first_opcode = %s\n", first_opcode);
+ debug ("second_opcode = %s\n", second_opcode);
+ sprintf (token, "q_%s_%s", second_opcode, first_opcode);
+ p_opcode = (partemplate *) hash_find (parop_hash, token);
+ if (p_opcode)
+ {
+ debug ("Found instruction %s\n", p_opcode->name);
+ p_insn.tm = p_opcode;
+ p_insn.swap_operands = 1;
+ }
+ else
+ return 0;
+ }
+ *current_posn = save_char;
+ }
+ { /* Find operands */
+ int paren_not_balanced;
+ int expecting_operand = 0;
+ int found_separator = 0;
+ do
+ {
+ /* skip optional white space before operand */
+ while (!is_operand_char (*current_posn) && *current_posn != END_OF_INSN)
+ {
+ if (!is_space_char (*current_posn) && *current_posn != PARALLEL_SEPARATOR)
+ {
+ as_bad ("Invalid character %s before %s operand",
+ output_invalid (*current_posn),
+ ordinal_names[insn.operands]);
+ return 1;
+ }
+ if (*current_posn == PARALLEL_SEPARATOR)
+ found_separator = 1;
+ current_posn++;
+ }
+ token_start = current_posn; /* after white space */
+ paren_not_balanced = 0;
+ while (paren_not_balanced || *current_posn != ',')
+ {
+ if (*current_posn == END_OF_INSN)
+ {
+ if (paren_not_balanced)
+ {
+ as_bad ("Unbalanced parenthesis in %s operand.",
+ ordinal_names[insn.operands]);
+ return 1;
+ }
+ else
+ break; /* we are done */
+ }
+ else if (*current_posn == PARALLEL_SEPARATOR)
+ {
+ while (is_space_char (*(current_posn - 1)))
+ current_posn--;
+ break;
+ }
+ else if (!is_operand_char (*current_posn) && !is_space_char (*current_posn))
+ {
+ as_bad ("Invalid character %s in %s operand",
+ output_invalid (*current_posn),
+ ordinal_names[insn.operands]);
+ return 1;
+ }
+ if (*current_posn == '(')
+ ++paren_not_balanced;
+ if (*current_posn == ')')
+ --paren_not_balanced;
+ current_posn++;
+ }
+ if (current_posn != token_start)
+ { /* yes, we've read in another operand */
+ p_insn.operands[found_separator]++;
+ if (p_insn.operands[found_separator] > MAX_OPERANDS)
+ {
+ as_bad ("Spurious operands; (%d operands/instruction max)",
+ MAX_OPERANDS);
+ return 1;
+ }
+ /* now parse operand adding info to 'insn' as we go along */
+ save_char = *current_posn;
+ *current_posn = '\0';
+ p_insn.operand_type[found_separator][p_insn.operands[found_separator] - 1] =
+ tic30_operand (token_start);
+ *current_posn = save_char;
+ if (!p_insn.operand_type[found_separator][p_insn.operands[found_separator] - 1])
+ return 1;
+ }
+ else
+ {
+ if (expecting_operand)
+ {
+ as_bad ("Expecting operand after ','; got nothing");
+ return 1;
+ }
+ if (*current_posn == ',')
+ {
+ as_bad ("Expecting operand before ','; got nothing");
+ return 1;
+ }
+ }
+ /* now *current_posn must be either ',' or END_OF_INSN */
+ if (*current_posn == ',')
+ {
+ if (*++current_posn == END_OF_INSN)
+ { /* just skip it, if it's \n complain */
+ as_bad ("Expecting operand after ','; got nothing");
+ return 1;
+ }
+ expecting_operand = 1;
+ }
+ }
+ while (*current_posn != END_OF_INSN); /* until we get end of insn */
+ }
+ if (p_insn.swap_operands)
+ {
+ int temp_num, i;
+ operand *temp_op;
+
+ temp_num = p_insn.operands[0];
+ p_insn.operands[0] = p_insn.operands[1];
+ p_insn.operands[1] = temp_num;
+ for (i = 0; i < MAX_OPERANDS; i++)
+ {
+ temp_op = p_insn.operand_type[0][i];
+ p_insn.operand_type[0][i] = p_insn.operand_type[1][i];
+ p_insn.operand_type[1][i] = temp_op;
+ }
+ }
+ if (p_insn.operands[0] != p_insn.tm->operands_1)
+ {
+ as_bad ("incorrect number of operands given in the first instruction");
+ return 1;
+ }
+ if (p_insn.operands[1] != p_insn.tm->operands_2)
+ {
+ as_bad ("incorrect number of operands given in the second instruction");
+ return 1;
+ }
+ debug ("Number of operands in first insn: %d\n", p_insn.operands[0]);
+ debug ("Number of operands in second insn: %d\n", p_insn.operands[1]);
+ { /* Now check if operands are correct */
+ int count;
+ int num_rn = 0;
+ int num_ind = 0;
+ for (count = 0; count < 2; count++)
+ {
+ int i;
+ for (i = 0; i < p_insn.operands[count]; i++)
+ {
+ if ((p_insn.operand_type[count][i]->op_type &
+ p_insn.tm->operand_types[count][i]) == 0)
+ {
+ as_bad ("%s instruction, operand %d doesn't match", ordinal_names[count], i + 1);
+ return 1;
+ }
+ /* Get number of R register and indirect reference contained within the first
+ two operands of each instruction. This is required for the multiply
+ parallel instructions which require two R registers and two indirect
+ references, but not in any particular place. */
+ if ((p_insn.operand_type[count][i]->op_type & Rn) && i < 2)
+ num_rn++;
+ else if ((p_insn.operand_type[count][i]->op_type & Indirect) && i < 2)
+ num_ind++;
+ }
+ }
+ if ((p_insn.tm->operand_types[0][0] & (Indirect | Rn)) == (Indirect | Rn))
+ {
+ /* Check for the multiply instructions */
+ if (num_rn != 2)
+ {
+ as_bad ("incorrect format for multiply parallel instruction");
+ return 1;
+ }
+ if (num_ind != 2)
+ { /* Shouldn't get here */
+ as_bad ("incorrect format for multiply parallel instruction");
+ return 1;
+ }
+ if ((p_insn.operand_type[0][2]->reg.opcode != 0x00) &&
+ (p_insn.operand_type[0][2]->reg.opcode != 0x01))
+ {
+ as_bad ("destination for multiply can only be R0 or R1");
+ return 1;
+ }
+ if ((p_insn.operand_type[1][2]->reg.opcode != 0x02) &&
+ (p_insn.operand_type[1][2]->reg.opcode != 0x03))
+ {
+ as_bad ("destination for add/subtract can only be R2 or R3");
+ return 1;
+ }
+ /* Now determine the P field for the instruction */
+ if (p_insn.operand_type[0][0]->op_type & Indirect)
+ {
+ if (p_insn.operand_type[0][1]->op_type & Indirect)
+ p_insn.p_field = 0x00000000; /* Ind * Ind, Rn +/- Rn */
+ else if (p_insn.operand_type[1][0]->op_type & Indirect)
+ p_insn.p_field = 0x01000000; /* Ind * Rn, Ind +/- Rn */
+ else
+ p_insn.p_field = 0x03000000; /* Ind * Rn, Rn +/- Ind */
+ }
+ else
+ {
+ if (p_insn.operand_type[0][1]->op_type & Rn)
+ p_insn.p_field = 0x02000000; /* Rn * Rn, Ind +/- Ind */
+ else if (p_insn.operand_type[1][0]->op_type & Indirect)
+ {
+ operand *temp;
+ p_insn.p_field = 0x01000000; /* Rn * Ind, Ind +/- Rn */
+ /* Need to swap the two multiply operands around so that everything is in
+ its place for the opcode makeup ie so Ind * Rn, Ind +/- Rn */
+ temp = p_insn.operand_type[0][0];
+ p_insn.operand_type[0][0] = p_insn.operand_type[0][1];
+ p_insn.operand_type[0][1] = temp;
+ }
+ else
+ {
+ operand *temp;
+ p_insn.p_field = 0x03000000; /* Rn * Ind, Rn +/- Ind */
+ temp = p_insn.operand_type[0][0];
+ p_insn.operand_type[0][0] = p_insn.operand_type[0][1];
+ p_insn.operand_type[0][1] = temp;
+ }
+ }
+ }
+ }
+ debug ("P field: %08X\n", p_insn.p_field);
+ /* Finalise opcode. This is easier for parallel instructions as they have to be
+ fully resolved, there are no memory addresses allowed, except through indirect
+ addressing, so there are no labels to resolve. */
+ {
+ p_insn.opcode = p_insn.tm->base_opcode;
+ switch (p_insn.tm->oporder)
+ {
+ case OO_4op1:
+ p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum);
+ p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 3);
+ p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8);
+ p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11);
+ p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16);
+ p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 22);
+ break;
+ case OO_4op2:
+ p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum);
+ p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 3);
+ p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.ARnum << 8);
+ p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.mod << 11);
+ p_insn.opcode |= (p_insn.operand_type[1][1]->reg.opcode << 19);
+ p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 22);
+ if (p_insn.operand_type[1][1]->reg.opcode == p_insn.operand_type[0][1]->reg.opcode)
+ as_warn ("loading the same register in parallel operation");
+ break;
+ case OO_4op3:
+ p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.ARnum);
+ p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.mod << 3);
+ p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8);
+ p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11);
+ p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16);
+ p_insn.opcode |= (p_insn.operand_type[0][0]->reg.opcode << 22);
+ break;
+ case OO_5op1:
+ p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum);
+ p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 3);
+ p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8);
+ p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11);
+ p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16);
+ p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 19);
+ p_insn.opcode |= (p_insn.operand_type[0][2]->reg.opcode << 22);
+ break;
+ case OO_5op2:
+ p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.ARnum);
+ p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.mod << 3);
+ p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8);
+ p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11);
+ p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16);
+ p_insn.opcode |= (p_insn.operand_type[0][0]->reg.opcode << 19);
+ p_insn.opcode |= (p_insn.operand_type[0][2]->reg.opcode << 22);
+ break;
+ case OO_PField:
+ p_insn.opcode |= p_insn.p_field;
+ if (p_insn.operand_type[0][2]->reg.opcode == 0x01)
+ p_insn.opcode |= 0x00800000;
+ if (p_insn.operand_type[1][2]->reg.opcode == 0x03)
+ p_insn.opcode |= 0x00400000;
+ switch (p_insn.p_field)
+ {
+ case 0x00000000:
+ p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.ARnum);
+ p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.mod << 3);
+ p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum << 8);
+ p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 11);
+ p_insn.opcode |= (p_insn.operand_type[1][1]->reg.opcode << 16);
+ p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 19);
+ break;
+ case 0x01000000:
+ p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.ARnum);
+ p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.mod << 3);
+ p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum << 8);
+ p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 11);
+ p_insn.opcode |= (p_insn.operand_type[1][1]->reg.opcode << 16);
+ p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 19);
+ break;
+ case 0x02000000:
+ p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum);
+ p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 3);
+ p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.ARnum << 8);
+ p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.mod << 11);
+ p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 16);
+ p_insn.opcode |= (p_insn.operand_type[0][0]->reg.opcode << 19);
+ break;
+ case 0x03000000:
+ p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum);
+ p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 3);
+ p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum << 8);
+ p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 11);
+ p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16);
+ p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 19);
+ break;
+ }
+ break;
+ }
+ } /* Opcode is finalised at this point for all parallel instructions. */
+ { /* Output opcode */
+ char *p;
+ p = frag_more (INSN_SIZE);
+ md_number_to_chars (p, (valueT) p_insn.opcode, INSN_SIZE);
+ }
+ {
+ int i, j;
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < p_insn.operands[i]; j++)
+ free (p_insn.operand_type[i][j]);
+ }
+ debug ("Final opcode: %08X\n", p_insn.opcode);
+ debug ("\n");
+ return 1;
+}
+
+operand *
+tic30_operand (token)
+ char *token;
+{
+ int count;
+ char ind_buffer[strlen (token)];
+ operand *current_op;
+
+ debug ("In tic30_operand with %s\n", token);
+ current_op = (operand *) malloc (sizeof (operand));
+ memset (current_op, '\0', sizeof (operand));
+ if (*token == DIRECT_REFERENCE)
+ {
+ char *token_posn = token + 1;
+ int direct_label = 0;
+ debug ("Found direct reference\n");
+ while (*token_posn)
+ {
+ if (!is_digit_char (*token_posn))
+ direct_label = 1;
+ token_posn++;
+ }
+ if (direct_label)
+ {
+ char *save_input_line_pointer;
+ segT retval;
+ debug ("Direct reference is a label\n");
+ current_op->direct.label = token + 1;
+ save_input_line_pointer = input_line_pointer;
+ input_line_pointer = token + 1;
+ debug ("Current input_line_pointer: %s\n", input_line_pointer);
+ retval = expression (&current_op->direct.direct_expr);
+ debug ("Expression type: %d\n", current_op->direct.direct_expr.X_op);
+ debug ("Expression addnum: %d\n", current_op->direct.direct_expr.X_add_number);
+ debug ("Segment: %d\n", retval);
+ input_line_pointer = save_input_line_pointer;
+ if (current_op->direct.direct_expr.X_op == O_constant)
+ {
+ current_op->direct.address = current_op->direct.direct_expr.X_add_number;
+ current_op->direct.resolved = 1;
+ }
+ }
+ else
+ {
+ debug ("Direct reference is a number\n");
+ current_op->direct.address = atoi (token + 1);
+ current_op->direct.resolved = 1;
+ }
+ current_op->op_type = Direct;
+ }
+ else if (*token == INDIRECT_REFERENCE)
+ { /* Indirect reference operand */
+ int found_ar = 0;
+ int found_disp = 0;
+ int ar_number = -1;
+ int disp_number = 0;
+ int buffer_posn = 1;
+ ind_addr_type *ind_addr_op;
+ debug ("Found indirect reference\n");
+ ind_buffer[0] = *token;
+ for (count = 1; count < strlen (token); count++)
+ { /* Strip operand */
+ ind_buffer[buffer_posn] = tolower (*(token + count));
+ if ((*(token + count - 1) == 'a' || *(token + count - 1) == 'A') &&
+ (*(token + count) == 'r' || *(token + count) == 'R'))
+ {
+ /* AR reference is found, so get its number and remove it from the buffer
+ so it can pass through hash_find() */
+ if (found_ar)
+ {
+ as_bad ("More than one AR register found in indirect reference");
+ return NULL;
+ }
+ if (*(token + count + 1) < '0' || *(token + count + 1) > '7')
+ {
+ as_bad ("Illegal AR register in indirect reference");
+ return NULL;
+ }
+ ar_number = *(token + count + 1) - '0';
+ found_ar = 1;
+ count++;
+ }
+ if (*(token + count) == '(')
+ {
+ /* Parenthesis found, so check if a displacement value is inside. If so, get
+ the value and remove it from the buffer. */
+ if (is_digit_char (*(token + count + 1)))
+ {
+ char disp[10];
+ int disp_posn = 0;
+
+ if (found_disp)
+ {
+ as_bad ("More than one displacement found in indirect reference");
+ return NULL;
+ }
+ count++;
+ while (*(token + count) != ')')
+ {
+ if (!is_digit_char (*(token + count)))
+ {
+ as_bad ("Invalid displacement in indirect reference");
+ return NULL;
+ }
+ disp[disp_posn++] = *(token + (count++));
+ }
+ disp[disp_posn] = '\0';
+ disp_number = atoi (disp);
+ count--;
+ found_disp = 1;
+ }
+ }
+ buffer_posn++;
+ }
+ ind_buffer[buffer_posn] = '\0';
+ if (!found_ar)
+ {
+ as_bad ("AR register not found in indirect reference");
+ return NULL;
+ }
+ ind_addr_op = (ind_addr_type *) hash_find (ind_hash, ind_buffer);
+ if (ind_addr_op)
+ {
+ debug ("Found indirect reference: %s\n", ind_addr_op->syntax);
+ if (ind_addr_op->displacement == IMPLIED_DISP)
+ {
+ found_disp = 1;
+ disp_number = 1;
+ }
+ else if ((ind_addr_op->displacement == DISP_REQUIRED) && !found_disp)
+ {
+ /* Maybe an implied displacement of 1 again */
+ as_bad ("required displacement wasn't given in indirect reference");
+ return 0;
+ }
+ }
+ else
+ {
+ as_bad ("illegal indirect reference");
+ return NULL;
+ }
+ if (found_disp && (disp_number < 0 || disp_number > 255))
+ {
+ as_bad ("displacement must be an unsigned 8-bit number");
+ return NULL;
+ }
+ current_op->indirect.mod = ind_addr_op->modfield;
+ current_op->indirect.disp = disp_number;
+ current_op->indirect.ARnum = ar_number;
+ current_op->op_type = Indirect;
+ }
+ else
+ {
+ reg *regop = (reg *) hash_find (reg_hash, token);
+ if (regop)
+ {
+ debug ("Found register operand: %s\n", regop->name);
+ if (regop->regtype == REG_ARn)
+ current_op->op_type = ARn;
+ else if (regop->regtype == REG_Rn)
+ current_op->op_type = Rn;
+ else if (regop->regtype == REG_DP)
+ current_op->op_type = DPReg;
+ else
+ current_op->op_type = OtherReg;
+ current_op->reg.opcode = regop->opcode;
+ }
+ else
+ {
+ if (!is_digit_char (*token) || *(token + 1) == 'x' || strchr (token, 'h'))
+ {
+ char *save_input_line_pointer;
+ segT retval;
+ debug ("Probably a label: %s\n", token);
+ current_op->immediate.label = (char *) malloc (strlen (token) + 1);
+ strcpy (current_op->immediate.label, token);
+ current_op->immediate.label[strlen (token)] = '\0';
+ save_input_line_pointer = input_line_pointer;
+ input_line_pointer = token;
+ debug ("Current input_line_pointer: %s\n", input_line_pointer);
+ retval = expression (&current_op->immediate.imm_expr);
+ debug ("Expression type: %d\n", current_op->immediate.imm_expr.X_op);
+ debug ("Expression addnum: %d\n", current_op->immediate.imm_expr.X_add_number);
+ debug ("Segment: %d\n", retval);
+ input_line_pointer = save_input_line_pointer;
+ if (current_op->immediate.imm_expr.X_op == O_constant)
+ {
+ current_op->immediate.s_number = current_op->immediate.imm_expr.X_add_number;
+ current_op->immediate.u_number = (unsigned int) current_op->immediate.imm_expr.X_add_number;
+ current_op->immediate.resolved = 1;
+ }
+ }
+ else
+ {
+ unsigned count;
+ debug ("Found a number or displacement\n");
+ for (count = 0; count < strlen (token); count++)
+ if (*(token + count) == '.')
+ current_op->immediate.decimal_found = 1;
+ current_op->immediate.label = (char *) malloc (strlen (token) + 1);
+ strcpy (current_op->immediate.label, token);
+ current_op->immediate.label[strlen (token)] = '\0';
+ current_op->immediate.f_number = (float) atof (token);
+ current_op->immediate.s_number = (int) atoi (token);
+ current_op->immediate.u_number = (unsigned int) atoi (token);
+ current_op->immediate.resolved = 1;
+ }
+ current_op->op_type = Disp | Abs24 | Imm16 | Imm24;
+ if (current_op->immediate.u_number >= 0 && current_op->immediate.u_number <= 31)
+ current_op->op_type |= IVector;
+ }
+ }
+ return current_op;
+}
+
+/* next_line points to the next line after the current instruction (current_line).
+ Search for the parallel bars, and if found, merge two lines into internal syntax
+ for a parallel instruction:
+ q_[INSN1]_[INSN2] [OPERANDS1] | [OPERANDS2]
+ By this stage, all comments are scrubbed, and only the bare lines are given.
+ */
+
+#define NONE 0
+#define START_OPCODE 1
+#define END_OPCODE 2
+#define START_OPERANDS 3
+#define END_OPERANDS 4
+
+char *
+tic30_find_parallel_insn (current_line, next_line)
+ char *current_line;
+ char *next_line;
+{
+ int found_parallel = 0;
+ char first_opcode[256];
+ char second_opcode[256];
+ char first_operands[256];
+ char second_operands[256];
+ char *parallel_insn;
+
+ debug ("In tic30_find_parallel_insn()\n");
+ while (!is_end_of_line[(int) *next_line])
+ {
+ if (*next_line == PARALLEL_SEPARATOR && *(next_line + 1) == PARALLEL_SEPARATOR)
+ {
+ found_parallel = 1;
+ next_line++;
+ break;
+ }
+ next_line++;
+ }
+ if (!found_parallel)
+ return NULL;
+ debug ("Found a parallel instruction\n");
+ {
+ int i;
+ char *opcode, *operands, *line;
+
+ for (i = 0; i < 2; i++)
+ {
+ if (i == 0)
+ {
+ opcode = &first_opcode[0];
+ operands = &first_operands[0];
+ line = current_line;
+ }
+ else
+ {
+ opcode = &second_opcode[0];
+ operands = &second_operands[0];
+ line = next_line;
+ }
+ {
+ int search_status = NONE;
+ int char_ptr = 0;
+ char c;
+
+ while (!is_end_of_line[(int) (c = *line)] && *line)
+ {
+ if (is_opcode_char (c) && search_status == NONE)
+ {
+ opcode[char_ptr++] = tolower (c);
+ search_status = START_OPCODE;
+ }
+ else if (is_opcode_char (c) && search_status == START_OPCODE)
+ {
+ opcode[char_ptr++] = tolower (c);
+ }
+ else if (!is_opcode_char (c) && search_status == START_OPCODE)
+ {
+ opcode[char_ptr] = '\0';
+ char_ptr = 0;
+ search_status = END_OPCODE;
+ }
+ else if (is_operand_char (c) && search_status == START_OPERANDS)
+ {
+ operands[char_ptr++] = c;
+ }
+ if (is_operand_char (c) && search_status == END_OPCODE)
+ {
+ operands[char_ptr++] = c;
+ search_status = START_OPERANDS;
+ }
+ line++;
+ }
+ if (search_status != START_OPERANDS)
+ return NULL;
+ operands[char_ptr] = '\0';
+ }
+ }
+ }
+ parallel_insn = (char *) malloc (strlen (first_opcode) + strlen (first_operands) +
+ strlen (second_opcode) + strlen (second_operands) + 8);
+ sprintf (parallel_insn, "q_%s_%s %s | %s", first_opcode, second_opcode, first_operands, second_operands);
+ debug ("parallel insn = %s\n", parallel_insn);
+ return parallel_insn;
+}
+
+#undef NONE
+#undef START_OPCODE
+#undef END_OPCODE
+#undef START_OPERANDS
+#undef END_OPERANDS
+
+/* In order to get gas to ignore any | chars at the start of a line,
+ this function returns true if a | is found in a line. */
+
+int
+tic30_unrecognized_line (c)
+ int c;
+{
+ debug ("In tc_unrecognized_line\n");
+ return (c == PARALLEL_SEPARATOR);
+}
+
+int
+md_estimate_size_before_relax (fragP, segment)
+ fragS *fragP;
+ segT segment;
+{
+ debug ("In md_estimate_size_before_relax()\n");
+ return 0;
+}
+
+void
+md_convert_frag (abfd, sec, fragP)
+ bfd *abfd;
+ segT sec;
+ register fragS *fragP;
+{
+ debug ("In md_convert_frag()\n");
+}
+
+int
+md_apply_fix (fixP, valP)
+ fixS *fixP;
+ valueT *valP;
+{
+ valueT value = *valP;
+
+ debug ("In md_apply_fix() with value = %ld\n", (long) value);
+ debug ("Values in fixP\n");
+ debug ("fx_size = %d\n", fixP->fx_size);
+ debug ("fx_pcrel = %d\n", fixP->fx_pcrel);
+ debug ("fx_where = %d\n", fixP->fx_where);
+ debug ("fx_offset = %d\n", (int) fixP->fx_offset);
+ {
+ char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
+ value /= INSN_SIZE;
+ if (fixP->fx_size == 1)
+ { /* Special fix for LDP instruction. */
+ value = (value & 0x00FF0000) >> 16;
+ }
+ debug ("new value = %ld\n", (long) value);
+ md_number_to_chars (buf, value, fixP->fx_size);
+ }
+ return 1;
+}
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ int i;
+
+ debug ("In md_parse_option()\n");
+ for (i = 0; i < c; i++)
+ {
+ printf ("%c\n", arg[c]);
+ }
+ return 0;
+}
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+ debug ("In md_show_usage()\n");
+}
+
+symbolS *
+md_undefined_symbol (name)
+ char *name;
+{
+ debug ("In md_undefined_symbol()\n");
+ return (symbolS *) 0;
+}
+
+valueT
+md_section_align (segment, size)
+ segT segment;
+ valueT size;
+{
+ debug ("In md_section_align() segment = %d and size = %d\n", segment, size);
+ size = (size + 3) / 4;
+ size *= 4;
+ debug ("New size value = %d\n", size);
+ return size;
+}
+
+long
+md_pcrel_from (fixP)
+ fixS *fixP;
+{
+ int offset;
+
+ debug ("In md_pcrel_from()\n");
+ debug ("fx_where = %d\n", fixP->fx_where);
+ debug ("fx_size = %d\n", fixP->fx_size);
+ /* Find the opcode that represents the current instruction in the fr_literal
+ storage area, and check bit 21. Bit 21 contains whether the current instruction
+ is a delayed one or not, and then set the offset value appropriately. */
+ if (fixP->fx_frag->fr_literal[fixP->fx_where - fixP->fx_size + 1] & 0x20)
+ offset = 3;
+ else
+ offset = 1;
+ debug ("offset = %d\n", offset);
+ /* PC Relative instructions have a format:
+ displacement = Label - (PC + offset)
+ This function returns PC + offset where:
+ fx_where - fx_size = PC
+ INSN_SIZE * offset = offset number of instructions
+ */
+ return fixP->fx_where - fixP->fx_size + (INSN_SIZE * offset);
+}
+
+char *
+md_atof (what_statement_type, literalP, sizeP)
+ int what_statement_type;
+ char *literalP;
+ int *sizeP;
+{
+ int prec;
+ char *token;
+ char keepval;
+ unsigned long value;
+ /* char *atof_ieee (); */
+ float float_value;
+ debug ("In md_atof()\n");
+ debug ("precision = %c\n", what_statement_type);
+ debug ("literal = %s\n", literalP);
+ debug ("line = ");
+ token = input_line_pointer;
+ while (!is_end_of_line[(unsigned) *input_line_pointer] && (*input_line_pointer) && (*input_line_pointer != ','))
+ {
+ debug ("%c", *input_line_pointer);
+ input_line_pointer++;
+ }
+ keepval = *input_line_pointer;
+ *input_line_pointer = '\0';
+ debug ("\n");
+ float_value = (float) atof (token);
+ *input_line_pointer = keepval;
+ debug ("float_value = %f\n", float_value);
+ switch (what_statement_type)
+ {
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ prec = 4;
+ break;
+
+ default:
+ *sizeP = 0;
+ return "Bad call to MD_ATOF()";
+ }
+ if (float_value == 0.0)
+ {
+ value = (prec == 2) ? 0x00008000L : 0x80000000L;
+ }
+ else
+ {
+ unsigned long exp, sign, mant, tmsfloat;
+ tmsfloat = *((long *) &float_value);
+ sign = tmsfloat & 0x80000000;
+ mant = tmsfloat & 0x007FFFFF;
+ exp = tmsfloat & 0x7F800000;
+ exp <<= 1;
+ if (exp == 0xFF000000)
+ {
+ if (mant == 0)
+ value = 0x7F7FFFFF;
+ else if (sign == 0)
+ value = 0x7F7FFFFF;
+ else
+ value = 0x7F800000;
+ }
+ else
+ {
+ exp -= 0x7F000000;
+ if (sign)
+ {
+ mant = mant & 0x007FFFFF;
+ mant = -mant;
+ mant = mant & 0x00FFFFFF;
+ if (mant == 0)
+ {
+ mant |= 0x00800000;
+ exp = (long) exp - 0x01000000;
+ }
+ }
+ tmsfloat = exp | mant;
+ value = tmsfloat;
+ }
+ if (prec == 2)
+ {
+ long exp, mant;
+
+ if (tmsfloat == 0x80000000)
+ {
+ value = 0x8000;
+ }
+ else
+ {
+ value = 0;
+ exp = (tmsfloat & 0xFF000000);
+ exp >>= 24;
+ mant = tmsfloat & 0x007FFFFF;
+ if (tmsfloat & 0x00800000)
+ {
+ mant |= 0xFF000000;
+ mant += 0x00000800;
+ mant >>= 12;
+ mant |= 0x00000800;
+ mant &= 0x0FFF;
+ if (exp > 7)
+ value = 0x7800;
+ }
+ else
+ {
+ mant |= 0x00800000;
+ mant += 0x00000800;
+ exp += (mant >> 24);
+ mant >>= 12;
+ mant &= 0x07FF;
+ if (exp > 7)
+ value = 0x77FF;
+ }
+ if (exp < -8)
+ value = 0x8000;
+ if (value == 0)
+ {
+ mant = (exp << 12) | mant;
+ value = mant & 0xFFFF;
+ }
+ }
+ }
+ }
+ md_number_to_chars (literalP, value, prec);
+ *sizeP = prec;
+ return 0;
+}
+
+void
+md_number_to_chars (buf, val, n)
+ char *buf;
+ valueT val;
+ int n;
+{
+ debug ("In md_number_to_chars()\n");
+ number_to_chars_bigendian (buf, val, n);
+ /* number_to_chars_littleendian(buf,val,n); */
+}
+
+#define F(SZ,PCREL) (((SZ) << 1) + (PCREL))
+#define MAP(SZ,PCREL,TYPE) case F(SZ,PCREL): code = (TYPE); break
+
+arelent *
+tc_gen_reloc (section, fixP)
+ asection *section;
+ fixS *fixP;
+{
+ arelent *rel;
+ bfd_reloc_code_real_type code = 0;
+
+ debug ("In tc_gen_reloc()\n");
+ debug ("fixP.size = %d\n", fixP->fx_size);
+ debug ("fixP.pcrel = %d\n", fixP->fx_pcrel);
+ debug ("addsy.name = %s\n", S_GET_NAME (fixP->fx_addsy));
+ switch (F (fixP->fx_size, fixP->fx_pcrel))
+ {
+ MAP (1, 0, BFD_RELOC_TIC30_LDP);
+ MAP (2, 0, BFD_RELOC_16);
+ MAP (3, 0, BFD_RELOC_24);
+ MAP (2, 1, BFD_RELOC_16_PCREL);
+ MAP (4, 0, BFD_RELOC_32);
+ default:
+ as_bad ("Can not do %d byte %srelocation", fixP->fx_size,
+ fixP->fx_pcrel ? "pc-relative " : "");
+ }
+#undef MAP
+#undef F
+
+ rel = (arelent *) xmalloc (sizeof (arelent));
+ assert (rel != 0);
+ rel->sym_ptr_ptr = &fixP->fx_addsy->bsym;
+ rel->address = fixP->fx_frag->fr_address + fixP->fx_where;
+ if (fixP->fx_pcrel)
+ rel->addend = fixP->fx_addnumber;
+ else
+ rel->addend = 0;
+ rel->howto = bfd_reloc_type_lookup (stdoutput, code);
+ if (!rel->howto)
+ {
+ const char *name;
+ name = S_GET_NAME (fixP->fx_addsy);
+ if (name == NULL)
+ name = "<unknown>";
+ as_fatal ("Cannot generate relocation type for symbol %s, code %s", name, bfd_get_reloc_code_name (code));
+ }
+ return rel;
+}
+
+void
+tc_aout_pre_write_hook ()
+{
+ debug ("In tc_aout_pre_write_hook()\n");
+}
+
+void
+md_operand (expressionP)
+ expressionS *expressionP;
+{
+ debug ("In md_operand()\n");
+}
+
+char output_invalid_buf[8];
+
+char *
+output_invalid (c)
+ char c;
+{
+ if (isprint (c))
+ sprintf (output_invalid_buf, "'%c'", c);
+ else
+ sprintf (output_invalid_buf, "(0x%x)", (unsigned) c);
+ return output_invalid_buf;
+}
diff --git a/gas/config/tc-tic30.h b/gas/config/tc-tic30.h
new file mode 100644
index 0000000000..d172d2e5c5
--- /dev/null
+++ b/gas/config/tc-tic30.h
@@ -0,0 +1,55 @@
+/* tc-tic30.h -- Header file for tc-tic30.c
+ Copyright (C) 1998 Free Software Foundation.
+ Contributed by Steven Haworth (steve@pm.cse.rmit.edu.au)
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#ifndef _TC_TIC30_H_
+#define _TC_TIC30_H_
+
+#define TC_TIC30 1
+
+#ifdef OBJ_AOUT
+#define TARGET_FORMAT "a.out-tic30"
+#endif
+
+#define TARGET_ARCH bfd_arch_tic30
+#define TARGET_BYTES_BIG_ENDIAN 1
+
+#define WORKING_DOT_WORD
+
+char *output_invalid PARAMS ((int c));
+
+#define END_OF_INSN '\0'
+#define MAX_OPERANDS 6
+#define DIRECT_REFERENCE '@'
+#define INDIRECT_REFERENCE '*'
+#define PARALLEL_SEPARATOR '|'
+#define INSN_SIZE 4
+
+/* Define this to 1 if you want the debug output to be on stdout,
+ otherwise stderr will be used. If stderr is used, there will be a
+ better synchronisation with the as_bad outputs, but you can't
+ capture the output. */
+#define USE_STDOUT 0
+
+#define tc_unrecognized_line tic30_unrecognized_line
+
+extern int tic30_unrecognized_line PARAMS ((int));
+
+#endif
diff --git a/gas/config/tc-tic80.c b/gas/config/tc-tic80.c
new file mode 100644
index 0000000000..f31dba32f9
--- /dev/null
+++ b/gas/config/tc-tic80.c
@@ -0,0 +1,1061 @@
+/* tc-tic80.c -- Assemble for the TI TMS320C80 (MV)
+ Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include "as.h"
+#include "opcode/tic80.h"
+
+#define internal_error(what) \
+ as_fatal(_("internal error:%s:%d: %s\n"),__FILE__,__LINE__,what)
+#define internal_error_a(what,arg) \
+ as_fatal(_("internal error:%s:%d: %s %d\n"),__FILE__,__LINE__,what,arg)
+
+
+/* Generic assembler global variables which must be defined by all targets. */
+
+/* Characters which always start a comment. */
+const char comment_chars[] = ";";
+
+/* Characters which start a comment at the beginning of a line. */
+const char line_comment_chars[] = ";*#";
+
+/* Characters which may be used to separate multiple commands on a single
+ line. The semicolon is such a character by default and should not be
+ explicitly listed. */
+const char line_separator_chars[] = "";
+
+/* Characters which are used to indicate an exponent in a floating
+ point number. */
+const char EXP_CHARS[] = "eE";
+
+/* Characters which mean that a number is a floating point constant,
+ as in 0f1.0. */
+const char FLT_CHARS[] = "fF";
+
+/* This table describes all the machine specific pseudo-ops the assembler
+ has to support. The fields are:
+
+ pseudo-op name without dot
+ function to call to execute this pseudo-op
+ integer arg to pass to the function */
+
+extern void obj_coff_section ();
+
+const pseudo_typeS md_pseudo_table[] =
+{
+ { "align", s_align_bytes, 4 }, /* Do byte alignment, default is a 4 byte boundary */
+ { "word", cons, 4 }, /* FIXME: Should this be machine independent? */
+ { "bss", s_lcomm_bytes, 1 },
+ { "sect", obj_coff_section, 0}, /* For compatibility with TI tools */
+ { "section", obj_coff_section, 0}, /* Standard COFF .section pseudo-op */
+ { NULL, NULL, 0 }
+};
+
+/* Opcode hash table. */
+static struct hash_control *tic80_hash;
+
+static struct tic80_opcode * find_opcode PARAMS ((struct tic80_opcode *, expressionS []));
+static void build_insn PARAMS ((struct tic80_opcode *, expressionS *));
+static int get_operands PARAMS ((expressionS exp[]));
+static int const_overflow PARAMS ((unsigned long num, int bits, int flags));
+
+/* Replace short PC relative instructions with long form when necessary. Currently
+ this is off by default or when given the -no-relax option. Turning it on by using
+ the -relax option forces all PC relative instructions to use the long form, which
+ is why it is currently not the default. */
+static int tic80_relax = 0;
+
+
+int
+md_estimate_size_before_relax (fragP, segment_type)
+ fragS *fragP;
+ segT segment_type;
+{
+ internal_error (_("Relaxation is a luxury we can't afford"));
+ return (-1);
+}
+
+/* We have no need to default values of symbols. */
+
+/* ARGSUSED */
+symbolS *
+md_undefined_symbol (name)
+ char *name;
+{
+ return 0;
+}
+
+/* Turn a string in input_line_pointer into a floating point constant of type
+ type, and store the appropriate bytes in *litP. The number of LITTLENUMS
+ emitted is stored in *sizeP . An error message is returned, or NULL on OK.
+ */
+
+#define MAX_LITTLENUMS 4
+
+char *
+md_atof (type, litP, sizeP)
+ int type;
+ char *litP;
+ int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ char *t;
+ char *atof_ieee ();
+
+ switch (type)
+ {
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ prec = 4;
+ break;
+
+ default:
+ *sizeP = 0;
+ return _("bad call to md_atof ()");
+ }
+
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ {
+ input_line_pointer = t;
+ }
+
+ *sizeP = prec * sizeof (LITTLENUM_TYPE);
+
+ for (wordP = words; prec--;)
+ {
+ md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+ return (NULL);
+}
+
+/* Check to see if the constant value in NUM will fit in a field of
+ width BITS if it has flags FLAGS. */
+
+static int
+const_overflow (num, bits, flags)
+ unsigned long num;
+ int bits;
+ int flags;
+{
+ long min, max;
+ int retval = 0;
+
+ /* Only need to check fields less than 32 bits wide */
+ if (bits < 32)
+ if (flags & TIC80_OPERAND_SIGNED)
+ {
+ max = (1 << (bits - 1)) - 1;
+ min = - (1 << (bits - 1));
+ retval = ((long) num > max) || ((long) num < min);
+ }
+ else
+ {
+ max = (1 << bits) - 1;
+ min = 0;
+ retval = (num > max) || (num < min);
+ }
+ return (retval);
+}
+
+/* get_operands() parses a string of operands and fills in a passed array of
+ expressions in EXP.
+
+ Note that we use O_absent expressions to record additional information
+ about the previous non-O_absent expression, such as ":m" or ":s"
+ modifiers or register numbers enclosed in parens like "(r10)".
+
+ Returns the number of expressions that were placed in EXP.
+
+ */
+
+static int
+get_operands (exp)
+ expressionS exp[];
+{
+ char *p = input_line_pointer;
+ int numexp = 0;
+ int mflag = 0;
+ int sflag = 0;
+ int parens = 0;
+
+ while (*p)
+ {
+ /* Skip leading whitespace */
+ while (*p == ' ' || *p == '\t' || *p == ',')
+ {
+ p++;
+ }
+
+ /* Check to see if we have any operands left to parse */
+ if (*p == 0 || *p == '\n' || *p == '\r')
+ {
+ break;
+ }
+
+ /* Notice scaling or direct memory operand modifiers and save them in
+ an O_absent expression after the expression that they modify. */
+
+ if (*p == ':')
+ {
+ p++;
+ exp[numexp].X_op = O_absent;
+ if (*p == 'm')
+ {
+ p++;
+ /* This is a ":m" modifier */
+ exp[numexp].X_add_number = TIC80_OPERAND_M_SI | TIC80_OPERAND_M_LI;
+ }
+ else if (*p == 's')
+ {
+ p++;
+ /* This is a ":s" modifier */
+ exp[numexp].X_add_number = TIC80_OPERAND_SCALED;
+ }
+ else
+ {
+ as_bad (_("':' not followed by 'm' or 's'"));
+ }
+ numexp++;
+ continue;
+ }
+
+ /* Handle leading '(' on operands that use them, by recording that we
+ have entered a paren nesting level and then continuing. We complain
+ about multiple nesting. */
+
+ if (*p == '(')
+ {
+ if (++parens != 1)
+ {
+ as_bad (_("paren nesting"));
+ }
+ p++;
+ continue;
+ }
+
+ /* Handle trailing ')' on operands that use them, by reducing the
+ nesting level and then continuing. We complain if there were too
+ many closures. */
+
+ if (*p == ')')
+ {
+ /* Record that we have left a paren group and continue */
+ if (--parens < 0)
+ {
+ as_bad (_("mismatched parenthesis"));
+ }
+ p++;
+ continue;
+ }
+
+ /* Begin operand parsing at the current scan point. */
+
+ input_line_pointer = p;
+ expression (&exp[numexp]);
+
+ if (exp[numexp].X_op == O_illegal)
+ {
+ as_bad (_("illegal operand"));
+ }
+ else if (exp[numexp].X_op == O_absent)
+ {
+ as_bad (_("missing operand"));
+ }
+
+ numexp++;
+ p = input_line_pointer;
+ }
+
+ if (parens)
+ {
+ exp[numexp].X_op = O_absent;
+ exp[numexp++].X_add_number = TIC80_OPERAND_PARENS;
+ }
+
+ /* Mark the end of the valid operands with an illegal expression. */
+ exp[numexp].X_op = O_illegal;
+
+ return (numexp);
+}
+
+/* find_opcode() gets a pointer to the entry in the opcode table that
+ matches the instruction being assembled, or returns NULL if no such match
+ is found.
+
+ First it parses all the operands and save them as expressions. Note that
+ we use O_absent expressions to record additional information about the
+ previous non-O_absent expression, such as ":m" or ":s" modifiers or
+ register numbers enclosed in parens like "(r10)".
+
+ It then looks at all opcodes with the same name and uses the operands to
+ choose the correct opcode. */
+
+static struct tic80_opcode *
+find_opcode (opcode, myops)
+ struct tic80_opcode *opcode;
+ expressionS myops[];
+{
+ int numexp; /* Number of expressions from parsing operands */
+ int expi; /* Index of current expression to match */
+ int opi; /* Index of current operand to match */
+ int match = 0; /* Set to 1 when an operand match is found */
+ struct tic80_opcode *opc = opcode; /* Pointer to current opcode table entry */
+ const struct tic80_opcode *end; /* Pointer to end of opcode table */
+
+ /* First parse all the operands so we only have to do it once. There may
+ be more expressions generated than there are operands. */
+
+ numexp = get_operands (myops);
+
+ /* For each opcode with the same name, try to match it against the parsed
+ operands. */
+
+ end = tic80_opcodes + tic80_num_opcodes;
+ while (!match && (opc < end) && (strcmp (opc -> name, opcode -> name) == 0))
+ {
+ /* Start off assuming a match. If we find a mismatch, then this is
+ reset and the operand/expr matching loop terminates with match
+ equal to zero, which allows us to try the next opcode. */
+
+ match = 1;
+
+ /* For each expression, try to match it against the current operand
+ for the current opcode. Upon any mismatch, we abandon further
+ matching for the current opcode table entry. */
+
+ for (expi = 0, opi = -1; (expi < numexp) && match; expi++)
+ {
+ int bits, flags, X_op, num;
+
+ X_op = myops[expi].X_op;
+ num = myops[expi].X_add_number;
+
+ /* The O_absent expressions apply to the same operand as the most
+ recent non O_absent expression. So only increment the operand
+ index when the current expression is not one of these special
+ expressions. */
+
+ if (X_op != O_absent)
+ {
+ opi++;
+ }
+
+ flags = tic80_operands[opc -> operands[opi]].flags;
+ bits = tic80_operands[opc -> operands[opi]].bits;
+
+ switch (X_op)
+ {
+ case O_register:
+ /* Also check that registers that are supposed to be even actually
+ are even. */
+ if (((flags & TIC80_OPERAND_GPR) != (num & TIC80_OPERAND_GPR)) ||
+ ((flags & TIC80_OPERAND_FPA) != (num & TIC80_OPERAND_FPA)) ||
+ ((flags & TIC80_OPERAND_CR) != (num & TIC80_OPERAND_CR)) ||
+ ((flags & TIC80_OPERAND_EVEN) && (num & 1)) ||
+ const_overflow (num & ~TIC80_OPERAND_MASK, bits, flags))
+ {
+ match = 0;
+ }
+ break;
+ case O_constant:
+ if ((flags & TIC80_OPERAND_ENDMASK) && (num == 32))
+ {
+ /* Endmask values of 0 and 32 give identical results */
+ num = 0;
+ }
+ if ((flags & (TIC80_OPERAND_FPA | TIC80_OPERAND_GPR)) ||
+ const_overflow (num, bits, flags))
+ {
+ match = 0;
+ }
+ break;
+ case O_symbol:
+ if ((bits < 32) && (flags & TIC80_OPERAND_PCREL) && !tic80_relax)
+ {
+ /* The default is to prefer the short form of PC relative relocations.
+ This is the only form that the TI assembler supports.
+ If the -relax option is given, we never use the short forms.
+ FIXME: Should be able to choose "best-fit". */
+ }
+ else if ((bits == 32) /* && (flags & TIC80_OPERAND_BASEREL) */)
+ {
+ /* The default is to prefer the long form of base relative relocations.
+ This is the only form that the TI assembler supports.
+ If the -no-relax option is given, we always use the long form of
+ PC relative relocations.
+ FIXME: Should be able to choose "best-fit". */
+ }
+ else
+ {
+ /* Symbols that don't match one of the above cases are
+ rejected as an operand. */
+ match = 0;
+ }
+ break;
+ case O_absent:
+ /* If this is an O_absent expression, then it may be an expression that
+ supplies additional information about the operand, such as ":m" or
+ ":s" modifiers. Check to see that the operand matches this requirement. */
+ if (!((num & TIC80_OPERAND_M_SI) && (flags & TIC80_OPERAND_M_SI) ||
+ (num & TIC80_OPERAND_M_LI) && (flags & TIC80_OPERAND_M_LI) ||
+ (num & TIC80_OPERAND_SCALED) && (flags & TIC80_OPERAND_SCALED)))
+ {
+ match = 0;
+ }
+ break;
+ case O_big:
+ if ((num > 0) || !(flags & TIC80_OPERAND_FLOAT))
+ {
+ match = 0;
+ }
+ break;
+ case O_illegal:
+ case O_symbol_rva:
+ case O_uminus:
+ case O_bit_not:
+ case O_logical_not:
+ case O_multiply:
+ case O_divide:
+ case O_modulus:
+ case O_left_shift:
+ case O_right_shift:
+ case O_bit_inclusive_or:
+ case O_bit_or_not:
+ case O_bit_exclusive_or:
+ case O_bit_and:
+ case O_add:
+ case O_subtract:
+ case O_eq:
+ case O_ne:
+ case O_lt:
+ case O_le:
+ case O_ge:
+ case O_gt:
+ case O_logical_and:
+ case O_logical_or:
+ case O_max:
+ default:
+ internal_error_a (_("unhandled expression type"), X_op);
+ }
+ }
+ if (!match)
+ {
+ opc++;
+ }
+ }
+
+ return (match ? opc : NULL);
+
+#if 0
+
+ /* Now search the opcode table table for one with operands that
+ matches what we've got. */
+
+ while (!match)
+ {
+ match = 1;
+ for (i = 0; opcode -> operands[i]; i++)
+ {
+ int flags = tic80_operands[opcode->operands[i]].flags;
+ int X_op = myops[i].X_op;
+ int num = myops[i].X_add_number;
+
+ if (X_op == 0)
+ {
+ match = 0;
+ break;
+ }
+
+ if (flags & (TIC80_OPERAND_GPR | TIC80_OPERAND_FPA | TIC80_OPERAND_CR))
+ {
+ if ((X_op != O_register) ||
+ ((flags & TIC80_OPERAND_GPR) != (num & TIC80_OPERAND_GPR)) ||
+ ((flags & TIC80_OPERAND_FPA) != (num & TIC80_OPERAND_FPA)) ||
+ ((flags & TIC80_OPERAND_CR) != (num & TIC80_OPERAND_CR)))
+ {
+ match=0;
+ break;
+ }
+ }
+
+ if (((flags & TIC80_OPERAND_MINUS) && ((X_op != O_absent) || (num != TIC80_OPERAND_MINUS))) ||
+ ((flags & TIC80_OPERAND_PLUS) && ((X_op != O_absent) || (num != TIC80_OPERAND_PLUS))) ||
+ ((flags & TIC80_OPERAND_ATMINUS) && ((X_op != O_absent) || (num != TIC80_OPERAND_ATMINUS))) ||
+ ((flags & TIC80_OPERAND_ATPAR) && ((X_op != O_absent) || (num != TIC80_OPERAND_ATPAR))) ||
+ ((flags & TIC80_OPERAND_ATSIGN) && ((X_op != O_absent) || (num != TIC80_OPERAND_ATSIGN))))
+ {
+ match=0;
+ break;
+ }
+ }
+ /* we're only done if the operands matched so far AND there
+ are no more to check */
+ if (match && myops[i].X_op==0)
+ break;
+ else
+ match = 0;
+
+ next_opcode = opcode+1;
+ if (next_opcode->opcode == 0)
+ break;
+ if (strcmp(next_opcode->name, opcode->name))
+ break;
+ opcode = next_opcode;
+ }
+
+ if (!match)
+ {
+ as_bad (_("bad opcode or operands"));
+ return (0);
+ }
+
+ /* Check that all registers that are required to be even are. */
+ /* Also, if any operands were marked as registers, but were really symbols */
+ /* fix that here. */
+ for (i=0; opcode->operands[i]; i++)
+ {
+ if ((tic80_operands[opcode->operands[i]].flags & TIC80_OPERAND_EVEN) &&
+ (myops[i].X_add_number & 1))
+ as_fatal (_("Register number must be EVEN"));
+ if (myops[i].X_op == O_register)
+ {
+ if (!(tic80_operands[opcode->operands[i]].flags & TIC80_OPERAND_REG))
+ {
+ myops[i].X_op = O_symbol;
+ myops[i].X_add_symbol = symbol_find_or_make ((char *)myops[i].X_op_symbol);
+ myops[i].X_add_number = 0;
+ myops[i].X_op_symbol = NULL;
+ }
+ }
+ }
+
+#endif
+}
+
+/* build_insn takes a pointer to the opcode entry in the opcode table
+ and the array of operand expressions and writes out the instruction.
+
+ Note that the opcode word and extended word may be written to different
+ frags, with the opcode at the end of one frag and the extension at the
+ beginning of the next. */
+
+static void
+build_insn (opcode, opers)
+ struct tic80_opcode *opcode;
+ expressionS *opers;
+{
+ int expi; /* Index of current expression to match */
+ int opi; /* Index of current operand to match */
+ unsigned long insn[2]; /* Instruction and long immediate (if any) */
+ char *f; /* Pointer to frag location for insn[0] */
+ fragS *ffrag; /* Frag containing location f */
+ char *fx = NULL; /* Pointer to frag location for insn[1] */
+ fragS *fxfrag; /* Frag containing location fx */
+
+ /* Start with the raw opcode bits from the opcode table. */
+ insn[0] = opcode -> opcode;
+
+ /* We are going to insert at least one 32 bit opcode so get the
+ frag now. */
+
+ f = frag_more (4);
+ ffrag = frag_now;
+
+ /* For each operand expression, insert the appropriate bits into the
+ instruction . */
+ for (expi = 0, opi = -1; opers[expi].X_op != O_illegal; expi++)
+ {
+ int bits, shift, flags, X_op, num;
+
+ X_op = opers[expi].X_op;
+ num = opers[expi].X_add_number;
+
+ /* The O_absent expressions apply to the same operand as the most
+ recent non O_absent expression. So only increment the operand
+ index when the current expression is not one of these special
+ expressions. */
+
+ if (X_op != O_absent)
+ {
+ opi++;
+ }
+
+ flags = tic80_operands[opcode -> operands[opi]].flags;
+ bits = tic80_operands[opcode -> operands[opi]].bits;
+ shift = tic80_operands[opcode -> operands[opi]].shift;
+
+ switch (X_op)
+ {
+ case O_register:
+ num &= ~TIC80_OPERAND_MASK;
+ insn[0] = insn[0] | (num << shift);
+ break;
+ case O_constant:
+ if ((flags & TIC80_OPERAND_ENDMASK) && (num == 32))
+ {
+ /* Endmask values of 0 and 32 give identical results */
+ num = 0;
+ }
+ else if ((flags & TIC80_OPERAND_BITNUM))
+ {
+ /* BITNUM values are stored in one's complement form */
+ num = (~num & 0x1F);
+ }
+ /* Mask off upper bits, just it case it is signed and is negative */
+ if (bits < 32)
+ {
+ num &= (1 << bits) - 1;
+ insn[0] = insn[0] | (num << shift);
+ }
+ else
+ {
+ fx = frag_more (4);
+ fxfrag = frag_now;
+ insn[1] = num;
+ }
+ break;
+ case O_symbol:
+ if (bits == 32)
+ {
+ fx = frag_more (4);
+ fxfrag = frag_now;
+ insn[1] = 0;
+ if (flags & TIC80_OPERAND_PCREL)
+ {
+ fix_new_exp (fxfrag,
+ fx - (fxfrag -> fr_literal),
+ 4,
+ &opers[expi],
+ 1,
+ R_MPPCR);
+ }
+ else
+ {
+ fix_new_exp (fxfrag,
+ fx - (fxfrag -> fr_literal),
+ 4,
+ &opers[expi],
+ 0,
+ R_RELLONGX);
+ }
+ }
+ else if (flags & TIC80_OPERAND_PCREL)
+ {
+ fix_new_exp (ffrag,
+ f - (ffrag -> fr_literal),
+ 4, /* FIXME! how is this used? */
+ &opers[expi],
+ 1,
+ R_MPPCR15W);
+ }
+ else
+ {
+ internal_error (_("symbol reloc that is not PC relative or 32 bits"));
+ }
+ break;
+ case O_absent:
+ /* Each O_absent expression can indicate exactly one possible modifier. */
+ if ((num & TIC80_OPERAND_M_SI) && (flags & TIC80_OPERAND_M_SI))
+ {
+ insn[0] = insn[0] | (1 << 17);
+ }
+ else if ((num & TIC80_OPERAND_M_LI) && (flags & TIC80_OPERAND_M_LI))
+ {
+ insn[0] = insn[0] | (1 << 15);
+ }
+ else if ((num & TIC80_OPERAND_SCALED) && (flags & TIC80_OPERAND_SCALED))
+ {
+ insn[0] = insn[0] | (1 << 11);
+ }
+ else if ((num & TIC80_OPERAND_PARENS) && (flags & TIC80_OPERAND_PARENS))
+ {
+ /* No code to generate, just accept and discard this expression */
+ }
+ else
+ {
+ internal_error_a (_("unhandled operand modifier"), opers[expi].X_add_number);
+ }
+ break;
+ case O_big:
+ fx = frag_more (4);
+ fxfrag = frag_now;
+ {
+ int precision = 2;
+ long exponent_bits = 8L;
+ LITTLENUM_TYPE words[2];
+ /* Value is still in generic_floating_point_number */
+ gen_to_words (words, precision, exponent_bits);
+ insn[1] = (words[0] << 16) | words[1];
+ }
+ break;
+ case O_illegal:
+ case O_symbol_rva:
+ case O_uminus:
+ case O_bit_not:
+ case O_logical_not:
+ case O_multiply:
+ case O_divide:
+ case O_modulus:
+ case O_left_shift:
+ case O_right_shift:
+ case O_bit_inclusive_or:
+ case O_bit_or_not:
+ case O_bit_exclusive_or:
+ case O_bit_and:
+ case O_add:
+ case O_subtract:
+ case O_eq:
+ case O_ne:
+ case O_lt:
+ case O_le:
+ case O_ge:
+ case O_gt:
+ case O_logical_and:
+ case O_logical_or:
+ case O_max:
+ default:
+ internal_error_a (_("unhandled expression"), X_op);
+ break;
+ }
+ }
+
+ /* Write out the instruction, either 4 or 8 bytes. */
+
+ md_number_to_chars (f, insn[0], 4);
+ if (fx != NULL)
+ {
+ md_number_to_chars (fx, insn[1], 4);
+ }
+}
+
+/* This is the main entry point for the machine-dependent assembler. Gas
+ calls this function for each input line which does not contain a
+ pseudoop.
+
+ STR points to a NULL terminated machine dependent instruction. This
+ function is supposed to emit the frags/bytes it assembles to. */
+
+void
+md_assemble (str)
+ char *str;
+{
+ char *scan;
+ unsigned char *input_line_save;
+ struct tic80_opcode *opcode;
+ expressionS myops[16];
+ unsigned long insn;
+
+ /* Ensure there is something there to assemble. */
+ assert (str);
+
+ /* Drop any leading whitespace. */
+ while (isspace (*str))
+ {
+ str++;
+ }
+
+ /* Isolate the mnemonic from the rest of the string by finding the first
+ whitespace character and zapping it to a null byte. */
+ for (scan = str; *scan != '\000' && !isspace (*scan); scan++) {;}
+ if (*scan != '\000')
+ {
+ *scan++ = '\000';
+ }
+
+ /* Try to find this mnemonic in the hash table */
+ if ((opcode = (struct tic80_opcode *) hash_find (tic80_hash, str)) == NULL)
+ {
+ as_bad (_("Invalid mnemonic: '%s'"), str);
+ return;
+ }
+
+ str = scan;
+ while (isspace (*scan))
+ {
+ scan++;
+ }
+
+ input_line_save = input_line_pointer;
+ input_line_pointer = str;
+
+ opcode = find_opcode (opcode, myops);
+ if (opcode == NULL)
+ {
+ as_bad (_("Invalid operands: '%s'"), input_line_save);
+ }
+
+ input_line_pointer = input_line_save;
+ build_insn (opcode, myops);
+}
+
+/* This function is called once at the start of assembly, after the command
+ line arguments have been parsed and all the machine independent
+ initializations have been completed.
+
+ It should set up all the tables, etc., that the machine dependent part of
+ the assembler will need. */
+
+void
+md_begin ()
+{
+ char *prev_name = "";
+ register const struct tic80_opcode *op;
+ register const struct tic80_opcode *op_end;
+ const struct predefined_symbol *pdsp;
+ extern int coff_flags; /* Defined in obj-coff.c */
+
+ /* Set F_AR32WR in coff_flags, which will end up in the file header
+ f_flags field. */
+
+ coff_flags |= F_AR32WR; /* TIc80 is 32 bit little endian */
+
+ /* Insert unique names into hash table. The TIc80 instruction set
+ has many identical opcode names that have different opcodes based
+ on the operands. This hash table then provides a quick index to
+ the first opcode with a particular name in the opcode table. */
+
+ tic80_hash = hash_new ();
+ op_end = tic80_opcodes + tic80_num_opcodes;
+ for (op = tic80_opcodes; op < op_end; op++)
+ {
+ if (strcmp (prev_name, op -> name) != 0)
+ {
+ prev_name = (char *) op -> name;
+ hash_insert (tic80_hash, op -> name, (char *) op);
+ }
+ }
+
+ /* Insert the predefined symbols into the symbol table. We use symbol_create
+ rather than symbol_new so that these symbols don't end up in the object
+ files' symbol table. Note that the values of the predefined symbols include
+ some upper bits that distinguish the type of the symbol (register, bitnum,
+ condition code, etc) and these bits must be masked away before actually
+ inserting the values into the instruction stream. For registers we put
+ these bits in the symbol table since we use them later and there is no
+ question that they aren't part of the register number. For constants we
+ can't do that since the constant can be any value, so they are masked off
+ before putting them into the symbol table. */
+
+ pdsp = NULL;
+ while ((pdsp = tic80_next_predefined_symbol (pdsp)) != NULL)
+ {
+ segT segment;
+ valueT valu;
+ int symtype;
+
+ symtype = PDS_VALUE (pdsp) & TIC80_OPERAND_MASK;
+ switch (symtype)
+ {
+ case TIC80_OPERAND_GPR:
+ case TIC80_OPERAND_FPA:
+ case TIC80_OPERAND_CR:
+ segment = reg_section;
+ valu = PDS_VALUE (pdsp);
+ break;
+ case TIC80_OPERAND_CC:
+ case TIC80_OPERAND_BITNUM:
+ segment = absolute_section;
+ valu = PDS_VALUE (pdsp) & ~TIC80_OPERAND_MASK;
+ break;
+ default:
+ internal_error_a (_("unhandled predefined symbol bits"), symtype);
+ break;
+ }
+ symbol_table_insert (symbol_create (PDS_NAME (pdsp), segment, valu,
+ &zero_address_frag));
+ }
+}
+
+
+
+/* The assembler adds md_shortopts to the string passed to getopt. */
+
+CONST char *md_shortopts = "";
+
+/* The assembler adds md_longopts to the machine independent long options
+ that are passed to getopt. */
+
+struct option md_longopts[] = {
+
+#define OPTION_RELAX (OPTION_MD_BASE)
+ {"relax", no_argument, NULL, OPTION_RELAX},
+
+#define OPTION_NO_RELAX (OPTION_RELAX + 1)
+ {"no-relax", no_argument, NULL, OPTION_NO_RELAX},
+
+ {NULL, no_argument, NULL, 0}
+};
+
+size_t md_longopts_size = sizeof(md_longopts);
+
+/* The md_parse_option function will be called whenever getopt returns an
+ unrecognized code, presumably indicating a special code value which
+ appears in md_longopts for machine specific command line options. */
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ switch (c)
+ {
+ case OPTION_RELAX:
+ tic80_relax = 1;
+ break;
+ case OPTION_NO_RELAX:
+ tic80_relax = 0;
+ break;
+ default:
+ return (0);
+ }
+ return (1);
+}
+
+/* The md_show_usage function will be called whenever a usage message is
+ printed. It should print a description of the machine specific options
+ found in md_longopts. */
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+ fprintf (stream, "\
+TIc80 options:\n\
+-relax alter PC relative branch instructions to use long form when needed\n\
+-no-relax always use short PC relative branch instructions, error on overflow\n");
+}
+
+
+/* Attempt to simplify or even eliminate a fixup. The return value is
+ ignored; perhaps it was once meaningful, but now it is historical.
+ To indicate that a fixup has been eliminated, set fixP->fx_done.
+ */
+
+void
+md_apply_fix (fixP, val)
+ fixS *fixP;
+ long val;
+{
+ char *dest = fixP -> fx_frag -> fr_literal + fixP -> fx_where;
+ int overflow;
+
+ switch (fixP -> fx_r_type)
+ {
+ case R_RELLONGX:
+ md_number_to_chars (dest, (valueT) val, 4);
+ break;
+ case R_MPPCR:
+ val >>= 2;
+ val += 1; /* Target address computed from inst start */
+ md_number_to_chars (dest, (valueT) val, 4);
+ break;
+ case R_MPPCR15W:
+ overflow = (val < -65536L) || (val > 65532L);
+ if (overflow)
+ {
+ as_bad_where (fixP -> fx_file, fixP -> fx_line,
+ _("PC offset 0x%lx outside range 0x%lx-0x%lx"),
+ val, -65536L, 65532L);
+ }
+ else
+ {
+ val >>= 2;
+ *dest++ = val & 0xFF;
+ val >>= 8;
+ *dest = (*dest & 0x80) | (val & 0x7F);
+ }
+ break;
+ case R_ABS:
+ md_number_to_chars (dest, (valueT) val, fixP -> fx_size);
+ break;
+ default:
+ internal_error_a (_("unhandled relocation type in fixup"), fixP -> fx_r_type);
+ break;
+ }
+}
+
+
+/* Functions concerning relocs. */
+
+/* The location from which a PC relative jump should be calculated,
+ given a PC relative reloc.
+
+ For the TIc80, this is the address of the 32 bit opcode containing
+ the PC relative field. */
+
+long
+md_pcrel_from (fixP)
+ fixS *fixP;
+{
+ return (fixP -> fx_frag -> fr_address + fixP -> fx_where) ;
+}
+
+/*
+ * Called after relax() is finished.
+ * In: Address of frag.
+ * fr_type == rs_machine_dependent.
+ * fr_subtype is what the address relaxed to.
+ *
+ * Out: Any fixSs and constants are set up.
+ * Caller will turn frag into a ".space 0".
+ */
+
+void
+md_convert_frag (headers, seg, fragP)
+ object_headers *headers;
+ segT seg;
+ fragS *fragP;
+{
+ internal_error (_("md_convert_frag() not implemented yet"));
+ abort ();
+}
+
+
+/*ARGSUSED*/
+void
+tc_coff_symbol_emit_hook (ignore)
+ symbolS *ignore;
+{
+}
+
+#if defined OBJ_COFF
+
+short
+tc_coff_fix2rtype (fixP)
+ fixS *fixP;
+{
+ return (fixP -> fx_r_type);
+}
+
+#endif /* OBJ_COFF */
+
+/* end of tc-tic80.c */
diff --git a/gas/config/tc-tic80.h b/gas/config/tc-tic80.h
new file mode 100644
index 0000000000..06ff249dd0
--- /dev/null
+++ b/gas/config/tc-tic80.h
@@ -0,0 +1,63 @@
+/* This file is tc-tic80.h
+ Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#define TC_TIC80
+
+#define TARGET_BYTES_BIG_ENDIAN 0
+
+#define TARGET_ARCH bfd_arch_tic80
+#define TARGET_FORMAT "coff-tic80"
+#define BFD_ARCH TARGET_ARCH
+
+/* We need the extra field in the fixup struct to put the relocation in. */
+
+#define NEED_FX_R_TYPE
+
+/* Define md_number_to_chars as the appropriate standard big endian or
+ little endian function. Should we someday support endianness as a
+ runtime decision, this will need to change. */
+
+#define md_number_to_chars number_to_chars_littleendian
+
+/* Define away the call to md_operand in the expression parsing code.
+ This is called whenever the expression parser can't parse the input
+ and gives the assembler backend a chance to deal with it instead. */
+
+#define md_operand(x)
+
+#ifdef OBJ_COFF
+
+/* COFF specific definitions. */
+
+#define COFF_MAGIC TIC80_ARCH_MAGIC
+
+/* Whether a reloc should be output. */
+
+#define TC_COUNT_RELOC(fixp) ((fixp) -> fx_addsy != NULL)
+
+/* This macro translates between an internal fix and an coff reloc type */
+
+#define TC_COFF_FIX2RTYPE(fixP) tc_coff_fix2rtype(fixP)
+
+extern short tc_coff_fix2rtype ();
+
+#endif /* OBJ_COFF */
+
+/* end of tc-tic80.h */
diff --git a/gas/config/tc-v850.c b/gas/config/tc-v850.c
new file mode 100644
index 0000000000..c8ab145ade
--- /dev/null
+++ b/gas/config/tc-v850.c
@@ -0,0 +1,2478 @@
+/* tc-v850.c -- Assembler code for the NEC V850
+ Copyright (C) 1996, 1997, 1998 Free Software Foundation.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "as.h"
+#include "subsegs.h"
+#include "opcode/v850.h"
+
+#define AREA_ZDA 0
+#define AREA_SDA 1
+#define AREA_TDA 2
+
+/* sign-extend a 16-bit number */
+#define SEXT16(x) ((((x) & 0xffff) ^ (~ 0x7fff)) + 0x8000)
+
+/* Temporarily holds the reloc in a cons expression. */
+static bfd_reloc_code_real_type hold_cons_reloc;
+
+/* Set to TRUE if we want to be pedantic about signed overflows. */
+static boolean warn_signed_overflows = FALSE;
+static boolean warn_unsigned_overflows = FALSE;
+
+/* Indicates the target BFD machine number. */
+static int machine = -1;
+
+/* Indicates the target processor(s) for the assemble. */
+static unsigned int processor_mask = -1;
+
+
+/* Structure to hold information about predefined registers. */
+struct reg_name
+{
+ const char * name;
+ int value;
+};
+
+/* Generic assembler global variables which must be defined by all targets. */
+
+/* Characters which always start a comment. */
+const char comment_chars[] = "#";
+
+/* Characters which start a comment at the beginning of a line. */
+const char line_comment_chars[] = ";#";
+
+/* Characters which may be used to separate multiple commands on a
+ single line. */
+const char line_separator_chars[] = ";";
+
+/* Characters which are used to indicate an exponent in a floating
+ point number. */
+const char EXP_CHARS[] = "eE";
+
+/* Characters which mean that a number is a floating point constant,
+ as in 0d1.0. */
+const char FLT_CHARS[] = "dD";
+
+
+const relax_typeS md_relax_table[] =
+{
+ /* Conditional branches. */
+ {0xff, -0x100, 2, 1},
+ {0x1fffff, -0x200000, 6, 0},
+ /* Unconditional branches. */
+ {0xff, -0x100, 2, 3},
+ {0x1fffff, -0x200000, 4, 0},
+};
+
+
+static segT sdata_section = NULL;
+static segT tdata_section = NULL;
+static segT zdata_section = NULL;
+static segT sbss_section = NULL;
+static segT tbss_section = NULL;
+static segT zbss_section = NULL;
+static segT rosdata_section = NULL;
+static segT rozdata_section = NULL;
+static segT scommon_section = NULL;
+static segT tcommon_section = NULL;
+static segT zcommon_section = NULL;
+static segT call_table_data_section = NULL;
+static segT call_table_text_section = NULL;
+
+/* fixups */
+#define MAX_INSN_FIXUPS (5)
+struct v850_fixup
+{
+ expressionS exp;
+ int opindex;
+ bfd_reloc_code_real_type reloc;
+};
+
+struct v850_fixup fixups [MAX_INSN_FIXUPS];
+static int fc;
+
+
+void
+v850_sdata (int ignore)
+{
+ obj_elf_section_change_hook();
+
+ subseg_set (sdata_section, (subsegT) get_absolute_expression ());
+
+ demand_empty_rest_of_line ();
+}
+
+void
+v850_tdata (int ignore)
+{
+ obj_elf_section_change_hook();
+
+ subseg_set (tdata_section, (subsegT) get_absolute_expression ());
+
+ demand_empty_rest_of_line ();
+}
+
+void
+v850_zdata (int ignore)
+{
+ obj_elf_section_change_hook();
+
+ subseg_set (zdata_section, (subsegT) get_absolute_expression ());
+
+ demand_empty_rest_of_line ();
+}
+
+void
+v850_sbss (int ignore)
+{
+ obj_elf_section_change_hook();
+
+ subseg_set (sbss_section, (subsegT) get_absolute_expression ());
+
+ demand_empty_rest_of_line ();
+}
+
+void
+v850_tbss (int ignore)
+{
+ obj_elf_section_change_hook();
+
+ subseg_set (tbss_section, (subsegT) get_absolute_expression ());
+
+ demand_empty_rest_of_line ();
+}
+
+void
+v850_zbss (int ignore)
+{
+ obj_elf_section_change_hook();
+
+ subseg_set (zbss_section, (subsegT) get_absolute_expression ());
+
+ demand_empty_rest_of_line ();
+}
+
+void
+v850_rosdata (int ignore)
+{
+ obj_elf_section_change_hook();
+
+ subseg_set (rosdata_section, (subsegT) get_absolute_expression ());
+
+ demand_empty_rest_of_line ();
+}
+
+void
+v850_rozdata (int ignore)
+{
+ obj_elf_section_change_hook();
+
+ subseg_set (rozdata_section, (subsegT) get_absolute_expression ());
+
+ demand_empty_rest_of_line ();
+}
+
+void
+v850_call_table_data (int ignore)
+{
+ obj_elf_section_change_hook();
+
+ subseg_set (call_table_data_section, (subsegT) get_absolute_expression ());
+
+ demand_empty_rest_of_line ();
+}
+
+void
+v850_call_table_text (int ignore)
+{
+ obj_elf_section_change_hook();
+
+ subseg_set (call_table_text_section, (subsegT) get_absolute_expression ());
+
+ demand_empty_rest_of_line ();
+}
+
+void
+v850_bss (int ignore)
+{
+ register int temp = get_absolute_expression ();
+
+ obj_elf_section_change_hook();
+
+ subseg_set (bss_section, (subsegT) temp);
+
+ demand_empty_rest_of_line ();
+}
+
+void
+v850_offset (int ignore)
+{
+ int temp = get_absolute_expression ();
+
+ temp -= frag_now_fix();
+
+ if (temp > 0)
+ (void) frag_more (temp);
+
+ demand_empty_rest_of_line ();
+}
+
+/* Copied from obj_elf_common() in gas/config/obj-elf.c */
+static void
+v850_comm (area)
+ int area;
+{
+ char * name;
+ char c;
+ char * p;
+ int temp;
+ int size;
+ symbolS * symbolP;
+ int have_align;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+
+ /* just after name is now '\0' */
+ p = input_line_pointer;
+ *p = c;
+
+ SKIP_WHITESPACE ();
+
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("Expected comma after symbol-name"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ input_line_pointer ++; /* skip ',' */
+
+ if ((temp = get_absolute_expression ()) < 0)
+ {
+ /* xgettext:c-format */
+ as_bad (_(".COMMon length (%d.) < 0! Ignored."), temp);
+ ignore_rest_of_line ();
+ return;
+ }
+
+ size = temp;
+ *p = 0;
+ symbolP = symbol_find_or_make (name);
+ *p = c;
+
+ if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
+ {
+ as_bad (_("Ignoring attempt to re-define symbol"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ if (S_GET_VALUE (symbolP) != 0)
+ {
+ if (S_GET_VALUE (symbolP) != size)
+ {
+ /* xgettext:c-format */
+ as_warn (_("Length of .comm \"%s\" is already %ld. Not changed to %d."),
+ S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size);
+ }
+ }
+
+ know (symbolP->sy_frag == & zero_address_frag);
+
+ if (*input_line_pointer != ',')
+ have_align = 0;
+ else
+ {
+ have_align = 1;
+ input_line_pointer++;
+ SKIP_WHITESPACE ();
+ }
+
+ if (! have_align || *input_line_pointer != '"')
+ {
+ if (! have_align)
+ temp = 0;
+ else
+ {
+ temp = get_absolute_expression ();
+
+ if (temp < 0)
+ {
+ temp = 0;
+ as_warn (_("Common alignment negative; 0 assumed"));
+ }
+ }
+
+ if (symbolP->local)
+ {
+ segT old_sec;
+ int old_subsec;
+ char * pfrag;
+ int align;
+ flagword applicable;
+
+ old_sec = now_seg;
+ old_subsec = now_subseg;
+
+ applicable = bfd_applicable_section_flags (stdoutput);
+
+ applicable &= SEC_ALLOC;
+
+ switch (area)
+ {
+ case AREA_SDA:
+ if (sbss_section == NULL)
+ {
+ sbss_section = subseg_new (".sbss", 0);
+
+ bfd_set_section_flags (stdoutput, sbss_section, applicable);
+
+ seg_info (sbss_section)->bss = 1;
+ }
+ break;
+
+ case AREA_ZDA:
+ if (zbss_section == NULL)
+ {
+ zbss_section = subseg_new (".zbss", 0);
+
+ bfd_set_section_flags (stdoutput, sbss_section, applicable);
+
+ seg_info (zbss_section)->bss = 1;
+ }
+ break;
+
+ case AREA_TDA:
+ if (tbss_section == NULL)
+ {
+ tbss_section = subseg_new (".tbss", 0);
+
+ bfd_set_section_flags (stdoutput, tbss_section, applicable);
+
+ seg_info (tbss_section)->bss = 1;
+ }
+ break;
+ }
+
+ if (temp)
+ {
+ /* convert to a power of 2 alignment */
+ for (align = 0; (temp & 1) == 0; temp >>= 1, ++align)
+ ;
+
+ if (temp != 1)
+ {
+ as_bad (_("Common alignment not a power of 2"));
+ ignore_rest_of_line ();
+ return;
+ }
+ }
+ else
+ align = 0;
+
+ switch (area)
+ {
+ case AREA_SDA:
+ record_alignment (sbss_section, align);
+ obj_elf_section_change_hook();
+ subseg_set (sbss_section, 0);
+ break;
+
+ case AREA_ZDA:
+ record_alignment (zbss_section, align);
+ obj_elf_section_change_hook();
+ subseg_set (zbss_section, 0);
+ break;
+
+ case AREA_TDA:
+ record_alignment (tbss_section, align);
+ obj_elf_section_change_hook();
+ subseg_set (tbss_section, 0);
+ break;
+
+ default:
+ abort();
+ }
+
+ if (align)
+ frag_align (align, 0, 0);
+
+ switch (area)
+ {
+ case AREA_SDA:
+ if (S_GET_SEGMENT (symbolP) == sbss_section)
+ symbolP->sy_frag->fr_symbol = 0;
+ break;
+
+ case AREA_ZDA:
+ if (S_GET_SEGMENT (symbolP) == zbss_section)
+ symbolP->sy_frag->fr_symbol = 0;
+ break;
+
+ case AREA_TDA:
+ if (S_GET_SEGMENT (symbolP) == tbss_section)
+ symbolP->sy_frag->fr_symbol = 0;
+ break;
+
+ default:
+ abort();
+ }
+
+ symbolP->sy_frag = frag_now;
+ pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
+ (offsetT) size, (char *) 0);
+ *pfrag = 0;
+ S_SET_SIZE (symbolP, size);
+
+ switch (area)
+ {
+ case AREA_SDA:
+ S_SET_SEGMENT (symbolP, sbss_section);
+ break;
+
+ case AREA_ZDA:
+ S_SET_SEGMENT (symbolP, zbss_section);
+ break;
+
+ case AREA_TDA:
+ S_SET_SEGMENT (symbolP, tbss_section);
+ break;
+
+ default:
+ abort();
+ }
+
+ S_CLEAR_EXTERNAL (symbolP);
+ obj_elf_section_change_hook();
+ subseg_set (old_sec, old_subsec);
+ }
+ else
+ {
+ allocate_common:
+ S_SET_VALUE (symbolP, (valueT) size);
+ S_SET_ALIGN (symbolP, temp);
+ S_SET_EXTERNAL (symbolP);
+
+ switch (area)
+ {
+ case AREA_SDA:
+ if (scommon_section == NULL)
+ {
+ flagword applicable;
+
+ applicable = bfd_applicable_section_flags (stdoutput);
+
+ scommon_section = subseg_new (".scommon", 0);
+
+ bfd_set_section_flags (stdoutput, scommon_section, applicable
+ & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
+ | SEC_HAS_CONTENTS) | SEC_IS_COMMON);
+ }
+ S_SET_SEGMENT (symbolP, scommon_section);
+ break;
+
+ case AREA_ZDA:
+ if (zcommon_section == NULL)
+ {
+ flagword applicable;
+
+ applicable = bfd_applicable_section_flags (stdoutput);
+
+ zcommon_section = subseg_new (".zcommon", 0);
+
+ bfd_set_section_flags (stdoutput, zcommon_section, applicable
+ & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
+ | SEC_HAS_CONTENTS) | SEC_IS_COMMON);
+ }
+ S_SET_SEGMENT (symbolP, zcommon_section);
+ break;
+
+ case AREA_TDA:
+ if (tcommon_section == NULL)
+ {
+ flagword applicable;
+
+ applicable = bfd_applicable_section_flags (stdoutput);
+
+ tcommon_section = subseg_new (".tcommon", 0);
+
+ bfd_set_section_flags (stdoutput, tcommon_section, applicable
+ & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
+ | SEC_HAS_CONTENTS) | SEC_IS_COMMON);
+ }
+ S_SET_SEGMENT (symbolP, tcommon_section);
+ break;
+
+ default:
+ abort();
+ }
+ }
+ }
+ else
+ {
+ input_line_pointer++;
+ /* @@ Some use the dot, some don't. Can we get some consistency?? */
+ if (*input_line_pointer == '.')
+ input_line_pointer++;
+ /* @@ Some say data, some say bss. */
+ if (strncmp (input_line_pointer, "bss\"", 4)
+ && strncmp (input_line_pointer, "data\"", 5))
+ {
+ while (*--input_line_pointer != '"')
+ ;
+ input_line_pointer--;
+ goto bad_common_segment;
+ }
+ while (*input_line_pointer++ != '"')
+ ;
+ goto allocate_common;
+ }
+
+ symbolP->bsym->flags |= BSF_OBJECT;
+
+ demand_empty_rest_of_line ();
+ return;
+
+ {
+ bad_common_segment:
+ p = input_line_pointer;
+ while (*p && *p != '\n')
+ p++;
+ c = *p;
+ *p = '\0';
+ as_bad (_("bad .common segment %s"), input_line_pointer + 1);
+ *p = c;
+ input_line_pointer = p;
+ ignore_rest_of_line ();
+ return;
+ }
+}
+
+void
+set_machine (int number)
+{
+ machine = number;
+ bfd_set_arch_mach (stdoutput, TARGET_ARCH, machine);
+
+ switch (machine)
+ {
+ case 0: processor_mask = PROCESSOR_V850; break;
+ case bfd_mach_v850e: processor_mask = PROCESSOR_V850E; break;
+ case bfd_mach_v850ea: processor_mask = PROCESSOR_V850EA; break;
+ }
+}
+
+/* The target specific pseudo-ops which we support. */
+const pseudo_typeS md_pseudo_table[] =
+{
+ {"sdata", v850_sdata, 0},
+ {"tdata", v850_tdata, 0},
+ {"zdata", v850_zdata, 0},
+ {"sbss", v850_sbss, 0},
+ {"tbss", v850_tbss, 0},
+ {"zbss", v850_zbss, 0},
+ {"rosdata", v850_rosdata, 0},
+ {"rozdata", v850_rozdata, 0},
+ {"bss", v850_bss, 0},
+ {"offset", v850_offset, 0},
+ {"word", cons, 4},
+ {"zcomm", v850_comm, AREA_ZDA},
+ {"scomm", v850_comm, AREA_SDA},
+ {"tcomm", v850_comm, AREA_TDA},
+ {"v850", set_machine, 0},
+ {"call_table_data", v850_call_table_data, 0},
+ {"call_table_text", v850_call_table_text, 0},
+ {"v850e", set_machine, bfd_mach_v850e},
+ {"v850ea", set_machine, bfd_mach_v850ea},
+ { NULL, NULL, 0}
+};
+
+/* Opcode hash table. */
+static struct hash_control *v850_hash;
+
+/* This table is sorted. Suitable for searching by a binary search. */
+static const struct reg_name pre_defined_registers[] =
+{
+ { "ep", 30 }, /* ep - element ptr */
+ { "gp", 4 }, /* gp - global ptr */
+ { "hp", 2 }, /* hp - handler stack ptr */
+ { "lp", 31 }, /* lp - link ptr */
+ { "r0", 0 },
+ { "r1", 1 },
+ { "r10", 10 },
+ { "r11", 11 },
+ { "r12", 12 },
+ { "r13", 13 },
+ { "r14", 14 },
+ { "r15", 15 },
+ { "r16", 16 },
+ { "r17", 17 },
+ { "r18", 18 },
+ { "r19", 19 },
+ { "r2", 2 },
+ { "r20", 20 },
+ { "r21", 21 },
+ { "r22", 22 },
+ { "r23", 23 },
+ { "r24", 24 },
+ { "r25", 25 },
+ { "r26", 26 },
+ { "r27", 27 },
+ { "r28", 28 },
+ { "r29", 29 },
+ { "r3", 3 },
+ { "r30", 30 },
+ { "r31", 31 },
+ { "r4", 4 },
+ { "r5", 5 },
+ { "r6", 6 },
+ { "r7", 7 },
+ { "r8", 8 },
+ { "r9", 9 },
+ { "sp", 3 }, /* sp - stack ptr */
+ { "tp", 5 }, /* tp - text ptr */
+ { "zero", 0 },
+};
+#define REG_NAME_CNT (sizeof (pre_defined_registers) / sizeof (struct reg_name))
+
+
+static const struct reg_name system_registers[] =
+{
+ { "ctbp", 20 },
+ { "ctpc", 16 },
+ { "ctpsw", 17 },
+ { "dbpc", 18 },
+ { "dbpsw", 19 },
+ { "ecr", 4 },
+ { "eipc", 0 },
+ { "eipsw", 1 },
+ { "fepc", 2 },
+ { "fepsw", 3 },
+ { "psw", 5 },
+};
+#define SYSREG_NAME_CNT (sizeof (system_registers) / sizeof (struct reg_name))
+
+static const struct reg_name system_list_registers[] =
+{
+ {"PS", 5 },
+ {"SR", 0 + 1}
+};
+#define SYSREGLIST_NAME_CNT (sizeof (system_list_registers) / sizeof (struct reg_name))
+
+static const struct reg_name cc_names[] =
+{
+ { "c", 0x1 },
+ { "e", 0x2 },
+ { "ge", 0xe },
+ { "gt", 0xf },
+ { "h", 0xb },
+ { "l", 0x1 },
+ { "le", 0x7 },
+ { "lt", 0x6 },
+ { "n", 0x4 },
+ { "nc", 0x9 },
+ { "ne", 0xa },
+ { "nh", 0x3 },
+ { "nl", 0x9 },
+ { "ns", 0xc },
+ { "nv", 0x8 },
+ { "nz", 0xa },
+ { "p", 0xc },
+ { "s", 0x4 },
+ { "sa", 0xd },
+ { "t", 0x5 },
+ { "v", 0x0 },
+ { "z", 0x2 },
+};
+#define CC_NAME_CNT (sizeof (cc_names) / sizeof (struct reg_name))
+
+/* reg_name_search does a binary search of the given register table
+ to see if "name" is a valid regiter name. Returns the register
+ number from the array on success, or -1 on failure. */
+
+static int
+reg_name_search (regs, regcount, name, accept_numbers)
+ const struct reg_name * regs;
+ int regcount;
+ const char * name;
+ boolean accept_numbers;
+{
+ int middle, low, high;
+ int cmp;
+ symbolS * symbolP;
+
+ /* If the register name is a symbol, then evaluate it. */
+ if ((symbolP = symbol_find (name)) != NULL)
+ {
+ /* If the symbol is an alias for another name then use that.
+ If the symbol is an alias for a number, then return the number. */
+ if (symbolP->sy_value.X_op == O_symbol)
+ {
+ name = S_GET_NAME (symbolP->sy_value.X_add_symbol);
+ }
+ else if (accept_numbers)
+ {
+ int reg = S_GET_VALUE (symbolP);
+
+ if (reg >= 0 && reg <= 31)
+ return reg;
+ }
+
+ /* Otherwise drop through and try parsing name normally. */
+ }
+
+ low = 0;
+ high = regcount - 1;
+
+ do
+ {
+ middle = (low + high) / 2;
+ cmp = strcasecmp (name, regs[middle].name);
+ if (cmp < 0)
+ high = middle - 1;
+ else if (cmp > 0)
+ low = middle + 1;
+ else
+ return regs[middle].value;
+ }
+ while (low <= high);
+ return -1;
+}
+
+
+/* Summary of register_name().
+ *
+ * in: Input_line_pointer points to 1st char of operand.
+ *
+ * out: A expressionS.
+ * The operand may have been a register: in this case, X_op == O_register,
+ * X_add_number is set to the register number, and truth is returned.
+ * Input_line_pointer->(next non-blank) char after operand, or is in
+ * its original state.
+ */
+static boolean
+register_name (expressionP)
+ expressionS * expressionP;
+{
+ int reg_number;
+ char * name;
+ char * start;
+ char c;
+
+ /* Find the spelling of the operand */
+ start = name = input_line_pointer;
+
+ c = get_symbol_end ();
+
+ reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT,
+ name, FALSE);
+
+ * input_line_pointer = c; /* put back the delimiting char */
+
+ /* look to see if it's in the register table */
+ if (reg_number >= 0)
+ {
+ expressionP->X_op = O_register;
+ expressionP->X_add_number = reg_number;
+
+ /* make the rest nice */
+ expressionP->X_add_symbol = NULL;
+ expressionP->X_op_symbol = NULL;
+
+ return true;
+ }
+ else
+ {
+ /* reset the line as if we had not done anything */
+ input_line_pointer = start;
+
+ return false;
+ }
+}
+
+/* Summary of system_register_name().
+ *
+ * in: Input_line_pointer points to 1st char of operand.
+ * expressionP points to an expression structure to be filled in.
+ * accept_numbers is true iff numerical register names may be used.
+ * accept_list_names is true iff the special names PS and SR may be
+ * accepted.
+ *
+ * out: A expressionS structure in expressionP.
+ * The operand may have been a register: in this case, X_op == O_register,
+ * X_add_number is set to the register number, and truth is returned.
+ * Input_line_pointer->(next non-blank) char after operand, or is in
+ * its original state.
+ */
+static boolean
+system_register_name (expressionP, accept_numbers, accept_list_names)
+ expressionS * expressionP;
+ boolean accept_numbers;
+ boolean accept_list_names;
+{
+ int reg_number;
+ char * name;
+ char * start;
+ char c;
+
+ /* Find the spelling of the operand */
+ start = name = input_line_pointer;
+
+ c = get_symbol_end ();
+ reg_number = reg_name_search (system_registers, SYSREG_NAME_CNT, name,
+ accept_numbers);
+
+ * input_line_pointer = c; /* put back the delimiting char */
+
+ if (reg_number < 0
+ && accept_numbers)
+ {
+ input_line_pointer = start; /* reset input_line pointer */
+
+ if (isdigit (* input_line_pointer))
+ {
+ reg_number = strtol (input_line_pointer, & input_line_pointer, 10);
+
+ /* Make sure that the register number is allowable. */
+ if ( reg_number < 0
+ || reg_number > 5
+ && reg_number < 16
+ || reg_number > 20
+ )
+ {
+ reg_number = -1;
+ }
+ }
+ else if (accept_list_names)
+ {
+ c = get_symbol_end ();
+ reg_number = reg_name_search (system_list_registers,
+ SYSREGLIST_NAME_CNT, name, FALSE);
+
+ * input_line_pointer = c; /* put back the delimiting char */
+ }
+ }
+
+ /* look to see if it's in the register table */
+ if (reg_number >= 0)
+ {
+ expressionP->X_op = O_register;
+ expressionP->X_add_number = reg_number;
+
+ /* make the rest nice */
+ expressionP->X_add_symbol = NULL;
+ expressionP->X_op_symbol = NULL;
+
+ return true;
+ }
+ else
+ {
+ /* reset the line as if we had not done anything */
+ input_line_pointer = start;
+
+ return false;
+ }
+}
+
+/* Summary of cc_name().
+ *
+ * in: Input_line_pointer points to 1st char of operand.
+ *
+ * out: A expressionS.
+ * The operand may have been a register: in this case, X_op == O_register,
+ * X_add_number is set to the register number, and truth is returned.
+ * Input_line_pointer->(next non-blank) char after operand, or is in
+ * its original state.
+ */
+static boolean
+cc_name (expressionP)
+ expressionS * expressionP;
+{
+ int reg_number;
+ char * name;
+ char * start;
+ char c;
+
+ /* Find the spelling of the operand */
+ start = name = input_line_pointer;
+
+ c = get_symbol_end ();
+ reg_number = reg_name_search (cc_names, CC_NAME_CNT, name, FALSE);
+
+ * input_line_pointer = c; /* put back the delimiting char */
+
+ /* look to see if it's in the register table */
+ if (reg_number >= 0)
+ {
+ expressionP->X_op = O_constant;
+ expressionP->X_add_number = reg_number;
+
+ /* make the rest nice */
+ expressionP->X_add_symbol = NULL;
+ expressionP->X_op_symbol = NULL;
+
+ return true;
+ }
+ else
+ {
+ /* reset the line as if we had not done anything */
+ input_line_pointer = start;
+
+ return false;
+ }
+}
+
+static void
+skip_white_space (void)
+{
+ while ( * input_line_pointer == ' '
+ || * input_line_pointer == '\t')
+ ++ input_line_pointer;
+}
+
+/* Summary of parse_register_list ().
+ *
+ * in: Input_line_pointer points to 1st char of a list of registers.
+ * insn is the partially constructed instruction.
+ * operand is the operand being inserted.
+ *
+ * out: NULL if the parse completed successfully, otherwise a
+ * pointer to an error message is returned. If the parse
+ * completes the correct bit fields in the instruction
+ * will be filled in.
+ *
+ * Parses register lists with the syntax:
+ *
+ * { rX }
+ * { rX, rY }
+ * { rX - rY }
+ * { rX - rY, rZ }
+ * etc
+ *
+ * and also parses constant epxressions whoes bits indicate the
+ * registers in the lists. The LSB in the expression refers to
+ * the lowest numbered permissable register in the register list,
+ * and so on upwards. System registers are considered to be very
+ * high numbers.
+ *
+ */
+static char *
+parse_register_list
+(
+ unsigned long * insn,
+ const struct v850_operand * operand
+)
+{
+ static int type1_regs[ 32 ] = { 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
+ static int type2_regs[ 32 ] = { 19, 18, 17, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
+ static int type3_regs[ 32 ] = { 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 15, 13, 12, 7, 6, 5, 4, 11, 10, 9, 8 };
+ int * regs;
+ expressionS exp;
+
+
+ /* Select a register array to parse. */
+ switch (operand->shift)
+ {
+ case 0xffe00001: regs = type1_regs; break;
+ case 0xfff8000f: regs = type2_regs; break;
+ case 0xfff8001f: regs = type3_regs; break;
+ default:
+ as_bad (_("unknown operand shift: %x\n"), operand->shift);
+ return _("internal failure in parse_register_list");
+ }
+
+ skip_white_space ();
+
+ /* If the expression starts with a curly brace it is a register list.
+ Otherwise it is a constant expression, whoes bits indicate which
+ registers are to be included in the list. */
+
+ if (* input_line_pointer != '{')
+ {
+ int bits;
+ int reg;
+ int i;
+
+ expression (& exp);
+
+ if (exp.X_op != O_constant)
+ return _("constant expression or register list expected");
+
+ if (regs == type1_regs)
+ {
+ if (exp.X_add_number & 0xFFFFF000)
+ return _("high bits set in register list expression");
+
+ for (reg = 20; reg < 32; reg ++)
+ if (exp.X_add_number & (1 << (reg - 20)))
+ {
+ for (i = 0; i < 32; i++)
+ if (regs[i] == reg)
+ * insn |= (1 << i);
+ }
+ }
+ else if (regs == type2_regs)
+ {
+ if (exp.X_add_number & 0xFFFE0000)
+ return _("high bits set in register list expression");
+
+ for (reg = 1; reg < 16; reg ++)
+ if (exp.X_add_number & (1 << (reg - 1)))
+ {
+ for (i = 0; i < 32; i++)
+ if (regs[i] == reg)
+ * insn |= (1 << i);
+ }
+
+ if (exp.X_add_number & (1 << 15))
+ * insn |= (1 << 3);
+
+ if (exp.X_add_number & (1 << 16))
+ * insn |= (1 << 19);
+ }
+ else /* regs == type3_regs */
+ {
+ if (exp.X_add_number & 0xFFFE0000)
+ return _("high bits set in register list expression");
+
+ for (reg = 16; reg < 32; reg ++)
+ if (exp.X_add_number & (1 << (reg - 16)))
+ {
+ for (i = 0; i < 32; i++)
+ if (regs[i] == reg)
+ * insn |= (1 << i);
+ }
+
+ if (exp.X_add_number & (1 << 16))
+ * insn |= (1 << 19);
+ }
+
+ return NULL;
+ }
+
+ input_line_pointer ++;
+
+ /* Parse the register list until a terminator (closing curly brace or
+ new-line) is found. */
+ for (;;)
+ {
+ if (register_name (& exp))
+ {
+ int i;
+
+ /* Locate the given register in the list, and if it is there,
+ insert the corresponding bit into the instruction. */
+ for (i = 0; i < 32; i++)
+ {
+ if (regs[ i ] == exp.X_add_number)
+ {
+ * insn |= (1 << i);
+ break;
+ }
+ }
+
+ if (i == 32)
+ {
+ return _("illegal register included in list");
+ }
+ }
+ else if (system_register_name (& exp, true, true))
+ {
+ if (regs == type1_regs)
+ {
+ return _("system registers cannot be included in list");
+ }
+ else if (exp.X_add_number == 5)
+ {
+ if (regs == type2_regs)
+ return _("PSW cannot be included in list");
+ else
+ * insn |= 0x8;
+ }
+ else if (exp.X_add_number < 4)
+ * insn |= 0x80000;
+ else
+ return _("High value system registers cannot be included in list");
+ }
+ else if (* input_line_pointer == '}')
+ {
+ input_line_pointer ++;
+ break;
+ }
+ else if (* input_line_pointer == ',')
+ {
+ input_line_pointer ++;
+ continue;
+ }
+ else if (* input_line_pointer == '-')
+ {
+ /* We have encountered a range of registers: rX - rY */
+ int j;
+ expressionS exp2;
+
+ /* Skip the dash. */
+ ++ input_line_pointer;
+
+ /* Get the second register in the range. */
+ if (! register_name (& exp2))
+ {
+ return _("second register should follow dash in register list");
+ exp2.X_add_number = exp.X_add_number;
+ }
+
+ /* Add the rest of the registers in the range. */
+ for (j = exp.X_add_number + 1; j <= exp2.X_add_number; j++)
+ {
+ int i;
+
+ /* Locate the given register in the list, and if it is there,
+ insert the corresponding bit into the instruction. */
+ for (i = 0; i < 32; i++)
+ {
+ if (regs[ i ] == j)
+ {
+ * insn |= (1 << i);
+ break;
+ }
+ }
+
+ if (i == 32)
+ return _("illegal register included in list");
+ }
+ }
+ else
+ {
+ break;
+ }
+
+ skip_white_space ();
+ }
+
+ return NULL;
+}
+
+CONST char * md_shortopts = "m:";
+
+struct option md_longopts[] =
+{
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof md_longopts;
+
+
+void
+md_show_usage (stream)
+ FILE * stream;
+{
+ fprintf (stream, _(" V850 options:\n"));
+ fprintf (stream, _(" -mwarn-signed-overflow Warn if signed immediate values overflow\n"));
+ fprintf (stream, _(" -mwarn-unsigned-overflow Warn if unsigned immediate values overflow\n"));
+ fprintf (stream, _(" -mv850 The code is targeted at the v850\n"));
+ fprintf (stream, _(" -mv850e The code is targeted at the v850e\n"));
+ fprintf (stream, _(" -mv850ea The code is targeted at the v850ea\n"));
+ fprintf (stream, _(" -mv850any The code is generic, despite any processor specific instructions\n"));
+}
+
+int
+md_parse_option (c, arg)
+ int c;
+ char * arg;
+{
+ if (c != 'm')
+ {
+ /* xgettext:c-format */
+ fprintf (stderr, _("unknown command line option: -%c%s\n"), c, arg);
+ return 0;
+ }
+
+ if (strcmp (arg, "warn-signed-overflow") == 0)
+ {
+ warn_signed_overflows = TRUE;
+ }
+ else if (strcmp (arg, "warn-unsigned-overflow") == 0)
+ {
+ warn_unsigned_overflows = TRUE;
+ }
+ else if (strcmp (arg, "v850") == 0)
+ {
+ machine = 0;
+ processor_mask = PROCESSOR_V850;
+ }
+ else if (strcmp (arg, "v850e") == 0)
+ {
+ machine = bfd_mach_v850e;
+ processor_mask = PROCESSOR_V850E;
+ }
+ else if (strcmp (arg, "v850ea") == 0)
+ {
+ machine = bfd_mach_v850ea;
+ processor_mask = PROCESSOR_V850EA;
+ }
+ else if (strcmp (arg, "v850any") == 0)
+ {
+ machine = 0; /* Tell the world that this is for any v850 chip. */
+ processor_mask = PROCESSOR_V850EA; /* But support instructions for the extended versions. */
+ }
+ else
+ {
+ /* xgettext:c-format */
+ fprintf (stderr, _("unknown command line option: -%c%s\n"), c, arg);
+ return 0;
+ }
+
+ return 1;
+}
+
+symbolS *
+md_undefined_symbol (name)
+ char * name;
+{
+ return 0;
+}
+
+char *
+md_atof (type, litp, sizep)
+ int type;
+ char * litp;
+ int * sizep;
+{
+ int prec;
+ LITTLENUM_TYPE words[4];
+ char * t;
+ int i;
+
+ switch (type)
+ {
+ case 'f':
+ prec = 2;
+ break;
+
+ case 'd':
+ prec = 4;
+ break;
+
+ default:
+ *sizep = 0;
+ return _("bad call to md_atof");
+ }
+
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+
+ *sizep = prec * 2;
+
+ for (i = prec - 1; i >= 0; i--)
+ {
+ md_number_to_chars (litp, (valueT) words[i], 2);
+ litp += 2;
+ }
+
+ return NULL;
+}
+
+
+/* Very gross. */
+void
+md_convert_frag (abfd, sec, fragP)
+ bfd * abfd;
+ asection * sec;
+ fragS * fragP;
+{
+ subseg_change (sec, 0);
+
+ /* In range conditional or unconditional branch. */
+ if (fragP->fr_subtype == 0 || fragP->fr_subtype == 2)
+ {
+ fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
+ fragP->fr_offset, 1, BFD_RELOC_UNUSED + (int)fragP->fr_opcode);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 2;
+ }
+ /* Out of range conditional branch. Emit a branch around a jump. */
+ else if (fragP->fr_subtype == 1)
+ {
+ unsigned char *buffer =
+ (unsigned char *) (fragP->fr_fix + fragP->fr_literal);
+
+ /* Reverse the condition of the first branch. */
+ buffer[0] ^= 0x08;
+ /* Mask off all the displacement bits. */
+ buffer[0] &= 0x8f;
+ buffer[1] &= 0x07;
+ /* Now set the displacement bits so that we branch
+ around the unconditional branch. */
+ buffer[0] |= 0x30;
+
+ /* Now create the unconditional branch + fixup to the final
+ target. */
+ md_number_to_chars (buffer + 2, 0x00000780, 4);
+ fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, BFD_RELOC_UNUSED +
+ (int) fragP->fr_opcode + 1);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 6;
+ }
+ /* Out of range unconditional branch. Emit a jump. */
+ else if (fragP->fr_subtype == 3)
+ {
+ md_number_to_chars (fragP->fr_fix + fragP->fr_literal, 0x00000780, 4);
+ fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, BFD_RELOC_UNUSED +
+ (int) fragP->fr_opcode + 1);
+ fragP->fr_var = 0;
+ fragP->fr_fix += 4;
+ }
+ else
+ abort ();
+}
+
+valueT
+md_section_align (seg, addr)
+ asection * seg;
+ valueT addr;
+{
+ int align = bfd_get_section_alignment (stdoutput, seg);
+ return ((addr + (1 << align) - 1) & (-1 << align));
+}
+
+void
+md_begin ()
+{
+ char * prev_name = "";
+ register const struct v850_opcode * op;
+ flagword applicable;
+
+ if (strncmp (TARGET_CPU, "v850ea", 6) == 0)
+ {
+ if (machine == -1)
+ machine = bfd_mach_v850ea;
+
+ if (processor_mask == -1)
+ processor_mask = PROCESSOR_V850EA;
+ }
+ else if (strncmp (TARGET_CPU, "v850e", 5) == 0)
+ {
+ if (machine == -1)
+ machine = bfd_mach_v850e;
+
+ if (processor_mask == -1)
+ processor_mask = PROCESSOR_V850E;
+ }
+ else
+ if (strncmp (TARGET_CPU, "v850", 4) == 0)
+ {
+ if (machine == -1)
+ machine = 0;
+
+ if (processor_mask == -1)
+ processor_mask = PROCESSOR_V850;
+ }
+ else
+ /* xgettext:c-format */
+ as_bad (_("Unable to determine default target processor from string: %s"),
+ TARGET_CPU);
+
+ v850_hash = hash_new();
+
+ /* Insert unique names into hash table. The V850 instruction set
+ has many identical opcode names that have different opcodes based
+ on the operands. This hash table then provides a quick index to
+ the first opcode with a particular name in the opcode table. */
+
+ op = v850_opcodes;
+ while (op->name)
+ {
+ if (strcmp (prev_name, op->name))
+ {
+ prev_name = (char *) op->name;
+ hash_insert (v850_hash, op->name, (char *) op);
+ }
+ op++;
+ }
+
+ bfd_set_arch_mach (stdoutput, TARGET_ARCH, machine);
+
+ applicable = bfd_applicable_section_flags (stdoutput);
+
+ call_table_data_section = subseg_new (".call_table_data", 0);
+ bfd_set_section_flags (stdoutput, call_table_data_section,
+ applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC
+ | SEC_DATA | SEC_HAS_CONTENTS));
+
+ call_table_text_section = subseg_new (".call_table_text", 0);
+ bfd_set_section_flags (stdoutput, call_table_text_section,
+ applicable & (SEC_ALLOC | SEC_LOAD | SEC_READONLY
+ | SEC_CODE));
+
+ /* Restore text section as the current default. */
+ subseg_set (text_section, 0);
+}
+
+
+static bfd_reloc_code_real_type
+handle_ctoff (const struct v850_operand * operand)
+{
+ if (operand == NULL)
+ return BFD_RELOC_V850_CALLT_16_16_OFFSET;
+
+ if ( operand->bits != 6
+ || operand->shift != 0)
+ {
+ as_bad (_("ctoff() relocation used on an instruction which does not support it"));
+ return BFD_RELOC_64; /* Used to indicate an error condition. */
+ }
+
+ return BFD_RELOC_V850_CALLT_6_7_OFFSET;
+}
+
+static bfd_reloc_code_real_type
+handle_sdaoff (const struct v850_operand * operand)
+{
+ if (operand == NULL) return BFD_RELOC_V850_SDA_16_16_OFFSET;
+ if (operand->bits == 15 && operand->shift == 17) return BFD_RELOC_V850_SDA_15_16_OFFSET;
+ if (operand->bits == -1) return BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET;
+
+ if ( operand->bits != 16
+ || operand->shift != 16)
+ {
+ as_bad (_("sdaoff() relocation used on an instruction which does not support it"));
+ return BFD_RELOC_64; /* Used to indicate an error condition. */
+ }
+
+ return BFD_RELOC_V850_SDA_16_16_OFFSET;
+}
+
+static bfd_reloc_code_real_type
+handle_zdaoff (const struct v850_operand * operand)
+{
+ if (operand == NULL) return BFD_RELOC_V850_ZDA_16_16_OFFSET;
+ if (operand->bits == 15 && operand->shift == 17) return BFD_RELOC_V850_ZDA_15_16_OFFSET;
+ if (operand->bits == -1) return BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET;
+
+ if ( operand->bits != 16
+ || operand->shift != 16)
+ {
+ as_bad (_("zdaoff() relocation used on an instruction which does not support it"));
+ return BFD_RELOC_64; /* Used to indicate an error condition. */
+ }
+
+ return BFD_RELOC_V850_ZDA_16_16_OFFSET;
+}
+
+static bfd_reloc_code_real_type
+handle_tdaoff (const struct v850_operand * operand)
+{
+ if (operand == NULL) return BFD_RELOC_V850_TDA_7_7_OFFSET; /* data item, not an instruction. */
+ if (operand->bits == 6 && operand->shift == 1) return BFD_RELOC_V850_TDA_6_8_OFFSET; /* sld.w/sst.w, operand: D8_6 */
+ if (operand->bits == 4 && operand->insert != NULL) return BFD_RELOC_V850_TDA_4_5_OFFSET; /* sld.hu, operand: D5-4 */
+ if (operand->bits == 4 && operand->insert == NULL) return BFD_RELOC_V850_TDA_4_4_OFFSET; /* sld.bu, operand: D4 */
+ if (operand->bits == 16 && operand->shift == 16) return BFD_RELOC_V850_TDA_16_16_OFFSET; /* set1 & chums, operands: D16 */
+
+ if (operand->bits != 7)
+ {
+ as_bad (_("tdaoff() relocation used on an instruction which does not support it"));
+ return BFD_RELOC_64; /* Used to indicate an error condition. */
+ }
+
+ return operand->insert != NULL
+ ? BFD_RELOC_V850_TDA_7_8_OFFSET /* sld.h/sst.h, operand: D8_7 */
+ : BFD_RELOC_V850_TDA_7_7_OFFSET; /* sld.b/sst.b, opreand: D7 */
+}
+
+/* Warning: The code in this function relies upon the definitions
+ in the v850_operands[] array (defined in opcodes/v850-opc.c)
+ matching the hard coded values contained herein. */
+
+static bfd_reloc_code_real_type
+v850_reloc_prefix (const struct v850_operand * operand)
+{
+ boolean paren_skipped = false;
+
+
+ /* Skip leading opening parenthesis. */
+ if (* input_line_pointer == '(')
+ {
+ ++ input_line_pointer;
+ paren_skipped = true;
+ }
+
+#define CHECK_(name, reloc) \
+ if (strncmp (input_line_pointer, name##"(", strlen (name) + 1) == 0) \
+ { \
+ input_line_pointer += strlen (name); \
+ return reloc; \
+ }
+
+ CHECK_ ("hi0", BFD_RELOC_HI16);
+ CHECK_ ("hi", BFD_RELOC_HI16_S);
+ CHECK_ ("lo", BFD_RELOC_LO16);
+ CHECK_ ("sdaoff", handle_sdaoff (operand));
+ CHECK_ ("zdaoff", handle_zdaoff (operand));
+ CHECK_ ("tdaoff", handle_tdaoff (operand));
+ CHECK_ ("hilo", BFD_RELOC_32);
+ CHECK_ ("ctoff", handle_ctoff (operand));
+
+ /* Restore skipped parenthesis. */
+ if (paren_skipped)
+ -- input_line_pointer;
+
+ return BFD_RELOC_UNUSED;
+}
+
+/* Insert an operand value into an instruction. */
+
+static unsigned long
+v850_insert_operand (insn, operand, val, file, line, str)
+ unsigned long insn;
+ const struct v850_operand * operand;
+ offsetT val;
+ char * file;
+ unsigned int line;
+ char * str;
+{
+ if (operand->insert)
+ {
+ const char * message = NULL;
+
+ insn = operand->insert (insn, val, & message);
+ if (message != NULL)
+ {
+ if ((operand->flags & V850_OPERAND_SIGNED)
+ && ! warn_signed_overflows
+ && strstr (message, "out of range") != NULL)
+ {
+ /* skip warning... */
+ }
+ else if ((operand->flags & V850_OPERAND_SIGNED) == 0
+ && ! warn_unsigned_overflows
+ && strstr (message, "out of range") != NULL)
+ {
+ /* skip warning... */
+ }
+ else if (str)
+ {
+ if (file == (char *) NULL)
+ as_warn ("%s: %s", str, message);
+ else
+ as_warn_where (file, line, "%s: %s", str, message);
+ }
+ else
+ {
+ if (file == (char *) NULL)
+ as_warn (message);
+ else
+ as_warn_where (file, line, message);
+ }
+ }
+ }
+ else
+ {
+ if (operand->bits != 32)
+ {
+ long min, max;
+ offsetT test;
+
+ if ((operand->flags & V850_OPERAND_SIGNED) != 0)
+ {
+ if (! warn_signed_overflows)
+ max = (1 << operand->bits) - 1;
+ else
+ max = (1 << (operand->bits - 1)) - 1;
+
+ min = - (1 << (operand->bits - 1));
+ }
+ else
+ {
+ max = (1 << operand->bits) - 1;
+
+ if (! warn_unsigned_overflows)
+ min = - (1 << (operand->bits - 1));
+ else
+ min = 0;
+ }
+
+ if (val < (offsetT) min || val > (offsetT) max)
+ {
+ /* xgettext:c-format */
+ const char * err = _("operand out of range (%s not between %ld and %ld)");
+ char buf[100];
+
+ /* Restore min and mix to expected values for decimal ranges. */
+ if ((operand->flags & V850_OPERAND_SIGNED)
+ && ! warn_signed_overflows)
+ max = (1 << (operand->bits - 1)) - 1;
+
+ if (! (operand->flags & V850_OPERAND_SIGNED)
+ && ! warn_unsigned_overflows)
+ min = 0;
+
+ if (str)
+ {
+ sprintf (buf, "%s: ", str);
+
+ sprint_value (buf + strlen (buf), val);
+ }
+ else
+ sprint_value (buf, val);
+
+ if (file == (char *) NULL)
+ as_warn (err, buf, min, max);
+ else
+ as_warn_where (file, line, err, buf, min, max);
+ }
+ }
+
+ insn |= (((long) val & ((1 << operand->bits) - 1)) << operand->shift);
+ }
+
+ return insn;
+}
+
+
+static char copy_of_instruction [128];
+
+void
+md_assemble (str)
+ char * str;
+{
+ char * s;
+ char * start_of_operands;
+ struct v850_opcode * opcode;
+ struct v850_opcode * next_opcode;
+ const unsigned char * opindex_ptr;
+ int next_opindex;
+ int relaxable;
+ unsigned long insn;
+ unsigned long insn_size;
+ char * f;
+ int i;
+ int match;
+ boolean extra_data_after_insn = false;
+ unsigned extra_data_len;
+ unsigned long extra_data;
+ char * saved_input_line_pointer;
+
+
+ strncpy (copy_of_instruction, str, sizeof (copy_of_instruction) - 1);
+
+ /* Get the opcode. */
+ for (s = str; *s != '\0' && ! isspace (*s); s++)
+ continue;
+
+ if (*s != '\0')
+ *s++ = '\0';
+
+ /* find the first opcode with the proper name */
+ opcode = (struct v850_opcode *) hash_find (v850_hash, str);
+ if (opcode == NULL)
+ {
+ /* xgettext:c-format */
+ as_bad (_("Unrecognized opcode: `%s'"), str);
+ ignore_rest_of_line ();
+ return;
+ }
+
+ str = s;
+ while (isspace (* str))
+ ++ str;
+
+ start_of_operands = str;
+
+ saved_input_line_pointer = input_line_pointer;
+
+ for (;;)
+ {
+ const char * errmsg = NULL;
+
+ match = 0;
+
+ if ((opcode->processors & processor_mask) == 0)
+ {
+ errmsg = _("Target processor does not support this instruction.");
+ goto error;
+ }
+
+ relaxable = 0;
+ fc = 0;
+ next_opindex = 0;
+ insn = opcode->opcode;
+ extra_data_after_insn = false;
+
+ input_line_pointer = str = start_of_operands;
+
+ for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr ++)
+ {
+ const struct v850_operand * operand;
+ char * hold;
+ expressionS ex;
+ bfd_reloc_code_real_type reloc;
+
+ if (next_opindex == 0)
+ {
+ operand = & v850_operands[ * opindex_ptr ];
+ }
+ else
+ {
+ operand = & v850_operands[ next_opindex ];
+ next_opindex = 0;
+ }
+
+ errmsg = NULL;
+
+ while (*str == ' ' || *str == ',' || *str == '[' || *str == ']')
+ ++ str;
+
+ if (operand->flags & V850_OPERAND_RELAX)
+ relaxable = 1;
+
+ /* Gather the operand. */
+ hold = input_line_pointer;
+ input_line_pointer = str;
+
+ /* lo(), hi(), hi0(), etc... */
+ if ((reloc = v850_reloc_prefix (operand)) != BFD_RELOC_UNUSED)
+ {
+ /* This is a fake reloc, used to indicate an error condition. */
+ if (reloc == BFD_RELOC_64)
+ {
+ match = 1;
+ goto error;
+ }
+
+ expression (& ex);
+
+ if (ex.X_op == O_constant)
+ {
+ switch (reloc)
+ {
+ case BFD_RELOC_V850_ZDA_16_16_OFFSET:
+ /* To cope with "not1 7, zdaoff(0xfffff006)[r0]"
+ and the like. */
+ /* Fall through. */
+
+ case BFD_RELOC_LO16:
+ {
+ /* Truncate, then sign extend the value. */
+ ex.X_add_number = SEXT16 (ex.X_add_number);
+ break;
+ }
+
+ case BFD_RELOC_HI16:
+ {
+ /* Truncate, then sign extend the value. */
+ ex.X_add_number = SEXT16 (ex.X_add_number >> 16);
+ break;
+ }
+
+ case BFD_RELOC_HI16_S:
+ {
+ /* Truncate, then sign extend the value. */
+ int temp = (ex.X_add_number >> 16) & 0xffff;
+
+ temp += (ex.X_add_number >> 15) & 1;
+
+ ex.X_add_number = SEXT16 (temp);
+ break;
+ }
+
+ case BFD_RELOC_32:
+ if ((operand->flags & V850E_IMMEDIATE32) == 0)
+ {
+ errmsg = _("immediate operand is too large");
+ goto error;
+ }
+
+ extra_data_after_insn = true;
+ extra_data_len = 4;
+ extra_data = ex.X_add_number;
+ ex.X_add_number = 0;
+ break;
+
+ default:
+ fprintf (stderr, "reloc: %d\n", reloc);
+ as_bad (_("AAARG -> unhandled constant reloc"));
+ break;
+ }
+
+ if (fc > MAX_INSN_FIXUPS)
+ as_fatal (_("too many fixups"));
+
+ fixups[ fc ].exp = ex;
+ fixups[ fc ].opindex = * opindex_ptr;
+ fixups[ fc ].reloc = reloc;
+ fc++;
+ }
+ else
+ {
+ if (reloc == BFD_RELOC_32)
+ {
+ if ((operand->flags & V850E_IMMEDIATE32) == 0)
+ {
+ errmsg = _("immediate operand is too large");
+ goto error;
+ }
+
+ extra_data_after_insn = true;
+ extra_data_len = 4;
+ extra_data = ex.X_add_number;
+ }
+
+ if (fc > MAX_INSN_FIXUPS)
+ as_fatal (_("too many fixups"));
+
+ fixups[ fc ].exp = ex;
+ fixups[ fc ].opindex = * opindex_ptr;
+ fixups[ fc ].reloc = reloc;
+ fc++;
+ }
+ }
+ else
+ {
+ errmsg = NULL;
+
+ if ((operand->flags & V850_OPERAND_REG) != 0)
+ {
+ if (!register_name (& ex))
+ {
+ errmsg = _("invalid register name");
+ }
+ else if ((operand->flags & V850_NOT_R0)
+ && ex.X_add_number == 0)
+ {
+ errmsg = _("register r0 cannot be used here");
+
+ /* Force an error message to be generated by
+ skipping over any following potential matches
+ for this opcode. */
+ opcode += 3;
+ }
+ }
+ else if ((operand->flags & V850_OPERAND_SRG) != 0)
+ {
+ if (!system_register_name (& ex, true, false))
+ {
+ errmsg = _("invalid system register name");
+ }
+ }
+ else if ((operand->flags & V850_OPERAND_EP) != 0)
+ {
+ char * start = input_line_pointer;
+ char c = get_symbol_end ();
+
+ if (strcmp (start, "ep") != 0 && strcmp (start, "r30") != 0)
+ {
+ /* Put things back the way we found them. */
+ *input_line_pointer = c;
+ input_line_pointer = start;
+ errmsg = _("expected EP register");
+ goto error;
+ }
+
+ *input_line_pointer = c;
+ str = input_line_pointer;
+ input_line_pointer = hold;
+
+ while (*str == ' ' || *str == ',' || *str == '[' || *str == ']')
+ ++ str;
+ continue;
+ }
+ else if ((operand->flags & V850_OPERAND_CC) != 0)
+ {
+ if (!cc_name (& ex))
+ {
+ errmsg = _("invalid condition code name");
+ }
+ }
+ else if (operand->flags & V850E_PUSH_POP)
+ {
+ errmsg = parse_register_list (& insn, operand);
+
+ /* The parse_register_list() function has already done
+ everything, so fake a dummy expression. */
+ ex.X_op = O_constant;
+ ex.X_add_number = 0;
+ }
+ else if (operand->flags & V850E_IMMEDIATE16)
+ {
+ expression (& ex);
+
+ if (ex.X_op != O_constant)
+ errmsg = _("constant expression expected");
+ else if (ex.X_add_number & 0xffff0000)
+ {
+ if (ex.X_add_number & 0xffff)
+ errmsg = _("constant too big to fit into instruction");
+ else if ((insn & 0x001fffc0) == 0x00130780)
+ ex.X_add_number >>= 16;
+ else
+ errmsg = _("constant too big to fit into instruction");
+ }
+
+ extra_data_after_insn = true;
+ extra_data_len = 2;
+ extra_data = ex.X_add_number;
+ ex.X_add_number = 0;
+ }
+ else if (operand->flags & V850E_IMMEDIATE32)
+ {
+ expression (& ex);
+
+ if (ex.X_op != O_constant)
+ errmsg = _("constant expression expected");
+
+ extra_data_after_insn = true;
+ extra_data_len = 4;
+ extra_data = ex.X_add_number;
+ ex.X_add_number = 0;
+ }
+ else if (register_name (& ex)
+ && (operand->flags & V850_OPERAND_REG) == 0)
+ {
+ char c;
+ int exists = 0;
+
+ /* It is possible that an alias has been defined that
+ matches a register name. For example the code may
+ include a ".set ZERO, 0" directive, which matches
+ the register name "zero". Attempt to reparse the
+ field as an expression, and only complain if we
+ cannot generate a constant. */
+
+ input_line_pointer = str;
+
+ c = get_symbol_end ();
+
+ if (symbol_find (str) != NULL)
+ exists = 1;
+
+ * input_line_pointer = c;
+ input_line_pointer = str;
+
+ expression (& ex);
+
+ if (ex.X_op != O_constant)
+ {
+ /* If this register is actually occuring too early on
+ the parsing of the instruction, (because another
+ field is missing) then report this. */
+ if (opindex_ptr[1] != 0
+ && (v850_operands [opindex_ptr [1]].flags & V850_OPERAND_REG))
+ errmsg = _("syntax error: value is missing before the register name");
+ else
+ errmsg = _("syntax error: register not expected");
+
+ /* If we created a symbol in the process of this test then
+ delete it now, so that it will not be output with the real
+ symbols... */
+ if (exists == 0
+ && ex.X_op == O_symbol)
+ symbol_remove (ex.X_add_symbol,
+ & symbol_rootP, & symbol_lastP);
+ }
+ }
+ else if (system_register_name (& ex, false, false)
+ && (operand->flags & V850_OPERAND_SRG) == 0)
+ {
+ errmsg = _("syntax error: system register not expected");
+ }
+ else if (cc_name (&ex)
+ && (operand->flags & V850_OPERAND_CC) == 0)
+ {
+ errmsg = _("syntax error: condition code not expected");
+ }
+ else
+ {
+ expression (& ex);
+ /* Special case:
+ If we are assembling a MOV instruction (or a CALLT.... :-)
+ and the immediate value does not fit into the bits
+ available then create a fake error so that the next MOV
+ instruction will be selected. This one has a 32 bit
+ immediate field. */
+
+ if (((insn & 0x07e0) == 0x0200)
+ && ex.X_op == O_constant
+ && (ex.X_add_number < (- (1 << (operand->bits - 1)))
+ || ex.X_add_number > ((1 << operand->bits) - 1)))
+ errmsg = _("immediate operand is too large");
+ }
+
+ if (errmsg)
+ goto error;
+
+/* fprintf (stderr, " insn: %x, operand %d, op: %d, add_number: %d\n",
+ insn, opindex_ptr - opcode->operands, ex.X_op, ex.X_add_number); */
+
+ switch (ex.X_op)
+ {
+ case O_illegal:
+ errmsg = _("illegal operand");
+ goto error;
+ case O_absent:
+ errmsg = _("missing operand");
+ goto error;
+ case O_register:
+ if ((operand->flags & (V850_OPERAND_REG | V850_OPERAND_SRG)) == 0)
+ {
+ errmsg = _("invalid operand");
+ goto error;
+ }
+ insn = v850_insert_operand (insn, operand, ex.X_add_number,
+ (char *) NULL, 0,
+ copy_of_instruction);
+ break;
+
+ case O_constant:
+ insn = v850_insert_operand (insn, operand, ex.X_add_number,
+ (char *) NULL, 0,
+ copy_of_instruction);
+ break;
+
+ default:
+ /* We need to generate a fixup for this expression. */
+ if (fc >= MAX_INSN_FIXUPS)
+ as_fatal (_("too many fixups"));
+
+ fixups[ fc ].exp = ex;
+ fixups[ fc ].opindex = * opindex_ptr;
+ fixups[ fc ].reloc = BFD_RELOC_UNUSED;
+ ++fc;
+ break;
+ }
+ }
+
+ str = input_line_pointer;
+ input_line_pointer = hold;
+
+ while (*str == ' ' || *str == ',' || *str == '[' || *str == ']'
+ || *str == ')')
+ ++str;
+ }
+ match = 1;
+
+ error:
+ if (match == 0)
+ {
+ next_opcode = opcode + 1;
+ if (next_opcode->name != NULL
+ && strcmp (next_opcode->name, opcode->name) == 0)
+ {
+ opcode = next_opcode;
+
+ /* Skip versions that are not supported by the target
+ processor. */
+ if ((opcode->processors & processor_mask) == 0)
+ goto error;
+
+ continue;
+ }
+
+ as_bad ("%s: %s", copy_of_instruction, errmsg);
+
+ if (* input_line_pointer == ']')
+ ++ input_line_pointer;
+
+ ignore_rest_of_line ();
+ input_line_pointer = saved_input_line_pointer;
+ return;
+ }
+ break;
+ }
+
+ while (isspace (*str))
+ ++str;
+
+ if (*str != '\0')
+ /* xgettext:c-format */
+ as_bad (_("junk at end of line: `%s'"), str);
+
+ input_line_pointer = str;
+
+ /* Write out the instruction. */
+
+ if (relaxable && fc > 0)
+ {
+ insn_size = 2;
+ fc = 0;
+
+ if (!strcmp (opcode->name, "br"))
+ {
+ f = frag_var (rs_machine_dependent, 4, 2, 2,
+ fixups[0].exp.X_add_symbol,
+ fixups[0].exp.X_add_number,
+ (char *)fixups[0].opindex);
+ md_number_to_chars (f, insn, insn_size);
+ md_number_to_chars (f + 2, 0, 2);
+ }
+ else
+ {
+ f = frag_var (rs_machine_dependent, 6, 4, 0,
+ fixups[0].exp.X_add_symbol,
+ fixups[0].exp.X_add_number,
+ (char *)fixups[0].opindex);
+ md_number_to_chars (f, insn, insn_size);
+ md_number_to_chars (f + 2, 0, 4);
+ }
+ }
+ else
+ {
+ /* Four byte insns have an opcode with the two high bits on. */
+ if ((insn & 0x0600) == 0x0600)
+ insn_size = 4;
+ else
+ insn_size = 2;
+
+ /* Special case: 32 bit MOV */
+ if ((insn & 0xffe0) == 0x0620)
+ insn_size = 2;
+
+ f = frag_more (insn_size);
+
+ md_number_to_chars (f, insn, insn_size);
+
+ if (extra_data_after_insn)
+ {
+ f = frag_more (extra_data_len);
+
+ md_number_to_chars (f, extra_data, extra_data_len);
+
+ extra_data_after_insn = false;
+ }
+ }
+
+ /* Create any fixups. At this point we do not use a
+ bfd_reloc_code_real_type, but instead just use the
+ BFD_RELOC_UNUSED plus the operand index. This lets us easily
+ handle fixups for any operand type, although that is admittedly
+ not a very exciting feature. We pick a BFD reloc type in
+ md_apply_fix. */
+ for (i = 0; i < fc; i++)
+ {
+ const struct v850_operand * operand;
+ bfd_reloc_code_real_type reloc;
+
+ operand = & v850_operands[ fixups[i].opindex ];
+
+ reloc = fixups[i].reloc;
+
+ if (reloc != BFD_RELOC_UNUSED)
+ {
+ reloc_howto_type * reloc_howto = bfd_reloc_type_lookup (stdoutput,
+ reloc);
+ int size;
+ int address;
+ fixS * fixP;
+
+ if (!reloc_howto)
+ abort();
+
+ size = bfd_get_reloc_size (reloc_howto);
+
+ /* XXX This will abort on an R_V850_8 reloc -
+ is this reloc actually used ? */
+ if (size != 2 && size != 4)
+ abort ();
+
+ address = (f - frag_now->fr_literal) + insn_size - size;
+
+ if (reloc == BFD_RELOC_32)
+ {
+ address += 2;
+ }
+
+ fixP = fix_new_exp (frag_now, address, size,
+ & fixups[i].exp,
+ reloc_howto->pc_relative,
+ reloc);
+
+ switch (reloc)
+ {
+ case BFD_RELOC_LO16:
+ case BFD_RELOC_HI16:
+ case BFD_RELOC_HI16_S:
+ fixP->fx_no_overflow = 1;
+ break;
+ }
+ }
+ else
+ {
+ fix_new_exp (
+ frag_now,
+ f - frag_now->fr_literal, 4,
+ & fixups[i].exp,
+ 1 /* FIXME: V850_OPERAND_RELATIVE ??? */,
+ (bfd_reloc_code_real_type) (fixups[i].opindex
+ + (int) BFD_RELOC_UNUSED)
+ );
+ }
+ }
+
+ input_line_pointer = saved_input_line_pointer;
+}
+
+
+/* If while processing a fixup, a reloc really needs to be created */
+/* then it is done here. */
+
+arelent *
+tc_gen_reloc (seg, fixp)
+ asection * seg;
+ fixS * fixp;
+{
+ arelent * reloc;
+
+ reloc = (arelent *) xmalloc (sizeof (arelent));
+ reloc->sym_ptr_ptr = & fixp->fx_addsy->bsym;
+ reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
+
+ if (reloc->howto == (reloc_howto_type *) NULL)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ /* xgettext:c-format */
+ _("reloc %d not supported by object file format"),
+ (int) fixp->fx_r_type);
+
+ xfree (reloc);
+
+ return NULL;
+ }
+
+ if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
+ || fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT)
+ reloc->addend = fixp->fx_offset;
+ else
+ reloc->addend = fixp->fx_addnumber;
+
+ return reloc;
+}
+
+/* Assume everything will fit in two bytes, then expand as necessary. */
+int
+md_estimate_size_before_relax (fragp, seg)
+ fragS * fragp;
+ asection * seg;
+{
+ if (fragp->fr_subtype == 0)
+ fragp->fr_var = 4;
+ else if (fragp->fr_subtype == 2)
+ fragp->fr_var = 2;
+ else
+ abort ();
+ return 2;
+}
+
+long
+v850_pcrel_from_section (fixp, section)
+ fixS * fixp;
+ segT section;
+{
+ /* If the symbol is undefined, or in a section other than our own,
+ then let the linker figure it out. */
+ if (fixp->fx_addsy != (symbolS *) NULL
+ && (! S_IS_DEFINED (fixp->fx_addsy)
+ || (S_GET_SEGMENT (fixp->fx_addsy) != section)))
+ {
+ /* The symbol is undefined/not in our section.
+ Let the linker figure it out. */
+ return 0;
+ }
+
+ return fixp->fx_frag->fr_address + fixp->fx_where;
+}
+
+int
+md_apply_fix3 (fixp, valuep, seg)
+ fixS * fixp;
+ valueT * valuep;
+ segT seg;
+{
+ valueT value;
+ char * where;
+
+ if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ {
+ fixp->fx_done = 0;
+ return 1;
+ }
+
+ if (fixp->fx_addsy == (symbolS *) NULL)
+ {
+ value = * valuep;
+ fixp->fx_done = 1;
+ }
+ else if (fixp->fx_pcrel)
+ value = * valuep;
+ else
+ {
+ value = fixp->fx_offset;
+ if (fixp->fx_subsy != (symbolS *) NULL)
+ {
+ if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
+ value -= S_GET_VALUE (fixp->fx_subsy);
+ else
+ {
+ /* We don't actually support subtracting a symbol. */
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("expression too complex"));
+ }
+ }
+ }
+
+ if ((int) fixp->fx_r_type >= (int) BFD_RELOC_UNUSED)
+ {
+ int opindex;
+ const struct v850_operand * operand;
+ unsigned long insn;
+
+ opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
+ operand = & v850_operands[ opindex ];
+
+ /* Fetch the instruction, insert the fully resolved operand
+ value, and stuff the instruction back again.
+
+ Note the instruction has been stored in little endian
+ format! */
+ where = fixp->fx_frag->fr_literal + fixp->fx_where;
+
+ insn = bfd_getl32 ((unsigned char *) where);
+ insn = v850_insert_operand (insn, operand, (offsetT) value,
+ fixp->fx_file, fixp->fx_line, NULL);
+ bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
+
+ if (fixp->fx_done)
+ {
+ /* Nothing else to do here. */
+ return 1;
+ }
+
+ /* Determine a BFD reloc value based on the operand information.
+ We are only prepared to turn a few of the operands into relocs. */
+
+ if (operand->bits == 22)
+ fixp->fx_r_type = BFD_RELOC_V850_22_PCREL;
+ else if (operand->bits == 9)
+ fixp->fx_r_type = BFD_RELOC_V850_9_PCREL;
+ else
+ {
+ /* fprintf (stderr, "bits: %d, insn: %x\n", operand->bits, insn); */
+
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("unresolved expression that must be resolved"));
+ fixp->fx_done = 1;
+ return 1;
+ }
+ }
+ else if (fixp->fx_done)
+ {
+ /* We still have to insert the value into memory! */
+ where = fixp->fx_frag->fr_literal + fixp->fx_where;
+
+ if (fixp->fx_size == 1)
+ * where = value & 0xff;
+ else if (fixp->fx_size == 2)
+ bfd_putl16 (value & 0xffff, (unsigned char *) where);
+ else if (fixp->fx_size == 4)
+ bfd_putl32 (value, (unsigned char *) where);
+ }
+
+ fixp->fx_addnumber = value;
+ return 1;
+}
+
+
+/* Parse a cons expression. We have to handle hi(), lo(), etc
+ on the v850. */
+void
+parse_cons_expression_v850 (exp)
+ expressionS *exp;
+{
+ /* See if there's a reloc prefix like hi() we have to handle. */
+ hold_cons_reloc = v850_reloc_prefix (NULL);
+
+ /* Do normal expression parsing. */
+ expression (exp);
+}
+
+/* Create a fixup for a cons expression. If parse_cons_expression_v850
+ found a reloc prefix, then we use that reloc, else we choose an
+ appropriate one based on the size of the expression. */
+void
+cons_fix_new_v850 (frag, where, size, exp)
+ fragS *frag;
+ int where;
+ int size;
+ expressionS *exp;
+{
+ if (hold_cons_reloc == BFD_RELOC_UNUSED)
+ {
+ if (size == 4)
+ hold_cons_reloc = BFD_RELOC_32;
+ if (size == 2)
+ hold_cons_reloc = BFD_RELOC_16;
+ if (size == 1)
+ hold_cons_reloc = BFD_RELOC_8;
+ }
+
+ if (exp != NULL)
+ fix_new_exp (frag, where, size, exp, 0, hold_cons_reloc);
+ else
+ fix_new (frag, where, size, NULL, 0, 0, hold_cons_reloc);
+}
+boolean
+v850_fix_adjustable (fixP)
+ fixS *fixP;
+{
+
+ if (fixP->fx_addsy == NULL)
+ return 1;
+
+ /* Prevent all adjustments to global symbols. */
+ if (S_IS_EXTERN (fixP->fx_addsy))
+ return 0;
+ if (S_IS_WEAK (fixP->fx_addsy))
+ return 0;
+ /* Don't adjust function names */
+ if (S_IS_FUNCTION (fixP->fx_addsy))
+ return 0;
+
+ /* We need the symbol name for the VTABLE entries */
+ if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ return 0;
+
+ return 1;
+}
+
+int
+v850_force_relocation (fixp)
+ struct fix *fixp;
+{
+ if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ return 1;
+
+ return 0;
+}
diff --git a/gas/config/tc-v850.h b/gas/config/tc-v850.h
new file mode 100644
index 0000000000..fad4d1cf85
--- /dev/null
+++ b/gas/config/tc-v850.h
@@ -0,0 +1,85 @@
+/* tc-v850.h -- Header file for tc-v850.c.
+ Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#define TC_V850
+
+#include <elf/v850.h>
+
+#define TARGET_BYTES_BIG_ENDIAN 0
+
+#ifndef BFD_ASSEMBLER
+ #error V850 support requires BFD_ASSEMBLER
+#endif
+
+/* The target BFD architecture. */
+#define TARGET_ARCH bfd_arch_v850
+
+/* The target BFD format. */
+#define TARGET_FORMAT "elf32-v850"
+
+#define MD_APPLY_FIX3
+#define md_operand(x)
+
+#define obj_fix_adjustable(fixP) v850_fix_adjustable(fixP)
+#define TC_FORCE_RELOCATION(fixp) v850_force_relocation(fixp)
+extern int v850_force_relocation PARAMS ((struct fix *));
+
+/* Permit temporary numeric labels. */
+#define LOCAL_LABELS_FB 1
+
+#define DIFF_EXPR_OK /* foo-. gets turned into PC relative relocs */
+
+/* We don't need to handle .word strangely. */
+#define WORKING_DOT_WORD
+
+#define md_number_to_chars number_to_chars_littleendian
+
+/* We need to handle lo(), hi(), etc etc in .hword, .word, etc
+ directives, so we have to parse "cons" expressions ourselves. */
+#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_cons_expression_v850 (EXP)
+#define TC_CONS_FIX_NEW cons_fix_new_v850
+extern const struct relax_type md_relax_table[];
+#define TC_GENERIC_RELAX_TABLE md_relax_table
+
+
+/* This section must be in the small data area (pointed to by GP). */
+#define SHF_V850_GPREL 0x10000000
+/* This section must be in the tiny data area (pointed to by EP). */
+#define SHF_V850_EPREL 0x20000000
+/* This section must be in the zero data area (pointed to by R0). */
+#define SHF_V850_R0REL 0x40000000
+
+#define ELF_TC_SPECIAL_SECTIONS \
+ { ".sdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_GPREL }, \
+ { ".rosdata", SHT_PROGBITS, SHF_ALLOC + SHF_V850_GPREL }, \
+ { ".sbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_GPREL }, \
+ { ".scommon", SHT_V850_SCOMMON, SHF_ALLOC + SHF_WRITE + SHF_V850_GPREL }, \
+ { ".tdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_EPREL }, \
+ { ".tbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_EPREL }, \
+ { ".tcommon", SHT_V850_TCOMMON, SHF_ALLOC + SHF_WRITE + SHF_V850_R0REL }, \
+ { ".zdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_R0REL }, \
+ { ".rozdata", SHT_PROGBITS, SHF_ALLOC + SHF_V850_R0REL }, \
+ { ".zbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_R0REL }, \
+ { ".zcommon", SHT_V850_ZCOMMON, SHF_ALLOC + SHF_WRITE + SHF_V850_R0REL }, \
+ { ".call_table_data", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, \
+ { ".call_table_text", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_EXECINSTR },
+
+#define MD_PCREL_FROM_SECTION(fixP,section) v850_pcrel_from_section (fixP, section)
+extern long v850_pcrel_from_section ();
diff --git a/gas/config/tc-vax.c b/gas/config/tc-vax.c
new file mode 100644
index 0000000000..24e4a9b229
--- /dev/null
+++ b/gas/config/tc-vax.c
@@ -0,0 +1,3242 @@
+/* tc-vax.c - vax-specific -
+ Copyright (C) 1987, 91, 92, 93, 94, 95, 1998 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include "as.h"
+
+#include "vax-inst.h"
+#include "obstack.h" /* For FRAG_APPEND_1_CHAR macro in "frags.h" */
+
+/* These chars start a comment anywhere in a source file (except inside
+ another comment */
+const char comment_chars[] = "#";
+
+/* These chars only start a comment at the beginning of a line. */
+/* Note that for the VAX the are the same as comment_chars above. */
+const char line_comment_chars[] = "#";
+
+const char line_separator_chars[] = "";
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* as in 0f123.456 */
+/* or 0H1.234E-12 (see exp chars above) */
+const char FLT_CHARS[] = "dDfFgGhH";
+
+/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
+ changed in read.c . Ideally it shouldn't have to know about it at all,
+ but nothing is ideal around here. */
+
+/* Hold details of an operand expression */
+static expressionS exp_of_operand[VIT_MAX_OPERANDS];
+static segT seg_of_operand[VIT_MAX_OPERANDS];
+
+/* A vax instruction after decoding. */
+static struct vit v;
+
+/* Hold details of big operands. */
+LITTLENUM_TYPE big_operand_bits[VIT_MAX_OPERANDS][SIZE_OF_LARGE_NUMBER];
+FLONUM_TYPE float_operand[VIT_MAX_OPERANDS];
+/* Above is made to point into big_operand_bits by md_begin(). */
+
+int flag_hash_long_names; /* -+ */
+int flag_one; /* -1 */
+int flag_show_after_trunc; /* -H */
+int flag_no_hash_mixed_case; /* -h NUM */
+
+/*
+ * For VAX, relative addresses of "just the right length" are easy.
+ * The branch displacement is always the last operand, even in
+ * synthetic instructions.
+ * For VAX, we encode the relax_substateTs (in e.g. fr_substate) as:
+ *
+ * 4 3 2 1 0 bit number
+ * ---/ /--+-------+-------+-------+-------+-------+
+ * | what state ? | how long ? |
+ * ---/ /--+-------+-------+-------+-------+-------+
+ *
+ * The "how long" bits are 00=byte, 01=word, 10=long.
+ * This is a Un*x convention.
+ * Not all lengths are legit for a given value of (what state).
+ * The "how long" refers merely to the displacement length.
+ * The address usually has some constant bytes in it as well.
+ *
+
+ groups for VAX address relaxing.
+
+ 1. "foo" pc-relative.
+ length of byte, word, long
+
+ 2a. J<cond> where <cond> is a simple flag test.
+ length of byte, word, long.
+ VAX opcodes are: (Hex)
+ bneq/bnequ 12
+ beql/beqlu 13
+ bgtr 14
+ bleq 15
+ bgeq 18
+ blss 19
+ bgtru 1a
+ blequ 1b
+ bvc 1c
+ bvs 1d
+ bgequ/bcc 1e
+ blssu/bcs 1f
+ Always, you complement 0th bit to reverse condition.
+ Always, 1-byte opcode, then 1-byte displacement.
+
+ 2b. J<cond> where cond tests a memory bit.
+ length of byte, word, long.
+ Vax opcodes are: (Hex)
+ bbs e0
+ bbc e1
+ bbss e2
+ bbcs e3
+ bbsc e4
+ bbcc e5
+ bbssi e6
+ bbcci e7
+ Always, you complement 0th bit to reverse condition.
+ Always, 1-byte opcde, longword-address, byte-address, 1-byte-displacement
+
+ 2c. J<cond> where cond tests low-order memory bit
+ length of byte,word,long.
+ Vax opcodes are: (Hex)
+ blbs e8
+ blbc e9
+ Always, you complement 0th bit to reverse condition.
+ Always, 1-byte opcode, longword-address, 1-byte displacement.
+
+ 3. Jbs/Jbr.
+ length of byte,word,long.
+ Vax opcodes are: (Hex)
+ bsbb 10
+ brb 11
+ These are like (2) but there is no condition to reverse.
+ Always, 1 byte opcode, then displacement/absolute.
+
+ 4a. JacbX
+ length of word, long.
+ Vax opcodes are: (Hex)
+ acbw 3d
+ acbf 4f
+ acbd 6f
+ abcb 9d
+ acbl f1
+ acbg 4ffd
+ acbh 6ffd
+ Always, we cannot reverse the sense of the branch; we have a word
+ displacement.
+ The double-byte op-codes don't hurt: we never want to modify the
+ opcode, so we don't care how many bytes are between the opcode and
+ the operand.
+
+ 4b. JXobXXX
+ length of long, long, byte.
+ Vax opcodes are: (Hex)
+ aoblss f2
+ aobleq f3
+ sobgeq f4
+ sobgtr f5
+ Always, we cannot reverse the sense of the branch; we have a byte
+ displacement.
+
+ The only time we need to modify the opcode is for class 2 instructions.
+ After relax() we may complement the lowest order bit of such instruction
+ to reverse sense of branch.
+
+ For class 2 instructions, we store context of "where is the opcode literal".
+ We can change an opcode's lowest order bit without breaking anything else.
+
+ We sometimes store context in the operand literal. This way we can figure out
+ after relax() what the original addressing mode was.
+ */
+
+/* These displacements are relative to the start address of the
+ displacement. The first letter is Byte, Word. 2nd letter is
+ Forward, Backward. */
+#define BF (1+ 127)
+#define BB (1+-128)
+#define WF (2+ 32767)
+#define WB (2+-32768)
+/* Dont need LF, LB because they always reach. [They are coded as 0.] */
+
+
+#define C(a,b) ENCODE_RELAX(a,b)
+/* This macro has no side-effects. */
+#define ENCODE_RELAX(what,length) (((what) << 2) + (length))
+
+const relax_typeS md_relax_table[] =
+{
+ {1, 1, 0, 0}, /* error sentinel 0,0 */
+ {1, 1, 0, 0}, /* unused 0,1 */
+ {1, 1, 0, 0}, /* unused 0,2 */
+ {1, 1, 0, 0}, /* unused 0,3 */
+ {BF + 1, BB + 1, 2, C (1, 1)},/* B^"foo" 1,0 */
+ {WF + 1, WB + 1, 3, C (1, 2)},/* W^"foo" 1,1 */
+ {0, 0, 5, 0}, /* L^"foo" 1,2 */
+ {1, 1, 0, 0}, /* unused 1,3 */
+ {BF, BB, 1, C (2, 1)}, /* b<cond> B^"foo" 2,0 */
+ {WF + 2, WB + 2, 4, C (2, 2)},/* br.+? brw X 2,1 */
+ {0, 0, 7, 0}, /* br.+? jmp X 2,2 */
+ {1, 1, 0, 0}, /* unused 2,3 */
+ {BF, BB, 1, C (3, 1)}, /* brb B^foo 3,0 */
+ {WF, WB, 2, C (3, 2)}, /* brw W^foo 3,1 */
+ {0, 0, 5, 0}, /* Jmp L^foo 3,2 */
+ {1, 1, 0, 0}, /* unused 3,3 */
+ {1, 1, 0, 0}, /* unused 4,0 */
+ {WF, WB, 2, C (4, 2)}, /* acb_ ^Wfoo 4,1 */
+ {0, 0, 10, 0}, /* acb_,br,jmp L^foo4,2 */
+ {1, 1, 0, 0}, /* unused 4,3 */
+ {BF, BB, 1, C (5, 1)}, /* Xob___,,foo 5,0 */
+ {WF + 4, WB + 4, 6, C (5, 2)},/* Xob.+2,brb.+3,brw5,1 */
+ {0, 0, 9, 0}, /* Xob.+2,brb.+6,jmp5,2 */
+};
+
+#undef C
+#undef BF
+#undef BB
+#undef WF
+#undef WB
+
+void float_cons ();
+
+const pseudo_typeS md_pseudo_table[] =
+{
+ {"dfloat", float_cons, 'd'},
+ {"ffloat", float_cons, 'f'},
+ {"gfloat", float_cons, 'g'},
+ {"hfloat", float_cons, 'h'},
+ {0},
+};
+
+#define STATE_PC_RELATIVE (1)
+#define STATE_CONDITIONAL_BRANCH (2)
+#define STATE_ALWAYS_BRANCH (3) /* includes BSB... */
+#define STATE_COMPLEX_BRANCH (4)
+#define STATE_COMPLEX_HOP (5)
+
+#define STATE_BYTE (0)
+#define STATE_WORD (1)
+#define STATE_LONG (2)
+#define STATE_UNDF (3) /* Symbol undefined in pass1 */
+
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+int flonum_gen2vax PARAMS ((char format_letter, FLONUM_TYPE * f,
+ LITTLENUM_TYPE * words));
+static const char *vip_begin PARAMS ((int, const char *, const char *,
+ const char *));
+static void vip_op_defaults PARAMS ((const char *, const char *, const char *));
+static void vip_op PARAMS ((char *, struct vop *));
+static void vip PARAMS ((struct vit *, char *));
+
+void
+md_begin ()
+{
+ const char *errtxt;
+ FLONUM_TYPE *fP;
+ int i;
+
+ if ((errtxt = vip_begin (1, "$", "*", "`")) != 0)
+ {
+ as_fatal (_("VIP_BEGIN error:%s"), errtxt);
+ }
+
+ for (i = 0, fP = float_operand;
+ fP < float_operand + VIT_MAX_OPERANDS;
+ i++, fP++)
+ {
+ fP->low = &big_operand_bits[i][0];
+ fP->high = &big_operand_bits[i][SIZE_OF_LARGE_NUMBER - 1];
+ }
+}
+
+void
+md_number_to_chars (con, value, nbytes)
+ char con[];
+ valueT value;
+ int nbytes;
+{
+ number_to_chars_littleendian (con, value, nbytes);
+}
+
+/* Fix up some data or instructions after we find out the value of a symbol
+ that they reference. */
+
+void /* Knows about order of bytes in address. */
+md_apply_fix (fixP, value)
+ fixS *fixP;
+ long value;
+{
+ number_to_chars_littleendian (fixP->fx_where + fixP->fx_frag->fr_literal,
+ (valueT) value, fixP->fx_size);
+}
+
+long
+md_chars_to_number (con, nbytes)
+ unsigned char con[]; /* Low order byte 1st. */
+ int nbytes; /* Number of bytes in the input. */
+{
+ long retval;
+ for (retval = 0, con += nbytes - 1; nbytes--; con--)
+ {
+ retval <<= BITS_PER_CHAR;
+ retval |= *con;
+ }
+ return retval;
+}
+
+/* vax:md_assemble() emit frags for 1 instruction */
+
+void
+md_assemble (instruction_string)
+ char *instruction_string; /* A string: assemble 1 instruction. */
+{
+ /* Non-zero if operand expression's segment is not known yet. */
+ int is_undefined;
+
+ int length_code;
+ char *p;
+ /* An operand. Scans all operands. */
+ struct vop *operandP;
+ char *save_input_line_pointer;
+ /* What used to live after an expression. */
+ char c_save;
+ /* 1: instruction_string bad for all passes. */
+ int goofed;
+ /* Points to slot just after last operand. */
+ struct vop *end_operandP;
+ /* Points to expression values for this operand. */
+ expressionS *expP;
+ segT *segP;
+
+ /* These refer to an instruction operand expression. */
+ /* Target segment of the address. */
+ segT to_seg;
+ valueT this_add_number;
+ /* Positive (minuend) symbol. */
+ struct symbol *this_add_symbol;
+ /* As a number. */
+ long opcode_as_number;
+ /* Least significant byte 1st. */
+ char *opcode_as_chars;
+ /* As an array of characters. */
+ /* Least significant byte 1st */
+ char *opcode_low_byteP;
+ /* length (bytes) meant by vop_short. */
+ int length;
+ /* 0, or 1 if '@' is in addressing mode. */
+ int at;
+ /* From vop_nbytes: vax_operand_width (in bytes) */
+ int nbytes;
+ FLONUM_TYPE *floatP;
+ LITTLENUM_TYPE literal_float[8];
+ /* Big enough for any floating point literal. */
+
+ vip (&v, instruction_string);
+
+ /*
+ * Now we try to find as many as_warn()s as we can. If we do any as_warn()s
+ * then goofed=1. Notice that we don't make any frags yet.
+ * Should goofed be 1, then this instruction will wedge in any pass,
+ * and we can safely flush it, without causing interpass symbol phase
+ * errors. That is, without changing label values in different passes.
+ */
+ if ((goofed = (*v.vit_error)) != 0)
+ {
+ as_warn (_("Ignoring statement due to \"%s\""), v.vit_error);
+ }
+ /*
+ * We need to use expression() and friends, which require us to diddle
+ * input_line_pointer. So we save it and restore it later.
+ */
+ save_input_line_pointer = input_line_pointer;
+ for (operandP = v.vit_operand,
+ expP = exp_of_operand,
+ segP = seg_of_operand,
+ floatP = float_operand,
+ end_operandP = v.vit_operand + v.vit_operands;
+
+ operandP < end_operandP;
+
+ operandP++, expP++, segP++, floatP++)
+ { /* for each operand */
+ if (operandP->vop_error)
+ {
+ as_warn (_("Ignoring statement because \"%s\""), operandP->vop_error);
+ goofed = 1;
+ }
+ else
+ {
+ /* statement has no syntax goofs: lets sniff the expression */
+ int can_be_short = 0; /* 1 if a bignum can be reduced to a short literal. */
+
+ input_line_pointer = operandP->vop_expr_begin;
+ c_save = operandP->vop_expr_end[1];
+ operandP->vop_expr_end[1] = '\0';
+ /* If to_seg == SEG_PASS1, expression() will have set need_pass_2 = 1. */
+ *segP = expression (expP);
+ switch (expP->X_op)
+ {
+ case O_absent:
+ /* for BSD4.2 compatibility, missing expression is absolute 0 */
+ expP->X_op = O_constant;
+ expP->X_add_number = 0;
+ /* For SEG_ABSOLUTE, we shouldn't need to set X_op_symbol,
+ X_add_symbol to any particular value. But, we will program
+ defensively. Since this situation occurs rarely so it costs
+ us little to do, and stops Dean worrying about the origin of
+ random bits in expressionS's. */
+ expP->X_add_symbol = NULL;
+ expP->X_op_symbol = NULL;
+ break;
+
+ case O_symbol:
+ case O_constant:
+ break;
+
+ default:
+ /*
+ * Major bug. We can't handle the case of a
+ * SEG_OP expression in a VIT_OPCODE_SYNTHETIC
+ * variable-length instruction.
+ * We don't have a frag type that is smart enough to
+ * relax a SEG_OP, and so we just force all
+ * SEG_OPs to behave like SEG_PASS1s.
+ * Clearly, if there is a demand we can invent a new or
+ * modified frag type and then coding up a frag for this
+ * case will be easy. SEG_OP was invented for the
+ * .words after a CASE opcode, and was never intended for
+ * instruction operands.
+ */
+ need_pass_2 = 1;
+ as_warn (_("Can't relocate expression"));
+ break;
+
+ case O_big:
+ /* Preserve the bits. */
+ if (expP->X_add_number > 0)
+ {
+ bignum_copy (generic_bignum, expP->X_add_number,
+ floatP->low, SIZE_OF_LARGE_NUMBER);
+ }
+ else
+ {
+ know (expP->X_add_number < 0);
+ flonum_copy (&generic_floating_point_number,
+ floatP);
+ if (strchr ("s i", operandP->vop_short))
+ {
+ /* Could possibly become S^# */
+ flonum_gen2vax (-expP->X_add_number, floatP, literal_float);
+ switch (-expP->X_add_number)
+ {
+ case 'f':
+ can_be_short =
+ (literal_float[0] & 0xFC0F) == 0x4000
+ && literal_float[1] == 0;
+ break;
+
+ case 'd':
+ can_be_short =
+ (literal_float[0] & 0xFC0F) == 0x4000
+ && literal_float[1] == 0
+ && literal_float[2] == 0
+ && literal_float[3] == 0;
+ break;
+
+ case 'g':
+ can_be_short =
+ (literal_float[0] & 0xFF81) == 0x4000
+ && literal_float[1] == 0
+ && literal_float[2] == 0
+ && literal_float[3] == 0;
+ break;
+
+ case 'h':
+ can_be_short = ((literal_float[0] & 0xFFF8) == 0x4000
+ && (literal_float[1] & 0xE000) == 0
+ && literal_float[2] == 0
+ && literal_float[3] == 0
+ && literal_float[4] == 0
+ && literal_float[5] == 0
+ && literal_float[6] == 0
+ && literal_float[7] == 0);
+ break;
+
+ default:
+ BAD_CASE (-expP->X_add_number);
+ break;
+ } /* switch (float type) */
+ } /* if (could want to become S^#...) */
+ } /* bignum or flonum ? */
+
+ if (operandP->vop_short == 's'
+ || operandP->vop_short == 'i'
+ || (operandP->vop_short == ' '
+ && operandP->vop_reg == 0xF
+ && (operandP->vop_mode & 0xE) == 0x8))
+ {
+ /* Saw a '#'. */
+ if (operandP->vop_short == ' ')
+ {
+ /* We must chose S^ or I^. */
+ if (expP->X_add_number > 0)
+ {
+ /* Bignum: Short literal impossible. */
+ operandP->vop_short = 'i';
+ operandP->vop_mode = 8;
+ operandP->vop_reg = 0xF; /* VAX PC. */
+ }
+ else
+ {
+ /* Flonum: Try to do it. */
+ if (can_be_short)
+ {
+ operandP->vop_short = 's';
+ operandP->vop_mode = 0;
+ operandP->vop_ndx = -1;
+ operandP->vop_reg = -1;
+ expP->X_op = O_constant;
+ }
+ else
+ {
+ operandP->vop_short = 'i';
+ operandP->vop_mode = 8;
+ operandP->vop_reg = 0xF; /* VAX PC */
+ }
+ } /* bignum or flonum ? */
+ } /* if #, but no S^ or I^ seen. */
+ /* No more ' ' case: either 's' or 'i'. */
+ if (operandP->vop_short == 's')
+ {
+ /* Wants to be a short literal. */
+ if (expP->X_add_number > 0)
+ {
+ as_warn (_("Bignum not permitted in short literal. Immediate mode assumed."));
+ operandP->vop_short = 'i';
+ operandP->vop_mode = 8;
+ operandP->vop_reg = 0xF; /* VAX PC. */
+ }
+ else
+ {
+ if (!can_be_short)
+ {
+ as_warn (_("Can't do flonum short literal: immediate mode used."));
+ operandP->vop_short = 'i';
+ operandP->vop_mode = 8;
+ operandP->vop_reg = 0xF; /* VAX PC. */
+ }
+ else
+ { /* Encode short literal now. */
+ int temp = 0;
+
+ switch (-expP->X_add_number)
+ {
+ case 'f':
+ case 'd':
+ temp = literal_float[0] >> 4;
+ break;
+
+ case 'g':
+ temp = literal_float[0] >> 1;
+ break;
+
+ case 'h':
+ temp = ((literal_float[0] << 3) & 070)
+ | ((literal_float[1] >> 13) & 07);
+ break;
+
+ default:
+ BAD_CASE (-expP->X_add_number);
+ break;
+ }
+
+ floatP->low[0] = temp & 077;
+ floatP->low[1] = 0;
+ } /* if can be short literal float */
+ } /* flonum or bignum ? */
+ }
+ else
+ { /* I^# seen: set it up if float. */
+ if (expP->X_add_number < 0)
+ {
+ memcpy (floatP->low, literal_float, sizeof (literal_float));
+ }
+ } /* if S^# seen. */
+ }
+ else
+ {
+ as_warn (_("A bignum/flonum may not be a displacement: 0x%lx used"),
+ (expP->X_add_number = 0x80000000L));
+ /* Chosen so luser gets the most offset bits to patch later. */
+ }
+ expP->X_add_number = floatP->low[0]
+ | ((LITTLENUM_MASK & (floatP->low[1])) << LITTLENUM_NUMBER_OF_BITS);
+ /*
+ * For the O_big case we have:
+ * If vop_short == 's' then a short floating literal is in the
+ * lowest 6 bits of floatP -> low [0], which is
+ * big_operand_bits [---] [0].
+ * If vop_short == 'i' then the appropriate number of elements
+ * of big_operand_bits [---] [...] are set up with the correct
+ * bits.
+ * Also, just in case width is byte word or long, we copy the lowest
+ * 32 bits of the number to X_add_number.
+ */
+ break;
+ }
+ if (input_line_pointer != operandP->vop_expr_end + 1)
+ {
+ as_warn ("Junk at end of expression \"%s\"", input_line_pointer);
+ goofed = 1;
+ }
+ operandP->vop_expr_end[1] = c_save;
+ }
+ } /* for(each operand) */
+
+ input_line_pointer = save_input_line_pointer;
+
+ if (need_pass_2 || goofed)
+ {
+ return;
+ }
+
+
+ /* Emit op-code. */
+ /* Remember where it is, in case we want to modify the op-code later. */
+ opcode_low_byteP = frag_more (v.vit_opcode_nbytes);
+ memcpy (opcode_low_byteP, v.vit_opcode, v.vit_opcode_nbytes);
+ opcode_as_number = md_chars_to_number (opcode_as_chars = v.vit_opcode, 4);
+ for (operandP = v.vit_operand,
+ expP = exp_of_operand,
+ segP = seg_of_operand,
+ floatP = float_operand,
+ end_operandP = v.vit_operand + v.vit_operands;
+
+ operandP < end_operandP;
+
+ operandP++,
+ floatP++,
+ segP++,
+ expP++)
+ {
+ if (operandP->vop_ndx >= 0)
+ {
+ /* indexed addressing byte */
+ /* Legality of indexed mode already checked: it is OK */
+ FRAG_APPEND_1_CHAR (0x40 + operandP->vop_ndx);
+ } /* if(vop_ndx>=0) */
+
+ /* Here to make main operand frag(s). */
+ this_add_number = expP->X_add_number;
+ this_add_symbol = expP->X_add_symbol;
+ to_seg = *segP;
+ is_undefined = (to_seg == SEG_UNKNOWN);
+ at = operandP->vop_mode & 1;
+ length = (operandP->vop_short == 'b'
+ ? 1 : (operandP->vop_short == 'w'
+ ? 2 : (operandP->vop_short == 'l'
+ ? 4 : 0)));
+ nbytes = operandP->vop_nbytes;
+ if (operandP->vop_access == 'b')
+ {
+ if (to_seg == now_seg || is_undefined)
+ {
+ /* If is_undefined, then it might BECOME now_seg. */
+ if (nbytes)
+ {
+ p = frag_more (nbytes);
+ fix_new (frag_now, p - frag_now->fr_literal, nbytes,
+ this_add_symbol, this_add_number, 1, NO_RELOC);
+ }
+ else
+ { /* to_seg==now_seg || to_seg == SEG_UNKNOWN */
+ /* nbytes==0 */
+ length_code = is_undefined ? STATE_UNDF : STATE_BYTE;
+ if (opcode_as_number & VIT_OPCODE_SPECIAL)
+ {
+ if (operandP->vop_width == VAX_WIDTH_UNCONDITIONAL_JUMP)
+ {
+ /* br or jsb */
+ frag_var (rs_machine_dependent, 5, 1,
+ ENCODE_RELAX (STATE_ALWAYS_BRANCH, length_code),
+ this_add_symbol, this_add_number,
+ opcode_low_byteP);
+ }
+ else
+ {
+ if (operandP->vop_width == VAX_WIDTH_WORD_JUMP)
+ {
+ length_code = STATE_WORD;
+ /* JF: There is no state_byte for this one! */
+ frag_var (rs_machine_dependent, 10, 2,
+ ENCODE_RELAX (STATE_COMPLEX_BRANCH, length_code),
+ this_add_symbol, this_add_number,
+ opcode_low_byteP);
+ }
+ else
+ {
+ know (operandP->vop_width == VAX_WIDTH_BYTE_JUMP);
+ frag_var (rs_machine_dependent, 9, 1,
+ ENCODE_RELAX (STATE_COMPLEX_HOP, length_code),
+ this_add_symbol, this_add_number,
+ opcode_low_byteP);
+ }
+ }
+ }
+ else
+ {
+ know (operandP->vop_width == VAX_WIDTH_CONDITIONAL_JUMP);
+ frag_var (rs_machine_dependent, 7, 1,
+ ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, length_code),
+ this_add_symbol, this_add_number,
+ opcode_low_byteP);
+ }
+ }
+ }
+ else
+ {
+ /* to_seg != now_seg && to_seg != SEG_UNKNOWN */
+ /*
+ * --- SEG FLOAT MAY APPEAR HERE ----
+ */
+ if (to_seg == SEG_ABSOLUTE)
+ {
+ if (nbytes)
+ {
+ know (!(opcode_as_number & VIT_OPCODE_SYNTHETIC));
+ p = frag_more (nbytes);
+ /* Conventional relocation. */
+ fix_new (frag_now, p - frag_now->fr_literal,
+ nbytes, &abs_symbol, this_add_number,
+ 1, NO_RELOC);
+ }
+ else
+ {
+ know (opcode_as_number & VIT_OPCODE_SYNTHETIC);
+ if (opcode_as_number & VIT_OPCODE_SPECIAL)
+ {
+ if (operandP->vop_width == VAX_WIDTH_UNCONDITIONAL_JUMP)
+ {
+ /* br or jsb */
+ *opcode_low_byteP = opcode_as_chars[0] + VAX_WIDEN_LONG;
+ know (opcode_as_chars[1] == 0);
+ p = frag_more (5);
+ p[0] = VAX_ABSOLUTE_MODE; /* @#... */
+ md_number_to_chars (p + 1, this_add_number, 4);
+ /* Now (eg) JMP @#foo or JSB @#foo. */
+ }
+ else
+ {
+ if (operandP->vop_width == VAX_WIDTH_WORD_JUMP)
+ {
+ p = frag_more (10);
+ p[0] = 2;
+ p[1] = 0;
+ p[2] = VAX_BRB;
+ p[3] = 6;
+ p[4] = VAX_JMP;
+ p[5] = VAX_ABSOLUTE_MODE; /* @#... */
+ md_number_to_chars (p + 6, this_add_number, 4);
+ /*
+ * Now (eg) ACBx 1f
+ * BRB 2f
+ * 1: JMP @#foo
+ * 2:
+ */
+ }
+ else
+ {
+ know (operandP->vop_width == VAX_WIDTH_BYTE_JUMP);
+ p = frag_more (9);
+ p[0] = 2;
+ p[1] = VAX_BRB;
+ p[2] = 6;
+ p[3] = VAX_JMP;
+ p[4] = VAX_PC_RELATIVE_MODE + 1; /* @#... */
+ md_number_to_chars (p + 5, this_add_number, 4);
+ /*
+ * Now (eg) xOBxxx 1f
+ * BRB 2f
+ * 1: JMP @#foo
+ * 2:
+ */
+ }
+ }
+ }
+ else
+ {
+ /* b<cond> */
+ *opcode_low_byteP ^= 1;
+ /* To reverse the condition in a VAX branch,
+ complement the lowest order bit. */
+ p = frag_more (7);
+ p[0] = 6;
+ p[1] = VAX_JMP;
+ p[2] = VAX_ABSOLUTE_MODE; /* @#... */
+ md_number_to_chars (p + 3, this_add_number, 4);
+ /*
+ * Now (eg) BLEQ 1f
+ * JMP @#foo
+ * 1:
+ */
+ }
+ }
+ }
+ else
+ {
+ /* to_seg != now_seg && to_seg != SEG_UNKNOWN && to_Seg != SEG_ABSOLUTE */
+ if (nbytes > 0)
+ {
+ /* Pc-relative. Conventional relocation. */
+ know (!(opcode_as_number & VIT_OPCODE_SYNTHETIC));
+ p = frag_more (nbytes);
+ fix_new (frag_now, p - frag_now->fr_literal,
+ nbytes, &abs_symbol, this_add_number,
+ 1, NO_RELOC);
+ }
+ else
+ {
+ know (opcode_as_number & VIT_OPCODE_SYNTHETIC);
+ if (opcode_as_number & VIT_OPCODE_SPECIAL)
+ {
+ if (operandP->vop_width == VAX_WIDTH_UNCONDITIONAL_JUMP)
+ {
+ /* br or jsb */
+ know (opcode_as_chars[1] == 0);
+ *opcode_low_byteP = opcode_as_chars[0] + VAX_WIDEN_LONG;
+ p = frag_more (5);
+ p[0] = VAX_PC_RELATIVE_MODE;
+ fix_new (frag_now,
+ p + 1 - frag_now->fr_literal, 4,
+ this_add_symbol,
+ this_add_number, 1, NO_RELOC);
+ /* Now eg JMP foo or JSB foo. */
+ }
+ else
+ {
+ if (operandP->vop_width == VAX_WIDTH_WORD_JUMP)
+ {
+ p = frag_more (10);
+ p[0] = 0;
+ p[1] = 2;
+ p[2] = VAX_BRB;
+ p[3] = 6;
+ p[4] = VAX_JMP;
+ p[5] = VAX_PC_RELATIVE_MODE;
+ fix_new (frag_now,
+ p + 6 - frag_now->fr_literal, 4,
+ this_add_symbol,
+ this_add_number, 1, NO_RELOC);
+ /*
+ * Now (eg) ACBx 1f
+ * BRB 2f
+ * 1: JMP foo
+ * 2:
+ */
+ }
+ else
+ {
+ know (operandP->vop_width == VAX_WIDTH_BYTE_JUMP);
+ p = frag_more (10);
+ p[0] = 2;
+ p[1] = VAX_BRB;
+ p[2] = 6;
+ p[3] = VAX_JMP;
+ p[4] = VAX_PC_RELATIVE_MODE;
+ fix_new (frag_now,
+ p + 5 - frag_now->fr_literal,
+ 4, this_add_symbol,
+ this_add_number, 1, NO_RELOC);
+ /*
+ * Now (eg) xOBxxx 1f
+ * BRB 2f
+ * 1: JMP foo
+ * 2:
+ */
+ }
+ }
+ }
+ else
+ {
+ know (operandP->vop_width == VAX_WIDTH_CONDITIONAL_JUMP);
+ *opcode_low_byteP ^= 1; /* Reverse branch condition. */
+ p = frag_more (7);
+ p[0] = 6;
+ p[1] = VAX_JMP;
+ p[2] = VAX_PC_RELATIVE_MODE;
+ fix_new (frag_now, p + 3 - frag_now->fr_literal,
+ 4, this_add_symbol,
+ this_add_number, 1, NO_RELOC);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ know (operandP->vop_access != 'b'); /* So it is ordinary operand. */
+ know (operandP->vop_access != ' '); /* ' ' target-independent: elsewhere. */
+ know (operandP->vop_access == 'a'
+ || operandP->vop_access == 'm'
+ || operandP->vop_access == 'r'
+ || operandP->vop_access == 'v'
+ || operandP->vop_access == 'w');
+ if (operandP->vop_short == 's')
+ {
+ if (to_seg == SEG_ABSOLUTE)
+ {
+ if (this_add_number >= 64)
+ {
+ as_warn (_("Short literal overflow(%ld.), immediate mode assumed."),
+ (long) this_add_number);
+ operandP->vop_short = 'i';
+ operandP->vop_mode = 8;
+ operandP->vop_reg = 0xF;
+ }
+ }
+ else
+ {
+ as_warn (_("Forced short literal to immediate mode. now_seg=%s to_seg=%s"),
+ segment_name (now_seg), segment_name (to_seg));
+ operandP->vop_short = 'i';
+ operandP->vop_mode = 8;
+ operandP->vop_reg = 0xF;
+ }
+ }
+ if (operandP->vop_reg >= 0 && (operandP->vop_mode < 8
+ || (operandP->vop_reg != 0xF && operandP->vop_mode < 10)))
+ {
+ /* One byte operand. */
+ know (operandP->vop_mode > 3);
+ FRAG_APPEND_1_CHAR (operandP->vop_mode << 4 | operandP->vop_reg);
+ /* All 1-bytes except S^# happen here. */
+ }
+ else
+ {
+ /* {@}{q^}foo{(Rn)} or S^#foo */
+ if (operandP->vop_reg == -1 && operandP->vop_short != 's')
+ {
+ /* "{@}{q^}foo" */
+ if (to_seg == now_seg)
+ {
+ if (length == 0)
+ {
+ know (operandP->vop_short == ' ');
+ p = frag_var (rs_machine_dependent, 10, 2,
+ ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE),
+ this_add_symbol, this_add_number,
+ opcode_low_byteP);
+ know (operandP->vop_mode == 10 + at);
+ *p = at << 4;
+ /* At is the only context we need to carry
+ to other side of relax() process. Must
+ be in the correct bit position of VAX
+ operand spec. byte. */
+ }
+ else
+ {
+ know (length);
+ know (operandP->vop_short != ' ');
+ p = frag_more (length + 1);
+ p[0] = 0xF | ((at + "?\12\14?\16"[length]) << 4);
+ fix_new (frag_now, p + 1 - frag_now->fr_literal,
+ length, this_add_symbol,
+ this_add_number, 1, NO_RELOC);
+ }
+ }
+ else
+ { /* to_seg != now_seg */
+ if (this_add_symbol == NULL)
+ {
+ know (to_seg == SEG_ABSOLUTE);
+ /* Do @#foo: simpler relocation than foo-.(pc) anyway. */
+ p = frag_more (5);
+ p[0] = VAX_ABSOLUTE_MODE; /* @#... */
+ md_number_to_chars (p + 1, this_add_number, 4);
+ if (length && length != 4)
+ {
+ as_warn (_("Length specification ignored. Address mode 9F used"));
+ }
+ }
+ else
+ {
+ /* {@}{q^}other_seg */
+ know ((length == 0 && operandP->vop_short == ' ')
+ || (length > 0 && operandP->vop_short != ' '));
+ if (is_undefined)
+ {
+ /*
+ * We have a SEG_UNKNOWN symbol. It might
+ * turn out to be in the same segment as
+ * the instruction, permitting relaxation.
+ */
+ p = frag_var (rs_machine_dependent, 5, 2,
+ ENCODE_RELAX (STATE_PC_RELATIVE, STATE_UNDF),
+ this_add_symbol, this_add_number,
+ 0);
+ p[0] = at << 4;
+ }
+ else
+ {
+ if (length == 0)
+ {
+ know (operandP->vop_short == ' ');
+ length = 4; /* Longest possible. */
+ }
+ p = frag_more (length + 1);
+ p[0] = 0xF | ((at + "?\12\14?\16"[length]) << 4);
+ md_number_to_chars (p + 1, this_add_number, length);
+ fix_new (frag_now,
+ p + 1 - frag_now->fr_literal,
+ length, this_add_symbol,
+ this_add_number, 1, NO_RELOC);
+ }
+ }
+ }
+ }
+ else
+ {
+ /* {@}{q^}foo(Rn) or S^# or I^# or # */
+ if (operandP->vop_mode < 0xA)
+ {
+ /* # or S^# or I^# */
+ if (operandP->vop_access == 'v'
+ || operandP->vop_access == 'a')
+ {
+ if (operandP->vop_access == 'v')
+ as_warn (_("Invalid operand: immediate value used as base address."));
+ else
+ as_warn (_("Invalid operand: immediate value used as address."));
+ /* gcc 2.6.3 is known to generate these in at least
+ one case. */
+ }
+ if (length == 0
+ && to_seg == SEG_ABSOLUTE && (expP->X_op != O_big)
+ && operandP->vop_mode == 8 /* No '@'. */
+ && this_add_number < 64)
+ {
+ operandP->vop_short = 's';
+ }
+ if (operandP->vop_short == 's')
+ {
+ FRAG_APPEND_1_CHAR (this_add_number);
+ }
+ else
+ {
+ /* I^#... */
+ know (nbytes);
+ p = frag_more (nbytes + 1);
+ know (operandP->vop_reg == 0xF);
+ p[0] = (operandP->vop_mode << 4) | 0xF;
+ if ((to_seg == SEG_ABSOLUTE) && (expP->X_op != O_big))
+ {
+ /*
+ * If nbytes > 4, then we are scrod. We
+ * don't know if the high order bytes
+ * are to be 0xFF or 0x00. BSD4.2 & RMS
+ * say use 0x00. OK --- but this
+ * assembler needs ANOTHER rewrite to
+ * cope properly with this bug. */
+ md_number_to_chars (p + 1, this_add_number, min (4, nbytes));
+ if (nbytes > 4)
+ {
+ memset (p + 5, '\0', nbytes - 4);
+ }
+ }
+ else
+ {
+ if (expP->X_op == O_big)
+ {
+ /*
+ * Problem here is to get the bytes
+ * in the right order. We stored
+ * our constant as LITTLENUMs, not
+ * bytes. */
+ LITTLENUM_TYPE *lP;
+
+ lP = floatP->low;
+ if (nbytes & 1)
+ {
+ know (nbytes == 1);
+ p[1] = *lP;
+ }
+ else
+ {
+ for (p++; nbytes; nbytes -= 2, p += 2, lP++)
+ {
+ md_number_to_chars (p, *lP, 2);
+ }
+ }
+ }
+ else
+ {
+ fix_new (frag_now, p + 1 - frag_now->fr_literal,
+ nbytes, this_add_symbol,
+ this_add_number, 0, NO_RELOC);
+ }
+ }
+ }
+ }
+ else
+ { /* {@}{q^}foo(Rn) */
+ know ((length == 0 && operandP->vop_short == ' ')
+ || (length > 0 && operandP->vop_short != ' '));
+ if (length == 0)
+ {
+ if (to_seg == SEG_ABSOLUTE)
+ {
+ long test;
+
+ test = this_add_number;
+
+ if (test < 0)
+ test = ~test;
+
+ length = test & 0xffff8000 ? 4
+ : test & 0xffffff80 ? 2
+ : 1;
+ }
+ else
+ {
+ length = 4;
+ }
+ }
+ p = frag_more (1 + length);
+ know (operandP->vop_reg >= 0);
+ p[0] = operandP->vop_reg
+ | ((at | "?\12\14?\16"[length]) << 4);
+ if (to_seg == SEG_ABSOLUTE)
+ {
+ md_number_to_chars (p + 1, this_add_number, length);
+ }
+ else
+ {
+ fix_new (frag_now, p + 1 - frag_now->fr_literal,
+ length, this_add_symbol,
+ this_add_number, 0, NO_RELOC);
+ }
+ }
+ }
+ } /* if(single-byte-operand) */
+ }
+ } /* for(operandP) */
+} /* vax_assemble() */
+
+/*
+ * md_estimate_size_before_relax()
+ *
+ * Called just before relax().
+ * Any symbol that is now undefined will not become defined.
+ * Return the correct fr_subtype in the frag.
+ * Return the initial "guess for fr_var" to caller.
+ * The guess for fr_var is ACTUALLY the growth beyond fr_fix.
+ * Whatever we do to grow fr_fix or fr_var contributes to our returned value.
+ * Although it may not be explicit in the frag, pretend fr_var starts with a
+ * 0 value.
+ */
+int
+md_estimate_size_before_relax (fragP, segment)
+ fragS *fragP;
+ segT segment;
+{
+ char *p;
+ int old_fr_fix;
+
+ old_fr_fix = fragP->fr_fix;
+ switch (fragP->fr_subtype)
+ {
+ case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_UNDF):
+ if (S_GET_SEGMENT (fragP->fr_symbol) == segment)
+ { /* A relaxable case. */
+ fragP->fr_subtype = ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE);
+ }
+ else
+ {
+ p = fragP->fr_literal + old_fr_fix;
+ p[0] |= VAX_PC_RELATIVE_MODE; /* Preserve @ bit. */
+ fragP->fr_fix += 1 + 4;
+ fix_new (fragP, old_fr_fix + 1, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
+ frag_wane (fragP);
+ }
+ break;
+
+ case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_UNDF):
+ if (S_GET_SEGMENT (fragP->fr_symbol) == segment)
+ {
+ fragP->fr_subtype = ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_BYTE);
+ }
+ else
+ {
+ p = fragP->fr_literal + old_fr_fix;
+ *fragP->fr_opcode ^= 1; /* Reverse sense of branch. */
+ p[0] = 6;
+ p[1] = VAX_JMP;
+ p[2] = VAX_PC_RELATIVE_MODE; /* ...(PC) */
+ fragP->fr_fix += 1 + 1 + 1 + 4;
+ fix_new (fragP, old_fr_fix + 3, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
+ frag_wane (fragP);
+ }
+ break;
+
+ case ENCODE_RELAX (STATE_COMPLEX_BRANCH, STATE_UNDF):
+ if (S_GET_SEGMENT (fragP->fr_symbol) == segment)
+ {
+ fragP->fr_subtype = ENCODE_RELAX (STATE_COMPLEX_BRANCH, STATE_WORD);
+ }
+ else
+ {
+ p = fragP->fr_literal + old_fr_fix;
+ p[0] = 2;
+ p[1] = 0;
+ p[2] = VAX_BRB;
+ p[3] = 6;
+ p[4] = VAX_JMP;
+ p[5] = VAX_PC_RELATIVE_MODE; /* ...(pc) */
+ fragP->fr_fix += 2 + 2 + 1 + 1 + 4;
+ fix_new (fragP, old_fr_fix + 6, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
+ frag_wane (fragP);
+ }
+ break;
+
+ case ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_UNDF):
+ if (S_GET_SEGMENT (fragP->fr_symbol) == segment)
+ {
+ fragP->fr_subtype = ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_BYTE);
+ }
+ else
+ {
+ p = fragP->fr_literal + old_fr_fix;
+ p[0] = 2;
+ p[1] = VAX_BRB;
+ p[2] = 6;
+ p[3] = VAX_JMP;
+ p[4] = VAX_PC_RELATIVE_MODE; /* ...(pc) */
+ fragP->fr_fix += 1 + 2 + 1 + 1 + 4;
+ fix_new (fragP, old_fr_fix + 5, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
+ frag_wane (fragP);
+ }
+ break;
+
+ case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_UNDF):
+ if (S_GET_SEGMENT (fragP->fr_symbol) == segment)
+ {
+ fragP->fr_subtype = ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_BYTE);
+ }
+ else
+ {
+ p = fragP->fr_literal + old_fr_fix;
+ *fragP->fr_opcode += VAX_WIDEN_LONG;
+ p[0] = VAX_PC_RELATIVE_MODE; /* ...(PC) */
+ fragP->fr_fix += 1 + 4;
+ fix_new (fragP, old_fr_fix + 1, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
+ frag_wane (fragP);
+ }
+ break;
+
+ default:
+ break;
+ }
+ return (fragP->fr_var + fragP->fr_fix - old_fr_fix);
+} /* md_estimate_size_before_relax() */
+
+/*
+ * md_convert_frag();
+ *
+ * Called after relax() is finished.
+ * In: Address of frag.
+ * fr_type == rs_machine_dependent.
+ * fr_subtype is what the address relaxed to.
+ *
+ * Out: Any fixSs and constants are set up.
+ * Caller will turn frag into a ".space 0".
+ */
+void
+md_convert_frag (headers, seg, fragP)
+ object_headers *headers;
+ segT seg;
+ fragS *fragP;
+{
+ char *addressP; /* -> _var to change. */
+ char *opcodeP; /* -> opcode char(s) to change. */
+ short int length_code; /* 2=long 1=word 0=byte */
+ short int extension = 0; /* Size of relaxed address. */
+ /* Added to fr_fix: incl. ALL var chars. */
+ symbolS *symbolP;
+ long where;
+ long address_of_var;
+ /* Where, in file space, is _var of *fragP? */
+ long target_address = 0;
+ /* Where, in file space, does addr point? */
+
+ know (fragP->fr_type == rs_machine_dependent);
+ length_code = fragP->fr_subtype & 3; /* depends on ENCODE_RELAX() */
+ know (length_code >= 0 && length_code < 3);
+ where = fragP->fr_fix;
+ addressP = fragP->fr_literal + where;
+ opcodeP = fragP->fr_opcode;
+ symbolP = fragP->fr_symbol;
+ know (symbolP);
+ target_address = S_GET_VALUE (symbolP) + fragP->fr_offset;
+ address_of_var = fragP->fr_address + where;
+
+ switch (fragP->fr_subtype)
+ {
+
+ case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE):
+ know (*addressP == 0 || *addressP == 0x10); /* '@' bit. */
+ addressP[0] |= 0xAF; /* Byte displacement. */
+ addressP[1] = target_address - (address_of_var + 2);
+ extension = 2;
+ break;
+
+ case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_WORD):
+ know (*addressP == 0 || *addressP == 0x10); /* '@' bit. */
+ addressP[0] |= 0xCF; /* Word displacement. */
+ md_number_to_chars (addressP + 1, target_address - (address_of_var + 3), 2);
+ extension = 3;
+ break;
+
+ case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_LONG):
+ know (*addressP == 0 || *addressP == 0x10); /* '@' bit. */
+ addressP[0] |= 0xEF; /* Long word displacement. */
+ md_number_to_chars (addressP + 1, target_address - (address_of_var + 5), 4);
+ extension = 5;
+ break;
+
+ case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_BYTE):
+ addressP[0] = target_address - (address_of_var + 1);
+ extension = 1;
+ break;
+
+ case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_WORD):
+ opcodeP[0] ^= 1; /* Reverse sense of test. */
+ addressP[0] = 3;
+ addressP[1] = VAX_BRB + VAX_WIDEN_WORD;
+ md_number_to_chars (addressP + 2, target_address - (address_of_var + 4), 2);
+ extension = 4;
+ break;
+
+ case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_LONG):
+ opcodeP[0] ^= 1; /* Reverse sense of test. */
+ addressP[0] = 6;
+ addressP[1] = VAX_JMP;
+ addressP[2] = VAX_PC_RELATIVE_MODE;
+ md_number_to_chars (addressP + 3, target_address, 4);
+ extension = 7;
+ break;
+
+ case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_BYTE):
+ addressP[0] = target_address - (address_of_var + 1);
+ extension = 1;
+ break;
+
+ case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_WORD):
+ opcodeP[0] += VAX_WIDEN_WORD; /* brb -> brw, bsbb -> bsbw */
+ md_number_to_chars (addressP, target_address - (address_of_var + 2), 2);
+ extension = 2;
+ break;
+
+ case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_LONG):
+ opcodeP[0] += VAX_WIDEN_LONG; /* brb -> jmp, bsbb -> jsb */
+ addressP[0] = VAX_PC_RELATIVE_MODE;
+ md_number_to_chars (addressP + 1, target_address - (address_of_var + 5), 4);
+ extension = 5;
+ break;
+
+ case ENCODE_RELAX (STATE_COMPLEX_BRANCH, STATE_WORD):
+ md_number_to_chars (addressP, target_address - (address_of_var + 2), 2);
+ extension = 2;
+ break;
+
+ case ENCODE_RELAX (STATE_COMPLEX_BRANCH, STATE_LONG):
+ addressP[0] = 2;
+ addressP[1] = 0;
+ addressP[2] = VAX_BRB;
+ addressP[3] = 6;
+ addressP[4] = VAX_JMP;
+ addressP[5] = VAX_PC_RELATIVE_MODE;
+ md_number_to_chars (addressP + 6, target_address, 4);
+ extension = 10;
+ break;
+
+ case ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_BYTE):
+ addressP[0] = target_address - (address_of_var + 1);
+ extension = 1;
+ break;
+
+ case ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_WORD):
+ addressP[0] = 2;
+ addressP[1] = VAX_BRB;
+ addressP[2] = 3;
+ addressP[3] = VAX_BRW;
+ md_number_to_chars (addressP + 4, target_address - (address_of_var + 6), 2);
+ extension = 6;
+ break;
+
+ case ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_LONG):
+ addressP[0] = 2;
+ addressP[1] = VAX_BRB;
+ addressP[2] = 6;
+ addressP[3] = VAX_JMP;
+ addressP[4] = VAX_PC_RELATIVE_MODE;
+ md_number_to_chars (addressP + 5, target_address, 4);
+ extension = 9;
+ break;
+
+ default:
+ BAD_CASE (fragP->fr_subtype);
+ break;
+ }
+ fragP->fr_fix += extension;
+} /* md_convert_frag() */
+
+/* Translate internal format of relocation info into target format.
+
+ On vax: first 4 bytes are normal unsigned long, next three bytes
+ are symbolnum, least sig. byte first. Last byte is broken up with
+ the upper nibble as nuthin, bit 3 as extern, bits 2 & 1 as length, and
+ bit 0 as pcrel. */
+#ifdef comment
+void
+md_ri_to_chars (the_bytes, ri)
+ char *the_bytes;
+ struct reloc_info_generic ri;
+{
+ /* this is easy */
+ md_number_to_chars (the_bytes, ri.r_address, sizeof (ri.r_address));
+ /* now the fun stuff */
+ the_bytes[6] = (ri.r_symbolnum >> 16) & 0x0ff;
+ the_bytes[5] = (ri.r_symbolnum >> 8) & 0x0ff;
+ the_bytes[4] = ri.r_symbolnum & 0x0ff;
+ the_bytes[7] = (((ri.r_extern << 3) & 0x08) | ((ri.r_length << 1) & 0x06) |
+ ((ri.r_pcrel << 0) & 0x01)) & 0x0F;
+}
+
+#endif /* comment */
+
+void
+tc_aout_fix_to_chars (where, fixP, segment_address_in_file)
+ char *where;
+ fixS *fixP;
+ relax_addressT segment_address_in_file;
+{
+ /*
+ * In: length of relocation (or of address) in chars: 1, 2 or 4.
+ * Out: GNU LD relocation length code: 0, 1, or 2.
+ */
+
+ static const unsigned char nbytes_r_length[] = {42, 0, 1, 42, 2};
+ long r_symbolnum;
+
+ know (fixP->fx_addsy != NULL);
+
+ md_number_to_chars (where,
+ fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
+ 4);
+
+ r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy)
+ ? S_GET_TYPE (fixP->fx_addsy)
+ : fixP->fx_addsy->sy_number);
+
+ where[6] = (r_symbolnum >> 16) & 0x0ff;
+ where[5] = (r_symbolnum >> 8) & 0x0ff;
+ where[4] = r_symbolnum & 0x0ff;
+ where[7] = ((((!S_IS_DEFINED (fixP->fx_addsy)) << 3) & 0x08)
+ | ((nbytes_r_length[fixP->fx_size] << 1) & 0x06)
+ | (((fixP->fx_pcrel << 0) & 0x01) & 0x0f));
+}
+
+/*
+ * BUGS, GRIPES, APOLOGIA, etc.
+ *
+ * The opcode table 'votstrs' needs to be sorted on opcode frequency.
+ * That is, AFTER we hash it with hash_...(), we want most-used opcodes
+ * to come out of the hash table faster.
+ *
+ * I am sorry to inflict yet another VAX assembler on the world, but
+ * RMS says we must do everything from scratch, to prevent pin-heads
+ * restricting this software.
+ */
+
+/*
+ * This is a vaguely modular set of routines in C to parse VAX
+ * assembly code using DEC mnemonics. It is NOT un*x specific.
+ *
+ * The idea here is that the assembler has taken care of all:
+ * labels
+ * macros
+ * listing
+ * pseudo-ops
+ * line continuation
+ * comments
+ * condensing any whitespace down to exactly one space
+ * and all we have to do is parse 1 line into a vax instruction
+ * partially formed. We will accept a line, and deliver:
+ * an error message (hopefully empty)
+ * a skeleton VAX instruction (tree structure)
+ * textual pointers to all the operand expressions
+ * a warning message that notes a silly operand (hopefully empty)
+ */
+
+/*
+ * E D I T H I S T O R Y
+ *
+ * 17may86 Dean Elsner. Bug if line ends immediately after opcode.
+ * 30apr86 Dean Elsner. New vip_op() uses arg block so change call.
+ * 6jan86 Dean Elsner. Crock vip_begin() to call vip_op_defaults().
+ * 2jan86 Dean Elsner. Invent synthetic opcodes.
+ * Widen vax_opcodeT to 32 bits. Use a bit for VIT_OPCODE_SYNTHETIC,
+ * which means this is not a real opcode, it is like a macro; it will
+ * be relax()ed into 1 or more instructions.
+ * Use another bit for VIT_OPCODE_SPECIAL if the op-code is not optimised
+ * like a regular branch instruction. Option added to vip_begin():
+ * exclude synthetic opcodes. Invent synthetic_votstrs[].
+ * 31dec85 Dean Elsner. Invent vit_opcode_nbytes.
+ * Also make vit_opcode into a char[]. We now have n-byte vax opcodes,
+ * so caller's don't have to know the difference between a 1-byte & a
+ * 2-byte op-code. Still need vax_opcodeT concept, so we know how
+ * big an object must be to hold an op.code.
+ * 30dec85 Dean Elsner. Widen typedef vax_opcodeT in "vax-inst.h"
+ * because vax opcodes may be 16 bits. Our crufty C compiler was
+ * happily initialising 8-bit vot_codes with 16-bit numbers!
+ * (Wouldn't the 'phone company like to compress data so easily!)
+ * 29dec85 Dean Elsner. New static table vax_operand_width_size[].
+ * Invented so we know hw many bytes a "I^#42" needs in its immediate
+ * operand. Revised struct vop in "vax-inst.h": explicitly include
+ * byte length of each operand, and it's letter-code datum type.
+ * 17nov85 Dean Elsner. Name Change.
+ * Due to ar(1) truncating names, we learned the hard way that
+ * "vax-inst-parse.c" -> "vax-inst-parse." dropping the "o" off
+ * the archived object name. SO... we shortened the name of this
+ * source file, and changed the makefile.
+ */
+
+/* handle of the OPCODE hash table */
+static struct hash_control *op_hash;
+
+/*
+ * In: 1 character, from "bdfghloqpw" being the data-type of an operand
+ * of a vax instruction.
+ *
+ * Out: the length of an operand of that type, in bytes.
+ * Special branch operands types "-?!" have length 0.
+ */
+
+static const short int vax_operand_width_size[256] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 8, 0, 4, 8, 16, 0, 0, 0, 4, 0, 0,16, /* ..b.d.fgh...l..o */
+ 0, 8, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, /* .q.....w........ */
+ 0, 0, 1, 0, 8, 0, 4, 8, 16, 0, 0, 0, 4, 0, 0,16, /* ..b.d.fgh...l..o */
+ 0, 8, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, /* .q.....w........ */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+/*
+ * This perversion encodes all the vax opcodes as a bunch of strings.
+ * RMS says we should build our hash-table at run-time. Hmm.
+ * Please would someone arrange these in decreasing frequency of opcode?
+ * Because of the way hash_...() works, the most frequently used opcode
+ * should be textually first and so on.
+ *
+ * Input for this table was 'vax.opcodes', awk(1)ed by 'vax.opcodes.c.awk' .
+ * So change 'vax.opcodes', then re-generate this table.
+ */
+
+#include "opcode/vax.h"
+
+/*
+ * This is a table of optional op-codes. All of them represent
+ * 'synthetic' instructions that seem popular.
+ *
+ * Here we make some pseudo op-codes. Every code has a bit set to say
+ * it is synthetic. This lets you catch them if you want to
+ * ban these opcodes. They are mnemonics for "elastic" instructions
+ * that are supposed to assemble into the fewest bytes needed to do a
+ * branch, or to do a conditional branch, or whatever.
+ *
+ * The opcode is in the usual place [low-order n*8 bits]. This means
+ * that if you mask off the bucky bits, the usual rules apply about
+ * how long the opcode is.
+ *
+ * All VAX branch displacements come at the end of the instruction.
+ * For simple branches (1-byte opcode + 1-byte displacement) the last
+ * operand is coded 'b?' where the "data type" '?' is a clue that we
+ * may reverse the sense of the branch (complement lowest order bit)
+ * and branch around a jump. This is by far the most common case.
+ * That is why the VIT_OPCODE_SYNTHETIC bit is set: it says this is
+ * a 0-byte op-code followed by 2 or more bytes of operand address.
+ *
+ * If the op-code has VIT_OPCODE_SPECIAL set, then we have a more unusual
+ * case.
+ *
+ * For JBSB & JBR the treatment is the similar, except (1) we have a 'bw'
+ * option before (2) we can directly JSB/JMP because there is no condition.
+ * These operands have 'b-' as their access/data type.
+ *
+ * That leaves a bunch of random opcodes: JACBx, JxOBxxx. In these
+ * cases, we do the same idea. JACBxxx are all marked with a 'b!'
+ * JAOBxxx & JSOBxxx are marked with a 'b:'.
+ *
+ */
+#if (VIT_OPCODE_SYNTHETIC != 0x80000000)
+You have just broken the encoding below, which assumes the sign bit
+ means 'I am an imaginary instruction'.
+#endif
+
+#if (VIT_OPCODE_SPECIAL != 0x40000000)
+ You have just broken the encoding below, which assumes the 0x40 M bit means
+ 'I am not to be "optimised" the way normal branches are'.
+#endif
+
+static const struct vot
+ synthetic_votstrs[] =
+{
+ {"jbsb", {"b-", 0xC0000010}}, /* BSD 4.2 */
+/* jsb used already */
+ {"jbr", {"b-", 0xC0000011}}, /* BSD 4.2 */
+ {"jr", {"b-", 0xC0000011}}, /* consistent */
+ {"jneq", {"b?", 0x80000012}},
+ {"jnequ", {"b?", 0x80000012}},
+ {"jeql", {"b?", 0x80000013}},
+ {"jeqlu", {"b?", 0x80000013}},
+ {"jgtr", {"b?", 0x80000014}},
+ {"jleq", {"b?", 0x80000015}},
+/* un-used opcodes here */
+ {"jgeq", {"b?", 0x80000018}},
+ {"jlss", {"b?", 0x80000019}},
+ {"jgtru", {"b?", 0x8000001a}},
+ {"jlequ", {"b?", 0x8000001b}},
+ {"jvc", {"b?", 0x8000001c}},
+ {"jvs", {"b?", 0x8000001d}},
+ {"jgequ", {"b?", 0x8000001e}},
+ {"jcc", {"b?", 0x8000001e}},
+ {"jlssu", {"b?", 0x8000001f}},
+ {"jcs", {"b?", 0x8000001f}},
+
+ {"jacbw", {"rwrwmwb!", 0xC000003d}},
+ {"jacbf", {"rfrfmfb!", 0xC000004f}},
+ {"jacbd", {"rdrdmdb!", 0xC000006f}},
+ {"jacbb", {"rbrbmbb!", 0xC000009d}},
+ {"jacbl", {"rlrlmlb!", 0xC00000f1}},
+ {"jacbg", {"rgrgmgb!", 0xC0004ffd}},
+ {"jacbh", {"rhrhmhb!", 0xC0006ffd}},
+
+ {"jbs", {"rlvbb?", 0x800000e0}},
+ {"jbc", {"rlvbb?", 0x800000e1}},
+ {"jbss", {"rlvbb?", 0x800000e2}},
+ {"jbcs", {"rlvbb?", 0x800000e3}},
+ {"jbsc", {"rlvbb?", 0x800000e4}},
+ {"jbcc", {"rlvbb?", 0x800000e5}},
+ {"jbssi", {"rlvbb?", 0x800000e6}},
+ {"jbcci", {"rlvbb?", 0x800000e7}},
+ {"jlbs", {"rlb?", 0x800000e8}},
+ {"jlbc", {"rlb?", 0x800000e9}},
+
+ {"jaoblss", {"rlmlb:", 0xC00000f2}},
+ {"jaobleq", {"rlmlb:", 0xC00000f3}},
+ {"jsobgeq", {"mlb:", 0xC00000f4}},
+ {"jsobgtr", {"mlb:", 0xC00000f5}},
+
+/* CASEx has no branch addresses in our conception of it. */
+/* You should use ".word ..." statements after the "case ...". */
+
+ {"", {"", 0}} /* empty is end sentinel */
+
+}; /* synthetic_votstrs */
+
+/*
+ * v i p _ b e g i n ( )
+ *
+ * Call me once before you decode any lines.
+ * I decode votstrs into a hash table at op_hash (which I create).
+ * I return an error text or null.
+ * If you want, I will include the 'synthetic' jXXX instructions in the
+ * instruction table.
+ * You must nominate metacharacters for eg DEC's "#", "@", "^".
+ */
+
+static const char *
+vip_begin (synthetic_too, immediate, indirect, displen)
+ int synthetic_too; /* 1 means include jXXX op-codes. */
+ const char *immediate, *indirect, *displen;
+{
+ const struct vot *vP; /* scan votstrs */
+ const char *retval = 0; /* error text */
+
+ op_hash = hash_new ();
+
+ for (vP = votstrs; *vP->vot_name && !retval; vP++)
+ retval = hash_insert (op_hash, vP->vot_name, (PTR) &vP->vot_detail);
+
+ if (synthetic_too)
+ for (vP = synthetic_votstrs; *vP->vot_name && !retval; vP++)
+ retval = hash_insert (op_hash, vP->vot_name, (PTR) &vP->vot_detail);
+
+#ifndef CONST_TABLE
+ vip_op_defaults (immediate, indirect, displen);
+#endif
+
+ return retval;
+}
+
+
+/*
+ * v i p ( )
+ *
+ * This converts a string into a vax instruction.
+ * The string must be a bare single instruction in dec-vax (with BSD4 frobs)
+ * format.
+ * It provides some error messages: at most one fatal error message (which
+ * stops the scan) and at most one warning message for each operand.
+ * The vax instruction is returned in exploded form, since we have no
+ * knowledge of how you parse (or evaluate) your expressions.
+ * We do however strip off and decode addressing modes and operation
+ * mnemonic.
+ *
+ * The exploded instruction is returned to a struct vit of your choice.
+ * #include "vax-inst.h" to know what a struct vit is.
+ *
+ * This function's value is a string. If it is not "" then an internal
+ * logic error was found: read this code to assign meaning to the string.
+ * No argument string should generate such an error string:
+ * it means a bug in our code, not in the user's text.
+ *
+ * You MUST have called vip_begin() once before using this function.
+ */
+
+static void
+vip (vitP, instring)
+ struct vit *vitP; /* We build an exploded instruction here. */
+ char *instring; /* Text of a vax instruction: we modify. */
+{
+ /* How to bit-encode this opcode. */
+ struct vot_wot *vwP;
+ /* 1/skip whitespace.2/scan vot_how */
+ char *p;
+ char *q;
+ /* counts number of operands seen */
+ unsigned char count;
+ /* scan operands in struct vit */
+ struct vop *operandp;
+ /* error over all operands */
+ const char *alloperr;
+ /* Remember char, (we clobber it with '\0' temporarily). */
+ char c;
+ /* Op-code of this instruction. */
+ vax_opcodeT oc;
+
+ if (*instring == ' ')
+ ++instring; /* Skip leading whitespace. */
+ for (p = instring; *p && *p != ' '; p++);; /* MUST end in end-of-string or exactly 1 space. */
+ /* Scanned up to end of operation-code. */
+ /* Operation-code is ended with whitespace. */
+ if (p - instring == 0)
+ {
+ vitP->vit_error = _("No operator");
+ count = 0;
+ memset (vitP->vit_opcode, '\0', sizeof (vitP->vit_opcode));
+ }
+ else
+ {
+ c = *p;
+ *p = '\0';
+ /*
+ * Here with instring pointing to what better be an op-name, and p
+ * pointing to character just past that.
+ * We trust instring points to an op-name, with no whitespace.
+ */
+ vwP = (struct vot_wot *) hash_find (op_hash, instring);
+ *p = c; /* Restore char after op-code. */
+ if (vwP == 0)
+ {
+ vitP->vit_error = _("Unknown operator");
+ count = 0;
+ memset (vitP->vit_opcode, '\0', sizeof (vitP->vit_opcode));
+ }
+ else
+ {
+ /*
+ * We found a match! So lets pick up as many operands as the
+ * instruction wants, and even gripe if there are too many.
+ * We expect comma to seperate each operand.
+ * We let instring track the text, while p tracks a part of the
+ * struct vot.
+ */
+ const char *howp;
+ /*
+ * The lines below know about 2-byte opcodes starting FD,FE or FF.
+ * They also understand synthetic opcodes. Note:
+ * we return 32 bits of opcode, including bucky bits, BUT
+ * an opcode length is either 8 or 16 bits for vit_opcode_nbytes.
+ */
+ oc = vwP->vot_code; /* The op-code. */
+ vitP->vit_opcode_nbytes = (oc & 0xFF) >= 0xFD ? 2 : 1;
+ md_number_to_chars (vitP->vit_opcode, oc, 4);
+ count = 0; /* no operands seen yet */
+ instring = p; /* point just past operation code */
+ alloperr = "";
+ for (howp = vwP->vot_how, operandp = vitP->vit_operand;
+ !(alloperr && *alloperr) && *howp;
+ operandp++, howp += 2)
+ {
+ /*
+ * Here to parse one operand. Leave instring pointing just
+ * past any one ',' that marks the end of this operand.
+ */
+ if (!howp[1])
+ as_fatal (_("odd number of bytes in operand description"));
+ else if (*instring)
+ {
+ for (q = instring; (c = *q) && c != ','; q++)
+ ;
+ /*
+ * Q points to ',' or '\0' that ends argument. C is that
+ * character.
+ */
+ *q = 0;
+ operandp->vop_width = howp[1];
+ operandp->vop_nbytes = vax_operand_width_size[(unsigned) howp[1]];
+ operandp->vop_access = howp[0];
+ vip_op (instring, operandp);
+ *q = c; /* Restore input text. */
+ if (operandp->vop_error)
+ alloperr = _("Bad operand");
+ instring = q + (c ? 1 : 0); /* next operand (if any) */
+ count++; /* won another argument, may have an operr */
+ }
+ else
+ alloperr = _("Not enough operands");
+ }
+ if (!*alloperr)
+ {
+ if (*instring == ' ')
+ instring++; /* Skip whitespace. */
+ if (*instring)
+ alloperr = _("Too many operands");
+ }
+ vitP->vit_error = alloperr;
+ }
+ }
+ vitP->vit_operands = count;
+}
+
+#ifdef test
+
+/*
+ * Test program for above.
+ */
+
+struct vit myvit; /* build an exploded vax instruction here */
+char answer[100]; /* human types a line of vax assembler here */
+char *mybug; /* "" or an internal logic diagnostic */
+int mycount; /* number of operands */
+struct vop *myvop; /* scan operands from myvit */
+int mysynth; /* 1 means want synthetic opcodes. */
+char my_immediate[200];
+char my_indirect[200];
+char my_displen[200];
+
+main ()
+{
+ char *p;
+
+ printf ("0 means no synthetic instructions. ");
+ printf ("Value for vip_begin? ");
+ gets (answer);
+ sscanf (answer, "%d", &mysynth);
+ printf ("Synthetic opcodes %s be included.\n", mysynth ? "will" : "will not");
+ printf ("enter immediate symbols eg enter # ");
+ gets (my_immediate);
+ printf ("enter indirect symbols eg enter @ ");
+ gets (my_indirect);
+ printf ("enter displen symbols eg enter ^ ");
+ gets (my_displen);
+ if (p = vip_begin (mysynth, my_immediate, my_indirect, my_displen))
+ {
+ error ("vip_begin=%s", p);
+ }
+ printf ("An empty input line will quit you from the vax instruction parser\n");
+ for (;;)
+ {
+ printf ("vax instruction: ");
+ fflush (stdout);
+ gets (answer);
+ if (!*answer)
+ {
+ break; /* out of for each input text loop */
+ }
+ vip (&myvit, answer);
+ if (*myvit.vit_error)
+ {
+ printf ("ERR:\"%s\"\n", myvit.vit_error);
+ }
+ printf ("opcode=");
+ for (mycount = myvit.vit_opcode_nbytes, p = myvit.vit_opcode;
+ mycount;
+ mycount--, p++
+ )
+ {
+ printf ("%02x ", *p & 0xFF);
+ }
+ printf (" operand count=%d.\n", mycount = myvit.vit_operands);
+ for (myvop = myvit.vit_operand; mycount; mycount--, myvop++)
+ {
+ printf ("mode=%xx reg=%xx ndx=%xx len='%c'=%c%c%d. expr=\"",
+ myvop->vop_mode, myvop->vop_reg, myvop->vop_ndx,
+ myvop->vop_short, myvop->vop_access, myvop->vop_width,
+ myvop->vop_nbytes);
+ for (p = myvop->vop_expr_begin; p <= myvop->vop_expr_end; p++)
+ {
+ putchar (*p);
+ }
+ printf ("\"\n");
+ if (myvop->vop_error)
+ {
+ printf (" err:\"%s\"\n", myvop->vop_error);
+ }
+ if (myvop->vop_warn)
+ {
+ printf (" wrn:\"%s\"\n", myvop->vop_warn);
+ }
+ }
+ }
+ vip_end ();
+ exit (EXIT_SUCCESS);
+}
+
+#endif /* #ifdef test */
+
+/* end of vax_ins_parse.c */
+
+/* vax_reg_parse.c - convert a VAX register name to a number */
+
+/* Copyright (C) 1987 Free Software Foundation, Inc. A part of GNU. */
+
+/*
+ * v a x _ r e g _ p a r s e ( )
+ *
+ * Take 3 char.s, the last of which may be `\0` (non-existent)
+ * and return the VAX register number that they represent.
+ *
+ * Return -1 if they don't form a register name. Good names return
+ * a number from 0:15 inclusive.
+ *
+ * Case is not important in a name.
+ *
+ * Register names understood are:
+ *
+ * R0
+ * R1
+ * R2
+ * R3
+ * R4
+ * R5
+ * R6
+ * R7
+ * R8
+ * R9
+ * R10
+ * R11
+ * R12 AP
+ * R13 FP
+ * R14 SP
+ * R15 PC
+ *
+ */
+
+#include <ctype.h>
+#define AP (12)
+#define FP (13)
+#define SP (14)
+#define PC (15)
+
+int /* return -1 or 0:15 */
+vax_reg_parse (c1, c2, c3) /* 3 chars of register name */
+ char c1, c2, c3; /* c3 == 0 if 2-character reg name */
+{
+ int retval; /* return -1:15 */
+
+ retval = -1;
+
+ if (isupper (c1))
+ c1 = tolower (c1);
+ if (isupper (c2))
+ c2 = tolower (c2);
+ if (isdigit (c2) && c1 == 'r')
+ {
+ retval = c2 - '0';
+ if (isdigit (c3))
+ {
+ retval = retval * 10 + c3 - '0';
+ retval = (retval > 15) ? -1 : retval;
+ /* clamp the register value to 1 hex digit */
+ }
+ else if (c3)
+ retval = -1; /* c3 must be '\0' or a digit */
+ }
+ else if (c3) /* There are no three letter regs */
+ retval = -1;
+ else if (c2 == 'p')
+ {
+ switch (c1)
+ {
+ case 's':
+ retval = SP;
+ break;
+ case 'f':
+ retval = FP;
+ break;
+ case 'a':
+ retval = AP;
+ break;
+ default:
+ retval = -1;
+ }
+ }
+ else if (c1 == 'p' && c2 == 'c')
+ retval = PC;
+ else
+ retval = -1;
+ return (retval);
+}
+
+/*
+ * v i p _ o p ( )
+ *
+ * Parse a vax operand in DEC assembler notation.
+ * For speed, expect a string of whitespace to be reduced to a single ' '.
+ * This is the case for GNU AS, and is easy for other DEC-compatible
+ * assemblers.
+ *
+ * Knowledge about DEC VAX assembler operand notation lives here.
+ * This doesn't even know what a register name is, except it believes
+ * all register names are 2 or 3 characters, and lets vax_reg_parse() say
+ * what number each name represents.
+ * It does, however, know that PC, SP etc are special registers so it can
+ * detect addressing modes that are silly for those registers.
+ *
+ * Where possible, it delivers 1 fatal or 1 warning message if the operand
+ * is suspect. Exactly what we test for is still evolving.
+ */
+
+/*
+ * B u g s
+ *
+ * Arg block.
+ *
+ * There were a number of 'mismatched argument type' bugs to vip_op.
+ * The most general solution is to typedef each (of many) arguments.
+ * We used instead a typedef'd argument block. This is less modular
+ * than using seperate return pointers for each result, but runs faster
+ * on most engines, and seems to keep programmers happy. It will have
+ * to be done properly if we ever want to use vip_op as a general-purpose
+ * module (it was designed to be).
+ *
+ * G^
+ *
+ * Doesn't support DEC "G^" format operands. These always take 5 bytes
+ * to express, and code as modes 8F or 9F. Reason: "G^" deprives you of
+ * optimising to (say) a "B^" if you are lucky in the way you link.
+ * When someone builds a linker smart enough to convert "G^" to "B^", "W^"
+ * whenever possible, then we should implement it.
+ * If there is some other use for "G^", feel free to code it in!
+ *
+ *
+ * speed
+ *
+ * If I nested if()s more, I could avoid testing (*err) which would save
+ * time, space and page faults. I didn't nest all those if()s for clarity
+ * and because I think the mode testing can be re-arranged 1st to test the
+ * commoner constructs 1st. Does anybody have statistics on this?
+ *
+ *
+ *
+ * error messages
+ *
+ * In future, we should be able to 'compose' error messages in a scratch area
+ * and give the user MUCH more informative error messages. Although this takes
+ * a little more code at run-time, it will make this module much more self-
+ * documenting. As an example of what sucks now: most error messages have
+ * hardwired into them the DEC VAX metacharacters "#^@" which are nothing like
+ * the Un*x characters "$`*", that most users will expect from this AS.
+ */
+
+/*
+ * The input is a string, ending with '\0'.
+ *
+ * We also require a 'hint' of what kind of operand is expected: so
+ * we can remind caller not to write into literals for instance.
+ *
+ * The output is a skeletal instruction.
+ *
+ * The algorithm has two parts.
+ * 1. extract the syntactic features (parse off all the @^#-()+[] mode crud);
+ * 2. express the @^#-()+[] as some parameters suited to further analysis.
+ *
+ * 2nd step is where we detect the googles of possible invalid combinations
+ * a human (or compiler) might write. Note that if we do a half-way
+ * decent assembler, we don't know how long to make (eg) displacement
+ * fields when we first meet them (because they may not have defined values).
+ * So we must wait until we know how many bits are needed for each address,
+ * then we can know both length and opcodes of instructions.
+ * For reason(s) above, we will pass to our caller a 'broken' instruction
+ * of these major components, from which our caller can generate instructions:
+ * - displacement length I^ S^ L^ B^ W^ unspecified
+ * - mode (many)
+ * - register R0-R15 or absent
+ * - index register R0-R15 or absent
+ * - expression text what we don't parse
+ * - error text(s) why we couldn't understand the operand
+ */
+
+/*
+ * To decode output of this, test errtxt. If errtxt[0] == '\0', then
+ * we had no errors that prevented parsing. Also, if we ever report
+ * an internal bug, errtxt[0] is set non-zero. So one test tells you
+ * if the other outputs are to be taken seriously.
+ */
+
+
+/*
+ * Because this module is useful for both VMS and UN*X style assemblers
+ * and because of the variety of UN*X assemblers we must recognise
+ * the different conventions for assembler operand notation. For example
+ * VMS says "#42" for immediate mode, while most UN*X say "$42".
+ * We permit arbitrary sets of (single) characters to represent the
+ * 3 concepts that DEC writes '#', '@', '^'.
+ */
+
+/* character tests */
+#define VIP_IMMEDIATE 01 /* Character is like DEC # */
+#define VIP_INDIRECT 02 /* Char is like DEC @ */
+#define VIP_DISPLEN 04 /* Char is like DEC ^ */
+
+#define IMMEDIATEP(c) (vip_metacharacters [(c)&0xff]&VIP_IMMEDIATE)
+#define INDIRECTP(c) (vip_metacharacters [(c)&0xff]&VIP_INDIRECT)
+#define DISPLENP(c) (vip_metacharacters [(c)&0xff]&VIP_DISPLEN)
+
+/* We assume 8 bits per byte. Use vip_op_defaults() to set these up BEFORE we
+ * are ever called.
+ */
+
+#if defined(CONST_TABLE)
+#define _ 0,
+#define I VIP_IMMEDIATE,
+#define S VIP_INDIRECT,
+#define D VIP_DISPLEN,
+static const char
+vip_metacharacters[256] =
+{
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /* ^@ ^A ^B ^C ^D ^E ^F ^G ^H ^I ^J ^K ^L ^M ^N ^O*/
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /* ^P ^Q ^R ^S ^T ^U ^V ^W ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */
+ _ _ _ _ I _ _ _ _ _ S _ _ _ _ _ /* sp ! " # $ % & ' ( ) * + , - . / */
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /*0 1 2 3 4 5 6 7 8 9 : ; < = > ?*/
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /*@ A B C D E F G H I J K L M N O*/
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /*P Q R S T U V W X Y Z [ \ ] ^ _*/
+ D _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /*` a b c d e f g h i j k l m n o*/
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /*p q r s t u v w x y z { | } ~ ^?*/
+
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+};
+#undef _
+#undef I
+#undef S
+#undef D
+#else
+static char vip_metacharacters[256];
+
+static void
+vip_op_1 (bit, syms)
+ int bit;
+ const char *syms;
+{
+ unsigned char t;
+
+ while ((t = *syms++) != 0)
+ vip_metacharacters[t] |= bit;
+}
+
+/* Can be called any time. More arguments may appear in future. */
+static void
+vip_op_defaults (immediate, indirect, displen)
+ const char *immediate;
+ const char *indirect;
+ const char *displen;
+{
+ vip_op_1 (VIP_IMMEDIATE, immediate);
+ vip_op_1 (VIP_INDIRECT, indirect);
+ vip_op_1 (VIP_DISPLEN, displen);
+}
+
+#endif
+
+
+/*
+ * Dec defines the semantics of address modes (and values)
+ * by a two-letter code, explained here.
+ *
+ * letter 1: access type
+ *
+ * a address calculation - no data access, registers forbidden
+ * b branch displacement
+ * m read - let go of bus - write back "modify"
+ * r read
+ * v bit field address: like 'a' but registers are OK
+ * w write
+ * space no operator (eg ".long foo") [our convention]
+ *
+ * letter 2: data type (i.e. width, alignment)
+ *
+ * b byte
+ * d double precision floating point (D format)
+ * f single precision floating point (F format)
+ * g G format floating
+ * h H format floating
+ * l longword
+ * o octaword
+ * q quadword
+ * w word
+ * ? simple synthetic branch operand
+ * - unconditional synthetic JSB/JSR operand
+ * ! complex synthetic branch operand
+ *
+ * The '-?!' letter 2's are not for external consumption. They are used
+ * for various assemblers. Generally, all unknown widths are assumed 0.
+ * We don't limit your choice of width character.
+ *
+ * DEC operands are hard work to parse. For example, '@' as the first
+ * character means indirect (deferred) mode but elswhere it is a shift
+ * operator.
+ * The long-winded explanation of how this is supposed to work is
+ * cancelled. Read a DEC vax manual.
+ * We try hard not to parse anything that MIGHT be part of the expression
+ * buried in that syntax. For example if we see @...(Rn) we don't check
+ * for '-' before the '(' because mode @-(Rn) does not exist.
+ *
+ * After parsing we have:
+ *
+ * at 1 if leading '@' (or Un*x '*')
+ * len takes one value from " bilsw". eg B^ -> 'b'.
+ * hash 1 if leading '#' (or Un*x '$')
+ * expr_begin, expr_end the expression we did not parse
+ * even though we don't interpret it, we make use
+ * of its presence or absence.
+ * sign -1: -(Rn) 0: absent +1: (Rn)+
+ * paren 1 if () are around register
+ * reg major register number 0:15 -1 means absent
+ * ndx index register number 0:15 -1 means absent
+ *
+ * Again, I dare not explain it: just trace ALL the code!
+ */
+
+static void
+vip_op (optext, vopP)
+ /* user's input string e.g.: "@B^foo@bar(AP)[FP]:" */
+ char *optext;
+ /* Input fields: vop_access, vop_width.
+ Output fields: _ndx, _reg, _mode, _short, _warn,
+ _error _expr_begin, _expr_end, _nbytes.
+ vop_nbytes : number of bytes in a datum. */
+ struct vop *vopP;
+{
+ /* track operand text forward */
+ char *p;
+ /* track operand text backward */
+ char *q;
+ /* 1 if leading '@' ('*') seen */
+ int at;
+ /* one of " bilsw" */
+ char len;
+ /* 1 if leading '#' ('$') seen */
+ int hash;
+ /* -1, 0 or +1 */
+ int sign = 0;
+ /* 1 if () surround register */
+ int paren = 0;
+ /* register number, -1:absent */
+ int reg = 0;
+ /* index register number -1:absent */
+ int ndx = 0;
+ /* report illegal operand, ""==OK */
+ /* " " is a FAKE error: means we won */
+ /* ANY err that begins with ' ' is a fake. */
+ /* " " is converted to "" before return */
+ const char *err;
+ /* warn about weird modes pf address */
+ const char *wrn;
+ /* preserve q in case we backup */
+ char *oldq = NULL;
+ /* build up 4-bit operand mode here */
+ /* note: index mode is in ndx, this is */
+ /* the major mode of operand address */
+ int mode = 0;
+ /*
+ * Notice how we move wrong-arg-type bugs INSIDE this module: if we
+ * get the types wrong below, we lose at compile time rather than at
+ * lint or run time.
+ */
+ char access_mode; /* vop_access. */
+ char width; /* vop_width. */
+
+ access_mode = vopP->vop_access;
+ width = vopP->vop_width;
+ /* None of our code bugs (yet), no user text errors, no warnings
+ even. */
+ err = wrn = 0;
+
+ p = optext;
+
+ if (*p == ' ') /* Expect all whitespace reduced to ' '. */
+ p++; /* skip over whitespace */
+
+ if ((at = INDIRECTP (*p)) != 0)
+ { /* 1 if *p=='@'(or '*' for Un*x) */
+ p++; /* at is determined */
+ if (*p == ' ') /* Expect all whitespace reduced to ' '. */
+ p++; /* skip over whitespace */
+ }
+
+ /*
+ * This code is subtle. It tries to detect all legal (letter)'^'
+ * but it doesn't waste time explicitly testing for premature '\0' because
+ * this case is rejected as a mismatch against either (letter) or '^'.
+ */
+ {
+ char c;
+
+ c = *p;
+ if (isupper (c))
+ c = tolower (c);
+ if (DISPLENP (p[1]) && strchr ("bilws", len = c))
+ p += 2; /* skip (letter) '^' */
+ else /* no (letter) '^' seen */
+ len = ' '; /* len is determined */
+ }
+
+ if (*p == ' ') /* Expect all whitespace reduced to ' '. */
+ p++; /* skip over whitespace */
+
+ if ((hash = IMMEDIATEP (*p)) != 0) /* 1 if *p=='#' ('$' for Un*x) */
+ p++; /* hash is determined */
+
+ /*
+ * p points to what may be the beginning of an expression.
+ * We have peeled off the front all that is peelable.
+ * We know at, len, hash.
+ *
+ * Lets point q at the end of the text and parse that (backwards).
+ */
+
+ for (q = p; *q; q++)
+ ;
+ q--; /* now q points at last char of text */
+
+ if (*q == ' ' && q >= p) /* Expect all whitespace reduced to ' '. */
+ q--;
+ /* reverse over whitespace, but don't */
+ /* run back over *p */
+
+ /*
+ * As a matter of policy here, we look for [Rn], although both Rn and S^#
+ * forbid [Rn]. This is because it is easy, and because only a sick
+ * cyborg would have [...] trailing an expression in a VAX-like assembler.
+ * A meticulous parser would first check for Rn followed by '(' or '['
+ * and not parse a trailing ']' if it found another. We just ban expressions
+ * ending in ']'.
+ */
+ if (*q == ']')
+ {
+ while (q >= p && *q != '[')
+ q--;
+ /* either q<p or we got matching '[' */
+ if (q < p)
+ err = _("no '[' to match ']'");
+ else
+ {
+ /*
+ * Confusers like "[]" will eventually lose with a bad register
+ * name error. So again we don't need to check for early '\0'.
+ */
+ if (q[3] == ']')
+ ndx = vax_reg_parse (q[1], q[2], 0);
+ else if (q[4] == ']')
+ ndx = vax_reg_parse (q[1], q[2], q[3]);
+ else
+ ndx = -1;
+ /*
+ * Since we saw a ']' we will demand a register name in the [].
+ * If luser hasn't given us one: be rude.
+ */
+ if (ndx < 0)
+ err = _("bad register in []");
+ else if (ndx == PC)
+ err = _("[PC] index banned");
+ else
+ q--; /* point q just before "[...]" */
+ }
+ }
+ else
+ ndx = -1; /* no ']', so no iNDeX register */
+
+ /*
+ * If err = "..." then we lost: run away.
+ * Otherwise ndx == -1 if there was no "[...]".
+ * Otherwise, ndx is index register number, and q points before "[...]".
+ */
+
+ if (*q == ' ' && q >= p) /* Expect all whitespace reduced to ' '. */
+ q--;
+ /* reverse over whitespace, but don't */
+ /* run back over *p */
+ if (!err || !*err)
+ {
+ sign = 0; /* no ()+ or -() seen yet */
+
+ if (q > p + 3 && *q == '+' && q[-1] == ')')
+ {
+ sign = 1; /* we saw a ")+" */
+ q--; /* q points to ')' */
+ }
+
+ if (*q == ')' && q > p + 2)
+ {
+ paren = 1; /* assume we have "(...)" */
+ while (q >= p && *q != '(')
+ q--;
+ /* either q<p or we got matching '(' */
+ if (q < p)
+ err = _("no '(' to match ')'");
+ else
+ {
+ /*
+ * Confusers like "()" will eventually lose with a bad register
+ * name error. So again we don't need to check for early '\0'.
+ */
+ if (q[3] == ')')
+ reg = vax_reg_parse (q[1], q[2], 0);
+ else if (q[4] == ')')
+ reg = vax_reg_parse (q[1], q[2], q[3]);
+ else
+ reg = -1;
+ /*
+ * Since we saw a ')' we will demand a register name in the ')'.
+ * This is nasty: why can't our hypothetical assembler permit
+ * parenthesised expressions? BECAUSE I AM LAZY! That is why.
+ * Abuse luser if we didn't spy a register name.
+ */
+ if (reg < 0)
+ {
+ /* JF allow parenthasized expressions. I hope this works */
+ paren = 0;
+ while (*q != ')')
+ q++;
+ /* err = "unknown register in ()"; */
+ }
+ else
+ q--; /* point just before '(' of "(...)" */
+ /*
+ * If err == "..." then we lost. Run away.
+ * Otherwise if reg >= 0 then we saw (Rn).
+ */
+ }
+ /*
+ * If err == "..." then we lost.
+ * Otherwise paren==1 and reg = register in "()".
+ */
+ }
+ else
+ paren = 0;
+ /*
+ * If err == "..." then we lost.
+ * Otherwise, q points just before "(Rn)", if any.
+ * If there was a "(...)" then paren==1, and reg is the register.
+ */
+
+ /*
+ * We should only seek '-' of "-(...)" if:
+ * we saw "(...)" paren == 1
+ * we have no errors so far ! *err
+ * we did not see '+' of "(...)+" sign < 1
+ * We don't check len. We want a specific error message later if
+ * user tries "x^...-(Rn)". This is a feature not a bug.
+ */
+ if (!err || !*err)
+ {
+ if (paren && sign < 1)/* !sign is adequate test */
+ {
+ if (*q == '-')
+ {
+ sign = -1;
+ q--;
+ }
+ }
+ /*
+ * We have back-tracked over most
+ * of the crud at the end of an operand.
+ * Unless err, we know: sign, paren. If paren, we know reg.
+ * The last case is of an expression "Rn".
+ * This is worth hunting for if !err, !paren.
+ * We wouldn't be here if err.
+ * We remember to save q, in case we didn't want "Rn" anyway.
+ */
+ if (!paren)
+ {
+ if (*q == ' ' && q >= p) /* Expect all whitespace reduced to ' '. */
+ q--;
+ /* reverse over whitespace, but don't */
+ /* run back over *p */
+ if (q > p && q < p + 3) /* room for Rn or Rnn exactly? */
+ reg = vax_reg_parse (p[0], p[1], q < p + 2 ? 0 : p[2]);
+ else
+ reg = -1; /* always comes here if no register at all */
+ /*
+ * Here with a definitive reg value.
+ */
+ if (reg >= 0)
+ {
+ oldq = q;
+ q = p - 1;
+ }
+ }
+ }
+ }
+ /*
+ * have reg. -1:absent; else 0:15
+ */
+
+ /*
+ * We have: err, at, len, hash, ndx, sign, paren, reg.
+ * Also, any remaining expression is from *p through *q inclusive.
+ * Should there be no expression, q==p-1. So expression length = q-p+1.
+ * This completes the first part: parsing the operand text.
+ */
+
+ /*
+ * We now want to boil the data down, checking consistency on the way.
+ * We want: len, mode, reg, ndx, err, p, q, wrn, bug.
+ * We will deliver a 4-bit reg, and a 4-bit mode.
+ */
+
+ /*
+ * Case of branch operand. Different. No L^B^W^I^S^ allowed for instance.
+ *
+ * in: at ?
+ * len ?
+ * hash ?
+ * p:q ?
+ * sign ?
+ * paren ?
+ * reg ?
+ * ndx ?
+ *
+ * out: mode 0
+ * reg -1
+ * len ' '
+ * p:q whatever was input
+ * ndx -1
+ * err " " or error message, and other outputs trashed
+ */
+ /* branch operands have restricted forms */
+ if ((!err || !*err) && access_mode == 'b')
+ {
+ if (at || hash || sign || paren || ndx >= 0 || reg >= 0 || len != ' ')
+ err = _("invalid branch operand");
+ else
+ err = " ";
+ }
+
+ /* Since nobody seems to use it: comment this 'feature'(?) out for now. */
+#ifdef NEVER
+ /*
+ * Case of stand-alone operand. e.g. ".long foo"
+ *
+ * in: at ?
+ * len ?
+ * hash ?
+ * p:q ?
+ * sign ?
+ * paren ?
+ * reg ?
+ * ndx ?
+ *
+ * out: mode 0
+ * reg -1
+ * len ' '
+ * p:q whatever was input
+ * ndx -1
+ * err " " or error message, and other outputs trashed
+ */
+ if ((!err || !*err) && access_mode == ' ')
+ {
+ if (at)
+ err = _("address prohibits @");
+ else if (hash)
+ err = _("address prohibits #");
+ else if (sign)
+ {
+ if (sign < 0)
+ err = _("address prohibits -()");
+ else
+ err = _("address prohibits ()+");
+ }
+ else if (paren)
+ err = _("address prohibits ()");
+ else if (ndx >= 0)
+ err = _("address prohibits []");
+ else if (reg >= 0)
+ err = _("address prohibits register");
+ else if (len != ' ')
+ err = _("address prohibits displacement length specifier");
+ else
+ {
+ err = " "; /* succeed */
+ mode = 0;
+ }
+ }
+#endif /*#Ifdef NEVER*/
+
+ /*
+ * Case of S^#.
+ *
+ * in: at 0
+ * len 's' definition
+ * hash 1 demand
+ * p:q demand not empty
+ * sign 0 by paren==0
+ * paren 0 by "()" scan logic because "S^" seen
+ * reg -1 or nn by mistake
+ * ndx -1
+ *
+ * out: mode 0
+ * reg -1
+ * len 's'
+ * exp
+ * ndx -1
+ */
+ if ((!err || !*err) && len == 's')
+ {
+ if (!hash || paren || at || ndx >= 0)
+ err = _("invalid operand of S^#");
+ else
+ {
+ if (reg >= 0)
+ {
+ /*
+ * SHIT! we saw S^#Rnn ! put the Rnn back in
+ * expression. KLUDGE! Use oldq so we don't
+ * need to know exact length of reg name.
+ */
+ q = oldq;
+ reg = 0;
+ }
+ /*
+ * We have all the expression we will ever get.
+ */
+ if (p > q)
+ err = _("S^# needs expression");
+ else if (access_mode == 'r')
+ {
+ err = " "; /* WIN! */
+ mode = 0;
+ }
+ else
+ err = _("S^# may only read-access");
+ }
+ }
+
+ /*
+ * Case of -(Rn), which is weird case.
+ *
+ * in: at 0
+ * len '
+ * hash 0
+ * p:q q<p
+ * sign -1 by definition
+ * paren 1 by definition
+ * reg present by definition
+ * ndx optional
+ *
+ * out: mode 7
+ * reg present
+ * len ' '
+ * exp "" enforce empty expression
+ * ndx optional warn if same as reg
+ */
+ if ((!err || !*err) && sign < 0)
+ {
+ if (len != ' ' || hash || at || p <= q)
+ err = _("invalid operand of -()");
+ else
+ {
+ err = " "; /* win */
+ mode = 7;
+ if (reg == PC)
+ wrn = _("-(PC) unpredictable");
+ else if (reg == ndx)
+ wrn = _("[]index same as -()register: unpredictable");
+ }
+ }
+
+ /*
+ * We convert "(Rn)" to "@Rn" for our convenience.
+ * (I hope this is convenient: has someone got a better way to parse this?)
+ * A side-effect of this is that "@Rn" is a valid operand.
+ */
+ if (paren && !sign && !hash && !at && len == ' ' && p > q)
+ {
+ at = 1;
+ paren = 0;
+ }
+
+ /*
+ * Case of (Rn)+, which is slightly different.
+ *
+ * in: at
+ * len ' '
+ * hash 0
+ * p:q q<p
+ * sign +1 by definition
+ * paren 1 by definition
+ * reg present by definition
+ * ndx optional
+ *
+ * out: mode 8+@
+ * reg present
+ * len ' '
+ * exp "" enforce empty expression
+ * ndx optional warn if same as reg
+ */
+ if ((!err || !*err) && sign > 0)
+ {
+ if (len != ' ' || hash || p <= q)
+ err = _("invalid operand of ()+");
+ else
+ {
+ err = " "; /* win */
+ mode = 8 + (at ? 1 : 0);
+ if (reg == PC)
+ wrn = _("(PC)+ unpredictable");
+ else if (reg == ndx)
+ wrn = _("[]index same as ()+register: unpredictable");
+ }
+ }
+
+ /*
+ * Case of #, without S^.
+ *
+ * in: at
+ * len ' ' or 'i'
+ * hash 1 by definition
+ * p:q
+ * sign 0
+ * paren 0
+ * reg absent
+ * ndx optional
+ *
+ * out: mode 8+@
+ * reg PC
+ * len ' ' or 'i'
+ * exp
+ * ndx optional
+ */
+ if ((!err || !*err) && hash)
+ {
+ if (len != 'i' && len != ' ')
+ err = _("# conflicts length");
+ else if (paren)
+ err = _("# bars register");
+ else
+ {
+ if (reg >= 0)
+ {
+ /*
+ * SHIT! we saw #Rnn! Put the Rnn back into the expression.
+ * By using oldq, we don't need to know how long Rnn was.
+ * KLUDGE!
+ */
+ q = oldq;
+ reg = -1; /* no register any more */
+ }
+ err = " "; /* win */
+
+ /* JF a bugfix, I think! */
+ if (at && access_mode == 'a')
+ vopP->vop_nbytes = 4;
+
+ mode = (at ? 9 : 8);
+ reg = PC;
+ if ((access_mode == 'm' || access_mode == 'w') && !at)
+ wrn = _("writing or modifying # is unpredictable");
+ }
+ }
+ /*
+ * If !*err, then sign == 0
+ * hash == 0
+ */
+
+ /*
+ * Case of Rn. We seperate this one because it has a few special
+ * errors the remaining modes lack.
+ *
+ * in: at optional
+ * len ' '
+ * hash 0 by program logic
+ * p:q empty
+ * sign 0 by program logic
+ * paren 0 by definition
+ * reg present by definition
+ * ndx optional
+ *
+ * out: mode 5+@
+ * reg present
+ * len ' ' enforce no length
+ * exp "" enforce empty expression
+ * ndx optional warn if same as reg
+ */
+ if ((!err || !*err) && !paren && reg >= 0)
+ {
+ if (len != ' ')
+ err = _("length not needed");
+ else if (at)
+ {
+ err = " "; /* win */
+ mode = 6; /* @Rn */
+ }
+ else if (ndx >= 0)
+ err = _("can't []index a register, because it has no address");
+ else if (access_mode == 'a')
+ err = _("a register has no address");
+ else
+ {
+ /*
+ * Idea here is to detect from length of datum
+ * and from register number if we will touch PC.
+ * Warn if we do.
+ * vop_nbytes is number of bytes in operand.
+ * Compute highest byte affected, compare to PC0.
+ */
+ if ((vopP->vop_nbytes + reg * 4) > 60)
+ wrn = _("PC part of operand unpredictable");
+ err = " "; /* win */
+ mode = 5; /* Rn */
+ }
+ }
+ /*
+ * If !*err, sign == 0
+ * hash == 0
+ * paren == 1 OR reg==-1
+ */
+
+ /*
+ * Rest of cases fit into one bunch.
+ *
+ * in: at optional
+ * len ' ' or 'b' or 'w' or 'l'
+ * hash 0 by program logic
+ * p:q expected (empty is not an error)
+ * sign 0 by program logic
+ * paren optional
+ * reg optional
+ * ndx optional
+ *
+ * out: mode 10 + @ + len
+ * reg optional
+ * len ' ' or 'b' or 'w' or 'l'
+ * exp maybe empty
+ * ndx optional warn if same as reg
+ */
+ if (!err || !*err)
+ {
+ err = " "; /* win (always) */
+ mode = 10 + (at ? 1 : 0);
+ switch (len)
+ {
+ case 'l':
+ mode += 2;
+ case 'w':
+ mode += 2;
+ case ' ': /* assumed B^ until our caller changes it */
+ case 'b':
+ break;
+ }
+ }
+
+ /*
+ * here with completely specified mode
+ * len
+ * reg
+ * expression p,q
+ * ndx
+ */
+
+ if (*err == ' ')
+ err = 0; /* " " is no longer an error */
+
+ vopP->vop_mode = mode;
+ vopP->vop_reg = reg;
+ vopP->vop_short = len;
+ vopP->vop_expr_begin = p;
+ vopP->vop_expr_end = q;
+ vopP->vop_ndx = ndx;
+ vopP->vop_error = err;
+ vopP->vop_warn = wrn;
+}
+
+/*
+
+ Summary of vip_op outputs.
+
+ mode reg len ndx
+ (Rn) => @Rn
+ {@}Rn 5+@ n ' ' optional
+ branch operand 0 -1 ' ' -1
+ S^#foo 0 -1 's' -1
+ -(Rn) 7 n ' ' optional
+ {@}(Rn)+ 8+@ n ' ' optional
+ {@}#foo, no S^ 8+@ PC " i" optional
+ {@}{q^}{(Rn)} 10+@+q option " bwl" optional
+
+ */
+
+#ifdef TEST /* #Define to use this testbed. */
+
+/*
+ * Follows a test program for this function.
+ * We declare arrays non-local in case some of our tiny-minded machines
+ * default to small stacks. Also, helps with some debuggers.
+ */
+
+#include <stdio.h>
+
+char answer[100]; /* human types into here */
+char *p; /* */
+char *myerr;
+char *mywrn;
+char *mybug;
+char myaccess;
+char mywidth;
+char mymode;
+char myreg;
+char mylen;
+char *myleft;
+char *myright;
+char myndx;
+int my_operand_length;
+char my_immediate[200];
+char my_indirect[200];
+char my_displen[200];
+
+main ()
+{
+ printf ("enter immediate symbols eg enter # ");
+ gets (my_immediate);
+ printf ("enter indirect symbols eg enter @ ");
+ gets (my_indirect);
+ printf ("enter displen symbols eg enter ^ ");
+ gets (my_displen);
+ vip_op_defaults (my_immediate, my_indirect, my_displen);
+ for (;;)
+ {
+ printf ("access,width (eg 'ab' or 'wh') [empty line to quit] : ");
+ fflush (stdout);
+ gets (answer);
+ if (!answer[0])
+ exit (EXIT_SUCCESS);
+ myaccess = answer[0];
+ mywidth = answer[1];
+ switch (mywidth)
+ {
+ case 'b':
+ my_operand_length = 1;
+ break;
+ case 'd':
+ my_operand_length = 8;
+ break;
+ case 'f':
+ my_operand_length = 4;
+ break;
+ case 'g':
+ my_operand_length = 16;
+ break;
+ case 'h':
+ my_operand_length = 32;
+ break;
+ case 'l':
+ my_operand_length = 4;
+ break;
+ case 'o':
+ my_operand_length = 16;
+ break;
+ case 'q':
+ my_operand_length = 8;
+ break;
+ case 'w':
+ my_operand_length = 2;
+ break;
+ case '!':
+ case '?':
+ case '-':
+ my_operand_length = 0;
+ break;
+
+ default:
+ my_operand_length = 2;
+ printf ("I dn't understand access width %c\n", mywidth);
+ break;
+ }
+ printf ("VAX assembler instruction operand: ");
+ fflush (stdout);
+ gets (answer);
+ mybug = vip_op (answer, myaccess, mywidth, my_operand_length,
+ &mymode, &myreg, &mylen, &myleft, &myright, &myndx,
+ &myerr, &mywrn);
+ if (*myerr)
+ {
+ printf ("error: \"%s\"\n", myerr);
+ if (*mybug)
+ printf (" bug: \"%s\"\n", mybug);
+ }
+ else
+ {
+ if (*mywrn)
+ printf ("warning: \"%s\"\n", mywrn);
+ mumble ("mode", mymode);
+ mumble ("register", myreg);
+ mumble ("index", myndx);
+ printf ("width:'%c' ", mylen);
+ printf ("expression: \"");
+ while (myleft <= myright)
+ putchar (*myleft++);
+ printf ("\"\n");
+ }
+ }
+}
+
+mumble (text, value)
+ char *text;
+ int value;
+{
+ printf ("%s:", text);
+ if (value >= 0)
+ printf ("%xx", value);
+ else
+ printf ("ABSENT");
+ printf (" ");
+}
+
+#endif /* ifdef TEST */
+
+/* end: vip_op.c */
+
+const int md_short_jump_size = 3;
+const int md_long_jump_size = 6;
+const int md_reloc_size = 8; /* Size of relocation record */
+
+void
+md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
+ char *ptr;
+ addressT from_addr, to_addr;
+ fragS *frag;
+ symbolS *to_symbol;
+{
+ valueT offset;
+
+ /* This former calculation was off by two:
+ offset = to_addr - (from_addr + 1);
+ We need to account for the one byte instruction and also its
+ two byte operand. */
+ offset = to_addr - (from_addr + 1 + 2);
+ *ptr++ = VAX_BRW; /* branch with word (16 bit) offset */
+ md_number_to_chars (ptr, offset, 2);
+}
+
+void
+md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
+ char *ptr;
+ addressT from_addr, to_addr;
+ fragS *frag;
+ symbolS *to_symbol;
+{
+ valueT offset;
+
+ offset = to_addr - S_GET_VALUE (to_symbol);
+ *ptr++ = VAX_JMP; /* arbitrary jump */
+ *ptr++ = VAX_ABSOLUTE_MODE;
+ md_number_to_chars (ptr, offset, 4);
+ fix_new (frag, ptr - frag->fr_literal, 4, to_symbol, (long) 0, 0, NO_RELOC);
+}
+
+#ifdef OBJ_VMS
+CONST char *md_shortopts = "d:STt:V+1h:Hv::";
+#else
+CONST char *md_shortopts = "d:STt:V";
+#endif
+struct option md_longopts[] = {
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof(md_longopts);
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ switch (c)
+ {
+ case 'S':
+ as_warn (_("SYMBOL TABLE not implemented"));
+ break;
+
+ case 'T':
+ as_warn (_("TOKEN TRACE not implemented"));
+ break;
+
+ case 'd':
+ as_warn (_("Displacement length %s ignored!"), arg);
+ break;
+
+ case 't':
+ as_warn (_("I don't need or use temp. file \"%s\"."), arg);
+ break;
+
+ case 'V':
+ as_warn (_("I don't use an interpass file! -V ignored"));
+ break;
+
+#ifdef OBJ_VMS
+ case '+': /* For g++. Hash any name > 31 chars long. */
+ flag_hash_long_names = 1;
+ break;
+
+ case '1': /* For backward compatibility */
+ flag_one = 1;
+ break;
+
+ case 'H': /* Show new symbol after hash truncation */
+ flag_show_after_trunc = 1;
+ break;
+
+ case 'h': /* No hashing of mixed-case names */
+ {
+ extern char vms_name_mapping;
+ vms_name_mapping = atoi (arg);
+ flag_no_hash_mixed_case = 1;
+ }
+ break;
+
+ case 'v':
+ {
+ extern char *compiler_version_string;
+ if (!arg || !*arg || access (arg, 0) == 0)
+ return 0; /* have caller show the assembler version */
+ compiler_version_string = arg;
+ }
+ break;
+#endif
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+ fprintf(stream, _("\
+VAX options:\n\
+-d LENGTH ignored\n\
+-J ignored\n\
+-S ignored\n\
+-t FILE ignored\n\
+-T ignored\n\
+-V ignored\n"));
+#ifdef OBJ_VMS
+ fprintf (stream, _("\
+VMS options:\n\
+-+ hash encode names longer than 31 characters\n\
+-1 `const' handling compatible with gcc 1.x\n\
+-H show new symbol after hash truncation\n\
+-h NUM don't hash mixed-case names, and adjust case:\n\
+ 0 = upper, 2 = lower, 3 = preserve case\n\
+-v\"VERSION\" code being assembled was produced by compiler \"VERSION\"\n"));
+#endif
+}
+
+/* We have no need to default values of symbols. */
+
+/* ARGSUSED */
+symbolS *
+md_undefined_symbol (name)
+ char *name;
+{
+ return 0;
+}
+
+/* Round up a section size to the appropriate boundary. */
+valueT
+md_section_align (segment, size)
+ segT segment;
+ valueT size;
+{
+ return size; /* Byte alignment is fine */
+}
+
+/* Exactly what point is a PC-relative offset relative TO?
+ On the vax, they're relative to the address of the offset, plus
+ its size. (??? Is this right? FIXME-SOON) */
+long
+md_pcrel_from (fixP)
+ fixS *fixP;
+{
+ return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
+}
+
+/* end of tc-vax.c */
diff --git a/gas/config/tc-vax.h b/gas/config/tc-vax.h
new file mode 100644
index 0000000000..b6791f7f58
--- /dev/null
+++ b/gas/config/tc-vax.h
@@ -0,0 +1,45 @@
+/* tc-vax.h -- Header file for tc-vax.c.
+ Copyright (C) 1987, 91, 92, 93, 95, 96, 1997 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#define TC_VAX 1
+
+#define TARGET_BYTES_BIG_ENDIAN 0
+
+#define NO_RELOC 0
+#define NOP_OPCODE 0x01
+
+#define tc_aout_pre_write_hook(x) {;} /* not used */
+#define tc_crawl_symbol_chain(a) {;} /* not used */
+#define tc_headers_hook(a) {;} /* not used */
+#define md_operand(x)
+
+long md_chars_to_number PARAMS ((unsigned char *, int));
+
+extern const struct relax_type md_relax_table[];
+#define TC_GENERIC_RELAX_TABLE md_relax_table
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of tc-vax.h */
diff --git a/gas/config/tc-w65.c b/gas/config/tc-w65.c
new file mode 100644
index 0000000000..72201e7b76
--- /dev/null
+++ b/gas/config/tc-w65.c
@@ -0,0 +1,1219 @@
+/* tc-w65.c -- Assemble code for the W65816
+ Copyright (C) 1995, 1998 Free Software Foundation.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/*
+ Written By Steve Chamberlain
+ sac@cygnus.com
+ */
+
+#include <stdio.h>
+#include "as.h"
+#include "bfd.h"
+#include "subsegs.h"
+#define DEFINE_TABLE
+#include "../opcodes/w65-opc.h"
+#include <ctype.h>
+
+const char comment_chars[] = "!";
+CONST char line_separator_chars[] = ";";
+const char line_comment_chars[] = "!#";
+
+/* This table describes all the machine specific pseudo-ops the assembler
+ has to support. The fields are:
+ pseudo-op name without dot
+ function to call to execute this pseudo-op
+ Integer arg to pass to the function
+ */
+
+#define OP_BCC 0x90
+#define OP_BCS 0xB0
+#define OP_BEQ 0xF0
+#define OP_BMI 0x30
+#define OP_BNE 0xD0
+#define OP_BPL 0x10
+#define OP_BRA 0x80
+#define OP_BRL 0x82
+#define OP_BVC 0x50
+#define OP_BVS 0x70
+
+void s_longa ();
+const pseudo_typeS md_pseudo_table[] =
+{
+ {"int", cons, 2},
+ {"word", cons, 2},
+ {"longa", s_longa, 0},
+ {"longi", s_longa, 1},
+ {0, 0, 0}
+};
+
+
+void cons ();
+void s_align_bytes ();
+
+
+/*int md_reloc_size; */
+
+static int relax; /* set if -relax seen */
+
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* As in 0f12.456 */
+/* or 0d1.2345e12 */
+const char FLT_CHARS[] = "rRsSfFdDxXpP";
+
+
+
+static struct hash_control *opcode_hash_control; /* Opcode mnemonics */
+
+int M; /* M flag */
+int X; /* X flag */
+
+
+
+
+#define C(a,b) ENCODE_RELAX(a,b)
+#define ENCODE_RELAX(what,length) (((what) << 2) + (length))
+
+#define GET_WHAT(x) ((x>>2))
+
+#define BYTE_DISP 1
+#define WORD_DISP 2
+#define UNDEF_BYTE_DISP 0
+#define UNDEF_WORD_DISP 3
+
+#define COND_BRANCH 1
+#define UNCOND_BRANCH 2
+#define END 3
+
+#define BYTE_F 127 /* How far we can branch forwards */
+#define BYTE_B -126 /* How far we can branch backwards */
+#define WORD_F 32767
+#define WORD_B 32768
+
+relax_typeS md_relax_table[C (END, 0)];
+
+/*
+ This function is called once, at assembler startup time. This should
+ set up all the tables, etc that the MD part of the assembler needs
+ */
+
+
+void
+s_longa (xmode)
+{
+ int *p = xmode ? &X : &M;
+ while (*input_line_pointer == ' ')
+ input_line_pointer++;
+ if (strncmp (input_line_pointer, "on", 2) == 0)
+ {
+ input_line_pointer += 2;
+ *p = 0;
+ }
+ else if (strncmp (input_line_pointer, "off", 3) == 0)
+ {
+ *p = 1;
+ input_line_pointer += 3;
+ }
+ else
+ as_bad (_("need on or off."));
+ demand_empty_rest_of_line ();
+}
+void
+md_begin ()
+{
+ relax_typeS *table;
+ struct opinfo *opcode;
+ char *prev_name = "";
+
+ opcode_hash_control = hash_new ();
+
+ /* Insert unique names into hash table */
+ for (opcode = optable; opcode->name; opcode++)
+ {
+ if (strcmp (prev_name, opcode->name))
+ {
+ prev_name = opcode->name;
+ hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
+ }
+ else
+ {
+ /* Make all the opcodes with the same name point to the same
+ string */
+ opcode->name = prev_name;
+ }
+ }
+
+
+ /* Initialize the relax table. We use a local variable to avoid
+ warnings about modifying a supposedly const data structure. */
+ table = (relax_typeS *) md_relax_table;
+ table[C (COND_BRANCH, BYTE_DISP)].rlx_forward = BYTE_F;
+ table[C (COND_BRANCH, BYTE_DISP)].rlx_backward = BYTE_B;
+ table[C (COND_BRANCH, BYTE_DISP)].rlx_length = 2;
+ table[C (COND_BRANCH, BYTE_DISP)].rlx_more = C (COND_BRANCH, WORD_DISP);
+
+ table[C (COND_BRANCH, WORD_DISP)].rlx_forward = WORD_F;
+ table[C (COND_BRANCH, WORD_DISP)].rlx_backward = WORD_B;
+ table[C (COND_BRANCH, WORD_DISP)].rlx_length = 5;
+ table[C (COND_BRANCH, WORD_DISP)].rlx_more = 0;
+
+ table[C (UNCOND_BRANCH, BYTE_DISP)].rlx_forward = BYTE_F;
+ table[C (UNCOND_BRANCH, BYTE_DISP)].rlx_backward = BYTE_B;
+ table[C (UNCOND_BRANCH, BYTE_DISP)].rlx_length = 2;
+ table[C (UNCOND_BRANCH, BYTE_DISP)].rlx_more = C (UNCOND_BRANCH, WORD_DISP);
+
+ table[C (UNCOND_BRANCH, WORD_DISP)].rlx_forward = WORD_F;
+ table[C (UNCOND_BRANCH, WORD_DISP)].rlx_backward = WORD_B;
+ table[C (UNCOND_BRANCH, WORD_DISP)].rlx_length = 3;
+ table[C (UNCOND_BRANCH, WORD_DISP)].rlx_more = 0;
+
+ flag_signed_overflow_ok = 1;
+}
+
+static expressionS immediate; /* absolute expression */
+static expressionS immediate1; /* absolute expression */
+
+
+static symbolS *
+dot ()
+{
+ const char *fake;
+
+ /* JF: '.' is pseudo symbol with value of current location
+ in current segment. */
+ fake = FAKE_LABEL_NAME;
+ return symbol_new (fake,
+ now_seg,
+ (valueT) frag_now_fix (),
+ frag_now);
+
+}
+
+int expr_size;
+int expr_shift;
+int tc_cons_reloc;
+void
+w65_expression (dest, bytes)
+ expressionS *dest;
+ unsigned int bytes;
+{
+ expr_size = 0;
+ expr_shift = 0;
+ tc_cons_reloc = 0;
+ while (*input_line_pointer == ' ')
+ input_line_pointer++;
+
+ if (*input_line_pointer == '<')
+ {
+ expr_size = 1;
+ input_line_pointer++;
+ }
+ else if (*input_line_pointer == '>')
+ {
+ expr_shift = 1;
+ input_line_pointer++;
+ }
+ else if (*input_line_pointer == '^')
+ {
+ expr_shift = 2;
+ input_line_pointer++;
+ }
+
+ expr (0, dest);
+}
+
+int amode;
+static
+char *
+parse_exp (s, bytes)
+ char *s;
+ int bytes;
+{
+ char *save;
+ char *new;
+
+ save = input_line_pointer;
+ input_line_pointer = s;
+ w65_expression (&immediate, bytes);
+ if (immediate.X_op == O_absent)
+ as_bad (_("missing operand"));
+ new = input_line_pointer;
+ input_line_pointer = save;
+ return new;
+}
+
+
+static
+char *
+get_operands (info, ptr)
+ struct opinfo *info;
+ char *ptr;
+{
+ register int override_len = 0;
+ register int bytes = 0;
+ while (*ptr == ' ')
+ ptr++;
+
+ if (ptr[0] == '#')
+ {
+ ptr++;
+ switch (info->amode)
+ {
+ case ADDR_IMMTOI:
+ bytes = X ? 1 : 2;
+ amode = ADDR_IMMTOI;
+ break;
+ case ADDR_IMMTOA:
+ bytes = M ? 1 : 2;
+ amode = ADDR_IMMTOA;
+ break;
+ case ADDR_IMMCOP:
+ bytes = 1;
+ amode = ADDR_IMMCOP;
+ break;
+ case ADDR_DIR:
+ bytes = 2;
+ amode = ADDR_ABS;
+ break;
+ default:
+ abort ();
+ break;
+ }
+ ptr = parse_exp (ptr);
+ }
+ else if (ptr[0] == '!')
+ {
+ ptr = parse_exp (ptr + 1);
+ if (ptr[0] == ',')
+ {
+ if (ptr[1] == 'y')
+ {
+ amode = ADDR_ABS_IDX_Y;
+ bytes = 2;
+ ptr += 2;
+ }
+ else if (ptr[1] == 'x')
+ {
+ amode = ADDR_ABS_IDX_X;
+ bytes = 2;
+ ptr += 2;
+ }
+ else
+ {
+ as_bad (_("syntax error after <exp"));
+ }
+ }
+ else
+ {
+ amode = ADDR_ABS;
+ bytes = 2;
+ }
+ }
+ else if (ptr[0] == '>')
+ {
+ ptr = parse_exp (ptr + 1);
+ if (ptr[0] == ',' && ptr[1] == 'x')
+ {
+ amode = ADDR_ABS_LONG_IDX_X;
+ bytes = 3;
+ ptr += 2;
+ }
+ else
+ {
+ amode = ADDR_ABS_LONG;
+ bytes = 3;
+ }
+ }
+ else if (ptr[0] == '<')
+ {
+ ptr = parse_exp (ptr + 1);
+ if (ptr[0] == ',')
+ {
+ if (ptr[1] == 'y')
+ {
+ amode = ADDR_DIR_IDX_Y;
+ ptr += 2;
+ bytes = 2;
+ }
+ else if (ptr[1] == 'x')
+ {
+ amode = ADDR_DIR_IDX_X;
+ ptr += 2;
+ bytes = 2;
+ }
+ else
+ {
+ as_bad (_("syntax error after <exp"));
+ }
+ }
+ else
+ {
+ amode = ADDR_DIR;
+ bytes = 1;
+ }
+ }
+ else if (ptr[0] == 'a')
+ {
+ amode = ADDR_ACC;
+ }
+ else if (ptr[0] == '(')
+ {
+ /* Look for (exp),y
+ (<exp),y
+ (exp,x)
+ (<exp,x)
+ (exp)
+ (!exp)
+ (exp)
+ (<exp)
+ (exp,x)
+ (!exp,x)
+ (exp,s)
+ (exp,s),y */
+
+ ptr++;
+ if (ptr[0] == '<')
+ {
+ override_len = 1;
+ ptr++;
+ }
+ else if (ptr[0] == '!')
+ {
+ override_len = 2;
+ ptr++;
+ }
+ else if (ptr[0] == '>')
+ {
+ override_len = 3;
+ ptr++;
+ }
+ else
+ {
+ override_len = 0;
+ }
+ ptr = parse_exp (ptr);
+
+ if (ptr[0] == ',')
+ {
+ ptr++;
+ if (ptr[0] == 'x' && ptr[1] == ')')
+ {
+ ptr += 2;
+
+ if (override_len == 1)
+ {
+ amode = ADDR_DIR_IDX_IND_X;
+ bytes = 2;
+ }
+ else
+ {
+ amode = ADDR_ABS_IND_IDX;
+ bytes = 2;
+ }
+ }
+ else if (ptr[0] == 's' && ptr[1] == ')' && ptr[2] == ',' && ptr[3] == 'y')
+ {
+ amode = ADDR_STACK_REL_INDX_IDX;
+ bytes = 1;
+ ptr += 4;
+ }
+ }
+ else if (ptr[0] == ')')
+ {
+ if (ptr[1] == ',' && ptr[2] == 'y')
+ {
+ amode = ADDR_DIR_IND_IDX_Y;
+ ptr += 3;
+ bytes = 2;
+ }
+ else
+ {
+ if (override_len == 1)
+ {
+ amode = ADDR_DIR_IND;
+ bytes = 1;
+ }
+ else
+ {
+ amode = ADDR_ABS_IND;
+ bytes = 2;
+ }
+ ptr++;
+
+ }
+ }
+
+ }
+ else if (ptr[0] == '[')
+ {
+ ptr = parse_exp (ptr + 1);
+ if (ptr[0] == ']')
+ {
+ ptr++;
+ if (ptr[0] == ',' && ptr[1] == 'y')
+ {
+ bytes = 1;
+ amode = ADDR_DIR_IND_IDX_Y_LONG;
+ ptr += 2;
+ }
+ else
+ {
+ if (info->code == O_jmp)
+ {
+ bytes = 2;
+ amode = ADDR_ABS_IND_LONG;
+ }
+ else
+{
+ bytes = 1;
+
+ amode = ADDR_DIR_IND_LONG;
+ }
+ }
+ }
+ }
+ else
+ {
+ ptr = parse_exp (ptr, 2);
+ if (ptr[0] == ',')
+ {
+ if (ptr[1] == 'y')
+ {
+ if (override_len == 1)
+ {
+ bytes = 1;
+ amode = ADDR_DIR_IDX_Y;
+ }
+ else
+ {
+ amode = ADDR_ABS_IDX_Y;
+ bytes = 2;
+ }
+ ptr += 2;
+ }
+ else if (ptr[1] == 'x')
+ {
+ if (override_len == 1)
+ {
+ amode = ADDR_DIR_IDX_X;
+ bytes = 1;
+ }
+ else
+ {
+ amode = ADDR_ABS_IDX_X;
+ bytes = 2;
+ }
+ ptr += 2;
+ }
+ else if (ptr[1] == 's')
+ {
+ bytes = 1;
+ amode = ADDR_STACK_REL;
+ ptr += 2;
+ }
+ else
+ {
+ bytes = 1;
+ immediate1 = immediate;
+ ptr = parse_exp (ptr + 1);
+ amode = ADDR_BLOCK_MOVE;
+ }
+ }
+ else
+ {
+ switch (info->amode)
+ {
+ case ADDR_PC_REL:
+ amode = ADDR_PC_REL;
+ bytes = 1;
+ break;
+ case ADDR_PC_REL_LONG:
+ amode = ADDR_PC_REL_LONG;
+ bytes = 2;
+ break;
+ default:
+ if (override_len == 1)
+ {
+ amode = ADDR_DIR;
+ bytes = 1;
+ }
+ else if (override_len == 3)
+ {
+ bytes = 3;
+ amode = ADDR_ABS_LONG;
+ }
+ else
+ {
+ amode = ADDR_ABS;
+ bytes = 2;
+ }
+ }
+ }
+ }
+
+ switch (bytes)
+ {
+ case 1:
+ switch (expr_shift)
+ {
+ case 0:
+ if (amode == ADDR_DIR)
+ tc_cons_reloc = R_W65_DP;
+ else
+tc_cons_reloc = R_W65_ABS8;
+ break;
+ case 1:
+ tc_cons_reloc = R_W65_ABS8S8;
+ break;
+ case 2:
+ tc_cons_reloc = R_W65_ABS8S16;
+ break;
+ }
+ break;
+ case 2:
+ switch (expr_shift)
+ {
+ case 0:
+ tc_cons_reloc = R_W65_ABS16;
+ break;
+ case 1:
+ tc_cons_reloc = R_W65_ABS16S8;
+ break;
+ case 2:
+ tc_cons_reloc = R_W65_ABS16S16;
+ break;
+ }
+ }
+ return ptr;
+}
+
+/* Passed a pointer to a list of opcodes which use different
+ addressing modes, return the opcode which matches the opcodes
+ provided
+ */
+
+static
+struct opinfo *
+get_specific (opcode)
+ struct opinfo *opcode;
+{
+ int ocode = opcode->code;
+
+ for (; opcode->code == ocode; opcode++)
+ {
+ if (opcode->amode == amode)
+ return opcode;
+ }
+ return 0;
+}
+
+int
+check (operand, low, high)
+ expressionS *operand;
+ int low;
+ int high;
+{
+ if (operand->X_op != O_constant
+ || operand->X_add_number < low
+ || operand->X_add_number > high)
+ {
+ as_bad ("operand must be absolute in range %d..%d", low, high);
+ }
+ return operand->X_add_number;
+}
+
+
+static int log2[] =
+{0, 0, 1, 0, 2};
+
+/* Now we know what sort of opcodes it is, lets build the bytes -
+ */
+static void
+build_Mytes (opcode)
+ struct opinfo *opcode;
+{
+ int size;
+ int type;
+ int pcrel;
+ char *output;
+
+ if (opcode->amode == ADDR_IMPLIED)
+ {
+ output = frag_more (1);
+ }
+ else if (opcode->amode == ADDR_PC_REL)
+ {
+ int type;
+ /* This is a relaxable insn, so we do some special handling */
+ type = opcode->val == OP_BRA ? UNCOND_BRANCH : COND_BRANCH;
+ output = frag_var (rs_machine_dependent,
+ md_relax_table[C (type, WORD_DISP)].rlx_length,
+ md_relax_table[C (type, BYTE_DISP)].rlx_length,
+ C (type, UNDEF_BYTE_DISP),
+ immediate.X_add_symbol,
+ immediate.X_add_number,
+ 0);
+ }
+ else
+ {
+ switch (opcode->amode)
+ {
+ GETINFO (size, type, pcrel);
+ }
+
+ /* If something special was done in the
+ expression modify the reloc type */
+ if (tc_cons_reloc)
+ {
+ type = tc_cons_reloc;
+ }
+
+
+
+ /* 1 byte for the opcode + the bytes for the addrmode */
+ output = frag_more (size + 1);
+
+ if (opcode->amode == ADDR_BLOCK_MOVE)
+ {
+ /* Two relocs for this one */
+ fix_new_exp (frag_now,
+ output + 1 - frag_now->fr_literal,
+ 1,
+ &immediate,
+ 0,
+ R_W65_ABS8S16);
+
+ fix_new_exp (frag_now,
+ output + 2 - frag_now->fr_literal,
+ 1,
+ &immediate1,
+ 0,
+ R_W65_ABS8S16);
+ }
+ else if (type >= 0
+ && opcode->amode != ADDR_IMPLIED
+ && opcode->amode != ADDR_ACC
+ && opcode->amode != ADDR_STACK)
+ {
+ fix_new_exp (frag_now,
+ output + 1 - frag_now->fr_literal,
+ size,
+ &immediate,
+ pcrel,
+ type);
+ }
+ }
+ output[0] = opcode->val;
+}
+
+/* This is the guts of the machine-dependent assembler. STR points to a
+ machine dependent instruction. This function is supposed to emit
+ the frags/bytes it assembles to.
+ */
+
+void
+md_assemble (str)
+ char *str;
+{
+ unsigned char *op_start;
+ unsigned char *op_end;
+ struct opinfo *opcode;
+ char name[20];
+ int nlen = 0;
+ char *p;
+
+ /* Drop leading whitespace */
+ while (*str == ' ')
+ str++;
+
+ /* all opcodes are three letters */
+ name[0] = str[0];
+ name[1] = str[1];
+ name[2] = str[2];
+ name[3] = 0;
+
+ tc_cons_reloc = 0;
+ str += 3;
+ opcode = (struct opinfo *) hash_find (opcode_hash_control, name);
+
+ if (opcode == NULL)
+ {
+ as_bad (_("unknown opcode"));
+ return;
+ }
+
+ if (opcode->amode != ADDR_IMPLIED
+ && opcode->amode != ADDR_STACK)
+ {
+ get_operands (opcode, str);
+ opcode = get_specific (opcode);
+ }
+
+ if (opcode == 0)
+ {
+ /* Couldn't find an opcode which matched the operands */
+
+
+ char *where = frag_more (1);
+
+ where[0] = 0x0;
+ where[1] = 0x0;
+ as_bad (_("invalid operands for opcode"));
+ return;
+ }
+
+ build_Mytes (opcode);
+}
+
+
+void
+DEFUN (tc_crawl_symbol_chain, (headers),
+ object_headers * headers)
+{
+ printf (_("call to tc_crawl_symbol_chain \n"));
+}
+
+symbolS *
+DEFUN (md_undefined_symbol, (name),
+ char *name)
+{
+ return 0;
+}
+
+void
+DEFUN (tc_headers_hook, (headers),
+ object_headers * headers)
+{
+ printf (_("call to tc_headers_hook \n"));
+}
+
+/* Various routines to kill one day */
+/* Equal to MAX_PRECISION in atof-ieee.c */
+#define MAX_LITTLENUMS 6
+
+/* Turn a string in input_line_pointer into a floating point constant of type
+ type, and store the appropriate bytes in *litP. The number of LITTLENUMS
+ emitted is stored in *sizeP . An error message is returned, or NULL on OK.
+ */
+char *
+md_atof (type, litP, sizeP)
+ char type;
+ char *litP;
+ int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ char *t;
+ char *atof_ieee ();
+
+ switch (type)
+ {
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ prec = 4;
+ break;
+
+ case 'x':
+ case 'X':
+ prec = 6;
+ break;
+
+ case 'p':
+ case 'P':
+ prec = 6;
+ break;
+
+ default:
+ *sizeP = 0;
+ return _("Bad call to MD_NTOF()");
+ }
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+
+ *sizeP = prec * sizeof (LITTLENUM_TYPE);
+ for (wordP = words + prec - 1; prec--;)
+ {
+ md_number_to_chars (litP, (valueT) (*wordP--), sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+ return 0;
+}
+
+int
+md_parse_option (c,a)
+ int c;
+ char *a;
+
+{
+ return 1;
+}
+
+void
+tc_Nout_fix_to_chars ()
+{
+ printf (_("call to tc_Nout_fix_to_chars \n"));
+ abort ();
+}
+
+/*
+called after relaxing, change the frags so they know how big they are
+*/
+void
+md_convert_frag (headers, seg, fragP)
+ object_headers *headers;
+ segT seg;
+ fragS *fragP;
+{
+ int disp_size = 0;
+ int inst_size = 0;
+ unsigned char *buffer = (unsigned char *) (fragP->fr_fix + fragP->fr_literal);
+
+ switch (fragP->fr_subtype)
+ {
+ case C (COND_BRANCH, BYTE_DISP):
+ case C (UNCOND_BRANCH, BYTE_DISP):
+ disp_size = 1;
+ inst_size = 1;
+ break;
+
+ /* cond branches to a known 16 bit displacement */
+ case C (COND_BRANCH, WORD_DISP):
+ switch (buffer[0])
+ {
+ case OP_BCC:
+ case OP_BCS:
+ case OP_BEQ:
+ case OP_BMI:
+ case OP_BNE:
+ case OP_BPL:
+ case OP_BVS:
+ case OP_BVC:
+ /* Invert the sense of the test */
+ buffer[0] ^= 0x20;
+ buffer[1] = 3; /* Jump over following brl */
+ buffer[2] = OP_BRL;
+ buffer[3] = 0;
+ buffer[4] = 0;
+ disp_size = 2;
+ inst_size = 3;
+ break;
+ default:
+ abort ();
+ }
+ break;
+ case C (UNCOND_BRANCH, WORD_DISP):
+ /* Unconditional branches to a known 16 bit displacement */
+
+ switch (buffer[0])
+ {
+ case OP_BRA:
+ buffer[0] = OP_BRL;
+ disp_size = 2;
+ inst_size = 1;
+ break;
+ default:
+ abort ();
+ }
+ break;
+ /* got to create a branch over a reloc here */
+ case C (COND_BRANCH, UNDEF_WORD_DISP):
+ buffer[0] ^= 0x20; /* invert test */
+ buffer[1] = 3;
+ buffer[2] = OP_BRL;
+ buffer[3] = 0;
+ buffer[4] = 0;
+ fix_new (fragP,
+ fragP->fr_fix + 3,
+ 4,
+ fragP->fr_symbol,
+ fragP->fr_offset,
+ 0,
+ R_W65_PCR16);
+
+ fragP->fr_fix += disp_size + inst_size;
+ fragP->fr_var = 0;
+ break;
+ case C (UNCOND_BRANCH, UNDEF_WORD_DISP):
+ buffer[0] = OP_BRL;
+ buffer[1] = 0;
+ buffer[2] = 0;
+ fix_new (fragP,
+ fragP->fr_fix + 1,
+ 4,
+ fragP->fr_symbol,
+ fragP->fr_offset,
+ 0,
+ R_W65_PCR16);
+
+ fragP->fr_fix += disp_size + inst_size;
+ fragP->fr_var = 0;
+ break;
+ default:
+ abort ();
+ }
+ if (inst_size)
+ {
+ /* Get the address of the end of the instruction */
+ int next_inst = fragP->fr_fix + fragP->fr_address + disp_size + inst_size;
+ int targ_addr = (S_GET_VALUE (fragP->fr_symbol) +
+ fragP->fr_offset);
+ int disp = targ_addr - next_inst;
+
+ md_number_to_chars (buffer + inst_size, disp, disp_size);
+ fragP->fr_fix += disp_size + inst_size;
+ fragP->fr_var = 0;
+ }
+}
+
+
+valueT
+DEFUN (md_section_align, (seg, size),
+ segT seg AND
+ valueT size)
+{
+ return ((size + (1 << section_alignment[(int) seg]) - 1)
+ & (-1 << section_alignment[(int) seg]));
+
+}
+
+void
+md_apply_fix (fixP, val)
+ fixS *fixP;
+ long val;
+{
+ char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
+ int addr = fixP->fx_frag->fr_address + fixP->fx_where;
+
+ if (fixP->fx_r_type == 0)
+ {
+ if (fixP->fx_size == 1)
+ fixP->fx_r_type = R_W65_ABS8;
+ else
+ fixP->fx_r_type = R_W65_ABS16;
+ }
+
+ switch (fixP->fx_r_type)
+ {
+ case R_W65_ABS8S16:
+ val >>= 8;
+ case R_W65_ABS8S8:
+ val >>= 8;
+ case R_W65_ABS8:
+ *buf++ = val;
+ break;
+ case R_W65_ABS16S16:
+ val >>= 8;
+ case R_W65_ABS16S8:
+ val >>= 8;
+ case R_W65_ABS16:
+ *buf++ = val >> 0;
+ *buf++ = val >> 8;
+ break;
+ case R_W65_ABS24:
+ *buf++ = val >> 0;
+ *buf++ = val >> 8;
+ *buf++ = val >> 16;
+ break;
+ case R_W65_PCR8:
+ *buf++ = val - addr - 1;
+ break;
+ case R_W65_PCR16:
+ val = val - addr - 1;
+ *buf++ = val;
+ *buf++ = val >> 8;
+ break;
+ case R_W65_DP:
+ *buf++ = val;
+ break;
+
+ default:
+ abort ();
+ }
+}
+
+/* Put number into target byte order */
+
+void
+md_number_to_chars (ptr, use, nbytes)
+ char *ptr;
+ valueT use;
+ int nbytes;
+{
+ number_to_chars_littleendian (ptr, use, nbytes);
+}
+
+long
+md_pcrel_from (fixP)
+ fixS *fixP;
+{
+ int gap = fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address - 1;
+ return gap;
+}
+
+void
+tc_coff_symbol_emit_hook (x)
+ struct symbol *x;
+{
+}
+
+short
+tc_coff_fix2rtype (fix_ptr)
+ fixS *fix_ptr;
+{
+ return fix_ptr->fx_r_type;
+}
+
+void
+tc_reloc_mangle (fix_ptr, intr, base)
+ fixS *fix_ptr;
+ struct internal_reloc *intr;
+ bfd_vma base;
+
+{
+ symbolS *symbol_ptr;
+
+ symbol_ptr = fix_ptr->fx_addsy;
+
+ /* If this relocation is attached to a symbol then it's ok
+ to output it */
+ if (fix_ptr->fx_r_type == RELOC_32)
+ {
+ /* cons likes to create reloc32's whatever the size of the reloc..
+ */
+ switch (fix_ptr->fx_size)
+ {
+ case 2:
+ intr->r_type = R_IMM16;
+ break;
+ case 1:
+ intr->r_type = R_IMM8;
+ break;
+ default:
+ abort ();
+ }
+ }
+ else
+ {
+ if (fix_ptr->fx_size == 4)
+ intr->r_type = R_W65_ABS24;
+ else
+ intr->r_type = fix_ptr->fx_r_type;
+ }
+
+ intr->r_vaddr = fix_ptr->fx_frag->fr_address + fix_ptr->fx_where + base;
+ intr->r_offset = fix_ptr->fx_offset;
+
+ /* Turn the segment of the symbol into an offset. */
+ if (symbol_ptr)
+ {
+ symbolS *dot;
+
+ dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot;
+ if (dot)
+ {
+ intr->r_offset += S_GET_VALUE (symbol_ptr);
+ intr->r_symndx = dot->sy_number;
+ }
+ else
+ {
+ intr->r_symndx = symbol_ptr->sy_number;
+ }
+ }
+ else
+ {
+ intr->r_symndx = -1;
+ }
+}
+
+int
+tc_coff_sizemachdep (frag)
+ fragS *frag;
+{
+ return md_relax_table[frag->fr_subtype].rlx_length;
+}
+
+
+
+
+
+/*
+called just before address relaxation, return the length
+by which a fragment must grow to reach it's destination
+*/
+int
+md_estimate_size_before_relax (fragP, segment_type)
+ register fragS *fragP;
+ register segT segment_type;
+{
+ int what = GET_WHAT (fragP->fr_subtype);
+
+ switch (fragP->fr_subtype)
+ {
+ default:
+ abort ();
+ case C (COND_BRANCH, UNDEF_BYTE_DISP):
+ case C (UNCOND_BRANCH, UNDEF_BYTE_DISP):
+ /* used to be a branch to somewhere which was unknown */
+ if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type)
+ {
+ /* Got a symbol and it's defined in this segment, become byte
+ sized - maybe it will fix up */
+ fragP->fr_subtype = C (what, BYTE_DISP);
+ fragP->fr_var = md_relax_table[C (what, BYTE_DISP)].rlx_length;
+ }
+ else
+ {
+ /* Its got a segment, but its not ours, so it will always be long */
+ fragP->fr_subtype = C (what, UNDEF_WORD_DISP);
+ fragP->fr_var = md_relax_table[C (what, WORD_DISP)].rlx_length;
+ return md_relax_table[C (what, WORD_DISP)].rlx_length;
+ }
+ }
+ return fragP->fr_var;
+}
+
+
+
+CONST char *md_shortopts = "";
+struct option md_longopts[] = {
+#define OPTION_RELAX (OPTION_MD_BASE)
+ {NULL, no_argument, NULL, 0}
+};
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+
+}
+
+size_t md_longopts_size = sizeof(md_longopts);
diff --git a/gas/config/tc-w65.h b/gas/config/tc-w65.h
new file mode 100644
index 0000000000..9794ad2eb5
--- /dev/null
+++ b/gas/config/tc-w65.h
@@ -0,0 +1,61 @@
+/* This file is tc-w65.h
+ Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+
+#define TC_W65
+
+#define TARGET_BYTES_BIG_ENDIAN 0
+
+#if ANSI_PROTOTYPES
+struct internal_reloc;
+#endif
+
+#define WORKING_DOT_WORD
+
+/* This macro translates between an internal fix and an coff reloc type */
+#define TC_COFF_FIX2RTYPE(fixP) tc_coff_fix2rtype(fixP)
+
+#define BFD_ARCH bfd_arch_w65
+#define COFF_MAGIC 0x6500
+
+#define IGNORE_NONSTANDARD_ESCAPES
+
+#define TC_RELOC_MANGLE(s,a,b,c) tc_reloc_mangle(a,b,c)
+extern void tc_reloc_mangle
+ PARAMS ((struct fix *, struct internal_reloc *, bfd_vma));
+
+#define DO_NOT_STRIP 0
+#define LISTING_HEADER "W65816 GAS "
+#define NEED_FX_R_TYPE 1
+#define RELOC_32 1234
+
+#define TC_COFF_SIZEMACHDEP(frag) tc_coff_sizemachdep(frag)
+#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) w65_expression (EXP, NBYTES)
+#define TC_COUNT_RELOC(x) (1)
+#define TC_CONS_RELOC tc_cons_reloc
+#define DONT_OVERFLOW
+int tc_cons_reloc;
+
+#define md_operand(x)
+
+extern struct relax_type md_relax_table[];
+#define TC_GENERIC_RELAX_TABLE md_relax_table
+
+/* end of tc-w65.h */
diff --git a/gas/config/tc-z8k.c b/gas/config/tc-z8k.c
new file mode 100644
index 0000000000..16113414f0
--- /dev/null
+++ b/gas/config/tc-z8k.c
@@ -0,0 +1,1589 @@
+/* tc-z8k.c -- Assemble code for the Zilog Z800n
+ Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/*
+ Written By Steve Chamberlain
+ sac@cygnus.com
+ */
+#define DEFINE_TABLE
+#include <stdio.h>
+
+#include "opcodes/z8k-opc.h"
+
+#include "as.h"
+#include "bfd.h"
+#include <ctype.h>
+
+const char comment_chars[] =
+{'!', 0};
+const char line_separator_chars[] =
+{';', 0};
+const char line_comment_chars[] =
+{'#', 0};
+
+extern int machine;
+extern int coff_flags;
+int segmented_mode;
+const int md_reloc_size;
+
+/* This table describes all the machine specific pseudo-ops the assembler
+ has to support. The fields are:
+ pseudo-op name without dot
+ function to call to execute this pseudo-op
+ Integer arg to pass to the function
+ */
+
+void cons ();
+
+void
+s_segm ()
+{
+ segmented_mode = 1;
+ machine = bfd_mach_z8001;
+ coff_flags = F_Z8001;
+}
+
+void
+s_unseg ()
+{
+ segmented_mode = 0;
+ machine = bfd_mach_z8002;
+ coff_flags = F_Z8002;
+}
+
+static
+void
+even ()
+{
+ frag_align (1, 0, 0);
+ record_alignment (now_seg, 1);
+}
+
+void obj_coff_section ();
+
+int
+tohex (c)
+ int c;
+{
+ if (isdigit (c))
+ return c - '0';
+ if (islower (c))
+ return c - 'a' + 10;
+ return c - 'A' + 10;
+}
+
+void
+sval ()
+{
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '\'')
+ {
+ int c;
+ input_line_pointer++;
+ c = *input_line_pointer++;
+ while (c != '\'')
+ {
+ if (c == '%')
+ {
+ c = (tohex (input_line_pointer[0]) << 4)
+ | tohex (input_line_pointer[1]);
+ input_line_pointer += 2;
+ }
+ FRAG_APPEND_1_CHAR (c);
+ c = *input_line_pointer++;
+ }
+ demand_empty_rest_of_line ();
+ }
+
+}
+const pseudo_typeS md_pseudo_table[] =
+{
+ {"int", cons, 2},
+ {"data.b", cons, 1},
+ {"data.w", cons, 2},
+ {"data.l", cons, 4},
+ {"form", listing_psize, 0},
+ {"heading", listing_title, 0},
+ {"import", s_ignore, 0},
+ {"page", listing_eject, 0},
+ {"program", s_ignore, 0},
+ {"z8001", s_segm, 0},
+ {"z8002", s_unseg, 0},
+
+
+ {"segm", s_segm, 0},
+ {"unsegm", s_unseg, 0},
+ {"unseg", s_unseg, 0},
+ {"name", s_app_file, 0},
+ {"global", s_globl, 0},
+ {"wval", cons, 2},
+ {"lval", cons, 4},
+ {"bval", cons, 1},
+ {"sval", sval, 0},
+ {"rsect", obj_coff_section, 0},
+ {"sect", obj_coff_section, 0},
+ {"block", s_space, 0},
+ {"even", even, 0},
+ {0, 0, 0}
+};
+
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* As in 0f12.456 */
+/* or 0d1.2345e12 */
+const char FLT_CHARS[] = "rRsSfFdDxXpP";
+
+static struct hash_control *opcode_hash_control; /* Opcode mnemonics */
+
+void
+md_begin ()
+{
+ opcode_entry_type *opcode;
+ char *prev_name = "";
+ int idx = 0;
+
+ opcode_hash_control = hash_new ();
+
+ for (opcode = z8k_table; opcode->name; opcode++)
+ {
+ /* Only enter unique codes into the table */
+ char *src = opcode->name;
+
+ if (strcmp (opcode->name, prev_name))
+ {
+ hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
+ idx++;
+ }
+ opcode->idx = idx;
+ prev_name = opcode->name;
+ }
+
+ /* default to z8002 */
+ s_unseg ();
+
+ /* insert the pseudo ops too */
+ for (idx = 0; md_pseudo_table[idx].poc_name; idx++)
+ {
+ opcode_entry_type *fake_opcode;
+ fake_opcode = (opcode_entry_type *) malloc (sizeof (opcode_entry_type));
+ fake_opcode->name = md_pseudo_table[idx].poc_name,
+ fake_opcode->func = (void *) (md_pseudo_table + idx);
+ fake_opcode->opcode = 250;
+ hash_insert (opcode_hash_control, fake_opcode->name, fake_opcode);
+ }
+
+ linkrelax = 1;
+}
+
+struct z8k_exp
+{
+ char *e_beg;
+ char *e_end;
+ expressionS e_exp;
+};
+typedef struct z8k_op
+{
+ char regsize; /* 'b','w','r','q' */
+ unsigned int reg; /* 0..15 */
+
+ int mode;
+
+ unsigned int x_reg; /* any other register associated with the mode */
+ expressionS exp; /* any expression */
+}
+
+op_type;
+
+static expressionS *da_operand;
+static expressionS *imm_operand;
+
+int reg[16];
+int the_cc;
+int the_ctrl;
+int the_flags;
+int the_interrupt;
+
+char *
+DEFUN (whatreg, (reg, src),
+ int *reg AND
+ char *src)
+{
+ if (isdigit (src[1]))
+ {
+ *reg = (src[0] - '0') * 10 + src[1] - '0';
+ return src + 2;
+ }
+ else
+ {
+ *reg = (src[0] - '0');
+ return src + 1;
+ }
+}
+
+/*
+ parse operands
+
+ rh0-rh7, rl0-rl7
+ r0-r15
+ rr0-rr14
+ rq0--rq12
+ WREG r0,r1,r2,r3,r4,r5,r6,r7,fp,sp
+ r0l,r0h,..r7l,r7h
+ @WREG
+ @WREG+
+ @-WREG
+ #const
+
+ */
+
+/* try and parse a reg name, returns number of chars consumed */
+char *
+DEFUN (parse_reg, (src, mode, reg),
+ char *src AND
+ int *mode AND
+ unsigned int *reg)
+{
+ char *res = 0;
+ char regno;
+
+ if (src[0] == 's' && src[1] == 'p')
+ {
+ if (segmented_mode)
+ {
+ *mode = CLASS_REG_LONG;
+ *reg = 14;
+ }
+ else
+ {
+ *mode = CLASS_REG_WORD;
+ *reg = 15;
+ }
+ return src + 2;
+ }
+ if (src[0] == 'r')
+ {
+ if (src[1] == 'r')
+ {
+ *mode = CLASS_REG_LONG;
+ res = whatreg (reg, src + 2);
+ regno = *reg;
+ if (regno > 14)
+ as_warn (_("register rr%d, out of range."),regno);
+ }
+ else if (src[1] == 'h')
+ {
+ *mode = CLASS_REG_BYTE;
+ res = whatreg (reg, src + 2);
+ regno = *reg;
+ if (regno > 7)
+ as_warn (_("register rh%d, out of range."),regno);
+ }
+ else if (src[1] == 'l')
+ {
+ *mode = CLASS_REG_BYTE;
+ res = whatreg (reg, src + 2);
+ regno = *reg;
+ if (regno > 7)
+ as_warn (_("register rl%d, out of range."),regno);
+ *reg += 8;
+ }
+ else if (src[1] == 'q')
+ {
+ *mode = CLASS_REG_QUAD;
+ res = whatreg (reg, src + 2);
+ regno = *reg;
+ if (regno > 12)
+ as_warn (_("register rq%d, out of range."),regno);
+ }
+ else
+ {
+ *mode = CLASS_REG_WORD;
+ res = whatreg (reg, src + 1);
+ regno = *reg;
+ if (regno > 15)
+ as_warn (_("register r%d, out of range."),regno);
+ }
+ }
+ return res;
+
+}
+
+char *
+DEFUN (parse_exp, (s, op),
+ char *s AND
+ expressionS * op)
+{
+ char *save = input_line_pointer;
+ char *new;
+
+ input_line_pointer = s;
+ expression (op);
+ if (op->X_op == O_absent)
+ as_bad (_("missing operand"));
+ new = input_line_pointer;
+ input_line_pointer = save;
+ return new;
+}
+
+/* The many forms of operand:
+
+ <rb>
+ <r>
+ <rr>
+ <rq>
+ @r
+ #exp
+ exp
+ exp(r)
+ r(#exp)
+ r(r)
+
+
+
+ */
+
+static
+char *
+DEFUN (checkfor, (ptr, what),
+ char *ptr AND
+ char what)
+{
+ if (*ptr == what)
+ ptr++;
+ else
+ {
+ as_bad (_("expected %c"), what);
+ }
+ return ptr;
+}
+
+/* Make sure the mode supplied is the size of a word */
+static void
+DEFUN (regword, (mode, string),
+ int mode AND
+ char *string)
+{
+ int ok;
+
+ ok = CLASS_REG_WORD;
+ if (ok != mode)
+ {
+ as_bad (_("register is wrong size for a word %s"), string);
+ }
+}
+
+/* Make sure the mode supplied is the size of an address */
+static void
+DEFUN (regaddr, (mode, string),
+ int mode AND
+ char *string)
+{
+ int ok;
+
+ ok = segmented_mode ? CLASS_REG_LONG : CLASS_REG_WORD;
+ if (ok != mode)
+ {
+ as_bad (_("register is wrong size for address %s"), string);
+ }
+}
+
+struct ctrl_names
+{
+ int value;
+ char *name;
+};
+
+struct ctrl_names ctrl_table[] =
+{
+ 0x2, "fcw",
+ 0X3, "refresh",
+ 0x4, "psapseg",
+ 0x5, "psapoff",
+ 0x5, "psap",
+ 0x6, "nspseg",
+ 0x7, "nspoff",
+ 0x7, "nsp",
+ 0, 0
+};
+
+static void
+DEFUN (get_ctrl_operand, (ptr, mode, dst),
+ char **ptr AND
+ struct z8k_op *mode AND
+ unsigned int dst)
+{
+ char *src = *ptr;
+ int r;
+ int i;
+
+ while (*src == ' ')
+ src++;
+
+ mode->mode = CLASS_CTRL;
+ for (i = 0; ctrl_table[i].name; i++)
+ {
+ int j;
+
+ for (j = 0; ctrl_table[i].name[j]; j++)
+ {
+ if (ctrl_table[i].name[j] != src[j])
+ goto fail;
+ }
+ the_ctrl = ctrl_table[i].value;
+ *ptr = src + j;
+ return;
+ fail:;
+ }
+ the_ctrl = 0;
+ return;
+}
+
+struct flag_names
+{
+ int value;
+ char *name;
+
+};
+
+struct flag_names flag_table[] =
+{
+ 0x1, "p",
+ 0x1, "v",
+ 0x2, "s",
+ 0x4, "z",
+ 0x8, "c",
+ 0x0, "+",
+ 0, 0
+};
+
+static void
+DEFUN (get_flags_operand, (ptr, mode, dst),
+ char **ptr AND
+ struct z8k_op *mode AND
+ unsigned int dst)
+{
+ char *src = *ptr;
+ int r;
+ int i;
+ int j;
+
+ while (*src == ' ')
+ src++;
+
+ mode->mode = CLASS_FLAGS;
+ the_flags = 0;
+ for (j = 0; j <= 9; j++)
+ {
+ if (!src[j])
+ goto done;
+ for (i = 0; flag_table[i].name; i++)
+ {
+ if (flag_table[i].name[0] == src[j])
+ {
+ the_flags = the_flags | flag_table[i].value;
+ goto match;
+ }
+ }
+ goto done;
+ match:
+ ;
+ }
+ done:
+ *ptr = src + j;
+ return;
+}
+
+
+struct interrupt_names
+{
+ int value;
+ char *name;
+
+};
+
+struct interrupt_names intr_table[] =
+{
+ 0x1, "nvi",
+ 0x2, "vi",
+ 0x3, "both",
+ 0x3, "all",
+ 0, 0
+};
+
+static void
+DEFUN (get_interrupt_operand, (ptr, mode, dst),
+ char **ptr AND
+ struct z8k_op *mode AND
+ unsigned int dst)
+{
+ char *src = *ptr;
+ int r;
+ int i;
+
+ while (*src == ' ')
+ src++;
+
+ mode->mode = CLASS_IMM;
+ for (i = 0; intr_table[i].name; i++)
+ {
+ int j;
+
+ for (j = 0; intr_table[i].name[j]; j++)
+ {
+ if (intr_table[i].name[j] != src[j])
+ goto fail;
+ }
+ the_interrupt = intr_table[i].value;
+ *ptr = src + j;
+ return;
+ fail:;
+ }
+ the_interrupt = 0x0;
+ return;
+}
+
+struct cc_names
+{
+ int value;
+ char *name;
+
+};
+
+struct cc_names table[] =
+{
+ 0x0, "f",
+ 0x1, "lt",
+ 0x2, "le",
+ 0x3, "ule",
+ 0x4, "ov",
+ 0x4, "pe",
+ 0x5, "mi",
+ 0x6, "eq",
+ 0x6, "z",
+ 0x7, "c",
+ 0x7, "ult",
+ 0x8, "t",
+ 0x9, "ge",
+ 0xa, "gt",
+ 0xb, "ugt",
+ 0xc, "nov",
+ 0xc, "po",
+ 0xd, "pl",
+ 0xe, "ne",
+ 0xe, "nz",
+ 0xf, "nc",
+ 0xf, "uge",
+ 0, 0
+};
+
+static void
+DEFUN (get_cc_operand, (ptr, mode, dst),
+ char **ptr AND
+ struct z8k_op *mode AND
+ unsigned int dst)
+{
+ char *src = *ptr;
+ int r;
+ int i;
+
+ while (*src == ' ')
+ src++;
+
+ mode->mode = CLASS_CC;
+ for (i = 0; table[i].name; i++)
+ {
+ int j;
+
+ for (j = 0; table[i].name[j]; j++)
+ {
+ if (table[i].name[j] != src[j])
+ goto fail;
+ }
+ the_cc = table[i].value;
+ *ptr = src + j;
+ return;
+ fail:;
+ }
+ the_cc = 0x8;
+}
+
+static void
+get_operand (ptr, mode, dst)
+ char **ptr;
+ struct z8k_op *mode;
+ unsigned int dst;
+{
+ char *src = *ptr;
+ char *end;
+ unsigned int num;
+ unsigned int len;
+ unsigned int size;
+
+ mode->mode = 0;
+
+ while (*src == ' ')
+ src++;
+ if (*src == '#')
+ {
+ mode->mode = CLASS_IMM;
+ imm_operand = &(mode->exp);
+ src = parse_exp (src + 1, &(mode->exp));
+ }
+ else if (*src == '@')
+ {
+ int d;
+
+ mode->mode = CLASS_IR;
+ src = parse_reg (src + 1, &d, &mode->reg);
+ }
+ else
+ {
+ int regn;
+
+ end = parse_reg (src, &mode->mode, &regn);
+
+ if (end)
+ {
+ int nw, nr;
+
+ src = end;
+ if (*src == '(')
+ {
+ src++;
+ end = parse_reg (src, &nw, &nr);
+ if (end)
+ {
+ /* Got Ra(Rb) */
+ src = end;
+
+ if (*src != ')')
+ {
+ as_bad (_("Missing ) in ra(rb)"));
+ }
+ else
+ {
+ src++;
+ }
+
+ regaddr (mode->mode, "ra(rb) ra");
+/* regword (mode->mode, "ra(rb) rb");*/
+ mode->mode = CLASS_BX;
+ mode->reg = regn;
+ mode->x_reg = nr;
+ reg[ARG_RX] = nr;
+ }
+ else
+ {
+ /* Got Ra(disp) */
+ if (*src == '#')
+ src++;
+ src = parse_exp (src, &(mode->exp));
+ src = checkfor (src, ')');
+ mode->mode = CLASS_BA;
+ mode->reg = regn;
+ mode->x_reg = 0;
+ imm_operand = &(mode->exp);
+ }
+ }
+ else
+ {
+ mode->reg = regn;
+ mode->x_reg = 0;
+ }
+ }
+ else
+ {
+ /* No initial reg */
+ src = parse_exp (src, &(mode->exp));
+ if (*src == '(')
+ {
+ src++;
+ end = parse_reg (src, &(mode->mode), &regn);
+ regword (mode->mode, "addr(Ra) ra");
+ mode->mode = CLASS_X;
+ mode->reg = regn;
+ mode->x_reg = 0;
+ da_operand = &(mode->exp);
+ src = checkfor (end, ')');
+ }
+ else
+ {
+ /* Just an address */
+ mode->mode = CLASS_DA;
+ mode->reg = 0;
+ mode->x_reg = 0;
+ da_operand = &(mode->exp);
+ }
+ }
+ }
+ *ptr = src;
+}
+
+static
+char *
+get_operands (opcode, op_end, operand)
+ opcode_entry_type *opcode;
+ char *op_end;
+ op_type *operand;
+{
+ char *ptr = op_end;
+char *savptr;
+ switch (opcode->noperands)
+ {
+ case 0:
+ operand[0].mode = 0;
+ operand[1].mode = 0;
+ break;
+
+ case 1:
+ ptr++;
+ if (opcode->arg_info[0] == CLASS_CC)
+ {
+ get_cc_operand (&ptr, operand + 0, 0);
+ }
+ else if (opcode->arg_info[0] == CLASS_FLAGS)
+ {
+ get_flags_operand (&ptr, operand + 0, 0);
+ }
+ else if (opcode->arg_info[0] == (CLASS_IMM +(ARG_IMM2)))
+ {
+ get_interrupt_operand (&ptr, operand + 0, 0);
+ }
+ else
+ {
+ get_operand (&ptr, operand + 0, 0);
+ }
+ operand[1].mode = 0;
+ break;
+
+ case 2:
+ ptr++;
+ savptr = ptr;
+ if (opcode->arg_info[0] == CLASS_CC)
+ {
+ get_cc_operand (&ptr, operand + 0, 0);
+ }
+ else if (opcode->arg_info[0] == CLASS_CTRL)
+ {
+ get_ctrl_operand (&ptr, operand + 0, 0);
+ if (the_ctrl == 0)
+ {
+ ptr = savptr;
+ get_operand (&ptr, operand + 0, 0);
+ if (ptr == 0)
+ return;
+ if (*ptr == ',')
+ ptr++;
+ get_ctrl_operand (&ptr, operand + 1, 1);
+ return ptr;
+ }
+ }
+ else
+ {
+ get_operand (&ptr, operand + 0, 0);
+ }
+ if (ptr == 0)
+ return;
+ if (*ptr == ',')
+ ptr++;
+ get_operand (&ptr, operand + 1, 1);
+ break;
+
+ case 3:
+ ptr++;
+ get_operand (&ptr, operand + 0, 0);
+ if (*ptr == ',')
+ ptr++;
+ get_operand (&ptr, operand + 1, 1);
+ if (*ptr == ',')
+ ptr++;
+ get_operand (&ptr, operand + 2, 2);
+ break;
+
+ case 4:
+ ptr++;
+ get_operand (&ptr, operand + 0, 0);
+ if (*ptr == ',')
+ ptr++;
+ get_operand (&ptr, operand + 1, 1);
+ if (*ptr == ',')
+ ptr++;
+ get_operand (&ptr, operand + 2, 2);
+ if (*ptr == ',')
+ ptr++;
+ get_cc_operand (&ptr, operand + 3, 3);
+ break;
+ default:
+ abort ();
+ }
+
+ return ptr;
+}
+
+/* Passed a pointer to a list of opcodes which use different
+ addressing modes, return the opcode which matches the opcodes
+ provided
+ */
+
+static
+opcode_entry_type *
+DEFUN (get_specific, (opcode, operands),
+ opcode_entry_type * opcode AND
+ op_type * operands)
+
+{
+ opcode_entry_type *this_try = opcode;
+ int found = 0;
+ unsigned int noperands = opcode->noperands;
+
+ unsigned int dispreg;
+ unsigned int this_index = opcode->idx;
+
+ while (this_index == opcode->idx && !found)
+ {
+ unsigned int i;
+
+ this_try = opcode++;
+ for (i = 0; i < noperands; i++)
+ {
+ int mode = operands[i].mode;
+
+ if ((mode & CLASS_MASK) != (this_try->arg_info[i] & CLASS_MASK))
+ {
+ /* it could be an pc rel operand, if this is a da mode and
+ we like disps, then insert it */
+
+ if (mode == CLASS_DA && this_try->arg_info[i] == CLASS_DISP)
+ {
+ /* This is the case */
+ operands[i].mode = CLASS_DISP;
+ }
+ else if (mode == CLASS_BA && this_try->arg_info[i])
+ {
+ /* Can't think of a way to turn what we've been given into
+ something that's ok */
+ goto fail;
+ }
+ else if (this_try->arg_info[i] & CLASS_PR)
+ {
+ if (mode == CLASS_REG_LONG && segmented_mode)
+ {
+ /* ok */
+ }
+ else if (mode == CLASS_REG_WORD && !segmented_mode)
+ {
+ /* ok */
+ }
+ else
+ goto fail;
+ }
+ else
+ goto fail;
+ }
+ switch (mode & CLASS_MASK)
+ {
+ default:
+ break;
+ case CLASS_X:
+ case CLASS_IR:
+ case CLASS_BA:
+ case CLASS_BX:
+ case CLASS_DISP:
+ case CLASS_REG:
+ case CLASS_REG_WORD:
+ case CLASS_REG_BYTE:
+ case CLASS_REG_QUAD:
+ case CLASS_REG_LONG:
+ case CLASS_REGN0:
+ reg[this_try->arg_info[i] & ARG_MASK] = operands[i].reg;
+ break;
+ }
+ }
+
+ found = 1;
+ fail:;
+ }
+ if (found)
+ return this_try;
+ else
+ return 0;
+}
+
+static void
+DEFUN (check_operand, (operand, width, string),
+ struct z8k_op *operand AND
+ unsigned int width AND
+ char *string)
+{
+ if (operand->exp.X_add_symbol == 0
+ && operand->exp.X_op_symbol == 0)
+ {
+
+ /* No symbol involved, let's look at offset, it's dangerous if any of
+ the high bits are not 0 or ff's, find out by oring or anding with
+ the width and seeing if the answer is 0 or all fs*/
+ if ((operand->exp.X_add_number & ~width) != 0 &&
+ (operand->exp.X_add_number | width) != (~0))
+ {
+ as_warn (_("operand %s0x%x out of range."), string, operand->exp.X_add_number);
+ }
+ }
+
+}
+
+static char buffer[20];
+
+static void
+DEFUN (newfix, (ptr, type, operand),
+ int ptr AND
+ int type AND
+ expressionS * operand)
+{
+ if (operand->X_add_symbol
+ || operand->X_op_symbol
+ || operand->X_add_number)
+ {
+ fix_new_exp (frag_now,
+ ptr,
+ 1,
+ operand,
+ 0,
+ type);
+ }
+}
+
+static char *
+DEFUN (apply_fix, (ptr, type, operand, size),
+ char *ptr AND
+ int type AND
+ expressionS * operand AND
+ int size)
+{
+ int n = operand->X_add_number;
+
+ operand->X_add_number = n;
+ newfix ((ptr - buffer) / 2, type, operand);
+#if 1
+ switch (size)
+ {
+ case 8: /* 8 nibbles == 32 bits */
+ *ptr++ = n >> 28;
+ *ptr++ = n >> 24;
+ *ptr++ = n >> 20;
+ *ptr++ = n >> 16;
+ case 4: /* 4 niblles == 16 bits */
+ *ptr++ = n >> 12;
+ *ptr++ = n >> 8;
+ case 2:
+ *ptr++ = n >> 4;
+ case 1:
+ *ptr++ = n >> 0;
+ break;
+ }
+#endif
+ return ptr;
+
+}
+
+/* Now we know what sort of opcodes it is, lets build the bytes -
+ */
+#define INSERT(x,y) *x++ = y>>24; *x++ = y>> 16; *x++=y>>8; *x++ =y;
+static void
+build_bytes (this_try, operand)
+ opcode_entry_type * this_try;
+ struct z8k_op *operand;
+{
+ unsigned int i;
+
+ int length;
+ char *output;
+ char *output_ptr = buffer;
+ char part;
+ int c;
+ char high;
+ int nib;
+ int nibble;
+ unsigned int *class_ptr;
+
+ frag_wane (frag_now);
+ frag_new (0);
+
+ memset (buffer, 20, 0);
+ class_ptr = this_try->byte_info;
+top:;
+
+ for (nibble = 0; c = *class_ptr++; nibble++)
+ {
+
+ switch (c & CLASS_MASK)
+ {
+ default:
+
+ abort ();
+ case CLASS_ADDRESS:
+ /* Direct address, we don't cope with the SS mode right now */
+ if (segmented_mode)
+ {
+ da_operand->X_add_number |= 0x80000000;
+ output_ptr = apply_fix (output_ptr, R_IMM32, da_operand, 8);
+ }
+ else
+ {
+ output_ptr = apply_fix (output_ptr, R_IMM16, da_operand, 4);
+ }
+ da_operand = 0;
+ break;
+ case CLASS_DISP8:
+ /* pc rel 8 bit */
+ output_ptr = apply_fix (output_ptr, R_JR, da_operand, 2);
+ da_operand = 0;
+ break;
+
+ case CLASS_0DISP7:
+ /* pc rel 7 bit */
+ *output_ptr = 0;
+ output_ptr = apply_fix (output_ptr, R_DISP7, da_operand, 2);
+ da_operand = 0;
+ break;
+
+ case CLASS_1DISP7:
+ /* pc rel 7 bit */
+ *output_ptr = 0x80;
+ output_ptr = apply_fix (output_ptr, R_DISP7, da_operand, 2);
+ output_ptr[-2] = 0x8;
+ da_operand = 0;
+ break;
+
+ case CLASS_BIT_1OR2:
+ *output_ptr = c & 0xf;
+ if (imm_operand)
+ {
+ if (imm_operand->X_add_number == 2)
+ {
+ *output_ptr |= 2;
+ }
+ else if (imm_operand->X_add_number != 1)
+ {
+ as_bad (_("immediate must be 1 or 2"));
+ }
+ }
+ else
+ {
+ as_bad (_("immediate 1 or 2 expected"));
+ }
+ output_ptr++;
+ break;
+ case CLASS_CC:
+ *output_ptr++ = the_cc;
+ break;
+ case CLASS_0CCC:
+ *output_ptr++ = the_ctrl;
+ break;
+ case CLASS_1CCC:
+ *output_ptr++ = the_ctrl | 0x8;
+ break;
+ case CLASS_00II:
+ *output_ptr++ = (~the_interrupt & 0x3);
+ break;
+ case CLASS_01II:
+ *output_ptr++ = (~the_interrupt & 0x3) | 0x4;
+ break;
+ case CLASS_FLAGS:
+ *output_ptr++ = the_flags;
+ break;
+ case CLASS_BIT:
+ *output_ptr++ = c & 0xf;
+ break;
+ case CLASS_REGN0:
+ if (reg[c & 0xf] == 0)
+ {
+ as_bad (_("can't use R0 here"));
+ }
+ case CLASS_REG:
+ case CLASS_REG_BYTE:
+ case CLASS_REG_WORD:
+ case CLASS_REG_LONG:
+ case CLASS_REG_QUAD:
+ /* Insert bit mattern of
+ right reg */
+ *output_ptr++ = reg[c & 0xf];
+ break;
+ case CLASS_DISP:
+ output_ptr = apply_fix (output_ptr, R_IMM16, da_operand, 4);
+ da_operand = 0;
+ break;
+
+ case CLASS_IMM:
+ {
+ nib = 0;
+ switch (c & ARG_MASK)
+ {
+ case ARG_IMM4:
+ output_ptr = apply_fix (output_ptr, R_IMM4L, imm_operand, 1);
+ break;
+ case ARG_IMM4M1:
+ imm_operand->X_add_number--;
+ output_ptr = apply_fix (output_ptr, R_IMM4L, imm_operand, 1);
+ break;
+ case ARG_IMMNMINUS1:
+ imm_operand->X_add_number--;
+ output_ptr = apply_fix (output_ptr, R_IMM4L, imm_operand, 1);
+ break;
+ case ARG_NIM8:
+ imm_operand->X_add_number = -imm_operand->X_add_number;
+ case ARG_IMM8:
+ output_ptr = apply_fix (output_ptr, R_IMM8, imm_operand, 2);
+ break;
+ case ARG_IMM16:
+ output_ptr = apply_fix (output_ptr, R_IMM16, imm_operand, 4);
+ break;
+
+ case ARG_IMM32:
+ output_ptr = apply_fix (output_ptr, R_IMM32, imm_operand, 8);
+ break;
+
+ default:
+ abort ();
+ }
+ }
+ }
+ }
+
+ /* Copy from the nibble buffer into the frag */
+
+ {
+ int length = (output_ptr - buffer) / 2;
+ char *src = buffer;
+ char *fragp = frag_more (length);
+
+ while (src < output_ptr)
+ {
+ *fragp = (src[0] << 4) | src[1];
+ src += 2;
+ fragp++;
+ }
+
+ }
+
+}
+
+/* This is the guts of the machine-dependent assembler. STR points to a
+ machine dependent instruction. This funciton is supposed to emit
+ the frags/bytes it assembles to.
+ */
+
+void
+DEFUN (md_assemble, (str),
+ char *str)
+{
+ char *op_start;
+ char *op_end;
+ unsigned int i;
+ struct z8k_op operand[3];
+ opcode_entry_type *opcode;
+ opcode_entry_type *prev_opcode;
+
+ char *dot = 0;
+ char c;
+
+ /* Drop leading whitespace */
+ while (*str == ' ')
+ str++;
+
+ /* find the op code end */
+ for (op_start = op_end = str;
+ *op_end != 0 && *op_end != ' ';
+ op_end++)
+ {
+ }
+
+ ;
+
+ if (op_end == op_start)
+ {
+ as_bad (_("can't find opcode "));
+ }
+ c = *op_end;
+
+ *op_end = 0;
+
+ opcode = (opcode_entry_type *) hash_find (opcode_hash_control,
+ op_start);
+
+
+ if (opcode == NULL)
+ {
+ as_bad (_("unknown opcode"));
+ return;
+ }
+
+ if (opcode->opcode == 250)
+ {
+ /* was really a pseudo op */
+
+ pseudo_typeS *p;
+ char oc;
+
+ char *old = input_line_pointer;
+ *op_end = c;
+
+
+ input_line_pointer = op_end;
+
+ oc = *old;
+ *old = '\n';
+ while (*input_line_pointer == ' ')
+ input_line_pointer++;
+ p = (pseudo_typeS *) (opcode->func);
+
+ (p->poc_handler) (p->poc_val);
+ input_line_pointer = old;
+ *old = oc;
+ }
+ else
+ {
+ input_line_pointer = get_operands (opcode, op_end,
+ operand);
+ prev_opcode = opcode;
+
+ opcode = get_specific (opcode, operand);
+
+ if (opcode == 0)
+ {
+ /* Couldn't find an opcode which matched the operands */
+ char *where = frag_more (2);
+
+ where[0] = 0x0;
+ where[1] = 0x0;
+
+ as_bad (_("Can't find opcode to match operands"));
+ return;
+ }
+
+ build_bytes (opcode, operand);
+ }
+}
+
+void
+DEFUN (tc_crawl_symbol_chain, (headers),
+ object_headers * headers)
+{
+ printf (_("call to tc_crawl_symbol_chain \n"));
+}
+
+symbolS *
+DEFUN (md_undefined_symbol, (name),
+ char *name)
+{
+ return 0;
+}
+
+void
+DEFUN (tc_headers_hook, (headers),
+ object_headers * headers)
+{
+ printf (_("call to tc_headers_hook \n"));
+}
+
+/* Various routines to kill one day */
+/* Equal to MAX_PRECISION in atof-ieee.c */
+#define MAX_LITTLENUMS 6
+
+/* Turn a string in input_line_pointer into a floating point constant of type
+ type, and store the appropriate bytes in *litP. The number of LITTLENUMS
+ emitted is stored in *sizeP . An error message is returned, or NULL on OK.
+ */
+char *
+md_atof (type, litP, sizeP)
+ char type;
+ char *litP;
+ int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ char *t;
+ char *atof_ieee ();
+
+ switch (type)
+ {
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ prec = 4;
+ break;
+
+ case 'x':
+ case 'X':
+ prec = 6;
+ break;
+
+ case 'p':
+ case 'P':
+ prec = 6;
+ break;
+
+ default:
+ *sizeP = 0;
+ return _("Bad call to MD_ATOF()");
+ }
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+
+ *sizeP = prec * sizeof (LITTLENUM_TYPE);
+ for (wordP = words; prec--;)
+ {
+ md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+ return 0;
+}
+
+CONST char *md_shortopts = "z:";
+struct option md_longopts[] = {
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof(md_longopts);
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
+{
+ switch (c)
+ {
+ case 'z':
+ if (!strcmp (arg, "8001"))
+ s_segm ();
+ else if (!strcmp (arg, "8002"))
+ s_unseg ();
+ else
+ {
+ as_bad (_("invalid architecture -z%s"), arg);
+ return 0;
+ }
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+ fprintf(stream, _("\
+Z8K options:\n\
+-z8001 generate segmented code\n\
+-z8002 generate unsegmented code\n"));
+}
+
+void
+tc_aout_fix_to_chars ()
+{
+ printf (_("call to tc_aout_fix_to_chars \n"));
+ abort ();
+}
+
+void
+md_convert_frag (headers, seg, fragP)
+ object_headers *headers;
+ segT seg;
+ fragS *fragP;
+{
+ printf (_("call to md_convert_frag \n"));
+ abort ();
+}
+
+valueT
+DEFUN (md_section_align, (seg, size),
+ segT seg AND
+ valueT size)
+{
+ return ((size + (1 << section_alignment[(int) seg]) - 1) & (-1 << section_alignment[(int) seg]));
+
+}
+
+void
+md_apply_fix (fixP, val)
+ fixS *fixP;
+ long val;
+{
+ char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
+
+ switch (fixP->fx_r_type)
+ {
+ case R_IMM4L:
+ buf[0] = (buf[0] & 0xf0) | ((buf[0] + val) & 0xf);
+ break;
+
+ case R_JR:
+
+ *buf++ = val;
+ /* if (val != 0) abort();*/
+ break;
+
+ case R_DISP7:
+
+ *buf++ += val;
+ /* if (val != 0) abort();*/
+ break;
+
+ case R_IMM8:
+ buf[0] += val;
+ break;
+ case R_IMM16:
+ *buf++ = (val >> 8);
+ *buf++ = val;
+ break;
+ case R_IMM32:
+ *buf++ = (val >> 24);
+ *buf++ = (val >> 16);
+ *buf++ = (val >> 8);
+ *buf++ = val;
+ break;
+#if 0
+ case R_DA | R_SEG:
+ *buf++ = (val >> 16);
+ *buf++ = 0x00;
+ *buf++ = (val >> 8);
+ *buf++ = val;
+ break;
+#endif
+
+ case 0:
+ md_number_to_chars (buf, val, fixP->fx_size);
+ break;
+
+ default:
+ abort ();
+
+ }
+}
+
+int
+md_estimate_size_before_relax (fragP, segment_type)
+ register fragS *fragP;
+ register segT segment_type;
+{
+ printf (_("call tomd_estimate_size_before_relax \n"));
+ abort ();
+}
+
+/* Put number into target byte order */
+
+void
+DEFUN (md_number_to_chars, (ptr, use, nbytes),
+ char *ptr AND
+ valueT use AND
+ int nbytes)
+{
+ number_to_chars_bigendian (ptr, use, nbytes);
+}
+long
+md_pcrel_from (fixP)
+ fixS *fixP;
+{
+ abort ();
+}
+
+void
+tc_coff_symbol_emit_hook (s)
+ struct symbol *s;
+{
+}
+
+void
+tc_reloc_mangle (fix_ptr, intr, base)
+ fixS *fix_ptr;
+ struct internal_reloc *intr;
+ bfd_vma base;
+
+{
+ symbolS *symbol_ptr;
+
+ if (fix_ptr->fx_addsy &&
+ fix_ptr->fx_subsy)
+ {
+ symbolS *add = fix_ptr->fx_addsy;
+ symbolS *sub = fix_ptr->fx_subsy;
+ if (S_GET_SEGMENT(add) != S_GET_SEGMENT(sub))
+ {
+ as_bad(_("Can't subtract symbols in different sections %s %s"),
+ S_GET_NAME(add), S_GET_NAME(sub));
+ }
+ else {
+ int diff = S_GET_VALUE(add) - S_GET_VALUE(sub);
+ fix_ptr->fx_addsy = 0;
+ fix_ptr->fx_subsy = 0;
+ fix_ptr->fx_offset += diff;
+ }
+ }
+ symbol_ptr = fix_ptr->fx_addsy;
+
+ /* If this relocation is attached to a symbol then it's ok
+ to output it */
+ if (fix_ptr->fx_r_type == 0)
+ {
+ /* cons likes to create reloc32's whatever the size of the reloc.. */
+ switch (fix_ptr->fx_size)
+ {
+ case 2:
+ intr->r_type = R_IMM16;
+ break;
+ case 1:
+ intr->r_type = R_IMM8;
+ break;
+ case 4:
+ intr->r_type = R_IMM32;
+ break;
+ default:
+ abort ();
+ }
+
+ }
+ else
+ {
+ intr->r_type = fix_ptr->fx_r_type;
+ }
+
+ intr->r_vaddr = fix_ptr->fx_frag->fr_address + fix_ptr->fx_where + base;
+ intr->r_offset = fix_ptr->fx_offset;
+
+ if (symbol_ptr)
+ intr->r_symndx = symbol_ptr->sy_number;
+ else
+ intr->r_symndx = -1;
+}
+
diff --git a/gas/config/tc-z8k.h b/gas/config/tc-z8k.h
new file mode 100644
index 0000000000..d88b656d6e
--- /dev/null
+++ b/gas/config/tc-z8k.h
@@ -0,0 +1,54 @@
+/* This file is tc-z8k.h
+ Copyright (C) 1987-1992, 93, 95, 97, 1998 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+
+#define TC_Z8K
+#define TARGET_BYTES_BIG_ENDIAN 1
+
+#if ANSI_PROTOTYPES
+struct internal_reloc;
+#endif
+
+#define WORKING_DOT_WORD
+
+#ifndef BFD_ASSEMBLER
+#define LOCAL_LABEL(x) 0
+#endif
+
+/* This macro translates between an internal fix and an coff reloc type */
+#define TC_COFF_FIX2RTYPE(fixP) abort();
+
+#define BFD_ARCH bfd_arch_z8k
+#define COFF_MAGIC 0x8000
+#define TC_COUNT_RELOC(x) (1)
+#define IGNORE_NONSTANDARD_ESCAPES
+
+#define TC_RELOC_MANGLE(s,a,b,c) tc_reloc_mangle(a,b,c)
+extern void tc_reloc_mangle
+ PARAMS ((struct fix *, struct internal_reloc *, bfd_vma));
+
+#define DO_NOT_STRIP 0
+#define LISTING_HEADER "Zilog Z8000 GAS "
+#define NEED_FX_R_TYPE 1
+#define RELOC_32 1234
+
+#define md_operand(x)
+
+/* end of tc-z8k.h */
diff --git a/gas/config/te-386bsd.h b/gas/config/te-386bsd.h
new file mode 100644
index 0000000000..dbff99027e
--- /dev/null
+++ b/gas/config/te-386bsd.h
@@ -0,0 +1,31 @@
+/* te-386bsd.h -- 386BSD target environment declarations.
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TE_386BSD 1
+
+#include "obj-format.h"
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of te-sun3.h */
diff --git a/gas/config/te-aux.h b/gas/config/te-aux.h
new file mode 100644
index 0000000000..da6fa0164c
--- /dev/null
+++ b/gas/config/te-aux.h
@@ -0,0 +1,17 @@
+#define TE_AUX
+
+/* From obj-coff.h:
+ This internal_lineno crap is to stop namespace pollution from the
+ bfd internal coff headerfile. */
+#define internal_lineno bfd_internal_lineno
+#include "coff/aux-coff.h" /* override bits in coff/internal.h */
+#undef internal_lineno
+
+#define COFF_NOLOAD_PROBLEM
+#define KEEP_RELOC_INFO
+
+#include "obj-format.h"
+
+#ifndef LOCAL_LABELS_FB
+#define LOCAL_LABELS_FB 1
+#endif
diff --git a/gas/config/te-delt88.h b/gas/config/te-delt88.h
new file mode 100644
index 0000000000..adcd6b7f7b
--- /dev/null
+++ b/gas/config/te-delt88.h
@@ -0,0 +1,13 @@
+/* This file is te-delta88.h. */
+
+#define TE_DELTA88 1
+
+#define COFF_NOLOAD_PROBLEM 1
+
+/* Added these, because if we don't know what we're targetting we may
+ need an assembler version of libgcc, and that will use local
+ labels. */
+#define LOCAL_LABELS_DOLLAR 1
+#define LOCAL_LABELS_FB 1
+
+#include "obj-format.h"
diff --git a/gas/config/te-delta.h b/gas/config/te-delta.h
new file mode 100644
index 0000000000..be6c62c6c1
--- /dev/null
+++ b/gas/config/te-delta.h
@@ -0,0 +1,14 @@
+#define TE_DELTA
+
+#include "obj-format.h"
+
+#define COFF_NOLOAD_PROBLEM 1
+#define COFF_COMMON_ADDEND 1
+
+/* Added these, because if we don't know what we're targetting we may
+ need an assembler version of libgcc, and that will use local
+ labels. */
+#define LOCAL_LABELS_DOLLAR 1
+#define LOCAL_LABELS_FB 1
+
+/* end of te-delta.h */
diff --git a/gas/config/te-dpx2.h b/gas/config/te-dpx2.h
new file mode 100644
index 0000000000..45341ca5b3
--- /dev/null
+++ b/gas/config/te-dpx2.h
@@ -0,0 +1,12 @@
+/* Machine specific defines for the dpx2 machine */
+
+/* The magic number is not the usual MC68MAGIC. */
+#define COFF_MAGIC MC68KBCSMAGIC
+
+#define REGISTER_PREFIX_OPTIONAL 1
+
+#define TARGET_FORMAT "coff-m68k-un"
+
+#include "obj-format.h"
+
+/* end of te-dpx2.h */
diff --git a/gas/config/te-dynix.h b/gas/config/te-dynix.h
new file mode 100644
index 0000000000..9e7b30f978
--- /dev/null
+++ b/gas/config/te-dynix.h
@@ -0,0 +1,7 @@
+/* This is for i386-sequent-bsd. The assembler probably does not
+ actually work, as the support in BFD is not complete as of this
+ writing. See bfd/i386-dynix.c. */
+
+#define TE_DYNIX 1
+
+#include "obj-format.h"
diff --git a/gas/config/te-epoc-pe.h b/gas/config/te-epoc-pe.h
new file mode 100644
index 0000000000..6c5f9141d2
--- /dev/null
+++ b/gas/config/te-epoc-pe.h
@@ -0,0 +1,8 @@
+#define TE_PE
+#define TE_EPOC
+#define LEX_AT 1 /* can have @'s inside labels */
+
+/* The PE format supports long section names. */
+#define COFF_LONG_SECTION_NAMES
+
+#include "obj-format.h"
diff --git a/gas/config/te-generic.h b/gas/config/te-generic.h
new file mode 100644
index 0000000000..b8eda4505f
--- /dev/null
+++ b/gas/config/te-generic.h
@@ -0,0 +1,22 @@
+/*
+ * This file is te-generic.h and is intended to be a template for
+ * target environment specific header files.
+ *
+ * It is my intent that this file will evolve into a file suitable for config,
+ * compile, and copying as an aid for testing and porting. xoxorich.
+ */
+
+/* Added these, because if we don't know what we're targetting we may
+ need an assembler version of libgcc, and that will use local
+ labels. */
+#define LOCAL_LABELS_DOLLAR 1
+#define LOCAL_LABELS_FB 1
+
+/* these define interfaces */
+#ifdef OBJ_HEADER
+#include OBJ_HEADER
+#else
+#include "obj-format.h"
+#endif
+
+/* end of te-generic.h */
diff --git a/gas/config/te-go32.h b/gas/config/te-go32.h
new file mode 100644
index 0000000000..49fbd2e1ac
--- /dev/null
+++ b/gas/config/te-go32.h
@@ -0,0 +1,16 @@
+/*
+ * This file is te-go32.h
+ */
+
+#define TE_GO32
+
+#define LOCAL_LABELS_DOLLAR 1
+#define LOCAL_LABELS_FB 1
+
+#define TARGET_FORMAT "coff-go32"
+
+/* GAS should treat '.align value' as an alignment of 2**value */
+#define USE_ALIGN_PTWO
+
+/* these define interfaces */
+#include "obj-format.h"
diff --git a/gas/config/te-hp300.h b/gas/config/te-hp300.h
new file mode 100644
index 0000000000..8e94ab4167
--- /dev/null
+++ b/gas/config/te-hp300.h
@@ -0,0 +1,25 @@
+/* te-hp300.h -- hpux 9000/300 target environment declarations.
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define LOCAL_LABELS_DOLLAR 1
+#define LOCAL_LABELS_FB 1
+
+#include "obj-format.h"
+
+/* end of te-hp300.h */
diff --git a/gas/config/te-hppa.h b/gas/config/te-hppa.h
new file mode 100644
index 0000000000..8fc4fa7806
--- /dev/null
+++ b/gas/config/te-hppa.h
@@ -0,0 +1,26 @@
+/* Machine specific defines for the PA machine
+ Copyright 1987, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ HP PA-RISC and OSF/1 support was contributed by the Center for
+ Software Science at the University of Utah.
+ */
+
+/* these define interfaces */
+#include "obj-format.h"
diff --git a/gas/config/te-i386aix.h b/gas/config/te-i386aix.h
new file mode 100644
index 0000000000..f8f0945c94
--- /dev/null
+++ b/gas/config/te-i386aix.h
@@ -0,0 +1,29 @@
+/*
+ * This file is te-i386aix.h and is built from pieces of code from Minh Tran-Le
+ * <TRANLE@INTELLICORP.COM> by rich@cygnus.com.
+ */
+
+#define TE_I386AIX 1
+
+#include "obj-format.h"
+
+/*
+ * Undefine REVERSE_SORT_RELOCS to keep the relocation entries sorted
+ * in ascending vaddr.
+ */
+#undef REVERSE_SORT_RELOCS
+
+/*
+ * Define KEEP_RELOC_INFO so that the strip reloc info flag F_RELFLG
+ * is not used in the filehdr for COFF output.
+ */
+#define KEEP_RELOC_INFO
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 79
+ * End:
+ */
+
+/* end of te-i386aix.h */
diff --git a/gas/config/te-ic960.h b/gas/config/te-ic960.h
new file mode 100644
index 0000000000..8331fb962e
--- /dev/null
+++ b/gas/config/te-ic960.h
@@ -0,0 +1,38 @@
+/* This file is te-ic960.h
+ Copyright (C) 1987-1992, 94, 95, 1997 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/*
+ * This file is te-ic960.h and is intended to define ic960 environment
+ * specific differences.
+ */
+
+#define OBJ_COFF_OMIT_OPTIONAL_HEADER
+
+#ifndef BFD_ASSEMBLER
+#define LOCAL_LABEL(name) ((name[0] =='L') \
+ || (name[0] =='.' \
+ && (name[1]=='C' \
+ || name[1]=='I' \
+ || name[1]=='.')))
+#endif
+
+#include "obj-format.h"
+
+/* end of te-ic960.h */
diff --git a/gas/config/te-linux.h b/gas/config/te-linux.h
new file mode 100644
index 0000000000..c235a7ab8a
--- /dev/null
+++ b/gas/config/te-linux.h
@@ -0,0 +1,4 @@
+#define TE_LINUX
+#define LOCAL_LABELS_FB 1
+
+#include "obj-format.h"
diff --git a/gas/config/te-lnews.h b/gas/config/te-lnews.h
new file mode 100644
index 0000000000..acbcc5a641
--- /dev/null
+++ b/gas/config/te-lnews.h
@@ -0,0 +1,5 @@
+/* te-lnews.h -- little-endian NEWS emulation. */
+
+#define ECOFF_LITTLE_FORMAT "ecoff-biglittlemips"
+
+#include "obj-format.h"
diff --git a/gas/config/te-lynx.h b/gas/config/te-lynx.h
new file mode 100644
index 0000000000..708515d0cd
--- /dev/null
+++ b/gas/config/te-lynx.h
@@ -0,0 +1,7 @@
+#define TE_LYNX
+
+#include "obj-format.h"
+
+#ifndef LOCAL_LABELS_FB
+#define LOCAL_LABELS_FB 1
+#endif
diff --git a/gas/config/te-mach.h b/gas/config/te-mach.h
new file mode 100644
index 0000000000..b7547f8c81
--- /dev/null
+++ b/gas/config/te-mach.h
@@ -0,0 +1,2 @@
+#define TE_Mach
+#include "obj-format.h"
diff --git a/gas/config/te-macos.h b/gas/config/te-macos.h
new file mode 100644
index 0000000000..5f48dc4478
--- /dev/null
+++ b/gas/config/te-macos.h
@@ -0,0 +1,11 @@
+/* This file is te-macos.h. */
+
+#define TE_POWERMAC 1
+
+/* Added these, because if we don't know what we're targetting we may
+ need an assembler version of libgcc, and that will use local
+ labels. */
+#define LOCAL_LABELS_DOLLAR 1
+#define LOCAL_LABELS_FB 1
+
+#include "obj-format.h"
diff --git a/gas/config/te-multi.h b/gas/config/te-multi.h
new file mode 100644
index 0000000000..b8eda4505f
--- /dev/null
+++ b/gas/config/te-multi.h
@@ -0,0 +1,22 @@
+/*
+ * This file is te-generic.h and is intended to be a template for
+ * target environment specific header files.
+ *
+ * It is my intent that this file will evolve into a file suitable for config,
+ * compile, and copying as an aid for testing and porting. xoxorich.
+ */
+
+/* Added these, because if we don't know what we're targetting we may
+ need an assembler version of libgcc, and that will use local
+ labels. */
+#define LOCAL_LABELS_DOLLAR 1
+#define LOCAL_LABELS_FB 1
+
+/* these define interfaces */
+#ifdef OBJ_HEADER
+#include OBJ_HEADER
+#else
+#include "obj-format.h"
+#endif
+
+/* end of te-generic.h */
diff --git a/gas/config/te-nbsd.h b/gas/config/te-nbsd.h
new file mode 100644
index 0000000000..cee4600077
--- /dev/null
+++ b/gas/config/te-nbsd.h
@@ -0,0 +1,23 @@
+/* te-nbsd.h -- NetBSD target environment declarations.
+ Copyright (C) 1987, 90, 91, 92, 94, 95, 1998 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#define TE_NetBSD 1
+#define LOCAL_LABELS_FB 1
+#include "obj-format.h"
diff --git a/gas/config/te-nbsd532.h b/gas/config/te-nbsd532.h
new file mode 100644
index 0000000000..8cf9e5fab5
--- /dev/null
+++ b/gas/config/te-nbsd532.h
@@ -0,0 +1,19 @@
+/*
+ * This file is te-netbsd532.h
+ *
+ * Written by Ian Dall <idall@eleceng.adelaide.edu.au>
+ *
+ * 19-Jun-94
+ *
+ */
+
+#define TARGET_FORMAT "a.out-ns32k-netbsd"
+
+#include "obj-format.h"
+
+/* Maybe these should be more like TC_NS32532 and TC_NS32381 in case
+ * of conflicts. NS32381 is used in opcode/ns32k.h and that is also
+ * used by GDB. Need to check.
+ */
+#define NS32532
+#define NS32381
diff --git a/gas/config/te-pc532mach.h b/gas/config/te-pc532mach.h
new file mode 100644
index 0000000000..0ee7ff8d79
--- /dev/null
+++ b/gas/config/te-pc532mach.h
@@ -0,0 +1,19 @@
+/*
+ * This file is te-pc532.h
+ *
+ * Written by Ian Dall <idall@eleceng.adelaide.edu.au>
+ *
+ * 24-May-94
+ *
+ */
+
+#define TARGET_FORMAT "a.out-pc532-mach"
+
+#include "obj-format.h"
+
+/* Maybe these should be more like TC_NS32532 and TC_NS32381 in case
+ * of conflicts. NS32381 is used in opcode/ns32k.h and that is also
+ * used by GDB. Need to check.
+ */
+#define NS32532
+#define NS32381
diff --git a/gas/config/te-pe.h b/gas/config/te-pe.h
new file mode 100644
index 0000000000..1c1f0b27bc
--- /dev/null
+++ b/gas/config/te-pe.h
@@ -0,0 +1,7 @@
+#define TE_PE
+#define LEX_AT 1 /* can have @'s inside labels */
+
+/* The PE format supports long section names. */
+#define COFF_LONG_SECTION_NAMES
+
+#include "obj-format.h"
diff --git a/gas/config/te-ppcnw.h b/gas/config/te-ppcnw.h
new file mode 100644
index 0000000000..2ddf050381
--- /dev/null
+++ b/gas/config/te-ppcnw.h
@@ -0,0 +1,31 @@
+/* te-ppcnw.h -- Power PC running Netware environment declarations.
+ Copyright (C) 1994 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Added these, because if we don't know what we're targetting we may
+ need an assembler version of libgcc, and that will use local
+ labels. */
+#define LOCAL_LABELS_DOLLAR 1
+#define LOCAL_LABELS_FB 1
+
+/* these define interfaces */
+#include "obj-format.h"
+
+/* gcc uses escape sequences for ppc/netware */
+
+#undef NO_STRING_ESCAPES
diff --git a/gas/config/te-psos.h b/gas/config/te-psos.h
new file mode 100644
index 0000000000..2ad4153b81
--- /dev/null
+++ b/gas/config/te-psos.h
@@ -0,0 +1,22 @@
+/*
+ * This file is te-psos.h for embedded systems running pSOS.
+ * Contributed by Martin Anantharaman (martin@mail.imech.uni-duisburg.de)
+ */
+
+#define TE_PSOS
+
+/* Added these, because if we don't know what we're targetting we may
+ need an assembler version of libgcc, and that will use local
+ labels. */
+
+#define LOCAL_LABELS_DOLLAR 1
+#define LOCAL_LABELS_FB 1
+
+/* This makes GAS more versatile and blocks some ELF'isms in
+ tc-m68k.h. */
+
+#define REGISTER_PREFIX_OPTIONAL 1
+
+#include "obj-format.h"
+
+/* end of te-psos.h */
diff --git a/gas/config/te-riscix.h b/gas/config/te-riscix.h
new file mode 100644
index 0000000000..7c7253ebcb
--- /dev/null
+++ b/gas/config/te-riscix.h
@@ -0,0 +1,6 @@
+#define TE_RISCIX
+
+#define LOCAL_LABELS_DOLLAR 1
+#define LOCAL_LABELS_FB 1
+
+#include "obj-format.h"
diff --git a/gas/config/te-sparcaout.h b/gas/config/te-sparcaout.h
new file mode 100644
index 0000000000..63101840fa
--- /dev/null
+++ b/gas/config/te-sparcaout.h
@@ -0,0 +1,21 @@
+/* te-sparcaout.h -- embedded sparc-aout target environment declarations.
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TE_SPARCAOUT 1
+#include "obj-format.h"
diff --git a/gas/config/te-sun3.h b/gas/config/te-sun3.h
new file mode 100644
index 0000000000..475d42b74f
--- /dev/null
+++ b/gas/config/te-sun3.h
@@ -0,0 +1,48 @@
+/* te-sun3.h -- Sun-3 target environment declarations.
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This header file contains the #defines specific
+ to SUN computer SUN 3 series computers. (The only kind
+ we have around here, unfortunatly.)
+
+ Rumor has it that this file will work on the Sun-2 if the assembler
+ is called with -m68010 This is not tested. */
+
+
+#define TE_SUN3 1
+
+#define LOCAL_LABELS_DOLLAR 1
+#define LOCAL_LABELS_FB 1
+
+/* Could also be :
+ #define S_LOCAL_NAME(s) (S_GET_NAME(s)[0] == '.' &&
+ S_GET_NAME(s)[1] == 'L' ||
+ S_GET_NAME(s)[1] == '.')
+ */
+
+#include "obj-format.h"
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of te-sun3.h */
diff --git a/gas/config/te-svr4.h b/gas/config/te-svr4.h
new file mode 100644
index 0000000000..7217ee119e
--- /dev/null
+++ b/gas/config/te-svr4.h
@@ -0,0 +1,4 @@
+#define TE_SVR4
+#define LOCAL_LABELS_FB 1
+
+#include "obj-format.h"
diff --git a/gas/config/te-sysv32.h b/gas/config/te-sysv32.h
new file mode 100644
index 0000000000..923e6e5799
--- /dev/null
+++ b/gas/config/te-sysv32.h
@@ -0,0 +1,6 @@
+/* Remove leading underscore from the gcc generated symbol names */
+#define STRIP_UNDERSCORE
+
+#include "obj-format.h"
+
+/* end of te-sysv32.h */
diff --git a/gas/config/vax-inst.h b/gas/config/vax-inst.h
new file mode 100644
index 0000000000..2ad8f98c18
--- /dev/null
+++ b/gas/config/vax-inst.h
@@ -0,0 +1,77 @@
+/* vax-inst.h - GNU - Part of vax.c
+ Copyright (C) 1987, 1992, 1995 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * This is part of vax-ins-parse.c & friends.
+ * We want to parse a vax instruction text into a tree defined here.
+ */
+
+#define VIT_MAX_OPERANDS (6) /* maximum number of operands in one */
+/* single vax instruction */
+
+struct vop /* vax instruction operand */
+{
+ short int vop_ndx; /* -1, or index register. eg 7=[R7] */
+ short int vop_reg; /* -1, or register number. eg @I^#=0xF */
+ /* Helps distinguish "abs" from "abs(PC)". */
+ short int vop_mode; /* addressing mode 4 bits. eg I^#=0x9 */
+ char vop_short; /* operand displacement length as written */
+ /* ' '=none, "bilsw"=B^I^L^S^W^. */
+ char vop_access; /* 'b'branch ' 'no-instruction 'amrvw'norm */
+ char vop_width; /* Operand width, one of "bdfghloqw" */
+ const char *vop_warn; /* warning message of this operand, if any */
+ const char *vop_error; /* say if operand is inappropriate */
+ char *vop_expr_begin; /* Unparsed expression, 1st char ... */
+ char *vop_expr_end; /* ... last char. */
+ unsigned char vop_nbytes; /* number of bytes in datum */
+};
+
+
+typedef long vax_opcodeT; /* For initialising array of opcodes */
+/* Some synthetic opcodes > 16 bits! */
+
+#define VIT_OPCODE_SYNTHETIC 0x80000000 /* Not real hardware instruction. */
+#define VIT_OPCODE_SPECIAL 0x40000000 /* Not normal branch optimising. */
+/* Never set without ..._SYNTHETIC */
+
+#define VAX_WIDTH_UNCONDITIONAL_JUMP '-' /* These are encoded into */
+#define VAX_WIDTH_CONDITIONAL_JUMP '?' /* vop_width when vop_access=='b' */
+#define VAX_WIDTH_WORD_JUMP '!' /* and VIT_OPCODE_SYNTHETIC set. */
+#define VAX_WIDTH_BYTE_JUMP ':' /* */
+
+#define VAX_JMP (0x17) /* Useful for branch optimising. Jump instr*/
+#define VAX_PC_RELATIVE_MODE (0xef) /* Use it after VAX_JMP */
+#define VAX_ABSOLUTE_MODE (0x9F)/* Use as @#... */
+#define VAX_BRB (0x11) /* Canonical branch. */
+#define VAX_BRW (0x31) /* Another canonical branch */
+#define VAX_WIDEN_WORD (0x20) /* Add this to byte branch to get word br. */
+#define VAX_WIDEN_LONG (0x6) /* Add this to byte branch to get long jmp.*/
+/* Needs VAX_PC_RELATIVE_MODE byte after it*/
+
+struct vit /* vax instruction tree */
+{
+ /* vit_opcode is char[] for portability. */
+ char vit_opcode[sizeof (vax_opcodeT)];
+ unsigned char vit_opcode_nbytes; /* How long is _opcode? (chars) */
+ unsigned char vit_operands; /* */
+ struct vop vit_operand[VIT_MAX_OPERANDS]; /* operands */
+ const char *vit_error; /* "" or error text */
+};
+
+/* end of vax-inst.h */
diff --git a/gas/config/vms-a-conf.h b/gas/config/vms-a-conf.h
new file mode 100644
index 0000000000..688fc6890c
--- /dev/null
+++ b/gas/config/vms-a-conf.h
@@ -0,0 +1,129 @@
+/* vms-alpha-conf.h. Generated manually from conf.in,
+ and used by config-gas-alpha.com when constructing config.h. */
+
+/* Define if using alloca.c. */
+#ifdef __GNUC__
+#undef C_ALLOCA
+#else
+#define C_ALLOCA
+#endif
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+#undef CRAY_STACKSEG_END
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+#undef HAVE_ALLOCA_H
+
+/* Define as __inline if that's what the C compiler calls it. */
+#ifdef __GNUC__
+#undef inline
+#else
+#define inline
+#endif
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+#define STACK_DIRECTION (-1)
+
+/* Should gas use high-level BFD interfaces? */
+#define BFD_ASSEMBLER
+
+/* Some assert/preprocessor combinations are incapable of handling
+ certain kinds of constructs in the argument of assert. For example,
+ quoted strings (if requoting isn't done right) or newlines. */
+#ifdef __GNUC__
+#undef BROKEN_ASSERT
+#else
+#define BROKEN_ASSERT
+#endif
+
+/* If we aren't doing cross-assembling, some operations can be optimized,
+ since byte orders and value sizes don't need to be adjusted. */
+#undef CROSS_COMPILE
+
+/* Some gas code wants to know these parameters. */
+#define TARGET_ALIAS "alpha-vms"
+#define TARGET_CPU "alpha"
+#define TARGET_CANONICAL "alpha-dec-vms"
+#define TARGET_OS "openVMS/Alpha"
+#define TARGET_VENDOR "dec"
+
+/* Sometimes the system header files don't declare malloc and realloc. */
+#undef NEED_DECLARATION_MALLOC
+
+/* Sometimes the system header files don't declare free. */
+#undef NEED_DECLARATION_FREE
+
+/* Sometimes errno.h doesn't declare errno itself. */
+#undef NEED_DECLARATION_ERRNO
+
+#undef MANY_SEGMENTS
+
+/* Needed only for sparc configuration */
+#undef sparcv9
+
+/* Define if you have the remove function. */
+#define HAVE_REMOVE
+
+/* Define if you have the unlink function. */
+#undef HAVE_UNLINK
+
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H
+
+/* Define if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H
+
+/* Define if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define if you have the <sys/types.h> header file. */
+#ifdef __GNUC__
+#define HAVE_SYS_TYPES_H
+#else
+#undef HAVE_SYS_TYPES_H
+#endif
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H /* config-gas.com will make one if necessary */
+
+/* Define if you have the <varargs.h> header file. */
+#undef HAVE_VARARGS_H
+
+/* VMS-specific: we need to set up EXIT_xxx here because the default
+ values in as.h are inappropriate for VMS, but we also want to prevent
+ as.h's inclusion of <stdlib.h> from triggering redefinition warnings.
+ <stdlib.h> guards itself against multiple inclusion, so including it
+ here turns as.h's later #include into a no-op. (We can't simply use
+ #ifndef HAVE_STDLIB_H here, because the <stdlib.h> in several older
+ gcc-vms distributions neglects to define these two required macros.) */
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if __DECC
+#undef EXIT_SUCCESS
+#undef EXIT_FAILURE
+#define EXIT_SUCCESS 1 /* SS$_NORMAL, STS$K_SUCCESS */
+#define EXIT_FAILURE 0x10000002 /* (STS$K_ERROR | STS$M_INHIB_MSG) */
+#endif
+
+#include <unixlib.h>
+#if __DECC
+extern int strcasecmp ();
+extern int strncasecmp ();
+#endif
diff --git a/gas/config/vms-conf.h b/gas/config/vms-conf.h
new file mode 100644
index 0000000000..7225cfce1b
--- /dev/null
+++ b/gas/config/vms-conf.h
@@ -0,0 +1,179 @@
+/* vms-conf.h. Generated manually from conf.in,
+ and used by config-gas.com when constructing config.h. */
+
+/* Define if using alloca.c. */
+#ifdef __GNUC__
+#undef C_ALLOCA
+#else
+#define C_ALLOCA
+#endif
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+#undef CRAY_STACKSEG_END
+
+/* Define if you have alloca, as a function or macro. */
+#undef HAVE_ALLOCA
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+#undef HAVE_ALLOCA_H
+
+/* Define as __inline if that's what the C compiler calls it. */
+#ifdef __GNUC__
+#undef inline
+#else
+#define inline
+#endif
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+#define STACK_DIRECTION (-1)
+
+/* Define if lex declares yytext as a char * by default, not a char[]. */
+#undef YYTEXT_POINTER
+
+/* Name of package. */
+#undef PACKAGE
+
+/* Version of package. */
+/* Define in by config-gas.com */
+/* #undef VERSION */
+
+/* Should gas use high-level BFD interfaces? */
+#undef BFD_ASSEMBLER
+
+/* Some assert/preprocessor combinations are incapable of handling
+ certain kinds of constructs in the argument of assert. For example,
+ quoted strings (if requoting isn't done right) or newlines. */
+#ifdef __GNUC__
+#undef BROKEN_ASSERT
+#else
+#define BROKEN_ASSERT
+#endif
+
+/* If we aren't doing cross-assembling, some operations can be optimized,
+ since byte orders and value sizes don't need to be adjusted. */
+#undef CROSS_COMPILE
+
+/* Some gas code wants to know these parameters. */
+#define TARGET_ALIAS "vms"
+#define TARGET_CPU "vax"
+#define TARGET_CANONICAL "vax-dec-vms"
+#define TARGET_OS "vms"
+#define TARGET_VENDOR "dec"
+
+/* Sometimes the system header files don't declare strstr. */
+#undef NEED_DECLARATION_STRSTR
+
+/* Sometimes the system header files don't declare malloc and realloc. */
+#undef NEED_DECLARATION_MALLOC
+
+/* Sometimes the system header files don't declare free. */
+#undef NEED_DECLARATION_FREE
+
+/* Sometimes the system header files don't declare sbrk. */
+#undef NEED_DECLARATION_SBRK
+
+/* Sometimes errno.h doesn't declare errno itself. */
+#undef NEED_DECLARATION_ERRNO
+
+#undef MANY_SEGMENTS
+
+/* The configure script defines this for some targets based on the
+ target name used. It is not always defined. */
+#undef TARGET_BYTES_BIG_ENDIAN
+
+/* Needed only for some configurations that can produce multiple output
+ formats. */
+#undef DEFAULT_EMULATION
+#undef EMULATIONS
+#undef USE_EMULATIONS
+#undef OBJ_MAYBE_AOUT
+#undef OBJ_MAYBE_BOUT
+#undef OBJ_MAYBE_COFF
+#undef OBJ_MAYBE_ECOFF
+#undef OBJ_MAYBE_ELF
+#undef OBJ_MAYBE_GENERIC
+#undef OBJ_MAYBE_HP300
+#undef OBJ_MAYBE_IEEE
+#undef OBJ_MAYBE_SOM
+#undef OBJ_MAYBE_VMS
+
+/* Used for some of the COFF configurations, when the COFF code needs
+ to select something based on the CPU type before it knows it... */
+#undef I386COFF
+#undef M68KCOFF
+#undef M88KCOFF
+
+/* Using cgen code? */
+#undef USING_CGEN
+
+/* Needed only for sparc configuration. */
+#undef DEFAULT_ARCH
+
+/* Needed only for PowerPC Solaris. */
+#undef TARGET_SOLARIS_COMMENT
+
+/* Needed only for SCO 5. */
+#undef SCO_ELF
+
+/* Define if you have the remove function. */
+#define HAVE_REMOVE
+
+/* Define if you have the sbrk function. */
+/* sbrk() is available, but we don't want gas to use it. */
+#undef HAVE_SBRK
+
+/* Define if you have the unlink function. */
+#undef HAVE_UNLINK
+
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H
+
+/* Define if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H
+
+/* Define if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define if you have the <sys/types.h> header file. */
+#ifdef __GNUC__
+#define HAVE_SYS_TYPES_H
+#else
+#undef HAVE_SYS_TYPES_H
+#endif
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H /* config-gas.com will make one if necessary */
+
+/* Define if you have the <varargs.h> header file. */
+#undef HAVE_VARARGS_H
+
+/* VMS-specific: we need to set up EXIT_xxx here because the default
+ values in as.h are inappropriate for VMS, but we also want to prevent
+ as.h's inclusion of <stdlib.h> from triggering redefinition warnings.
+ <stdlib.h> guards itself against multiple inclusion, so including it
+ here turns as.h's later #include into a no-op. (We can't simply use
+ #ifndef HAVE_STDLIB_H here, because the <stdlib.h> in several older
+ gcc-vms distributions neglects to define these two required macros.) */
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#undef EXIT_SUCCESS
+#undef EXIT_FAILURE
+#endif
+#define EXIT_SUCCESS 1 /* SS$_NORMAL, STS$K_SUCCESS */
+#define EXIT_FAILURE 0x10000002 /* (STS$K_ERROR | STS$M_INHIB_MSG) */
diff --git a/gas/configure b/gas/configure
new file mode 100755
index 0000000000..b8eefe4a59
--- /dev/null
+++ b/gas/configure
@@ -0,0 +1,5750 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+ --enable-shared[=PKGS] build shared libraries [default=yes]"
+ac_help="$ac_help
+ --enable-static[=PKGS] build static libraries [default=yes]"
+ac_help="$ac_help
+ --with-gnu-ld assume the C compiler uses GNU ld [default=no]"
+ac_help="$ac_help
+ --enable-bfd-assembler use BFD back end for writing object files"
+ac_help="$ac_help
+ targets alternative target configurations besides the primary"
+ac_help="$ac_help
+ --enable-commonbfdlib build shared BFD/opcodes/libiberty library"
+ac_help="$ac_help
+ --disable-nls do not use Native Language Support"
+ac_help="$ac_help
+ --with-included-gettext use the GNU gettext library included here"
+ac_help="$ac_help
+ --enable-maintainer-mode enable make rules and dependencies not useful
+ (and sometimes confusing) to the casual installer"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.13"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=as.h
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+# configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+# same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+# as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:592: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+echo "configure:613: checking target system type" >&5
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+ case $nonopt in
+ NONE) target_alias=$host_alias ;;
+ *) target_alias=$nonopt ;;
+ esac ;;
+esac
+
+target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:631: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+ case $nonopt in
+ NONE) build_alias=$host_alias ;;
+ *) build_alias=$nonopt ;;
+ esac ;;
+esac
+
+build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:666: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
+echo "configure:719: checking whether build environment is sane" >&5
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
+ if test "$*" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftestfile`
+ fi
+ if test "$*" != "X $srcdir/configure conftestfile" \
+ && test "$*" != "X conftestfile $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ { echo "configure: error: ls -t appears to fail. Make sure there is not a broken
+alias in your environment" 1>&2; exit 1; }
+ fi
+
+ test "$2" = conftestfile
+ )
+then
+ # Ok.
+ :
+else
+ { echo "configure: error: newly created file is older than distributed files!
+Check your system clock" 1>&2; exit 1; }
+fi
+rm -f conftest*
+echo "$ac_t""yes" 1>&6
+if test "$program_transform_name" = s,x,x,; then
+ program_transform_name=
+else
+ # Double any \ or $. echo might interpret backslashes.
+ cat <<\EOF_SED > conftestsed
+s,\\,\\\\,g; s,\$,$$,g
+EOF_SED
+ program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
+ rm -f conftestsed
+fi
+test "$program_prefix" != NONE &&
+ program_transform_name="s,^,${program_prefix},; $program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
+
+# sed with no file args requires a program.
+test "$program_transform_name" = "" && program_transform_name="s,x,x,"
+
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+echo "configure:776: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftestmake <<\EOF
+all:
+ @echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+ eval ac_cv_prog_make_${ac_make}_set=yes
+else
+ eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ SET_MAKE=
+else
+ echo "$ac_t""no" 1>&6
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+PACKAGE=gas
+
+VERSION=2.9.4
+
+if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
+ { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; }
+fi
+cat >> confdefs.h <<EOF
+#define PACKAGE "$PACKAGE"
+EOF
+
+cat >> confdefs.h <<EOF
+#define VERSION "$VERSION"
+EOF
+
+
+
+missing_dir=`cd $ac_aux_dir && pwd`
+echo $ac_n "checking for working aclocal""... $ac_c" 1>&6
+echo "configure:822: checking for working aclocal" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (aclocal --version) < /dev/null > /dev/null 2>&1; then
+ ACLOCAL=aclocal
+ echo "$ac_t""found" 1>&6
+else
+ ACLOCAL="$missing_dir/missing aclocal"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working autoconf""... $ac_c" 1>&6
+echo "configure:835: checking for working autoconf" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (autoconf --version) < /dev/null > /dev/null 2>&1; then
+ AUTOCONF=autoconf
+ echo "$ac_t""found" 1>&6
+else
+ AUTOCONF="$missing_dir/missing autoconf"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working automake""... $ac_c" 1>&6
+echo "configure:848: checking for working automake" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (automake --version) < /dev/null > /dev/null 2>&1; then
+ AUTOMAKE=automake
+ echo "$ac_t""found" 1>&6
+else
+ AUTOMAKE="$missing_dir/missing automake"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working autoheader""... $ac_c" 1>&6
+echo "configure:861: checking for working autoheader" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (autoheader --version) < /dev/null > /dev/null 2>&1; then
+ AUTOHEADER=autoheader
+ echo "$ac_t""found" 1>&6
+else
+ AUTOHEADER="$missing_dir/missing autoheader"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6
+echo "configure:874: checking for working makeinfo" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (makeinfo --version) < /dev/null > /dev/null 2>&1; then
+ MAKEINFO=makeinfo
+ echo "$ac_t""found" 1>&6
+else
+ MAKEINFO="$missing_dir/missing makeinfo"
+ echo "$ac_t""missing" 1>&6
+fi
+
+
+
+# Check whether --enable-shared or --disable-shared was given.
+if test "${enable_shared+set}" = set; then
+ enableval="$enable_shared"
+ p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_shared=yes ;;
+no) enable_shared=no ;;
+*)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+ for pkg in $enableval; do
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+else
+ enable_shared=yes
+fi
+
+# Check whether --enable-static or --disable-static was given.
+if test "${enable_static+set}" = set; then
+ enableval="$enable_static"
+ p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_static=yes ;;
+no) enable_static=no ;;
+*)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+ for pkg in $enableval; do
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+else
+ enable_static=yes
+fi
+
+# Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:937: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:967: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:997: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1048: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:1080: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 1091 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:1096: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:1122: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:1127: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1136: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:1155: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+
+# Check whether --with-gnu-ld or --without-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+ withval="$with_gnu_ld"
+ test "$withval" = no || with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi
+
+
+ac_prog=ld
+if test "$ac_cv_prog_gcc" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ echo $ac_n "checking for ld used by GCC""... $ac_c" 1>&6
+echo "configure:1199: checking for ld used by GCC" >&5
+ ac_prog=`($CC -print-prog-name=ld) 2>&5`
+ case "$ac_prog" in
+ # Accept absolute paths.
+ /* | [A-Za-z]:\\*)
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ echo $ac_n "checking for GNU ld""... $ac_c" 1>&6
+echo "configure:1217: checking for GNU ld" >&5
+else
+ echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
+echo "configure:1220: checking for non-GNU ld" >&5
+fi
+if eval "test \"`echo '$''{'ac_cv_path_LD'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -z "$LD"; then
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog"; then
+ ac_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+ test "$with_gnu_ld" != no && break
+ else
+ test "$with_gnu_ld" != yes && break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+else
+ ac_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$ac_cv_path_LD"
+if test -n "$LD"; then
+ echo "$ac_t""$LD" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+test -z "$LD" && { echo "configure: error: no acceptable ld found in \$PATH" 1>&2; exit 1; }
+
+echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6
+echo "configure:1256: checking if the linker ($LD) is GNU ld" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gnu_ld'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+ ac_cv_prog_gnu_ld=yes
+else
+ ac_cv_prog_gnu_ld=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gnu_ld" 1>&6
+
+
+echo $ac_n "checking for BSD-compatible nm""... $ac_c" 1>&6
+echo "configure:1272: checking for BSD-compatible nm" >&5
+if eval "test \"`echo '$''{'ac_cv_path_NM'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$NM"; then
+ # Let the user override the test.
+ ac_cv_path_NM="$NM"
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in /usr/ucb /usr/ccs/bin $PATH /bin; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/nm; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+ ac_cv_path_NM="$ac_dir/nm -B"
+ elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+ ac_cv_path_NM="$ac_dir/nm -p"
+ else
+ ac_cv_path_NM="$ac_dir/nm"
+ fi
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm
+fi
+fi
+
+NM="$ac_cv_path_NM"
+echo "$ac_t""$NM" 1>&6
+
+
+echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
+echo "configure:1307: checking whether ln -s works" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ rm -f conftestdata
+if ln -s X conftestdata 2>/dev/null
+then
+ rm -f conftestdata
+ ac_cv_prog_LN_S="ln -s"
+else
+ ac_cv_prog_LN_S=ln
+fi
+fi
+LN_S="$ac_cv_prog_LN_S"
+if test "$ac_cv_prog_LN_S" = "ln -s"; then
+ echo "$ac_t""yes" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test $host != $build; then
+ ac_tool_prefix=${host_alias}-
+else
+ ac_tool_prefix=
+fi
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+# Check for any special flags to pass to ltconfig.
+libtool_flags=
+test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared"
+test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static"
+test "$silent" = yes && libtool_flags="$libtool_flags --silent"
+test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc"
+test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld"
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case "$host" in
+*-*-irix6*)
+ # Find out which ABI we are using.
+ echo '#line 1349 "configure"' > conftest.$ac_ext
+ if { (eval echo configure:1350: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ case "`/usr/bin/file conftest.o`" in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ CFLAGS="$CFLAGS -belf"
+ ;;
+
+*-*-cygwin*)
+ # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dlltool; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1375: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_DLLTOOL'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$DLLTOOL"; then
+ ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+DLLTOOL="$ac_cv_prog_DLLTOOL"
+if test -n "$DLLTOOL"; then
+ echo "$ac_t""$DLLTOOL" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+if test -z "$ac_cv_prog_DLLTOOL"; then
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "dlltool", so it can be a program name with args.
+set dummy dlltool; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1407: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_DLLTOOL'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$DLLTOOL"; then
+ ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_DLLTOOL="dlltool"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_DLLTOOL" && ac_cv_prog_DLLTOOL="false"
+fi
+fi
+DLLTOOL="$ac_cv_prog_DLLTOOL"
+if test -n "$DLLTOOL"; then
+ echo "$ac_t""$DLLTOOL" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ DLLTOOL="false"
+fi
+fi
+
+# Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args.
+set dummy ${ac_tool_prefix}as; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1442: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_AS'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$AS"; then
+ ac_cv_prog_AS="$AS" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_AS="${ac_tool_prefix}as"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+AS="$ac_cv_prog_AS"
+if test -n "$AS"; then
+ echo "$ac_t""$AS" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+if test -z "$ac_cv_prog_AS"; then
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "as", so it can be a program name with args.
+set dummy as; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1474: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_AS'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$AS"; then
+ ac_cv_prog_AS="$AS" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_AS="as"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_AS" && ac_cv_prog_AS="false"
+fi
+fi
+AS="$ac_cv_prog_AS"
+if test -n "$AS"; then
+ echo "$ac_t""$AS" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ AS="false"
+fi
+fi
+
+
+ ;;
+
+esac
+
+# Actually configure libtool. ac_aux_dir is where install-sh is found.
+CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \
+LD="$LD" NM="$NM" RANLIB="$RANLIB" LN_S="$LN_S" \
+DLLTOOL="$DLLTOOL" AS="$AS" \
+${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \
+$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $host \
+|| { echo "configure: error: libtool configure failed" 1>&2; exit 1; }
+
+# Redirect the config.log output again, so that the ltconfig log is not
+# clobbered by the next message.
+exec 5>>./config.log
+
+
+user_bfd_gas=
+# Check whether --enable-bfd-assembler or --disable-bfd-assembler was given.
+if test "${enable_bfd_assembler+set}" = set; then
+ enableval="$enable_bfd_assembler"
+ case "${enableval}" in
+ yes) need_bfd=yes user_bfd_gas=yes ;;
+ no) user_bfd_gas=no ;;
+ *) { echo "configure: error: bad value ${enableval} given for bfd-assembler option" 1>&2; exit 1; } ;;
+esac
+fi
+# Check whether --enable-targets or --disable-targets was given.
+if test "${enable_targets+set}" = set; then
+ enableval="$enable_targets"
+ case "${enableval}" in
+ yes | "") { echo "configure: error: enable-targets option must specify target names or 'all'" 1>&2; exit 1; }
+ ;;
+ no) enable_targets= ;;
+ *) enable_targets=$enableval ;;
+esac
+fi
+# Check whether --enable-commonbfdlib or --disable-commonbfdlib was given.
+if test "${enable_commonbfdlib+set}" = set; then
+ enableval="$enable_commonbfdlib"
+ case "${enableval}" in
+ yes) commonbfdlib=true ;;
+ no) commonbfdlib=false ;;
+ *) { echo "configure: error: bad value ${enableval} for BFD commonbfdlib option" 1>&2; exit 1; } ;;
+esac
+fi
+
+using_cgen=no
+
+# Generate a header file
+
+
+
+
+te_file=generic
+
+# Makefile target for installing gas in $(tooldir)/bin.
+install_tooldir=install-exec-tooldir
+
+canon_targets=""
+if test -n "$enable_targets" ; then
+ for t in `echo $enable_targets | sed 's/,/ /g'`; do
+ result=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $t 2>/dev/null`
+ if test -n "$result" ; then
+ canon_targets="$canon_targets $result"
+# else
+# # Permit "all", etc. We don't support it yet though.
+# canon_targets="$canon_targets $t"
+ fi
+ done
+ _gas_uniq_list="$canon_targets"
+_gas_uniq_newlist=""
+for _gas_uniq_i in _gas_uniq_dummy $_gas_uniq_list ; do
+ case $_gas_uniq_i in
+ _gas_uniq_dummy) ;;
+ *) case " $_gas_uniq_newlist " in
+ *" $_gas_uniq_i "*) ;;
+ *) _gas_uniq_newlist="$_gas_uniq_newlist $_gas_uniq_i" ;;
+ esac ;;
+ esac
+done
+canon_targets=$_gas_uniq_newlist
+
+fi
+
+emulations=""
+
+for this_target in $target $canon_targets ; do
+
+ eval `echo $this_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/cpu=\1 vendor=\2 os=\3/'`
+
+ # check for architecture variants
+ arch=
+ endian=
+ case ${cpu} in
+ alpha*) cpu_type=alpha ;;
+ armeb) cpu_type=arm endian=big ;;
+ arm*) cpu_type=arm endian=little ;;
+ armb*) cpu_type=arm endian=little ;;
+ armv*l) cpu_type=arm endian=little ;;
+ armv*b) cpu_type=arm endian=big ;;
+ strongarm*) cpu_type=arm endian=little ;;
+ thumb*) cpu_type=arm endian=little ;;
+ hppa*) cpu_type=hppa ;;
+ i[456]86) cpu_type=i386 ;;
+ m680[012346]0) cpu_type=m68k ;;
+ m68008) cpu_type=m68k ;;
+ m683??) cpu_type=m68k ;;
+ m5200) cpu_type=m68k ;;
+ m8*) cpu_type=m88k ;;
+ mips*el) cpu_type=mips endian=little ;;
+ mips*) cpu_type=mips endian=big ;;
+ powerpcle*) cpu_type=ppc endian=little ;;
+ powerpc*) cpu_type=ppc endian=big ;;
+ rs6000*) cpu_type=ppc ;;
+ sparclite*) cpu_type=sparc arch=sparclite ;;
+ sparclet*) cpu_type=sparc arch=sparclet ;;
+ sparc64*) cpu_type=sparc arch=v9-64 ;;
+ sparc86x*) cpu_type=sparc arch=sparc86x ;;
+ sparc*) cpu_type=sparc arch=sparclite ;; # ??? See tc-sparc.c.
+ v850*) cpu_type=v850 ;;
+ *) cpu_type=${cpu} ;;
+ esac
+
+ if test ${this_target} = $target ; then
+ target_cpu_type=${cpu_type}
+ elif test ${target_cpu_type} != ${cpu_type} ; then
+ continue
+ fi
+
+ generic_target=${cpu_type}-$vendor-$os
+ dev=no
+ bfd_gas=no
+ em=generic
+
+ # assign object format
+ case ${generic_target} in
+ a29k-*-coff) fmt=coff ;;
+ a29k-amd-udi) fmt=coff ;;
+ a29k-amd-ebmon) fmt=coff ;;
+ a29k-nyu-sym1) fmt=coff ;;
+ a29k-*-vxworks*) fmt=coff ;;
+
+ alpha*-*-*vms*) fmt=evax ;;
+ alpha*-*-netware*) fmt=ecoff ;;
+ alpha*-*-openbsd*) fmt=ecoff ;;
+ alpha*-*-osf*) fmt=ecoff ;;
+ alpha*-*-linuxecoff*) fmt=ecoff ;;
+ alpha*-*-linux-gnu*) fmt=elf em=linux ;;
+ alpha*-*-netbsd*) fmt=elf em=nbsd ;;
+
+ arc-*-elf*) fmt=elf bfd_gas=yes ;;
+
+ arm-*-aout) fmt=aout ;;
+ arm-*-coff | thumb-*-coff) fmt=coff ;;
+ arm-*-elf | thumb-*-elf) fmt=elf ;;
+ arm-*-linux*aout*) fmt=aout em=linux ;;
+ arm-*-linux* | armv*-*-linux-gnu) fmt=elf em=linux ;;
+ arm-*-netbsd*) fmt=aout em=nbsd bfd_gas=yes ;;
+ arm-*-oabi | thumb-*-oabi) fmt=elf ;;
+ arm-epoc-pe | thumb-epoc-pe) fmt=coff em=epoc-pe ;;
+ arm-*-pe | thumb-*-pe) fmt=coff em=pe ;;
+ arm-*-riscix*) fmt=aout em=riscix ;;
+
+ d10v-*-*) fmt=elf bfd_gas=yes ;;
+ d30v-*-*) fmt=elf bfd_gas=yes ;;
+
+
+ fr30-*-*) fmt=elf bfd_gas=yes ;;
+
+ hppa-*-*elf*) fmt=elf em=hppa ;;
+ hppa-*-lites*) fmt=elf em=hppa ;;
+ hppa-*-osf*) fmt=som em=hppa ;;
+ hppa-*-rtems*) fmt=elf em=hppa ;;
+ hppa-*-hpux*) fmt=som em=hppa ;;
+ hppa-*-mpeix*) fmt=som em=hppa ;;
+ hppa-*-bsd*) fmt=som em=hppa ;;
+ hppa-*-hiux*) fmt=som em=hppa ;;
+
+ h8300-*-coff) fmt=coff ;;
+
+ i386-ibm-aix*) fmt=coff em=i386aix ;;
+ i386-sequent-bsd*) fmt=aout em=dynix bfd_gas=yes ;;
+ i386-*-beospe*) fmt=coff em=pe bfd_gas=yes ;;
+ i386-*-beoself* | i386-*-beos*) fmt=elf bfd_gas=yes ;;
+ i386-*-bsd*) fmt=aout em=386bsd ;;
+ i386-*-netbsd0.8) fmt=aout em=386bsd ;;
+ i386-*-netbsd*) fmt=aout em=nbsd bfd_gas=yes;;
+ i386-*-openbsd*) fmt=aout em=nbsd bfd_gas=yes;;
+ i386-*-linux*aout* | i386-*-linuxoldld) fmt=aout em=linux ;;
+ i386-*-linux*coff*) fmt=coff em=linux ;;
+ i386-*-linux-gnu*) fmt=elf em=linux bfd_gas=yes ;;
+ i386-*-lynxos*) fmt=coff em=lynx ;;
+ i386-*-sysv4* | i386-*-solaris* | i386-*-elf)
+ fmt=elf bfd_gas=yes ;;
+ i386-*-freebsdelf*) fmt=elf bfd_gas=yes ;;
+ i386-*-freebsd*) fmt=aout em=386bsd ;;
+ i386-*-coff | i386-*-sysv* | i386-*-sco3.2v5*coff | i386-*-isc*)
+ fmt=coff ;;
+ i386-*-sco3.2v5*) fmt=elf
+ if test ${this_target} = $target; then
+ cat >> confdefs.h <<\EOF
+#define SCO_ELF 1
+EOF
+
+ fi
+ ;;
+ i386-*-sco3.2*) fmt=coff ;;
+ i386-*-vsta) fmt=aout ;;
+ i386-*-msdosdjgpp* | i386-*-go32* | i386-go32-rtems*)
+ fmt=coff em=go32;;
+ i386-*-rtems*) fmt=coff ;;
+ i386-*-gnu*) fmt=elf ;;
+ i386-*-mach*)
+ fmt=aout em=mach bfd_gas=yes ;;
+ i386-*-msdos*) fmt=aout ;;
+ i386-*-moss*) fmt=elf ;;
+ i386-*-pe) fmt=coff em=pe ;;
+ i386-*-cygwin*) fmt=coff em=pe bfd_gas=yes ;;
+ i386-*-mingw32*) fmt=coff em=pe bfd_gas=yes ;;
+ i386-*-*nt*) fmt=coff em=pe ;;
+ i960-*-bout) fmt=bout ;;
+ i960-*-coff) fmt=coff em=ic960 ;;
+ i960-*-rtems*) fmt=coff em=ic960 ;;
+ i960-*-nindy*) fmt=bout ;;
+ i960-*-vxworks4*) fmt=bout ;;
+ i960-*-vxworks5.0) fmt=bout ;;
+ i960-*-vxworks5.*) fmt=coff em=ic960 ;;
+ i960-*-vxworks*) fmt=bout ;;
+
+ m32r-*-*) fmt=elf bfd_gas=yes ;;
+
+ m68k-*-vxworks* | m68k-ericsson-ose | m68k-*-sunos*)
+ fmt=aout em=sun3 ;;
+ m68k-motorola-sysv*) fmt=coff em=delta ;;
+ m68k-bull-sysv3*) fmt=coff em=dpx2 ;;
+ m68k-apollo-*) fmt=coff em=apollo ;;
+ m68k-*-sysv4*) # must be before -sysv*
+ fmt=elf em=svr4 ;;
+ m68k-*-elf*) fmt=elf ;;
+ m68k-*-coff | m68k-*-sysv* | m68k-*-rtems*)
+ fmt=coff ;;
+ m68k-*-hpux*) fmt=hp300 em=hp300 ;;
+ m68k-*-linux*aout*) fmt=aout em=linux ;;
+ m68k-*-linux-gnu*) fmt=elf em=linux ;;
+ m68k-*-gnu*) fmt=elf ;;
+ m68k-*-lynxos*) fmt=coff em=lynx ;;
+ m68k-*-netbsd*) fmt=aout em=nbsd bfd_gas=yes ;;
+ m68k-*-openbsd*) fmt=aout em=nbsd bfd_gas=yes ;;
+ m68k-apple-aux*) fmt=coff em=aux ;;
+ m68k-*-psos*) fmt=elf em=psos;;
+
+ m88k-motorola-sysv3*) fmt=coff em=delt88 ;;
+ m88k-*-coff*) fmt=coff ;;
+
+ mcore-*-elf) fmt=elf bfd_gas=yes ;;
+ mcore-*-pe) fmt=coff em=pe bfd_gas=yes ;;
+
+ # don't change em like *-*-bsd does
+ mips-dec-netbsd*) fmt=elf endian=little ;;
+ mips-dec-openbsd*) fmt=elf endian=little ;;
+ mips-dec-bsd*) fmt=aout endian=little ;;
+ mips-sony-bsd*) fmt=ecoff ;;
+ mips-*-bsd*) { echo "configure: error: Unknown vendor for mips-bsd configuration." 1>&2; exit 1; } ;;
+ mips-*-ultrix*) fmt=ecoff endian=little ;;
+ mips-*-osf*) fmt=ecoff endian=little ;;
+ mips-*-ecoff*) fmt=ecoff ;;
+ mips-*-ecoff*) fmt=ecoff ;;
+ mips-*-irix6*) fmt=elf ;;
+ mips-*-irix5*) fmt=elf ;;
+ mips-*-irix*) fmt=ecoff ;;
+ mips-*-lnews*) fmt=ecoff em=lnews ;;
+ mips-*-riscos*) fmt=ecoff ;;
+ mips-*-sysv*) fmt=ecoff ;;
+ mips-*-elf* | mips-*-rtems* | mips-*-linux-gnu* | mips-*-gnu* | mips-*-openbsd*)
+ fmt=elf ;;
+ mips-*-vxworks*) fmt=elf
+ cat >> confdefs.h <<\EOF
+#define MIPS_STABS_ELF 1
+EOF
+
+ ;;
+ mn10200-*-*) fmt=elf bfd_gas=yes ;;
+ mn10300-*-*) fmt=elf bfd_gas=yes ;;
+ ppc-*-pe | ppc-*-cygwin* | ppc-*-winnt*)
+ fmt=coff em=pe ;;
+ ppc-*-aix*) fmt=coff ;;
+ ppc-*-beos*) fmt=coff ;;
+ ppc-*-*bsd* | ppc-*-elf* | ppc-*-eabi* | ppc-*-sysv4*)
+ fmt=elf ;;
+ ppc-*-linux-gnu*) fmt=elf
+ case "$endian" in
+ big) ;;
+ *) { echo "configure: error: GNU/Linux must be configured big endian" 1>&2; exit 1; } ;;
+ esac
+ ;;
+ ppc-*-solaris*) fmt=elf
+ if test ${this_target} = $target; then
+ cat >> confdefs.h <<\EOF
+#define TARGET_SOLARIS_COMMENT 1
+EOF
+
+ fi
+ if test x${endian} = xbig; then
+ { echo "configure: error: Solaris must be configured little endian" 1>&2; exit 1; }
+ fi
+ ;;
+ ppc-*-rtems*) fmt=elf ;;
+ ppc-*-macos* | ppc-*-mpw*)
+ fmt=coff em=macos ;;
+ ppc-*-netware*) fmt=elf em=ppcnw ;;
+
+ sh-*-elf*) fmt=elf ;;
+ sh-*-coff*) fmt=coff ;;
+ sh-*-rtems*) fmt=coff ;;
+
+ ns32k-pc532-mach* | ns32k-pc532-ux*) fmt=aout em=pc532mach ;;
+ ns32k-pc532-netbsd* | ns32k-pc532-lites*) fmt=aout em=nbsd532 ;;
+ ns32k-pc532-openbsd*) fmt=aout em=nbsd532 ;;
+
+ sparc-*-rtems*) fmt=aout ;;
+ sparc-*-sunos4*) fmt=aout em=sun3 ;;
+ sparc-*-aout | sparc*-*-vxworks*)
+ fmt=aout em=sparcaout ;;
+ sparc-*-coff) fmt=coff ;;
+ sparc-*-linux*aout*) fmt=aout em=linux ;;
+ sparc-*-linux-gnu*) fmt=elf em=linux ;;
+ sparc-*-lynxos*) fmt=coff em=lynx ;;
+ sparc-fujitsu-none) fmt=aout ;;
+ sparc-*-elf | sparc-*-sysv4* | sparc-*-solaris*)
+ fmt=elf ;;
+ sparc-*-netbsd*) fmt=aout em=nbsd ;;
+ sparc-*-openbsd*) fmt=aout em=nbsd ;;
+
+ strongarm-*-coff) fmt=coff ;;
+ strongarm-*-elf) fmt=elf ;;
+
+ tic30-*-*aout*) fmt=aout bfd_gas=yes ;;
+ tic30-*-*coff*) fmt=coff bfd_gas=yes ;;
+ tic80-*-*) fmt=coff ;;
+
+ v850-*-*) fmt=elf bfd_gas=yes ;;
+ v850e-*-*) fmt=elf bfd_gas=yes ;;
+ v850ea-*-*) fmt=elf bfd_gas=yes ;;
+
+ vax-*-bsd* | vax-*-ultrix*)
+ fmt=aout ;;
+ vax-*-vms) fmt=vms ;;
+
+
+ z8k-*-coff | z8k-*-sim)
+ fmt=coff ;;
+
+ w65-*-*) fmt=coff ;;
+
+ *-*-aout | *-*-scout)
+ fmt=aout ;;
+ *-*-nindy*)
+ fmt=bout ;;
+ *-*-bsd*)
+ fmt=aout em=sun3 ;;
+ *-*-generic) fmt=generic ;;
+ *-*-xray | *-*-hms) fmt=coff ;;
+ *-*-sim) fmt=coff ;;
+ *-*-elf | *-*-sysv4* | *-*-solaris*)
+ echo "configure: warning: GAS support for ${generic_target} is incomplete." 1>&2
+ fmt=elf dev=yes ;;
+ *-*-vxworks) fmt=aout ;;
+ *-*-netware) fmt=elf ;;
+ esac
+
+ if test ${this_target} = $target ; then
+ endian_def=
+ if test x${endian} = xbig; then
+ endian_def=1
+ elif test x${endian} = xlittle; then
+ endian_def=0
+ fi
+ if test x${endian_def} != x; then
+ cat >> confdefs.h <<EOF
+#define TARGET_BYTES_BIG_ENDIAN $endian_def
+EOF
+
+ fi
+ fi
+
+ case ${cpu_type}-${fmt} in
+ alpha*-*) bfd_gas=yes ;;
+ arm-*) bfd_gas=yes ;;
+ # not yet
+ # i386-aout) bfd_gas=preferred ;;
+ mips-*) bfd_gas=yes ;;
+ ns32k-*) bfd_gas=yes ;;
+ ppc-*) bfd_gas=yes ;;
+ sparc-*) bfd_gas=yes ;;
+ strongarm-*) bfd_gas=yes ;;
+ *-elf) bfd_gas=yes ;;
+ *-ecoff) bfd_gas=yes ;;
+ *-som) bfd_gas=yes ;;
+ *) ;;
+ esac
+
+# Other random stuff.
+
+ # Do we need the opcodes library?
+ case ${cpu_type} in
+ vax | i386 | tic30)
+ ;;
+
+ *)
+ need_opcodes=yes
+
+ case "${enable_shared}" in
+ yes) shared_opcodes=true ;;
+ *opcodes*) shared_opcodes=true ;;
+ *) shared_opcodes=false ;;
+ esac
+ if test "${shared_opcodes}" = "true"; then
+ # A shared libopcodes must be linked against libbfd.
+ need_bfd=yes
+ fi
+ ;;
+ esac
+
+ # Any other special object files needed ?
+ case ${cpu_type} in
+ fr30 | m32r)
+ using_cgen=yes
+ ;;
+
+ m68k)
+ case ${extra_objects} in
+ *m68k-parse.o*) ;;
+ *) extra_objects="$extra_objects m68k-parse.o" ;;
+ esac
+ ;;
+
+ mips)
+ echo ${extra_objects} | grep -s "itbl-parse.o"
+ if test $? -ne 0 ; then
+ extra_objects="$extra_objects itbl-parse.o"
+ fi
+
+ echo ${extra_objects} | grep -s "itbl-lex.o"
+ if test $? -ne 0 ; then
+ extra_objects="$extra_objects itbl-lex.o"
+ fi
+
+ echo ${extra_objects} | grep -s "itbl-ops.o"
+ if test $? -ne 0 ; then
+ extra_objects="$extra_objects itbl-ops.o"
+ fi
+ ;;
+
+ sparc)
+ if test $this_target = $target ; then
+ cat >> confdefs.h <<EOF
+#define DEFAULT_ARCH "${arch}"
+EOF
+
+ fi
+ ;;
+ *)
+ ;;
+ esac
+
+ if test $using_cgen = yes ; then
+ case "x${extra_objects}" in
+ *cgen.o*) ;;
+ *) extra_objects="$extra_objects cgen.o" ;;
+ esac
+ fi
+
+# See if we really can support this configuration with the emulation code.
+
+ if test $this_target = $target ; then
+ primary_bfd_gas=$bfd_gas
+ obj_format=$fmt
+ te_file=$em
+
+ if test $bfd_gas = no ; then
+ # Can't support other configurations this way.
+ break
+ fi
+ elif test $bfd_gas = no ; then
+ # Can't support this configuration.
+ break
+ fi
+
+# From target name and format, produce a list of supported emulations.
+
+ case ${generic_target}-${fmt} in
+ mips-*-irix5*-*) emulation="mipsbelf mipslelf mipself mipsbecoff mipslecoff mipsecoff" ;;
+ mips-*-linux-gnu*-*) case "$endian" in
+ big) emulation="mipsbelf mipslelf mipself mipsbecoff mipslecoff mipsecoff" ;;
+ *) emulation="mipslelf mipsbelf mipself mipslecoff mipsbecoff mipsecoff" ;;
+ esac ;;
+ mips-*-lnews*-ecoff) ;;
+ mips-*-*-ecoff) case "$endian" in
+ big) emulation="mipsbecoff mipslecoff mipsecoff" ;;
+ *) emulation="mipslecoff mipsbecoff mipsecoff" ;;
+ esac ;;
+ mips-*-*-elf) case "$endian" in
+ big) emulation="mipsbelf mipslelf mipself" ;;
+ *) emulation="mipslelf mipsbelf mipself" ;;
+ # Uncommenting the next line will turn on support for i386 COFF
+ # in any i386 ELF configuration. This probably doesn't work
+ # correctly.
+ # i386-*-*-elf) emulation="i386coff i386elf" ;;
+ esac ;;
+ esac
+
+ emulations="$emulations $emulation"
+
+done
+
+# Assign floating point type. Most processors with FP support
+# IEEE FP. On those that don't support FP at all, usually IEEE
+# is emulated.
+case ${target_cpu} in
+ vax | tahoe ) atof=${target_cpu} ;;
+ *) atof=ieee ;;
+esac
+
+case "${obj_format}" in
+ "") { echo "configure: error: GAS does not know what format to use for target ${target}" 1>&2; exit 1; } ;;
+esac
+
+# Unfortunately the cpu in cpu-opc.h file isn't always $(TARGET_CPU).
+cgen_cpu_prefix=""
+if test $using_cgen = yes ; then
+ case ${target_cpu} in
+ *) cgen_cpu_prefix=${target_cpu} ;;
+ esac
+
+ cat >> confdefs.h <<\EOF
+#define USING_CGEN 1
+EOF
+
+fi
+
+
+if test ! -r ${srcdir}/config/tc-${target_cpu_type}.c; then
+ { echo "configure: error: GAS does not support target CPU ${target_cpu_type}" 1>&2; exit 1; }
+fi
+
+if test ! -r ${srcdir}/config/obj-${obj_format}.c; then
+ { echo "configure: error: GAS does not have support for object file format ${obj_format}" 1>&2; exit 1; }
+fi
+
+case ${user_bfd_gas}-${primary_bfd_gas} in
+ yes-yes | no-no)
+ # We didn't override user's choice.
+ ;;
+ no-yes)
+ echo "configure: warning: Use of BFD is required for ${target}; overriding config options." 1>&2
+ ;;
+ no-preferred)
+ primary_bfd_gas=no
+ ;;
+ *-preferred)
+ primary_bfd_gas=yes
+ ;;
+ yes-*)
+ primary_bfd_gas=yes
+ ;;
+ -*)
+ # User specified nothing.
+ ;;
+esac
+
+# Some COFF configurations want these random other flags set.
+case ${obj_format} in
+ coff)
+ case ${target_cpu_type} in
+ i386) cat >> confdefs.h <<\EOF
+#define I386COFF 1
+EOF
+ ;;
+ m68k) cat >> confdefs.h <<\EOF
+#define M68KCOFF 1
+EOF
+ ;;
+ m88k) cat >> confdefs.h <<\EOF
+#define M88KCOFF 1
+EOF
+ ;;
+ esac
+ ;;
+esac
+
+# Getting this done right is going to be a bitch. Each configuration specified
+# with --enable-targets=... should be checked for environment, format, cpu, and
+# bfd_gas setting.
+#
+# For each configuration, the necessary object file support code must be linked
+# in. This might be only one, it might be up to four. The necessary emulation
+# code needs to be provided, too.
+#
+# And then there's "--enable-targets=all"....
+#
+# For now, just always do it for MIPS ELF or ECOFF configurations. Sigh.
+
+formats="${obj_format}"
+emfiles=""
+EMULATIONS=""
+_gas_uniq_list="$emulations"
+_gas_uniq_newlist=""
+for _gas_uniq_i in _gas_uniq_dummy $_gas_uniq_list ; do
+ case $_gas_uniq_i in
+ _gas_uniq_dummy) ;;
+ *) case " $_gas_uniq_newlist " in
+ *" $_gas_uniq_i "*) ;;
+ *) _gas_uniq_newlist="$_gas_uniq_newlist $_gas_uniq_i" ;;
+ esac ;;
+ esac
+done
+emulations=$_gas_uniq_newlist
+
+for em in . $emulations ; do
+ case $em in
+ .) continue ;;
+ mipsbelf | mipslelf)
+ fmt=elf file=mipself ;;
+ mipsbecoff | mipslecoff)
+ fmt=ecoff file=mipsecoff ;;
+ i386coff)
+ fmt=coff file=i386coff ;;
+ i386elf)
+ fmt=elf file=i386elf ;;
+ esac
+ formats="$formats $fmt"
+ emfiles="$emfiles e-$file.o"
+ EMULATIONS="$EMULATIONS &$em,"
+done
+_gas_uniq_list="$formats"
+_gas_uniq_newlist=""
+for _gas_uniq_i in _gas_uniq_dummy $_gas_uniq_list ; do
+ case $_gas_uniq_i in
+ _gas_uniq_dummy) ;;
+ *) case " $_gas_uniq_newlist " in
+ *" $_gas_uniq_i "*) ;;
+ *) _gas_uniq_newlist="$_gas_uniq_newlist $_gas_uniq_i" ;;
+ esac ;;
+ esac
+done
+formats=$_gas_uniq_newlist
+
+_gas_uniq_list="$emfiles"
+_gas_uniq_newlist=""
+for _gas_uniq_i in _gas_uniq_dummy $_gas_uniq_list ; do
+ case $_gas_uniq_i in
+ _gas_uniq_dummy) ;;
+ *) case " $_gas_uniq_newlist " in
+ *" $_gas_uniq_i "*) ;;
+ *) _gas_uniq_newlist="$_gas_uniq_newlist $_gas_uniq_i" ;;
+ esac ;;
+ esac
+done
+emfiles=$_gas_uniq_newlist
+
+if test `set . $formats ; shift ; echo $#` -gt 1 ; then
+ for fmt in $formats ; do
+ case $fmt in
+ aout) cat >> confdefs.h <<\EOF
+#define OBJ_MAYBE_AOUT 1
+EOF
+ ;;
+ bout) cat >> confdefs.h <<\EOF
+#define OBJ_MAYBE_BOUT 1
+EOF
+ ;;
+ coff) cat >> confdefs.h <<\EOF
+#define OBJ_MAYBE_COFF 1
+EOF
+ ;;
+ ecoff) cat >> confdefs.h <<\EOF
+#define OBJ_MAYBE_ECOFF 1
+EOF
+ ;;
+ elf) cat >> confdefs.h <<\EOF
+#define OBJ_MAYBE_ELF 1
+EOF
+ ;;
+ generic) cat >> confdefs.h <<\EOF
+#define OBJ_MAYBE_GENERIC 1
+EOF
+ ;;
+ hp300) cat >> confdefs.h <<\EOF
+#define OBJ_MAYBE_HP300 1
+EOF
+ ;;
+ ieee) cat >> confdefs.h <<\EOF
+#define OBJ_MAYBE_IEEE 1
+EOF
+ ;;
+ som) cat >> confdefs.h <<\EOF
+#define OBJ_MAYBE_SOM 1
+EOF
+ ;;
+ vms) cat >> confdefs.h <<\EOF
+#define OBJ_MAYBE_VMS 1
+EOF
+ ;;
+ esac
+ extra_objects="$extra_objects obj-$fmt.o"
+ done
+ obj_format=multi
+fi
+if test `set . $emfiles ; shift ; echo $#` -gt 0 ; then
+ te_file=multi
+ extra_objects="$extra_objects $emfiles"
+ DEFAULT_EMULATION=`set . $emulations ; echo $2`
+ cat >> confdefs.h <<\EOF
+#define USE_EMULATIONS 1
+EOF
+
+fi
+
+cat >> confdefs.h <<EOF
+#define EMULATIONS $EMULATIONS
+EOF
+
+cat >> confdefs.h <<EOF
+#define DEFAULT_EMULATION "$DEFAULT_EMULATION"
+EOF
+
+
+case ${primary_bfd_gas}-${target_cpu_type}-${obj_format} in
+ yes-*-coff) need_bfd=yes ;;
+ no-*-coff) need_bfd=yes
+ cat >> confdefs.h <<\EOF
+#define MANY_SEGMENTS 1
+EOF
+ ;;
+esac
+
+reject_dev_configs=yes
+
+case ${reject_dev_configs}-${dev} in
+ yes-yes) # Oops.
+ { echo "configure: error: GAS does not support the ${generic_target} configuration." 1>&2; exit 1; }
+ ;;
+esac
+
+
+
+
+
+
+
+case "${primary_bfd_gas}" in
+ yes) cat >> confdefs.h <<\EOF
+#define BFD_ASSEMBLER 1
+EOF
+
+ need_bfd=yes ;;
+esac
+
+# do we need the opcodes library?
+case "${need_opcodes}" in
+yes)
+ OPCODES_LIB=../opcodes/libopcodes.la
+ ;;
+esac
+
+case "${need_bfd}" in
+yes)
+ BFDLIB=../bfd/libbfd.la
+ ALL_OBJ_DEPS="$ALL_OBJ_DEPS ../bfd/bfd.h"
+ ;;
+esac
+
+
+
+
+
+
+cat >> confdefs.h <<EOF
+#define TARGET_ALIAS "${target_alias}"
+EOF
+
+cat >> confdefs.h <<EOF
+#define TARGET_CANONICAL "${target}"
+EOF
+
+cat >> confdefs.h <<EOF
+#define TARGET_CPU "${target_cpu}"
+EOF
+
+cat >> confdefs.h <<EOF
+#define TARGET_VENDOR "${target_vendor}"
+EOF
+
+cat >> confdefs.h <<EOF
+#define TARGET_OS "${target_os}"
+EOF
+
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2323: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2353: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2404: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:2436: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 2447 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:2452: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:2478: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:2483: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:2492: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:2511: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+
+
+for ac_prog in 'bison -y' byacc
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2548: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$YACC"; then
+ ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_YACC="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+YACC="$ac_cv_prog_YACC"
+if test -n "$YACC"; then
+ echo "$ac_t""$YACC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:2579: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 2594 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2600: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 2611 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2617: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+#line 2628 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2634: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+missing_dir=`cd $ac_aux_dir && pwd`
+for ac_prog in flex lex
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2664: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LEX'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$LEX"; then
+ ac_cv_prog_LEX="$LEX" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_LEX="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+LEX="$ac_cv_prog_LEX"
+if test -n "$LEX"; then
+ echo "$ac_t""$LEX" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$LEX" && break
+done
+test -n "$LEX" || LEX=""$missing_dir/missing flex""
+
+# Extract the first word of "flex", so it can be a program name with args.
+set dummy flex; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2697: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LEX'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$LEX"; then
+ ac_cv_prog_LEX="$LEX" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_LEX="flex"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_LEX" && ac_cv_prog_LEX="lex"
+fi
+fi
+LEX="$ac_cv_prog_LEX"
+if test -n "$LEX"; then
+ echo "$ac_t""$LEX" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$LEXLIB"
+then
+ case "$LEX" in
+ flex*) ac_lib=fl ;;
+ *) ac_lib=l ;;
+ esac
+ echo $ac_n "checking for yywrap in -l$ac_lib""... $ac_c" 1>&6
+echo "configure:2731: checking for yywrap in -l$ac_lib" >&5
+ac_lib_var=`echo $ac_lib'_'yywrap | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-l$ac_lib $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2739 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char yywrap();
+
+int main() {
+yywrap()
+; return 0; }
+EOF
+if { (eval echo configure:2750: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LEXLIB="-l$ac_lib"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+echo $ac_n "checking lex output file root""... $ac_c" 1>&6
+echo "configure:2773: checking lex output file root" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_lex_root'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # The minimal lex program is just a single line: %%. But some broken lexes
+# (Solaris, I think it was) want two %% lines, so accommodate them.
+echo '%%
+%%' | $LEX
+if test -f lex.yy.c; then
+ ac_cv_prog_lex_root=lex.yy
+elif test -f lexyy.c; then
+ ac_cv_prog_lex_root=lexyy
+else
+ { echo "configure: error: cannot find output from $LEX; giving up" 1>&2; exit 1; }
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_lex_root" 1>&6
+LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root
+
+echo $ac_n "checking whether yytext is a pointer""... $ac_c" 1>&6
+echo "configure:2794: checking whether yytext is a pointer" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_lex_yytext_pointer'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # POSIX says lex can declare yytext either as a pointer or an array; the
+# default is implementation-dependent. Figure out which it is, since
+# not all implementations provide the %pointer and %array declarations.
+ac_cv_prog_lex_yytext_pointer=no
+echo 'extern char *yytext;' >>$LEX_OUTPUT_ROOT.c
+ac_save_LIBS="$LIBS"
+LIBS="$LIBS $LEXLIB"
+cat > conftest.$ac_ext <<EOF
+#line 2806 "configure"
+#include "confdefs.h"
+`cat $LEX_OUTPUT_ROOT.c`
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:2813: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_cv_prog_lex_yytext_pointer=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+rm -f "${LEX_OUTPUT_ROOT}.c"
+
+fi
+
+echo "$ac_t""$ac_cv_prog_lex_yytext_pointer" 1>&6
+if test $ac_cv_prog_lex_yytext_pointer = yes; then
+ cat >> confdefs.h <<\EOF
+#define YYTEXT_POINTER 1
+EOF
+
+fi
+
+
+ALL_LINGUAS=
+echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6
+echo "configure:2837: checking for POSIXized ISC" >&5
+if test -d /etc/conf/kconfig.d &&
+ grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1
+then
+ echo "$ac_t""yes" 1>&6
+ ISC=yes # If later tests want to check for ISC.
+ cat >> confdefs.h <<\EOF
+#define _POSIX_SOURCE 1
+EOF
+
+ if test "$GCC" = yes; then
+ CC="$CC -posix"
+ else
+ CC="$CC -Xp"
+ fi
+else
+ echo "$ac_t""no" 1>&6
+ ISC=
+fi
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:2858: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2863 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2871: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ ac_cv_header_stdc=yes
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 2888 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 2906 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2927 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:2938: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+ cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:2962: checking for working const" >&5
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2967 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this. */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this. */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this. */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in an arm
+ of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:3016: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_const=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+ cat >> confdefs.h <<\EOF
+#define const
+EOF
+
+fi
+
+echo $ac_n "checking for inline""... $ac_c" 1>&6
+echo "configure:3037: checking for inline" >&5
+if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat > conftest.$ac_ext <<EOF
+#line 3044 "configure"
+#include "confdefs.h"
+
+int main() {
+} $ac_kw foo() {
+; return 0; }
+EOF
+if { (eval echo configure:3051: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_inline=$ac_kw; break
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+done
+
+fi
+
+echo "$ac_t""$ac_cv_c_inline" 1>&6
+case "$ac_cv_c_inline" in
+ inline | yes) ;;
+ no) cat >> confdefs.h <<\EOF
+#define inline
+EOF
+ ;;
+ *) cat >> confdefs.h <<EOF
+#define inline $ac_cv_c_inline
+EOF
+ ;;
+esac
+
+echo $ac_n "checking for off_t""... $ac_c" 1>&6
+echo "configure:3077: checking for off_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3082 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_off_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_off_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_off_t" 1>&6
+if test $ac_cv_type_off_t = no; then
+ cat >> confdefs.h <<\EOF
+#define off_t long
+EOF
+
+fi
+
+echo $ac_n "checking for size_t""... $ac_c" 1>&6
+echo "configure:3110: checking for size_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3115 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_size_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_size_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_size_t" 1>&6
+if test $ac_cv_type_size_t = no; then
+ cat >> confdefs.h <<\EOF
+#define size_t unsigned
+EOF
+
+fi
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments. Useless!
+echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
+echo "configure:3145: checking for working alloca.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3150 "configure"
+#include "confdefs.h"
+#include <alloca.h>
+int main() {
+char *p = alloca(2 * sizeof(int));
+; return 0; }
+EOF
+if { (eval echo configure:3157: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_cv_header_alloca_h=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_alloca_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_alloca_h" 1>&6
+if test $ac_cv_header_alloca_h = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA_H 1
+EOF
+
+fi
+
+echo $ac_n "checking for alloca""... $ac_c" 1>&6
+echo "configure:3178: checking for alloca" >&5
+if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3183 "configure"
+#include "confdefs.h"
+
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else
+# if HAVE_ALLOCA_H
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+# endif
+# endif
+# endif
+# endif
+#endif
+
+int main() {
+char *p = (char *) alloca(1);
+; return 0; }
+EOF
+if { (eval echo configure:3211: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_cv_func_alloca_works=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_func_alloca_works=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_func_alloca_works" 1>&6
+if test $ac_cv_func_alloca_works = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA 1
+EOF
+
+fi
+
+if test $ac_cv_func_alloca_works = no; then
+ # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+ # that cause trouble. Some versions do not even contain alloca or
+ # contain a buggy version. If you still want to use their alloca,
+ # use ar to extract alloca.o from them instead of compiling alloca.c.
+ ALLOCA=alloca.${ac_objext}
+ cat >> confdefs.h <<\EOF
+#define C_ALLOCA 1
+EOF
+
+
+echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
+echo "configure:3243: checking whether alloca needs Cray hooks" >&5
+if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3248 "configure"
+#include "confdefs.h"
+#if defined(CRAY) && ! defined(CRAY2)
+webecray
+#else
+wenotbecray
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "webecray" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_os_cray=yes
+else
+ rm -rf conftest*
+ ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_os_cray" 1>&6
+if test $ac_cv_os_cray = yes; then
+for ac_func in _getb67 GETB67 getb67; do
+ echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:3273: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3278 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3301: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<EOF
+#define CRAY_STACKSEG_END $ac_func
+EOF
+
+ break
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+done
+fi
+
+echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
+echo "configure:3328: checking stack direction for C alloca" >&5
+if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_c_stack_direction=0
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3336 "configure"
+#include "confdefs.h"
+find_stack_direction ()
+{
+ static char *addr = 0;
+ auto char dummy;
+ if (addr == 0)
+ {
+ addr = &dummy;
+ return find_stack_direction ();
+ }
+ else
+ return (&dummy > addr) ? 1 : -1;
+}
+main ()
+{
+ exit (find_stack_direction() < 0);
+}
+EOF
+if { (eval echo configure:3355: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_c_stack_direction=1
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_c_stack_direction=-1
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_c_stack_direction" 1>&6
+cat >> confdefs.h <<EOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+EOF
+
+fi
+
+for ac_hdr in unistd.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:3380: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3385 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:3390: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_func in getpagesize
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:3419: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3424 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3447: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+echo $ac_n "checking for working mmap""... $ac_c" 1>&6
+echo "configure:3472: checking for working mmap" >&5
+if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_mmap_fixed_mapped=no
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3480 "configure"
+#include "confdefs.h"
+
+/* Thanks to Mike Haertel and Jim Avera for this test.
+ Here is a matrix of mmap possibilities:
+ mmap private not fixed
+ mmap private fixed at somewhere currently unmapped
+ mmap private fixed at somewhere already mapped
+ mmap shared not fixed
+ mmap shared fixed at somewhere currently unmapped
+ mmap shared fixed at somewhere already mapped
+ For private mappings, we should verify that changes cannot be read()
+ back from the file, nor mmap's back from the file at a different
+ address. (There have been systems where private was not correctly
+ implemented like the infamous i386 svr4.0, and systems where the
+ VM page cache was not coherent with the filesystem buffer cache
+ like early versions of FreeBSD and possibly contemporary NetBSD.)
+ For shared mappings, we should conversely verify that changes get
+ propogated back to all the places they're supposed to be.
+
+ Grep wants private fixed already mapped.
+ The main things grep needs to know about mmap are:
+ * does it exist and is it safe to write into the mmap'd area
+ * how to use it (BSD variants) */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+/* This mess was copied from the GNU getpagesize.h. */
+#ifndef HAVE_GETPAGESIZE
+# ifdef HAVE_UNISTD_H
+# include <unistd.h>
+# endif
+
+/* Assume that all systems that can run configure have sys/param.h. */
+# ifndef HAVE_SYS_PARAM_H
+# define HAVE_SYS_PARAM_H 1
+# endif
+
+# ifdef _SC_PAGESIZE
+# define getpagesize() sysconf(_SC_PAGESIZE)
+# else /* no _SC_PAGESIZE */
+# ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+# ifdef EXEC_PAGESIZE
+# define getpagesize() EXEC_PAGESIZE
+# else /* no EXEC_PAGESIZE */
+# ifdef NBPG
+# define getpagesize() NBPG * CLSIZE
+# ifndef CLSIZE
+# define CLSIZE 1
+# endif /* no CLSIZE */
+# else /* no NBPG */
+# ifdef NBPC
+# define getpagesize() NBPC
+# else /* no NBPC */
+# ifdef PAGESIZE
+# define getpagesize() PAGESIZE
+# endif /* PAGESIZE */
+# endif /* no NBPC */
+# endif /* no NBPG */
+# endif /* no EXEC_PAGESIZE */
+# else /* no HAVE_SYS_PARAM_H */
+# define getpagesize() 8192 /* punt totally */
+# endif /* no HAVE_SYS_PARAM_H */
+# endif /* no _SC_PAGESIZE */
+
+#endif /* no HAVE_GETPAGESIZE */
+
+#ifdef __cplusplus
+extern "C" { void *malloc(unsigned); }
+#else
+char *malloc();
+#endif
+
+int
+main()
+{
+ char *data, *data2, *data3;
+ int i, pagesize;
+ int fd;
+
+ pagesize = getpagesize();
+
+ /*
+ * First, make a file with some known garbage in it.
+ */
+ data = malloc(pagesize);
+ if (!data)
+ exit(1);
+ for (i = 0; i < pagesize; ++i)
+ *(data + i) = rand();
+ umask(0);
+ fd = creat("conftestmmap", 0600);
+ if (fd < 0)
+ exit(1);
+ if (write(fd, data, pagesize) != pagesize)
+ exit(1);
+ close(fd);
+
+ /*
+ * Next, try to mmap the file at a fixed address which
+ * already has something else allocated at it. If we can,
+ * also make sure that we see the same garbage.
+ */
+ fd = open("conftestmmap", O_RDWR);
+ if (fd < 0)
+ exit(1);
+ data2 = malloc(2 * pagesize);
+ if (!data2)
+ exit(1);
+ data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1);
+ if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_FIXED, fd, 0L))
+ exit(1);
+ for (i = 0; i < pagesize; ++i)
+ if (*(data + i) != *(data2 + i))
+ exit(1);
+
+ /*
+ * Finally, make sure that changes to the mapped area
+ * do not percolate back to the file as seen by read().
+ * (This is a bug on some variants of i386 svr4.0.)
+ */
+ for (i = 0; i < pagesize; ++i)
+ *(data2 + i) = *(data2 + i) + 1;
+ data3 = malloc(pagesize);
+ if (!data3)
+ exit(1);
+ if (read(fd, data3, pagesize) != pagesize)
+ exit(1);
+ for (i = 0; i < pagesize; ++i)
+ if (*(data + i) != *(data3 + i))
+ exit(1);
+ close(fd);
+ unlink("conftestmmap");
+ exit(0);
+}
+
+EOF
+if { (eval echo configure:3620: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_func_mmap_fixed_mapped=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_func_mmap_fixed_mapped=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_func_mmap_fixed_mapped" 1>&6
+if test $ac_cv_func_mmap_fixed_mapped = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_MMAP 1
+EOF
+
+fi
+
+
+ for ac_hdr in argz.h limits.h locale.h nl_types.h malloc.h string.h \
+unistd.h values.h sys/param.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:3648: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3653 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:3658: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ for ac_func in getcwd munmap putenv setenv setlocale strchr strcasecmp \
+__argz_count __argz_stringify __argz_next
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:3688: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3693 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3716: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+ if test "${ac_cv_func_stpcpy+set}" != "set"; then
+ for ac_func in stpcpy
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:3745: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3750 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3773: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ fi
+ if test "${ac_cv_func_stpcpy}" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_STPCPY 1
+EOF
+
+ fi
+
+ if test $ac_cv_header_locale_h = yes; then
+ echo $ac_n "checking for LC_MESSAGES""... $ac_c" 1>&6
+echo "configure:3807: checking for LC_MESSAGES" >&5
+if eval "test \"`echo '$''{'am_cv_val_LC_MESSAGES'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3812 "configure"
+#include "confdefs.h"
+#include <locale.h>
+int main() {
+return LC_MESSAGES
+; return 0; }
+EOF
+if { (eval echo configure:3819: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ am_cv_val_LC_MESSAGES=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ am_cv_val_LC_MESSAGES=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$am_cv_val_LC_MESSAGES" 1>&6
+ if test $am_cv_val_LC_MESSAGES = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_LC_MESSAGES 1
+EOF
+
+ fi
+ fi
+ echo $ac_n "checking whether NLS is requested""... $ac_c" 1>&6
+echo "configure:3840: checking whether NLS is requested" >&5
+ # Check whether --enable-nls or --disable-nls was given.
+if test "${enable_nls+set}" = set; then
+ enableval="$enable_nls"
+ USE_NLS=$enableval
+else
+ USE_NLS=yes
+fi
+
+ echo "$ac_t""$USE_NLS" 1>&6
+
+
+ USE_INCLUDED_LIBINTL=no
+
+ if test "$USE_NLS" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define ENABLE_NLS 1
+EOF
+
+ echo $ac_n "checking whether included gettext is requested""... $ac_c" 1>&6
+echo "configure:3860: checking whether included gettext is requested" >&5
+ # Check whether --with-included-gettext or --without-included-gettext was given.
+if test "${with_included_gettext+set}" = set; then
+ withval="$with_included_gettext"
+ nls_cv_force_use_gnu_gettext=$withval
+else
+ nls_cv_force_use_gnu_gettext=no
+fi
+
+ echo "$ac_t""$nls_cv_force_use_gnu_gettext" 1>&6
+
+ nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext"
+ if test "$nls_cv_force_use_gnu_gettext" != "yes"; then
+ nls_cv_header_intl=
+ nls_cv_header_libgt=
+ CATOBJEXT=NONE
+
+ ac_safe=`echo "libintl.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for libintl.h""... $ac_c" 1>&6
+echo "configure:3879: checking for libintl.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3884 "configure"
+#include "confdefs.h"
+#include <libintl.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:3889: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ echo $ac_n "checking for gettext in libc""... $ac_c" 1>&6
+echo "configure:3906: checking for gettext in libc" >&5
+if eval "test \"`echo '$''{'gt_cv_func_gettext_libc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3911 "configure"
+#include "confdefs.h"
+#include <libintl.h>
+int main() {
+return (int) gettext ("")
+; return 0; }
+EOF
+if { (eval echo configure:3918: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ gt_cv_func_gettext_libc=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ gt_cv_func_gettext_libc=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$gt_cv_func_gettext_libc" 1>&6
+
+ if test "$gt_cv_func_gettext_libc" != "yes"; then
+ echo $ac_n "checking for bindtextdomain in -lintl""... $ac_c" 1>&6
+echo "configure:3934: checking for bindtextdomain in -lintl" >&5
+ac_lib_var=`echo intl'_'bindtextdomain | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lintl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3942 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char bindtextdomain();
+
+int main() {
+bindtextdomain()
+; return 0; }
+EOF
+if { (eval echo configure:3953: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ echo $ac_n "checking for gettext in libintl""... $ac_c" 1>&6
+echo "configure:3969: checking for gettext in libintl" >&5
+if eval "test \"`echo '$''{'gt_cv_func_gettext_libintl'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3974 "configure"
+#include "confdefs.h"
+
+int main() {
+return (int) gettext ("")
+; return 0; }
+EOF
+if { (eval echo configure:3981: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ gt_cv_func_gettext_libintl=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ gt_cv_func_gettext_libintl=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$gt_cv_func_gettext_libintl" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ fi
+
+ if test "$gt_cv_func_gettext_libc" = "yes" \
+ || test "$gt_cv_func_gettext_libintl" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_GETTEXT 1
+EOF
+
+ # Extract the first word of "msgfmt", so it can be a program name with args.
+set dummy msgfmt; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:4009: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$MSGFMT" in
+ /*)
+ ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then
+ ac_cv_path_MSGFMT="$ac_dir/$ac_word"
+ break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="no"
+ ;;
+esac
+fi
+MSGFMT="$ac_cv_path_MSGFMT"
+if test -n "$MSGFMT"; then
+ echo "$ac_t""$MSGFMT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ if test "$MSGFMT" != "no"; then
+ for ac_func in dcgettext
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:4043: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4048 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:4071: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ # Extract the first word of "gmsgfmt", so it can be a program name with args.
+set dummy gmsgfmt; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:4098: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$GMSGFMT" in
+ /*)
+ ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_GMSGFMT="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT"
+ ;;
+esac
+fi
+GMSGFMT="$ac_cv_path_GMSGFMT"
+if test -n "$GMSGFMT"; then
+ echo "$ac_t""$GMSGFMT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ # Extract the first word of "xgettext", so it can be a program name with args.
+set dummy xgettext; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:4134: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$XGETTEXT" in
+ /*)
+ ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then
+ ac_cv_path_XGETTEXT="$ac_dir/$ac_word"
+ break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":"
+ ;;
+esac
+fi
+XGETTEXT="$ac_cv_path_XGETTEXT"
+if test -n "$XGETTEXT"; then
+ echo "$ac_t""$XGETTEXT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ cat > conftest.$ac_ext <<EOF
+#line 4166 "configure"
+#include "confdefs.h"
+
+int main() {
+extern int _nl_msg_cat_cntr;
+ return _nl_msg_cat_cntr
+; return 0; }
+EOF
+if { (eval echo configure:4174: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ CATOBJEXT=.gmo
+ DATADIRNAME=share
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CATOBJEXT=.mo
+ DATADIRNAME=lib
+fi
+rm -f conftest*
+ INSTOBJEXT=.mo
+ fi
+ fi
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+
+ if test "$CATOBJEXT" = "NONE"; then
+ nls_cv_use_gnu_gettext=yes
+ fi
+ fi
+
+ if test "$nls_cv_use_gnu_gettext" = "yes"; then
+ INTLOBJS="\$(GETTOBJS)"
+ # Extract the first word of "msgfmt", so it can be a program name with args.
+set dummy msgfmt; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:4206: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$MSGFMT" in
+ /*)
+ ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then
+ ac_cv_path_MSGFMT="$ac_dir/$ac_word"
+ break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="msgfmt"
+ ;;
+esac
+fi
+MSGFMT="$ac_cv_path_MSGFMT"
+if test -n "$MSGFMT"; then
+ echo "$ac_t""$MSGFMT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ # Extract the first word of "gmsgfmt", so it can be a program name with args.
+set dummy gmsgfmt; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:4240: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$GMSGFMT" in
+ /*)
+ ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_GMSGFMT="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT"
+ ;;
+esac
+fi
+GMSGFMT="$ac_cv_path_GMSGFMT"
+if test -n "$GMSGFMT"; then
+ echo "$ac_t""$GMSGFMT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ # Extract the first word of "xgettext", so it can be a program name with args.
+set dummy xgettext; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:4276: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$XGETTEXT" in
+ /*)
+ ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then
+ ac_cv_path_XGETTEXT="$ac_dir/$ac_word"
+ break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":"
+ ;;
+esac
+fi
+XGETTEXT="$ac_cv_path_XGETTEXT"
+if test -n "$XGETTEXT"; then
+ echo "$ac_t""$XGETTEXT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+ USE_INCLUDED_LIBINTL=yes
+ CATOBJEXT=.gmo
+ INSTOBJEXT=.mo
+ DATADIRNAME=share
+ INTLDEPS='$(top_builddir)/../intl/libintl.a'
+ INTLLIBS=$INTLDEPS
+ LIBS=`echo $LIBS | sed -e 's/-lintl//'`
+ nls_cv_header_intl=libintl.h
+ nls_cv_header_libgt=libgettext.h
+ fi
+
+ if test "$XGETTEXT" != ":"; then
+ if $XGETTEXT --omit-header /dev/null 2> /dev/null; then
+ : ;
+ else
+ echo "$ac_t""found xgettext programs is not GNU xgettext; ignore it" 1>&6
+ XGETTEXT=":"
+ fi
+ fi
+
+ # We need to process the po/ directory.
+ POSUB=po
+ else
+ DATADIRNAME=share
+ nls_cv_header_intl=libintl.h
+ nls_cv_header_libgt=libgettext.h
+ fi
+
+ # If this is used in GNU gettext we have to set USE_NLS to `yes'
+ # because some of the sources are only built for this goal.
+ if test "$PACKAGE" = gettext; then
+ USE_NLS=yes
+ USE_INCLUDED_LIBINTL=yes
+ fi
+
+ for lang in $ALL_LINGUAS; do
+ GMOFILES="$GMOFILES $lang.gmo"
+ POFILES="$POFILES $lang.po"
+ done
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if test "x$CATOBJEXT" != "x"; then
+ if test "x$ALL_LINGUAS" = "x"; then
+ LINGUAS=
+ else
+ echo $ac_n "checking for catalogs to be installed""... $ac_c" 1>&6
+echo "configure:4366: checking for catalogs to be installed" >&5
+ NEW_LINGUAS=
+ for lang in ${LINGUAS=$ALL_LINGUAS}; do
+ case "$ALL_LINGUAS" in
+ *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;;
+ esac
+ done
+ LINGUAS=$NEW_LINGUAS
+ echo "$ac_t""$LINGUAS" 1>&6
+ fi
+
+ if test -n "$LINGUAS"; then
+ for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done
+ fi
+ fi
+
+ if test $ac_cv_header_locale_h = yes; then
+ INCLUDE_LOCALE_H="#include <locale.h>"
+ else
+ INCLUDE_LOCALE_H="\
+/* The system does not provide the header <locale.h>. Take care yourself. */"
+ fi
+
+
+ if test -f $srcdir/po2tbl.sed.in; then
+ if test "$CATOBJEXT" = ".cat"; then
+ ac_safe=`echo "linux/version.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for linux/version.h""... $ac_c" 1>&6
+echo "configure:4394: checking for linux/version.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4399 "configure"
+#include "confdefs.h"
+#include <linux/version.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:4404: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ msgformat=linux
+else
+ echo "$ac_t""no" 1>&6
+msgformat=xopen
+fi
+
+
+ sed -e '/^#/d' $srcdir/$msgformat-msg.sed > po2msg.sed
+ fi
+ sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \
+ $srcdir/po2tbl.sed.in > po2tbl.sed
+ fi
+
+ if test "$PACKAGE" = "gettext"; then
+ GT_NO="#NO#"
+ GT_YES=
+ else
+ GT_NO=
+ GT_YES="#YES#"
+ fi
+
+
+
+ MKINSTALLDIRS="\$(srcdir)/../../mkinstalldirs"
+
+
+ l=
+
+
+ if test -d $srcdir/po; then
+ test -d po || mkdir po
+ if test "x$srcdir" != "x."; then
+ if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then
+ posrcprefix="$srcdir/"
+ else
+ posrcprefix="../$srcdir/"
+ fi
+ else
+ posrcprefix="../"
+ fi
+ rm -f po/POTFILES
+ sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \
+ < $srcdir/po/POTFILES.in > po/POTFILES
+ fi
+
+
+echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6
+echo "configure:4467: checking whether to enable maintainer-specific portions of Makefiles" >&5
+ # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given.
+if test "${enable_maintainer_mode+set}" = set; then
+ enableval="$enable_maintainer_mode"
+ USE_MAINTAINER_MODE=$enableval
+else
+ USE_MAINTAINER_MODE=no
+fi
+
+ echo "$ac_t""$USE_MAINTAINER_MODE" 1>&6
+
+
+if test $USE_MAINTAINER_MODE = yes; then
+ MAINTAINER_MODE_TRUE=
+ MAINTAINER_MODE_FALSE='#'
+else
+ MAINTAINER_MODE_TRUE='#'
+ MAINTAINER_MODE_FALSE=
+fi
+ MAINT=$MAINTAINER_MODE_TRUE
+
+
+echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6
+echo "configure:4490: checking for Cygwin environment" >&5
+if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4495 "configure"
+#include "confdefs.h"
+
+int main() {
+
+#ifndef __CYGWIN__
+#define __CYGWIN__ __CYGWIN32__
+#endif
+return __CYGWIN__;
+; return 0; }
+EOF
+if { (eval echo configure:4506: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_cygwin=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_cygwin=no
+fi
+rm -f conftest*
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_cygwin" 1>&6
+CYGWIN=
+test "$ac_cv_cygwin" = yes && CYGWIN=yes
+echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6
+echo "configure:4523: checking for mingw32 environment" >&5
+if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4528 "configure"
+#include "confdefs.h"
+
+int main() {
+return __MINGW32__;
+; return 0; }
+EOF
+if { (eval echo configure:4535: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_mingw32=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_mingw32=no
+fi
+rm -f conftest*
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_mingw32" 1>&6
+MINGW32=
+test "$ac_cv_mingw32" = yes && MINGW32=yes
+
+
+echo $ac_n "checking for executable suffix""... $ac_c" 1>&6
+echo "configure:4554: checking for executable suffix" >&5
+if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$CYGWIN" = yes || test "$MINGW32" = yes; then
+ ac_cv_exeext=.exe
+else
+ rm -f conftest*
+ echo 'int main () { return 0; }' > conftest.$ac_ext
+ ac_cv_exeext=
+ if { (eval echo configure:4564: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ for file in conftest.*; do
+ case $file in
+ *.c | *.o | *.obj | *.ilk | *.pdb) ;;
+ *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;;
+ esac
+ done
+ else
+ { echo "configure: error: installation or configuration problem: compiler cannot create executables." 1>&2; exit 1; }
+ fi
+ rm -f conftest*
+ test x"${ac_cv_exeext}" = x && ac_cv_exeext=no
+fi
+fi
+
+EXEEXT=""
+test x"${ac_cv_exeext}" != xno && EXEEXT=${ac_cv_exeext}
+echo "$ac_t""${ac_cv_exeext}" 1>&6
+ac_exeext=$EXEEXT
+
+
+for ac_hdr in string.h stdlib.h memory.h strings.h unistd.h stdarg.h varargs.h errno.h sys/types.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:4589: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4594 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:4599: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+# Put this here so that autoconf's "cross-compiling" message doesn't confuse
+# people who are not cross-compiling but are compiling cross-assemblers.
+echo $ac_n "checking whether compiling a cross-assembler""... $ac_c" 1>&6
+echo "configure:4629: checking whether compiling a cross-assembler" >&5
+if test "${host}" = "${target}"; then
+ cross_gas=no
+else
+ cross_gas=yes
+ cat >> confdefs.h <<\EOF
+#define CROSS_COMPILE 1
+EOF
+
+fi
+echo "$ac_t""$cross_gas" 1>&6
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments. Useless!
+echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
+echo "configure:4644: checking for working alloca.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4649 "configure"
+#include "confdefs.h"
+#include <alloca.h>
+int main() {
+char *p = alloca(2 * sizeof(int));
+; return 0; }
+EOF
+if { (eval echo configure:4656: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_cv_header_alloca_h=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_alloca_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_alloca_h" 1>&6
+if test $ac_cv_header_alloca_h = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA_H 1
+EOF
+
+fi
+
+echo $ac_n "checking for alloca""... $ac_c" 1>&6
+echo "configure:4677: checking for alloca" >&5
+if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4682 "configure"
+#include "confdefs.h"
+
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else
+# if HAVE_ALLOCA_H
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+# endif
+# endif
+# endif
+# endif
+#endif
+
+int main() {
+char *p = (char *) alloca(1);
+; return 0; }
+EOF
+if { (eval echo configure:4710: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_cv_func_alloca_works=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_func_alloca_works=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_func_alloca_works" 1>&6
+if test $ac_cv_func_alloca_works = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA 1
+EOF
+
+fi
+
+if test $ac_cv_func_alloca_works = no; then
+ # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+ # that cause trouble. Some versions do not even contain alloca or
+ # contain a buggy version. If you still want to use their alloca,
+ # use ar to extract alloca.o from them instead of compiling alloca.c.
+ ALLOCA=alloca.${ac_objext}
+ cat >> confdefs.h <<\EOF
+#define C_ALLOCA 1
+EOF
+
+
+echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
+echo "configure:4742: checking whether alloca needs Cray hooks" >&5
+if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4747 "configure"
+#include "confdefs.h"
+#if defined(CRAY) && ! defined(CRAY2)
+webecray
+#else
+wenotbecray
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "webecray" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_os_cray=yes
+else
+ rm -rf conftest*
+ ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_os_cray" 1>&6
+if test $ac_cv_os_cray = yes; then
+for ac_func in _getb67 GETB67 getb67; do
+ echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:4772: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4777 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:4800: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<EOF
+#define CRAY_STACKSEG_END $ac_func
+EOF
+
+ break
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+done
+fi
+
+echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
+echo "configure:4827: checking stack direction for C alloca" >&5
+if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_c_stack_direction=0
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4835 "configure"
+#include "confdefs.h"
+find_stack_direction ()
+{
+ static char *addr = 0;
+ auto char dummy;
+ if (addr == 0)
+ {
+ addr = &dummy;
+ return find_stack_direction ();
+ }
+ else
+ return (&dummy > addr) ? 1 : -1;
+}
+main ()
+{
+ exit (find_stack_direction() < 0);
+}
+EOF
+if { (eval echo configure:4854: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_c_stack_direction=1
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_c_stack_direction=-1
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_c_stack_direction" 1>&6
+cat >> confdefs.h <<EOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+EOF
+
+fi
+
+echo $ac_n "checking for inline""... $ac_c" 1>&6
+echo "configure:4876: checking for inline" >&5
+if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat > conftest.$ac_ext <<EOF
+#line 4883 "configure"
+#include "confdefs.h"
+
+int main() {
+} $ac_kw foo() {
+; return 0; }
+EOF
+if { (eval echo configure:4890: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_inline=$ac_kw; break
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+done
+
+fi
+
+echo "$ac_t""$ac_cv_c_inline" 1>&6
+case "$ac_cv_c_inline" in
+ inline | yes) ;;
+ no) cat >> confdefs.h <<\EOF
+#define inline
+EOF
+ ;;
+ *) cat >> confdefs.h <<EOF
+#define inline $ac_cv_c_inline
+EOF
+ ;;
+esac
+
+
+# VMS doesn't have unlink.
+for ac_func in unlink remove
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:4920: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4925 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:4948: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+ break
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+# Some systems don't have sbrk().
+for ac_func in sbrk
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:4977: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4982 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:5005: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+# Some non-ANSI preprocessors botch requoting inside strings. That's bad
+# enough, but on some of those systems, the assert macro relies on requoting
+# working properly!
+echo $ac_n "checking for working assert macro""... $ac_c" 1>&6
+echo "configure:5034: checking for working assert macro" >&5
+if eval "test \"`echo '$''{'gas_cv_assert_ok'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5039 "configure"
+#include "confdefs.h"
+#include <assert.h>
+#include <stdio.h>
+int main() {
+
+/* check for requoting problems */
+static int a, b, c, d;
+static char *s;
+assert (!strcmp(s, "foo bar baz quux"));
+/* check for newline handling */
+assert (a == b
+ || c == d);
+
+; return 0; }
+EOF
+if { (eval echo configure:5055: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ gas_cv_assert_ok=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ gas_cv_assert_ok=no
+fi
+rm -f conftest*
+fi
+echo "$ac_t""$gas_cv_assert_ok" 1>&6
+test $gas_cv_assert_ok = yes || cat >> confdefs.h <<\EOF
+#define BROKEN_ASSERT 1
+EOF
+
+
+
+# On some systems, the system header files may not declare malloc, realloc,
+# and free. There are places where gas needs these functions to have been
+# declared -- such as when taking their addresses.
+gas_test_headers="
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+"
+
+echo $ac_n "checking whether declaration is required for strstr""... $ac_c" 1>&6
+echo "configure:5096: checking whether declaration is required for strstr" >&5
+if eval "test \"`echo '$''{'gas_cv_decl_needed_strstr'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5101 "configure"
+#include "confdefs.h"
+$gas_test_headers
+int main() {
+
+typedef char *(*f)();
+f x;
+x = (f) strstr;
+
+; return 0; }
+EOF
+if { (eval echo configure:5112: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ gas_cv_decl_needed_strstr=no
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ gas_cv_decl_needed_strstr=yes
+fi
+rm -f conftest*
+fi
+echo "$ac_t""$gas_cv_decl_needed_strstr" 1>&6
+if test $gas_cv_decl_needed_strstr = yes; then
+ cat >> confdefs.h <<\EOF
+#define NEED_DECLARATION_STRSTR 1
+EOF
+
+fi
+
+
+echo $ac_n "checking whether declaration is required for malloc""... $ac_c" 1>&6
+echo "configure:5133: checking whether declaration is required for malloc" >&5
+if eval "test \"`echo '$''{'gas_cv_decl_needed_malloc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5138 "configure"
+#include "confdefs.h"
+$gas_test_headers
+int main() {
+
+typedef char *(*f)();
+f x;
+x = (f) malloc;
+
+; return 0; }
+EOF
+if { (eval echo configure:5149: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ gas_cv_decl_needed_malloc=no
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ gas_cv_decl_needed_malloc=yes
+fi
+rm -f conftest*
+fi
+echo "$ac_t""$gas_cv_decl_needed_malloc" 1>&6
+if test $gas_cv_decl_needed_malloc = yes; then
+ cat >> confdefs.h <<\EOF
+#define NEED_DECLARATION_MALLOC 1
+EOF
+
+fi
+
+
+echo $ac_n "checking whether declaration is required for free""... $ac_c" 1>&6
+echo "configure:5170: checking whether declaration is required for free" >&5
+if eval "test \"`echo '$''{'gas_cv_decl_needed_free'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5175 "configure"
+#include "confdefs.h"
+$gas_test_headers
+int main() {
+
+typedef void (*f)();
+f x;
+x = (f) free;
+
+; return 0; }
+EOF
+if { (eval echo configure:5186: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ gas_cv_decl_needed_free=no
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ gas_cv_decl_needed_free=yes
+fi
+rm -f conftest*
+fi
+echo "$ac_t""$gas_cv_decl_needed_free" 1>&6
+if test $gas_cv_decl_needed_free = yes; then
+ cat >> confdefs.h <<\EOF
+#define NEED_DECLARATION_FREE 1
+EOF
+
+fi
+
+
+echo $ac_n "checking whether declaration is required for sbrk""... $ac_c" 1>&6
+echo "configure:5207: checking whether declaration is required for sbrk" >&5
+if eval "test \"`echo '$''{'gas_cv_decl_needed_sbrk'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5212 "configure"
+#include "confdefs.h"
+$gas_test_headers
+int main() {
+
+typedef char *(*f)();
+f x;
+x = (f) sbrk;
+
+; return 0; }
+EOF
+if { (eval echo configure:5223: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ gas_cv_decl_needed_sbrk=no
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ gas_cv_decl_needed_sbrk=yes
+fi
+rm -f conftest*
+fi
+echo "$ac_t""$gas_cv_decl_needed_sbrk" 1>&6
+if test $gas_cv_decl_needed_sbrk = yes; then
+ cat >> confdefs.h <<\EOF
+#define NEED_DECLARATION_SBRK 1
+EOF
+
+fi
+
+
+echo $ac_n "checking whether declaration is required for environ""... $ac_c" 1>&6
+echo "configure:5244: checking whether declaration is required for environ" >&5
+if eval "test \"`echo '$''{'gas_cv_decl_needed_environ'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5249 "configure"
+#include "confdefs.h"
+$gas_test_headers
+int main() {
+
+typedef char **f;
+f x;
+x = (f) environ;
+
+; return 0; }
+EOF
+if { (eval echo configure:5260: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ gas_cv_decl_needed_environ=no
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ gas_cv_decl_needed_environ=yes
+fi
+rm -f conftest*
+fi
+echo "$ac_t""$gas_cv_decl_needed_environ" 1>&6
+if test $gas_cv_decl_needed_environ = yes; then
+ cat >> confdefs.h <<\EOF
+#define NEED_DECLARATION_ENVIRON 1
+EOF
+
+fi
+
+
+# Does errno.h declare errno, or do we have to add a separate declaration
+# for it?
+
+echo $ac_n "checking whether declaration is required for errno""... $ac_c" 1>&6
+echo "configure:5284: checking whether declaration is required for errno" >&5
+if eval "test \"`echo '$''{'gas_cv_decl_needed_errno'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5289 "configure"
+#include "confdefs.h"
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+int main() {
+
+typedef int f;
+f x;
+x = (f) errno;
+
+; return 0; }
+EOF
+if { (eval echo configure:5304: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ gas_cv_decl_needed_errno=no
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ gas_cv_decl_needed_errno=yes
+fi
+rm -f conftest*
+fi
+echo "$ac_t""$gas_cv_decl_needed_errno" 1>&6
+if test $gas_cv_decl_needed_errno = yes; then
+ cat >> confdefs.h <<\EOF
+#define NEED_DECLARATION_ERRNO 1
+EOF
+
+fi
+
+
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile doc/Makefile .gdbinit:gdbinit.in po/Makefile.in:po/Make-in config.h:config.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@PACKAGE@%$PACKAGE%g
+s%@VERSION@%$VERSION%g
+s%@ACLOCAL@%$ACLOCAL%g
+s%@AUTOCONF@%$AUTOCONF%g
+s%@AUTOMAKE@%$AUTOMAKE%g
+s%@AUTOHEADER@%$AUTOHEADER%g
+s%@MAKEINFO@%$MAKEINFO%g
+s%@SET_MAKE@%$SET_MAKE%g
+s%@RANLIB@%$RANLIB%g
+s%@CC@%$CC%g
+s%@LD@%$LD%g
+s%@NM@%$NM%g
+s%@LN_S@%$LN_S%g
+s%@LIBTOOL@%$LIBTOOL%g
+s%@DLLTOOL@%$DLLTOOL%g
+s%@AS@%$AS%g
+s%@cgen_cpu_prefix@%$cgen_cpu_prefix%g
+s%@extra_objects@%$extra_objects%g
+s%@target_cpu_type@%$target_cpu_type%g
+s%@obj_format@%$obj_format%g
+s%@te_file@%$te_file%g
+s%@install_tooldir@%$install_tooldir%g
+s%@atof@%$atof%g
+s%@BFDLIB@%$BFDLIB%g
+s%@OPCODES_LIB@%$OPCODES_LIB%g
+s%@ALL_OBJ_DEPS@%$ALL_OBJ_DEPS%g
+s%@YACC@%$YACC%g
+s%@LEX@%$LEX%g
+s%@LEXLIB@%$LEXLIB%g
+s%@CPP@%$CPP%g
+s%@LEX_OUTPUT_ROOT@%$LEX_OUTPUT_ROOT%g
+s%@ALLOCA@%$ALLOCA%g
+s%@USE_NLS@%$USE_NLS%g
+s%@MSGFMT@%$MSGFMT%g
+s%@GMSGFMT@%$GMSGFMT%g
+s%@XGETTEXT@%$XGETTEXT%g
+s%@USE_INCLUDED_LIBINTL@%$USE_INCLUDED_LIBINTL%g
+s%@CATALOGS@%$CATALOGS%g
+s%@CATOBJEXT@%$CATOBJEXT%g
+s%@DATADIRNAME@%$DATADIRNAME%g
+s%@GMOFILES@%$GMOFILES%g
+s%@INSTOBJEXT@%$INSTOBJEXT%g
+s%@INTLDEPS@%$INTLDEPS%g
+s%@INTLLIBS@%$INTLLIBS%g
+s%@INTLOBJS@%$INTLOBJS%g
+s%@POFILES@%$POFILES%g
+s%@POSUB@%$POSUB%g
+s%@INCLUDE_LOCALE_H@%$INCLUDE_LOCALE_H%g
+s%@GT_NO@%$GT_NO%g
+s%@GT_YES@%$GT_YES%g
+s%@MKINSTALLDIRS@%$MKINSTALLDIRS%g
+s%@l@%$l%g
+s%@MAINTAINER_MODE_TRUE@%$MAINTAINER_MODE_TRUE%g
+s%@MAINTAINER_MODE_FALSE@%$MAINTAINER_MODE_FALSE%g
+s%@MAINT@%$MAINT%g
+s%@EXEEXT@%$EXEEXT%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile doc/Makefile .gdbinit:gdbinit.in po/Makefile.in:po/Make-in"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='\([ ][ ]*\)[^ ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='\([ ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+ CONFIG_HEADERS="config.h:config.in"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ echo creating $ac_file
+
+ rm -f conftest.frag conftest.in conftest.out
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h. And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+ ac_lines=`grep -c . conftest.vals`
+ # grep -c gives empty output for an empty file on some AIX systems.
+ if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+ # Write a limited-size here document to conftest.frag.
+ echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+ echo 'CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+ rm -f conftest.vals
+ mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+ rm -f conftest.frag conftest.h
+ echo "/* $ac_file. Generated automatically by configure. */" > conftest.h
+ cat conftest.in >> conftest.h
+ rm -f conftest.in
+ if cmp -s $ac_file conftest.h 2>/dev/null; then
+ echo "$ac_file is unchanged"
+ rm -f conftest.h
+ else
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ fi
+ rm -f $ac_file
+ mv conftest.h $ac_file
+ fi
+fi; done
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+target_cpu_type=${target_cpu_type}
+ cgen_cpu_prefix=${cgen_cpu_prefix}
+ obj_format=${obj_format}
+ te_file=${te_file}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h
+rm -f targ-cpu.c targ-cpu.h obj-format.h obj-format.c targ-env.h atof-targ.c itbl-cpu.h
+ echo '#include "tc-'"${target_cpu_type}"'.h"' > targ-cpu.h
+ echo '#include "obj-'"${obj_format}"'.h"' > obj-format.h
+ echo '#include "te-'"${te_file}"'.h"' > targ-env.h
+ echo '#include "itbl-'"${target_cpu_type}"'.h"' > itbl-cpu.h
+ if test "x$cgen_cpu_prefix" != x ; then
+ echo '#include "opcodes/'"${cgen_cpu_prefix}"'-desc.h"' > cgen-desc.h
+ fi
+
+ sed -e '/POTFILES =/r po/POTFILES' po/Makefile.in > po/Makefile
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/gas/configure.bat b/gas/configure.bat
new file mode 100644
index 0000000000..1fd269fd67
--- /dev/null
+++ b/gas/configure.bat
@@ -0,0 +1,57 @@
+@echo off
+if "%1" == "h8/300" goto h8300
+
+echo Configuring gas for go32
+update config/tc-i386.c targ-cpu.c
+update config/tc-i386.h targ-cpu.h
+update config/te-go32.h targ-env.h
+update config/obj-coff.h obj-format.h
+update config/obj-coff.c obj-format.c
+update config/atof-ieee.c atof-targ.c
+goto common
+
+:h8300
+echo Configuring gas for H8/300
+copy config\ho-go32.h host.h
+copy config\tc-h8300.c targ-cpu.c
+copy config\tc-h8300.h targ-cpu.h
+copy config\te-generic.h targ-env.h
+copy config\objcoffbfd.h obj-format.h
+copy config\objcoffbfd.c obj-format.c
+copy config\atof-ieee.c atof-targ.c
+
+:common
+
+echo # Makefile generated by "configure.bat"> Makefile.2
+echo all.dos : as.new gasp.new>> Makefile.2
+
+if exist config.sed del config.sed
+
+echo "s/@srcdir@/./g ">> config.sed
+echo "s/@target_alias@/go32/ ">> config.sed
+echo "s/@prefix@// ">> config.sed
+echo "s/@CC@/gcc/g ">> config.sed
+echo "s/@OPCODES_LIB@/..\/opcodes\/libopcodes.a/g ">> config.sed
+echo "s/@BFDLIB@/..\/bfd\/libbfd.a/g ">> config.sed
+echo "s/@ALL_OBJ_DEPS@/..\/bfd\/bfd.h/g ">> config.sed
+
+echo "/^all[ ]*:/ a\ ">> config.sed
+echo "dummy: ">> config.sed
+
+echo "s/\/usr[^ ]*.h//g ">> config.sed
+
+echo "/^config.h[ ]*:/ d ">> config.sed
+echo "s/^Makefile/not-Makefile/ ">> config.sed
+
+sed -e "s/^\"//" -e "s/\"$//" -e "s/[ ]*$//" config.sed > config2.sed
+sed -f config2.sed Makefile.in >> Makefile.2
+update Makefile.2 Makefile
+del Makefile.2
+del config.sed
+del config2.sed
+
+echo #ifndef GAS_VERSION> config.new
+sed -n "/^VERSION=/p" Makefile.in | sed -e "s/VERSION=/#define GAS_VERSION \"/" -e "s/$/\"/">> config.new
+type config\go32.cfg >> config.new
+echo #endif>> config.new
+update config.new config.h
diff --git a/gas/configure.in b/gas/configure.in
new file mode 100644
index 0000000000..4d847ba9af
--- /dev/null
+++ b/gas/configure.in
@@ -0,0 +1,766 @@
+dnl Process this file with autoconf to produce a configure script.
+dnl
+dnl And be careful when changing it! If you must add tests with square
+dnl brackets, be sure changequote invocations surround it.
+dnl
+dnl
+dnl v2.5 needed for --bindir et al
+AC_PREREQ(2.13)
+AC_INIT(as.h)
+
+AC_CANONICAL_SYSTEM
+
+AM_INIT_AUTOMAKE(gas, 2.9.4)
+
+AM_PROG_LIBTOOL
+
+user_bfd_gas=
+AC_ARG_ENABLE(bfd-assembler,
+[ --enable-bfd-assembler use BFD back end for writing object files],
+[case "${enableval}" in
+ yes) need_bfd=yes user_bfd_gas=yes ;;
+ no) user_bfd_gas=no ;;
+ *) AC_MSG_ERROR(bad value ${enableval} given for bfd-assembler option) ;;
+esac])dnl
+AC_ARG_ENABLE(targets,
+[ targets alternative target configurations besides the primary],
+[case "${enableval}" in
+ yes | "") AC_ERROR(enable-targets option must specify target names or 'all')
+ ;;
+ no) enable_targets= ;;
+ *) enable_targets=$enableval ;;
+esac])dnl
+AC_ARG_ENABLE(commonbfdlib,
+[ --enable-commonbfdlib build shared BFD/opcodes/libiberty library],
+[case "${enableval}" in
+ yes) commonbfdlib=true ;;
+ no) commonbfdlib=false ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for BFD commonbfdlib option]) ;;
+esac])dnl
+
+using_cgen=no
+
+# Generate a header file
+AM_CONFIG_HEADER(config.h:config.in)
+
+te_file=generic
+
+# Makefile target for installing gas in $(tooldir)/bin.
+install_tooldir=install-exec-tooldir
+
+canon_targets=""
+if test -n "$enable_targets" ; then
+ for t in `echo $enable_targets | sed 's/,/ /g'`; do
+ result=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $t 2>/dev/null`
+ if test -n "$result" ; then
+ canon_targets="$canon_targets $result"
+# else
+# # Permit "all", etc. We don't support it yet though.
+# canon_targets="$canon_targets $t"
+ fi
+ done
+ GAS_UNIQ(canon_targets)
+fi
+
+emulations=""
+
+for this_target in $target $canon_targets ; do
+
+changequote(,)dnl
+ eval `echo $this_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/cpu=\1 vendor=\2 os=\3/'`
+changequote([,])dnl
+
+ # check for architecture variants
+ arch=
+ endian=
+ case ${cpu} in
+ alpha*) cpu_type=alpha ;;
+ armeb) cpu_type=arm endian=big ;;
+ arm*) cpu_type=arm endian=little ;;
+ armb*) cpu_type=arm endian=little ;;
+ armv*l) cpu_type=arm endian=little ;;
+ armv*b) cpu_type=arm endian=big ;;
+ strongarm*) cpu_type=arm endian=little ;;
+ thumb*) cpu_type=arm endian=little ;;
+ hppa*) cpu_type=hppa ;;
+changequote(,)dnl
+ i[456]86) cpu_type=i386 ;;
+ m680[012346]0) cpu_type=m68k ;;
+changequote([,])dnl
+ m68008) cpu_type=m68k ;;
+ m683??) cpu_type=m68k ;;
+ m5200) cpu_type=m68k ;;
+ m8*) cpu_type=m88k ;;
+ mips*el) cpu_type=mips endian=little ;;
+ mips*) cpu_type=mips endian=big ;;
+ powerpcle*) cpu_type=ppc endian=little ;;
+ powerpc*) cpu_type=ppc endian=big ;;
+ rs6000*) cpu_type=ppc ;;
+ sparclite*) cpu_type=sparc arch=sparclite ;;
+ sparclet*) cpu_type=sparc arch=sparclet ;;
+ sparc64*) cpu_type=sparc arch=v9-64 ;;
+ sparc86x*) cpu_type=sparc arch=sparc86x ;;
+ sparc*) cpu_type=sparc arch=sparclite ;; # ??? See tc-sparc.c.
+ v850*) cpu_type=v850 ;;
+ *) cpu_type=${cpu} ;;
+ esac
+
+ if test ${this_target} = $target ; then
+ target_cpu_type=${cpu_type}
+ elif test ${target_cpu_type} != ${cpu_type} ; then
+ continue
+ fi
+
+ generic_target=${cpu_type}-$vendor-$os
+ dev=no
+ bfd_gas=no
+ em=generic
+
+ # assign object format
+ case ${generic_target} in
+ a29k-*-coff) fmt=coff ;;
+ a29k-amd-udi) fmt=coff ;;
+ a29k-amd-ebmon) fmt=coff ;;
+ a29k-nyu-sym1) fmt=coff ;;
+ a29k-*-vxworks*) fmt=coff ;;
+
+ alpha*-*-*vms*) fmt=evax ;;
+ alpha*-*-netware*) fmt=ecoff ;;
+ alpha*-*-openbsd*) fmt=ecoff ;;
+ alpha*-*-osf*) fmt=ecoff ;;
+ alpha*-*-linuxecoff*) fmt=ecoff ;;
+ alpha*-*-linux-gnu*) fmt=elf em=linux ;;
+ alpha*-*-netbsd*) fmt=elf em=nbsd ;;
+
+ arc-*-elf*) fmt=elf bfd_gas=yes ;;
+
+ arm-*-aout) fmt=aout ;;
+ arm-*-coff | thumb-*-coff) fmt=coff ;;
+ arm-*-elf | thumb-*-elf) fmt=elf ;;
+ arm-*-linux*aout*) fmt=aout em=linux ;;
+ arm-*-linux* | armv*-*-linux-gnu) fmt=elf em=linux ;;
+ arm-*-netbsd*) fmt=aout em=nbsd bfd_gas=yes ;;
+ arm-*-oabi | thumb-*-oabi) fmt=elf ;;
+ arm-epoc-pe | thumb-epoc-pe) fmt=coff em=epoc-pe ;;
+ arm-*-pe | thumb-*-pe) fmt=coff em=pe ;;
+ arm-*-riscix*) fmt=aout em=riscix ;;
+
+ d10v-*-*) fmt=elf bfd_gas=yes ;;
+ d30v-*-*) fmt=elf bfd_gas=yes ;;
+
+
+ fr30-*-*) fmt=elf bfd_gas=yes ;;
+
+ hppa-*-*elf*) fmt=elf em=hppa ;;
+ hppa-*-lites*) fmt=elf em=hppa ;;
+ hppa-*-osf*) fmt=som em=hppa ;;
+ hppa-*-rtems*) fmt=elf em=hppa ;;
+ hppa-*-hpux*) fmt=som em=hppa ;;
+ hppa-*-mpeix*) fmt=som em=hppa ;;
+ hppa-*-bsd*) fmt=som em=hppa ;;
+ hppa-*-hiux*) fmt=som em=hppa ;;
+
+ h8300-*-coff) fmt=coff ;;
+
+ i386-ibm-aix*) fmt=coff em=i386aix ;;
+ i386-sequent-bsd*) fmt=aout em=dynix bfd_gas=yes ;;
+ i386-*-beospe*) fmt=coff em=pe bfd_gas=yes ;;
+ i386-*-beoself* | i386-*-beos*) fmt=elf bfd_gas=yes ;;
+ i386-*-bsd*) fmt=aout em=386bsd ;;
+ i386-*-netbsd0.8) fmt=aout em=386bsd ;;
+ i386-*-netbsd*) fmt=aout em=nbsd bfd_gas=yes;;
+ i386-*-openbsd*) fmt=aout em=nbsd bfd_gas=yes;;
+ i386-*-linux*aout* | i386-*-linuxoldld) fmt=aout em=linux ;;
+ i386-*-linux*coff*) fmt=coff em=linux ;;
+ i386-*-linux-gnu*) fmt=elf em=linux bfd_gas=yes ;;
+ i386-*-lynxos*) fmt=coff em=lynx ;;
+ i386-*-sysv4* | i386-*-solaris* | i386-*-elf)
+ fmt=elf bfd_gas=yes ;;
+ i386-*-freebsdelf*) fmt=elf bfd_gas=yes ;;
+ i386-*-freebsd*) fmt=aout em=386bsd ;;
+ i386-*-coff | i386-*-sysv* | i386-*-sco3.2v5*coff | i386-*-isc*)
+ fmt=coff ;;
+ i386-*-sco3.2v5*) fmt=elf
+ if test ${this_target} = $target; then
+ AC_DEFINE(SCO_ELF, 1,
+ [Define if defaulting to ELF on SCO 5.])
+ fi
+ ;;
+ i386-*-sco3.2*) fmt=coff ;;
+ i386-*-vsta) fmt=aout ;;
+ i386-*-msdosdjgpp* | i386-*-go32* | i386-go32-rtems*)
+ fmt=coff em=go32;;
+ i386-*-rtems*) fmt=coff ;;
+ i386-*-gnu*) fmt=elf ;;
+ i386-*-mach*)
+ fmt=aout em=mach bfd_gas=yes ;;
+ i386-*-msdos*) fmt=aout ;;
+ i386-*-moss*) fmt=elf ;;
+ i386-*-pe) fmt=coff em=pe ;;
+ i386-*-cygwin*) fmt=coff em=pe bfd_gas=yes ;;
+ i386-*-mingw32*) fmt=coff em=pe bfd_gas=yes ;;
+ i386-*-*nt*) fmt=coff em=pe ;;
+ i960-*-bout) fmt=bout ;;
+ i960-*-coff) fmt=coff em=ic960 ;;
+ i960-*-rtems*) fmt=coff em=ic960 ;;
+ i960-*-nindy*) fmt=bout ;;
+ i960-*-vxworks4*) fmt=bout ;;
+ i960-*-vxworks5.0) fmt=bout ;;
+ i960-*-vxworks5.*) fmt=coff em=ic960 ;;
+ i960-*-vxworks*) fmt=bout ;;
+
+ m32r-*-*) fmt=elf bfd_gas=yes ;;
+
+ m68k-*-vxworks* | m68k-ericsson-ose | m68k-*-sunos*)
+ fmt=aout em=sun3 ;;
+ m68k-motorola-sysv*) fmt=coff em=delta ;;
+ m68k-bull-sysv3*) fmt=coff em=dpx2 ;;
+ m68k-apollo-*) fmt=coff em=apollo ;;
+ m68k-*-sysv4*) # must be before -sysv*
+ fmt=elf em=svr4 ;;
+ m68k-*-elf*) fmt=elf ;;
+ m68k-*-coff | m68k-*-sysv* | m68k-*-rtems*)
+ fmt=coff ;;
+ m68k-*-hpux*) fmt=hp300 em=hp300 ;;
+ m68k-*-linux*aout*) fmt=aout em=linux ;;
+ m68k-*-linux-gnu*) fmt=elf em=linux ;;
+ m68k-*-gnu*) fmt=elf ;;
+ m68k-*-lynxos*) fmt=coff em=lynx ;;
+ m68k-*-netbsd*) fmt=aout em=nbsd bfd_gas=yes ;;
+ m68k-*-openbsd*) fmt=aout em=nbsd bfd_gas=yes ;;
+ m68k-apple-aux*) fmt=coff em=aux ;;
+ m68k-*-psos*) fmt=elf em=psos;;
+
+ m88k-motorola-sysv3*) fmt=coff em=delt88 ;;
+ m88k-*-coff*) fmt=coff ;;
+
+ mcore-*-elf) fmt=elf bfd_gas=yes ;;
+ mcore-*-pe) fmt=coff em=pe bfd_gas=yes ;;
+
+ # don't change em like *-*-bsd does
+ mips-dec-netbsd*) fmt=elf endian=little ;;
+ mips-dec-openbsd*) fmt=elf endian=little ;;
+ mips-dec-bsd*) fmt=aout endian=little ;;
+ mips-sony-bsd*) fmt=ecoff ;;
+ mips-*-bsd*) AC_MSG_ERROR(Unknown vendor for mips-bsd configuration.) ;;
+ mips-*-ultrix*) fmt=ecoff endian=little ;;
+ mips-*-osf*) fmt=ecoff endian=little ;;
+ mips-*-ecoff*) fmt=ecoff ;;
+ mips-*-ecoff*) fmt=ecoff ;;
+ mips-*-irix6*) fmt=elf ;;
+ mips-*-irix5*) fmt=elf ;;
+ mips-*-irix*) fmt=ecoff ;;
+ mips-*-lnews*) fmt=ecoff em=lnews ;;
+ mips-*-riscos*) fmt=ecoff ;;
+ mips-*-sysv*) fmt=ecoff ;;
+ mips-*-elf* | mips-*-rtems* | mips-*-linux-gnu* | mips-*-gnu* | mips-*-openbsd*)
+ fmt=elf ;;
+ mips-*-vxworks*) fmt=elf
+ AC_DEFINE(MIPS_STABS_ELF, 1,
+ [Use ELF stabs for MIPS, not ECOFF stabs])
+ ;;
+ mn10200-*-*) fmt=elf bfd_gas=yes ;;
+ mn10300-*-*) fmt=elf bfd_gas=yes ;;
+ ppc-*-pe | ppc-*-cygwin* | ppc-*-winnt*)
+ fmt=coff em=pe ;;
+ ppc-*-aix*) fmt=coff ;;
+ ppc-*-beos*) fmt=coff ;;
+ ppc-*-*bsd* | ppc-*-elf* | ppc-*-eabi* | ppc-*-sysv4*)
+ fmt=elf ;;
+ ppc-*-linux-gnu*) fmt=elf
+ case "$endian" in
+ big) ;;
+ *) AC_MSG_ERROR(GNU/Linux must be configured big endian) ;;
+ esac
+ ;;
+ ppc-*-solaris*) fmt=elf
+ if test ${this_target} = $target; then
+ AC_DEFINE(TARGET_SOLARIS_COMMENT, 1,
+ [Define if default target is PowerPC Solaris.])
+ fi
+ if test x${endian} = xbig; then
+ AC_MSG_ERROR(Solaris must be configured little endian)
+ fi
+ ;;
+ ppc-*-rtems*) fmt=elf ;;
+ ppc-*-macos* | ppc-*-mpw*)
+ fmt=coff em=macos ;;
+ ppc-*-netware*) fmt=elf em=ppcnw ;;
+
+ sh-*-elf*) fmt=elf ;;
+ sh-*-coff*) fmt=coff ;;
+ sh-*-rtems*) fmt=coff ;;
+
+ ns32k-pc532-mach* | ns32k-pc532-ux*) fmt=aout em=pc532mach ;;
+ ns32k-pc532-netbsd* | ns32k-pc532-lites*) fmt=aout em=nbsd532 ;;
+ ns32k-pc532-openbsd*) fmt=aout em=nbsd532 ;;
+
+ sparc-*-rtems*) fmt=aout ;;
+ sparc-*-sunos4*) fmt=aout em=sun3 ;;
+ sparc-*-aout | sparc*-*-vxworks*)
+ fmt=aout em=sparcaout ;;
+ sparc-*-coff) fmt=coff ;;
+ sparc-*-linux*aout*) fmt=aout em=linux ;;
+ sparc-*-linux-gnu*) fmt=elf em=linux ;;
+ sparc-*-lynxos*) fmt=coff em=lynx ;;
+ sparc-fujitsu-none) fmt=aout ;;
+ sparc-*-elf | sparc-*-sysv4* | sparc-*-solaris*)
+ fmt=elf ;;
+ sparc-*-netbsd*) fmt=aout em=nbsd ;;
+ sparc-*-openbsd*) fmt=aout em=nbsd ;;
+
+ strongarm-*-coff) fmt=coff ;;
+ strongarm-*-elf) fmt=elf ;;
+
+ tic30-*-*aout*) fmt=aout bfd_gas=yes ;;
+ tic30-*-*coff*) fmt=coff bfd_gas=yes ;;
+ tic80-*-*) fmt=coff ;;
+
+ v850-*-*) fmt=elf bfd_gas=yes ;;
+ v850e-*-*) fmt=elf bfd_gas=yes ;;
+ v850ea-*-*) fmt=elf bfd_gas=yes ;;
+
+ vax-*-bsd* | vax-*-ultrix*)
+ fmt=aout ;;
+ vax-*-vms) fmt=vms ;;
+
+
+ z8k-*-coff | z8k-*-sim)
+ fmt=coff ;;
+
+ w65-*-*) fmt=coff ;;
+
+ *-*-aout | *-*-scout)
+ fmt=aout ;;
+ *-*-nindy*)
+ fmt=bout ;;
+ *-*-bsd*)
+ fmt=aout em=sun3 ;;
+ *-*-generic) fmt=generic ;;
+ *-*-xray | *-*-hms) fmt=coff ;;
+ *-*-sim) fmt=coff ;;
+ *-*-elf | *-*-sysv4* | *-*-solaris*)
+ AC_MSG_WARN(GAS support for ${generic_target} is incomplete.)
+ fmt=elf dev=yes ;;
+ *-*-vxworks) fmt=aout ;;
+ *-*-netware) fmt=elf ;;
+ esac
+
+ if test ${this_target} = $target ; then
+ endian_def=
+ if test x${endian} = xbig; then
+ endian_def=1
+ elif test x${endian} = xlittle; then
+ endian_def=0
+ fi
+ if test x${endian_def} != x; then
+ AC_DEFINE_UNQUOTED(TARGET_BYTES_BIG_ENDIAN, $endian_def,
+ [Define as 1 if big endian.])
+ fi
+ fi
+
+ case ${cpu_type}-${fmt} in
+ alpha*-*) bfd_gas=yes ;;
+ arm-*) bfd_gas=yes ;;
+ # not yet
+ # i386-aout) bfd_gas=preferred ;;
+ mips-*) bfd_gas=yes ;;
+ ns32k-*) bfd_gas=yes ;;
+ ppc-*) bfd_gas=yes ;;
+ sparc-*) bfd_gas=yes ;;
+ strongarm-*) bfd_gas=yes ;;
+ *-elf) bfd_gas=yes ;;
+ *-ecoff) bfd_gas=yes ;;
+ *-som) bfd_gas=yes ;;
+ *) ;;
+ esac
+
+# Other random stuff.
+
+ # Do we need the opcodes library?
+ case ${cpu_type} in
+ vax | i386 | tic30)
+ ;;
+
+ *)
+ need_opcodes=yes
+
+ case "${enable_shared}" in
+ yes) shared_opcodes=true ;;
+ *opcodes*) shared_opcodes=true ;;
+ *) shared_opcodes=false ;;
+ esac
+ if test "${shared_opcodes}" = "true"; then
+ # A shared libopcodes must be linked against libbfd.
+ need_bfd=yes
+ fi
+ ;;
+ esac
+
+ # Any other special object files needed ?
+ case ${cpu_type} in
+ fr30 | m32r)
+ using_cgen=yes
+ ;;
+
+ m68k)
+ case ${extra_objects} in
+ *m68k-parse.o*) ;;
+ *) extra_objects="$extra_objects m68k-parse.o" ;;
+ esac
+ ;;
+
+ mips)
+ echo ${extra_objects} | grep -s "itbl-parse.o"
+ if test $? -ne 0 ; then
+ extra_objects="$extra_objects itbl-parse.o"
+ fi
+
+ echo ${extra_objects} | grep -s "itbl-lex.o"
+ if test $? -ne 0 ; then
+ extra_objects="$extra_objects itbl-lex.o"
+ fi
+
+ echo ${extra_objects} | grep -s "itbl-ops.o"
+ if test $? -ne 0 ; then
+ extra_objects="$extra_objects itbl-ops.o"
+ fi
+ ;;
+
+ sparc)
+ if test $this_target = $target ; then
+ AC_DEFINE_UNQUOTED(DEFAULT_ARCH, "${arch}", [Default architecture.])
+ fi
+ ;;
+ *)
+ ;;
+ esac
+
+ if test $using_cgen = yes ; then
+ case "x${extra_objects}" in
+ *cgen.o*) ;;
+ *) extra_objects="$extra_objects cgen.o" ;;
+ esac
+ fi
+
+# See if we really can support this configuration with the emulation code.
+
+ if test $this_target = $target ; then
+ primary_bfd_gas=$bfd_gas
+ obj_format=$fmt
+ te_file=$em
+
+ if test $bfd_gas = no ; then
+ # Can't support other configurations this way.
+ break
+ fi
+ elif test $bfd_gas = no ; then
+ # Can't support this configuration.
+ break
+ fi
+
+# From target name and format, produce a list of supported emulations.
+
+ case ${generic_target}-${fmt} in
+ mips-*-irix5*-*) emulation="mipsbelf mipslelf mipself mipsbecoff mipslecoff mipsecoff" ;;
+ mips-*-linux-gnu*-*) case "$endian" in
+ big) emulation="mipsbelf mipslelf mipself mipsbecoff mipslecoff mipsecoff" ;;
+ *) emulation="mipslelf mipsbelf mipself mipslecoff mipsbecoff mipsecoff" ;;
+ esac ;;
+ mips-*-lnews*-ecoff) ;;
+ mips-*-*-ecoff) case "$endian" in
+ big) emulation="mipsbecoff mipslecoff mipsecoff" ;;
+ *) emulation="mipslecoff mipsbecoff mipsecoff" ;;
+ esac ;;
+ mips-*-*-elf) case "$endian" in
+ big) emulation="mipsbelf mipslelf mipself" ;;
+ *) emulation="mipslelf mipsbelf mipself" ;;
+ # Uncommenting the next line will turn on support for i386 COFF
+ # in any i386 ELF configuration. This probably doesn't work
+ # correctly.
+ # i386-*-*-elf) emulation="i386coff i386elf" ;;
+ esac ;;
+ esac
+
+ emulations="$emulations $emulation"
+
+done
+
+# Assign floating point type. Most processors with FP support
+# IEEE FP. On those that don't support FP at all, usually IEEE
+# is emulated.
+case ${target_cpu} in
+ vax | tahoe ) atof=${target_cpu} ;;
+ *) atof=ieee ;;
+esac
+
+case "${obj_format}" in
+ "") AC_MSG_ERROR(GAS does not know what format to use for target ${target}) ;;
+esac
+
+# Unfortunately the cpu in cpu-opc.h file isn't always $(TARGET_CPU).
+cgen_cpu_prefix=""
+if test $using_cgen = yes ; then
+ case ${target_cpu} in
+ *) cgen_cpu_prefix=${target_cpu} ;;
+ esac
+ AC_SUBST(cgen_cpu_prefix)
+ AC_DEFINE(USING_CGEN, 1, [Using cgen code?])
+fi
+
+dnl
+dnl Make sure the desired support files exist.
+dnl
+
+if test ! -r ${srcdir}/config/tc-${target_cpu_type}.c; then
+ AC_MSG_ERROR(GAS does not support target CPU ${target_cpu_type})
+fi
+
+if test ! -r ${srcdir}/config/obj-${obj_format}.c; then
+ AC_MSG_ERROR(GAS does not have support for object file format ${obj_format})
+fi
+
+case ${user_bfd_gas}-${primary_bfd_gas} in
+ yes-yes | no-no)
+ # We didn't override user's choice.
+ ;;
+ no-yes)
+ AC_MSG_WARN(Use of BFD is required for ${target}; overriding config options.)
+ ;;
+ no-preferred)
+ primary_bfd_gas=no
+ ;;
+ *-preferred)
+ primary_bfd_gas=yes
+ ;;
+ yes-*)
+ primary_bfd_gas=yes
+ ;;
+ -*)
+ # User specified nothing.
+ ;;
+esac
+
+# Some COFF configurations want these random other flags set.
+case ${obj_format} in
+ coff)
+ case ${target_cpu_type} in
+ i386) AC_DEFINE(I386COFF, 1, [Using i386 COFF?]) ;;
+ m68k) AC_DEFINE(M68KCOFF, 1, [Using m68k COFF?]) ;;
+ m88k) AC_DEFINE(M88KCOFF, 1, [Using m88k COFF?]) ;;
+ esac
+ ;;
+esac
+
+# Getting this done right is going to be a bitch. Each configuration specified
+# with --enable-targets=... should be checked for environment, format, cpu, and
+# bfd_gas setting.
+#
+# For each configuration, the necessary object file support code must be linked
+# in. This might be only one, it might be up to four. The necessary emulation
+# code needs to be provided, too.
+#
+# And then there's "--enable-targets=all"....
+#
+# For now, just always do it for MIPS ELF or ECOFF configurations. Sigh.
+
+formats="${obj_format}"
+emfiles=""
+EMULATIONS=""
+GAS_UNIQ(emulations)
+for em in . $emulations ; do
+ case $em in
+ .) continue ;;
+ mipsbelf | mipslelf)
+ fmt=elf file=mipself ;;
+ mipsbecoff | mipslecoff)
+ fmt=ecoff file=mipsecoff ;;
+ i386coff)
+ fmt=coff file=i386coff ;;
+ i386elf)
+ fmt=elf file=i386elf ;;
+ esac
+ formats="$formats $fmt"
+ emfiles="$emfiles e-$file.o"
+ EMULATIONS="$EMULATIONS &$em,"
+done
+GAS_UNIQ(formats)
+GAS_UNIQ(emfiles)
+if test `set . $formats ; shift ; echo $#` -gt 1 ; then
+ for fmt in $formats ; do
+ case $fmt in
+ aout) AC_DEFINE(OBJ_MAYBE_AOUT, 1, [a.out support?]) ;;
+ bout) AC_DEFINE(OBJ_MAYBE_BOUT, 1, [b.out support?]) ;;
+ coff) AC_DEFINE(OBJ_MAYBE_COFF, 1, [COFF support?]) ;;
+ ecoff) AC_DEFINE(OBJ_MAYBE_ECOFF, 1, [ECOFF support?]) ;;
+ elf) AC_DEFINE(OBJ_MAYBE_ELF, 1, [ELF support?]) ;;
+ generic) AC_DEFINE(OBJ_MAYBE_GENERIC, 1, [generic support?]) ;;
+ hp300) AC_DEFINE(OBJ_MAYBE_HP300, 1, [HP300 support?]) ;;
+ ieee) AC_DEFINE(OBJ_MAYBE_IEEE, 1, [IEEE support?]) ;;
+ som) AC_DEFINE(OBJ_MAYBE_SOM, 1, [SOM support?]) ;;
+ vms) AC_DEFINE(OBJ_MAYBE_VMS, 1, [VMS support?]) ;;
+ esac
+ extra_objects="$extra_objects obj-$fmt.o"
+ done
+ obj_format=multi
+fi
+if test `set . $emfiles ; shift ; echo $#` -gt 0 ; then
+ te_file=multi
+ extra_objects="$extra_objects $emfiles"
+ DEFAULT_EMULATION=`set . $emulations ; echo $2`
+ AC_DEFINE(USE_EMULATIONS, 1, [Use emulation support?])
+fi
+AC_SUBST(extra_objects)
+AC_DEFINE_UNQUOTED(EMULATIONS, $EMULATIONS, [Supported emulations.])
+AC_DEFINE_UNQUOTED(DEFAULT_EMULATION, "$DEFAULT_EMULATION",
+ [Default emulation.])
+
+case ${primary_bfd_gas}-${target_cpu_type}-${obj_format} in
+ yes-*-coff) need_bfd=yes ;;
+ no-*-coff) need_bfd=yes
+ AC_DEFINE(MANY_SEGMENTS, 1, [old COFF support?]) ;;
+esac
+
+reject_dev_configs=yes
+
+case ${reject_dev_configs}-${dev} in
+ yes-yes) # Oops.
+ AC_MSG_ERROR(GAS does not support the ${generic_target} configuration.)
+ ;;
+esac
+
+AC_SUBST(target_cpu_type)
+AC_SUBST(obj_format)
+AC_SUBST(te_file)
+AC_SUBST(install_tooldir)
+AC_SUBST(atof)
+dnl AC_SUBST(emulation)
+
+case "${primary_bfd_gas}" in
+ yes) AC_DEFINE(BFD_ASSEMBLER, 1, [Use BFD interface?])
+ need_bfd=yes ;;
+esac
+
+# do we need the opcodes library?
+case "${need_opcodes}" in
+yes)
+ OPCODES_LIB=../opcodes/libopcodes.la
+ ;;
+esac
+
+case "${need_bfd}" in
+yes)
+ BFDLIB=../bfd/libbfd.la
+ ALL_OBJ_DEPS="$ALL_OBJ_DEPS ../bfd/bfd.h"
+ ;;
+esac
+
+AC_SUBST(BFDLIB)
+AC_SUBST(OPCODES_LIB)
+
+AC_SUBST(ALL_OBJ_DEPS)
+
+AC_DEFINE_UNQUOTED(TARGET_ALIAS, "${target_alias}", [Target alias.])
+AC_DEFINE_UNQUOTED(TARGET_CANONICAL, "${target}", [Canonical target.])
+AC_DEFINE_UNQUOTED(TARGET_CPU, "${target_cpu}", [Target CPU.])
+AC_DEFINE_UNQUOTED(TARGET_VENDOR, "${target_vendor}", [Target vendor.])
+AC_DEFINE_UNQUOTED(TARGET_OS, "${target_os}", [Target OS.])
+
+AC_PROG_CC
+
+AC_PROG_YACC
+AM_PROG_LEX
+
+ALL_LINGUAS=
+CY_GNU_GETTEXT
+
+AM_MAINTAINER_MODE
+AC_EXEEXT
+
+AC_CHECK_HEADERS(string.h stdlib.h memory.h strings.h unistd.h stdarg.h varargs.h errno.h sys/types.h)
+
+# Put this here so that autoconf's "cross-compiling" message doesn't confuse
+# people who are not cross-compiling but are compiling cross-assemblers.
+AC_MSG_CHECKING(whether compiling a cross-assembler)
+if test "${host}" = "${target}"; then
+ cross_gas=no
+else
+ cross_gas=yes
+ AC_DEFINE(CROSS_COMPILE, 1, [Compiling cross-assembler?])
+fi
+AC_MSG_RESULT($cross_gas)
+
+dnl ansidecl.h will deal with const
+dnl AC_CONST
+AC_FUNC_ALLOCA
+AC_C_INLINE
+
+# VMS doesn't have unlink.
+AC_CHECK_FUNCS(unlink remove, break)
+
+# Some systems don't have sbrk().
+AC_CHECK_FUNCS(sbrk)
+
+# Some non-ANSI preprocessors botch requoting inside strings. That's bad
+# enough, but on some of those systems, the assert macro relies on requoting
+# working properly!
+GAS_WORKING_ASSERT
+
+# On some systems, the system header files may not declare malloc, realloc,
+# and free. There are places where gas needs these functions to have been
+# declared -- such as when taking their addresses.
+gas_test_headers="
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+"
+GAS_CHECK_DECL_NEEDED(strstr, f, char *(*f)(), $gas_test_headers)
+GAS_CHECK_DECL_NEEDED(malloc, f, char *(*f)(), $gas_test_headers)
+GAS_CHECK_DECL_NEEDED(free, f, void (*f)(), $gas_test_headers)
+GAS_CHECK_DECL_NEEDED(sbrk, f, char *(*f)(), $gas_test_headers)
+GAS_CHECK_DECL_NEEDED(environ, f, char **f, $gas_test_headers)
+
+# Does errno.h declare errno, or do we have to add a separate declaration
+# for it?
+GAS_CHECK_DECL_NEEDED(errno, f, int f, [
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+])
+
+dnl This must come last.
+
+dnl We used to make symlinks to files in the source directory, but now
+dnl we just use the right name for .c files, and create .h files in
+dnl the build directory which include the right .h file. Make sure
+dnl the old symlinks don't exist, so that a reconfigure in an existing
+dnl directory behaves reasonably.
+
+AC_OUTPUT(Makefile doc/Makefile .gdbinit:gdbinit.in po/Makefile.in:po/Make-in,
+[rm -f targ-cpu.c targ-cpu.h obj-format.h obj-format.c targ-env.h atof-targ.c itbl-cpu.h
+ echo '#include "tc-'"${target_cpu_type}"'.h"' > targ-cpu.h
+ echo '#include "obj-'"${obj_format}"'.h"' > obj-format.h
+ echo '#include "te-'"${te_file}"'.h"' > targ-env.h
+ echo '#include "itbl-'"${target_cpu_type}"'.h"' > itbl-cpu.h
+ if test "x$cgen_cpu_prefix" != x ; then
+ echo '#include "opcodes/'"${cgen_cpu_prefix}"'-desc.h"' > cgen-desc.h
+ fi
+
+ sed -e '/POTFILES =/r po/POTFILES' po/Makefile.in > po/Makefile],
+[target_cpu_type=${target_cpu_type}
+ cgen_cpu_prefix=${cgen_cpu_prefix}
+ obj_format=${obj_format}
+ te_file=${te_file}])
diff --git a/gas/debug.c b/gas/debug.c
new file mode 100644
index 0000000000..e99f23f32a
--- /dev/null
+++ b/gas/debug.c
@@ -0,0 +1,104 @@
+/* This file is debug.c
+ Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Routines for debug use only. */
+
+#include "as.h"
+#include "subsegs.h"
+
+dmp_frags ()
+{
+ frchainS *chp;
+ char *p;
+
+ for (chp = frchain_root; chp; chp = chp->frch_next)
+ {
+ switch (chp->frch_seg)
+ {
+ case SEG_DATA:
+ p = "Data";
+ break;
+ case SEG_TEXT:
+ p = "Text";
+ break;
+ default:
+ p = "???";
+ break;
+ }
+ printf ("\nSEGMENT %s %d\n", p, chp->frch_subseg);
+ dmp_frag (chp->frch_root, "\t");
+ }
+}
+
+dmp_frag (fp, indent)
+ struct frag *fp;
+ char *indent;
+{
+ for (; fp; fp = fp->fr_next)
+ {
+ printf ("%sFRAGMENT @ 0x%x\n", indent, fp);
+ switch (fp->fr_type)
+ {
+ case rs_align:
+ printf ("%srs_align(%d)\n", indent, fp->fr_offset);
+ break;
+ case rs_fill:
+ printf ("%srs_fill(%d)\n", indent, fp->fr_offset);
+ printf ("%s", indent);
+ var_chars (fp, fp->fr_var + fp->fr_fix);
+ printf ("%s\t repeated %d times,",
+ indent, fp->fr_offset);
+ printf (" fixed length if # chars == 0)\n");
+ break;
+ case rs_org:
+ printf ("%srs_org(%d+sym @0x%x)\n", indent,
+ fp->fr_offset, fp->fr_symbol);
+ printf ("%sfill with ", indent);
+ var_chars (fp, 1);
+ printf ("\n");
+ break;
+ case rs_machine_dependent:
+ printf ("%smachine_dep\n", indent);
+ break;
+ default:
+ printf ("%sunknown type\n", indent);
+ break;
+ }
+ printf ("%saddr=%d(0x%x)\n", indent, fp->fr_address, fp->fr_address);
+ printf ("%sfr_fix=%d\n", indent, fp->fr_fix);
+ printf ("%sfr_var=%d\n", indent, fp->fr_var);
+ printf ("%sfr_offset=%d\n", indent, fp->fr_offset);
+ printf ("%schars @ 0x%x\n", indent, fp->fr_literal);
+ printf ("\n");
+ }
+}
+
+var_chars (fp, n)
+ struct frag *fp;
+ int n;
+{
+ unsigned char *p;
+
+ for (p = (unsigned char *) fp->fr_literal; n; n--, p++)
+ {
+ printf ("%02x ", *p);
+ }
+}
+
+/* end of debug.c */
diff --git a/gas/dep-in.sed b/gas/dep-in.sed
new file mode 100644
index 0000000000..c07f9693b0
--- /dev/null
+++ b/gas/dep-in.sed
@@ -0,0 +1,45 @@
+:loop
+/\\$/N
+/\\$/b loop
+
+s! ../config.h!!g
+s! ../../bfd/bfd.h!!g
+s! ../itbl-parse.h!!g
+s!@INCDIR@!$(INCDIR)!g
+s!@BFDDIR@!$(BFDDIR)!g
+s!@SRCDIR@/config!$(srcdir)/config!g
+s!@SRCDIR@/../opcodes!$(srcdir)/../opcodes!g
+s!@SRCDIR@/!!g
+s! config.h!!g
+s! as.h!!g
+s! asintl.h!!g
+s! targ-env.h!!g
+s! obj-format.h!!g
+s! targ-cpu.h!!g
+s! flonum.h!!g
+s! expr.h!!g
+s! struc-symbol.h!!g
+s! write.h!!g
+s! frags.h!!g
+s! hash.h!!g
+s! read.h!!g
+s! symbols.h!!g
+s! tc.h!!g
+s! obj.h!!g
+s! listing.h!!g
+s! bignum.h!!g
+s! bit_fix.h!!g
+s! itbl-cpu.h!!g
+s! \$(srcdir)/config/te-generic.h!!g
+s! \$(INCDIR)/libiberty.h!!g
+s! \$(INCDIR)/ansidecl.h!!g
+s! \$(INCDIR)/fopen-same.h!!g
+
+s/\\\n */ /g
+
+s/ *$//
+s/ */ /g
+/:$/d
+
+s/\(.\{50\}[^ ]*\) /\1 \\\
+ /g
diff --git a/gas/depend.c b/gas/depend.c
new file mode 100644
index 0000000000..f17c7c8e3a
--- /dev/null
+++ b/gas/depend.c
@@ -0,0 +1,208 @@
+/* depend.c - Handle dependency tracking.
+ Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include "as.h"
+
+/* The file to write to, or NULL if no dependencies being kept. */
+static char *dep_file = NULL;
+
+struct dependency
+{
+ char *file;
+ struct dependency *next;
+};
+
+/* All the files we depend on. */
+static struct dependency *dep_chain = NULL;
+
+/* Current column in output file. */
+static int column = 0;
+
+static int quote_string_for_make PARAMS ((FILE *, char *));
+static void wrap_output PARAMS ((FILE *, char *, int));
+
+/* Number of columns allowable. */
+#define MAX_COLUMNS 72
+
+
+
+/* Start saving dependencies, to be written to FILENAME. If this is
+ never called, then dependency tracking is simply skipped. */
+
+void
+start_dependencies (filename)
+ char *filename;
+{
+ dep_file = filename;
+}
+
+/* Noticed a new filename, so try to register it. */
+
+void
+register_dependency (filename)
+ char *filename;
+{
+ struct dependency *dep;
+
+ if (dep_file == NULL)
+ return;
+
+ for (dep = dep_chain; dep != NULL; dep = dep->next)
+ {
+ if (! strcmp (filename, dep->file))
+ return;
+ }
+
+ dep = (struct dependency *) xmalloc (sizeof (struct dependency));
+ dep->file = xstrdup (filename);
+ dep->next = dep_chain;
+ dep_chain = dep;
+}
+
+/* Quote a file name the way `make' wants it, and print it to FILE.
+ If FILE is NULL, do no printing, but return the length of the
+ quoted string.
+
+ This code is taken from gcc with only minor changes. */
+
+static int
+quote_string_for_make (file, src)
+ FILE *file;
+ char *src;
+{
+ char *p = src;
+ int i = 0;
+ for (;;)
+ {
+ char c = *p++;
+ switch (c)
+ {
+ case '\0':
+ case ' ':
+ case '\t':
+ {
+ /* GNU make uses a weird quoting scheme for white space.
+ A space or tab preceded by 2N+1 backslashes represents
+ N backslashes followed by space; a space or tab
+ preceded by 2N backslashes represents N backslashes at
+ the end of a file name; and backslashes in other
+ contexts should not be doubled. */
+ char *q;
+ for (q = p - 1; src < q && q[-1] == '\\'; q--)
+ {
+ if (file)
+ putc ('\\', file);
+ i++;
+ }
+ }
+ if (!c)
+ return i;
+ if (file)
+ putc ('\\', file);
+ i++;
+ goto ordinary_char;
+
+ case '$':
+ if (file)
+ putc (c, file);
+ i++;
+ /* Fall through. This can mishandle things like "$(" but
+ there's no easy fix. */
+ default:
+ ordinary_char:
+ /* This can mishandle characters in the string "\0\n%*?[\\~";
+ exactly which chars are mishandled depends on the `make' version.
+ We know of no portable solution for this;
+ even GNU make 3.76.1 doesn't solve the problem entirely.
+ (Also, '\0' is mishandled due to our calling conventions.) */
+ if (file)
+ putc (c, file);
+ i++;
+ break;
+ }
+ }
+}
+
+/* Append some output to the file, keeping track of columns and doing
+ wrapping as necessary. */
+
+static void
+wrap_output (f, string, spacer)
+ FILE *f;
+ char *string;
+ int spacer;
+{
+ int len = quote_string_for_make (NULL, string);
+
+ if (len == 0)
+ return;
+
+ if (column && MAX_COLUMNS - 1 /*spacer*/ - 2 /*` \'*/ < column + len)
+ {
+ fprintf (f, " \\\n ");
+ column = 0;
+ if (spacer == ' ')
+ spacer = '\0';
+ }
+
+ if (spacer == ' ')
+ {
+ putc (spacer, f);
+ ++column;
+ }
+
+ quote_string_for_make (f, string);
+ column += len;
+
+ if (spacer == ':')
+ {
+ putc (spacer, f);
+ ++column;
+ }
+}
+
+/* Print dependency file. */
+
+void
+print_dependencies ()
+{
+ FILE *f;
+ struct dependency *dep;
+
+ if (dep_file == NULL)
+ return;
+
+ f = fopen (dep_file, "w");
+ if (f == NULL)
+ {
+ as_warn (_("Can't open `%s' for writing"), dep_file);
+ return;
+ }
+
+ column = 0;
+ wrap_output (f, out_file_name, ':');
+ for (dep = dep_chain; dep != NULL; dep = dep->next)
+ wrap_output (f, dep->file, ' ');
+
+ putc ('\n', f);
+
+ if (fclose (f))
+ as_warn (_("Can't close `%s'"), dep_file);
+}
diff --git a/gas/doc/Makefile.am b/gas/doc/Makefile.am
new file mode 100644
index 0000000000..eaf5a4ab14
--- /dev/null
+++ b/gas/doc/Makefile.am
@@ -0,0 +1,49 @@
+## Process this file with automake to generate Makefile.in
+
+AUTOMAKE_OPTIONS = cygnus
+
+# What version of the manual you want; "all" includes everything
+CONFIG=all
+
+man_MANS = as.1
+
+info_TEXINFOS = as.texinfo gasp.texi
+
+asconfig.texi: $(CONFIG).texi
+ rm -f asconfig.texi
+ ln -s $(srcdir)/$(CONFIG).texi ./asconfig.texi >/dev/null 2>&1 \
+ || ln $(srcdir)/$(CONFIG).texi ./asconfig.texi >/dev/null 2>&1 \
+ || cp $(srcdir)/$(CONFIG).texi ./asconfig.texi
+
+CPU_DOCS = \
+ c-a29k.texi \
+ c-arm.texi \
+ c-d10v.texi \
+ c-h8300.texi \
+ c-h8500.texi \
+ c-hppa.texi \
+ c-i386.texi \
+ c-i960.texi \
+ c-m68k.texi \
+ c-mips.texi \
+ c-ns32k.texi \
+ c-sh.texi \
+ c-sparc.texi \
+ c-vax.texi \
+ c-v850.texi \
+ c-z8k.texi
+
+gasver.texi: Makefile
+ rm -f $@
+ echo '@set VERSION $(VERSION)' > $@
+
+as.info: $(srcdir)/as.texinfo asconfig.texi gasver.texi $(CPU_DOCS)
+as.dvi: $(srcdir)/as.texinfo asconfig.texi gasver.texi $(CPU_DOCS)
+
+# This one isn't ready for prime time yet. Not even a little bit.
+
+noinst_TEXINFOS = internals.texi
+
+DISTCLEANFILES = asconfig.texi
+
+MAINTAINERCLEANFILES = gasver.texi
diff --git a/gas/doc/Makefile.in b/gas/doc/Makefile.in
new file mode 100644
index 0000000000..5f4d1a5269
--- /dev/null
+++ b/gas/doc/Makefile.in
@@ -0,0 +1,438 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_alias = @build_alias@
+build_triplet = @build@
+host_alias = @host_alias@
+host_triplet = @host@
+target_alias = @target_alias@
+target_triplet = @target@
+ALL_OBJ_DEPS = @ALL_OBJ_DEPS@
+AS = @AS@
+BFDLIB = @BFDLIB@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+DATADIRNAME = @DATADIRNAME@
+DLLTOOL = @DLLTOOL@
+EXEEXT = @EXEEXT@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GT_NO = @GT_NO@
+GT_YES = @GT_YES@
+INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@
+INSTOBJEXT = @INSTOBJEXT@
+INTLDEPS = @INTLDEPS@
+INTLLIBS = @INTLLIBS@
+INTLOBJS = @INTLOBJS@
+LD = @LD@
+LEX = @LEX@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+NM = @NM@
+OPCODES_LIB = @OPCODES_LIB@
+PACKAGE = @PACKAGE@
+POFILES = @POFILES@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+USE_NLS = @USE_NLS@
+USE_SYMBOL_UNDERSCORE = @USE_SYMBOL_UNDERSCORE@
+VERSION = @VERSION@
+YACC = @YACC@
+atof = @atof@
+cgen_cpu_prefix = @cgen_cpu_prefix@
+extra_objects = @extra_objects@
+install_tooldir = @install_tooldir@
+l = @l@
+obj_format = @obj_format@
+target_cpu_type = @target_cpu_type@
+te_file = @te_file@
+
+AUTOMAKE_OPTIONS = cygnus
+
+# What version of the manual you want; "all" includes everything
+CONFIG = all
+
+man_MANS = as.1
+
+info_TEXINFOS = as.texinfo gasp.texi
+
+CPU_DOCS = \
+ c-a29k.texi \
+ c-arm.texi \
+ c-d10v.texi \
+ c-h8300.texi \
+ c-h8500.texi \
+ c-hppa.texi \
+ c-i386.texi \
+ c-i960.texi \
+ c-m68k.texi \
+ c-mips.texi \
+ c-ns32k.texi \
+ c-sh.texi \
+ c-sparc.texi \
+ c-vax.texi \
+ c-v850.texi \
+ c-z8k.texi
+
+
+# This one isn't ready for prime time yet. Not even a little bit.
+
+noinst_TEXINFOS = internals.texi
+
+DISTCLEANFILES = asconfig.texi
+
+MAINTAINERCLEANFILES = gasver.texi
+mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES =
+TEXI2DVI = `if test -f $(top_srcdir)/../texinfo/util/texi2dvi; then echo $(top_srcdir)/../texinfo/util/texi2dvi; else echo texi2dvi; fi`
+TEXINFO_TEX = $(top_srcdir)/../texinfo/texinfo.tex
+INFO_DEPS = as.info gasp.info
+DVIS = as.dvi gasp.dvi
+TEXINFOS = as.texinfo gasp.texi
+man1dir = $(mandir)/man1
+MANS = $(man_MANS)
+
+NROFF = nroff
+DIST_COMMON = Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP_ENV = --best
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .dvi .info .ps .texi .texinfo .txi
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --cygnus doc/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+as.info: as.texinfo
+as.dvi: as.texinfo
+
+
+gasp.info: gasp.texi
+gasp.dvi: gasp.texi
+
+
+DVIPS = dvips
+
+.texi.info:
+ @rm -f $@ $@-[0-9] $@-[0-9][0-9]
+ $(MAKEINFO) -I $(srcdir) $<
+
+.texi.dvi:
+ TEXINPUTS=$(top_srcdir)/../texinfo/texinfo.tex:$$TEXINPUTS \
+ MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $<
+
+.texi:
+ @rm -f $@ $@-[0-9] $@-[0-9][0-9]
+ $(MAKEINFO) -I $(srcdir) $<
+
+.texinfo.info:
+ @rm -f $@ $@-[0-9] $@-[0-9][0-9]
+ $(MAKEINFO) -I $(srcdir) $<
+
+.texinfo:
+ @rm -f $@ $@-[0-9] $@-[0-9][0-9]
+ $(MAKEINFO) -I $(srcdir) $<
+
+.texinfo.dvi:
+ TEXINPUTS=$(top_srcdir)/../texinfo/texinfo.tex:$$TEXINPUTS \
+ MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $<
+
+.txi.info:
+ @rm -f $@ $@-[0-9] $@-[0-9][0-9]
+ $(MAKEINFO) -I $(srcdir) $<
+
+.txi.dvi:
+ TEXINPUTS=$(top_srcdir)/../texinfo/texinfo.tex:$$TEXINPUTS \
+ MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $<
+
+.txi:
+ @rm -f $@ $@-[0-9] $@-[0-9][0-9]
+ $(MAKEINFO) -I $(srcdir) $<
+.dvi.ps:
+ $(DVIPS) $< -o $@
+
+install-info-am: $(INFO_DEPS)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(infodir)
+ @list='$(INFO_DEPS)'; \
+ for file in $$list; do \
+ if test -f $$file; then d=.; else d=$(srcdir); fi; \
+ for ifile in `cd $$d && echo $$file $$file-[0-9] $$file-[0-9][0-9]`; do \
+ if test -f $$d/$$ifile; then \
+ echo " $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile"; \
+ $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile; \
+ else : ; fi; \
+ done; \
+ done
+ @$(POST_INSTALL)
+ @if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then \
+ list='$(INFO_DEPS)'; \
+ for file in $$list; do \
+ echo " install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file";\
+ install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file || :;\
+ done; \
+ else : ; fi
+
+uninstall-info:
+ $(PRE_UNINSTALL)
+ @if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then \
+ ii=yes; \
+ else ii=; fi; \
+ list='$(INFO_DEPS)'; \
+ for file in $$list; do \
+ test -z "$ii" \
+ || install-info --info-dir=$(DESTDIR)$(infodir) --remove $$file; \
+ done
+ @$(NORMAL_UNINSTALL)
+ list='$(INFO_DEPS)'; \
+ for file in $$list; do \
+ (cd $(DESTDIR)$(infodir) && rm -f $$file $$file-[0-9] $$file-[0-9][0-9]); \
+ done
+
+dist-info: $(INFO_DEPS)
+ list='$(INFO_DEPS)'; \
+ for base in $$list; do \
+ if test -f $$base; then d=.; else d=$(srcdir); fi; \
+ for file in `cd $$d && eval echo $$base*`; do \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file; \
+ done; \
+ done
+
+mostlyclean-aminfo:
+ -rm -f as.aux as.cp as.cps as.dvi as.fn as.fns as.ky as.kys as.ps \
+ as.log as.pg as.toc as.tp as.tps as.vr as.vrs as.op as.tr \
+ as.cv as.cn gasp.aux gasp.cp gasp.cps gasp.dvi gasp.fn \
+ gasp.fns gasp.ky gasp.kys gasp.ps gasp.log gasp.pg gasp.toc \
+ gasp.tp gasp.tps gasp.vr gasp.vrs gasp.op gasp.tr gasp.cv \
+ gasp.cn
+
+clean-aminfo:
+
+distclean-aminfo:
+
+maintainer-clean-aminfo:
+ for i in $(INFO_DEPS); do \
+ rm -f $$i; \
+ if test "`echo $$i-[0-9]*`" != "$$i-[0-9]*"; then \
+ rm -f $$i-[0-9]*; \
+ fi; \
+ done
+clean-info: mostlyclean-aminfo
+
+install-man1:
+ $(mkinstalldirs) $(DESTDIR)$(man1dir)
+ @list='$(man1_MANS)'; \
+ l2='$(man_MANS)'; for i in $$l2; do \
+ case "$$i" in \
+ *.1*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+ else file=$$i; fi; \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \
+ $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \
+ done
+
+uninstall-man1:
+ @list='$(man1_MANS)'; \
+ l2='$(man_MANS)'; for i in $$l2; do \
+ case "$$i" in \
+ *.1*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \
+ rm -f $(DESTDIR)$(man1dir)/$$inst; \
+ done
+install-man: $(MANS)
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-man1
+uninstall-man:
+ @$(NORMAL_UNINSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) uninstall-man1
+tags: TAGS
+TAGS:
+
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = doc
+
+distdir: $(DISTFILES)
+ @for file in $(DISTFILES); do \
+ if test -f $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ cp -pr $$/$$file $(distdir)/$$file; \
+ else \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+ $(MAKE) $(AM_MAKEFLAGS) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-info
+info-am: $(INFO_DEPS)
+info: info-am
+dvi-am: $(DVIS)
+dvi: dvi-am
+check-am:
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-info-am:
+install-info: install-info-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am: install-man
+install-data: install-data-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-man
+uninstall: uninstall-am
+all-am: Makefile $(MANS)
+all-redirect: all-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(mandir)/man1
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+mostlyclean-am: mostlyclean-aminfo mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am: clean-aminfo clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am: distclean-aminfo distclean-generic clean-am
+ -rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am: maintainer-clean-aminfo maintainer-clean-generic \
+ distclean-am
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: install-info-am uninstall-info mostlyclean-aminfo \
+distclean-aminfo clean-aminfo maintainer-clean-aminfo install-man1 \
+uninstall-man1 install-man uninstall-man tags distdir info-am info \
+dvi-am dvi check check-am installcheck-am installcheck install-info-am \
+install-info install-exec-am install-exec install-data-am install-data \
+install-am install uninstall-am uninstall all-redirect all-am all \
+installdirs mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+asconfig.texi: $(CONFIG).texi
+ rm -f asconfig.texi
+ ln -s $(srcdir)/$(CONFIG).texi ./asconfig.texi >/dev/null 2>&1 \
+ || ln $(srcdir)/$(CONFIG).texi ./asconfig.texi >/dev/null 2>&1 \
+ || cp $(srcdir)/$(CONFIG).texi ./asconfig.texi
+
+gasver.texi: Makefile
+ rm -f $@
+ echo '@set VERSION $(VERSION)' > $@
+
+as.info: $(srcdir)/as.texinfo asconfig.texi gasver.texi $(CPU_DOCS)
+as.dvi: $(srcdir)/as.texinfo asconfig.texi gasver.texi $(CPU_DOCS)
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/gas/doc/all.texi b/gas/doc/all.texi
new file mode 100644
index 0000000000..9b90c5bada
--- /dev/null
+++ b/gas/doc/all.texi
@@ -0,0 +1,72 @@
+@c Copyright 1992, 1993 Free Software Foundation, Inc.
+@c This file is part of the documentation for the GAS manual
+
+@c Configuration settings for all-inclusive version of manual
+
+@c switches:------------------------------------------------------------
+@c Properties of the manual
+@c ========================
+@c Discuss all architectures?
+@set ALL-ARCH
+@c A generic form of manual (not tailored to specific target)?
+@set GENERIC
+@c Include text on assembler internals?
+@clear INTERNALS
+@c Many object formats supported in this config?
+@set MULTI-OBJ
+
+@c Object formats of interest
+@c ==========================
+@set AOUT
+@set BOUT
+@set COFF
+@set ELF
+@set SOM
+
+@c CPUs of interest
+@c ================
+@set A29K
+@set ARC
+@set ARM
+@set D10V
+@set D30V
+@set H8/300
+@set H8/500
+@set SH
+@set I80386
+@set I960
+@set MCORE
+@set MIPS
+@set M32R
+@set M680X0
+@set Z8000
+@set SPARC
+@set VAX
+@set VXWORKS
+@set HPPA
+@set V850
+
+@c Does this version of the assembler use the difference-table kluge?
+@set DIFF-TBL-KLUGE
+
+@c Do all machines described use IEEE floating point?
+@clear IEEEFLOAT
+
+@c Is a word 32 bits, or 16?
+@clear W32
+@set W16
+
+@c Do symbols have different characters than usual?
+@clear SPECIAL-SYMS
+
+@c strings:------------------------------------------------------------
+@c Name of the assembler:
+@set AS as
+@c Name of C compiler:
+@set GCC gcc
+@c Name of linker:
+@set LD ld
+@c Text for target machine (best not used in generic case; but just in case...)
+@set TARGET machine specific
+@c Name of object format NOT SET in generic version
+@clear OBJ-NAME
diff --git a/gas/doc/as.1 b/gas/doc/as.1
new file mode 100644
index 0000000000..adf28868ea
--- /dev/null
+++ b/gas/doc/as.1
@@ -0,0 +1,302 @@
+.\" Copyright (c) 1991, 1992, 1996, 1997, 1998 Free Software Foundation
+.\" See section COPYING for conditions for redistribution
+.TH as 1 "29 March 1996" "cygnus support" "GNU Development Tools"
+
+.SH NAME
+GNU as \- the portable GNU assembler.
+
+.SH SYNOPSIS
+.na
+.B as
+.RB "[\|" \-a "[\|" dhlns "\|]" \c
+\&\[\|\=\c
+.I file\c
+\&\|]\|]
+.RB "[\|" \-D "\|]"
+.RB "[\|" \-\-defsym\ SYM=VAL "\|]"
+.RB "[\|" \-f "\|]"
+.RB "[\|" \-\-gstabs "\|]"
+.RB "[\|" \-I
+.I path\c
+\&\|]
+.RB "[\|" \-K "\|]"
+.RB "[\|" \-L "\|]"
+.RB "[\|" \-M\ |\ \-\-mri "\|]"
+.RB "[\|" \-o
+.I objfile\c
+\&\|]
+.RB "[\|" \-R "\|]"
+.RB "[\|" \-\-traditional\-format "\|]"
+.RB "[\|" \-v "\|]"
+.RB "[\|" \-w "\|]"
+.RB "[\|" \-\^\- "\ |\ " \c
+.I files\c
+\&\|.\|.\|.\|]
+
+.I i960-only options:
+.br
+.RB "[\|" \-ACA "\||\|" \-ACA_A "\||\|" \-ACB\c
+.RB "\||\|" \-ACC "\||\|" \-AKA "\||\|" \-AKB\c
+.RB "\||\|" \-AKC "\||\|" \-AMC "\|]"
+.RB "[\|" \-b "\|]"
+.RB "[\|" \-no-relax "\|]"
+
+.I m680x0-only options:
+.br
+.RB "[\|" \-l "\|]"
+.RB "[\|" \-mc68000 "\||\|" \-mc68010 "\||\|" \-mc68020 "\|]"
+.ad b
+
+.SH DESCRIPTION
+GNU \c
+.B as\c
+\& is really a family of assemblers.
+If you use (or have used) the GNU assembler on one architecture, you
+should find a fairly similar environment when you use it on another
+architecture. Each version has much in common with the others,
+including object file formats, most assembler directives (often called
+\c
+.I pseudo-ops)\c
+\& and assembler syntax.
+
+For information on the syntax and pseudo-ops used by GNU \c
+.B as\c
+\&, see `\|\c
+.B as\c
+\|' entry in \c
+.B info \c
+(or the manual \c
+.I
+.I
+Using as: The GNU Assembler\c
+\&).
+
+\c
+.B as\c
+\& is primarily intended to assemble the output of the GNU C
+compiler \c
+.B gcc\c
+\& for use by the linker \c
+.B ld\c
+\&. Nevertheless,
+we've tried to make \c
+.B as\c
+\& assemble correctly everything that the native
+assembler would.
+This doesn't mean \c
+.B as\c
+\& always uses the same syntax as another
+assembler for the same architecture; for example, we know of several
+incompatible versions of 680x0 assembly language syntax.
+
+Each time you run \c
+.B as\c
+\& it assembles exactly one source
+program. The source program is made up of one or more files.
+(The standard input is also a file.)
+
+If \c
+.B as\c
+\& is given no file names it attempts to read one input file
+from the \c
+.B as\c
+\& standard input, which is normally your terminal. You
+may have to type \c
+.B ctl-D\c
+\& to tell \c
+.B as\c
+\& there is no more program
+to assemble. Use `\|\c
+.B \-\^\-\c
+\|' if you need to explicitly name the standard input file
+in your command line.
+
+.B as\c
+\& may write warnings and error messages to the standard error
+file (usually your terminal). This should not happen when \c
+.B as\c
+\& is
+run automatically by a compiler. Warnings report an assumption made so
+that \c
+.B as\c
+\& could keep assembling a flawed program; errors report a
+grave problem that stops the assembly.
+
+.SH OPTIONS
+.TP
+.BR \-a
+Turn on assembly listings. There are various suboptions.
+.B d
+omits debugging directives.
+.B h
+includes the high level source code; this is only available if the
+source file can be found, and the code was compiled with
+.B \-g.
+.B l
+includes an assembly listing.
+.B n
+omits forms processing.
+.B s
+includes a symbol listing.
+.B =
+.I file
+sets the listing file name; this must be the last suboption.
+The default suboptions are
+.B hls.
+.TP
+.B \-D
+This option is accepted only for script compatibility with calls to
+other assemblers; it has no effect on \c
+.B as\c
+\&.
+.TP
+.B \-\-defsym SYM=VALUE
+Define the symbol SYM to be VALUE before assembling the input file.
+VALUE must be an integer constant. As in C, a leading 0x indicates a
+hexadecimal value, and a leading 0 indicates an octal value.
+.TP
+.B \-f
+``fast''--skip preprocessing (assume source is compiler output).
+.TP
+.BI "\-I\ " path
+Add
+.I path
+to the search list for
+.B .include
+directives.
+.TP
+.B \-\-gstabs
+Generate stabs debugging information for each assembler line. This
+may help debugging assembler code, if the debugger can handle it.
+.TP
+.B \-K
+Issue warnings when difference tables altered for long displacements.
+.TP
+.B \-L
+Keep (in symbol table) local symbols, starting with `\|\c
+.B L\c
+\|'
+.TP
+.B \-M, \-\-mri
+Assemble in MRI compatibility mode.
+.TP
+.BI "\-o\ " objfile
+Name the object-file output from \c
+.B as
+.TP
+.B \-R
+Fold data section into text section
+.TP
+.B \-\-traditional\-format
+Use same format as native assembler, when possible.
+.TP
+.B \-v
+Announce \c
+.B as\c
+\& version
+.TP
+.B \-W
+Suppress warning messages
+.TP
+.IR "\-\^\-" "\ |\ " "files\|.\|.\|."
+Source files to assemble, or standard input (\c
+.BR "\-\^\-" ")"
+.TP
+.BI \-A var
+.I
+(When configured for Intel 960.)
+Specify which variant of the 960 architecture is the target.
+.TP
+.B \-b
+.I
+(When configured for Intel 960.)
+Add code to collect statistics about branches taken.
+.TP
+.B \-no-relax
+.I
+(When configured for Intel 960.)
+Do not alter compare-and-branch instructions for long displacements;
+error if necessary.
+.TP
+.B \-l
+.I
+(When configured for Motorola 68000).
+.br
+Shorten references to undefined symbols, to one word instead of two.
+.TP
+.BR "\-mc68000" "\||\|" "\-mc68010" "\||\|" "\-mc68020"
+.I
+(When configured for Motorola 68000).
+.br
+Specify what processor in the 68000 family is the target (default 68020)
+
+.PP
+Options may be in any order, and may be
+before, after, or between file names. The order of file names is
+significant.
+
+`\|\c
+.B \-\^\-\c
+\|' (two hyphens) by itself names the standard input file
+explicitly, as one of the files for \c
+.B as\c
+\& to assemble.
+
+Except for `\|\c
+.B \-\^\-\c
+\|' any command line argument that begins with a
+hyphen (`\|\c
+.B \-\c
+\|') is an option. Each option changes the behavior of
+\c
+.B as\c
+\&. No option changes the way another option works. An
+option is a `\|\c
+.B \-\c
+\|' followed by one or more letters; the case of
+the letter is important. All options are optional.
+
+The `\|\c
+.B \-o\c
+\|' option expects exactly one file name to follow. The file
+name may either immediately follow the option's letter (compatible
+with older assemblers) or it may be the next command argument (GNU
+standard).
+
+These two command lines are equivalent:
+.br
+.B
+as\ \ \-o\ \ my\-object\-file.o\ \ mumble.s
+.br
+.B
+as\ \ \-omy\-object\-file.o\ \ mumble.s
+
+.SH "SEE ALSO"
+.RB "`\|" as "\|'"
+entry in
+.B
+info\c
+\&;
+.I
+Using as: The GNU Assembler\c
+\&;
+.BR gcc "(" 1 "),"
+.BR ld "(" 1 ")."
+
+.SH COPYING
+Copyright (c) 1991, 1992 Free Software Foundation, Inc.
+.PP
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+.PP
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+.PP
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo
new file mode 100644
index 0000000000..afe362a7fb
--- /dev/null
+++ b/gas/doc/as.texinfo
@@ -0,0 +1,5322 @@
+\input texinfo @c -*-Texinfo-*-
+@c Copyright (c) 1991, 92, 93, 94, 95, 96, 97, 1998
+@c Free Software Foundation, Inc.
+@c UPDATE!! On future updates--
+@c (1) check for new machine-dep cmdline options in
+@c md_parse_option definitions in config/tc-*.c
+@c (2) for platform-specific directives, examine md_pseudo_op
+@c in config/tc-*.c
+@c (3) for object-format specific directives, examine obj_pseudo_op
+@c in config/obj-*.c
+@c (4) portable directives in potable[] in read.c
+@c %**start of header
+@setfilename as.info
+@c ---config---
+@c defaults, config file may override:
+@set have-stabs
+@c ---
+@include asconfig.texi
+@include gasver.texi
+@c ---
+@c common OR combinations of conditions
+@ifset AOUT
+@set aout-bout
+@end ifset
+@ifset ARM/Thumb
+@set ARM
+@end ifset
+@ifset BOUT
+@set aout-bout
+@end ifset
+@ifset H8/300
+@set H8
+@end ifset
+@ifset H8/500
+@set H8
+@end ifset
+@ifset SH
+@set H8
+@end ifset
+@ifset HPPA
+@set abnormal-separator
+@end ifset
+@c ------------
+@ifset GENERIC
+@settitle Using @value{AS}
+@end ifset
+@ifclear GENERIC
+@settitle Using @value{AS} (@value{TARGET})
+@end ifclear
+@setchapternewpage odd
+@c %**end of header
+
+@c @smallbook
+@c @set SMALL
+@c WARE! Some of the machine-dependent sections contain tables of machine
+@c instructions. Except in multi-column format, these tables look silly.
+@c Unfortunately, Texinfo doesn't have a general-purpose multi-col format, so
+@c the multi-col format is faked within @example sections.
+@c
+@c Again unfortunately, the natural size that fits on a page, for these tables,
+@c is different depending on whether or not smallbook is turned on.
+@c This matters, because of order: text flow switches columns at each page
+@c break.
+@c
+@c The format faked in this source works reasonably well for smallbook,
+@c not well for the default large-page format. This manual expects that if you
+@c turn on @smallbook, you will also uncomment the "@set SMALL" to enable the
+@c tables in question. You can turn on one without the other at your
+@c discretion, of course.
+@ifinfo
+@set SMALL
+@c the insn tables look just as silly in info files regardless of smallbook,
+@c might as well show 'em anyways.
+@end ifinfo
+
+@ifinfo
+@format
+START-INFO-DIR-ENTRY
+* As: (as). The GNU assembler.
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+
+@finalout
+@syncodeindex ky cp
+
+@ifinfo
+This file documents the GNU Assembler "@value{AS}".
+
+Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this manual
+under the conditions for verbatim copying, provided that the entire resulting
+derived work is distributed under the terms of a permission notice identical to
+this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end ifinfo
+
+@titlepage
+@title Using @value{AS}
+@subtitle The @sc{gnu} Assembler
+@ifclear GENERIC
+@subtitle for the @value{TARGET} family
+@end ifclear
+@sp 1
+@subtitle Version @value{VERSION}
+@sp 1
+@sp 13
+The Free Software Foundation Inc. thanks The Nice Computer
+Company of Australia for loaning Dean Elsner to write the
+first (Vax) version of @code{as} for Project @sc{gnu}.
+The proprietors, management and staff of TNCCA thank FSF for
+distracting the boss while they got some work
+done.
+@sp 3
+@author Dean Elsner, Jay Fenlason & friends
+@page
+@tex
+{\parskip=0pt
+\hfill {\it Using {\tt @value{AS}}}\par
+\hfill Edited by Cygnus Support\par
+}
+%"boxit" macro for figures:
+%Modified from Knuth's ``boxit'' macro from TeXbook (answer to exercise 21.3)
+\gdef\boxit#1#2{\vbox{\hrule\hbox{\vrule\kern3pt
+ \vbox{\parindent=0pt\parskip=0pt\hsize=#1\kern3pt\strut\hfil
+#2\hfil\strut\kern3pt}\kern3pt\vrule}\hrule}}%box with visible outline
+\gdef\ibox#1#2{\hbox to #1{#2\hfil}\kern8pt}% invisible box
+@end tex
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1991, 92, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this manual
+under the conditions for verbatim copying, provided that the entire resulting
+derived work is distributed under the terms of a permission notice identical to
+this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end titlepage
+
+@ifinfo
+@node Top
+@top Using @value{AS}
+
+This file is a user guide to the @sc{gnu} assembler @code{@value{AS}} version
+@value{VERSION}.
+@ifclear GENERIC
+This version of the file describes @code{@value{AS}} configured to generate
+code for @value{TARGET} architectures.
+@end ifclear
+@menu
+* Overview:: Overview
+* Invoking:: Command-Line Options
+* Syntax:: Syntax
+* Sections:: Sections and Relocation
+* Symbols:: Symbols
+* Expressions:: Expressions
+* Pseudo Ops:: Assembler Directives
+* Machine Dependencies:: Machine Dependent Features
+* Reporting Bugs:: Reporting Bugs
+* Acknowledgements:: Who Did What
+* Index:: Index
+@end menu
+@end ifinfo
+
+@node Overview
+@chapter Overview
+@iftex
+This manual is a user guide to the @sc{gnu} assembler @code{@value{AS}}.
+@ifclear GENERIC
+This version of the manual describes @code{@value{AS}} configured to generate
+code for @value{TARGET} architectures.
+@end ifclear
+@end iftex
+
+@cindex invocation summary
+@cindex option summary
+@cindex summary of options
+Here is a brief summary of how to invoke @code{@value{AS}}. For details,
+@pxref{Invoking,,Comand-Line Options}.
+
+@c We don't use deffn and friends for the following because they seem
+@c to be limited to one line for the header.
+@smallexample
+@value{AS} [ -a[cdhlns][=file] ] [ -D ] [ --defsym @var{sym}=@var{val} ]
+ [ -f ] [ --gstabs ] [ --help ] [ -I @var{dir} ] [ -J ] [ -K ] [ -L ]
+ [ --keep-locals ] [ -o @var{objfile} ] [ -R ] [ --statistics ] [ -v ]
+ [ -version ] [ --version ] [ -W ] [ -w ] [ -x ] [ -Z ]
+@ifset A29K
+@c am29k has no machine-dependent assembler options
+@end ifset
+@ifset ARC
+ [ -mbig-endian | -mlittle-endian ]
+@end ifset
+@ifset ARM
+ [ -m[arm]1 | -m[arm]2 | -m[arm]250 | -m[arm]3 | -m[arm]6 | -m[arm]7[t][[d]m[i]] ]
+ [ -m[arm]v2 | -m[arm]v2a | -m[arm]v3 | -m[arm]v3m | -m[arm]v4 | -m[arm]v4t ]
+ [ -mthumb | -mall ]
+ [ -mfpa10 | -mfpa11 | -mfpe-old | -mno-fpu ]
+ [ -EB | -EL ]
+ [ -mapcs-32 | -mapcs-26 ]
+@end ifset
+@ifset D10V
+ [ -O ]
+@end ifset
+@ifset D30V
+ [ -O | -n | -N ]
+@end ifset
+@ifset H8
+@c Hitachi family chips have no machine-dependent assembler options
+@end ifset
+@ifset HPPA
+@c HPPA has no machine-dependent assembler options (yet).
+@end ifset
+@ifset SPARC
+@c The order here is important. See c-sparc.texi.
+ [ -Av6 | -Av7 | -Av8 | -Asparclet | -Asparclite
+ -Av8plus | -Av8plusa | -Av9 | -Av9a ]
+ [ -xarch=v8plus | -xarch=v8plusa ] [ -bump ] [ -32 | -64 ]
+@end ifset
+@ifset Z8000
+@c Z8000 has no machine-dependent assembler options
+@end ifset
+@ifset I960
+@c see md_parse_option in tc-i960.c
+ [ -ACA | -ACA_A | -ACB | -ACC | -AKA | -AKB | -AKC | -AMC ]
+ [ -b ] [ -no-relax ]
+@end ifset
+@ifset M680X0
+ [ -l ] [ -m68000 | -m68010 | -m68020 | ... ]
+@end ifset
+@ifset MCORE
+ [ -jsri2bsr ] [ -sifilter ] [ -relax ]
+@end ifset
+@ifset MIPS
+ [ -nocpp ] [ -EL ] [ -EB ] [ -G @var{num} ] [ -mcpu=@var{CPU} ]
+ [ -mips1 ] [ -mips2 ] [ -mips3 ] [ -m4650 ] [ -no-m4650 ]
+ [ --trap ] [ --break ]
+ [ --emulation=@var{name} ]
+@end ifset
+ [ -- | @var{files} @dots{} ]
+@end smallexample
+
+@table @code
+@item -a[cdhlmns]
+Turn on listings, in any of a variety of ways:
+
+@table @code
+@item -ac
+omit false conditionals
+
+@item -ad
+omit debugging directives
+
+@item -ah
+include high-level source
+
+@item -al
+include assembly
+
+@item -am
+include macro expansions
+
+@item -an
+omit forms processing
+
+@item -as
+include symbols
+
+@item =file
+set the name of the listing file
+@end table
+
+You may combine these options; for example, use @samp{-aln} for assembly
+listing without forms processing. The @samp{=file} option, if used, must be
+the last one. By itself, @samp{-a} defaults to @samp{-ahls}.
+
+@item -D
+Ignored. This option is accepted for script compatibility with calls to
+other assemblers.
+
+@item --defsym @var{sym}=@var{value}
+Define the symbol @var{sym} to be @var{value} before assembling the input file.
+@var{value} must be an integer constant. As in C, a leading @samp{0x}
+indicates a hexadecimal value, and a leading @samp{0} indicates an octal value.
+
+@item -f
+``fast''---skip whitespace and comment preprocessing (assume source is
+compiler output).
+
+@item --gstabs
+Generate stabs debugging information for each assembler line. This
+may help debugging assembler code, if the debugger can handle it.
+
+@item --help
+Print a summary of the command line options and exit.
+
+@item -I @var{dir}
+Add directory @var{dir} to the search list for @code{.include} directives.
+
+@item -J
+Don't warn about signed overflow.
+
+@item -K
+@ifclear DIFF-TBL-KLUGE
+This option is accepted but has no effect on the @value{TARGET} family.
+@end ifclear
+@ifset DIFF-TBL-KLUGE
+Issue warnings when difference tables altered for long displacements.
+@end ifset
+
+@item -L
+@itemx --keep-locals
+Keep (in the symbol table) local symbols. On traditional a.out systems
+these start with @samp{L}, but different systems have different local
+label prefixes.
+
+@item -o @var{objfile}
+Name the object-file output from @code{@value{AS}} @var{objfile}.
+
+@item -R
+Fold the data section into the text section.
+
+@item --statistics
+Print the maximum space (in bytes) and total time (in seconds) used by
+assembly.
+
+@item --strip-local-absolute
+Remove local absolute symbols from the outgoing symbol table.
+
+@item -v
+@itemx -version
+Print the @code{as} version.
+
+@item --version
+Print the @code{as} version and exit.
+
+@item -W
+Suppress warning messages.
+
+@item -w
+Ignored.
+
+@item -x
+Ignored.
+
+@item -Z
+Generate an object file even after errors.
+
+@item -- | @var{files} @dots{}
+Standard input, or source files to assemble.
+
+@end table
+
+@ifset ARC
+The following options are available when @value{AS} is configured for
+an ARC processor.
+
+@table @code
+
+@cindex ARC endianness
+@cindex endianness, ARC
+@cindex big endian output, ARC
+@item -mbig-endian
+Generate ``big endian'' format output.
+
+@cindex little endian output, ARC
+@item -mlittle-endian
+Generate ``little endian'' format output.
+
+@end table
+@end ifset
+
+@ifset ARM
+The following options are available when @value{AS} is configured for the ARM
+processor family.
+
+@table @code
+@item -m[arm]1 | -m[arm]2 | -m[arm]250 | -m[arm]3 | -m[arm]6 | -m[arm]7[t][[d]m] | -m[arm]v2 | -m[arm]v2a | -m[arm]v3 | -m[arm]v3m | -m[arm]v4 | -m[arm]v4t
+Specify which variant of the ARM architecture is the target.
+@item -mthumb | -mall
+Enable or disable Thumb only instruction decoding.
+@item -mfpa10 | -mfpa11 | -mfpe-old | -mno-fpu
+Select which Floating Point architcture is the target.
+@item -mapcs-32 | -mapcs-26
+Select which procedure calling convention is in use.
+@item -EB | -EL
+Select either big-endian (-EB) or little-endian (-EL) output.
+@end table
+@end ifset
+
+@ifset D10V
+The following options are available when @value{AS} is configured for
+a D10V processor.
+@table @code
+@cindex D10V optimization
+@cindex optimization, D10V
+@item -O
+Optimize output by parallelizing instructions.
+@end table
+@end ifset
+
+@ifset D30V
+The following options are available when @value{AS} is configured for a D30V
+processor.
+@table @code
+@cindex D30V optimization
+@cindex optimization, D30V
+@item -O
+Optimize output by parallelizing instructions.
+
+@cindex D30V nops
+@item -n
+Warn when nops are generated.
+
+@cindex D30V nops after 32-bit multiply
+@item -N
+Warn when a nop after a 32-bit multiply instruction is generated.
+@end table
+@end ifset
+
+@ifset I960
+The following options are available when @value{AS} is configured for the
+Intel 80960 processor.
+
+@table @code
+@item -ACA | -ACA_A | -ACB | -ACC | -AKA | -AKB | -AKC | -AMC
+Specify which variant of the 960 architecture is the target.
+
+@item -b
+Add code to collect statistics about branches taken.
+
+@item -no-relax
+Do not alter compare-and-branch instructions for long displacements;
+error if necessary.
+
+@end table
+@end ifset
+
+
+@ifset M680X0
+The following options are available when @value{AS} is configured for the
+Motorola 68000 series.
+
+@table @code
+
+@item -l
+Shorten references to undefined symbols, to one word instead of two.
+
+@item -m68000 | -m68008 | -m68010 | -m68020 | -m68030 | -m68040 | -m68060
+@itemx | -m68302 | -m68331 | -m68332 | -m68333 | -m68340 | -mcpu32 | -m5200
+Specify what processor in the 68000 family is the target. The default
+is normally the 68020, but this can be changed at configuration time.
+
+@item -m68881 | -m68882 | -mno-68881 | -mno-68882
+The target machine does (or does not) have a floating-point coprocessor.
+The default is to assume a coprocessor for 68020, 68030, and cpu32. Although
+the basic 68000 is not compatible with the 68881, a combination of the
+two can be specified, since it's possible to do emulation of the
+coprocessor instructions with the main processor.
+
+@item -m68851 | -mno-68851
+The target machine does (or does not) have a memory-management
+unit coprocessor. The default is to assume an MMU for 68020 and up.
+
+@end table
+@end ifset
+
+@ifset SPARC
+The following options are available when @code{@value{AS}} is configured
+for the SPARC architecture:
+
+@table @code
+@item -Av6 | -Av7 | -Av8 | -Asparclet | -Asparclite
+@itemx -Av8plus | -Av8plusa | -Av9 | -Av9a
+Explicitly select a variant of the SPARC architecture.
+
+@samp{-Av8plus} and @samp{-Av8plusa} select a 32 bit environment.
+@samp{-Av9} and @samp{-Av9a} select a 64 bit environment.
+
+@samp{-Av8plusa} and @samp{-Av9a} enable the SPARC V9 instruction set with
+UltraSPARC extensions.
+
+@item -xarch=v8plus | -xarch=v8plusa
+For compatibility with the Solaris v9 assembler. These options are
+equivalent to -Av8plus and -Av8plusa, respectively.
+
+@item -bump
+Warn when the assembler switches to another architecture.
+@end table
+@end ifset
+
+@ifset MIPS
+The following options are available when @value{AS} is configured for
+a MIPS processor.
+
+@table @code
+@item -G @var{num}
+This option sets the largest size of an object that can be referenced
+implicitly with the @code{gp} register. It is only accepted for targets that
+use ECOFF format, such as a DECstation running Ultrix. The default value is 8.
+
+@cindex MIPS endianness
+@cindex endianness, MIPS
+@cindex big endian output, MIPS
+@item -EB
+Generate ``big endian'' format output.
+
+@cindex little endian output, MIPS
+@item -EL
+Generate ``little endian'' format output.
+
+@cindex MIPS ISA
+@item -mips1
+@itemx -mips2
+@itemx -mips3
+Generate code for a particular MIPS Instruction Set Architecture level.
+@samp{-mips1} corresponds to the @sc{r2000} and @sc{r3000} processors,
+@samp{-mips2} to the @sc{r6000} processor, and @samp{-mips3} to the @sc{r4000}
+processor.
+
+@item -m4650
+@itemx -no-m4650
+Generate code for the MIPS @sc{r4650} chip. This tells the assembler to accept
+the @samp{mad} and @samp{madu} instruction, and to not schedule @samp{nop}
+instructions around accesses to the @samp{HI} and @samp{LO} registers.
+@samp{-no-m4650} turns off this option.
+
+@item -mcpu=@var{CPU}
+Generate code for a particular MIPS cpu. This has little effect on the
+assembler, but it is passed by @code{@value{GCC}}.
+
+@cindex emulation
+@item --emulation=@var{name}
+This option causes @code{@value{AS}} to emulate @code{@value{AS}} configured
+for some other target, in all respects, including output format (choosing
+between ELF and ECOFF only), handling of pseudo-opcodes which may generate
+debugging information or store symbol table information, and default
+endianness. The available configuration names are: @samp{mipsecoff},
+@samp{mipself}, @samp{mipslecoff}, @samp{mipsbecoff}, @samp{mipslelf},
+@samp{mipsbelf}. The first two do not alter the default endianness from that
+of the primary target for which the assembler was configured; the others change
+the default to little- or big-endian as indicated by the @samp{b} or @samp{l}
+in the name. Using @samp{-EB} or @samp{-EL} will override the endianness
+selection in any case.
+
+This option is currently supported only when the primary target
+@code{@value{AS}} is configured for is a MIPS ELF or ECOFF target.
+Furthermore, the primary target or others specified with
+@samp{--enable-targets=@dots{}} at configuration time must include support for
+the other format, if both are to be available. For example, the Irix 5
+configuration includes support for both.
+
+Eventually, this option will support more configurations, with more
+fine-grained control over the assembler's behavior, and will be supported for
+more processors.
+
+@item -nocpp
+@code{@value{AS}} ignores this option. It is accepted for compatibility with
+the native tools.
+
+@need 900
+@item --trap
+@itemx --no-trap
+@itemx --break
+@itemx --no-break
+Control how to deal with multiplication overflow and division by zero.
+@samp{--trap} or @samp{--no-break} (which are synonyms) take a trap exception
+(and only work for Instruction Set Architecture level 2 and higher);
+@samp{--break} or @samp{--no-trap} (also synonyms, and the default) take a
+break exception.
+@end table
+@end ifset
+
+@ifset MCORE
+The following options are available when @value{AS} is configured for
+an MCore processor.
+
+@table @code
+@item -jsri2bsr
+@itemx -nojsri2bsr
+Enable or disable the JSRI to BSR transformation. By default this is enabled.
+The command line option @samp{-nojsri2bsr} can be used to disable it.
+
+@item -sifilter
+@itemx -nosifilter
+Enable or disable the silicon filter behaviour. By default this is disabled.
+The default can be overidden by the @samp{-sifilter} command line option.
+
+@item -relax
+Alter jump instructions for long displacements.
+
+
+@end table
+@end ifset
+
+@menu
+* Manual:: Structure of this Manual
+* GNU Assembler:: The GNU Assembler
+* Object Formats:: Object File Formats
+* Command Line:: Command Line
+* Input Files:: Input Files
+* Object:: Output (Object) File
+* Errors:: Error and Warning Messages
+@end menu
+
+@node Manual
+@section Structure of this Manual
+
+@cindex manual, structure and purpose
+This manual is intended to describe what you need to know to use
+@sc{gnu} @code{@value{AS}}. We cover the syntax expected in source files, including
+notation for symbols, constants, and expressions; the directives that
+@code{@value{AS}} understands; and of course how to invoke @code{@value{AS}}.
+
+@ifclear GENERIC
+We also cover special features in the @value{TARGET}
+configuration of @code{@value{AS}}, including assembler directives.
+@end ifclear
+@ifset GENERIC
+This manual also describes some of the machine-dependent features of
+various flavors of the assembler.
+@end ifset
+
+@cindex machine instructions (not covered)
+On the other hand, this manual is @emph{not} intended as an introduction
+to programming in assembly language---let alone programming in general!
+In a similar vein, we make no attempt to introduce the machine
+architecture; we do @emph{not} describe the instruction set, standard
+mnemonics, registers or addressing modes that are standard to a
+particular architecture.
+@ifset GENERIC
+You may want to consult the manufacturer's
+machine architecture manual for this information.
+@end ifset
+@ifclear GENERIC
+@ifset H8/300
+For information on the H8/300 machine instruction set, see @cite{H8/300
+Series Programming Manual} (Hitachi ADE--602--025). For the H8/300H,
+see @cite{H8/300H Series Programming Manual} (Hitachi).
+@end ifset
+@ifset H8/500
+For information on the H8/500 machine instruction set, see @cite{H8/500
+Series Programming Manual} (Hitachi M21T001).
+@end ifset
+@ifset SH
+For information on the Hitachi SH machine instruction set, see
+@cite{SH-Microcomputer User's Manual} (Hitachi Micro Systems, Inc.).
+@end ifset
+@ifset Z8000
+For information on the Z8000 machine instruction set, see @cite{Z8000 CPU Technical Manual}
+@end ifset
+@end ifclear
+
+@c I think this is premature---doc@cygnus.com, 17jan1991
+@ignore
+Throughout this manual, we assume that you are running @dfn{GNU},
+the portable operating system from the @dfn{Free Software
+Foundation, Inc.}. This restricts our attention to certain kinds of
+computer (in particular, the kinds of computers that @sc{gnu} can run on);
+once this assumption is granted examples and definitions need less
+qualification.
+
+@code{@value{AS}} is part of a team of programs that turn a high-level
+human-readable series of instructions into a low-level
+computer-readable series of instructions. Different versions of
+@code{@value{AS}} are used for different kinds of computer.
+@end ignore
+
+@c There used to be a section "Terminology" here, which defined
+@c "contents", "byte", "word", and "long". Defining "word" to any
+@c particular size is confusing when the .word directive may generate 16
+@c bits on one machine and 32 bits on another; in general, for the user
+@c version of this manual, none of these terms seem essential to define.
+@c They were used very little even in the former draft of the manual;
+@c this draft makes an effort to avoid them (except in names of
+@c directives).
+
+@node GNU Assembler
+@section The GNU Assembler
+
+@sc{gnu} @code{as} is really a family of assemblers.
+@ifclear GENERIC
+This manual describes @code{@value{AS}}, a member of that family which is
+configured for the @value{TARGET} architectures.
+@end ifclear
+If you use (or have used) the @sc{gnu} assembler on one architecture, you
+should find a fairly similar environment when you use it on another
+architecture. Each version has much in common with the others,
+including object file formats, most assembler directives (often called
+@dfn{pseudo-ops}) and assembler syntax.@refill
+
+@cindex purpose of @sc{gnu} assembler
+@code{@value{AS}} is primarily intended to assemble the output of the
+@sc{gnu} C compiler @code{@value{GCC}} for use by the linker
+@code{@value{LD}}. Nevertheless, we've tried to make @code{@value{AS}}
+assemble correctly everything that other assemblers for the same
+machine would assemble.
+@ifset VAX
+Any exceptions are documented explicitly (@pxref{Machine Dependencies}).
+@end ifset
+@ifset M680X0
+@c This remark should appear in generic version of manual; assumption
+@c here is that generic version sets M680x0.
+This doesn't mean @code{@value{AS}} always uses the same syntax as another
+assembler for the same architecture; for example, we know of several
+incompatible versions of 680x0 assembly language syntax.
+@end ifset
+
+Unlike older assemblers, @code{@value{AS}} is designed to assemble a source
+program in one pass of the source file. This has a subtle impact on the
+@kbd{.org} directive (@pxref{Org,,@code{.org}}).
+
+@node Object Formats
+@section Object File Formats
+
+@cindex object file format
+The @sc{gnu} assembler can be configured to produce several alternative
+object file formats. For the most part, this does not affect how you
+write assembly language programs; but directives for debugging symbols
+are typically different in different file formats. @xref{Symbol
+Attributes,,Symbol Attributes}.
+@ifclear GENERIC
+@ifclear MULTI-OBJ
+On the @value{TARGET}, @code{@value{AS}} is configured to produce
+@value{OBJ-NAME} format object files.
+@end ifclear
+@c The following should exhaust all configs that set MULTI-OBJ, ideally
+@ifset A29K
+On the @value{TARGET}, @code{@value{AS}} can be configured to produce either
+@code{a.out} or COFF format object files.
+@end ifset
+@ifset I960
+On the @value{TARGET}, @code{@value{AS}} can be configured to produce either
+@code{b.out} or COFF format object files.
+@end ifset
+@ifset HPPA
+On the @value{TARGET}, @code{@value{AS}} can be configured to produce either
+SOM or ELF format object files.
+@end ifset
+@end ifclear
+
+@node Command Line
+@section Command Line
+
+@cindex command line conventions
+After the program name @code{@value{AS}}, the command line may contain
+options and file names. Options may appear in any order, and may be
+before, after, or between file names. The order of file names is
+significant.
+
+@cindex standard input, as input file
+@kindex --
+@file{--} (two hyphens) by itself names the standard input file
+explicitly, as one of the files for @code{@value{AS}} to assemble.
+
+@cindex options, command line
+Except for @samp{--} any command line argument that begins with a
+hyphen (@samp{-}) is an option. Each option changes the behavior of
+@code{@value{AS}}. No option changes the way another option works. An
+option is a @samp{-} followed by one or more letters; the case of
+the letter is important. All options are optional.
+
+Some options expect exactly one file name to follow them. The file
+name may either immediately follow the option's letter (compatible
+with older assemblers) or it may be the next command argument (@sc{gnu}
+standard). These two command lines are equivalent:
+
+@smallexample
+@value{AS} -o my-object-file.o mumble.s
+@value{AS} -omy-object-file.o mumble.s
+@end smallexample
+
+@node Input Files
+@section Input Files
+
+@cindex input
+@cindex source program
+@cindex files, input
+We use the phrase @dfn{source program}, abbreviated @dfn{source}, to
+describe the program input to one run of @code{@value{AS}}. The program may
+be in one or more files; how the source is partitioned into files
+doesn't change the meaning of the source.
+
+@c I added "con" prefix to "catenation" just to prove I can overcome my
+@c APL training... doc@cygnus.com
+The source program is a concatenation of the text in all the files, in the
+order specified.
+
+Each time you run @code{@value{AS}} it assembles exactly one source
+program. The source program is made up of one or more files.
+(The standard input is also a file.)
+
+You give @code{@value{AS}} a command line that has zero or more input file
+names. The input files are read (from left file name to right). A
+command line argument (in any position) that has no special meaning
+is taken to be an input file name.
+
+If you give @code{@value{AS}} no file names it attempts to read one input file
+from the @code{@value{AS}} standard input, which is normally your terminal. You
+may have to type @key{ctl-D} to tell @code{@value{AS}} there is no more program
+to assemble.
+
+Use @samp{--} if you need to explicitly name the standard input file
+in your command line.
+
+If the source is empty, @code{@value{AS}} produces a small, empty object
+file.
+
+@subheading Filenames and Line-numbers
+
+@cindex input file linenumbers
+@cindex line numbers, in input files
+There are two ways of locating a line in the input file (or files) and
+either may be used in reporting error messages. One way refers to a line
+number in a physical file; the other refers to a line number in a
+``logical'' file. @xref{Errors, ,Error and Warning Messages}.
+
+@dfn{Physical files} are those files named in the command line given
+to @code{@value{AS}}.
+
+@dfn{Logical files} are simply names declared explicitly by assembler
+directives; they bear no relation to physical files. Logical file names help
+error messages reflect the original source file, when @code{@value{AS}} source
+is itself synthesized from other files. @code{@value{AS}} understands the
+@samp{#} directives emitted by the @code{@value{GCC}} preprocessor. See also
+@ref{File,,@code{.file}}.
+
+@node Object
+@section Output (Object) File
+
+@cindex object file
+@cindex output file
+@kindex a.out
+@kindex .o
+Every time you run @code{@value{AS}} it produces an output file, which is
+your assembly language program translated into numbers. This file
+is the object file. Its default name is
+@ifclear BOUT
+@code{a.out}.
+@end ifclear
+@ifset BOUT
+@ifset GENERIC
+@code{a.out}, or
+@end ifset
+@code{b.out} when @code{@value{AS}} is configured for the Intel 80960.
+@end ifset
+You can give it another name by using the @code{-o} option. Conventionally,
+object file names end with @file{.o}. The default name is used for historical
+reasons: older assemblers were capable of assembling self-contained programs
+directly into a runnable program. (For some formats, this isn't currently
+possible, but it can be done for the @code{a.out} format.)
+
+@cindex linker
+@kindex ld
+The object file is meant for input to the linker @code{@value{LD}}. It contains
+assembled program code, information to help @code{@value{LD}} integrate
+the assembled program into a runnable file, and (optionally) symbolic
+information for the debugger.
+
+@c link above to some info file(s) like the description of a.out.
+@c don't forget to describe @sc{gnu} info as well as Unix lossage.
+
+@node Errors
+@section Error and Warning Messages
+
+@cindex error messsages
+@cindex warning messages
+@cindex messages from assembler
+@code{@value{AS}} may write warnings and error messages to the standard error
+file (usually your terminal). This should not happen when a compiler
+runs @code{@value{AS}} automatically. Warnings report an assumption made so
+that @code{@value{AS}} could keep assembling a flawed program; errors report a
+grave problem that stops the assembly.
+
+@cindex format of warning messages
+Warning messages have the format
+
+@smallexample
+file_name:@b{NNN}:Warning Message Text
+@end smallexample
+
+@noindent
+@cindex line numbers, in warnings/errors
+(where @b{NNN} is a line number). If a logical file name has been given
+(@pxref{File,,@code{.file}}) it is used for the filename, otherwise the name of
+the current input file is used. If a logical line number was given
+@ifset GENERIC
+(@pxref{Line,,@code{.line}})
+@end ifset
+@ifclear GENERIC
+@ifclear A29K
+(@pxref{Line,,@code{.line}})
+@end ifclear
+@ifset A29K
+(@pxref{Ln,,@code{.ln}})
+@end ifset
+@end ifclear
+then it is used to calculate the number printed,
+otherwise the actual line in the current source file is printed. The
+message text is intended to be self explanatory (in the grand Unix
+tradition).
+
+@cindex format of error messages
+Error messages have the format
+@smallexample
+file_name:@b{NNN}:FATAL:Error Message Text
+@end smallexample
+The file name and line number are derived as for warning
+messages. The actual message text may be rather less explanatory
+because many of them aren't supposed to happen.
+
+@node Invoking
+@chapter Command-Line Options
+
+@cindex options, all versions of assembler
+This chapter describes command-line options available in @emph{all}
+versions of the @sc{gnu} assembler; @pxref{Machine Dependencies}, for options specific
+@ifclear GENERIC
+to the @value{TARGET}.
+@end ifclear
+@ifset GENERIC
+to particular machine architectures.
+@end ifset
+
+If you are invoking @code{@value{AS}} via the @sc{gnu} C compiler (version 2),
+you can use the @samp{-Wa} option to pass arguments through to the assembler.
+The assembler arguments must be separated from each other (and the @samp{-Wa})
+by commas. For example:
+
+@smallexample
+gcc -c -g -O -Wa,-alh,-L file.c
+@end smallexample
+
+@noindent
+This passes two options to the assembler: @samp{-alh} (emit a listing to
+standard output with with high-level and assembly source) and @samp{-L} (retain
+local symbols in the symbol table).
+
+Usually you do not need to use this @samp{-Wa} mechanism, since many compiler
+command-line options are automatically passed to the assembler by the compiler.
+(You can call the @sc{gnu} compiler driver with the @samp{-v} option to see
+precisely what options it passes to each compilation pass, including the
+assembler.)
+
+@menu
+* a:: -a[cdhlns] enable listings
+* D:: -D for compatibility
+* f:: -f to work faster
+* I:: -I for .include search path
+@ifclear DIFF-TBL-KLUGE
+* K:: -K for compatibility
+@end ifclear
+@ifset DIFF-TBL-KLUGE
+* K:: -K for difference tables
+@end ifset
+
+* L:: -L to retain local labels
+* M:: -M or --mri to assemble in MRI compatibility mode
+* MD:: --MD for dependency tracking
+* o:: -o to name the object file
+* R:: -R to join data and text sections
+* statistics:: --statistics to see statistics about assembly
+* traditional-format:: --traditional-format for compatible output
+* v:: -v to announce version
+* W:: -W to suppress warnings
+* Z:: -Z to make object file even after errors
+@end menu
+
+@node a
+@section Enable Listings: @code{-a[cdhlns]}
+
+@kindex -a
+@kindex -ac
+@kindex -ad
+@kindex -ah
+@kindex -al
+@kindex -an
+@kindex -as
+@cindex listings, enabling
+@cindex assembly listings, enabling
+
+These options enable listing output from the assembler. By itself,
+@samp{-a} requests high-level, assembly, and symbols listing.
+You can use other letters to select specific options for the list:
+@samp{-ah} requests a high-level language listing,
+@samp{-al} requests an output-program assembly listing, and
+@samp{-as} requests a symbol table listing.
+High-level listings require that a compiler debugging option like
+@samp{-g} be used, and that assembly listings (@samp{-al}) be requested
+also.
+
+Use the @samp{-ac} option to omit false conditionals from a listing. Any lines
+which are not assembled because of a false @code{.if} (or @code{.ifdef}, or any
+other conditional), or a true @code{.if} followed by an @code{.else}, will be
+omitted from the listing.
+
+Use the @samp{-ad} option to omit debugging directives from the
+listing.
+
+Once you have specified one of these options, you can further control
+listing output and its appearance using the directives @code{.list},
+@code{.nolist}, @code{.psize}, @code{.eject}, @code{.title}, and
+@code{.sbttl}.
+The @samp{-an} option turns off all forms processing.
+If you do not request listing output with one of the @samp{-a} options, the
+listing-control directives have no effect.
+
+The letters after @samp{-a} may be combined into one option,
+@emph{e.g.}, @samp{-aln}.
+
+@node D
+@section @code{-D}
+
+@kindex -D
+This option has no effect whatsoever, but it is accepted to make it more
+likely that scripts written for other assemblers also work with
+@code{@value{AS}}.
+
+@node f
+@section Work Faster: @code{-f}
+
+@kindex -f
+@cindex trusted compiler
+@cindex faster processing (@code{-f})
+@samp{-f} should only be used when assembling programs written by a
+(trusted) compiler. @samp{-f} stops the assembler from doing whitespace
+and comment preprocessing on
+the input file(s) before assembling them. @xref{Preprocessing,
+,Preprocessing}.
+
+@quotation
+@emph{Warning:} if you use @samp{-f} when the files actually need to be
+preprocessed (if they contain comments, for example), @code{@value{AS}} does
+not work correctly.
+@end quotation
+
+@node I
+@section @code{.include} search path: @code{-I} @var{path}
+
+@kindex -I @var{path}
+@cindex paths for @code{.include}
+@cindex search path for @code{.include}
+@cindex @code{include} directive search path
+Use this option to add a @var{path} to the list of directories
+@code{@value{AS}} searches for files specified in @code{.include}
+directives (@pxref{Include,,@code{.include}}). You may use @code{-I} as
+many times as necessary to include a variety of paths. The current
+working directory is always searched first; after that, @code{@value{AS}}
+searches any @samp{-I} directories in the same order as they were
+specified (left to right) on the command line.
+
+@node K
+@section Difference Tables: @code{-K}
+
+@kindex -K
+@ifclear DIFF-TBL-KLUGE
+On the @value{TARGET} family, this option is allowed, but has no effect. It is
+permitted for compatibility with the @sc{gnu} assembler on other platforms,
+where it can be used to warn when the assembler alters the machine code
+generated for @samp{.word} directives in difference tables. The @value{TARGET}
+family does not have the addressing limitations that sometimes lead to this
+alteration on other platforms.
+@end ifclear
+
+@ifset DIFF-TBL-KLUGE
+@cindex difference tables, warning
+@cindex warning for altered difference tables
+@code{@value{AS}} sometimes alters the code emitted for directives of the form
+@samp{.word @var{sym1}-@var{sym2}}; @pxref{Word,,@code{.word}}.
+You can use the @samp{-K} option if you want a warning issued when this
+is done.
+@end ifset
+
+@node L
+@section Include Local Labels: @code{-L}
+
+@kindex -L
+@cindex local labels, retaining in output
+Labels beginning with @samp{L} (upper case only) are called @dfn{local
+labels}. @xref{Symbol Names}. Normally you do not see such labels when
+debugging, because they are intended for the use of programs (like
+compilers) that compose assembler programs, not for your notice.
+Normally both @code{@value{AS}} and @code{@value{LD}} discard such labels, so you do not
+normally debug with them.
+
+This option tells @code{@value{AS}} to retain those @samp{L@dots{}} symbols
+in the object file. Usually if you do this you also tell the linker
+@code{@value{LD}} to preserve symbols whose names begin with @samp{L}.
+
+By default, a local label is any label beginning with @samp{L}, but each
+target is allowed to redefine the local label prefix.
+@ifset HPPA
+On the HPPA local labels begin with @samp{L$}.
+@end ifset
+@ifset ARM
+@samp{;} for the ARM family;
+@end ifset
+
+@node M
+@section Assemble in MRI Compatibility Mode: @code{-M}
+
+@kindex -M
+@cindex MRI compatibility mode
+The @code{-M} or @code{--mri} option selects MRI compatibility mode. This
+changes the syntax and pseudo-op handling of @code{@value{AS}} to make it
+compatible with the @code{ASM68K} or the @code{ASM960} (depending upon the
+configured target) assembler from Microtec Research. The exact nature of the
+MRI syntax will not be documented here; see the MRI manuals for more
+information. Note in particular that the handling of macros and macro
+arguments is somewhat different. The purpose of this option is to permit
+assembling existing MRI assembler code using @code{@value{AS}}.
+
+The MRI compatibility is not complete. Certain operations of the MRI assembler
+depend upon its object file format, and can not be supported using other object
+file formats. Supporting these would require enhancing each object file format
+individually. These are:
+
+@itemize @bullet
+@item global symbols in common section
+
+The m68k MRI assembler supports common sections which are merged by the linker.
+Other object file formats do not support this. @code{@value{AS}} handles
+common sections by treating them as a single common symbol. It permits local
+symbols to be defined within a common section, but it can not support global
+symbols, since it has no way to describe them.
+
+@item complex relocations
+
+The MRI assemblers support relocations against a negated section address, and
+relocations which combine the start addresses of two or more sections. These
+are not support by other object file formats.
+
+@item @code{END} pseudo-op specifying start address
+
+The MRI @code{END} pseudo-op permits the specification of a start address.
+This is not supported by other object file formats. The start address may
+instead be specified using the @code{-e} option to the linker, or in a linker
+script.
+
+@item @code{IDNT}, @code{.ident} and @code{NAME} pseudo-ops
+
+The MRI @code{IDNT}, @code{.ident} and @code{NAME} pseudo-ops assign a module
+name to the output file. This is not supported by other object file formats.
+
+@item @code{ORG} pseudo-op
+
+The m68k MRI @code{ORG} pseudo-op begins an absolute section at a given
+address. This differs from the usual @code{@value{AS}} @code{.org} pseudo-op,
+which changes the location within the current section. Absolute sections are
+not supported by other object file formats. The address of a section may be
+assigned within a linker script.
+@end itemize
+
+There are some other features of the MRI assembler which are not supported by
+@code{@value{AS}}, typically either because they are difficult or because they
+seem of little consequence. Some of these may be supported in future releases.
+
+@itemize @bullet
+
+@item EBCDIC strings
+
+EBCDIC strings are not supported.
+
+@item packed binary coded decimal
+
+Packed binary coded decimal is not supported. This means that the @code{DC.P}
+and @code{DCB.P} pseudo-ops are not supported.
+
+@item @code{FEQU} pseudo-op
+
+The m68k @code{FEQU} pseudo-op is not supported.
+
+@item @code{NOOBJ} pseudo-op
+
+The m68k @code{NOOBJ} pseudo-op is not supported.
+
+@item @code{OPT} branch control options
+
+The m68k @code{OPT} branch control options---@code{B}, @code{BRS}, @code{BRB},
+@code{BRL}, and @code{BRW}---are ignored. @code{@value{AS}} automatically
+relaxes all branches, whether forward or backward, to an appropriate size, so
+these options serve no purpose.
+
+@item @code{OPT} list control options
+
+The following m68k @code{OPT} list control options are ignored: @code{C},
+@code{CEX}, @code{CL}, @code{CRE}, @code{E}, @code{G}, @code{I}, @code{M},
+@code{MEX}, @code{MC}, @code{MD}, @code{X}.
+
+@item other @code{OPT} options
+
+The following m68k @code{OPT} options are ignored: @code{NEST}, @code{O},
+@code{OLD}, @code{OP}, @code{P}, @code{PCO}, @code{PCR}, @code{PCS}, @code{R}.
+
+@item @code{OPT} @code{D} option is default
+
+The m68k @code{OPT} @code{D} option is the default, unlike the MRI assembler.
+@code{OPT NOD} may be used to turn it off.
+
+@item @code{XREF} pseudo-op.
+
+The m68k @code{XREF} pseudo-op is ignored.
+
+@item @code{.debug} pseudo-op
+
+The i960 @code{.debug} pseudo-op is not supported.
+
+@item @code{.extended} pseudo-op
+
+The i960 @code{.extended} pseudo-op is not supported.
+
+@item @code{.list} pseudo-op.
+
+The various options of the i960 @code{.list} pseudo-op are not supported.
+
+@item @code{.optimize} pseudo-op
+
+The i960 @code{.optimize} pseudo-op is not supported.
+
+@item @code{.output} pseudo-op
+
+The i960 @code{.output} pseudo-op is not supported.
+
+@item @code{.setreal} pseudo-op
+
+The i960 @code{.setreal} pseudo-op is not supported.
+
+@end itemize
+
+@node MD
+@section Dependency tracking: @code{--MD}
+
+@kindex --MD
+@cindex dependency tracking
+@cindex make rules
+
+@code{@value{AS}} can generate a dependency file for the file it creates. This
+file consists of a single rule suitable for @code{make} describing the
+dependencies of the main source file.
+
+The rule is written to the file named in its argument.
+
+This feature is used in the automatic updating of makefiles.
+
+@node o
+@section Name the Object File: @code{-o}
+
+@kindex -o
+@cindex naming object file
+@cindex object file name
+There is always one object file output when you run @code{@value{AS}}. By
+default it has the name
+@ifset GENERIC
+@ifset I960
+@file{a.out} (or @file{b.out}, for Intel 960 targets only).
+@end ifset
+@ifclear I960
+@file{a.out}.
+@end ifclear
+@end ifset
+@ifclear GENERIC
+@ifset I960
+@file{b.out}.
+@end ifset
+@ifclear I960
+@file{a.out}.
+@end ifclear
+@end ifclear
+You use this option (which takes exactly one filename) to give the
+object file a different name.
+
+Whatever the object file is called, @code{@value{AS}} overwrites any
+existing file of the same name.
+
+@node R
+@section Join Data and Text Sections: @code{-R}
+
+@kindex -R
+@cindex data and text sections, joining
+@cindex text and data sections, joining
+@cindex joining text and data sections
+@cindex merging text and data sections
+@code{-R} tells @code{@value{AS}} to write the object file as if all
+data-section data lives in the text section. This is only done at
+the very last moment: your binary data are the same, but data
+section parts are relocated differently. The data section part of
+your object file is zero bytes long because all its bytes are
+appended to the text section. (@xref{Sections,,Sections and Relocation}.)
+
+When you specify @code{-R} it would be possible to generate shorter
+address displacements (because we do not have to cross between text and
+data section). We refrain from doing this simply for compatibility with
+older versions of @code{@value{AS}}. In future, @code{-R} may work this way.
+
+@ifset COFF
+When @code{@value{AS}} is configured for COFF output,
+this option is only useful if you use sections named @samp{.text} and
+@samp{.data}.
+@end ifset
+
+@ifset HPPA
+@code{-R} is not supported for any of the HPPA targets. Using
+@code{-R} generates a warning from @code{@value{AS}}.
+@end ifset
+
+@node statistics
+@section Display Assembly Statistics: @code{--statistics}
+
+@kindex --statistics
+@cindex statistics, about assembly
+@cindex time, total for assembly
+@cindex space used, maximum for assembly
+Use @samp{--statistics} to display two statistics about the resources used by
+@code{@value{AS}}: the maximum amount of space allocated during the assembly
+(in bytes), and the total execution time taken for the assembly (in @sc{cpu}
+seconds).
+
+@node traditional-format
+@section Compatible output: @code{--traditional-format}
+
+@kindex --traditional-format
+For some targets, the output of @code{@value{AS}} is different in some ways
+from the output of some existing assembler. This switch requests
+@code{@value{AS}} to use the traditional format instead.
+
+For example, it disables the exception frame optimizations which
+@code{@value{AS}} normally does by default on @code{@value{GCC}} output.
+
+@node v
+@section Announce Version: @code{-v}
+
+@kindex -v
+@kindex -version
+@cindex assembler version
+@cindex version of assembler
+You can find out what version of as is running by including the
+option @samp{-v} (which you can also spell as @samp{-version}) on the
+command line.
+
+@node W
+@section Suppress Warnings: @code{-W}
+
+@kindex -W
+@cindex suppressing warnings
+@cindex warnings, suppressing
+@code{@value{AS}} should never give a warning or error message when
+assembling compiler output. But programs written by people often
+cause @code{@value{AS}} to give a warning that a particular assumption was
+made. All such warnings are directed to the standard error file.
+If you use this option, no warnings are issued. This option only
+affects the warning messages: it does not change any particular of how
+@code{@value{AS}} assembles your file. Errors, which stop the assembly, are
+still reported.
+
+@node Z
+@section Generate Object File in Spite of Errors: @code{-Z}
+@cindex object file, after errors
+@cindex errors, continuing after
+After an error message, @code{@value{AS}} normally produces no output. If for
+some reason you are interested in object file output even after
+@code{@value{AS}} gives an error message on your program, use the @samp{-Z}
+option. If there are any errors, @code{@value{AS}} continues anyways, and
+writes an object file after a final warning message of the form @samp{@var{n}
+errors, @var{m} warnings, generating bad object file.}
+
+@node Syntax
+@chapter Syntax
+
+@cindex machine-independent syntax
+@cindex syntax, machine-independent
+This chapter describes the machine-independent syntax allowed in a
+source file. @code{@value{AS}} syntax is similar to what many other
+assemblers use; it is inspired by the BSD 4.2
+@ifclear VAX
+assembler.
+@end ifclear
+@ifset VAX
+assembler, except that @code{@value{AS}} does not assemble Vax bit-fields.
+@end ifset
+
+@menu
+* Preprocessing:: Preprocessing
+* Whitespace:: Whitespace
+* Comments:: Comments
+* Symbol Intro:: Symbols
+* Statements:: Statements
+* Constants:: Constants
+@end menu
+
+@node Preprocessing
+@section Preprocessing
+
+@cindex preprocessing
+The @code{@value{AS}} internal preprocessor:
+@itemize @bullet
+@cindex whitespace, removed by preprocessor
+@item
+adjusts and removes extra whitespace. It leaves one space or tab before
+the keywords on a line, and turns any other whitespace on the line into
+a single space.
+
+@cindex comments, removed by preprocessor
+@item
+removes all comments, replacing them with a single space, or an
+appropriate number of newlines.
+
+@cindex constants, converted by preprocessor
+@item
+converts character constants into the appropriate numeric values.
+@end itemize
+
+It does not do macro processing, include file handling, or
+anything else you may get from your C compiler's preprocessor. You can
+do include file processing with the @code{.include} directive
+(@pxref{Include,,@code{.include}}). You can use the @sc{gnu} C compiler driver
+to get other ``CPP'' style preprocessing, by giving the input file a
+@samp{.S} suffix. @xref{Overall Options,, Options Controlling the Kind of
+Output, gcc.info, Using GNU CC}.
+
+Excess whitespace, comments, and character constants
+cannot be used in the portions of the input text that are not
+preprocessed.
+
+@cindex turning preprocessing on and off
+@cindex preprocessing, turning on and off
+@kindex #NO_APP
+@kindex #APP
+If the first line of an input file is @code{#NO_APP} or if you use the
+@samp{-f} option, whitespace and comments are not removed from the input file.
+Within an input file, you can ask for whitespace and comment removal in
+specific portions of the by putting a line that says @code{#APP} before the
+text that may contain whitespace or comments, and putting a line that says
+@code{#NO_APP} after this text. This feature is mainly intend to support
+@code{asm} statements in compilers whose output is otherwise free of comments
+and whitespace.
+
+@node Whitespace
+@section Whitespace
+
+@cindex whitespace
+@dfn{Whitespace} is one or more blanks or tabs, in any order.
+Whitespace is used to separate symbols, and to make programs neater for
+people to read. Unless within character constants
+(@pxref{Characters,,Character Constants}), any whitespace means the same
+as exactly one space.
+
+@node Comments
+@section Comments
+
+@cindex comments
+There are two ways of rendering comments to @code{@value{AS}}. In both
+cases the comment is equivalent to one space.
+
+Anything from @samp{/*} through the next @samp{*/} is a comment.
+This means you may not nest these comments.
+
+@smallexample
+/*
+ The only way to include a newline ('\n') in a comment
+ is to use this sort of comment.
+*/
+
+/* This sort of comment does not nest. */
+@end smallexample
+
+@cindex line comment character
+Anything from the @dfn{line comment} character to the next newline
+is considered a comment and is ignored. The line comment character is
+@ifset A29K
+@samp{;} for the AMD 29K family;
+@end ifset
+@ifset ARC
+@samp{;} on the ARC;
+@end ifset
+@ifset H8/300
+@samp{;} for the H8/300 family;
+@end ifset
+@ifset H8/500
+@samp{!} for the H8/500 family;
+@end ifset
+@ifset HPPA
+@samp{;} for the HPPA;
+@end ifset
+@ifset I960
+@samp{#} on the i960;
+@end ifset
+@ifset SH
+@samp{!} for the Hitachi SH;
+@end ifset
+@ifset SPARC
+@samp{!} on the SPARC;
+@end ifset
+@ifset M32R
+@samp{#} on the m32r;
+@end ifset
+@ifset M680X0
+@samp{|} on the 680x0;
+@end ifset
+@ifset VAX
+@samp{#} on the Vax;
+@end ifset
+@ifset Z8000
+@samp{!} for the Z8000;
+@end ifset
+@ifset V850
+@samp{#} on the V850;
+@end ifset
+see @ref{Machine Dependencies}. @refill
+@c FIXME What about i386, m88k, i860?
+
+@ifset GENERIC
+On some machines there are two different line comment characters. One
+character only begins a comment if it is the first non-whitespace character on
+a line, while the other always begins a comment.
+@end ifset
+
+@ifset V850
+The V850 assembler also supports a double dash as starting a comment that
+extends to the end of the line.
+
+@samp{--};
+@end ifset
+
+@kindex #
+@cindex lines starting with @code{#}
+@cindex logical line numbers
+To be compatible with past assemblers, lines that begin with @samp{#} have a
+special interpretation. Following the @samp{#} should be an absolute
+expression (@pxref{Expressions}): the logical line number of the @emph{next}
+line. Then a string (@pxref{Strings,, Strings}) is allowed: if present it is a
+new logical file name. The rest of the line, if any, should be whitespace.
+
+If the first non-whitespace characters on the line are not numeric,
+the line is ignored. (Just like a comment.)
+
+@smallexample
+ # This is an ordinary comment.
+# 42-6 "new_file_name" # New logical file name
+ # This is logical line # 36.
+@end smallexample
+This feature is deprecated, and may disappear from future versions
+of @code{@value{AS}}.
+
+@node Symbol Intro
+@section Symbols
+
+@cindex characters used in symbols
+@ifclear SPECIAL-SYMS
+A @dfn{symbol} is one or more characters chosen from the set of all
+letters (both upper and lower case), digits and the three characters
+@samp{_.$}.
+@end ifclear
+@ifset SPECIAL-SYMS
+@ifclear GENERIC
+@ifset H8
+A @dfn{symbol} is one or more characters chosen from the set of all
+letters (both upper and lower case), digits and the three characters
+@samp{._$}. (Save that, on the H8/300 only, you may not use @samp{$} in
+symbol names.)
+@end ifset
+@end ifclear
+@end ifset
+@ifset GENERIC
+On most machines, you can also use @code{$} in symbol names; exceptions
+are noted in @ref{Machine Dependencies}.
+@end ifset
+No symbol may begin with a digit. Case is significant.
+There is no length limit: all characters are significant. Symbols are
+delimited by characters not in that set, or by the beginning of a file
+(since the source program must end with a newline, the end of a file is
+not a possible symbol delimiter). @xref{Symbols}.
+@cindex length of symbols
+
+@node Statements
+@section Statements
+
+@cindex statements, structure of
+@cindex line separator character
+@cindex statement separator character
+@ifclear GENERIC
+@ifclear abnormal-separator
+A @dfn{statement} ends at a newline character (@samp{\n}) or at a
+semicolon (@samp{;}). The newline or semicolon is considered part of
+the preceding statement. Newlines and semicolons within character
+constants are an exception: they do not end statements.
+@end ifclear
+@ifset abnormal-separator
+@ifset A29K
+A @dfn{statement} ends at a newline character (@samp{\n}) or an ``at''
+sign (@samp{@@}). The newline or at sign is considered part of the
+preceding statement. Newlines and at signs within character constants
+are an exception: they do not end statements.
+@end ifset
+@ifset HPPA
+A @dfn{statement} ends at a newline character (@samp{\n}) or an exclamation
+point (@samp{!}). The newline or exclamation point is considered part of the
+preceding statement. Newlines and exclamation points within character
+constants are an exception: they do not end statements.
+@end ifset
+@ifset H8
+A @dfn{statement} ends at a newline character (@samp{\n}); or (for the
+H8/300) a dollar sign (@samp{$}); or (for the
+Hitachi-SH or the
+H8/500) a semicolon
+(@samp{;}). The newline or separator character is considered part of
+the preceding statement. Newlines and separators within character
+constants are an exception: they do not end statements.
+@end ifset
+@end ifset
+@end ifclear
+@ifset GENERIC
+A @dfn{statement} ends at a newline character (@samp{\n}) or line
+separator character. (The line separator is usually @samp{;}, unless
+this conflicts with the comment character; @pxref{Machine Dependencies}.) The
+newline or separator character is considered part of the preceding
+statement. Newlines and separators within character constants are an
+exception: they do not end statements.
+@end ifset
+
+@cindex newline, required at file end
+@cindex EOF, newline must precede
+It is an error to end any statement with end-of-file: the last
+character of any input file should be a newline.@refill
+
+An empty statement is allowed, and may include whitespace. It is ignored.
+
+@cindex instructions and directives
+@cindex directives and instructions
+@c "key symbol" is not used elsewhere in the document; seems pedantic to
+@c @defn{} it in that case, as was done previously... doc@cygnus.com,
+@c 13feb91.
+A statement begins with zero or more labels, optionally followed by a
+key symbol which determines what kind of statement it is. The key
+symbol determines the syntax of the rest of the statement. If the
+symbol begins with a dot @samp{.} then the statement is an assembler
+directive: typically valid for any computer. If the symbol begins with
+a letter the statement is an assembly language @dfn{instruction}: it
+assembles into a machine language instruction.
+@ifset GENERIC
+Different versions of @code{@value{AS}} for different computers
+recognize different instructions. In fact, the same symbol may
+represent a different instruction in a different computer's assembly
+language.@refill
+@end ifset
+
+@cindex @code{:} (label)
+@cindex label (@code{:})
+A label is a symbol immediately followed by a colon (@code{:}).
+Whitespace before a label or after a colon is permitted, but you may not
+have whitespace between a label's symbol and its colon. @xref{Labels}.
+
+@ifset HPPA
+For HPPA targets, labels need not be immediately followed by a colon, but
+the definition of a label must begin in column zero. This also implies that
+only one label may be defined on each line.
+@end ifset
+
+@smallexample
+label: .directive followed by something
+another_label: # This is an empty statement.
+ instruction operand_1, operand_2, @dots{}
+@end smallexample
+
+@node Constants
+@section Constants
+
+@cindex constants
+A constant is a number, written so that its value is known by
+inspection, without knowing any context. Like this:
+@smallexample
+@group
+.byte 74, 0112, 092, 0x4A, 0X4a, 'J, '\J # All the same value.
+.ascii "Ring the bell\7" # A string constant.
+.octa 0x123456789abcdef0123456789ABCDEF0 # A bignum.
+.float 0f-314159265358979323846264338327\
+95028841971.693993751E-40 # - pi, a flonum.
+@end group
+@end smallexample
+
+@menu
+* Characters:: Character Constants
+* Numbers:: Number Constants
+@end menu
+
+@node Characters
+@subsection Character Constants
+
+@cindex character constants
+@cindex constants, character
+There are two kinds of character constants. A @dfn{character} stands
+for one character in one byte and its value may be used in
+numeric expressions. String constants (properly called string
+@emph{literals}) are potentially many bytes and their values may not be
+used in arithmetic expressions.
+
+@menu
+* Strings:: Strings
+* Chars:: Characters
+@end menu
+
+@node Strings
+@subsubsection Strings
+
+@cindex string constants
+@cindex constants, string
+A @dfn{string} is written between double-quotes. It may contain
+double-quotes or null characters. The way to get special characters
+into a string is to @dfn{escape} these characters: precede them with
+a backslash @samp{\} character. For example @samp{\\} represents
+one backslash: the first @code{\} is an escape which tells
+@code{@value{AS}} to interpret the second character literally as a backslash
+(which prevents @code{@value{AS}} from recognizing the second @code{\} as an
+escape character). The complete list of escapes follows.
+
+@cindex escape codes, character
+@cindex character escape codes
+@table @kbd
+@c @item \a
+@c Mnemonic for ACKnowledge; for ASCII this is octal code 007.
+@c
+@cindex @code{\b} (backspace character)
+@cindex backspace (@code{\b})
+@item \b
+Mnemonic for backspace; for ASCII this is octal code 010.
+
+@c @item \e
+@c Mnemonic for EOText; for ASCII this is octal code 004.
+@c
+@cindex @code{\f} (formfeed character)
+@cindex formfeed (@code{\f})
+@item \f
+Mnemonic for FormFeed; for ASCII this is octal code 014.
+
+@cindex @code{\n} (newline character)
+@cindex newline (@code{\n})
+@item \n
+Mnemonic for newline; for ASCII this is octal code 012.
+
+@c @item \p
+@c Mnemonic for prefix; for ASCII this is octal code 033, usually known as @code{escape}.
+@c
+@cindex @code{\r} (carriage return character)
+@cindex carriage return (@code{\r})
+@item \r
+Mnemonic for carriage-Return; for ASCII this is octal code 015.
+
+@c @item \s
+@c Mnemonic for space; for ASCII this is octal code 040. Included for compliance with
+@c other assemblers.
+@c
+@cindex @code{\t} (tab)
+@cindex tab (@code{\t})
+@item \t
+Mnemonic for horizontal Tab; for ASCII this is octal code 011.
+
+@c @item \v
+@c Mnemonic for Vertical tab; for ASCII this is octal code 013.
+@c @item \x @var{digit} @var{digit} @var{digit}
+@c A hexadecimal character code. The numeric code is 3 hexadecimal digits.
+@c
+@cindex @code{\@var{ddd}} (octal character code)
+@cindex octal character code (@code{\@var{ddd}})
+@item \ @var{digit} @var{digit} @var{digit}
+An octal character code. The numeric code is 3 octal digits.
+For compatibility with other Unix systems, 8 and 9 are accepted as digits:
+for example, @code{\008} has the value 010, and @code{\009} the value 011.
+
+@cindex @code{\@var{xd...}} (hex character code)
+@cindex hex character code (@code{\@var{xd...}})
+@item \@code{x} @var{hex-digits...}
+A hex character code. All trailing hex digits are combined. Either upper or
+lower case @code{x} works.
+
+@cindex @code{\\} (@samp{\} character)
+@cindex backslash (@code{\\})
+@item \\
+Represents one @samp{\} character.
+
+@c @item \'
+@c Represents one @samp{'} (accent acute) character.
+@c This is needed in single character literals
+@c (@xref{Characters,,Character Constants}.) to represent
+@c a @samp{'}.
+@c
+@cindex @code{\"} (doublequote character)
+@cindex doublequote (@code{\"})
+@item \"
+Represents one @samp{"} character. Needed in strings to represent
+this character, because an unescaped @samp{"} would end the string.
+
+@item \ @var{anything-else}
+Any other character when escaped by @kbd{\} gives a warning, but
+assembles as if the @samp{\} was not present. The idea is that if
+you used an escape sequence you clearly didn't want the literal
+interpretation of the following character. However @code{@value{AS}} has no
+other interpretation, so @code{@value{AS}} knows it is giving you the wrong
+code and warns you of the fact.
+@end table
+
+Which characters are escapable, and what those escapes represent,
+varies widely among assemblers. The current set is what we think
+the BSD 4.2 assembler recognizes, and is a subset of what most C
+compilers recognize. If you are in doubt, do not use an escape
+sequence.
+
+@node Chars
+@subsubsection Characters
+
+@cindex single character constant
+@cindex character, single
+@cindex constant, single character
+A single character may be written as a single quote immediately
+followed by that character. The same escapes apply to characters as
+to strings. So if you want to write the character backslash, you
+must write @kbd{'\\} where the first @code{\} escapes the second
+@code{\}. As you can see, the quote is an acute accent, not a
+grave accent. A newline
+@ifclear GENERIC
+@ifclear abnormal-separator
+(or semicolon @samp{;})
+@end ifclear
+@ifset abnormal-separator
+@ifset A29K
+(or at sign @samp{@@})
+@end ifset
+@ifset H8
+(or dollar sign @samp{$}, for the H8/300; or semicolon @samp{;} for the
+Hitachi SH or
+H8/500)
+@end ifset
+@end ifset
+@end ifclear
+immediately following an acute accent is taken as a literal character
+and does not count as the end of a statement. The value of a character
+constant in a numeric expression is the machine's byte-wide code for
+that character. @code{@value{AS}} assumes your character code is ASCII:
+@kbd{'A} means 65, @kbd{'B} means 66, and so on. @refill
+
+@node Numbers
+@subsection Number Constants
+
+@cindex constants, number
+@cindex number constants
+@code{@value{AS}} distinguishes three kinds of numbers according to how they
+are stored in the target machine. @emph{Integers} are numbers that
+would fit into an @code{int} in the C language. @emph{Bignums} are
+integers, but they are stored in more than 32 bits. @emph{Flonums}
+are floating point numbers, described below.
+
+@menu
+* Integers:: Integers
+* Bignums:: Bignums
+* Flonums:: Flonums
+@ifclear GENERIC
+@ifset I960
+* Bit Fields:: Bit Fields
+@end ifset
+@end ifclear
+@end menu
+
+@node Integers
+@subsubsection Integers
+@cindex integers
+@cindex constants, integer
+
+@cindex binary integers
+@cindex integers, binary
+A binary integer is @samp{0b} or @samp{0B} followed by zero or more of
+the binary digits @samp{01}.
+
+@cindex octal integers
+@cindex integers, octal
+An octal integer is @samp{0} followed by zero or more of the octal
+digits (@samp{01234567}).
+
+@cindex decimal integers
+@cindex integers, decimal
+A decimal integer starts with a non-zero digit followed by zero or
+more digits (@samp{0123456789}).
+
+@cindex hexadecimal integers
+@cindex integers, hexadecimal
+A hexadecimal integer is @samp{0x} or @samp{0X} followed by one or
+more hexadecimal digits chosen from @samp{0123456789abcdefABCDEF}.
+
+Integers have the usual values. To denote a negative integer, use
+the prefix operator @samp{-} discussed under expressions
+(@pxref{Prefix Ops,,Prefix Operators}).
+
+@node Bignums
+@subsubsection Bignums
+
+@cindex bignums
+@cindex constants, bignum
+A @dfn{bignum} has the same syntax and semantics as an integer
+except that the number (or its negative) takes more than 32 bits to
+represent in binary. The distinction is made because in some places
+integers are permitted while bignums are not.
+
+@node Flonums
+@subsubsection Flonums
+@cindex flonums
+@cindex floating point numbers
+@cindex constants, floating point
+
+@cindex precision, floating point
+A @dfn{flonum} represents a floating point number. The translation is
+indirect: a decimal floating point number from the text is converted by
+@code{@value{AS}} to a generic binary floating point number of more than
+sufficient precision. This generic floating point number is converted
+to a particular computer's floating point format (or formats) by a
+portion of @code{@value{AS}} specialized to that computer.
+
+A flonum is written by writing (in order)
+@itemize @bullet
+@item
+The digit @samp{0}.
+@ifset HPPA
+(@samp{0} is optional on the HPPA.)
+@end ifset
+
+@item
+A letter, to tell @code{@value{AS}} the rest of the number is a flonum.
+@ifset GENERIC
+@kbd{e} is recommended. Case is not important.
+@ignore
+@c FIXME: verify if flonum syntax really this vague for most cases
+(Any otherwise illegal letter works here, but that might be changed. Vax BSD
+4.2 assembler seems to allow any of @samp{defghDEFGH}.)
+@end ignore
+
+On the H8/300, H8/500,
+Hitachi SH,
+and AMD 29K architectures, the letter must be
+one of the letters @samp{DFPRSX} (in upper or lower case).
+
+On the ARC, the letter must be one of the letters @samp{DFRS}
+(in upper or lower case).
+
+On the Intel 960 architecture, the letter must be
+one of the letters @samp{DFT} (in upper or lower case).
+
+On the HPPA architecture, the letter must be @samp{E} (upper case only).
+@end ifset
+@ifclear GENERIC
+@ifset A29K
+One of the letters @samp{DFPRSX} (in upper or lower case).
+@end ifset
+@ifset ARC
+One of the letters @samp{DFRS} (in upper or lower case).
+@end ifset
+@ifset H8
+One of the letters @samp{DFPRSX} (in upper or lower case).
+@end ifset
+@ifset HPPA
+The letter @samp{E} (upper case only).
+@end ifset
+@ifset I960
+One of the letters @samp{DFT} (in upper or lower case).
+@end ifset
+@end ifclear
+
+@item
+An optional sign: either @samp{+} or @samp{-}.
+
+@item
+An optional @dfn{integer part}: zero or more decimal digits.
+
+@item
+An optional @dfn{fractional part}: @samp{.} followed by zero
+or more decimal digits.
+
+@item
+An optional exponent, consisting of:
+
+@itemize @bullet
+@item
+An @samp{E} or @samp{e}.
+@c I can't find a config where "EXP_CHARS" is other than 'eE', but in
+@c principle this can perfectly well be different on different targets.
+@item
+Optional sign: either @samp{+} or @samp{-}.
+@item
+One or more decimal digits.
+@end itemize
+
+@end itemize
+
+At least one of the integer part or the fractional part must be
+present. The floating point number has the usual base-10 value.
+
+@code{@value{AS}} does all processing using integers. Flonums are computed
+independently of any floating point hardware in the computer running
+@code{@value{AS}}.
+
+@ifclear GENERIC
+@ifset I960
+@c Bit fields are written as a general facility but are also controlled
+@c by a conditional-compilation flag---which is as of now (21mar91)
+@c turned on only by the i960 config of GAS.
+@node Bit Fields
+@subsubsection Bit Fields
+
+@cindex bit fields
+@cindex constants, bit field
+You can also define numeric constants as @dfn{bit fields}.
+specify two numbers separated by a colon---
+@example
+@var{mask}:@var{value}
+@end example
+@noindent
+@code{@value{AS}} applies a bitwise @sc{and} between @var{mask} and
+@var{value}.
+
+The resulting number is then packed
+@ifset GENERIC
+@c this conditional paren in case bit fields turned on elsewhere than 960
+(in host-dependent byte order)
+@end ifset
+into a field whose width depends on which assembler directive has the
+bit-field as its argument. Overflow (a result from the bitwise and
+requiring more binary digits to represent) is not an error; instead,
+more constants are generated, of the specified width, beginning with the
+least significant digits.@refill
+
+The directives @code{.byte}, @code{.hword}, @code{.int}, @code{.long},
+@code{.short}, and @code{.word} accept bit-field arguments.
+@end ifset
+@end ifclear
+
+@node Sections
+@chapter Sections and Relocation
+@cindex sections
+@cindex relocation
+
+@menu
+* Secs Background:: Background
+* Ld Sections:: Linker Sections
+* As Sections:: Assembler Internal Sections
+* Sub-Sections:: Sub-Sections
+* bss:: bss Section
+@end menu
+
+@node Secs Background
+@section Background
+
+Roughly, a section is a range of addresses, with no gaps; all data
+``in'' those addresses is treated the same for some particular purpose.
+For example there may be a ``read only'' section.
+
+@cindex linker, and assembler
+@cindex assembler, and linker
+The linker @code{@value{LD}} reads many object files (partial programs) and
+combines their contents to form a runnable program. When @code{@value{AS}}
+emits an object file, the partial program is assumed to start at address 0.
+@code{@value{LD}} assigns the final addresses for the partial program, so that
+different partial programs do not overlap. This is actually an
+oversimplification, but it suffices to explain how @code{@value{AS}} uses
+sections.
+
+@code{@value{LD}} moves blocks of bytes of your program to their run-time
+addresses. These blocks slide to their run-time addresses as rigid
+units; their length does not change and neither does the order of bytes
+within them. Such a rigid unit is called a @emph{section}. Assigning
+run-time addresses to sections is called @dfn{relocation}. It includes
+the task of adjusting mentions of object-file addresses so they refer to
+the proper run-time addresses.
+@ifset H8
+For the H8/300 and H8/500,
+and for the Hitachi SH,
+@code{@value{AS}} pads sections if needed to
+ensure they end on a word (sixteen bit) boundary.
+@end ifset
+
+@cindex standard assembler sections
+An object file written by @code{@value{AS}} has at least three sections, any
+of which may be empty. These are named @dfn{text}, @dfn{data} and
+@dfn{bss} sections.
+
+@ifset COFF
+@ifset GENERIC
+When it generates COFF output,
+@end ifset
+@code{@value{AS}} can also generate whatever other named sections you specify
+using the @samp{.section} directive (@pxref{Section,,@code{.section}}).
+If you do not use any directives that place output in the @samp{.text}
+or @samp{.data} sections, these sections still exist, but are empty.
+@end ifset
+
+@ifset HPPA
+@ifset GENERIC
+When @code{@value{AS}} generates SOM or ELF output for the HPPA,
+@end ifset
+@code{@value{AS}} can also generate whatever other named sections you
+specify using the @samp{.space} and @samp{.subspace} directives. See
+@cite{HP9000 Series 800 Assembly Language Reference Manual}
+(HP 92432-90001) for details on the @samp{.space} and @samp{.subspace}
+assembler directives.
+
+@ifset SOM
+Additionally, @code{@value{AS}} uses different names for the standard
+text, data, and bss sections when generating SOM output. Program text
+is placed into the @samp{$CODE$} section, data into @samp{$DATA$}, and
+BSS into @samp{$BSS$}.
+@end ifset
+@end ifset
+
+Within the object file, the text section starts at address @code{0}, the
+data section follows, and the bss section follows the data section.
+
+@ifset HPPA
+When generating either SOM or ELF output files on the HPPA, the text
+section starts at address @code{0}, the data section at address
+@code{0x4000000}, and the bss section follows the data section.
+@end ifset
+
+To let @code{@value{LD}} know which data changes when the sections are
+relocated, and how to change that data, @code{@value{AS}} also writes to the
+object file details of the relocation needed. To perform relocation
+@code{@value{LD}} must know, each time an address in the object
+file is mentioned:
+@itemize @bullet
+@item
+Where in the object file is the beginning of this reference to
+an address?
+@item
+How long (in bytes) is this reference?
+@item
+Which section does the address refer to? What is the numeric value of
+@display
+(@var{address}) @minus{} (@var{start-address of section})?
+@end display
+@item
+Is the reference to an address ``Program-Counter relative''?
+@end itemize
+
+@cindex addresses, format of
+@cindex section-relative addressing
+In fact, every address @code{@value{AS}} ever uses is expressed as
+@display
+(@var{section}) + (@var{offset into section})
+@end display
+@noindent
+Further, most expressions @code{@value{AS}} computes have this section-relative
+nature.
+@ifset SOM
+(For some object formats, such as SOM for the HPPA, some expressions are
+symbol-relative instead.)
+@end ifset
+
+In this manual we use the notation @{@var{secname} @var{N}@} to mean ``offset
+@var{N} into section @var{secname}.''
+
+Apart from text, data and bss sections you need to know about the
+@dfn{absolute} section. When @code{@value{LD}} mixes partial programs,
+addresses in the absolute section remain unchanged. For example, address
+@code{@{absolute 0@}} is ``relocated'' to run-time address 0 by
+@code{@value{LD}}. Although the linker never arranges two partial programs'
+data sections with overlapping addresses after linking, @emph{by definition}
+their absolute sections must overlap. Address @code{@{absolute@ 239@}} in one
+part of a program is always the same address when the program is running as
+address @code{@{absolute@ 239@}} in any other part of the program.
+
+The idea of sections is extended to the @dfn{undefined} section. Any
+address whose section is unknown at assembly time is by definition
+rendered @{undefined @var{U}@}---where @var{U} is filled in later.
+Since numbers are always defined, the only way to generate an undefined
+address is to mention an undefined symbol. A reference to a named
+common block would be such a symbol: its value is unknown at assembly
+time so it has section @emph{undefined}.
+
+By analogy the word @emph{section} is used to describe groups of sections in
+the linked program. @code{@value{LD}} puts all partial programs' text
+sections in contiguous addresses in the linked program. It is
+customary to refer to the @emph{text section} of a program, meaning all
+the addresses of all partial programs' text sections. Likewise for
+data and bss sections.
+
+Some sections are manipulated by @code{@value{LD}}; others are invented for
+use of @code{@value{AS}} and have no meaning except during assembly.
+
+@node Ld Sections
+@section Linker Sections
+@code{@value{LD}} deals with just four kinds of sections, summarized below.
+
+@table @strong
+
+@ifset COFF
+@cindex named sections
+@cindex sections, named
+@item named sections
+@end ifset
+@ifset aout-bout
+@cindex text section
+@cindex data section
+@itemx text section
+@itemx data section
+@end ifset
+These sections hold your program. @code{@value{AS}} and @code{@value{LD}} treat them as
+separate but equal sections. Anything you can say of one section is
+true another.
+@ifset aout-bout
+When the program is running, however, it is
+customary for the text section to be unalterable. The
+text section is often shared among processes: it contains
+instructions, constants and the like. The data section of a running
+program is usually alterable: for example, C variables would be stored
+in the data section.
+@end ifset
+
+@cindex bss section
+@item bss section
+This section contains zeroed bytes when your program begins running. It
+is used to hold unitialized variables or common storage. The length of
+each partial program's bss section is important, but because it starts
+out containing zeroed bytes there is no need to store explicit zero
+bytes in the object file. The bss section was invented to eliminate
+those explicit zeros from object files.
+
+@cindex absolute section
+@item absolute section
+Address 0 of this section is always ``relocated'' to runtime address 0.
+This is useful if you want to refer to an address that @code{@value{LD}} must
+not change when relocating. In this sense we speak of absolute
+addresses being ``unrelocatable'': they do not change during relocation.
+
+@cindex undefined section
+@item undefined section
+This ``section'' is a catch-all for address references to objects not in
+the preceding sections.
+@c FIXME: ref to some other doc on obj-file formats could go here.
+@end table
+
+@cindex relocation example
+An idealized example of three relocatable sections follows.
+@ifset COFF
+The example uses the traditional section names @samp{.text} and @samp{.data}.
+@end ifset
+Memory addresses are on the horizontal axis.
+
+@c TEXI2ROFF-KILL
+@ifinfo
+@c END TEXI2ROFF-KILL
+@smallexample
+ +-----+----+--+
+partial program # 1: |ttttt|dddd|00|
+ +-----+----+--+
+
+ text data bss
+ seg. seg. seg.
+
+ +---+---+---+
+partial program # 2: |TTT|DDD|000|
+ +---+---+---+
+
+ +--+---+-----+--+----+---+-----+~~
+linked program: | |TTT|ttttt| |dddd|DDD|00000|
+ +--+---+-----+--+----+---+-----+~~
+
+ addresses: 0 @dots{}
+@end smallexample
+@c TEXI2ROFF-KILL
+@end ifinfo
+@need 5000
+@tex
+
+\line{\it Partial program \#1: \hfil}
+\line{\ibox{2.5cm}{\tt text}\ibox{2cm}{\tt data}\ibox{1cm}{\tt bss}\hfil}
+\line{\boxit{2.5cm}{\tt ttttt}\boxit{2cm}{\tt dddd}\boxit{1cm}{\tt 00}\hfil}
+
+\line{\it Partial program \#2: \hfil}
+\line{\ibox{1cm}{\tt text}\ibox{1.5cm}{\tt data}\ibox{1cm}{\tt bss}\hfil}
+\line{\boxit{1cm}{\tt TTT}\boxit{1.5cm}{\tt DDDD}\boxit{1cm}{\tt 000}\hfil}
+
+\line{\it linked program: \hfil}
+\line{\ibox{.5cm}{}\ibox{1cm}{\tt text}\ibox{2.5cm}{}\ibox{.75cm}{}\ibox{2cm}{\tt data}\ibox{1.5cm}{}\ibox{2cm}{\tt bss}\hfil}
+\line{\boxit{.5cm}{}\boxit{1cm}{\tt TTT}\boxit{2.5cm}{\tt
+ttttt}\boxit{.75cm}{}\boxit{2cm}{\tt dddd}\boxit{1.5cm}{\tt
+DDDD}\boxit{2cm}{\tt 00000}\ \dots\hfil}
+
+\line{\it addresses: \hfil}
+\line{0\dots\hfil}
+
+@end tex
+@c END TEXI2ROFF-KILL
+
+@node As Sections
+@section Assembler Internal Sections
+
+@cindex internal assembler sections
+@cindex sections in messages, internal
+These sections are meant only for the internal use of @code{@value{AS}}. They
+have no meaning at run-time. You do not really need to know about these
+sections for most purposes; but they can be mentioned in @code{@value{AS}}
+warning messages, so it might be helpful to have an idea of their
+meanings to @code{@value{AS}}. These sections are used to permit the
+value of every expression in your assembly language program to be a
+section-relative address.
+
+@table @b
+@cindex assembler internal logic error
+@item ASSEMBLER-INTERNAL-LOGIC-ERROR!
+An internal assembler logic error has been found. This means there is a
+bug in the assembler.
+
+@cindex expr (internal section)
+@item expr section
+The assembler stores complex expression internally as combinations of
+symbols. When it needs to represent an expression as a symbol, it puts
+it in the expr section.
+@c FIXME item debug
+@c FIXME item transfer[t] vector preload
+@c FIXME item transfer[t] vector postload
+@c FIXME item register
+@end table
+
+@node Sub-Sections
+@section Sub-Sections
+
+@cindex numbered subsections
+@cindex grouping data
+@ifset aout-bout
+Assembled bytes
+@ifset COFF
+conventionally
+@end ifset
+fall into two sections: text and data.
+@end ifset
+You may have separate groups of
+@ifset GENERIC
+data in named sections
+@end ifset
+@ifclear GENERIC
+@ifclear aout-bout
+data in named sections
+@end ifclear
+@ifset aout-bout
+text or data
+@end ifset
+@end ifclear
+that you want to end up near to each other in the object file, even though they
+are not contiguous in the assembler source. @code{@value{AS}} allows you to
+use @dfn{subsections} for this purpose. Within each section, there can be
+numbered subsections with values from 0 to 8192. Objects assembled into the
+same subsection go into the object file together with other objects in the same
+subsection. For example, a compiler might want to store constants in the text
+section, but might not want to have them interspersed with the program being
+assembled. In this case, the compiler could issue a @samp{.text 0} before each
+section of code being output, and a @samp{.text 1} before each group of
+constants being output.
+
+Subsections are optional. If you do not use subsections, everything
+goes in subsection number zero.
+
+@ifset GENERIC
+Each subsection is zero-padded up to a multiple of four bytes.
+(Subsections may be padded a different amount on different flavors
+of @code{@value{AS}}.)
+@end ifset
+@ifclear GENERIC
+@ifset H8
+On the H8/300 and H8/500 platforms, each subsection is zero-padded to a word
+boundary (two bytes).
+The same is true on the Hitachi SH.
+@end ifset
+@ifset I960
+@c FIXME section padding (alignment)?
+@c Rich Pixley says padding here depends on target obj code format; that
+@c doesn't seem particularly useful to say without further elaboration,
+@c so for now I say nothing about it. If this is a generic BFD issue,
+@c these paragraphs might need to vanish from this manual, and be
+@c discussed in BFD chapter of binutils (or some such).
+@end ifset
+@ifset A29K
+On the AMD 29K family, no particular padding is added to section or
+subsection sizes; @value{AS} forces no alignment on this platform.
+@end ifset
+@end ifclear
+
+Subsections appear in your object file in numeric order, lowest numbered
+to highest. (All this to be compatible with other people's assemblers.)
+The object file contains no representation of subsections; @code{@value{LD}} and
+other programs that manipulate object files see no trace of them.
+They just see all your text subsections as a text section, and all your
+data subsections as a data section.
+
+To specify which subsection you want subsequent statements assembled
+into, use a numeric argument to specify it, in a @samp{.text
+@var{expression}} or a @samp{.data @var{expression}} statement.
+@ifset COFF
+@ifset GENERIC
+When generating COFF output, you
+@end ifset
+@ifclear GENERIC
+You
+@end ifclear
+can also use an extra subsection
+argument with arbitrary named sections: @samp{.section @var{name},
+@var{expression}}.
+@end ifset
+@var{Expression} should be an absolute expression.
+(@xref{Expressions}.) If you just say @samp{.text} then @samp{.text 0}
+is assumed. Likewise @samp{.data} means @samp{.data 0}. Assembly
+begins in @code{text 0}. For instance:
+@smallexample
+.text 0 # The default subsection is text 0 anyway.
+.ascii "This lives in the first text subsection. *"
+.text 1
+.ascii "But this lives in the second text subsection."
+.data 0
+.ascii "This lives in the data section,"
+.ascii "in the first data subsection."
+.text 0
+.ascii "This lives in the first text section,"
+.ascii "immediately following the asterisk (*)."
+@end smallexample
+
+Each section has a @dfn{location counter} incremented by one for every byte
+assembled into that section. Because subsections are merely a convenience
+restricted to @code{@value{AS}} there is no concept of a subsection location
+counter. There is no way to directly manipulate a location counter---but the
+@code{.align} directive changes it, and any label definition captures its
+current value. The location counter of the section where statements are being
+assembled is said to be the @dfn{active} location counter.
+
+@node bss
+@section bss Section
+
+@cindex bss section
+@cindex common variable storage
+The bss section is used for local common variable storage.
+You may allocate address space in the bss section, but you may
+not dictate data to load into it before your program executes. When
+your program starts running, all the contents of the bss
+section are zeroed bytes.
+
+The @code{.lcomm} pseudo-op defines a symbol in the bss section; see
+@ref{Lcomm,,@code{.lcomm}}.
+
+The @code{.comm} pseudo-op may be used to declare a common symbol, which is
+another form of uninitialized symbol; see @xref{Comm,,@code{.comm}}.
+
+@ifset GENERIC
+When assembling for a target which supports multiple sections, such as ELF or
+COFF, you may switch into the @code{.bss} section and define symbols as usual;
+see @ref{Section,,@code{.section}}. You may only assemble zero values into the
+section. Typically the section will only contain symbol definitions and
+@code{.skip} directives (@pxref{Skip,,@code{.skip}}).
+@end ifset
+
+@node Symbols
+@chapter Symbols
+
+@cindex symbols
+Symbols are a central concept: the programmer uses symbols to name
+things, the linker uses symbols to link, and the debugger uses symbols
+to debug.
+
+@quotation
+@cindex debuggers, and symbol order
+@emph{Warning:} @code{@value{AS}} does not place symbols in the object file in
+the same order they were declared. This may break some debuggers.
+@end quotation
+
+@menu
+* Labels:: Labels
+* Setting Symbols:: Giving Symbols Other Values
+* Symbol Names:: Symbol Names
+* Dot:: The Special Dot Symbol
+* Symbol Attributes:: Symbol Attributes
+@end menu
+
+@node Labels
+@section Labels
+
+@cindex labels
+A @dfn{label} is written as a symbol immediately followed by a colon
+@samp{:}. The symbol then represents the current value of the
+active location counter, and is, for example, a suitable instruction
+operand. You are warned if you use the same symbol to represent two
+different locations: the first definition overrides any other
+definitions.
+
+@ifset HPPA
+On the HPPA, the usual form for a label need not be immediately followed by a
+colon, but instead must start in column zero. Only one label may be defined on
+a single line. To work around this, the HPPA version of @code{@value{AS}} also
+provides a special directive @code{.label} for defining labels more flexibly.
+@end ifset
+
+@node Setting Symbols
+@section Giving Symbols Other Values
+
+@cindex assigning values to symbols
+@cindex symbol values, assigning
+A symbol can be given an arbitrary value by writing a symbol, followed
+by an equals sign @samp{=}, followed by an expression
+(@pxref{Expressions}). This is equivalent to using the @code{.set}
+directive. @xref{Set,,@code{.set}}.
+
+@node Symbol Names
+@section Symbol Names
+
+@cindex symbol names
+@cindex names, symbol
+@ifclear SPECIAL-SYMS
+Symbol names begin with a letter or with one of @samp{._}. On most
+machines, you can also use @code{$} in symbol names; exceptions are
+noted in @ref{Machine Dependencies}. That character may be followed by any
+string of digits, letters, dollar signs (unless otherwise noted in
+@ref{Machine Dependencies}), and underscores.
+@end ifclear
+@ifset A29K
+For the AMD 29K family, @samp{?} is also allowed in the
+body of a symbol name, though not at its beginning.
+@end ifset
+
+@ifset SPECIAL-SYMS
+@ifset H8
+Symbol names begin with a letter or with one of @samp{._}. On the
+Hitachi SH or the
+H8/500, you can also use @code{$} in symbol names. That character may
+be followed by any string of digits, letters, dollar signs (save on the
+H8/300), and underscores.
+@end ifset
+@end ifset
+
+Case of letters is significant: @code{foo} is a different symbol name
+than @code{Foo}.
+
+Each symbol has exactly one name. Each name in an assembly language program
+refers to exactly one symbol. You may use that symbol name any number of times
+in a program.
+
+@subheading Local Symbol Names
+
+@cindex local symbol names
+@cindex symbol names, local
+@cindex temporary symbol names
+@cindex symbol names, temporary
+Local symbols help compilers and programmers use names temporarily.
+There are ten local symbol names, which are re-used throughout the
+program. You may refer to them using the names @samp{0} @samp{1}
+@dots{} @samp{9}. To define a local symbol, write a label of the form
+@samp{@b{N}:} (where @b{N} represents any digit). To refer to the most
+recent previous definition of that symbol write @samp{@b{N}b}, using the
+same digit as when you defined the label. To refer to the next
+definition of a local label, write @samp{@b{N}f}---where @b{N} gives you
+a choice of 10 forward references. The @samp{b} stands for
+``backwards'' and the @samp{f} stands for ``forwards''.
+
+Local symbols are not emitted by the current @sc{gnu} C compiler.
+
+There is no restriction on how you can use these labels, but
+remember that at any point in the assembly you can refer to at most
+10 prior local labels and to at most 10 forward local labels.
+
+Local symbol names are only a notation device. They are immediately
+transformed into more conventional symbol names before the assembler
+uses them. The symbol names stored in the symbol table, appearing in
+error messages and optionally emitted to the object file have these
+parts:
+
+@table @code
+@item L
+All local labels begin with @samp{L}. Normally both @code{@value{AS}} and
+@code{@value{LD}} forget symbols that start with @samp{L}. These labels are
+used for symbols you are never intended to see. If you use the
+@samp{-L} option then @code{@value{AS}} retains these symbols in the
+object file. If you also instruct @code{@value{LD}} to retain these symbols,
+you may use them in debugging.
+
+@item @var{digit}
+If the label is written @samp{0:} then the digit is @samp{0}.
+If the label is written @samp{1:} then the digit is @samp{1}.
+And so on up through @samp{9:}.
+
+@item @kbd{C-A}
+This unusual character is included so you do not accidentally invent
+a symbol of the same name. The character has ASCII value
+@samp{\001}.
+
+@item @emph{ordinal number}
+This is a serial number to keep the labels distinct. The first
+@samp{0:} gets the number @samp{1}; The 15th @samp{0:} gets the
+number @samp{15}; @emph{etc.}. Likewise for the other labels @samp{1:}
+through @samp{9:}.
+@end table
+
+For instance, the first @code{1:} is named @code{L1@kbd{C-A}1}, the 44th
+@code{3:} is named @code{L3@kbd{C-A}44}.
+
+@node Dot
+@section The Special Dot Symbol
+
+@cindex dot (symbol)
+@cindex @code{.} (symbol)
+@cindex current address
+@cindex location counter
+The special symbol @samp{.} refers to the current address that
+@code{@value{AS}} is assembling into. Thus, the expression @samp{melvin:
+.long .} defines @code{melvin} to contain its own address.
+Assigning a value to @code{.} is treated the same as a @code{.org}
+directive. Thus, the expression @samp{.=.+4} is the same as saying
+@ifclear no-space-dir
+@samp{.space 4}.
+@end ifclear
+@ifset no-space-dir
+@ifset A29K
+@samp{.block 4}.
+@end ifset
+@end ifset
+
+@node Symbol Attributes
+@section Symbol Attributes
+
+@cindex symbol attributes
+@cindex attributes, symbol
+Every symbol has, as well as its name, the attributes ``Value'' and
+``Type''. Depending on output format, symbols can also have auxiliary
+attributes.
+@ifset INTERNALS
+The detailed definitions are in @file{a.out.h}.
+@end ifset
+
+If you use a symbol without defining it, @code{@value{AS}} assumes zero for
+all these attributes, and probably won't warn you. This makes the
+symbol an externally defined symbol, which is generally what you
+would want.
+
+@menu
+* Symbol Value:: Value
+* Symbol Type:: Type
+@ifset aout-bout
+@ifset GENERIC
+* a.out Symbols:: Symbol Attributes: @code{a.out}
+@end ifset
+@ifclear GENERIC
+@ifclear BOUT
+* a.out Symbols:: Symbol Attributes: @code{a.out}
+@end ifclear
+@ifset BOUT
+* a.out Symbols:: Symbol Attributes: @code{a.out}, @code{b.out}
+@end ifset
+@end ifclear
+@end ifset
+@ifset COFF
+* COFF Symbols:: Symbol Attributes for COFF
+@end ifset
+@ifset SOM
+* SOM Symbols:: Symbol Attributes for SOM
+@end ifset
+@end menu
+
+@node Symbol Value
+@subsection Value
+
+@cindex value of a symbol
+@cindex symbol value
+The value of a symbol is (usually) 32 bits. For a symbol which labels a
+location in the text, data, bss or absolute sections the value is the
+number of addresses from the start of that section to the label.
+Naturally for text, data and bss sections the value of a symbol changes
+as @code{@value{LD}} changes section base addresses during linking. Absolute
+symbols' values do not change during linking: that is why they are
+called absolute.
+
+The value of an undefined symbol is treated in a special way. If it is
+0 then the symbol is not defined in this assembler source file, and
+@code{@value{LD}} tries to determine its value from other files linked into the
+same program. You make this kind of symbol simply by mentioning a symbol
+name without defining it. A non-zero value represents a @code{.comm}
+common declaration. The value is how much common storage to reserve, in
+bytes (addresses). The symbol refers to the first address of the
+allocated storage.
+
+@node Symbol Type
+@subsection Type
+
+@cindex type of a symbol
+@cindex symbol type
+The type attribute of a symbol contains relocation (section)
+information, any flag settings indicating that a symbol is external, and
+(optionally), other information for linkers and debuggers. The exact
+format depends on the object-code output format in use.
+
+@ifset aout-bout
+@ifclear GENERIC
+@ifset BOUT
+@c The following avoids a "widow" subsection title. @group would be
+@c better if it were available outside examples.
+@need 1000
+@node a.out Symbols
+@subsection Symbol Attributes: @code{a.out}, @code{b.out}
+
+@cindex @code{b.out} symbol attributes
+@cindex symbol attributes, @code{b.out}
+These symbol attributes appear only when @code{@value{AS}} is configured for
+one of the Berkeley-descended object output formats---@code{a.out} or
+@code{b.out}.
+
+@end ifset
+@ifclear BOUT
+@node a.out Symbols
+@subsection Symbol Attributes: @code{a.out}
+
+@cindex @code{a.out} symbol attributes
+@cindex symbol attributes, @code{a.out}
+
+@end ifclear
+@end ifclear
+@ifset GENERIC
+@node a.out Symbols
+@subsection Symbol Attributes: @code{a.out}
+
+@cindex @code{a.out} symbol attributes
+@cindex symbol attributes, @code{a.out}
+
+@end ifset
+@menu
+* Symbol Desc:: Descriptor
+* Symbol Other:: Other
+@end menu
+
+@node Symbol Desc
+@subsubsection Descriptor
+
+@cindex descriptor, of @code{a.out} symbol
+This is an arbitrary 16-bit value. You may establish a symbol's
+descriptor value by using a @code{.desc} statement
+(@pxref{Desc,,@code{.desc}}). A descriptor value means nothing to
+@code{@value{AS}}.
+
+@node Symbol Other
+@subsubsection Other
+
+@cindex other attribute, of @code{a.out} symbol
+This is an arbitrary 8-bit value. It means nothing to @code{@value{AS}}.
+@end ifset
+
+@ifset COFF
+@node COFF Symbols
+@subsection Symbol Attributes for COFF
+
+@cindex COFF symbol attributes
+@cindex symbol attributes, COFF
+
+The COFF format supports a multitude of auxiliary symbol attributes;
+like the primary symbol attributes, they are set between @code{.def} and
+@code{.endef} directives.
+
+@subsubsection Primary Attributes
+
+@cindex primary attributes, COFF symbols
+The symbol name is set with @code{.def}; the value and type,
+respectively, with @code{.val} and @code{.type}.
+
+@subsubsection Auxiliary Attributes
+
+@cindex auxiliary attributes, COFF symbols
+The @code{@value{AS}} directives @code{.dim}, @code{.line}, @code{.scl},
+@code{.size}, and @code{.tag} can generate auxiliary symbol table
+information for COFF.
+@end ifset
+
+@ifset SOM
+@node SOM Symbols
+@subsection Symbol Attributes for SOM
+
+@cindex SOM symbol attributes
+@cindex symbol attributes, SOM
+
+The SOM format for the HPPA supports a multitude of symbol attributes set with
+the @code{.EXPORT} and @code{.IMPORT} directives.
+
+The attributes are described in @cite{HP9000 Series 800 Assembly
+Language Reference Manual} (HP 92432-90001) under the @code{IMPORT} and
+@code{EXPORT} assembler directive documentation.
+@end ifset
+
+@node Expressions
+@chapter Expressions
+
+@cindex expressions
+@cindex addresses
+@cindex numeric values
+An @dfn{expression} specifies an address or numeric value.
+Whitespace may precede and/or follow an expression.
+
+The result of an expression must be an absolute number, or else an offset into
+a particular section. If an expression is not absolute, and there is not
+enough information when @code{@value{AS}} sees the expression to know its
+section, a second pass over the source program might be necessary to interpret
+the expression---but the second pass is currently not implemented.
+@code{@value{AS}} aborts with an error message in this situation.
+
+@menu
+* Empty Exprs:: Empty Expressions
+* Integer Exprs:: Integer Expressions
+@end menu
+
+@node Empty Exprs
+@section Empty Expressions
+
+@cindex empty expressions
+@cindex expressions, empty
+An empty expression has no value: it is just whitespace or null.
+Wherever an absolute expression is required, you may omit the
+expression, and @code{@value{AS}} assumes a value of (absolute) 0. This
+is compatible with other assemblers.
+
+@node Integer Exprs
+@section Integer Expressions
+
+@cindex integer expressions
+@cindex expressions, integer
+An @dfn{integer expression} is one or more @emph{arguments} delimited
+by @emph{operators}.
+
+@menu
+* Arguments:: Arguments
+* Operators:: Operators
+* Prefix Ops:: Prefix Operators
+* Infix Ops:: Infix Operators
+@end menu
+
+@node Arguments
+@subsection Arguments
+
+@cindex expression arguments
+@cindex arguments in expressions
+@cindex operands in expressions
+@cindex arithmetic operands
+@dfn{Arguments} are symbols, numbers or subexpressions. In other
+contexts arguments are sometimes called ``arithmetic operands''. In
+this manual, to avoid confusing them with the ``instruction operands'' of
+the machine language, we use the term ``argument'' to refer to parts of
+expressions only, reserving the word ``operand'' to refer only to machine
+instruction operands.
+
+Symbols are evaluated to yield @{@var{section} @var{NNN}@} where
+@var{section} is one of text, data, bss, absolute,
+or undefined. @var{NNN} is a signed, 2's complement 32 bit
+integer.
+
+Numbers are usually integers.
+
+A number can be a flonum or bignum. In this case, you are warned
+that only the low order 32 bits are used, and @code{@value{AS}} pretends
+these 32 bits are an integer. You may write integer-manipulating
+instructions that act on exotic constants, compatible with other
+assemblers.
+
+@cindex subexpressions
+Subexpressions are a left parenthesis @samp{(} followed by an integer
+expression, followed by a right parenthesis @samp{)}; or a prefix
+operator followed by an argument.
+
+@node Operators
+@subsection Operators
+
+@cindex operators, in expressions
+@cindex arithmetic functions
+@cindex functions, in expressions
+@dfn{Operators} are arithmetic functions, like @code{+} or @code{%}. Prefix
+operators are followed by an argument. Infix operators appear
+between their arguments. Operators may be preceded and/or followed by
+whitespace.
+
+@node Prefix Ops
+@subsection Prefix Operator
+
+@cindex prefix operators
+@code{@value{AS}} has the following @dfn{prefix operators}. They each take
+one argument, which must be absolute.
+
+@c the tex/end tex stuff surrounding this small table is meant to make
+@c it align, on the printed page, with the similar table in the next
+@c section (which is inside an enumerate).
+@tex
+\global\advance\leftskip by \itemindent
+@end tex
+
+@table @code
+@item -
+@dfn{Negation}. Two's complement negation.
+@item ~
+@dfn{Complementation}. Bitwise not.
+@end table
+
+@tex
+\global\advance\leftskip by -\itemindent
+@end tex
+
+@node Infix Ops
+@subsection Infix Operators
+
+@cindex infix operators
+@cindex operators, permitted arguments
+@dfn{Infix operators} take two arguments, one on either side. Operators
+have precedence, but operations with equal precedence are performed left
+to right. Apart from @code{+} or @code{-}, both arguments must be
+absolute, and the result is absolute.
+
+@enumerate
+@cindex operator precedence
+@cindex precedence of operators
+
+@item
+Highest Precedence
+
+@table @code
+@item *
+@dfn{Multiplication}.
+
+@item /
+@dfn{Division}. Truncation is the same as the C operator @samp{/}
+
+@item %
+@dfn{Remainder}.
+
+@item <
+@itemx <<
+@dfn{Shift Left}. Same as the C operator @samp{<<}.
+
+@item >
+@itemx >>
+@dfn{Shift Right}. Same as the C operator @samp{>>}.
+@end table
+
+@item
+Intermediate precedence
+
+@table @code
+@item |
+
+@dfn{Bitwise Inclusive Or}.
+
+@item &
+@dfn{Bitwise And}.
+
+@item ^
+@dfn{Bitwise Exclusive Or}.
+
+@item !
+@dfn{Bitwise Or Not}.
+@end table
+
+@item
+Lowest Precedence
+
+@table @code
+@cindex addition, permitted arguments
+@cindex plus, permitted arguments
+@cindex arguments for addition
+@item +
+@dfn{Addition}. If either argument is absolute, the result has the section of
+the other argument. You may not add together arguments from different
+sections.
+
+@cindex subtraction, permitted arguments
+@cindex minus, permitted arguments
+@cindex arguments for subtraction
+@item -
+@dfn{Subtraction}. If the right argument is absolute, the
+result has the section of the left argument.
+If both arguments are in the same section, the result is absolute.
+You may not subtract arguments from different sections.
+@c FIXME is there still something useful to say about undefined - undefined ?
+@end table
+@end enumerate
+
+In short, it's only meaningful to add or subtract the @emph{offsets} in an
+address; you can only have a defined section in one of the two arguments.
+
+@node Pseudo Ops
+@chapter Assembler Directives
+
+@cindex directives, machine independent
+@cindex pseudo-ops, machine independent
+@cindex machine independent directives
+All assembler directives have names that begin with a period (@samp{.}).
+The rest of the name is letters, usually in lower case.
+
+This chapter discusses directives that are available regardless of the
+target machine configuration for the @sc{gnu} assembler.
+@ifset GENERIC
+Some machine configurations provide additional directives.
+@xref{Machine Dependencies}.
+@end ifset
+@ifclear GENERIC
+@ifset machine-directives
+@xref{Machine Dependencies} for additional directives.
+@end ifset
+@end ifclear
+
+@menu
+* Abort:: @code{.abort}
+@ifset COFF
+* ABORT:: @code{.ABORT}
+@end ifset
+
+* Align:: @code{.align @var{abs-expr} , @var{abs-expr}}
+* Ascii:: @code{.ascii "@var{string}"}@dots{}
+* Asciz:: @code{.asciz "@var{string}"}@dots{}
+* Balign:: @code{.balign @var{abs-expr} , @var{abs-expr}}
+* Byte:: @code{.byte @var{expressions}}
+* Comm:: @code{.comm @var{symbol} , @var{length} }
+* Data:: @code{.data @var{subsection}}
+@ifset COFF
+* Def:: @code{.def @var{name}}
+@end ifset
+@ifset aout-bout
+* Desc:: @code{.desc @var{symbol}, @var{abs-expression}}
+@end ifset
+@ifset COFF
+* Dim:: @code{.dim}
+@end ifset
+
+* Double:: @code{.double @var{flonums}}
+* Eject:: @code{.eject}
+* Else:: @code{.else}
+* End:: @code{.end}
+@ifset COFF
+* Endef:: @code{.endef}
+@end ifset
+
+* Endfunc:: @code{.endfunc}
+* Endif:: @code{.endif}
+* Equ:: @code{.equ @var{symbol}, @var{expression}}
+* Equiv:: @code{.equiv @var{symbol}, @var{expression}}
+* Err:: @code{.err}
+* Exitm:: @code{.exitm}
+* Extern:: @code{.extern}
+* Fail:: @code{.fail}
+@ifclear no-file-dir
+* File:: @code{.file @var{string}}
+@end ifclear
+
+* Fill:: @code{.fill @var{repeat} , @var{size} , @var{value}}
+* Float:: @code{.float @var{flonums}}
+* Func:: @code{.func}
+* Global:: @code{.global @var{symbol}}, @code{.globl @var{symbol}}
+* hword:: @code{.hword @var{expressions}}
+* Ident:: @code{.ident}
+* If:: @code{.if @var{absolute expression}}
+* Include:: @code{.include "@var{file}"}
+* Int:: @code{.int @var{expressions}}
+* Irp:: @code{.irp @var{symbol},@var{values}}@dots{}
+* Irpc:: @code{.irpc @var{symbol},@var{values}}@dots{}
+* Lcomm:: @code{.lcomm @var{symbol} , @var{length}}
+* Lflags:: @code{.lflags}
+@ifclear no-line-dir
+* Line:: @code{.line @var{line-number}}
+@end ifclear
+
+* Ln:: @code{.ln @var{line-number}}
+* Linkonce:: @code{.linkonce [@var{type}]}
+* List:: @code{.list}
+* Long:: @code{.long @var{expressions}}
+@ignore
+* Lsym:: @code{.lsym @var{symbol}, @var{expression}}
+@end ignore
+
+* Macro:: @code{.macro @var{name} @var{args}}@dots{}
+* MRI:: @code{.mri @var{val}}
+
+* Nolist:: @code{.nolist}
+* Octa:: @code{.octa @var{bignums}}
+* Org:: @code{.org @var{new-lc} , @var{fill}}
+* P2align:: @code{.p2align @var{abs-expr} , @var{abs-expr}}
+* Print:: @code{.print @var{string}}
+* Psize:: @code{.psize @var{lines}, @var{columns}}
+* Purgem:: @code{.purgem @var{name}}
+* Quad:: @code{.quad @var{bignums}}
+* Rept:: @code{.rept @var{count}}
+* Sbttl:: @code{.sbttl "@var{subheading}"}
+@ifset COFF
+* Scl:: @code{.scl @var{class}}
+* Section:: @code{.section @var{name}, @var{subsection}}
+@end ifset
+
+* Set:: @code{.set @var{symbol}, @var{expression}}
+* Short:: @code{.short @var{expressions}}
+* Single:: @code{.single @var{flonums}}
+@ifset COFF
+* Size:: @code{.size}
+@end ifset
+
+* Skip:: @code{.skip @var{size} , @var{fill}}
+* Sleb128:: @code{.sleb128 @var{expressions}}
+* Space:: @code{.space @var{size} , @var{fill}}
+@ifset have-stabs
+* Stab:: @code{.stabd, .stabn, .stabs}
+@end ifset
+
+* String:: @code{.string "@var{str}"}
+* Struct:: @code{.struct @var{expression}}
+@ifset ELF
+* Symver:: @code{.symver @var{name},@var{name2@@nodename}}
+@end ifset
+@ifset COFF
+* Tag:: @code{.tag @var{structname}}
+@end ifset
+
+* Text:: @code{.text @var{subsection}}
+* Title:: @code{.title "@var{heading}"}
+@ifset COFF
+* Type:: @code{.type @var{int}}
+* Val:: @code{.val @var{addr}}
+@end ifset
+
+* Uleb128:: @code{.uleb128 @var{expressions}}
+* Word:: @code{.word @var{expressions}}
+* Deprecated:: Deprecated Directives
+@end menu
+
+@node Abort
+@section @code{.abort}
+
+@cindex @code{abort} directive
+@cindex stopping the assembly
+This directive stops the assembly immediately. It is for
+compatibility with other assemblers. The original idea was that the
+assembly language source would be piped into the assembler. If the sender
+of the source quit, it could use this directive tells @code{@value{AS}} to
+quit also. One day @code{.abort} will not be supported.
+
+@ifset COFF
+@node ABORT
+@section @code{.ABORT}
+
+@cindex @code{ABORT} directive
+When producing COFF output, @code{@value{AS}} accepts this directive as a
+synonym for @samp{.abort}.
+
+@ifset BOUT
+When producing @code{b.out} output, @code{@value{AS}} accepts this directive,
+but ignores it.
+@end ifset
+@end ifset
+
+@node Align
+@section @code{.align @var{abs-expr}, @var{abs-expr}, @var{abs-expr}}
+
+@cindex padding the location counter
+@cindex @code{align} directive
+Pad the location counter (in the current subsection) to a particular storage
+boundary. The first expression (which must be absolute) is the alignment
+required, as described below.
+
+The second expression (also absolute) gives the fill value to be stored in the
+padding bytes. It (and the comma) may be omitted. If it is omitted, the
+padding bytes are normally zero. However, on some systems, if the section is
+marked as containing code and the fill value is omitted, the space is filled
+with no-op instructions.
+
+The third expression is also absolute, and is also optional. If it is present,
+it is the maximum number of bytes that should be skipped by this alignment
+directive. If doing the alignment would require skipping more bytes than the
+specified maximum, then the alignment is not done at all. You can omit the
+fill value (the second argument) entirely by simply using two commas after the
+required alignment; this can be useful if you want the alignment to be filled
+with no-op instructions when appropriate.
+
+The way the required alignment is specified varies from system to system.
+For the a29k, hppa, m68k, m88k, w65, sparc, and Hitachi SH, and i386 using ELF
+format,
+the first expression is the
+alignment request in bytes. For example @samp{.align 8} advances
+the location counter until it is a multiple of 8. If the location counter
+is already a multiple of 8, no change is needed.
+
+For other systems, including the i386 using a.out format, it is the
+number of low-order zero bits the location counter must have after
+advancement. For example @samp{.align 3} advances the location
+counter until it a multiple of 8. If the location counter is already a
+multiple of 8, no change is needed.
+
+This inconsistency is due to the different behaviors of the various
+native assemblers for these systems which GAS must emulate.
+GAS also provides @code{.balign} and @code{.p2align} directives,
+described later, which have a consistent behavior across all
+architectures (but are specific to GAS).
+
+@node Ascii
+@section @code{.ascii "@var{string}"}@dots{}
+
+@cindex @code{ascii} directive
+@cindex string literals
+@code{.ascii} expects zero or more string literals (@pxref{Strings})
+separated by commas. It assembles each string (with no automatic
+trailing zero byte) into consecutive addresses.
+
+@node Asciz
+@section @code{.asciz "@var{string}"}@dots{}
+
+@cindex @code{asciz} directive
+@cindex zero-terminated strings
+@cindex null-terminated strings
+@code{.asciz} is just like @code{.ascii}, but each string is followed by
+a zero byte. The ``z'' in @samp{.asciz} stands for ``zero''.
+
+@node Balign
+@section @code{.balign[wl] @var{abs-expr}, @var{abs-expr}, @var{abs-expr}}
+
+@cindex padding the location counter given number of bytes
+@cindex @code{balign} directive
+Pad the location counter (in the current subsection) to a particular
+storage boundary. The first expression (which must be absolute) is the
+alignment request in bytes. For example @samp{.balign 8} advances
+the location counter until it is a multiple of 8. If the location counter
+is already a multiple of 8, no change is needed.
+
+The second expression (also absolute) gives the fill value to be stored in the
+padding bytes. It (and the comma) may be omitted. If it is omitted, the
+padding bytes are normally zero. However, on some systems, if the section is
+marked as containing code and the fill value is omitted, the space is filled
+with no-op instructions.
+
+The third expression is also absolute, and is also optional. If it is present,
+it is the maximum number of bytes that should be skipped by this alignment
+directive. If doing the alignment would require skipping more bytes than the
+specified maximum, then the alignment is not done at all. You can omit the
+fill value (the second argument) entirely by simply using two commas after the
+required alignment; this can be useful if you want the alignment to be filled
+with no-op instructions when appropriate.
+
+@cindex @code{balignw} directive
+@cindex @code{balignl} directive
+The @code{.balignw} and @code{.balignl} directives are variants of the
+@code{.balign} directive. The @code{.balignw} directive treats the fill
+pattern as a two byte word value. The @code{.balignl} directives treats the
+fill pattern as a four byte longword value. For example, @code{.balignw
+4,0x368d} will align to a multiple of 4. If it skips two bytes, they will be
+filled in with the value 0x368d (the exact placement of the bytes depends upon
+the endianness of the processor). If it skips 1 or 3 bytes, the fill value is
+undefined.
+
+@node Byte
+@section @code{.byte @var{expressions}}
+
+@cindex @code{byte} directive
+@cindex integers, one byte
+@code{.byte} expects zero or more expressions, separated by commas.
+Each expression is assembled into the next byte.
+
+@node Comm
+@section @code{.comm @var{symbol} , @var{length} }
+
+@cindex @code{comm} directive
+@cindex symbol, common
+@code{.comm} declares a common symbol named @var{symbol}. When linking, a
+common symbol in one object file may be merged with a defined or common symbol
+of the same name in another object file. If @code{@value{LD}} does not see a
+definition for the symbol--just one or more common symbols--then it will
+allocate @var{length} bytes of uninitialized memory. @var{length} must be an
+absolute expression. If @code{@value{LD}} sees multiple common symbols with
+the same name, and they do not all have the same size, it will allocate space
+using the largest size.
+
+@ifset ELF
+When using ELF, the @code{.comm} directive takes an optional third argument.
+This is the desired alignment of the symbol, specified as a byte boundary (for
+example, an alignment of 16 means that the least significant 4 bits of the
+address should be zero). The alignment must be an absolute expression, and it
+must be a power of two. If @code{@value{LD}} allocates uninitialized memory
+for the common symbol, it will use the alignment when placing the symbol. If
+no alignment is specified, @code{@value{AS}} will set the alignment to the
+largest power of two less than or equal to the size of the symbol, up to a
+maximum of 16.
+@end ifset
+
+@ifset HPPA
+The syntax for @code{.comm} differs slightly on the HPPA. The syntax is
+@samp{@var{symbol} .comm, @var{length}}; @var{symbol} is optional.
+@end ifset
+
+@node Data
+@section @code{.data @var{subsection}}
+
+@cindex @code{data} directive
+@code{.data} tells @code{@value{AS}} to assemble the following statements onto the
+end of the data subsection numbered @var{subsection} (which is an
+absolute expression). If @var{subsection} is omitted, it defaults
+to zero.
+
+@ifset COFF
+@node Def
+@section @code{.def @var{name}}
+
+@cindex @code{def} directive
+@cindex COFF symbols, debugging
+@cindex debugging COFF symbols
+Begin defining debugging information for a symbol @var{name}; the
+definition extends until the @code{.endef} directive is encountered.
+@ifset BOUT
+
+This directive is only observed when @code{@value{AS}} is configured for COFF
+format output; when producing @code{b.out}, @samp{.def} is recognized,
+but ignored.
+@end ifset
+@end ifset
+
+@ifset aout-bout
+@node Desc
+@section @code{.desc @var{symbol}, @var{abs-expression}}
+
+@cindex @code{desc} directive
+@cindex COFF symbol descriptor
+@cindex symbol descriptor, COFF
+This directive sets the descriptor of the symbol (@pxref{Symbol Attributes})
+to the low 16 bits of an absolute expression.
+
+@ifset COFF
+The @samp{.desc} directive is not available when @code{@value{AS}} is
+configured for COFF output; it is only for @code{a.out} or @code{b.out}
+object format. For the sake of compatibility, @code{@value{AS}} accepts
+it, but produces no output, when configured for COFF.
+@end ifset
+@end ifset
+
+@ifset COFF
+@node Dim
+@section @code{.dim}
+
+@cindex @code{dim} directive
+@cindex COFF auxiliary symbol information
+@cindex auxiliary symbol information, COFF
+This directive is generated by compilers to include auxiliary debugging
+information in the symbol table. It is only permitted inside
+@code{.def}/@code{.endef} pairs.
+@ifset BOUT
+
+@samp{.dim} is only meaningful when generating COFF format output; when
+@code{@value{AS}} is generating @code{b.out}, it accepts this directive but
+ignores it.
+@end ifset
+@end ifset
+
+@node Double
+@section @code{.double @var{flonums}}
+
+@cindex @code{double} directive
+@cindex floating point numbers (double)
+@code{.double} expects zero or more flonums, separated by commas. It
+assembles floating point numbers.
+@ifset GENERIC
+The exact kind of floating point numbers emitted depends on how
+@code{@value{AS}} is configured. @xref{Machine Dependencies}.
+@end ifset
+@ifclear GENERIC
+@ifset IEEEFLOAT
+On the @value{TARGET} family @samp{.double} emits 64-bit floating-point numbers
+in @sc{ieee} format.
+@end ifset
+@end ifclear
+
+@node Eject
+@section @code{.eject}
+
+@cindex @code{eject} directive
+@cindex new page, in listings
+@cindex page, in listings
+@cindex listing control: new page
+Force a page break at this point, when generating assembly listings.
+
+@node Else
+@section @code{.else}
+
+@cindex @code{else} directive
+@code{.else} is part of the @code{@value{AS}} support for conditional
+assembly; @pxref{If,,@code{.if}}. It marks the beginning of a section
+of code to be assembled if the condition for the preceding @code{.if}
+was false.
+
+@node End
+@section @code{.end}
+
+@cindex @code{end} directive
+@code{.end} marks the end of the assembly file. @code{@value{AS}} does not
+process anything in the file past the @code{.end} directive.
+
+@ifset COFF
+@node Endef
+@section @code{.endef}
+
+@cindex @code{endef} directive
+This directive flags the end of a symbol definition begun with
+@code{.def}.
+@ifset BOUT
+
+@samp{.endef} is only meaningful when generating COFF format output; if
+@code{@value{AS}} is configured to generate @code{b.out}, it accepts this
+directive but ignores it.
+@end ifset
+@end ifset
+
+@node Endfunc
+@section @code{.endfunc}
+@cindex @code{endfunc} directive
+@code{.endfunc} marks the end of a function specified with @code{.func}.
+
+@node Endif
+@section @code{.endif}
+
+@cindex @code{endif} directive
+@code{.endif} is part of the @code{@value{AS}} support for conditional assembly;
+it marks the end of a block of code that is only assembled
+conditionally. @xref{If,,@code{.if}}.
+
+@node Equ
+@section @code{.equ @var{symbol}, @var{expression}}
+
+@cindex @code{equ} directive
+@cindex assigning values to symbols
+@cindex symbols, assigning values to
+This directive sets the value of @var{symbol} to @var{expression}.
+It is synonymous with @samp{.set}; @pxref{Set,,@code{.set}}.
+
+@ifset HPPA
+The syntax for @code{equ} on the HPPA is
+@samp{@var{symbol} .equ @var{expression}}.
+@end ifset
+
+@node Equiv
+@section @code{.equiv @var{symbol}, @var{expression}}
+@cindex @code{equiv} directive
+The @code{.equiv} directive is like @code{.equ} and @code{.set}, except that
+the assembler will signal an error if @var{symbol} is already defined.
+
+Except for the contents of the error message, this is roughly equivalent to
+@smallexample
+.ifdef SYM
+.err
+.endif
+.equ SYM,VAL
+@end smallexample
+
+@node Err
+@section @code{.err}
+@cindex @code{err} directive
+If @code{@value{AS}} assembles a @code{.err} directive, it will print an error
+message and, unless the @code{-Z} option was used, it will not generate an
+object file. This can be used to signal error an conditionally compiled code.
+
+@node Exitm
+@section @code{.exitm}
+Exit early from the current macro definition. @xref{Macro}.
+
+@node Extern
+@section @code{.extern}
+
+@cindex @code{extern} directive
+@code{.extern} is accepted in the source program---for compatibility
+with other assemblers---but it is ignored. @code{@value{AS}} treats
+all undefined symbols as external.
+
+@node Fail
+@section @code{.fail @var{expression}}
+
+@cindex @code{fail} directive
+Generates an error or a warning. If the value of the @var{expression} is 500
+or more, @code{@value{AS}} will print a warning message. If the value is less
+than 500, @code{@value{AS}} will print an error message. The message will
+include the value of @var{expression}. This can occasionally be useful inside
+complex nested macros or conditional assembly.
+
+@ifclear no-file-dir
+@node File
+@section @code{.file @var{string}}
+
+@cindex @code{file} directive
+@cindex logical file name
+@cindex file name, logical
+@code{.file} tells @code{@value{AS}} that we are about to start a new logical
+file. @var{string} is the new file name. In general, the filename is
+recognized whether or not it is surrounded by quotes @samp{"}; but if you wish
+to specify an empty file name, you must give the quotes--@code{""}. This
+statement may go away in future: it is only recognized to be compatible with
+old @code{@value{AS}} programs.
+@ifset A29K
+In some configurations of @code{@value{AS}}, @code{.file} has already been
+removed to avoid conflicts with other assemblers. @xref{Machine Dependencies}.
+@end ifset
+@end ifclear
+
+@node Fill
+@section @code{.fill @var{repeat} , @var{size} , @var{value}}
+
+@cindex @code{fill} directive
+@cindex writing patterns in memory
+@cindex patterns, writing in memory
+@var{result}, @var{size} and @var{value} are absolute expressions.
+This emits @var{repeat} copies of @var{size} bytes. @var{Repeat}
+may be zero or more. @var{Size} may be zero or more, but if it is
+more than 8, then it is deemed to have the value 8, compatible with
+other people's assemblers. The contents of each @var{repeat} bytes
+is taken from an 8-byte number. The highest order 4 bytes are
+zero. The lowest order 4 bytes are @var{value} rendered in the
+byte-order of an integer on the computer @code{@value{AS}} is assembling for.
+Each @var{size} bytes in a repetition is taken from the lowest order
+@var{size} bytes of this number. Again, this bizarre behavior is
+compatible with other people's assemblers.
+
+@var{size} and @var{value} are optional.
+If the second comma and @var{value} are absent, @var{value} is
+assumed zero. If the first comma and following tokens are absent,
+@var{size} is assumed to be 1.
+
+@node Float
+@section @code{.float @var{flonums}}
+
+@cindex floating point numbers (single)
+@cindex @code{float} directive
+This directive assembles zero or more flonums, separated by commas. It
+has the same effect as @code{.single}.
+@ifset GENERIC
+The exact kind of floating point numbers emitted depends on how
+@code{@value{AS}} is configured.
+@xref{Machine Dependencies}.
+@end ifset
+@ifclear GENERIC
+@ifset IEEEFLOAT
+On the @value{TARGET} family, @code{.float} emits 32-bit floating point numbers
+in @sc{ieee} format.
+@end ifset
+@end ifclear
+
+@node Func
+@section @code{.func @var{name}[,@var{label}]}
+@cindex @code{func} directive
+@code{.func} emits debugging information to denote function @var{name}, and
+is ignored unless the file is assembled with debugging enabled.
+Only @samp{--gstabs} is currently supported.
+@var{label} is the entry point of the function and if omitted @var{name}
+prepended with the @samp{leading char} is used.
+@samp{leading char} is usually @code{_} or nothing, depending on the target.
+All functions are currently defined to have @code{void} return type.
+The function must be terminated with @code{.endfunc}.
+
+@node Global
+@section @code{.global @var{symbol}}, @code{.globl @var{symbol}}
+
+@cindex @code{global} directive
+@cindex symbol, making visible to linker
+@code{.global} makes the symbol visible to @code{@value{LD}}. If you define
+@var{symbol} in your partial program, its value is made available to
+other partial programs that are linked with it. Otherwise,
+@var{symbol} takes its attributes from a symbol of the same name
+from another file linked into the same program.
+
+Both spellings (@samp{.globl} and @samp{.global}) are accepted, for
+compatibility with other assemblers.
+
+@ifset HPPA
+On the HPPA, @code{.global} is not always enough to make it accessible to other
+partial programs. You may need the HPPA-only @code{.EXPORT} directive as well.
+@xref{HPPA Directives,, HPPA Assembler Directives}.
+@end ifset
+
+@node hword
+@section @code{.hword @var{expressions}}
+
+@cindex @code{hword} directive
+@cindex integers, 16-bit
+@cindex numbers, 16-bit
+@cindex sixteen bit integers
+This expects zero or more @var{expressions}, and emits
+a 16 bit number for each.
+
+@ifset GENERIC
+This directive is a synonym for @samp{.short}; depending on the target
+architecture, it may also be a synonym for @samp{.word}.
+@end ifset
+@ifclear GENERIC
+@ifset W32
+This directive is a synonym for @samp{.short}.
+@end ifset
+@ifset W16
+This directive is a synonym for both @samp{.short} and @samp{.word}.
+@end ifset
+@end ifclear
+
+@node Ident
+@section @code{.ident}
+
+@cindex @code{ident} directive
+This directive is used by some assemblers to place tags in object files.
+@code{@value{AS}} simply accepts the directive for source-file
+compatibility with such assemblers, but does not actually emit anything
+for it.
+
+@node If
+@section @code{.if @var{absolute expression}}
+
+@cindex conditional assembly
+@cindex @code{if} directive
+@code{.if} marks the beginning of a section of code which is only
+considered part of the source program being assembled if the argument
+(which must be an @var{absolute expression}) is non-zero. The end of
+the conditional section of code must be marked by @code{.endif}
+(@pxref{Endif,,@code{.endif}}); optionally, you may include code for the
+alternative condition, flagged by @code{.else} (@pxref{Else,,@code{.else}}).
+
+The following variants of @code{.if} are also supported:
+@table @code
+@cindex @code{ifdef} directive
+@item .ifdef @var{symbol}
+Assembles the following section of code if the specified @var{symbol}
+has been defined.
+
+@cindex @code{ifc} directive
+@item .ifc @var{string1},@var{string2}
+Assembles the following section of code if the two strings are the same. The
+strings may be optionally quoted with single quotes. If they are not quoted,
+the first string stops at the first comma, and the second string stops at the
+end of the line. Strings which contain whitespace should be quoted. The
+string comparison is case sensitive.
+
+@cindex @code{ifeq} directive
+@item .ifeq @var{absolute expression}
+Assembles the following section of code if the argument is zero.
+
+@cindex @code{ifeqs} directive
+@item .ifeqs @var{string1},@var{string2}
+Another form of @code{.ifc}. The strings must be quoted using double quotes.
+
+@cindex @code{ifge} directive
+@item .ifge @var{absolute expression}
+Assembles the following section of code if the argument is greater than or
+equal to zero.
+
+@cindex @code{ifgt} directive
+@item .ifgt @var{absolute expression}
+Assembles the following section of code if the argument is greater than zero.
+
+@cindex @code{ifle} directive
+@item .ifle @var{absolute expression}
+Assembles the following section of code if the argument is less than or equal
+to zero.
+
+@cindex @code{iflt} directive
+@item .iflt @var{absolute expression}
+Assembles the following section of code if the argument is less than zero.
+
+@cindex @code{ifnc} directive
+@item .ifnc @var{string1},@var{string2}.
+Like @code{.ifc}, but the sense of the test is reversed: this assembles the
+following section of code if the two strings are not the same.
+
+@cindex @code{ifndef} directive
+@cindex @code{ifnotdef} directive
+@item .ifndef @var{symbol}
+@itemx .ifnotdef @var{symbol}
+Assembles the following section of code if the specified @var{symbol}
+has not been defined. Both spelling variants are equivalent.
+
+@cindex @code{ifne} directive
+@item .ifne @var{absolute expression}
+Assembles the following section of code if the argument is not equal to zero
+(in other words, this is equivalent to @code{.if}).
+
+@cindex @code{ifnes} directive
+@item .ifnes @var{string1},@var{string2}
+Like @code{.ifeqs}, but the sense of the test is reversed: this assembles the
+following section of code if the two strings are not the same.
+@end table
+
+@node Include
+@section @code{.include "@var{file}"}
+
+@cindex @code{include} directive
+@cindex supporting files, including
+@cindex files, including
+This directive provides a way to include supporting files at specified
+points in your source program. The code from @var{file} is assembled as
+if it followed the point of the @code{.include}; when the end of the
+included file is reached, assembly of the original file continues. You
+can control the search paths used with the @samp{-I} command-line option
+(@pxref{Invoking,,Command-Line Options}). Quotation marks are required
+around @var{file}.
+
+@node Int
+@section @code{.int @var{expressions}}
+
+@cindex @code{int} directive
+@cindex integers, 32-bit
+Expect zero or more @var{expressions}, of any section, separated by commas.
+For each expression, emit a number that, at run time, is the value of that
+expression. The byte order and bit size of the number depends on what kind
+of target the assembly is for.
+
+@ifclear GENERIC
+@ifset H8
+On the H8/500 and most forms of the H8/300, @code{.int} emits 16-bit
+integers. On the H8/300H and the Hitachi SH, however, @code{.int} emits
+32-bit integers.
+@end ifset
+@end ifclear
+
+@node Irp
+@section @code{.irp @var{symbol},@var{values}}@dots{}
+
+@cindex @code{irp} directive
+Evaluate a sequence of statements assigning different values to @var{symbol}.
+The sequence of statements starts at the @code{.irp} directive, and is
+terminated by an @code{.endr} directive. For each @var{value}, @var{symbol} is
+set to @var{value}, and the sequence of statements is assembled. If no
+@var{value} is listed, the sequence of statements is assembled once, with
+@var{symbol} set to the null string. To refer to @var{symbol} within the
+sequence of statements, use @var{\symbol}.
+
+For example, assembling
+
+@example
+ .irp param,1,2,3
+ move d\param,sp@@-
+ .endr
+@end example
+
+is equivalent to assembling
+
+@example
+ move d1,sp@@-
+ move d2,sp@@-
+ move d3,sp@@-
+@end example
+
+@node Irpc
+@section @code{.irpc @var{symbol},@var{values}}@dots{}
+
+@cindex @code{irpc} directive
+Evaluate a sequence of statements assigning different values to @var{symbol}.
+The sequence of statements starts at the @code{.irpc} directive, and is
+terminated by an @code{.endr} directive. For each character in @var{value},
+@var{symbol} is set to the character, and the sequence of statements is
+assembled. If no @var{value} is listed, the sequence of statements is
+assembled once, with @var{symbol} set to the null string. To refer to
+@var{symbol} within the sequence of statements, use @var{\symbol}.
+
+For example, assembling
+
+@example
+ .irpc param,123
+ move d\param,sp@@-
+ .endr
+@end example
+
+is equivalent to assembling
+
+@example
+ move d1,sp@@-
+ move d2,sp@@-
+ move d3,sp@@-
+@end example
+
+@node Lcomm
+@section @code{.lcomm @var{symbol} , @var{length}}
+
+@cindex @code{lcomm} directive
+@cindex local common symbols
+@cindex symbols, local common
+Reserve @var{length} (an absolute expression) bytes for a local common
+denoted by @var{symbol}. The section and value of @var{symbol} are
+those of the new local common. The addresses are allocated in the bss
+section, so that at run-time the bytes start off zeroed. @var{Symbol}
+is not declared global (@pxref{Global,,@code{.global}}), so is normally
+not visible to @code{@value{LD}}.
+
+@ifset GENERIC
+Some targets permit a third argument to be used with @code{.lcomm}. This
+argument specifies the desired alignment of the symbol in the bss section.
+@end ifset
+
+@ifset HPPA
+The syntax for @code{.lcomm} differs slightly on the HPPA. The syntax is
+@samp{@var{symbol} .lcomm, @var{length}}; @var{symbol} is optional.
+@end ifset
+
+@node Lflags
+@section @code{.lflags}
+
+@cindex @code{lflags} directive (ignored)
+@code{@value{AS}} accepts this directive, for compatibility with other
+assemblers, but ignores it.
+
+@ifclear no-line-dir
+@node Line
+@section @code{.line @var{line-number}}
+
+@cindex @code{line} directive
+@end ifclear
+@ifset no-line-dir
+@node Ln
+@section @code{.ln @var{line-number}}
+
+@cindex @code{ln} directive
+@end ifset
+@cindex logical line number
+@ifset aout-bout
+Change the logical line number. @var{line-number} must be an absolute
+expression. The next line has that logical line number. Therefore any other
+statements on the current line (after a statement separator character) are
+reported as on logical line number @var{line-number} @minus{} 1. One day
+@code{@value{AS}} will no longer support this directive: it is recognized only
+for compatibility with existing assembler programs.
+
+@ifset GENERIC
+@ifset A29K
+@emph{Warning:} In the AMD29K configuration of @value{AS}, this command is
+not available; use the synonym @code{.ln} in that context.
+@end ifset
+@end ifset
+@end ifset
+
+@ifclear no-line-dir
+Even though this is a directive associated with the @code{a.out} or
+@code{b.out} object-code formats, @code{@value{AS}} still recognizes it
+when producing COFF output, and treats @samp{.line} as though it
+were the COFF @samp{.ln} @emph{if} it is found outside a
+@code{.def}/@code{.endef} pair.
+
+Inside a @code{.def}, @samp{.line} is, instead, one of the directives
+used by compilers to generate auxiliary symbol information for
+debugging.
+@end ifclear
+
+@node Linkonce
+@section @code{.linkonce [@var{type}]}
+@cindex COMDAT
+@cindex @code{linkonce} directive
+@cindex common sections
+Mark the current section so that the linker only includes a single copy of it.
+This may be used to include the same section in several different object files,
+but ensure that the linker will only include it once in the final output file.
+The @code{.linkonce} pseudo-op must be used for each instance of the section.
+Duplicate sections are detected based on the section name, so it should be
+unique.
+
+This directive is only supported by a few object file formats; as of this
+writing, the only object file format which supports it is the Portable
+Executable format used on Windows NT.
+
+The @var{type} argument is optional. If specified, it must be one of the
+following strings. For example:
+@smallexample
+.linkonce same_size
+@end smallexample
+Not all types may be supported on all object file formats.
+
+@table @code
+@item discard
+Silently discard duplicate sections. This is the default.
+
+@item one_only
+Warn if there are duplicate sections, but still keep only one copy.
+
+@item same_size
+Warn if any of the duplicates have different sizes.
+
+@item same_contents
+Warn if any of the duplicates do not have exactly the same contents.
+@end table
+
+@node Ln
+@section @code{.ln @var{line-number}}
+
+@cindex @code{ln} directive
+@ifclear no-line-dir
+@samp{.ln} is a synonym for @samp{.line}.
+@end ifclear
+@ifset no-line-dir
+Tell @code{@value{AS}} to change the logical line number. @var{line-number}
+must be an absolute expression. The next line has that logical
+line number, so any other statements on the current line (after a
+statement separator character @code{;}) are reported as on logical
+line number @var{line-number} @minus{} 1.
+@ifset BOUT
+
+This directive is accepted, but ignored, when @code{@value{AS}} is
+configured for @code{b.out}; its effect is only associated with COFF
+output format.
+@end ifset
+@end ifset
+
+@node MRI
+@section @code{.mri @var{val}}
+
+@cindex @code{mri} directive
+@cindex MRI mode, temporarily
+If @var{val} is non-zero, this tells @code{@value{AS}} to enter MRI mode. If
+@var{val} is zero, this tells @code{@value{AS}} to exit MRI mode. This change
+affects code assembled until the next @code{.mri} directive, or until the end
+of the file. @xref{M, MRI mode, MRI mode}.
+
+@node List
+@section @code{.list}
+
+@cindex @code{list} directive
+@cindex listing control, turning on
+Control (in conjunction with the @code{.nolist} directive) whether or
+not assembly listings are generated. These two directives maintain an
+internal counter (which is zero initially). @code{.list} increments the
+counter, and @code{.nolist} decrements it. Assembly listings are
+generated whenever the counter is greater than zero.
+
+By default, listings are disabled. When you enable them (with the
+@samp{-a} command line option; @pxref{Invoking,,Command-Line Options}),
+the initial value of the listing counter is one.
+
+@node Long
+@section @code{.long @var{expressions}}
+
+@cindex @code{long} directive
+@code{.long} is the same as @samp{.int}, @pxref{Int,,@code{.int}}.
+
+@ignore
+@c no one seems to know what this is for or whether this description is
+@c what it really ought to do
+@node Lsym
+@section @code{.lsym @var{symbol}, @var{expression}}
+
+@cindex @code{lsym} directive
+@cindex symbol, not referenced in assembly
+@code{.lsym} creates a new symbol named @var{symbol}, but does not put it in
+the hash table, ensuring it cannot be referenced by name during the
+rest of the assembly. This sets the attributes of the symbol to be
+the same as the expression value:
+@smallexample
+@var{other} = @var{descriptor} = 0
+@var{type} = @r{(section of @var{expression})}
+@var{value} = @var{expression}
+@end smallexample
+@noindent
+The new symbol is not flagged as external.
+@end ignore
+
+@node Macro
+@section @code{.macro}
+
+@cindex macros
+The commands @code{.macro} and @code{.endm} allow you to define macros that
+generate assembly output. For example, this definition specifies a macro
+@code{sum} that puts a sequence of numbers into memory:
+
+@example
+ .macro sum from=0, to=5
+ .long \from
+ .if \to-\from
+ sum "(\from+1)",\to
+ .endif
+ .endm
+@end example
+
+@noindent
+With that definition, @samp{SUM 0,5} is equivalent to this assembly input:
+
+@example
+ .long 0
+ .long 1
+ .long 2
+ .long 3
+ .long 4
+ .long 5
+@end example
+
+@ftable @code
+@item .macro @var{macname}
+@itemx .macro @var{macname} @var{macargs} @dots{}
+@cindex @code{macro} directive
+Begin the definition of a macro called @var{macname}. If your macro
+definition requires arguments, specify their names after the macro name,
+separated by commas or spaces. You can supply a default value for any
+macro argument by following the name with @samp{=@var{deflt}}. For
+example, these are all valid @code{.macro} statements:
+
+@table @code
+@item .macro comm
+Begin the definition of a macro called @code{comm}, which takes no
+arguments.
+
+@item .macro plus1 p, p1
+@itemx .macro plus1 p p1
+Either statement begins the definition of a macro called @code{plus1},
+which takes two arguments; within the macro definition, write
+@samp{\p} or @samp{\p1} to evaluate the arguments.
+
+@item .macro reserve_str p1=0 p2
+Begin the definition of a macro called @code{reserve_str}, with two
+arguments. The first argument has a default value, but not the second.
+After the definition is complete, you can call the macro either as
+@samp{reserve_str @var{a},@var{b}} (with @samp{\p1} evaluating to
+@var{a} and @samp{\p2} evaluating to @var{b}), or as @samp{reserve_str
+,@var{b}} (with @samp{\p1} evaluating as the default, in this case
+@samp{0}, and @samp{\p2} evaluating to @var{b}).
+@end table
+
+When you call a macro, you can specify the argument values either by
+position, or by keyword. For example, @samp{sum 9,17} is equivalent to
+@samp{sum to=17, from=9}.
+
+@item .endm
+@cindex @code{endm} directive
+Mark the end of a macro definition.
+
+@item .exitm
+@cindex @code{exitm} directive
+Exit early from the current macro definition.
+
+@cindex number of macros executed
+@cindex macros, count executed
+@item \@@
+@code{@value{AS}} maintains a counter of how many macros it has
+executed in this pseudo-variable; you can copy that number to your
+output with @samp{\@@}, but @emph{only within a macro definition}.
+
+@ignore
+@item LOCAL @var{name} [ , @dots{} ]
+@emph{Warning: @code{LOCAL} is only available if you select ``alternate
+macro syntax'' with @samp{-a} or @samp{--alternate}.} @xref{Alternate,,
+Alternate macro syntax}.
+
+Generate a string replacement for each of the @var{name} arguments, and
+replace any instances of @var{name} in each macro expansion. The
+replacement string is unique in the assembly, and different for each
+separate macro expansion. @code{LOCAL} allows you to write macros that
+define symbols, without fear of conflict between separate macro expansions.
+@end ignore
+@end ftable
+
+@node Nolist
+@section @code{.nolist}
+
+@cindex @code{nolist} directive
+@cindex listing control, turning off
+Control (in conjunction with the @code{.list} directive) whether or
+not assembly listings are generated. These two directives maintain an
+internal counter (which is zero initially). @code{.list} increments the
+counter, and @code{.nolist} decrements it. Assembly listings are
+generated whenever the counter is greater than zero.
+
+@node Octa
+@section @code{.octa @var{bignums}}
+
+@c FIXME: double size emitted for "octa" on i960, others? Or warn?
+@cindex @code{octa} directive
+@cindex integer, 16-byte
+@cindex sixteen byte integer
+This directive expects zero or more bignums, separated by commas. For each
+bignum, it emits a 16-byte integer.
+
+The term ``octa'' comes from contexts in which a ``word'' is two bytes;
+hence @emph{octa}-word for 16 bytes.
+
+@node Org
+@section @code{.org @var{new-lc} , @var{fill}}
+
+@cindex @code{org} directive
+@cindex location counter, advancing
+@cindex advancing location counter
+@cindex current address, advancing
+Advance the location counter of the current section to
+@var{new-lc}. @var{new-lc} is either an absolute expression or an
+expression with the same section as the current subsection. That is,
+you can't use @code{.org} to cross sections: if @var{new-lc} has the
+wrong section, the @code{.org} directive is ignored. To be compatible
+with former assemblers, if the section of @var{new-lc} is absolute,
+@code{@value{AS}} issues a warning, then pretends the section of @var{new-lc}
+is the same as the current subsection.
+
+@code{.org} may only increase the location counter, or leave it
+unchanged; you cannot use @code{.org} to move the location counter
+backwards.
+
+@c double negative used below "not undefined" because this is a specific
+@c reference to "undefined" (as SEG_UNKNOWN is called in this manual)
+@c section. doc@cygnus.com 18feb91
+Because @code{@value{AS}} tries to assemble programs in one pass, @var{new-lc}
+may not be undefined. If you really detest this restriction we eagerly await
+a chance to share your improved assembler.
+
+Beware that the origin is relative to the start of the section, not
+to the start of the subsection. This is compatible with other
+people's assemblers.
+
+When the location counter (of the current subsection) is advanced, the
+intervening bytes are filled with @var{fill} which should be an
+absolute expression. If the comma and @var{fill} are omitted,
+@var{fill} defaults to zero.
+
+@node P2align
+@section @code{.p2align[wl] @var{abs-expr}, @var{abs-expr}, @var{abs-expr}}
+
+@cindex padding the location counter given a power of two
+@cindex @code{p2align} directive
+Pad the location counter (in the current subsection) to a particular
+storage boundary. The first expression (which must be absolute) is the
+number of low-order zero bits the location counter must have after
+advancement. For example @samp{.p2align 3} advances the location
+counter until it a multiple of 8. If the location counter is already a
+multiple of 8, no change is needed.
+
+The second expression (also absolute) gives the fill value to be stored in the
+padding bytes. It (and the comma) may be omitted. If it is omitted, the
+padding bytes are normally zero. However, on some systems, if the section is
+marked as containing code and the fill value is omitted, the space is filled
+with no-op instructions.
+
+The third expression is also absolute, and is also optional. If it is present,
+it is the maximum number of bytes that should be skipped by this alignment
+directive. If doing the alignment would require skipping more bytes than the
+specified maximum, then the alignment is not done at all. You can omit the
+fill value (the second argument) entirely by simply using two commas after the
+required alignment; this can be useful if you want the alignment to be filled
+with no-op instructions when appropriate.
+
+@cindex @code{p2alignw} directive
+@cindex @code{p2alignl} directive
+The @code{.p2alignw} and @code{.p2alignl} directives are variants of the
+@code{.p2align} directive. The @code{.p2alignw} directive treats the fill
+pattern as a two byte word value. The @code{.p2alignl} directives treats the
+fill pattern as a four byte longword value. For example, @code{.p2alignw
+2,0x368d} will align to a multiple of 4. If it skips two bytes, they will be
+filled in with the value 0x368d (the exact placement of the bytes depends upon
+the endianness of the processor). If it skips 1 or 3 bytes, the fill value is
+undefined.
+
+@node Print
+@section @code{.print @var{string}}
+
+@cindex @code{print} directive
+@code{@value{AS}} will print @var{string} on the standard output during
+assembly. You must put @var{string} in double quotes.
+
+@node Psize
+@section @code{.psize @var{lines} , @var{columns}}
+
+@cindex @code{psize} directive
+@cindex listing control: paper size
+@cindex paper size, for listings
+Use this directive to declare the number of lines---and, optionally, the
+number of columns---to use for each page, when generating listings.
+
+If you do not use @code{.psize}, listings use a default line-count
+of 60. You may omit the comma and @var{columns} specification; the
+default width is 200 columns.
+
+@code{@value{AS}} generates formfeeds whenever the specified number of
+lines is exceeded (or whenever you explicitly request one, using
+@code{.eject}).
+
+If you specify @var{lines} as @code{0}, no formfeeds are generated save
+those explicitly specified with @code{.eject}.
+
+@node Purgem
+@section @code{.purgem @var{name}}
+
+@cindex @code{purgem} directive
+Undefine the macro @var{name}, so that later uses of the string will not be
+expanded. @xref{Macro}.
+
+@node Quad
+@section @code{.quad @var{bignums}}
+
+@cindex @code{quad} directive
+@code{.quad} expects zero or more bignums, separated by commas. For
+each bignum, it emits
+@ifclear bignum-16
+an 8-byte integer. If the bignum won't fit in 8 bytes, it prints a
+warning message; and just takes the lowest order 8 bytes of the bignum.
+@cindex eight-byte integer
+@cindex integer, 8-byte
+
+The term ``quad'' comes from contexts in which a ``word'' is two bytes;
+hence @emph{quad}-word for 8 bytes.
+@end ifclear
+@ifset bignum-16
+a 16-byte integer. If the bignum won't fit in 16 bytes, it prints a
+warning message; and just takes the lowest order 16 bytes of the bignum.
+@cindex sixteen-byte integer
+@cindex integer, 16-byte
+@end ifset
+
+@node Rept
+@section @code{.rept @var{count}}
+
+@cindex @code{rept} directive
+Repeat the sequence of lines between the @code{.rept} directive and the next
+@code{.endr} directive @var{count} times.
+
+For example, assembling
+
+@example
+ .rept 3
+ .long 0
+ .endr
+@end example
+
+is equivalent to assembling
+
+@example
+ .long 0
+ .long 0
+ .long 0
+@end example
+
+@node Sbttl
+@section @code{.sbttl "@var{subheading}"}
+
+@cindex @code{sbttl} directive
+@cindex subtitles for listings
+@cindex listing control: subtitle
+Use @var{subheading} as the title (third line, immediately after the
+title line) when generating assembly listings.
+
+This directive affects subsequent pages, as well as the current page if
+it appears within ten lines of the top of a page.
+
+@ifset COFF
+@node Scl
+@section @code{.scl @var{class}}
+
+@cindex @code{scl} directive
+@cindex symbol storage class (COFF)
+@cindex COFF symbol storage class
+Set the storage-class value for a symbol. This directive may only be
+used inside a @code{.def}/@code{.endef} pair. Storage class may flag
+whether a symbol is static or external, or it may record further
+symbolic debugging information.
+@ifset BOUT
+
+The @samp{.scl} directive is primarily associated with COFF output; when
+configured to generate @code{b.out} output format, @code{@value{AS}}
+accepts this directive but ignores it.
+@end ifset
+@end ifset
+
+@node Section
+@section @code{.section @var{name}}
+
+@cindex @code{section} directive
+@cindex named section
+Use the @code{.section} directive to assemble the following code into a section
+named @var{name}.
+
+This directive is only supported for targets that actually support arbitrarily
+named sections; on @code{a.out} targets, for example, it is not accepted, even
+with a standard @code{a.out} section name.
+
+@ifset COFF
+For COFF targets, the @code{.section} directive is used in one of the following
+ways:
+@smallexample
+.section @var{name}[, "@var{flags}"]
+.section @var{name}[, @var{subsegment}]
+@end smallexample
+
+If the optional argument is quoted, it is taken as flags to use for the
+section. Each flag is a single character. The following flags are recognized:
+@table @code
+@item b
+bss section (uninitialized data)
+@item n
+section is not loaded
+@item w
+writable section
+@item d
+data section
+@item r
+read-only section
+@item x
+executable section
+@end table
+
+If no flags are specified, the default flags depend upon the section name. If
+the section name is not recognized, the default will be for the section to be
+loaded and writable.
+
+If the optional argument to the @code{.section} directive is not quoted, it is
+taken as a subsegment number (@pxref{Sub-Sections}).
+@end ifset
+
+@ifset ELF
+For ELF targets, the @code{.section} directive is used like this:
+@smallexample
+.section @var{name}[, "@var{flags}"[, @@@var{type}]]
+@end smallexample
+The optional @var{flags} argument is a quoted string which may contain any
+combintion of the following characters:
+@table @code
+@item a
+section is allocatable
+@item w
+section is writable
+@item x
+section is executable
+@end table
+
+The optional @var{type} argument may contain one of the following constants:
+@table @code
+@item @@progbits
+section contains data
+@item @@nobits
+section does not contain data (i.e., section only occupies space)
+@end table
+
+If no flags are specified, the default flags depend upon the section name. If
+the section name is not recognized, the default will be for the section to have
+none of the above flags: it will not be allocated in memory, nor writable, nor
+executable. The section will contain data.
+
+For ELF targets, the assembler supports another type of @code{.section}
+directive for compatibility with the Solaris assembler:
+@smallexample
+.section "@var{name}"[, @var{flags}...]
+@end smallexample
+Note that the section name is quoted. There may be a sequence of comma
+separated flags:
+@table @code
+@item #alloc
+section is allocatable
+@item #write
+section is writable
+@item #execinstr
+section is executable
+@end table
+@end ifset
+
+@node Set
+@section @code{.set @var{symbol}, @var{expression}}
+
+@cindex @code{set} directive
+@cindex symbol value, setting
+Set the value of @var{symbol} to @var{expression}. This
+changes @var{symbol}'s value and type to conform to
+@var{expression}. If @var{symbol} was flagged as external, it remains
+flagged (@pxref{Symbol Attributes}).
+
+You may @code{.set} a symbol many times in the same assembly.
+
+If you @code{.set} a global symbol, the value stored in the object
+file is the last value stored into it.
+
+@ifset HPPA
+The syntax for @code{set} on the HPPA is
+@samp{@var{symbol} .set @var{expression}}.
+@end ifset
+
+@node Short
+@section @code{.short @var{expressions}}
+
+@cindex @code{short} directive
+@ifset GENERIC
+@code{.short} is normally the same as @samp{.word}.
+@xref{Word,,@code{.word}}.
+
+In some configurations, however, @code{.short} and @code{.word} generate
+numbers of different lengths; @pxref{Machine Dependencies}.
+@end ifset
+@ifclear GENERIC
+@ifset W16
+@code{.short} is the same as @samp{.word}. @xref{Word,,@code{.word}}.
+@end ifset
+@ifset W32
+This expects zero or more @var{expressions}, and emits
+a 16 bit number for each.
+@end ifset
+@end ifclear
+
+@node Single
+@section @code{.single @var{flonums}}
+
+@cindex @code{single} directive
+@cindex floating point numbers (single)
+This directive assembles zero or more flonums, separated by commas. It
+has the same effect as @code{.float}.
+@ifset GENERIC
+The exact kind of floating point numbers emitted depends on how
+@code{@value{AS}} is configured. @xref{Machine Dependencies}.
+@end ifset
+@ifclear GENERIC
+@ifset IEEEFLOAT
+On the @value{TARGET} family, @code{.single} emits 32-bit floating point
+numbers in @sc{ieee} format.
+@end ifset
+@end ifclear
+
+@ifset COFF
+@node Size
+@section @code{.size}
+
+@cindex @code{size} directive
+This directive is generated by compilers to include auxiliary debugging
+information in the symbol table. It is only permitted inside
+@code{.def}/@code{.endef} pairs.
+@ifset BOUT
+
+@samp{.size} is only meaningful when generating COFF format output; when
+@code{@value{AS}} is generating @code{b.out}, it accepts this directive but
+ignores it.
+@end ifset
+@end ifset
+
+@node Sleb128
+@section @code{.sleb128 @var{expressions}}
+
+@cindex @code{sleb128} directive
+@var{sleb128} stands for ``signed little endian base 128.'' This is a
+compact, variable length representation of numbers used by the DWARF
+symbolic debugging format. @xref{Uleb128,@code{.uleb128}}.
+
+@ifclear no-space-dir
+@node Skip
+@section @code{.skip @var{size} , @var{fill}}
+
+@cindex @code{skip} directive
+@cindex filling memory
+This directive emits @var{size} bytes, each of value @var{fill}. Both
+@var{size} and @var{fill} are absolute expressions. If the comma and
+@var{fill} are omitted, @var{fill} is assumed to be zero. This is the same as
+@samp{.space}.
+
+@node Space
+@section @code{.space @var{size} , @var{fill}}
+
+@cindex @code{space} directive
+@cindex filling memory
+This directive emits @var{size} bytes, each of value @var{fill}. Both
+@var{size} and @var{fill} are absolute expressions. If the comma
+and @var{fill} are omitted, @var{fill} is assumed to be zero. This is the same
+as @samp{.skip}.
+
+@ifset HPPA
+@quotation
+@emph{Warning:} @code{.space} has a completely different meaning for HPPA
+targets; use @code{.block} as a substitute. See @cite{HP9000 Series 800
+Assembly Language Reference Manual} (HP 92432-90001) for the meaning of the
+@code{.space} directive. @xref{HPPA Directives,,HPPA Assembler Directives},
+for a summary.
+@end quotation
+@end ifset
+@end ifclear
+
+@ifset A29K
+@ifclear GENERIC
+@node Space
+@section @code{.space}
+@cindex @code{space} directive
+@end ifclear
+On the AMD 29K, this directive is ignored; it is accepted for
+compatibility with other AMD 29K assemblers.
+
+@quotation
+@emph{Warning:} In most versions of the @sc{gnu} assembler, the directive
+@code{.space} has the effect of @code{.block} @xref{Machine Dependencies}.
+@end quotation
+@end ifset
+
+@ifset have-stabs
+@node Stab
+@section @code{.stabd, .stabn, .stabs}
+
+@cindex symbolic debuggers, information for
+@cindex @code{stab@var{x}} directives
+There are three directives that begin @samp{.stab}.
+All emit symbols (@pxref{Symbols}), for use by symbolic debuggers.
+The symbols are not entered in the @code{@value{AS}} hash table: they
+cannot be referenced elsewhere in the source file.
+Up to five fields are required:
+
+@table @var
+@item string
+This is the symbol's name. It may contain any character except
+@samp{\000}, so is more general than ordinary symbol names. Some
+debuggers used to code arbitrarily complex structures into symbol names
+using this field.
+
+@item type
+An absolute expression. The symbol's type is set to the low 8 bits of
+this expression. Any bit pattern is permitted, but @code{@value{LD}}
+and debuggers choke on silly bit patterns.
+
+@item other
+An absolute expression. The symbol's ``other'' attribute is set to the
+low 8 bits of this expression.
+
+@item desc
+An absolute expression. The symbol's descriptor is set to the low 16
+bits of this expression.
+
+@item value
+An absolute expression which becomes the symbol's value.
+@end table
+
+If a warning is detected while reading a @code{.stabd}, @code{.stabn},
+or @code{.stabs} statement, the symbol has probably already been created;
+you get a half-formed symbol in your object file. This is
+compatible with earlier assemblers!
+
+@table @code
+@cindex @code{stabd} directive
+@item .stabd @var{type} , @var{other} , @var{desc}
+
+The ``name'' of the symbol generated is not even an empty string.
+It is a null pointer, for compatibility. Older assemblers used a
+null pointer so they didn't waste space in object files with empty
+strings.
+
+The symbol's value is set to the location counter,
+relocatably. When your program is linked, the value of this symbol
+is the address of the location counter when the @code{.stabd} was
+assembled.
+
+@cindex @code{stabn} directive
+@item .stabn @var{type} , @var{other} , @var{desc} , @var{value}
+The name of the symbol is set to the empty string @code{""}.
+
+@cindex @code{stabs} directive
+@item .stabs @var{string} , @var{type} , @var{other} , @var{desc} , @var{value}
+All five fields are specified.
+@end table
+@end ifset
+@c end have-stabs
+
+@node String
+@section @code{.string} "@var{str}"
+
+@cindex string, copying to object file
+@cindex @code{string} directive
+
+Copy the characters in @var{str} to the object file. You may specify more than
+one string to copy, separated by commas. Unless otherwise specified for a
+particular machine, the assembler marks the end of each string with a 0 byte.
+You can use any of the escape sequences described in @ref{Strings,,Strings}.
+
+@node Struct
+@section @code{.struct @var{expression}}
+
+@cindex @code{struct} directive
+Switch to the absolute section, and set the section offset to @var{expression},
+which must be an absolute expression. You might use this as follows:
+@smallexample
+ .struct 0
+field1:
+ .struct field1 + 4
+field2:
+ .struct field2 + 4
+field3:
+@end smallexample
+This would define the symbol @code{field1} to have the value 0, the symbol
+@code{field2} to have the value 4, and the symbol @code{field3} to have the
+value 8. Assembly would be left in the absolute section, and you would need to
+use a @code{.section} directive of some sort to change to some other section
+before further assembly.
+
+@ifset ELF
+@node Symver
+@section @code{.symver}
+@cindex @code{symver} directive
+@cindex symbol versioning
+@cindex versions of symbols
+Use the @code{.symver} directive to bind symbols to specific version nodes
+within a source file. This is only supported on ELF platforms, and is
+typically used when assembling files to be linked into a shared library.
+There are cases where it may make sense to use this in objects to be bound
+into an application itself so as to override a versioned symbol from a
+shared library.
+
+For ELF targets, the @code{.symver} directive is used like this:
+@smallexample
+.symver @var{name}, @var{name2@@nodename}
+@end smallexample
+In this case, the symbol @var{name} must exist and be defined within the file
+being assembled. The @code{.versym} directive effectively creates a symbol
+alias with the name @var{name2@@nodename}, and in fact the main reason that we
+just don't try and create a regular alias is that the @var{@@} character isn't
+permitted in symbol names. The @var{name2} part of the name is the actual name
+of the symbol by which it will be externally referenced. The name @var{name}
+itself is merely a name of convenience that is used so that it is possible to
+have definitions for multiple versions of a function within a single source
+file, and so that the compiler can unambiguously know which version of a
+function is being mentioned. The @var{nodename} portion of the alias should be
+the name of a node specified in the version script supplied to the linker when
+building a shared library. If you are attempting to override a versioned
+symbol from a shared library, then @var{nodename} should correspond to the
+nodename of the symbol you are trying to override.
+@end ifset
+
+@ifset COFF
+@node Tag
+@section @code{.tag @var{structname}}
+
+@cindex COFF structure debugging
+@cindex structure debugging, COFF
+@cindex @code{tag} directive
+This directive is generated by compilers to include auxiliary debugging
+information in the symbol table. It is only permitted inside
+@code{.def}/@code{.endef} pairs. Tags are used to link structure
+definitions in the symbol table with instances of those structures.
+@ifset BOUT
+
+@samp{.tag} is only used when generating COFF format output; when
+@code{@value{AS}} is generating @code{b.out}, it accepts this directive but
+ignores it.
+@end ifset
+@end ifset
+
+@node Text
+@section @code{.text @var{subsection}}
+
+@cindex @code{text} directive
+Tells @code{@value{AS}} to assemble the following statements onto the end of
+the text subsection numbered @var{subsection}, which is an absolute
+expression. If @var{subsection} is omitted, subsection number zero
+is used.
+
+@node Title
+@section @code{.title "@var{heading}"}
+
+@cindex @code{title} directive
+@cindex listing control: title line
+Use @var{heading} as the title (second line, immediately after the
+source file name and pagenumber) when generating assembly listings.
+
+This directive affects subsequent pages, as well as the current page if
+it appears within ten lines of the top of a page.
+
+@ifset COFF
+@node Type
+@section @code{.type @var{int}}
+
+@cindex COFF symbol type
+@cindex symbol type, COFF
+@cindex @code{type} directive
+This directive, permitted only within @code{.def}/@code{.endef} pairs,
+records the integer @var{int} as the type attribute of a symbol table entry.
+@ifset BOUT
+
+@samp{.type} is associated only with COFF format output; when
+@code{@value{AS}} is configured for @code{b.out} output, it accepts this
+directive but ignores it.
+@end ifset
+@end ifset
+
+@ifset COFF
+@node Val
+@section @code{.val @var{addr}}
+
+@cindex @code{val} directive
+@cindex COFF value attribute
+@cindex value attribute, COFF
+This directive, permitted only within @code{.def}/@code{.endef} pairs,
+records the address @var{addr} as the value attribute of a symbol table
+entry.
+@ifset BOUT
+
+@samp{.val} is used only for COFF output; when @code{@value{AS}} is
+configured for @code{b.out}, it accepts this directive but ignores it.
+@end ifset
+@end ifset
+
+@node Uleb128
+@section @code{.uleb128 @var{expressions}}
+
+@cindex @code{uleb128} directive
+@var{uleb128} stands for ``unsigned little endian base 128.'' This is a
+compact, variable length representation of numbers used by the DWARF
+symbolic debugging format. @xref{Sleb128,@code{.sleb128}}.
+
+@node Word
+@section @code{.word @var{expressions}}
+
+@cindex @code{word} directive
+This directive expects zero or more @var{expressions}, of any section,
+separated by commas.
+@ifclear GENERIC
+@ifset W32
+For each expression, @code{@value{AS}} emits a 32-bit number.
+@end ifset
+@ifset W16
+For each expression, @code{@value{AS}} emits a 16-bit number.
+@end ifset
+@end ifclear
+@ifset GENERIC
+
+The size of the number emitted, and its byte order,
+depend on what target computer the assembly is for.
+@end ifset
+
+@c on amd29k, i960, sparc the "special treatment to support compilers" doesn't
+@c happen---32-bit addressability, period; no long/short jumps.
+@ifset DIFF-TBL-KLUGE
+@cindex difference tables altered
+@cindex altered difference tables
+@quotation
+@emph{Warning: Special Treatment to support Compilers}
+@end quotation
+
+@ifset GENERIC
+Machines with a 32-bit address space, but that do less than 32-bit
+addressing, require the following special treatment. If the machine of
+interest to you does 32-bit addressing (or doesn't require it;
+@pxref{Machine Dependencies}), you can ignore this issue.
+
+@end ifset
+In order to assemble compiler output into something that works,
+@code{@value{AS}} occasionlly does strange things to @samp{.word} directives.
+Directives of the form @samp{.word sym1-sym2} are often emitted by
+compilers as part of jump tables. Therefore, when @code{@value{AS}} assembles a
+directive of the form @samp{.word sym1-sym2}, and the difference between
+@code{sym1} and @code{sym2} does not fit in 16 bits, @code{@value{AS}}
+creates a @dfn{secondary jump table}, immediately before the next label.
+This secondary jump table is preceded by a short-jump to the
+first byte after the secondary table. This short-jump prevents the flow
+of control from accidentally falling into the new table. Inside the
+table is a long-jump to @code{sym2}. The original @samp{.word}
+contains @code{sym1} minus the address of the long-jump to
+@code{sym2}.
+
+If there were several occurrences of @samp{.word sym1-sym2} before the
+secondary jump table, all of them are adjusted. If there was a
+@samp{.word sym3-sym4}, that also did not fit in sixteen bits, a
+long-jump to @code{sym4} is included in the secondary jump table,
+and the @code{.word} directives are adjusted to contain @code{sym3}
+minus the address of the long-jump to @code{sym4}; and so on, for as many
+entries in the original jump table as necessary.
+
+@ifset INTERNALS
+@emph{This feature may be disabled by compiling @code{@value{AS}} with the
+@samp{-DWORKING_DOT_WORD} option.} This feature is likely to confuse
+assembly language programmers.
+@end ifset
+@end ifset
+@c end DIFF-TBL-KLUGE
+
+@node Deprecated
+@section Deprecated Directives
+
+@cindex deprecated directives
+@cindex obsolescent directives
+One day these directives won't work.
+They are included for compatibility with older assemblers.
+@table @t
+@item .abort
+@item .line
+@end table
+
+@ifset GENERIC
+@node Machine Dependencies
+@chapter Machine Dependent Features
+
+@cindex machine dependencies
+The machine instruction sets are (almost by definition) different on
+each machine where @code{@value{AS}} runs. Floating point representations
+vary as well, and @code{@value{AS}} often supports a few additional
+directives or command-line options for compatibility with other
+assemblers on a particular platform. Finally, some versions of
+@code{@value{AS}} support special pseudo-instructions for branch
+optimization.
+
+This chapter discusses most of these differences, though it does not
+include details on any machine's instruction set. For details on that
+subject, see the hardware manufacturer's manual.
+
+@menu
+@ifset A29K
+* AMD29K-Dependent:: AMD 29K Dependent Features
+@end ifset
+@ifset ARC
+* ARC-Dependent:: ARC Dependent Features
+@end ifset
+@ifset ARM
+* ARM-Dependent:: ARM Dependent Features
+@end ifset
+@ifset D10V
+* D10V-Dependent:: D10V Dependent Features
+@end ifset
+@ifset D30V
+* D30V-Dependent:: D30V Dependent Features
+@end ifset
+@ifset H8/300
+* H8/300-Dependent:: Hitachi H8/300 Dependent Features
+@end ifset
+@ifset H8/500
+* H8/500-Dependent:: Hitachi H8/500 Dependent Features
+@end ifset
+@ifset HPPA
+* HPPA-Dependent:: HPPA Dependent Features
+@end ifset
+@ifset I80386
+* i386-Dependent:: Intel 80386 Dependent Features
+@end ifset
+@ifset I960
+* i960-Dependent:: Intel 80960 Dependent Features
+@end ifset
+@ifset M680X0
+* M68K-Dependent:: M680x0 Dependent Features
+@end ifset
+@ifset MIPS
+* MIPS-Dependent:: MIPS Dependent Features
+@end ifset
+@ifset SH
+* SH-Dependent:: Hitachi SH Dependent Features
+@end ifset
+@ifset SPARC
+* Sparc-Dependent:: SPARC Dependent Features
+@end ifset
+@ifset V850
+* V850-Dependent:: V850 Dependent Features
+@end ifset
+@ifset Z8000
+* Z8000-Dependent:: Z8000 Dependent Features
+@end ifset
+@ifset VAX
+* Vax-Dependent:: VAX Dependent Features
+@end ifset
+@end menu
+
+@lowersections
+@end ifset
+
+@c The following major nodes are *sections* in the GENERIC version, *chapters*
+@c in single-cpu versions. This is mainly achieved by @lowersections. There is a
+@c peculiarity: to preserve cross-references, there must be a node called
+@c "Machine Dependencies". Hence the conditional nodenames in each
+@c major node below. Node defaulting in makeinfo requires adjacency of
+@c node and sectioning commands; hence the repetition of @chapter BLAH
+@c in both conditional blocks.
+
+@ifset ARC
+@ifset GENERIC
+@page
+@node ARC-Dependent
+@chapter ARC Dependent Features
+@end ifset
+@ifclear GENERIC
+@node Machine Dependencies
+@chapter ARC Dependent Features
+@end ifclear
+
+@cindex ARC support
+@menu
+* ARC-Opts:: Options
+* ARC-Float:: Floating Point
+* ARC-Directives:: Sparc Machine Directives
+@end menu
+
+@node ARC-Opts
+@section Options
+
+@cindex options for ARC
+@cindex ARC options
+@cindex architectures, ARC
+@cindex ARC architectures
+The ARC chip family includes several successive levels (or other
+variants) of chip, using the same core instruction set, but including
+a few additional instructions at each level.
+
+By default, @code{@value{AS}} assumes the core instruction set (ARC
+base). The @code{.cpu} pseudo-op is intended to be used to select
+the variant.
+
+@table @code
+@cindex @code{-mbig-endian} option (ARC)
+@cindex @code{-mlittle-endian} option (ARC)
+@cindex ARC big-endian output
+@cindex ARC little-endian output
+@cindex big-endian output, ARC
+@cindex little-endian output, ARC
+@item -mbig-endian
+@itemx -mlittle-endian
+Any @sc{arc} configuration of @code{@value{AS}} can select big-endian or
+little-endian output at run time (unlike most other @sc{gnu} development
+tools, which must be configured for one or the other). Use
+@samp{-mbig-endian} to select big-endian output, and @samp{-mlittle-endian}
+for little-endian.
+@end table
+
+@node ARC-Float
+@section Floating Point
+
+@cindex floating point, ARC (@sc{ieee})
+@cindex ARC floating point (@sc{ieee})
+The ARC cpu family currently does not have hardware floating point
+support. Software floating point support is provided by @code{GCC}
+and uses @sc{ieee} floating-point numbers.
+
+@node ARC-Directives
+@section ARC Machine Directives
+
+@cindex ARC machine directives
+@cindex machine directives, ARC
+The ARC version of @code{@value{AS}} supports the following additional
+machine directives:
+
+@table @code
+@item .cpu
+@cindex @code{cpu} directive, SPARC
+This must be followed by the desired cpu.
+The ARC is intended to be customizable, @code{.cpu} is used to
+select the desired variant [though currently there are none].
+
+@end table
+
+@end ifset
+
+@ifset A29K
+@include c-a29k.texi
+@end ifset
+
+@ifset ARM
+@include c-arm.texi
+@end ifset
+
+@ifset Hitachi-all
+@ifclear GENERIC
+@node Machine Dependencies
+@chapter Machine Dependent Features
+
+The machine instruction sets are different on each Hitachi chip family,
+and there are also some syntax differences among the families. This
+chapter describes the specific @code{@value{AS}} features for each
+family.
+
+@menu
+* H8/300-Dependent:: Hitachi H8/300 Dependent Features
+* H8/500-Dependent:: Hitachi H8/500 Dependent Features
+* SH-Dependent:: Hitachi SH Dependent Features
+@end menu
+@lowersections
+@end ifclear
+@end ifset
+
+@ifset D10V
+@include c-d10v.texi
+@end ifset
+
+@ifset D30V
+@include c-d30v.texi
+@end ifset
+
+@ifset H8/300
+@include c-h8300.texi
+@end ifset
+
+@ifset H8/500
+@include c-h8500.texi
+@end ifset
+
+@ifset HPPA
+@include c-hppa.texi
+@end ifset
+
+@ifset I80386
+@include c-i386.texi
+@end ifset
+
+@ifset I960
+@include c-i960.texi
+@end ifset
+
+
+@ifset M680X0
+@include c-m68k.texi
+@end ifset
+
+@ifset MIPS
+@include c-mips.texi
+@end ifset
+
+@ifset NS32K
+@include c-ns32k.texi
+@end ifset
+
+@ifset SH
+@include c-sh.texi
+@end ifset
+
+@ifset SPARC
+@include c-sparc.texi
+@end ifset
+
+@ifset Z8000
+@include c-z8k.texi
+@end ifset
+
+@ifset VAX
+@include c-vax.texi
+@end ifset
+
+@ifset V850
+@include c-v850.texi
+@end ifset
+
+@ifset GENERIC
+@c reverse effect of @down at top of generic Machine-Dep chapter
+@raisesections
+@end ifset
+
+@node Reporting Bugs
+@chapter Reporting Bugs
+@cindex bugs in assembler
+@cindex reporting bugs in assembler
+
+Your bug reports play an essential role in making @code{@value{AS}} reliable.
+
+Reporting a bug may help you by bringing a solution to your problem, or it may
+not. But in any case the principal function of a bug report is to help the
+entire community by making the next version of @code{@value{AS}} work better.
+Bug reports are your contribution to the maintenance of @code{@value{AS}}.
+
+In order for a bug report to serve its purpose, you must include the
+information that enables us to fix the bug.
+
+@menu
+* Bug Criteria:: Have you found a bug?
+* Bug Reporting:: How to report bugs
+@end menu
+
+@node Bug Criteria
+@section Have you found a bug?
+@cindex bug criteria
+
+If you are not sure whether you have found a bug, here are some guidelines:
+
+@itemize @bullet
+@cindex fatal signal
+@cindex assembler crash
+@cindex crash of assembler
+@item
+If the assembler gets a fatal signal, for any input whatever, that is a
+@code{@value{AS}} bug. Reliable assemblers never crash.
+
+@cindex error on valid input
+@item
+If @code{@value{AS}} produces an error message for valid input, that is a bug.
+
+@cindex invalid input
+@item
+If @code{@value{AS}} does not produce an error message for invalid input, that
+is a bug. However, you should note that your idea of ``invalid input'' might
+be our idea of ``an extension'' or ``support for traditional practice''.
+
+@item
+If you are an experienced user of assemblers, your suggestions for improvement
+of @code{@value{AS}} are welcome in any case.
+@end itemize
+
+@node Bug Reporting
+@section How to report bugs
+@cindex bug reports
+@cindex assembler bugs, reporting
+
+A number of companies and individuals offer support for @sc{gnu} products. If
+you obtained @code{@value{AS}} from a support organization, we recommend you
+contact that organization first.
+
+You can find contact information for many support companies and
+individuals in the file @file{etc/SERVICE} in the @sc{gnu} Emacs
+distribution.
+
+In any event, we also recommend that you send bug reports for @code{@value{AS}}
+to @samp{bug-gnu-utils@@gnu.org}.
+
+The fundamental principle of reporting bugs usefully is this:
+@strong{report all the facts}. If you are not sure whether to state a
+fact or leave it out, state it!
+
+Often people omit facts because they think they know what causes the problem
+and assume that some details do not matter. Thus, you might assume that the
+name of a symbol you use in an example does not matter. Well, probably it does
+not, but one cannot be sure. Perhaps the bug is a stray memory reference which
+happens to fetch from the location where that name is stored in memory;
+perhaps, if the name were different, the contents of that location would fool
+the assembler into doing the right thing despite the bug. Play it safe and
+give a specific, complete example. That is the easiest thing for you to do,
+and the most helpful.
+
+Keep in mind that the purpose of a bug report is to enable us to fix the bug if
+it is new to us. Therefore, always write your bug reports on the assumption
+that the bug has not been reported previously.
+
+Sometimes people give a few sketchy facts and ask, ``Does this ring a
+bell?'' Those bug reports are useless, and we urge everyone to
+@emph{refuse to respond to them} except to chide the sender to report
+bugs properly.
+
+To enable us to fix the bug, you should include all these things:
+
+@itemize @bullet
+@item
+The version of @code{@value{AS}}. @code{@value{AS}} announces it if you start
+it with the @samp{--version} argument.
+
+Without this, we will not know whether there is any point in looking for
+the bug in the current version of @code{@value{AS}}.
+
+@item
+Any patches you may have applied to the @code{@value{AS}} source.
+
+@item
+The type of machine you are using, and the operating system name and
+version number.
+
+@item
+What compiler (and its version) was used to compile @code{@value{AS}}---e.g.
+``@code{gcc-2.7}''.
+
+@item
+The command arguments you gave the assembler to assemble your example and
+observe the bug. To guarantee you will not omit something important, list them
+all. A copy of the Makefile (or the output from make) is sufficient.
+
+If we were to try to guess the arguments, we would probably guess wrong
+and then we might not encounter the bug.
+
+@item
+A complete input file that will reproduce the bug. If the bug is observed when
+the assembler is invoked via a compiler, send the assembler source, not the
+high level language source. Most compilers will produce the assembler source
+when run with the @samp{-S} option. If you are using @code{@value{GCC}}, use
+the options @samp{-v --save-temps}; this will save the assembler source in a
+file with an extension of @file{.s}, and also show you exactly how
+@code{@value{AS}} is being run.
+
+@item
+A description of what behavior you observe that you believe is
+incorrect. For example, ``It gets a fatal signal.''
+
+Of course, if the bug is that @code{@value{AS}} gets a fatal signal, then we
+will certainly notice it. But if the bug is incorrect output, we might not
+notice unless it is glaringly wrong. You might as well not give us a chance to
+make a mistake.
+
+Even if the problem you experience is a fatal signal, you should still say so
+explicitly. Suppose something strange is going on, such as, your copy of
+@code{@value{AS}} is out of synch, or you have encountered a bug in the C
+library on your system. (This has happened!) Your copy might crash and ours
+would not. If you told us to expect a crash, then when ours fails to crash, we
+would know that the bug was not happening for us. If you had not told us to
+expect a crash, then we would not be able to draw any conclusion from our
+observations.
+
+@item
+If you wish to suggest changes to the @code{@value{AS}} source, send us context
+diffs, as generated by @code{diff} with the @samp{-u}, @samp{-c}, or @samp{-p}
+option. Always send diffs from the old file to the new file. If you even
+discuss something in the @code{@value{AS}} source, refer to it by context, not
+by line number.
+
+The line numbers in our development sources will not match those in your
+sources. Your line numbers would convey no useful information to us.
+@end itemize
+
+Here are some things that are not necessary:
+
+@itemize @bullet
+@item
+A description of the envelope of the bug.
+
+Often people who encounter a bug spend a lot of time investigating
+which changes to the input file will make the bug go away and which
+changes will not affect it.
+
+This is often time consuming and not very useful, because the way we
+will find the bug is by running a single example under the debugger
+with breakpoints, not by pure deduction from a series of examples.
+We recommend that you save your time for something else.
+
+Of course, if you can find a simpler example to report @emph{instead}
+of the original one, that is a convenience for us. Errors in the
+output will be easier to spot, running under the debugger will take
+less time, and so on.
+
+However, simplification is not vital; if you do not want to do this,
+report the bug anyway and send us the entire test case you used.
+
+@item
+A patch for the bug.
+
+A patch for the bug does help us if it is a good one. But do not omit
+the necessary information, such as the test case, on the assumption that
+a patch is all we need. We might see problems with your patch and decide
+to fix the problem another way, or we might not understand it at all.
+
+Sometimes with a program as complicated as @code{@value{AS}} it is very hard to
+construct an example that will make the program follow a certain path through
+the code. If you do not send us the example, we will not be able to construct
+one, so we will not be able to verify that the bug is fixed.
+
+And if we cannot understand what bug you are trying to fix, or why your
+patch should be an improvement, we will not install it. A test case will
+help us to understand.
+
+@item
+A guess about what the bug is or what it depends on.
+
+Such guesses are usually wrong. Even we cannot guess right about such
+things without first using the debugger to find the facts.
+@end itemize
+
+@node Acknowledgements
+@chapter Acknowledgements
+
+If you have contributed to @code{@value{AS}} and your name isn't listed here,
+it is not meant as a slight. We just don't know about it. Send mail to the
+maintainer, and we'll correct the situation. Currently
+@c (January 1994),
+the maintainer is Ken Raeburn (email address @code{raeburn@@cygnus.com}).
+
+Dean Elsner wrote the original @sc{gnu} assembler for the VAX.@footnote{Any
+more details?}
+
+Jay Fenlason maintained GAS for a while, adding support for GDB-specific debug
+information and the 68k series machines, most of the preprocessing pass, and
+extensive changes in @file{messages.c}, @file{input-file.c}, @file{write.c}.
+
+K. Richard Pixley maintained GAS for a while, adding various enhancements and
+many bug fixes, including merging support for several processors, breaking GAS
+up to handle multiple object file format back ends (including heavy rewrite,
+testing, an integration of the coff and b.out back ends), adding configuration
+including heavy testing and verification of cross assemblers and file splits
+and renaming, converted GAS to strictly ANSI C including full prototypes, added
+support for m680[34]0 and cpu32, did considerable work on i960 including a COFF
+port (including considerable amounts of reverse engineering), a SPARC opcode
+file rewrite, DECstation, rs6000, and hp300hpux host ports, updated ``know''
+assertions and made them work, much other reorganization, cleanup, and lint.
+
+Ken Raeburn wrote the high-level BFD interface code to replace most of the code
+in format-specific I/O modules.
+
+The original VMS support was contributed by David L. Kashtan. Eric Youngdale
+has done much work with it since.
+
+The Intel 80386 machine description was written by Eliot Dresselhaus.
+
+Minh Tran-Le at IntelliCorp contributed some AIX 386 support.
+
+The Motorola 88k machine description was contributed by Devon Bowen of Buffalo
+University and Torbjorn Granlund of the Swedish Institute of Computer Science.
+
+Keith Knowles at the Open Software Foundation wrote the original MIPS back end
+(@file{tc-mips.c}, @file{tc-mips.h}), and contributed Rose format support
+(which hasn't been merged in yet). Ralph Campbell worked with the MIPS code to
+support a.out format.
+
+Support for the Zilog Z8k and Hitachi H8/300 and H8/500 processors (tc-z8k,
+tc-h8300, tc-h8500), and IEEE 695 object file format (obj-ieee), was written by
+Steve Chamberlain of Cygnus Support. Steve also modified the COFF back end to
+use BFD for some low-level operations, for use with the H8/300 and AMD 29k
+targets.
+
+John Gilmore built the AMD 29000 support, added @code{.include} support, and
+simplified the configuration of which versions accept which directives. He
+updated the 68k machine description so that Motorola's opcodes always produced
+fixed-size instructions (e.g. @code{jsr}), while synthetic instructions
+remained shrinkable (@code{jbsr}). John fixed many bugs, including true tested
+cross-compilation support, and one bug in relaxation that took a week and
+required the proverbial one-bit fix.
+
+Ian Lance Taylor of Cygnus Support merged the Motorola and MIT syntax for the
+68k, completed support for some COFF targets (68k, i386 SVR3, and SCO Unix),
+added support for MIPS ECOFF and ELF targets, wrote the initial RS/6000 and
+PowerPC assembler, and made a few other minor patches.
+
+Steve Chamberlain made @code{@value{AS}} able to generate listings.
+
+Hewlett-Packard contributed support for the HP9000/300.
+
+Jeff Law wrote GAS and BFD support for the native HPPA object format (SOM)
+along with a fairly extensive HPPA testsuite (for both SOM and ELF object
+formats). This work was supported by both the Center for Software Science at
+the University of Utah and Cygnus Support.
+
+Support for ELF format files has been worked on by Mark Eichin of Cygnus
+Support (original, incomplete implementation for SPARC), Pete Hoogenboom and
+Jeff Law at the University of Utah (HPPA mainly), Michael Meissner of the Open
+Software Foundation (i386 mainly), and Ken Raeburn of Cygnus Support (sparc,
+and some initial 64-bit support).
+
+Richard Henderson rewrote the Alpha assembler. Klaus Kaempf wrote GAS and BFD
+support for openVMS/Alpha.
+
+Several engineers at Cygnus Support have also provided many small bug fixes and
+configuration enhancements.
+
+Many others have contributed large or small bugfixes and enhancements. If
+you have contributed significant work and are not mentioned on this list, and
+want to be, let us know. Some of the history has been lost; we are not
+intentionally leaving anyone out.
+
+@node Index
+@unnumbered Index
+
+@printindex cp
+
+@contents
+@bye
+@c Local Variables:
+@c fill-column: 79
+@c End:
diff --git a/gas/doc/c-a29k.texi b/gas/doc/c-a29k.texi
new file mode 100644
index 0000000000..4d115d807f
--- /dev/null
+++ b/gas/doc/c-a29k.texi
@@ -0,0 +1,182 @@
+@c Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+@c This is part of the GAS manual.
+@c For copying conditions, see the file as.texinfo.
+@ifset GENERIC
+@page
+@node AMD29K-Dependent
+@chapter AMD 29K Dependent Features
+@end ifset
+@ifclear GENERIC
+@node Machine Dependencies
+@chapter AMD 29K Dependent Features
+@end ifclear
+
+@cindex AMD 29K support
+@cindex 29K support
+@menu
+* AMD29K Options:: Options
+* AMD29K Syntax:: Syntax
+* AMD29K Floating Point:: Floating Point
+* AMD29K Directives:: AMD 29K Machine Directives
+* AMD29K Opcodes:: Opcodes
+@end menu
+
+@node AMD29K Options
+@section Options
+@cindex AMD 29K options (none)
+@cindex options for AMD29K (none)
+@code{@value{AS}} has no additional command-line options for the AMD
+29K family.
+
+@node AMD29K Syntax
+@section Syntax
+@menu
+* AMD29K-Macros:: Macros
+* AMD29K-Chars:: Special Characters
+* AMD29K-Regs:: Register Names
+@end menu
+
+@node AMD29K-Macros
+@subsection Macros
+
+@cindex Macros, AMD 29K
+@cindex AMD 29K macros
+The macro syntax used on the AMD 29K is like that described in the AMD
+29K Family Macro Assembler Specification. Normal @code{@value{AS}}
+macros should still work.
+
+@node AMD29K-Chars
+@subsection Special Characters
+
+@cindex line comment character, AMD 29K
+@cindex AMD 29K line comment character
+@samp{;} is the line comment character.
+
+@cindex identifiers, AMD 29K
+@cindex AMD 29K identifiers
+The character @samp{?} is permitted in identifiers (but may not begin
+an identifier).
+
+@node AMD29K-Regs
+@subsection Register Names
+
+@cindex AMD 29K register names
+@cindex register names, AMD 29K
+General-purpose registers are represented by predefined symbols of the
+form @samp{GR@var{nnn}} (for global registers) or @samp{LR@var{nnn}}
+(for local registers), where @var{nnn} represents a number between
+@code{0} and @code{127}, written with no leading zeros. The leading
+letters may be in either upper or lower case; for example, @samp{gr13}
+and @samp{LR7} are both valid register names.
+
+You may also refer to general-purpose registers by specifying the
+register number as the result of an expression (prefixed with @samp{%%}
+to flag the expression as a register number):
+@smallexample
+%%@var{expression}
+@end smallexample
+@noindent
+---where @var{expression} must be an absolute expression evaluating to a
+number between @code{0} and @code{255}. The range [0, 127] refers to
+global registers, and the range [128, 255] to local registers.
+
+@cindex special purpose registers, AMD 29K
+@cindex AMD 29K special purpose registers
+@cindex protected registers, AMD 29K
+@cindex AMD 29K protected registers
+In addition, @code{@value{AS}} understands the following protected
+special-purpose register names for the AMD 29K family:
+
+@smallexample
+ vab chd pc0
+ ops chc pc1
+ cps rbp pc2
+ cfg tmc mmu
+ cha tmr lru
+@end smallexample
+
+These unprotected special-purpose register names are also recognized:
+@smallexample
+ ipc alu fpe
+ ipa bp inte
+ ipb fc fps
+ q cr exop
+@end smallexample
+
+@node AMD29K Floating Point
+@section Floating Point
+
+@cindex floating point, AMD 29K (@sc{ieee})
+@cindex AMD 29K floating point (@sc{ieee})
+The AMD 29K family uses @sc{ieee} floating-point numbers.
+
+@node AMD29K Directives
+@section AMD 29K Machine Directives
+
+@cindex machine directives, AMD 29K
+@cindex AMD 29K machine directives
+@table @code
+@cindex @code{block} directive, AMD 29K
+@item .block @var{size} , @var{fill}
+This directive emits @var{size} bytes, each of value @var{fill}. Both
+@var{size} and @var{fill} are absolute expressions. If the comma
+and @var{fill} are omitted, @var{fill} is assumed to be zero.
+
+In other versions of the @sc{gnu} assembler, this directive is called
+@samp{.space}.
+@end table
+
+@table @code
+@cindex @code{cputype} directive, AMD 29K
+@item .cputype
+This directive is ignored; it is accepted for compatibility with other
+AMD 29K assemblers.
+
+@cindex @code{file} directive, AMD 29K
+@item .file
+This directive is ignored; it is accepted for compatibility with other
+AMD 29K assemblers.
+
+@quotation
+@emph{Warning:} in other versions of the @sc{gnu} assembler, @code{.file} is
+used for the directive called @code{.app-file} in the AMD 29K support.
+@end quotation
+
+@cindex @code{line} directive, AMD 29K
+@item .line
+This directive is ignored; it is accepted for compatibility with other
+AMD 29K assemblers.
+
+@ignore
+@c since we're ignoring .lsym...
+@cindex @code{reg} directive, AMD 29K
+@item .reg @var{symbol}, @var{expression}
+@code{.reg} has the same effect as @code{.lsym}; @pxref{Lsym,,@code{.lsym}}.
+@end ignore
+
+@cindex @code{sect} directive, AMD 29K
+@item .sect
+This directive is ignored; it is accepted for compatibility with other
+AMD 29K assemblers.
+
+@cindex @code{use} directive, AMD 29K
+@item .use @var{section name}
+Establishes the section and subsection for the following code;
+@var{section name} may be one of @code{.text}, @code{.data},
+@code{.data1}, or @code{.lit}. With one of the first three @var{section
+name} options, @samp{.use} is equivalent to the machine directive
+@var{section name}; the remaining case, @samp{.use .lit}, is the same as
+@samp{.data 200}.
+@end table
+
+@node AMD29K Opcodes
+@section Opcodes
+
+@cindex AMD 29K opcodes
+@cindex opcodes for AMD 29K
+@code{@value{AS}} implements all the standard AMD 29K opcodes. No
+additional pseudo-instructions are needed on this family.
+
+For information on the 29K machine instruction set, see @cite{Am29000
+User's Manual}, Advanced Micro Devices, Inc.
+
diff --git a/gas/doc/c-arm.texi b/gas/doc/c-arm.texi
new file mode 100644
index 0000000000..b94fb2a12f
--- /dev/null
+++ b/gas/doc/c-arm.texi
@@ -0,0 +1,207 @@
+@c Copyright (C) 1996, 1998, 1999 Free Software Foundation, Inc.
+@c This is part of the GAS manual.
+@c For copying conditions, see the file as.texinfo.
+
+@ifset GENERIC
+@page
+@node ARM-Dependent
+@chapter ARM Dependent Features
+@end ifset
+
+@ifclear GENERIC
+@node Machine Dependencies
+@chapter ARM Dependent Features
+@end ifclear
+
+@cindex ARM support
+@cindex Thumb support
+@menu
+* ARM Options:: Options
+* ARM Syntax:: Syntax
+* ARM Floating Point:: Floating Point
+* ARM Directives:: ARM Machine Directives
+* ARM Opcodes:: Opcodes
+@end menu
+
+@node ARM Options
+@section Options
+@cindex ARM options (none)
+@cindex options for ARM (none)
+@table @code
+@cindex @code{-marm} command line option, ARM
+@item -marm @var{[2|250|3|6|60|600|610|620|7|7m|7d|7dm|7di|7dmi|70|700|700i|710|710c|7100|7500|7500fe|7tdmi|8|810|9|9tdmistrongarm|strongarm110|strongarm1100]}
+This option specifies the target processor. The assembler will issue an
+error message if an attempt is made to assemble an instruction which
+will not execute on the target processor.
+@cindex @code{-marmv} command line option, ARM
+@item -marmv @var{[2|2a|3|3m|4|4t]}
+This option specifies the target architecture. The assembler will issue
+an error message if an attempt is made to assemble an instruction which
+will not execute on the target architecture.
+@cindex @code{-mthumb} command line option, ARM
+@item -mthumb
+This option specifies that only Thumb instructions should be assembled.
+@cindex @code{-mall} command line option, ARM
+@item -mall
+This option specifies that any Arm or Thumb instruction should be assembled.
+@cindex @code{-mfpa} command line option, ARM
+@item -mfpa @var{[10|11]}
+This option specifies the floating point architecture in use on the
+target processor.
+@cindex @code{-mfpe-old} command line option, ARM
+@item -mfpe-old
+Do not allow the assemble of floating point multiple instructions.
+@cindex @code{-mno-fpu} command line option, ARM
+@item -mno-fpu
+Do not allow the assembly of any floating point instructions.
+@cindex @code{-mthumb-interwork} command line option, ARM
+@item -mthumb-interwork
+This option specifies that the output generated by the assembler should
+be marked as supporting interworking.
+@cindex @code{-mapcs} command line option, ARM
+@item -mapcs @var{[26|32]}
+This option specifies that the output generated by the assembler should
+be marked as supporting the indicated version of the Arm Procedure.
+Calling Standard.
+@item -mapcs-float
+This indicates the the floating point variant of the APCS should be
+used. In this variant floating point arguments are passed in FP
+registers ratehr than integer registers.
+@item -mapcs-reentrant
+This indicates that the reentrant variant of the APCS should be used.
+This variant supports position independent code.
+@cindex @code{-EB} command line option, ARM
+@item -EB
+This option specifies that the output generated by the assembler should
+be marked as being encoded for a big-endian processor.
+@cindex @code{-EL} command line option, ARM
+@item -EL
+This option specifies that the output generated by the assembler should
+be marked as being encoded for a little-endian processor.
+@cindex @code{-k} command line option, ARM
+@cindex PIC code generation for ARM
+@item -k
+This option enables the generation of PIC (position independent code).
+@item -moabi
+This indicates that the code should be assembled using the old ARM ELF
+conventions, based on a beta release release of the ARM-ELF
+specifications, rather than the default conventions which are based on
+the final release of the ARM-ELF specifications.
+@end table
+
+
+@node ARM Syntax
+@section Syntax
+@menu
+* ARM-Chars:: Special Characters
+* ARM-Regs:: Register Names
+@end menu
+
+@node ARM-Chars
+@subsection Special Characters
+
+@cindex line comment character, ARM
+@cindex ARM line comment character
+The presence of a @samp{#} and @samp{@@} on a line indicates the start of
+a comment that extends to the end of the current line.
+
+@cindex identifiers, ARM
+@cindex ARM identifiers
+*TODO* Explain about /data modifier on symbols.
+
+@node ARM-Regs
+@subsection Register Names
+
+@cindex ARM register names
+@cindex register names, ARM
+*TODO* Explain about ARM register naming, and the predefined names.
+
+@node ARM Floating Point
+@section Floating Point
+
+@cindex floating point, ARM (@sc{ieee})
+@cindex ARM floating point (@sc{ieee})
+The ARM family uses @sc{ieee} floating-point numbers.
+
+
+
+@node ARM Directives
+@section ARM Machine Directives
+
+@cindex machine directives, ARM
+@cindex ARM machine directives
+@table @code
+
+@cindex @code{req} directive, ARM
+@item @var{name} .req @var{register name}
+This creates an alias for @var{register name} called @var{name}. For
+example:
+
+@smallexample
+ foo .req r0
+@end smallexample
+
+@cindex @code{code} directive, ARM
+@item .code @var{[16|32]}
+This directive selects the instruction set being generated. The value 16
+selects Thumb, with the value 32 selecting ARM.
+
+@cindex @code{thumb} directive, ARM
+@item .thumb
+This performs the same action as @var{.code 16}.
+
+@cindex @code{arm} directive, ARM
+@item .arm
+This performs the same action as @var{.code 32}.
+
+@cindex @code{force_thumb} directive, ARM
+@item .force_thumb
+This directive forces the selection of Thumb instructions, even if the
+target processor does not support those instructions
+
+@cindex @code{thumb_func} directive, ARM
+@item .thumb_func
+This directive specifies that the following symbol is the name of a
+Thumb encoded function. This information is necessary in order to allow
+the assembler and linker to generate correct code for interworking
+between Arm and Thumb instructions and should be used even if
+interworking is not going to be performed.
+
+@cindex @code{.ltorg} directive, ARM
+@item .ltorg
+This directive causes the current contents of the literal pool to be
+dumped into the current section (which is assumed to be the .text
+section) at the current location (aligned to a word boundary).
+
+@cindex @code{.pool} directive, ARM
+@item .pool
+This is a synonym for .ltorg.
+
+@end table
+
+@node ARM Opcodes
+@section Opcodes
+
+@cindex ARM opcodes
+@cindex opcodes for ARM
+@code{@value{AS}} implements all the standard ARM opcodes.
+
+*TODO* Document the pseudo-ops (adr, nop)
+
+GAS for the ARM supports a synthetic register load instruction whoes
+syntax is:
+
+@smallexample
+ ldr <register> , = <expression>
+@end smallexample
+
+If expression evaluates to a numeric constant then a MOV or MVN
+instruction will be used in place of the LDR instruction, if the
+constant can be generated by either of these instructions. Otherwise
+the constant will be placed into the nearest literal pool (if it not
+already there) and a PC relative LDR instruction will be generated.
+
+For information on the ARM or Thumb instruction sets, see @cite{ARM
+Software Development Toolkit Reference Manual}, Advanced RISC Machines
+Ltd.
+
diff --git a/gas/doc/c-d10v.texi b/gas/doc/c-d10v.texi
new file mode 100644
index 0000000000..8d7bf88c99
--- /dev/null
+++ b/gas/doc/c-d10v.texi
@@ -0,0 +1,250 @@
+@c Copyright (C) 1996 Free Software Foundation, Inc.
+@c This is part of the GAS manual.
+@c For copying conditions, see the file as.texinfo.
+@ifset GENERIC
+@page
+@node D10V-Dependent
+@chapter D10V Dependent Features
+@end ifset
+@ifclear GENERIC
+@node Machine Dependencies
+@chapter D10V Dependent Features
+@end ifclear
+
+@cindex D10V support
+@menu
+* D10V-Opts:: D10V Options
+* D10V-Syntax:: Syntax
+* D10V-Float:: Floating Point
+* D10V-Opcodes:: Opcodes
+@end menu
+
+@node D10V-Opts
+@section D10V Options
+@cindex options, D10V
+@cindex D10V options
+The Mitsubishi D10V version of @code{@value{AS}} has a few machine
+dependent options.
+
+@table @samp
+@item -O
+The D10V can often execute two sub-instructions in parallel. When this option
+is used, @code{@value{AS}} will attempt to optimize its output by detecting when
+instructions can be executed in parallel.
+@item --nowarnswap
+To optimize execution performance, @code{@value{AS}} will sometimes swap the
+order of instructions. Normally this generates a warning. When this option
+is used, no warning will be generated when instructions are swapped.
+@end table
+
+@node D10V-Syntax
+@section Syntax
+@cindex D10V syntax
+@cindex syntax, D10V
+
+The D10V syntax is based on the syntax in Mitsubishi's D10V architecture manual.
+The differences are detailed below.
+
+@menu
+* D10V-Size:: Size Modifiers
+* D10V-Subs:: Sub-Instructions
+* D10V-Chars:: Special Characters
+* D10V-Regs:: Register Names
+* D10V-Addressing:: Addressing Modes
+* D10V-Word:: @@WORD Modifier
+@end menu
+
+
+@node D10V-Size
+@subsection Size Modifiers
+@cindex D10V size modifiers
+@cindex size modifiers, D10V
+The D10V version of @code{@value{AS}} uses the instruction names in the D10V
+Architecture Manual. However, the names in the manual are sometimes ambiguous.
+There are instruction names that can assemble to a short or long form opcode.
+How does the assembler pick the correct form? @code{@value{AS}} will always pick the
+smallest form if it can. When dealing with a symbol that is not defined yet when a
+line is being assembled, it will always use the long form. If you need to force the
+assembler to use either the short or long form of the instruction, you can append
+either @samp{.s} (short) or @samp{.l} (long) to it. For example, if you are writing
+an assembly program and you want to do a branch to a symbol that is defined later
+in your program, you can write @samp{bra.s foo}.
+Objdump and GDB will always append @samp{.s} or @samp{.l} to instructions which
+have both short and long forms.
+
+@node D10V-Subs
+@subsection Sub-Instructions
+@cindex D10V sub-instructions
+@cindex sub-instructions, D10V
+The D10V assembler takes as input a series of instructions, either one-per-line,
+or in the special two-per-line format described in the next section. Some of these
+instructions will be short-form or sub-instructions. These sub-instructions can be packed
+into a single instruction. The assembler will do this automatically. It will also detect
+when it should not pack instructions. For example, when a label is defined, the next
+instruction will never be packaged with the previous one. Whenever a branch and link
+instruction is called, it will not be packaged with the next instruction so the return
+address will be valid. Nops are automatically inserted when necessary.
+
+If you do not want the assembler automatically making these decisions, you can control
+the packaging and execution type (parallel or sequential) with the special execution
+symbols described in the next section.
+
+@node D10V-Chars
+@subsection Special Characters
+@cindex line comment character, D10V
+@cindex D10V line comment character
+@samp{;} and @samp{#} are the line comment characters.
+@cindex sub-instruction ordering, D10V
+@cindex D10V sub-instruction ordering
+Sub-instructions may be executed in order, in reverse-order, or in parallel.
+Instructions listed in the standard one-per-line format will be executed sequentially.
+To specify the executing order, use the following symbols:
+@table @samp
+@item ->
+Sequential with instruction on the left first.
+@item <-
+Sequential with instruction on the right first.
+@item ||
+Parallel
+@end table
+The D10V syntax allows either one instruction per line, one instruction per line with
+the execution symbol, or two instructions per line. For example
+@table @code
+@item abs a1 -> abs r0
+Execute these sequentially. The instruction on the right is in the right
+container and is executed second.
+@item abs r0 <- abs a1
+Execute these reverse-sequentially. The instruction on the right is in the right
+container, and is executed first.
+@item ld2w r2,@@r8+ || mac a0,r0,r7
+Execute these in parallel.
+@item ld2w r2,@@r8+ ||
+@itemx mac a0,r0,r7
+Two-line format. Execute these in parallel.
+@item ld2w r2,@@r8+
+@itemx mac a0,r0,r7
+Two-line format. Execute these sequentially. Assembler will
+put them in the proper containers.
+@item ld2w r2,@@r8+ ->
+@itemx mac a0,r0,r7
+Two-line format. Execute these sequentially. Same as above but
+second instruction will always go into right container.
+@end table
+@cindex symbol names, @samp{$} in
+@cindex @code{$} in symbol names
+Since @samp{$} has no special meaning, you may use it in symbol names.
+
+@node D10V-Regs
+@subsection Register Names
+@cindex D10V registers
+@cindex registers, D10V
+You can use the predefined symbols @samp{r0} through @samp{r15} to refer to the D10V
+registers. You can also use @samp{sp} as an alias for @samp{r15}. The accumulators
+are @samp{a0} and @samp{a1}. There are special register-pair names that may
+optionally be used in opcodes that require even-numbered registers. Register names are
+not case sensitive.
+
+Register Pairs
+@table @code
+@item r0-r1
+@item r2-r3
+@item r4-r5
+@item r6-r7
+@item r8-r9
+@item r10-r11
+@item r12-r13
+@item r14-r15
+@end table
+
+The D10V also has predefined symbols for these control registers and status bits:
+@table @code
+@item psw
+Processor Status Word
+@item bpsw
+Backup Processor Status Word
+@item pc
+Program Counter
+@item bpc
+Backup Program Counter
+@item rpt_c
+Repeat Count
+@item rpt_s
+Repeat Start address
+@item rpt_e
+Repeat End address
+@item mod_s
+Modulo Start address
+@item mod_e
+Modulo End address
+@item iba
+Instruction Break Address
+@item f0
+Flag 0
+@item f1
+Flag 1
+@item c
+Carry flag
+@end table
+
+@node D10V-Addressing
+@subsection Addressing Modes
+@cindex addressing modes, D10V
+@cindex D10V addressing modes
+@code{@value{AS}} understands the following addressing modes for the D10V.
+@code{R@var{n}} in the following refers to any of the numbered
+registers, but @emph{not} the control registers.
+@table @code
+@item R@var{n}
+Register direct
+@item @@R@var{n}
+Register indirect
+@item @@R@var{n}+
+Register indirect with post-increment
+@item @@R@var{n}-
+Register indirect with post-decrement
+@item @@-SP
+Register indirect with pre-decrement
+@item @@(@var{disp}, R@var{n})
+Register indirect with displacement
+@item @var{addr}
+PC relative address (for branch or rep).
+@item #@var{imm}
+Immediate data (the @samp{#} is optional and ignored)
+@end table
+
+@node D10V-Word
+@subsection @@WORD Modifier
+@cindex D10V @@word modifier
+@cindex @@word modifier, D10V
+Any symbol followed by @code{@@word} will be replaced by the symbol's value
+shifted right by 2. This is used in situations such as loading a register
+with the address of a function (or any other code fragment). For example, if
+you want to load a register with the location of the function @code{main} then
+jump to that function, you could do it as follws:
+@smallexample
+@group
+ldi r2, main@@word
+jmp r2
+@end group
+@end smallexample
+
+@node D10V-Float
+@section Floating Point
+@cindex floating point, D10V
+@cindex D10V floating point
+The D10V has no hardware floating point, but the @code{.float} and @code{.double}
+directives generates @sc{ieee} floating-point numbers for compatibility
+with other development tools.
+
+@node D10V-Opcodes
+@section Opcodes
+@cindex D10V opcode summary
+@cindex opcode summary, D10V
+@cindex mnemonics, D10V
+@cindex instruction summary, D10V
+For detailed information on the D10V machine instruction set, see
+@cite{D10V Architecture: A VLIW Microprocessor for Multimedia Applications}
+(Mitsubishi Electric Corp.).
+@code{@value{AS}} implements all the standard D10V opcodes. The only changes are those
+described in the section on size modifiers
+
diff --git a/gas/doc/c-d30v.texi b/gas/doc/c-d30v.texi
new file mode 100644
index 0000000000..731b3441e0
--- /dev/null
+++ b/gas/doc/c-d30v.texi
@@ -0,0 +1,292 @@
+@c Copyright (C) 1997 Free Software Foundation, Inc.
+@c This is part of the GAS manual.
+@c For copying conditions, see the file as.texinfo.
+@ifset GENERIC
+@page
+@node D30V-Dependent
+@chapter D30V Dependent Features
+@end ifset
+@ifclear GENERIC
+@node Machine Dependencies
+@chapter D30V Dependent Features
+@end ifclear
+
+@cindex D30V support
+@menu
+* D30V-Opts:: D30V Options
+* D30V-Syntax:: Syntax
+* D30V-Float:: Floating Point
+* D30V-Opcodes:: Opcodes
+@end menu
+
+@node D30V-Opts
+@section D30V Options
+@cindex options, D30V
+@cindex D30V options
+The Mitsubishi D30V version of @code{@value{AS}} has a few machine
+dependent options.
+
+@table @samp
+@item -O
+The D30V can often execute two sub-instructions in parallel. When this option
+is used, @code{@value{AS}} will attempt to optimize its output by detecting when
+instructions can be executed in parallel.
+
+@item -n
+When this option is used, @code{@value{AS}} will issue a warning every
+time it adds a nop instruction.
+
+@item -N
+When this option is used, @code{@value{AS}} will issue a warning if it
+needs to insert a nop after a 32-bit multiply before a load or 16-bit
+multiply instruction.
+@end table
+
+@node D30V-Syntax
+@section Syntax
+@cindex D30V syntax
+@cindex syntax, D30V
+
+The D30V syntax is based on the syntax in Mitsubishi's D30V architecture manual.
+The differences are detailed below.
+
+@menu
+* D30V-Size:: Size Modifiers
+* D30V-Subs:: Sub-Instructions
+* D30V-Chars:: Special Characters
+* D30V-Guarded:: Guarded Execution
+* D30V-Regs:: Register Names
+* D30V-Addressing:: Addressing Modes
+@end menu
+
+
+@node D30V-Size
+@subsection Size Modifiers
+@cindex D30V size modifiers
+@cindex size modifiers, D30V
+The D30V version of @code{@value{AS}} uses the instruction names in the D30V
+Architecture Manual. However, the names in the manual are sometimes ambiguous.
+There are instruction names that can assemble to a short or long form opcode.
+How does the assembler pick the correct form? @code{@value{AS}} will always pick the
+smallest form if it can. When dealing with a symbol that is not defined yet when a
+line is being assembled, it will always use the long form. If you need to force the
+assembler to use either the short or long form of the instruction, you can append
+either @samp{.s} (short) or @samp{.l} (long) to it. For example, if you are writing
+an assembly program and you want to do a branch to a symbol that is defined later
+in your program, you can write @samp{bra.s foo}.
+Objdump and GDB will always append @samp{.s} or @samp{.l} to instructions which
+have both short and long forms.
+
+@node D30V-Subs
+@subsection Sub-Instructions
+@cindex D30V sub-instructions
+@cindex sub-instructions, D30V
+The D30V assembler takes as input a series of instructions, either one-per-line,
+or in the special two-per-line format described in the next section. Some of these
+instructions will be short-form or sub-instructions. These sub-instructions can be packed
+into a single instruction. The assembler will do this automatically. It will also detect
+when it should not pack instructions. For example, when a label is defined, the next
+instruction will never be packaged with the previous one. Whenever a branch and link
+instruction is called, it will not be packaged with the next instruction so the return
+address will be valid. Nops are automatically inserted when necessary.
+
+If you do not want the assembler automatically making these decisions, you can control
+the packaging and execution type (parallel or sequential) with the special execution
+symbols described in the next section.
+
+@node D30V-Chars
+@subsection Special Characters
+@cindex line comment character, D30V
+@cindex D30V line comment character
+@samp{;} and @samp{#} are the line comment characters.
+@cindex sub-instruction ordering, D30V
+@cindex D30V sub-instruction ordering
+Sub-instructions may be executed in order, in reverse-order, or in parallel.
+Instructions listed in the standard one-per-line format will be executed
+sequentially unless you use the @samp{-O} option.
+
+To specify the executing order, use the following symbols:
+@table @samp
+@item ->
+Sequential with instruction on the left first.
+
+@item <-
+Sequential with instruction on the right first.
+
+@item ||
+Parallel
+@end table
+
+The D30V syntax allows either one instruction per line, one instruction per line with
+the execution symbol, or two instructions per line. For example
+@table @code
+@item abs r2,r3 -> abs r4,r5
+Execute these sequentially. The instruction on the right is in the right
+container and is executed second.
+
+@item abs r2,r3 <- abs r4,r5
+Execute these reverse-sequentially. The instruction on the right is in the right
+container, and is executed first.
+
+@item abs r2,r3 || abs r4,r5
+Execute these in parallel.
+
+@item ldw r2,@@(r3,r4) ||
+@itemx mulx r6,r8,r9
+Two-line format. Execute these in parallel.
+
+@item mulx a0,r8,r9
+@itemx stw r2,@@(r3,r4)
+Two-line format. Execute these sequentially unless @samp{-O} option is
+used. If the @samp{-O} option is used, the assembler will determine if
+the instructions could be done in parallel (the above two instructions
+can be done in parallel), and if so, emit them as parallel instructions.
+The assembler will put them in the proper containers. In the above
+example, the assembler will put the @samp{stw} instruction in left
+container and the @samp{mulx} instruction in the right container.
+
+@item stw r2,@@(r3,r4) ->
+@itemx mulx a0,r8,r9
+Two-line format. Execute the @samp{stw} instruction followed by the
+@samp{mulx} instruction sequentially. The first instruction goes in the
+left container and the second instruction goes into right container.
+The assembler will give an error if the machine ordering constraints are
+violated.
+
+@item stw r2,@@(r3,r4) <-
+@itemx mulx a0,r8,r9
+Same as previous example, except that the @samp{mulx} instruction is
+executed before the @samp{stw} instruction.
+@end table
+
+@cindex symbol names, @samp{$} in
+@cindex @code{$} in symbol names
+Since @samp{$} has no special meaning, you may use it in symbol names.
+
+@node D30V-Guarded
+@subsection Guarded Execution
+@cindex D30V Guarded Execution
+@code{@value{AS}} supports the full range of guarded execution
+directives for each instruction. Just append the directive after the
+instruction proper. The directives are:
+
+@table @samp
+@item /tx
+Execute the instruction if flag f0 is true.
+@item /fx
+Execute the instruction if flag f0 is false.
+@item /xt
+Execute the instruction if flag f1 is true.
+@item /xf
+Execute the instruction if flag f1 is false.
+@item /tt
+Execute the instruction if both flags f0 and f1 are true.
+@item /tf
+Execute the instruction if flag f0 is true and flag f1 is false.
+@end table
+
+@node D30V-Regs
+@subsection Register Names
+@cindex D30V registers
+@cindex registers, D30V
+You can use the predefined symbols @samp{r0} through @samp{r63} to refer
+to the D30V registers. You can also use @samp{sp} as an alias for
+@samp{r63} and @samp{link} as an alias for @samp{r62}. The accumulators
+are @samp{a0} and @samp{a1}.
+
+The D30V also has predefined symbols for these control registers and status bits:
+@table @code
+@item psw
+Processor Status Word
+@item bpsw
+Backup Processor Status Word
+@item pc
+Program Counter
+@item bpc
+Backup Program Counter
+@item rpt_c
+Repeat Count
+@item rpt_s
+Repeat Start address
+@item rpt_e
+Repeat End address
+@item mod_s
+Modulo Start address
+@item mod_e
+Modulo End address
+@item iba
+Instruction Break Address
+@item f0
+Flag 0
+@item f1
+Flag 1
+@item f2
+Flag 2
+@item f3
+Flag 3
+@item f4
+Flag 4
+@item f5
+Flag 5
+@item f6
+Flag 6
+@item f7
+Flag 7
+@item s
+Same as flag 4 (saturation flag)
+@item v
+Same as flag 5 (overflow flag)
+@item va
+Same as flag 6 (sticky overflow flag)
+@item c
+Same as flag 7 (carry/borrow flag)
+@item b
+Same as flag 7 (carry/borrow flag)
+@end table
+
+@node D30V-Addressing
+@subsection Addressing Modes
+@cindex addressing modes, D30V
+@cindex D30V addressing modes
+@code{@value{AS}} understands the following addressing modes for the D30V.
+@code{R@var{n}} in the following refers to any of the numbered
+registers, but @emph{not} the control registers.
+@table @code
+@item R@var{n}
+Register direct
+@item @@R@var{n}
+Register indirect
+@item @@R@var{n}+
+Register indirect with post-increment
+@item @@R@var{n}-
+Register indirect with post-decrement
+@item @@-SP
+Register indirect with pre-decrement
+@item @@(@var{disp}, R@var{n})
+Register indirect with displacement
+@item @var{addr}
+PC relative address (for branch or rep).
+@item #@var{imm}
+Immediate data (the @samp{#} is optional and ignored)
+@end table
+
+@node D30V-Float
+@section Floating Point
+@cindex floating point, D30V
+@cindex D30V floating point
+The D30V has no hardware floating point, but the @code{.float} and @code{.double}
+directives generates @sc{ieee} floating-point numbers for compatibility
+with other development tools.
+
+@node D30V-Opcodes
+@section Opcodes
+@cindex D30V opcode summary
+@cindex opcode summary, D30V
+@cindex mnemonics, D30V
+@cindex instruction summary, D30V
+For detailed information on the D30V machine instruction set, see
+@cite{D30V Architecture: A VLIW Microprocessor for Multimedia Applications}
+(Mitsubishi Electric Corp.).
+@code{@value{AS}} implements all the standard D30V opcodes. The only changes are those
+described in the section on size modifiers
+
diff --git a/gas/doc/c-h8300.texi b/gas/doc/c-h8300.texi
new file mode 100644
index 0000000000..a270918f92
--- /dev/null
+++ b/gas/doc/c-h8300.texi
@@ -0,0 +1,342 @@
+@c Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+@c This is part of the GAS manual.
+@c For copying conditions, see the file as.texinfo.
+@ifset GENERIC
+@page
+@end ifset
+@node H8/300-Dependent
+@chapter H8/300 Dependent Features
+
+@cindex H8/300 support
+@menu
+* H8/300 Options:: Options
+* H8/300 Syntax:: Syntax
+* H8/300 Floating Point:: Floating Point
+* H8/300 Directives:: H8/300 Machine Directives
+* H8/300 Opcodes:: Opcodes
+@end menu
+
+@node H8/300 Options
+@section Options
+
+@cindex H8/300 options (none)
+@cindex options, H8/300 (none)
+@code{@value{AS}} has no additional command-line options for the Hitachi
+H8/300 family.
+
+@node H8/300 Syntax
+@section Syntax
+@menu
+* H8/300-Chars:: Special Characters
+* H8/300-Regs:: Register Names
+* H8/300-Addressing:: Addressing Modes
+@end menu
+
+@node H8/300-Chars
+@subsection Special Characters
+
+@cindex line comment character, H8/300
+@cindex H8/300 line comment character
+@samp{;} is the line comment character.
+
+@cindex line separator, H8/300
+@cindex statement separator, H8/300
+@cindex H8/300 line separator
+@samp{$} can be used instead of a newline to separate statements.
+Therefore @emph{you may not use @samp{$} in symbol names} on the H8/300.
+
+@node H8/300-Regs
+@subsection Register Names
+
+@cindex H8/300 registers
+@cindex register names, H8/300
+You can use predefined symbols of the form @samp{r@var{n}h} and
+@samp{r@var{n}l} to refer to the H8/300 registers as sixteen 8-bit
+general-purpose registers. @var{n} is a digit from @samp{0} to
+@samp{7}); for instance, both @samp{r0h} and @samp{r7l} are valid
+register names.
+
+You can also use the eight predefined symbols @samp{r@var{n}} to refer
+to the H8/300 registers as 16-bit registers (you must use this form for
+addressing).
+
+On the H8/300H, you can also use the eight predefined symbols
+@samp{er@var{n}} (@samp{er0} @dots{} @samp{er7}) to refer to the 32-bit
+general purpose registers.
+
+The two control registers are called @code{pc} (program counter; a
+16-bit register, except on the H8/300H where it is 24 bits) and
+@code{ccr} (condition code register; an 8-bit register). @code{r7} is
+used as the stack pointer, and can also be called @code{sp}.
+
+@node H8/300-Addressing
+@subsection Addressing Modes
+
+@cindex addressing modes, H8/300
+@cindex H8/300 addressing modes
+@value{AS} understands the following addressing modes for the H8/300:
+@table @code
+@item r@var{n}
+Register direct
+
+@item @@r@var{n}
+Register indirect
+
+@need 1200
+@item @@(@var{d}, r@var{n})
+@itemx @@(@var{d}:16, r@var{n})
+@itemx @@(@var{d}:24, r@var{n})
+Register indirect: 16-bit or 24-bit displacement @var{d} from register
+@var{n}. (24-bit displacements are only meaningful on the H8/300H.)
+
+@item @@r@var{n}+
+Register indirect with post-increment
+
+@item @@-r@var{n}
+Register indirect with pre-decrement
+
+@item @code{@@}@var{aa}
+@itemx @code{@@}@var{aa}:8
+@itemx @code{@@}@var{aa}:16
+@itemx @code{@@}@var{aa}:24
+Absolute address @code{aa}. (The address size @samp{:24} only makes
+sense on the H8/300H.)
+
+@item #@var{xx}
+@itemx #@var{xx}:8
+@itemx #@var{xx}:16
+@itemx #@var{xx}:32
+Immediate data @var{xx}. You may specify the @samp{:8}, @samp{:16}, or
+@samp{:32} for clarity, if you wish; but @code{@value{AS}} neither
+requires this nor uses it---the data size required is taken from
+context.
+
+@item @code{@@}@code{@@}@var{aa}
+@itemx @code{@@}@code{@@}@var{aa}:8
+Memory indirect. You may specify the @samp{:8} for clarity, if you
+wish; but @code{@value{AS}} neither requires this nor uses it.
+@end table
+
+@node H8/300 Floating Point
+@section Floating Point
+
+@cindex floating point, H8/300 (@sc{ieee})
+@cindex H8/300 floating point (@sc{ieee})
+The H8/300 family has no hardware floating point, but the @code{.float}
+directive generates @sc{ieee} floating-point numbers for compatibility
+with other development tools.
+
+@page
+@node H8/300 Directives
+@section H8/300 Machine Directives
+
+@cindex H8/300 machine directives (none)
+@cindex machine directives, H8/300 (none)
+@cindex @code{word} directive, H8/300
+@cindex @code{int} directive, H8/300
+@code{@value{AS}} has only one machine-dependent directive for the
+H8/300:
+
+@table @code
+@cindex H8/300H, assembling for
+@item .h8300h
+Recognize and emit additional instructions for the H8/300H variant, and
+also make @code{.int} emit 32-bit numbers rather than the usual (16-bit)
+for the H8/300 family.
+@end table
+
+On the H8/300 family (including the H8/300H) @samp{.word} directives
+generate 16-bit numbers.
+
+@node H8/300 Opcodes
+@section Opcodes
+
+@cindex H8/300 opcode summary
+@cindex opcode summary, H8/300
+@cindex mnemonics, H8/300
+@cindex instruction summary, H8/300
+For detailed information on the H8/300 machine instruction set, see
+@cite{H8/300 Series Programming Manual} (Hitachi ADE--602--025). For
+information specific to the H8/300H, see @cite{H8/300H Series
+Programming Manual} (Hitachi).
+
+@code{@value{AS}} implements all the standard H8/300 opcodes. No additional
+pseudo-instructions are needed on this family.
+
+@ifset SMALL
+@c this table, due to the multi-col faking and hardcoded order, looks silly
+@c except in smallbook. See comments below "@set SMALL" near top of this file.
+
+The following table summarizes the H8/300 opcodes, and their arguments.
+Entries marked @samp{*} are opcodes used only on the H8/300H.
+
+@smallexample
+@c Using @group seems to use the normal baselineskip, not the smallexample
+@c baselineskip; looks approx doublespaced.
+ @i{Legend:}
+ Rs @r{source register}
+ Rd @r{destination register}
+ abs @r{absolute address}
+ imm @r{immediate data}
+ disp:N @r{N-bit displacement from a register}
+ pcrel:N @r{N-bit displacement relative to program counter}
+
+ add.b #imm,rd * andc #imm,ccr
+ add.b rs,rd band #imm,rd
+ add.w rs,rd band #imm,@@rd
+* add.w #imm,rd band #imm,@@abs:8
+* add.l rs,rd bra pcrel:8
+* add.l #imm,rd * bra pcrel:16
+ adds #imm,rd bt pcrel:8
+ addx #imm,rd * bt pcrel:16
+ addx rs,rd brn pcrel:8
+ and.b #imm,rd * brn pcrel:16
+ and.b rs,rd bf pcrel:8
+* and.w rs,rd * bf pcrel:16
+* and.w #imm,rd bhi pcrel:8
+* and.l #imm,rd * bhi pcrel:16
+* and.l rs,rd bls pcrel:8
+@page
+* bls pcrel:16 bld #imm,rd
+ bcc pcrel:8 bld #imm,@@rd
+* bcc pcrel:16 bld #imm,@@abs:8
+ bhs pcrel:8 bnot #imm,rd
+* bhs pcrel:16 bnot #imm,@@rd
+ bcs pcrel:8 bnot #imm,@@abs:8
+* bcs pcrel:16 bnot rs,rd
+ blo pcrel:8 bnot rs,@@rd
+* blo pcrel:16 bnot rs,@@abs:8
+ bne pcrel:8 bor #imm,rd
+* bne pcrel:16 bor #imm,@@rd
+ beq pcrel:8 bor #imm,@@abs:8
+* beq pcrel:16 bset #imm,rd
+ bvc pcrel:8 bset #imm,@@rd
+* bvc pcrel:16 bset #imm,@@abs:8
+ bvs pcrel:8 bset rs,rd
+* bvs pcrel:16 bset rs,@@rd
+ bpl pcrel:8 bset rs,@@abs:8
+* bpl pcrel:16 bsr pcrel:8
+ bmi pcrel:8 bsr pcrel:16
+* bmi pcrel:16 bst #imm,rd
+ bge pcrel:8 bst #imm,@@rd
+* bge pcrel:16 bst #imm,@@abs:8
+ blt pcrel:8 btst #imm,rd
+* blt pcrel:16 btst #imm,@@rd
+ bgt pcrel:8 btst #imm,@@abs:8
+* bgt pcrel:16 btst rs,rd
+ ble pcrel:8 btst rs,@@rd
+* ble pcrel:16 btst rs,@@abs:8
+ bclr #imm,rd bxor #imm,rd
+ bclr #imm,@@rd bxor #imm,@@rd
+ bclr #imm,@@abs:8 bxor #imm,@@abs:8
+ bclr rs,rd cmp.b #imm,rd
+ bclr rs,@@rd cmp.b rs,rd
+ bclr rs,@@abs:8 cmp.w rs,rd
+ biand #imm,rd cmp.w rs,rd
+ biand #imm,@@rd * cmp.w #imm,rd
+ biand #imm,@@abs:8 * cmp.l #imm,rd
+ bild #imm,rd * cmp.l rs,rd
+ bild #imm,@@rd daa rs
+ bild #imm,@@abs:8 das rs
+ bior #imm,rd dec.b rs
+ bior #imm,@@rd * dec.w #imm,rd
+ bior #imm,@@abs:8 * dec.l #imm,rd
+ bist #imm,rd divxu.b rs,rd
+ bist #imm,@@rd * divxu.w rs,rd
+ bist #imm,@@abs:8 * divxs.b rs,rd
+ bixor #imm,rd * divxs.w rs,rd
+ bixor #imm,@@rd eepmov
+ bixor #imm,@@abs:8 * eepmovw
+@page
+* exts.w rd mov.w rs,@@abs:16
+* exts.l rd * mov.l #imm,rd
+* extu.w rd * mov.l rs,rd
+* extu.l rd * mov.l @@rs,rd
+ inc rs * mov.l @@(disp:16,rs),rd
+* inc.w #imm,rd * mov.l @@(disp:24,rs),rd
+* inc.l #imm,rd * mov.l @@rs+,rd
+ jmp @@rs * mov.l @@abs:16,rd
+ jmp abs * mov.l @@abs:24,rd
+ jmp @@@@abs:8 * mov.l rs,@@rd
+ jsr @@rs * mov.l rs,@@(disp:16,rd)
+ jsr abs * mov.l rs,@@(disp:24,rd)
+ jsr @@@@abs:8 * mov.l rs,@@-rd
+ ldc #imm,ccr * mov.l rs,@@abs:16
+ ldc rs,ccr * mov.l rs,@@abs:24
+* ldc @@abs:16,ccr movfpe @@abs:16,rd
+* ldc @@abs:24,ccr movtpe rs,@@abs:16
+* ldc @@(disp:16,rs),ccr mulxu.b rs,rd
+* ldc @@(disp:24,rs),ccr * mulxu.w rs,rd
+* ldc @@rs+,ccr * mulxs.b rs,rd
+* ldc @@rs,ccr * mulxs.w rs,rd
+* mov.b @@(disp:24,rs),rd neg.b rs
+* mov.b rs,@@(disp:24,rd) * neg.w rs
+ mov.b @@abs:16,rd * neg.l rs
+ mov.b rs,rd nop
+ mov.b @@abs:8,rd not.b rs
+ mov.b rs,@@abs:8 * not.w rs
+ mov.b rs,rd * not.l rs
+ mov.b #imm,rd or.b #imm,rd
+ mov.b @@rs,rd or.b rs,rd
+ mov.b @@(disp:16,rs),rd * or.w #imm,rd
+ mov.b @@rs+,rd * or.w rs,rd
+ mov.b @@abs:8,rd * or.l #imm,rd
+ mov.b rs,@@rd * or.l rs,rd
+ mov.b rs,@@(disp:16,rd) orc #imm,ccr
+ mov.b rs,@@-rd pop.w rs
+ mov.b rs,@@abs:8 * pop.l rs
+ mov.w rs,@@rd push.w rs
+* mov.w @@(disp:24,rs),rd * push.l rs
+* mov.w rs,@@(disp:24,rd) rotl.b rs
+* mov.w @@abs:24,rd * rotl.w rs
+* mov.w rs,@@abs:24 * rotl.l rs
+ mov.w rs,rd rotr.b rs
+ mov.w #imm,rd * rotr.w rs
+ mov.w @@rs,rd * rotr.l rs
+ mov.w @@(disp:16,rs),rd rotxl.b rs
+ mov.w @@rs+,rd * rotxl.w rs
+ mov.w @@abs:16,rd * rotxl.l rs
+ mov.w rs,@@(disp:16,rd) rotxr.b rs
+ mov.w rs,@@-rd * rotxr.w rs
+@page
+* rotxr.l rs * stc ccr,@@(disp:24,rd)
+ bpt * stc ccr,@@-rd
+ rte * stc ccr,@@abs:16
+ rts * stc ccr,@@abs:24
+ shal.b rs sub.b rs,rd
+* shal.w rs sub.w rs,rd
+* shal.l rs * sub.w #imm,rd
+ shar.b rs * sub.l rs,rd
+* shar.w rs * sub.l #imm,rd
+* shar.l rs subs #imm,rd
+ shll.b rs subx #imm,rd
+* shll.w rs subx rs,rd
+* shll.l rs * trapa #imm
+ shlr.b rs xor #imm,rd
+* shlr.w rs xor rs,rd
+* shlr.l rs * xor.w #imm,rd
+ sleep * xor.w rs,rd
+ stc ccr,rd * xor.l #imm,rd
+* stc ccr,@@rs * xor.l rs,rd
+* stc ccr,@@(disp:16,rd) xorc #imm,ccr
+@end smallexample
+@end ifset
+
+@cindex size suffixes, H8/300
+@cindex H8/300 size suffixes
+Four H8/300 instructions (@code{add}, @code{cmp}, @code{mov},
+@code{sub}) are defined with variants using the suffixes @samp{.b},
+@samp{.w}, and @samp{.l} to specify the size of a memory operand.
+@code{@value{AS}} supports these suffixes, but does not require them;
+since one of the operands is always a register, @code{@value{AS}} can
+deduce the correct size.
+
+For example, since @code{r0} refers to a 16-bit register,
+@example
+mov r0,@@foo
+@exdent is equivalent to
+mov.w r0,@@foo
+@end example
+
+If you use the size suffixes, @code{@value{AS}} issues a warning when
+the suffix and the register size do not match.
diff --git a/gas/doc/c-h8500.texi b/gas/doc/c-h8500.texi
new file mode 100644
index 0000000000..10f0e64153
--- /dev/null
+++ b/gas/doc/c-h8500.texi
@@ -0,0 +1,272 @@
+@c Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+@c This is part of the GAS manual.
+@c For copying conditions, see the file as.texinfo.
+@page
+@node H8/500-Dependent
+@chapter H8/500 Dependent Features
+
+@cindex H8/500 support
+@menu
+* H8/500 Options:: Options
+* H8/500 Syntax:: Syntax
+* H8/500 Floating Point:: Floating Point
+* H8/500 Directives:: H8/500 Machine Directives
+* H8/500 Opcodes:: Opcodes
+@end menu
+
+@node H8/500 Options
+@section Options
+
+@cindex H8/500 options (none)
+@cindex options, H8/500 (none)
+@code{@value{AS}} has no additional command-line options for the Hitachi
+H8/500 family.
+
+@node H8/500 Syntax
+@section Syntax
+
+@menu
+* H8/500-Chars:: Special Characters
+* H8/500-Regs:: Register Names
+* H8/500-Addressing:: Addressing Modes
+@end menu
+
+@node H8/500-Chars
+@subsection Special Characters
+
+@cindex line comment character, H8/500
+@cindex H8/500 line comment character
+@samp{!} is the line comment character.
+
+@cindex line separator, H8/500
+@cindex statement separator, H8/500
+@cindex H8/500 line separator
+@samp{;} can be used instead of a newline to separate statements.
+
+@cindex symbol names, @samp{$} in
+@cindex @code{$} in symbol names
+Since @samp{$} has no special meaning, you may use it in symbol names.
+
+@node H8/500-Regs
+@subsection Register Names
+
+@cindex H8/500 registers
+@cindex registers, H8/500
+You can use the predefined symbols @samp{r0}, @samp{r1}, @samp{r2},
+@samp{r3}, @samp{r4}, @samp{r5}, @samp{r6}, and @samp{r7} to refer to
+the H8/500 registers.
+
+The H8/500 also has these control registers:
+
+@table @code
+@item cp
+code pointer
+
+@item dp
+data pointer
+
+@item bp
+base pointer
+
+@item tp
+stack top pointer
+
+@item ep
+extra pointer
+
+@item sr
+status register
+
+@item ccr
+condition code register
+@end table
+
+All registers are 16 bits long. To represent 32 bit numbers, use two
+adjacent registers; for distant memory addresses, use one of the segment
+pointers (@code{cp} for the program counter; @code{dp} for
+@code{r0}--@code{r3}; @code{ep} for @code{r4} and @code{r5}; and
+@code{tp} for @code{r6} and @code{r7}.
+
+@node H8/500-Addressing
+@subsection Addressing Modes
+
+@cindex addressing modes, H8/500
+@cindex H8/500 addressing modes
+@value{AS} understands the following addressing modes for the H8/500:
+@table @code
+@item R@var{n}
+Register direct
+
+@item @@R@var{n}
+Register indirect
+
+@item @@(d:8, R@var{n})
+Register indirect with 8 bit signed displacement
+
+@item @@(d:16, R@var{n})
+Register indirect with 16 bit signed displacement
+
+@item @@-R@var{n}
+Register indirect with pre-decrement
+
+@item @@R@var{n}+
+Register indirect with post-increment
+
+@item @@@var{aa}:8
+8 bit absolute address
+
+@item @@@var{aa}:16
+16 bit absolute address
+
+@item #@var{xx}:8
+8 bit immediate
+
+@item #@var{xx}:16
+16 bit immediate
+@end table
+
+@node H8/500 Floating Point
+@section Floating Point
+
+@cindex floating point, H8/500 (@sc{ieee})
+@cindex H8/500 floating point (@sc{ieee})
+The H8/500 family has no hardware floating point, but the @code{.float}
+directive generates @sc{ieee} floating-point numbers for compatibility
+with other development tools.
+
+@node H8/500 Directives
+@section H8/500 Machine Directives
+
+@cindex H8/500 machine directives (none)
+@cindex machine directives, H8/500 (none)
+@cindex @code{word} directive, H8/500
+@cindex @code{int} directive, H8/500
+@code{@value{AS}} has no machine-dependent directives for the H8/500.
+However, on this platform the @samp{.int} and @samp{.word} directives
+generate 16-bit numbers.
+
+@node H8/500 Opcodes
+@section Opcodes
+
+@cindex H8/500 opcode summary
+@cindex opcode summary, H8/500
+@cindex mnemonics, H8/500
+@cindex instruction summary, H8/500
+For detailed information on the H8/500 machine instruction set, see
+@cite{H8/500 Series Programming Manual} (Hitachi M21T001).
+
+@code{@value{AS}} implements all the standard H8/500 opcodes. No additional
+pseudo-instructions are needed on this family.
+
+@ifset SMALL
+@c this table, due to the multi-col faking and hardcoded order, looks silly
+@c except in smallbook. See comments below "@set SMALL" near top of this file.
+
+The following table summarizes H8/500 opcodes and their operands:
+
+@c Use @group if it ever works, instead of @page
+@page
+@smallexample
+@i{Legend:}
+abs8 @r{8-bit absolute address}
+abs16 @r{16-bit absolute address}
+abs24 @r{24-bit absolute address}
+crb @r{@code{ccr}, @code{br}, @code{ep}, @code{dp}, @code{tp}, @code{dp}}
+disp8 @r{8-bit displacement}
+ea @r{@code{rn}, @code{@@rn}, @code{@@(d:8, rn)}, @code{@@(d:16, rn)},}
+ @r{@code{@@-rn}, @code{@@rn+}, @code{@@aa:8}, @code{@@aa:16},}
+ @r{@code{#xx:8}, @code{#xx:16}}
+ea_mem @r{@code{@@rn}, @code{@@(d:8, rn)}, @code{@@(d:16, rn)},}
+ @r{@code{@@-rn}, @code{@@rn+}, @code{@@aa:8}, @code{@@aa:16}}
+ea_noimm @r{@code{rn}, @code{@@rn}, @code{@@(d:8, rn)}, @code{@@(d:16, rn)},}
+ @r{@code{@@-rn}, @code{@@rn+}, @code{@@aa:8}, @code{@@aa:16}}
+fp r6
+imm4 @r{4-bit immediate data}
+imm8 @r{8-bit immediate data}
+imm16 @r{16-bit immediate data}
+pcrel8 @r{8-bit offset from program counter}
+pcrel16 @r{16-bit offset from program counter}
+qim @r{@code{-2}, @code{-1}, @code{1}, @code{2}}
+rd @r{any register}
+rs @r{a register distinct from rd}
+rlist @r{comma-separated list of registers in parentheses;}
+ @r{register ranges @code{rd-rs} are allowed}
+sp @r{stack pointer (@code{r7})}
+sr @r{status register}
+sz @r{size; @samp{.b} or @samp{.w}. If omitted, default @samp{.w}}
+
+ldc[.b] ea,crb bcc[.w] pcrel16
+ldc[.w] ea,sr bcc[.b] pcrel8
+add[:q] sz qim,ea_noimm bhs[.w] pcrel16
+add[:g] sz ea,rd bhs[.b] pcrel8
+adds sz ea,rd bcs[.w] pcrel16
+addx sz ea,rd bcs[.b] pcrel8
+and sz ea,rd blo[.w] pcrel16
+andc[.b] imm8,crb blo[.b] pcrel8
+andc[.w] imm16,sr bne[.w] pcrel16
+bpt bne[.b] pcrel8
+bra[.w] pcrel16 beq[.w] pcrel16
+bra[.b] pcrel8 beq[.b] pcrel8
+bt[.w] pcrel16 bvc[.w] pcrel16
+bt[.b] pcrel8 bvc[.b] pcrel8
+brn[.w] pcrel16 bvs[.w] pcrel16
+brn[.b] pcrel8 bvs[.b] pcrel8
+bf[.w] pcrel16 bpl[.w] pcrel16
+bf[.b] pcrel8 bpl[.b] pcrel8
+bhi[.w] pcrel16 bmi[.w] pcrel16
+bhi[.b] pcrel8 bmi[.b] pcrel8
+bls[.w] pcrel16 bge[.w] pcrel16
+bls[.b] pcrel8 bge[.b] pcrel8
+@page
+blt[.w] pcrel16 mov[:g][.b] imm8,ea_mem
+blt[.b] pcrel8 mov[:g][.w] imm16,ea_mem
+bgt[.w] pcrel16 movfpe[.b] ea,rd
+bgt[.b] pcrel8 movtpe[.b] rs,ea_noimm
+ble[.w] pcrel16 mulxu sz ea,rd
+ble[.b] pcrel8 neg sz ea
+bclr sz imm4,ea_noimm nop
+bclr sz rs,ea_noimm not sz ea
+bnot sz imm4,ea_noimm or sz ea,rd
+bnot sz rs,ea_noimm orc[.b] imm8,crb
+bset sz imm4,ea_noimm orc[.w] imm16,sr
+bset sz rs,ea_noimm pjmp abs24
+bsr[.b] pcrel8 pjmp @@rd
+bsr[.w] pcrel16 pjsr abs24
+btst sz imm4,ea_noimm pjsr @@rd
+btst sz rs,ea_noimm prtd imm8
+clr sz ea prtd imm16
+cmp[:e][.b] imm8,rd prts
+cmp[:i][.w] imm16,rd rotl sz ea
+cmp[:g].b imm8,ea_noimm rotr sz ea
+cmp[:g][.w] imm16,ea_noimm rotxl sz ea
+Cmp[:g] sz ea,rd rotxr sz ea
+dadd rs,rd rtd imm8
+divxu sz ea,rd rtd imm16
+dsub rs,rd rts
+exts[.b] rd scb/f rs,pcrel8
+extu[.b] rd scb/ne rs,pcrel8
+jmp @@rd scb/eq rs,pcrel8
+jmp @@(imm8,rd) shal sz ea
+jmp @@(imm16,rd) shar sz ea
+jmp abs16 shll sz ea
+jsr @@rd shlr sz ea
+jsr @@(imm8,rd) sleep
+jsr @@(imm16,rd) stc[.b] crb,ea_noimm
+jsr abs16 stc[.w] sr,ea_noimm
+ldm @@sp+,(rlist) stm (rlist),@@-sp
+link fp,imm8 sub sz ea,rd
+link fp,imm16 subs sz ea,rd
+mov[:e][.b] imm8,rd subx sz ea,rd
+mov[:i][.w] imm16,rd swap[.b] rd
+mov[:l][.w] abs8,rd tas[.b] ea
+mov[:l].b abs8,rd trapa imm4
+mov[:s][.w] rs,abs8 trap/vs
+mov[:s].b rs,abs8 tst sz ea
+mov[:f][.w] @@(disp8,fp),rd unlk fp
+mov[:f][.w] rs,@@(disp8,fp) xch[.w] rs,rd
+mov[:f].b @@(disp8,fp),rd xor sz ea,rd
+mov[:f].b rs,@@(disp8,fp) xorc.b imm8,crb
+mov[:g] sz rs,ea_mem xorc.w imm16,sr
+mov[:g] sz ea,rd
+@end smallexample
+@end ifset
diff --git a/gas/doc/c-hppa.texi b/gas/doc/c-hppa.texi
new file mode 100644
index 0000000000..5fa535fd78
--- /dev/null
+++ b/gas/doc/c-hppa.texi
@@ -0,0 +1,263 @@
+@c Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+@c This is part of the GAS manual.
+@c For copying conditions, see the file as.texinfo.
+@page
+@node HPPA-Dependent
+@chapter HPPA Dependent Features
+
+@cindex support
+@menu
+* HPPA Notes:: Notes
+* HPPA Options:: Options
+* HPPA Syntax:: Syntax
+* HPPA Floating Point:: Floating Point
+* HPPA Directives:: HPPA Machine Directives
+* HPPA Opcodes:: Opcodes
+@end menu
+
+@node HPPA Notes
+@section Notes
+As a back end for @sc{gnu} @sc{cc} @code{@value{AS}} has been throughly tested and should
+work extremely well. We have tested it only minimally on hand written assembly
+code and no one has tested it much on the assembly output from the HP
+compilers.
+
+The format of the debugging sections has changed since the original
+@code{@value{AS}} port (version 1.3X) was released; therefore,
+you must rebuild all HPPA objects and libraries with the new
+assembler so that you can debug the final executable.
+
+The HPPA @code{@value{AS}} port generates a small subset of the relocations
+available in the SOM and ELF object file formats. Additional relocation
+support will be added as it becomes necessary.
+
+@node HPPA Options
+@section Options
+@code{@value{AS}} has no machine-dependent command-line options for the HPPA.
+
+@cindex HPPA Syntax
+@node HPPA Syntax
+@section Syntax
+The assembler syntax closely follows the HPPA instruction set
+reference manual; assembler directives and general syntax closely follow the
+HPPA assembly language reference manual, with a few noteworthy differences.
+
+First, a colon may immediately follow a label definition. This is
+simply for compatibility with how most assembly language programmers
+write code.
+
+Some obscure expression parsing problems may affect hand written code which
+uses the @code{spop} instructions, or code which makes significant
+use of the @code{!} line separator.
+
+@code{@value{AS}} is much less forgiving about missing arguments and other
+similar oversights than the HP assembler. @code{@value{AS}} notifies you
+of missing arguments as syntax errors; this is regarded as a feature, not a
+bug.
+
+Finally, @code{@value{AS}} allows you to use an external symbol without
+explicitly importing the symbol. @emph{Warning:} in the future this will be
+an error for HPPA targets.
+
+Special characters for HPPA targets include:
+
+@samp{;} is the line comment character.
+
+@samp{!} can be used instead of a newline to separate statements.
+
+Since @samp{$} has no special meaning, you may use it in symbol names.
+
+@node HPPA Floating Point
+@section Floating Point
+@cindex floating point, HPPA (@sc{ieee})
+@cindex HPPA floating point (@sc{ieee})
+The HPPA family uses @sc{ieee} floating-point numbers.
+
+@node HPPA Directives
+@section HPPA Assembler Directives
+
+@code{@value{AS}} for the HPPA supports many additional directives for
+compatibility with the native assembler. This section describes them only
+briefly. For detailed information on HPPA-specific assembler directives, see
+@cite{HP9000 Series 800 Assembly Language Reference Manual} (HP 92432-90001).
+
+@cindex HPPA directives not supported
+@code{@value{AS}} does @emph{not} support the following assembler directives
+described in the HP manual:
+
+@example
+.endm .liston
+.enter .locct
+.leave .macro
+.listoff
+@end example
+
+@cindex @code{.param} on HPPA
+Beyond those implemented for compatibility, @code{@value{AS}} supports one
+additional assembler directive for the HPPA: @code{.param}. It conveys
+register argument locations for static functions. Its syntax closely follows
+the @code{.export} directive.
+
+@cindex HPPA-only directives
+These are the additional directives in @code{@value{AS}} for the HPPA:
+
+@table @code
+@item .block @var{n}
+@itemx .blockz @var{n}
+Reserve @var{n} bytes of storage, and initialize them to zero.
+
+@item .call
+Mark the beginning of a procedure call. Only the special case with @emph{no
+arguments} is allowed.
+
+@item .callinfo [ @var{param}=@var{value}, @dots{} ] [ @var{flag}, @dots{} ]
+Specify a number of parameters and flags that define the environment for a
+procedure.
+
+@var{param} may be any of @samp{frame} (frame size), @samp{entry_gr} (end of
+general register range), @samp{entry_fr} (end of float register range),
+@samp{entry_sr} (end of space register range).
+
+The values for @var{flag} are @samp{calls} or @samp{caller} (proc has
+subroutines), @samp{no_calls} (proc does not call subroutines), @samp{save_rp}
+(preserve return pointer), @samp{save_sp} (proc preserves stack pointer),
+@samp{no_unwind} (do not unwind this proc), @samp{hpux_int} (proc is interrupt
+routine).
+
+@item .code
+Assemble into the standard section called @samp{$TEXT$}, subsection
+@samp{$CODE$}.
+
+@ifset SOM
+@item .copyright "@var{string}"
+In the SOM object format, insert @var{string} into the object code, marked as a
+copyright string.
+@end ifset
+
+@ifset ELF
+@item .copyright "@var{string}"
+In the ELF object format, insert @var{string} into the object code, marked as a
+version string.
+@end ifset
+
+@item .enter
+Not yet supported; the assembler rejects programs containing this directive.
+
+@item .entry
+Mark the beginning of a procedure.
+
+@item .exit
+Mark the end of a procedure.
+
+@item .export @var{name} [ ,@var{typ} ] [ ,@var{param}=@var{r} ]
+Make a procedure @var{name} available to callers. @var{typ}, if present, must
+be one of @samp{absolute}, @samp{code} (ELF only, not SOM), @samp{data},
+@samp{entry}, @samp{data}, @samp{entry}, @samp{millicode}, @samp{plabel},
+@samp{pri_prog}, or @samp{sec_prog}.
+
+@var{param}, if present, provides either relocation information for the
+procedure arguments and result, or a privilege level. @var{param} may be
+@samp{argw@var{n}} (where @var{n} ranges from @code{0} to @code{3}, and
+indicates one of four one-word arguments); @samp{rtnval} (the procedure's
+result); or @samp{priv_lev} (privilege level). For arguments or the result,
+@var{r} specifies how to relocate, and must be one of @samp{no} (not
+relocatable), @samp{gr} (argument is in general register), @samp{fr} (in
+floating point register), or @samp{fu} (upper half of float register).
+For @samp{priv_lev}, @var{r} is an integer.
+
+@item .half @var{n}
+Define a two-byte integer constant @var{n}; synonym for the portable
+@code{@value{AS}} directive @code{.short}.
+
+@item .import @var{name} [ ,@var{typ} ]
+Converse of @code{.export}; make a procedure available to call. The arguments
+use the same conventions as the first two arguments for @code{.export}.
+
+@item .label @var{name}
+Define @var{name} as a label for the current assembly location.
+
+@item .leave
+Not yet supported; the assembler rejects programs containing this directive.
+
+@item .origin @var{lc}
+Advance location counter to @var{lc}. Synonym for the @code{@value{as}}
+portable directive @code{.org}.
+
+@item .param @var{name} [ ,@var{typ} ] [ ,@var{param}=@var{r} ]
+@c Not in HP manual; @sc{gnu} HPPA extension
+Similar to @code{.export}, but used for static procedures.
+
+@item .proc
+Use preceding the first statement of a procedure.
+
+@item .procend
+Use following the last statement of a procedure.
+
+@item @var{label} .reg @var{expr}
+@c ?? Not in HP manual (Jan 1988 vn)
+Synonym for @code{.equ}; define @var{label} with the absolute expression
+@var{expr} as its value.
+
+@item .space @var{secname} [ ,@var{params} ]
+Switch to section @var{secname}, creating a new section by that name if
+necessary. You may only use @var{params} when creating a new section, not
+when switching to an existing one. @var{secname} may identify a section by
+number rather than by name.
+
+If specified, the list @var{params} declares attributes of the section,
+identified by keywords. The keywords recognized are @samp{spnum=@var{exp}}
+(identify this section by the number @var{exp}, an absolute expression),
+@samp{sort=@var{exp}} (order sections according to this sort key when linking;
+@var{exp} is an absolute expression), @samp{unloadable} (section contains no
+loadable data), @samp{notdefined} (this section defined elsewhere), and
+@samp{private} (data in this section not available to other programs).
+
+@item .spnum @var{secnam}
+@c ?? Not in HP manual (Jan 1988)
+Allocate four bytes of storage, and initialize them with the section number of
+the section named @var{secnam}. (You can define the section number with the
+HPPA @code{.space} directive.)
+
+@cindex @code{string} directive on HPPA
+@item .string "@var{str}"
+Copy the characters in the string @var{str} to the object file.
+@xref{Strings,,Strings}, for information on escape sequences you can use in
+@code{@value{AS}} strings.
+
+@emph{Warning!} The HPPA version of @code{.string} differs from the
+usual @code{@value{AS}} definition: it does @emph{not} write a zero byte
+after copying @var{str}.
+
+@item .stringz "@var{str}"
+Like @code{.string}, but appends a zero byte after copying @var{str} to object
+file.
+
+@item .subspa @var{name} [ ,@var{params} ]
+@itemx .nsubspa @var{name} [ ,@var{params} ]
+Similar to @code{.space}, but selects a subsection @var{name} within the
+current section. You may only specify @var{params} when you create a
+subsection (in the first instance of @code{.subspa} for this @var{name}).
+
+If specified, the list @var{params} declares attributes of the subsection,
+identified by keywords. The keywords recognized are @samp{quad=@var{expr}}
+(``quadrant'' for this subsection), @samp{align=@var{expr}} (alignment for
+beginning of this subsection; a power of two), @samp{access=@var{expr}} (value
+for ``access rights'' field), @samp{sort=@var{expr}} (sorting order for this
+subspace in link), @samp{code_only} (subsection contains only code),
+@samp{unloadable} (subsection cannot be loaded into memory), @samp{common}
+(subsection is common block), @samp{dup_comm} (initialized data may have
+duplicate names), or @samp{zero} (subsection is all zeros, do not write in
+object file).
+
+@code{.nsubspa} always creates a new subspace with the given name, even
+if one with the same name already exists.
+
+@item .version "@var{str}"
+Write @var{str} as version identifier in object code.
+@end table
+
+@node HPPA Opcodes
+@section Opcodes
+For detailed information on the HPPA machine instruction set, see
+@cite{PA-RISC Architecture and Instruction Set Reference Manual}
+(HP 09740-90039).
diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi
new file mode 100644
index 0000000000..e27893b892
--- /dev/null
+++ b/gas/doc/c-i386.texi
@@ -0,0 +1,518 @@
+@c Copyright (C) 1991, 92, 93, 94, 95, 97, 1998 Free Software Foundation, Inc.
+@c This is part of the GAS manual.
+@c For copying conditions, see the file as.texinfo.
+@ifset GENERIC
+@page
+@node i386-Dependent
+@chapter 80386 Dependent Features
+@end ifset
+@ifclear GENERIC
+@node Machine Dependencies
+@chapter 80386 Dependent Features
+@end ifclear
+
+@cindex i386 support
+@cindex i80306 support
+@menu
+* i386-Options:: Options
+* i386-Syntax:: AT&T Syntax versus Intel Syntax
+* i386-Mnemonics:: Instruction Naming
+* i386-Regs:: Register Naming
+* i386-Prefixes:: Instruction Prefixes
+* i386-Memory:: Memory References
+* i386-jumps:: Handling of Jump Instructions
+* i386-Float:: Floating Point
+* i386-SIMD:: Intel's MMX and AMD's 3DNow! SIMD Operations
+* i386-16bit:: Writing 16-bit Code
+* i386-Bugs:: AT&T Syntax bugs
+* i386-Notes:: Notes
+@end menu
+
+@node i386-Options
+@section Options
+
+@cindex options for i386 (none)
+@cindex i386 options (none)
+The 80386 has no machine dependent options.
+
+@node i386-Syntax
+@section AT&T Syntax versus Intel Syntax
+
+@cindex i386 syntax compatibility
+@cindex syntax compatibility, i386
+In order to maintain compatibility with the output of @code{@value{GCC}},
+@code{@value{AS}} supports AT&T System V/386 assembler syntax. This is quite
+different from Intel syntax. We mention these differences because
+almost all 80386 documents use Intel syntax. Notable differences
+between the two syntaxes are:
+
+@cindex immediate operands, i386
+@cindex i386 immediate operands
+@cindex register operands, i386
+@cindex i386 register operands
+@cindex jump/call operands, i386
+@cindex i386 jump/call operands
+@cindex operand delimiters, i386
+@itemize @bullet
+@item
+AT&T immediate operands are preceded by @samp{$}; Intel immediate
+operands are undelimited (Intel @samp{push 4} is AT&T @samp{pushl $4}).
+AT&T register operands are preceded by @samp{%}; Intel register operands
+are undelimited. AT&T absolute (as opposed to PC relative) jump/call
+operands are prefixed by @samp{*}; they are undelimited in Intel syntax.
+
+@cindex i386 source, destination operands
+@cindex source, destination operands; i386
+@item
+AT&T and Intel syntax use the opposite order for source and destination
+operands. Intel @samp{add eax, 4} is @samp{addl $4, %eax}. The
+@samp{source, dest} convention is maintained for compatibility with
+previous Unix assemblers. Note that instructions with more than one
+source operand, such as the @samp{enter} instruction, do @emph{not} have
+reversed order. @ref{i386-Bugs}.
+
+@cindex mnemonic suffixes, i386
+@cindex sizes operands, i386
+@cindex i386 size suffixes
+@item
+In AT&T syntax the size of memory operands is determined from the last
+character of the instruction mnemonic. Mnemonic suffixes of @samp{b},
+@samp{w}, and @samp{l} specify byte (8-bit), word (16-bit), and long
+(32-bit) memory references. Intel syntax accomplishes this by prefixing
+memory operands (@emph{not} the instruction mnemonics) with @samp{byte
+ptr}, @samp{word ptr}, and @samp{dword ptr}. Thus, Intel @samp{mov al,
+byte ptr @var{foo}} is @samp{movb @var{foo}, %al} in AT&T syntax.
+
+@cindex return instructions, i386
+@cindex i386 jump, call, return
+@item
+Immediate form long jumps and calls are
+@samp{lcall/ljmp $@var{section}, $@var{offset}} in AT&T syntax; the
+Intel syntax is
+@samp{call/jmp far @var{section}:@var{offset}}. Also, the far return
+instruction
+is @samp{lret $@var{stack-adjust}} in AT&T syntax; Intel syntax is
+@samp{ret far @var{stack-adjust}}.
+
+@cindex sections, i386
+@cindex i386 sections
+@item
+The AT&T assembler does not provide support for multiple section
+programs. Unix style systems expect all programs to be single sections.
+@end itemize
+
+@node i386-Mnemonics
+@section Instruction Naming
+
+@cindex i386 instruction naming
+@cindex instruction naming, i386
+Instruction mnemonics are suffixed with one character modifiers which
+specify the size of operands. The letters @samp{b}, @samp{w}, and
+@samp{l} specify byte, word, and long operands. If no suffix is
+specified by an instruction then @code{@value{AS}} tries to fill in the
+missing suffix based on the destination register operand (the last one
+by convention). Thus, @samp{mov %ax, %bx} is equivalent to @samp{movw
+%ax, %bx}; also, @samp{mov $1, %bx} is equivalent to @samp{movw $1,
+%bx}. Note that this is incompatible with the AT&T Unix assembler which
+assumes that a missing mnemonic suffix implies long operand size. (This
+incompatibility does not affect compiler output since compilers always
+explicitly specify the mnemonic suffix.)
+
+Almost all instructions have the same names in AT&T and Intel format.
+There are a few exceptions. The sign extend and zero extend
+instructions need two sizes to specify them. They need a size to
+sign/zero extend @emph{from} and a size to zero extend @emph{to}. This
+is accomplished by using two instruction mnemonic suffixes in AT&T
+syntax. Base names for sign extend and zero extend are
+@samp{movs@dots{}} and @samp{movz@dots{}} in AT&T syntax (@samp{movsx}
+and @samp{movzx} in Intel syntax). The instruction mnemonic suffixes
+are tacked on to this base name, the @emph{from} suffix before the
+@emph{to} suffix. Thus, @samp{movsbl %al, %edx} is AT&T syntax for
+``move sign extend @emph{from} %al @emph{to} %edx.'' Possible suffixes,
+thus, are @samp{bl} (from byte to long), @samp{bw} (from byte to word),
+and @samp{wl} (from word to long).
+
+@cindex conversion instructions, i386
+@cindex i386 conversion instructions
+The Intel-syntax conversion instructions
+
+@itemize @bullet
+@item
+@samp{cbw} --- sign-extend byte in @samp{%al} to word in @samp{%ax},
+
+@item
+@samp{cwde} --- sign-extend word in @samp{%ax} to long in @samp{%eax},
+
+@item
+@samp{cwd} --- sign-extend word in @samp{%ax} to long in @samp{%dx:%ax},
+
+@item
+@samp{cdq} --- sign-extend dword in @samp{%eax} to quad in @samp{%edx:%eax},
+@end itemize
+
+@noindent
+are called @samp{cbtw}, @samp{cwtl}, @samp{cwtd}, and @samp{cltd} in
+AT&T naming. @code{@value{AS}} accepts either naming for these instructions.
+
+@cindex jump instructions, i386
+@cindex call instructions, i386
+Far call/jump instructions are @samp{lcall} and @samp{ljmp} in
+AT&T syntax, but are @samp{call far} and @samp{jump far} in Intel
+convention.
+
+@node i386-Regs
+@section Register Naming
+
+@cindex i386 registers
+@cindex registers, i386
+Register operands are always prefixed with @samp{%}. The 80386 registers
+consist of
+
+@itemize @bullet
+@item
+the 8 32-bit registers @samp{%eax} (the accumulator), @samp{%ebx},
+@samp{%ecx}, @samp{%edx}, @samp{%edi}, @samp{%esi}, @samp{%ebp} (the
+frame pointer), and @samp{%esp} (the stack pointer).
+
+@item
+the 8 16-bit low-ends of these: @samp{%ax}, @samp{%bx}, @samp{%cx},
+@samp{%dx}, @samp{%di}, @samp{%si}, @samp{%bp}, and @samp{%sp}.
+
+@item
+the 8 8-bit registers: @samp{%ah}, @samp{%al}, @samp{%bh},
+@samp{%bl}, @samp{%ch}, @samp{%cl}, @samp{%dh}, and @samp{%dl} (These
+are the high-bytes and low-bytes of @samp{%ax}, @samp{%bx},
+@samp{%cx}, and @samp{%dx})
+
+@item
+the 6 section registers @samp{%cs} (code section), @samp{%ds}
+(data section), @samp{%ss} (stack section), @samp{%es}, @samp{%fs},
+and @samp{%gs}.
+
+@item
+the 3 processor control registers @samp{%cr0}, @samp{%cr2}, and
+@samp{%cr3}.
+
+@item
+the 6 debug registers @samp{%db0}, @samp{%db1}, @samp{%db2},
+@samp{%db3}, @samp{%db6}, and @samp{%db7}.
+
+@item
+the 2 test registers @samp{%tr6} and @samp{%tr7}.
+
+@item
+the 8 floating point register stack @samp{%st} or equivalently
+@samp{%st(0)}, @samp{%st(1)}, @samp{%st(2)}, @samp{%st(3)},
+@samp{%st(4)}, @samp{%st(5)}, @samp{%st(6)}, and @samp{%st(7)}.
+@end itemize
+
+@node i386-Prefixes
+@section Instruction Prefixes
+
+@cindex i386 instruction prefixes
+@cindex instruction prefixes, i386
+@cindex prefixes, i386
+Instruction prefixes are used to modify the following instruction. They
+are used to repeat string instructions, to provide section overrides, to
+perform bus lock operations, and to change operand and address sizes.
+(Most instructions that normally operate on 32-bit operands will use
+16-bit operands if the instruction has an ``operand size'' prefix.)
+Instruction prefixes are best written on the same line as the instruction
+they act upon. For example, the @samp{scas} (scan string) instruction is
+repeated with:
+
+@smallexample
+ repne scas %es:(%edi),%al
+@end smallexample
+
+You may also place prefixes on the lines immediately preceding the
+instruction, but this circumvents checks that @code{@value{AS}} does
+with prefixes, and will not work with all prefixes.
+
+Here is a list of instruction prefixes:
+
+@cindex section override prefixes, i386
+@itemize @bullet
+@item
+Section override prefixes @samp{cs}, @samp{ds}, @samp{ss}, @samp{es},
+@samp{fs}, @samp{gs}. These are automatically added by specifying
+using the @var{section}:@var{memory-operand} form for memory references.
+
+@cindex size prefixes, i386
+@item
+Operand/Address size prefixes @samp{data16} and @samp{addr16}
+change 32-bit operands/addresses into 16-bit operands/addresses,
+while @samp{data32} and @samp{addr32} change 16-bit ones (in a
+@code{.code16} section) into 32-bit operands/addresses. These prefixes
+@emph{must} appear on the same line of code as the instruction they
+modify. For example, in a 16-bit @code{.code16} section, you might
+write:
+
+@smallexample
+ addr32 jmpl *(%ebx)
+@end smallexample
+
+@cindex bus lock prefixes, i386
+@cindex inhibiting interrupts, i386
+@item
+The bus lock prefix @samp{lock} inhibits interrupts during execution of
+the instruction it precedes. (This is only valid with certain
+instructions; see a 80386 manual for details).
+
+@cindex coprocessor wait, i386
+@item
+The wait for coprocessor prefix @samp{wait} waits for the coprocessor to
+complete the current instruction. This should never be needed for the
+80386/80387 combination.
+
+@cindex repeat prefixes, i386
+@item
+The @samp{rep}, @samp{repe}, and @samp{repne} prefixes are added
+to string instructions to make them repeat @samp{%ecx} times (@samp{%cx}
+times if the current address size is 16-bits).
+@end itemize
+
+@node i386-Memory
+@section Memory References
+
+@cindex i386 memory references
+@cindex memory references, i386
+An Intel syntax indirect memory reference of the form
+
+@smallexample
+@var{section}:[@var{base} + @var{index}*@var{scale} + @var{disp}]
+@end smallexample
+
+@noindent
+is translated into the AT&T syntax
+
+@smallexample
+@var{section}:@var{disp}(@var{base}, @var{index}, @var{scale})
+@end smallexample
+
+@noindent
+where @var{base} and @var{index} are the optional 32-bit base and
+index registers, @var{disp} is the optional displacement, and
+@var{scale}, taking the values 1, 2, 4, and 8, multiplies @var{index}
+to calculate the address of the operand. If no @var{scale} is
+specified, @var{scale} is taken to be 1. @var{section} specifies the
+optional section register for the memory operand, and may override the
+default section register (see a 80386 manual for section register
+defaults). Note that section overrides in AT&T syntax @emph{must}
+be preceded by a @samp{%}. If you specify a section override which
+coincides with the default section register, @code{@value{AS}} does @emph{not}
+output any section register override prefixes to assemble the given
+instruction. Thus, section overrides can be specified to emphasize which
+section register is used for a given memory operand.
+
+Here are some examples of Intel and AT&T style memory references:
+
+@table @asis
+@item AT&T: @samp{-4(%ebp)}, Intel: @samp{[ebp - 4]}
+@var{base} is @samp{%ebp}; @var{disp} is @samp{-4}. @var{section} is
+missing, and the default section is used (@samp{%ss} for addressing with
+@samp{%ebp} as the base register). @var{index}, @var{scale} are both missing.
+
+@item AT&T: @samp{foo(,%eax,4)}, Intel: @samp{[foo + eax*4]}
+@var{index} is @samp{%eax} (scaled by a @var{scale} 4); @var{disp} is
+@samp{foo}. All other fields are missing. The section register here
+defaults to @samp{%ds}.
+
+@item AT&T: @samp{foo(,1)}; Intel @samp{[foo]}
+This uses the value pointed to by @samp{foo} as a memory operand.
+Note that @var{base} and @var{index} are both missing, but there is only
+@emph{one} @samp{,}. This is a syntactic exception.
+
+@item AT&T: @samp{%gs:foo}; Intel @samp{gs:foo}
+This selects the contents of the variable @samp{foo} with section
+register @var{section} being @samp{%gs}.
+@end table
+
+Absolute (as opposed to PC relative) call and jump operands must be
+prefixed with @samp{*}. If no @samp{*} is specified, @code{@value{AS}}
+always chooses PC relative addressing for jump/call labels.
+
+Any instruction that has a memory operand, but no register operand,
+@emph{must} specify its size (byte, word, or long) with an instruction
+mnemonic suffix (@samp{b}, @samp{w}, or @samp{l}, respectively).
+
+@node i386-jumps
+@section Handling of Jump Instructions
+
+@cindex jump optimization, i386
+@cindex i386 jump optimization
+Jump instructions are always optimized to use the smallest possible
+displacements. This is accomplished by using byte (8-bit) displacement
+jumps whenever the target is sufficiently close. If a byte displacement
+is insufficient a long (32-bit) displacement is used. We do not support
+word (16-bit) displacement jumps in 32-bit mode (i.e. prefixing the jump
+instruction with the @samp{data16} instruction prefix), since the 80386
+insists upon masking @samp{%eip} to 16 bits after the word displacement
+is added.
+
+Note that the @samp{jcxz}, @samp{jecxz}, @samp{loop}, @samp{loopz},
+@samp{loope}, @samp{loopnz} and @samp{loopne} instructions only come in byte
+displacements, so that if you use these instructions (@code{@value{GCC}} does
+not use them) you may get an error message (and incorrect code). The AT&T
+80386 assembler tries to get around this problem by expanding @samp{jcxz foo}
+to
+
+@smallexample
+ jcxz cx_zero
+ jmp cx_nonzero
+cx_zero: jmp foo
+cx_nonzero:
+@end smallexample
+
+@node i386-Float
+@section Floating Point
+
+@cindex i386 floating point
+@cindex floating point, i386
+All 80387 floating point types except packed BCD are supported.
+(BCD support may be added without much difficulty). These data
+types are 16-, 32-, and 64- bit integers, and single (32-bit),
+double (64-bit), and extended (80-bit) precision floating point.
+Each supported type has an instruction mnemonic suffix and a constructor
+associated with it. Instruction mnemonic suffixes specify the operand's
+data type. Constructors build these data types into memory.
+
+@cindex @code{float} directive, i386
+@cindex @code{single} directive, i386
+@cindex @code{double} directive, i386
+@cindex @code{tfloat} directive, i386
+@itemize @bullet
+@item
+Floating point constructors are @samp{.float} or @samp{.single},
+@samp{.double}, and @samp{.tfloat} for 32-, 64-, and 80-bit formats.
+These correspond to instruction mnemonic suffixes @samp{s}, @samp{l},
+and @samp{t}. @samp{t} stands for 80-bit (ten byte) real. The 80387
+only supports this format via the @samp{fldt} (load 80-bit real to stack
+top) and @samp{fstpt} (store 80-bit real and pop stack) instructions.
+
+@cindex @code{word} directive, i386
+@cindex @code{long} directive, i386
+@cindex @code{int} directive, i386
+@cindex @code{quad} directive, i386
+@item
+Integer constructors are @samp{.word}, @samp{.long} or @samp{.int}, and
+@samp{.quad} for the 16-, 32-, and 64-bit integer formats. The
+corresponding instruction mnemonic suffixes are @samp{s} (single),
+@samp{l} (long), and @samp{q} (quad). As with the 80-bit real format,
+the 64-bit @samp{q} format is only present in the @samp{fildq} (load
+quad integer to stack top) and @samp{fistpq} (store quad integer and pop
+stack) instructions.
+@end itemize
+
+Register to register operations should not use instruction mnemonic suffixes.
+@samp{fstl %st, %st(1)} will give a warning, and be assembled as if you
+wrote @samp{fst %st, %st(1)}, since all register to register operations
+use 80-bit floating point operands. (Contrast this with @samp{fstl %st, mem},
+which converts @samp{%st} from 80-bit to 64-bit floating point format,
+then stores the result in the 4 byte location @samp{mem})
+
+@node i386-SIMD
+@section Intel's MMX and AMD's 3DNow! SIMD Operations
+
+@cindex MMX, i386
+@cindex 3DNow!, i386
+@cindex SIMD, i386
+
+@code{@value{AS}} supports Intel's MMX instruction set (SIMD
+instructions for integer data), available on Intel's Pentium MMX
+processors and Pentium II processors, AMD's K6 and K6-2 processors,
+Cyrix' M2 processor, and probably others. It also supports AMD's 3DNow!
+instruction set (SIMD instructions for 32-bit floating point data)
+available on AMD's K6-2 processor and possibly others in the future.
+
+Currently, @code{@value{AS}} does not support Intel's floating point
+SIMD, Katmai (KNI).
+
+The eight 64-bit MMX operands, also used by 3DNow!, are called @samp{%mm0},
+@samp{%mm1}, ... @samp{%mm7}. They contain eight 8-bit integers, four
+16-bit integers, two 32-bit integers, one 64-bit integer, or two 32-bit
+floating point values. The MMX registers cannot be used at the same time
+as the floating point stack.
+
+See Intel and AMD documentation, keeping in mind that the operand order in
+instructions is reversed from the Intel syntax.
+
+@node i386-16bit
+@section Writing 16-bit Code
+
+@cindex i386 16-bit code
+@cindex 16-bit code, i386
+@cindex real-mode code, i386
+@cindex @code{code16} directive, i386
+@cindex @code{code32} directive, i386
+While @code{@value{AS}} normally writes only ``pure'' 32-bit i386 code,
+it also supports writing code to run in real mode or in 16-bit protected
+mode code segments. To do this, put a @samp{.code16} directive before
+the assembly language instructions to be run in 16-bit mode. You can
+switch @code{@value{AS}} back to writing normal 32-bit code with the
+@samp{.code32} directive.
+
+The code which @code{@value{AS}} generates in 16-bit mode will not
+necessarily run on a 16-bit pre-80386 processor. To write code that
+runs on such a processor, you must refrain from using @emph{any} 32-bit
+constructs which require @code{@value{AS}} to output address or operand
+size prefixes.
+
+Note that writing 16-bit code instructions by explicitly specifying a
+prefix or an instruction mnemonic suffix within a 32-bit code section
+generates different machine instructions than those generated for a
+16-bit code segment. In a 32-bit code section, the following code
+generates the machine opcode bytes @samp{66 6a 04}, which pushes the
+value @samp{4} onto the stack, decrementing @samp{%esp} by 2.
+
+@smallexample
+ pushw $4
+@end smallexample
+
+The same code in a 16-bit code section would generate the machine
+opcode bytes @samp{6a 04} (ie. without the operand size prefix), which
+is correct since the processor default operand size is assumed to be 16
+bits in a 16-bit code section.
+
+@node i386-Bugs
+@section AT&T Syntax bugs
+
+The UnixWare assembler, and probably other AT&T derived ix86 Unix
+assemblers, generate floating point instructions with reversed source
+and destination registers in certain cases. Unfortunately, gcc and
+possibly many other programs use this reversed syntax, so we're stuck
+with it.
+
+For example
+
+@smallexample
+ fsub %st,%st(3)
+@end smallexample
+@noindent
+results in @samp{%st(3)} being updated to @samp{%st - %st(3)} rather
+than the expected @samp{%st(3) - %st}. This happens with all the
+non-commutative arithmetic floating point operations with two register
+operands where the source register is @samp{%st} and the destination
+register is @samp{%st(i)}.
+
+@node i386-Notes
+@section Notes
+
+@cindex i386 @code{mul}, @code{imul} instructions
+@cindex @code{mul} instruction, i386
+@cindex @code{imul} instruction, i386
+There is some trickery concerning the @samp{mul} and @samp{imul}
+instructions that deserves mention. The 16-, 32-, and 64-bit expanding
+multiplies (base opcode @samp{0xf6}; extension 4 for @samp{mul} and 5
+for @samp{imul}) can be output only in the one operand form. Thus,
+@samp{imul %ebx, %eax} does @emph{not} select the expanding multiply;
+the expanding multiply would clobber the @samp{%edx} register, and this
+would confuse @code{@value{GCC}} output. Use @samp{imul %ebx} to get the
+64-bit product in @samp{%edx:%eax}.
+
+We have added a two operand form of @samp{imul} when the first operand
+is an immediate mode expression and the second operand is a register.
+This is just a shorthand, so that, multiplying @samp{%eax} by 69, for
+example, can be done with @samp{imul $69, %eax} rather than @samp{imul
+$69, %eax, %eax}.
+
diff --git a/gas/doc/c-i960.texi b/gas/doc/c-i960.texi
new file mode 100644
index 0000000000..177030ab0b
--- /dev/null
+++ b/gas/doc/c-i960.texi
@@ -0,0 +1,298 @@
+@c Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+@c This is part of the GAS manual.
+@c For copying conditions, see the file as.texinfo.
+@ifset GENERIC
+@page
+@node i960-Dependent
+@chapter Intel 80960 Dependent Features
+@end ifset
+@ifclear GENERIC
+@node Machine Dependencies
+@chapter Intel 80960 Dependent Features
+@end ifclear
+
+@cindex i960 support
+@menu
+* Options-i960:: i960 Command-line Options
+* Floating Point-i960:: Floating Point
+* Directives-i960:: i960 Machine Directives
+* Opcodes for i960:: i960 Opcodes
+@end menu
+
+@c FIXME! Add Syntax sec with discussion of bitfields here, at least so
+@c long as they're not turned on for other machines than 960.
+
+@node Options-i960
+
+@section i960 Command-line Options
+
+@cindex i960 options
+@cindex options, i960
+@table @code
+
+@cindex i960 architecture options
+@cindex architecture options, i960
+@cindex @code{-A} options, i960
+@item -ACA | -ACA_A | -ACB | -ACC | -AKA | -AKB | -AKC | -AMC
+Select the 80960 architecture. Instructions or features not supported
+by the selected architecture cause fatal errors.
+
+@samp{-ACA} is equivalent to @samp{-ACA_A}; @samp{-AKC} is equivalent to
+@samp{-AMC}. Synonyms are provided for compatibility with other tools.
+
+If you do not specify any of these options, @code{@value{AS}} generates code
+for any instruction or feature that is supported by @emph{some} version of the
+960 (even if this means mixing architectures!). In principle,
+@code{@value{AS}} attempts to deduce the minimal sufficient processor type if
+none is specified; depending on the object code format, the processor type may
+be recorded in the object file. If it is critical that the @code{@value{AS}}
+output match a specific architecture, specify that architecture explicitly.
+
+@cindex @code{-b} option, i960
+@cindex branch recording, i960
+@cindex i960 branch recording
+@item -b
+Add code to collect information about conditional branches taken, for
+later optimization using branch prediction bits. (The conditional branch
+instructions have branch prediction bits in the CA, CB, and CC
+architectures.) If @var{BR} represents a conditional branch instruction,
+the following represents the code generated by the assembler when
+@samp{-b} is specified:
+
+@smallexample
+ call @var{increment routine}
+ .word 0 # pre-counter
+Label: @var{BR}
+ call @var{increment routine}
+ .word 0 # post-counter
+@end smallexample
+
+The counter following a branch records the number of times that branch
+was @emph{not} taken; the differenc between the two counters is the
+number of times the branch @emph{was} taken.
+
+@cindex @code{gbr960}, i960 postprocessor
+@cindex branch statistics table, i960
+A table of every such @code{Label} is also generated, so that the
+external postprocessor @code{gbr960} (supplied by Intel) can locate all
+the counters. This table is always labelled @samp{__BRANCH_TABLE__};
+this is a local symbol to permit collecting statistics for many separate
+object files. The table is word aligned, and begins with a two-word
+header. The first word, initialized to 0, is used in maintaining linked
+lists of branch tables. The second word is a count of the number of
+entries in the table, which follow immediately: each is a word, pointing
+to one of the labels illustrated above.
+
+@c TEXI2ROFF-KILL
+@ifinfo
+@c END TEXI2ROFF-KILL
+@example
+ +------------+------------+------------+ ... +------------+
+ | | | | | |
+ | *NEXT | COUNT: N | *BRLAB 1 | | *BRLAB N |
+ | | | | | |
+ +------------+------------+------------+ ... +------------+
+
+ __BRANCH_TABLE__ layout
+@end example
+@c TEXI2ROFF-KILL
+@end ifinfo
+@need 2000
+@tex
+\vskip 1pc
+\line{\leftskip=0pt\hskip\tableindent
+\boxit{2cm}{\tt *NEXT}\boxit{2cm}{\tt COUNT: \it N}\boxit{2cm}{\tt
+*BRLAB 1}\ibox{1cm}{\quad\dots}\boxit{2cm}{\tt *BRLAB \it N}\hfil}
+\centerline{\it {\tt \_\_BRANCH\_TABLE\_\_} layout}
+@end tex
+@c END TEXI2ROFF-KILL
+
+The first word of the header is used to locate multiple branch tables,
+since each object file may contain one. Normally the links are
+maintained with a call to an initialization routine, placed at the
+beginning of each function in the file. The @sc{gnu} C compiler
+generates these calls automatically when you give it a @samp{-b} option.
+For further details, see the documentation of @samp{gbr960}.
+
+@cindex @code{-no-relax} option, i960
+@item -no-relax
+Normally, Compare-and-Branch instructions with targets that require
+displacements greater than 13 bits (or that have external targets) are
+replaced with the corresponding compare (or @samp{chkbit}) and branch
+instructions. You can use the @samp{-no-relax} option to specify that
+@code{@value{AS}} should generate errors instead, if the target displacement
+is larger than 13 bits.
+
+This option does not affect the Compare-and-Jump instructions; the code
+emitted for them is @emph{always} adjusted when necessary (depending on
+displacement size), regardless of whether you use @samp{-no-relax}.
+@end table
+
+@node Floating Point-i960
+@section Floating Point
+
+@cindex floating point, i960 (@sc{ieee})
+@cindex i960 floating point (@sc{ieee})
+@code{@value{AS}} generates @sc{ieee} floating-point numbers for the directives
+@samp{.float}, @samp{.double}, @samp{.extended}, and @samp{.single}.
+
+@node Directives-i960
+@section i960 Machine Directives
+
+@cindex machine directives, i960
+@cindex i960 machine directives
+
+@table @code
+@cindex @code{bss} directive, i960
+@item .bss @var{symbol}, @var{length}, @var{align}
+Reserve @var{length} bytes in the bss section for a local @var{symbol},
+aligned to the power of two specified by @var{align}. @var{length} and
+@var{align} must be positive absolute expressions. This directive
+differs from @samp{.lcomm} only in that it permits you to specify
+an alignment. @xref{Lcomm,,@code{.lcomm}}.
+@end table
+
+@table @code
+@cindex @code{extended} directive, i960
+@item .extended @var{flonums}
+@code{.extended} expects zero or more flonums, separated by commas; for
+each flonum, @samp{.extended} emits an @sc{ieee} extended-format (80-bit)
+floating-point number.
+
+@cindex @code{leafproc} directive, i960
+@item .leafproc @var{call-lab}, @var{bal-lab}
+You can use the @samp{.leafproc} directive in conjunction with the
+optimized @code{callj} instruction to enable faster calls of leaf
+procedures. If a procedure is known to call no other procedures, you
+may define an entry point that skips procedure prolog code (and that does
+not depend on system-supplied saved context), and declare it as the
+@var{bal-lab} using @samp{.leafproc}. If the procedure also has an
+entry point that goes through the normal prolog, you can specify that
+entry point as @var{call-lab}.
+
+A @samp{.leafproc} declaration is meant for use in conjunction with the
+optimized call instruction @samp{callj}; the directive records the data
+needed later to choose between converting the @samp{callj} into a
+@code{bal} or a @code{call}.
+
+@var{call-lab} is optional; if only one argument is present, or if the
+two arguments are identical, the single argument is assumed to be the
+@code{bal} entry point.
+
+@cindex @code{sysproc} directive, i960
+@item .sysproc @var{name}, @var{index}
+The @samp{.sysproc} directive defines a name for a system procedure.
+After you define it using @samp{.sysproc}, you can use @var{name} to
+refer to the system procedure identified by @var{index} when calling
+procedures with the optimized call instruction @samp{callj}.
+
+Both arguments are required; @var{index} must be between 0 and 31
+(inclusive).
+@end table
+
+@node Opcodes for i960
+@section i960 Opcodes
+
+@cindex opcodes, i960
+@cindex i960 opcodes
+All Intel 960 machine instructions are supported;
+@pxref{Options-i960,,i960 Command-line Options} for a discussion of
+selecting the instruction subset for a particular 960
+architecture.@refill
+
+Some opcodes are processed beyond simply emitting a single corresponding
+instruction: @samp{callj}, and Compare-and-Branch or Compare-and-Jump
+instructions with target displacements larger than 13 bits.
+
+@menu
+* callj-i960:: @code{callj}
+* Compare-and-branch-i960:: Compare-and-Branch
+@end menu
+
+@node callj-i960
+@subsection @code{callj}
+
+@cindex @code{callj}, i960 pseudo-opcode
+@cindex i960 @code{callj} pseudo-opcode
+You can write @code{callj} to have the assembler or the linker determine
+the most appropriate form of subroutine call: @samp{call},
+@samp{bal}, or @samp{calls}. If the assembly source contains
+enough information---a @samp{.leafproc} or @samp{.sysproc} directive
+defining the operand---then @code{@value{AS}} translates the
+@code{callj}; if not, it simply emits the @code{callj}, leaving it
+for the linker to resolve.
+
+@node Compare-and-branch-i960
+@subsection Compare-and-Branch
+
+@cindex i960 compare/branch instructions
+@cindex compare/branch instructions, i960
+The 960 architectures provide combined Compare-and-Branch instructions
+that permit you to store the branch target in the lower 13 bits of the
+instruction word itself. However, if you specify a branch target far
+enough away that its address won't fit in 13 bits, the assembler can
+either issue an error, or convert your Compare-and-Branch instruction
+into separate instructions to do the compare and the branch.
+
+@cindex compare and jump expansions, i960
+@cindex i960 compare and jump expansions
+Whether @code{@value{AS}} gives an error or expands the instruction depends
+on two choices you can make: whether you use the @samp{-no-relax} option,
+and whether you use a ``Compare and Branch'' instruction or a ``Compare
+and Jump'' instruction. The ``Jump'' instructions are @emph{always}
+expanded if necessary; the ``Branch'' instructions are expanded when
+necessary @emph{unless} you specify @code{-no-relax}---in which case
+@code{@value{AS}} gives an error instead.
+
+These are the Compare-and-Branch instructions, their ``Jump'' variants,
+and the instruction pairs they may expand into:
+
+@c TEXI2ROFF-KILL
+@ifinfo
+@c END TEXI2ROFF-KILL
+@example
+ Compare and
+ Branch Jump Expanded to
+ ------ ------ ------------
+ bbc chkbit; bno
+ bbs chkbit; bo
+ cmpibe cmpije cmpi; be
+ cmpibg cmpijg cmpi; bg
+ cmpibge cmpijge cmpi; bge
+ cmpibl cmpijl cmpi; bl
+ cmpible cmpijle cmpi; ble
+ cmpibno cmpijno cmpi; bno
+ cmpibne cmpijne cmpi; bne
+ cmpibo cmpijo cmpi; bo
+ cmpobe cmpoje cmpo; be
+ cmpobg cmpojg cmpo; bg
+ cmpobge cmpojge cmpo; bge
+ cmpobl cmpojl cmpo; bl
+ cmpoble cmpojle cmpo; ble
+ cmpobne cmpojne cmpo; bne
+@end example
+@c TEXI2ROFF-KILL
+@end ifinfo
+@tex
+\hskip\tableindent
+\halign{\hfil {\tt #}\quad&\hfil {\tt #}\qquad&{\tt #}\hfil\cr
+\omit{\hfil\it Compare and\hfil}\span\omit&\cr
+{\it Branch}&{\it Jump}&{\it Expanded to}\cr
+ bbc& & chkbit; bno\cr
+ bbs& & chkbit; bo\cr
+ cmpibe& cmpije& cmpi; be\cr
+ cmpibg& cmpijg& cmpi; bg\cr
+ cmpibge& cmpijge& cmpi; bge\cr
+ cmpibl& cmpijl& cmpi; bl\cr
+ cmpible& cmpijle& cmpi; ble\cr
+ cmpibno& cmpijno& cmpi; bno\cr
+ cmpibne& cmpijne& cmpi; bne\cr
+ cmpibo& cmpijo& cmpi; bo\cr
+ cmpobe& cmpoje& cmpo; be\cr
+ cmpobg& cmpojg& cmpo; bg\cr
+ cmpobge& cmpojge& cmpo; bge\cr
+ cmpobl& cmpojl& cmpo; bl\cr
+ cmpoble& cmpojle& cmpo; ble\cr
+ cmpobne& cmpojne& cmpo; bne\cr}
+@end tex
+@c END TEXI2ROFF-KILL
diff --git a/gas/doc/c-m32r.texi b/gas/doc/c-m32r.texi
new file mode 100644
index 0000000000..f121ede481
--- /dev/null
+++ b/gas/doc/c-m32r.texi
@@ -0,0 +1,13 @@
+@c Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+@c This is part of the GAS manual.
+@c For copying conditions, see the file as.texinfo.
+@ifset GENERIC
+@page
+@node M32R-Dependent
+@chapter M32R Dependent Features
+@end ifset
+@ifclear GENERIC
+@node Machine Dependencies
+@chapter M32R Dependent Features
+@end ifclear
+
diff --git a/gas/doc/c-m68k.texi b/gas/doc/c-m68k.texi
new file mode 100644
index 0000000000..16f857f3a7
--- /dev/null
+++ b/gas/doc/c-m68k.texi
@@ -0,0 +1,503 @@
+@c Copyright (C) 1991, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+@c This is part of the GAS manual.
+@c For copying conditions, see the file as.texinfo.
+@ifset GENERIC
+@page
+@node M68K-Dependent
+@chapter M680x0 Dependent Features
+@end ifset
+@ifclear GENERIC
+@node Machine Dependencies
+@chapter M680x0 Dependent Features
+@end ifclear
+
+@cindex M680x0 support
+@menu
+* M68K-Opts:: M680x0 Options
+* M68K-Syntax:: Syntax
+* M68K-Moto-Syntax:: Motorola Syntax
+* M68K-Float:: Floating Point
+* M68K-Directives:: 680x0 Machine Directives
+* M68K-opcodes:: Opcodes
+@end menu
+
+@node M68K-Opts
+@section M680x0 Options
+
+@cindex options, M680x0
+@cindex M680x0 options
+The Motorola 680x0 version of @code{@value{AS}} has a few machine
+dependent options.
+
+@cindex @samp{-l} option, M680x0
+You can use the @samp{-l} option to shorten the size of references to undefined
+symbols. If you do not use the @samp{-l} option, references to undefined
+symbols are wide enough for a full @code{long} (32 bits). (Since
+@code{@value{AS}} cannot know where these symbols end up, @code{@value{AS}} can
+only allocate space for the linker to fill in later. Since @code{@value{AS}}
+does not know how far away these symbols are, it allocates as much space as it
+can.) If you use this option, the references are only one word wide (16 bits).
+This may be useful if you want the object file to be as small as possible, and
+you know that the relevant symbols are always less than 17 bits away.
+
+@cindex @samp{--register-prefix-optional} option, M680x0
+For some configurations, especially those where the compiler normally
+does not prepend an underscore to the names of user variables, the
+assembler requires a @samp{%} before any use of a register name. This
+is intended to let the assembler distinguish between C variables and
+functions named @samp{a0} through @samp{a7}, and so on. The @samp{%} is
+always accepted, but is not required for certain configurations, notably
+@samp{sun3}. The @samp{--register-prefix-optional} option may be used
+to permit omitting the @samp{%} even for configurations for which it is
+normally required. If this is done, it will generally be impossible to
+refer to C variables and functions with the same names as register
+names.
+
+@cindex @samp{--bitwise-or} option, M680x0
+Normally the character @samp{|} is treated as a comment character, which
+means that it can not be used in expressions. The @samp{--bitwise-or}
+option turns @samp{|} into a normal character. In this mode, you must
+either use C style comments, or start comments with a @samp{#} character
+at the beginning of a line.
+
+@cindex @samp{--base-size-default-16}
+@cindex @samp{--base-size-default-32}
+If you use an addressing mode with a base register without specifying
+the size, @code{@value{AS}} will normally use the full 32 bit value.
+For example, the addressing mode @samp{%a0@@(%d0)} is equivalent to
+@samp{%a0@@(%d0:l)}. You may use the @samp{--base-size-default-16}
+option to tell @code{@value{AS}} to default to using the 16 bit value.
+In this case, @samp{%a0@@(%d0)} is equivalent to @samp{%a0@@(%d0:w)}.
+You may use the @samp{--base-size-default-32} option to restore the
+default behaviour.
+
+@cindex @samp{--disp-size-default-16}
+@cindex @samp{--disp-size-default-32}
+If you use an addressing mode with a displacement, and the value of the
+displacement is not known, @code{@value{AS}} will normally assume that
+the value is 32 bits. For example, if the symbol @samp{disp} has not
+been defined, @code{@value{AS}} will assemble the addressing mode
+@samp{%a0@@(disp,%d0)} as though @samp{disp} is a 32 bit value. You may
+use the @samp{--disp-size-default-16} option to tell @code{@value{AS}}
+to instead assume that the displacement is 16 bits. In this case,
+@code{@value{AS}} will assemble @samp{%a0@@(disp,%d0)} as though
+@samp{disp} is a 16 bit value. You may use the
+@samp{--disp-size-default-32} option to restore the default behaviour.
+
+@cindex @samp{-m68000} and related options
+@cindex architecture options, M680x0
+@cindex M680x0 architecture options
+@code{@value{AS}} can assemble code for several different members of the
+Motorola 680x0 family. The default depends upon how @code{@value{AS}}
+was configured when it was built; normally, the default is to assemble
+code for the 68020 microprocessor. The following options may be used to
+change the default. These options control which instructions and
+addressing modes are permitted. The members of the 680x0 family are
+very similar. For detailed information about the differences, see the
+Motorola manuals.
+
+@table @samp
+@item -m68000
+@itemx -m68ec000
+@itemx -m68hc000
+@itemx -m68hc001
+@itemx -m68008
+@itemx -m68302
+@itemx -m68306
+@itemx -m68307
+@itemx -m68322
+@itemx -m68356
+Assemble for the 68000. @samp{-m68008}, @samp{-m68302}, and so on are synonyms
+for @samp{-m68000}, since the chips are the same from the point of view
+of the assembler.
+
+@item -m68010
+Assemble for the 68010.
+
+@item -m68020
+@itemx -m68ec020
+Assemble for the 68020. This is normally the default.
+
+@item -m68030
+@itemx -m68ec030
+Assemble for the 68030.
+
+@item -m68040
+@itemx -m68ec040
+Assemble for the 68040.
+
+@item -m68060
+@itemx -m68ec060
+Assemble for the 68060.
+
+@item -mcpu32
+@itemx -m68330
+@itemx -m68331
+@itemx -m68332
+@itemx -m68333
+@itemx -m68334
+@itemx -m68336
+@itemx -m68340
+@itemx -m68341
+@itemx -m68349
+@itemx -m68360
+Assemble for the CPU32 family of chips.
+
+@item -m5200
+Assemble for the ColdFire family of chips.
+
+@item -m68881
+@itemx -m68882
+Assemble 68881 floating point instructions. This is the default for the
+68020, 68030, and the CPU32. The 68040 and 68060 always support
+floating point instructions.
+
+@item -mno-68881
+Do not assemble 68881 floating point instructions. This is the default
+for 68000 and the 68010. The 68040 and 68060 always support floating
+point instructions, even if this option is used.
+
+@item -m68851
+Assemble 68851 MMU instructions. This is the default for the 68020,
+68030, and 68060. The 68040 accepts a somewhat different set of MMU
+instructions; @samp{-m68851} and @samp{-m68040} should not be used
+together.
+
+@item -mno-68851
+Do not assemble 68851 MMU instructions. This is the default for the
+68000, 68010, and the CPU32. The 68040 accepts a somewhat different set
+of MMU instructions.
+@end table
+
+@node M68K-Syntax
+@section Syntax
+
+@cindex @sc{mit}
+This syntax for the Motorola 680x0 was developed at @sc{mit}.
+
+@cindex M680x0 syntax
+@cindex syntax, M680x0
+@cindex M680x0 size modifiers
+@cindex size modifiers, M680x0
+The 680x0 version of @code{@value{AS}} uses instructions names and
+syntax compatible with the Sun assembler. Intervening periods are
+ignored; for example, @samp{movl} is equivalent to @samp{mov.l}.
+
+In the following table @var{apc} stands for any of the address registers
+(@samp{%a0} through @samp{%a7}), the program counter (@samp{%pc}), the
+zero-address relative to the program counter (@samp{%zpc}), a suppressed
+address register (@samp{%za0} through @samp{%za7}), or it may be omitted
+entirely. The use of @var{size} means one of @samp{w} or @samp{l}, and
+it may be omitted, along with the leading colon, unless a scale is also
+specified. The use of @var{scale} means one of @samp{1}, @samp{2},
+@samp{4}, or @samp{8}, and it may always be omitted along with the
+leading colon.
+
+@cindex M680x0 addressing modes
+@cindex addressing modes, M680x0
+The following addressing modes are understood:
+@table @dfn
+@item Immediate
+@samp{#@var{number}}
+
+@item Data Register
+@samp{%d0} through @samp{%d7}
+
+@item Address Register
+@samp{%a0} through @samp{%a7}@*
+@samp{%a7} is also known as @samp{%sp}, i.e. the Stack Pointer. @code{%a6}
+is also known as @samp{%fp}, the Frame Pointer.
+
+@item Address Register Indirect
+@samp{%a0@@} through @samp{%a7@@}
+
+@item Address Register Postincrement
+@samp{%a0@@+} through @samp{%a7@@+}
+
+@item Address Register Predecrement
+@samp{%a0@@-} through @samp{%a7@@-}
+
+@item Indirect Plus Offset
+@samp{@var{apc}@@(@var{number})}
+
+@item Index
+@samp{@var{apc}@@(@var{number},@var{register}:@var{size}:@var{scale})}
+
+The @var{number} may be omitted.
+
+@item Postindex
+@samp{@var{apc}@@(@var{number})@@(@var{onumber},@var{register}:@var{size}:@var{scale})}
+
+The @var{onumber} or the @var{register}, but not both, may be omitted.
+
+@item Preindex
+@samp{@var{apc}@@(@var{number},@var{register}:@var{size}:@var{scale})@@(@var{onumber})}
+
+The @var{number} may be omitted. Omitting the @var{register} produces
+the Postindex addressing mode.
+
+@item Absolute
+@samp{@var{symbol}}, or @samp{@var{digits}}, optionally followed by
+@samp{:b}, @samp{:w}, or @samp{:l}.
+@end table
+
+@node M68K-Moto-Syntax
+@section Motorola Syntax
+
+@cindex Motorola syntax for the 680x0
+@cindex alternate syntax for the 680x0
+
+The standard Motorola syntax for this chip differs from the syntax
+already discussed (@pxref{M68K-Syntax,,Syntax}). @code{@value{AS}} can
+accept Motorola syntax for operands, even if @sc{mit} syntax is used for
+other operands in the same instruction. The two kinds of syntax are
+fully compatible.
+
+In the following table @var{apc} stands for any of the address registers
+(@samp{%a0} through @samp{%a7}), the program counter (@samp{%pc}), the
+zero-address relative to the program counter (@samp{%zpc}), or a
+suppressed address register (@samp{%za0} through @samp{%za7}). The use
+of @var{size} means one of @samp{w} or @samp{l}, and it may always be
+omitted along with the leading dot. The use of @var{scale} means one of
+@samp{1}, @samp{2}, @samp{4}, or @samp{8}, and it may always be omitted
+along with the leading asterisk.
+
+The following additional addressing modes are understood:
+
+@table @dfn
+@item Address Register Indirect
+@samp{(%a0)} through @samp{(%a7)}@*
+@samp{%a7} is also known as @samp{%sp}, i.e. the Stack Pointer. @code{%a6}
+is also known as @samp{%fp}, the Frame Pointer.
+
+@item Address Register Postincrement
+@samp{(%a0)+} through @samp{(%a7)+}
+
+@item Address Register Predecrement
+@samp{-(%a0)} through @samp{-(%a7)}
+
+@item Indirect Plus Offset
+@samp{@var{number}(@var{%a0})} through @samp{@var{number}(@var{%a7})},
+or @samp{@var{number}(@var{%pc})}.
+
+The @var{number} may also appear within the parentheses, as in
+@samp{(@var{number},@var{%a0})}. When used with the @var{pc}, the
+@var{number} may be omitted (with an address register, omitting the
+@var{number} produces Address Register Indirect mode).
+
+@item Index
+@samp{@var{number}(@var{apc},@var{register}.@var{size}*@var{scale})}
+
+The @var{number} may be omitted, or it may appear within the
+parentheses. The @var{apc} may be omitted. The @var{register} and the
+@var{apc} may appear in either order. If both @var{apc} and
+@var{register} are address registers, and the @var{size} and @var{scale}
+are omitted, then the first register is taken as the base register, and
+the second as the index register.
+
+@item Postindex
+@samp{([@var{number},@var{apc}],@var{register}.@var{size}*@var{scale},@var{onumber})}
+
+The @var{onumber}, or the @var{register}, or both, may be omitted.
+Either the @var{number} or the @var{apc} may be omitted, but not both.
+
+@item Preindex
+@samp{([@var{number},@var{apc},@var{register}.@var{size}*@var{scale}],@var{onumber})}
+
+The @var{number}, or the @var{apc}, or the @var{register}, or any two of
+them, may be omitted. The @var{onumber} may be omitted. The
+@var{register} and the @var{apc} may appear in either order. If both
+@var{apc} and @var{register} are address registers, and the @var{size}
+and @var{scale} are omitted, then the first register is taken as the
+base register, and the second as the index register.
+@end table
+
+@node M68K-Float
+@section Floating Point
+
+@cindex floating point, M680x0
+@cindex M680x0 floating point
+Packed decimal (P) format floating literals are not supported.
+Feel free to add the code!
+
+The floating point formats generated by directives are these.
+
+@table @code
+@cindex @code{float} directive, M680x0
+@item .float
+@code{Single} precision floating point constants.
+
+@cindex @code{double} directive, M680x0
+@item .double
+@code{Double} precision floating point constants.
+
+@cindex @code{extend} directive M680x0
+@cindex @code{ldouble} directive M680x0
+@item .extend
+@itemx .ldouble
+@code{Extended} precision (@code{long double}) floating point constants.
+@end table
+
+@node M68K-Directives
+@section 680x0 Machine Directives
+
+@cindex M680x0 directives
+@cindex directives, M680x0
+In order to be compatible with the Sun assembler the 680x0 assembler
+understands the following directives.
+
+@table @code
+@cindex @code{data1} directive, M680x0
+@item .data1
+This directive is identical to a @code{.data 1} directive.
+
+@cindex @code{data2} directive, M680x0
+@item .data2
+This directive is identical to a @code{.data 2} directive.
+
+@cindex @code{even} directive, M680x0
+@item .even
+This directive is a special case of the @code{.align} directive; it
+aligns the output to an even byte boundary.
+
+@cindex @code{skip} directive, M680x0
+@item .skip
+This directive is identical to a @code{.space} directive.
+@end table
+
+@need 2000
+@node M68K-opcodes
+@section Opcodes
+
+@cindex M680x0 opcodes
+@cindex opcodes, M680x0
+@cindex instruction set, M680x0
+@c doc@cygnus.com: I don't see any point in the following
+@c paragraph. Bugs are bugs; how does saying this
+@c help anyone?
+@ignore
+Danger: Several bugs have been found in the opcode table (and
+fixed). More bugs may exist. Be careful when using obscure
+instructions.
+@end ignore
+
+@menu
+* M68K-Branch:: Branch Improvement
+* M68K-Chars:: Special Characters
+@end menu
+
+@node M68K-Branch
+@subsection Branch Improvement
+
+@cindex pseudo-opcodes, M680x0
+@cindex M680x0 pseudo-opcodes
+@cindex branch improvement, M680x0
+@cindex M680x0 branch improvement
+Certain pseudo opcodes are permitted for branch instructions.
+They expand to the shortest branch instruction that reach the
+target. Generally these mnemonics are made by substituting @samp{j} for
+@samp{b} at the start of a Motorola mnemonic.
+
+The following table summarizes the pseudo-operations. A @code{*} flags
+cases that are more fully described after the table:
+
+@smallexample
+ Displacement
+ +-------------------------------------------------
+ | 68020 68000/10
+Pseudo-Op |BYTE WORD LONG LONG non-PC relative
+ +-------------------------------------------------
+ jbsr |bsrs bsr bsrl jsr jsr
+ jra |bras bra bral jmp jmp
+* jXX |bXXs bXX bXXl bNXs;jmpl bNXs;jmp
+* dbXX |dbXX dbXX dbXX; bra; jmpl
+* fjXX |fbXXw fbXXw fbXXl fbNXw;jmp
+
+XX: condition
+NX: negative of condition XX
+
+@end smallexample
+@center @code{*}---see full description below
+
+@table @code
+@item jbsr
+@itemx jra
+These are the simplest jump pseudo-operations; they always map to one
+particular machine instruction, depending on the displacement to the
+branch target.
+
+@item j@var{XX}
+Here, @samp{j@var{XX}} stands for an entire family of pseudo-operations,
+where @var{XX} is a conditional branch or condition-code test. The full
+list of pseudo-ops in this family is:
+@smallexample
+ jhi jls jcc jcs jne jeq jvc
+ jvs jpl jmi jge jlt jgt jle
+@end smallexample
+
+For the cases of non-PC relative displacements and long displacements on
+the 68000 or 68010, @code{@value{AS}} issues a longer code fragment in terms of
+@var{NX}, the opposite condition to @var{XX}. For example, for the
+non-PC relative case:
+@smallexample
+ j@var{XX} foo
+@end smallexample
+gives
+@smallexample
+ b@var{NX}s oof
+ jmp foo
+ oof:
+@end smallexample
+
+@item db@var{XX}
+The full family of pseudo-operations covered here is
+@smallexample
+ dbhi dbls dbcc dbcs dbne dbeq dbvc
+ dbvs dbpl dbmi dbge dblt dbgt dble
+ dbf dbra dbt
+@end smallexample
+
+Other than for word and byte displacements, when the source reads
+@samp{db@var{XX} foo}, @code{@value{AS}} emits
+@smallexample
+ db@var{XX} oo1
+ bra oo2
+ oo1:jmpl foo
+ oo2:
+@end smallexample
+
+@item fj@var{XX}
+This family includes
+@smallexample
+ fjne fjeq fjge fjlt fjgt fjle fjf
+ fjt fjgl fjgle fjnge fjngl fjngle fjngt
+ fjnle fjnlt fjoge fjogl fjogt fjole fjolt
+ fjor fjseq fjsf fjsne fjst fjueq fjuge
+ fjugt fjule fjult fjun
+@end smallexample
+
+For branch targets that are not PC relative, @code{@value{AS}} emits
+@smallexample
+ fb@var{NX} oof
+ jmp foo
+ oof:
+@end smallexample
+when it encounters @samp{fj@var{XX} foo}.
+
+@end table
+
+@node M68K-Chars
+@subsection Special Characters
+
+@cindex special characters, M680x0
+@cindex M680x0 immediate character
+@cindex immediate character, M680x0
+@cindex M680x0 line comment character
+@cindex line comment character, M680x0
+@cindex comments, M680x0
+The immediate character is @samp{#} for Sun compatibility. The
+line-comment character is @samp{|} (unless the @samp{--bitwise-or}
+option is used). If a @samp{#} appears at the beginning of a line, it
+is treated as a comment unless it looks like @samp{# line file}, in
+which case it is treated normally.
+
diff --git a/gas/doc/c-mips.texi b/gas/doc/c-mips.texi
new file mode 100644
index 0000000000..523dda3799
--- /dev/null
+++ b/gas/doc/c-mips.texi
@@ -0,0 +1,257 @@
+@c Copyright (C) 1991, 92, 93, 94, 95, 1997 Free Software Foundation, Inc.
+@c This is part of the GAS manual.
+@c For copying conditions, see the file as.texinfo.
+@ifset GENERIC
+@page
+@node MIPS-Dependent
+@chapter MIPS Dependent Features
+@end ifset
+@ifclear GENERIC
+@node Machine Dependencies
+@chapter MIPS Dependent Features
+@end ifclear
+
+@cindex MIPS processor
+@sc{gnu} @code{@value{AS}} for @sc{mips} architectures supports several
+different @sc{mips} processors, and MIPS ISA levels I through IV. For
+information about the @sc{mips} instruction set, see @cite{MIPS RISC
+Architecture}, by Kane and Heindrich (Prentice-Hall). For an overview
+of @sc{mips} assembly conventions, see ``Appendix D: Assembly Language
+Programming'' in the same work.
+
+@menu
+* MIPS Opts:: Assembler options
+* MIPS Object:: ECOFF object code
+* MIPS Stabs:: Directives for debugging information
+* MIPS ISA:: Directives to override the ISA level
+* MIPS autoextend:: Directives for extending MIPS 16 bit instructions
+* MIPS insn:: Directive to mark data as an instruction
+* MIPS option stack:: Directives to save and restore options
+@end menu
+
+@node MIPS Opts
+@section Assembler options
+
+The @sc{mips} configurations of @sc{gnu} @code{@value{AS}} support these
+special options:
+
+@table @code
+@cindex @code{-G} option (MIPS)
+@item -G @var{num}
+This option sets the largest size of an object that can be referenced
+implicitly with the @code{gp} register. It is only accepted for targets
+that use @sc{ecoff} format. The default value is 8.
+
+@cindex @code{-EB} option (MIPS)
+@cindex @code{-EL} option (MIPS)
+@cindex MIPS big-endian output
+@cindex MIPS little-endian output
+@cindex big-endian output, MIPS
+@cindex little-endian output, MIPS
+@item -EB
+@itemx -EL
+Any @sc{mips} configuration of @code{@value{AS}} can select big-endian or
+little-endian output at run time (unlike the other @sc{gnu} development
+tools, which must be configured for one or the other). Use @samp{-EB}
+to select big-endian output, and @samp{-EL} for little-endian.
+
+@cindex MIPS architecture options
+@item -mips1
+@itemx -mips2
+@itemx -mips3
+@itemx -mips4
+Generate code for a particular MIPS Instruction Set Architecture level.
+@samp{-mips1} corresponds to the @sc{r2000} and @sc{r3000} processors,
+@samp{-mips2} to the @sc{r6000} processor, @samp{-mips3} to the
+@sc{r4000} processor, and @samp{-mips4} to the @sc{r8000} and
+@sc{r10000} processors. You can also switch instruction sets during the
+assembly; see @ref{MIPS ISA,, Directives to override the ISA level}.
+
+@item -mips16
+@itemx -no-mips16
+Generate code for the MIPS 16 processor. This is equivalent to putting
+@samp{.set mips16} at the start of the assembly file. @samp{-no-mips16}
+turns off this option.
+
+@item -m4010
+@itemx -no-m4010
+Generate code for the LSI @sc{r4010} chip. This tells the assembler to
+accept the @sc{r4010} specific instructions (@samp{addciu}, @samp{ffc},
+etc.), and to not schedule @samp{nop} instructions around accesses to
+the @samp{HI} and @samp{LO} registers. @samp{-no-m4010} turns off this
+option.
+
+@item -m4650
+@itemx -no-m4650
+Generate code for the MIPS @sc{r4650} chip. This tells the assembler to accept
+the @samp{mad} and @samp{madu} instruction, and to not schedule @samp{nop}
+instructions around accesses to the @samp{HI} and @samp{LO} registers.
+@samp{-no-m4650} turns off this option.
+
+@itemx -m3900
+@itemx -no-m3900
+@itemx -m4100
+@itemx -no-m4100
+For each option @samp{-m@var{nnnn}}, generate code for the MIPS
+@sc{r@var{nnnn}} chip. This tells the assembler to accept instructions
+specific to that chip, and to schedule for that chip's hazards.
+
+@item -mcpu=@var{cpu}
+Generate code for a particular MIPS cpu. It is exactly equivalent to
+@samp{-m@var{cpu}}, except that there are more value of @var{cpu}
+understood. Valid @var{cpu} value are:
+
+@quotation
+2000,
+3000,
+3900,
+4000,
+4010,
+4100,
+4111,
+4300,
+4400,
+4600,
+4650,
+5000,
+6000,
+8000,
+10000
+@end quotation
+
+
+@cindex @code{-nocpp} ignored (MIPS)
+@item -nocpp
+This option is ignored. It is accepted for command-line compatibility with
+other assemblers, which use it to turn off C style preprocessing. With
+@sc{gnu} @code{@value{AS}}, there is no need for @samp{-nocpp}, because the
+@sc{gnu} assembler itself never runs the C preprocessor.
+
+@item --trap
+@itemx --no-break
+@c FIXME! (1) reflect these options (next item too) in option summaries;
+@c (2) stop teasing, say _which_ instructions expanded _how_.
+@code{@value{AS}} automatically macro expands certain division and
+multiplication instructions to check for overflow and division by zero. This
+option causes @code{@value{AS}} to generate code to take a trap exception
+rather than a break exception when an error is detected. The trap instructions
+are only supported at Instruction Set Architecture level 2 and higher.
+
+@item --break
+@itemx --no-trap
+Generate code to take a break exception rather than a trap exception when an
+error is detected. This is the default.
+@end table
+
+@node MIPS Object
+@section MIPS ECOFF object code
+
+@cindex ECOFF sections
+@cindex MIPS ECOFF sections
+Assembling for a @sc{mips} @sc{ecoff} target supports some additional sections
+besides the usual @code{.text}, @code{.data} and @code{.bss}. The
+additional sections are @code{.rdata}, used for read-only data,
+@code{.sdata}, used for small data, and @code{.sbss}, used for small
+common objects.
+
+@cindex small objects, MIPS ECOFF
+@cindex @code{gp} register, MIPS
+When assembling for @sc{ecoff}, the assembler uses the @code{$gp} (@code{$28})
+register to form the address of a ``small object''. Any object in the
+@code{.sdata} or @code{.sbss} sections is considered ``small'' in this sense.
+For external objects, or for objects in the @code{.bss} section, you can use
+the @code{@value{GCC}} @samp{-G} option to control the size of objects addressed via
+@code{$gp}; the default value is 8, meaning that a reference to any object
+eight bytes or smaller uses @code{$gp}. Passing @samp{-G 0} to
+@code{@value{AS}} prevents it from using the @code{$gp} register on the basis
+of object size (but the assembler uses @code{$gp} for objects in @code{.sdata}
+or @code{sbss} in any case). The size of an object in the @code{.bss} section
+is set by the @code{.comm} or @code{.lcomm} directive that defines it. The
+size of an external object may be set with the @code{.extern} directive. For
+example, @samp{.extern sym,4} declares that the object at @code{sym} is 4 bytes
+in length, whie leaving @code{sym} otherwise undefined.
+
+Using small @sc{ecoff} objects requires linker support, and assumes that the
+@code{$gp} register is correctly initialized (normally done automatically by
+the startup code). @sc{mips} @sc{ecoff} assembly code must not modify the
+@code{$gp} register.
+
+@node MIPS Stabs
+@section Directives for debugging information
+
+@cindex MIPS debugging directives
+@sc{mips} @sc{ecoff} @code{@value{AS}} supports several directives used for
+generating debugging information which are not support by traditional @sc{mips}
+assemblers. These are @code{.def}, @code{.endef}, @code{.dim}, @code{.file},
+@code{.scl}, @code{.size}, @code{.tag}, @code{.type}, @code{.val},
+@code{.stabd}, @code{.stabn}, and @code{.stabs}. The debugging information
+generated by the three @code{.stab} directives can only be read by @sc{gdb},
+not by traditional @sc{mips} debuggers (this enhancement is required to fully
+support C++ debugging). These directives are primarily used by compilers, not
+assembly language programmers!
+
+@node MIPS ISA
+@section Directives to override the ISA level
+
+@cindex MIPS ISA override
+@kindex @code{.set mips@var{n}}
+@sc{gnu} @code{@value{AS}} supports an additional directive to change
+the @sc{mips} Instruction Set Architecture level on the fly: @code{.set
+mips@var{n}}. @var{n} should be a number from 0 to 4. A value from 1
+to 4 makes the assembler accept instructions for the corresponding
+@sc{isa} level, from that point on in the assembly. @code{.set
+mips@var{n}} affects not only which instructions are permitted, but also
+how certain macros are expanded. @code{.set mips0} restores the
+@sc{isa} level to its original level: either the level you selected with
+command line options, or the default for your configuration. You can
+use this feature to permit specific @sc{r4000} instructions while
+assembling in 32 bit mode. Use this directive with care!
+
+The directive @samp{.set mips16} puts the assembler into MIPS 16 mode,
+in which it will assemble instructions for the MIPS 16 processor. Use
+@samp{.set nomips16} to return to normal 32 bit mode.
+
+Traditional @sc{mips} assemblers do not support this directive.
+
+@node MIPS autoextend
+@section Directives for extending MIPS 16 bit instructions
+
+@kindex @code{.set autoextend}
+@kindex @code{.set noautoextend}
+By default, MIPS 16 instructions are automatically extended to 32 bits
+when necessary. The directive @samp{.set noautoextend} will turn this
+off. When @samp{.set noautoextend} is in effect, any 32 bit instruction
+must be explicitly extended with the @samp{.e} modifier (e.g.,
+@samp{li.e $4,1000}). The directive @samp{.set autoextend} may be used
+to once again automatically extend instructions when necessary.
+
+This directive is only meaningful when in MIPS 16 mode. Traditional
+@sc{mips} assemblers do not support this directive.
+
+@node MIPS insn
+@section Directive to mark data as an instruction
+
+@kindex @code{.insn}
+The @code{.insn} directive tells @code{@value{AS}} that the following
+data is actually instructions. This makes a difference in MIPS 16 mode:
+when loading the address of a label which precedes instructions,
+@code{@value{AS}} automatically adds 1 to the value, so that jumping to
+the loaded address will do the right thing.
+
+@node MIPS option stack
+@section Directives to save and restore options
+
+@cindex MIPS option stack
+@kindex @code{.set push}
+@kindex @code{.set pop}
+The directives @code{.set push} and @code{.set pop} may be used to save
+and restore the current settings for all the options which are
+controlled by @code{.set}. The @code{.set push} directive saves the
+current settings on a stack. The @code{.set pop} directive pops the
+stack and restores the settings.
+
+These directives can be useful inside an macro which must change an
+option such as the ISA level or instruction reordering but does not want
+to change the state of the code which invoked the macro.
+
+Traditional @sc{mips} assemblers do not support these directives.
diff --git a/gas/doc/c-ns32k.texi b/gas/doc/c-ns32k.texi
new file mode 100644
index 0000000000..29c61d9478
--- /dev/null
+++ b/gas/doc/c-ns32k.texi
@@ -0,0 +1,30 @@
+@c Copyright (c) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+@c This is part of the GAS manual.
+@c For copying conditions, see the file as.texinfo.
+
+@ignore
+@c FIXME! Stop ignoring when filled in.
+@node 32x32
+@chapter 32x32
+
+@section Options
+The 32x32 version of @code{@value{AS}} accepts a @samp{-m32032} option to
+specify thiat it is compiling for a 32032 processor, or a
+@samp{-m32532} to specify that it is compiling for a 32532 option.
+The default (if neither is specified) is chosen when the assembler
+is compiled.
+
+@section Syntax
+I don't know anything about the 32x32 syntax assembled by
+@code{@value{AS}}. Someone who undersands the processor (I've never seen
+one) and the possible syntaxes should write this section.
+
+@section Floating Point
+The 32x32 uses @sc{ieee} floating point numbers, but @code{@value{AS}}
+only creates single or double precision values. I don't know if the
+32x32 understands extended precision numbers.
+
+@section 32x32 Machine Directives
+The 32x32 has no machine dependent directives.
+
+@end ignore
diff --git a/gas/doc/c-sh.texi b/gas/doc/c-sh.texi
new file mode 100644
index 0000000000..e20f554378
--- /dev/null
+++ b/gas/doc/c-sh.texi
@@ -0,0 +1,272 @@
+@c Copyright (C) 1991, 92, 93, 94, 95, 1997 Free Software Foundation, Inc.
+@c This is part of the GAS manual.
+@c For copying conditions, see the file as.texinfo.
+@page
+@node SH-Dependent
+@chapter Hitachi SH Dependent Features
+
+@cindex SH support
+@menu
+* SH Options:: Options
+* SH Syntax:: Syntax
+* SH Floating Point:: Floating Point
+* SH Directives:: SH Machine Directives
+* SH Opcodes:: Opcodes
+@end menu
+
+@node SH Options
+@section Options
+
+@cindex SH options (none)
+@cindex options, SH (none)
+@code{@value{AS}} has no additional command-line options for the Hitachi
+SH family.
+
+@node SH Syntax
+@section Syntax
+
+@menu
+* SH-Chars:: Special Characters
+* SH-Regs:: Register Names
+* SH-Addressing:: Addressing Modes
+@end menu
+
+@node SH-Chars
+@subsection Special Characters
+
+@cindex line comment character, SH
+@cindex SH line comment character
+@samp{!} is the line comment character.
+
+@cindex line separator, SH
+@cindex statement separator, SH
+@cindex SH line separator
+You can use @samp{;} instead of a newline to separate statements.
+
+@cindex symbol names, @samp{$} in
+@cindex @code{$} in symbol names
+Since @samp{$} has no special meaning, you may use it in symbol names.
+
+@node SH-Regs
+@subsection Register Names
+
+@cindex SH registers
+@cindex registers, SH
+You can use the predefined symbols @samp{r0}, @samp{r1}, @samp{r2},
+@samp{r3}, @samp{r4}, @samp{r5}, @samp{r6}, @samp{r7}, @samp{r8},
+@samp{r9}, @samp{r10}, @samp{r11}, @samp{r12}, @samp{r13}, @samp{r14},
+and @samp{r15} to refer to the SH registers.
+
+The SH also has these control registers:
+
+@table @code
+@item pr
+procedure register (holds return address)
+
+@item pc
+program counter
+
+@item mach
+@itemx macl
+high and low multiply accumulator registers
+
+@item sr
+status register
+
+@item gbr
+global base register
+
+@item vbr
+vector base register (for interrupt vectors)
+@end table
+
+@node SH-Addressing
+@subsection Addressing Modes
+
+@cindex addressing modes, SH
+@cindex SH addressing modes
+@code{@value{AS}} understands the following addressing modes for the SH.
+@code{R@var{n}} in the following refers to any of the numbered
+registers, but @emph{not} the control registers.
+
+@table @code
+@item R@var{n}
+Register direct
+
+@item @@R@var{n}
+Register indirect
+
+@item @@-R@var{n}
+Register indirect with pre-decrement
+
+@item @@R@var{n}+
+Register indirect with post-increment
+
+@item @@(@var{disp}, R@var{n})
+Register indirect with displacement
+
+@item @@(R0, R@var{n})
+Register indexed
+
+@item @@(@var{disp}, GBR)
+@code{GBR} offset
+
+@item @@(R0, GBR)
+GBR indexed
+
+@item @var{addr}
+@itemx @@(@var{disp}, PC)
+PC relative address (for branch or for addressing memory). The
+@code{@value{AS}} implementation allows you to use the simpler form
+@var{addr} anywhere a PC relative address is called for; the alternate
+form is supported for compatibility with other assemblers.
+
+@item #@var{imm}
+Immediate data
+@end table
+
+@node SH Floating Point
+@section Floating Point
+
+@cindex floating point, SH (@sc{ieee})
+@cindex SH floating point (@sc{ieee})
+The SH family has no hardware floating point, but the @code{.float}
+directive generates @sc{ieee} floating-point numbers for compatibility
+with other development tools.
+
+@node SH Directives
+@section SH Machine Directives
+
+@cindex SH machine directives
+@cindex machine directives, SH
+@cindex @code{uaword} directive, SH
+@cindex @code{ualong} directive, SH
+
+@table @code
+@item uaword
+@itemx ualong
+@code{@value{AS}} will issue a warning when a misaligned @code{.word} or
+@code{.long} directive is used. You may use @code{.uaword} or
+@code{.ualong} to indicate that the value is intentionally misaligned.
+@end table
+
+@node SH Opcodes
+@section Opcodes
+
+@cindex SH opcode summary
+@cindex opcode summary, SH
+@cindex mnemonics, SH
+@cindex instruction summary, SH
+For detailed information on the SH machine instruction set, see
+@cite{SH-Microcomputer User's Manual} (Hitachi Micro Systems, Inc.).
+
+@code{@value{AS}} implements all the standard SH opcodes. No additional
+pseudo-instructions are needed on this family. Note, however, that
+because @code{@value{AS}} supports a simpler form of PC-relative
+addressing, you may simply write (for example)
+
+@example
+mov.l bar,r0
+@end example
+
+@noindent
+where other assemblers might require an explicit displacement to
+@code{bar} from the program counter:
+
+@example
+mov.l @@(@var{disp}, PC)
+@end example
+
+@ifset SMALL
+@c this table, due to the multi-col faking and hardcoded order, looks silly
+@c except in smallbook. See comments below "@set SMALL" near top of this file.
+
+Here is a summary of SH opcodes:
+
+@page
+@smallexample
+@i{Legend:}
+Rn @r{a numbered register}
+Rm @r{another numbered register}
+#imm @r{immediate data}
+disp @r{displacement}
+disp8 @r{8-bit displacement}
+disp12 @r{12-bit displacement}
+
+add #imm,Rn lds.l @@Rn+,PR
+add Rm,Rn mac.w @@Rm+,@@Rn+
+addc Rm,Rn mov #imm,Rn
+addv Rm,Rn mov Rm,Rn
+and #imm,R0 mov.b Rm,@@(R0,Rn)
+and Rm,Rn mov.b Rm,@@-Rn
+and.b #imm,@@(R0,GBR) mov.b Rm,@@Rn
+bf disp8 mov.b @@(disp,Rm),R0
+bra disp12 mov.b @@(disp,GBR),R0
+bsr disp12 mov.b @@(R0,Rm),Rn
+bt disp8 mov.b @@Rm+,Rn
+clrmac mov.b @@Rm,Rn
+clrt mov.b R0,@@(disp,Rm)
+cmp/eq #imm,R0 mov.b R0,@@(disp,GBR)
+cmp/eq Rm,Rn mov.l Rm,@@(disp,Rn)
+cmp/ge Rm,Rn mov.l Rm,@@(R0,Rn)
+cmp/gt Rm,Rn mov.l Rm,@@-Rn
+cmp/hi Rm,Rn mov.l Rm,@@Rn
+cmp/hs Rm,Rn mov.l @@(disp,Rn),Rm
+cmp/pl Rn mov.l @@(disp,GBR),R0
+cmp/pz Rn mov.l @@(disp,PC),Rn
+cmp/str Rm,Rn mov.l @@(R0,Rm),Rn
+div0s Rm,Rn mov.l @@Rm+,Rn
+div0u mov.l @@Rm,Rn
+div1 Rm,Rn mov.l R0,@@(disp,GBR)
+exts.b Rm,Rn mov.w Rm,@@(R0,Rn)
+exts.w Rm,Rn mov.w Rm,@@-Rn
+extu.b Rm,Rn mov.w Rm,@@Rn
+extu.w Rm,Rn mov.w @@(disp,Rm),R0
+jmp @@Rn mov.w @@(disp,GBR),R0
+jsr @@Rn mov.w @@(disp,PC),Rn
+ldc Rn,GBR mov.w @@(R0,Rm),Rn
+ldc Rn,SR mov.w @@Rm+,Rn
+ldc Rn,VBR mov.w @@Rm,Rn
+ldc.l @@Rn+,GBR mov.w R0,@@(disp,Rm)
+ldc.l @@Rn+,SR mov.w R0,@@(disp,GBR)
+ldc.l @@Rn+,VBR mova @@(disp,PC),R0
+lds Rn,MACH movt Rn
+lds Rn,MACL muls Rm,Rn
+lds Rn,PR mulu Rm,Rn
+lds.l @@Rn+,MACH neg Rm,Rn
+lds.l @@Rn+,MACL negc Rm,Rn
+@page
+nop stc VBR,Rn
+not Rm,Rn stc.l GBR,@@-Rn
+or #imm,R0 stc.l SR,@@-Rn
+or Rm,Rn stc.l VBR,@@-Rn
+or.b #imm,@@(R0,GBR) sts MACH,Rn
+rotcl Rn sts MACL,Rn
+rotcr Rn sts PR,Rn
+rotl Rn sts.l MACH,@@-Rn
+rotr Rn sts.l MACL,@@-Rn
+rte sts.l PR,@@-Rn
+rts sub Rm,Rn
+sett subc Rm,Rn
+shal Rn subv Rm,Rn
+shar Rn swap.b Rm,Rn
+shll Rn swap.w Rm,Rn
+shll16 Rn tas.b @@Rn
+shll2 Rn trapa #imm
+shll8 Rn tst #imm,R0
+shlr Rn tst Rm,Rn
+shlr16 Rn tst.b #imm,@@(R0,GBR)
+shlr2 Rn xor #imm,R0
+shlr8 Rn xor Rm,Rn
+sleep xor.b #imm,@@(R0,GBR)
+stc GBR,Rn xtrct Rm,Rn
+stc SR,Rn
+@end smallexample
+@end ifset
+
+@ifset Hitachi-all
+@ifclear GENERIC
+@raisesections
+@end ifclear
+@end ifset
+
diff --git a/gas/doc/c-sparc.texi b/gas/doc/c-sparc.texi
new file mode 100644
index 0000000000..f871c82b05
--- /dev/null
+++ b/gas/doc/c-sparc.texi
@@ -0,0 +1,179 @@
+@c Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+@c This is part of the GAS manual.
+@c For copying conditions, see the file as.texinfo.
+@ifset GENERIC
+@page
+@node Sparc-Dependent
+@chapter SPARC Dependent Features
+@end ifset
+@ifclear GENERIC
+@node Machine Dependencies
+@chapter SPARC Dependent Features
+@end ifclear
+
+@cindex SPARC support
+@menu
+* Sparc-Opts:: Options
+* Sparc-Aligned-Data:: Option to enforce aligned data
+* Sparc-Float:: Floating Point
+* Sparc-Directives:: Sparc Machine Directives
+@end menu
+
+@node Sparc-Opts
+@section Options
+
+@cindex options for SPARC
+@cindex SPARC options
+@cindex architectures, SPARC
+@cindex SPARC architectures
+The SPARC chip family includes several successive levels, using the same
+core instruction set, but including a few additional instructions at
+each level. There are exceptions to this however. For details on what
+instructions each variant supports, please see the chip's architecture
+reference manual.
+
+By default, @code{@value{AS}} assumes the core instruction set (SPARC
+v6), but ``bumps'' the architecture level as needed: it switches to
+successively higher architectures as it encounters instructions that
+only exist in the higher levels.
+
+If not configured for SPARC v9 (@code{sparc64-*-*}) GAS will not bump
+passed sparclite by default, an option must be passed to enable the
+v9 instructions.
+
+GAS treats sparclite as being compatible with v8, unless an architecture
+is explicitly requested. SPARC v9 is always incompatible with sparclite.
+
+@c The order here is the same as the order of enum sparc_opcode_arch_val
+@c to give the user a sense of the order of the "bumping".
+
+@table @code
+@kindex -Av6
+@kindex Av7
+@kindex -Av8
+@kindex -Asparclet
+@kindex -Asparclite
+@kindex -Av9
+@kindex -Av9a
+@item -Av6 | -Av7 | -Av8 | -Asparclet | -Asparclite
+@itemx -Av8plus | -Av8plusa | -Av9 | -Av9a
+Use one of the @samp{-A} options to select one of the SPARC
+architectures explicitly. If you select an architecture explicitly,
+@code{@value{AS}} reports a fatal error if it encounters an instruction
+or feature requiring an incompatible or higher level.
+
+@samp{-Av8plus} and @samp{-Av8plusa} select a 32 bit environment.
+
+@samp{-Av9} and @samp{-Av9a} select a 64 bit environment and are not
+available unless GAS is explicitly configured with 64 bit environment
+support.
+
+@samp{-Av8plusa} and @samp{-Av9a} enable the SPARC V9 instruction set with
+UltraSPARC extensions.
+
+@item -xarch=v8plus | -xarch=v8plusa
+For compatibility with the Solaris v9 assembler. These options are
+equivalent to -Av8plus and -Av8plusa, respectively.
+
+@item -bump
+Warn whenever it is necessary to switch to another level.
+If an architecture level is explicitly requested, GAS will not issue
+warnings until that level is reached, and will then bump the level
+as required (except between incompatible levels).
+
+@item -32 | -64
+Select the word size, either 32 bits or 64 bits.
+These options are only available with the ELF object file format,
+and require that the necessary BFD support has been included.
+@end table
+
+@node Sparc-Aligned-Data
+@section Enforcing aligned data
+
+@cindex data alignment on SPARC
+@cindex SPARC data alignment
+SPARC GAS normally permits data to be misaligned. For example, it
+permits the @code{.long} pseudo-op to be used on a byte boundary.
+However, the native SunOS and Solaris assemblers issue an error when
+they see misaligned data.
+
+@kindex --enforce-aligned-data
+You can use the @code{--enforce-aligned-data} option to make SPARC GAS
+also issue an error about misaligned data, just as the SunOS and Solaris
+assemblers do.
+
+The @code{--enforce-aligned-data} option is not the default because gcc
+issues misaligned data pseudo-ops when it initializes certain packed
+data structures (structures defined using the @code{packed} attribute).
+You may have to assemble with GAS in order to initialize packed data
+structures in your own code.
+
+@ignore
+@c FIXME: (sparc) Fill in "syntax" section!
+@c subsection syntax
+I don't know anything about Sparc syntax. Someone who does
+will have to write this section.
+@end ignore
+
+@node Sparc-Float
+@section Floating Point
+
+@cindex floating point, SPARC (@sc{ieee})
+@cindex SPARC floating point (@sc{ieee})
+The Sparc uses @sc{ieee} floating-point numbers.
+
+@node Sparc-Directives
+@section Sparc Machine Directives
+
+@cindex SPARC machine directives
+@cindex machine directives, SPARC
+The Sparc version of @code{@value{AS}} supports the following additional
+machine directives:
+
+@table @code
+@cindex @code{align} directive, SPARC
+@item .align
+This must be followed by the desired alignment in bytes.
+
+@cindex @code{common} directive, SPARC
+@item .common
+This must be followed by a symbol name, a positive number, and
+@code{"bss"}. This behaves somewhat like @code{.comm}, but the
+syntax is different.
+
+@cindex @code{half} directive, SPARC
+@item .half
+This is functionally identical to @code{.short}.
+
+@cindex @code{proc} directive, SPARC
+@item .proc
+This directive is ignored. Any text following it on the same
+line is also ignored.
+
+@cindex @code{reserve} directive, SPARC
+@item .reserve
+This must be followed by a symbol name, a positive number, and
+@code{"bss"}. This behaves somewhat like @code{.lcomm}, but the
+syntax is different.
+
+@cindex @code{seg} directive, SPARC
+@item .seg
+This must be followed by @code{"text"}, @code{"data"}, or
+@code{"data1"}. It behaves like @code{.text}, @code{.data}, or
+@code{.data 1}.
+
+@cindex @code{skip} directive, SPARC
+@item .skip
+This is functionally identical to the @code{.space} directive.
+
+@cindex @code{word} directive, SPARC
+@item .word
+On the Sparc, the @code{.word} directive produces 32 bit values,
+instead of the 16 bit values it produces on many other machines.
+
+@cindex @code{xword} directive, SPARC
+@item .xword
+On the Sparc V9 processor, the @code{.xword} directive produces
+64 bit values.
+@end table
+
diff --git a/gas/doc/c-v850.texi b/gas/doc/c-v850.texi
new file mode 100644
index 0000000000..5416e0f1b8
--- /dev/null
+++ b/gas/doc/c-v850.texi
@@ -0,0 +1,363 @@
+@c Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+@c This is part of the GAS manual.
+@c For copying conditions, see the file as.texinfo.
+
+@node V850-Dependent
+@chapter v850 Dependent Features
+
+@cindex V850 support
+@menu
+* V850 Options:: Options
+* V850 Syntax:: Syntax
+* V850 Floating Point:: Floating Point
+* V850 Directives:: V850 Machine Directives
+* V850 Opcodes:: Opcodes
+@end menu
+
+@node V850 Options
+@section Options
+@cindex V850 options (none)
+@cindex options for V850 (none)
+@code{@value{AS}} supports the following additional command-line options
+for the V850 processor family:
+
+@cindex command line options, V850
+@cindex V850 command line options
+@table @code
+
+@cindex @code{-wsigned_overflow} command line option, V850
+@item -wsigned_overflow
+Causes warnings to be produced when signed immediate values overflow the
+space available for then within their opcodes. By default this option
+is disabled as it is possible to receive spurious warnings due to using
+exact bit patterns as immediate constants.
+
+@cindex @code{-wunsigned_overflow} command line option, V850
+@item -wunsigned_overflow
+Causes warnings to be produced when unsigned immediate values overflow
+the space available for then within their opcodes. By default this
+option is disabled as it is possible to receive spurious warnings due to
+using exact bit patterns as immediate constants.
+
+@cindex @code{-mv850} command line option, V850
+@item -mv850
+Specifies that the assembled code should be marked as being targeted at
+the V850 processor. This allows the linker to detect attempts to link
+such code with code assembled for other processors.
+
+@cindex @code{-mv850e} command line option, V850
+@item -mv850e
+Specifies that the assembled code should be marked as being targeted at
+the V850E processor. This allows the linker to detect attempts to link
+such code with code assembled for other processors.
+
+@cindex @code{-mv850any} command line option, V850
+@item -mv850any
+Specifies that the assembled code should be marked as being targeted at
+the V850 processor but support instructions that are specific to the
+extended variants of the process. This allows the production of
+binaries that contain target specific code, but which are also intended
+to be used in a generic fashion. For example libgcc.a contains generic
+routines used by the code produced by GCC for all versions of the v850
+architecture, together with support routines only used by the V850E
+architecture.
+
+@end table
+
+
+@node V850 Syntax
+@section Syntax
+@menu
+* V850-Chars:: Special Characters
+* V850-Regs:: Register Names
+@end menu
+
+@node V850-Chars
+@subsection Special Characters
+
+@cindex line comment character, V850
+@cindex V850 line comment character
+@samp{#} is the line comment character.
+@node V850-Regs
+@subsection Register Names
+
+@cindex V850 register names
+@cindex register names, V850
+@code{@value{AS}} supports the following names for registers:
+@table @code
+@cindex @code{zero} register, V850
+@item general register 0
+r0, zero
+@item general register 1
+r1
+@item general register 2
+r2, hp
+@cindex @code{sp} register, V850
+@item general register 3
+r3, sp
+@cindex @code{gp} register, V850
+@item general register 4
+r4, gp
+@cindex @code{tp} register, V850
+@item general register 5
+r5, tp
+@item general register 6
+r6
+@item general register 7
+r7
+@item general register 8
+r8
+@item general register 9
+r9
+@item general register 10
+r10
+@item general register 11
+r11
+@item general register 12
+r12
+@item general register 13
+r13
+@item general register 14
+r14
+@item general register 15
+r15
+@item general register 16
+r16
+@item general register 17
+r17
+@item general register 18
+r18
+@item general register 19
+r19
+@item general register 20
+r20
+@item general register 21
+r21
+@item general register 22
+r22
+@item general register 23
+r23
+@item general register 24
+r24
+@item general register 25
+r25
+@item general register 26
+r26
+@item general register 27
+r27
+@item general register 28
+r28
+@item general register 29
+r29
+@cindex @code{ep} register, V850
+@item general register 30
+r30, ep
+@cindex @code{lp} register, V850
+@item general register 31
+r31, lp
+@cindex @code{eipc} register, V850
+@item system register 0
+eipc
+@cindex @code{eipsw} register, V850
+@item system register 1
+eipsw
+@cindex @code{fepc} register, V850
+@item system register 2
+fepc
+@cindex @code{fepsw} register, V850
+@item system register 3
+fepsw
+@cindex @code{ecr} register, V850
+@item system register 4
+ecr
+@cindex @code{psw} register, V850
+@item system register 5
+psw
+@cindex @code{ctpc} register, V850
+@item system register 16
+ctpc
+@cindex @code{ctpsw} register, V850
+@item system register 17
+ctpsw
+@cindex @code{dbpc} register, V850
+@item system register 18
+dbpc
+@cindex @code{dbpsw} register, V850
+@item system register 19
+dbpsw
+@cindex @code{ctbp} register, V850
+@item system register 20
+ctbp
+@end table
+
+@node V850 Floating Point
+@section Floating Point
+
+@cindex floating point, V850 (@sc{ieee})
+@cindex V850 floating point (@sc{ieee})
+The V850 family uses @sc{ieee} floating-point numbers.
+
+@node V850 Directives
+@section V850 Machine Directives
+
+@cindex machine directives, V850
+@cindex V850 machine directives
+@table @code
+@cindex @code{offset} directive, V850
+@item .offset @var{<expression>}
+Moves the offset into the current section to the specified amount.
+
+@cindex @code{section} directive, V850
+@item .section "name", <type>
+This is an extension to the standard .section directive. It sets the
+current section to be <type> and creates an alias for this section
+called "name".
+
+@cindex @code{.v850} directive, V850
+@item .v850
+Specifies that the assembled code should be marked as being targeted at
+the V850 processor. This allows the linker to detect attempts to link
+such code with code assembled for other processors.
+
+@cindex @code{.v850e} directive, V850
+@item .v850e
+Specifies that the assembled code should be marked as being targeted at
+the V850E processor. This allows the linker to detect attempts to link
+such code with code assembled for other processors.
+
+@end table
+
+@node V850 Opcodes
+@section Opcodes
+
+@cindex V850 opcodes
+@cindex opcodes for V850
+@code{@value{AS}} implements all the standard V850 opcodes.
+
+@code{@value{AS}} also implements the following pseudo ops:
+
+@table @code
+
+@cindex @code{hi0} pseudo-op, V850
+@item hi0()
+Computes the higher 16 bits of the given expression and stores it into
+the immediate operand field of the given instruction. For example:
+
+ @samp{mulhi hi0(here - there), r5, r6}
+
+computes the difference between the address of labels 'here' and
+'there', takes the upper 16 bits of this difference, shifts it down 16
+bits and then mutliplies it by the lower 16 bits in register 5, putting
+the result into register 6.
+
+@cindex @code{lo} pseudo-op, V850
+@item lo()
+Computes the lower 16 bits of the given expression and stores it into
+the immediate operand field of the given instruction. For example:
+
+ @samp{addi lo(here - there), r5, r6}
+
+computes the difference between the address of labels 'here' and
+'there', takes the lower 16 bits of this difference and adds it to
+register 5, putting the result into register 6.
+
+@cindex @code{hi} pseudo-op, V850
+@item hi()
+Computes the higher 16 bits of the given expression and then adds the
+value of the most significant bit of the lower 16 bits of the expression
+and stores the result into the immediate operand field of the given
+instruction. For example the following code can be used to compute the
+address of the label 'here' and store it into register 6:
+
+ @samp{movhi hi(here), r0, r6}
+ @samp{movea lo(here), r6, r6}
+
+The reason for this special behaviour is that movea performs a sign
+extention on its immediate operand. So for example if the address of
+'here' was 0xFFFFFFFF then without the special behaviour of the hi()
+pseudo-op the movhi instruction would put 0xFFFF0000 into r6, then the
+movea instruction would takes its immediate operand, 0xFFFF, sign extend
+it to 32 bits, 0xFFFFFFFF, and then add it into r6 giving 0xFFFEFFFF
+which is wrong (the fifth nibble is E). With the hi() pseudo op adding
+in the top bit of the lo() pseudo op, the movhi instruction actually
+stores 0 into r6 (0xFFFF + 1 = 0x0000), so that the movea instruction
+stores 0xFFFFFFFF into r6 - the right value.
+
+@cindex @code{hilo} pseudo-op, V850
+@item hilo()
+Computes the 32 bit value of the given expression and stores it into
+the immediate operand field of the given instruction (which must be a
+mov instruction). For example:
+
+ @samp{mov hilo(here), r6}
+
+computes the absolute address of label 'here' and puts the result into
+register 6.
+
+@cindex @code{sdaoff} pseudo-op, V850
+@item sdaoff()
+Computes the offset of the named variable from the start of the Small
+Data Area (whoes address is held in register 4, the GP register) and
+stores the result as a 16 bit signed value in the immediate operand
+field of the given instruction. For example:
+
+ @samp{ld.w sdaoff(_a_variable)[gp],r6}
+
+loads the contents of the location pointed to by the label '_a_variable'
+into register 6, provided that the label is located somewhere within +/-
+32K of the address held in the GP register. [Note the linker assumes
+that the GP register contains a fixed address set to the address of the
+label called '__gp'. This can either be set up automatically by the
+linker, or specifically set by using the @samp{--defsym __gp=<value>}
+command line option].
+
+@cindex @code{tdaoff} pseudo-op, V850
+@item tdaoff()
+Computes the offset of the named variable from the start of the Tiny
+Data Area (whoes address is held in register 30, the EP register) and
+stores the result as a 4,5, 7 or 8 bit unsigned value in the immediate
+operand field of the given instruction. For example:
+
+ @samp{sld.w tdaoff(_a_variable)[ep],r6}
+
+loads the contents of the location pointed to by the label '_a_variable'
+into register 6, provided that the label is located somewhere within +256
+bytes of the address held in the EP register. [Note the linker assumes
+that the EP register contains a fixed address set to the address of the
+label called '__ep'. This can either be set up automatically by the
+linker, or specifically set by using the @samp{--defsym __ep=<value>}
+command line option].
+
+@cindex @code{zdaoff} pseudo-op, V850
+@item zdaoff()
+Computes the offset of the named variable from address 0 and stores the
+result as a 16 bit signed value in the immediate operand field of the
+given instruction. For example:
+
+ @samp{movea zdaoff(_a_variable),zero,r6}
+
+puts the address of the label '_a_variable' into register 6, assuming
+that the label is somewhere within the first 32K of memory. (Strictly
+speaking it also possible to access the last 32K of memory as well, as
+the offsets are signed).
+
+@cindex @code{ctoff} pseudo-op, V850
+@item ctoff()
+Computes the offset of the named variable from the start of the Call
+Table Area (whoes address is helg in system register 20, the CTBP
+register) and stores the result a 6 or 16 bit unsigned value in the
+immediate field of then given instruction or piece of data. For
+example:
+
+ @samp{callt ctoff(table_func1)}
+
+will put the call the function whoes address is held in the call table
+at the location labeled 'table_func1'.
+
+@end table
+
+
+For information on the V850 instruction set, see @cite{V850
+Family 32-/16-Bit single-Chip Microcontroller Architecture Manual} from NEC.
+Ltd.
+
diff --git a/gas/doc/c-vax.texi b/gas/doc/c-vax.texi
new file mode 100644
index 0000000000..b13d7e5a49
--- /dev/null
+++ b/gas/doc/c-vax.texi
@@ -0,0 +1,357 @@
+@c Copyright (C) 1991, 92, 93, 94, 95, 96, 1998 Free Software Foundation, Inc.
+@c This is part of the GAS manual.
+@c For copying conditions, see the file as.texinfo.
+@c VAX/VMS description exhanced and corrected by Klaus K"aempf, kkaempf@progis.de
+@ifset GENERIC
+@node Vax-Dependent
+@chapter VAX Dependent Features
+@cindex VAX support
+
+@end ifset
+@ifclear GENERIC
+@node Machine Dependencies
+@chapter VAX Dependent Features
+@cindex VAX support
+
+@end ifclear
+
+@menu
+* VAX-Opts:: VAX Command-Line Options
+* VAX-float:: VAX Floating Point
+* VAX-directives:: Vax Machine Directives
+* VAX-opcodes:: VAX Opcodes
+* VAX-branch:: VAX Branch Improvement
+* VAX-operands:: VAX Operands
+* VAX-no:: Not Supported on VAX
+@end menu
+
+
+@node VAX-Opts
+@section VAX Command-Line Options
+
+@cindex command-line options ignored, VAX
+@cindex VAX command-line options ignored
+The Vax version of @code{@value{AS}} accepts any of the following options,
+gives a warning message that the option was ignored and proceeds.
+These options are for compatibility with scripts designed for other
+people's assemblers.
+
+@table @code
+@cindex @code{-D}, ignored on VAX
+@cindex @code{-S}, ignored on VAX
+@cindex @code{-T}, ignored on VAX
+@item @code{-D} (Debug)
+@itemx @code{-S} (Symbol Table)
+@itemx @code{-T} (Token Trace)
+These are obsolete options used to debug old assemblers.
+
+@cindex @code{-d}, VAX option
+@item @code{-d} (Displacement size for JUMPs)
+This option expects a number following the @samp{-d}. Like options
+that expect filenames, the number may immediately follow the
+@samp{-d} (old standard) or constitute the whole of the command line
+argument that follows @samp{-d} (@sc{gnu} standard).
+
+@cindex @code{-V}, redundant on VAX
+@item @code{-V} (Virtualize Interpass Temporary File)
+Some other assemblers use a temporary file. This option
+commanded them to keep the information in active memory rather
+than in a disk file. @code{@value{AS}} always does this, so this
+option is redundant.
+
+@cindex @code{-J}, ignored on VAX
+@item @code{-J} (JUMPify Longer Branches)
+Many 32-bit computers permit a variety of branch instructions
+to do the same job. Some of these instructions are short (and
+fast) but have a limited range; others are long (and slow) but
+can branch anywhere in virtual memory. Often there are 3
+flavors of branch: short, medium and long. Some other
+assemblers would emit short and medium branches, unless told by
+this option to emit short and long branches.
+
+@cindex @code{-t}, ignored on VAX
+@item @code{-t} (Temporary File Directory)
+Some other assemblers may use a temporary file, and this option
+takes a filename being the directory to site the temporary
+file. Since @code{@value{AS}} does not use a temporary disk file, this
+option makes no difference. @samp{-t} needs exactly one
+filename.
+@end table
+
+@cindex VMS (VAX) options
+@cindex options for VAX/VMS
+@cindex VAX/VMS options
+@cindex Vax-11 C compatibility
+@cindex symbols with uppercase, VAX/VMS
+The Vax version of the assembler accepts additional options when
+compiled for VMS:
+
+@table @samp
+@cindex @samp{-h} option, VAX/VMS
+@item -h @var{n}
+External symbol or section (used for global variables) names are not
+case sensitive on VAX/VMS and always mapped to upper case. This is
+contrary to the C language definition which explicitly distinguishes
+upper and lower case. To implement a standard conforming C compiler,
+names must be changed (mapped) to preserve the case information. The
+default mapping is to convert all lower case characters to uppercase and
+adding an underscore followed by a 6 digit hex value, representing a 24
+digit binary value. The one digits in the binary value represent which
+characters are uppercase in the original symbol name.
+
+The @samp{-h @var{n}} option determines how we map names. This takes
+several values. No @samp{-h} switch at all allows case hacking as
+described above. A value of zero (@samp{-h0}) implies names should be
+upper case, and inhibits the case hack. A value of 2 (@samp{-h2})
+implies names should be all lower case, with no case hack. A value of 3
+(@samp{-h3}) implies that case should be preserved. The value 1 is
+unused. The @code{-H} option directs @code{@value{AS}} to display
+every mapped symbol during assembly.
+
+Symbols whose names include a dollar sign @samp{$} are exceptions to the
+general name mapping. These symbols are normally only used to reference
+VMS library names. Such symbols are always mapped to upper case.
+
+@cindex @samp{-+} option, VAX/VMS
+@item -+
+The @samp{-+} option causes @code{@value{AS}} to truncate any symbol
+name larger than 31 characters. The @samp{-+} option also prevents some
+code following the @samp{_main} symbol normally added to make the object
+file compatible with Vax-11 "C".
+
+@cindex @samp{-1} option, VAX/VMS
+@item -1
+This option is ignored for backward compatibility with @code{@value{AS}}
+version 1.x.
+
+@cindex @samp{-H} option, VAX/VMS
+@item -H
+The @samp{-H} option causes @code{@value{AS}} to print every symbol
+which was changed by case mapping.
+@end table
+
+@node VAX-float
+@section VAX Floating Point
+
+@cindex VAX floating point
+@cindex floating point, VAX
+Conversion of flonums to floating point is correct, and
+compatible with previous assemblers. Rounding is
+towards zero if the remainder is exactly half the least significant bit.
+
+@code{D}, @code{F}, @code{G} and @code{H} floating point formats
+are understood.
+
+Immediate floating literals (@emph{e.g.} @samp{S`$6.9})
+are rendered correctly. Again, rounding is towards zero in the
+boundary case.
+
+@cindex @code{float} directive, VAX
+@cindex @code{double} directive, VAX
+The @code{.float} directive produces @code{f} format numbers.
+The @code{.double} directive produces @code{d} format numbers.
+
+@node VAX-directives
+@section Vax Machine Directives
+
+@cindex machine directives, VAX
+@cindex VAX machine directives
+The Vax version of the assembler supports four directives for
+generating Vax floating point constants. They are described in the
+table below.
+
+@cindex wide floating point directives, VAX
+@table @code
+@cindex @code{dfloat} directive, VAX
+@item .dfloat
+This expects zero or more flonums, separated by commas, and
+assembles Vax @code{d} format 64-bit floating point constants.
+
+@cindex @code{ffloat} directive, VAX
+@item .ffloat
+This expects zero or more flonums, separated by commas, and
+assembles Vax @code{f} format 32-bit floating point constants.
+
+@cindex @code{gfloat} directive, VAX
+@item .gfloat
+This expects zero or more flonums, separated by commas, and
+assembles Vax @code{g} format 64-bit floating point constants.
+
+@cindex @code{hfloat} directive, VAX
+@item .hfloat
+This expects zero or more flonums, separated by commas, and
+assembles Vax @code{h} format 128-bit floating point constants.
+
+@end table
+
+@node VAX-opcodes
+@section VAX Opcodes
+
+@cindex VAX opcode mnemonics
+@cindex opcode mnemonics, VAX
+@cindex mnemonics for opcodes, VAX
+All DEC mnemonics are supported. Beware that @code{case@dots{}}
+instructions have exactly 3 operands. The dispatch table that
+follows the @code{case@dots{}} instruction should be made with
+@code{.word} statements. This is compatible with all unix
+assemblers we know of.
+
+@node VAX-branch
+@section VAX Branch Improvement
+
+@cindex VAX branch improvement
+@cindex branch improvement, VAX
+@cindex pseudo-ops for branch, VAX
+Certain pseudo opcodes are permitted. They are for branch
+instructions. They expand to the shortest branch instruction that
+reaches the target. Generally these mnemonics are made by
+substituting @samp{j} for @samp{b} at the start of a DEC mnemonic.
+This feature is included both for compatibility and to help
+compilers. If you do not need this feature, avoid these
+opcodes. Here are the mnemonics, and the code they can expand into.
+
+@table @code
+@item jbsb
+@samp{Jsb} is already an instruction mnemonic, so we chose @samp{jbsb}.
+@table @asis
+@item (byte displacement)
+@kbd{bsbb @dots{}}
+@item (word displacement)
+@kbd{bsbw @dots{}}
+@item (long displacement)
+@kbd{jsb @dots{}}
+@end table
+@item jbr
+@itemx jr
+Unconditional branch.
+@table @asis
+@item (byte displacement)
+@kbd{brb @dots{}}
+@item (word displacement)
+@kbd{brw @dots{}}
+@item (long displacement)
+@kbd{jmp @dots{}}
+@end table
+@item j@var{COND}
+@var{COND} may be any one of the conditional branches
+@code{neq}, @code{nequ}, @code{eql}, @code{eqlu}, @code{gtr},
+@code{geq}, @code{lss}, @code{gtru}, @code{lequ}, @code{vc}, @code{vs},
+@code{gequ}, @code{cc}, @code{lssu}, @code{cs}.
+@var{COND} may also be one of the bit tests
+@code{bs}, @code{bc}, @code{bss}, @code{bcs}, @code{bsc}, @code{bcc},
+@code{bssi}, @code{bcci}, @code{lbs}, @code{lbc}.
+@var{NOTCOND} is the opposite condition to @var{COND}.
+@table @asis
+@item (byte displacement)
+@kbd{b@var{COND} @dots{}}
+@item (word displacement)
+@kbd{b@var{NOTCOND} foo ; brw @dots{} ; foo:}
+@item (long displacement)
+@kbd{b@var{NOTCOND} foo ; jmp @dots{} ; foo:}
+@end table
+@item jacb@var{X}
+@var{X} may be one of @code{b d f g h l w}.
+@table @asis
+@item (word displacement)
+@kbd{@var{OPCODE} @dots{}}
+@item (long displacement)
+@example
+@var{OPCODE} @dots{}, foo ;
+brb bar ;
+foo: jmp @dots{} ;
+bar:
+@end example
+@end table
+@item jaob@var{YYY}
+@var{YYY} may be one of @code{lss leq}.
+@item jsob@var{ZZZ}
+@var{ZZZ} may be one of @code{geq gtr}.
+@table @asis
+@item (byte displacement)
+@kbd{@var{OPCODE} @dots{}}
+@item (word displacement)
+@example
+@var{OPCODE} @dots{}, foo ;
+brb bar ;
+foo: brw @var{destination} ;
+bar:
+@end example
+@item (long displacement)
+@example
+@var{OPCODE} @dots{}, foo ;
+brb bar ;
+foo: jmp @var{destination} ;
+bar:
+@end example
+@end table
+@item aobleq
+@itemx aoblss
+@itemx sobgeq
+@itemx sobgtr
+@table @asis
+@item (byte displacement)
+@kbd{@var{OPCODE} @dots{}}
+@item (word displacement)
+@example
+@var{OPCODE} @dots{}, foo ;
+brb bar ;
+foo: brw @var{destination} ;
+bar:
+@end example
+@item (long displacement)
+@example
+@var{OPCODE} @dots{}, foo ;
+brb bar ;
+foo: jmp @var{destination} ;
+bar:
+@end example
+@end table
+@end table
+
+@node VAX-operands
+@section VAX Operands
+
+@cindex VAX operand notation
+@cindex operand notation, VAX
+@cindex immediate character, VAX
+@cindex VAX immediate character
+The immediate character is @samp{$} for Unix compatibility, not
+@samp{#} as DEC writes it.
+
+@cindex indirect character, VAX
+@cindex VAX indirect character
+The indirect character is @samp{*} for Unix compatibility, not
+@samp{@@} as DEC writes it.
+
+@cindex displacement sizing character, VAX
+@cindex VAX displacement sizing character
+The displacement sizing character is @samp{`} (an accent grave) for
+Unix compatibility, not @samp{^} as DEC writes it. The letter
+preceding @samp{`} may have either case. @samp{G} is not
+understood, but all other letters (@code{b i l s w}) are understood.
+
+@cindex register names, VAX
+@cindex VAX register names
+Register names understood are @code{r0 r1 r2 @dots{} r15 ap fp sp
+pc}. Upper and lower case letters are equivalent.
+
+For instance
+@smallexample
+tstb *w`$4(r5)
+@end smallexample
+
+Any expression is permitted in an operand. Operands are comma
+separated.
+
+@c There is some bug to do with recognizing expressions
+@c in operands, but I forget what it is. It is
+@c a syntax clash because () is used as an address mode
+@c and to encapsulate sub-expressions.
+
+@node VAX-no
+@section Not Supported on VAX
+
+@cindex VAX bitfields not supported
+@cindex bitfields, not supported on VAX
+Vax bit fields can not be assembled with @code{@value{AS}}. Someone
+can add the required code if they really need it.
diff --git a/gas/doc/c-z8k.texi b/gas/doc/c-z8k.texi
new file mode 100644
index 0000000000..1fb10e3b2c
--- /dev/null
+++ b/gas/doc/c-z8k.texi
@@ -0,0 +1,380 @@
+@c Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+@c This is part of the GAS manual.
+@c For copying conditions, see the file as.texinfo.
+@ifset GENERIC
+@page
+@node Z8000-Dependent
+@chapter Z8000 Dependent Features
+@end ifset
+@ifclear GENERIC
+@node Machine Dependencies
+@chapter Z8000 Dependent Features
+@end ifclear
+
+@cindex Z8000 support
+The Z8000 @value{AS} supports both members of the Z8000 family: the
+unsegmented Z8002, with 16 bit addresses, and the segmented Z8001 with
+24 bit addresses.
+
+When the assembler is in unsegmented mode (specified with the
+@code{unsegm} directive), an address takes up one word (16 bit)
+sized register. When the assembler is in segmented mode (specified with
+the @code{segm} directive), a 24-bit address takes up a long (32 bit)
+register. @xref{Z8000 Directives,,Assembler Directives for the Z8000},
+for a list of other Z8000 specific assembler directives.
+
+@menu
+* Z8000 Options:: No special command-line options for Z8000
+* Z8000 Syntax:: Assembler syntax for the Z8000
+* Z8000 Directives:: Special directives for the Z8000
+* Z8000 Opcodes:: Opcodes
+@end menu
+
+@node Z8000 Options
+@section Options
+
+@cindex Z8000 options
+@cindex options, Z8000
+@code{@value{AS}} has no additional command-line options for the Zilog
+Z8000 family.
+
+@node Z8000 Syntax
+@section Syntax
+@menu
+* Z8000-Chars:: Special Characters
+* Z8000-Regs:: Register Names
+* Z8000-Addressing:: Addressing Modes
+@end menu
+
+@node Z8000-Chars
+@subsection Special Characters
+
+@cindex line comment character, Z8000
+@cindex Z8000 line comment character
+@samp{!} is the line comment character.
+
+@cindex line separator, Z8000
+@cindex statement separator, Z8000
+@cindex Z8000 line separator
+You can use @samp{;} instead of a newline to separate statements.
+
+@node Z8000-Regs
+@subsection Register Names
+
+@cindex Z8000 registers
+@cindex registers, Z8000
+The Z8000 has sixteen 16 bit registers, numbered 0 to 15. You can refer
+to different sized groups of registers by register number, with the
+prefix @samp{r} for 16 bit registers, @samp{rr} for 32 bit registers and
+@samp{rq} for 64 bit registers. You can also refer to the contents of
+the first eight (of the sixteen 16 bit registers) by bytes. They are
+named @samp{r@var{n}h} and @samp{r@var{n}l}.
+
+@smallexample
+@exdent @emph{byte registers}
+r0l r0h r1h r1l r2h r2l r3h r3l
+r4h r4l r5h r5l r6h r6l r7h r7l
+
+@exdent @emph{word registers}
+r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15
+
+@exdent @emph{long word registers}
+rr0 rr2 rr4 rr6 rr8 rr10 rr12 rr14
+
+@exdent @emph{quad word registers}
+rq0 rq4 rq8 rq12
+@end smallexample
+
+@node Z8000-Addressing
+@subsection Addressing Modes
+
+@cindex addressing modes, Z8000
+@cindex Z800 addressing modes
+@value{AS} understands the following addressing modes for the Z8000:
+
+@table @code
+@item r@var{n}
+Register direct
+
+@item @@r@var{n}
+Indirect register
+
+@item @var{addr}
+Direct: the 16 bit or 24 bit address (depending on whether the assembler
+is in segmented or unsegmented mode) of the operand is in the instruction.
+
+@item address(r@var{n})
+Indexed: the 16 or 24 bit address is added to the 16 bit register to produce
+the final address in memory of the operand.
+
+@item r@var{n}(#@var{imm})
+Base Address: the 16 or 24 bit register is added to the 16 bit sign
+extended immediate displacement to produce the final address in memory
+of the operand.
+
+@item r@var{n}(r@var{m})
+Base Index: the 16 or 24 bit register r@var{n} is added to the sign
+extended 16 bit index register r@var{m} to produce the final address in
+memory of the operand.
+
+@item #@var{xx}
+Immediate data @var{xx}.
+@end table
+
+@node Z8000 Directives
+@section Assembler Directives for the Z8000
+
+@cindex Z8000 directives
+@cindex directives, Z8000
+The Z8000 port of @value{AS} includes these additional assembler directives,
+for compatibility with other Z8000 assemblers. As shown, these do not
+begin with @samp{.} (unlike the ordinary @value{AS} directives).
+
+@table @code
+@kindex segm
+@item segm
+Generates code for the segmented Z8001.
+
+@kindex unsegm
+@item unsegm
+Generates code for the unsegmented Z8002.
+
+@kindex name
+@item name
+Synonym for @code{.file}
+
+@kindex global
+@item global
+Synonym for @code{.global}
+
+@kindex wval
+@item wval
+Synonym for @code{.word}
+
+@kindex lval
+@item lval
+Synonym for @code{.long}
+
+@kindex bval
+@item bval
+Synonym for @code{.byte}
+
+@kindex sval
+@item sval
+Assemble a string. @code{sval} expects one string literal, delimited by
+single quotes. It assembles each byte of the string into consecutive
+addresses. You can use the escape sequence @samp{%@var{xx}} (where
+@var{xx} represents a two-digit hexadecimal number) to represent the
+character whose @sc{ascii} value is @var{xx}. Use this feature to
+describe single quote and other characters that may not appear in string
+literals as themselves. For example, the C statement @w{@samp{char *a =
+"he said \"it's 50% off\"";}} is represented in Z8000 assembly language
+(shown with the assembler output in hex at the left) as
+
+@iftex
+@begingroup
+@let@nonarrowing=@comment
+@end iftex
+@smallexample
+68652073 sval 'he said %22it%27s 50%25 off%22%00'
+61696420
+22697427
+73203530
+25206F66
+662200
+@end smallexample
+@iftex
+@endgroup
+@end iftex
+
+@kindex rsect
+@item rsect
+synonym for @code{.section}
+
+@kindex block
+@item block
+synonym for @code{.space}
+
+@kindex even
+@item even
+special case of @code{.align}; aligns output to even byte boundary.
+@end table
+
+@node Z8000 Opcodes
+@section Opcodes
+
+@cindex Z8000 opcode summary
+@cindex opcode summary, Z8000
+@cindex mnemonics, Z8000
+@cindex instruction summary, Z8000
+For detailed information on the Z8000 machine instruction set, see
+@cite{Z8000 Technical Manual}.
+
+@ifset SMALL
+@c this table, due to the multi-col faking and hardcoded order, looks silly
+@c except in smallbook. See comments below "@set SMALL" near top of this file.
+
+The following table summarizes the opcodes and their arguments:
+@iftex
+@begingroup
+@let@nonarrowing=@comment
+@end iftex
+@smallexample
+
+ rs @r{16 bit source register}
+ rd @r{16 bit destination register}
+ rbs @r{8 bit source register}
+ rbd @r{8 bit destination register}
+ rrs @r{32 bit source register}
+ rrd @r{32 bit destination register}
+ rqs @r{64 bit source register}
+ rqd @r{64 bit destination register}
+ addr @r{16/24 bit address}
+ imm @r{immediate data}
+
+adc rd,rs clrb addr cpsir @@rd,@@rs,rr,cc
+adcb rbd,rbs clrb addr(rd) cpsirb @@rd,@@rs,rr,cc
+add rd,@@rs clrb rbd dab rbd
+add rd,addr com @@rd dbjnz rbd,disp7
+add rd,addr(rs) com addr dec @@rd,imm4m1
+add rd,imm16 com addr(rd) dec addr(rd),imm4m1
+add rd,rs com rd dec addr,imm4m1
+addb rbd,@@rs comb @@rd dec rd,imm4m1
+addb rbd,addr comb addr decb @@rd,imm4m1
+addb rbd,addr(rs) comb addr(rd) decb addr(rd),imm4m1
+addb rbd,imm8 comb rbd decb addr,imm4m1
+addb rbd,rbs comflg flags decb rbd,imm4m1
+addl rrd,@@rs cp @@rd,imm16 di i2
+addl rrd,addr cp addr(rd),imm16 div rrd,@@rs
+addl rrd,addr(rs) cp addr,imm16 div rrd,addr
+addl rrd,imm32 cp rd,@@rs div rrd,addr(rs)
+addl rrd,rrs cp rd,addr div rrd,imm16
+and rd,@@rs cp rd,addr(rs) div rrd,rs
+and rd,addr cp rd,imm16 divl rqd,@@rs
+and rd,addr(rs) cp rd,rs divl rqd,addr
+and rd,imm16 cpb @@rd,imm8 divl rqd,addr(rs)
+and rd,rs cpb addr(rd),imm8 divl rqd,imm32
+andb rbd,@@rs cpb addr,imm8 divl rqd,rrs
+andb rbd,addr cpb rbd,@@rs djnz rd,disp7
+andb rbd,addr(rs) cpb rbd,addr ei i2
+andb rbd,imm8 cpb rbd,addr(rs) ex rd,@@rs
+andb rbd,rbs cpb rbd,imm8 ex rd,addr
+bit @@rd,imm4 cpb rbd,rbs ex rd,addr(rs)
+bit addr(rd),imm4 cpd rd,@@rs,rr,cc ex rd,rs
+bit addr,imm4 cpdb rbd,@@rs,rr,cc exb rbd,@@rs
+bit rd,imm4 cpdr rd,@@rs,rr,cc exb rbd,addr
+bit rd,rs cpdrb rbd,@@rs,rr,cc exb rbd,addr(rs)
+bitb @@rd,imm4 cpi rd,@@rs,rr,cc exb rbd,rbs
+bitb addr(rd),imm4 cpib rbd,@@rs,rr,cc ext0e imm8
+bitb addr,imm4 cpir rd,@@rs,rr,cc ext0f imm8
+bitb rbd,imm4 cpirb rbd,@@rs,rr,cc ext8e imm8
+bitb rbd,rs cpl rrd,@@rs ext8f imm8
+bpt cpl rrd,addr exts rrd
+call @@rd cpl rrd,addr(rs) extsb rd
+call addr cpl rrd,imm32 extsl rqd
+call addr(rd) cpl rrd,rrs halt
+calr disp12 cpsd @@rd,@@rs,rr,cc in rd,@@rs
+clr @@rd cpsdb @@rd,@@rs,rr,cc in rd,imm16
+clr addr cpsdr @@rd,@@rs,rr,cc inb rbd,@@rs
+clr addr(rd) cpsdrb @@rd,@@rs,rr,cc inb rbd,imm16
+clr rd cpsi @@rd,@@rs,rr,cc inc @@rd,imm4m1
+clrb @@rd cpsib @@rd,@@rs,rr,cc inc addr(rd),imm4m1
+inc addr,imm4m1 ldb rbd,rs(rx) mult rrd,addr(rs)
+inc rd,imm4m1 ldb rd(imm16),rbs mult rrd,imm16
+incb @@rd,imm4m1 ldb rd(rx),rbs mult rrd,rs
+incb addr(rd),imm4m1 ldctl ctrl,rs multl rqd,@@rs
+incb addr,imm4m1 ldctl rd,ctrl multl rqd,addr
+incb rbd,imm4m1 ldd @@rs,@@rd,rr multl rqd,addr(rs)
+ind @@rd,@@rs,ra lddb @@rs,@@rd,rr multl rqd,imm32
+indb @@rd,@@rs,rba lddr @@rs,@@rd,rr multl rqd,rrs
+inib @@rd,@@rs,ra lddrb @@rs,@@rd,rr neg @@rd
+inibr @@rd,@@rs,ra ldi @@rd,@@rs,rr neg addr
+iret ldib @@rd,@@rs,rr neg addr(rd)
+jp cc,@@rd ldir @@rd,@@rs,rr neg rd
+jp cc,addr ldirb @@rd,@@rs,rr negb @@rd
+jp cc,addr(rd) ldk rd,imm4 negb addr
+jr cc,disp8 ldl @@rd,rrs negb addr(rd)
+ld @@rd,imm16 ldl addr(rd),rrs negb rbd
+ld @@rd,rs ldl addr,rrs nop
+ld addr(rd),imm16 ldl rd(imm16),rrs or rd,@@rs
+ld addr(rd),rs ldl rd(rx),rrs or rd,addr
+ld addr,imm16 ldl rrd,@@rs or rd,addr(rs)
+ld addr,rs ldl rrd,addr or rd,imm16
+ld rd(imm16),rs ldl rrd,addr(rs) or rd,rs
+ld rd(rx),rs ldl rrd,imm32 orb rbd,@@rs
+ld rd,@@rs ldl rrd,rrs orb rbd,addr
+ld rd,addr ldl rrd,rs(imm16) orb rbd,addr(rs)
+ld rd,addr(rs) ldl rrd,rs(rx) orb rbd,imm8
+ld rd,imm16 ldm @@rd,rs,n orb rbd,rbs
+ld rd,rs ldm addr(rd),rs,n out @@rd,rs
+ld rd,rs(imm16) ldm addr,rs,n out imm16,rs
+ld rd,rs(rx) ldm rd,@@rs,n outb @@rd,rbs
+lda rd,addr ldm rd,addr(rs),n outb imm16,rbs
+lda rd,addr(rs) ldm rd,addr,n outd @@rd,@@rs,ra
+lda rd,rs(imm16) ldps @@rs outdb @@rd,@@rs,rba
+lda rd,rs(rx) ldps addr outib @@rd,@@rs,ra
+ldar rd,disp16 ldps addr(rs) outibr @@rd,@@rs,ra
+ldb @@rd,imm8 ldr disp16,rs pop @@rd,@@rs
+ldb @@rd,rbs ldr rd,disp16 pop addr(rd),@@rs
+ldb addr(rd),imm8 ldrb disp16,rbs pop addr,@@rs
+ldb addr(rd),rbs ldrb rbd,disp16 pop rd,@@rs
+ldb addr,imm8 ldrl disp16,rrs popl @@rd,@@rs
+ldb addr,rbs ldrl rrd,disp16 popl addr(rd),@@rs
+ldb rbd,@@rs mbit popl addr,@@rs
+ldb rbd,addr mreq rd popl rrd,@@rs
+ldb rbd,addr(rs) mres push @@rd,@@rs
+ldb rbd,imm8 mset push @@rd,addr
+ldb rbd,rbs mult rrd,@@rs push @@rd,addr(rs)
+ldb rbd,rs(imm16) mult rrd,addr push @@rd,imm16
+push @@rd,rs set addr,imm4 subl rrd,imm32
+pushl @@rd,@@rs set rd,imm4 subl rrd,rrs
+pushl @@rd,addr set rd,rs tcc cc,rd
+pushl @@rd,addr(rs) setb @@rd,imm4 tccb cc,rbd
+pushl @@rd,rrs setb addr(rd),imm4 test @@rd
+res @@rd,imm4 setb addr,imm4 test addr
+res addr(rd),imm4 setb rbd,imm4 test addr(rd)
+res addr,imm4 setb rbd,rs test rd
+res rd,imm4 setflg imm4 testb @@rd
+res rd,rs sinb rbd,imm16 testb addr
+resb @@rd,imm4 sinb rd,imm16 testb addr(rd)
+resb addr(rd),imm4 sind @@rd,@@rs,ra testb rbd
+resb addr,imm4 sindb @@rd,@@rs,rba testl @@rd
+resb rbd,imm4 sinib @@rd,@@rs,ra testl addr
+resb rbd,rs sinibr @@rd,@@rs,ra testl addr(rd)
+resflg imm4 sla rd,imm8 testl rrd
+ret cc slab rbd,imm8 trdb @@rd,@@rs,rba
+rl rd,imm1or2 slal rrd,imm8 trdrb @@rd,@@rs,rba
+rlb rbd,imm1or2 sll rd,imm8 trib @@rd,@@rs,rbr
+rlc rd,imm1or2 sllb rbd,imm8 trirb @@rd,@@rs,rbr
+rlcb rbd,imm1or2 slll rrd,imm8 trtdrb @@ra,@@rb,rbr
+rldb rbb,rba sout imm16,rs trtib @@ra,@@rb,rr
+rr rd,imm1or2 soutb imm16,rbs trtirb @@ra,@@rb,rbr
+rrb rbd,imm1or2 soutd @@rd,@@rs,ra trtrb @@ra,@@rb,rbr
+rrc rd,imm1or2 soutdb @@rd,@@rs,rba tset @@rd
+rrcb rbd,imm1or2 soutib @@rd,@@rs,ra tset addr
+rrdb rbb,rba soutibr @@rd,@@rs,ra tset addr(rd)
+rsvd36 sra rd,imm8 tset rd
+rsvd38 srab rbd,imm8 tsetb @@rd
+rsvd78 sral rrd,imm8 tsetb addr
+rsvd7e srl rd,imm8 tsetb addr(rd)
+rsvd9d srlb rbd,imm8 tsetb rbd
+rsvd9f srll rrd,imm8 xor rd,@@rs
+rsvdb9 sub rd,@@rs xor rd,addr
+rsvdbf sub rd,addr xor rd,addr(rs)
+sbc rd,rs sub rd,addr(rs) xor rd,imm16
+sbcb rbd,rbs sub rd,imm16 xor rd,rs
+sc imm8 sub rd,rs xorb rbd,@@rs
+sda rd,rs subb rbd,@@rs xorb rbd,addr
+sdab rbd,rs subb rbd,addr xorb rbd,addr(rs)
+sdal rrd,rs subb rbd,addr(rs) xorb rbd,imm8
+sdl rd,rs subb rbd,imm8 xorb rbd,rbs
+sdlb rbd,rs subb rbd,rbs xorb rbd,rbs
+sdll rrd,rs subl rrd,@@rs
+set @@rd,imm4 subl rrd,addr
+set addr(rd),imm4 subl rrd,addr(rs)
+@end smallexample
+@iftex
+@endgroup
+@end iftex
+@end ifset
+
diff --git a/gas/doc/gasp.texi b/gas/doc/gasp.texi
new file mode 100644
index 0000000000..64cd6f44b1
--- /dev/null
+++ b/gas/doc/gasp.texi
@@ -0,0 +1,1086 @@
+\input texinfo @c -*- Texinfo -*-
+@setfilename gasp.info
+@c
+@c This file documents the assembly preprocessor "GASP"
+@c
+@c Copyright (c) 1994 Free Software Foundation, Inc.
+@c
+@c This text may be freely distributed under the terms of the GNU
+@c General Public License.
+
+@ifinfo
+@format
+START-INFO-DIR-ENTRY
+* gasp: (gasp). The GNU Assembler Preprocessor
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+
+@syncodeindex ky cp
+@syncodeindex fn cp
+
+@finalout
+@setchapternewpage odd
+@settitle GASP
+@titlepage
+@c FIXME boring title
+@title GASP, an assembly preprocessor
+@subtitle for GASP version 1
+@sp 1
+@subtitle March 1994
+@author Roland Pesch
+@page
+
+@tex
+{\parskip=0pt \hfill Cygnus Support\par
+}
+@end tex
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1994, 1995 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end titlepage
+
+@ifinfo
+Copyright @copyright{} 1994, 1995 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries a copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+@end ignore
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+
+@node Top
+@top GASP
+
+GASP is a preprocessor for assembly programs.
+
+This file describes version 1 of GASP.
+
+Steve Chamberlain wrote GASP; Roland Pesch wrote this manual.
+
+@menu
+* Overview:: What is GASP?
+* Invoking GASP:: Command line options.
+* Commands:: Preprocessor commands.
+* Index:: Index.
+@end menu
+@end ifinfo
+
+@node Overview
+@chapter What is GASP?
+
+The primary purpose of the @sc{gnu} assembler is to assemble the output of
+other programs---notably compilers. When you have to hand-code
+specialized routines in assembly, that means the @sc{gnu} assembler is
+an unfriendly processor: it has no directives for macros, conditionals,
+or many other conveniences that you might expect.
+
+In some cases you can simply use the C preprocessor, or a generalized
+preprocessor like @sc{m4}; but this can be awkward, since none of these
+things are designed with assembly in mind.
+
+@sc{gasp} fills this need. It is expressly designed to provide the
+facilities you need with hand-coded assembly code. Implementing it as a
+preprocessor, rather than part of the assembler, allows the maximum
+flexibility: you can use it with hand-coded assembly, without paying a
+penalty of added complexity in the assembler you use for compiler
+output.
+
+Here is a small example to give the flavor of @sc{gasp}. This input to
+@sc{gasp}
+
+@cartouche
+@example
+ .MACRO saveregs from=8 to=14
+count .ASSIGNA \from
+ ! save r\from..r\to
+ .AWHILE \&count LE \to
+ mov r\&count,@@-sp
+count .ASSIGNA \&count + 1
+ .AENDW
+ .ENDM
+
+ saveregs from=12
+
+bar: mov #H'dead+10,r0
+foo .SDATAC "hello"<10>
+ .END
+@end example
+@end cartouche
+
+@noindent
+generates this assembly program:
+
+@cartouche
+@example
+ ! save r12..r14
+ mov r12,@@-sp
+ mov r13,@@-sp
+ mov r14,@@-sp
+
+bar: mov #57005+10,r0
+foo: .byte 6,104,101,108,108,111,10
+@end example
+@end cartouche
+
+@node Invoking GASP
+@chapter Command Line Options
+
+@c FIXME! Or is there a simpler way, calling from GAS option?
+The simplest way to use @sc{gasp} is to run it as a filter and assemble
+its output. In Unix and its ilk, you can do this, for example:
+
+@c FIXME! GASP filename suffix convention?
+@example
+$ gasp prog.asm | as -o prog.o
+@end example
+
+Naturally, there are also a few command-line options to allow you to
+request variations on this basic theme. Here is the full set of
+possibilities for the @sc{gasp} command line.
+
+@example
+gasp [ -a | --alternate ]
+ [ -c @var{char} | --commentchar @var{char} ]
+ [ -d | --debug ] [ -h | --help ] [ -M | --mri ]
+ [ -o @var{outfile} | --output @var{outfile} ]
+ [ -p | --print ] [ -s | --copysource ]
+ [ -u | --unreasonable ] [ -v | --version ]
+ @var{infile} @dots{}
+@end example
+
+@ftable @code
+@item @var{infile} @dots{}
+@c FIXME! Why not stdin as default infile?
+The input file names. You must specify at least one input file; if you
+specify more, @sc{gasp} preprocesses them all, concatenating the output
+in the order you list the @var{infile} arguments.
+
+Mark the end of each input file with the preprocessor command
+@code{.END}. @xref{Other Commands,, Miscellaneous commands}.
+
+@item -a
+@itemx --alternate
+Use alternative macro syntax. @xref{Alternate,, Alternate macro
+syntax}, for a discussion of how this syntax differs from the default
+@sc{gasp} syntax.
+
+@cindex comment character, changing
+@cindex semicolon, as comment
+@cindex exclamation mark, as comment
+@cindex shriek, as comment
+@cindex bang, as comment
+@cindex @code{!} default comment char
+@cindex @code{;} as comment char
+@item -c '@var{char}'
+@itemx --commentchar '@var{char}'
+Use @var{char} as the comment character. The default comment character
+is @samp{!}. For example, to use a semicolon as the comment character,
+specify @w{@samp{-c ';'}} on the @sc{gasp} command line. Since
+assembler command characters often have special significance to command
+shells, it is a good idea to quote or escape @var{char} when you specify
+a comment character.
+
+For the sake of simplicity, all examples in this manual use the default
+comment character @samp{!}.
+
+@item -d
+@itemx --debug
+Show debugging statistics. In this version of @sc{gasp}, this option
+produces statistics about the string buffers that @sc{gasp} allocates
+internally. For each defined buffersize @var{s}, @sc{gasp} shows the
+number of strings @var{n} that it allocated, with a line like this:
+
+@example
+strings size @var{s} : @var{n}
+@end example
+
+@noindent
+@sc{gasp} displays these statistics on the standard error stream, when
+done preprocessing.
+
+@item -h
+@itemx --help
+Display a summary of the @sc{gasp} command line options.
+
+@item -M
+@itemx --mri
+Use MRI compatibility mode. Using this option causes @sc{gasp} to
+accept the syntax and pseudo-ops used by the Microtec Research
+@code{ASM68K} assembler.
+
+@item -o @var{outfile}
+@itemx --output @var{outfile}
+Write the output in a file called @var{outfile}. If you do not use the
+@samp{-o} option, @sc{gasp} writes its output on the standard output
+stream.
+
+@item -p
+@itemx --print
+Print line numbers. @sc{gasp} obeys this option @emph{only} if you also
+specify @samp{-s} to copy source lines to its output. With @samp{-s
+-p}, @sc{gasp} displays the line number of each source line copied
+(immediately after the comment character at the beginning of the line).
+
+@item -s
+@itemx --copysource
+Copy the source lines to the output file. Use this option
+to see the effect of each preprocessor line on the @sc{gasp} output.
+@sc{gasp} places a comment character (@samp{!} by default) at
+the beginning of each source line it copies, so that you can use this
+option and still assemble the result.
+
+@item -u
+@itemx --unreasonable
+Bypass ``unreasonable expansion'' limit. Since you can define @sc{gasp}
+macros inside other macro definitions, the preprocessor normally
+includes a sanity check. If your program requires more than 1,000
+nested expansions, @sc{gasp} normally exits with an error message. Use
+this option to turn off this check, allowing unlimited nested
+expansions.
+
+@item -v
+@itemx --version
+Display the @sc{gasp} version number.
+@end ftable
+
+@node Commands
+@chapter Preprocessor Commands
+
+@sc{gasp} commands have a straightforward syntax that fits in well with
+assembly conventions. In general, a command extends for a line, and may
+have up to three fields: an optional label, the command itself, and
+optional arguments to the command. You can write commands in upper or
+lower case, though this manual shows them in upper case. @xref{Syntax
+Details,, Details of the GASP syntax}, for more information.
+
+@menu
+* Conditionals::
+* Loops::
+* Variables::
+* Macros::
+* Data::
+* Listings::
+* Other Commands::
+* Syntax Details::
+* Alternate::
+@end menu
+
+@node Conditionals
+@section Conditional assembly
+
+The conditional-assembly directives allow you to include or exclude
+portions of an assembly depending on how a pair of expressions, or a
+pair of strings, compare.
+
+The overall structure of conditionals is familiar from many other
+contexts. @code{.AIF} marks the start of a conditional, and precedes
+assembly for the case when the condition is true. An optional
+@code{.AELSE} precedes assembly for the converse case, and an
+@code{.AENDI} marks the end of the condition.
+
+@c FIXME! Why doesn't -u turn off this check?
+You may nest conditionals up to a depth of 100; @sc{gasp} rejects
+nesting beyond that, because it may indicate a bug in your macro
+structure.
+
+@c FIXME! Why isn't there something like cpp's -D option? Conditionals
+@c would be much more useful if there were.
+Conditionals are primarily useful inside macro definitions, where you
+often need different effects depending on argument values.
+@xref{Macros,, Defining your own directives}, for details about defining
+macros.
+
+@ftable @code
+@item .AIF @var{expra} @var{cmp} @var{exprb}
+@itemx .AIF "@var{stra}" @var{cmp} "@var{strb}"
+
+The governing condition goes on the same line as the @code{.AIF}
+preprocessor command. You may compare either two strings, or two
+expressions.
+
+When you compare strings, only two conditional @var{cmp} comparison
+operators are available: @samp{EQ} (true if @var{stra} and @var{strb}
+are identical), and @samp{NE} (the opposite).
+
+When you compare two expressions, @emph{both expressions must be
+absolute} (@pxref{Expressions,, Arithmetic expressions in GASP}). You
+can use these @var{cmp} comparison operators with expressions:
+
+@ftable @code
+@item EQ
+Are @var{expra} and @var{exprb} equal? (For strings, are @var{stra} and
+@var{strb} identical?)
+
+@item NE
+Are @var{expra} and @var{exprb} different? (For strings, are @var{stra}
+and @var{strb} different?
+
+@item LT
+Is @var{expra} less than @var{exprb}? (Not allowed for strings.)
+
+@item LE
+Is @var{expra} less than or equal to @var{exprb}? (Not allowed for strings.)
+
+@item GT
+Is @var{expra} greater than @var{exprb}? (Not allowed for strings.)
+
+@item GE
+Is @var{expra} greater than or equal to @var{exprb}? (Not allowed for
+strings.)
+@end ftable
+
+@item .AELSE
+Marks the start of assembly code to be included if the condition fails.
+Optional, and only allowed within a conditional (between @code{.AIF} and
+@code{.AENDI}).
+
+@item .AENDI
+Marks the end of a conditional assembly.
+@end ftable
+
+@node Loops
+@section Repetitive sections of assembly
+
+Two preprocessor directives allow you to repeatedly issue copies of the
+same block of assembly code.
+
+@ftable @code
+@item .AREPEAT @var{aexp}
+@itemx .AENDR
+If you simply need to repeat the same block of assembly over and over a
+fixed number of times, sandwich one instance of the repeated block
+between @code{.AREPEAT} and @code{.AENDR}. Specify the number of
+copies as @var{aexp} (which must be an absolute expression). For
+example, this repeats two assembly statements three times in succession:
+
+@cartouche
+@example
+ .AREPEAT 3
+ rotcl r2
+ div1 r0,r1
+ .AENDR
+@end example
+@end cartouche
+
+@item .AWHILE @var{expra} @var{cmp} @var{exprb}
+@itemx .AENDW
+@itemx .AWHILE @var{stra} @var{cmp} @var{strb}
+@itemx .AENDW
+To repeat a block of assembly depending on a conditional test, rather
+than repeating it for a specific number of times, use @code{.AWHILE}.
+@code{.AENDW} marks the end of the repeated block. The conditional
+comparison works exactly the same way as for @code{.AIF}, with the same
+comparison operators (@pxref{Conditionals,, Conditional assembly}).
+
+Since the terms of the comparison must be absolute expression,
+@code{.AWHILE} is primarily useful within macros. @xref{Macros,,
+Defining your own directives}.
+@end ftable
+
+@cindex loops, breaking out of
+@cindex breaking out of loops
+You can use the @code{.EXITM} preprocessor directive to break out of
+loops early (as well as to break out of macros). @xref{Macros,,
+Defining your own directives}.
+
+@node Variables
+@section Preprocessor variables
+
+You can use variables in @sc{gasp} to represent strings, registers, or
+the results of expressions.
+
+You must distinguish two kinds of variables:
+@enumerate
+@item
+Variables defined with @code{.EQU} or @code{.ASSIGN}. To evaluate this
+kind of variable in your assembly output, simply mention its name. For
+example, these two lines define and use a variable @samp{eg}:
+
+@cartouche
+@example
+eg .EQU FLIP-64
+ @dots{}
+ mov.l eg,r0
+@end example
+@end cartouche
+
+@emph{Do not use} this kind of variable in conditional expressions or
+while loops; @sc{gasp} only evaluates these variables when writing
+assembly output.
+
+@item
+Variables for use during preprocessing. You can define these
+with @code{.ASSIGNC} or @code{.ASSIGNA}. To evaluate this
+kind of variable, write @samp{\&} before the variable name; for example,
+
+@cartouche
+@example
+opcit .ASSIGNA 47
+ @dots{}
+ .AWHILE \&opcit GT 0
+ @dots{}
+ .AENDW
+@end example
+@end cartouche
+
+@sc{gasp} treats macro arguments almost the same way, but to evaluate
+them you use the prefix @samp{\} rather than @samp{\&}.
+@xref{Macros,, Defining your own directives}.
+@end enumerate
+
+@ftable @code
+@item @var{pvar} .EQU @var{expr}
+@c FIXME! Anything to beware of re GAS directive of same name?
+Assign preprocessor variable @var{pvar} the value of the expression
+@var{expr}. There are no restrictions on redefinition; use @samp{.EQU}
+with the same @var{pvar} as often as you find it convenient.
+
+@item @var{pvar} .ASSIGN @var{expr}
+Almost the same as @code{.EQU}, save that you may not redefine
+@var{pvar} using @code{.ASSIGN} once it has a value.
+@c FIXME!! Supposed to work this way, apparently, but on 9feb94 works
+@c just like .EQU
+
+@item @var{pvar} .ASSIGNA @var{aexpr}
+Define a variable with a numeric value, for use during preprocessing.
+@var{aexpr} must be an absolute expression. You can redefine variables
+with @code{.ASSIGNA} at any time.
+
+@item @var{pvar} .ASSIGNC "@var{str}"
+Define a variable with a string value, for use during preprocessing.
+You can redefine variables with @code{.ASSIGNC} at any time.
+
+@item @var{pvar} .REG (@var{register})
+Use @code{.REG} to define a variable that represents a register. In
+particular, @var{register} is @emph{not evaluated} as an expression.
+You may use @code{.REG} at will to redefine register variables.
+@end ftable
+
+All these directives accept the variable name in the ``label'' position,
+that is at the left margin. You may specify a colon after the variable
+name if you wish; the first example above could have started @samp{eg:}
+with the same effect.
+
+@c pagebreak makes for better aesthetics---ensures macro and expansion together
+@page
+@node Macros
+@section Defining your own directives
+
+The commands @code{.MACRO} and @code{.ENDM} allow you to define macros
+that generate assembly output. You can use these macros with a syntax
+similar to built-in @sc{gasp} or assembler directives. For example,
+this definition specifies a macro @code{SUM} that adds together a range of
+consecutive registers:
+
+@cartouche
+@example
+ .MACRO SUM FROM=0, TO=9
+ ! \FROM \TO
+ mov r\FROM,r10
+COUNT .ASSIGNA \FROM+1
+ .AWHILE \&COUNT LE \TO
+ add r\&COUNT,r10
+COUNT .ASSIGNA \&COUNT+1
+ .AENDW
+ .ENDM
+@end example
+@end cartouche
+
+@noindent
+With that definition, @samp{SUM 0,5} generates this assembly output:
+
+@cartouche
+@example
+ ! 0 5
+ mov r0,r10
+ add r1,r10
+ add r2,r10
+ add r3,r10
+ add r4,r10
+ add r5,r10
+@end example
+@end cartouche
+
+@ftable @code
+@item .MACRO @var{macname}
+@itemx .MACRO @var{macname} @var{macargs} @dots{}
+Begin the definition of a macro called @var{macname}. If your macro
+definition requires arguments, specify their names after the macro name,
+separated by commas or spaces. You can supply a default value for any
+macro argument by following the name with @samp{=@var{deflt}}. For
+example, these are all valid @code{.MACRO} statements:
+
+@table @code
+@item .MACRO COMM
+Begin the definition of a macro called @code{COMM}, which takes no
+arguments.
+
+@item .MACRO PLUS1 P, P1
+@itemx .MACRO PLUS1 P P1
+Either statement begins the definition of a macro called @code{PLUS1},
+which takes two arguments; within the macro definition, write
+@samp{\P} or @samp{\P1} to evaluate the arguments.
+
+@item .MACRO RESERVE_STR P1=0 P2
+Begin the definition of a macro called @code{RESERVE_STR}, with two
+arguments. The first argument has a default value, but not the second.
+After the definition is complete, you can call the macro either as
+@samp{RESERVE_STR @var{a},@var{b}} (with @samp{\P1} evaluating to
+@var{a} and @samp{\P2} evaluating to @var{b}), or as @samp{RESERVE_STR
+,@var{b}} (with @samp{\P1} evaluating as the default, in this case
+@samp{0}, and @samp{\P2} evaluating to @var{b}).
+@end table
+
+When you call a macro, you can specify the argument values either by
+position, or by keyword. For example, @samp{SUM 9,17} is equivalent to
+@samp{SUM TO=17, FROM=9}. Macro arguments are preprocessor variables
+similar to the variables you define with @samp{.ASSIGNA} or
+@samp{.ASSIGNC}; in particular, you can use them in conditionals or for
+loop control. (The only difference is the prefix you write to evaluate
+the variable: for a macro argument, write @samp{\@var{argname}}, but for
+a preprocessor variable, write @samp{\&@var{varname}}.)
+
+@item @var{name} .MACRO
+@itemx @var{name} .MACRO ( @var{macargs} @dots{} )
+@c FIXME check: I think no error _and_ no args recognized if I use form
+@c NAME .MACRO ARG ARG
+An alternative form of introducing a macro definition: specify the macro
+name in the label position, and the arguments (if any) between
+parentheses after the name. Defaulting rules and usage work the same
+way as for the other macro definition syntax.
+
+@item .ENDM
+Mark the end of a macro definition.
+
+@item .EXITM
+Exit early from the current macro definition, @code{.AREPEAT} loop, or
+@code{.AWHILE} loop.
+
+@cindex number of macros executed
+@cindex macros, count executed
+@item \@@
+@sc{gasp} maintains a counter of how many macros it has
+executed in this pseudo-variable; you can copy that number to your
+output with @samp{\@@}, but @emph{only within a macro definition}.
+
+@item LOCAL @var{name} [ , @dots{} ]
+@emph{Warning: @code{LOCAL} is only available if you select ``alternate
+macro syntax'' with @samp{-a} or @samp{--alternate}.} @xref{Alternate,,
+Alternate macro syntax}.
+
+Generate a string replacement for each of the @var{name} arguments, and
+replace any instances of @var{name} in each macro expansion. The
+replacement string is unique in the assembly, and different for each
+separate macro expansion. @code{LOCAL} allows you to write macros that
+define symbols, without fear of conflict between separate macro expansions.
+@end ftable
+
+@node Data
+@section Data output
+
+In assembly code, you often need to specify working areas of memory;
+depending on the application, you may want to initialize such memory or
+not. @sc{gasp} provides preprocessor directives to help you avoid
+repetitive coding for both purposes.
+
+You can use labels as usual to mark the data areas.
+
+@menu
+* Initialized::
+* Uninitialized::
+@end menu
+
+@node Initialized
+@subsection Initialized data
+
+These are the @sc{gasp} directives for initialized data, and the standard
+@sc{gnu} assembler directives they expand to:
+
+@ftable @code
+@item .DATA @var{expr}, @var{expr}, @dots{}
+@itemx .DATA.B @var{expr}, @var{expr}, @dots{}
+@itemx .DATA.W @var{expr}, @var{expr}, @dots{}
+@itemx .DATA.L @var{expr}, @var{expr}, @dots{}
+Evaluate arithmetic expressions @var{expr}, and emit the corresponding
+@code{as} directive (labelled with @var{lab}). The unqualified
+@code{.DATA} emits @samp{.long}; @code{.DATA.B} emits @samp{.byte};
+@code{.DATA.W} emits @samp{.short}; and @code{.DATA.L} emits
+@samp{.long}.
+
+For example, @samp{foo .DATA 1,2,3} emits @samp{foo: .long 1,2,3}.
+
+@item .DATAB @var{repeat}, @var{expr}
+@itemx .DATAB.B @var{repeat}, @var{expr}
+@itemx .DATAB.W @var{repeat}, @var{expr}
+@itemx .DATAB.L @var{repeat}, @var{expr}
+@c FIXME! Looks like gasp accepts and ignores args after 2nd.
+Make @code{as} emit @var{repeat} copies of the value of the expression
+@var{expr} (using the @code{as} directive @code{.fill}).
+@samp{.DATAB.B} repeats one-byte values; @samp{.DATAB.W} repeats
+two-byte values; and @samp{.DATAB.L} repeats four-byte values.
+@samp{.DATAB} without a suffix repeats four-byte values, just like
+@samp{.DATAB.L}.
+
+@c FIXME! Allowing zero might be useful for edge conditions in macros.
+@var{repeat} must be an absolute expression with a positive value.
+
+@item .SDATA "@var{str}" @dots{}
+String data. Emits a concatenation of bytes, precisely as you specify
+them (in particular, @emph{nothing is added to mark the end} of the
+string). @xref{Constants,, String and numeric constants}, for details
+about how to write strings. @code{.SDATA} concatenates multiple
+arguments, making it easy to switch between string representations. You
+can use commas to separate the individual arguments for clarity, if you
+choose.
+
+@item .SDATAB @var{repeat}, "@var{str}" @dots{}
+Repeated string data. The first argument specifies how many copies of
+the string to emit; the remaining arguments specify the string, in the
+same way as the arguments to @code{.SDATA}.
+
+@item .SDATAZ "@var{str}" @dots{}
+Zero-terminated string data. Just like @code{.SDATA}, except that
+@code{.SDATAZ} writes a zero byte at the end of the string.
+
+@item .SDATAC "@var{str}" @dots{}
+Count-prefixed string data. Just like @code{.SDATA}, except that
+@sc{gasp} precedes the string with a leading one-byte count. For
+example, @samp{.SDATAC "HI"} generates @samp{.byte 2,72,73}. Since the
+count field is only one byte, you can only use @code{.SDATAC} for
+strings less than 256 bytes in length.
+@end ftable
+
+@node Uninitialized
+@subsection Uninitialized data
+
+@c FIXME! .space different on some platforms, notably HPPA. Config?
+Use the @code{.RES}, @code{.SRES}, @code{.SRESC}, and @code{.SRESZ}
+directives to reserve memory and leave it uninitialized. @sc{gasp}
+resolves these directives to appropriate calls of the @sc{gnu}
+@code{as} @code{.space} directive.
+
+@ftable @code
+@item .RES @var{count}
+@itemx .RES.B @var{count}
+@itemx .RES.W @var{count}
+@itemx .RES.L @var{count}
+Reserve room for @var{count} uninitialized elements of data. The
+suffix specifies the size of each element: @code{.RES.B} reserves
+@var{count} bytes, @code{.RES.W} reserves @var{count} pairs of bytes,
+and @code{.RES.L} reserves @var{count} quartets. @code{.RES} without a
+suffix is equivalent to @code{.RES.L}.
+
+@item .SRES @var{count}
+@itemx .SRES.B @var{count}
+@itemx .SRES.W @var{count}
+@itemx .SRES.L @var{count}
+@c FIXME! This is boring. Shouldn't it at least have a different
+@c default size? (e.g. the "S" suggests "string", for which .B
+@c would be more appropriate)
+@code{.SRES} is a synonym for @samp{.RES}.
+
+@item .SRESC @var{count}
+@itemx .SRESC.B @var{count}
+@itemx .SRESC.W @var{count}
+@itemx .SRESC.L @var{count}
+Like @code{.SRES}, but reserves space for @code{@var{count}+1} elements.
+
+@item .SRESZ @var{count}
+@itemx .SRESZ.B @var{count}
+@itemx .SRESZ.W @var{count}
+@itemx .SRESZ.L @var{count}
+Like @code{.SRES}, but reserves space for @code{@var{count}+1} elements.
+@end ftable
+
+@node Listings
+@section Assembly listing control
+
+The @sc{gasp} listing-control directives correspond to
+related @sc{gnu} @code{as} directives.
+
+@ftable @code
+@item .PRINT LIST
+@itemx .PRINT NOLIST
+Print control. This directive emits the @sc{gnu} @code{as} directive
+@code{.list} or @code{.nolist}, according to its argument. @xref{List,,
+@code{.list}, as.info, Using as}, for details on how these directives
+interact.
+
+@item .FORM LIN=@var{ln}
+@itemx .FORM COL=@var{cols}
+@itemx .FORM LIN=@var{ln} COL=@var{cols}
+Specify the page size for assembly listings: @var{ln} represents the
+number of lines, and @var{cols} the number of columns. You may specify
+either page dimension independently, or both together. If you do not
+specify the number of lines, @sc{gasp} assumes 60 lines; if you do not
+specify the number of columns, @sc{gasp} assumes 132 columns.
+(Any values you may have specified in previous instances of @code{.FORM}
+do @emph{not} carry over as defaults.) Emits the @code{.psize}
+assembler directive.
+
+@item .HEADING @var{string}
+Specify @var{string} as the title of your assembly listings. Emits
+@samp{.title "@var{string}"}.
+
+@item .PAGE
+Force a new page in assembly listings. Emits @samp{.eject}.
+@end ftable
+
+@node Other Commands
+@section Miscellaneous commands
+
+@ftable @code
+@item .ALTERNATE
+Use the alternate macro syntax henceforth in the assembly.
+@xref{Alternate,, Alternate macro syntax}.
+
+@item .ORG
+@c FIXME! This is very strange, since _GAS_ understands .org
+This command is recognized, but not yet implemented. @sc{gasp}
+generates an error message for programs that use @code{.ORG}.
+
+@item .RADIX @var{s}
+@c FIXME no test cases in testsuite/gasp
+@sc{gasp} understands numbers in any of base two, eight, ten, or
+sixteen. You can encode the base explicitly in any numeric constant
+(@pxref{Constants,, String and numeric constants}). If you write
+numbers without an explicit indication of the base, the most recent
+@samp{.RADIX @var{s}} command determines how they are interpreted.
+@var{s} is a single letter, one of the following:
+
+@table @code
+@item .RADIX B
+Base 2.
+
+@item .RADIX Q
+Base 8.
+
+@item .RADIX D
+Base 10. This is the original default radix.
+
+@item .RADIX H
+Base 16.
+@end table
+
+You may specify the argument @var{s} in lower case (any of @samp{bqdh})
+with the same effects.
+
+@item .EXPORT @var{name}
+@itemx .GLOBAL @var{name}
+@c FIXME! No test cases in testsuite/gasp
+Declare @var{name} global (emits @samp{.global @var{name}}). The two
+directives are synonymous.
+
+@item .PROGRAM
+No effect: @sc{gasp} accepts this directive, and silently ignores it.
+
+@item .END
+Mark end of each preprocessor file. @sc{gasp} issues a warning if it
+reaches end of file without seeing this command.
+
+@item .INCLUDE "@var{str}"
+Preprocess the file named by @var{str}, as if its contents appeared
+where the @code{.INCLUDE} directive does. @sc{gasp} imposes a maximum
+limit of 30 stacked include files, as a sanity check.
+@c FIXME! Why is include depth not affected by -u?
+
+@item .ALIGN @var{size}
+@c FIXME! Why is this not utterly pointless?
+Evaluate the absolute expression @var{size}, and emit the assembly
+instruction @samp{.align @var{size}} using the result.
+@end ftable
+
+@node Syntax Details
+@section Details of the GASP syntax
+
+Since @sc{gasp} is meant to work with assembly code, its statement
+syntax has no surprises for the assembly programmer.
+
+@cindex whitespace
+@emph{Whitespace} (blanks or tabs; @emph{not} newline) is partially
+significant, in that it delimits up to three fields in a line. The
+amount of whitespace does not matter; you may line up fields in separate
+lines if you wish, but @sc{gasp} does not require that.
+
+@cindex fields of @sc{gasp} source line
+@cindex label field
+The @emph{first field}, an optional @dfn{label}, must be flush left in a
+line (with no leading whitespace) if it appears at all. You may use a
+colon after the label if you wish; @sc{gasp} neither requires the colon
+nor objects to it (but will not include it as part of the label name).
+
+@cindex directive field
+The @emph{second field}, which must appear after some whitespace,
+contains a @sc{gasp} or assembly @dfn{directive}.
+
+@cindex argument fields
+Any @emph{further fields} on a line are @dfn{arguments} to the
+directive; you can separate them from one another using either commas or
+whitespace.
+
+@menu
+* Markers::
+* Constants::
+* Symbols::
+* Expressions::
+* String Builtins::
+@end menu
+
+@node Markers
+@subsection Special syntactic markers
+
+@sc{gasp} recognizes a few special markers: to delimit comments, to
+continue a statement on the next line, to separate symbols from other
+characters, and to copy text to the output literally. (One other
+special marker, @samp{\@@}, works only within macro definitions;
+@pxref{Macros,, Defining your own directives}.)
+
+@cindex comments
+The trailing part of any @sc{gasp} source line may be a @dfn{comment}.
+A comment begins with the first unquoted comment character (@samp{!} by
+default), or an escaped or doubled comment character (@samp{\!} or
+@samp{!!} by default), and extends to the end of a line. You can
+specify what comment character to use with the @samp{-c} option
+(@pxref{Invoking GASP,, Command Line Options}). The two kinds of
+comment markers lead to slightly different treatment:
+
+@table @code
+@item !
+A single, un-escaped comment character generates an assembly comment in
+the @sc{gasp} output. @sc{gasp} evaluates any preprocessor variables
+(macro arguments, or variables defined with @code{.ASSIGNA} or
+@code{.ASSIGNC}) present. For example, a macro that begins like this
+
+@example
+ .MACRO SUM FROM=0, TO=9
+ ! \FROM \TO
+@end example
+
+@noindent
+issues as the first line of output a comment that records the
+values you used to call the macro.
+
+@c comments, preprocessor-only
+@c preprocessor-only comments
+@c GASP-only comments
+@item \!
+@itemx !!
+Either an escaped comment character, or a double comment character,
+marks a @sc{gasp} source comment. @sc{gasp} does not copy such comments
+to the assembly output.
+@end table
+
+@cindex continuation character
+@kindex +
+To @emph{continue a statement} on the next line of the file, begin the
+second line with the character @samp{+}.
+
+@cindex literal copy to output
+@cindex copying literally to output
+@cindex preprocessing, avoiding
+@cindex avoiding preprocessing
+Occasionally you may want to prevent @sc{gasp} from preprocessing some
+particular bit of text. To @emph{copy literally} from the @sc{gasp}
+source to its output, place @samp{\(} before the string to copy, and
+@samp{)} at the end. For example, write @samp{\(\!)} if you need the
+characters @samp{\!} in your assembly output.
+
+@cindex symbol separator
+@cindex text, separating from symbols
+@cindex symbols, separating from text
+To @emph{separate a preprocessor variable} from text to appear
+immediately after its value, write a single quote (@code{'}). For
+example, @samp{.SDATA "\P'1"} writes a string built by concatenating the
+value of @code{P} and the digit @samp{1}. (You cannot achieve this by
+writing just @samp{\P1}, since @samp{P1} is itself a valid name for a
+preprocessor variable.)
+
+@node Constants
+@subsection String and numeric constants
+
+There are two ways of writing @dfn{string constants} in @sc{gasp}: as
+literal text, and by numeric byte value. Specify a string literal
+between double quotes (@code{"@var{str}"}). Specify an individual
+numeric byte value as an absolute expression between angle brackets
+(@code{<@var{expr}>}. Directives that output strings allow you to
+specify any number of either kind of value, in whatever order is
+convenient, and concatenate the result. (Alternate syntax mode
+introduces a number of alternative string notations; @pxref{Alternate,,
+Alternate macro syntax}.)
+
+@c Details of numeric notation, e.g. base prefixes
+You can write @dfn{numeric constants} either in a specific base, or in
+whatever base is currently selected (either 10, or selected by the most
+recent @code{.RADIX}).
+
+To write a number in a @emph{specific base}, use the pattern
+@code{@var{s}'@var{ddd}}: a base specifier character @var{s}, followed
+by a single quote followed by digits @var{ddd}. The base specifier
+character matches those you can specify with @code{.RADIX}: @samp{B} for
+base 2, @samp{Q} for base 8, @samp{D} for base 10, and @samp{H} for base
+16. (You can write this character in lower case if you prefer.)
+
+@c FIXME! What are rules for recognizing number in deflt base? Whatever
+@c is left over after parsing other things??
+
+@node Symbols
+@subsection Symbols
+
+@sc{gasp} recognizes symbol names that start with any alphabetic character,
+@samp{_}, or @samp{$}, and continue with any of the same characters or
+with digits. Label names follow the same rules.
+
+@node Expressions
+@subsection Arithmetic expressions in GASP
+
+@cindex absolute expressions
+@cindex relocatable expressions
+There are two kinds of expressions, depending on their result:
+@dfn{absolute} expressions, which resolve to a constant (that is, they
+do not involve any values unknown to @sc{gasp}), and @dfn{relocatable}
+expressions, which must reduce to the form
+
+@example
+@var{addsym}+@var{const}-@var{subsym}
+@end example
+
+@noindent
+where @var{addsym} and @var{subsym} are assembly symbols of unknown
+value, and @var{const} is a constant.
+
+Arithmetic for @sc{gasp} expressions follows very similar rules to C.
+You can use parentheses to change precedence; otherwise, arithmetic
+primitives have decreasing precedence in the order of the following
+list.
+
+@enumerate
+@item
+Single-argument @code{+} (identity), @code{-} (arithmetic opposite), or
+@code{~} (bitwise negation). @emph{The argument must be an absolute
+expression.}
+
+@item
+@code{*} (multiplication) and @code{/} (division). @emph{Both arguments
+must be absolute expressions.}
+
+@item
+@code{+} (addition) and @code{-} (subtraction). @emph{At least one argument
+must be absolute.}
+@c FIXME! Actually, subtraction doesn't check for this.
+
+@item
+@code{&} (bitwise and). @emph{Both arguments must be absolute.}
+
+@item
+@c FIXME! I agree ~ is a better notation than ^ for xor, but is the
+@c improvement worth differing from C?
+@code{|} (bitwise or) and @code{~} (bitwise exclusive or; @code{^} in
+C). @emph{Both arguments must be absolute.}
+@end enumerate
+
+@node String Builtins
+@subsection String primitives
+
+You can use these primitives to manipulate strings (in the argument
+field of @sc{gasp} statements):
+
+@ftable @code
+@item .LEN("@var{str}")
+Calculate the length of string @code{"@var{str}"}, as an absolute
+expression. For example, @samp{.RES.B .LEN("sample")} reserves six
+bytes of memory.
+
+@item .INSTR("@var{string}", "@var{seg}", @var{ix})
+Search for the first occurrence of @var{seg} after position @var{ix} of
+@var{string}. For example, @samp{.INSTR("ABCDEFG", "CDE", 0)} evaluates
+to the absolute result @code{2}.
+
+The result is @code{-1} if @var{seg} does not occur in @var{string}
+after position @var{ix}.
+
+@item .SUBSTR("@var{string}",@var{start},@var{len})
+The substring of @var{string} beginning at byte number @var{start} and
+extending for @var{len} bytes.
+@end ftable
+
+@node Alternate
+@section Alternate macro syntax
+
+If you specify @samp{-a} or @samp{--alternate} on the @sc{gasp} command
+line, the preprocessor uses somewhat different syntax. This syntax is
+reminiscent of the syntax of Phar Lap macro assembler, but it
+is @emph{not} meant to be a full emulation of Phar Lap or similar
+assemblers. In particular, @sc{gasp} does not support directives such
+as @code{DB} and @code{IRP}, even in alternate syntax mode.
+
+In particular, @samp{-a} (or @samp{--alternate}) elicits these
+differences:
+
+@table @emph
+@item Preprocessor directives
+You can use @sc{gasp} preprocessor directives without a leading @samp{.}
+dot. For example, you can write @samp{SDATA} with the same effect as
+@samp{.SDATA}.
+
+@item LOCAL
+One additional directive, @code{LOCAL}, is available. @xref{Macros,,
+Defining your own directives}, for an explanation of how to use
+@code{LOCAL}.
+
+@need 2000
+@item String delimiters
+You can write strings delimited in these other ways besides
+@code{"@var{string}"}:
+
+@table @code
+@item '@var{string}'
+You can delimit strings with single-quote charaters.
+
+@item <@var{string}>
+You can delimit strings with matching angle brackets.
+@end table
+
+@item single-character string escape
+To include any single character literally in a string (even if the
+character would otherwise have some special meaning), you can prefix the
+character with @samp{!} (an exclamation mark). For example, you can
+write @samp{<4.3 !> 5.4!!>} to get the literal text @samp{4.3 > 5.4!}.
+
+@item Expression results as strings
+You can write @samp{%@var{expr}} to evaluate the expression @var{expr}
+and use the result as a string.
+@end table
+
+@node Index
+@unnumbered Index
+
+@printindex cp
+
+@contents
+@bye
diff --git a/gas/doc/h8.texi b/gas/doc/h8.texi
new file mode 100644
index 0000000000..0df17144bf
--- /dev/null
+++ b/gas/doc/h8.texi
@@ -0,0 +1,26 @@
+@clear ALL-ARCH
+@clear GENERIC
+@clear INTERNALS
+@clear MULTI-OBJ
+@clear AOUT
+@clear BOUT
+@set COFF
+@clear ELF
+@set Hitachi-all
+@set H8/300
+@set H8/500
+@set SH
+@clear DIFF-TBL-KLUGE
+@set IEEEFLOAT
+@clear W32
+@set W16
+@set SPECIAL-SYMS
+@set AS as
+@set GCC gcc
+@set LD ld
+@set TARGET H8/300 and H8/500
+@set TARGET H8/300, H8/500, and Hitachi SH
+@set OBJ-NAME COFF
+@c
+@clear have-stabs
+@set abnormal-separator
diff --git a/gas/doc/internals.texi b/gas/doc/internals.texi
new file mode 100644
index 0000000000..dd3b4ab15e
--- /dev/null
+++ b/gas/doc/internals.texi
@@ -0,0 +1,1557 @@
+\input texinfo
+@setfilename internals.info
+@node Top
+@top Assembler Internals
+@raisesections
+@cindex internals
+
+This chapter describes the internals of the assembler. It is incomplete, but
+it may help a bit.
+
+This chapter was last modified on $Date$. It is not updated regularly, and it
+may be out of date.
+
+@menu
+* GAS versions:: GAS versions
+* Data types:: Data types
+* GAS processing:: What GAS does when it runs
+* Porting GAS:: Porting GAS
+* Relaxation:: Relaxation
+* Broken words:: Broken words
+* Internal functions:: Internal functions
+* Test suite:: Test suite
+@end menu
+
+@node GAS versions
+@section GAS versions
+
+GAS has acquired layers of code over time. The original GAS only supported the
+a.out object file format, with three sections. Support for multiple sections
+has been added in two different ways.
+
+The preferred approach is to use the version of GAS created when the symbol
+@code{BFD_ASSEMBLER} is defined. The other versions of GAS are documented for
+historical purposes, and to help anybody who has to debug code written for
+them.
+
+The type @code{segT} is used to represent a section in code which must work
+with all versions of GAS.
+
+@menu
+* Original GAS:: Original GAS version
+* MANY_SEGMENTS:: MANY_SEGMENTS gas version
+* BFD_ASSEMBLER:: BFD_ASSEMBLER gas version
+@end menu
+
+@node Original GAS
+@subsection Original GAS
+
+The original GAS only supported the a.out object file format with three
+sections: @samp{.text}, @samp{.data}, and @samp{.bss}. This is the version of
+GAS that is compiled if neither @code{BFD_ASSEMBLER} nor @code{MANY_SEGMENTS}
+is defined. This version of GAS is still used for the m68k-aout target, and
+perhaps others.
+
+This version of GAS should not be used for any new development.
+
+There is still code that is specific to this version of GAS, notably in
+@file{write.c}. There is no way for this code to loop through all the
+sections; it simply looks at global variables like @code{text_frag_root} and
+@code{data_frag_root}.
+
+The type @code{segT} is an enum.
+
+@node MANY_SEGMENTS
+@subsection MANY_SEGMENTS gas version
+@cindex MANY_SEGMENTS
+
+The @code{MANY_SEGMENTS} version of gas is only used for COFF. It uses the BFD
+library, but it writes out all the data itself using @code{bfd_write}. This
+version of gas supports up to 40 normal sections. The section names are stored
+in the @code{seg_name} array. Other information is stored in the
+@code{segment_info} array.
+
+The type @code{segT} is an enum. Code that wants to examine all the sections
+can use a @code{segT} variable as loop index from @code{SEG_E0} up to but not
+including @code{SEG_UNKNOWN}.
+
+Most of the code specific to this version of GAS is in the file
+@file{config/obj-coff.c}, in the portion of that file that is compiled when
+@code{BFD_ASSEMBLER} is not defined.
+
+This version of GAS is still used for several COFF targets.
+
+@node BFD_ASSEMBLER
+@subsection BFD_ASSEMBLER gas version
+@cindex BFD_ASSEMBLER
+
+The preferred version of GAS is the @code{BFD_ASSEMBLER} version. In this
+version of GAS, the output file is a normal BFD, and the BFD routines are used
+to generate the output.
+
+@code{BFD_ASSEMBLER} will automatically be used for certain targets, including
+those that use the ELF, ECOFF, and SOM object file formats, and also all Alpha,
+MIPS, PowerPC, and SPARC targets. You can force the use of
+@code{BFD_ASSEMBLER} for other targets with the configure option
+@samp{--enable-bfd-assembler}; however, it has not been tested for many
+targets, and can not be assumed to work.
+
+@node Data types
+@section Data types
+@cindex internals, data types
+
+This section describes some fundamental GAS data types.
+
+@menu
+* Symbols:: The symbolS structure
+* Expressions:: The expressionS structure
+* Fixups:: The fixS structure
+* Frags:: The fragS structure
+@end menu
+
+@node Symbols
+@subsection Symbols
+@cindex internals, symbols
+@cindex symbols, internal
+@cindex symbolS structure
+
+The definition for @code{struct symbol}, also known as @code{symbolS}, is
+located in @file{struc-symbol.h}. Symbol structures contain the following
+fields:
+
+@table @code
+@item sy_value
+This is an @code{expressionS} that describes the value of the symbol. It might
+refer to one or more other symbols; if so, its true value may not be known
+until @code{resolve_symbol_value} is called in @code{write_object_file}.
+
+The expression is often simply a constant. Before @code{resolve_symbol_value}
+is called, the value is the offset from the frag (@pxref{Frags}). Afterward,
+the frag address has been added in.
+
+@item sy_resolved
+This field is non-zero if the symbol's value has been completely resolved. It
+is used during the final pass over the symbol table.
+
+@item sy_resolving
+This field is used to detect loops while resolving the symbol's value.
+
+@item sy_used_in_reloc
+This field is non-zero if the symbol is used by a relocation entry. If a local
+symbol is used in a relocation entry, it must be possible to redirect those
+relocations to other symbols, or this symbol cannot be removed from the final
+symbol list.
+
+@item sy_next
+@itemx sy_previous
+These pointers to other @code{symbolS} structures describe a singly or doubly
+linked list. (If @code{SYMBOLS_NEED_BACKPOINTERS} is not defined, the
+@code{sy_previous} field will be omitted; @code{SYMBOLS_NEED_BACKPOINTERS} is
+always defined if @code{BFD_ASSEMBLER}.) These fields should be accessed with
+the @code{symbol_next} and @code{symbol_previous} macros.
+
+@item sy_frag
+This points to the frag (@pxref{Frags}) that this symbol is attached to.
+
+@item sy_used
+Whether the symbol is used as an operand or in an expression. Note: Not all of
+the backends keep this information accurate; backends which use this bit are
+responsible for setting it when a symbol is used in backend routines.
+
+@item sy_mri_common
+Whether the symbol is an MRI common symbol created by the @code{COMMON}
+pseudo-op when assembling in MRI mode.
+
+@item bsym
+If @code{BFD_ASSEMBLER} is defined, this points to the BFD @code{asymbol} that
+will be used in writing the object file.
+
+@item sy_name_offset
+(Only used if @code{BFD_ASSEMBLER} is not defined.) This is the position of
+the symbol's name in the string table of the object file. On some formats,
+this will start at position 4, with position 0 reserved for unnamed symbols.
+This field is not used until @code{write_object_file} is called.
+
+@item sy_symbol
+(Only used if @code{BFD_ASSEMBLER} is not defined.) This is the
+format-specific symbol structure, as it would be written into the object file.
+
+@item sy_number
+(Only used if @code{BFD_ASSEMBLER} is not defined.) This is a 24-bit symbol
+number, for use in constructing relocation table entries.
+
+@item sy_obj
+This format-specific data is of type @code{OBJ_SYMFIELD_TYPE}. If no macro by
+that name is defined in @file{obj-format.h}, this field is not defined.
+
+@item sy_tc
+This processor-specific data is of type @code{TC_SYMFIELD_TYPE}. If no macro
+by that name is defined in @file{targ-cpu.h}, this field is not defined.
+
+@item TARGET_SYMBOL_FIELDS
+If this macro is defined, it defines additional fields in the symbol structure.
+This macro is obsolete, and should be replaced when possible by uses of
+@code{OBJ_SYMFIELD_TYPE} and @code{TC_SYMFIELD_TYPE}.
+@end table
+
+There are a number of access routines used to extract the fields of a
+@code{symbolS} structure. When possible, these routines should be used rather
+than referring to the fields directly. These routines will work for any GAS
+version.
+
+@table @code
+@item S_SET_VALUE
+@cindex S_SET_VALUE
+Set the symbol's value.
+
+@item S_GET_VALUE
+@cindex S_GET_VALUE
+Get the symbol's value. This will cause @code{resolve_symbol_value} to be
+called if necessary, so @code{S_GET_VALUE} should only be called when it is
+safe to resolve symbols (i.e., after the entire input file has been read and
+all symbols have been defined).
+
+@item S_SET_SEGMENT
+@cindex S_SET_SEGMENT
+Set the section of the symbol.
+
+@item S_GET_SEGMENT
+@cindex S_GET_SEGMENT
+Get the symbol's section.
+
+@item S_GET_NAME
+@cindex S_GET_NAME
+Get the name of the symbol.
+
+@item S_SET_NAME
+@cindex S_SET_NAME
+Set the name of the symbol.
+
+@item S_IS_EXTERNAL
+@cindex S_IS_EXTERNAL
+Return non-zero if the symbol is externally visible.
+
+@item S_IS_EXTERN
+@cindex S_IS_EXTERN
+A synonym for @code{S_IS_EXTERNAL}. Don't use it.
+
+@item S_IS_WEAK
+@cindex S_IS_WEAK
+Return non-zero if the symbol is weak.
+
+@item S_IS_COMMON
+@cindex S_IS_COMMON
+Return non-zero if this is a common symbol. Common symbols are sometimes
+represented as undefined symbols with a value, in which case this function will
+not be reliable.
+
+@item S_IS_DEFINED
+@cindex S_IS_DEFINED
+Return non-zero if this symbol is defined. This function is not reliable when
+called on a common symbol.
+
+@item S_IS_DEBUG
+@cindex S_IS_DEBUG
+Return non-zero if this is a debugging symbol.
+
+@item S_IS_LOCAL
+@cindex S_IS_LOCAL
+Return non-zero if this is a local assembler symbol which should not be
+included in the final symbol table. Note that this is not the opposite of
+@code{S_IS_EXTERNAL}. The @samp{-L} assembler option affects the return value
+of this function.
+
+@item S_SET_EXTERNAL
+@cindex S_SET_EXTERNAL
+Mark the symbol as externally visible.
+
+@item S_CLEAR_EXTERNAL
+@cindex S_CLEAR_EXTERNAL
+Mark the symbol as not externally visible.
+
+@item S_SET_WEAK
+@cindex S_SET_WEAK
+Mark the symbol as weak.
+
+@item S_GET_TYPE
+@item S_GET_DESC
+@item S_GET_OTHER
+@cindex S_GET_TYPE
+@cindex S_GET_DESC
+@cindex S_GET_OTHER
+Get the @code{type}, @code{desc}, and @code{other} fields of the symbol. These
+are only defined for object file formats for which they make sense (primarily
+a.out).
+
+@item S_SET_TYPE
+@item S_SET_DESC
+@item S_SET_OTHER
+@cindex S_SET_TYPE
+@cindex S_SET_DESC
+@cindex S_SET_OTHER
+Set the @code{type}, @code{desc}, and @code{other} fields of the symbol. These
+are only defined for object file formats for which they make sense (primarily
+a.out).
+
+@item S_GET_SIZE
+@cindex S_GET_SIZE
+Get the size of a symbol. This is only defined for object file formats for
+which it makes sense (primarily ELF).
+
+@item S_SET_SIZE
+@cindex S_SET_SIZE
+Set the size of a symbol. This is only defined for object file formats for
+which it makes sense (primarily ELF).
+@end table
+
+@node Expressions
+@subsection Expressions
+@cindex internals, expressions
+@cindex expressions, internal
+@cindex expressionS structure
+
+Expressions are stored in an @code{expressionS} structure. The structure is
+defined in @file{expr.h}.
+
+@cindex expression
+The macro @code{expression} will create an @code{expressionS} structure based
+on the text found at the global variable @code{input_line_pointer}.
+
+@cindex make_expr_symbol
+@cindex expr_symbol_where
+A single @code{expressionS} structure can represent a single operation.
+Complex expressions are formed by creating @dfn{expression symbols} and
+combining them in @code{expressionS} structures. An expression symbol is
+created by calling @code{make_expr_symbol}. An expression symbol should
+naturally never appear in a symbol table, and the implementation of
+@code{S_IS_LOCAL} (@pxref{Symbols}) reflects that. The function
+@code{expr_symbol_where} returns non-zero if a symbol is an expression symbol,
+and also returns the file and line for the expression which caused it to be
+created.
+
+The @code{expressionS} structure has two symbol fields, a number field, an
+operator field, and a field indicating whether the number is unsigned.
+
+The operator field is of type @code{operatorT}, and describes how to interpret
+the other fields; see the definition in @file{expr.h} for the possibilities.
+
+An @code{operatorT} value of @code{O_big} indicates either a floating point
+number, stored in the global variable @code{generic_floating_point_number}, or
+an integer to large to store in an @code{offsetT} type, stored in the global
+array @code{generic_bignum}. This rather inflexible approach makes it
+impossible to use floating point numbers or large expressions in complex
+expressions.
+
+@node Fixups
+@subsection Fixups
+@cindex internals, fixups
+@cindex fixups
+@cindex fixS structure
+
+A @dfn{fixup} is basically anything which can not be resolved in the first
+pass. Sometimes a fixup can be resolved by the end of the assembly; if not,
+the fixup becomes a relocation entry in the object file.
+
+@cindex fix_new
+@cindex fix_new_exp
+A fixup is created by a call to @code{fix_new} or @code{fix_new_exp}. Both
+take a frag (@pxref{Frags}), a position within the frag, a size, an indication
+of whether the fixup is PC relative, and a type. In a @code{BFD_ASSEMBLER}
+GAS, the type is nominally a @code{bfd_reloc_code_real_type}, but several
+targets use other type codes to represent fixups that can not be described as
+relocations.
+
+The @code{fixS} structure has a number of fields, several of which are obsolete
+or are only used by a particular target. The important fields are:
+
+@table @code
+@item fx_frag
+The frag (@pxref{Frags}) this fixup is in.
+
+@item fx_where
+The location within the frag where the fixup occurs.
+
+@item fx_addsy
+The symbol this fixup is against. Typically, the value of this symbol is added
+into the object contents. This may be NULL.
+
+@item fx_subsy
+The value of this symbol is subtracted from the object contents. This is
+normally NULL.
+
+@item fx_offset
+A number which is added into the fixup.
+
+@item fx_addnumber
+Some CPU backends use this field to convey information between
+@code{md_apply_fix} and @code{tc_gen_reloc}. The machine independent code does
+not use it.
+
+@item fx_next
+The next fixup in the section.
+
+@item fx_r_type
+The type of the fixup. This field is only defined if @code{BFD_ASSEMBLER}, or
+if the target defines @code{NEED_FX_R_TYPE}.
+
+@item fx_size
+The size of the fixup. This is mostly used for error checking.
+
+@item fx_pcrel
+Whether the fixup is PC relative.
+
+@item fx_done
+Non-zero if the fixup has been applied, and no relocation entry needs to be
+generated.
+
+@item fx_file
+@itemx fx_line
+The file and line where the fixup was created.
+
+@item tc_fix_data
+This has the type @code{TC_FIX_TYPE}, and is only defined if the target defines
+that macro.
+@end table
+
+@node Frags
+@subsection Frags
+@cindex internals, frags
+@cindex frags
+@cindex fragS structure.
+
+The @code{fragS} structure is defined in @file{as.h}. Each frag represents a
+portion of the final object file. As GAS reads the source file, it creates
+frags to hold the data that it reads. At the end of the assembly the frags and
+fixups are processed to produce the final contents.
+
+@table @code
+@item fr_address
+The address of the frag. This is not set until the assembler rescans the list
+of all frags after the entire input file is parsed. The function
+@code{relax_segment} fills in this field.
+
+@item fr_next
+Pointer to the next frag in this (sub)section.
+
+@item fr_fix
+Fixed number of characters we know we're going to emit to the output file. May
+be zero.
+
+@item fr_var
+Variable number of characters we may output, after the initial @code{fr_fix}
+characters. May be zero.
+
+@item fr_offset
+The interpretation of this field is controlled by @code{fr_type}. Generally,
+if @code{fr_var} is non-zero, this is a repeat count: the @code{fr_var}
+characters are output @code{fr_offset} times.
+
+@item line
+Holds line number info when an assembler listing was requested.
+
+@item fr_type
+Relaxation state. This field indicates the interpretation of @code{fr_offset},
+@code{fr_symbol} and the variable-length tail of the frag, as well as the
+treatment it gets in various phases of processing. It does not affect the
+initial @code{fr_fix} characters; they are always supposed to be output
+verbatim (fixups aside). See below for specific values this field can have.
+
+@item fr_subtype
+Relaxation substate. If the macro @code{md_relax_frag} isn't defined, this is
+assumed to be an index into @code{TC_GENERIC_RELAX_TABLE} for the generic
+relaxation code to process (@pxref{Relaxation}). If @code{md_relax_frag} is
+defined, this field is available for any use by the CPU-specific code.
+
+@item fr_symbol
+This normally indicates the symbol to use when relaxing the frag according to
+@code{fr_type}.
+
+@item fr_opcode
+Points to the lowest-addressed byte of the opcode, for use in relaxation.
+
+@item tc_frag_data
+Target specific fragment data of type TC_FRAG_TYPE.
+Only present if @code{TC_FRAG_TYPE} is defined.
+
+@item fr_file
+@itemx fr_line
+The file and line where this frag was last modified.
+
+@item fr_literal
+Declared as a one-character array, this last field grows arbitrarily large to
+hold the actual contents of the frag.
+@end table
+
+These are the possible relaxation states, provided in the enumeration type
+@code{relax_stateT}, and the interpretations they represent for the other
+fields:
+
+@table @code
+@item rs_align
+@itemx rs_align_code
+The start of the following frag should be aligned on some boundary. In this
+frag, @code{fr_offset} is the logarithm (base 2) of the alignment in bytes.
+(For example, if alignment on an 8-byte boundary were desired, @code{fr_offset}
+would have a value of 3.) The variable characters indicate the fill pattern to
+be used. The @code{fr_subtype} field holds the maximum number of bytes to skip
+when doing this alignment. If more bytes are needed, the alignment is not
+done. An @code{fr_subtype} value of 0 means no maximum, which is the normal
+case. Target backends can use @code{rs_align_code} to handle certain types of
+alignment differently.
+
+@item rs_broken_word
+This indicates that ``broken word'' processing should be done (@pxref{Broken
+words}). If broken word processing is not necessary on the target machine,
+this enumerator value will not be defined.
+
+@item rs_cfa
+This state is used to implement exception frame optimizations. The
+@code{fr_symbol} is an expression symbol for the subtraction which may be
+relaxed. The @code{fr_opcode} field holds the frag for the preceding command
+byte. The @code{fr_offset} field holds the offset within that frag. The
+@code{fr_subtype} field is used during relaxation to hold the current size of
+the frag.
+
+@item rs_fill
+The variable characters are to be repeated @code{fr_offset} times. If
+@code{fr_offset} is 0, this frag has a length of @code{fr_fix}. Most frags
+have this type.
+
+@item rs_leb128
+This state is used to implement the DWARF ``little endian base 128''
+variable length number format. The @code{fr_symbol} is always an expression
+symbol, as constant expressions are emitted directly. The @code{fr_offset}
+field is used during relaxation to hold the previous size of the number so
+that we can determine if the fragment changed size.
+
+@item rs_machine_dependent
+Displacement relaxation is to be done on this frag. The target is indicated by
+@code{fr_symbol} and @code{fr_offset}, and @code{fr_subtype} indicates the
+particular machine-specific addressing mode desired. @xref{Relaxation}.
+
+@item rs_org
+The start of the following frag should be pushed back to some specific offset
+within the section. (Some assemblers use the value as an absolute address; GAS
+does not handle final absolute addresses, but rather requires that the linker
+set them.) The offset is given by @code{fr_symbol} and @code{fr_offset}; one
+character from the variable-length tail is used as the fill character.
+@end table
+
+@cindex frchainS structure
+A chain of frags is built up for each subsection. The data structure
+describing a chain is called a @code{frchainS}, and contains the following
+fields:
+
+@table @code
+@item frch_root
+Points to the first frag in the chain. May be NULL if there are no frags in
+this chain.
+@item frch_last
+Points to the last frag in the chain, or NULL if there are none.
+@item frch_next
+Next in the list of @code{frchainS} structures.
+@item frch_seg
+Indicates the section this frag chain belongs to.
+@item frch_subseg
+Subsection (subsegment) number of this frag chain.
+@item fix_root, fix_tail
+(Defined only if @code{BFD_ASSEMBLER} is defined). Point to first and last
+@code{fixS} structures associated with this subsection.
+@item frch_obstack
+Not currently used. Intended to be used for frag allocation for this
+subsection. This should reduce frag generation caused by switching sections.
+@item frch_frag_now
+The current frag for this subsegment.
+@end table
+
+A @code{frchainS} corresponds to a subsection; each section has a list of
+@code{frchainS} records associated with it. In most cases, only one subsection
+of each section is used, so the list will only be one element long, but any
+processing of frag chains should be prepared to deal with multiple chains per
+section.
+
+After the input files have been completely processed, and no more frags are to
+be generated, the frag chains are joined into one per section for further
+processing. After this point, it is safe to operate on one chain per section.
+
+The assembler always has a current frag, named @code{frag_now}. More space is
+allocated for the current frag using the @code{frag_more} function; this
+returns a pointer to the amount of requested space. Relaxing is done using
+variant frags allocated by @code{frag_var} or @code{frag_variant}
+(@pxref{Relaxation}).
+
+@node GAS processing
+@section What GAS does when it runs
+@cindex internals, overview
+
+This is a quick look at what an assembler run looks like.
+
+@itemize @bullet
+@item
+The assembler initializes itself by calling various init routines.
+
+@item
+For each source file, the @code{read_a_source_file} function reads in the file
+and parses it. The global variable @code{input_line_pointer} points to the
+current text; it is guaranteed to be correct up to the end of the line, but not
+farther.
+
+@item
+For each line, the assembler passes labels to the @code{colon} function, and
+isolates the first word. If it looks like a pseudo-op, the word is looked up
+in the pseudo-op hash table @code{po_hash} and dispatched to a pseudo-op
+routine. Otherwise, the target dependent @code{md_assemble} routine is called
+to parse the instruction.
+
+@item
+When pseudo-ops or instructions output data, they add it to a frag, calling
+@code{frag_more} to get space to store it in.
+
+@item
+Pseudo-ops and instructions can also output fixups created by @code{fix_new} or
+@code{fix_new_exp}.
+
+@item
+For certain targets, instructions can create variant frags which are used to
+store relaxation information (@pxref{Relaxation}).
+
+@item
+When the input file is finished, the @code{write_object_file} routine is
+called. It assigns addresses to all the frags (@code{relax_segment}), resolves
+all the fixups (@code{fixup_segment}), resolves all the symbol values (using
+@code{resolve_symbol_value}), and finally writes out the file (in the
+@code{BFD_ASSEMBLER} case, this is done by simply calling @code{bfd_close}).
+@end itemize
+
+@node Porting GAS
+@section Porting GAS
+@cindex porting
+
+Each GAS target specifies two main things: the CPU file and the object format
+file. Two main switches in the @file{configure.in} file handle this. The
+first switches on CPU type to set the shell variable @code{cpu_type}. The
+second switches on the entire target to set the shell variable @code{fmt}.
+
+The configure script uses the value of @code{cpu_type} to select two files in
+the @file{config} directory: @file{tc-@var{CPU}.c} and @file{tc-@var{CPU}.h}.
+The configuration process will create a file named @file{targ-cpu.h} in the
+build directory which includes @file{tc-@var{CPU}.h}.
+
+The configure script also uses the value of @code{fmt} to select two files:
+@file{obj-@var{fmt}.c} and @file{obj-@var{fmt}.h}. The configuration process
+will create a file named @file{obj-format.h} in the build directory which
+includes @file{obj-@var{fmt}.h}.
+
+You can also set the emulation in the configure script by setting the @code{em}
+variable. Normally the default value of @samp{generic} is fine. The
+configuration process will create a file named @file{targ-env.h} in the build
+directory which includes @file{te-@var{em}.h}.
+
+Porting GAS to a new CPU requires writing the @file{tc-@var{CPU}} files.
+Porting GAS to a new object file format requires writing the
+@file{obj-@var{fmt}} files. There is sometimes some interaction between these
+two files, but it is normally minimal.
+
+The best approach is, of course, to copy existing files. The documentation
+below assumes that you are looking at existing files to see usage details.
+
+These interfaces have grown over time, and have never been carefully thought
+out or designed. Nothing about the interfaces described here is cast in stone.
+It is possible that they will change from one version of the assembler to the
+next. Also, new macros are added all the time as they are needed.
+
+@menu
+* CPU backend:: Writing a CPU backend
+* Object format backend:: Writing an object format backend
+* Emulations:: Writing emulation files
+@end menu
+
+@node CPU backend
+@subsection Writing a CPU backend
+@cindex CPU backend
+@cindex @file{tc-@var{CPU}}
+
+The CPU backend files are the heart of the assembler. They are the only parts
+of the assembler which actually know anything about the instruction set of the
+processor.
+
+You must define a reasonably small list of macros and functions in the CPU
+backend files. You may define a large number of additional macros in the CPU
+backend files, not all of which are documented here. You must, of course,
+define macros in the @file{.h} file, which is included by every assembler
+source file. You may define the functions as macros in the @file{.h} file, or
+as functions in the @file{.c} file.
+
+@table @code
+@item TC_@var{CPU}
+@cindex TC_@var{CPU}
+By convention, you should define this macro in the @file{.h} file. For
+example, @file{tc-m68k.h} defines @code{TC_M68K}. You might have to use this
+if it is necessary to add CPU specific code to the object format file.
+
+@item TARGET_FORMAT
+This macro is the BFD target name to use when creating the output file. This
+will normally depend upon the @code{OBJ_@var{FMT}} macro.
+
+@item TARGET_ARCH
+This macro is the BFD architecture to pass to @code{bfd_set_arch_mach}.
+
+@item TARGET_MACH
+This macro is the BFD machine number to pass to @code{bfd_set_arch_mach}. If
+it is not defined, GAS will use 0.
+
+@item TARGET_BYTES_BIG_ENDIAN
+You should define this macro to be non-zero if the target is big endian, and
+zero if the target is little endian.
+
+@item md_shortopts
+@itemx md_longopts
+@itemx md_longopts_size
+@itemx md_parse_option
+@itemx md_show_usage
+@cindex md_shortopts
+@cindex md_longopts
+@cindex md_longopts_size
+@cindex md_parse_option
+@cindex md_show_usage
+GAS uses these variables and functions during option processing.
+@code{md_shortopts} is a @code{const char *} which GAS adds to the machine
+independent string passed to @code{getopt}. @code{md_longopts} is a
+@code{struct option []} which GAS adds to the machine independent long options
+passed to @code{getopt}; you may use @code{OPTION_MD_BASE}, defined in
+@file{as.h}, as the start of a set of long option indices, if necessary.
+@code{md_longopts_size} is a @code{size_t} holding the size @code{md_longopts}.
+GAS will call @code{md_parse_option} whenever @code{getopt} returns an
+unrecognized code, presumably indicating a special code value which appears in
+@code{md_longopts}. GAS will call @code{md_show_usage} when a usage message is
+printed; it should print a description of the machine specific options.
+
+@item md_begin
+@cindex md_begin
+GAS will call this function at the start of the assembly, after the command
+line arguments have been parsed and all the machine independent initializations
+have been completed.
+
+@item md_cleanup
+@cindex md_cleanup
+If you define this macro, GAS will call it at the end of each input file.
+
+@item md_assemble
+@cindex md_assemble
+GAS will call this function for each input line which does not contain a
+pseudo-op. The argument is a null terminated string. The function should
+assemble the string as an instruction with operands. Normally
+@code{md_assemble} will do this by calling @code{frag_more} and writing out
+some bytes (@pxref{Frags}). @code{md_assemble} will call @code{fix_new} to
+create fixups as needed (@pxref{Fixups}). Targets which need to do special
+purpose relaxation will call @code{frag_var}.
+
+@item md_pseudo_table
+@cindex md_pseudo_table
+This is a const array of type @code{pseudo_typeS}. It is a mapping from
+pseudo-op names to functions. You should use this table to implement
+pseudo-ops which are specific to the CPU.
+
+@item tc_conditional_pseudoop
+@cindex tc_conditional_pseudoop
+If this macro is defined, GAS will call it with a @code{pseudo_typeS} argument.
+It should return non-zero if the pseudo-op is a conditional which controls
+whether code is assembled, such as @samp{.if}. GAS knows about the normal
+conditional pseudo-ops,and you should normally not have to define this macro.
+
+@item comment_chars
+@cindex comment_chars
+This is a null terminated @code{const char} array of characters which start a
+comment.
+
+@item tc_comment_chars
+@cindex tc_comment_chars
+If this macro is defined, GAS will use it instead of @code{comment_chars}.
+
+@item tc_symbol_chars
+@cindex tc_symbol_chars
+If this macro is defined, it is a pointer to a null terminated list of
+characters which may appear in an operand. GAS already assumes that all
+alphanumberic characters, and @samp{$}, @samp{.}, and @samp{_} may appear in an
+operand (see @samp{symbol_chars} in @file{app.c}). This macro may be defined
+to treat additional characters as appearing in an operand. This affects the
+way in which GAS removes whitespace before passing the string to
+@samp{md_assemble}.
+
+@item line_comment_chars
+@cindex line_comment_chars
+This is a null terminated @code{const char} array of characters which start a
+comment when they appear at the start of a line.
+
+@item line_separator_chars
+@cindex line_separator_chars
+This is a null terminated @code{const char} array of characters which separate
+lines (semicolon and newline are such characters by default, and need not be
+listed in this array).
+
+@item EXP_CHARS
+@cindex EXP_CHARS
+This is a null terminated @code{const char} array of characters which may be
+used as the exponent character in a floating point number. This is normally
+@code{"eE"}.
+
+@item FLT_CHARS
+@cindex FLT_CHARS
+This is a null terminated @code{const char} array of characters which may be
+used to indicate a floating point constant. A zero followed by one of these
+characters is assumed to be followed by a floating point number; thus they
+operate the way that @code{0x} is used to indicate a hexadecimal constant.
+Usually this includes @samp{r} and @samp{f}.
+
+@item LEX_AT
+@cindex LEX_AT
+You may define this macro to the lexical type of the @kbd{@}} character. The
+default is zero.
+
+Lexical types are a combination of @code{LEX_NAME} and @code{LEX_BEGIN_NAME},
+both defined in @file{read.h}. @code{LEX_NAME} indicates that the character
+may appear in a name. @code{LEX_BEGIN_NAME} indicates that the character may
+appear at the beginning of a nem.
+
+@item LEX_BR
+@cindex LEX_BR
+You may define this macro to the lexical type of the brace characters @kbd{@{},
+@kbd{@}}, @kbd{[}, and @kbd{]}. The default value is zero.
+
+@item LEX_PCT
+@cindex LEX_PCT
+You may define this macro to the lexical type of the @kbd{%} character. The
+default value is zero.
+
+@item LEX_QM
+@cindex LEX_QM
+You may define this macro to the lexical type of the @kbd{?} character. The
+default value it zero.
+
+@item LEX_DOLLAR
+@cindex LEX_DOLLAR
+You may define this macro to the lexical type of the @kbd{$} character. The
+default value is @code{LEX_NAME | LEX_BEGIN_NAME}.
+
+@item SINGLE_QUOTE_STRINGS
+@cindex SINGLE_QUOTE_STRINGS
+If you define this macro, GAS will treat single quotes as string delimiters.
+Normally only double quotes are accepted as string delimiters.
+
+@item NO_STRING_ESCAPES
+@cindex NO_STRING_ESCAPES
+If you define this macro, GAS will not permit escape sequences in a string.
+
+@item ONLY_STANDARD_ESCAPES
+@cindex ONLY_STANDARD_ESCAPES
+If you define this macro, GAS will warn about the use of nonstandard escape
+sequences in a string.
+
+@item md_start_line_hook
+@cindex md_start_line_hook
+If you define this macro, GAS will call it at the start of each line.
+
+@item LABELS_WITHOUT_COLONS
+@cindex LABELS_WITHOUT_COLONS
+If you define this macro, GAS will assume that any text at the start of a line
+is a label, even if it does not have a colon.
+
+@item TC_START_LABEL
+@cindex TC_START_LABEL
+You may define this macro to control what GAS considers to be a label. The
+default definition is to accept any name followed by a colon character.
+
+@item NO_PSEUDO_DOT
+@cindex NO_PSEUDO_DOT
+If you define this macro, GAS will not require pseudo-ops to start with a
+@kbd{.} character.
+
+@item TC_EQUAL_IN_INSN
+@cindex TC_EQUAL_IN_INSN
+If you define this macro, it should return nonzero if the instruction is
+permitted to contain an @kbd{=} character. GAS will use this to decide if a
+@kbd{=} is an assignment or an instruction.
+
+@item TC_EOL_IN_INSN
+@cindex TC_EOL_IN_INSN
+If you define this macro, it should return nonzero if the current input line
+pointer should be treated as the end of a line.
+
+@item md_parse_name
+@cindex md_parse_name
+If this macro is defined, GAS will call it for any symbol found in an
+expression. You can define this to handle special symbols in a special way.
+If a symbol always has a certain value, you should normally enter it in the
+symbol table, perhaps using @code{reg_section}.
+
+@item md_undefined_symbol
+@cindex md_undefined_symbol
+GAS will call this function when a symbol table lookup fails, before it
+creates a new symbol. Typically this would be used to supply symbols whose
+name or value changes dynamically, possibly in a context sensitive way.
+Predefined symbols with fixed values, such as register names or condition
+codes, are typically entered directly into the symbol table when @code{md_begin}
+is called.
+
+@item md_operand
+@cindex md_operand
+GAS will call this function for any expression that can not be recognized.
+When the function is called, @code{input_line_pointer} will point to the start
+of the expression.
+
+@item tc_unrecognized_line
+@cindex tc_unrecognized_line
+If you define this macro, GAS will call it when it finds a line that it can not
+parse.
+
+@item md_do_align
+@cindex md_do_align
+You may define this macro to handle an alignment directive. GAS will call it
+when the directive is seen in the input file. For example, the i386 backend
+uses this to generate efficient nop instructions of varying lengths, depending
+upon the number of bytes that the alignment will skip.
+
+@item HANDLE_ALIGN
+@cindex HANDLE_ALIGN
+You may define this macro to do special handling for an alignment directive.
+GAS will call it at the end of the assembly.
+
+@item md_flush_pending_output
+@cindex md_flush_pending_output
+If you define this macro, GAS will call it each time it skips any space because of a
+space filling or alignment or data allocation pseudo-op.
+
+@item TC_PARSE_CONS_EXPRESSION
+@cindex TC_PARSE_CONS_EXPRESSION
+You may define this macro to parse an expression used in a data allocation
+pseudo-op such as @code{.word}. You can use this to recognize relocation
+directives that may appear in such directives.
+
+@item BITFIELD_CONS_EXPRESSION
+@cindex BITFIELD_CONS_EXPRESSION
+If you define this macro, GAS will recognize bitfield instructions in data
+allocation pseudo-ops, as used on the i960.
+
+@item REPEAT_CONS_EXPRESSION
+@cindex REPEAT_CONS_EXPRESSION
+If you define this macro, GAS will recognize repeat counts in data allocation
+pseudo-ops, as used on the MIPS.
+
+@item md_cons_align
+@cindex md_cons_align
+You may define this macro to do any special alignment before a data allocation
+pseudo-op.
+
+@item TC_CONS_FIX_NEW
+@cindex TC_CONS_FIX_NEW
+You may define this macro to generate a fixup for a data allocation pseudo-op.
+
+@item TC_INIT_FIX_DATA (@var{fixp})
+@cindex TC_INIT_FIX_DATA
+A C statement to initialize the target specific fields of fixup @var{fixp}.
+These fields are defined with the @code{TC_FIX_TYPE} macro.
+
+@item TC_FIX_DATA_PRINT (@var{stream}, @var{fixp})
+@cindex TC_FIX_DATA_PRINT
+A C statement to output target specific debugging information for
+fixup @var{fixp} to @var{stream}. This macro is called by @code{print_fixup}.
+
+@item TC_FRAG_INIT (@var{fragp})
+@cindex TC_FRAG_INIT
+A C statement to initialize the target specific fields of frag @var{fragp}.
+These fields are defined with the @code{TC_FRAG_TYPE} macro.
+
+@item md_number_to_chars
+@cindex md_number_to_chars
+This should just call either @code{number_to_chars_bigendian} or
+@code{number_to_chars_littleendian}, whichever is appropriate. On targets like
+the MIPS which support options to change the endianness, which function to call
+is a runtime decision. On other targets, @code{md_number_to_chars} can be a
+simple macro.
+
+@item md_reloc_size
+@cindex md_reloc_size
+This variable is only used in the original version of gas (not
+@code{BFD_ASSEMBLER} and not @code{MANY_SEGMENTS}). It holds the size of a
+relocation entry.
+
+@item WORKING_DOT_WORD
+@itemx md_short_jump_size
+@itemx md_long_jump_size
+@itemx md_create_short_jump
+@itemx md_create_long_jump
+@cindex WORKING_DOT_WORD
+@cindex md_short_jump_size
+@cindex md_long_jump_size
+@cindex md_create_short_jump
+@cindex md_create_long_jump
+If @code{WORKING_DOT_WORD} is defined, GAS will not do broken word processing
+(@pxref{Broken words}). Otherwise, you should set @code{md_short_jump_size} to
+the size of a short jump (a jump that is just long enough to jump around a long
+jmp) and @code{md_long_jump_size} to the size of a long jump (a jump that can
+go anywhere in the function), You should define @code{md_create_short_jump} to
+create a short jump around a long jump, and define @code{md_create_long_jump}
+to create a long jump.
+
+@item md_estimate_size_before_relax
+@cindex md_estimate_size_before_relax
+This function returns an estimate of the size of a @code{rs_machine_dependent}
+frag before any relaxing is done. It may also create any necessary
+relocations.
+
+@item md_relax_frag
+@cindex md_relax_frag
+This macro may be defined to relax a frag. GAS will call this with the frag
+and the change in size of all previous frags; @code{md_relax_frag} should
+return the change in size of the frag. @xref{Relaxation}.
+
+@item TC_GENERIC_RELAX_TABLE
+@cindex TC_GENERIC_RELAX_TABLE
+If you do not define @code{md_relax_frag}, you may define
+@code{TC_GENERIC_RELAX_TABLE} as a table of @code{relax_typeS} structures. The
+machine independent code knows how to use such a table to relax PC relative
+references. See @file{tc-m68k.c} for an example. @xref{Relaxation}.
+
+@item md_prepare_relax_scan
+@cindex md_prepare_relax_scan
+If defined, it is a C statement that is invoked prior to scanning
+the relax table.
+
+@item LINKER_RELAXING_SHRINKS_ONLY
+@cindex LINKER_RELAXING_SHRINKS_ONLY
+If you define this macro, and the global variable @samp{linkrelax} is set
+(because of a command line option, or unconditionally in @code{md_begin}), a
+@samp{.align} directive will cause extra space to be allocated. The linker can
+then discard this space when relaxing the section.
+
+@item md_convert_frag
+@cindex md_convert_frag
+GAS will call this for each rs_machine_dependent fragment.
+The instruction is completed using the data from the relaxation pass.
+It may also create any necessary relocations.
+@xref{Relaxation}.
+
+@item md_apply_fix
+@cindex md_apply_fix
+GAS will call this for each fixup. It should store the correct value in the
+object file.
+
+@item TC_HANDLES_FX_DONE
+@cindex TC_HANDLES_FX_DONE
+If this macro is defined, it means that @code{md_apply_fix} correctly sets the
+@code{fx_done} field in the fixup.
+
+@item tc_gen_reloc
+@cindex tc_gen_reloc
+A @code{BFD_ASSEMBLER} GAS will call this to generate a reloc. GAS will pass
+the resulting reloc to @code{bfd_install_relocation}. This currently works
+poorly, as @code{bfd_install_relocation} often does the wrong thing, and
+instances of @code{tc_gen_reloc} have been written to work around the problems,
+which in turns makes it difficult to fix @code{bfd_install_relocation}.
+
+@item RELOC_EXPANSION_POSSIBLE
+@cindex RELOC_EXPANSION_POSSIBLE
+If you define this macro, it means that @code{tc_gen_reloc} may return multiple
+relocation entries for a single fixup. In this case, the return value of
+@code{tc_gen_reloc} is a pointer to a null terminated array.
+
+@item MAX_RELOC_EXPANSION
+@cindex MAX_RELOC_EXPANSION
+You must define this if @code{RELOC_EXPANSION_POSSIBLE} is defined; it
+indicates the largest number of relocs which @code{tc_gen_reloc} may return for
+a single fixup.
+
+@item tc_fix_adjustable
+@cindex tc_fix_adjustable
+You may define this macro to indicate whether a fixup against a locally defined
+symbol should be adjusted to be against the section symbol. It should return a
+non-zero value if the adjustment is acceptable.
+
+@item MD_PCREL_FROM_SECTION
+@cindex MD_PCREL_FROM_SECTION
+If you define this macro, it should return the offset between the address of a
+PC relative fixup and the position from which the PC relative adjustment should
+be made. On many processors, the base of a PC relative instruction is the next
+instruction, so this macro would return the length of an instruction.
+
+@item md_pcrel_from
+@cindex md_pcrel_from
+This is the default value of @code{MD_PCREL_FROM_SECTION}. The difference is
+that @code{md_pcrel_from} does not take a section argument.
+
+@item tc_frob_label
+@cindex tc_frob_label
+If you define this macro, GAS will call it each time a label is defined.
+
+@item md_section_align
+@cindex md_section_align
+GAS will call this function for each section at the end of the assembly, to
+permit the CPU backend to adjust the alignment of a section.
+
+@item tc_frob_section
+@cindex tc_frob_section
+If you define this macro, a @code{BFD_ASSEMBLER} GAS will call it for each
+section at the end of the assembly.
+
+@item tc_frob_file_before_adjust
+@cindex tc_frob_file_before_adjust
+If you define this macro, GAS will call it after the symbol values are
+resolved, but before the fixups have been changed from local symbols to section
+symbols.
+
+@item tc_frob_symbol
+@cindex tc_frob_symbol
+If you define this macro, GAS will call it for each symbol. You can indicate
+that the symbol should not be included in the object file by definining this
+macro to set its second argument to a non-zero value.
+
+@item tc_frob_file
+@cindex tc_frob_file
+If you define this macro, GAS will call it after the symbol table has been
+completed, but before the relocations have been generated.
+
+@item tc_frob_file_after_relocs
+If you define this macro, GAS will call it after the relocs have been
+generated.
+
+@item LISTING_HEADER
+A string to use on the header line of a listing. The default value is simply
+@code{"GAS LISTING"}.
+
+@item LISTING_WORD_SIZE
+The number of bytes to put into a word in a listing. This affects the way the
+bytes are clumped together in the listing. For example, a value of 2 might
+print @samp{1234 5678} where a value of 1 would print @samp{12 34 56 78}. The
+default value is 4.
+
+@item LISTING_LHS_WIDTH
+The number of words of data to print on the first line of a listing for a
+particular source line, where each word is @code{LISTING_WORD_SIZE} bytes. The
+default value is 1.
+
+@item LISTING_LHS_WIDTH_SECOND
+Like @code{LISTING_LHS_WIDTH}, but applying to the second and subsequent line
+of the data printed for a particular source line. The default value is 1.
+
+@item LISTING_LHS_CONT_LINES
+The maximum number of continuation lines to print in a listing for a particular
+source line. The default value is 4.
+
+@item LISTING_RHS_WIDTH
+The maximum number of characters to print from one line of the input file. The
+default value is 100.
+@end table
+
+@node Object format backend
+@subsection Writing an object format backend
+@cindex object format backend
+@cindex @file{obj-@var{fmt}}
+
+As with the CPU backend, the object format backend must define a few things,
+and may define some other things. The interface to the object format backend
+is generally simpler; most of the support for an object file format consists of
+defining a number of pseudo-ops.
+
+The object format @file{.h} file must include @file{targ-cpu.h}.
+
+This section will only define the @code{BFD_ASSEMBLER} version of GAS. It is
+impossible to support a new object file format using any other version anyhow,
+as the original GAS version only supports a.out, and the @code{MANY_SEGMENTS}
+GAS version only supports COFF.
+
+@table @code
+@item OBJ_@var{format}
+@cindex OBJ_@var{format}
+By convention, you should define this macro in the @file{.h} file. For
+example, @file{obj-elf.h} defines @code{OBJ_ELF}. You might have to use this
+if it is necessary to add object file format specific code to the CPU file.
+
+@item obj_begin
+If you define this macro, GAS will call it at the start of the assembly, after
+the command line arguments have been parsed and all the machine independent
+initializations have been completed.
+
+@item obj_app_file
+@cindex obj_app_file
+If you define this macro, GAS will invoke it when it sees a @code{.file}
+pseudo-op or a @samp{#} line as used by the C preprocessor.
+
+@item OBJ_COPY_SYMBOL_ATTRIBUTES
+@cindex OBJ_COPY_SYMBOL_ATTRIBUTES
+You should define this macro to copy object format specific information from
+one symbol to another. GAS will call it when one symbol is equated to
+another.
+
+@item obj_fix_adjustable
+@cindex obj_fix_adjustable
+You may define this macro to indicate whether a fixup against a locally defined
+symbol should be adjusted to be against the section symbol. It should return a
+non-zero value if the adjustment is acceptable.
+
+@item obj_sec_sym_ok_for_reloc
+@cindex obj_sec_sym_ok_for_reloc
+You may define this macro to indicate that it is OK to use a section symbol in
+a relocateion entry. If it is not, GAS will define a new symbol at the start
+of a section.
+
+@item EMIT_SECTION_SYMBOLS
+@cindex EMIT_SECTION_SYMBOLS
+You should define this macro with a zero value if you do not want to include
+section symbols in the output symbol table. The default value for this macro
+is one.
+
+@item obj_adjust_symtab
+@cindex obj_adjust_symtab
+If you define this macro, GAS will invoke it just before setting the symbol
+table of the output BFD. For example, the COFF support uses this macro to
+generate a @code{.file} symbol if none was generated previously.
+
+@item SEPARATE_STAB_SECTIONS
+@cindex SEPARATE_STAB_SECTIONS
+You may define this macro to indicate that stabs should be placed in separate
+sections, as in ELF.
+
+@item INIT_STAB_SECTION
+@cindex INIT_STAB_SECTION
+You may define this macro to initialize the stabs section in the output file.
+
+@item OBJ_PROCESS_STAB
+@cindex OBJ_PROCESS_STAB
+You may define this macro to do specific processing on a stabs entry.
+
+@item obj_frob_section
+@cindex obj_frob_section
+If you define this macro, GAS will call it for each section at the end of the
+assembly.
+
+@item obj_frob_file_before_adjust
+@cindex obj_frob_file_before_adjust
+If you define this macro, GAS will call it after the symbol values are
+resolved, but before the fixups have been changed from local symbols to section
+symbols.
+
+@item obj_frob_symbol
+@cindex obj_frob_symbol
+If you define this macro, GAS will call it for each symbol. You can indicate
+that the symbol should not be included in the object file by definining this
+macro to set its second argument to a non-zero value.
+
+@item obj_frob_file
+@cindex obj_frob_file
+If you define this macro, GAS will call it after the symbol table has been
+completed, but before the relocations have been generated.
+
+@item obj_frob_file_after_relocs
+If you define this macro, GAS will call it after the relocs have been
+generated.
+@end table
+
+@node Emulations
+@subsection Writing emulation files
+
+Normally you do not have to write an emulation file. You can just use
+@file{te-generic.h}.
+
+If you do write your own emulation file, it must include @file{obj-format.h}.
+
+An emulation file will often define @code{TE_@var{EM}}; this may then be used
+in other files to change the output.
+
+@node Relaxation
+@section Relaxation
+@cindex relaxation
+
+@dfn{Relaxation} is a generic term used when the size of some instruction or
+data depends upon the value of some symbol or other data.
+
+GAS knows to relax a particular type of PC relative relocation using a table.
+You can also define arbitrarily complex forms of relaxation yourself.
+
+@menu
+* Relaxing with a table:: Relaxing with a table
+* General relaxing:: General relaxing
+@end menu
+
+@node Relaxing with a table
+@subsection Relaxing with a table
+
+If you do not define @code{md_relax_frag}, and you do define
+@code{TC_GENERIC_RELAX_TABLE}, GAS will relax @code{rs_machine_dependent} frags
+based on the frag subtype and the displacement to some specified target
+address. The basic idea is that several machines have different addressing
+modes for instructions that can specify different ranges of values, with
+successive modes able to access wider ranges, including the entirety of the
+previous range. Smaller ranges are assumed to be more desirable (perhaps the
+instruction requires one word instead of two or three); if this is not the
+case, don't describe the smaller-range, inferior mode.
+
+The @code{fr_subtype} field of a frag is an index into a CPU-specific
+relaxation table. That table entry indicates the range of values that can be
+stored, the number of bytes that will have to be added to the frag to
+accomodate the addressing mode, and the index of the next entry to examine if
+the value to be stored is outside the range accessible by the current
+addressing mode. The @code{fr_symbol} field of the frag indicates what symbol
+is to be accessed; the @code{fr_offset} field is added in.
+
+If the @code{TC_PCREL_ADJUST} macro is defined, which currently should only happen
+for the NS32k family, the @code{TC_PCREL_ADJUST} macro is called on the frag to
+compute an adjustment to be made to the displacement.
+
+The value fitted by the relaxation code is always assumed to be a displacement
+from the current frag. (More specifically, from @code{fr_fix} bytes into the
+frag.)
+@ignore
+This seems kinda silly. What about fitting small absolute values? I suppose
+@code{md_assemble} is supposed to take care of that, but if the operand is a
+difference between symbols, it might not be able to, if the difference was not
+computable yet.
+@end ignore
+
+The end of the relaxation sequence is indicated by a ``next'' value of 0. This
+means that the first entry in the table can't be used.
+
+For some configurations, the linker can do relaxing within a section of an
+object file. If call instructions of various sizes exist, the linker can
+determine which should be used in each instance, when a symbol's value is
+resolved. In order for the linker to avoid wasting space and having to insert
+no-op instructions, it must be able to expand or shrink the section contents
+while still preserving intra-section references and meeting alignment
+requirements.
+
+For the i960 using b.out format, no expansion is done; instead, each
+@samp{.align} directive causes extra space to be allocated, enough that when
+the linker is relaxing a section and removing unneeded space, it can discard
+some or all of this extra padding and cause the following data to be correctly
+aligned.
+
+For the H8/300, I think the linker expands calls that can't reach, and doesn't
+worry about alignment issues; the cpu probably never needs any significant
+alignment beyond the instruction size.
+
+The relaxation table type contains these fields:
+
+@table @code
+@item long rlx_forward
+Forward reach, must be non-negative.
+@item long rlx_backward
+Backward reach, must be zero or negative.
+@item rlx_length
+Length in bytes of this addressing mode.
+@item rlx_more
+Index of the next-longer relax state, or zero if there is no next relax state.
+@end table
+
+The relaxation is done in @code{relax_segment} in @file{write.c}. The
+difference in the length fields between the original mode and the one finally
+chosen by the relaxing code is taken as the size by which the current frag will
+be increased in size. For example, if the initial relaxing mode has a length
+of 2 bytes, and because of the size of the displacement, it gets upgraded to a
+mode with a size of 6 bytes, it is assumed that the frag will grow by 4 bytes.
+(The initial two bytes should have been part of the fixed portion of the frag,
+since it is already known that they will be output.) This growth must be
+effected by @code{md_convert_frag}; it should increase the @code{fr_fix} field
+by the appropriate size, and fill in the appropriate bytes of the frag.
+(Enough space for the maximum growth should have been allocated in the call to
+frag_var as the second argument.)
+
+If relocation records are needed, they should be emitted by
+@code{md_estimate_size_before_relax}. This function should examine the target
+symbol of the supplied frag and correct the @code{fr_subtype} of the frag if
+needed. When this function is called, if the symbol has not yet been defined,
+it will not become defined later; however, its value may still change if the
+section it is in gets relaxed.
+
+Usually, if the symbol is in the same section as the frag (given by the
+@var{sec} argument), the narrowest likely relaxation mode is stored in
+@code{fr_subtype}, and that's that.
+
+If the symbol is undefined, or in a different section (and therefore moveable
+to an arbitrarily large distance), the largest available relaxation mode is
+specified, @code{fix_new} is called to produce the relocation record,
+@code{fr_fix} is increased to include the relocated field (remember, this
+storage was allocated when @code{frag_var} was called), and @code{frag_wane} is
+called to convert the frag to an @code{rs_fill} frag with no variant part.
+Sometimes changing addressing modes may also require rewriting the instruction.
+It can be accessed via @code{fr_opcode} or @code{fr_fix}.
+
+Sometimes @code{fr_var} is increased instead, and @code{frag_wane} is not
+called. I'm not sure, but I think this is to keep @code{fr_fix} referring to
+an earlier byte, and @code{fr_subtype} set to @code{rs_machine_dependent} so
+that @code{md_convert_frag} will get called.
+
+@node General relaxing
+@subsection General relaxing
+
+If using a simple table is not suitable, you may implement arbitrarily complex
+relaxation semantics yourself. For example, the MIPS backend uses this to emit
+different instruction sequences depending upon the size of the symbol being
+accessed.
+
+When you assemble an instruction that may need relaxation, you should allocate
+a frag using @code{frag_var} or @code{frag_variant} with a type of
+@code{rs_machine_dependent}. You should store some sort of information in the
+@code{fr_subtype} field so that you can figure out what to do with the frag
+later.
+
+When GAS reaches the end of the input file, it will look through the frags and
+work out their final sizes.
+
+GAS will first call @code{md_estimate_size_before_relax} on each
+@code{rs_machine_dependent} frag. This function must return an estimated size
+for the frag.
+
+GAS will then loop over the frags, calling @code{md_relax_frag} on each
+@code{rs_machine_dependent} frag. This function should return the change in
+size of the frag. GAS will keep looping over the frags until none of the frags
+changes size.
+
+@node Broken words
+@section Broken words
+@cindex internals, broken words
+@cindex broken words
+
+Some compilers, including GCC, will sometimes emit switch tables specifying
+16-bit @code{.word} displacements to branch targets, and branch instructions
+that load entries from that table to compute the target address. If this is
+done on a 32-bit machine, there is a chance (at least with really large
+functions) that the displacement will not fit in 16 bits. The assembler
+handles this using a concept called @dfn{broken words}. This idea is well
+named, since there is an implied promise that the 16-bit field will in fact
+hold the specified displacement.
+
+If broken word processing is enabled, and a situation like this is encountered,
+the assembler will insert a jump instruction into the instruction stream, close
+enough to be reached with the 16-bit displacement. This jump instruction will
+transfer to the real desired target address. Thus, as long as the @code{.word}
+value really is used as a displacement to compute an address to jump to, the
+net effect will be correct (minus a very small efficiency cost). If
+@code{.word} directives with label differences for values are used for other
+purposes, however, things may not work properly. For targets which use broken
+words, the @samp{-K} option will warn when a broken word is discovered.
+
+The broken word code is turned off by the @code{WORKING_DOT_WORD} macro. It
+isn't needed if @code{.word} emits a value large enough to contain an address
+(or, more correctly, any possible difference between two addresses).
+
+@node Internal functions
+@section Internal functions
+
+This section describes basic internal functions used by GAS.
+
+@menu
+* Warning and error messages:: Warning and error messages
+* Hash tables:: Hash tables
+@end menu
+
+@node Warning and error messages
+@subsection Warning and error messages
+
+@deftypefun @{@} int had_warnings (void)
+@deftypefunx @{@} int had_errors (void)
+Returns non-zero if any warnings or errors, respectively, have been printed
+during this invocation.
+@end deftypefun
+
+@deftypefun @{@} void as_perror (const char *@var{gripe}, const char *@var{filename})
+Displays a BFD or system error, then clears the error status.
+@end deftypefun
+
+@deftypefun @{@} void as_tsktsk (const char *@var{format}, ...)
+@deftypefunx @{@} void as_warn (const char *@var{format}, ...)
+@deftypefunx @{@} void as_bad (const char *@var{format}, ...)
+@deftypefunx @{@} void as_fatal (const char *@var{format}, ...)
+These functions display messages about something amiss with the input file, or
+internal problems in the assembler itself. The current file name and line
+number are printed, followed by the supplied message, formatted using
+@code{vfprintf}, and a final newline.
+
+An error indicated by @code{as_bad} will result in a non-zero exit status when
+the assembler has finished. Calling @code{as_fatal} will result in immediate
+termination of the assembler process.
+@end deftypefun
+
+@deftypefun @{@} void as_warn_where (char *@var{file}, unsigned int @var{line}, const char *@var{format}, ...)
+@deftypefunx @{@} void as_bad_where (char *@var{file}, unsigned int @var{line}, const char *@var{format}, ...)
+These variants permit specification of the file name and line number, and are
+used when problems are detected when reprocessing information saved away when
+processing some earlier part of the file. For example, fixups are processed
+after all input has been read, but messages about fixups should refer to the
+original filename and line number that they are applicable to.
+@end deftypefun
+
+@deftypefun @{@} void fprint_value (FILE *@var{file}, valueT @var{val})
+@deftypefunx @{@} void sprint_value (char *@var{buf}, valueT @var{val})
+These functions are helpful for converting a @code{valueT} value into printable
+format, in case it's wider than modes that @code{*printf} can handle. If the
+type is narrow enough, a decimal number will be produced; otherwise, it will be
+in hexadecimal. The value itself is not examined to make this determination.
+@end deftypefun
+
+@node Hash tables
+@subsection Hash tables
+@cindex hash tables
+
+@deftypefun @{@} @{struct hash_control *@} hash_new (void)
+Creates the hash table control structure.
+@end deftypefun
+
+@deftypefun @{@} void hash_die (struct hash_control *)
+Destroy a hash table.
+@end deftypefun
+
+@deftypefun @{@} PTR hash_delete (struct hash_control *, const char *)
+Deletes entry from the hash table, returns the value it had.
+@end deftypefun
+
+@deftypefun @{@} PTR hash_replace (struct hash_control *, const char *, PTR)
+Updates the value for an entry already in the table, returning the old value.
+If no entry was found, just returns NULL.
+@end deftypefun
+
+@deftypefun @{@} @{const char *@} hash_insert (struct hash_control *, const char *, PTR)
+Inserting a value already in the table is an error.
+Returns an error message or NULL.
+@end deftypefun
+
+@deftypefun @{@} @{const char *@} hash_jam (struct hash_control *, const char *, PTR)
+Inserts if the value isn't already present, updates it if it is.
+@end deftypefun
+
+@node Test suite
+@section Test suite
+@cindex test suite
+
+The test suite is kind of lame for most processors. Often it only checks to
+see if a couple of files can be assembled without the assembler reporting any
+errors. For more complete testing, write a test which either examines the
+assembler listing, or runs @code{objdump} and examines its output. For the
+latter, the TCL procedure @code{run_dump_test} may come in handy. It takes the
+base name of a file, and looks for @file{@var{file}.d}. This file should
+contain as its initial lines a set of variable settings in @samp{#} comments,
+in the form:
+
+@example
+ #@var{varname}: @var{value}
+@end example
+
+The @var{varname} may be @code{objdump}, @code{nm}, or @code{as}, in which case
+it specifies the options to be passed to the specified programs. Exactly one
+of @code{objdump} or @code{nm} must be specified, as that also specifies which
+program to run after the assembler has finished. If @var{varname} is
+@code{source}, it specifies the name of the source file; otherwise,
+@file{@var{file}.s} is used. If @var{varname} is @code{name}, it specifies the
+name of the test to be used in the @code{pass} or @code{fail} messages.
+
+The non-commented parts of the file are interpreted as regular expressions, one
+per line. Blank lines in the @code{objdump} or @code{nm} output are skipped,
+as are blank lines in the @code{.d} file; the other lines are tested to see if
+the regular expression matches the program output. If it does not, the test
+fails.
+
+Note that this means the tests must be modified if the @code{objdump} output
+style is changed.
+
+@bye
+@c Local Variables:
+@c fill-column: 79
+@c End:
diff --git a/gas/ecoff.c b/gas/ecoff.c
new file mode 100644
index 0000000000..c3c9375527
--- /dev/null
+++ b/gas/ecoff.c
@@ -0,0 +1,5308 @@
+/* ECOFF debugging support.
+ Copyright (C) 1993, 94, 95, 96, 97, 98 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+ This file was put together by Ian Lance Taylor <ian@cygnus.com>. A
+ good deal of it comes directly from mips-tfile.c, by Michael
+ Meissner <meissner@osf.org>.
+
+ This file is part of GAS.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include "as.h"
+
+/* This file is compiled conditionally for those targets which use
+ ECOFF debugging information (e.g., MIPS ECOFF, MIPS ELF, Alpha
+ ECOFF). */
+
+#ifdef ECOFF_DEBUGGING
+
+#include "coff/internal.h"
+#include "coff/symconst.h"
+#include "ecoff.h"
+#include "aout/stab_gnu.h"
+
+#include <ctype.h>
+
+/* Why isn't this in coff/sym.h? */
+#define ST_RFDESCAPE 0xfff
+
+/* This file constructs the information used by the ECOFF debugging
+ format. It just builds a large block of data.
+
+ We support both ECOFF style debugging and stabs debugging (the
+ stabs symbols are encapsulated in ECOFF symbols). This should let
+ us handle anything the compiler might throw at us. */
+
+/* Here is a brief description of the MIPS ECOFF symbol table, by
+ Michael Meissner. The MIPS symbol table has the following pieces:
+
+ Symbolic Header
+ |
+ +-- Auxiliary Symbols
+ |
+ +-- Dense number table
+ |
+ +-- Optimizer Symbols
+ |
+ +-- External Strings
+ |
+ +-- External Symbols
+ |
+ +-- Relative file descriptors
+ |
+ +-- File table
+ |
+ +-- Procedure table
+ |
+ +-- Line number table
+ |
+ +-- Local Strings
+ |
+ +-- Local Symbols
+
+ The symbolic header points to each of the other tables, and also
+ contains the number of entries. It also contains a magic number
+ and MIPS compiler version number, such as 2.0.
+
+ The auxiliary table is a series of 32 bit integers, that are
+ referenced as needed from the local symbol table. Unlike standard
+ COFF, the aux. information does not follow the symbol that uses
+ it, but rather is a separate table. In theory, this would allow
+ the MIPS compilers to collapse duplicate aux. entries, but I've not
+ noticed this happening with the 1.31 compiler suite. The different
+ types of aux. entries are:
+
+ 1) dnLow: Low bound on array dimension.
+
+ 2) dnHigh: High bound on array dimension.
+
+ 3) isym: Index to the local symbol which is the start of the
+ function for the end of function first aux. entry.
+
+ 4) width: Width of structures and bitfields.
+
+ 5) count: Count of ranges for variant part.
+
+ 6) rndx: A relative index into the symbol table. The relative
+ index field has two parts: rfd which is a pointer into the
+ relative file index table or ST_RFDESCAPE which says the next
+ aux. entry is the file number, and index: which is the pointer
+ into the local symbol within a given file table. This is for
+ things like references to types defined in another file.
+
+ 7) Type information: This is like the COFF type bits, except it
+ is 32 bits instead of 16; they still have room to add new
+ basic types; and they can handle more than 6 levels of array,
+ pointer, function, etc. Each type information field contains
+ the following structure members:
+
+ a) fBitfield: a bit that says this is a bitfield, and the
+ size in bits follows as the next aux. entry.
+
+ b) continued: a bit that says the next aux. entry is a
+ continuation of the current type information (in case
+ there are more than 6 levels of array/ptr/function).
+
+ c) bt: an integer containing the base type before adding
+ array, pointer, function, etc. qualifiers. The
+ current base types that I have documentation for are:
+
+ btNil -- undefined
+ btAdr -- address - integer same size as ptr
+ btChar -- character
+ btUChar -- unsigned character
+ btShort -- short
+ btUShort -- unsigned short
+ btInt -- int
+ btUInt -- unsigned int
+ btLong -- long
+ btULong -- unsigned long
+ btFloat -- float (real)
+ btDouble -- Double (real)
+ btStruct -- Structure (Record)
+ btUnion -- Union (variant)
+ btEnum -- Enumerated
+ btTypedef -- defined via a typedef isymRef
+ btRange -- subrange of int
+ btSet -- pascal sets
+ btComplex -- fortran complex
+ btDComplex -- fortran double complex
+ btIndirect -- forward or unnamed typedef
+ btFixedDec -- Fixed Decimal
+ btFloatDec -- Float Decimal
+ btString -- Varying Length Character String
+ btBit -- Aligned Bit String
+ btPicture -- Picture
+ btVoid -- Void (MIPS cc revision >= 2.00)
+
+ d) tq0 - tq5: type qualifier fields as needed. The
+ current type qualifier fields I have documentation for
+ are:
+
+ tqNil -- no more qualifiers
+ tqPtr -- pointer
+ tqProc -- procedure
+ tqArray -- array
+ tqFar -- 8086 far pointers
+ tqVol -- volatile
+
+
+ The dense number table is used in the front ends, and disappears by
+ the time the .o is created.
+
+ With the 1.31 compiler suite, the optimization symbols don't seem
+ to be used as far as I can tell.
+
+ The linker is the first entity that creates the relative file
+ descriptor table, and I believe it is used so that the individual
+ file table pointers don't have to be rewritten when the objects are
+ merged together into the program file.
+
+ Unlike COFF, the basic symbol & string tables are split into
+ external and local symbols/strings. The relocation information
+ only goes off of the external symbol table, and the debug
+ information only goes off of the internal symbol table. The
+ external symbols can have links to an appropriate file index and
+ symbol within the file to give it the appropriate type information.
+ Because of this, the external symbols are actually larger than the
+ internal symbols (to contain the link information), and contain the
+ local symbol structure as a member, though this member is not the
+ first member of the external symbol structure (!). I suspect this
+ split is to make strip easier to deal with.
+
+ Each file table has offsets for where the line numbers, local
+ strings, local symbols, and procedure table starts from within the
+ global tables, and the indexs are reset to 0 for each of those
+ tables for the file.
+
+ The procedure table contains the binary equivalents of the .ent
+ (start of the function address), .frame (what register is the
+ virtual frame pointer, constant offset from the register to obtain
+ the VFP, and what register holds the return address), .mask/.fmask
+ (bitmask of saved registers, and where the first register is stored
+ relative to the VFP) assembler directives. It also contains the
+ low and high bounds of the line numbers if debugging is turned on.
+
+ The line number table is a compressed form of the normal COFF line
+ table. Each line number entry is either 1 or 3 bytes long, and
+ contains a signed delta from the previous line, and an unsigned
+ count of the number of instructions this statement takes.
+
+ The local symbol table contains the following fields:
+
+ 1) iss: index to the local string table giving the name of the
+ symbol.
+
+ 2) value: value of the symbol (address, register number, etc.).
+
+ 3) st: symbol type. The current symbol types are:
+
+ stNil -- Nuthin' special
+ stGlobal -- external symbol
+ stStatic -- static
+ stParam -- procedure argument
+ stLocal -- local variable
+ stLabel -- label
+ stProc -- External Procedure
+ stBlock -- beginning of block
+ stEnd -- end (of anything)
+ stMember -- member (of anything)
+ stTypedef -- type definition
+ stFile -- file name
+ stRegReloc -- register relocation
+ stForward -- forwarding address
+ stStaticProc -- Static procedure
+ stConstant -- const
+
+ 4) sc: storage class. The current storage classes are:
+
+ scText -- text symbol
+ scData -- initialized data symbol
+ scBss -- un-initialized data symbol
+ scRegister -- value of symbol is register number
+ scAbs -- value of symbol is absolute
+ scUndefined -- who knows?
+ scCdbLocal -- variable's value is IN se->va.??
+ scBits -- this is a bit field
+ scCdbSystem -- value is IN debugger's address space
+ scRegImage -- register value saved on stack
+ scInfo -- symbol contains debugger information
+ scUserStruct -- addr in struct user for current process
+ scSData -- load time only small data
+ scSBss -- load time only small common
+ scRData -- load time only read only data
+ scVar -- Var parameter (fortranpascal)
+ scCommon -- common variable
+ scSCommon -- small common
+ scVarRegister -- Var parameter in a register
+ scVariant -- Variant record
+ scSUndefined -- small undefined(external) data
+ scInit -- .init section symbol
+
+ 5) index: pointer to a local symbol or aux. entry.
+
+
+
+ For the following program:
+
+ #include <stdio.h>
+
+ main(){
+ printf("Hello World!\n");
+ return 0;
+ }
+
+ Mips-tdump produces the following information:
+
+ Global file header:
+ magic number 0x162
+ # sections 2
+ timestamp 645311799, Wed Jun 13 17:16:39 1990
+ symbolic header offset 284
+ symbolic header size 96
+ optional header 56
+ flags 0x0
+
+ Symbolic header, magic number = 0x7009, vstamp = 1.31:
+
+ Info Offset Number Bytes
+ ==== ====== ====== =====
+
+ Line numbers 380 4 4 [13]
+ Dense numbers 0 0 0
+ Procedures Tables 384 1 52
+ Local Symbols 436 16 192
+ Optimization Symbols 0 0 0
+ Auxiliary Symbols 628 39 156
+ Local Strings 784 80 80
+ External Strings 864 144 144
+ File Tables 1008 2 144
+ Relative Files 0 0 0
+ External Symbols 1152 20 320
+
+ File #0, "hello2.c"
+
+ Name index = 1 Readin = No
+ Merge = No Endian = LITTLE
+ Debug level = G2 Language = C
+ Adr = 0x00000000
+
+ Info Start Number Size Offset
+ ==== ===== ====== ==== ======
+ Local strings 0 15 15 784
+ Local symbols 0 6 72 436
+ Line numbers 0 13 13 380
+ Optimization symbols 0 0 0 0
+ Procedures 0 1 52 384
+ Auxiliary symbols 0 14 56 628
+ Relative Files 0 0 0 0
+
+ There are 6 local symbols, starting at 436
+
+ Symbol# 0: "hello2.c"
+ End+1 symbol = 6
+ String index = 1
+ Storage class = Text Index = 6
+ Symbol type = File Value = 0
+
+ Symbol# 1: "main"
+ End+1 symbol = 5
+ Type = int
+ String index = 10
+ Storage class = Text Index = 12
+ Symbol type = Proc Value = 0
+
+ Symbol# 2: ""
+ End+1 symbol = 4
+ String index = 0
+ Storage class = Text Index = 4
+ Symbol type = Block Value = 8
+
+ Symbol# 3: ""
+ First symbol = 2
+ String index = 0
+ Storage class = Text Index = 2
+ Symbol type = End Value = 28
+
+ Symbol# 4: "main"
+ First symbol = 1
+ String index = 10
+ Storage class = Text Index = 1
+ Symbol type = End Value = 52
+
+ Symbol# 5: "hello2.c"
+ First symbol = 0
+ String index = 1
+ Storage class = Text Index = 0
+ Symbol type = End Value = 0
+
+ There are 14 auxiliary table entries, starting at 628.
+
+ * #0 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
+ * #1 24, [ 24/ 0], [ 6 0:0 0:0:0:0:0:0]
+ * #2 8, [ 8/ 0], [ 2 0:0 0:0:0:0:0:0]
+ * #3 16, [ 16/ 0], [ 4 0:0 0:0:0:0:0:0]
+ * #4 24, [ 24/ 0], [ 6 0:0 0:0:0:0:0:0]
+ * #5 32, [ 32/ 0], [ 8 0:0 0:0:0:0:0:0]
+ * #6 40, [ 40/ 0], [10 0:0 0:0:0:0:0:0]
+ * #7 44, [ 44/ 0], [11 0:0 0:0:0:0:0:0]
+ * #8 12, [ 12/ 0], [ 3 0:0 0:0:0:0:0:0]
+ * #9 20, [ 20/ 0], [ 5 0:0 0:0:0:0:0:0]
+ * #10 28, [ 28/ 0], [ 7 0:0 0:0:0:0:0:0]
+ * #11 36, [ 36/ 0], [ 9 0:0 0:0:0:0:0:0]
+ #12 5, [ 5/ 0], [ 1 1:0 0:0:0:0:0:0]
+ #13 24, [ 24/ 0], [ 6 0:0 0:0:0:0:0:0]
+
+ There are 1 procedure descriptor entries, starting at 0.
+
+ Procedure descriptor 0:
+ Name index = 10 Name = "main"
+ .mask 0x80000000,-4 .fmask 0x00000000,0
+ .frame $29,24,$31
+ Opt. start = -1 Symbols start = 1
+ First line # = 3 Last line # = 6
+ Line Offset = 0 Address = 0x00000000
+
+ There are 4 bytes holding line numbers, starting at 380.
+ Line 3, delta 0, count 2
+ Line 4, delta 1, count 3
+ Line 5, delta 1, count 2
+ Line 6, delta 1, count 6
+
+ File #1, "/usr/include/stdio.h"
+
+ Name index = 1 Readin = No
+ Merge = Yes Endian = LITTLE
+ Debug level = G2 Language = C
+ Adr = 0x00000000
+
+ Info Start Number Size Offset
+ ==== ===== ====== ==== ======
+ Local strings 15 65 65 799
+ Local symbols 6 10 120 508
+ Line numbers 0 0 0 380
+ Optimization symbols 0 0 0 0
+ Procedures 1 0 0 436
+ Auxiliary symbols 14 25 100 684
+ Relative Files 0 0 0 0
+
+ There are 10 local symbols, starting at 442
+
+ Symbol# 0: "/usr/include/stdio.h"
+ End+1 symbol = 10
+ String index = 1
+ Storage class = Text Index = 10
+ Symbol type = File Value = 0
+
+ Symbol# 1: "_iobuf"
+ End+1 symbol = 9
+ String index = 22
+ Storage class = Info Index = 9
+ Symbol type = Block Value = 20
+
+ Symbol# 2: "_cnt"
+ Type = int
+ String index = 29
+ Storage class = Info Index = 4
+ Symbol type = Member Value = 0
+
+ Symbol# 3: "_ptr"
+ Type = ptr to char
+ String index = 34
+ Storage class = Info Index = 15
+ Symbol type = Member Value = 32
+
+ Symbol# 4: "_base"
+ Type = ptr to char
+ String index = 39
+ Storage class = Info Index = 16
+ Symbol type = Member Value = 64
+
+ Symbol# 5: "_bufsiz"
+ Type = int
+ String index = 45
+ Storage class = Info Index = 4
+ Symbol type = Member Value = 96
+
+ Symbol# 6: "_flag"
+ Type = short
+ String index = 53
+ Storage class = Info Index = 3
+ Symbol type = Member Value = 128
+
+ Symbol# 7: "_file"
+ Type = char
+ String index = 59
+ Storage class = Info Index = 2
+ Symbol type = Member Value = 144
+
+ Symbol# 8: ""
+ First symbol = 1
+ String index = 0
+ Storage class = Info Index = 1
+ Symbol type = End Value = 0
+
+ Symbol# 9: "/usr/include/stdio.h"
+ First symbol = 0
+ String index = 1
+ Storage class = Text Index = 0
+ Symbol type = End Value = 0
+
+ There are 25 auxiliary table entries, starting at 642.
+
+ * #14 -1, [4095/1048575], [63 1:1 f:f:f:f:f:f]
+ #15 65544, [ 8/ 16], [ 2 0:0 1:0:0:0:0:0]
+ #16 65544, [ 8/ 16], [ 2 0:0 1:0:0:0:0:0]
+ * #17 196656, [ 48/ 48], [12 0:0 3:0:0:0:0:0]
+ * #18 8191, [4095/ 1], [63 1:1 0:0:0:0:f:1]
+ * #19 1, [ 1/ 0], [ 0 1:0 0:0:0:0:0:0]
+ * #20 20479, [4095/ 4], [63 1:1 0:0:0:0:f:4]
+ * #21 1, [ 1/ 0], [ 0 1:0 0:0:0:0:0:0]
+ * #22 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
+ * #23 2, [ 2/ 0], [ 0 0:1 0:0:0:0:0:0]
+ * #24 160, [ 160/ 0], [40 0:0 0:0:0:0:0:0]
+ * #25 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
+ * #26 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
+ * #27 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
+ * #28 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
+ * #29 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
+ * #30 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
+ * #31 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
+ * #32 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
+ * #33 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
+ * #34 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
+ * #35 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
+ * #36 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
+ * #37 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
+ * #38 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
+
+ There are 0 procedure descriptor entries, starting at 1.
+
+ There are 20 external symbols, starting at 1152
+
+ Symbol# 0: "_iob"
+ Type = array [3 {160}] of struct _iobuf { ifd = 1, index = 1 }
+ String index = 0 Ifd = 1
+ Storage class = Nil Index = 17
+ Symbol type = Global Value = 60
+
+ Symbol# 1: "fopen"
+ String index = 5 Ifd = 1
+ Storage class = Nil Index = 1048575
+ Symbol type = Proc Value = 0
+
+ Symbol# 2: "fdopen"
+ String index = 11 Ifd = 1
+ Storage class = Nil Index = 1048575
+ Symbol type = Proc Value = 0
+
+ Symbol# 3: "freopen"
+ String index = 18 Ifd = 1
+ Storage class = Nil Index = 1048575
+ Symbol type = Proc Value = 0
+
+ Symbol# 4: "popen"
+ String index = 26 Ifd = 1
+ Storage class = Nil Index = 1048575
+ Symbol type = Proc Value = 0
+
+ Symbol# 5: "tmpfile"
+ String index = 32 Ifd = 1
+ Storage class = Nil Index = 1048575
+ Symbol type = Proc Value = 0
+
+ Symbol# 6: "ftell"
+ String index = 40 Ifd = 1
+ Storage class = Nil Index = 1048575
+ Symbol type = Proc Value = 0
+
+ Symbol# 7: "rewind"
+ String index = 46 Ifd = 1
+ Storage class = Nil Index = 1048575
+ Symbol type = Proc Value = 0
+
+ Symbol# 8: "setbuf"
+ String index = 53 Ifd = 1
+ Storage class = Nil Index = 1048575
+ Symbol type = Proc Value = 0
+
+ Symbol# 9: "setbuffer"
+ String index = 60 Ifd = 1
+ Storage class = Nil Index = 1048575
+ Symbol type = Proc Value = 0
+
+ Symbol# 10: "setlinebuf"
+ String index = 70 Ifd = 1
+ Storage class = Nil Index = 1048575
+ Symbol type = Proc Value = 0
+
+ Symbol# 11: "fgets"
+ String index = 81 Ifd = 1
+ Storage class = Nil Index = 1048575
+ Symbol type = Proc Value = 0
+
+ Symbol# 12: "gets"
+ String index = 87 Ifd = 1
+ Storage class = Nil Index = 1048575
+ Symbol type = Proc Value = 0
+
+ Symbol# 13: "ctermid"
+ String index = 92 Ifd = 1
+ Storage class = Nil Index = 1048575
+ Symbol type = Proc Value = 0
+
+ Symbol# 14: "cuserid"
+ String index = 100 Ifd = 1
+ Storage class = Nil Index = 1048575
+ Symbol type = Proc Value = 0
+
+ Symbol# 15: "tempnam"
+ String index = 108 Ifd = 1
+ Storage class = Nil Index = 1048575
+ Symbol type = Proc Value = 0
+
+ Symbol# 16: "tmpnam"
+ String index = 116 Ifd = 1
+ Storage class = Nil Index = 1048575
+ Symbol type = Proc Value = 0
+
+ Symbol# 17: "sprintf"
+ String index = 123 Ifd = 1
+ Storage class = Nil Index = 1048575
+ Symbol type = Proc Value = 0
+
+ Symbol# 18: "main"
+ Type = int
+ String index = 131 Ifd = 0
+ Storage class = Text Index = 1
+ Symbol type = Proc Value = 0
+
+ Symbol# 19: "printf"
+ String index = 136 Ifd = 0
+ Storage class = Undefined Index = 1048575
+ Symbol type = Proc Value = 0
+
+ The following auxiliary table entries were unused:
+
+ #0 0 0x00000000 void
+ #2 8 0x00000008 char
+ #3 16 0x00000010 short
+ #4 24 0x00000018 int
+ #5 32 0x00000020 long
+ #6 40 0x00000028 float
+ #7 44 0x0000002c double
+ #8 12 0x0000000c unsigned char
+ #9 20 0x00000014 unsigned short
+ #10 28 0x0000001c unsigned int
+ #11 36 0x00000024 unsigned long
+ #14 0 0x00000000 void
+ #15 24 0x00000018 int
+ #19 32 0x00000020 long
+ #20 40 0x00000028 float
+ #21 44 0x0000002c double
+ #22 12 0x0000000c unsigned char
+ #23 20 0x00000014 unsigned short
+ #24 28 0x0000001c unsigned int
+ #25 36 0x00000024 unsigned long
+ #26 48 0x00000030 struct no name { ifd = -1, index = 1048575 }
+*/
+
+/* Redefinition of of storage classes as an enumeration for better
+ debugging. */
+
+typedef enum sc {
+ sc_Nil = scNil, /* no storage class */
+ sc_Text = scText, /* text symbol */
+ sc_Data = scData, /* initialized data symbol */
+ sc_Bss = scBss, /* un-initialized data symbol */
+ sc_Register = scRegister, /* value of symbol is register number */
+ sc_Abs = scAbs, /* value of symbol is absolute */
+ sc_Undefined = scUndefined, /* who knows? */
+ sc_CdbLocal = scCdbLocal, /* variable's value is IN se->va.?? */
+ sc_Bits = scBits, /* this is a bit field */
+ sc_CdbSystem = scCdbSystem, /* value is IN CDB's address space */
+ sc_RegImage = scRegImage, /* register value saved on stack */
+ sc_Info = scInfo, /* symbol contains debugger information */
+ sc_UserStruct = scUserStruct, /* addr in struct user for current process */
+ sc_SData = scSData, /* load time only small data */
+ sc_SBss = scSBss, /* load time only small common */
+ sc_RData = scRData, /* load time only read only data */
+ sc_Var = scVar, /* Var parameter (fortran,pascal) */
+ sc_Common = scCommon, /* common variable */
+ sc_SCommon = scSCommon, /* small common */
+ sc_VarRegister = scVarRegister, /* Var parameter in a register */
+ sc_Variant = scVariant, /* Variant record */
+ sc_SUndefined = scSUndefined, /* small undefined(external) data */
+ sc_Init = scInit, /* .init section symbol */
+ sc_Max = scMax /* Max storage class+1 */
+} sc_t;
+
+/* Redefinition of symbol type. */
+
+typedef enum st {
+ st_Nil = stNil, /* Nuthin' special */
+ st_Global = stGlobal, /* external symbol */
+ st_Static = stStatic, /* static */
+ st_Param = stParam, /* procedure argument */
+ st_Local = stLocal, /* local variable */
+ st_Label = stLabel, /* label */
+ st_Proc = stProc, /* " " Procedure */
+ st_Block = stBlock, /* beginning of block */
+ st_End = stEnd, /* end (of anything) */
+ st_Member = stMember, /* member (of anything - struct/union/enum */
+ st_Typedef = stTypedef, /* type definition */
+ st_File = stFile, /* file name */
+ st_RegReloc = stRegReloc, /* register relocation */
+ st_Forward = stForward, /* forwarding address */
+ st_StaticProc = stStaticProc, /* load time only static procs */
+ st_Constant = stConstant, /* const */
+ st_Str = stStr, /* string */
+ st_Number = stNumber, /* pure number (ie. 4 NOR 2+2) */
+ st_Expr = stExpr, /* 2+2 vs. 4 */
+ st_Type = stType, /* post-coercion SER */
+ st_Max = stMax /* max type+1 */
+} st_t;
+
+/* Redefinition of type qualifiers. */
+
+typedef enum tq {
+ tq_Nil = tqNil, /* bt is what you see */
+ tq_Ptr = tqPtr, /* pointer */
+ tq_Proc = tqProc, /* procedure */
+ tq_Array = tqArray, /* duh */
+ tq_Far = tqFar, /* longer addressing - 8086/8 land */
+ tq_Vol = tqVol, /* volatile */
+ tq_Max = tqMax /* Max type qualifier+1 */
+} tq_t;
+
+/* Redefinition of basic types. */
+
+typedef enum bt {
+ bt_Nil = btNil, /* undefined */
+ bt_Adr = btAdr, /* address - integer same size as pointer */
+ bt_Char = btChar, /* character */
+ bt_UChar = btUChar, /* unsigned character */
+ bt_Short = btShort, /* short */
+ bt_UShort = btUShort, /* unsigned short */
+ bt_Int = btInt, /* int */
+ bt_UInt = btUInt, /* unsigned int */
+ bt_Long = btLong, /* long */
+ bt_ULong = btULong, /* unsigned long */
+ bt_Float = btFloat, /* float (real) */
+ bt_Double = btDouble, /* Double (real) */
+ bt_Struct = btStruct, /* Structure (Record) */
+ bt_Union = btUnion, /* Union (variant) */
+ bt_Enum = btEnum, /* Enumerated */
+ bt_Typedef = btTypedef, /* defined via a typedef, isymRef points */
+ bt_Range = btRange, /* subrange of int */
+ bt_Set = btSet, /* pascal sets */
+ bt_Complex = btComplex, /* fortran complex */
+ bt_DComplex = btDComplex, /* fortran double complex */
+ bt_Indirect = btIndirect, /* forward or unnamed typedef */
+ bt_FixedDec = btFixedDec, /* Fixed Decimal */
+ bt_FloatDec = btFloatDec, /* Float Decimal */
+ bt_String = btString, /* Varying Length Character String */
+ bt_Bit = btBit, /* Aligned Bit String */
+ bt_Picture = btPicture, /* Picture */
+ bt_Void = btVoid, /* Void */
+ bt_Max = btMax /* Max basic type+1 */
+} bt_t;
+
+#define N_TQ itqMax
+
+/* States for whether to hash type or not. */
+typedef enum hash_state {
+ hash_no = 0, /* don't hash type */
+ hash_yes = 1, /* ok to hash type, or use previous hash */
+ hash_record = 2 /* ok to record hash, but don't use prev. */
+} hash_state_t;
+
+/* Types of different sized allocation requests. */
+enum alloc_type {
+ alloc_type_none, /* dummy value */
+ alloc_type_scope, /* nested scopes linked list */
+ alloc_type_vlinks, /* glue linking pages in varray */
+ alloc_type_shash, /* string hash element */
+ alloc_type_thash, /* type hash element */
+ alloc_type_tag, /* struct/union/tag element */
+ alloc_type_forward, /* element to hold unknown tag */
+ alloc_type_thead, /* head of type hash list */
+ alloc_type_varray, /* general varray allocation */
+ alloc_type_lineno, /* line number list */
+ alloc_type_last /* last+1 element for array bounds */
+};
+
+/* Types of auxiliary type information. */
+enum aux_type {
+ aux_tir, /* TIR type information */
+ aux_rndx, /* relative index into symbol table */
+ aux_dnLow, /* low dimension */
+ aux_dnHigh, /* high dimension */
+ aux_isym, /* symbol table index (end of proc) */
+ aux_iss, /* index into string space (not used) */
+ aux_width, /* width for non-default sized struc fields */
+ aux_count /* count of ranges for variant arm */
+};
+
+/* Structures to provide n-number of virtual arrays, each of which can
+ grow linearly, and which are written in the object file as
+ sequential pages. On systems with a BSD malloc, the
+ MAX_CLUSTER_PAGES should be 1 less than a power of two, since
+ malloc adds it's overhead, and rounds up to the next power of 2.
+ Pages are linked together via a linked list.
+
+ If PAGE_SIZE is > 4096, the string length in the shash_t structure
+ can't be represented (assuming there are strings > 4096 bytes). */
+
+/* FIXME: Yes, there can be such strings while emitting C++ class debug
+ info. Templates are the offender here, the test case in question
+ having a mangled class name of
+
+ t7rb_tree4Z4xkeyZt4pair2ZC4xkeyZt7xsocket1Z4UserZt9select1st2Zt4pair\
+ 2ZC4xkeyZt7xsocket1Z4UserZ4xkeyZt4less1Z4xkey
+
+ Repeat that a couple dozen times while listing the class members and
+ you've got strings over 4k. Hack around this for now by increasing
+ the page size. A proper solution would abandon this structure scheme
+ certainly for very large strings, and possibly entirely. */
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE (8*1024) /* size of varray pages */
+#endif
+
+#define PAGE_USIZE ((unsigned long) PAGE_SIZE)
+
+#ifndef MAX_CLUSTER_PAGES /* # pages to get from system */
+#define MAX_CLUSTER_PAGES 63
+#endif
+
+/* Linked list connecting separate page allocations. */
+typedef struct vlinks {
+ struct vlinks *prev; /* previous set of pages */
+ struct vlinks *next; /* next set of pages */
+ union page *datum; /* start of page */
+ unsigned long start_index; /* starting index # of page */
+} vlinks_t;
+
+
+/* Virtual array header. */
+typedef struct varray {
+ vlinks_t *first; /* first page link */
+ vlinks_t *last; /* last page link */
+ unsigned long num_allocated; /* # objects allocated */
+ unsigned short object_size; /* size in bytes of each object */
+ unsigned short objects_per_page; /* # objects that can fit on a page */
+ unsigned short objects_last_page; /* # objects allocated on last page */
+} varray_t;
+
+#ifndef MALLOC_CHECK
+#define OBJECTS_PER_PAGE(type) (PAGE_SIZE / sizeof (type))
+#else
+#define OBJECTS_PER_PAGE(type) ((sizeof (type) > 1) ? 1 : PAGE_SIZE)
+#endif
+
+#define INIT_VARRAY(type) { /* macro to initialize a varray */ \
+ (vlinks_t *)0, /* first */ \
+ (vlinks_t *)0, /* last */ \
+ 0, /* num_allocated */ \
+ sizeof (type), /* object_size */ \
+ OBJECTS_PER_PAGE (type), /* objects_per_page */ \
+ OBJECTS_PER_PAGE (type), /* objects_last_page */ \
+}
+
+
+/* Master type for indexes within the symbol table. */
+typedef unsigned long symint_t;
+
+
+/* Linked list support for nested scopes (file, block, structure, etc.). */
+typedef struct scope {
+ struct scope *prev; /* previous scope level */
+ struct scope *free; /* free list pointer */
+ struct localsym *lsym; /* pointer to local symbol node */
+ st_t type; /* type of the node */
+} scope_t;
+
+
+/* For a local symbol we store a gas symbol as well as the debugging
+ information we generate. The gas symbol will be NULL if this is
+ only a debugging symbol. */
+typedef struct localsym {
+ const char *name; /* symbol name */
+ symbolS *as_sym; /* symbol as seen by gas */
+ bfd_vma addend; /* addend to as_sym value */
+ struct efdr *file_ptr; /* file pointer */
+ struct ecoff_proc *proc_ptr; /* proc pointer */
+ struct localsym *begin_ptr; /* symbol at start of block */
+ struct ecoff_aux *index_ptr; /* index value to be filled in */
+ struct forward *forward_ref; /* forward references to this symbol */
+ long sym_index; /* final symbol index */
+ EXTR ecoff_sym; /* ECOFF debugging symbol */
+} localsym_t;
+
+
+/* For aux information we keep the type and the data. */
+typedef struct ecoff_aux {
+ enum aux_type type; /* aux type */
+ AUXU data; /* aux data */
+} aux_t;
+
+/* For a procedure we store the gas symbol as well as the PDR
+ debugging information. */
+typedef struct ecoff_proc {
+ localsym_t *sym; /* associated symbol */
+ PDR pdr; /* ECOFF debugging info */
+} proc_t;
+
+/* Number of proc_t structures allocated. */
+static unsigned long proc_cnt;
+
+
+/* Forward reference list for tags referenced, but not yet defined. */
+typedef struct forward {
+ struct forward *next; /* next forward reference */
+ struct forward *free; /* free list pointer */
+ aux_t *ifd_ptr; /* pointer to store file index */
+ aux_t *index_ptr; /* pointer to store symbol index */
+} forward_t;
+
+
+/* Linked list support for tags. The first tag in the list is always
+ the current tag for that block. */
+typedef struct tag {
+ struct tag *free; /* free list pointer */
+ struct shash *hash_ptr; /* pointer to the hash table head */
+ struct tag *same_name; /* tag with same name in outer scope */
+ struct tag *same_block; /* next tag defined in the same block. */
+ struct forward *forward_ref; /* list of forward references */
+ bt_t basic_type; /* bt_Struct, bt_Union, or bt_Enum */
+ symint_t ifd; /* file # tag defined in */
+ localsym_t *sym; /* file's local symbols */
+} tag_t;
+
+
+/* Head of a block's linked list of tags. */
+typedef struct thead {
+ struct thead *prev; /* previous block */
+ struct thead *free; /* free list pointer */
+ struct tag *first_tag; /* first tag in block defined */
+} thead_t;
+
+
+/* Union containing pointers to each the small structures which are freed up. */
+typedef union small_free {
+ scope_t *f_scope; /* scope structure */
+ thead_t *f_thead; /* tag head structure */
+ tag_t *f_tag; /* tag element structure */
+ forward_t *f_forward; /* forward tag reference */
+} small_free_t;
+
+
+/* String hash table entry. */
+
+typedef struct shash {
+ char *string; /* string we are hashing */
+ symint_t indx; /* index within string table */
+ EXTR *esym_ptr; /* global symbol pointer */
+ localsym_t *sym_ptr; /* local symbol pointer */
+ localsym_t *end_ptr; /* symbol pointer to end block */
+ tag_t *tag_ptr; /* tag pointer */
+ proc_t *proc_ptr; /* procedure descriptor pointer */
+} shash_t;
+
+
+/* Type hash table support. The size of the hash table must fit
+ within a page with the other extended file descriptor information.
+ Because unique types which are hashed are fewer in number than
+ strings, we use a smaller hash value. */
+
+#define HASHBITS 30
+
+#ifndef THASH_SIZE
+#define THASH_SIZE 113
+#endif
+
+typedef struct thash {
+ struct thash *next; /* next hash value */
+ AUXU type; /* type we are hashing */
+ symint_t indx; /* index within string table */
+} thash_t;
+
+
+/* Extended file descriptor that contains all of the support necessary
+ to add things to each file separately. */
+typedef struct efdr {
+ FDR fdr; /* File header to be written out */
+ FDR *orig_fdr; /* original file header */
+ char *name; /* filename */
+ int fake; /* whether this is faked .file */
+ symint_t void_type; /* aux. pointer to 'void' type */
+ symint_t int_type; /* aux. pointer to 'int' type */
+ scope_t *cur_scope; /* current nested scopes */
+ symint_t file_index; /* current file number */
+ int nested_scopes; /* # nested scopes */
+ varray_t strings; /* local strings */
+ varray_t symbols; /* local symbols */
+ varray_t procs; /* procedures */
+ varray_t aux_syms; /* auxiliary symbols */
+ struct efdr *next_file; /* next file descriptor */
+ /* string/type hash tables */
+ struct hash_control *str_hash; /* string hash table */
+ thash_t *thash_head[THASH_SIZE];
+} efdr_t;
+
+/* Pre-initialized extended file structure. */
+static const efdr_t init_file =
+{
+ { /* FDR structure */
+ 0, /* adr: memory address of beginning of file */
+ 0, /* rss: file name (of source, if known) */
+ 0, /* issBase: file's string space */
+ 0, /* cbSs: number of bytes in the ss */
+ 0, /* isymBase: beginning of symbols */
+ 0, /* csym: count file's of symbols */
+ 0, /* ilineBase: file's line symbols */
+ 0, /* cline: count of file's line symbols */
+ 0, /* ioptBase: file's optimization entries */
+ 0, /* copt: count of file's optimization entries */
+ 0, /* ipdFirst: start of procedures for this file */
+ 0, /* cpd: count of procedures for this file */
+ 0, /* iauxBase: file's auxiliary entries */
+ 0, /* caux: count of file's auxiliary entries */
+ 0, /* rfdBase: index into the file indirect table */
+ 0, /* crfd: count file indirect entries */
+ langC, /* lang: language for this file */
+ 1, /* fMerge: whether this file can be merged */
+ 0, /* fReadin: true if read in (not just created) */
+ TARGET_BYTES_BIG_ENDIAN, /* fBigendian: if 1, compiled on big endian machine */
+ GLEVEL_2, /* glevel: level this file was compiled with */
+ 0, /* reserved: reserved for future use */
+ 0, /* cbLineOffset: byte offset from header for this file ln's */
+ 0, /* cbLine: size of lines for this file */
+ },
+
+ (FDR *)0, /* orig_fdr: original file header pointer */
+ (char *)0, /* name: pointer to filename */
+ 0, /* fake: whether this is a faked .file */
+ 0, /* void_type: ptr to aux node for void type */
+ 0, /* int_type: ptr to aux node for int type */
+ (scope_t *)0, /* cur_scope: current scope being processed */
+ 0, /* file_index: current file # */
+ 0, /* nested_scopes: # nested scopes */
+ INIT_VARRAY (char), /* strings: local string varray */
+ INIT_VARRAY (localsym_t), /* symbols: local symbols varray */
+ INIT_VARRAY (proc_t), /* procs: procedure varray */
+ INIT_VARRAY (aux_t), /* aux_syms: auxiliary symbols varray */
+
+ (struct efdr *)0, /* next_file: next file structure */
+
+ (struct hash_control *)0, /* str_hash: string hash table */
+ { 0 }, /* thash_head: type hash table */
+};
+
+
+static efdr_t *first_file; /* first file descriptor */
+static efdr_t **last_file_ptr = &first_file; /* file descriptor tail */
+
+
+/* Line number information is kept in a list until the assembly is
+ finished. */
+typedef struct lineno_list {
+ struct lineno_list *next; /* next element in list */
+ efdr_t *file; /* file this line is in */
+ proc_t *proc; /* procedure this line is in */
+ fragS *frag; /* fragment this line number is in */
+ unsigned long paddr; /* offset within fragment */
+ long lineno; /* actual line number */
+} lineno_list_t;
+
+static lineno_list_t *first_lineno;
+static lineno_list_t *last_lineno;
+static lineno_list_t **last_lineno_ptr = &first_lineno;
+
+/* Sometimes there will be some .loc statements before a .ent. We
+ keep them in this list so that we can fill in the procedure pointer
+ after we see the .ent. */
+static lineno_list_t *noproc_lineno;
+
+/* Union of various things that are held in pages. */
+typedef union page {
+ char byte [ PAGE_SIZE ];
+ unsigned char ubyte [ PAGE_SIZE ];
+ efdr_t file [ PAGE_SIZE / sizeof (efdr_t) ];
+ FDR ofile [ PAGE_SIZE / sizeof (FDR) ];
+ proc_t proc [ PAGE_SIZE / sizeof (proc_t) ];
+ localsym_t sym [ PAGE_SIZE / sizeof (localsym_t) ];
+ aux_t aux [ PAGE_SIZE / sizeof (aux_t) ];
+ DNR dense [ PAGE_SIZE / sizeof (DNR) ];
+ scope_t scope [ PAGE_SIZE / sizeof (scope_t) ];
+ vlinks_t vlinks [ PAGE_SIZE / sizeof (vlinks_t) ];
+ shash_t shash [ PAGE_SIZE / sizeof (shash_t) ];
+ thash_t thash [ PAGE_SIZE / sizeof (thash_t) ];
+ tag_t tag [ PAGE_SIZE / sizeof (tag_t) ];
+ forward_t forward [ PAGE_SIZE / sizeof (forward_t) ];
+ thead_t thead [ PAGE_SIZE / sizeof (thead_t) ];
+ lineno_list_t lineno [ PAGE_SIZE / sizeof (lineno_list_t) ];
+} page_type;
+
+
+/* Structure holding allocation information for small sized structures. */
+typedef struct alloc_info {
+ char *alloc_name; /* name of this allocation type (must be first) */
+ page_type *cur_page; /* current page being allocated from */
+ small_free_t free_list; /* current free list if any */
+ int unallocated; /* number of elements unallocated on page */
+ int total_alloc; /* total number of allocations */
+ int total_free; /* total number of frees */
+ int total_pages; /* total number of pages allocated */
+} alloc_info_t;
+
+
+/* Type information collected together. */
+typedef struct type_info {
+ bt_t basic_type; /* basic type */
+ int orig_type; /* original COFF-based type */
+ int num_tq; /* # type qualifiers */
+ int num_dims; /* # dimensions */
+ int num_sizes; /* # sizes */
+ int extra_sizes; /* # extra sizes not tied with dims */
+ tag_t * tag_ptr; /* tag pointer */
+ int bitfield; /* symbol is a bitfield */
+ tq_t type_qualifiers[N_TQ]; /* type qualifiers (ptr, func, array)*/
+ symint_t dimensions [N_TQ]; /* dimensions for each array */
+ symint_t sizes [N_TQ+2]; /* sizes of each array slice + size of
+ struct/union/enum + bitfield size */
+} type_info_t;
+
+/* Pre-initialized type_info struct. */
+static const type_info_t type_info_init = {
+ bt_Nil, /* basic type */
+ T_NULL, /* original COFF-based type */
+ 0, /* # type qualifiers */
+ 0, /* # dimensions */
+ 0, /* # sizes */
+ 0, /* sizes not tied with dims */
+ NULL, /* ptr to tag */
+ 0, /* bitfield */
+ { /* type qualifiers */
+ tq_Nil,
+ tq_Nil,
+ tq_Nil,
+ tq_Nil,
+ tq_Nil,
+ tq_Nil,
+ },
+ { /* dimensions */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ },
+ { /* sizes */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ },
+};
+
+/* Global hash table for the tags table and global table for file
+ descriptors. */
+
+static varray_t file_desc = INIT_VARRAY (efdr_t);
+
+static struct hash_control *tag_hash;
+
+/* Static types for int and void. Also, remember the last function's
+ type (which is set up when we encounter the declaration for the
+ function, and used when the end block for the function is emitted. */
+
+static type_info_t int_type_info;
+static type_info_t void_type_info;
+static type_info_t last_func_type_info;
+static symbolS *last_func_sym_value;
+
+
+/* Convert COFF basic type to ECOFF basic type. The T_NULL type
+ really should use bt_Void, but this causes the current ecoff GDB to
+ issue unsupported type messages, and the Ultrix 4.00 dbx (aka MIPS
+ 2.0) doesn't understand it, even though the compiler generates it.
+ Maybe this will be fixed in 2.10 or 2.20 of the MIPS compiler
+ suite, but for now go with what works.
+
+ It would make sense for the .type and .scl directives to use the
+ ECOFF numbers directly, rather than using the COFF numbers and
+ mapping them. Unfortunately, this is historically what mips-tfile
+ expects, and changing gcc now would be a considerable pain (the
+ native compiler generates debugging information internally, rather
+ than via the assembler, so it will never use .type or .scl). */
+
+static const bt_t map_coff_types[] = {
+ bt_Nil, /* T_NULL */
+ bt_Nil, /* T_ARG */
+ bt_Char, /* T_CHAR */
+ bt_Short, /* T_SHORT */
+ bt_Int, /* T_INT */
+ bt_Long, /* T_LONG */
+ bt_Float, /* T_FLOAT */
+ bt_Double, /* T_DOUBLE */
+ bt_Struct, /* T_STRUCT */
+ bt_Union, /* T_UNION */
+ bt_Enum, /* T_ENUM */
+ bt_Enum, /* T_MOE */
+ bt_UChar, /* T_UCHAR */
+ bt_UShort, /* T_USHORT */
+ bt_UInt, /* T_UINT */
+ bt_ULong /* T_ULONG */
+};
+
+/* Convert COFF storage class to ECOFF storage class. */
+static const sc_t map_coff_storage[] = {
+ sc_Nil, /* 0: C_NULL */
+ sc_Abs, /* 1: C_AUTO auto var */
+ sc_Undefined, /* 2: C_EXT external */
+ sc_Data, /* 3: C_STAT static */
+ sc_Register, /* 4: C_REG register */
+ sc_Undefined, /* 5: C_EXTDEF ??? */
+ sc_Text, /* 6: C_LABEL label */
+ sc_Text, /* 7: C_ULABEL user label */
+ sc_Info, /* 8: C_MOS member of struct */
+ sc_Abs, /* 9: C_ARG argument */
+ sc_Info, /* 10: C_STRTAG struct tag */
+ sc_Info, /* 11: C_MOU member of union */
+ sc_Info, /* 12: C_UNTAG union tag */
+ sc_Info, /* 13: C_TPDEF typedef */
+ sc_Data, /* 14: C_USTATIC ??? */
+ sc_Info, /* 15: C_ENTAG enum tag */
+ sc_Info, /* 16: C_MOE member of enum */
+ sc_Register, /* 17: C_REGPARM register parameter */
+ sc_Bits, /* 18; C_FIELD bitfield */
+ sc_Nil, /* 19 */
+ sc_Nil, /* 20 */
+ sc_Nil, /* 21 */
+ sc_Nil, /* 22 */
+ sc_Nil, /* 23 */
+ sc_Nil, /* 24 */
+ sc_Nil, /* 25 */
+ sc_Nil, /* 26 */
+ sc_Nil, /* 27 */
+ sc_Nil, /* 28 */
+ sc_Nil, /* 29 */
+ sc_Nil, /* 30 */
+ sc_Nil, /* 31 */
+ sc_Nil, /* 32 */
+ sc_Nil, /* 33 */
+ sc_Nil, /* 34 */
+ sc_Nil, /* 35 */
+ sc_Nil, /* 36 */
+ sc_Nil, /* 37 */
+ sc_Nil, /* 38 */
+ sc_Nil, /* 39 */
+ sc_Nil, /* 40 */
+ sc_Nil, /* 41 */
+ sc_Nil, /* 42 */
+ sc_Nil, /* 43 */
+ sc_Nil, /* 44 */
+ sc_Nil, /* 45 */
+ sc_Nil, /* 46 */
+ sc_Nil, /* 47 */
+ sc_Nil, /* 48 */
+ sc_Nil, /* 49 */
+ sc_Nil, /* 50 */
+ sc_Nil, /* 51 */
+ sc_Nil, /* 52 */
+ sc_Nil, /* 53 */
+ sc_Nil, /* 54 */
+ sc_Nil, /* 55 */
+ sc_Nil, /* 56 */
+ sc_Nil, /* 57 */
+ sc_Nil, /* 58 */
+ sc_Nil, /* 59 */
+ sc_Nil, /* 60 */
+ sc_Nil, /* 61 */
+ sc_Nil, /* 62 */
+ sc_Nil, /* 63 */
+ sc_Nil, /* 64 */
+ sc_Nil, /* 65 */
+ sc_Nil, /* 66 */
+ sc_Nil, /* 67 */
+ sc_Nil, /* 68 */
+ sc_Nil, /* 69 */
+ sc_Nil, /* 70 */
+ sc_Nil, /* 71 */
+ sc_Nil, /* 72 */
+ sc_Nil, /* 73 */
+ sc_Nil, /* 74 */
+ sc_Nil, /* 75 */
+ sc_Nil, /* 76 */
+ sc_Nil, /* 77 */
+ sc_Nil, /* 78 */
+ sc_Nil, /* 79 */
+ sc_Nil, /* 80 */
+ sc_Nil, /* 81 */
+ sc_Nil, /* 82 */
+ sc_Nil, /* 83 */
+ sc_Nil, /* 84 */
+ sc_Nil, /* 85 */
+ sc_Nil, /* 86 */
+ sc_Nil, /* 87 */
+ sc_Nil, /* 88 */
+ sc_Nil, /* 89 */
+ sc_Nil, /* 90 */
+ sc_Nil, /* 91 */
+ sc_Nil, /* 92 */
+ sc_Nil, /* 93 */
+ sc_Nil, /* 94 */
+ sc_Nil, /* 95 */
+ sc_Nil, /* 96 */
+ sc_Nil, /* 97 */
+ sc_Nil, /* 98 */
+ sc_Nil, /* 99 */
+ sc_Text, /* 100: C_BLOCK block start/end */
+ sc_Text, /* 101: C_FCN function start/end */
+ sc_Info, /* 102: C_EOS end of struct/union/enum */
+ sc_Nil, /* 103: C_FILE file start */
+ sc_Nil, /* 104: C_LINE line number */
+ sc_Nil, /* 105: C_ALIAS combined type info */
+ sc_Nil, /* 106: C_HIDDEN ??? */
+};
+
+/* Convert COFF storage class to ECOFF symbol type. */
+static const st_t map_coff_sym_type[] = {
+ st_Nil, /* 0: C_NULL */
+ st_Local, /* 1: C_AUTO auto var */
+ st_Global, /* 2: C_EXT external */
+ st_Static, /* 3: C_STAT static */
+ st_Local, /* 4: C_REG register */
+ st_Global, /* 5: C_EXTDEF ??? */
+ st_Label, /* 6: C_LABEL label */
+ st_Label, /* 7: C_ULABEL user label */
+ st_Member, /* 8: C_MOS member of struct */
+ st_Param, /* 9: C_ARG argument */
+ st_Block, /* 10: C_STRTAG struct tag */
+ st_Member, /* 11: C_MOU member of union */
+ st_Block, /* 12: C_UNTAG union tag */
+ st_Typedef, /* 13: C_TPDEF typedef */
+ st_Static, /* 14: C_USTATIC ??? */
+ st_Block, /* 15: C_ENTAG enum tag */
+ st_Member, /* 16: C_MOE member of enum */
+ st_Param, /* 17: C_REGPARM register parameter */
+ st_Member, /* 18; C_FIELD bitfield */
+ st_Nil, /* 19 */
+ st_Nil, /* 20 */
+ st_Nil, /* 21 */
+ st_Nil, /* 22 */
+ st_Nil, /* 23 */
+ st_Nil, /* 24 */
+ st_Nil, /* 25 */
+ st_Nil, /* 26 */
+ st_Nil, /* 27 */
+ st_Nil, /* 28 */
+ st_Nil, /* 29 */
+ st_Nil, /* 30 */
+ st_Nil, /* 31 */
+ st_Nil, /* 32 */
+ st_Nil, /* 33 */
+ st_Nil, /* 34 */
+ st_Nil, /* 35 */
+ st_Nil, /* 36 */
+ st_Nil, /* 37 */
+ st_Nil, /* 38 */
+ st_Nil, /* 39 */
+ st_Nil, /* 40 */
+ st_Nil, /* 41 */
+ st_Nil, /* 42 */
+ st_Nil, /* 43 */
+ st_Nil, /* 44 */
+ st_Nil, /* 45 */
+ st_Nil, /* 46 */
+ st_Nil, /* 47 */
+ st_Nil, /* 48 */
+ st_Nil, /* 49 */
+ st_Nil, /* 50 */
+ st_Nil, /* 51 */
+ st_Nil, /* 52 */
+ st_Nil, /* 53 */
+ st_Nil, /* 54 */
+ st_Nil, /* 55 */
+ st_Nil, /* 56 */
+ st_Nil, /* 57 */
+ st_Nil, /* 58 */
+ st_Nil, /* 59 */
+ st_Nil, /* 60 */
+ st_Nil, /* 61 */
+ st_Nil, /* 62 */
+ st_Nil, /* 63 */
+ st_Nil, /* 64 */
+ st_Nil, /* 65 */
+ st_Nil, /* 66 */
+ st_Nil, /* 67 */
+ st_Nil, /* 68 */
+ st_Nil, /* 69 */
+ st_Nil, /* 70 */
+ st_Nil, /* 71 */
+ st_Nil, /* 72 */
+ st_Nil, /* 73 */
+ st_Nil, /* 74 */
+ st_Nil, /* 75 */
+ st_Nil, /* 76 */
+ st_Nil, /* 77 */
+ st_Nil, /* 78 */
+ st_Nil, /* 79 */
+ st_Nil, /* 80 */
+ st_Nil, /* 81 */
+ st_Nil, /* 82 */
+ st_Nil, /* 83 */
+ st_Nil, /* 84 */
+ st_Nil, /* 85 */
+ st_Nil, /* 86 */
+ st_Nil, /* 87 */
+ st_Nil, /* 88 */
+ st_Nil, /* 89 */
+ st_Nil, /* 90 */
+ st_Nil, /* 91 */
+ st_Nil, /* 92 */
+ st_Nil, /* 93 */
+ st_Nil, /* 94 */
+ st_Nil, /* 95 */
+ st_Nil, /* 96 */
+ st_Nil, /* 97 */
+ st_Nil, /* 98 */
+ st_Nil, /* 99 */
+ st_Block, /* 100: C_BLOCK block start/end */
+ st_Proc, /* 101: C_FCN function start/end */
+ st_End, /* 102: C_EOS end of struct/union/enum */
+ st_File, /* 103: C_FILE file start */
+ st_Nil, /* 104: C_LINE line number */
+ st_Nil, /* 105: C_ALIAS combined type info */
+ st_Nil, /* 106: C_HIDDEN ??? */
+};
+
+
+/* Keep track of different sized allocation requests. */
+static alloc_info_t alloc_counts[ (int)alloc_type_last ];
+
+/* Record whether we have seen any debugging information. */
+int ecoff_debugging_seen = 0;
+
+/* Various statics. */
+static efdr_t *cur_file_ptr = (efdr_t *) 0; /* current file desc. header */
+static proc_t *cur_proc_ptr = (proc_t *) 0; /* current procedure header */
+static proc_t *first_proc_ptr = (proc_t *) 0; /* first procedure header */
+static thead_t *top_tag_head = (thead_t *) 0; /* top level tag head */
+static thead_t *cur_tag_head = (thead_t *) 0; /* current tag head */
+#ifdef ECOFF_DEBUG
+static int debug = 0; /* trace functions */
+#endif
+static int stabs_seen = 0; /* != 0 if stabs have been seen */
+
+static int current_file_idx;
+static const char *current_stabs_filename;
+
+/* Pseudo symbol to use when putting stabs into the symbol table. */
+#ifndef STABS_SYMBOL
+#define STABS_SYMBOL "@stabs"
+#endif
+
+static char stabs_symbol[] = STABS_SYMBOL;
+
+/* Prototypes for functions defined in this file. */
+
+static void add_varray_page PARAMS ((varray_t *vp));
+static symint_t add_string PARAMS ((varray_t *vp,
+ struct hash_control *hash_tbl,
+ const char *str,
+ shash_t **ret_hash));
+static localsym_t *add_ecoff_symbol PARAMS ((const char *str, st_t type,
+ sc_t storage, symbolS *sym,
+ bfd_vma addend, symint_t value,
+ symint_t indx));
+static symint_t add_aux_sym_symint PARAMS ((symint_t aux_word));
+static symint_t add_aux_sym_rndx PARAMS ((int file_index,
+ symint_t sym_index));
+static symint_t add_aux_sym_tir PARAMS ((type_info_t *t,
+ hash_state_t state,
+ thash_t **hash_tbl));
+static tag_t *get_tag PARAMS ((const char *tag, localsym_t *sym,
+ bt_t basic_type));
+static void add_unknown_tag PARAMS ((tag_t *ptag));
+static void add_procedure PARAMS ((char *func));
+static void add_file PARAMS ((const char *file_name, int indx, int fake));
+#ifdef ECOFF_DEBUG
+static char *sc_to_string PARAMS ((sc_t storage_class));
+static char *st_to_string PARAMS ((st_t symbol_type));
+#endif
+static void mark_stabs PARAMS ((int));
+static char *ecoff_add_bytes PARAMS ((char **buf, char **bufend,
+ char *bufptr, unsigned long need));
+static unsigned long ecoff_padding_adjust
+ PARAMS ((const struct ecoff_debug_swap *backend, char **buf, char **bufend,
+ unsigned long offset, char **bufptrptr));
+static unsigned long ecoff_build_lineno
+ PARAMS ((const struct ecoff_debug_swap *backend, char **buf, char **bufend,
+ unsigned long offset, long *linecntptr));
+static unsigned long ecoff_build_symbols
+ PARAMS ((const struct ecoff_debug_swap *backend, char **buf, char **bufend,
+ unsigned long offset));
+static unsigned long ecoff_build_procs
+ PARAMS ((const struct ecoff_debug_swap *backend, char **buf, char **bufend,
+ unsigned long offset));
+static unsigned long ecoff_build_aux
+ PARAMS ((const struct ecoff_debug_swap *backend, char **buf, char **bufend,
+ unsigned long offset));
+static unsigned long ecoff_build_strings PARAMS ((char **buf, char **bufend,
+ unsigned long offset,
+ varray_t *vp));
+static unsigned long ecoff_build_ss
+ PARAMS ((const struct ecoff_debug_swap *backend, char **buf, char **bufend,
+ unsigned long offset));
+static unsigned long ecoff_build_fdr
+ PARAMS ((const struct ecoff_debug_swap *backend, char **buf, char **bufend,
+ unsigned long offset));
+static void ecoff_setup_ext PARAMS ((void));
+static page_type *allocate_cluster PARAMS ((unsigned long npages));
+static page_type *allocate_page PARAMS ((void));
+static scope_t *allocate_scope PARAMS ((void));
+static void free_scope PARAMS ((scope_t *ptr));
+static vlinks_t *allocate_vlinks PARAMS ((void));
+static shash_t *allocate_shash PARAMS ((void));
+static thash_t *allocate_thash PARAMS ((void));
+static tag_t *allocate_tag PARAMS ((void));
+static void free_tag PARAMS ((tag_t *ptr));
+static forward_t *allocate_forward PARAMS ((void));
+static thead_t *allocate_thead PARAMS ((void));
+static void free_thead PARAMS ((thead_t *ptr));
+static lineno_list_t *allocate_lineno_list PARAMS ((void));
+
+/* This function should be called when the assembler starts up. */
+
+void
+ecoff_read_begin_hook ()
+{
+ tag_hash = hash_new ();
+ top_tag_head = allocate_thead ();
+ top_tag_head->first_tag = (tag_t *) NULL;
+ top_tag_head->free = (thead_t *) NULL;
+ top_tag_head->prev = cur_tag_head;
+ cur_tag_head = top_tag_head;
+}
+
+/* This function should be called when a symbol is created. */
+
+void
+ecoff_symbol_new_hook (symbolP)
+ symbolS *symbolP;
+{
+ /* Make sure that we have a file pointer, but only if we have seen a
+ file. If we haven't seen a file, then this is a probably special
+ symbol created by md_begin which may required special handling at
+ some point. Creating a dummy file with a dummy name is certainly
+ wrong. */
+ if (cur_file_ptr == (efdr_t *) NULL
+ && seen_at_least_1_file ())
+ add_file ((const char *) NULL, 0, 1);
+ symbolP->ecoff_file = cur_file_ptr;
+ symbolP->ecoff_symbol = NULL;
+ symbolP->ecoff_extern_size = 0;
+}
+
+/* Add a page to a varray object. */
+
+static void
+add_varray_page (vp)
+ varray_t *vp; /* varray to add page to */
+{
+ vlinks_t *new_links = allocate_vlinks ();
+
+#ifdef MALLOC_CHECK
+ if (vp->object_size > 1)
+ new_links->datum = (page_type *) xcalloc (1, vp->object_size);
+ else
+#endif
+ new_links->datum = allocate_page ();
+
+ alloc_counts[(int)alloc_type_varray].total_alloc++;
+ alloc_counts[(int)alloc_type_varray].total_pages++;
+
+ new_links->start_index = vp->num_allocated;
+ vp->objects_last_page = 0;
+
+ if (vp->first == (vlinks_t *) NULL) /* first allocation? */
+ vp->first = vp->last = new_links;
+ else
+ { /* 2nd or greater allocation */
+ new_links->prev = vp->last;
+ vp->last->next = new_links;
+ vp->last = new_links;
+ }
+}
+
+/* Add a string (and null pad) to one of the string tables. */
+
+static symint_t
+add_string (vp, hash_tbl, str, ret_hash)
+ varray_t *vp; /* string obstack */
+ struct hash_control *hash_tbl; /* ptr to hash table */
+ const char *str; /* string */
+ shash_t **ret_hash; /* return hash pointer */
+{
+ register unsigned long len = strlen (str);
+ register shash_t *hash_ptr;
+
+ if (len >= PAGE_USIZE)
+ as_fatal (_("String too big (%lu bytes)"), len);
+
+ hash_ptr = (shash_t *) hash_find (hash_tbl, str);
+ if (hash_ptr == (shash_t *) NULL)
+ {
+ register const char *err;
+
+ if (vp->objects_last_page + len >= PAGE_USIZE)
+ {
+ vp->num_allocated =
+ ((vp->num_allocated + PAGE_USIZE - 1) / PAGE_USIZE) * PAGE_USIZE;
+ add_varray_page (vp);
+ }
+
+ hash_ptr = allocate_shash ();
+ hash_ptr->indx = vp->num_allocated;
+
+ hash_ptr->string = &vp->last->datum->byte[vp->objects_last_page];
+
+ vp->objects_last_page += len + 1;
+ vp->num_allocated += len + 1;
+
+ strcpy (hash_ptr->string, str);
+
+ err = hash_insert (hash_tbl, str, (char *) hash_ptr);
+ if (err)
+ as_fatal (_("Inserting \"%s\" into string hash table: %s"),
+ str, err);
+ }
+
+ if (ret_hash != (shash_t **) NULL)
+ *ret_hash = hash_ptr;
+
+ return hash_ptr->indx;
+}
+
+/* Add debugging information for a symbol. */
+
+static localsym_t *
+add_ecoff_symbol (str, type, storage, sym_value, addend, value, indx)
+ const char *str; /* symbol name */
+ st_t type; /* symbol type */
+ sc_t storage; /* storage class */
+ symbolS *sym_value; /* associated symbol. */
+ bfd_vma addend; /* addend to sym_value. */
+ symint_t value; /* value of symbol */
+ symint_t indx; /* index to local/aux. syms */
+{
+ localsym_t *psym;
+ register scope_t *pscope;
+ register thead_t *ptag_head;
+ register tag_t *ptag;
+ register tag_t *ptag_next;
+ register varray_t *vp;
+ register int scope_delta = 0;
+ shash_t *hash_ptr = (shash_t *) NULL;
+
+ if (cur_file_ptr == (efdr_t *) NULL)
+ as_fatal (_("no current file pointer"));
+
+ vp = &cur_file_ptr->symbols;
+
+ if (vp->objects_last_page == vp->objects_per_page)
+ add_varray_page (vp);
+
+ psym = &vp->last->datum->sym[ vp->objects_last_page++ ];
+
+ if (str == (const char *) NULL && sym_value != (symbolS *) NULL)
+ psym->name = S_GET_NAME (sym_value);
+ else
+ psym->name = str;
+ psym->as_sym = sym_value;
+ if (sym_value != (symbolS *) NULL)
+ sym_value->ecoff_symbol = psym;
+ psym->addend = addend;
+ psym->file_ptr = cur_file_ptr;
+ psym->proc_ptr = cur_proc_ptr;
+ psym->begin_ptr = (localsym_t *) NULL;
+ psym->index_ptr = (aux_t *) NULL;
+ psym->forward_ref = (forward_t *) NULL;
+ psym->sym_index = -1;
+ memset (&psym->ecoff_sym, 0, sizeof (EXTR));
+ psym->ecoff_sym.asym.value = value;
+ psym->ecoff_sym.asym.st = (unsigned) type;
+ psym->ecoff_sym.asym.sc = (unsigned) storage;
+ psym->ecoff_sym.asym.index = indx;
+
+ /* If there is an associated symbol, we wait until the end of the
+ assembly before deciding where to put the name (it may be just an
+ external symbol). Otherwise, this is just a debugging symbol and
+ the name should go with the current file. */
+ if (sym_value == (symbolS *) NULL)
+ psym->ecoff_sym.asym.iss = ((str == (const char *) NULL)
+ ? 0
+ : add_string (&cur_file_ptr->strings,
+ cur_file_ptr->str_hash,
+ str,
+ &hash_ptr));
+
+ ++vp->num_allocated;
+
+ if (ECOFF_IS_STAB (&psym->ecoff_sym.asym))
+ return psym;
+
+ /* Save the symbol within the hash table if this is a static
+ item, and it has a name. */
+ if (hash_ptr != (shash_t *) NULL
+ && (type == st_Global || type == st_Static || type == st_Label
+ || type == st_Proc || type == st_StaticProc))
+ hash_ptr->sym_ptr = psym;
+
+ /* push or pop a scope if appropriate. */
+ switch (type)
+ {
+ default:
+ break;
+
+ case st_File: /* beginning of file */
+ case st_Proc: /* procedure */
+ case st_StaticProc: /* static procedure */
+ case st_Block: /* begin scope */
+ pscope = allocate_scope ();
+ pscope->prev = cur_file_ptr->cur_scope;
+ pscope->lsym = psym;
+ pscope->type = type;
+ cur_file_ptr->cur_scope = pscope;
+
+ if (type != st_File)
+ scope_delta = 1;
+
+ /* For every block type except file, struct, union, or
+ enumeration blocks, push a level on the tag stack. We omit
+ file types, so that tags can span file boundaries. */
+ if (type != st_File && storage != sc_Info)
+ {
+ ptag_head = allocate_thead ();
+ ptag_head->first_tag = 0;
+ ptag_head->prev = cur_tag_head;
+ cur_tag_head = ptag_head;
+ }
+ break;
+
+ case st_End:
+ pscope = cur_file_ptr->cur_scope;
+ if (pscope == (scope_t *) NULL)
+ as_fatal (_("too many st_End's"));
+ else
+ {
+ st_t begin_type = (st_t) pscope->lsym->ecoff_sym.asym.st;
+
+ psym->begin_ptr = pscope->lsym;
+
+ if (begin_type != st_File)
+ scope_delta = -1;
+
+ /* Except for file, structure, union, or enumeration end
+ blocks remove all tags created within this scope. */
+ if (begin_type != st_File && storage != sc_Info)
+ {
+ ptag_head = cur_tag_head;
+ cur_tag_head = ptag_head->prev;
+
+ for (ptag = ptag_head->first_tag;
+ ptag != (tag_t *) NULL;
+ ptag = ptag_next)
+ {
+ if (ptag->forward_ref != (forward_t *) NULL)
+ add_unknown_tag (ptag);
+
+ ptag_next = ptag->same_block;
+ ptag->hash_ptr->tag_ptr = ptag->same_name;
+ free_tag (ptag);
+ }
+
+ free_thead (ptag_head);
+ }
+
+ cur_file_ptr->cur_scope = pscope->prev;
+
+ /* block begin gets next sym #. This is set when we know
+ the symbol index value. */
+
+ /* Functions push two or more aux words as follows:
+ 1st word: index+1 of the end symbol (filled in later).
+ 2nd word: type of the function (plus any aux words needed).
+ Also, tie the external pointer back to the function begin symbol. */
+ if (begin_type != st_File && begin_type != st_Block)
+ {
+ symint_t ty;
+ varray_t *svp = &cur_file_ptr->aux_syms;
+
+ pscope->lsym->ecoff_sym.asym.index = add_aux_sym_symint (0);
+ pscope->lsym->index_ptr =
+ &svp->last->datum->aux[svp->objects_last_page - 1];
+ ty = add_aux_sym_tir (&last_func_type_info,
+ hash_no,
+ &cur_file_ptr->thash_head[0]);
+
+/* This seems to be unnecessary. I'm not even sure what it is
+ * intended to do. It's from mips-tfile.
+ * if (last_func_sym_value != (symbolS *) NULL)
+ * {
+ * last_func_sym_value->ifd = cur_file_ptr->file_index;
+ * last_func_sym_value->index = ty;
+ * }
+ */
+ }
+
+ free_scope (pscope);
+ }
+ }
+
+ cur_file_ptr->nested_scopes += scope_delta;
+
+#ifdef ECOFF_DEBUG
+ if (debug && type != st_File
+ && (debug > 2 || type == st_Block || type == st_End
+ || type == st_Proc || type == st_StaticProc))
+ {
+ char *sc_str = sc_to_string (storage);
+ char *st_str = st_to_string (type);
+ int depth = cur_file_ptr->nested_scopes + (scope_delta < 0);
+
+ fprintf (stderr,
+ "\tlsym\tv= %10ld, depth= %2d, sc= %-12s",
+ value, depth, sc_str);
+
+ if (str_start && str_end_p1 - str_start > 0)
+ fprintf (stderr, " st= %-11s name= %.*s\n", st_str, str_end_p1 - str_start, str_start);
+ else
+ {
+ unsigned long len = strlen (st_str);
+ fprintf (stderr, " st= %.*s\n", len-1, st_str);
+ }
+ }
+#endif
+
+ return psym;
+}
+
+/* Add an auxiliary symbol (passing a symint). This is actually used
+ for integral aux types, not just symints. */
+
+static symint_t
+add_aux_sym_symint (aux_word)
+ symint_t aux_word; /* auxiliary information word */
+{
+ register varray_t *vp;
+ register aux_t *aux_ptr;
+
+ if (cur_file_ptr == (efdr_t *) NULL)
+ as_fatal (_("no current file pointer"));
+
+ vp = &cur_file_ptr->aux_syms;
+
+ if (vp->objects_last_page == vp->objects_per_page)
+ add_varray_page (vp);
+
+ aux_ptr = &vp->last->datum->aux[vp->objects_last_page++];
+ aux_ptr->type = aux_isym;
+ aux_ptr->data.isym = aux_word;
+
+ return vp->num_allocated++;
+}
+
+
+/* Add an auxiliary symbol (passing a file/symbol index combo). */
+
+static symint_t
+add_aux_sym_rndx (file_index, sym_index)
+ int file_index;
+ symint_t sym_index;
+{
+ register varray_t *vp;
+ register aux_t *aux_ptr;
+
+ if (cur_file_ptr == (efdr_t *) NULL)
+ as_fatal (_("no current file pointer"));
+
+ vp = &cur_file_ptr->aux_syms;
+
+ if (vp->objects_last_page == vp->objects_per_page)
+ add_varray_page (vp);
+
+ aux_ptr = &vp->last->datum->aux[vp->objects_last_page++];
+ aux_ptr->type = aux_rndx;
+ aux_ptr->data.rndx.rfd = file_index;
+ aux_ptr->data.rndx.index = sym_index;
+
+ return vp->num_allocated++;
+}
+
+/* Add an auxiliary symbol (passing the basic type and possibly
+ type qualifiers). */
+
+static symint_t
+add_aux_sym_tir (t, state, hash_tbl)
+ type_info_t *t; /* current type information */
+ hash_state_t state; /* whether to hash type or not */
+ thash_t **hash_tbl; /* pointer to hash table to use */
+{
+ register varray_t *vp;
+ register aux_t *aux_ptr;
+ static AUXU init_aux;
+ symint_t ret;
+ int i;
+ AUXU aux;
+
+ if (cur_file_ptr == (efdr_t *) NULL)
+ as_fatal (_("no current file pointer"));
+
+ vp = &cur_file_ptr->aux_syms;
+
+ aux = init_aux;
+ aux.ti.bt = (int) t->basic_type;
+ aux.ti.continued = 0;
+ aux.ti.fBitfield = t->bitfield;
+
+ aux.ti.tq0 = (int) t->type_qualifiers[0];
+ aux.ti.tq1 = (int) t->type_qualifiers[1];
+ aux.ti.tq2 = (int) t->type_qualifiers[2];
+ aux.ti.tq3 = (int) t->type_qualifiers[3];
+ aux.ti.tq4 = (int) t->type_qualifiers[4];
+ aux.ti.tq5 = (int) t->type_qualifiers[5];
+
+
+ /* For anything that adds additional information, we must not hash,
+ so check here, and reset our state. */
+
+ if (state != hash_no
+ && (t->type_qualifiers[0] == tq_Array
+ || t->type_qualifiers[1] == tq_Array
+ || t->type_qualifiers[2] == tq_Array
+ || t->type_qualifiers[3] == tq_Array
+ || t->type_qualifiers[4] == tq_Array
+ || t->type_qualifiers[5] == tq_Array
+ || t->basic_type == bt_Struct
+ || t->basic_type == bt_Union
+ || t->basic_type == bt_Enum
+ || t->bitfield
+ || t->num_dims > 0))
+ state = hash_no;
+
+ /* See if we can hash this type, and save some space, but some types
+ can't be hashed (because they contain arrays or continuations),
+ and others can be put into the hash list, but cannot use existing
+ types because other aux entries precede this one. */
+
+ if (state != hash_no)
+ {
+ register thash_t *hash_ptr;
+ register symint_t hi;
+
+ hi = aux.isym & ((1 << HASHBITS) - 1);
+ hi %= THASH_SIZE;
+
+ for (hash_ptr = hash_tbl[hi];
+ hash_ptr != (thash_t *)0;
+ hash_ptr = hash_ptr->next)
+ {
+ if (aux.isym == hash_ptr->type.isym)
+ break;
+ }
+
+ if (hash_ptr != (thash_t *) NULL && state == hash_yes)
+ return hash_ptr->indx;
+
+ if (hash_ptr == (thash_t *) NULL)
+ {
+ hash_ptr = allocate_thash ();
+ hash_ptr->next = hash_tbl[hi];
+ hash_ptr->type = aux;
+ hash_ptr->indx = vp->num_allocated;
+ hash_tbl[hi] = hash_ptr;
+ }
+ }
+
+ /* Everything is set up, add the aux symbol. */
+ if (vp->objects_last_page == vp->objects_per_page)
+ add_varray_page (vp);
+
+ aux_ptr = &vp->last->datum->aux[ vp->objects_last_page++ ];
+ aux_ptr->type = aux_tir;
+ aux_ptr->data = aux;
+
+ ret = vp->num_allocated++;
+
+ /* Add bitfield length if it exists.
+
+ NOTE: Mips documentation claims bitfield goes at the end of the
+ AUX record, but the DECstation compiler emits it here.
+ (This would only make a difference for enum bitfields.)
+
+ Also note: We use the last size given since gcc may emit 2
+ for an enum bitfield. */
+
+ if (t->bitfield)
+ (void) add_aux_sym_symint ((symint_t)t->sizes[t->num_sizes-1]);
+
+
+ /* Add tag information if needed. Structure, union, and enum
+ references add 2 aux symbols: a [file index, symbol index]
+ pointer to the structure type, and the current file index. */
+
+ if (t->basic_type == bt_Struct
+ || t->basic_type == bt_Union
+ || t->basic_type == bt_Enum)
+ {
+ register symint_t file_index = t->tag_ptr->ifd;
+ register localsym_t *sym = t->tag_ptr->sym;
+ register forward_t *forward_ref = allocate_forward ();
+
+ if (sym != (localsym_t *) NULL)
+ {
+ forward_ref->next = sym->forward_ref;
+ sym->forward_ref = forward_ref;
+ }
+ else
+ {
+ forward_ref->next = t->tag_ptr->forward_ref;
+ t->tag_ptr->forward_ref = forward_ref;
+ }
+
+ (void) add_aux_sym_rndx (ST_RFDESCAPE, indexNil);
+ forward_ref->index_ptr
+ = &vp->last->datum->aux[ vp->objects_last_page - 1];
+
+ (void) add_aux_sym_symint (file_index);
+ forward_ref->ifd_ptr
+ = &vp->last->datum->aux[ vp->objects_last_page - 1];
+ }
+
+ /* Add information about array bounds if they exist. */
+ for (i = 0; i < t->num_dims; i++)
+ {
+ (void) add_aux_sym_rndx (ST_RFDESCAPE,
+ cur_file_ptr->int_type);
+
+ (void) add_aux_sym_symint (cur_file_ptr->file_index); /* file index*/
+ (void) add_aux_sym_symint ((symint_t) 0); /* low bound */
+ (void) add_aux_sym_symint (t->dimensions[i] - 1); /* high bound*/
+ (void) add_aux_sym_symint ((t->dimensions[i] == 0) /* stride */
+ ? 0
+ : (t->sizes[i] * 8) / t->dimensions[i]);
+ };
+
+ /* NOTE: Mips documentation claims that the bitfield width goes here.
+ But it needs to be emitted earlier. */
+
+ return ret;
+}
+
+/* Add a tag to the tag table (unless it already exists). */
+
+static tag_t *
+get_tag (tag, sym, basic_type)
+ const char *tag; /* tag name */
+ localsym_t *sym; /* tag start block */
+ bt_t basic_type; /* bt_Struct, bt_Union, or bt_Enum */
+{
+ shash_t *hash_ptr;
+ const char *err;
+ tag_t *tag_ptr;
+
+ if (cur_file_ptr == (efdr_t *) NULL)
+ as_fatal (_("no current file pointer"));
+
+ hash_ptr = (shash_t *) hash_find (tag_hash, tag);
+
+ if (hash_ptr != (shash_t *) NULL
+ && hash_ptr->tag_ptr != (tag_t *) NULL)
+ {
+ tag_ptr = hash_ptr->tag_ptr;
+ if (sym != (localsym_t *) NULL)
+ {
+ tag_ptr->basic_type = basic_type;
+ tag_ptr->ifd = cur_file_ptr->file_index;
+ tag_ptr->sym = sym;
+ }
+ return tag_ptr;
+ }
+
+ if (hash_ptr == (shash_t *) NULL)
+ {
+ char *perm;
+
+ perm = xmalloc ((unsigned long) (strlen (tag) + 1));
+ strcpy (perm, tag);
+ hash_ptr = allocate_shash ();
+ err = hash_insert (tag_hash, perm, (char *) hash_ptr);
+ if (err)
+ as_fatal (_("Inserting \"%s\" into tag hash table: %s"),
+ tag, err);
+ hash_ptr->string = perm;
+ }
+
+ tag_ptr = allocate_tag ();
+ tag_ptr->forward_ref = (forward_t *) NULL;
+ tag_ptr->hash_ptr = hash_ptr;
+ tag_ptr->same_name = hash_ptr->tag_ptr;
+ tag_ptr->basic_type = basic_type;
+ tag_ptr->sym = sym;
+ tag_ptr->ifd = ((sym == (localsym_t *) NULL)
+ ? (symint_t) -1
+ : cur_file_ptr->file_index);
+ tag_ptr->same_block = cur_tag_head->first_tag;
+
+ cur_tag_head->first_tag = tag_ptr;
+ hash_ptr->tag_ptr = tag_ptr;
+
+ return tag_ptr;
+}
+
+/* Add an unknown {struct, union, enum} tag. */
+
+static void
+add_unknown_tag (ptag)
+ tag_t *ptag; /* pointer to tag information */
+{
+ shash_t *hash_ptr = ptag->hash_ptr;
+ char *name = hash_ptr->string;
+ localsym_t *sym;
+ forward_t **pf;
+
+#ifdef ECOFF_DEBUG
+ if (debug > 1)
+ {
+ char *agg_type = "{unknown aggregate type}";
+ switch (ptag->basic_type)
+ {
+ case bt_Struct: agg_type = "struct"; break;
+ case bt_Union: agg_type = "union"; break;
+ case bt_Enum: agg_type = "enum"; break;
+ default: break;
+ }
+
+ fprintf (stderr, "unknown %s %.*s found\n", agg_type,
+ hash_ptr->len, name_start);
+ }
+#endif
+
+ sym = add_ecoff_symbol (name,
+ st_Block,
+ sc_Info,
+ (symbolS *) NULL,
+ (bfd_vma) 0,
+ (symint_t) 0,
+ (symint_t) 0);
+
+ (void) add_ecoff_symbol (name,
+ st_End,
+ sc_Info,
+ (symbolS *) NULL,
+ (bfd_vma) 0,
+ (symint_t) 0,
+ (symint_t) 0);
+
+ for (pf = &sym->forward_ref; *pf != (forward_t *) NULL; pf = &(*pf)->next)
+ ;
+ *pf = ptag->forward_ref;
+}
+
+/* Add a procedure to the current file's list of procedures, and record
+ this is the current procedure. */
+
+static void
+add_procedure (func)
+ char *func; /* func name */
+{
+ register varray_t *vp;
+ register proc_t *new_proc_ptr;
+ symbolS *sym;
+
+#ifdef ECOFF_DEBUG
+ if (debug)
+ fputc ('\n', stderr);
+#endif
+
+ if (cur_file_ptr == (efdr_t *) NULL)
+ as_fatal (_("no current file pointer"));
+
+ vp = &cur_file_ptr->procs;
+
+ if (vp->objects_last_page == vp->objects_per_page)
+ add_varray_page (vp);
+
+ cur_proc_ptr = new_proc_ptr = &vp->last->datum->proc[vp->objects_last_page++];
+
+ if (first_proc_ptr == (proc_t *) NULL)
+ first_proc_ptr = new_proc_ptr;
+
+ vp->num_allocated++;
+
+ new_proc_ptr->pdr.isym = -1;
+ new_proc_ptr->pdr.iline = -1;
+ new_proc_ptr->pdr.lnLow = -1;
+ new_proc_ptr->pdr.lnHigh = -1;
+
+ /* Set the BSF_FUNCTION flag for the symbol. */
+ sym = symbol_find_or_make (func);
+ sym->bsym->flags |= BSF_FUNCTION;
+
+ /* Push the start of the function. */
+ new_proc_ptr->sym = add_ecoff_symbol ((const char *) NULL, st_Proc, sc_Text,
+ sym, (bfd_vma) 0, (symint_t) 0,
+ (symint_t) 0);
+
+ ++proc_cnt;
+
+ /* Fill in the linenos preceding the .ent, if any. */
+ if (noproc_lineno != (lineno_list_t *) NULL)
+ {
+ lineno_list_t *l;
+
+ for (l = noproc_lineno; l != (lineno_list_t *) NULL; l = l->next)
+ l->proc = new_proc_ptr;
+ *last_lineno_ptr = noproc_lineno;
+ while (*last_lineno_ptr != NULL)
+ {
+ last_lineno = *last_lineno_ptr;
+ last_lineno_ptr = &last_lineno->next;
+ }
+ noproc_lineno = (lineno_list_t *) NULL;
+ }
+}
+
+symbolS *
+ecoff_get_cur_proc_sym ()
+{
+ return (cur_proc_ptr ? cur_proc_ptr->sym->as_sym : NULL);
+}
+
+/* Add a new filename, and set up all of the file relative
+ virtual arrays (strings, symbols, aux syms, etc.). Record
+ where the current file structure lives. */
+
+static void
+add_file (file_name, indx, fake)
+ const char *file_name; /* file name */
+ int indx;
+ int fake;
+{
+ register int first_ch;
+ register efdr_t *fil_ptr;
+
+#ifdef ECOFF_DEBUG
+ if (debug)
+ fprintf (stderr, "\tfile\t%.*s\n", len, file_start);
+#endif
+
+ /* If the file name is NULL, then no .file symbol appeared, and we
+ want to use the actual file name. */
+ if (file_name == (const char *) NULL)
+ {
+ char *file;
+
+ if (first_file != (efdr_t *) NULL)
+ as_fatal (_("fake .file after real one"));
+ as_where (&file, (unsigned int *) NULL);
+ file_name = (const char *) file;
+
+ /* Automatically generate ECOFF debugging information, since I
+ think that's what other ECOFF assemblers do. We don't do
+ this if we see a .file directive with a string, since that
+ implies that some sort of debugging information is being
+ provided. */
+ if (! symbol_table_frozen && debug_type == DEBUG_NONE)
+ debug_type = DEBUG_ECOFF;
+ }
+
+#ifndef NO_LISTING
+ if (listing)
+ listing_source_file (file_name);
+#endif
+
+ current_stabs_filename = file_name;
+
+ /* If we're creating stabs, then we don't actually make a new FDR.
+ Instead, we just create a stabs symbol. */
+ if (stabs_seen)
+ {
+ (void) add_ecoff_symbol (file_name, st_Nil, sc_Nil,
+ symbol_new ("L0\001", now_seg,
+ (valueT) frag_now_fix (),
+ frag_now),
+ (bfd_vma) 0, 0, ECOFF_MARK_STAB (N_SOL));
+ return;
+ }
+
+ first_ch = *file_name;
+
+ /* FIXME: We can't safely merge files which have line number
+ information (fMerge will be zero in this case). Otherwise, we
+ get incorrect line number debugging info. See for instance
+ ecoff_build_lineno, which will end up setting all file->fdr.*
+ fields multiple times, resulting in incorrect debug info. In
+ order to make this work right, all line number and symbol info
+ for the same source file has to be adjacent in the object file,
+ so that a single file descriptor can be used to point to them.
+ This would require maintaining file specific lists of line
+ numbers and symbols for each file, so that they can be merged
+ together (or output together) when two .file pseudo-ops are
+ merged into one file descriptor. */
+
+ /* See if the file has already been created. */
+ for (fil_ptr = first_file;
+ fil_ptr != (efdr_t *) NULL;
+ fil_ptr = fil_ptr->next_file)
+ {
+ if (first_ch == fil_ptr->name[0]
+ && strcmp (file_name, fil_ptr->name) == 0
+ && fil_ptr->fdr.fMerge)
+ {
+ cur_file_ptr = fil_ptr;
+ if (! fake)
+ cur_file_ptr->fake = 0;
+ break;
+ }
+ }
+
+ /* If this is a new file, create it. */
+ if (fil_ptr == (efdr_t *) NULL)
+ {
+ if (file_desc.objects_last_page == file_desc.objects_per_page)
+ add_varray_page (&file_desc);
+
+ fil_ptr = cur_file_ptr =
+ &file_desc.last->datum->file[file_desc.objects_last_page++];
+ *fil_ptr = init_file;
+
+ fil_ptr->file_index = current_file_idx++;
+ ++file_desc.num_allocated;
+
+ fil_ptr->fake = fake;
+
+ /* Allocate the string hash table. */
+ fil_ptr->str_hash = hash_new ();
+
+ /* Make sure 0 byte in string table is null */
+ add_string (&fil_ptr->strings,
+ fil_ptr->str_hash,
+ "",
+ (shash_t **)0);
+
+ if (strlen (file_name) > PAGE_USIZE - 2)
+ as_fatal (_("Filename goes over one page boundary."));
+
+ /* Push the start of the filename. We assume that the filename
+ will be stored at string offset 1. */
+ (void) add_ecoff_symbol (file_name, st_File, sc_Text,
+ (symbolS *) NULL, (bfd_vma) 0,
+ (symint_t) 0, (symint_t) 0);
+ fil_ptr->fdr.rss = 1;
+ fil_ptr->name = &fil_ptr->strings.last->datum->byte[1];
+
+ /* Update the linked list of file descriptors. */
+ *last_file_ptr = fil_ptr;
+ last_file_ptr = &fil_ptr->next_file;
+
+ /* Add void & int types to the file (void should be first to catch
+ errant 0's within the index fields). */
+ fil_ptr->void_type = add_aux_sym_tir (&void_type_info,
+ hash_yes,
+ &cur_file_ptr->thash_head[0]);
+
+ fil_ptr->int_type = add_aux_sym_tir (&int_type_info,
+ hash_yes,
+ &cur_file_ptr->thash_head[0]);
+ }
+}
+
+/* This function is called when the assembler notices a preprocessor
+ directive switching to a new file. This will not happen in
+ compiler output, only in hand coded assembler. */
+
+void
+ecoff_new_file (name)
+ const char *name;
+{
+ if (cur_file_ptr != NULL && strcmp (cur_file_ptr->name, name) == 0)
+ return;
+ add_file (name, 0, 0);
+
+ /* This is a hand coded assembler file, so automatically turn on
+ debugging information. */
+ if (debug_type == DEBUG_NONE)
+ debug_type = DEBUG_ECOFF;
+}
+
+#ifdef ECOFF_DEBUG
+
+/* Convert storage class to string. */
+
+static char *
+sc_to_string(storage_class)
+ sc_t storage_class;
+{
+ switch(storage_class)
+ {
+ case sc_Nil: return "Nil,";
+ case sc_Text: return "Text,";
+ case sc_Data: return "Data,";
+ case sc_Bss: return "Bss,";
+ case sc_Register: return "Register,";
+ case sc_Abs: return "Abs,";
+ case sc_Undefined: return "Undefined,";
+ case sc_CdbLocal: return "CdbLocal,";
+ case sc_Bits: return "Bits,";
+ case sc_CdbSystem: return "CdbSystem,";
+ case sc_RegImage: return "RegImage,";
+ case sc_Info: return "Info,";
+ case sc_UserStruct: return "UserStruct,";
+ case sc_SData: return "SData,";
+ case sc_SBss: return "SBss,";
+ case sc_RData: return "RData,";
+ case sc_Var: return "Var,";
+ case sc_Common: return "Common,";
+ case sc_SCommon: return "SCommon,";
+ case sc_VarRegister: return "VarRegister,";
+ case sc_Variant: return "Variant,";
+ case sc_SUndefined: return "SUndefined,";
+ case sc_Init: return "Init,";
+ case sc_Max: return "Max,";
+ }
+
+ return "???,";
+}
+
+#endif /* DEBUG */
+
+#ifdef ECOFF_DEBUG
+
+/* Convert symbol type to string. */
+
+static char *
+st_to_string(symbol_type)
+ st_t symbol_type;
+{
+ switch(symbol_type)
+ {
+ case st_Nil: return "Nil,";
+ case st_Global: return "Global,";
+ case st_Static: return "Static,";
+ case st_Param: return "Param,";
+ case st_Local: return "Local,";
+ case st_Label: return "Label,";
+ case st_Proc: return "Proc,";
+ case st_Block: return "Block,";
+ case st_End: return "End,";
+ case st_Member: return "Member,";
+ case st_Typedef: return "Typedef,";
+ case st_File: return "File,";
+ case st_RegReloc: return "RegReloc,";
+ case st_Forward: return "Forward,";
+ case st_StaticProc: return "StaticProc,";
+ case st_Constant: return "Constant,";
+ case st_Str: return "String,";
+ case st_Number: return "Number,";
+ case st_Expr: return "Expr,";
+ case st_Type: return "Type,";
+ case st_Max: return "Max,";
+ }
+
+ return "???,";
+}
+
+#endif /* DEBUG */
+
+/* Parse .begin directives which have a label as the first argument
+ which gives the location of the start of the block. */
+
+void
+ecoff_directive_begin (ignore)
+ int ignore;
+{
+ char *name;
+ char name_end;
+
+ if (cur_file_ptr == (efdr_t *) NULL)
+ {
+ as_warn (_(".begin directive without a preceding .file directive"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ if (cur_proc_ptr == (proc_t *) NULL)
+ {
+ as_warn (_(".begin directive without a preceding .ent directive"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ name = input_line_pointer;
+ name_end = get_symbol_end ();
+
+ (void) add_ecoff_symbol ((const char *) NULL, st_Block, sc_Text,
+ symbol_find_or_make (name),
+ (bfd_vma) 0, (symint_t) 0, (symint_t) 0);
+
+ *input_line_pointer = name_end;
+
+ /* The line number follows, but we don't use it. */
+ (void) get_absolute_expression ();
+ demand_empty_rest_of_line ();
+}
+
+/* Parse .bend directives which have a label as the first argument
+ which gives the location of the end of the block. */
+
+void
+ecoff_directive_bend (ignore)
+ int ignore;
+{
+ char *name;
+ char name_end;
+ symbolS *endsym;
+
+ if (cur_file_ptr == (efdr_t *) NULL)
+ {
+ as_warn (_(".bend directive without a preceding .file directive"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ if (cur_proc_ptr == (proc_t *) NULL)
+ {
+ as_warn (_(".bend directive without a preceding .ent directive"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ name = input_line_pointer;
+ name_end = get_symbol_end ();
+
+ /* The value is the distance between the .bend directive and the
+ corresponding symbol. We fill in the offset when we write out
+ the symbol. */
+ endsym = symbol_find (name);
+ if (endsym == (symbolS *) NULL)
+ as_warn (_(".bend directive names unknown symbol"));
+ else
+ (void) add_ecoff_symbol ((const char *) NULL, st_End, sc_Text, endsym,
+ (bfd_vma) 0, (symint_t) 0, (symint_t) 0);
+
+ *input_line_pointer = name_end;
+
+ /* The line number follows, but we don't use it. */
+ (void) get_absolute_expression ();
+ demand_empty_rest_of_line ();
+}
+
+/* COFF debugging information is provided as a series of directives
+ (.def, .scl, etc.). We build up information as we read the
+ directives in the following static variables, and file it away when
+ we reach the .endef directive. */
+static char *coff_sym_name;
+static type_info_t coff_type;
+static sc_t coff_storage_class;
+static st_t coff_symbol_typ;
+static int coff_is_function;
+static char *coff_tag;
+static valueT coff_value;
+static symbolS *coff_sym_value;
+static bfd_vma coff_sym_addend;
+static int coff_inside_enumeration;
+
+/* Handle a .def directive: start defining a symbol. */
+
+void
+ecoff_directive_def (ignore)
+ int ignore;
+{
+ char *name;
+ char name_end;
+
+ ecoff_debugging_seen = 1;
+
+ SKIP_WHITESPACE ();
+
+ name = input_line_pointer;
+ name_end = get_symbol_end ();
+
+ if (coff_sym_name != (char *) NULL)
+ as_warn (_(".def pseudo-op used inside of .def/.endef; ignored"));
+ else if (*name == '\0')
+ as_warn (_("Empty symbol name in .def; ignored"));
+ else
+ {
+ if (coff_sym_name != (char *) NULL)
+ free (coff_sym_name);
+ if (coff_tag != (char *) NULL)
+ free (coff_tag);
+ coff_sym_name = (char *) xmalloc ((unsigned long) (strlen (name) + 1));
+ strcpy (coff_sym_name, name);
+ coff_type = type_info_init;
+ coff_storage_class = sc_Nil;
+ coff_symbol_typ = st_Nil;
+ coff_is_function = 0;
+ coff_tag = (char *) NULL;
+ coff_value = 0;
+ coff_sym_value = (symbolS *) NULL;
+ coff_sym_addend = 0;
+ }
+
+ *input_line_pointer = name_end;
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle a .dim directive, used to give dimensions for an array. The
+ arguments are comma separated numbers. mips-tfile assumes that
+ there will not be more than 6 dimensions, and gdb won't read any
+ more than that anyhow, so I will also make that assumption. */
+
+void
+ecoff_directive_dim (ignore)
+ int ignore;
+{
+ int dimens[N_TQ];
+ int i;
+
+ if (coff_sym_name == (char *) NULL)
+ {
+ as_warn (_(".dim pseudo-op used outside of .def/.endef; ignored"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ for (i = 0; i < N_TQ; i++)
+ {
+ SKIP_WHITESPACE ();
+ dimens[i] = get_absolute_expression ();
+ if (*input_line_pointer == ',')
+ ++input_line_pointer;
+ else
+ {
+ if (*input_line_pointer != '\n'
+ && *input_line_pointer != ';')
+ as_warn (_("Badly formed .dim directive"));
+ break;
+ }
+ }
+
+ if (i == N_TQ)
+ --i;
+
+ /* The dimensions are stored away in reverse order. */
+ for (; i >= 0; i--)
+ {
+ if (coff_type.num_dims >= N_TQ)
+ {
+ as_warn (_("Too many .dim entries"));
+ break;
+ }
+ coff_type.dimensions[coff_type.num_dims] = dimens[i];
+ ++coff_type.num_dims;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle a .scl directive, which sets the COFF storage class of the
+ symbol. */
+
+void
+ecoff_directive_scl (ignore)
+ int ignore;
+{
+ long val;
+
+ if (coff_sym_name == (char *) NULL)
+ {
+ as_warn (_(".scl pseudo-op used outside of .def/.endef; ignored"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ val = get_absolute_expression ();
+
+ coff_symbol_typ = map_coff_sym_type[val];
+ coff_storage_class = map_coff_storage[val];
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle a .size directive. For some reason mips-tfile.c thinks that
+ .size can have multiple arguments. We humor it, although gcc will
+ never generate more than one argument. */
+
+void
+ecoff_directive_size (ignore)
+ int ignore;
+{
+ int sizes[N_TQ];
+ int i;
+
+ if (coff_sym_name == (char *) NULL)
+ {
+ as_warn (_(".size pseudo-op used outside of .def/.endef; ignored"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ for (i = 0; i < N_TQ; i++)
+ {
+ SKIP_WHITESPACE ();
+ sizes[i] = get_absolute_expression ();
+ if (*input_line_pointer == ',')
+ ++input_line_pointer;
+ else
+ {
+ if (*input_line_pointer != '\n'
+ && *input_line_pointer != ';')
+ as_warn (_("Badly formed .size directive"));
+ break;
+ }
+ }
+
+ if (i == N_TQ)
+ --i;
+
+ /* The sizes are stored away in reverse order. */
+ for (; i >= 0; i--)
+ {
+ if (coff_type.num_sizes >= N_TQ)
+ {
+ as_warn (_("Too many .size entries"));
+ break;
+ }
+ coff_type.sizes[coff_type.num_sizes] = sizes[i];
+ ++coff_type.num_sizes;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the .type directive, which gives the COFF type of the
+ symbol. */
+
+void
+ecoff_directive_type (ignore)
+ int ignore;
+{
+ long val;
+ tq_t *tq_ptr;
+ tq_t *tq_shft;
+
+ if (coff_sym_name == (char *) NULL)
+ {
+ as_warn (_(".type pseudo-op used outside of .def/.endef; ignored"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ val = get_absolute_expression ();
+
+ coff_type.orig_type = BTYPE (val);
+ coff_type.basic_type = map_coff_types[coff_type.orig_type];
+
+ tq_ptr = &coff_type.type_qualifiers[N_TQ];
+ while (val &~ N_BTMASK)
+ {
+ if (tq_ptr == &coff_type.type_qualifiers[0])
+ {
+ /* FIXME: We could handle this by setting the continued bit.
+ There would still be a limit: the .type argument can not
+ be infinite. */
+ as_warn (_("The type of %s is too complex; it will be simplified"),
+ coff_sym_name);
+ break;
+ }
+ if (ISPTR (val))
+ *--tq_ptr = tq_Ptr;
+ else if (ISFCN (val))
+ *--tq_ptr = tq_Proc;
+ else if (ISARY (val))
+ *--tq_ptr = tq_Array;
+ else
+ as_fatal (_("Unrecognized .type argument"));
+
+ val = DECREF (val);
+ }
+
+ tq_shft = &coff_type.type_qualifiers[0];
+ while (tq_ptr != &coff_type.type_qualifiers[N_TQ])
+ *tq_shft++ = *tq_ptr++;
+
+ if (tq_shft != &coff_type.type_qualifiers[0] && tq_shft[-1] == tq_Proc)
+ {
+ /* If this is a function, ignore it, so that we don't get two
+ entries (one from the .ent, and one for the .def that
+ precedes it). Save the type information so that the end
+ block can properly add it after the begin block index. For
+ MIPS knows what reason, we must strip off the function type
+ at this point. */
+ coff_is_function = 1;
+ tq_shft[-1] = tq_Nil;
+ }
+
+ while (tq_shft != &coff_type.type_qualifiers[N_TQ])
+ *tq_shft++ = tq_Nil;
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the .tag directive, which gives the name of a structure,
+ union or enum. */
+
+void
+ecoff_directive_tag (ignore)
+ int ignore;
+{
+ char *name;
+ char name_end;
+
+ if (coff_sym_name == (char *) NULL)
+ {
+ as_warn (_(".tag pseudo-op used outside of .def/.endef; ignored"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ name = input_line_pointer;
+ name_end = get_symbol_end ();
+
+ coff_tag = (char *) xmalloc ((unsigned long) (strlen (name) + 1));
+ strcpy (coff_tag, name);
+
+ *input_line_pointer = name_end;
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the .val directive, which gives the value of the symbol. It
+ may be the name of a static or global symbol. */
+
+void
+ecoff_directive_val (ignore)
+ int ignore;
+{
+ expressionS exp;
+
+ if (coff_sym_name == (char *) NULL)
+ {
+ as_warn (_(".val pseudo-op used outside of .def/.endef; ignored"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ expression (&exp);
+ if (exp.X_op != O_constant && exp.X_op != O_symbol)
+ {
+ as_bad (_(".val expression is too copmlex"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ if (exp.X_op == O_constant)
+ coff_value = exp.X_add_number;
+ else
+ {
+ coff_sym_value = exp.X_add_symbol;
+ coff_sym_addend = exp.X_add_number;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the .endef directive, which terminates processing of COFF
+ debugging information for a symbol. */
+
+void
+ecoff_directive_endef (ignore)
+ int ignore;
+{
+ char *name;
+ symint_t indx;
+ localsym_t *sym;
+
+ demand_empty_rest_of_line ();
+
+ if (coff_sym_name == (char *) NULL)
+ {
+ as_warn (_(".endef pseudo-op used before .def; ignored"));
+ return;
+ }
+
+ name = coff_sym_name;
+ coff_sym_name = (char *) NULL;
+
+ /* If the symbol is a static or external, we have already gotten the
+ appropriate type and class, so make sure we don't override those
+ values. This is needed because there are some type and classes
+ that are not in COFF, such as short data, etc. */
+ if (coff_sym_value != (symbolS *) NULL)
+ {
+ coff_symbol_typ = st_Nil;
+ coff_storage_class = sc_Nil;
+ }
+
+ coff_type.extra_sizes = coff_tag != (char *) NULL;
+ if (coff_type.num_dims > 0)
+ {
+ int diff = coff_type.num_dims - coff_type.num_sizes;
+ int i = coff_type.num_dims - 1;
+ int j;
+
+ if (coff_type.num_sizes != 1 || diff < 0)
+ {
+ as_warn (_("Bad COFF debugging info"));
+ return;
+ }
+
+ /* If this is an array, make sure the same number of dimensions
+ and sizes were passed, creating extra sizes for multiply
+ dimensioned arrays if not passed. */
+ coff_type.extra_sizes = 0;
+ if (diff)
+ {
+ j = (sizeof (coff_type.sizes) / sizeof (coff_type.sizes[0])) - 1;
+ while (j >= 0)
+ {
+ coff_type.sizes[j] = (((j - diff) >= 0)
+ ? coff_type.sizes[j - diff]
+ : 0);
+ j--;
+ }
+
+ coff_type.num_sizes = i + 1;
+ for (i--; i >= 0; i--)
+ coff_type.sizes[i] = (coff_type.dimensions[i + 1] == 0
+ ? 0
+ : (coff_type.sizes[i + 1]
+ / coff_type.dimensions[i + 1]));
+ }
+ }
+ else if (coff_symbol_typ == st_Member
+ && coff_type.num_sizes - coff_type.extra_sizes == 1)
+ {
+ /* Is this a bitfield? This is indicated by a structure memeber
+ having a size field that isn't an array. */
+ coff_type.bitfield = 1;
+ }
+
+ /* Except for enumeration members & begin/ending of scopes, put the
+ type word in the aux. symbol table. */
+ if (coff_symbol_typ == st_Block || coff_symbol_typ == st_End)
+ indx = 0;
+ else if (coff_inside_enumeration)
+ indx = cur_file_ptr->void_type;
+ else
+ {
+ if (coff_type.basic_type == bt_Struct
+ || coff_type.basic_type == bt_Union
+ || coff_type.basic_type == bt_Enum)
+ {
+ if (coff_tag == (char *) NULL)
+ {
+ as_warn (_("No tag specified for %s"), name);
+ return;
+ }
+
+ coff_type.tag_ptr = get_tag (coff_tag, (localsym_t *) NULL,
+ coff_type.basic_type);
+ }
+
+ if (coff_is_function)
+ {
+ last_func_type_info = coff_type;
+ last_func_sym_value = coff_sym_value;
+ return;
+ }
+
+ indx = add_aux_sym_tir (&coff_type,
+ hash_yes,
+ &cur_file_ptr->thash_head[0]);
+ }
+
+ /* Do any last minute adjustments that are necessary. */
+ switch (coff_symbol_typ)
+ {
+ default:
+ break;
+
+ /* For the beginning of structs, unions, and enumerations, the
+ size info needs to be passed in the value field. */
+ case st_Block:
+ if (coff_type.num_sizes - coff_type.num_dims - coff_type.extra_sizes
+ != 1)
+ {
+ as_warn (_("Bad COFF debugging information"));
+ return;
+ }
+ else
+ coff_value = coff_type.sizes[0];
+
+ coff_inside_enumeration = (coff_type.orig_type == T_ENUM);
+ break;
+
+ /* For the end of structs, unions, and enumerations, omit the
+ name which is always ".eos". This needs to be done last, so
+ that any error reporting above gives the correct name. */
+ case st_End:
+ free (name);
+ name = (char *) NULL;
+ coff_value = 0;
+ coff_inside_enumeration = 0;
+ break;
+
+ /* Members of structures and unions that aren't bitfields, need
+ to adjust the value from a byte offset to a bit offset.
+ Members of enumerations do not have the value adjusted, and
+ can be distinguished by indx == indexNil. For enumerations,
+ update the maximum enumeration value. */
+ case st_Member:
+ if (! coff_type.bitfield && ! coff_inside_enumeration)
+ coff_value *= 8;
+
+ break;
+ }
+
+ /* Add the symbol. */
+ sym = add_ecoff_symbol (name,
+ coff_symbol_typ,
+ coff_storage_class,
+ coff_sym_value,
+ coff_sym_addend,
+ (symint_t) coff_value,
+ indx);
+
+ /* deal with struct, union, and enum tags. */
+ if (coff_symbol_typ == st_Block)
+ {
+ /* Create or update the tag information. */
+ tag_t *tag_ptr = get_tag (name,
+ sym,
+ coff_type.basic_type);
+ forward_t **pf;
+
+ /* Remember any forward references. */
+ for (pf = &sym->forward_ref;
+ *pf != (forward_t *) NULL;
+ pf = &(*pf)->next)
+ ;
+ *pf = tag_ptr->forward_ref;
+ tag_ptr->forward_ref = (forward_t *) NULL;
+ }
+}
+
+/* Parse .end directives. */
+
+void
+ecoff_directive_end (ignore)
+ int ignore;
+{
+ char *name;
+ char name_end;
+ register int ch;
+ symbolS *ent;
+
+ if (cur_file_ptr == (efdr_t *) NULL)
+ {
+ as_warn (_(".end directive without a preceding .file directive"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ if (cur_proc_ptr == (proc_t *) NULL)
+ {
+ as_warn (_(".end directive without a preceding .ent directive"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ name = input_line_pointer;
+ name_end = get_symbol_end ();
+
+ ch = *name;
+ if (! is_name_beginner (ch))
+ {
+ as_warn (_(".end directive has no name"));
+ *input_line_pointer = name_end;
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ /* The value is the distance between the .end directive and the
+ corresponding symbol. We create a fake symbol to hold the
+ current location, and put in the offset when we write out the
+ symbol. */
+ ent = symbol_find (name);
+ if (ent == (symbolS *) NULL)
+ as_warn (_(".end directive names unknown symbol"));
+ else
+ (void) add_ecoff_symbol ((const char *) NULL, st_End, sc_Text,
+ symbol_new ("L0\001", now_seg,
+ (valueT) frag_now_fix (),
+ frag_now),
+ (bfd_vma) 0, (symint_t) 0, (symint_t) 0);
+
+ cur_proc_ptr = (proc_t *) NULL;
+
+ *input_line_pointer = name_end;
+ demand_empty_rest_of_line ();
+}
+
+/* Parse .ent directives. */
+
+void
+ecoff_directive_ent (ignore)
+ int ignore;
+{
+ char *name;
+ char name_end;
+ register int ch;
+
+ if (cur_file_ptr == (efdr_t *) NULL)
+ add_file ((const char *) NULL, 0, 1);
+
+ if (cur_proc_ptr != (proc_t *) NULL)
+ {
+ as_warn (_("second .ent directive found before .end directive"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ name = input_line_pointer;
+ name_end = get_symbol_end ();
+
+ ch = *name;
+ if (! is_name_beginner (ch))
+ {
+ as_warn (_(".ent directive has no name"));
+ *input_line_pointer = name_end;
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ add_procedure (name);
+
+ *input_line_pointer = name_end;
+
+ /* The .ent directive is sometimes followed by a number. I'm not
+ really sure what the number means. I don't see any way to store
+ the information in the PDR. The Irix 4 assembler seems to ignore
+ the information. */
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == ',')
+ {
+ ++input_line_pointer;
+ SKIP_WHITESPACE ();
+ }
+ if (isdigit (*input_line_pointer) || *input_line_pointer == '-')
+ (void) get_absolute_expression ();
+
+ demand_empty_rest_of_line ();
+}
+
+/* Parse .extern directives. */
+
+void
+ecoff_directive_extern (ignore)
+ int ignore;
+{
+ char *name;
+ int c;
+ symbolS *symbolp;
+ valueT size;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ symbolp = symbol_find_or_make (name);
+ *input_line_pointer = c;
+
+ S_SET_EXTERNAL (symbolp);
+
+ if (*input_line_pointer == ',')
+ ++input_line_pointer;
+ size = get_absolute_expression ();
+
+ symbolp->ecoff_extern_size = size;
+}
+
+/* Parse .file directives. */
+
+void
+ecoff_directive_file (ignore)
+ int ignore;
+{
+ int indx;
+ char *name;
+ int len;
+
+ if (cur_proc_ptr != (proc_t *) NULL)
+ {
+ as_warn (_("No way to handle .file within .ent/.end section"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ indx = (int) get_absolute_expression ();
+
+ /* FIXME: we don't have to save the name here. */
+ name = demand_copy_C_string (&len);
+
+ add_file (name, indx - 1, 0);
+
+ demand_empty_rest_of_line ();
+}
+
+/* Parse .fmask directives. */
+
+void
+ecoff_directive_fmask (ignore)
+ int ignore;
+{
+ long val;
+
+ if (cur_proc_ptr == (proc_t *) NULL)
+ {
+ as_warn (_(".fmask outside of .ent"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ if (get_absolute_expression_and_terminator (&val) != ',')
+ {
+ as_warn (_("Bad .fmask directive"));
+ --input_line_pointer;
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ cur_proc_ptr->pdr.fregmask = val;
+ cur_proc_ptr->pdr.fregoffset = get_absolute_expression ();
+
+ demand_empty_rest_of_line ();
+}
+
+/* Parse .frame directives. */
+
+void
+ecoff_directive_frame (ignore)
+ int ignore;
+{
+ long val;
+
+ if (cur_proc_ptr == (proc_t *) NULL)
+ {
+ as_warn (_(".frame outside of .ent"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ cur_proc_ptr->pdr.framereg = tc_get_register (1);
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer++ != ','
+ || get_absolute_expression_and_terminator (&val) != ',')
+ {
+ as_warn (_("Bad .frame directive"));
+ --input_line_pointer;
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ cur_proc_ptr->pdr.frameoffset = val;
+
+ cur_proc_ptr->pdr.pcreg = tc_get_register (0);
+
+#if 0 /* Alpha-OSF1 adds "the offset of saved $a0 from $sp", according
+ to Sandro. I don't yet know where this value should be stored, if
+ anywhere. */
+ demand_empty_rest_of_line ();
+#else
+ s_ignore (42);
+#endif
+}
+
+/* Parse .mask directives. */
+
+void
+ecoff_directive_mask (ignore)
+ int ignore;
+{
+ long val;
+
+ if (cur_proc_ptr == (proc_t *) NULL)
+ {
+ as_warn (_(".mask outside of .ent"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ if (get_absolute_expression_and_terminator (&val) != ',')
+ {
+ as_warn (_("Bad .mask directive"));
+ --input_line_pointer;
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ cur_proc_ptr->pdr.regmask = val;
+ cur_proc_ptr->pdr.regoffset = get_absolute_expression ();
+
+ demand_empty_rest_of_line ();
+}
+
+/* Parse .loc directives. */
+
+void
+ecoff_directive_loc (ignore)
+ int ignore;
+{
+ lineno_list_t *list;
+ symint_t lineno;
+
+ if (cur_file_ptr == (efdr_t *) NULL)
+ {
+ as_warn (_(".loc before .file"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ if (now_seg != text_section)
+ {
+ as_warn (_(".loc outside of .text"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ /* Skip the file number. */
+ SKIP_WHITESPACE ();
+ get_absolute_expression ();
+ SKIP_WHITESPACE ();
+
+ lineno = get_absolute_expression ();
+
+#ifndef NO_LISTING
+ if (listing)
+ listing_source_line (lineno);
+#endif
+
+ /* If we're building stabs, then output a special label rather than
+ ECOFF line number info. */
+ if (stabs_seen)
+ {
+ (void) add_ecoff_symbol ((char *) NULL, st_Label, sc_Text,
+ symbol_new ("L0\001", now_seg,
+ (valueT) frag_now_fix (),
+ frag_now),
+ (bfd_vma) 0, 0, lineno);
+ return;
+ }
+
+ list = allocate_lineno_list ();
+
+ list->next = (lineno_list_t *) NULL;
+ list->file = cur_file_ptr;
+ list->proc = cur_proc_ptr;
+ list->frag = frag_now;
+ list->paddr = frag_now_fix ();
+ list->lineno = lineno;
+
+ /* We don't want to merge files which have line numbers. */
+ cur_file_ptr->fdr.fMerge = 0;
+
+ /* A .loc directive will sometimes appear before a .ent directive,
+ which means that cur_proc_ptr will be NULL here. Arrange to
+ patch this up. */
+ if (cur_proc_ptr == (proc_t *) NULL)
+ {
+ lineno_list_t **pl;
+
+ pl = &noproc_lineno;
+ while (*pl != (lineno_list_t *) NULL)
+ pl = &(*pl)->next;
+ *pl = list;
+ }
+ else
+ {
+ last_lineno = list;
+ *last_lineno_ptr = list;
+ last_lineno_ptr = &list->next;
+ }
+}
+
+/* The MIPS assembler sometimes inserts nop instructions in the
+ instruction stream. When this happens, we must patch up the .loc
+ information so that it points to the instruction after the nop. */
+
+void
+ecoff_fix_loc (old_frag, old_frag_offset)
+ fragS *old_frag;
+ unsigned long old_frag_offset;
+{
+ if (last_lineno != NULL
+ && last_lineno->frag == old_frag
+ && last_lineno->paddr == old_frag_offset)
+ {
+ last_lineno->frag = frag_now;
+ last_lineno->paddr = frag_now_fix ();
+ }
+}
+
+/* Make sure the @stabs symbol is emitted. */
+
+static void
+mark_stabs (ignore)
+ int ignore;
+{
+ if (! stabs_seen)
+ {
+ /* Add a dummy @stabs dymbol. */
+ stabs_seen = 1;
+ (void) add_ecoff_symbol (stabs_symbol, stNil, scInfo,
+ (symbolS *) NULL,
+ (bfd_vma) 0, (symint_t) -1,
+ ECOFF_MARK_STAB (0));
+ }
+}
+
+/* Parse .weakext directives. */
+#ifndef TC_MIPS
+/* For TC_MIPS use the version in tc-mips.c. */
+void
+ecoff_directive_weakext (ignore)
+ int ignore;
+{
+ char *name;
+ int c;
+ symbolS *symbolP;
+ expressionS exp;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ symbolP = symbol_find_or_make (name);
+ *input_line_pointer = c;
+
+ SKIP_WHITESPACE ();
+
+ if (*input_line_pointer == ',')
+ {
+ if (S_IS_DEFINED (symbolP))
+ {
+ as_bad (_("Ignoring attempt to redefine symbol `%s'."),
+ S_GET_NAME (symbolP));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ ++input_line_pointer;
+ SKIP_WHITESPACE ();
+ if (! is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ expression (&exp);
+ if (exp.X_op != O_symbol)
+ {
+ as_bad (_("bad .weakext directive"));
+ ignore_rest_of_line();
+ return;
+ }
+ symbolP->sy_value = exp;
+ }
+ }
+
+ S_SET_WEAK (symbolP);
+
+ demand_empty_rest_of_line ();
+}
+#endif /* not TC_MIPS */
+
+/* Handle .stabs directives. The actual parsing routine is done by a
+ generic routine. This routine is called via OBJ_PROCESS_STAB.
+ When this is called, input_line_pointer will be pointing at the
+ value field of the stab.
+
+ .stabs directives have five fields:
+ "string" a string, encoding the type information.
+ code a numeric code, defined in <stab.h>
+ 0 a zero
+ desc a zero or line number
+ value a numeric value or an address.
+
+ If the value is relocatable, we transform this into:
+ iss points as an index into string space
+ value value from lookup of the name
+ st st from lookup of the name
+ sc sc from lookup of the name
+ index code|CODE_MASK
+
+ If the value is not relocatable, we transform this into:
+ iss points as an index into string space
+ value value
+ st st_Nil
+ sc sc_Nil
+ index code|CODE_MASK
+
+ .stabn directives have four fields (string is null):
+ code a numeric code, defined in <stab.h>
+ 0 a zero
+ desc a zero or a line number
+ value a numeric value or an address. */
+
+void
+ecoff_stab (sec, what, string, type, other, desc)
+ segT sec;
+ int what;
+ const char *string;
+ int type;
+ int other;
+ int desc;
+{
+ efdr_t *save_file_ptr = cur_file_ptr;
+ symbolS *sym;
+ symint_t value;
+ bfd_vma addend;
+ st_t st;
+ sc_t sc;
+ symint_t indx;
+ localsym_t *hold = NULL;
+
+ ecoff_debugging_seen = 1;
+
+ /* We don't handle .stabd. */
+ if (what != 's' && what != 'n')
+ {
+ as_bad (_(".stab%c is not supported"), what);
+ return;
+ }
+
+ /* A .stabn uses a null name, not an empty string. */
+ if (what == 'n')
+ string = NULL;
+
+ /* We ignore the other field. */
+ if (other != 0)
+ as_warn (_(".stab%c: ignoring non-zero other field"), what);
+
+ /* Make sure we have a current file. */
+ if (cur_file_ptr == (efdr_t *) NULL)
+ {
+ add_file ((const char *) NULL, 0, 1);
+ save_file_ptr = cur_file_ptr;
+ }
+
+ /* For stabs in ECOFF, the first symbol must be @stabs. This is a
+ signal to gdb. */
+ if (stabs_seen == 0)
+ mark_stabs (0);
+
+ /* Line number stabs are handled differently, since they have two
+ values, the line number and the address of the label. We use the
+ index field (aka desc) to hold the line number, and the value
+ field to hold the address. The symbol type is st_Label, which
+ should be different from the other stabs, so that gdb can
+ recognize it. */
+ if (type == N_SLINE)
+ {
+ SYMR dummy_symr;
+ char *name;
+ char name_end;
+
+#ifndef NO_LISTING
+ if (listing)
+ listing_source_line ((unsigned int) desc);
+#endif
+
+ dummy_symr.index = desc;
+ if (dummy_symr.index != desc)
+ {
+ as_warn (_("Line number (%d) for .stab%c directive cannot fit in index field (20 bits)"),
+ desc, what);
+ return;
+ }
+
+ name = input_line_pointer;
+ name_end = get_symbol_end ();
+
+ sym = symbol_find_or_make (name);
+ *input_line_pointer = name_end;
+
+ value = 0;
+ addend = 0;
+ st = st_Label;
+ sc = sc_Text;
+ indx = desc;
+ }
+ else
+ {
+#ifndef NO_LISTING
+ if (listing && (type == N_SO || type == N_SOL))
+ listing_source_file (string);
+#endif
+
+ if (isdigit (*input_line_pointer)
+ || *input_line_pointer == '-'
+ || *input_line_pointer == '+')
+ {
+ st = st_Nil;
+ sc = sc_Nil;
+ sym = (symbolS *) NULL;
+ value = get_absolute_expression ();
+ addend = 0;
+ }
+ else if (! is_name_beginner ((unsigned char) *input_line_pointer))
+ {
+ as_warn (_("Illegal .stab%c directive, bad character"), what);
+ return;
+ }
+ else
+ {
+ expressionS exp;
+
+ sc = sc_Nil;
+ st = st_Nil;
+
+ expression (&exp);
+ if (exp.X_op == O_constant)
+ {
+ sym = NULL;
+ value = exp.X_add_number;
+ addend = 0;
+ }
+ else if (exp.X_op == O_symbol)
+ {
+ sym = exp.X_add_symbol;
+ value = 0;
+ addend = exp.X_add_number;
+ }
+ else
+ {
+ sym = make_expr_symbol (&exp);
+ value = 0;
+ addend = 0;
+ }
+ }
+
+ indx = ECOFF_MARK_STAB (type);
+ }
+
+ /* Don't store the stabs symbol we are creating as the type of the
+ ECOFF symbol. We want to compute the type of the ECOFF symbol
+ independently. */
+ if (sym != (symbolS *) NULL)
+ hold = sym->ecoff_symbol;
+
+ (void) add_ecoff_symbol (string, st, sc, sym, addend, value, indx);
+
+ if (sym != (symbolS *) NULL)
+ sym->ecoff_symbol = hold;
+
+ /* Restore normal file type. */
+ cur_file_ptr = save_file_ptr;
+}
+
+/* Frob an ECOFF symbol. Small common symbols go into a special
+ .scommon section rather than bfd_com_section. */
+
+void
+ecoff_frob_symbol (sym)
+ symbolS *sym;
+{
+ if (S_IS_COMMON (sym)
+ && S_GET_VALUE (sym) > 0
+ && S_GET_VALUE (sym) <= bfd_get_gp_size (stdoutput))
+ {
+ static asection scom_section;
+ static asymbol scom_symbol;
+
+ /* We must construct a fake section similar to bfd_com_section
+ but with the name .scommon. */
+ if (scom_section.name == NULL)
+ {
+ scom_section = bfd_com_section;
+ scom_section.name = ".scommon";
+ scom_section.output_section = &scom_section;
+ scom_section.symbol = &scom_symbol;
+ scom_section.symbol_ptr_ptr = &scom_section.symbol;
+ scom_symbol = *bfd_com_section.symbol;
+ scom_symbol.name = ".scommon";
+ scom_symbol.section = &scom_section;
+ }
+ S_SET_SEGMENT (sym, &scom_section);
+ }
+
+ /* Double check weak symbols. */
+ if (sym->bsym->flags & BSF_WEAK)
+ {
+ if (S_IS_COMMON (sym))
+ as_bad (_("Symbol `%s' can not be both weak and common"),
+ S_GET_NAME (sym));
+ }
+}
+
+/* Add bytes to the symbolic information buffer. */
+
+static char *
+ecoff_add_bytes (buf, bufend, bufptr, need)
+ char **buf;
+ char **bufend;
+ char *bufptr;
+ unsigned long need;
+{
+ unsigned long at;
+ unsigned long want;
+
+ at = bufptr - *buf;
+ need -= *bufend - bufptr;
+ if (need < PAGE_SIZE)
+ need = PAGE_SIZE;
+ want = (*bufend - *buf) + need;
+ *buf = xrealloc (*buf, want);
+ *bufend = *buf + want;
+ return *buf + at;
+}
+
+/* Adjust the symbolic information buffer to the alignment required
+ for the ECOFF target debugging information. */
+
+static unsigned long
+ecoff_padding_adjust (backend, buf, bufend, offset, bufptrptr)
+ const struct ecoff_debug_swap *backend;
+ char **buf;
+ char **bufend;
+ unsigned long offset;
+ char **bufptrptr;
+{
+ bfd_size_type align;
+
+ align = backend->debug_align;
+ if ((offset & (align - 1)) != 0)
+ {
+ unsigned long add;
+
+ add = align - (offset & (align - 1));
+ if (*bufend - (*buf + offset) < add)
+ (void) ecoff_add_bytes (buf, bufend, *buf + offset, add);
+ memset (*buf + offset, 0, add);
+ offset += add;
+ if (bufptrptr != (char **) NULL)
+ *bufptrptr = *buf + offset;
+ }
+
+ return offset;
+}
+
+/* Build the line number information. */
+
+static unsigned long
+ecoff_build_lineno (backend, buf, bufend, offset, linecntptr)
+ const struct ecoff_debug_swap *backend;
+ char **buf;
+ char **bufend;
+ unsigned long offset;
+ long *linecntptr;
+{
+ char *bufptr;
+ register lineno_list_t *l;
+ lineno_list_t *last;
+ efdr_t *file;
+ proc_t *proc;
+ unsigned long c;
+ long iline;
+ long totcount;
+ lineno_list_t first;
+ lineno_list_t *local_first_lineno = first_lineno;
+
+ if (linecntptr != (long *) NULL)
+ *linecntptr = 0;
+
+ bufptr = *buf + offset;
+
+ file = (efdr_t *) NULL;
+ proc = (proc_t *) NULL;
+ last = (lineno_list_t *) NULL;
+ c = offset;
+ iline = 0;
+ totcount = 0;
+
+ /* For some reason the address of the first procedure is ignored
+ when reading line numbers. This doesn't matter if the address of
+ the first procedure is 0, but when gcc is generating MIPS
+ embedded PIC code, it will put strings in the .text section
+ before the first procedure. We cope by inserting a dummy line if
+ the address of the first procedure is not 0. Hopefully this
+ won't screw things up too badly.
+
+ Don't do this for ECOFF assembly source line numbers. They work
+ without this extra attention. */
+ if (debug_type != DEBUG_ECOFF
+ && first_proc_ptr != (proc_t *) NULL
+ && local_first_lineno != (lineno_list_t *) NULL
+ && ((S_GET_VALUE (first_proc_ptr->sym->as_sym)
+ + bfd_get_section_vma (stdoutput,
+ S_GET_SEGMENT (first_proc_ptr->sym->as_sym)))
+ != 0))
+ {
+ first.file = local_first_lineno->file;
+ first.proc = local_first_lineno->proc;
+ first.frag = &zero_address_frag;
+ first.paddr = 0;
+ first.lineno = 0;
+
+ first.next = local_first_lineno;
+ local_first_lineno = &first;
+ }
+
+ for (l = local_first_lineno; l != (lineno_list_t *) NULL; l = l->next)
+ {
+ long count;
+ long delta;
+
+ /* Get the offset to the memory address of the next line number
+ (in words). Do this first, so that we can skip ahead to the
+ next useful line number entry. */
+ if (l->next == (lineno_list_t *) NULL)
+ {
+ /* We want a count of zero, but it will be decremented
+ before it is used. */
+ count = 1;
+ }
+ else if (l->next->frag->fr_address + l->next->paddr
+ > l->frag->fr_address + l->paddr)
+ {
+ count = ((l->next->frag->fr_address + l->next->paddr
+ - (l->frag->fr_address + l->paddr))
+ >> 2);
+ }
+ else
+ {
+ /* Don't change last, so we still get the right delta. */
+ continue;
+ }
+
+ if (l->file != file || l->proc != proc)
+ {
+ if (l->proc != proc && proc != (proc_t *) NULL)
+ proc->pdr.lnHigh = last->lineno;
+ if (l->file != file && file != (efdr_t *) NULL)
+ {
+ file->fdr.cbLine = c - file->fdr.cbLineOffset;
+ file->fdr.cline = totcount + count;
+ if (linecntptr != (long *) NULL)
+ *linecntptr += totcount + count;
+ totcount = 0;
+ }
+
+ if (l->file != file)
+ {
+ efdr_t *last_file = file;
+
+ file = l->file;
+ if (last_file != (efdr_t *) NULL)
+ file->fdr.ilineBase
+ = last_file->fdr.ilineBase + last_file->fdr.cline;
+ else
+ file->fdr.ilineBase = 0;
+ file->fdr.cbLineOffset = c;
+ }
+ if (l->proc != proc)
+ {
+ proc = l->proc;
+ if (proc != (proc_t *) NULL)
+ {
+ proc->pdr.lnLow = l->lineno;
+ proc->pdr.cbLineOffset = c - file->fdr.cbLineOffset;
+ proc->pdr.iline = totcount;
+ }
+ }
+
+ last = (lineno_list_t *) NULL;
+ }
+
+ totcount += count;
+
+ /* Get the offset to this line number. */
+ if (last == (lineno_list_t *) NULL)
+ delta = 0;
+ else
+ delta = l->lineno - last->lineno;
+
+ /* Put in the offset to this line number. */
+ while (delta != 0)
+ {
+ int setcount;
+
+ /* 1 is added to each count read. */
+ --count;
+ /* We can only adjust the word count by up to 15 words at a
+ time. */
+ if (count <= 0x0f)
+ {
+ setcount = count;
+ count = 0;
+ }
+ else
+ {
+ setcount = 0x0f;
+ count -= 0x0f;
+ }
+ if (delta >= -7 && delta <= 7)
+ {
+ if (bufptr >= *bufend)
+ bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 1);
+ *bufptr++ = setcount + (delta << 4);
+ delta = 0;
+ ++c;
+ }
+ else
+ {
+ int set;
+
+ if (*bufend - bufptr < 3)
+ bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 3);
+ *bufptr++ = setcount + (8 << 4);
+ if (delta < -0x8000)
+ {
+ set = -0x8000;
+ delta += 0x8000;
+ }
+ else if (delta > 0x7fff)
+ {
+ set = 0x7fff;
+ delta -= 0x7fff;
+ }
+ else
+ {
+ set = delta;
+ delta = 0;
+ }
+ *bufptr++ = set >> 8;
+ *bufptr++ = set & 0xffff;
+ c += 3;
+ }
+ }
+
+ /* Finish adjusting the count. */
+ while (count > 0)
+ {
+ if (bufptr >= *bufend)
+ bufptr = ecoff_add_bytes (buf, bufend, bufptr, (long) 1);
+ /* 1 is added to each count read. */
+ --count;
+ if (count > 0x0f)
+ {
+ *bufptr++ = 0x0f;
+ count -= 0x0f;
+ }
+ else
+ {
+ *bufptr++ = count;
+ count = 0;
+ }
+ ++c;
+ }
+
+ ++iline;
+ last = l;
+ }
+
+ if (proc != (proc_t *) NULL)
+ proc->pdr.lnHigh = last->lineno;
+ if (file != (efdr_t *) NULL)
+ {
+ file->fdr.cbLine = c - file->fdr.cbLineOffset;
+ file->fdr.cline = totcount;
+ }
+
+ if (linecntptr != (long *) NULL)
+ *linecntptr += totcount;
+
+ c = ecoff_padding_adjust (backend, buf, bufend, c, &bufptr);
+
+ return c;
+}
+
+/* Build and swap out the symbols. */
+
+static unsigned long
+ecoff_build_symbols (backend, buf, bufend, offset)
+ const struct ecoff_debug_swap *backend;
+ char **buf;
+ char **bufend;
+ unsigned long offset;
+{
+ const bfd_size_type external_sym_size = backend->external_sym_size;
+ void (* const swap_sym_out) PARAMS ((bfd *, const SYMR *, PTR))
+ = backend->swap_sym_out;
+ char *sym_out;
+ long isym;
+ vlinks_t *file_link;
+
+ sym_out = *buf + offset;
+
+ isym = 0;
+
+ /* The symbols are stored by file. */
+ for (file_link = file_desc.first;
+ file_link != (vlinks_t *) NULL;
+ file_link = file_link->next)
+ {
+ int ifilesym;
+ int fil_cnt;
+ efdr_t *fil_ptr;
+ efdr_t *fil_end;
+
+ if (file_link->next == (vlinks_t *) NULL)
+ fil_cnt = file_desc.objects_last_page;
+ else
+ fil_cnt = file_desc.objects_per_page;
+ fil_ptr = file_link->datum->file;
+ fil_end = fil_ptr + fil_cnt;
+ for (; fil_ptr < fil_end; fil_ptr++)
+ {
+ vlinks_t *sym_link;
+
+ fil_ptr->fdr.isymBase = isym;
+ ifilesym = isym;
+ for (sym_link = fil_ptr->symbols.first;
+ sym_link != (vlinks_t *) NULL;
+ sym_link = sym_link->next)
+ {
+ int sym_cnt;
+ localsym_t *sym_ptr;
+ localsym_t *sym_end;
+
+ if (sym_link->next == (vlinks_t *) NULL)
+ sym_cnt = fil_ptr->symbols.objects_last_page;
+ else
+ sym_cnt = fil_ptr->symbols.objects_per_page;
+ sym_ptr = sym_link->datum->sym;
+ sym_end = sym_ptr + sym_cnt;
+ for (; sym_ptr < sym_end; sym_ptr++)
+ {
+ int local;
+ symbolS *as_sym;
+ forward_t *f;
+
+ know (sym_ptr->file_ptr == fil_ptr);
+
+ /* If there is no associated gas symbol, then this
+ is a pure debugging symbol. We have already
+ added the name (if any) to fil_ptr->strings.
+ Otherwise we must decide whether this is an
+ external or a local symbol (actually, it may be
+ both if the local provides additional debugging
+ information for the external). */
+ local = 1;
+ as_sym = sym_ptr->as_sym;
+ if (as_sym != (symbolS *) NULL)
+ {
+ symint_t indx;
+
+ /* The value of a block start symbol is the
+ offset from the start of the procedure. For
+ other symbols we just use the gas value (but
+ we must offset it by the vma of the section,
+ just as BFD does, because BFD will not see
+ this value). */
+ if (sym_ptr->ecoff_sym.asym.st == (int) st_Block
+ && sym_ptr->ecoff_sym.asym.sc == (int) sc_Text)
+ {
+ symbolS *begin_sym;
+
+ know (sym_ptr->proc_ptr != (proc_t *) NULL);
+ begin_sym = sym_ptr->proc_ptr->sym->as_sym;
+ if (S_GET_SEGMENT (as_sym)
+ != S_GET_SEGMENT (begin_sym))
+ as_warn (_(".begin/.bend in different segments"));
+ sym_ptr->ecoff_sym.asym.value =
+ S_GET_VALUE (as_sym) - S_GET_VALUE (begin_sym);
+ }
+ else
+ sym_ptr->ecoff_sym.asym.value =
+ (S_GET_VALUE (as_sym)
+ + bfd_get_section_vma (stdoutput,
+ S_GET_SEGMENT (as_sym))
+ + sym_ptr->addend);
+
+ sym_ptr->ecoff_sym.weakext = S_IS_WEAK (as_sym);
+
+ /* Set st_Proc to st_StaticProc for local
+ functions. */
+ if (sym_ptr->ecoff_sym.asym.st == st_Proc
+ && S_IS_DEFINED (as_sym)
+ && ! S_IS_EXTERNAL (as_sym)
+ && ! S_IS_WEAK (as_sym))
+ sym_ptr->ecoff_sym.asym.st = st_StaticProc;
+
+ /* Get the type and storage class based on where
+ the symbol actually wound up. Traditionally,
+ N_LBRAC and N_RBRAC are *not* relocated. */
+ indx = sym_ptr->ecoff_sym.asym.index;
+ if (sym_ptr->ecoff_sym.asym.st == st_Nil
+ && sym_ptr->ecoff_sym.asym.sc == sc_Nil
+ && (! ECOFF_IS_STAB (&sym_ptr->ecoff_sym.asym)
+ || ((ECOFF_UNMARK_STAB (indx) != N_LBRAC)
+ && (ECOFF_UNMARK_STAB (indx) != N_RBRAC))))
+ {
+ segT seg;
+ const char *segname;
+ st_t st;
+ sc_t sc;
+
+ seg = S_GET_SEGMENT (as_sym);
+ segname = segment_name (seg);
+
+ if (! ECOFF_IS_STAB (&sym_ptr->ecoff_sym.asym)
+ && (S_IS_EXTERNAL (as_sym)
+ || S_IS_WEAK (as_sym)
+ || ! S_IS_DEFINED (as_sym)))
+ {
+ if ((as_sym->bsym->flags & BSF_FUNCTION) != 0)
+ st = st_Proc;
+ else
+ st = st_Global;
+ }
+ else if (seg == text_section)
+ st = st_Label;
+ else
+ st = st_Static;
+
+ if (! S_IS_DEFINED (as_sym))
+ {
+ if (as_sym->ecoff_extern_size == 0
+ || (as_sym->ecoff_extern_size
+ > bfd_get_gp_size (stdoutput)))
+ sc = sc_Undefined;
+ else
+ {
+ sc = sc_SUndefined;
+ sym_ptr->ecoff_sym.asym.value =
+ as_sym->ecoff_extern_size;
+ }
+#ifdef S_SET_SIZE
+ S_SET_SIZE (as_sym, as_sym->ecoff_extern_size);
+#endif
+ }
+ else if (S_IS_COMMON (as_sym))
+ {
+ if (S_GET_VALUE (as_sym) > 0
+ && (S_GET_VALUE (as_sym)
+ <= bfd_get_gp_size (stdoutput)))
+ sc = sc_SCommon;
+ else
+ sc = sc_Common;
+ }
+ else if (seg == text_section)
+ sc = sc_Text;
+ else if (seg == data_section)
+ sc = sc_Data;
+ else if (strcmp (segname, ".rdata") == 0
+ || strcmp (segname, ".rodata") == 0)
+ sc = sc_RData;
+ else if (strcmp (segname, ".sdata") == 0)
+ sc = sc_SData;
+ else if (seg == bss_section)
+ sc = sc_Bss;
+ else if (strcmp (segname, ".sbss") == 0)
+ sc = sc_SBss;
+ else if (seg == &bfd_abs_section)
+ sc = sc_Abs;
+ else
+ {
+ /* This must be a user named section.
+ This is not possible in ECOFF, but it
+ is in ELF. */
+ sc = sc_Data;
+ }
+
+ sym_ptr->ecoff_sym.asym.st = (int) st;
+ sym_ptr->ecoff_sym.asym.sc = (int) sc;
+ }
+
+ /* This is just an external symbol if it is
+ outside a procedure and it has a type.
+ FIXME: g++ will generate symbols which have
+ different names in the debugging information
+ than the actual symbol. Should we handle
+ them here? */
+ if ((S_IS_EXTERNAL (as_sym)
+ || S_IS_WEAK (as_sym)
+ || ! S_IS_DEFINED (as_sym))
+ && sym_ptr->proc_ptr == (proc_t *) NULL
+ && sym_ptr->ecoff_sym.asym.st != (int) st_Nil
+ && ! ECOFF_IS_STAB (&sym_ptr->ecoff_sym.asym))
+ local = 0;
+
+ /* This is just an external symbol if it is a
+ common symbol. */
+ if (S_IS_COMMON (as_sym))
+ local = 0;
+
+ /* If an st_end symbol has an associated gas
+ symbol, then it is a local label created for
+ a .bend or .end directive. Stabs line
+ numbers will have \001 in the names. */
+ if (local
+ && sym_ptr->ecoff_sym.asym.st != st_End
+ && strchr (sym_ptr->name, '\001') == 0)
+ sym_ptr->ecoff_sym.asym.iss =
+ add_string (&fil_ptr->strings,
+ fil_ptr->str_hash,
+ sym_ptr->name,
+ (shash_t **) NULL);
+ }
+
+ /* We now know the index of this symbol; fill in
+ locations that have been waiting for that
+ information. */
+ if (sym_ptr->begin_ptr != (localsym_t *) NULL)
+ {
+ localsym_t *begin_ptr;
+ st_t begin_type;
+
+ know (local);
+ begin_ptr = sym_ptr->begin_ptr;
+ know (begin_ptr->sym_index != -1);
+ sym_ptr->ecoff_sym.asym.index = begin_ptr->sym_index;
+ if (sym_ptr->ecoff_sym.asym.sc != (int) sc_Info)
+ sym_ptr->ecoff_sym.asym.iss =
+ begin_ptr->ecoff_sym.asym.iss;
+
+ begin_type = begin_ptr->ecoff_sym.asym.st;
+ if (begin_type == st_File
+ || begin_type == st_Block)
+ {
+ begin_ptr->ecoff_sym.asym.index =
+ isym - ifilesym + 1;
+ (*swap_sym_out) (stdoutput,
+ &begin_ptr->ecoff_sym.asym,
+ (*buf
+ + offset
+ + (begin_ptr->sym_index
+ * external_sym_size)));
+ }
+ else
+ {
+ know (begin_ptr->index_ptr != (aux_t *) NULL);
+ begin_ptr->index_ptr->data.isym =
+ isym - ifilesym + 1;
+ }
+
+ /* The value of the symbol marking the end of a
+ procedure is the size of the procedure. The
+ value of the symbol marking the end of a
+ block is the offset from the start of the
+ procedure to the block. */
+ if (begin_type == st_Proc
+ || begin_type == st_StaticProc)
+ {
+ know (as_sym != (symbolS *) NULL);
+ know (begin_ptr->as_sym != (symbolS *) NULL);
+ if (S_GET_SEGMENT (as_sym)
+ != S_GET_SEGMENT (begin_ptr->as_sym))
+ as_warn (_(".begin/.bend in different segments"));
+ sym_ptr->ecoff_sym.asym.value =
+ (S_GET_VALUE (as_sym)
+ - S_GET_VALUE (begin_ptr->as_sym));
+
+ /* If the size is odd, this is probably a
+ mips16 function; force it to be even. */
+ if ((sym_ptr->ecoff_sym.asym.value & 1) != 0)
+ ++sym_ptr->ecoff_sym.asym.value;
+
+#ifdef S_SET_SIZE
+ S_SET_SIZE (begin_ptr->as_sym,
+ sym_ptr->ecoff_sym.asym.value);
+#endif
+ }
+ else if (begin_type == st_Block
+ && sym_ptr->ecoff_sym.asym.sc != (int) sc_Info)
+ {
+ symbolS *begin_sym;
+
+ know (as_sym != (symbolS *) NULL);
+ know (sym_ptr->proc_ptr != (proc_t *) NULL);
+ begin_sym = sym_ptr->proc_ptr->sym->as_sym;
+ if (S_GET_SEGMENT (as_sym)
+ != S_GET_SEGMENT (begin_sym))
+ as_warn (_(".begin/.bend in different segments"));
+ sym_ptr->ecoff_sym.asym.value =
+ S_GET_VALUE (as_sym) - S_GET_VALUE (begin_sym);
+ }
+ }
+
+ for (f = sym_ptr->forward_ref;
+ f != (forward_t *) NULL;
+ f = f->next)
+ {
+ know (local);
+ f->ifd_ptr->data.isym = fil_ptr->file_index;
+ f->index_ptr->data.rndx.index = isym - ifilesym;
+ }
+
+ if (local)
+ {
+ if (*bufend - sym_out < external_sym_size)
+ sym_out = ecoff_add_bytes (buf, bufend,
+ sym_out,
+ external_sym_size);
+ (*swap_sym_out) (stdoutput, &sym_ptr->ecoff_sym.asym,
+ sym_out);
+ sym_out += external_sym_size;
+
+ sym_ptr->sym_index = isym;
+
+ if (sym_ptr->proc_ptr != (proc_t *) NULL
+ && sym_ptr->proc_ptr->sym == sym_ptr)
+ sym_ptr->proc_ptr->pdr.isym = isym - ifilesym;
+
+ ++isym;
+ }
+
+ /* Record the local symbol index and file number in
+ case this is an external symbol. Note that this
+ destroys the asym.index field. */
+ if (as_sym != (symbolS *) NULL
+ && as_sym->ecoff_symbol == sym_ptr)
+ {
+ if ((sym_ptr->ecoff_sym.asym.st == st_Proc
+ || sym_ptr->ecoff_sym.asym.st == st_StaticProc)
+ && local)
+ sym_ptr->ecoff_sym.asym.index = isym - ifilesym - 1;
+ sym_ptr->ecoff_sym.ifd = fil_ptr->file_index;
+
+ /* Don't try to merge an FDR which has an
+ external symbol attached to it. */
+ if (S_IS_EXTERNAL (as_sym) || S_IS_WEAK (as_sym))
+ fil_ptr->fdr.fMerge = 0;
+ }
+ }
+ }
+ fil_ptr->fdr.csym = isym - fil_ptr->fdr.isymBase;
+ }
+ }
+
+ return offset + isym * external_sym_size;
+}
+
+/* Swap out the procedure information. */
+
+static unsigned long
+ecoff_build_procs (backend, buf, bufend, offset)
+ const struct ecoff_debug_swap *backend;
+ char **buf;
+ char **bufend;
+ unsigned long offset;
+{
+ const bfd_size_type external_pdr_size = backend->external_pdr_size;
+ void (* const swap_pdr_out) PARAMS ((bfd *, const PDR *, PTR))
+ = backend->swap_pdr_out;
+ char *pdr_out;
+ long iproc;
+ vlinks_t *file_link;
+
+ pdr_out = *buf + offset;
+
+ iproc = 0;
+
+ /* The procedures are stored by file. */
+ for (file_link = file_desc.first;
+ file_link != (vlinks_t *) NULL;
+ file_link = file_link->next)
+ {
+ int fil_cnt;
+ efdr_t *fil_ptr;
+ efdr_t *fil_end;
+
+ if (file_link->next == (vlinks_t *) NULL)
+ fil_cnt = file_desc.objects_last_page;
+ else
+ fil_cnt = file_desc.objects_per_page;
+ fil_ptr = file_link->datum->file;
+ fil_end = fil_ptr + fil_cnt;
+ for (; fil_ptr < fil_end; fil_ptr++)
+ {
+ vlinks_t *proc_link;
+ int first;
+
+ fil_ptr->fdr.ipdFirst = iproc;
+ first = 1;
+ for (proc_link = fil_ptr->procs.first;
+ proc_link != (vlinks_t *) NULL;
+ proc_link = proc_link->next)
+ {
+ int prc_cnt;
+ proc_t *proc_ptr;
+ proc_t *proc_end;
+
+ if (proc_link->next == (vlinks_t *) NULL)
+ prc_cnt = fil_ptr->procs.objects_last_page;
+ else
+ prc_cnt = fil_ptr->procs.objects_per_page;
+ proc_ptr = proc_link->datum->proc;
+ proc_end = proc_ptr + prc_cnt;
+ for (; proc_ptr < proc_end; proc_ptr++)
+ {
+ symbolS *adr_sym;
+ unsigned long adr;
+
+ adr_sym = proc_ptr->sym->as_sym;
+ adr = (S_GET_VALUE (adr_sym)
+ + bfd_get_section_vma (stdoutput,
+ S_GET_SEGMENT (adr_sym)));
+ if (first)
+ {
+ /* This code used to force the adr of the very
+ first fdr to be 0. However, the native tools
+ don't do that, and I can't remember why it
+ used to work that way, so I took it out. */
+ fil_ptr->fdr.adr = adr;
+ first = 0;
+ }
+ proc_ptr->pdr.adr = adr - fil_ptr->fdr.adr;
+ if (*bufend - pdr_out < external_pdr_size)
+ pdr_out = ecoff_add_bytes (buf, bufend,
+ pdr_out,
+ external_pdr_size);
+ (*swap_pdr_out) (stdoutput, &proc_ptr->pdr, pdr_out);
+ pdr_out += external_pdr_size;
+ ++iproc;
+ }
+ }
+ fil_ptr->fdr.cpd = iproc - fil_ptr->fdr.ipdFirst;
+ }
+ }
+
+ return offset + iproc * external_pdr_size;
+}
+
+/* Swap out the aux information. */
+
+static unsigned long
+ecoff_build_aux (backend, buf, bufend, offset)
+ const struct ecoff_debug_swap *backend;
+ char **buf;
+ char **bufend;
+ unsigned long offset;
+{
+ int bigendian;
+ union aux_ext *aux_out;
+ long iaux;
+ vlinks_t *file_link;
+
+ bigendian = bfd_big_endian (stdoutput);
+
+ aux_out = (union aux_ext *) (*buf + offset);
+
+ iaux = 0;
+
+ /* The aux entries are stored by file. */
+ for (file_link = file_desc.first;
+ file_link != (vlinks_t *) NULL;
+ file_link = file_link->next)
+ {
+ int fil_cnt;
+ efdr_t *fil_ptr;
+ efdr_t *fil_end;
+
+ if (file_link->next == (vlinks_t *) NULL)
+ fil_cnt = file_desc.objects_last_page;
+ else
+ fil_cnt = file_desc.objects_per_page;
+ fil_ptr = file_link->datum->file;
+ fil_end = fil_ptr + fil_cnt;
+ for (; fil_ptr < fil_end; fil_ptr++)
+ {
+ vlinks_t *aux_link;
+
+ fil_ptr->fdr.fBigendian = bigendian;
+ fil_ptr->fdr.iauxBase = iaux;
+ for (aux_link = fil_ptr->aux_syms.first;
+ aux_link != (vlinks_t *) NULL;
+ aux_link = aux_link->next)
+ {
+ int aux_cnt;
+ aux_t *aux_ptr;
+ aux_t *aux_end;
+
+ if (aux_link->next == (vlinks_t *) NULL)
+ aux_cnt = fil_ptr->aux_syms.objects_last_page;
+ else
+ aux_cnt = fil_ptr->aux_syms.objects_per_page;
+ aux_ptr = aux_link->datum->aux;
+ aux_end = aux_ptr + aux_cnt;
+ for (; aux_ptr < aux_end; aux_ptr++)
+ {
+ if (*bufend - (char *) aux_out < sizeof (union aux_ext))
+ aux_out = ((union aux_ext *)
+ ecoff_add_bytes (buf, bufend,
+ (char *) aux_out,
+ sizeof (union aux_ext)));
+ switch (aux_ptr->type)
+ {
+ case aux_tir:
+ (*backend->swap_tir_out) (bigendian,
+ &aux_ptr->data.ti,
+ &aux_out->a_ti);
+ break;
+ case aux_rndx:
+ (*backend->swap_rndx_out) (bigendian,
+ &aux_ptr->data.rndx,
+ &aux_out->a_rndx);
+ break;
+ case aux_dnLow:
+ AUX_PUT_DNLOW (bigendian, aux_ptr->data.dnLow,
+ aux_out);
+ break;
+ case aux_dnHigh:
+ AUX_PUT_DNHIGH (bigendian, aux_ptr->data.dnHigh,
+ aux_out);
+ break;
+ case aux_isym:
+ AUX_PUT_ISYM (bigendian, aux_ptr->data.isym,
+ aux_out);
+ break;
+ case aux_iss:
+ AUX_PUT_ISS (bigendian, aux_ptr->data.iss,
+ aux_out);
+ break;
+ case aux_width:
+ AUX_PUT_WIDTH (bigendian, aux_ptr->data.width,
+ aux_out);
+ break;
+ case aux_count:
+ AUX_PUT_COUNT (bigendian, aux_ptr->data.count,
+ aux_out);
+ break;
+ }
+
+ ++aux_out;
+ ++iaux;
+ }
+ }
+ fil_ptr->fdr.caux = iaux - fil_ptr->fdr.iauxBase;
+ }
+ }
+
+ return ecoff_padding_adjust (backend, buf, bufend,
+ offset + iaux * sizeof (union aux_ext),
+ (char **) NULL);
+}
+
+/* Copy out the strings from a varray_t. This returns the number of
+ bytes copied, rather than the new offset. */
+
+static unsigned long
+ecoff_build_strings (buf, bufend, offset, vp)
+ char **buf;
+ char **bufend;
+ unsigned long offset;
+ varray_t *vp;
+{
+ unsigned long istr;
+ char *str_out;
+ vlinks_t *str_link;
+
+ str_out = *buf + offset;
+
+ istr = 0;
+
+ for (str_link = vp->first;
+ str_link != (vlinks_t *) NULL;
+ str_link = str_link->next)
+ {
+ unsigned long str_cnt;
+
+ if (str_link->next == (vlinks_t *) NULL)
+ str_cnt = vp->objects_last_page;
+ else
+ str_cnt = vp->objects_per_page;
+
+ if (*bufend - str_out < str_cnt)
+ str_out = ecoff_add_bytes (buf, bufend, str_out, str_cnt);
+
+ memcpy (str_out, str_link->datum->byte, str_cnt);
+ str_out += str_cnt;
+ istr += str_cnt;
+ }
+
+ return istr;
+}
+
+/* Dump out the local strings. */
+
+static unsigned long
+ecoff_build_ss (backend, buf, bufend, offset)
+ const struct ecoff_debug_swap *backend;
+ char **buf;
+ char **bufend;
+ unsigned long offset;
+{
+ long iss;
+ vlinks_t *file_link;
+
+ iss = 0;
+
+ for (file_link = file_desc.first;
+ file_link != (vlinks_t *) NULL;
+ file_link = file_link->next)
+ {
+ int fil_cnt;
+ efdr_t *fil_ptr;
+ efdr_t *fil_end;
+
+ if (file_link->next == (vlinks_t *) NULL)
+ fil_cnt = file_desc.objects_last_page;
+ else
+ fil_cnt = file_desc.objects_per_page;
+ fil_ptr = file_link->datum->file;
+ fil_end = fil_ptr + fil_cnt;
+ for (; fil_ptr < fil_end; fil_ptr++)
+ {
+ long ss_cnt;
+
+ fil_ptr->fdr.issBase = iss;
+ ss_cnt = ecoff_build_strings (buf, bufend, offset + iss,
+ &fil_ptr->strings);
+ fil_ptr->fdr.cbSs = ss_cnt;
+ iss += ss_cnt;
+ }
+ }
+
+ return ecoff_padding_adjust (backend, buf, bufend, offset + iss,
+ (char **) NULL);
+}
+
+/* Swap out the file descriptors. */
+
+static unsigned long
+ecoff_build_fdr (backend, buf, bufend, offset)
+ const struct ecoff_debug_swap *backend;
+ char **buf;
+ char **bufend;
+ unsigned long offset;
+{
+ const bfd_size_type external_fdr_size = backend->external_fdr_size;
+ void (* const swap_fdr_out) PARAMS ((bfd *, const FDR *, PTR))
+ = backend->swap_fdr_out;
+ long ifile;
+ char *fdr_out;
+ vlinks_t *file_link;
+
+ ifile = 0;
+
+ fdr_out = *buf + offset;
+
+ for (file_link = file_desc.first;
+ file_link != (vlinks_t *) NULL;
+ file_link = file_link->next)
+ {
+ int fil_cnt;
+ efdr_t *fil_ptr;
+ efdr_t *fil_end;
+
+ if (file_link->next == (vlinks_t *) NULL)
+ fil_cnt = file_desc.objects_last_page;
+ else
+ fil_cnt = file_desc.objects_per_page;
+ fil_ptr = file_link->datum->file;
+ fil_end = fil_ptr + fil_cnt;
+ for (; fil_ptr < fil_end; fil_ptr++)
+ {
+ if (*bufend - fdr_out < external_fdr_size)
+ fdr_out = ecoff_add_bytes (buf, bufend, fdr_out,
+ external_fdr_size);
+ (*swap_fdr_out) (stdoutput, &fil_ptr->fdr, fdr_out);
+ fdr_out += external_fdr_size;
+ ++ifile;
+ }
+ }
+
+ return offset + ifile * external_fdr_size;
+}
+
+/* Set up the external symbols. These are supposed to be handled by
+ the backend. This routine just gets the right information and
+ calls a backend function to deal with it. */
+
+static void
+ecoff_setup_ext ()
+{
+ register symbolS *sym;
+
+ for (sym = symbol_rootP; sym != (symbolS *) NULL; sym = symbol_next (sym))
+ {
+ if (sym->ecoff_symbol == NULL)
+ continue;
+
+ /* If this is a local symbol, then force the fields to zero. */
+ if (! S_IS_EXTERNAL (sym)
+ && ! S_IS_WEAK (sym)
+ && S_IS_DEFINED (sym))
+ {
+ sym->ecoff_symbol->ecoff_sym.asym.value = 0;
+ sym->ecoff_symbol->ecoff_sym.asym.st = (int) st_Nil;
+ sym->ecoff_symbol->ecoff_sym.asym.sc = (int) sc_Nil;
+ sym->ecoff_symbol->ecoff_sym.asym.index = indexNil;
+ }
+
+ obj_ecoff_set_ext (sym, &sym->ecoff_symbol->ecoff_sym);
+ }
+}
+
+/* Build the ECOFF debugging information. */
+
+unsigned long
+ecoff_build_debug (hdr, bufp, backend)
+ HDRR *hdr;
+ char **bufp;
+ const struct ecoff_debug_swap *backend;
+{
+ const bfd_size_type external_pdr_size = backend->external_pdr_size;
+ tag_t *ptag;
+ tag_t *ptag_next;
+ efdr_t *fil_ptr;
+ int end_warning;
+ efdr_t *hold_file_ptr;
+ proc_t * hold_proc_ptr;
+ symbolS *sym;
+ char *buf;
+ char *bufend;
+ unsigned long offset;
+
+ /* Make sure we have a file. */
+ if (first_file == (efdr_t *) NULL)
+ add_file ((const char *) NULL, 0, 1);
+
+ /* Handle any top level tags. */
+ for (ptag = top_tag_head->first_tag;
+ ptag != (tag_t *) NULL;
+ ptag = ptag_next)
+ {
+ if (ptag->forward_ref != (forward_t *) NULL)
+ add_unknown_tag (ptag);
+
+ ptag_next = ptag->same_block;
+ ptag->hash_ptr->tag_ptr = ptag->same_name;
+ free_tag (ptag);
+ }
+
+ free_thead (top_tag_head);
+
+ /* Look through the symbols. Add debugging information for each
+ symbol that has not already received it. */
+ hold_file_ptr = cur_file_ptr;
+ hold_proc_ptr = cur_proc_ptr;
+ cur_proc_ptr = (proc_t *) NULL;
+ for (sym = symbol_rootP; sym != (symbolS *) NULL; sym = symbol_next (sym))
+ {
+ if (sym->ecoff_symbol != NULL
+ || sym->ecoff_file == (efdr_t *) NULL
+ || (sym->bsym->flags & BSF_SECTION_SYM) != 0)
+ continue;
+
+ cur_file_ptr = sym->ecoff_file;
+ add_ecoff_symbol ((const char *) NULL, st_Nil, sc_Nil, sym,
+ (bfd_vma) 0, S_GET_VALUE (sym), indexNil);
+ }
+ cur_proc_ptr = hold_proc_ptr;
+ cur_file_ptr = hold_file_ptr;
+
+ /* Output an ending symbol for all the files. We have to do this
+ here for the last file, so we may as well do it for all of the
+ files. */
+ end_warning = 0;
+ for (fil_ptr = first_file;
+ fil_ptr != (efdr_t *) NULL;
+ fil_ptr = fil_ptr->next_file)
+ {
+ cur_file_ptr = fil_ptr;
+ while (cur_file_ptr->cur_scope != (scope_t *) NULL
+ && cur_file_ptr->cur_scope->prev != (scope_t *) NULL)
+ {
+ cur_file_ptr->cur_scope = cur_file_ptr->cur_scope->prev;
+ if (! end_warning && ! cur_file_ptr->fake)
+ {
+ as_warn (_("Missing .end or .bend at end of file"));
+ end_warning = 1;
+ }
+ }
+ if (cur_file_ptr->cur_scope != (scope_t *) NULL)
+ (void) add_ecoff_symbol ((const char *) NULL,
+ st_End, sc_Text,
+ (symbolS *) NULL,
+ (bfd_vma) 0,
+ (symint_t) 0,
+ (symint_t) 0);
+ }
+
+ /* Build the symbolic information. */
+ offset = 0;
+ buf = xmalloc (PAGE_SIZE);
+ bufend = buf + PAGE_SIZE;
+
+ /* Build the line number information. */
+ hdr->cbLineOffset = offset;
+ offset = ecoff_build_lineno (backend, &buf, &bufend, offset,
+ &hdr->ilineMax);
+ hdr->cbLine = offset - hdr->cbLineOffset;
+
+ /* We don't use dense numbers at all. */
+ hdr->idnMax = 0;
+ hdr->cbDnOffset = 0;
+
+ /* We can't build the PDR table until we have built the symbols,
+ because a PDR contains a symbol index. However, we set aside
+ space at this point. */
+ hdr->ipdMax = proc_cnt;
+ hdr->cbPdOffset = offset;
+ if (bufend - (buf + offset) < proc_cnt * external_pdr_size)
+ (void) ecoff_add_bytes (&buf, &bufend, buf + offset,
+ proc_cnt * external_pdr_size);
+ offset += proc_cnt * external_pdr_size;
+
+ /* Build the local symbols. */
+ hdr->cbSymOffset = offset;
+ offset = ecoff_build_symbols (backend, &buf, &bufend, offset);
+ hdr->isymMax = (offset - hdr->cbSymOffset) / backend->external_sym_size;
+
+ /* Building the symbols initializes the symbol index in the PDR's.
+ Now we can swap out the PDR's. */
+ (void) ecoff_build_procs (backend, &buf, &bufend, hdr->cbPdOffset);
+
+ /* We don't use optimization symbols. */
+ hdr->ioptMax = 0;
+ hdr->cbOptOffset = 0;
+
+ /* Swap out the auxiliary type information. */
+ hdr->cbAuxOffset = offset;
+ offset = ecoff_build_aux (backend, &buf, &bufend, offset);
+ hdr->iauxMax = (offset - hdr->cbAuxOffset) / sizeof (union aux_ext);
+
+ /* Copy out the local strings. */
+ hdr->cbSsOffset = offset;
+ offset = ecoff_build_ss (backend, &buf, &bufend, offset);
+ hdr->issMax = offset - hdr->cbSsOffset;
+
+ /* We don't use relative file descriptors. */
+ hdr->crfd = 0;
+ hdr->cbRfdOffset = 0;
+
+ /* Swap out the file descriptors. */
+ hdr->cbFdOffset = offset;
+ offset = ecoff_build_fdr (backend, &buf, &bufend, offset);
+ hdr->ifdMax = (offset - hdr->cbFdOffset) / backend->external_fdr_size;
+
+ /* Set up the external symbols, which are handled by the BFD back
+ end. */
+ hdr->issExtMax = 0;
+ hdr->cbSsExtOffset = 0;
+ hdr->iextMax = 0;
+ hdr->cbExtOffset = 0;
+ ecoff_setup_ext ();
+
+ know ((offset & (backend->debug_align - 1)) == 0);
+
+ /* FIXME: This value should be determined from the .verstamp directive,
+ with reasonable defaults in config files. */
+#ifdef TC_ALPHA
+ hdr->vstamp = 0x030b;
+#else
+ hdr->vstamp = 0x020b;
+#endif
+
+ *bufp = buf;
+ return offset;
+}
+
+/* Allocate a cluster of pages. */
+
+#ifndef MALLOC_CHECK
+
+static page_type *
+allocate_cluster (npages)
+ unsigned long npages;
+{
+ register page_type *value = (page_type *) xmalloc (npages * PAGE_USIZE);
+
+#ifdef ECOFF_DEBUG
+ if (debug > 3)
+ fprintf (stderr, "\talloc\tnpages = %d, value = 0x%.8x\n", npages, value);
+#endif
+
+ memset (value, 0, npages * PAGE_USIZE);
+
+ return value;
+}
+
+
+static page_type *cluster_ptr = NULL;
+static unsigned long pages_left = 0;
+
+#endif /* MALLOC_CHECK */
+
+/* Allocate one page (which is initialized to 0). */
+
+static page_type *
+allocate_page ()
+{
+#ifndef MALLOC_CHECK
+
+ if (pages_left == 0)
+ {
+ pages_left = MAX_CLUSTER_PAGES;
+ cluster_ptr = allocate_cluster (pages_left);
+ }
+
+ pages_left--;
+ return cluster_ptr++;
+
+#else /* MALLOC_CHECK */
+
+ page_type *ptr;
+
+ ptr = xmalloc (PAGE_USIZE);
+ memset (ptr, 0, PAGE_USIZE);
+ return ptr;
+
+#endif /* MALLOC_CHECK */
+}
+
+/* Allocate scoping information. */
+
+static scope_t *
+allocate_scope ()
+{
+ register scope_t *ptr;
+ static scope_t initial_scope;
+
+#ifndef MALLOC_CHECK
+
+ ptr = alloc_counts[(int)alloc_type_scope].free_list.f_scope;
+ if (ptr != (scope_t *) NULL)
+ alloc_counts[ (int)alloc_type_scope ].free_list.f_scope = ptr->free;
+ else
+ {
+ register int unallocated = alloc_counts[(int)alloc_type_scope].unallocated;
+ register page_type *cur_page = alloc_counts[(int)alloc_type_scope].cur_page;
+
+ if (unallocated == 0)
+ {
+ unallocated = PAGE_SIZE / sizeof (scope_t);
+ alloc_counts[(int)alloc_type_scope].cur_page = cur_page = allocate_page ();
+ alloc_counts[(int)alloc_type_scope].total_pages++;
+ }
+
+ ptr = &cur_page->scope[--unallocated];
+ alloc_counts[(int)alloc_type_scope].unallocated = unallocated;
+ }
+
+#else
+
+ ptr = (scope_t *) xmalloc (sizeof (scope_t));
+
+#endif
+
+ alloc_counts[(int)alloc_type_scope].total_alloc++;
+ *ptr = initial_scope;
+ return ptr;
+}
+
+/* Free scoping information. */
+
+static void
+free_scope (ptr)
+ scope_t *ptr;
+{
+ alloc_counts[(int)alloc_type_scope].total_free++;
+
+#ifndef MALLOC_CHECK
+ ptr->free = alloc_counts[(int)alloc_type_scope].free_list.f_scope;
+ alloc_counts[(int)alloc_type_scope].free_list.f_scope = ptr;
+#else
+ free ((PTR) ptr);
+#endif
+}
+
+/* Allocate links for pages in a virtual array. */
+
+static vlinks_t *
+allocate_vlinks ()
+{
+ register vlinks_t *ptr;
+ static vlinks_t initial_vlinks;
+
+#ifndef MALLOC_CHECK
+
+ register int unallocated = alloc_counts[(int)alloc_type_vlinks].unallocated;
+ register page_type *cur_page = alloc_counts[(int)alloc_type_vlinks].cur_page;
+
+ if (unallocated == 0)
+ {
+ unallocated = PAGE_SIZE / sizeof (vlinks_t);
+ alloc_counts[(int)alloc_type_vlinks].cur_page = cur_page = allocate_page ();
+ alloc_counts[(int)alloc_type_vlinks].total_pages++;
+ }
+
+ ptr = &cur_page->vlinks[--unallocated];
+ alloc_counts[(int)alloc_type_vlinks].unallocated = unallocated;
+
+#else
+
+ ptr = (vlinks_t *) xmalloc (sizeof (vlinks_t));
+
+#endif
+
+ alloc_counts[(int)alloc_type_vlinks].total_alloc++;
+ *ptr = initial_vlinks;
+ return ptr;
+}
+
+/* Allocate string hash buckets. */
+
+static shash_t *
+allocate_shash ()
+{
+ register shash_t *ptr;
+ static shash_t initial_shash;
+
+#ifndef MALLOC_CHECK
+
+ register int unallocated = alloc_counts[(int)alloc_type_shash].unallocated;
+ register page_type *cur_page = alloc_counts[(int)alloc_type_shash].cur_page;
+
+ if (unallocated == 0)
+ {
+ unallocated = PAGE_SIZE / sizeof (shash_t);
+ alloc_counts[(int)alloc_type_shash].cur_page = cur_page = allocate_page ();
+ alloc_counts[(int)alloc_type_shash].total_pages++;
+ }
+
+ ptr = &cur_page->shash[--unallocated];
+ alloc_counts[(int)alloc_type_shash].unallocated = unallocated;
+
+#else
+
+ ptr = (shash_t *) xmalloc (sizeof (shash_t));
+
+#endif
+
+ alloc_counts[(int)alloc_type_shash].total_alloc++;
+ *ptr = initial_shash;
+ return ptr;
+}
+
+/* Allocate type hash buckets. */
+
+static thash_t *
+allocate_thash ()
+{
+ register thash_t *ptr;
+ static thash_t initial_thash;
+
+#ifndef MALLOC_CHECK
+
+ register int unallocated = alloc_counts[(int)alloc_type_thash].unallocated;
+ register page_type *cur_page = alloc_counts[(int)alloc_type_thash].cur_page;
+
+ if (unallocated == 0)
+ {
+ unallocated = PAGE_SIZE / sizeof (thash_t);
+ alloc_counts[(int)alloc_type_thash].cur_page = cur_page = allocate_page ();
+ alloc_counts[(int)alloc_type_thash].total_pages++;
+ }
+
+ ptr = &cur_page->thash[--unallocated];
+ alloc_counts[(int)alloc_type_thash].unallocated = unallocated;
+
+#else
+
+ ptr = (thash_t *) xmalloc (sizeof (thash_t));
+
+#endif
+
+ alloc_counts[(int)alloc_type_thash].total_alloc++;
+ *ptr = initial_thash;
+ return ptr;
+}
+
+/* Allocate structure, union, or enum tag information. */
+
+static tag_t *
+allocate_tag ()
+{
+ register tag_t *ptr;
+ static tag_t initial_tag;
+
+#ifndef MALLOC_CHECK
+
+ ptr = alloc_counts[(int)alloc_type_tag].free_list.f_tag;
+ if (ptr != (tag_t *) NULL)
+ alloc_counts[(int)alloc_type_tag].free_list.f_tag = ptr->free;
+ else
+ {
+ register int unallocated = alloc_counts[(int)alloc_type_tag].unallocated;
+ register page_type *cur_page = alloc_counts[(int)alloc_type_tag].cur_page;
+
+ if (unallocated == 0)
+ {
+ unallocated = PAGE_SIZE / sizeof (tag_t);
+ alloc_counts[(int)alloc_type_tag].cur_page = cur_page = allocate_page ();
+ alloc_counts[(int)alloc_type_tag].total_pages++;
+ }
+
+ ptr = &cur_page->tag[--unallocated];
+ alloc_counts[(int)alloc_type_tag].unallocated = unallocated;
+ }
+
+#else
+
+ ptr = (tag_t *) xmalloc (sizeof (tag_t));
+
+#endif
+
+ alloc_counts[(int)alloc_type_tag].total_alloc++;
+ *ptr = initial_tag;
+ return ptr;
+}
+
+/* Free scoping information. */
+
+static void
+free_tag (ptr)
+ tag_t *ptr;
+{
+ alloc_counts[(int)alloc_type_tag].total_free++;
+
+#ifndef MALLOC_CHECK
+ ptr->free = alloc_counts[(int)alloc_type_tag].free_list.f_tag;
+ alloc_counts[(int)alloc_type_tag].free_list.f_tag = ptr;
+#else
+ free ((PTR_T) ptr);
+#endif
+}
+
+/* Allocate forward reference to a yet unknown tag. */
+
+static forward_t *
+allocate_forward ()
+{
+ register forward_t *ptr;
+ static forward_t initial_forward;
+
+#ifndef MALLOC_CHECK
+
+ register int unallocated = alloc_counts[(int)alloc_type_forward].unallocated;
+ register page_type *cur_page = alloc_counts[(int)alloc_type_forward].cur_page;
+
+ if (unallocated == 0)
+ {
+ unallocated = PAGE_SIZE / sizeof (forward_t);
+ alloc_counts[(int)alloc_type_forward].cur_page = cur_page = allocate_page ();
+ alloc_counts[(int)alloc_type_forward].total_pages++;
+ }
+
+ ptr = &cur_page->forward[--unallocated];
+ alloc_counts[(int)alloc_type_forward].unallocated = unallocated;
+
+#else
+
+ ptr = (forward_t *) xmalloc (sizeof (forward_t));
+
+#endif
+
+ alloc_counts[(int)alloc_type_forward].total_alloc++;
+ *ptr = initial_forward;
+ return ptr;
+}
+
+/* Allocate head of type hash list. */
+
+static thead_t *
+allocate_thead ()
+{
+ register thead_t *ptr;
+ static thead_t initial_thead;
+
+#ifndef MALLOC_CHECK
+
+ ptr = alloc_counts[(int)alloc_type_thead].free_list.f_thead;
+ if (ptr != (thead_t *) NULL)
+ alloc_counts[ (int)alloc_type_thead ].free_list.f_thead = ptr->free;
+ else
+ {
+ register int unallocated = alloc_counts[(int)alloc_type_thead].unallocated;
+ register page_type *cur_page = alloc_counts[(int)alloc_type_thead].cur_page;
+
+ if (unallocated == 0)
+ {
+ unallocated = PAGE_SIZE / sizeof (thead_t);
+ alloc_counts[(int)alloc_type_thead].cur_page = cur_page = allocate_page ();
+ alloc_counts[(int)alloc_type_thead].total_pages++;
+ }
+
+ ptr = &cur_page->thead[--unallocated];
+ alloc_counts[(int)alloc_type_thead].unallocated = unallocated;
+ }
+
+#else
+
+ ptr = (thead_t *) xmalloc (sizeof (thead_t));
+
+#endif
+
+ alloc_counts[(int)alloc_type_thead].total_alloc++;
+ *ptr = initial_thead;
+ return ptr;
+}
+
+/* Free scoping information. */
+
+static void
+free_thead (ptr)
+ thead_t *ptr;
+{
+ alloc_counts[(int)alloc_type_thead].total_free++;
+
+#ifndef MALLOC_CHECK
+ ptr->free = (thead_t *) alloc_counts[(int)alloc_type_thead].free_list.f_thead;
+ alloc_counts[(int)alloc_type_thead].free_list.f_thead = ptr;
+#else
+ free ((PTR_T) ptr);
+#endif
+}
+
+static lineno_list_t *
+allocate_lineno_list ()
+{
+ register lineno_list_t *ptr;
+ static lineno_list_t initial_lineno_list;
+
+#ifndef MALLOC_CHECK
+
+ register int unallocated = alloc_counts[(int)alloc_type_lineno].unallocated;
+ register page_type *cur_page = alloc_counts[(int)alloc_type_lineno].cur_page;
+
+ if (unallocated == 0)
+ {
+ unallocated = PAGE_SIZE / sizeof (lineno_list_t);
+ alloc_counts[(int)alloc_type_lineno].cur_page = cur_page = allocate_page ();
+ alloc_counts[(int)alloc_type_lineno].total_pages++;
+ }
+
+ ptr = &cur_page->lineno[--unallocated];
+ alloc_counts[(int)alloc_type_lineno].unallocated = unallocated;
+
+#else
+
+ ptr = (lineno_list_t *) xmalloc (sizeof (lineno_list_t));
+
+#endif
+
+ alloc_counts[(int)alloc_type_lineno].total_alloc++;
+ *ptr = initial_lineno_list;
+ return ptr;
+}
+
+void
+ecoff_set_gp_prolog_size (sz)
+ int sz;
+{
+ if (cur_proc_ptr == 0)
+ return;
+
+ cur_proc_ptr->pdr.gp_prologue = sz;
+ if (cur_proc_ptr->pdr.gp_prologue != sz)
+ {
+ as_warn (_("GP prologue size exceeds field size, using 0 instead"));
+ cur_proc_ptr->pdr.gp_prologue = 0;
+ }
+
+ cur_proc_ptr->pdr.gp_used = 1;
+}
+
+int
+ecoff_no_current_file ()
+{
+ return cur_file_ptr == (efdr_t *) NULL;
+}
+
+void
+ecoff_generate_asm_lineno ()
+{
+ unsigned int lineno;
+ char *filename;
+ lineno_list_t *list;
+
+ as_where (&filename, &lineno);
+
+ if (current_stabs_filename == (char *)NULL
+ || strcmp (current_stabs_filename, filename))
+ add_file (filename, 0, 1);
+
+ list = allocate_lineno_list ();
+
+ list->next = (lineno_list_t *) NULL;
+ list->file = cur_file_ptr;
+ list->proc = cur_proc_ptr;
+ list->frag = frag_now;
+ list->paddr = frag_now_fix ();
+ list->lineno = lineno;
+
+ /* We don't want to merge files which have line numbers. */
+ cur_file_ptr->fdr.fMerge = 0;
+
+ /* A .loc directive will sometimes appear before a .ent directive,
+ which means that cur_proc_ptr will be NULL here. Arrange to
+ patch this up. */
+ if (cur_proc_ptr == (proc_t *) NULL)
+ {
+ lineno_list_t **pl;
+
+ pl = &noproc_lineno;
+ while (*pl != (lineno_list_t *) NULL)
+ pl = &(*pl)->next;
+ *pl = list;
+ }
+ else
+ {
+ last_lineno = list;
+ *last_lineno_ptr = list;
+ last_lineno_ptr = &list->next;
+ }
+}
+
+#else
+
+void
+ecoff_generate_asm_lineno ()
+{
+}
+
+#endif /* ECOFF_DEBUGGING */
diff --git a/gas/ecoff.h b/gas/ecoff.h
new file mode 100644
index 0000000000..1a9b6fcdd3
--- /dev/null
+++ b/gas/ecoff.h
@@ -0,0 +1,110 @@
+/* ecoff.h -- header file for ECOFF debugging support
+ Copyright (C) 1993, 94, 95, 96, 1997 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+ Put together by Ian Lance Taylor <ian@cygnus.com>.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#ifndef GAS_ECOFF_H
+#define GAS_ECOFF_H
+
+#ifdef ECOFF_DEBUGGING
+
+#include "coff/sym.h"
+#include "coff/ecoff.h"
+
+/* Whether we have seen any ECOFF debugging information. */
+extern int ecoff_debugging_seen;
+
+/* This function should be called at the start of assembly, by
+ obj_read_begin_hook. */
+extern void ecoff_read_begin_hook PARAMS ((void));
+
+/* This function should be called when the assembler switches to a new
+ file. */
+extern void ecoff_new_file PARAMS ((const char *));
+
+/* This function should be called when a new symbol is created, by
+ obj_symbol_new_hook. */
+extern void ecoff_symbol_new_hook PARAMS ((struct symbol *));
+
+/* This function should be called by the obj_frob_symbol hook. */
+extern void ecoff_frob_symbol PARAMS ((struct symbol *));
+
+/* Build the ECOFF debugging information. This should be called by
+ obj_frob_file. This fills in the counts in *HDR; the offsets are
+ filled in relative to the start of the *BUFP. It sets *BUFP to a
+ block of memory holding the debugging information. It returns the
+ length of *BUFP. */
+extern unsigned long ecoff_build_debug
+ PARAMS ((HDRR *hdr, char **bufp, const struct ecoff_debug_swap *));
+
+/* Functions to handle the ECOFF debugging directives. */
+extern void ecoff_directive_begin PARAMS ((int));
+extern void ecoff_directive_bend PARAMS ((int));
+extern void ecoff_directive_end PARAMS ((int));
+extern void ecoff_directive_ent PARAMS ((int));
+extern void ecoff_directive_fmask PARAMS ((int));
+extern void ecoff_directive_frame PARAMS ((int));
+extern void ecoff_directive_loc PARAMS ((int));
+extern void ecoff_directive_mask PARAMS ((int));
+
+/* Other ECOFF directives. */
+extern void ecoff_directive_extern PARAMS ((int));
+extern void ecoff_directive_weakext PARAMS ((int));
+
+/* Functions to handle the COFF debugging directives. */
+extern void ecoff_directive_def PARAMS ((int));
+extern void ecoff_directive_dim PARAMS ((int));
+extern void ecoff_directive_endef PARAMS ((int));
+extern void ecoff_directive_file PARAMS ((int));
+extern void ecoff_directive_scl PARAMS ((int));
+extern void ecoff_directive_size PARAMS ((int));
+extern void ecoff_directive_tag PARAMS ((int));
+extern void ecoff_directive_type PARAMS ((int));
+extern void ecoff_directive_val PARAMS ((int));
+
+/* Handle stabs. */
+extern void ecoff_stab PARAMS ((segT sec, int what, const char *string,
+ int type, int other, int desc));
+
+/* Set the GP prologue size. */
+extern void ecoff_set_gp_prolog_size PARAMS ((int sz));
+
+/* This routine is called from the ECOFF code to set the external
+ information for a symbol. */
+#ifndef obj_ecoff_set_ext
+extern void obj_ecoff_set_ext PARAMS ((struct symbol *, EXTR *));
+#endif
+
+/* This routine is used to patch up a line number directive when
+ instructions are moved around. */
+extern void ecoff_fix_loc PARAMS ((fragS *, unsigned long));
+
+/* This function is called from read.c to peek at cur_file_ptr. */
+extern int ecoff_no_current_file PARAMS ((void));
+
+/* This function returns the symbol associated with the current proc. */
+extern struct symbol *ecoff_get_cur_proc_sym PARAMS ((void));
+
+#endif /* ECOFF_DEBUGGING */
+
+/* This routine is called from read.c to generate line number for .s file. */
+extern void ecoff_generate_asm_lineno PARAMS ((void));
+
+#endif /* ! GAS_ECOFF_H */
diff --git a/gas/ehopt.c b/gas/ehopt.c
new file mode 100644
index 0000000000..a0a5f62f4d
--- /dev/null
+++ b/gas/ehopt.c
@@ -0,0 +1,469 @@
+/* ehopt.c--optimize gcc exception frame information.
+ Copyright (C) 1998 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor <ian@cygnus.com>.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GAS 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 more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#include "as.h"
+#include "subsegs.h"
+
+/* We include this ELF file, even though we may not be assembling for
+ ELF, since the exception frame information is always in a format
+ derived from DWARF. */
+
+#include "elf/dwarf2.h"
+
+/* Try to optimize gcc 2.8 exception frame information.
+
+ Exception frame information is emitted for every function in the
+ .eh_frame section. Simple information for a function with no
+ exceptions looks like this:
+
+__FRAME_BEGIN__:
+ .4byte .LLCIE1 / Length of Common Information Entry
+.LSCIE1:
+ .4byte 0x0 / CIE Identifier Tag
+ .byte 0x1 / CIE Version
+ .byte 0x0 / CIE Augmentation (none)
+ .byte 0x1 / ULEB128 0x1 (CIE Code Alignment Factor)
+ .byte 0x7c / SLEB128 -4 (CIE Data Alignment Factor)
+ .byte 0x8 / CIE RA Column
+ .byte 0xc / DW_CFA_def_cfa
+ .byte 0x4 / ULEB128 0x4
+ .byte 0x4 / ULEB128 0x4
+ .byte 0x88 / DW_CFA_offset, column 0x8
+ .byte 0x1 / ULEB128 0x1
+ .align 4
+.LECIE1:
+ .set .LLCIE1,.LECIE1-.LSCIE1 / CIE Length Symbol
+ .4byte .LLFDE1 / FDE Length
+.LSFDE1:
+ .4byte .LSFDE1-__FRAME_BEGIN__ / FDE CIE offset
+ .4byte .LFB1 / FDE initial location
+ .4byte .LFE1-.LFB1 / FDE address range
+ .byte 0x4 / DW_CFA_advance_loc4
+ .4byte .LCFI0-.LFB1
+ .byte 0xe / DW_CFA_def_cfa_offset
+ .byte 0x8 / ULEB128 0x8
+ .byte 0x85 / DW_CFA_offset, column 0x5
+ .byte 0x2 / ULEB128 0x2
+ .byte 0x4 / DW_CFA_advance_loc4
+ .4byte .LCFI1-.LCFI0
+ .byte 0xd / DW_CFA_def_cfa_register
+ .byte 0x5 / ULEB128 0x5
+ .byte 0x4 / DW_CFA_advance_loc4
+ .4byte .LCFI2-.LCFI1
+ .byte 0x2e / DW_CFA_GNU_args_size
+ .byte 0x4 / ULEB128 0x4
+ .byte 0x4 / DW_CFA_advance_loc4
+ .4byte .LCFI3-.LCFI2
+ .byte 0x2e / DW_CFA_GNU_args_size
+ .byte 0x0 / ULEB128 0x0
+ .align 4
+.LEFDE1:
+ .set .LLFDE1,.LEFDE1-.LSFDE1 / FDE Length Symbol
+
+ The immediate issue we can address in the assembler is the
+ DW_CFA_advance_loc4 followed by a four byte value. The value is
+ the difference of two addresses in the function. Since gcc does
+ not know this value, it always uses four bytes. We will know the
+ value at the end of assembly, so we can do better. */
+
+static int eh_frame_code_alignment PARAMS ((void));
+
+/* Get the code alignment factor from the CIE. */
+
+static int
+eh_frame_code_alignment ()
+{
+ static int code_alignment;
+ segT current_seg;
+ subsegT current_subseg;
+ fragS *f;
+ fixS *fix;
+ int offset;
+ char augmentation[10];
+ int iaug;
+
+ if (code_alignment != 0)
+ return code_alignment;
+
+ /* We should find the CIE at the start of the .eh_frame section. */
+
+ current_seg = now_seg;
+ current_subseg = now_subseg;
+ subseg_new (".eh_frame", 0);
+#if defined (BFD_ASSEMBLER) || defined (MANY_SEGMENTS)
+ f = seg_info (now_seg)->frchainP->frch_root;
+#else
+ f = frchain_now->frch_root;
+#endif
+#ifdef BFD_ASSEMBLER
+ fix = seg_info (now_seg)->frchainP->fix_root;
+#else
+ fix = *seg_fix_rootP;
+#endif
+ subseg_set (current_seg, current_subseg);
+
+ /* Look through the frags of the section to find the code alignment. */
+
+ /* First make sure that the CIE Identifier Tag is 0. */
+
+ offset = 4;
+ while (f != NULL && offset >= f->fr_fix)
+ {
+ offset -= f->fr_fix;
+ f = f->fr_next;
+ }
+ if (f == NULL
+ || f->fr_fix - offset < 4
+ || f->fr_literal[offset] != 0
+ || f->fr_literal[offset + 1] != 0
+ || f->fr_literal[offset + 2] != 0
+ || f->fr_literal[offset + 3] != 0)
+ {
+ code_alignment = -1;
+ return -1;
+ }
+
+ /* Next make sure the CIE version number is 1. */
+
+ offset += 4;
+ while (f != NULL && offset >= f->fr_fix)
+ {
+ offset -= f->fr_fix;
+ f = f->fr_next;
+ }
+ if (f == NULL
+ || f->fr_fix - offset < 1
+ || f->fr_literal[offset] != 1)
+ {
+ code_alignment = -1;
+ return -1;
+ }
+
+ /* Skip the augmentation (a null terminated string). */
+
+ iaug = 0;
+ ++offset;
+ while (1)
+ {
+ while (f != NULL && offset >= f->fr_fix)
+ {
+ offset -= f->fr_fix;
+ f = f->fr_next;
+ }
+ if (f == NULL)
+ {
+ code_alignment = -1;
+ return -1;
+ }
+ while (offset < f->fr_fix && f->fr_literal[offset] != '\0')
+ {
+ if ((size_t) iaug < (sizeof augmentation) - 1)
+ {
+ augmentation[iaug] = f->fr_literal[offset];
+ ++iaug;
+ }
+ ++offset;
+ }
+ if (offset < f->fr_fix)
+ break;
+ }
+ ++offset;
+ while (f != NULL && offset >= f->fr_fix)
+ {
+ offset -= f->fr_fix;
+ f = f->fr_next;
+ }
+ if (f == NULL)
+ {
+ code_alignment = -1;
+ return -1;
+ }
+
+ augmentation[iaug] = '\0';
+ if (augmentation[0] == '\0')
+ {
+ /* No augmentation. */
+ }
+ else if (strcmp (augmentation, "eh") == 0)
+ {
+ /* We have to skip a pointer. Unfortunately, we don't know how
+ large it is. We find out by looking for a matching fixup. */
+ while (fix != NULL
+ && (fix->fx_frag != f || fix->fx_where != offset))
+ fix = fix->fx_next;
+ if (fix == NULL)
+ offset += 4;
+ else
+ offset += fix->fx_size;
+ while (f != NULL && offset >= f->fr_fix)
+ {
+ offset -= f->fr_fix;
+ f = f->fr_next;
+ }
+ if (f == NULL)
+ {
+ code_alignment = -1;
+ return -1;
+ }
+ }
+ else
+ {
+ code_alignment = -1;
+ return -1;
+ }
+
+ /* We're now at the code alignment factor, which is a ULEB128. If
+ it isn't a single byte, forget it. */
+
+ code_alignment = f->fr_literal[offset] & 0xff;
+ if ((code_alignment & 0x80) != 0 || code_alignment == 0)
+ {
+ code_alignment = -1;
+ return -1;
+ }
+
+ return code_alignment;
+}
+
+/* This function is called from emit_expr. It looks for cases which
+ we can optimize.
+
+ Rather than try to parse all this information as we read it, we
+ look for a single byte DW_CFA_advance_loc4 followed by a 4 byte
+ difference. We turn that into a rs_cfa_advance frag, and handle
+ those frags at the end of the assembly. If the gcc output changes
+ somewhat, this optimization may stop working.
+
+ This function returns non-zero if it handled the expression and
+ emit_expr should not do anything, or zero otherwise. It can also
+ change *EXP and *PNBYTES. */
+
+int
+check_eh_frame (exp, pnbytes)
+ expressionS *exp;
+ unsigned int *pnbytes;
+{
+ static int saw_size;
+ static symbolS *size_end_sym;
+ static int saw_advance_loc4;
+ static fragS *loc4_frag;
+ static int loc4_fix;
+
+ if (saw_size
+ && S_IS_DEFINED (size_end_sym))
+ {
+ /* We have come to the end of the CIE or FDE. See below where
+ we set saw_size. We must check this first because we may now
+ be looking at the next size. */
+ saw_size = 0;
+ saw_advance_loc4 = 0;
+ }
+
+ if (flag_traditional_format)
+ {
+ /* Don't optimize. */
+ }
+ else if (strcmp (segment_name (now_seg), ".eh_frame") != 0)
+ {
+ saw_size = 0;
+ saw_advance_loc4 = 0;
+ }
+ else if (! saw_size
+ && *pnbytes == 4)
+ {
+ /* This might be the size of the CIE or FDE. We want to know
+ the size so that we don't accidentally optimize across an FDE
+ boundary. We recognize the size in one of two forms: a
+ symbol which will later be defined as a difference, or a
+ subtraction of two symbols. Either way, we can tell when we
+ are at the end of the FDE because the symbol becomes defined
+ (in the case of a subtraction, the end symbol, from which the
+ start symbol is being subtracted). Other ways of describing
+ the size will not be optimized. */
+ if ((exp->X_op == O_symbol || exp->X_op == O_subtract)
+ && ! S_IS_DEFINED (exp->X_add_symbol))
+ {
+ saw_size = 1;
+ size_end_sym = exp->X_add_symbol;
+ }
+ }
+ else if (saw_size
+ && *pnbytes == 1
+ && exp->X_op == O_constant
+ && exp->X_add_number == DW_CFA_advance_loc4)
+ {
+ /* This might be a DW_CFA_advance_loc4. Record the frag and the
+ position within the frag, so that we can change it later. */
+ saw_advance_loc4 = 1;
+ frag_grow (1);
+ loc4_frag = frag_now;
+ loc4_fix = frag_now_fix ();
+ }
+ else if (saw_advance_loc4
+ && *pnbytes == 4
+ && exp->X_op == O_constant)
+ {
+ int ca;
+
+ /* This is a case which we can optimize. The two symbols being
+ subtracted were in the same frag and the expression was
+ reduced to a constant. We can do the optimization entirely
+ in this function. */
+
+ saw_advance_loc4 = 0;
+
+ ca = eh_frame_code_alignment ();
+ if (ca < 0)
+ {
+ /* Don't optimize. */
+ }
+ else if (exp->X_add_number % ca == 0
+ && exp->X_add_number / ca < 0x40)
+ {
+ loc4_frag->fr_literal[loc4_fix]
+ = DW_CFA_advance_loc | (exp->X_add_number / ca);
+ /* No more bytes needed. */
+ return 1;
+ }
+ else if (exp->X_add_number < 0x100)
+ {
+ loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc1;
+ *pnbytes = 1;
+ }
+ else if (exp->X_add_number < 0x10000)
+ {
+ loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc2;
+ *pnbytes = 2;
+ }
+ }
+ else if (saw_advance_loc4
+ && *pnbytes == 4
+ && exp->X_op == O_subtract)
+ {
+
+ /* This is a case we can optimize. The expression was not
+ reduced, so we can not finish the optimization until the end
+ of the assembly. We set up a variant frag which we handle
+ later. */
+
+ saw_advance_loc4 = 0;
+
+ frag_var (rs_cfa, 4, 0, 0, make_expr_symbol (exp),
+ loc4_fix, (char *) loc4_frag);
+
+ return 1;
+ }
+ else
+ saw_advance_loc4 = 0;
+
+ return 0;
+}
+
+/* The function estimates the size of a rs_cfa variant frag based on
+ the current values of the symbols. It is called before the
+ relaxation loop. We set fr_subtype to the expected length. */
+
+int
+eh_frame_estimate_size_before_relax (frag)
+ fragS *frag;
+{
+ int ca;
+ offsetT diff;
+ int ret;
+
+ ca = eh_frame_code_alignment ();
+ diff = resolve_symbol_value (frag->fr_symbol, 0);
+
+ if (ca < 0)
+ ret = 4;
+ else if (diff % ca == 0 && diff / ca < 0x40)
+ ret = 0;
+ else if (diff < 0x100)
+ ret = 1;
+ else if (diff < 0x10000)
+ ret = 2;
+ else
+ ret = 4;
+
+ frag->fr_subtype = ret;
+
+ return ret;
+}
+
+/* This function relaxes a rs_cfa variant frag based on the current
+ values of the symbols. fr_subtype is the current length of the
+ frag. This returns the change in frag length. */
+
+int
+eh_frame_relax_frag (frag)
+ fragS *frag;
+{
+ int oldsize, newsize;
+
+ oldsize = frag->fr_subtype;
+ newsize = eh_frame_estimate_size_before_relax (frag);
+ return newsize - oldsize;
+}
+
+/* This function converts a rs_cfa variant frag into a normal fill
+ frag. This is called after all relaxation has been done.
+ fr_subtype will be the desired length of the frag. */
+
+void
+eh_frame_convert_frag (frag)
+ fragS *frag;
+{
+ offsetT diff;
+ fragS *loc4_frag;
+ int loc4_fix;
+
+ loc4_frag = (fragS *) frag->fr_opcode;
+ loc4_fix = (int) frag->fr_offset;
+
+ diff = resolve_symbol_value (frag->fr_symbol, 1);
+
+ if (frag->fr_subtype == 0)
+ {
+ int ca;
+
+ ca = eh_frame_code_alignment ();
+ assert (ca > 0 && diff % ca == 0 && diff / ca < 0x40);
+ loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc | (diff / ca);
+ }
+ else if (frag->fr_subtype == 1)
+ {
+ assert (diff < 0x100);
+ loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc1;
+ frag->fr_literal[frag->fr_fix] = diff;
+ }
+ else if (frag->fr_subtype == 2)
+ {
+ assert (diff < 0x10000);
+ loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc2;
+ md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 2);
+ }
+ else
+ md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 4);
+
+ frag->fr_fix += frag->fr_subtype;
+ frag->fr_type = rs_fill;
+ frag->fr_offset = 0;
+}
diff --git a/gas/emul-target.h b/gas/emul-target.h
new file mode 100644
index 0000000000..3704050e91
--- /dev/null
+++ b/gas/emul-target.h
@@ -0,0 +1,43 @@
+#ifndef emul_init
+#define emul_init common_emul_init
+#endif
+
+#ifndef emul_bfd_name
+#define emul_bfd_name default_emul_bfd_name
+#endif
+
+#ifndef emul_local_labels_fb
+#define emul_local_labels_fb 0
+#endif
+
+#ifndef emul_local_labels_dollar
+#define emul_local_labels_dollar 0
+#endif
+
+#ifndef emul_leading_underscore
+#define emul_leading_underscore 2
+#endif
+
+#ifndef emul_strip_underscore
+#define emul_strip_underscore 0
+#endif
+
+#ifndef emul_default_endian
+#define emul_default_endian 2
+#endif
+
+#ifndef emul_fake_label_name
+#define emul_fake_label_name 0
+#endif
+
+struct emulation emul_struct_name = {
+ 0,
+ emul_name,
+ emul_init,
+ emul_bfd_name,
+ emul_local_labels_fb, emul_local_labels_dollar,
+ emul_leading_underscore, emul_strip_underscore,
+ emul_default_endian,
+ emul_fake_label_name,
+ emul_format,
+};
diff --git a/gas/emul.h b/gas/emul.h
new file mode 100644
index 0000000000..97c46d8b2a
--- /dev/null
+++ b/gas/emul.h
@@ -0,0 +1,23 @@
+#ifndef EMUL_DEFS
+#define EMUL_DEFS
+
+struct emulation {
+ void (*match) PARAMS ((const char *));
+ const char *name;
+ void (*init) PARAMS ((void));
+ const char *(*bfd_name) PARAMS ((void));
+ unsigned local_labels_fb : 1;
+ unsigned local_labels_dollar : 1;
+ unsigned leading_underscore : 2;
+ unsigned strip_underscore : 1;
+ unsigned default_endian : 2;
+ const char *fake_label_name;
+ const struct format_ops *format;
+};
+
+COMMON struct emulation *this_emulation;
+
+extern const char *default_emul_bfd_name PARAMS ((void));
+extern void common_emul_init PARAMS ((void));
+
+#endif
diff --git a/gas/expr.c b/gas/expr.c
new file mode 100644
index 0000000000..d5d55fd3e6
--- /dev/null
+++ b/gas/expr.c
@@ -0,0 +1,1859 @@
+/* expr.c -operands, expressions-
+ Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 97, 1998
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/*
+ * This is really a branch office of as-read.c. I split it out to clearly
+ * distinguish the world of expressions from the world of statements.
+ * (It also gives smaller files to re-compile.)
+ * Here, "operand"s are of expressions, not instructions.
+ */
+
+#include <ctype.h>
+#include <string.h>
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+#include "as.h"
+#include "obstack.h"
+
+static void floating_constant PARAMS ((expressionS * expressionP));
+static void integer_constant PARAMS ((int radix, expressionS * expressionP));
+static void mri_char_constant PARAMS ((expressionS *));
+static void current_location PARAMS ((expressionS *));
+static void clean_up_expression PARAMS ((expressionS * expressionP));
+static segT operand PARAMS ((expressionS *));
+static operatorT operator PARAMS ((void));
+
+extern const char EXP_CHARS[], FLT_CHARS[];
+
+/* We keep a mapping of expression symbols to file positions, so that
+ we can provide better error messages. */
+
+struct expr_symbol_line
+{
+ struct expr_symbol_line *next;
+ symbolS *sym;
+ char *file;
+ unsigned int line;
+};
+
+static struct expr_symbol_line *expr_symbol_lines;
+
+/* Build a dummy symbol to hold a complex expression. This is how we
+ build expressions up out of other expressions. The symbol is put
+ into the fake section expr_section. */
+
+symbolS *
+make_expr_symbol (expressionP)
+ expressionS *expressionP;
+{
+ expressionS zero;
+ const char *fake;
+ symbolS *symbolP;
+ struct expr_symbol_line *n;
+
+ if (expressionP->X_op == O_symbol
+ && expressionP->X_add_number == 0)
+ return expressionP->X_add_symbol;
+
+ if (expressionP->X_op == O_big)
+ {
+ /* This won't work, because the actual value is stored in
+ generic_floating_point_number or generic_bignum, and we are
+ going to lose it if we haven't already. */
+ if (expressionP->X_add_number > 0)
+ as_bad (_("bignum invalid; zero assumed"));
+ else
+ as_bad (_("floating point number invalid; zero assumed"));
+ zero.X_op = O_constant;
+ zero.X_add_number = 0;
+ zero.X_unsigned = 0;
+ clean_up_expression (&zero);
+ expressionP = &zero;
+ }
+
+ fake = FAKE_LABEL_NAME;
+
+ /* Putting constant symbols in absolute_section rather than
+ expr_section is convenient for the old a.out code, for which
+ S_GET_SEGMENT does not always retrieve the value put in by
+ S_SET_SEGMENT. */
+ symbolP = symbol_create (fake,
+ (expressionP->X_op == O_constant
+ ? absolute_section
+ : expr_section),
+ 0, &zero_address_frag);
+ symbolP->sy_value = *expressionP;
+
+ if (expressionP->X_op == O_constant)
+ resolve_symbol_value (symbolP, 1);
+
+ n = (struct expr_symbol_line *) xmalloc (sizeof *n);
+ n->sym = symbolP;
+ as_where (&n->file, &n->line);
+ n->next = expr_symbol_lines;
+ expr_symbol_lines = n;
+
+ return symbolP;
+}
+
+/* Return the file and line number for an expr symbol. Return
+ non-zero if something was found, 0 if no information is known for
+ the symbol. */
+
+int
+expr_symbol_where (sym, pfile, pline)
+ symbolS *sym;
+ char **pfile;
+ unsigned int *pline;
+{
+ register struct expr_symbol_line *l;
+
+ for (l = expr_symbol_lines; l != NULL; l = l->next)
+ {
+ if (l->sym == sym)
+ {
+ *pfile = l->file;
+ *pline = l->line;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* Utilities for building expressions.
+ Since complex expressions are recorded as symbols for use in other
+ expressions these return a symbolS * and not an expressionS *.
+ These explicitly do not take an "add_number" argument. */
+/* ??? For completeness' sake one might want expr_build_symbol.
+ It would just return its argument. */
+
+/* Build an expression for an unsigned constant.
+ The corresponding one for signed constants is missing because
+ there's currently no need for it. One could add an unsigned_p flag
+ but that seems more clumsy. */
+
+symbolS *
+expr_build_uconstant (value)
+ offsetT value;
+{
+ expressionS e;
+
+ e.X_op = O_constant;
+ e.X_add_number = value;
+ e.X_unsigned = 1;
+ return make_expr_symbol (&e);
+}
+
+/* Build an expression for OP s1. */
+
+symbolS *
+expr_build_unary (op, s1)
+ operatorT op;
+ symbolS *s1;
+{
+ expressionS e;
+
+ e.X_op = op;
+ e.X_add_symbol = s1;
+ e.X_add_number = 0;
+ return make_expr_symbol (&e);
+}
+
+/* Build an expression for s1 OP s2. */
+
+symbolS *
+expr_build_binary (op, s1, s2)
+ operatorT op;
+ symbolS *s1;
+ symbolS *s2;
+{
+ expressionS e;
+
+ e.X_op = op;
+ e.X_add_symbol = s1;
+ e.X_op_symbol = s2;
+ e.X_add_number = 0;
+ return make_expr_symbol (&e);
+}
+
+/* Build an expression for the current location ('.'). */
+
+symbolS *
+expr_build_dot ()
+{
+ expressionS e;
+
+ current_location (&e);
+ return make_expr_symbol (&e);
+}
+
+/*
+ * Build any floating-point literal here.
+ * Also build any bignum literal here.
+ */
+
+/* Seems atof_machine can backscan through generic_bignum and hit whatever
+ happens to be loaded before it in memory. And its way too complicated
+ for me to fix right. Thus a hack. JF: Just make generic_bignum bigger,
+ and never write into the early words, thus they'll always be zero.
+ I hate Dean's floating-point code. Bleh. */
+LITTLENUM_TYPE generic_bignum[SIZE_OF_LARGE_NUMBER + 6];
+FLONUM_TYPE generic_floating_point_number =
+{
+ &generic_bignum[6], /* low (JF: Was 0) */
+ &generic_bignum[SIZE_OF_LARGE_NUMBER + 6 - 1], /* high JF: (added +6) */
+ 0, /* leader */
+ 0, /* exponent */
+ 0 /* sign */
+};
+/* If nonzero, we've been asked to assemble nan, +inf or -inf */
+int generic_floating_point_magic;
+
+static void
+floating_constant (expressionP)
+ expressionS *expressionP;
+{
+ /* input_line_pointer->*/
+ /* floating-point constant. */
+ int error_code;
+
+ error_code = atof_generic (&input_line_pointer, ".", EXP_CHARS,
+ &generic_floating_point_number);
+
+ if (error_code)
+ {
+ if (error_code == ERROR_EXPONENT_OVERFLOW)
+ {
+ as_bad (_("bad floating-point constant: exponent overflow, probably assembling junk"));
+ }
+ else
+ {
+ as_bad (_("bad floating-point constant: unknown error code=%d."), error_code);
+ }
+ }
+ expressionP->X_op = O_big;
+ /* input_line_pointer->just after constant, */
+ /* which may point to whitespace. */
+ expressionP->X_add_number = -1;
+}
+
+static valueT
+generic_bignum_to_int32 ()
+{
+ valueT number =
+ ((generic_bignum[1] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS)
+ | (generic_bignum[0] & LITTLENUM_MASK);
+ number &= 0xffffffff;
+ return number;
+}
+
+#ifdef BFD64
+static valueT
+generic_bignum_to_int64 ()
+{
+ valueT number =
+ ((((((((valueT) generic_bignum[3] & LITTLENUM_MASK)
+ << LITTLENUM_NUMBER_OF_BITS)
+ | ((valueT) generic_bignum[2] & LITTLENUM_MASK))
+ << LITTLENUM_NUMBER_OF_BITS)
+ | ((valueT) generic_bignum[1] & LITTLENUM_MASK))
+ << LITTLENUM_NUMBER_OF_BITS)
+ | ((valueT) generic_bignum[0] & LITTLENUM_MASK));
+ return number;
+}
+#endif
+
+static void
+integer_constant (radix, expressionP)
+ int radix;
+ expressionS *expressionP;
+{
+ char *start; /* start of number. */
+ char *suffix = NULL;
+ char c;
+ valueT number; /* offset or (absolute) value */
+ short int digit; /* value of next digit in current radix */
+ short int maxdig = 0;/* highest permitted digit value. */
+ int too_many_digits = 0; /* if we see >= this number of */
+ char *name; /* points to name of symbol */
+ symbolS *symbolP; /* points to symbol */
+
+ int small; /* true if fits in 32 bits. */
+
+ /* May be bignum, or may fit in 32 bits. */
+ /* Most numbers fit into 32 bits, and we want this case to be fast.
+ so we pretend it will fit into 32 bits. If, after making up a 32
+ bit number, we realise that we have scanned more digits than
+ comfortably fit into 32 bits, we re-scan the digits coding them
+ into a bignum. For decimal and octal numbers we are
+ conservative: Some numbers may be assumed bignums when in fact
+ they do fit into 32 bits. Numbers of any radix can have excess
+ leading zeros: We strive to recognise this and cast them back
+ into 32 bits. We must check that the bignum really is more than
+ 32 bits, and change it back to a 32-bit number if it fits. The
+ number we are looking for is expected to be positive, but if it
+ fits into 32 bits as an unsigned number, we let it be a 32-bit
+ number. The cavalier approach is for speed in ordinary cases. */
+ /* This has been extended for 64 bits. We blindly assume that if
+ you're compiling in 64-bit mode, the target is a 64-bit machine.
+ This should be cleaned up. */
+
+#ifdef BFD64
+#define valuesize 64
+#else /* includes non-bfd case, mostly */
+#define valuesize 32
+#endif
+
+ if (flag_m68k_mri && radix == 0)
+ {
+ int flt = 0;
+
+ /* In MRI mode, the number may have a suffix indicating the
+ radix. For that matter, it might actually be a floating
+ point constant. */
+ for (suffix = input_line_pointer;
+ isalnum ((unsigned char) *suffix);
+ suffix++)
+ {
+ if (*suffix == 'e' || *suffix == 'E')
+ flt = 1;
+ }
+
+ if (suffix == input_line_pointer)
+ {
+ radix = 10;
+ suffix = NULL;
+ }
+ else
+ {
+ c = *--suffix;
+ if (islower ((unsigned char) c))
+ c = toupper (c);
+ if (c == 'B')
+ radix = 2;
+ else if (c == 'D')
+ radix = 10;
+ else if (c == 'O' || c == 'Q')
+ radix = 8;
+ else if (c == 'H')
+ radix = 16;
+ else if (suffix[1] == '.' || c == 'E' || flt)
+ {
+ floating_constant (expressionP);
+ return;
+ }
+ else
+ {
+ radix = 10;
+ suffix = NULL;
+ }
+ }
+ }
+
+ switch (radix)
+ {
+ case 2:
+ maxdig = 2;
+ too_many_digits = valuesize + 1;
+ break;
+ case 8:
+ maxdig = radix = 8;
+ too_many_digits = (valuesize + 2) / 3 + 1;
+ break;
+ case 16:
+ maxdig = radix = 16;
+ too_many_digits = (valuesize + 3) / 4 + 1;
+ break;
+ case 10:
+ maxdig = radix = 10;
+ too_many_digits = (valuesize + 12) / 4; /* very rough */
+ }
+#undef valuesize
+ start = input_line_pointer;
+ c = *input_line_pointer++;
+ for (number = 0;
+ (digit = hex_value (c)) < maxdig;
+ c = *input_line_pointer++)
+ {
+ number = number * radix + digit;
+ }
+ /* c contains character after number. */
+ /* input_line_pointer->char after c. */
+ small = (input_line_pointer - start - 1) < too_many_digits;
+
+ if (radix == 16 && c == '_')
+ {
+ /* This is literal of the form 0x333_0_12345678_1.
+ This example is equivalent to 0x00000333000000001234567800000001. */
+
+ int num_little_digits = 0;
+ int i;
+ input_line_pointer = start; /*->1st digit. */
+
+ know (LITTLENUM_NUMBER_OF_BITS == 16);
+
+ for (c = '_'; c == '_'; num_little_digits+=2)
+ {
+
+ /* Convert one 64-bit word. */
+ int ndigit = 0;
+ number = 0;
+ for (c = *input_line_pointer++;
+ (digit = hex_value (c)) < maxdig;
+ c = *(input_line_pointer++))
+ {
+ number = number * radix + digit;
+ ndigit++;
+ }
+
+ /* Check for 8 digit per word max. */
+ if (ndigit > 8)
+ as_bad (_("A bignum with underscores may not have more than 8 hex digits in any word."));
+
+ /* Add this chunk to the bignum. Shift things down 2 little digits.*/
+ know (LITTLENUM_NUMBER_OF_BITS == 16);
+ for (i = min (num_little_digits + 1, SIZE_OF_LARGE_NUMBER - 1); i >= 2; i--)
+ generic_bignum[i] = generic_bignum[i-2];
+
+ /* Add the new digits as the least significant new ones. */
+ generic_bignum[0] = number & 0xffffffff;
+ generic_bignum[1] = number >> 16;
+ }
+
+ /* Again, c is char after number, input_line_pointer->after c. */
+
+ if (num_little_digits > SIZE_OF_LARGE_NUMBER - 1)
+ num_little_digits = SIZE_OF_LARGE_NUMBER - 1;
+
+ assert (num_little_digits >= 4);
+
+ if (num_little_digits != 8)
+ as_bad (_("A bignum with underscores must have exactly 4 words."));
+
+ /* We might have some leading zeros. These can be trimmed to give
+ * us a change to fit this constant into a small number.
+ */
+ while (generic_bignum[num_little_digits-1] == 0 && num_little_digits > 1)
+ num_little_digits--;
+
+ if (num_little_digits <= 2)
+ {
+ /* will fit into 32 bits. */
+ number = generic_bignum_to_int32 ();
+ small = 1;
+ }
+#ifdef BFD64
+ else if (num_little_digits <= 4)
+ {
+ /* Will fit into 64 bits. */
+ number = generic_bignum_to_int64 ();
+ small = 1;
+ }
+#endif
+ else
+ {
+ small = 0;
+ number = num_little_digits; /* number of littlenums in the bignum. */
+ }
+ }
+ else if (!small)
+ {
+ /*
+ * we saw a lot of digits. manufacture a bignum the hard way.
+ */
+ LITTLENUM_TYPE *leader; /*->high order littlenum of the bignum. */
+ LITTLENUM_TYPE *pointer; /*->littlenum we are frobbing now. */
+ long carry;
+
+ leader = generic_bignum;
+ generic_bignum[0] = 0;
+ generic_bignum[1] = 0;
+ generic_bignum[2] = 0;
+ generic_bignum[3] = 0;
+ input_line_pointer = start; /*->1st digit. */
+ c = *input_line_pointer++;
+ for (;
+ (carry = hex_value (c)) < maxdig;
+ c = *input_line_pointer++)
+ {
+ for (pointer = generic_bignum;
+ pointer <= leader;
+ pointer++)
+ {
+ long work;
+
+ work = carry + radix * *pointer;
+ *pointer = work & LITTLENUM_MASK;
+ carry = work >> LITTLENUM_NUMBER_OF_BITS;
+ }
+ if (carry)
+ {
+ if (leader < generic_bignum + SIZE_OF_LARGE_NUMBER - 1)
+ {
+ /* room to grow a longer bignum. */
+ *++leader = carry;
+ }
+ }
+ }
+ /* again, c is char after number, */
+ /* input_line_pointer->after c. */
+ know (LITTLENUM_NUMBER_OF_BITS == 16);
+ if (leader < generic_bignum + 2)
+ {
+ /* will fit into 32 bits. */
+ number = generic_bignum_to_int32 ();
+ small = 1;
+ }
+#ifdef BFD64
+ else if (leader < generic_bignum + 4)
+ {
+ /* Will fit into 64 bits. */
+ number = generic_bignum_to_int64 ();
+ small = 1;
+ }
+#endif
+ else
+ {
+ number = leader - generic_bignum + 1; /* number of littlenums in the bignum. */
+ }
+ }
+
+ if (flag_m68k_mri && suffix != NULL && input_line_pointer - 1 == suffix)
+ c = *input_line_pointer++;
+
+ if (small)
+ {
+ /*
+ * here with number, in correct radix. c is the next char.
+ * note that unlike un*x, we allow "011f" "0x9f" to
+ * both mean the same as the (conventional) "9f". this is simply easier
+ * than checking for strict canonical form. syntax sux!
+ */
+
+ if (LOCAL_LABELS_FB && c == 'b')
+ {
+ /*
+ * backward ref to local label.
+ * because it is backward, expect it to be defined.
+ */
+ /* Construct a local label. */
+ name = fb_label_name ((int) number, 0);
+
+ /* seen before, or symbol is defined: ok */
+ symbolP = symbol_find (name);
+ if ((symbolP != NULL) && (S_IS_DEFINED (symbolP)))
+ {
+ /* local labels are never absolute. don't waste time
+ checking absoluteness. */
+ know (SEG_NORMAL (S_GET_SEGMENT (symbolP)));
+
+ expressionP->X_op = O_symbol;
+ expressionP->X_add_symbol = symbolP;
+ }
+ else
+ {
+ /* either not seen or not defined. */
+ /* @@ Should print out the original string instead of
+ the parsed number. */
+ as_bad (_("backw. ref to unknown label \"%d:\", 0 assumed."),
+ (int) number);
+ expressionP->X_op = O_constant;
+ }
+
+ expressionP->X_add_number = 0;
+ } /* case 'b' */
+ else if (LOCAL_LABELS_FB && c == 'f')
+ {
+ /*
+ * forward reference. expect symbol to be undefined or
+ * unknown. undefined: seen it before. unknown: never seen
+ * it before.
+ * construct a local label name, then an undefined symbol.
+ * don't create a xseg frag for it: caller may do that.
+ * just return it as never seen before.
+ */
+ name = fb_label_name ((int) number, 1);
+ symbolP = symbol_find_or_make (name);
+ /* we have no need to check symbol properties. */
+#ifndef many_segments
+ /* since "know" puts its arg into a "string", we
+ can't have newlines in the argument. */
+ know (S_GET_SEGMENT (symbolP) == undefined_section || S_GET_SEGMENT (symbolP) == text_section || S_GET_SEGMENT (symbolP) == data_section);
+#endif
+ expressionP->X_op = O_symbol;
+ expressionP->X_add_symbol = symbolP;
+ expressionP->X_add_number = 0;
+ } /* case 'f' */
+ else if (LOCAL_LABELS_DOLLAR && c == '$')
+ {
+ /* If the dollar label is *currently* defined, then this is just
+ another reference to it. If it is not *currently* defined,
+ then this is a fresh instantiation of that number, so create
+ it. */
+
+ if (dollar_label_defined ((long) number))
+ {
+ name = dollar_label_name ((long) number, 0);
+ symbolP = symbol_find (name);
+ know (symbolP != NULL);
+ }
+ else
+ {
+ name = dollar_label_name ((long) number, 1);
+ symbolP = symbol_find_or_make (name);
+ }
+
+ expressionP->X_op = O_symbol;
+ expressionP->X_add_symbol = symbolP;
+ expressionP->X_add_number = 0;
+ } /* case '$' */
+ else
+ {
+ expressionP->X_op = O_constant;
+#ifdef TARGET_WORD_SIZE
+ /* Sign extend NUMBER. */
+ number |= (-(number >> (TARGET_WORD_SIZE - 1))) << (TARGET_WORD_SIZE - 1);
+#endif
+ expressionP->X_add_number = number;
+ input_line_pointer--; /* restore following character. */
+ } /* really just a number */
+ }
+ else
+ {
+ /* not a small number */
+ expressionP->X_op = O_big;
+ expressionP->X_add_number = number; /* number of littlenums */
+ input_line_pointer--; /*->char following number. */
+ }
+}
+
+/* Parse an MRI multi character constant. */
+
+static void
+mri_char_constant (expressionP)
+ expressionS *expressionP;
+{
+ int i;
+
+ if (*input_line_pointer == '\''
+ && input_line_pointer[1] != '\'')
+ {
+ expressionP->X_op = O_constant;
+ expressionP->X_add_number = 0;
+ return;
+ }
+
+ /* In order to get the correct byte ordering, we must build the
+ number in reverse. */
+ for (i = SIZE_OF_LARGE_NUMBER - 1; i >= 0; i--)
+ {
+ int j;
+
+ generic_bignum[i] = 0;
+ for (j = 0; j < CHARS_PER_LITTLENUM; j++)
+ {
+ if (*input_line_pointer == '\'')
+ {
+ if (input_line_pointer[1] != '\'')
+ break;
+ ++input_line_pointer;
+ }
+ generic_bignum[i] <<= 8;
+ generic_bignum[i] += *input_line_pointer;
+ ++input_line_pointer;
+ }
+
+ if (i < SIZE_OF_LARGE_NUMBER - 1)
+ {
+ /* If there is more than one littlenum, left justify the
+ last one to make it match the earlier ones. If there is
+ only one, we can just use the value directly. */
+ for (; j < CHARS_PER_LITTLENUM; j++)
+ generic_bignum[i] <<= 8;
+ }
+
+ if (*input_line_pointer == '\''
+ && input_line_pointer[1] != '\'')
+ break;
+ }
+
+ if (i < 0)
+ {
+ as_bad (_("Character constant too large"));
+ i = 0;
+ }
+
+ if (i > 0)
+ {
+ int c;
+ int j;
+
+ c = SIZE_OF_LARGE_NUMBER - i;
+ for (j = 0; j < c; j++)
+ generic_bignum[j] = generic_bignum[i + j];
+ i = c;
+ }
+
+ know (LITTLENUM_NUMBER_OF_BITS == 16);
+ if (i > 2)
+ {
+ expressionP->X_op = O_big;
+ expressionP->X_add_number = i;
+ }
+ else
+ {
+ expressionP->X_op = O_constant;
+ if (i < 2)
+ expressionP->X_add_number = generic_bignum[0] & LITTLENUM_MASK;
+ else
+ expressionP->X_add_number =
+ (((generic_bignum[1] & LITTLENUM_MASK)
+ << LITTLENUM_NUMBER_OF_BITS)
+ | (generic_bignum[0] & LITTLENUM_MASK));
+ }
+
+ /* Skip the final closing quote. */
+ ++input_line_pointer;
+}
+
+/* Return an expression representing the current location. This
+ handles the magic symbol `.'. */
+
+static void
+current_location (expressionp)
+ expressionS *expressionp;
+{
+ if (now_seg == absolute_section)
+ {
+ expressionp->X_op = O_constant;
+ expressionp->X_add_number = abs_section_offset;
+ }
+ else
+ {
+ symbolS *symbolp;
+
+ symbolp = symbol_new (FAKE_LABEL_NAME, now_seg,
+ (valueT) frag_now_fix (),
+ frag_now);
+ expressionp->X_op = O_symbol;
+ expressionp->X_add_symbol = symbolp;
+ expressionp->X_add_number = 0;
+ }
+}
+
+/*
+ * Summary of operand().
+ *
+ * in: Input_line_pointer points to 1st char of operand, which may
+ * be a space.
+ *
+ * out: A expressionS.
+ * The operand may have been empty: in this case X_op == O_absent.
+ * Input_line_pointer->(next non-blank) char after operand.
+ */
+
+static segT
+operand (expressionP)
+ expressionS *expressionP;
+{
+ char c;
+ symbolS *symbolP; /* points to symbol */
+ char *name; /* points to name of symbol */
+ segT segment;
+
+ /* All integers are regarded as unsigned unless they are negated.
+ This is because the only thing which cares whether a number is
+ unsigned is the code in emit_expr which extends constants into
+ bignums. It should only sign extend negative numbers, so that
+ something like ``.quad 0x80000000'' is not sign extended even
+ though it appears negative if valueT is 32 bits. */
+ expressionP->X_unsigned = 1;
+
+ /* digits, assume it is a bignum. */
+
+ SKIP_WHITESPACE (); /* leading whitespace is part of operand. */
+ c = *input_line_pointer++; /* input_line_pointer->past char in c. */
+
+ switch (c)
+ {
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ input_line_pointer--;
+
+ integer_constant (flag_m68k_mri ? 0 : 10, expressionP);
+ break;
+
+ case '0':
+ /* non-decimal radix */
+
+ if (flag_m68k_mri)
+ {
+ char *s;
+
+ /* Check for a hex constant. */
+ for (s = input_line_pointer; hex_p (*s); s++)
+ ;
+ if (*s == 'h' || *s == 'H')
+ {
+ --input_line_pointer;
+ integer_constant (0, expressionP);
+ break;
+ }
+ }
+
+ c = *input_line_pointer;
+ switch (c)
+ {
+ case 'o':
+ case 'O':
+ case 'q':
+ case 'Q':
+ case '8':
+ case '9':
+ if (flag_m68k_mri)
+ {
+ integer_constant (0, expressionP);
+ break;
+ }
+ /* Fall through. */
+ default:
+ default_case:
+ if (c && strchr (FLT_CHARS, c))
+ {
+ input_line_pointer++;
+ floating_constant (expressionP);
+ expressionP->X_add_number =
+ - (isupper ((unsigned char) c) ? tolower (c) : c);
+ }
+ else
+ {
+ /* The string was only zero */
+ expressionP->X_op = O_constant;
+ expressionP->X_add_number = 0;
+ }
+
+ break;
+
+ case 'x':
+ case 'X':
+ if (flag_m68k_mri)
+ goto default_case;
+ input_line_pointer++;
+ integer_constant (16, expressionP);
+ break;
+
+ case 'b':
+ if (LOCAL_LABELS_FB && ! flag_m68k_mri)
+ {
+ /* This code used to check for '+' and '-' here, and, in
+ some conditions, fall through to call
+ integer_constant. However, that didn't make sense,
+ as integer_constant only accepts digits. */
+ /* Some of our code elsewhere does permit digits greater
+ than the expected base; for consistency, do the same
+ here. */
+ if (input_line_pointer[1] < '0'
+ || input_line_pointer[1] > '9')
+ {
+ /* Parse this as a back reference to label 0. */
+ input_line_pointer--;
+ integer_constant (10, expressionP);
+ break;
+ }
+ /* Otherwise, parse this as a binary number. */
+ }
+ /* Fall through. */
+ case 'B':
+ input_line_pointer++;
+ if (flag_m68k_mri)
+ goto default_case;
+ integer_constant (2, expressionP);
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ integer_constant (flag_m68k_mri ? 0 : 8, expressionP);
+ break;
+
+ case 'f':
+ if (LOCAL_LABELS_FB)
+ {
+ /* If it says "0f" and it could possibly be a floating point
+ number, make it one. Otherwise, make it a local label,
+ and try to deal with parsing the rest later. */
+ if (!input_line_pointer[1]
+ || (is_end_of_line[0xff & input_line_pointer[1]]))
+ goto is_0f_label;
+ {
+ char *cp = input_line_pointer + 1;
+ int r = atof_generic (&cp, ".", EXP_CHARS,
+ &generic_floating_point_number);
+ switch (r)
+ {
+ case 0:
+ case ERROR_EXPONENT_OVERFLOW:
+ if (*cp == 'f' || *cp == 'b')
+ /* looks like a difference expression */
+ goto is_0f_label;
+ else if (cp == input_line_pointer + 1)
+ /* No characters has been accepted -- looks like
+ end of operand. */
+ goto is_0f_label;
+ else
+ goto is_0f_float;
+ default:
+ as_fatal (_("expr.c(operand): bad atof_generic return val %d"),
+ r);
+ }
+ }
+
+ /* Okay, now we've sorted it out. We resume at one of these
+ two labels, depending on what we've decided we're probably
+ looking at. */
+ is_0f_label:
+ input_line_pointer--;
+ integer_constant (10, expressionP);
+ break;
+
+ is_0f_float:
+ /* fall through */
+ ;
+ }
+
+ case 'd':
+ case 'D':
+ if (flag_m68k_mri)
+ {
+ integer_constant (0, expressionP);
+ break;
+ }
+ /* Fall through. */
+ case 'F':
+ case 'r':
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ input_line_pointer++;
+ floating_constant (expressionP);
+ expressionP->X_add_number =
+ - (isupper ((unsigned char) c) ? tolower (c) : c);
+ break;
+
+ case '$':
+ if (LOCAL_LABELS_DOLLAR)
+ {
+ integer_constant (10, expressionP);
+ break;
+ }
+ else
+ goto default_case;
+ }
+
+ break;
+
+ case '(':
+ case '[':
+ /* didn't begin with digit & not a name */
+ segment = expression (expressionP);
+ /* Expression() will pass trailing whitespace */
+ if ((c == '(' && *input_line_pointer++ != ')')
+ || (c == '[' && *input_line_pointer++ != ']'))
+ {
+ as_bad (_("Missing ')' assumed"));
+ input_line_pointer--;
+ }
+ SKIP_WHITESPACE ();
+ /* here with input_line_pointer->char after "(...)" */
+ return segment;
+
+ case 'E':
+ if (! flag_m68k_mri || *input_line_pointer != '\'')
+ goto de_fault;
+ as_bad (_("EBCDIC constants are not supported"));
+ /* Fall through. */
+ case 'A':
+ if (! flag_m68k_mri || *input_line_pointer != '\'')
+ goto de_fault;
+ ++input_line_pointer;
+ /* Fall through. */
+ case '\'':
+ if (! flag_m68k_mri)
+ {
+ /* Warning: to conform to other people's assemblers NO
+ ESCAPEMENT is permitted for a single quote. The next
+ character, parity errors and all, is taken as the value
+ of the operand. VERY KINKY. */
+ expressionP->X_op = O_constant;
+ expressionP->X_add_number = *input_line_pointer++;
+ break;
+ }
+
+ mri_char_constant (expressionP);
+ break;
+
+ case '+':
+ (void) operand (expressionP);
+ break;
+
+ case '"':
+ /* Double quote is the bitwise not operator in MRI mode. */
+ if (! flag_m68k_mri)
+ goto de_fault;
+ /* Fall through. */
+ case '~':
+ /* ~ is permitted to start a label on the Delta. */
+ if (is_name_beginner (c))
+ goto isname;
+ case '!':
+ case '-':
+ {
+ operand (expressionP);
+ if (expressionP->X_op == O_constant)
+ {
+ /* input_line_pointer -> char after operand */
+ if (c == '-')
+ {
+ expressionP->X_add_number = - expressionP->X_add_number;
+ /* Notice: '-' may overflow: no warning is given. This is
+ compatible with other people's assemblers. Sigh. */
+ expressionP->X_unsigned = 0;
+ }
+ else if (c == '~' || c == '"')
+ expressionP->X_add_number = ~ expressionP->X_add_number;
+ else
+ expressionP->X_add_number = ! expressionP->X_add_number;
+ }
+ else if (expressionP->X_op != O_illegal
+ && expressionP->X_op != O_absent)
+ {
+ expressionP->X_add_symbol = make_expr_symbol (expressionP);
+ if (c == '-')
+ expressionP->X_op = O_uminus;
+ else if (c == '~' || c == '"')
+ expressionP->X_op = O_bit_not;
+ else
+ expressionP->X_op = O_logical_not;
+ expressionP->X_add_number = 0;
+ }
+ else
+ as_warn (_("Unary operator %c ignored because bad operand follows"),
+ c);
+ }
+ break;
+
+ case '$':
+ /* $ is the program counter when in MRI mode, or when DOLLAR_DOT
+ is defined. */
+#ifndef DOLLAR_DOT
+ if (! flag_m68k_mri)
+ goto de_fault;
+#endif
+ if (flag_m68k_mri && hex_p (*input_line_pointer))
+ {
+ /* In MRI mode, $ is also used as the prefix for a
+ hexadecimal constant. */
+ integer_constant (16, expressionP);
+ break;
+ }
+
+ if (is_part_of_name (*input_line_pointer))
+ goto isname;
+
+ current_location (expressionP);
+ break;
+
+ case '.':
+ if (!is_part_of_name (*input_line_pointer))
+ {
+ current_location (expressionP);
+ break;
+ }
+ else if ((strncasecmp (input_line_pointer, "startof.", 8) == 0
+ && ! is_part_of_name (input_line_pointer[8]))
+ || (strncasecmp (input_line_pointer, "sizeof.", 7) == 0
+ && ! is_part_of_name (input_line_pointer[7])))
+ {
+ int start;
+
+ start = (input_line_pointer[1] == 't'
+ || input_line_pointer[1] == 'T');
+ input_line_pointer += start ? 8 : 7;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != '(')
+ as_bad (_("syntax error in .startof. or .sizeof."));
+ else
+ {
+ char *buf;
+
+ ++input_line_pointer;
+ SKIP_WHITESPACE ();
+ name = input_line_pointer;
+ c = get_symbol_end ();
+
+ buf = (char *) xmalloc (strlen (name) + 10);
+ if (start)
+ sprintf (buf, ".startof.%s", name);
+ else
+ sprintf (buf, ".sizeof.%s", name);
+ symbolP = symbol_make (buf);
+ free (buf);
+
+ expressionP->X_op = O_symbol;
+ expressionP->X_add_symbol = symbolP;
+ expressionP->X_add_number = 0;
+
+ *input_line_pointer = c;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ')')
+ as_bad (_("syntax error in .startof. or .sizeof."));
+ else
+ ++input_line_pointer;
+ }
+ break;
+ }
+ else
+ {
+ goto isname;
+ }
+ case ',':
+ case '\n':
+ case '\0':
+ eol:
+ /* can't imagine any other kind of operand */
+ expressionP->X_op = O_absent;
+ input_line_pointer--;
+ break;
+
+ case '%':
+ if (! flag_m68k_mri)
+ goto de_fault;
+ integer_constant (2, expressionP);
+ break;
+
+ case '@':
+ if (! flag_m68k_mri)
+ goto de_fault;
+ integer_constant (8, expressionP);
+ break;
+
+ case ':':
+ if (! flag_m68k_mri)
+ goto de_fault;
+
+ /* In MRI mode, this is a floating point constant represented
+ using hexadecimal digits. */
+
+ ++input_line_pointer;
+ integer_constant (16, expressionP);
+ break;
+
+ case '*':
+ if (! flag_m68k_mri || is_part_of_name (*input_line_pointer))
+ goto de_fault;
+
+ current_location (expressionP);
+ break;
+
+ default:
+ de_fault:
+ if (is_end_of_line[(unsigned char) c])
+ goto eol;
+ if (is_name_beginner (c)) /* here if did not begin with a digit */
+ {
+ /*
+ * Identifier begins here.
+ * This is kludged for speed, so code is repeated.
+ */
+ isname:
+ name = --input_line_pointer;
+ c = get_symbol_end ();
+
+#ifdef md_parse_name
+ /* This is a hook for the backend to parse certain names
+ specially in certain contexts. If a name always has a
+ specific value, it can often be handled by simply
+ entering it in the symbol table. */
+ if (md_parse_name (name, expressionP))
+ {
+ *input_line_pointer = c;
+ break;
+ }
+#endif
+
+#ifdef TC_I960
+ /* The MRI i960 assembler permits
+ lda sizeof code,g13
+ FIXME: This should use md_parse_name. */
+ if (flag_mri
+ && (strcasecmp (name, "sizeof") == 0
+ || strcasecmp (name, "startof") == 0))
+ {
+ int start;
+ char *buf;
+
+ start = (name[1] == 't'
+ || name[1] == 'T');
+
+ *input_line_pointer = c;
+ SKIP_WHITESPACE ();
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+
+ buf = (char *) xmalloc (strlen (name) + 10);
+ if (start)
+ sprintf (buf, ".startof.%s", name);
+ else
+ sprintf (buf, ".sizeof.%s", name);
+ symbolP = symbol_make (buf);
+ free (buf);
+
+ expressionP->X_op = O_symbol;
+ expressionP->X_add_symbol = symbolP;
+ expressionP->X_add_number = 0;
+
+ *input_line_pointer = c;
+ SKIP_WHITESPACE ();
+
+ break;
+ }
+#endif
+
+ symbolP = symbol_find_or_make (name);
+
+ /* If we have an absolute symbol or a reg, then we know its
+ value now. */
+ segment = S_GET_SEGMENT (symbolP);
+ if (segment == absolute_section)
+ {
+ expressionP->X_op = O_constant;
+ expressionP->X_add_number = S_GET_VALUE (symbolP);
+ }
+ else if (segment == reg_section)
+ {
+ expressionP->X_op = O_register;
+ expressionP->X_add_number = S_GET_VALUE (symbolP);
+ }
+ else
+ {
+ expressionP->X_op = O_symbol;
+ expressionP->X_add_symbol = symbolP;
+ expressionP->X_add_number = 0;
+ }
+ *input_line_pointer = c;
+ }
+ else
+ {
+ /* Let the target try to parse it. Success is indicated by changing
+ the X_op field to something other than O_absent and pointing
+ input_line_pointer passed the expression. If it can't parse the
+ expression, X_op and input_line_pointer should be unchanged. */
+ expressionP->X_op = O_absent;
+ --input_line_pointer;
+ md_operand (expressionP);
+ if (expressionP->X_op == O_absent)
+ {
+ ++input_line_pointer;
+ as_bad (_("Bad expression"));
+ expressionP->X_op = O_constant;
+ expressionP->X_add_number = 0;
+ }
+ }
+ break;
+ }
+
+ /*
+ * It is more 'efficient' to clean up the expressionS when they are created.
+ * Doing it here saves lines of code.
+ */
+ clean_up_expression (expressionP);
+ SKIP_WHITESPACE (); /*->1st char after operand. */
+ know (*input_line_pointer != ' ');
+
+ /* The PA port needs this information. */
+ if (expressionP->X_add_symbol)
+ expressionP->X_add_symbol->sy_used = 1;
+
+ switch (expressionP->X_op)
+ {
+ default:
+ return absolute_section;
+ case O_symbol:
+ return S_GET_SEGMENT (expressionP->X_add_symbol);
+ case O_register:
+ return reg_section;
+ }
+} /* operand() */
+
+/* Internal. Simplify a struct expression for use by expr() */
+
+/*
+ * In: address of a expressionS.
+ * The X_op field of the expressionS may only take certain values.
+ * Elsewise we waste time special-case testing. Sigh. Ditto SEG_ABSENT.
+ * Out: expressionS may have been modified:
+ * 'foo-foo' symbol references cancelled to 0,
+ * which changes X_op from O_subtract to O_constant.
+ * Unused fields zeroed to help expr().
+ */
+
+static void
+clean_up_expression (expressionP)
+ expressionS *expressionP;
+{
+ switch (expressionP->X_op)
+ {
+ case O_illegal:
+ case O_absent:
+ expressionP->X_add_number = 0;
+ /* Fall through. */
+ case O_big:
+ case O_constant:
+ case O_register:
+ expressionP->X_add_symbol = NULL;
+ /* Fall through. */
+ case O_symbol:
+ case O_uminus:
+ case O_bit_not:
+ expressionP->X_op_symbol = NULL;
+ break;
+ case O_subtract:
+ if (expressionP->X_op_symbol == expressionP->X_add_symbol
+ || ((expressionP->X_op_symbol->sy_frag
+ == expressionP->X_add_symbol->sy_frag)
+ && SEG_NORMAL (S_GET_SEGMENT (expressionP->X_add_symbol))
+ && (S_GET_VALUE (expressionP->X_op_symbol)
+ == S_GET_VALUE (expressionP->X_add_symbol))))
+ {
+ addressT diff = (S_GET_VALUE (expressionP->X_add_symbol)
+ - S_GET_VALUE (expressionP->X_op_symbol));
+
+ expressionP->X_op = O_constant;
+ expressionP->X_add_symbol = NULL;
+ expressionP->X_op_symbol = NULL;
+ expressionP->X_add_number += diff;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/* Expression parser. */
+
+/*
+ * We allow an empty expression, and just assume (absolute,0) silently.
+ * Unary operators and parenthetical expressions are treated as operands.
+ * As usual, Q==quantity==operand, O==operator, X==expression mnemonics.
+ *
+ * We used to do a aho/ullman shift-reduce parser, but the logic got so
+ * warped that I flushed it and wrote a recursive-descent parser instead.
+ * Now things are stable, would anybody like to write a fast parser?
+ * Most expressions are either register (which does not even reach here)
+ * or 1 symbol. Then "symbol+constant" and "symbol-symbol" are common.
+ * So I guess it doesn't really matter how inefficient more complex expressions
+ * are parsed.
+ *
+ * After expr(RANK,resultP) input_line_pointer->operator of rank <= RANK.
+ * Also, we have consumed any leading or trailing spaces (operand does that)
+ * and done all intervening operators.
+ *
+ * This returns the segment of the result, which will be
+ * absolute_section or the segment of a symbol.
+ */
+
+#undef __
+#define __ O_illegal
+
+static const operatorT op_encoding[256] =
+{ /* maps ASCII->operators */
+
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+
+ __, O_bit_or_not, __, __, __, O_modulus, O_bit_and, __,
+ __, __, O_multiply, O_add, __, O_subtract, __, O_divide,
+ __, __, __, __, __, __, __, __,
+ __, __, __, __, O_lt, __, O_gt, __,
+ __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, O_bit_exclusive_or, __,
+ __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __,
+ __, __, __, __, O_bit_inclusive_or, __, __, __,
+
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __
+};
+
+
+/*
+ * Rank Examples
+ * 0 operand, (expression)
+ * 1 ||
+ * 2 &&
+ * 3 = <> < <= >= >
+ * 4 + -
+ * 5 used for * / % in MRI mode
+ * 6 & ^ ! |
+ * 7 * / % << >>
+ * 8 unary - unary ~
+ */
+static operator_rankT op_rank[] =
+{
+ 0, /* O_illegal */
+ 0, /* O_absent */
+ 0, /* O_constant */
+ 0, /* O_symbol */
+ 0, /* O_symbol_rva */
+ 0, /* O_register */
+ 0, /* O_bit */
+ 8, /* O_uminus */
+ 8, /* O_bit_not */
+ 8, /* O_logical_not */
+ 7, /* O_multiply */
+ 7, /* O_divide */
+ 7, /* O_modulus */
+ 7, /* O_left_shift */
+ 7, /* O_right_shift */
+ 6, /* O_bit_inclusive_or */
+ 6, /* O_bit_or_not */
+ 6, /* O_bit_exclusive_or */
+ 6, /* O_bit_and */
+ 4, /* O_add */
+ 4, /* O_subtract */
+ 3, /* O_eq */
+ 3, /* O_ne */
+ 3, /* O_lt */
+ 3, /* O_le */
+ 3, /* O_ge */
+ 3, /* O_gt */
+ 2, /* O_logical_and */
+ 1 /* O_logical_or */
+};
+
+/* Unfortunately, in MRI mode for the m68k, multiplication and
+ division have lower precedence than the bit wise operators. This
+ function sets the operator precedences correctly for the current
+ mode. Also, MRI uses a different bit_not operator, and this fixes
+ that as well. */
+
+#define STANDARD_MUL_PRECEDENCE (7)
+#define MRI_MUL_PRECEDENCE (5)
+
+void
+expr_set_precedence ()
+{
+ if (flag_m68k_mri)
+ {
+ op_rank[O_multiply] = MRI_MUL_PRECEDENCE;
+ op_rank[O_divide] = MRI_MUL_PRECEDENCE;
+ op_rank[O_modulus] = MRI_MUL_PRECEDENCE;
+ }
+ else
+ {
+ op_rank[O_multiply] = STANDARD_MUL_PRECEDENCE;
+ op_rank[O_divide] = STANDARD_MUL_PRECEDENCE;
+ op_rank[O_modulus] = STANDARD_MUL_PRECEDENCE;
+ }
+}
+
+/* Initialize the expression parser. */
+
+void
+expr_begin ()
+{
+ expr_set_precedence ();
+
+ /* Verify that X_op field is wide enough. */
+ {
+ expressionS e;
+ e.X_op = O_max;
+ assert (e.X_op == O_max);
+ }
+}
+
+/* Return the encoding for the operator at INPUT_LINE_POINTER.
+ Advance INPUT_LINE_POINTER to the last character in the operator
+ (i.e., don't change it for a single character operator). */
+
+static inline operatorT
+operator ()
+{
+ int c;
+ operatorT ret;
+
+ c = *input_line_pointer & 0xff;
+
+ switch (c)
+ {
+ default:
+ return op_encoding[c];
+
+ case '<':
+ switch (input_line_pointer[1])
+ {
+ default:
+ return op_encoding[c];
+ case '<':
+ ret = O_left_shift;
+ break;
+ case '>':
+ ret = O_ne;
+ break;
+ case '=':
+ ret = O_le;
+ break;
+ }
+ ++input_line_pointer;
+ return ret;
+
+ case '=':
+ if (input_line_pointer[1] != '=')
+ return op_encoding[c];
+
+ ++input_line_pointer;
+ return O_eq;
+
+ case '>':
+ switch (input_line_pointer[1])
+ {
+ default:
+ return op_encoding[c];
+ case '>':
+ ret = O_right_shift;
+ break;
+ case '=':
+ ret = O_ge;
+ break;
+ }
+ ++input_line_pointer;
+ return ret;
+
+ case '!':
+ /* We accept !! as equivalent to ^ for MRI compatibility. */
+ if (input_line_pointer[1] != '!')
+ {
+ if (flag_m68k_mri)
+ return O_bit_inclusive_or;
+ return op_encoding[c];
+ }
+ ++input_line_pointer;
+ return O_bit_exclusive_or;
+
+ case '|':
+ if (input_line_pointer[1] != '|')
+ return op_encoding[c];
+
+ ++input_line_pointer;
+ return O_logical_or;
+
+ case '&':
+ if (input_line_pointer[1] != '&')
+ return op_encoding[c];
+
+ ++input_line_pointer;
+ return O_logical_and;
+ }
+
+ /*NOTREACHED*/
+}
+
+/* Parse an expression. */
+
+segT
+expr (rank, resultP)
+ operator_rankT rank; /* Larger # is higher rank. */
+ expressionS *resultP; /* Deliver result here. */
+{
+ segT retval;
+ expressionS right;
+ operatorT op_left;
+ operatorT op_right;
+
+ know (rank >= 0);
+
+ retval = operand (resultP);
+
+ know (*input_line_pointer != ' '); /* Operand() gobbles spaces. */
+
+ op_left = operator ();
+ while (op_left != O_illegal && op_rank[(int) op_left] > rank)
+ {
+ segT rightseg;
+
+ input_line_pointer++; /*->after 1st character of operator. */
+
+ rightseg = expr (op_rank[(int) op_left], &right);
+ if (right.X_op == O_absent)
+ {
+ as_warn (_("missing operand; zero assumed"));
+ right.X_op = O_constant;
+ right.X_add_number = 0;
+ right.X_add_symbol = NULL;
+ right.X_op_symbol = NULL;
+ }
+
+ know (*input_line_pointer != ' ');
+
+ if (retval == undefined_section)
+ {
+ if (SEG_NORMAL (rightseg))
+ retval = rightseg;
+ }
+ else if (! SEG_NORMAL (retval))
+ retval = rightseg;
+ else if (SEG_NORMAL (rightseg)
+ && retval != rightseg
+#ifdef DIFF_EXPR_OK
+ && op_left != O_subtract
+#endif
+ )
+ as_bad (_("operation combines symbols in different segments"));
+
+ op_right = operator ();
+
+ know (op_right == O_illegal || op_rank[(int) op_right] <= op_rank[(int) op_left]);
+ know ((int) op_left >= (int) O_multiply
+ && (int) op_left <= (int) O_logical_or);
+
+ /* input_line_pointer->after right-hand quantity. */
+ /* left-hand quantity in resultP */
+ /* right-hand quantity in right. */
+ /* operator in op_left. */
+
+ if (resultP->X_op == O_big)
+ {
+ if (resultP->X_add_number > 0)
+ as_warn (_("left operand is a bignum; integer 0 assumed"));
+ else
+ as_warn (_("left operand is a float; integer 0 assumed"));
+ resultP->X_op = O_constant;
+ resultP->X_add_number = 0;
+ resultP->X_add_symbol = NULL;
+ resultP->X_op_symbol = NULL;
+ }
+ if (right.X_op == O_big)
+ {
+ if (right.X_add_number > 0)
+ as_warn (_("right operand is a bignum; integer 0 assumed"));
+ else
+ as_warn (_("right operand is a float; integer 0 assumed"));
+ right.X_op = O_constant;
+ right.X_add_number = 0;
+ right.X_add_symbol = NULL;
+ right.X_op_symbol = NULL;
+ }
+
+ /* Optimize common cases. */
+ if (op_left == O_add && right.X_op == O_constant)
+ {
+ /* X + constant. */
+ resultP->X_add_number += right.X_add_number;
+ }
+ /* This case comes up in PIC code. */
+ else if (op_left == O_subtract
+ && right.X_op == O_symbol
+ && resultP->X_op == O_symbol
+ && (right.X_add_symbol->sy_frag
+ == resultP->X_add_symbol->sy_frag)
+ && SEG_NORMAL (S_GET_SEGMENT (right.X_add_symbol)))
+
+ {
+ resultP->X_add_number -= right.X_add_number;
+ resultP->X_add_number += (S_GET_VALUE (resultP->X_add_symbol)
+ - S_GET_VALUE (right.X_add_symbol));
+ resultP->X_op = O_constant;
+ resultP->X_add_symbol = 0;
+ }
+ else if (op_left == O_subtract && right.X_op == O_constant)
+ {
+ /* X - constant. */
+ resultP->X_add_number -= right.X_add_number;
+ }
+ else if (op_left == O_add && resultP->X_op == O_constant)
+ {
+ /* Constant + X. */
+ resultP->X_op = right.X_op;
+ resultP->X_add_symbol = right.X_add_symbol;
+ resultP->X_op_symbol = right.X_op_symbol;
+ resultP->X_add_number += right.X_add_number;
+ retval = rightseg;
+ }
+ else if (resultP->X_op == O_constant && right.X_op == O_constant)
+ {
+ /* Constant OP constant. */
+ offsetT v = right.X_add_number;
+ if (v == 0 && (op_left == O_divide || op_left == O_modulus))
+ {
+ as_warn (_("division by zero"));
+ v = 1;
+ }
+ switch (op_left)
+ {
+ default: abort ();
+ case O_multiply: resultP->X_add_number *= v; break;
+ case O_divide: resultP->X_add_number /= v; break;
+ case O_modulus: resultP->X_add_number %= v; break;
+ case O_left_shift: resultP->X_add_number <<= v; break;
+ case O_right_shift:
+ /* We always use unsigned shifts, to avoid relying on
+ characteristics of the compiler used to compile gas. */
+ resultP->X_add_number =
+ (offsetT) ((valueT) resultP->X_add_number >> (valueT) v);
+ break;
+ case O_bit_inclusive_or: resultP->X_add_number |= v; break;
+ case O_bit_or_not: resultP->X_add_number |= ~v; break;
+ case O_bit_exclusive_or: resultP->X_add_number ^= v; break;
+ case O_bit_and: resultP->X_add_number &= v; break;
+ case O_add: resultP->X_add_number += v; break;
+ case O_subtract: resultP->X_add_number -= v; break;
+ case O_eq:
+ resultP->X_add_number =
+ resultP->X_add_number == v ? ~ (offsetT) 0 : 0;
+ break;
+ case O_ne:
+ resultP->X_add_number =
+ resultP->X_add_number != v ? ~ (offsetT) 0 : 0;
+ break;
+ case O_lt:
+ resultP->X_add_number =
+ resultP->X_add_number < v ? ~ (offsetT) 0 : 0;
+ break;
+ case O_le:
+ resultP->X_add_number =
+ resultP->X_add_number <= v ? ~ (offsetT) 0 : 0;
+ break;
+ case O_ge:
+ resultP->X_add_number =
+ resultP->X_add_number >= v ? ~ (offsetT) 0 : 0;
+ break;
+ case O_gt:
+ resultP->X_add_number =
+ resultP->X_add_number > v ? ~ (offsetT) 0 : 0;
+ break;
+ case O_logical_and:
+ resultP->X_add_number = resultP->X_add_number && v;
+ break;
+ case O_logical_or:
+ resultP->X_add_number = resultP->X_add_number || v;
+ break;
+ }
+ }
+ else if (resultP->X_op == O_symbol
+ && right.X_op == O_symbol
+ && (op_left == O_add
+ || op_left == O_subtract
+ || (resultP->X_add_number == 0
+ && right.X_add_number == 0)))
+ {
+ /* Symbol OP symbol. */
+ resultP->X_op = op_left;
+ resultP->X_op_symbol = right.X_add_symbol;
+ if (op_left == O_add)
+ resultP->X_add_number += right.X_add_number;
+ else if (op_left == O_subtract)
+ resultP->X_add_number -= right.X_add_number;
+ }
+ else
+ {
+ /* The general case. */
+ resultP->X_add_symbol = make_expr_symbol (resultP);
+ resultP->X_op_symbol = make_expr_symbol (&right);
+ resultP->X_op = op_left;
+ resultP->X_add_number = 0;
+ resultP->X_unsigned = 1;
+ }
+
+ op_left = op_right;
+ } /* While next operator is >= this rank. */
+
+ /* The PA port needs this information. */
+ if (resultP->X_add_symbol)
+ resultP->X_add_symbol->sy_used = 1;
+
+ return resultP->X_op == O_constant ? absolute_section : retval;
+}
+
+/*
+ * get_symbol_end()
+ *
+ * This lives here because it belongs equally in expr.c & read.c.
+ * Expr.c is just a branch office read.c anyway, and putting it
+ * here lessens the crowd at read.c.
+ *
+ * Assume input_line_pointer is at start of symbol name.
+ * Advance input_line_pointer past symbol name.
+ * Turn that character into a '\0', returning its former value.
+ * This allows a string compare (RMS wants symbol names to be strings)
+ * of the symbol name.
+ * There will always be a char following symbol name, because all good
+ * lines end in end-of-line.
+ */
+char
+get_symbol_end ()
+{
+ char c;
+
+ /* We accept \001 in a name in case this is being called with a
+ constructed string. */
+ if (is_name_beginner (c = *input_line_pointer++) || c == '\001')
+ while (is_part_of_name (c = *input_line_pointer++)
+ || c == '\001')
+ ;
+ *--input_line_pointer = 0;
+ return (c);
+}
+
+
+unsigned int
+get_single_number ()
+{
+ expressionS exp;
+ operand (&exp);
+ return exp.X_add_number;
+
+}
+
+/* end of expr.c */
diff --git a/gas/expr.h b/gas/expr.h
new file mode 100644
index 0000000000..da9074389f
--- /dev/null
+++ b/gas/expr.h
@@ -0,0 +1,162 @@
+/* expr.h -> header file for expr.c
+ Copyright (C) 1987, 92-97, 1998 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/*
+ * By popular demand, we define a struct to represent an expression.
+ * This will no doubt mutate as expressions become baroque.
+ *
+ * Currently, we support expressions like "foo OP bar + 42". In other
+ * words we permit a (possibly undefined) symbol, a (possibly
+ * undefined) symbol and the operation used to combine the symbols,
+ * and an (absolute) augend. RMS says this is so we can have 1-pass
+ * assembly for any compiler emissions, and a 'case' statement might
+ * emit 'undefined1 - undefined2'.
+ *
+ * The type of an expression used to be stored as a segment. That got
+ * confusing because it overloaded the concept of a segment. I added
+ * an operator field, instead.
+ */
+
+/* This is the type of an expression. The operator types are also
+ used while parsing an expression.
+
+ NOTE: This enumeration must match the op_rank array in expr.c. */
+
+typedef enum
+{
+ /* An illegal expression. */
+ O_illegal,
+ /* A nonexistent expression. */
+ O_absent,
+ /* X_add_number (a constant expression). */
+ O_constant,
+ /* X_add_symbol + X_add_number. */
+ O_symbol,
+ /* X_add_symbol + X_add_number - the base address of the image. */
+ O_symbol_rva,
+ /* A register (X_add_number is register number). */
+ O_register,
+ /* A big value. If X_add_number is negative or 0, the value is in
+ generic_floating_point_number. Otherwise the value is in
+ generic_bignum, and X_add_number is the number of LITTLENUMs in
+ the value. */
+ O_big,
+ /* (- X_add_symbol) + X_add_number. */
+ O_uminus,
+ /* (~ X_add_symbol) + X_add_number. */
+ O_bit_not,
+ /* (! X_add_symbol) + X_add_number. */
+ O_logical_not,
+ /* (X_add_symbol * X_op_symbol) + X_add_number. */
+ O_multiply,
+ /* (X_add_symbol / X_op_symbol) + X_add_number. */
+ O_divide,
+ /* X_add_symbol % X_op_symbol) + X_add_number. */
+ O_modulus,
+ /* X_add_symbol << X_op_symbol) + X_add_number. */
+ O_left_shift,
+ /* X_add_symbol >> X_op_symbol) + X_add_number. */
+ O_right_shift,
+ /* X_add_symbol | X_op_symbol) + X_add_number. */
+ O_bit_inclusive_or,
+ /* X_add_symbol |~ X_op_symbol) + X_add_number. */
+ O_bit_or_not,
+ /* X_add_symbol ^ X_op_symbol) + X_add_number. */
+ O_bit_exclusive_or,
+ /* X_add_symbol & X_op_symbol) + X_add_number. */
+ O_bit_and,
+ /* X_add_symbol + X_op_symbol) + X_add_number. */
+ O_add,
+ /* X_add_symbol - X_op_symbol) + X_add_number. */
+ O_subtract,
+ /* (X_add_symbol == X_op_symbol) + X_add_number. */
+ O_eq,
+ /* (X_add_symbol != X_op_symbol) + X_add_number. */
+ O_ne,
+ /* (X_add_symbol < X_op_symbol) + X_add_number. */
+ O_lt,
+ /* (X_add_symbol <= X_op_symbol) + X_add_number. */
+ O_le,
+ /* (X_add_symbol >= X_op_symbol) + X_add_number. */
+ O_ge,
+ /* (X_add_symbol > X_op_symbol) + X_add_number. */
+ O_gt,
+ /* (X_add_symbol && X_op_symbol) + X_add_number. */
+ O_logical_and,
+ /* (X_add_symbol || X_op_symbol) + X_add_number. */
+ O_logical_or,
+ /* this must be the largest value */
+ O_max
+} operatorT;
+
+typedef struct expressionS
+{
+ /* The main symbol. */
+ struct symbol *X_add_symbol;
+ /* The second symbol, if needed. */
+ struct symbol *X_op_symbol;
+ /* A number to add. */
+ offsetT X_add_number;
+ /* The type of the expression. We can't assume that an arbitrary
+ compiler can handle a bitfield of enum type. FIXME: We could
+ check this using autoconf. */
+#ifdef __GNUC__
+ operatorT X_op : 5;
+#else
+ unsigned X_op : 5;
+#endif
+ /* Non-zero if X_add_number should be regarded as unsigned. This is
+ only valid for O_constant expressions. It is only used when an
+ O_constant must be extended into a bignum (i.e., it is not used
+ when performing arithmetic on these values).
+ FIXME: This field is not set very reliably. */
+ unsigned int X_unsigned : 1;
+} expressionS;
+
+/* "result" should be type (expressionS *). */
+#define expression(result) expr (0, result)
+
+/* If an expression is O_big, look here for its value. These common
+ data may be clobbered whenever expr() is called. */
+/* Flonums returned here. Big enough to hold most precise flonum. */
+extern FLONUM_TYPE generic_floating_point_number;
+/* Bignums returned here. */
+extern LITTLENUM_TYPE generic_bignum[];
+/* Number of littlenums in above. */
+#define SIZE_OF_LARGE_NUMBER (20)
+
+typedef char operator_rankT;
+
+extern char get_symbol_end PARAMS ((void));
+extern void expr_begin PARAMS ((void));
+extern void expr_set_precedence PARAMS ((void));
+extern segT expr PARAMS ((int rank, expressionS * resultP));
+extern unsigned int get_single_number PARAMS ((void));
+extern struct symbol *make_expr_symbol PARAMS ((expressionS * expressionP));
+extern int expr_symbol_where
+ PARAMS ((struct symbol *, char **, unsigned int *));
+
+extern struct symbol * expr_build_uconstant PARAMS ((offsetT));
+extern struct symbol * expr_build_unary PARAMS ((operatorT, struct symbol *));
+extern struct symbol * expr_build_binary
+ PARAMS ((operatorT, struct symbol *, struct symbol *));
+extern struct symbol * expr_build_dot PARAMS ((void));
+
+/* end of expr.h */
diff --git a/gas/flonum-copy.c b/gas/flonum-copy.c
new file mode 100644
index 0000000000..5bcc5cce7e
--- /dev/null
+++ b/gas/flonum-copy.c
@@ -0,0 +1,73 @@
+/* flonum_copy.c - copy a flonum
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "as.h"
+
+void
+flonum_copy (in, out)
+ FLONUM_TYPE *in;
+ FLONUM_TYPE *out;
+{
+ unsigned int in_length; /* 0 origin */
+ unsigned int out_length; /* 0 origin */
+
+ out->sign = in->sign;
+ in_length = in->leader - in->low;
+
+ if (in->leader < in->low)
+ {
+ out->leader = out->low - 1; /* 0.0 case */
+ }
+ else
+ {
+ out_length = out->high - out->low;
+ /*
+ * Assume no GAPS in packing of littlenums.
+ * I.e. sizeof(array) == sizeof(element) * number_of_elements.
+ */
+ if (in_length <= out_length)
+ {
+ {
+ /*
+ * For defensive programming, zero any high-order littlenums we don't need.
+ * This is destroying evidence and wasting time, so why bother???
+ */
+ if (in_length < out_length)
+ {
+ memset ((char *) (out->low + in_length + 1), '\0', out_length - in_length);
+ }
+ }
+ memcpy ((void *) (out->low), (void *) (in->low), ((in_length + 1) * sizeof (LITTLENUM_TYPE)));
+ out->exponent = in->exponent;
+ out->leader = in->leader - in->low + out->low;
+ }
+ else
+ {
+ int shorten; /* 1-origin. Number of littlenums we drop. */
+
+ shorten = in_length - out_length;
+ /* Assume out_length >= 0 ! */
+ memcpy ((void *) (out->low), (void *) (in->low + shorten), ((out_length + 1) * sizeof (LITTLENUM_TYPE)));
+ out->leader = out->high;
+ out->exponent = in->exponent + shorten;
+ }
+ } /* if any significant bits */
+} /* flonum_copy() */
+
+/* end of flonum_copy.c */
diff --git a/gas/flonum-konst.c b/gas/flonum-konst.c
new file mode 100644
index 0000000000..22bba05974
--- /dev/null
+++ b/gas/flonum-konst.c
@@ -0,0 +1,209 @@
+/* flonum_const.c - Useful Flonum constants
+ Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 1996
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include <ansidecl.h>
+#include "flonum.h"
+/* JF: I added the last entry to this table, and I'm not
+ sure if its right or not. Could go either way. I wish
+ I really understood this stuff. */
+
+
+const int table_size_of_flonum_powers_of_ten = 13;
+
+static const LITTLENUM_TYPE zero[] =
+{1};
+
+/***********************************************************************\
+ * *
+ * Warning: the low order bits may be WRONG here. *
+ * I took this from a suspect bc(1) script. *
+ * "minus_X"[] is supposed to be 10^(2^-X) expressed in base 2^16. *
+ * The radix point is just AFTER the highest element of the [] *
+ * *
+ * Because bc rounds DOWN for printing (I think), the lowest *
+ * significance littlenums should probably have 1 added to them. *
+ * *
+ \***********************************************************************/
+
+/* JF: If this equals 6553/(2^16)+39321/(2^32)+... it approaches .1 */
+static const LITTLENUM_TYPE minus_1[] =
+{
+ 39322, 39321, 39321, 39321, 39321, 39321, 39321, 39321, 39321, 39321,
+ 39321, 39321, 39321, 39321, 39321, 39321, 39321, 39321, 39321, 6553};
+static const LITTLENUM_TYPE plus_1[] =
+{10};
+
+/* JF: If this equals 655/(2^16) + 23592/(2^32) + ... it approaches .01 */
+static const LITTLENUM_TYPE minus_2[] =
+{
+ 10486, 36700, 62914, 23592, 49807, 10485, 36700, 62914, 23592, 49807,
+ 10485, 36700, 62914, 23592, 49807, 10485, 36700, 62914, 23592, 655};
+static const LITTLENUM_TYPE plus_2[] =
+{100};
+
+/* This approaches .0001 */
+static const LITTLENUM_TYPE minus_3[] =
+{
+ 52534, 20027, 37329, 65116, 64067, 60397, 14784, 18979, 33659, 19503,
+ 2726, 9542, 629, 2202, 40475, 10590, 4299, 47815, 36280, 6};
+static const LITTLENUM_TYPE plus_3[] =
+{10000};
+
+/* JF: this approaches 1e-8 */
+static const LITTLENUM_TYPE minus_4[] =
+{
+ 22517, 49501, 54293, 19424, 60699, 6716, 24348, 22618, 23904, 21327,
+ 3919, 44703, 19149, 28803, 48959, 6259, 50273, 62237, 42};
+/* This equals 1525 * 2^16 + 57600 */
+static const LITTLENUM_TYPE plus_4[] =
+{57600, 1525};
+
+/* This approaches 1e-16 */
+static const LITTLENUM_TYPE minus_5[] =
+{
+ 22199, 45957, 17005, 26266, 10526, 16260, 55017, 35680, 40443, 19789,
+ 17356, 30195, 55905, 28426, 63010, 44197, 1844};
+static const LITTLENUM_TYPE plus_5[] =
+{28609, 34546, 35};
+
+static const LITTLENUM_TYPE minus_6[] =
+{
+ 30926, 26518, 13110, 43018, 54982, 48258, 24658, 15209, 63366, 11929,
+ 20069, 43857, 60487, 51};
+static const LITTLENUM_TYPE plus_6[] =
+{61313, 34220, 16731, 11629, 1262};
+
+static const LITTLENUM_TYPE minus_7[] =
+{
+ 29819, 14733, 21490, 40602, 31315, 65186, 2695};
+static const LITTLENUM_TYPE plus_7[] =
+{
+ 7937, 49002, 60772, 28216, 38893, 55975, 63988, 59711, 20227, 24};
+
+static const LITTLENUM_TYPE minus_8[] =
+{
+ 27579, 64807, 12543, 794, 13907, 61297, 12013, 64360, 15961, 20566,
+ 24178, 15922, 59427, 110};
+static const LITTLENUM_TYPE plus_8[] =
+{
+ 15873, 11925, 39177, 991, 14589, 3861, 58415, 9076, 62956, 54223,
+ 56328, 50180, 45274, 48333, 32537, 42547, 9731, 59679, 590};
+
+static const LITTLENUM_TYPE minus_9[] =
+{
+ 11042, 8464, 58971, 63429, 6022, 63485, 5500, 53464, 47545, 50068,
+ 56988, 22819, 49708, 54493, 9920, 47667, 40409, 35764, 10383, 54466,
+ 32702, 17493, 32420, 34382, 22750, 20681, 12300};
+static const LITTLENUM_TYPE plus_9[] =
+{
+ 20678, 27614, 28272, 53066, 55311, 54677, 29038, 9906, 26288, 44486,
+ 13860, 7445, 54106, 15426, 21518, 25599, 29632, 52309, 61207, 26105,
+ 10482, 21948, 51191, 32988, 60892, 62574, 61390, 24540, 21495, 5};
+
+static const LITTLENUM_TYPE minus_10[] =
+{
+ 6214, 48771, 23471, 30163, 31763, 38013, 57001, 11770, 18263, 36366,
+ 20742, 45086, 56969, 53231, 37856, 55814, 38057, 15692, 46761, 8713,
+ 6102, 20083, 8269, 11839, 11571, 50963, 15649, 11698, 40675, 2308};
+static const LITTLENUM_TYPE plus_10[] =
+{
+ 63839, 36576, 45712, 44516, 37803, 29482, 4966, 30556, 37961, 23310,
+ 27070, 44972, 29507, 48257, 45209, 7494, 17831, 38728, 41577, 29443,
+ 36016, 7955, 35339, 35479, 36011, 14553, 49618, 5588, 25396, 28};
+
+static const LITTLENUM_TYPE minus_11[] =
+{
+ 16663, 56882, 61983, 7804, 36555, 32060, 34502, 1000, 14356, 21681,
+ 6605, 34767, 51411, 59048, 53614, 39850, 30079, 6496, 6846, 26841,
+ 40778, 19578, 59899, 44085, 54016, 24259, 11232, 21229, 21313, 81};
+static const LITTLENUM_TYPE plus_11[] =
+{
+ 92, 9054, 62707, 17993, 7821, 56838, 13992, 21321, 29637, 48426,
+ 42982, 38668, 49574, 28820, 18200, 18927, 53979, 16219, 37484, 2516,
+ 44642, 14665, 11587, 41926, 13556, 23956, 54320, 6661, 55766, 805};
+
+static const LITTLENUM_TYPE minus_12[] =
+{
+ 33202, 45969, 58804, 56734, 16482, 26007, 44984, 49334, 31007, 32944,
+ 44517, 63329, 47131, 15291, 59465, 2264, 23218, 11829, 59771, 38798,
+ 31051, 28748, 23129, 40541, 41562, 35108, 50620, 59014, 51817, 6613};
+static const LITTLENUM_TYPE plus_12[] =
+{
+ 10098, 37922, 58070, 7432, 10470, 63465, 23718, 62190, 47420, 7009,
+ 38443, 4587, 45596, 38472, 52129, 52779, 29012, 13559, 48688, 31678,
+ 41753, 58662, 10668, 36067, 29906, 56906, 21461, 46556, 59571, 9};
+
+static const LITTLENUM_TYPE minus_13[] =
+{
+ 45309, 27592, 37144, 34637, 34328, 41671, 34620, 24135, 53401, 22112,
+ 21576, 45147, 39310, 44051, 48572, 3676, 46544, 59768, 33350, 2323,
+ 49524, 61568, 3903, 36487, 36356, 30903, 14975, 9035, 29715, 667};
+static const LITTLENUM_TYPE plus_13[] =
+{
+ 18788, 16960, 6318, 45685, 55400, 46230, 35794, 25588, 7253, 55541,
+ 49716, 59760, 63592, 8191, 63765, 58530, 44667, 13294, 10001, 55586,
+ 47887, 18738, 9509, 40896, 42506, 52580, 4171, 325, 12329, 98};
+
+/* Shut up complaints about differing pointer types. They only differ
+ in the const attribute, but there isn't any easy way to do this
+ */
+#define X (LITTLENUM_TYPE *)
+
+const FLONUM_TYPE flonum_negative_powers_of_ten[] =
+{
+ {X zero, X zero, X zero, 0, '+'},
+ {X minus_1, X minus_1 + 19, X minus_1 + 19, -20, '+'},
+ {X minus_2, X minus_2 + 19, X minus_2 + 19, -20, '+'},
+ {X minus_3, X minus_3 + 19, X minus_3 + 19, -20, '+'},
+ {X minus_4, X minus_4 + 18, X minus_4 + 18, -20, '+'},
+ {X minus_5, X minus_5 + 16, X minus_5 + 16, -20, '+'},
+ {X minus_6, X minus_6 + 13, X minus_6 + 13, -20, '+'},
+ {X minus_7, X minus_7 + 6, X minus_7 + 6, -20, '+'},
+ {X minus_8, X minus_8 + 13, X minus_8 + 13, -40, '+'},
+ {X minus_9, X minus_9 + 26, X minus_9 + 26, -80, '+'},
+ {X minus_10, X minus_10 + 29, X minus_10 + 29, -136, '+'},
+ {X minus_11, X minus_11 + 29, X minus_11 + 29, -242, '+'},
+ {X minus_12, X minus_12 + 29, X minus_12 + 29, -455, '+'},
+ {X minus_13, X minus_13 + 29, X minus_13 + 29, -880, '+'},
+};
+
+const FLONUM_TYPE flonum_positive_powers_of_ten[] =
+{
+ {X zero, X zero, X zero, 0, '+'},
+ {X plus_1, X plus_1 + 0, X plus_1 + 0, 0, '+'},
+ {X plus_2, X plus_2 + 0, X plus_2 + 0, 0, '+'},
+ {X plus_3, X plus_3 + 0, X plus_3 + 0, 0, '+'},
+ {X plus_4, X plus_4 + 1, X plus_4 + 1, 0, '+'},
+ {X plus_5, X plus_5 + 2, X plus_5 + 2, 1, '+'},
+ {X plus_6, X plus_6 + 4, X plus_6 + 4, 2, '+'},
+ {X plus_7, X plus_7 + 9, X plus_7 + 9, 4, '+'},
+ {X plus_8, X plus_8 + 18, X plus_8 + 18, 8, '+'},
+ {X plus_9, X plus_9 + 29, X plus_9 + 29, 24, '+'},
+ {X plus_10, X plus_10 + 29, X plus_10 + 29, 77, '+'},
+ {X plus_11, X plus_11 + 29, X plus_11 + 29, 183, '+'},
+ {X plus_12, X plus_12 + 29, X plus_12 + 29, 396, '+'},
+ {X plus_13, X plus_13 + 29, X plus_13 + 29, 821, '+'},
+};
+
+#ifdef VMS
+void dummy1 () { }
+#endif
+/* end of flonum_const.c */
diff --git a/gas/flonum-mult.c b/gas/flonum-mult.c
new file mode 100644
index 0000000000..434a73b041
--- /dev/null
+++ b/gas/flonum-mult.c
@@ -0,0 +1,200 @@
+/* flonum_mult.c - multiply two flonums
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of Gas, the GNU Assembler.
+
+ The GNU assembler is distributed in the hope that it will be
+ useful, but WITHOUT ANY WARRANTY. No author or distributor
+ accepts responsibility to anyone for the consequences of using it
+ or for whether it serves any particular purpose or works at all,
+ unless he says so in writing. Refer to the GNU Assembler General
+ Public License for full details.
+
+ Everyone is granted permission to copy, modify and redistribute
+ the GNU Assembler, but only under the conditions described in the
+ GNU Assembler General Public License. A copy of this license is
+ supposed to have been given to you along with the GNU Assembler
+ so you can know your rights and responsibilities. It should be
+ in a file named COPYING. Among other things, the copyright
+ notice and this notice must be preserved on all copies. */
+
+#include <ansidecl.h>
+#include "flonum.h"
+
+/* plan for a . b => p(roduct)
+
+
+ +-------+-------+-/ /-+-------+-------+
+ | a | a | ... | a | a |
+ | A | A-1 | | 1 | 0 |
+ +-------+-------+-/ /-+-------+-------+
+
+
+ +-------+-------+-/ /-+-------+-------+
+ | b | b | ... | b | b |
+ | B | B-1 | | 1 | 0 |
+ +-------+-------+-/ /-+-------+-------+
+
+
+ +-------+-------+-/ /-+-------+-/ /-+-------+-------+
+ | p | p | ... | p | ... | p | p |
+ | A+B+1| A+B | | N | | 1 | 0 |
+ +-------+-------+-/ /-+-------+-/ /-+-------+-------+
+
+ /^\
+ (carry) a .b ... | ... a .b a .b
+ A B | 0 1 0 0
+ |
+ ... | ... a .b
+ | 1 0
+ |
+ | ...
+ |
+ |
+ |
+ | ___
+ | \
+ +----- P = > a .b
+ N /__ i j
+
+ N = 0 ... A+B
+
+ for all i,j where i+j=N
+ [i,j integers > 0]
+
+ a[], b[], p[] may not intersect.
+ Zero length factors signify 0 significant bits: treat as 0.0.
+ 0.0 factors do the right thing.
+ Zero length product OK.
+
+ I chose the ForTran accent "foo[bar]" instead of the C accent "*garply"
+ because I felt the ForTran way was more intuitive. The C way would
+ probably yield better code on most C compilers. Dean Elsner.
+ (C style also gives deeper insight [to me] ... oh well ...)
+ */
+
+void
+flonum_multip (a, b, product)
+ const FLONUM_TYPE *a;
+ const FLONUM_TYPE *b;
+ FLONUM_TYPE *product;
+{
+ int size_of_a; /* 0 origin */
+ int size_of_b; /* 0 origin */
+ int size_of_product; /* 0 origin */
+ int size_of_sum; /* 0 origin */
+ int extra_product_positions; /* 1 origin */
+ unsigned long work;
+ unsigned long carry;
+ long exponent;
+ LITTLENUM_TYPE *q;
+ long significant; /* TRUE when we emit a non-0 littlenum */
+ /* ForTran accent follows. */
+ int P; /* Scan product low-order -> high. */
+ int N; /* As in sum above. */
+ int A; /* Which [] of a? */
+ int B; /* Which [] of b? */
+
+ if ((a->sign != '-' && a->sign != '+') || (b->sign != '-' && b->sign != '+'))
+ {
+ /* ...
+ Got to fail somehow. Any suggestions? */
+ product->sign = 0;
+ return;
+ }
+ product->sign = (a->sign == b->sign) ? '+' : '-';
+ size_of_a = a->leader - a->low;
+ size_of_b = b->leader - b->low;
+ exponent = a->exponent + b->exponent;
+ size_of_product = product->high - product->low;
+ size_of_sum = size_of_a + size_of_b;
+ extra_product_positions = size_of_product - size_of_sum;
+ if (extra_product_positions < 0)
+ {
+ P = extra_product_positions; /* P < 0 */
+ exponent -= extra_product_positions; /* Increases exponent. */
+ }
+ else
+ {
+ P = 0;
+ }
+ carry = 0;
+ significant = 0;
+ for (N = 0; N <= size_of_sum; N++)
+ {
+ work = carry;
+ carry = 0;
+ for (A = 0; A <= N; A++)
+ {
+ B = N - A;
+ if (A <= size_of_a && B <= size_of_b && B >= 0)
+ {
+#ifdef TRACE
+ printf ("a:low[%d.]=%04x b:low[%d.]=%04x work_before=%08x\n", A, a->low[A], B, b->low[B], work);
+#endif
+ /* Watch out for sign extension! Without the casts, on
+ the DEC Alpha, the multiplication result is *signed*
+ int, which gets sign-extended to convert to the
+ unsigned long! */
+ work += (unsigned long) a->low[A] * (unsigned long) b->low[B];
+ carry += work >> LITTLENUM_NUMBER_OF_BITS;
+ work &= LITTLENUM_MASK;
+#ifdef TRACE
+ printf ("work=%08x carry=%04x\n", work, carry);
+#endif
+ }
+ }
+ significant |= work;
+ if (significant || P < 0)
+ {
+ if (P >= 0)
+ {
+ product->low[P] = work;
+#ifdef TRACE
+ printf ("P=%d. work[p]:=%04x\n", P, work);
+#endif
+ }
+ P++;
+ }
+ else
+ {
+ extra_product_positions++;
+ exponent++;
+ }
+ }
+ /*
+ * [P]-> position # size_of_sum + 1.
+ * This is where 'carry' should go.
+ */
+#ifdef TRACE
+ printf ("final carry =%04x\n", carry);
+#endif
+ if (carry)
+ {
+ if (extra_product_positions > 0)
+ {
+ product->low[P] = carry;
+ }
+ else
+ {
+ /* No room at high order for carry littlenum. */
+ /* Shift right 1 to make room for most significant littlenum. */
+ exponent++;
+ P--;
+ for (q = product->low + P; q >= product->low; q--)
+ {
+ work = *q;
+ *q = carry;
+ carry = work;
+ }
+ }
+ }
+ else
+ {
+ P--;
+ }
+ product->leader = product->low + P;
+ product->exponent = exponent;
+}
+
+/* end of flonum_mult.c */
diff --git a/gas/flonum.h b/gas/flonum.h
new file mode 100644
index 0000000000..6684f496c2
--- /dev/null
+++ b/gas/flonum.h
@@ -0,0 +1,110 @@
+/* flonum.h - Floating point package
+
+ Copyright (C) 1987, 90, 91, 92, 94, 95, 1996 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/***********************************************************************\
+ * *
+ * Arbitrary-precision floating point arithmetic. *
+ * *
+ * *
+ * Notation: a floating point number is expressed as *
+ * MANTISSA * (2 ** EXPONENT). *
+ * *
+ * If this offends more traditional mathematicians, then *
+ * please tell me your nomenclature for flonums! *
+ * *
+ \***********************************************************************/
+
+#include "bignum.h"
+
+/***********************************************************************\
+ * *
+ * Variable precision floating point numbers. *
+ * *
+ * Exponent is the place value of the low littlenum. E.g.: *
+ * If 0: low points to the units littlenum. *
+ * If 1: low points to the LITTLENUM_RADIX littlenum. *
+ * If -1: low points to the 1/LITTLENUM_RADIX littlenum. *
+ * *
+ \***********************************************************************/
+
+/* JF: A sign value of 0 means we have been asked to assemble NaN
+ A sign value of 'P' means we've been asked to assemble +Inf
+ A sign value of 'N' means we've been asked to assemble -Inf
+ */
+struct FLONUM_STRUCT
+{
+ LITTLENUM_TYPE *low; /* low order littlenum of a bignum */
+ LITTLENUM_TYPE *high; /* high order littlenum of a bignum */
+ LITTLENUM_TYPE *leader; /* -> 1st non-zero littlenum */
+ /* If flonum is 0.0, leader==low-1 */
+ long exponent; /* base LITTLENUM_RADIX */
+ char sign; /* '+' or '-' */
+};
+
+typedef struct FLONUM_STRUCT FLONUM_TYPE;
+
+
+/***********************************************************************\
+ * *
+ * Since we can (& do) meet with exponents like 10^5000, it *
+ * is silly to make a table of ~ 10,000 entries, one for each *
+ * power of 10. We keep a table where item [n] is a struct *
+ * FLONUM_FLOATING_POINT representing 10^(2^n). We then *
+ * multiply appropriate entries from this table to get any *
+ * particular power of 10. For the example of 10^5000, a table *
+ * of just 25 entries suffices: 10^(2^-12)...10^(2^+12). *
+ * *
+ \***********************************************************************/
+
+
+extern const FLONUM_TYPE flonum_positive_powers_of_ten[];
+extern const FLONUM_TYPE flonum_negative_powers_of_ten[];
+extern const int table_size_of_flonum_powers_of_ten;
+/* Flonum_XXX_powers_of_ten[] table has */
+/* legal indices from 0 to */
+/* + this number inclusive. */
+
+
+
+/***********************************************************************\
+ * *
+ * Declare worker functions. *
+ * *
+ \***********************************************************************/
+
+int atof_generic PARAMS ((char **address_of_string_pointer,
+ const char *string_of_decimal_marks,
+ const char *string_of_decimal_exponent_marks,
+ FLONUM_TYPE * address_of_generic_floating_point_number));
+
+void flonum_copy PARAMS ((FLONUM_TYPE * in, FLONUM_TYPE * out));
+void flonum_multip PARAMS ((const FLONUM_TYPE * a, const FLONUM_TYPE * b,
+ FLONUM_TYPE * product));
+
+/***********************************************************************\
+ * *
+ * Declare error codes. *
+ * *
+ \***********************************************************************/
+
+#define ERROR_EXPONENT_OVERFLOW (2)
+
+/* end of flonum.h */
diff --git a/gas/frags.c b/gas/frags.c
new file mode 100644
index 0000000000..240b2ee63a
--- /dev/null
+++ b/gas/frags.c
@@ -0,0 +1,359 @@
+/* frags.c - manage frags -
+ Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 97, 1998
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include "as.h"
+#include "subsegs.h"
+#include "obstack.h"
+
+extern fragS zero_address_frag;
+extern fragS bss_address_frag;
+
+/* Initialization for frag routines. */
+void
+frag_init ()
+{
+ zero_address_frag.fr_type = rs_fill;
+ bss_address_frag.fr_type = rs_fill;
+}
+
+/* Allocate a frag on the specified obstack.
+ Call this routine from everywhere else, so that all the weird alignment
+ hackery can be done in just one place. */
+fragS *
+frag_alloc (ob)
+ struct obstack *ob;
+{
+ fragS *ptr;
+ int oalign;
+
+ (void) obstack_alloc (ob, 0);
+ oalign = obstack_alignment_mask (ob);
+ obstack_alignment_mask (ob) = 0;
+ ptr = (fragS *) obstack_alloc (ob, SIZEOF_STRUCT_FRAG);
+ obstack_alignment_mask (ob) = oalign;
+ memset (ptr, 0, SIZEOF_STRUCT_FRAG);
+ return ptr;
+}
+
+/*
+ * frag_grow()
+ *
+ * Try to augment current frag by nchars chars.
+ * If there is no room, close of the current frag with a ".fill 0"
+ * and begin a new frag. Unless the new frag has nchars chars available
+ * do not return. Do not set up any fields of *now_frag.
+ */
+void
+frag_grow (nchars)
+ unsigned int nchars;
+{
+ if (obstack_room (&frchain_now->frch_obstack) < nchars)
+ {
+ unsigned int n;
+ long oldc;
+
+ frag_wane (frag_now);
+ frag_new (0);
+ oldc = frchain_now->frch_obstack.chunk_size;
+ frchain_now->frch_obstack.chunk_size = 2 * nchars + SIZEOF_STRUCT_FRAG;
+ while ((n = obstack_room (&frchain_now->frch_obstack)) < nchars)
+ {
+ frag_wane (frag_now);
+ frag_new (0);
+ }
+ frchain_now->frch_obstack.chunk_size = oldc;
+ }
+ if (obstack_room (&frchain_now->frch_obstack) < nchars)
+ as_fatal (_("Can't extend frag %d. chars"), nchars);
+}
+
+/*
+ * frag_new()
+ *
+ * Call this to close off a completed frag, and start up a new (empty)
+ * frag, in the same subsegment as the old frag.
+ * [frchain_now remains the same but frag_now is updated.]
+ * Because this calculates the correct value of fr_fix by
+ * looking at the obstack 'frags', it needs to know how many
+ * characters at the end of the old frag belong to (the maximal)
+ * fr_var: the rest must belong to fr_fix.
+ * It doesn't actually set up the old frag's fr_var: you may have
+ * set fr_var == 1, but allocated 10 chars to the end of the frag:
+ * in this case you pass old_frags_var_max_size == 10.
+ *
+ * Make a new frag, initialising some components. Link new frag at end
+ * of frchain_now.
+ */
+void
+frag_new (old_frags_var_max_size)
+ /* Number of chars (already allocated on obstack frags) in
+ variable_length part of frag. */
+ int old_frags_var_max_size;
+{
+ fragS *former_last_fragP;
+ frchainS *frchP;
+
+ assert (frchain_now->frch_last == frag_now);
+
+ /* Fix up old frag's fr_fix. */
+ frag_now->fr_fix = frag_now_fix () - old_frags_var_max_size;
+ /* Make sure its type is valid. */
+ assert (frag_now->fr_type != 0);
+
+ /* This will align the obstack so the next struct we allocate on it
+ will begin at a correct boundary. */
+ obstack_finish (&frchain_now->frch_obstack);
+ frchP = frchain_now;
+ know (frchP);
+ former_last_fragP = frchP->frch_last;
+ assert (former_last_fragP != 0);
+ assert (former_last_fragP == frag_now);
+ frag_now = frag_alloc (&frchP->frch_obstack);
+
+ as_where (&frag_now->fr_file, &frag_now->fr_line);
+
+ /* Generally, frag_now->points to an address rounded up to next
+ alignment. However, characters will add to obstack frags
+ IMMEDIATELY after the struct frag, even if they are not starting
+ at an alignment address. */
+ former_last_fragP->fr_next = frag_now;
+ frchP->frch_last = frag_now;
+
+#ifndef NO_LISTING
+ {
+ extern struct list_info_struct *listing_tail;
+ frag_now->line = listing_tail;
+ }
+#endif
+
+ assert (frchain_now->frch_last == frag_now);
+
+ frag_now->fr_next = NULL;
+} /* frag_new() */
+
+/*
+ * frag_more()
+ *
+ * Start a new frag unless we have n more chars of room in the current frag.
+ * Close off the old frag with a .fill 0.
+ *
+ * Return the address of the 1st char to write into. Advance
+ * frag_now_growth past the new chars.
+ */
+
+char *
+frag_more (nchars)
+ int nchars;
+{
+ register char *retval;
+
+ if (now_seg == absolute_section)
+ {
+ as_bad (_("attempt to allocate data in absolute section"));
+ subseg_set (text_section, 0);
+ }
+
+ if (mri_common_symbol != NULL)
+ {
+ as_bad (_("attempt to allocate data in common section"));
+ mri_common_symbol = NULL;
+ }
+
+ frag_grow (nchars);
+ retval = obstack_next_free (&frchain_now->frch_obstack);
+ obstack_blank_fast (&frchain_now->frch_obstack, nchars);
+ return (retval);
+} /* frag_more() */
+
+/*
+ * frag_var()
+ *
+ * Start a new frag unless we have max_chars more chars of room in the current frag.
+ * Close off the old frag with a .fill 0.
+ *
+ * Set up a machine_dependent relaxable frag, then start a new frag.
+ * Return the address of the 1st char of the var part of the old frag
+ * to write into.
+ */
+
+char *
+frag_var (type, max_chars, var, subtype, symbol, offset, opcode)
+ relax_stateT type;
+ int max_chars;
+ int var;
+ relax_substateT subtype;
+ symbolS *symbol;
+ offsetT offset;
+ char *opcode;
+{
+ register char *retval;
+
+ frag_grow (max_chars);
+ retval = obstack_next_free (&frchain_now->frch_obstack);
+ obstack_blank_fast (&frchain_now->frch_obstack, max_chars);
+ frag_now->fr_var = var;
+ frag_now->fr_type = type;
+ frag_now->fr_subtype = subtype;
+ frag_now->fr_symbol = symbol;
+ frag_now->fr_offset = offset;
+ frag_now->fr_opcode = opcode;
+#ifdef USING_CGEN
+ frag_now->fr_cgen.insn = 0;
+ frag_now->fr_cgen.opindex = 0;
+ frag_now->fr_cgen.opinfo = 0;
+#endif
+#ifdef TC_FRAG_INIT
+ TC_FRAG_INIT (frag_now);
+#endif
+ as_where (&frag_now->fr_file, &frag_now->fr_line);
+ frag_new (max_chars);
+ return (retval);
+}
+
+/*
+ * frag_variant()
+ *
+ * OVE: This variant of frag_var assumes that space for the tail has been
+ * allocated by caller.
+ * No call to frag_grow is done.
+ */
+
+char *
+frag_variant (type, max_chars, var, subtype, symbol, offset, opcode)
+ relax_stateT type;
+ int max_chars;
+ int var;
+ relax_substateT subtype;
+ symbolS *symbol;
+ offsetT offset;
+ char *opcode;
+{
+ register char *retval;
+
+ retval = obstack_next_free (&frchain_now->frch_obstack);
+ frag_now->fr_var = var;
+ frag_now->fr_type = type;
+ frag_now->fr_subtype = subtype;
+ frag_now->fr_symbol = symbol;
+ frag_now->fr_offset = offset;
+ frag_now->fr_opcode = opcode;
+#ifdef USING_CGEN
+ frag_now->fr_cgen.insn = 0;
+ frag_now->fr_cgen.opindex = 0;
+ frag_now->fr_cgen.opinfo = 0;
+#endif
+#ifdef TC_FRAG_INIT
+ TC_FRAG_INIT (frag_now);
+#endif
+ as_where (&frag_now->fr_file, &frag_now->fr_line);
+ frag_new (max_chars);
+ return (retval);
+} /* frag_variant() */
+
+/*
+ * frag_wane()
+ *
+ * Reduce the variable end of a frag to a harmless state.
+ */
+void
+frag_wane (fragP)
+ register fragS *fragP;
+{
+ fragP->fr_type = rs_fill;
+ fragP->fr_offset = 0;
+ fragP->fr_var = 0;
+}
+
+/* Make an alignment frag. The size of this frag will be adjusted to
+ force the next frag to have the appropriate alignment. ALIGNMENT
+ is the power of two to which to align. FILL_CHARACTER is the
+ character to use to fill in any bytes which are skipped. MAX is
+ the maximum number of characters to skip when doing the alignment,
+ or 0 if there is no maximum. */
+
+void
+frag_align (alignment, fill_character, max)
+ int alignment;
+ int fill_character;
+ int max;
+{
+ if (now_seg == absolute_section)
+ {
+ addressT new_off;
+
+ new_off = ((abs_section_offset + alignment - 1)
+ &~ ((1 << alignment) - 1));
+ if (max == 0 || new_off - abs_section_offset <= (addressT) max)
+ abs_section_offset = new_off;
+ }
+ else
+ {
+ char *p;
+
+ p = frag_var (rs_align, 1, 1, (relax_substateT) max,
+ (symbolS *) 0, (offsetT) alignment, (char *) 0);
+ *p = fill_character;
+ }
+}
+
+/* Make an alignment frag like frag_align, but fill with a repeating
+ pattern rather than a single byte. ALIGNMENT is the power of two
+ to which to align. FILL_PATTERN is the fill pattern to repeat in
+ the bytes which are skipped. N_FILL is the number of bytes in
+ FILL_PATTERN. MAX is the maximum number of characters to skip when
+ doing the alignment, or 0 if there is no maximum. */
+
+void
+frag_align_pattern (alignment, fill_pattern, n_fill, max)
+ int alignment;
+ const char *fill_pattern;
+ int n_fill;
+ int max;
+{
+ char *p;
+
+ p = frag_var (rs_align, n_fill, n_fill, (relax_substateT) max,
+ (symbolS *) 0, (offsetT) alignment, (char *) 0);
+ memcpy (p, fill_pattern, n_fill);
+}
+
+addressT
+frag_now_fix ()
+{
+ if (now_seg == absolute_section)
+ return abs_section_offset;
+ return (addressT) ((char*) obstack_next_free (&frchain_now->frch_obstack)
+ - frag_now->fr_literal);
+}
+
+void
+frag_append_1_char (datum)
+ int datum;
+{
+ if (obstack_room (&frchain_now->frch_obstack) <= 1)
+ {
+ frag_wane (frag_now);
+ frag_new (0);
+ }
+ obstack_1grow (&frchain_now->frch_obstack, datum);
+}
+
+/* end of frags.c */
diff --git a/gas/frags.h b/gas/frags.h
new file mode 100644
index 0000000000..9590292a4d
--- /dev/null
+++ b/gas/frags.h
@@ -0,0 +1,158 @@
+/* frags.h - Header file for the frag concept.
+ Copyright (C) 1987, 92, 93, 94, 95, 97, 1998
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#ifndef FRAGS_H
+#define FRAGS_H
+
+#ifdef ANSI_PROTOTYPES
+struct obstack;
+#endif
+
+/*
+ * A code fragment (frag) is some known number of chars, followed by some
+ * unknown number of chars. Typically the unknown number of chars is an
+ * instruction address whose size is yet unknown. We always know the greatest
+ * possible size the unknown number of chars may become, and reserve that
+ * much room at the end of the frag.
+ * Once created, frags do not change address during assembly.
+ * We chain the frags in (a) forward-linked list(s). The object-file address
+ * of the 1st char of a frag is generally not known until after relax().
+ * Many things at assembly time describe an address by {object-file-address
+ * of a particular frag}+offset.
+
+ BUG: it may be smarter to have a single pointer off to various different
+ notes for different frag kinds. See how code pans
+ */
+
+struct frag
+{
+ /* Object file address. */
+ addressT fr_address;
+ /* Chain forward; ascending address order. Rooted in frch_root. */
+ struct frag *fr_next;
+
+ /* (Fixed) number of chars we know we have. May be 0. */
+ offsetT fr_fix;
+ /* (Variable) number of chars after above. May be 0. */
+ offsetT fr_var;
+ /* For variable-length tail. */
+ struct symbol *fr_symbol;
+ /* For variable-length tail. */
+ offsetT fr_offset;
+ /* Points to opcode low addr byte, for relaxation. */
+ char *fr_opcode;
+
+#ifndef NO_LISTING
+ struct list_info_struct *line;
+#endif
+
+ /* What state is my tail in? */
+ relax_stateT fr_type;
+ relax_substateT fr_subtype;
+
+#ifdef USING_CGEN
+ /* Don't include this unless using CGEN to keep frag size down. */
+ struct {
+ /* CGEN_INSN entry for this instruction. */
+ const struct cgen_insn *insn;
+ /* Index into operand table. */
+ int opindex;
+ /* Target specific data, usually reloc number. */
+ int opinfo;
+ } fr_cgen;
+#endif
+
+#ifdef TC_FRAG_TYPE
+ TC_FRAG_TYPE tc_frag_data;
+#endif
+
+ /* Where the frag was created, or where it became a variant frag. */
+ char *fr_file;
+ unsigned int fr_line;
+
+ /* Data begins here. */
+ char fr_literal[1];
+};
+
+#define SIZEOF_STRUCT_FRAG \
+((char *)zero_address_frag.fr_literal-(char *)&zero_address_frag)
+/* We want to say fr_literal[0] above. */
+
+/* Current frag we are building. This frag is incomplete. It is,
+ however, included in frchain_now. The fr_fix field is bogus;
+ instead, use frag_now_fix (). */
+COMMON fragS *frag_now;
+extern addressT frag_now_fix PARAMS ((void));
+
+/* For foreign-segment symbol fixups. */
+COMMON fragS zero_address_frag;
+/* For local common (N_BSS segment) fixups. */
+COMMON fragS bss_address_frag;
+
+#if 0
+/*
+ * A macro to speed up appending exactly 1 char
+ * to current frag.
+ */
+/* JF changed < 1 to <= 1 to avoid a race conditon */
+#define FRAG_APPEND_1_CHAR(datum) \
+{ \
+ if (obstack_room( &frags ) <= 1) {\
+ frag_wane (frag_now); \
+ frag_new (0); \
+ } \
+ obstack_1grow( &frags, datum ); \
+}
+#else
+extern void frag_append_1_char PARAMS ((int));
+#define FRAG_APPEND_1_CHAR(X) frag_append_1_char (X)
+#endif
+
+
+void frag_init PARAMS ((void));
+fragS *frag_alloc PARAMS ((struct obstack *));
+void frag_grow PARAMS ((unsigned int nchars));
+char *frag_more PARAMS ((int nchars));
+void frag_align PARAMS ((int alignment, int fill_character, int max));
+void frag_align_pattern PARAMS ((int alignment,
+ const char *fill_pattern,
+ int n_fill,
+ int max));
+void frag_new PARAMS ((int old_frags_var_max_size));
+void frag_wane PARAMS ((fragS * fragP));
+
+char *frag_variant PARAMS ((relax_stateT type,
+ int max_chars,
+ int var,
+ relax_substateT subtype,
+ symbolS * symbol,
+ offsetT offset,
+ char *opcode));
+
+char *frag_var PARAMS ((relax_stateT type,
+ int max_chars,
+ int var,
+ relax_substateT subtype,
+ symbolS * symbol,
+ offsetT offset,
+ char *opcode));
+
+#endif /* FRAGS_H */
diff --git a/gas/gasp.c b/gas/gasp.c
new file mode 100644
index 0000000000..fbb65e31b4
--- /dev/null
+++ b/gas/gasp.c
@@ -0,0 +1,3745 @@
+/* gasp.c - Gnu assembler preprocessor main program.
+ Copyright (C) 1994, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
+
+ Written by Steve and Judy Chamberlain of Cygnus Support,
+ sac@cygnus.com
+
+ This file is part of GASP, the GNU Assembler Preprocessor.
+
+ GASP is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GASP 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GASP; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/*
+
+This program translates the input macros and stuff into a form
+suitable for gas to consume.
+
+
+ gasp [-sdhau] [-c char] [-o <outfile>] <infile>*
+
+ -s copy source to output
+ -c <char> comments are started with <char> instead of !
+ -u allow unreasonable stuff
+ -p print line numbers
+ -d print debugging stats
+ -s semi colons start comments
+ -a use alternate syntax
+ Pseudo ops can start with or without a .
+ Labels have to be in first column.
+ -I specify include dir
+ Macro arg parameters subsituted by name, don't need the &.
+ String can start with ' too.
+ Strings can be surrounded by <..>
+ A %<exp> in a string evaluates the expression
+ Literal char in a string with !
+
+
+*/
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+#include <ctype.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef NEED_MALLOC_DECLARATION
+extern char *malloc ();
+#endif
+
+#include "ansidecl.h"
+#include "libiberty.h"
+#include "sb.h"
+#include "macro.h"
+#include "asintl.h"
+
+char *program_version = "1.2";
+
+/* This is normally declared in as.h, but we don't include that. We
+ need the function because other files linked with gasp.c might call
+ it. */
+extern void as_abort PARAMS ((const char *, int, const char *));
+
+#define MAX_INCLUDES 30 /* Maximum include depth */
+#define MAX_REASONABLE 1000 /* Maximum number of expansions */
+
+int unreasonable; /* -u on command line */
+int stats; /* -d on command line */
+int print_line_number; /* -p flag on command line */
+int copysource; /* -c flag on command line */
+int warnings; /* Number of WARNINGs generated so far. */
+int errors; /* Number of ERRORs generated so far. */
+int fatals; /* Number of fatal ERRORs generated so far (either 0 or 1). */
+int alternate = 0; /* -a on command line */
+int mri = 0; /* -M on command line */
+char comment_char = '!';
+int radix = 10; /* Default radix */
+
+int had_end; /* Seen .END */
+
+/* The output stream */
+FILE *outfile;
+
+/* the attributes of each character are stored as a bit pattern
+ chartype, which gives us quick tests. */
+
+
+#define FIRSTBIT 1
+#define NEXTBIT 2
+#define SEPBIT 4
+#define WHITEBIT 8
+#define COMMENTBIT 16
+#define BASEBIT 32
+#define ISCOMMENTCHAR(x) (chartype[(unsigned char)(x)] & COMMENTBIT)
+#define ISFIRSTCHAR(x) (chartype[(unsigned char)(x)] & FIRSTBIT)
+#define ISNEXTCHAR(x) (chartype[(unsigned char)(x)] & NEXTBIT)
+#define ISSEP(x) (chartype[(unsigned char)(x)] & SEPBIT)
+#define ISWHITE(x) (chartype[(unsigned char)(x)] & WHITEBIT)
+#define ISBASE(x) (chartype[(unsigned char)(x)] & BASEBIT)
+static char chartype[256];
+
+
+/* Conditional assembly uses the `ifstack'. Each aif pushes another
+ entry onto the stack, and sets the on flag if it should. The aelse
+ sets hadelse, and toggles on. An aend pops a level. We limit to
+ 100 levels of nesting, not because we're facists pigs with read
+ only minds, but because more than 100 levels of nesting is probably
+ a bug in the user's macro structure. */
+
+#define IFNESTING 100
+struct
+ {
+ int on; /* is the level being output */
+ int hadelse; /* has an aelse been seen */
+ }
+ifstack[IFNESTING];
+int ifi;
+
+/* The final and intermediate results of expression evaluation are kept in
+ exp_t's. Note that a symbol is not an sb, but a pointer into the input
+ line. It must be coped somewhere safe before the next line is read in. */
+
+typedef struct
+ {
+ char *name;
+ int len;
+ }
+symbol;
+
+typedef struct
+ {
+ int value; /* constant part */
+ symbol add_symbol; /* name part */
+ symbol sub_symbol; /* name part */
+ }
+exp_t;
+
+
+/* Hashing is done in a pretty standard way. A hash_table has a
+ pointer to a vector of pointers to hash_entrys, and the size of the
+ vector. A hash_entry contains a union of all the info we like to
+ store in hash table. If there is a hash collision, hash_entries
+ with the same hash are kept in a chain. */
+
+/* What the data in a hash_entry means */
+typedef enum
+ {
+ hash_integer, /* name->integer mapping */
+ hash_string, /* name->string mapping */
+ hash_macro, /* name is a macro */
+ hash_formal /* name is a formal argument */
+ } hash_type;
+
+typedef struct hs
+ {
+ sb key; /* symbol name */
+ hash_type type; /* symbol meaning */
+ union
+ {
+ sb s;
+ int i;
+ struct macro_struct *m;
+ struct formal_struct *f;
+ } value;
+ struct hs *next; /* next hash_entry with same hash key */
+ } hash_entry;
+
+typedef struct
+ {
+ hash_entry **table;
+ int size;
+ } hash_table;
+
+
+/* Structures used to store macros.
+
+ Each macro knows its name and included text. It gets built with a
+ list of formal arguments, and also keeps a hash table which points
+ into the list to speed up formal search. Each formal knows its
+ name and its default value. Each time the macro is expanded, the
+ formals get the actual values attatched to them. */
+
+/* describe the formal arguments to a macro */
+
+typedef struct formal_struct
+ {
+ struct formal_struct *next; /* next formal in list */
+ sb name; /* name of the formal */
+ sb def; /* the default value */
+ sb actual; /* the actual argument (changed on each expansion) */
+ int index; /* the index of the formal 0..formal_count-1 */
+ }
+formal_entry;
+
+/* describe the macro. */
+
+typedef struct macro_struct
+ {
+ sb sub; /* substitution text. */
+ int formal_count; /* number of formal args. */
+ formal_entry *formals; /* pointer to list of formal_structs */
+ hash_table formal_hash; /* hash table of formals. */
+ }
+macro_entry;
+
+/* how we nest files and expand macros etc.
+
+ we keep a stack of of include_stack structs. each include file
+ pushes a new level onto the stack. we keep an sb with a pushback
+ too. unget chars are pushed onto the pushback sb, getchars first
+ checks the pushback sb before reading from the input stream.
+
+ small things are expanded by adding the text of the item onto the
+ pushback sb. larger items are grown by pushing a new level and
+ allocating the entire pushback buf for the item. each time
+ something like a macro is expanded, the stack index is changed. we
+ can then perform an exitm by popping all entries off the stack with
+ the same stack index. if we're being reasonable, we can detect
+ recusive expansion by checking the index is reasonably small.
+ */
+
+typedef enum
+ {
+ include_file, include_repeat, include_while, include_macro
+ } include_type;
+
+struct include_stack
+ {
+ sb pushback; /* current pushback stream */
+ int pushback_index; /* next char to read from stream */
+ FILE *handle; /* open file */
+ sb name; /* name of file */
+ int linecount; /* number of lines read so far */
+ include_type type;
+ int index; /* index of this layer */
+ }
+include_stack[MAX_INCLUDES];
+
+struct include_stack *sp;
+#define isp (sp - include_stack)
+
+/* Include file list */
+
+typedef struct include_path
+{
+ struct include_path *next;
+ sb path;
+} include_path;
+
+include_path *paths_head;
+include_path *paths_tail;
+
+
+static void quit PARAMS ((void));
+static void hash_new_table PARAMS ((int, hash_table *));
+static int hash PARAMS ((sb *));
+static hash_entry *hash_create PARAMS ((hash_table *, sb *));
+static void hash_add_to_string_table PARAMS ((hash_table *, sb *, sb *, int));
+static void hash_add_to_int_table PARAMS ((hash_table *, sb *, int));
+static hash_entry *hash_lookup PARAMS ((hash_table *, sb *));
+static void checkconst PARAMS ((int, exp_t *));
+static int sb_strtol PARAMS ((int, sb *, int, int *));
+static int level_0 PARAMS ((int, sb *, exp_t *));
+static int level_1 PARAMS ((int, sb *, exp_t *));
+static int level_2 PARAMS ((int, sb *, exp_t *));
+static int level_3 PARAMS ((int, sb *, exp_t *));
+static int level_4 PARAMS ((int, sb *, exp_t *));
+static int level_5 PARAMS ((int, sb *, exp_t *));
+static int exp_parse PARAMS ((int, sb *, exp_t *));
+static void exp_string PARAMS ((exp_t *, sb *));
+static int exp_get_abs PARAMS ((const char *, int, sb *, int *));
+#if 0
+static void strip_comments PARAMS ((sb *));
+#endif
+static void unget PARAMS ((int));
+static void include_buf PARAMS ((sb *, sb *, include_type, int));
+static void include_print_where_line PARAMS ((FILE *));
+static void include_print_line PARAMS ((FILE *));
+static int get_line PARAMS ((sb *));
+static int grab_label PARAMS ((sb *, sb *));
+static void change_base PARAMS ((int, sb *, sb *));
+static void do_end PARAMS ((sb *));
+static void do_assign PARAMS ((int, int, sb *));
+static void do_radix PARAMS ((sb *));
+static int get_opsize PARAMS ((int, sb *, int *));
+static int eol PARAMS ((int, sb *));
+static void do_data PARAMS ((int, sb *, int));
+static void do_datab PARAMS ((int, sb *));
+static void do_align PARAMS ((int, sb *));
+static void do_res PARAMS ((int, sb *, int));
+static void do_export PARAMS ((sb *));
+static void do_print PARAMS ((int, sb *));
+static void do_heading PARAMS ((int, sb *));
+static void do_page PARAMS ((void));
+static void do_form PARAMS ((int, sb *));
+static int get_any_string PARAMS ((int, sb *, sb *, int, int));
+static int skip_openp PARAMS ((int, sb *));
+static int skip_closep PARAMS ((int, sb *));
+static int dolen PARAMS ((int, sb *, sb *));
+static int doinstr PARAMS ((int, sb *, sb *));
+static int dosubstr PARAMS ((int, sb *, sb *));
+static void process_assigns PARAMS ((int, sb *, sb *));
+static int get_and_process PARAMS ((int, sb *, sb *));
+static void process_file PARAMS ((void));
+static void free_old_entry PARAMS ((hash_entry *));
+static void do_assigna PARAMS ((int, sb *));
+static void do_assignc PARAMS ((int, sb *));
+static void do_reg PARAMS ((int, sb *));
+static int condass_lookup_name PARAMS ((sb *, int, sb *, int));
+static int whatcond PARAMS ((int, sb *, int *));
+static int istrue PARAMS ((int, sb *));
+static void do_aif PARAMS ((int, sb *));
+static void do_aelse PARAMS ((void));
+static void do_aendi PARAMS ((void));
+static int condass_on PARAMS ((void));
+static void do_if PARAMS ((int, sb *, int));
+static int get_mri_string PARAMS ((int, sb *, sb *, int));
+static void do_ifc PARAMS ((int, sb *, int));
+static void do_aendr PARAMS ((void));
+static void do_awhile PARAMS ((int, sb *));
+static void do_aendw PARAMS ((void));
+static void do_exitm PARAMS ((void));
+static void do_arepeat PARAMS ((int, sb *));
+static void do_endm PARAMS ((void));
+static void do_irp PARAMS ((int, sb *, int));
+static void do_local PARAMS ((int, sb *));
+static void do_macro PARAMS ((int, sb *));
+static int macro_op PARAMS ((int, sb *));
+static int getstring PARAMS ((int, sb *, sb *));
+static void do_sdata PARAMS ((int, sb *, int));
+static void do_sdatab PARAMS ((int, sb *));
+static int new_file PARAMS ((const char *));
+static void do_include PARAMS ((int, sb *));
+static void include_pop PARAMS ((void));
+static int get PARAMS ((void));
+static int linecount PARAMS ((void));
+static int include_next_index PARAMS ((void));
+static void chartype_init PARAMS ((void));
+static int process_pseudo_op PARAMS ((int, sb *, sb *));
+static void add_keyword PARAMS ((const char *, int));
+static void process_init PARAMS ((void));
+static void do_define PARAMS ((const char *));
+static void show_usage PARAMS ((FILE *, int));
+static void show_help PARAMS ((void));
+
+#define FATAL(x) \
+ do { include_print_where_line (stderr); fprintf x ; fatals++; quit(); } while(0)
+#define ERROR(x) \
+ do { include_print_where_line (stderr); fprintf x; errors++; } while(0)
+#define WARNING(x) \
+ do { include_print_where_line (stderr); fprintf x; warnings++;} while(0)
+
+
+
+/* exit the program and return the right ERROR code. */
+static void
+quit ()
+{
+ int exitcode;
+ if (fatals + errors)
+ exitcode = 1;
+ else
+ exitcode = 0;
+
+ if (stats)
+ {
+ int i;
+ for (i = 0; i < sb_max_power_two; i++)
+ {
+ fprintf (stderr, "strings size %8d : %d\n", 1<<i, string_count[i]);
+ }
+ }
+ exit (exitcode);
+}
+
+/* hash table maintenance. */
+
+/* build a new hash table with size buckets, and fill in the info at ptr. */
+
+static void
+hash_new_table (size, ptr)
+ int size;
+ hash_table *ptr;
+{
+ int i;
+ ptr->size = size;
+ ptr->table = (hash_entry **) xmalloc (size * (sizeof (hash_entry *)));
+ /* Fill with null-pointer, not zero-bit-pattern. */
+ for (i = 0; i < size; i++)
+ ptr->table[i] = 0;
+}
+
+/* calculate and return the hash value of the sb at key. */
+
+static int
+hash (key)
+ sb *key;
+{
+ int k = 0x1234;
+ int i;
+ char *p = key->ptr;
+ for (i = 0; i < key->len; i++)
+ {
+ k ^= (k << 2) ^ *p;
+ p++;
+ }
+ return k & 0xf0fff;
+}
+
+/* lookup key in hash_table tab, if present, then return it, otherwise
+ build a new one and fill it with hash_integer. */
+
+static
+hash_entry *
+hash_create (tab, key)
+ hash_table *tab;
+ sb *key;
+{
+ int k = hash (key) % tab->size;
+ hash_entry *p;
+ hash_entry **table = tab->table;
+
+ p = table[k];
+
+ while (1)
+ {
+ if (!p)
+ {
+ hash_entry *n = (hash_entry *) xmalloc (sizeof (hash_entry));
+ n->next = table[k];
+ sb_new (&n->key);
+ sb_add_sb (&n->key, key);
+ table[k] = n;
+ n->type = hash_integer;
+ return n;
+ }
+ if (strncmp (table[k]->key.ptr, key->ptr, key->len) == 0)
+ {
+ return p;
+ }
+ p = p->next;
+ }
+}
+
+/* add sb name with key into hash_table tab. if replacing old value
+ and again, then ERROR. */
+
+static
+void
+hash_add_to_string_table (tab, key, name, again)
+ hash_table *tab;
+ sb *key;
+ sb *name;
+ int again;
+{
+ hash_entry *ptr = hash_create (tab, key);
+ if (ptr->type == hash_integer)
+ {
+ sb_new (&ptr->value.s);
+ }
+ if (ptr->value.s.len)
+ {
+ if (!again)
+ ERROR ((stderr, _("redefinition not allowed\n")));
+ }
+
+ ptr->type = hash_string;
+ sb_reset (&ptr->value.s);
+
+ sb_add_sb (&ptr->value.s, name);
+}
+
+/* add integer name to hash_table tab with sb key. */
+
+static
+void
+hash_add_to_int_table (tab, key, name)
+ hash_table *tab;
+ sb *key;
+ int name;
+{
+ hash_entry *ptr = hash_create (tab, key);
+ ptr->value.i = name;
+}
+
+/* lookup sb key in hash_table tab. if found return hash_entry result,
+ else 0. */
+
+static
+hash_entry *
+hash_lookup (tab, key)
+ hash_table *tab;
+ sb *key;
+{
+ int k = hash (key) % tab->size;
+ hash_entry **table = tab->table;
+ hash_entry *p = table[k];
+ while (p)
+ {
+ if (p->key.len == key->len
+ && strncmp (p->key.ptr, key->ptr, key->len) == 0)
+ return p;
+ p = p->next;
+ }
+ return 0;
+}
+
+
+/* expressions
+
+ are handled in a really simple recursive decent way. each bit of
+ the machine takes an index into an sb and a pointer to an exp_t,
+ modifies the *exp_t and returns the index of the first character
+ past the part of the expression parsed.
+
+ expression precedence:
+ ( )
+ unary + - ~
+ * /
+ + -
+ &
+ | ~
+
+*/
+
+
+/* make sure that the exp_t at term is constant, if not the give the op ERROR. */
+
+static
+void
+checkconst (op, term)
+ int op;
+ exp_t *term;
+{
+ if (term->add_symbol.len
+ || term->sub_symbol.len)
+ {
+ ERROR ((stderr, _("the %c operator cannot take non-absolute arguments.\n"), op));
+ }
+}
+
+/* turn the number in string at idx into a number of base,
+ fill in ptr and return the index of the first character not in the
+ number. */
+
+static
+int
+sb_strtol (idx, string, base, ptr)
+ int idx;
+ sb *string;
+ int base;
+ int *ptr;
+{
+ int value = 0;
+ idx = sb_skip_white (idx, string);
+
+ while (idx < string->len)
+ {
+ int ch = string->ptr[idx];
+ int dig = 0;
+ if (isdigit (ch))
+ dig = ch - '0';
+ else if (ch >= 'a' && ch <= 'f')
+ dig = ch - 'a' + 10;
+ else if (ch >= 'A' && ch <= 'F')
+ dig = ch - 'A' + 10;
+ else
+ break;
+
+ if (dig >= base)
+ break;
+
+ value = value * base + dig;
+ idx++;
+ }
+ *ptr = value;
+ return idx;
+}
+
+static int
+level_0 (idx, string, lhs)
+ int idx;
+ sb *string;
+ exp_t *lhs;
+{
+ lhs->add_symbol.len = 0;
+ lhs->add_symbol.name = 0;
+
+ lhs->sub_symbol.len = 0;
+ lhs->sub_symbol.name = 0;
+
+ idx = sb_skip_white (idx, string);
+
+ lhs->value = 0;
+
+ if (isdigit ((unsigned char) string->ptr[idx]))
+ {
+ idx = sb_strtol (idx, string, 10, &lhs->value);
+ }
+ else if (ISFIRSTCHAR (string->ptr[idx]))
+ {
+ int len = 0;
+ lhs->add_symbol.name = string->ptr + idx;
+ while (idx < string->len && ISNEXTCHAR (string->ptr[idx]))
+ {
+ idx++;
+ len++;
+ }
+ lhs->add_symbol.len = len;
+ }
+ else if (string->ptr[idx] == '"')
+ {
+ sb acc;
+ sb_new (&acc);
+ ERROR ((stderr, _("string where expression expected.\n")));
+ idx = getstring (idx, string, &acc);
+ sb_kill (&acc);
+ }
+ else
+ {
+ ERROR ((stderr, _("can't find primary in expression.\n")));
+ idx++;
+ }
+ return sb_skip_white (idx, string);
+}
+
+
+
+static int
+level_1 (idx, string, lhs)
+ int idx;
+ sb *string;
+ exp_t *lhs;
+{
+ idx = sb_skip_white (idx, string);
+
+ switch (string->ptr[idx])
+ {
+ case '+':
+ idx = level_1 (idx + 1, string, lhs);
+ break;
+ case '~':
+ idx = level_1 (idx + 1, string, lhs);
+ checkconst ('~', lhs);
+ lhs->value = ~lhs->value;
+ break;
+ case '-':
+ {
+ symbol t;
+ idx = level_1 (idx + 1, string, lhs);
+ lhs->value = -lhs->value;
+ t = lhs->add_symbol;
+ lhs->add_symbol = lhs->sub_symbol;
+ lhs->sub_symbol = t;
+ break;
+ }
+ case '(':
+ idx++;
+ idx = level_5 (sb_skip_white (idx, string), string, lhs);
+ if (string->ptr[idx] != ')')
+ ERROR ((stderr, _("misplaced closing parens.\n")));
+ else
+ idx++;
+ break;
+ default:
+ idx = level_0 (idx, string, lhs);
+ break;
+ }
+ return sb_skip_white (idx, string);
+}
+
+static int
+level_2 (idx, string, lhs)
+ int idx;
+ sb *string;
+ exp_t *lhs;
+{
+ exp_t rhs;
+
+ idx = level_1 (idx, string, lhs);
+
+ while (idx < string->len && (string->ptr[idx] == '*'
+ || string->ptr[idx] == '/'))
+ {
+ char op = string->ptr[idx++];
+ idx = level_1 (idx, string, &rhs);
+ switch (op)
+ {
+ case '*':
+ checkconst ('*', lhs);
+ checkconst ('*', &rhs);
+ lhs->value *= rhs.value;
+ break;
+ case '/':
+ checkconst ('/', lhs);
+ checkconst ('/', &rhs);
+ if (rhs.value == 0)
+ ERROR ((stderr, _("attempt to divide by zero.\n")));
+ else
+ lhs->value /= rhs.value;
+ break;
+ }
+ }
+ return sb_skip_white (idx, string);
+}
+
+
+static int
+level_3 (idx, string, lhs)
+ int idx;
+ sb *string;
+ exp_t *lhs;
+{
+ exp_t rhs;
+
+ idx = level_2 (idx, string, lhs);
+
+ while (idx < string->len
+ && (string->ptr[idx] == '+'
+ || string->ptr[idx] == '-'))
+ {
+ char op = string->ptr[idx++];
+ idx = level_2 (idx, string, &rhs);
+ switch (op)
+ {
+ case '+':
+ lhs->value += rhs.value;
+ if (lhs->add_symbol.name && rhs.add_symbol.name)
+ {
+ ERROR ((stderr, _("can't add two relocatable expressions\n")));
+ }
+ /* change nn+symbol to symbol + nn */
+ if (rhs.add_symbol.name)
+ {
+ lhs->add_symbol = rhs.add_symbol;
+ }
+ break;
+ case '-':
+ lhs->value -= rhs.value;
+ lhs->sub_symbol = rhs.add_symbol;
+ break;
+ }
+ }
+ return sb_skip_white (idx, string);
+}
+
+static int
+level_4 (idx, string, lhs)
+ int idx;
+ sb *string;
+ exp_t *lhs;
+{
+ exp_t rhs;
+
+ idx = level_3 (idx, string, lhs);
+
+ while (idx < string->len &&
+ string->ptr[idx] == '&')
+ {
+ char op = string->ptr[idx++];
+ idx = level_3 (idx, string, &rhs);
+ switch (op)
+ {
+ case '&':
+ checkconst ('&', lhs);
+ checkconst ('&', &rhs);
+ lhs->value &= rhs.value;
+ break;
+ }
+ }
+ return sb_skip_white (idx, string);
+}
+
+static int
+level_5 (idx, string, lhs)
+ int idx;
+ sb *string;
+ exp_t *lhs;
+{
+ exp_t rhs;
+
+ idx = level_4 (idx, string, lhs);
+
+ while (idx < string->len
+ && (string->ptr[idx] == '|' || string->ptr[idx] == '~'))
+ {
+ char op = string->ptr[idx++];
+ idx = level_4 (idx, string, &rhs);
+ switch (op)
+ {
+ case '|':
+ checkconst ('|', lhs);
+ checkconst ('|', &rhs);
+ lhs->value |= rhs.value;
+ break;
+ case '~':
+ checkconst ('~', lhs);
+ checkconst ('~', &rhs);
+ lhs->value ^= rhs.value;
+ break;
+ }
+ }
+ return sb_skip_white (idx, string);
+}
+
+
+/* parse the expression at offset idx into string, fill up res with
+ the result. return the index of the first char past the expression.
+ */
+
+static int
+exp_parse (idx, string, res)
+ int idx;
+ sb *string;
+ exp_t *res;
+{
+ return level_5 (sb_skip_white (idx, string), string, res);
+}
+
+
+/* turn the expression at exp into text and glue it onto the end of
+ string. */
+
+static void
+exp_string (exp, string)
+ exp_t *exp;
+ sb *string;
+{
+ int np = 0;
+ int ad = 0;
+ sb_reset (string);
+
+ if (exp->add_symbol.len)
+ {
+ sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
+ np = 1;
+ ad = 1;
+ }
+ if (exp->value)
+ {
+ char buf[20];
+ if (np)
+ sb_add_char (string, '+');
+ sprintf (buf, "%d", exp->value);
+ sb_add_string (string, buf);
+ np = 1;
+ ad = 1;
+ }
+ if (exp->sub_symbol.len)
+ {
+ sb_add_char (string, '-');
+ sb_add_buffer (string, exp->add_symbol.name, exp->add_symbol.len);
+ np = 0;
+ ad = 1;
+ }
+
+ if (!ad)
+ sb_add_char (string, '0');
+}
+
+
+/* parse the expression at offset idx into sb in, return the value in val.
+ if the expression is not constant, give ERROR emsg. returns the index
+ of the first character past the end of the expression. */
+
+static int
+exp_get_abs (emsg, idx, in, val)
+ const char *emsg;
+ int idx;
+ sb *in;
+ int *val;
+{
+ exp_t res;
+ idx = exp_parse (idx, in, &res);
+ if (res.add_symbol.len || res.sub_symbol.len)
+ ERROR ((stderr, emsg));
+ *val = res.value;
+ return idx;
+}
+
+
+sb label; /* current label parsed from line */
+hash_table assign_hash_table; /* hash table for all assigned variables */
+hash_table keyword_hash_table; /* hash table for keyword */
+hash_table vars; /* hash table for eq variables */
+
+#define in_comment ';'
+
+#if 0
+static void
+strip_comments (out)
+ sb *out;
+{
+ char *s = out->ptr;
+ int i = 0;
+ for (i = 0; i < out->len; i++)
+ {
+ if (ISCOMMENTCHAR(s[i]))
+ {
+ out->len = i;
+ return;
+ }
+ }
+}
+#endif
+
+/* push back character ch so that it can be read again. */
+
+static void
+unget (ch)
+ int ch;
+{
+ if (ch == '\n')
+ {
+ sp->linecount--;
+ }
+ if (sp->pushback_index)
+ sp->pushback_index--;
+ else
+ sb_add_char (&sp->pushback, ch);
+}
+
+/* push the sb ptr onto the include stack, with the given name, type and index. */
+
+static
+void
+include_buf (name, ptr, type, index)
+ sb *name;
+ sb *ptr;
+ include_type type;
+ int index;
+{
+ sp++;
+ if (sp - include_stack >= MAX_INCLUDES)
+ FATAL ((stderr, _("unreasonable nesting.\n")));
+ sb_new (&sp->name);
+ sb_add_sb (&sp->name, name);
+ sp->handle = 0;
+ sp->linecount = 1;
+ sp->pushback_index = 0;
+ sp->type = type;
+ sp->index = index;
+ sb_new (&sp->pushback);
+ sb_add_sb (&sp->pushback, ptr);
+}
+
+
+/* used in ERROR messages, print info on where the include stack is onto file. */
+static
+void
+include_print_where_line (file)
+ FILE *file;
+{
+ struct include_stack *p = include_stack + 1;
+
+ while (p <= sp)
+ {
+ fprintf (file, "%s:%d ", sb_name (&p->name), p->linecount - 1);
+ p++;
+ }
+}
+
+/* used in listings, print the line number onto file. */
+static void
+include_print_line (file)
+ FILE *file;
+{
+ int n;
+ struct include_stack *p = include_stack + 1;
+
+ n = fprintf (file, "%4d", p->linecount);
+ p++;
+ while (p <= sp)
+ {
+ n += fprintf (file, ".%d", p->linecount);
+ p++;
+ }
+ while (n < 8 * 3)
+ {
+ fprintf (file, " ");
+ n++;
+ }
+}
+
+
+/* read a line from the top of the include stack into sb in. */
+
+static int
+get_line (in)
+ sb *in;
+{
+ int online = 0;
+ int more = 1;
+
+ if (copysource)
+ {
+ putc (comment_char, outfile);
+ if (print_line_number)
+ include_print_line (outfile);
+ }
+
+ while (1)
+ {
+ int ch = get ();
+
+ while (ch == '\r')
+ ch = get ();
+
+ if (ch == EOF)
+ {
+ if (online)
+ {
+ WARNING ((stderr, _("End of file not at start of line.\n")));
+ if (copysource)
+ putc ('\n', outfile);
+ ch = '\n';
+ }
+ else
+ more = 0;
+ break;
+ }
+
+ if (copysource)
+ {
+ putc (ch, outfile);
+ }
+
+ if (ch == '\n')
+ {
+ ch = get ();
+ online = 0;
+ if (ch == '+')
+ {
+ /* continued line */
+ if (copysource)
+ {
+ putc (comment_char, outfile);
+ putc ('+', outfile);
+ }
+ ch = get ();
+ }
+ else
+ {
+ if (ch != EOF)
+ unget (ch);
+ break;
+ }
+ }
+ else
+ {
+ sb_add_char (in, ch);
+ }
+ online++;
+ }
+
+ return more;
+}
+
+/* find a label from sb in and put it in out. */
+
+static int
+grab_label (in, out)
+ sb *in;
+ sb *out;
+{
+ int i = 0;
+ sb_reset (out);
+ if (ISFIRSTCHAR (in->ptr[i]) || in->ptr[i] == '\\')
+ {
+ sb_add_char (out, in->ptr[i]);
+ i++;
+ while ((ISNEXTCHAR (in->ptr[i])
+ || in->ptr[i] == '\\'
+ || in->ptr[i] == '&')
+ && i < in->len)
+ {
+ sb_add_char (out, in->ptr[i]);
+ i++;
+ }
+ }
+ return i;
+}
+
+/* find all strange base stuff and turn into decimal. also
+ find all the other numbers and convert them from the default radix */
+
+static void
+change_base (idx, in, out)
+ int idx;
+ sb *in;
+ sb *out;
+{
+ char buffer[20];
+
+ while (idx < in->len)
+ {
+ if (in->ptr[idx] == '\\'
+ && idx + 1 < in->len
+ && in->ptr[idx + 1] == '(')
+ {
+ idx += 2;
+ while (idx < in->len
+ && in->ptr[idx] != ')')
+ {
+ sb_add_char (out, in->ptr[idx]);
+ idx++;
+ }
+ if (idx < in->len)
+ idx++;
+ }
+ else if (idx < in->len - 1 && in->ptr[idx + 1] == '\'' && ! mri)
+ {
+ int base;
+ int value;
+ switch (in->ptr[idx])
+ {
+ case 'b':
+ case 'B':
+ base = 2;
+ break;
+ case 'q':
+ case 'Q':
+ base = 8;
+ break;
+ case 'h':
+ case 'H':
+ base = 16;
+ break;
+ case 'd':
+ case 'D':
+ base = 10;
+ break;
+ default:
+ ERROR ((stderr, _("Illegal base character %c.\n"), in->ptr[idx]));
+ base = 10;
+ break;
+ }
+
+ idx = sb_strtol (idx + 2, in, base, &value);
+ sprintf (buffer, "%d", value);
+ sb_add_string (out, buffer);
+ }
+ else if (ISFIRSTCHAR (in->ptr[idx]))
+ {
+ /* copy entire names through quickly */
+ sb_add_char (out, in->ptr[idx]);
+ idx++;
+ while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
+ {
+ sb_add_char (out, in->ptr[idx]);
+ idx++;
+ }
+ }
+ else if (isdigit ((unsigned char) in->ptr[idx]))
+ {
+ int value;
+ /* all numbers must start with a digit, let's chew it and
+ spit out decimal */
+ idx = sb_strtol (idx, in, radix, &value);
+ sprintf (buffer, "%d", value);
+ sb_add_string (out, buffer);
+
+ /* skip all undigsested letters */
+ while (idx < in->len && ISNEXTCHAR (in->ptr[idx]))
+ {
+ sb_add_char (out, in->ptr[idx]);
+ idx++;
+ }
+ }
+ else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
+ {
+ char tchar = in->ptr[idx];
+ /* copy entire names through quickly */
+ sb_add_char (out, in->ptr[idx]);
+ idx++;
+ while (idx < in->len && in->ptr[idx] != tchar)
+ {
+ sb_add_char (out, in->ptr[idx]);
+ idx++;
+ }
+ }
+ else
+ {
+ /* nothing special, just pass it through */
+ sb_add_char (out, in->ptr[idx]);
+ idx++;
+ }
+ }
+
+}
+
+/* .end */
+static void
+do_end (in)
+ sb *in;
+{
+ had_end = 1;
+ if (mri)
+ fprintf (outfile, "%s\n", sb_name (in));
+}
+
+/* .assign */
+
+static void
+do_assign (again, idx, in)
+ int again;
+ int idx;
+ sb *in;
+{
+ /* stick label in symbol table with following value */
+ exp_t e;
+ sb acc;
+
+ sb_new (&acc);
+ idx = exp_parse (idx, in, &e);
+ exp_string (&e, &acc);
+ hash_add_to_string_table (&assign_hash_table, &label, &acc, again);
+ sb_kill (&acc);
+}
+
+
+/* .radix [b|q|d|h] */
+
+static
+void
+do_radix (ptr)
+ sb *ptr;
+{
+ int idx = sb_skip_white (0, ptr);
+ switch (ptr->ptr[idx])
+ {
+ case 'B':
+ case 'b':
+ radix = 2;
+ break;
+ case 'q':
+ case 'Q':
+ radix = 8;
+ break;
+ case 'd':
+ case 'D':
+ radix = 10;
+ break;
+ case 'h':
+ case 'H':
+ radix = 16;
+ break;
+ default:
+ ERROR ((stderr, _("radix is %c must be one of b, q, d or h"), radix));
+ }
+}
+
+
+/* Parse off a .b, .w or .l */
+
+static int
+get_opsize (idx, in, size)
+ int idx;
+ sb *in;
+ int *size;
+{
+ *size = 4;
+ if (in->ptr[idx] == '.')
+ {
+ idx++;
+ }
+ switch (in->ptr[idx])
+ {
+ case 'b':
+ case 'B':
+ *size = 1;
+ break;
+ case 'w':
+ case 'W':
+ *size = 2;
+ break;
+ case 'l':
+ case 'L':
+ *size = 4;
+ break;
+ case ' ':
+ case '\t':
+ break;
+ default:
+ ERROR ((stderr, _("size must be one of b, w or l, is %c.\n"), in->ptr[idx]));
+ break;
+ }
+ idx++;
+
+ return idx;
+}
+
+static
+int eol(idx, line)
+ int idx;
+ sb *line;
+{
+ idx = sb_skip_white (idx, line);
+ if (idx < line->len
+ && ISCOMMENTCHAR(line->ptr[idx]))
+ return 1;
+ if (idx >= line->len)
+ return 1;
+ return 0;
+}
+
+/* .data [.b|.w|.l] <data>*
+ or d[bwl] <data>* */
+
+static void
+do_data (idx, in, size)
+ int idx;
+ sb *in;
+ int size;
+{
+ int opsize = 4;
+ char *opname = ".yikes!";
+ sb acc;
+ sb_new (&acc);
+
+ if (!size)
+ {
+ idx = get_opsize (idx, in, &opsize);
+ }
+ else {
+ opsize = size;
+ }
+ switch (opsize)
+ {
+ case 4:
+ opname = ".long";
+ break;
+ case 2:
+ opname = ".short";
+ break;
+ case 1:
+ opname = ".byte";
+ break;
+ }
+
+
+ fprintf (outfile, "%s\t", opname);
+
+ idx = sb_skip_white (idx, in);
+
+ if (alternate
+ && idx < in->len
+ && in->ptr[idx] == '"')
+ {
+ int i;
+ idx = getstring (idx, in, &acc);
+ for (i = 0; i < acc.len; i++)
+ {
+ if (i)
+ fprintf(outfile,",");
+ fprintf (outfile, "%d", acc.ptr[i]);
+ }
+ }
+ else
+ {
+ while (!eol (idx, in))
+ {
+ exp_t e;
+ idx = exp_parse (idx, in, &e);
+ exp_string (&e, &acc);
+ sb_add_char (&acc, 0);
+ fprintf (outfile, acc.ptr);
+ if (idx < in->len && in->ptr[idx] == ',')
+ {
+ fprintf (outfile, ",");
+ idx++;
+ }
+ }
+ }
+ sb_kill (&acc);
+ sb_print_at (outfile, idx, in);
+ fprintf (outfile, "\n");
+}
+
+/* .datab [.b|.w|.l] <repeat>,<fill> */
+
+static void
+do_datab (idx, in)
+ int idx;
+ sb *in;
+{
+ int opsize;
+ int repeat;
+ int fill;
+
+ idx = get_opsize (idx, in, &opsize);
+
+ idx = exp_get_abs (_("datab repeat must be constant.\n"), idx, in, &repeat);
+ idx = sb_skip_comma (idx, in);
+ idx = exp_get_abs (_("datab data must be absolute.\n"), idx, in, &fill);
+
+ fprintf (outfile, ".fill\t%d,%d,%d\n", repeat, opsize, fill);
+}
+
+/* .align <size> */
+
+static void
+do_align (idx, in)
+ int idx;
+ sb *in;
+{
+ int al, have_fill, fill;
+
+ idx = exp_get_abs (_("align needs absolute expression.\n"), idx, in, &al);
+ idx = sb_skip_white (idx, in);
+ have_fill = 0;
+ fill = 0;
+ if (! eol (idx, in))
+ {
+ idx = sb_skip_comma (idx, in);
+ idx = exp_get_abs (_(".align needs absolute fill value.\n"), idx, in,
+ &fill);
+ have_fill = 1;
+ }
+
+ if (al != 1
+ && al != 2
+ && al != 4)
+ WARNING ((stderr, _("alignment must be one of 1, 2 or 4.\n")));
+
+ fprintf (outfile, ".align %d", al);
+ if (have_fill)
+ fprintf (outfile, ",%d", fill);
+ fprintf (outfile, "\n");
+}
+
+/* .res[.b|.w|.l] <size> */
+
+static void
+do_res (idx, in, type)
+ int idx;
+ sb *in;
+ int type;
+{
+ int size = 4;
+ int count = 0;
+
+ idx = get_opsize (idx, in, &size);
+ while (!eol(idx, in))
+ {
+ idx = sb_skip_white (idx, in);
+ if (in->ptr[idx] == ',')
+ idx++;
+ idx = exp_get_abs (_("res needs absolute expression for fill count.\n"), idx, in, &count);
+
+ if (type == 'c' || type == 'z')
+ count++;
+
+ fprintf (outfile, ".space %d\n", count * size);
+ }
+}
+
+
+/* .export */
+
+static void
+do_export (in)
+ sb *in;
+{
+ fprintf (outfile, ".global %s\n", sb_name (in));
+}
+
+/* .print [list] [nolist] */
+
+static void
+do_print (idx, in)
+ int idx;
+ sb *in;
+{
+ idx = sb_skip_white (idx, in);
+ while (idx < in->len)
+ {
+ if (strncasecmp (in->ptr + idx, "LIST", 4) == 0)
+ {
+ fprintf (outfile, ".list\n");
+ idx += 4;
+ }
+ else if (strncasecmp (in->ptr + idx, "NOLIST", 6) == 0)
+ {
+ fprintf (outfile, ".nolist\n");
+ idx += 6;
+ }
+ idx++;
+ }
+}
+
+/* .head */
+static void
+do_heading (idx, in)
+ int idx;
+ sb *in;
+{
+ sb head;
+ sb_new (&head);
+ idx = getstring (idx, in, &head);
+ fprintf (outfile, ".title \"%s\"\n", sb_name (&head));
+ sb_kill (&head);
+}
+
+/* .page */
+
+static void
+do_page ()
+{
+ fprintf (outfile, ".eject\n");
+}
+
+/* .form [lin=<value>] [col=<value>] */
+static void
+do_form (idx, in)
+ int idx;
+ sb *in;
+{
+ int lines = 60;
+ int columns = 132;
+ idx = sb_skip_white (idx, in);
+
+ while (idx < in->len)
+ {
+
+ if (strncasecmp (in->ptr + idx, "LIN=", 4) == 0)
+ {
+ idx += 4;
+ idx = exp_get_abs (_("form LIN= needs absolute expresssion.\n"), idx, in, &lines);
+ }
+
+ if (strncasecmp (in->ptr + idx, _("COL="), 4) == 0)
+ {
+ idx += 4;
+ idx = exp_get_abs (_("form COL= needs absolute expresssion.\n"), idx, in, &columns);
+ }
+
+ idx++;
+ }
+ fprintf (outfile, ".psize %d,%d\n", lines, columns);
+
+}
+
+
+/* Fetch string from the input stream,
+ rules:
+ 'Bxyx<whitespace> -> return 'Bxyza
+ %<char> -> return string of decimal value of x
+ "<string>" -> return string
+ xyx<whitespace> -> return xyz
+*/
+static int
+get_any_string (idx, in, out, expand, pretend_quoted)
+ int idx;
+ sb *in;
+ sb *out;
+ int expand;
+ int pretend_quoted;
+{
+ sb_reset (out);
+ idx = sb_skip_white (idx, in);
+
+ if (idx < in->len)
+ {
+ if (in->len > 2 && in->ptr[idx+1] == '\'' && ISBASE (in->ptr[idx]))
+ {
+ while (!ISSEP (in->ptr[idx]))
+ sb_add_char (out, in->ptr[idx++]);
+ }
+ else if (in->ptr[idx] == '%'
+ && alternate
+ && expand)
+ {
+ int val;
+ char buf[20];
+ /* Turns the next expression into a string */
+ idx = exp_get_abs (_("% operator needs absolute expression"),
+ idx + 1,
+ in,
+ &val);
+ sprintf(buf, "%d", val);
+ sb_add_string (out, buf);
+ }
+ else if (in->ptr[idx] == '"'
+ || in->ptr[idx] == '<'
+ || (alternate && in->ptr[idx] == '\''))
+ {
+ if (alternate && expand)
+ {
+ /* Keep the quotes */
+ sb_add_char (out, '\"');
+
+ idx = getstring (idx, in, out);
+ sb_add_char (out, '\"');
+
+ }
+ else {
+ idx = getstring (idx, in, out);
+ }
+ }
+ else
+ {
+ while (idx < in->len
+ && (in->ptr[idx] == '"'
+ || in->ptr[idx] == '\''
+ || pretend_quoted
+ || !ISSEP (in->ptr[idx])))
+ {
+ if (in->ptr[idx] == '"'
+ || in->ptr[idx] == '\'')
+ {
+ char tchar = in->ptr[idx];
+ sb_add_char (out, in->ptr[idx++]);
+ while (idx < in->len
+ && in->ptr[idx] != tchar)
+ sb_add_char (out, in->ptr[idx++]);
+ if (idx == in->len)
+ return idx;
+ }
+ sb_add_char (out, in->ptr[idx++]);
+ }
+ }
+ }
+
+ return idx;
+}
+
+
+/* skip along sb in starting at idx, suck off whitespace a ( and more
+ whitespace. return the idx of the next char */
+
+static int
+skip_openp (idx, in)
+ int idx;
+ sb *in;
+{
+ idx = sb_skip_white (idx, in);
+ if (in->ptr[idx] != '(')
+ ERROR ((stderr, _("misplaced ( .\n")));
+ idx = sb_skip_white (idx + 1, in);
+ return idx;
+}
+
+/* skip along sb in starting at idx, suck off whitespace a ) and more
+ whitespace. return the idx of the next char */
+
+static int
+skip_closep (idx, in)
+ int idx;
+ sb *in;
+{
+ idx = sb_skip_white (idx, in);
+ if (in->ptr[idx] != ')')
+ ERROR ((stderr, _("misplaced ).\n")));
+ idx = sb_skip_white (idx + 1, in);
+ return idx;
+}
+
+/* .len */
+
+static int
+dolen (idx, in, out)
+ int idx;
+ sb *in;
+ sb *out;
+{
+
+ sb stringout;
+ char buffer[10];
+
+ sb_new (&stringout);
+ idx = skip_openp (idx, in);
+ idx = get_and_process (idx, in, &stringout);
+ idx = skip_closep (idx, in);
+ sprintf (buffer, "%d", stringout.len);
+ sb_add_string (out, buffer);
+
+ sb_kill (&stringout);
+ return idx;
+}
+
+
+/* .instr */
+
+static
+int
+doinstr (idx, in, out)
+ int idx;
+ sb *in;
+ sb *out;
+{
+ sb string;
+ sb search;
+ int i;
+ int start;
+ int res;
+ char buffer[10];
+
+ sb_new (&string);
+ sb_new (&search);
+ idx = skip_openp (idx, in);
+ idx = get_and_process (idx, in, &string);
+ idx = sb_skip_comma (idx, in);
+ idx = get_and_process (idx, in, &search);
+ idx = sb_skip_comma (idx, in);
+ if (isdigit ((unsigned char) in->ptr[idx]))
+ {
+ idx = exp_get_abs (_(".instr needs absolute expresson.\n"), idx, in, &start);
+ }
+ else
+ {
+ start = 0;
+ }
+ idx = skip_closep (idx, in);
+ res = -1;
+ for (i = start; i < string.len; i++)
+ {
+ if (strncmp (string.ptr + i, search.ptr, search.len) == 0)
+ {
+ res = i;
+ break;
+ }
+ }
+ sprintf (buffer, "%d", res);
+ sb_add_string (out, buffer);
+ sb_kill (&string);
+ sb_kill (&search);
+ return idx;
+}
+
+
+static int
+dosubstr (idx, in, out)
+ int idx;
+ sb *in;
+ sb *out;
+{
+ sb string;
+ int pos;
+ int len;
+ sb_new (&string);
+
+ idx = skip_openp (idx, in);
+ idx = get_and_process (idx, in, &string);
+ idx = sb_skip_comma (idx, in);
+ idx = exp_get_abs (_("need absolute position.\n"), idx, in, &pos);
+ idx = sb_skip_comma (idx, in);
+ idx = exp_get_abs (_("need absolute length.\n"), idx, in, &len);
+ idx = skip_closep (idx, in);
+
+
+ if (len < 0 || pos < 0 ||
+ pos > string.len
+ || pos + len > string.len)
+ {
+ sb_add_string (out, " ");
+ }
+ else
+ {
+ sb_add_char (out, '"');
+ while (len > 0)
+ {
+ sb_add_char (out, string.ptr[pos++]);
+ len--;
+ }
+ sb_add_char (out, '"');
+ }
+ sb_kill(&string);
+ return idx;
+}
+
+/* scan line, change tokens in the hash table to their replacements */
+static void
+process_assigns (idx, in, buf)
+ int idx;
+ sb *in;
+ sb *buf;
+{
+ while (idx < in->len)
+ {
+ hash_entry *ptr;
+ if (in->ptr[idx] == '\\'
+ && idx + 1 < in->len
+ && in->ptr[idx + 1] == '(')
+ {
+ do
+ {
+ sb_add_char (buf, in->ptr[idx]);
+ idx++;
+ }
+ while (idx < in->len && in->ptr[idx - 1] != ')');
+ }
+ else if (in->ptr[idx] == '\\'
+ && idx + 1 < in->len
+ && in->ptr[idx + 1] == '&')
+ {
+ idx = condass_lookup_name (in, idx + 2, buf, 1);
+ }
+ else if (in->ptr[idx] == '\\'
+ && idx + 1 < in->len
+ && in->ptr[idx + 1] == '$')
+ {
+ idx = condass_lookup_name (in, idx + 2, buf, 0);
+ }
+ else if (idx + 3 < in->len
+ && in->ptr[idx] == '.'
+ && toupper ((unsigned char) in->ptr[idx + 1]) == 'L'
+ && toupper ((unsigned char) in->ptr[idx + 2]) == 'E'
+ && toupper ((unsigned char) in->ptr[idx + 3]) == 'N')
+ idx = dolen (idx + 4, in, buf);
+ else if (idx + 6 < in->len
+ && in->ptr[idx] == '.'
+ && toupper ((unsigned char) in->ptr[idx + 1]) == 'I'
+ && toupper ((unsigned char) in->ptr[idx + 2]) == 'N'
+ && toupper ((unsigned char) in->ptr[idx + 3]) == 'S'
+ && toupper ((unsigned char) in->ptr[idx + 4]) == 'T'
+ && toupper ((unsigned char) in->ptr[idx + 5]) == 'R')
+ idx = doinstr (idx + 6, in, buf);
+ else if (idx + 7 < in->len
+ && in->ptr[idx] == '.'
+ && toupper ((unsigned char) in->ptr[idx + 1]) == 'S'
+ && toupper ((unsigned char) in->ptr[idx + 2]) == 'U'
+ && toupper ((unsigned char) in->ptr[idx + 3]) == 'B'
+ && toupper ((unsigned char) in->ptr[idx + 4]) == 'S'
+ && toupper ((unsigned char) in->ptr[idx + 5]) == 'T'
+ && toupper ((unsigned char) in->ptr[idx + 6]) == 'R')
+ idx = dosubstr (idx + 7, in, buf);
+ else if (ISFIRSTCHAR (in->ptr[idx]))
+ {
+ /* may be a simple name subsitution, see if we have a word */
+ sb acc;
+ int cur = idx + 1;
+ while (cur < in->len
+ && (ISNEXTCHAR (in->ptr[cur])))
+ cur++;
+
+ sb_new (&acc);
+ sb_add_buffer (&acc, in->ptr + idx, cur - idx);
+ ptr = hash_lookup (&assign_hash_table, &acc);
+ if (ptr)
+ {
+ /* Found a definition for it */
+ sb_add_sb (buf, &ptr->value.s);
+ }
+ else
+ {
+ /* No definition, just copy the word */
+ sb_add_sb (buf, &acc);
+ }
+ sb_kill (&acc);
+ idx = cur;
+ }
+ else
+ {
+ sb_add_char (buf, in->ptr[idx++]);
+ }
+ }
+}
+
+static int
+get_and_process (idx, in, out)
+ int idx;
+ sb *in;
+ sb *out;
+{
+ sb t;
+ sb_new (&t);
+ idx = get_any_string (idx, in, &t, 1, 0);
+ process_assigns (0, &t, out);
+ sb_kill (&t);
+ return idx;
+}
+
+static
+void
+process_file ()
+{
+ sb line;
+ sb t1, t2;
+ sb acc;
+ sb label_in;
+ int more;
+
+ sb_new (&line);
+ sb_new (&t1);
+ sb_new (&t2);
+ sb_new(&acc);
+ sb_new (&label_in);
+ sb_reset (&line);
+ more = get_line (&line);
+ while (more)
+ {
+ /* Find any label and pseudo op that we're intested in */
+ int l;
+ if (line.len == 0)
+ {
+ if (condass_on ())
+ fprintf (outfile, "\n");
+ }
+ else if (mri
+ && (line.ptr[0] == '*'
+ || line.ptr[0] == '!'))
+ {
+ /* MRI line comment. */
+ fprintf (outfile, sb_name (&line));
+ }
+ else
+ {
+ l = grab_label (&line, &label_in);
+ sb_reset (&label);
+
+ if (line.ptr[l] == ':')
+ l++;
+ while (ISWHITE (line.ptr[l]) && l < line.len)
+ l++;
+
+ if (label_in.len)
+ {
+ int do_assigns;
+
+ /* Munge the label, unless this is EQU or ASSIGN. */
+ do_assigns = 1;
+ if (l < line.len
+ && (line.ptr[l] == '.' || alternate || mri))
+ {
+ int lx = l;
+
+ if (line.ptr[lx] == '.')
+ ++lx;
+ if (lx + 3 <= line.len
+ && strncasecmp ("EQU", line.ptr + lx, 3) == 0
+ && (lx + 3 == line.len
+ || ! ISFIRSTCHAR (line.ptr[lx + 3])))
+ do_assigns = 0;
+ else if (lx + 6 <= line.len
+ && strncasecmp ("ASSIGN", line.ptr + lx, 6) == 0
+ && (lx + 6 == line.len
+ || ! ISFIRSTCHAR (line.ptr[lx + 6])))
+ do_assigns = 0;
+ }
+
+ if (do_assigns)
+ process_assigns (0, &label_in, &label);
+ else
+ sb_add_sb (&label, &label_in);
+ }
+
+ if (l < line.len)
+ {
+ if (process_pseudo_op (l, &line, &acc))
+ {
+
+
+
+ }
+ else if (condass_on ())
+ {
+ if (macro_op (l, &line))
+ {
+
+
+ }
+ else
+ {
+ {
+ if (label.len)
+ {
+ fprintf (outfile, "%s:\t", sb_name (&label));
+ }
+ else
+ fprintf (outfile, "\t");
+ sb_reset(&t1);
+ process_assigns (l, &line, &t1);
+ sb_reset (&t2);
+ change_base (0, &t1, &t2);
+ fprintf (outfile, "%s\n", sb_name (&t2));
+ }
+ }
+ }
+ }
+ else {
+ /* Only a label on this line */
+ if (label.len && condass_on())
+ {
+ fprintf (outfile, "%s:\n", sb_name (&label));
+ }
+ }
+ }
+
+ if (had_end)
+ break;
+ sb_reset (&line);
+ more = get_line (&line);
+ }
+
+ if (!had_end && !mri)
+ WARNING ((stderr, _("END missing from end of file.\n")));
+}
+
+
+
+
+
+static void
+free_old_entry (ptr)
+ hash_entry *ptr;
+{
+ if (ptr)
+ {
+ if (ptr->type == hash_string)
+ sb_kill(&ptr->value.s);
+ }
+}
+
+/* name: .ASSIGNA <value> */
+
+static void
+do_assigna (idx, in)
+ int idx;
+ sb *in;
+{
+ sb tmp;
+ int val;
+ sb_new (&tmp);
+
+ process_assigns (idx, in, &tmp);
+ idx = exp_get_abs (_(".ASSIGNA needs constant expression argument.\n"), 0, &tmp, &val);
+
+ if (!label.len)
+ {
+ ERROR ((stderr, _(".ASSIGNA without label.\n")));
+ }
+ else
+ {
+ hash_entry *ptr = hash_create (&vars, &label);
+ free_old_entry (ptr);
+ ptr->type = hash_integer;
+ ptr->value.i = val;
+ }
+ sb_kill (&tmp);
+}
+
+/* name: .ASSIGNC <string> */
+
+static void
+do_assignc (idx, in)
+ int idx;
+ sb *in;
+{
+ sb acc;
+ sb_new (&acc);
+ idx = getstring (idx, in, &acc);
+
+ if (!label.len)
+ {
+ ERROR ((stderr, _(".ASSIGNS without label.\n")));
+ }
+ else
+ {
+ hash_entry *ptr = hash_create (&vars, &label);
+ free_old_entry (ptr);
+ ptr->type = hash_string;
+ sb_new (&ptr->value.s);
+ sb_add_sb (&ptr->value.s, &acc);
+ }
+ sb_kill (&acc);
+}
+
+
+/* name: .REG (reg) */
+
+static void
+do_reg (idx, in)
+ int idx;
+ sb *in;
+{
+ /* remove reg stuff from inside parens */
+ sb what;
+ if (!mri)
+ idx = skip_openp (idx, in);
+ else
+ idx = sb_skip_white (idx, in);
+ sb_new (&what);
+ while (idx < in->len
+ && (mri
+ ? ! eol (idx, in)
+ : in->ptr[idx] != ')'))
+ {
+ sb_add_char (&what, in->ptr[idx]);
+ idx++;
+ }
+ hash_add_to_string_table (&assign_hash_table, &label, &what, 1);
+ sb_kill (&what);
+}
+
+
+static int
+condass_lookup_name (inbuf, idx, out, warn)
+ sb *inbuf;
+ int idx;
+ sb *out;
+ int warn;
+{
+ hash_entry *ptr;
+ sb condass_acc;
+ sb_new (&condass_acc);
+
+ while (idx < inbuf->len
+ && ISNEXTCHAR (inbuf->ptr[idx]))
+ {
+ sb_add_char (&condass_acc, inbuf->ptr[idx++]);
+ }
+
+ if (inbuf->ptr[idx] == '\'')
+ idx++;
+ ptr = hash_lookup (&vars, &condass_acc);
+
+
+ if (!ptr)
+ {
+ if (warn)
+ {
+ WARNING ((stderr, _("Can't find preprocessor variable %s.\n"), sb_name (&condass_acc)));
+ }
+ else
+ {
+ sb_add_string (out, "0");
+ }
+ }
+ else
+ {
+ if (ptr->type == hash_integer)
+ {
+ char buffer[30];
+ sprintf (buffer, "%d", ptr->value.i);
+ sb_add_string (out, buffer);
+ }
+ else
+ {
+ sb_add_sb (out, &ptr->value.s);
+ }
+ }
+ sb_kill (&condass_acc);
+ return idx;
+}
+
+#define EQ 1
+#define NE 2
+#define GE 3
+#define LT 4
+#define LE 5
+#define GT 6
+#define NEVER 7
+
+static int
+whatcond (idx, in, val)
+ int idx;
+ sb *in;
+ int *val;
+{
+ int cond;
+
+ idx = sb_skip_white (idx, in);
+ cond = NEVER;
+ if (idx + 1 < in->len)
+ {
+ char *p;
+ char a, b;
+
+ p = in->ptr + idx;
+ a = toupper ((unsigned char) p[0]);
+ b = toupper ((unsigned char) p[1]);
+ if (a == 'E' && b == 'Q')
+ cond = EQ;
+ else if (a == 'N' && b == 'E')
+ cond = NE;
+ else if (a == 'L' && b == 'T')
+ cond = LT;
+ else if (a == 'L' && b == 'E')
+ cond = LE;
+ else if (a == 'G' && b == 'T')
+ cond = GT;
+ else if (a == 'G' && b == 'E')
+ cond = GE;
+ }
+ if (cond == NEVER)
+ {
+ ERROR ((stderr, _("Comparison operator must be one of EQ, NE, LT, LE, GT or GE.\n")));
+ cond = NEVER;
+ }
+ idx = sb_skip_white (idx + 2, in);
+ *val = cond;
+ return idx;
+}
+
+static int
+istrue (idx, in)
+ int idx;
+ sb *in;
+{
+ int res;
+ sb acc_a;
+ sb cond;
+ sb acc_b;
+ sb_new (&acc_a);
+ sb_new (&cond);
+ sb_new (&acc_b);
+ idx = sb_skip_white (idx, in);
+
+ if (in->ptr[idx] == '"')
+ {
+ int cond;
+ int same;
+ /* This is a string comparision */
+ idx = getstring (idx, in, &acc_a);
+ idx = whatcond (idx, in, &cond);
+ idx = getstring (idx, in, &acc_b);
+ same = acc_a.len == acc_b.len && (strncmp (acc_a.ptr, acc_b.ptr, acc_a.len) == 0);
+
+ if (cond != EQ && cond != NE)
+ {
+ ERROR ((stderr, _("Comparison operator for strings must be EQ or NE\n")));
+ res = 0;
+ }
+ else
+ res = (cond != EQ) ^ same;
+ }
+ else
+ /* This is a numeric expression */
+ {
+ int vala;
+ int valb;
+ int cond;
+ idx = exp_get_abs (_("Conditional operator must have absolute operands.\n"), idx, in, &vala);
+ idx = whatcond (idx, in, &cond);
+ idx = sb_skip_white (idx, in);
+ if (in->ptr[idx] == '"')
+ {
+ WARNING ((stderr, _("String compared against expression.\n")));
+ res = 0;
+ }
+ else
+ {
+ idx = exp_get_abs (_("Conditional operator must have absolute operands.\n"), idx, in, &valb);
+ switch (cond)
+ {
+ default:
+ res = 42;
+ break;
+ case EQ:
+ res = vala == valb;
+ break;
+ case NE:
+ res = vala != valb;
+ break;
+ case LT:
+ res = vala < valb;
+ break;
+ case LE:
+ res = vala <= valb;
+ break;
+ case GT:
+ res = vala > valb;
+ break;
+ case GE:
+ res = vala >= valb;
+ break;
+ case NEVER:
+ res = 0;
+ break;
+ }
+ }
+ }
+
+ sb_kill (&acc_a);
+ sb_kill (&cond);
+ sb_kill (&acc_b);
+ return res;
+}
+
+/* .AIF */
+static void
+do_aif (idx, in)
+ int idx;
+ sb *in;
+{
+ if (ifi >= IFNESTING)
+ {
+ FATAL ((stderr, _("AIF nesting unreasonable.\n")));
+ }
+ ifi++;
+ ifstack[ifi].on = ifstack[ifi-1].on ? istrue (idx, in) : 0;
+ ifstack[ifi].hadelse = 0;
+}
+
+
+/* .AELSE */
+static void
+do_aelse ()
+{
+ ifstack[ifi].on = ifstack[ifi-1].on ? !ifstack[ifi].on : 0;
+ if (ifstack[ifi].hadelse)
+ {
+ ERROR ((stderr, _("Multiple AELSEs in AIF.\n")));
+ }
+ ifstack[ifi].hadelse = 1;
+}
+
+
+/* .AENDI */
+static void
+do_aendi ()
+{
+ if (ifi != 0)
+ {
+ ifi--;
+ }
+ else
+ {
+ ERROR ((stderr, _("AENDI without AIF.\n")));
+ }
+}
+
+static int
+condass_on ()
+{
+ return ifstack[ifi].on;
+}
+
+/* MRI IFEQ, IFNE, IFLT, IFLE, IFGE, IFGT. */
+
+static void
+do_if (idx, in, cond)
+ int idx;
+ sb *in;
+ int cond;
+{
+ int val;
+ int res;
+
+ if (ifi >= IFNESTING)
+ {
+ FATAL ((stderr, _("IF nesting unreasonable.\n")));
+ }
+
+ idx = exp_get_abs (_("Conditional operator must have absolute operands.\n"),
+ idx, in, &val);
+ switch (cond)
+ {
+ default:
+ case EQ: res = val == 0; break;
+ case NE: res = val != 0; break;
+ case LT: res = val < 0; break;
+ case LE: res = val <= 0; break;
+ case GE: res = val >= 0; break;
+ case GT: res = val > 0; break;
+ }
+
+ ifi++;
+ ifstack[ifi].on = ifstack[ifi-1].on ? res: 0;
+ ifstack[ifi].hadelse = 0;
+}
+
+/* Get a string for the MRI IFC or IFNC pseudo-ops. */
+
+static int
+get_mri_string (idx, in, val, terminator)
+ int idx;
+ sb *in;
+ sb *val;
+ int terminator;
+{
+ idx = sb_skip_white (idx, in);
+
+ if (idx < in->len
+ && in->ptr[idx] == '\'')
+ {
+ sb_add_char (val, '\'');
+ for (++idx; idx < in->len; ++idx)
+ {
+ sb_add_char (val, in->ptr[idx]);
+ if (in->ptr[idx] == '\'')
+ {
+ ++idx;
+ if (idx >= in->len
+ || in->ptr[idx] != '\'')
+ break;
+ }
+ }
+ idx = sb_skip_white (idx, in);
+ }
+ else
+ {
+ int i;
+
+ while (idx < in->len
+ && in->ptr[idx] != terminator)
+ {
+ sb_add_char (val, in->ptr[idx]);
+ ++idx;
+ }
+ i = val->len - 1;
+ while (i >= 0 && ISWHITE (val->ptr[i]))
+ --i;
+ val->len = i + 1;
+ }
+
+ return idx;
+}
+
+/* MRI IFC, IFNC. */
+
+static void
+do_ifc (idx, in, ifnc)
+ int idx;
+ sb *in;
+ int ifnc;
+{
+ sb first;
+ sb second;
+ int res;
+
+ if (ifi >= IFNESTING)
+ {
+ FATAL ((stderr, _("IF nesting unreasonable.\n")));
+ }
+
+ sb_new (&first);
+ sb_new (&second);
+
+ idx = get_mri_string (idx, in, &first, ',');
+
+ if (idx >= in->len || in->ptr[idx] != ',')
+ {
+ ERROR ((stderr, _("Bad format for IF or IFNC.\n")));
+ return;
+ }
+
+ idx = get_mri_string (idx + 1, in, &second, ';');
+
+ res = (first.len == second.len
+ && strncmp (first.ptr, second.ptr, first.len) == 0);
+ res ^= ifnc;
+
+ ifi++;
+ ifstack[ifi].on = ifstack[ifi-1].on ? res : 0;
+ ifstack[ifi].hadelse = 0;
+}
+
+/* .ENDR */
+static void
+do_aendr ()
+{
+ if (!mri)
+ ERROR ((stderr, _("AENDR without a AREPEAT.\n")));
+ else
+ ERROR ((stderr, _("ENDR without a REPT.\n")));
+}
+
+/* .AWHILE */
+
+static
+void
+do_awhile (idx, in)
+ int idx;
+ sb *in;
+{
+ int line = linecount ();
+ sb exp;
+ sb sub;
+ int doit;
+
+ sb_new (&sub);
+ sb_new (&exp);
+
+ process_assigns (idx, in, &exp);
+ doit = istrue (0, &exp);
+
+ if (! buffer_and_nest ("AWHILE", "AENDW", &sub, get_line))
+ FATAL ((stderr, _("AWHILE without a AENDW at %d.\n"), line - 1));
+
+ /* Turn
+ .AWHILE exp
+ foo
+ .AENDW
+ into
+ foo
+ .AWHILE exp
+ foo
+ .ENDW
+ */
+
+ if (doit)
+ {
+ int index = include_next_index ();
+
+ sb copy;
+ sb_new (&copy);
+ sb_add_sb (&copy, &sub);
+ sb_add_sb (&copy, in);
+ sb_add_string (&copy, "\n");
+ sb_add_sb (&copy, &sub);
+ sb_add_string (&copy, "\t.AENDW\n");
+ /* Push another WHILE */
+ include_buf (&exp, &copy, include_while, index);
+ sb_kill (&copy);
+ }
+ sb_kill (&exp);
+ sb_kill (&sub);
+}
+
+
+/* .AENDW */
+
+static void
+do_aendw ()
+{
+ ERROR ((stderr, _("AENDW without a AENDW.\n")));
+}
+
+
+/* .EXITM
+
+ Pop things off the include stack until the type and index changes */
+
+static void
+do_exitm ()
+{
+ include_type type = sp->type;
+ if (type == include_repeat
+ || type == include_while
+ || type == include_macro)
+ {
+ int index = sp->index;
+ include_pop ();
+ while (sp->index == index
+ && sp->type == type)
+ {
+ include_pop ();
+ }
+ }
+}
+
+/* .AREPEAT */
+
+static void
+do_arepeat (idx, in)
+ int idx;
+ sb *in;
+{
+ int line = linecount ();
+ sb exp; /* buffer with expression in it */
+ sb copy; /* expanded repeat block */
+ sb sub; /* contents of AREPEAT */
+ int rc;
+ int ret;
+ char buffer[30];
+
+ sb_new (&exp);
+ sb_new (&copy);
+ sb_new (&sub);
+ process_assigns (idx, in, &exp);
+ idx = exp_get_abs (_("AREPEAT must have absolute operand.\n"), 0, &exp, &rc);
+ if (!mri)
+ ret = buffer_and_nest ("AREPEAT", "AENDR", &sub, get_line);
+ else
+ ret = buffer_and_nest ("REPT", "ENDR", &sub, get_line);
+ if (! ret)
+ FATAL ((stderr, _("AREPEAT without a AENDR at %d.\n"), line - 1));
+ if (rc > 0)
+ {
+ /* Push back the text following the repeat, and another repeat block
+ so
+ .AREPEAT 20
+ foo
+ .AENDR
+ gets turned into
+ foo
+ .AREPEAT 19
+ foo
+ .AENDR
+ */
+ int index = include_next_index ();
+ sb_add_sb (&copy, &sub);
+ if (rc > 1)
+ {
+ if (!mri)
+ sprintf (buffer, "\t.AREPEAT %d\n", rc - 1);
+ else
+ sprintf (buffer, "\tREPT %d\n", rc - 1);
+ sb_add_string (&copy, buffer);
+ sb_add_sb (&copy, &sub);
+ if (!mri)
+ sb_add_string (&copy, " .AENDR\n");
+ else
+ sb_add_string (&copy, " ENDR\n");
+ }
+
+ include_buf (&exp, &copy, include_repeat, index);
+ }
+ sb_kill (&exp);
+ sb_kill (&sub);
+ sb_kill (&copy);
+}
+
+/* .ENDM */
+
+static void
+do_endm ()
+{
+ ERROR ((stderr, _(".ENDM without a matching .MACRO.\n")));
+}
+
+/* MRI IRP pseudo-op. */
+
+static void
+do_irp (idx, in, irpc)
+ int idx;
+ sb *in;
+ int irpc;
+{
+ const char *err;
+ sb out;
+
+ sb_new (&out);
+
+ err = expand_irp (irpc, idx, in, &out, get_line, comment_char);
+ if (err != NULL)
+ ERROR ((stderr, "%s\n", err));
+
+ fprintf (outfile, "%s", sb_terminate (&out));
+
+ sb_kill (&out);
+}
+
+/* MACRO PROCESSING */
+
+/* Parse off LOCAL n1, n2,... Invent a label name for it */
+static
+void
+do_local (idx, line)
+ int idx;
+ sb *line;
+{
+ ERROR ((stderr, _("LOCAL outside of MACRO")));
+}
+
+static void
+do_macro (idx, in)
+ int idx;
+ sb *in;
+{
+ const char *err;
+ int line = linecount ();
+
+ err = define_macro (idx, in, &label, get_line, (const char **) NULL);
+ if (err != NULL)
+ ERROR ((stderr, _("macro at line %d: %s\n"), line - 1, err));
+}
+
+static int
+macro_op (idx, in)
+ int idx;
+ sb *in;
+{
+ const char *err;
+ sb out;
+ sb name;
+
+ if (! macro_defined)
+ return 0;
+
+ sb_terminate (in);
+ if (! check_macro (in->ptr + idx, &out, comment_char, &err))
+ return 0;
+
+ if (err != NULL)
+ ERROR ((stderr, "%s\n", err));
+
+ sb_new (&name);
+ sb_add_string (&name, _("macro expansion"));
+
+ include_buf (&name, &out, include_macro, include_next_index ());
+
+ sb_kill (&name);
+ sb_kill (&out);
+
+ return 1;
+}
+
+/* STRING HANDLING */
+
+static int
+getstring (idx, in, acc)
+ int idx;
+ sb *in;
+ sb *acc;
+{
+ idx = sb_skip_white (idx, in);
+
+ while (idx < in->len
+ && (in->ptr[idx] == '"'
+ || in->ptr[idx] == '<'
+ || (in->ptr[idx] == '\'' && alternate)))
+ {
+ if (in->ptr[idx] == '<')
+ {
+ if (alternate || mri)
+ {
+ int nest = 0;
+ idx++;
+ while ((in->ptr[idx] != '>' || nest)
+ && idx < in->len)
+ {
+ if (in->ptr[idx] == '!')
+ {
+ idx++ ;
+ sb_add_char (acc, in->ptr[idx++]);
+ }
+ else {
+ if (in->ptr[idx] == '>')
+ nest--;
+ if (in->ptr[idx] == '<')
+ nest++;
+ sb_add_char (acc, in->ptr[idx++]);
+ }
+ }
+ idx++;
+ }
+ else {
+ int code;
+ idx++;
+ idx = exp_get_abs (_("Character code in string must be absolute expression.\n"),
+ idx, in, &code);
+ sb_add_char (acc, code);
+
+ if (in->ptr[idx] != '>')
+ ERROR ((stderr, _("Missing > for character code.\n")));
+ idx++;
+ }
+ }
+ else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
+ {
+ char tchar = in->ptr[idx];
+ idx++;
+ while (idx < in->len)
+ {
+ if (alternate && in->ptr[idx] == '!')
+ {
+ idx++ ;
+ sb_add_char (acc, in->ptr[idx++]);
+ }
+ else {
+ if (in->ptr[idx] == tchar)
+ {
+ idx++;
+ if (idx >= in->len || in->ptr[idx] != tchar)
+ break;
+ }
+ sb_add_char (acc, in->ptr[idx]);
+ idx++;
+ }
+ }
+ }
+ }
+
+ return idx;
+}
+
+/* .SDATA[C|Z] <string> */
+
+static
+void
+do_sdata (idx, in, type)
+ int idx;
+ sb *in;
+ int type;
+{
+ int nc = 0;
+ int pidx = -1;
+ sb acc;
+ sb_new (&acc);
+ fprintf (outfile, ".byte\t");
+
+ while (!eol (idx, in))
+ {
+ int i;
+ sb_reset (&acc);
+ idx = sb_skip_white (idx, in);
+ while (!eol (idx, in))
+ {
+ pidx = idx = get_any_string (idx, in, &acc, 0, 1);
+ if (type == 'c')
+ {
+ if (acc.len > 255)
+ {
+ ERROR ((stderr, _("string for SDATAC longer than 255 characters (%d).\n"), acc.len));
+ }
+ fprintf (outfile, "%d", acc.len);
+ nc = 1;
+ }
+
+ for (i = 0; i < acc.len; i++)
+ {
+ if (nc)
+ {
+ fprintf (outfile, ",");
+ }
+ fprintf (outfile, "%d", acc.ptr[i]);
+ nc = 1;
+ }
+
+ if (type == 'z')
+ {
+ if (nc)
+ fprintf (outfile, ",");
+ fprintf (outfile, "0");
+ }
+ idx = sb_skip_comma (idx, in);
+ if (idx == pidx) break;
+ }
+ if (!alternate && in->ptr[idx] != ',' && idx != in->len)
+ {
+ fprintf (outfile, "\n");
+ ERROR ((stderr, _("illegal character in SDATA line (0x%x).\n"), in->ptr[idx]));
+ break;
+ }
+ idx++;
+ }
+ sb_kill (&acc);
+ fprintf (outfile, "\n");
+}
+
+/* .SDATAB <count> <string> */
+
+static void
+do_sdatab (idx, in)
+ int idx;
+ sb *in;
+{
+ int repeat;
+ int i;
+ sb acc;
+ sb_new (&acc);
+
+ idx = exp_get_abs (_("Must have absolute SDATAB repeat count.\n"), idx, in, &repeat);
+ if (repeat <= 0)
+ {
+ ERROR ((stderr, _("Must have positive SDATAB repeat count (%d).\n"), repeat));
+ repeat = 1;
+ }
+
+ idx = sb_skip_comma (idx, in);
+ idx = getstring (idx, in, &acc);
+
+ for (i = 0; i < repeat; i++)
+ {
+ if (i)
+ fprintf (outfile, "\t");
+ fprintf (outfile, ".byte\t");
+ sb_print (outfile, &acc);
+ fprintf (outfile, "\n");
+ }
+ sb_kill (&acc);
+
+}
+
+static int
+new_file (name)
+ const char *name;
+{
+ FILE *newone = fopen (name, "r");
+ if (!newone)
+ return 0;
+
+ if (isp == MAX_INCLUDES)
+ FATAL ((stderr, _("Unreasonable include depth (%ld).\n"), (long) isp));
+
+ sp++;
+ sp->handle = newone;
+
+ sb_new (&sp->name);
+ sb_add_string (&sp->name, name);
+
+ sp->linecount = 1;
+ sp->pushback_index = 0;
+ sp->type = include_file;
+ sp->index = 0;
+ sb_new (&sp->pushback);
+ return 1;
+}
+
+static void
+do_include (idx, in)
+ int idx;
+ sb *in;
+{
+ sb t;
+ sb cat;
+ include_path *includes;
+
+ sb_new (&t);
+ sb_new (&cat);
+
+ if (! mri)
+ idx = getstring (idx, in, &t);
+ else
+ {
+ idx = sb_skip_white (idx, in);
+ while (idx < in->len && ! ISWHITE (in->ptr[idx]))
+ {
+ sb_add_char (&t, in->ptr[idx]);
+ ++idx;
+ }
+ }
+
+ for (includes = paths_head; includes; includes = includes->next)
+ {
+ sb_reset (&cat);
+ sb_add_sb (&cat, &includes->path);
+ sb_add_char (&cat, '/');
+ sb_add_sb (&cat, &t);
+ if (new_file (sb_name (&cat)))
+ {
+ break;
+ }
+ }
+ if (!includes)
+ {
+ if (! new_file (sb_name (&t)))
+ FATAL ((stderr, _("Can't open include file `%s'.\n"), sb_name (&t)));
+ }
+ sb_kill (&cat);
+ sb_kill (&t);
+}
+
+static void
+include_pop ()
+{
+ if (sp != include_stack)
+ {
+ if (sp->handle)
+ fclose (sp->handle);
+ sp--;
+ }
+}
+
+/* Get the next character from the include stack. If there's anything
+ in the pushback buffer, take that first. If we're at eof, pop from
+ the stack and try again. Keep the linecount up to date. */
+
+static int
+get ()
+{
+ int r;
+
+ if (sp->pushback.len != sp->pushback_index)
+ {
+ r = (char) (sp->pushback.ptr[sp->pushback_index++]);
+ /* When they've all gone, reset the pointer */
+ if (sp->pushback_index == sp->pushback.len)
+ {
+ sp->pushback.len = 0;
+ sp->pushback_index = 0;
+ }
+ }
+ else if (sp->handle)
+ {
+ r = getc (sp->handle);
+ }
+ else
+ r = EOF;
+
+ if (r == EOF && isp)
+ {
+ include_pop ();
+ r = get ();
+ while (r == EOF && isp)
+ {
+ include_pop ();
+ r = get ();
+ }
+ return r;
+ }
+ if (r == '\n')
+ {
+ sp->linecount++;
+ }
+
+ return r;
+}
+
+static int
+linecount ()
+{
+ return sp->linecount;
+}
+
+static int
+include_next_index ()
+{
+ static int index;
+ if (!unreasonable
+ && index > MAX_REASONABLE)
+ FATAL ((stderr, _("Unreasonable expansion (-u turns off check).\n")));
+ return ++index;
+}
+
+
+/* Initialize the chartype vector. */
+
+static void
+chartype_init ()
+{
+ int x;
+ for (x = 0; x < 256; x++)
+ {
+ if (isalpha (x) || x == '_' || x == '$')
+ chartype[x] |= FIRSTBIT;
+
+ if (mri && x == '.')
+ chartype[x] |= FIRSTBIT;
+
+ if (isdigit (x) || isalpha (x) || x == '_' || x == '$')
+ chartype[x] |= NEXTBIT;
+
+ if (x == ' ' || x == '\t' || x == ',' || x == '"' || x == ';'
+ || x == '"' || x == '<' || x == '>' || x == ')' || x == '(')
+ chartype[x] |= SEPBIT;
+
+ if (x == 'b' || x == 'B'
+ || x == 'q' || x == 'Q'
+ || x == 'h' || x == 'H'
+ || x == 'd' || x == 'D')
+ chartype [x] |= BASEBIT;
+
+ if (x == ' ' || x == '\t')
+ chartype[x] |= WHITEBIT;
+
+ if (x == comment_char)
+ chartype[x] |= COMMENTBIT;
+ }
+}
+
+
+
+/* What to do with all the keywords */
+#define PROCESS 0x1000 /* Run substitution over the line */
+#define LAB 0x2000 /* Spit out the label */
+
+#define K_EQU (PROCESS|1)
+#define K_ASSIGN (PROCESS|2)
+#define K_REG (PROCESS|3)
+#define K_ORG (PROCESS|4)
+#define K_RADIX (PROCESS|5)
+#define K_DATA (LAB|PROCESS|6)
+#define K_DATAB (LAB|PROCESS|7)
+#define K_SDATA (LAB|PROCESS|8)
+#define K_SDATAB (LAB|PROCESS|9)
+#define K_SDATAC (LAB|PROCESS|10)
+#define K_SDATAZ (LAB|PROCESS|11)
+#define K_RES (LAB|PROCESS|12)
+#define K_SRES (LAB|PROCESS|13)
+#define K_SRESC (LAB|PROCESS|14)
+#define K_SRESZ (LAB|PROCESS|15)
+#define K_EXPORT (LAB|PROCESS|16)
+#define K_GLOBAL (LAB|PROCESS|17)
+#define K_PRINT (LAB|PROCESS|19)
+#define K_FORM (LAB|PROCESS|20)
+#define K_HEADING (LAB|PROCESS|21)
+#define K_PAGE (LAB|PROCESS|22)
+#define K_IMPORT (LAB|PROCESS|23)
+#define K_PROGRAM (LAB|PROCESS|24)
+#define K_END (PROCESS|25)
+#define K_INCLUDE (PROCESS|26)
+#define K_IGNORED (PROCESS|27)
+#define K_ASSIGNA (PROCESS|28)
+#define K_ASSIGNC (29)
+#define K_AIF (PROCESS|30)
+#define K_AELSE (PROCESS|31)
+#define K_AENDI (PROCESS|32)
+#define K_AREPEAT (PROCESS|33)
+#define K_AENDR (PROCESS|34)
+#define K_AWHILE (35)
+#define K_AENDW (PROCESS|36)
+#define K_EXITM (37)
+#define K_MACRO (PROCESS|38)
+#define K_ENDM (39)
+#define K_ALIGN (PROCESS|LAB|40)
+#define K_ALTERNATE (41)
+#define K_DB (LAB|PROCESS|42)
+#define K_DW (LAB|PROCESS|43)
+#define K_DL (LAB|PROCESS|44)
+#define K_LOCAL (45)
+#define K_IFEQ (PROCESS|46)
+#define K_IFNE (PROCESS|47)
+#define K_IFLT (PROCESS|48)
+#define K_IFLE (PROCESS|49)
+#define K_IFGE (PROCESS|50)
+#define K_IFGT (PROCESS|51)
+#define K_IFC (PROCESS|52)
+#define K_IFNC (PROCESS|53)
+#define K_IRP (PROCESS|54)
+#define K_IRPC (PROCESS|55)
+
+
+struct keyword
+{
+ char *name;
+ int code;
+ int extra;
+};
+
+static struct keyword kinfo[] =
+{
+ { "EQU", K_EQU, 0 },
+ { "ALTERNATE", K_ALTERNATE, 0 },
+ { "ASSIGN", K_ASSIGN, 0 },
+ { "REG", K_REG, 0 },
+ { "ORG", K_ORG, 0 },
+ { "RADIX", K_RADIX, 0 },
+ { "DATA", K_DATA, 0 },
+ { "DB", K_DB, 0 },
+ { "DW", K_DW, 0 },
+ { "DL", K_DL, 0 },
+ { "DATAB", K_DATAB, 0 },
+ { "SDATA", K_SDATA, 0 },
+ { "SDATAB", K_SDATAB, 0 },
+ { "SDATAZ", K_SDATAZ, 0 },
+ { "SDATAC", K_SDATAC, 0 },
+ { "RES", K_RES, 0 },
+ { "SRES", K_SRES, 0 },
+ { "SRESC", K_SRESC, 0 },
+ { "SRESZ", K_SRESZ, 0 },
+ { "EXPORT", K_EXPORT, 0 },
+ { "GLOBAL", K_GLOBAL, 0 },
+ { "PRINT", K_PRINT, 0 },
+ { "FORM", K_FORM, 0 },
+ { "HEADING", K_HEADING, 0 },
+ { "PAGE", K_PAGE, 0 },
+ { "PROGRAM", K_IGNORED, 0 },
+ { "END", K_END, 0 },
+ { "INCLUDE", K_INCLUDE, 0 },
+ { "ASSIGNA", K_ASSIGNA, 0 },
+ { "ASSIGNC", K_ASSIGNC, 0 },
+ { "AIF", K_AIF, 0 },
+ { "AELSE", K_AELSE, 0 },
+ { "AENDI", K_AENDI, 0 },
+ { "AREPEAT", K_AREPEAT, 0 },
+ { "AENDR", K_AENDR, 0 },
+ { "EXITM", K_EXITM, 0 },
+ { "MACRO", K_MACRO, 0 },
+ { "ENDM", K_ENDM, 0 },
+ { "AWHILE", K_AWHILE, 0 },
+ { "ALIGN", K_ALIGN, 0 },
+ { "AENDW", K_AENDW, 0 },
+ { "ALTERNATE", K_ALTERNATE, 0 },
+ { "LOCAL", K_LOCAL, 0 },
+ { NULL, 0, 0 }
+};
+
+/* Although the conditional operators are handled by gas, we need to
+ handle them here as well, in case they are used in a recursive
+ macro to end the recursion. */
+
+static struct keyword mrikinfo[] =
+{
+ { "IFEQ", K_IFEQ, 0 },
+ { "IFNE", K_IFNE, 0 },
+ { "IFLT", K_IFLT, 0 },
+ { "IFLE", K_IFLE, 0 },
+ { "IFGE", K_IFGE, 0 },
+ { "IFGT", K_IFGT, 0 },
+ { "IFC", K_IFC, 0 },
+ { "IFNC", K_IFNC, 0 },
+ { "ELSEC", K_AELSE, 0 },
+ { "ENDC", K_AENDI, 0 },
+ { "MEXIT", K_EXITM, 0 },
+ { "REPT", K_AREPEAT, 0 },
+ { "IRP", K_IRP, 0 },
+ { "IRPC", K_IRPC, 0 },
+ { "ENDR", K_AENDR, 0 },
+ { NULL, 0, 0 }
+};
+
+/* Look for a pseudo op on the line. If one's there then call
+ its handler. */
+
+static int
+process_pseudo_op (idx, line, acc)
+ int idx;
+ sb *line;
+ sb *acc;
+{
+ int oidx = idx;
+
+ if (line->ptr[idx] == '.' || alternate || mri)
+ {
+ /* Scan forward and find pseudo name */
+ char *in;
+ hash_entry *ptr;
+
+ char *s;
+ char *e;
+ if (line->ptr[idx] == '.')
+ idx++;
+ in = line->ptr + idx;
+ s = in;
+ e = s;
+ sb_reset (acc);
+
+ while (idx < line->len && *e && ISFIRSTCHAR (*e))
+ {
+ sb_add_char (acc, *e);
+ e++;
+ idx++;
+ }
+
+ ptr = hash_lookup (&keyword_hash_table, acc);
+
+ if (!ptr)
+ {
+#if 0
+ /* This one causes lots of pain when trying to preprocess
+ ordinary code */
+ WARNING ((stderr, _("Unrecognised pseudo op `%s'.\n"), sb_name (acc)));
+#endif
+ return 0;
+ }
+ if (ptr->value.i & LAB)
+ { /* output the label */
+ if (label.len)
+ {
+ fprintf (outfile, "%s:\t", sb_name (&label));
+ }
+ else
+ fprintf (outfile, "\t");
+ }
+
+ if (mri && ptr->value.i == K_END)
+ {
+ sb t;
+
+ sb_new (&t);
+ sb_add_buffer (&t, line->ptr + oidx, idx - oidx);
+ fprintf (outfile, "\t%s", sb_name (&t));
+ sb_kill (&t);
+ }
+
+ if (ptr->value.i & PROCESS)
+ {
+ /* Polish the rest of the line before handling the pseudo op */
+#if 0
+ strip_comments(line);
+#endif
+ sb_reset (acc);
+ process_assigns (idx, line, acc);
+ sb_reset(line);
+ change_base (0, acc, line);
+ idx = 0;
+ }
+ if (!condass_on ())
+ {
+ switch (ptr->value.i)
+ {
+ case K_AIF:
+ do_aif (idx, line);
+ break;
+ case K_AELSE:
+ do_aelse ();
+ break;
+ case K_AENDI:
+ do_aendi ();
+ break;
+ }
+ return 1;
+ }
+ else
+ {
+ switch (ptr->value.i)
+ {
+ case K_ALTERNATE:
+ alternate = 1;
+ macro_init (1, mri, 0, exp_get_abs);
+ return 1;
+ case K_AELSE:
+ do_aelse ();
+ return 1;
+ case K_AENDI:
+ do_aendi ();
+ return 1;
+ case K_ORG:
+ ERROR ((stderr, _("ORG command not allowed.\n")));
+ break;
+ case K_RADIX:
+ do_radix (line);
+ return 1;
+ case K_DB:
+ do_data (idx, line, 1);
+ return 1;
+ case K_DW:
+ do_data (idx, line, 2);
+ return 1;
+ case K_DL:
+ do_data (idx, line, 4);
+ return 1;
+ case K_DATA:
+ do_data (idx, line, 0);
+ return 1;
+ case K_DATAB:
+ do_datab (idx, line);
+ return 1;
+ case K_SDATA:
+ do_sdata (idx, line, 0);
+ return 1;
+ case K_SDATAB:
+ do_sdatab (idx, line);
+ return 1;
+ case K_SDATAC:
+ do_sdata (idx, line, 'c');
+ return 1;
+ case K_SDATAZ:
+ do_sdata (idx, line, 'z');
+ return 1;
+ case K_ASSIGN:
+ do_assign (0, 0, line);
+ return 1;
+ case K_AIF:
+ do_aif (idx, line);
+ return 1;
+ case K_AREPEAT:
+ do_arepeat (idx, line);
+ return 1;
+ case K_AENDW:
+ do_aendw ();
+ return 1;
+ case K_AWHILE:
+ do_awhile (idx, line);
+ return 1;
+ case K_AENDR:
+ do_aendr ();
+ return 1;
+ case K_EQU:
+ do_assign (1, idx, line);
+ return 1;
+ case K_ALIGN:
+ do_align (idx, line);
+ return 1;
+ case K_RES:
+ do_res (idx, line, 0);
+ return 1;
+ case K_SRES:
+ do_res (idx, line, 's');
+ return 1;
+ case K_INCLUDE:
+ do_include (idx, line);
+ return 1;
+ case K_LOCAL:
+ do_local (idx, line);
+ return 1;
+ case K_MACRO:
+ do_macro (idx, line);
+ return 1;
+ case K_ENDM:
+ do_endm ();
+ return 1;
+ case K_SRESC:
+ do_res (idx, line, 'c');
+ return 1;
+ case K_PRINT:
+ do_print (idx, line);
+ return 1;
+ case K_FORM:
+ do_form (idx, line);
+ return 1;
+ case K_HEADING:
+ do_heading (idx, line);
+ return 1;
+ case K_PAGE:
+ do_page ();
+ return 1;
+ case K_GLOBAL:
+ case K_EXPORT:
+ do_export (line);
+ return 1;
+ case K_IMPORT:
+ return 1;
+ case K_SRESZ:
+ do_res (idx, line, 'z');
+ return 1;
+ case K_IGNORED:
+ return 1;
+ case K_END:
+ do_end (line);
+ return 1;
+ case K_ASSIGNA:
+ do_assigna (idx, line);
+ return 1;
+ case K_ASSIGNC:
+ do_assignc (idx, line);
+ return 1;
+ case K_EXITM:
+ do_exitm ();
+ return 1;
+ case K_REG:
+ do_reg (idx, line);
+ return 1;
+ case K_IFEQ:
+ do_if (idx, line, EQ);
+ return 1;
+ case K_IFNE:
+ do_if (idx, line, NE);
+ return 1;
+ case K_IFLT:
+ do_if (idx, line, LT);
+ return 1;
+ case K_IFLE:
+ do_if (idx, line, LE);
+ return 1;
+ case K_IFGE:
+ do_if (idx, line, GE);
+ return 1;
+ case K_IFGT:
+ do_if (idx, line, GT);
+ return 1;
+ case K_IFC:
+ do_ifc (idx, line, 0);
+ return 1;
+ case K_IFNC:
+ do_ifc (idx, line, 1);
+ return 1;
+ case K_IRP:
+ do_irp (idx, line, 0);
+ return 1;
+ case K_IRPC:
+ do_irp (idx, line, 1);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+
+
+/* Add a keyword to the hash table. */
+
+static void
+add_keyword (name, code)
+ const char *name;
+ int code;
+{
+ sb label;
+ int j;
+
+ sb_new (&label);
+ sb_add_string (&label, name);
+
+ hash_add_to_int_table (&keyword_hash_table, &label, code);
+
+ sb_reset (&label);
+ for (j = 0; name[j]; j++)
+ sb_add_char (&label, name[j] - 'A' + 'a');
+ hash_add_to_int_table (&keyword_hash_table, &label, code);
+
+ sb_kill (&label);
+}
+
+/* Build the keyword hash table - put each keyword in the table twice,
+ once upper and once lower case.*/
+
+static void
+process_init ()
+{
+ int i;
+
+ for (i = 0; kinfo[i].name; i++)
+ add_keyword (kinfo[i].name, kinfo[i].code);
+
+ if (mri)
+ {
+ for (i = 0; mrikinfo[i].name; i++)
+ add_keyword (mrikinfo[i].name, mrikinfo[i].code);
+ }
+}
+
+
+static void
+do_define (string)
+ const char *string;
+{
+ sb label;
+ int res = 1;
+ hash_entry *ptr;
+ sb_new (&label);
+
+
+ while (*string)
+ {
+ if (*string == '=')
+ {
+ sb value;
+ sb_new (&value);
+ string++;
+ while (*string)
+ {
+ sb_add_char (&value, *string);
+ string++;
+ }
+ exp_get_abs (_("Invalid expression on command line.\n"), 0, &value, &res);
+ sb_kill (&value);
+ break;
+ }
+ sb_add_char (&label, *string);
+
+ string ++;
+ }
+
+ ptr = hash_create (&vars, &label);
+ free_old_entry (ptr);
+ ptr->type = hash_integer;
+ ptr->value.i = res;
+ sb_kill (&label);
+}
+char *program_name;
+
+/* The list of long options. */
+static struct option long_options[] =
+{
+ { "alternate", no_argument, 0, 'a' },
+ { "include", required_argument, 0, 'I' },
+ { "commentchar", required_argument, 0, 'c' },
+ { "copysource", no_argument, 0, 's' },
+ { "debug", no_argument, 0, 'd' },
+ { "help", no_argument, 0, 'h' },
+ { "mri", no_argument, 0, 'M' },
+ { "output", required_argument, 0, 'o' },
+ { "print", no_argument, 0, 'p' },
+ { "unreasonable", no_argument, 0, 'u' },
+ { "version", no_argument, 0, 'v' },
+ { "define", required_argument, 0, 'd' },
+ { NULL, no_argument, 0, 0 }
+};
+
+/* Show a usage message and exit. */
+static void
+show_usage (file, status)
+ FILE *file;
+ int status;
+{
+ fprintf (file, _("\
+Usage: %s \n\
+ [-a] [--alternate] enter alternate macro mode\n\
+ [-c char] [--commentchar char] change the comment character from !\n\
+ [-d] [--debug] print some debugging info\n\
+ [-h] [--help] print this message\n\
+ [-M] [--mri] enter MRI compatibility mode\n\
+ [-o out] [--output out] set the output file\n\
+ [-p] [--print] print line numbers\n"), program_name);
+ fprintf (file, _("\
+ [-s] [--copysource] copy source through as comments \n\
+ [-u] [--unreasonable] allow unreasonable nesting\n\
+ [-v] [--version] print the program version\n\
+ [-Dname=value] create preprocessor variable called name, with value\n\
+ [-Ipath] add to include path list\n\
+ [in-file]\n"));
+ if (status == 0)
+ printf (_("\nReport bugs to bug-gnu-utils@gnu.org\n"));
+ exit (status);
+}
+
+/* Display a help message and exit. */
+static void
+show_help ()
+{
+ printf (_("%s: Gnu Assembler Macro Preprocessor\n"),
+ program_name);
+ show_usage (stdout, 0);
+}
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int opt;
+ char *out_name = 0;
+ sp = include_stack;
+
+ ifstack[0].on = 1;
+ ifi = 0;
+
+#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
+ setlocale (LC_MESSAGES, "");
+#endif
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+
+ program_name = argv[0];
+ xmalloc_set_program_name (program_name);
+
+ hash_new_table (101, &keyword_hash_table);
+ hash_new_table (101, &assign_hash_table);
+ hash_new_table (101, &vars);
+
+ sb_new (&label);
+
+ while ((opt = getopt_long (argc, argv, "I:sdhavc:upo:D:M", long_options,
+ (int *) NULL))
+ != EOF)
+ {
+ switch (opt)
+ {
+ case 'o':
+ out_name = optarg;
+ break;
+ case 'u':
+ unreasonable = 1;
+ break;
+ case 'I':
+ {
+ include_path *p = (include_path *) xmalloc (sizeof (include_path));
+ p->next = NULL;
+ sb_new (&p->path);
+ sb_add_string (&p->path, optarg);
+ if (paths_tail)
+ paths_tail->next = p;
+ else
+ paths_head = p;
+ paths_tail = p;
+ }
+ break;
+ case 'p':
+ print_line_number = 1;
+ break;
+ case 'c':
+ comment_char = optarg[0];
+ break;
+ case 'a':
+ alternate = 1;
+ break;
+ case 's':
+ copysource = 1;
+ break;
+ case 'd':
+ stats = 1;
+ break;
+ case 'D':
+ do_define (optarg);
+ break;
+ case 'M':
+ mri = 1;
+ comment_char = ';';
+ break;
+ case 'h':
+ show_help ();
+ /*NOTREACHED*/
+ case 'v':
+ /* This output is intended to follow the GNU standards document. */
+ printf (_("GNU assembler pre-processor %s\n"), program_version);
+ printf (_("Copyright 1996 Free Software Foundation, Inc.\n"));
+ printf (_("\
+This program is free software; you may redistribute it under the terms of\n\
+the GNU General Public License. This program has absolutely no warranty.\n"));
+ exit (0);
+ /*NOTREACHED*/
+ case 0:
+ break;
+ default:
+ show_usage (stderr, 1);
+ /*NOTREACHED*/
+ }
+ }
+
+ process_init ();
+
+ macro_init (alternate, mri, 0, exp_get_abs);
+
+ if (out_name) {
+ outfile = fopen (out_name, "w");
+ if (!outfile)
+ {
+ fprintf (stderr, _("%s: Can't open output file `%s'.\n"),
+ program_name, out_name);
+ exit (1);
+ }
+ }
+ else {
+ outfile = stdout;
+ }
+
+ chartype_init ();
+ if (!outfile)
+ outfile = stdout;
+
+ /* Process all the input files */
+
+ while (optind < argc)
+ {
+ if (new_file (argv[optind]))
+ {
+ process_file ();
+ }
+ else
+ {
+ fprintf (stderr, _("%s: Can't open input file `%s'.\n"),
+ program_name, argv[optind]);
+ exit (1);
+ }
+ optind++;
+ }
+
+ quit ();
+ return 0;
+}
+
+/* This function is used because an abort in some of the other files
+ may be compiled into as_abort because they include as.h. */
+
+void
+as_abort (file, line, fn)
+ const char *file, *fn;
+ int line;
+{
+ fprintf (stderr, _("Internal error, aborting at %s line %d"), file, line);
+ if (fn)
+ fprintf (stderr, " in %s", fn);
+ fprintf (stderr, _("\nPlease report this bug.\n"));
+ exit (1);
+}
diff --git a/gas/gdbinit.in b/gas/gdbinit.in
new file mode 100644
index 0000000000..e946726ec6
--- /dev/null
+++ b/gas/gdbinit.in
@@ -0,0 +1,39 @@
+dir @srcdir@
+dir .
+
+break as_warn
+break as_warn_where
+break as_bad
+break as_bad_where
+break as_fatal
+break as_perror
+break as_assert
+break as_abort
+
+define pe
+call print_expr ($)
+end
+
+document pe
+Print *$ as an expressionS, expanding parameters.
+end
+
+define ps
+call print_symbol_value ($)
+end
+
+document ps
+Print *$ as a symbolS, including expression value.
+end
+
+define pf
+call print_fixup ($)
+end
+
+document pf
+Print *$ as a fixS, including symbol value.
+end
+
+# Put this last, in case it fails.
+
+break abort
diff --git a/gas/hash.c b/gas/hash.c
new file mode 100644
index 0000000000..dccd660754
--- /dev/null
+++ b/gas/hash.c
@@ -0,0 +1,1028 @@
+/* hash.c - hash table lookup strings -
+ Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 1998
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * BUGS, GRIPES, APOLOGIA etc.
+ *
+ * A typical user doesn't need ALL this: I intend to make a library out
+ * of it one day - Dean Elsner.
+ * Also, I want to change the definition of a symbol to (address,length)
+ * so I can put arbitrary binary in the names stored. [see hsh.c for that]
+ *
+ * This slime is common coupled inside the module. Com-coupling (and other
+ * vandalism) was done to speed running time. The interfaces at the
+ * module's edges are adequately clean.
+ *
+ * There is no way to (a) run a test script through this heap and (b)
+ * compare results with previous scripts, to see if we have broken any
+ * code. Use GNU (f)utilities to do this. A few commands assist test.
+ * The testing is awkward: it tries to be both batch & interactive.
+ * For now, interactive rules!
+ */
+
+/*
+ * The idea is to implement a symbol table. A test jig is here.
+ * Symbols are arbitrary strings; they can't contain '\0'.
+ * [See hsh.c for a more general symbol flavour.]
+ * Each symbol is associated with a char*, which can point to anything
+ * you want, allowing an arbitrary property list for each symbol.
+ *
+ * The basic operations are:
+ *
+ * new creates symbol table, returns handle
+ * find (symbol) returns char*
+ * insert (symbol,char*) error if symbol already in table
+ * delete (symbol) returns char* if symbol was in table
+ * apply so you can delete all symbols before die()
+ * die destroy symbol table (free up memory)
+ *
+ * Supplementary functions include:
+ *
+ * say how big? what % full?
+ * replace (symbol,newval) report previous value
+ * jam (symbol,value) assert symbol:=value
+ *
+ * You, the caller, have control over errors: this just reports them.
+ *
+ * This package requires malloc(), free().
+ * Malloc(size) returns NULL or address of char[size].
+ * Free(address) frees same.
+ */
+
+/*
+ * The code and its structures are re-enterent.
+ *
+ * Before you do anything else, you must call hash_new() which will
+ * return the address of a hash-table-control-block. You then use
+ * this address as a handle of the symbol table by passing it to all
+ * the other hash_...() functions. The only approved way to recover
+ * the memory used by the symbol table is to call hash_die() with the
+ * handle of the symbol table.
+ *
+ * Before you call hash_die() you normally delete anything pointed to
+ * by individual symbols. After hash_die() you can't use that symbol
+ * table again.
+ *
+ * The char* you associate with a symbol may not be NULL (0) because
+ * NULL is returned whenever a symbol is not in the table. Any other
+ * value is OK, except DELETED, #defined below.
+ *
+ * When you supply a symbol string for insertion, YOU MUST PRESERVE THE
+ * STRING until that symbol is deleted from the table. The reason is that
+ * only the address you supply, NOT the symbol string itself, is stored
+ * in the symbol table.
+ *
+ * You may delete and add symbols arbitrarily.
+ * Any or all symbols may have the same 'value' (char *). In fact, these
+ * routines don't do anything with your symbol values.
+ *
+ * You have no right to know where the symbol:char* mapping is stored,
+ * because it moves around in memory; also because we may change how it
+ * works and we don't want to break your code do we? However the handle
+ * (address of struct hash_control) is never changed in
+ * the life of the symbol table.
+ *
+ * What you CAN find out about a symbol table is:
+ * how many slots are in the hash table?
+ * how many slots are filled with symbols?
+ * (total hashes,collisions) for (reads,writes) (*)
+ * All of the above values vary in time.
+ * (*) some of these numbers will not be meaningful if we change the
+ * internals. */
+
+/*
+ * I N T E R N A L
+ *
+ * Hash table is an array of hash_entries; each entry is a pointer to a
+ * a string and a user-supplied value 1 char* wide.
+ *
+ * The array always has 2 ** n elements, n>0, n integer.
+ * There is also a 'wall' entry after the array, which is always empty
+ * and acts as a sentinel to stop running off the end of the array.
+ * When the array gets too full, we create a new array twice as large
+ * and re-hash the symbols into the new array, then forget the old array.
+ * (Of course, we copy the values into the new array before we junk the
+ * old array!)
+ *
+ */
+
+#include <stdio.h>
+
+#ifndef FALSE
+#define FALSE (0)
+#define TRUE (!FALSE)
+#endif /* no FALSE yet */
+
+#include <ctype.h>
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+#include "as.h"
+
+#define error as_fatal
+
+static char _deleted_[1];
+#define DELETED ((PTR)_deleted_) /* guarenteed unique address */
+#define START_POWER (10) /* power of two: size of new hash table */
+
+/* TRUE if a symbol is in entry @ ptr. */
+#define islive(ptr) (ptr->hash_string && ptr->hash_string!=DELETED)
+
+enum stat_enum {
+ /* Number of slots in hash table. The wall does not count here.
+ We expect this is always a power of 2. */
+ STAT_SIZE = 0,
+ /* Number of hash_ask calls. */
+ STAT_ACCESS,
+ STAT_ACCESS_w,
+ /* Number of collisions (total). This may exceed STAT_ACCESS if we
+ have lots of collisions/access. */
+ STAT_COLLIDE,
+ STAT_COLLIDE_w,
+ /* Slots used right now. */
+ STAT_USED,
+ /* How many string compares? */
+ STAT_STRCMP,
+ STAT_STRCMP_w,
+ /* Size of statistics block... this must be last. */
+ STATLENGTH
+};
+#define STAT__READ (0) /* reading */
+#define STAT__WRITE (1) /* writing */
+
+/* When we grow a hash table, by what power of two do we increase it? */
+#define GROW_FACTOR 1
+/* When should we grow it? */
+#define FULL_VALUE(N) ((N) / 2)
+
+/* #define SUSPECT to do runtime checks */
+/* #define TEST to be a test jig for hash...() */
+
+#ifdef TEST
+/* TEST: use smaller hash table */
+#undef START_POWER
+#define START_POWER (3)
+#undef START_SIZE
+#define START_SIZE (8)
+#undef START_FULL
+#define START_FULL (4)
+#endif
+
+struct hash_entry
+{
+ const char *hash_string; /* points to where the symbol string is */
+ /* NULL means slot is not used */
+ /* DELETED means slot was deleted */
+ PTR hash_value; /* user's datum, associated with symbol */
+ unsigned long h;
+};
+
+struct hash_control {
+ struct hash_entry *hash_where;/* address of hash table */
+ int hash_sizelog; /* Log of ( hash_mask + 1 ) */
+ int hash_mask; /* masks a hash into index into table */
+ int hash_full; /* when hash_stat[STAT_USED] exceeds this, */
+ /* grow table */
+ struct hash_entry *hash_wall; /* point just after last (usable) entry */
+ /* here we have some statistics */
+ int hash_stat[STATLENGTH]; /* lies & statistics */
+};
+
+/*------------------ plan ---------------------------------- i = internal
+
+ struct hash_control * c;
+ struct hash_entry * e; i
+ int b[z]; buffer for statistics
+ z size of b
+ char * s; symbol string (address) [ key ]
+ char * v; value string (address) [datum]
+ boolean f; TRUE if we found s in hash table i
+ char * t; error string; 0 means OK
+ int a; access type [0...n) i
+
+ c=hash_new () create new hash_control
+
+ hash_die (c) destroy hash_control (and hash table)
+ table should be empty.
+ doesn't check if table is empty.
+ c has no meaning after this.
+
+ hash_say (c,b,z) report statistics of hash_control.
+ also report number of available statistics.
+
+ v=hash_delete (c,s) delete symbol, return old value if any.
+ ask() NULL means no old value.
+ f
+
+ v=hash_replace (c,s,v) replace old value of s with v.
+ ask() NULL means no old value: no table change.
+ f
+
+ t=hash_insert (c,s,v) insert (s,v) in c.
+ ask() return error string.
+ f it is an error to insert if s is already
+ in table.
+ if any error, c is unchanged.
+
+ t=hash_jam (c,s,v) assert that new value of s will be v. i
+ ask() it may decide to GROW the table. i
+ f i
+ grow() i
+ t=hash_grow (c) grow the hash table. i
+ jam() will invoke JAM. i
+
+ ?=hash_apply (c,y) apply y() to every symbol in c.
+ y evtries visited in 'unspecified' order.
+
+ v=hash_find (c,s) return value of s, or NULL if s not in c.
+ ask()
+ f
+
+ f,e=hash_ask() (c,s,a) return slot where s SHOULD live. i
+ code() maintain collision stats in c. i
+
+ .=hash_code (c,s) compute hash-code for s, i
+ from parameters of c. i
+
+ */
+
+/* Returned by hash_ask() to stop extra testing. hash_ask() wants to
+ return both a slot and a status. This is the status. TRUE: found
+ symbol FALSE: absent: empty or deleted slot Also returned by
+ hash_jam(). TRUE: we replaced a value FALSE: we inserted a value. */
+static char hash_found;
+
+static struct hash_entry *hash_ask PARAMS ((struct hash_control *,
+ const char *, int));
+static int hash_code PARAMS ((struct hash_control *, const char *));
+static const char *hash_grow PARAMS ((struct hash_control *));
+
+/* Create a new hash table. Return NULL if failed; otherwise return handle
+ (address of struct hash). */
+struct hash_control *
+hash_new ()
+{
+ struct hash_control *retval;
+ struct hash_entry *room; /* points to hash table */
+ struct hash_entry *wall;
+ struct hash_entry *entry;
+ int *ip; /* scan stats block of struct hash_control */
+ int *nd; /* limit of stats block */
+
+ room = (struct hash_entry *) xmalloc (sizeof (struct hash_entry)
+ /* +1 for the wall entry */
+ * ((1 << START_POWER) + 1));
+ retval = (struct hash_control *) xmalloc (sizeof (struct hash_control));
+
+ nd = retval->hash_stat + STATLENGTH;
+ for (ip = retval->hash_stat; ip < nd; ip++)
+ *ip = 0;
+
+ retval->hash_stat[STAT_SIZE] = 1 << START_POWER;
+ retval->hash_mask = (1 << START_POWER) - 1;
+ retval->hash_sizelog = START_POWER;
+ /* works for 1's compl ok */
+ retval->hash_where = room;
+ retval->hash_wall =
+ wall = room + (1 << START_POWER);
+ retval->hash_full = FULL_VALUE (1 << START_POWER);
+ for (entry = room; entry <= wall; entry++)
+ entry->hash_string = NULL;
+ return retval;
+}
+
+/*
+ * h a s h _ d i e ( )
+ *
+ * Table should be empty, but this is not checked.
+ * To empty the table, try hash_apply()ing a symbol deleter.
+ * Return to free memory both the hash table and it's control
+ * block.
+ * 'handle' has no meaning after this function.
+ * No errors are recoverable.
+ */
+void
+hash_die (handle)
+ struct hash_control *handle;
+{
+ free ((char *) handle->hash_where);
+ free ((char *) handle);
+}
+
+#ifdef TEST
+/*
+ * h a s h _ s a y ( )
+ *
+ * Return the size of the statistics table, and as many statistics as
+ * we can until either (a) we have run out of statistics or (b) caller
+ * has run out of buffer.
+ * NOTE: hash_say treats all statistics alike.
+ * These numbers may change with time, due to insertions, deletions
+ * and expansions of the table.
+ * The first "statistic" returned is the length of hash_stat[].
+ * Then contents of hash_stat[] are read out (in ascending order)
+ * until your buffer or hash_stat[] is exausted.
+ */
+static void
+hash_say (handle, buffer, bufsiz)
+ struct hash_control *handle;
+ int buffer[ /*bufsiz*/ ];
+ int bufsiz;
+{
+ int *nd; /* limit of statistics block */
+ int *ip; /* scan statistics */
+
+ ip = handle->hash_stat;
+ nd = ip + min (bufsiz - 1, STATLENGTH);
+ if (bufsiz > 0) /* trust nothing! bufsiz<=0 is dangerous */
+ {
+ *buffer++ = STATLENGTH;
+ for (; ip < nd; ip++, buffer++)
+ {
+ *buffer = *ip;
+ }
+ }
+}
+#endif
+
+/*
+ * h a s h _ d e l e t e ( )
+ *
+ * Try to delete a symbol from the table.
+ * If it was there, return its value (and adjust STAT_USED).
+ * Otherwise, return NULL.
+ * Anyway, the symbol is not present after this function.
+ *
+ */
+PTR /* NULL if string not in table, else */
+/* returns value of deleted symbol */
+hash_delete (handle, string)
+ struct hash_control *handle;
+ const char *string;
+{
+ PTR retval;
+ struct hash_entry *entry;
+
+ entry = hash_ask (handle, string, STAT__WRITE);
+ if (hash_found)
+ {
+ retval = entry->hash_value;
+ entry->hash_string = DELETED;
+ handle->hash_stat[STAT_USED] -= 1;
+#ifdef SUSPECT
+ if (handle->hash_stat[STAT_USED] < 0)
+ {
+ error ("hash_delete");
+ }
+#endif /* def SUSPECT */
+ }
+ else
+ {
+ retval = NULL;
+ }
+ return (retval);
+}
+
+/*
+ * h a s h _ r e p l a c e ( )
+ *
+ * Try to replace the old value of a symbol with a new value.
+ * Normally return the old value.
+ * Return NULL and don't change the table if the symbol is not already
+ * in the table.
+ */
+PTR
+hash_replace (handle, string, value)
+ struct hash_control *handle;
+ const char *string;
+ PTR value;
+{
+ struct hash_entry *entry;
+ char *retval;
+
+ entry = hash_ask (handle, string, STAT__WRITE);
+ if (hash_found)
+ {
+ retval = entry->hash_value;
+ entry->hash_value = value;
+ }
+ else
+ {
+ retval = NULL;
+ }
+ ;
+ return retval;
+}
+
+/*
+ * h a s h _ i n s e r t ( )
+ *
+ * Insert a (symbol-string, value) into the hash table.
+ * Return an error string, 0 means OK.
+ * It is an 'error' to insert an existing symbol.
+ */
+
+const char * /* return error string */
+hash_insert (handle, string, value)
+ struct hash_control *handle;
+ const char *string;
+ PTR value;
+{
+ struct hash_entry *entry;
+ const char *retval;
+
+ retval = 0;
+ if (handle->hash_stat[STAT_USED] > handle->hash_full)
+ {
+ retval = hash_grow (handle);
+ }
+ if (!retval)
+ {
+ entry = hash_ask (handle, string, STAT__WRITE);
+ if (hash_found)
+ {
+ retval = "exists";
+ }
+ else
+ {
+ entry->hash_value = value;
+ entry->hash_string = string;
+ handle->hash_stat[STAT_USED] += 1;
+ }
+ }
+ return retval;
+}
+
+/*
+ * h a s h _ j a m ( )
+ *
+ * Regardless of what was in the symbol table before, after hash_jam()
+ * the named symbol has the given value. The symbol is either inserted or
+ * (its value is) replaced.
+ * An error message string is returned, 0 means OK.
+ *
+ * WARNING: this may decide to grow the hashed symbol table.
+ * To do this, we call hash_grow(), WHICH WILL recursively CALL US.
+ *
+ * We report status internally: hash_found is TRUE if we replaced, but
+ * false if we inserted.
+ */
+const char *
+hash_jam (handle, string, value)
+ struct hash_control *handle;
+ const char *string;
+ PTR value;
+{
+ const char *retval;
+ struct hash_entry *entry;
+
+ retval = 0;
+ if (handle->hash_stat[STAT_USED] > handle->hash_full)
+ {
+ retval = hash_grow (handle);
+ }
+ if (!retval)
+ {
+ entry = hash_ask (handle, string, STAT__WRITE);
+ if (!hash_found)
+ {
+ entry->hash_string = string;
+ handle->hash_stat[STAT_USED] += 1;
+ }
+ entry->hash_value = value;
+ }
+ return retval;
+}
+
+/*
+ * h a s h _ g r o w ( )
+ *
+ * Grow a new (bigger) hash table from the old one.
+ * We choose to double the hash table's size.
+ * Return a human-scrutible error string: 0 if OK.
+ * Warning! This uses hash_jam(), which had better not recurse
+ * back here! Hash_jam() conditionally calls us, but we ALWAYS
+ * call hash_jam()!
+ * Internal.
+ */
+static const char *
+hash_grow (handle) /* make a hash table grow */
+ struct hash_control *handle;
+{
+ struct hash_entry *newwall;
+ struct hash_entry *newwhere;
+ struct hash_entry *newtrack;
+ struct hash_entry *oldtrack;
+ struct hash_entry *oldwhere;
+ struct hash_entry *oldwall;
+ int temp;
+ int newsize;
+ const char *string;
+ const char *retval;
+#ifdef SUSPECT
+ int oldused;
+#endif
+
+ /*
+ * capture info about old hash table
+ */
+ oldwhere = handle->hash_where;
+ oldwall = handle->hash_wall;
+#ifdef SUSPECT
+ oldused = handle->hash_stat[STAT_USED];
+#endif
+ /*
+ * attempt to get enough room for a hash table twice as big
+ */
+ temp = handle->hash_stat[STAT_SIZE];
+ newwhere = ((struct hash_entry *)
+ xmalloc ((unsigned long) ((temp << (GROW_FACTOR + 1))
+ /* +1 for wall slot */
+ * sizeof (struct hash_entry))));
+ if (newwhere == NULL)
+ return "no_room";
+
+ /*
+ * have enough room: now we do all the work.
+ * double the size of everything in handle.
+ */
+ handle->hash_mask = ((handle->hash_mask + 1) << GROW_FACTOR) - 1;
+ handle->hash_stat[STAT_SIZE] <<= GROW_FACTOR;
+ newsize = handle->hash_stat[STAT_SIZE];
+ handle->hash_where = newwhere;
+ handle->hash_full <<= GROW_FACTOR;
+ handle->hash_sizelog += GROW_FACTOR;
+ handle->hash_wall = newwall = newwhere + newsize;
+ /* Set all those pesky new slots to vacant. */
+ for (newtrack = newwhere; newtrack <= newwall; newtrack++)
+ newtrack->hash_string = NULL;
+ /* We will do a scan of the old table, the hard way, using the
+ * new control block to re-insert the data into new hash table. */
+ handle->hash_stat[STAT_USED] = 0;
+ for (oldtrack = oldwhere; oldtrack < oldwall; oldtrack++)
+ if (((string = oldtrack->hash_string) != NULL) && string != DELETED)
+ if ((retval = hash_jam (handle, string, oldtrack->hash_value)))
+ return retval;
+
+#ifdef SUSPECT
+ if (handle->hash_stat[STAT_USED] != oldused)
+ return "hash_used";
+#endif
+
+ /* We have a completely faked up control block.
+ Return the old hash table. */
+ free ((char *) oldwhere);
+
+ return 0;
+}
+
+#ifdef TEST
+/*
+ * h a s h _ a p p l y ( )
+ *
+ * Use this to scan each entry in symbol table.
+ * For each symbol, this calls (applys) a nominated function supplying the
+ * symbol's value (and the symbol's name).
+ * The idea is you use this to destroy whatever is associted with
+ * any values in the table BEFORE you destroy the table with hash_die.
+ * Of course, you can use it for other jobs; whenever you need to
+ * visit all extant symbols in the table.
+ *
+ * We choose to have a call-you-back idea for two reasons:
+ * asthetic: it is a neater idea to use apply than an explicit loop
+ * sensible: if we ever had to grow the symbol table (due to insertions)
+ * then we would lose our place in the table when we re-hashed
+ * symbols into the new table in a different order.
+ *
+ * The order symbols are visited depends entirely on the hashing function.
+ * Whenever you insert a (symbol, value) you risk expanding the table. If
+ * you do expand the table, then the hashing function WILL change, so you
+ * MIGHT get a different order of symbols visited. In other words, if you
+ * want the same order of visiting symbols as the last time you used
+ * hash_apply() then you better not have done any hash_insert()s or
+ * hash_jam()s since the last time you used hash_apply().
+ *
+ * In future we may use the value returned by your nominated function.
+ * One idea is to abort the scan if, after applying the function to a
+ * certain node, the function returns a certain code.
+ *
+ * The function you supply should be of the form:
+ * void myfunct(string,value)
+ * char * string; |* the symbol's name *|
+ * char * value; |* the symbol's value *|
+ * {
+ * |* ... *|
+ * }
+ *
+ */
+void
+hash_apply (handle, function)
+ struct hash_control *handle;
+ void (*function) ();
+{
+ struct hash_entry *entry;
+ struct hash_entry *wall;
+
+ wall = handle->hash_wall;
+ for (entry = handle->hash_where; entry < wall; entry++)
+ {
+ if (islive (entry)) /* silly code: tests entry->string twice! */
+ {
+ (*function) (entry->hash_string, entry->hash_value);
+ }
+ }
+}
+#endif
+
+/*
+ * h a s h _ f i n d ( )
+ *
+ * Given symbol string, find value (if any).
+ * Return found value or NULL.
+ */
+PTR
+hash_find (handle, string)
+ struct hash_control *handle;
+ const char *string;
+{
+ struct hash_entry *entry;
+
+ entry = hash_ask (handle, string, STAT__READ);
+ if (hash_found)
+ return entry->hash_value;
+ else
+ return NULL;
+}
+
+/*
+ * h a s h _ a s k ( )
+ *
+ * Searches for given symbol string.
+ * Return the slot where it OUGHT to live. It may be there.
+ * Return hash_found: TRUE only if symbol is in that slot.
+ * Access argument is to help keep statistics in control block.
+ * Internal.
+ */
+static struct hash_entry * /* string slot, may be empty or deleted */
+hash_ask (handle, string, access_type)
+ struct hash_control *handle;
+ const char *string;
+ int access_type;
+{
+ const char *s;
+ struct hash_entry *slot;
+ int collision; /* count collisions */
+ int strcmps;
+ int hcode;
+
+ /* start looking here */
+ hcode = hash_code (handle, string);
+ slot = handle->hash_where + (hcode & handle->hash_mask);
+
+ handle->hash_stat[STAT_ACCESS + access_type] += 1;
+ collision = strcmps = 0;
+ hash_found = FALSE;
+ while (((s = slot->hash_string) != NULL) && s != DELETED)
+ {
+ if (string == s)
+ {
+ hash_found = TRUE;
+ break;
+ }
+ if (slot->h == (unsigned long) hcode)
+ {
+ if (!strcmp (string, s))
+ {
+ hash_found = TRUE;
+ break;
+ }
+ strcmps++;
+ }
+ collision++;
+ slot++;
+ }
+ /*
+ * slot: return:
+ * in use: we found string slot
+ * at empty:
+ * at wall: we fell off: wrap round ????
+ * in table: dig here slot
+ * at DELETED: dig here slot
+ */
+ if (slot == handle->hash_wall)
+ {
+ slot = handle->hash_where;/* now look again */
+ while (((s = slot->hash_string) != NULL) && s != DELETED)
+ {
+ if (string == s)
+ {
+ hash_found = TRUE;
+ break;
+ }
+ if (slot->h == (unsigned long) hcode)
+ {
+ if (!strcmp (string, s))
+ {
+ hash_found = TRUE;
+ break;
+ }
+ strcmps++;
+ }
+ collision++;
+ slot++;
+ }
+ /*
+ * slot: return:
+ * in use: we found it slot
+ * empty: wall: ERROR IMPOSSIBLE !!!!
+ * in table: dig here slot
+ * DELETED:dig here slot
+ */
+ }
+ handle->hash_stat[STAT_COLLIDE + access_type] += collision;
+ handle->hash_stat[STAT_STRCMP + access_type] += strcmps;
+ if (!hash_found)
+ slot->h = hcode;
+ return slot; /* also return hash_found */
+}
+
+/*
+ * h a s h _ c o d e
+ *
+ * Does hashing of symbol string to hash number.
+ * Internal.
+ */
+static int
+hash_code (handle, string)
+ struct hash_control *handle;
+ const char *string;
+{
+#if 1 /* There seems to be some interesting property of this function
+ that prevents the bfd version below from being an adequate
+ substitute. @@ Figure out what this property is! */
+ long h; /* hash code built here */
+ long c; /* each character lands here */
+ int n; /* Amount to shift h by */
+
+ n = (handle->hash_sizelog - 3);
+ h = 0;
+ while ((c = *string++) != 0)
+ {
+ h += c;
+ h = (h << 3) + (h >> n) + c;
+ }
+ return h;
+#else
+ /* from bfd */
+ unsigned long h = 0;
+ unsigned int len = 0;
+ unsigned int c;
+
+ while ((c = *string++) != 0)
+ {
+ h += c + (c << 17);
+ h ^= h >> 2;
+ ++len;
+ }
+ h += len + (len << 17);
+ h ^= h >> 2;
+ return h;
+#endif
+}
+
+void
+hash_print_statistics (file, name, h)
+ FILE *file;
+ const char *name;
+ struct hash_control *h;
+{
+ unsigned long sz, used, pct;
+
+ if (h == 0)
+ return;
+
+ sz = h->hash_stat[STAT_SIZE];
+ used = h->hash_stat[STAT_USED];
+ pct = (used * 100 + sz / 2) / sz;
+
+ fprintf (file, "%s hash statistics:\n\t%lu/%lu slots used (%lu%%)\n",
+ name, used, sz, pct);
+
+#define P(name, off) \
+ fprintf (file, "\t%-16s %6dr + %6dw = %7d\n", name, \
+ h->hash_stat[off+STAT__READ], \
+ h->hash_stat[off+STAT__WRITE], \
+ h->hash_stat[off+STAT__READ] + h->hash_stat[off+STAT__WRITE])
+
+ P ("accesses:", STAT_ACCESS);
+ P ("collisions:", STAT_COLLIDE);
+ P ("string compares:", STAT_STRCMP);
+
+#undef P
+}
+
+/*
+ * Here is a test program to exercise above.
+ */
+#ifdef TEST
+
+#define TABLES (6) /* number of hash tables to maintain */
+/* (at once) in any testing */
+#define STATBUFSIZE (12) /* we can have 12 statistics */
+
+int statbuf[STATBUFSIZE]; /* display statistics here */
+char answer[100]; /* human farts here */
+char *hashtable[TABLES]; /* we test many hash tables at once */
+char *h; /* points to curent hash_control */
+char **pp;
+char *p;
+char *name;
+char *value;
+int size;
+int used;
+char command;
+int number; /* number 0:TABLES-1 of current hashed */
+/* symbol table */
+
+main ()
+{
+ void applicatee ();
+ void destroy ();
+ char *what ();
+ int *ip;
+
+ number = 0;
+ h = 0;
+ printf ("type h <RETURN> for help\n");
+ for (;;)
+ {
+ printf ("hash_test command: ");
+ gets (answer);
+ command = answer[0];
+ if (isupper (command))
+ command = tolower (command); /* ecch! */
+ switch (command)
+ {
+ case '#':
+ printf ("old hash table #=%d.\n", number);
+ whattable ();
+ break;
+ case '?':
+ for (pp = hashtable; pp < hashtable + TABLES; pp++)
+ {
+ printf ("address of hash table #%d control block is %xx\n"
+ ,pp - hashtable, *pp);
+ }
+ break;
+ case 'a':
+ hash_apply (h, applicatee);
+ break;
+ case 'd':
+ hash_apply (h, destroy);
+ hash_die (h);
+ break;
+ case 'f':
+ p = hash_find (h, name = what ("symbol"));
+ printf ("value of \"%s\" is \"%s\"\n", name, p ? p : "NOT-PRESENT");
+ break;
+ case 'h':
+ printf ("# show old, select new default hash table number\n");
+ printf ("? display all hashtable control block addresses\n");
+ printf ("a apply a simple display-er to each symbol in table\n");
+ printf ("d die: destroy hashtable\n");
+ printf ("f find value of nominated symbol\n");
+ printf ("h this help\n");
+ printf ("i insert value into symbol\n");
+ printf ("j jam value into symbol\n");
+ printf ("n new hashtable\n");
+ printf ("r replace a value with another\n");
+ printf ("s say what %% of table is used\n");
+ printf ("q exit this program\n");
+ printf ("x delete a symbol from table, report its value\n");
+ break;
+ case 'i':
+ p = hash_insert (h, name = what ("symbol"), value = what ("value"));
+ if (p)
+ {
+ printf ("symbol=\"%s\" value=\"%s\" error=%s\n", name, value,
+ p);
+ }
+ break;
+ case 'j':
+ p = hash_jam (h, name = what ("symbol"), value = what ("value"));
+ if (p)
+ {
+ printf ("symbol=\"%s\" value=\"%s\" error=%s\n", name, value, p);
+ }
+ break;
+ case 'n':
+ h = hashtable[number] = (char *) hash_new ();
+ break;
+ case 'q':
+ exit (EXIT_SUCCESS);
+ case 'r':
+ p = hash_replace (h, name = what ("symbol"), value = what ("value"));
+ printf ("old value was \"%s\"\n", p ? p : "{}");
+ break;
+ case 's':
+ hash_say (h, statbuf, STATBUFSIZE);
+ for (ip = statbuf; ip < statbuf + STATBUFSIZE; ip++)
+ {
+ printf ("%d ", *ip);
+ }
+ printf ("\n");
+ break;
+ case 'x':
+ p = hash_delete (h, name = what ("symbol"));
+ printf ("old value was \"%s\"\n", p ? p : "{}");
+ break;
+ default:
+ printf ("I can't understand command \"%c\"\n", command);
+ break;
+ }
+ }
+}
+
+char *
+what (description)
+ char *description;
+{
+ char *retval;
+ char *malloc ();
+
+ printf (" %s : ", description);
+ gets (answer);
+ /* will one day clean up answer here */
+ retval = malloc (strlen (answer) + 1);
+ if (!retval)
+ {
+ error ("room");
+ }
+ (void) strcpy (retval, answer);
+ return (retval);
+}
+
+void
+destroy (string, value)
+ char *string;
+ char *value;
+{
+ free (string);
+ free (value);
+}
+
+
+void
+applicatee (string, value)
+ char *string;
+ char *value;
+{
+ printf ("%.20s-%.20s\n", string, value);
+}
+
+whattable () /* determine number: what hash table to use */
+ /* also determine h: points to hash_control */
+{
+
+ for (;;)
+ {
+ printf (" what hash table (%d:%d) ? ", 0, TABLES - 1);
+ gets (answer);
+ sscanf (answer, "%d", &number);
+ if (number >= 0 && number < TABLES)
+ {
+ h = hashtable[number];
+ if (!h)
+ {
+ printf ("warning: current hash-table-#%d. has no hash-control\n", number);
+ }
+ return;
+ }
+ else
+ {
+ printf ("invalid hash table number: %d\n", number);
+ }
+ }
+}
+
+
+
+#endif /* #ifdef TEST */
+
+/* end of hash.c */
diff --git a/gas/hash.h b/gas/hash.h
new file mode 100644
index 0000000000..fb229c8086
--- /dev/null
+++ b/gas/hash.h
@@ -0,0 +1,45 @@
+/* hash.h - for hash.c
+ Copyright (C) 1987, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef hashH
+#define hashH
+
+struct hash_control;
+
+/* returns control block */
+struct hash_control *hash_new PARAMS ((void));
+void hash_die PARAMS ((struct hash_control *));
+/* returns previous value */
+PTR hash_delete PARAMS ((struct hash_control *, const char *str));
+/* returns previous value */
+PTR hash_replace PARAMS ((struct hash_control *, const char *str, PTR val));
+/* returns error string or null */
+const char *hash_insert PARAMS ((struct hash_control *, const char *str,
+ PTR val));
+/* returns value */
+PTR hash_find PARAMS ((struct hash_control *, const char *str));
+/* returns error text or null (internal) */
+const char *hash_jam PARAMS ((struct hash_control *, const char *str,
+ PTR val));
+
+void hash_print_statistics PARAMS ((FILE *, const char *,
+ struct hash_control *));
+#endif /* #ifdef hashH */
+
+/* end of hash.c */
diff --git a/gas/input-file.c b/gas/input-file.c
new file mode 100644
index 0000000000..c63f7c9b63
--- /dev/null
+++ b/gas/input-file.c
@@ -0,0 +1,248 @@
+/* input_file.c - Deal with Input Files -
+ Copyright (C) 1987, 1990, 1991, 1992, 1998 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * Confines all details of reading source bytes to this module.
+ * All O/S specific crocks should live here.
+ * What we lose in "efficiency" we gain in modularity.
+ * Note we don't need to #include the "as.h" file. No common coupling!
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "as.h"
+#include "input-file.h"
+
+static int input_file_get PARAMS ((char **));
+
+/* This variable is non-zero if the file currently being read should be
+ preprocessed by app. It is zero if the file can be read straight in.
+ */
+int preprocess = 0;
+
+/*
+ * This code opens a file, then delivers BUFFER_SIZE character
+ * chunks of the file on demand.
+ * BUFFER_SIZE is supposed to be a number chosen for speed.
+ * The caller only asks once what BUFFER_SIZE is, and asks before
+ * the nature of the input files (if any) is known.
+ */
+
+#define BUFFER_SIZE (32 * 1024)
+
+/*
+ * We use static data: the data area is not sharable.
+ */
+
+static FILE *f_in;
+static char *file_name;
+
+/* Struct for saving the state of this module for file includes. */
+struct saved_file
+ {
+ FILE *f_in;
+ char *file_name;
+ int preprocess;
+ char *app_save;
+ };
+
+/* These hooks accomodate most operating systems. */
+
+void
+input_file_begin ()
+{
+ f_in = (FILE *) 0;
+}
+
+void
+input_file_end ()
+{
+}
+
+/* Return BUFFER_SIZE. */
+unsigned int
+input_file_buffer_size ()
+{
+ return (BUFFER_SIZE);
+}
+
+int
+input_file_is_open ()
+{
+ return f_in != (FILE *) 0;
+}
+
+/* Push the state of our input, returning a pointer to saved info that
+ can be restored with input_file_pop (). */
+char *
+input_file_push ()
+{
+ register struct saved_file *saved;
+
+ saved = (struct saved_file *) xmalloc (sizeof *saved);
+
+ saved->f_in = f_in;
+ saved->file_name = file_name;
+ saved->preprocess = preprocess;
+ if (preprocess)
+ saved->app_save = app_push ();
+
+ input_file_begin (); /* Initialize for new file */
+
+ return (char *) saved;
+}
+
+void
+input_file_pop (arg)
+ char *arg;
+{
+ register struct saved_file *saved = (struct saved_file *) arg;
+
+ input_file_end (); /* Close out old file */
+
+ f_in = saved->f_in;
+ file_name = saved->file_name;
+ preprocess = saved->preprocess;
+ if (preprocess)
+ app_pop (saved->app_save);
+
+ free (arg);
+}
+
+void
+input_file_open (filename, pre)
+ char *filename; /* "" means use stdin. Must not be 0. */
+ int pre;
+{
+ int c;
+ char buf[80];
+
+ preprocess = pre;
+
+ assert (filename != 0); /* Filename may not be NULL. */
+ if (filename[0])
+ { /* We have a file name. Suck it and see. */
+ f_in = fopen (filename, "r");
+ file_name = filename;
+ }
+ else
+ { /* use stdin for the input file. */
+ f_in = stdin;
+ file_name = _("{standard input}"); /* For error messages. */
+ }
+ if (f_in == (FILE *) 0)
+ {
+ as_bad (_("Can't open %s for reading."), file_name);
+ as_perror ("%s", file_name);
+ return;
+ }
+
+ c = getc (f_in);
+ if (c == '#')
+ { /* Begins with comment, may not want to preprocess */
+ c = getc (f_in);
+ if (c == 'N')
+ {
+ fgets (buf, 80, f_in);
+ if (!strcmp (buf, "O_APP\n"))
+ preprocess = 0;
+ if (!strchr (buf, '\n'))
+ ungetc ('#', f_in); /* It was longer */
+ else
+ ungetc ('\n', f_in);
+ }
+ else if (c == '\n')
+ ungetc ('\n', f_in);
+ else
+ ungetc ('#', f_in);
+ }
+ else
+ ungetc (c, f_in);
+}
+
+/* Close input file. */
+void
+input_file_close ()
+{
+ if (f_in != NULL)
+ {
+ fclose (f_in);
+ } /* don't close a null file pointer */
+ f_in = 0;
+} /* input_file_close() */
+
+/* This function is passed to do_scrub_chars. */
+
+static int
+input_file_get (from)
+ char **from;
+{
+ static char buf[BUFFER_SIZE];
+ int size;
+
+ size = fread (buf, sizeof (char), sizeof buf, f_in);
+ if (size < 0)
+ {
+ as_perror (_("Can't read from %s"), file_name);
+ size = 0;
+ }
+ *from = buf;
+ return size;
+}
+
+/* Read a buffer from the input file. */
+
+char *
+input_file_give_next_buffer (where)
+ char *where; /* Where to place 1st character of new buffer. */
+{
+ char *return_value; /* -> Last char of what we read, + 1. */
+ register int size;
+
+ if (f_in == (FILE *) 0)
+ return 0;
+ /*
+ * fflush (stdin); could be done here if you want to synchronise
+ * stdin and stdout, for the case where our input file is stdin.
+ * Since the assembler shouldn't do any output to stdout, we
+ * don't bother to synch output and input.
+ */
+ if (preprocess)
+ size = do_scrub_chars (input_file_get, where, BUFFER_SIZE);
+ else
+ size = fread (where, sizeof (char), BUFFER_SIZE, f_in);
+ if (size < 0)
+ {
+ as_perror (_("Can't read from %s"), file_name);
+ size = 0;
+ }
+ if (size)
+ return_value = where + size;
+ else
+ {
+ if (fclose (f_in))
+ as_perror (_("Can't close %s"), file_name);
+ f_in = (FILE *) 0;
+ return_value = 0;
+ }
+ return (return_value);
+}
+
+/* end of input-file.c */
diff --git a/gas/input-file.h b/gas/input-file.h
new file mode 100644
index 0000000000..129bf2821d
--- /dev/null
+++ b/gas/input-file.h
@@ -0,0 +1,68 @@
+/* input_file.h header for input-file.c
+ Copyright (C) 1987, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*"input_file.c":Operating-system dependant functions to read source files.*/
+
+
+/*
+ * No matter what the operating system, this module must provide the
+ * following services to its callers.
+ *
+ * input_file_begin() Call once before anything else.
+ *
+ * input_file_end() Call once after everything else.
+ *
+ * input_file_buffer_size() Call anytime. Returns largest possible
+ * delivery from
+ * input_file_give_next_buffer().
+ *
+ * input_file_open(name) Call once for each input file.
+ *
+ * input_file_give_next_buffer(where) Call once to get each new buffer.
+ * Return 0: no more chars left in file,
+ * the file has already been closed.
+ * Otherwise: return a pointer to just
+ * after the last character we read
+ * into the buffer.
+ * If we can only read 0 characters, then
+ * end-of-file is faked.
+ *
+ * input_file_push() Push state, which can be restored
+ * later. Does implicit input_file_begin.
+ * Returns char * to saved state.
+ *
+ * input_file_pop (arg) Pops previously saved state.
+ *
+ * input_file_close () Closes opened file.
+ *
+ * All errors are reported (using as_perror) so caller doesn't have to think
+ * about I/O errors. No I/O errors are fatal: an end-of-file may be faked.
+ */
+
+char *input_file_give_next_buffer PARAMS ((char *where));
+char *input_file_push PARAMS ((void));
+unsigned int input_file_buffer_size PARAMS ((void));
+int input_file_is_open PARAMS ((void));
+void input_file_begin PARAMS ((void));
+void input_file_close PARAMS ((void));
+void input_file_end PARAMS ((void));
+void input_file_open PARAMS ((char *filename, int pre));
+void input_file_pop PARAMS ((char *arg));
+
+/* end of input_file.h */
diff --git a/gas/input-scrub.c b/gas/input-scrub.c
new file mode 100644
index 0000000000..46a3bb3b7f
--- /dev/null
+++ b/gas/input-scrub.c
@@ -0,0 +1,521 @@
+/* input_scrub.c - Break up input buffers into whole numbers of lines.
+ Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 1997
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include <errno.h> /* Need this to make errno declaration right */
+#include "as.h"
+#include "input-file.h"
+#include "sb.h"
+#include "listing.h"
+
+/*
+ * O/S independent module to supply buffers of sanitised source code
+ * to rest of assembler. We get sanitised input data of arbitrary length.
+ * We break these buffers on line boundaries, recombine pieces that
+ * were broken across buffers, and return a buffer of full lines to
+ * the caller.
+ * The last partial line begins the next buffer we build and return to caller.
+ * The buffer returned to caller is preceeded by BEFORE_STRING and followed
+ * by AFTER_STRING, as sentinels. The last character before AFTER_STRING
+ * is a newline.
+ * Also looks after line numbers, for e.g. error messages.
+ */
+
+/*
+ * We don't care how filthy our buffers are, but our callers assume
+ * that the following sanitation has already been done.
+ *
+ * No comments, reduce a comment to a space.
+ * Reduce a tab to a space unless it is 1st char of line.
+ * All multiple tabs and spaces collapsed into 1 char. Tab only
+ * legal if 1st char of line.
+ * # line file statements converted to .line x;.file y; statements.
+ * Escaped newlines at end of line: remove them but add as many newlines
+ * to end of statement as you removed in the middle, to synch line numbers.
+ */
+
+#define BEFORE_STRING ("\n")
+#define AFTER_STRING ("\0") /* memcpy of 0 chars might choke. */
+#define BEFORE_SIZE (1)
+#define AFTER_SIZE (1)
+
+static char *buffer_start; /*->1st char of full buffer area. */
+static char *partial_where; /*->after last full line in buffer. */
+static int partial_size; /* >=0. Number of chars in partial line in buffer. */
+static char save_source[AFTER_SIZE];
+/* Because we need AFTER_STRING just after last */
+/* full line, it clobbers 1st part of partial */
+/* line. So we preserve 1st part of partial */
+/* line here. */
+static unsigned int buffer_length; /* What is the largest size buffer that */
+/* input_file_give_next_buffer() could */
+/* return to us? */
+
+/* The index into an sb structure we are reading from. -1 if none. */
+static int sb_index = -1;
+
+/* If we are reading from an sb structure, this is it. */
+static sb from_sb;
+
+/* The number of nested sb structures we have included. */
+int macro_nest;
+
+/* We can have more than one source file open at once, though the info for all
+ but the latest one are saved off in a struct input_save. These files remain
+ open, so we are limited by the number of open files allowed by the
+ underlying OS. We may also sequentially read more than one source file in an
+ assembly. */
+
+/* We must track the physical file and line number for error messages. We also
+ track a "logical" file and line number corresponding to (C?) compiler
+ source line numbers. Whenever we open a file we must fill in
+ physical_input_file. So if it is NULL we have not opened any files yet. */
+
+static char *physical_input_file;
+static char *logical_input_file;
+
+typedef unsigned int line_numberT; /* 1-origin line number in a source file. */
+/* A line ends in '\n' or eof. */
+
+static line_numberT physical_input_line;
+static int logical_input_line;
+
+/* Struct used to save the state of the input handler during include files */
+struct input_save
+ {
+ char *buffer_start;
+ char *partial_where;
+ int partial_size;
+ char save_source[AFTER_SIZE];
+ unsigned int buffer_length;
+ char *physical_input_file;
+ char *logical_input_file;
+ line_numberT physical_input_line;
+ int logical_input_line;
+ int sb_index;
+ sb from_sb;
+ struct input_save *next_saved_file; /* Chain of input_saves */
+ char *input_file_save; /* Saved state of input routines */
+ char *saved_position; /* Caller's saved position in buf */
+ };
+
+static struct input_save *input_scrub_push PARAMS ((char *saved_position));
+static char *input_scrub_pop PARAMS ((struct input_save *arg));
+static void as_1_char PARAMS ((unsigned int c, FILE * stream));
+
+/* Saved information about the file that .include'd this one. When we hit EOF,
+ we automatically pop to that file. */
+
+static struct input_save *next_saved_file;
+
+/* Push the state of input reading and scrubbing so that we can #include.
+ The return value is a 'void *' (fudged for old compilers) to a save
+ area, which can be restored by passing it to input_scrub_pop(). */
+static struct input_save *
+input_scrub_push (saved_position)
+ char *saved_position;
+{
+ register struct input_save *saved;
+
+ saved = (struct input_save *) xmalloc (sizeof *saved);
+
+ saved->saved_position = saved_position;
+ saved->buffer_start = buffer_start;
+ saved->partial_where = partial_where;
+ saved->partial_size = partial_size;
+ saved->buffer_length = buffer_length;
+ saved->physical_input_file = physical_input_file;
+ saved->logical_input_file = logical_input_file;
+ saved->physical_input_line = physical_input_line;
+ saved->logical_input_line = logical_input_line;
+ saved->sb_index = sb_index;
+ saved->from_sb = from_sb;
+ memcpy (saved->save_source, save_source, sizeof (save_source));
+ saved->next_saved_file = next_saved_file;
+ saved->input_file_save = input_file_push ();
+
+ input_file_begin (); /* Reinitialize! */
+ logical_input_line = -1;
+ logical_input_file = (char *) NULL;
+ buffer_length = input_file_buffer_size ();
+ sb_index = -1;
+
+ buffer_start = xmalloc ((BEFORE_SIZE + buffer_length + buffer_length + AFTER_SIZE));
+ memcpy (buffer_start, BEFORE_STRING, (int) BEFORE_SIZE);
+
+ return saved;
+} /* input_scrub_push() */
+
+static char *
+input_scrub_pop (saved)
+ struct input_save *saved;
+{
+ char *saved_position;
+
+ input_scrub_end (); /* Finish off old buffer */
+
+ input_file_pop (saved->input_file_save);
+ saved_position = saved->saved_position;
+ buffer_start = saved->buffer_start;
+ buffer_length = saved->buffer_length;
+ physical_input_file = saved->physical_input_file;
+ logical_input_file = saved->logical_input_file;
+ physical_input_line = saved->physical_input_line;
+ logical_input_line = saved->logical_input_line;
+ sb_index = saved->sb_index;
+ from_sb = saved->from_sb;
+ partial_where = saved->partial_where;
+ partial_size = saved->partial_size;
+ next_saved_file = saved->next_saved_file;
+ memcpy (save_source, saved->save_source, sizeof (save_source));
+
+ free (saved);
+ return saved_position;
+}
+
+
+void
+input_scrub_begin ()
+{
+ know (strlen (BEFORE_STRING) == BEFORE_SIZE);
+ know (strlen (AFTER_STRING) == AFTER_SIZE || (AFTER_STRING[0] == '\0' && AFTER_SIZE == 1));
+
+ input_file_begin ();
+
+ buffer_length = input_file_buffer_size ();
+
+ buffer_start = xmalloc ((BEFORE_SIZE + buffer_length + buffer_length + AFTER_SIZE));
+ memcpy (buffer_start, BEFORE_STRING, (int) BEFORE_SIZE);
+
+ /* Line number things. */
+ logical_input_line = -1;
+ logical_input_file = (char *) NULL;
+ physical_input_file = NULL; /* No file read yet. */
+ next_saved_file = NULL; /* At EOF, don't pop to any other file */
+ do_scrub_begin (flag_m68k_mri);
+}
+
+void
+input_scrub_end ()
+{
+ if (buffer_start)
+ {
+ free (buffer_start);
+ buffer_start = 0;
+ input_file_end ();
+ }
+}
+
+/* Start reading input from a new file. */
+
+char * /* Return start of caller's part of buffer. */
+input_scrub_new_file (filename)
+ char *filename;
+{
+ input_file_open (filename, !flag_no_comments);
+ physical_input_file = filename[0] ? filename : _("{standard input}");
+ physical_input_line = 0;
+
+ partial_size = 0;
+ return (buffer_start + BEFORE_SIZE);
+}
+
+
+/* Include a file from the current file. Save our state, cause it to
+ be restored on EOF, and begin handling a new file. Same result as
+ input_scrub_new_file. */
+
+char *
+input_scrub_include_file (filename, position)
+ char *filename;
+ char *position;
+{
+ next_saved_file = input_scrub_push (position);
+ return input_scrub_new_file (filename);
+}
+
+/* Start getting input from an sb structure. This is used when
+ expanding a macro. */
+
+void
+input_scrub_include_sb (from, position)
+ sb *from;
+ char *position;
+{
+ if (macro_nest > max_macro_nest)
+ as_fatal (_("macros nested too deeply"));
+ ++macro_nest;
+
+ next_saved_file = input_scrub_push (position);
+
+ sb_new (&from_sb);
+ if (from->len >= 1 && from->ptr[0] != '\n')
+ {
+ /* Add the sentinel required by read.c. */
+ sb_add_char (&from_sb, '\n');
+ }
+ sb_add_sb (&from_sb, from);
+ sb_index = 1;
+
+ /* These variables are reset by input_scrub_push. Restore them
+ since we are, after all, still at the same point in the file. */
+ logical_input_line = next_saved_file->logical_input_line;
+ logical_input_file = next_saved_file->logical_input_file;
+}
+
+void
+input_scrub_close ()
+{
+ input_file_close ();
+}
+
+char *
+input_scrub_next_buffer (bufp)
+ char **bufp;
+{
+ register char *limit; /*->just after last char of buffer. */
+
+ if (sb_index >= 0)
+ {
+ if (sb_index >= from_sb.len)
+ {
+ sb_kill (&from_sb);
+ cond_finish_check (macro_nest);
+ --macro_nest;
+ partial_where = NULL;
+ if (next_saved_file != NULL)
+ *bufp = input_scrub_pop (next_saved_file);
+ return partial_where;
+ }
+
+ partial_where = from_sb.ptr + from_sb.len;
+ partial_size = 0;
+ *bufp = from_sb.ptr + sb_index;
+ sb_index = from_sb.len;
+ return partial_where;
+ }
+
+ *bufp = buffer_start + BEFORE_SIZE;
+
+ if (partial_size)
+ {
+ memcpy (buffer_start + BEFORE_SIZE, partial_where,
+ (unsigned int) partial_size);
+ memcpy (buffer_start + BEFORE_SIZE, save_source, AFTER_SIZE);
+ }
+ limit = input_file_give_next_buffer (buffer_start
+ + BEFORE_SIZE
+ + partial_size);
+ if (limit)
+ {
+ register char *p; /* Find last newline. */
+
+ for (p = limit - 1; *p != '\n'; --p)
+ ;
+ ++p;
+
+ while (p <= buffer_start + BEFORE_SIZE)
+ {
+ int limoff;
+
+ limoff = limit - buffer_start;
+ buffer_length += input_file_buffer_size ();
+ buffer_start = xrealloc (buffer_start,
+ (BEFORE_SIZE
+ + 2 * buffer_length
+ + AFTER_SIZE));
+ *bufp = buffer_start + BEFORE_SIZE;
+ limit = input_file_give_next_buffer (buffer_start + limoff);
+
+ if (limit == NULL)
+ {
+ as_warn (_("partial line at end of file ignored"));
+ partial_where = NULL;
+ if (next_saved_file)
+ *bufp = input_scrub_pop (next_saved_file);
+ return NULL;
+ }
+
+ for (p = limit - 1; *p != '\n'; --p)
+ ;
+ ++p;
+ }
+
+ partial_where = p;
+ partial_size = limit - p;
+ memcpy (save_source, partial_where, (int) AFTER_SIZE);
+ memcpy (partial_where, AFTER_STRING, (int) AFTER_SIZE);
+ }
+ else
+ {
+ partial_where = 0;
+ if (partial_size > 0)
+ {
+ as_warn (_("Partial line at end of file ignored"));
+ }
+
+ /* Tell the listing we've finished the file. */
+ LISTING_EOF ();
+
+ /* If we should pop to another file at EOF, do it. */
+ if (next_saved_file)
+ {
+ *bufp = input_scrub_pop (next_saved_file); /* Pop state */
+ /* partial_where is now correct to return, since we popped it. */
+ }
+ }
+ return (partial_where);
+} /* input_scrub_next_buffer() */
+
+/*
+ * The remaining part of this file deals with line numbers, error
+ * messages and so on.
+ */
+
+
+int
+seen_at_least_1_file () /* TRUE if we opened any file. */
+{
+ return (physical_input_file != NULL);
+}
+
+void
+bump_line_counters ()
+{
+ if (sb_index < 0)
+ {
+ ++physical_input_line;
+ if (logical_input_line >= 0)
+ ++logical_input_line;
+ }
+}
+
+/*
+ * new_logical_line()
+ *
+ * Tells us what the new logical line number and file are.
+ * If the line_number is -1, we don't change the current logical line
+ * number. If it is -2, we decrement the logical line number (this is
+ * to support the .appfile pseudo-op inserted into the stream by
+ * do_scrub_chars).
+ * If the fname is NULL, we don't change the current logical file name.
+ * Returns nonzero if the filename actually changes.
+ */
+int
+new_logical_line (fname, line_number)
+ char *fname; /* DON'T destroy it! We point to it! */
+ int line_number;
+{
+ if (line_number >= 0)
+ logical_input_line = line_number;
+ else if (line_number == -2 && logical_input_line > 0)
+ --logical_input_line;
+
+ if (fname
+ && (logical_input_file == NULL
+ || strcmp (logical_input_file, fname)))
+ {
+ logical_input_file = fname;
+ return 1;
+ }
+ else
+ return 0;
+} /* new_logical_line() */
+
+/*
+ * a s _ w h e r e ()
+ *
+ * Return the current file name and line number.
+ * namep should be char * const *, but there are compilers which screw
+ * up declarations like that, and it's easier to avoid it.
+ */
+void
+as_where (namep, linep)
+ char **namep;
+ unsigned int *linep;
+{
+ if (logical_input_file != NULL
+ && (linep == NULL || logical_input_line >= 0))
+ {
+ *namep = logical_input_file;
+ if (linep != NULL)
+ *linep = logical_input_line;
+ }
+ else if (physical_input_file != NULL)
+ {
+ *namep = physical_input_file;
+ if (linep != NULL)
+ *linep = physical_input_line;
+ }
+ else
+ {
+ *namep = 0;
+ if (linep != NULL)
+ *linep = 0;
+ }
+} /* as_where() */
+
+
+
+
+/*
+ * a s _ h o w m u c h ()
+ *
+ * Output to given stream how much of line we have scanned so far.
+ * Assumes we have scanned up to and including input_line_pointer.
+ * No free '\n' at end of line.
+ */
+void
+as_howmuch (stream)
+ FILE *stream; /* Opened for write please. */
+{
+ register char *p; /* Scan input line. */
+ /* register char c; JF unused */
+
+ for (p = input_line_pointer - 1; *p != '\n'; --p)
+ {
+ }
+ ++p; /* p->1st char of line. */
+ for (; p <= input_line_pointer; p++)
+ {
+ /* Assume ASCII. EBCDIC & other micro-computer char sets ignored. */
+ as_1_char ((unsigned char) *p, stream);
+ }
+}
+
+static void
+as_1_char (c, stream)
+ unsigned int c;
+ FILE *stream;
+{
+ if (c > 127)
+ {
+ (void) putc ('%', stream);
+ c -= 128;
+ }
+ if (c < 32)
+ {
+ (void) putc ('^', stream);
+ c += '@';
+ }
+ (void) putc (c, stream);
+}
+
+/* end of input_scrub.c */
diff --git a/gas/itbl-lex.l b/gas/itbl-lex.l
new file mode 100644
index 0000000000..a905ddd007
--- /dev/null
+++ b/gas/itbl-lex.l
@@ -0,0 +1,114 @@
+/* itbl-lex.l
+ Copyright (C) 1997 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+%{
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "itbl-parse.h"
+
+#ifdef DEBUG
+#define DBG(x) printf x
+#define MDBG(x) printf x
+#else
+#define DBG(x)
+#define MDBG(x)
+#endif
+
+int insntbl_line = 1;
+%}
+
+ALNUM [A-Za-z0-9_]
+DIGIT [0-9]
+ALPHA [A-Za-z_]
+HEX [0-9A-Fa-f]
+
+%%
+
+"creg"|"CREG" {
+ return CREG;
+ }
+"dreg"|"DREG" {
+ return DREG;
+ }
+"greg"|"GREG" {
+ return GREG;
+ }
+"immed"|"IMMED" {
+ return IMMED;
+ }
+"addr"|"ADDR" {
+ return ADDR;
+ }
+"insn"|"INSN" {
+ return INSN;
+ }
+"p"{DIGIT} {
+ yytext[yyleng] = 0;
+ yylval.processor = strtoul (yytext+1, 0, 0);
+ return PNUM;
+ }
+{DIGIT}+ {
+ yytext[yyleng] = 0;
+ yylval.num = strtoul (yytext, 0, 0);
+ return NUM;
+ }
+"0x"{HEX}+ {
+ yytext[yyleng] = 0;
+ yylval.num = strtoul (yytext, 0, 0);
+ return NUM;
+ }
+{ALPHA}{ALNUM}* {
+ yytext[yyleng] = 0;
+ yylval.str = strdup (yytext);
+ return ID;
+ }
+";"|"#" {
+ int c;
+ while ((c = input ()) != EOF)
+ {
+ if (c == '\n')
+ {
+ unput (c);
+ break;
+ }
+ }
+ }
+"\n" {
+ insntbl_line++;
+ MDBG (("in lex, NL = %d (x%x)\n", NL, NL));
+ return NL;
+ }
+" "|"\t" {
+ }
+. {
+ MDBG (("char = %x, %d\n", yytext[0], yytext[0]));
+ return yytext[0];
+ }
+%%
+
+#ifndef yywrap
+int
+yywrap ()
+ {
+ return 1;
+ }
+#endif
diff --git a/gas/itbl-ops.c b/gas/itbl-ops.c
new file mode 100644
index 0000000000..f008dcafeb
--- /dev/null
+++ b/gas/itbl-ops.c
@@ -0,0 +1,921 @@
+/* itbl-ops.c
+ Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/*======================================================================*/
+/*
+ * Herein lies the support for dynamic specification of processor
+ * instructions and registers. Mnemonics, values, and formats for each
+ * instruction and register are specified in an ascii file consisting of
+ * table entries. The grammar for the table is defined in the document
+ * "Processor instruction table specification".
+ *
+ * Instructions use the gnu assembler syntax, with the addition of
+ * allowing mnemonics for register.
+ * Eg. "func $2,reg3,0x100,symbol ; comment"
+ * func - opcode name
+ * $n - register n
+ * reg3 - mnemonic for processor's register defined in table
+ * 0xddd..d - immediate value
+ * symbol - address of label or external symbol
+ *
+ * First, itbl_parse reads in the table of register and instruction
+ * names and formats, and builds a list of entries for each
+ * processor/type combination. lex and yacc are used to parse
+ * the entries in the table and call functions defined here to
+ * add each entry to our list.
+ *
+ * Then, when assembling or disassembling, these functions are called to
+ * 1) get information on a processor's registers and
+ * 2) assemble/disassemble an instruction.
+ * To assemble(disassemble) an instruction, the function
+ * itbl_assemble(itbl_disassemble) is called to search the list of
+ * instruction entries, and if a match is found, uses the format
+ * described in the instruction entry structure to complete the action.
+ *
+ * Eg. Suppose we have a Mips coprocessor "cop3" with data register "d2"
+ * and we want to define function "pig" which takes two operands.
+ *
+ * Given the table entries:
+ * "p3 insn pig 0x1:24-21 dreg:20-16 immed:15-0"
+ * "p3 dreg d2 0x2"
+ * and that the instruction encoding for coprocessor pz has encoding:
+ * #define MIPS_ENCODE_COP_NUM(z) ((0x21|(z<<1))<<25)
+ * #define ITBL_ENCODE_PNUM(pnum) MIPS_ENCODE_COP_NUM(pnum)
+ *
+ * a structure to describe the instruction might look something like:
+ * struct itbl_entry = {
+ * e_processor processor = e_p3
+ * e_type type = e_insn
+ * char *name = "pig"
+ * uint value = 0x1
+ * uint flags = 0
+ * struct itbl_range range = 24-21
+ * struct itbl_field *field = {
+ * e_type type = e_dreg
+ * struct itbl_range range = 20-16
+ * struct itbl_field *next = {
+ * e_type type = e_immed
+ * struct itbl_range range = 15-0
+ * struct itbl_field *next = 0
+ * };
+ * };
+ * struct itbl_entry *next = 0
+ * };
+ *
+ * And the assembler instructions:
+ * "pig d2,0x100"
+ * "pig $2,0x100"
+ *
+ * would both assemble to the hex value:
+ * "0x4e220100"
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "itbl-ops.h"
+#include "itbl-parse.h"
+
+/* #define DEBUG */
+
+#ifdef DEBUG
+#include <assert.h>
+#define ASSERT(x) assert(x)
+#define DBG(x) printf x
+#else
+#define ASSERT(x)
+#define DBG(x)
+#endif
+
+#ifndef min
+#define min(a,b) (a<b?a:b)
+#endif
+
+int itbl_have_entries = 0;
+
+/*======================================================================*/
+/* structures for keeping itbl format entries */
+
+struct itbl_range
+ {
+ int sbit; /* mask starting bit position */
+ int ebit; /* mask ending bit position */
+ };
+
+struct itbl_field
+ {
+ e_type type; /* dreg/creg/greg/immed/symb */
+ struct itbl_range range; /* field's bitfield range within instruction */
+ unsigned long flags; /* field flags */
+ struct itbl_field *next; /* next field in list */
+ };
+
+
+/* These structures define the instructions and registers for a processor.
+ * If the type is an instruction, the structure defines the format of an
+ * instruction where the fields are the list of operands.
+ * The flags field below uses the same values as those defined in the
+ * gnu assembler and are machine specific. */
+struct itbl_entry
+ {
+ e_processor processor; /* processor number */
+ e_type type; /* dreg/creg/greg/insn */
+ char *name; /* mnemionic name for insn/register */
+ unsigned long value; /* opcode/instruction mask/register number */
+ unsigned long flags; /* effects of the instruction */
+ struct itbl_range range; /* bit range within instruction for value */
+ struct itbl_field *fields; /* list of operand definitions (if any) */
+ struct itbl_entry *next; /* next entry */
+ };
+
+
+/* local data and structures */
+
+static int itbl_num_opcodes = 0;
+/* Array of entries for each processor and entry type */
+static struct itbl_entry *entries[e_nprocs][e_ntypes] =
+{
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0}
+};
+
+/* local prototypes */
+static unsigned long build_opcode PARAMS ((struct itbl_entry *e));
+static e_type get_type PARAMS ((int yytype));
+static e_processor get_processor PARAMS ((int yyproc));
+static struct itbl_entry **get_entries PARAMS ((e_processor processor,
+ e_type type));
+static struct itbl_entry *find_entry_byname PARAMS ((e_processor processor,
+ e_type type, char *name));
+static struct itbl_entry *find_entry_byval PARAMS ((e_processor processor,
+ e_type type, unsigned long val, struct itbl_range *r));
+static struct itbl_entry *alloc_entry PARAMS ((e_processor processor,
+ e_type type, char *name, unsigned long value));
+static unsigned long apply_range PARAMS ((unsigned long value,
+ struct itbl_range r));
+static unsigned long extract_range PARAMS ((unsigned long value,
+ struct itbl_range r));
+static struct itbl_field *alloc_field PARAMS ((e_type type, int sbit,
+ int ebit, unsigned long flags));
+
+
+/*======================================================================*/
+/* Interfaces to the parser */
+
+
+/* Open the table and use lex and yacc to parse the entries.
+ * Return 1 for failure; 0 for success. */
+
+int
+itbl_parse (char *insntbl)
+{
+ extern FILE *yyin;
+ extern int yyparse (void);
+ yyin = fopen (insntbl, "r");
+ if (yyin == 0)
+ {
+ printf ("Can't open processor instruction specification file \"%s\"\n",
+ insntbl);
+ return 1;
+ }
+ else
+ {
+ while (yyparse ());
+ }
+ fclose (yyin);
+ itbl_have_entries = 1;
+ return 0;
+}
+
+/* Add a register entry */
+
+struct itbl_entry *
+itbl_add_reg (int yyprocessor, int yytype, char *regname,
+ int regnum)
+{
+#if 0
+#include "as.h"
+#include "symbols.h"
+ /* Since register names don't have a prefix, we put them in the symbol table so
+ they can't be used as symbols. This also simplifies argument parsing as
+ we can let gas parse registers for us. The recorded register number is
+ regnum. */
+ /* Use symbol_create here instead of symbol_new so we don't try to
+ output registers into the object file's symbol table. */
+ symbol_table_insert (symbol_create (regname, reg_section,
+ regnum, &zero_address_frag));
+#endif
+ return alloc_entry (get_processor (yyprocessor), get_type (yytype), regname,
+ (unsigned long) regnum);
+}
+
+/* Add an instruction entry */
+
+struct itbl_entry *
+itbl_add_insn (int yyprocessor, char *name, unsigned long value,
+ int sbit, int ebit, unsigned long flags)
+{
+ struct itbl_entry *e;
+ e = alloc_entry (get_processor (yyprocessor), e_insn, name, value);
+ if (e)
+ {
+ e->range.sbit = sbit;
+ e->range.ebit = ebit;
+ e->flags = flags;
+ itbl_num_opcodes++;
+ }
+ return e;
+}
+
+/* Add an operand to an instruction entry */
+
+struct itbl_field *
+itbl_add_operand (struct itbl_entry *e, int yytype, int sbit,
+ int ebit, unsigned long flags)
+{
+ struct itbl_field *f, **last_f;
+ if (!e)
+ return 0;
+ /* Add to end of fields' list. */
+ f = alloc_field (get_type (yytype), sbit, ebit, flags);
+ if (f)
+ {
+ last_f = &e->fields;
+ while (*last_f)
+ last_f = &(*last_f)->next;
+ *last_f = f;
+ f->next = 0;
+ }
+ return f;
+}
+
+
+/*======================================================================*/
+/* Interfaces for assembler and disassembler */
+
+#ifndef STAND_ALONE
+#include "as.h"
+#include "symbols.h"
+static void append_insns_as_macros (void);
+
+/* initialize for gas */
+void
+itbl_init (void)
+{
+ struct itbl_entry *e, **es;
+ e_processor procn;
+ e_type type;
+
+ if (!itbl_have_entries)
+ return;
+
+ /* Since register names don't have a prefix, put them in the symbol table so
+ they can't be used as symbols. This simplifies argument parsing as
+ we can let gas parse registers for us. */
+ /* Use symbol_create instead of symbol_new so we don't try to
+ output registers into the object file's symbol table. */
+
+ for (type = e_regtype0; type < e_nregtypes; type++)
+ for (procn = e_p0; procn < e_nprocs; procn++)
+ {
+ es = get_entries (procn, type);
+ for (e = *es; e; e = e->next)
+ {
+ symbol_table_insert (symbol_create (e->name, reg_section,
+ e->value, &zero_address_frag));
+ }
+ }
+ append_insns_as_macros ();
+}
+
+
+/* Append insns to opcodes table and increase number of opcodes
+ * Structure of opcodes table:
+ * struct itbl_opcode
+ * {
+ * const char *name;
+ * const char *args; - string describing the arguments.
+ * unsigned long match; - opcode, or ISA level if pinfo=INSN_MACRO
+ * unsigned long mask; - opcode mask, or macro id if pinfo=INSN_MACRO
+ * unsigned long pinfo; - insn flags, or INSN_MACRO
+ * };
+ * examples:
+ * {"li", "t,i", 0x34000000, 0xffe00000, WR_t },
+ * {"li", "t,I", 0, (int) M_LI, INSN_MACRO },
+ */
+
+static char *form_args (struct itbl_entry *e);
+static void
+append_insns_as_macros (void)
+{
+ struct ITBL_OPCODE_STRUCT *new_opcodes, *o;
+ struct itbl_entry *e, **es;
+ int n, id, size, new_size, new_num_opcodes;
+
+ if (!itbl_have_entries)
+ return;
+
+ if (!itbl_num_opcodes) /* no new instructions to add! */
+ {
+ return;
+ }
+ DBG (("previous num_opcodes=%d\n", ITBL_NUM_OPCODES));
+
+ new_num_opcodes = ITBL_NUM_OPCODES + itbl_num_opcodes;
+ ASSERT (new_num_opcodes >= itbl_num_opcodes);
+
+ size = sizeof (struct ITBL_OPCODE_STRUCT) * ITBL_NUM_OPCODES;
+ ASSERT (size >= 0);
+ DBG (("I get=%d\n", size / sizeof (ITBL_OPCODES[0])));
+
+ new_size = sizeof (struct ITBL_OPCODE_STRUCT) * new_num_opcodes;
+ ASSERT (new_size > size);
+
+ /* FIXME since ITBL_OPCODES culd be a static table,
+ we can't realloc or delete the old memory. */
+ new_opcodes = (struct ITBL_OPCODE_STRUCT *) malloc (new_size);
+ if (!new_opcodes)
+ {
+ printf (_("Unable to allocate memory for new instructions\n"));
+ return;
+ }
+ if (size) /* copy prexisting opcodes table */
+ memcpy (new_opcodes, ITBL_OPCODES, size);
+
+ /* FIXME! some NUMOPCODES are calculated expressions.
+ These need to be changed before itbls can be supported. */
+
+ id = ITBL_NUM_MACROS; /* begin the next macro id after the last */
+ o = &new_opcodes[ITBL_NUM_OPCODES]; /* append macro to opcodes list */
+ for (n = e_p0; n < e_nprocs; n++)
+ {
+ es = get_entries (n, e_insn);
+ for (e = *es; e; e = e->next)
+ {
+ /* name, args, mask, match, pinfo
+ * {"li", "t,i", 0x34000000, 0xffe00000, WR_t },
+ * {"li", "t,I", 0, (int) M_LI, INSN_MACRO },
+ * Construct args from itbl_fields.
+ */
+ o->name = e->name;
+ o->args = strdup (form_args (e));
+ o->mask = apply_range (e->value, e->range);
+ /* FIXME how to catch durring assembly? */
+ /* mask to identify this insn */
+ o->match = apply_range (e->value, e->range);
+ o->pinfo = 0;
+
+#ifdef USE_MACROS
+ o->mask = id++; /* FIXME how to catch durring assembly? */
+ o->match = 0; /* for macros, the insn_isa number */
+ o->pinfo = INSN_MACRO;
+#endif
+
+ /* Don't add instructions which caused an error */
+ if (o->args)
+ o++;
+ else
+ new_num_opcodes--;
+ }
+ }
+ ITBL_OPCODES = new_opcodes;
+ ITBL_NUM_OPCODES = new_num_opcodes;
+
+ /* FIXME
+ At this point, we can free the entries, as they should have
+ been added to the assembler's tables.
+ Don't free name though, since name is being used by the new
+ opcodes table.
+
+ Eventually, we should also free the new opcodes table itself
+ on exit.
+ */
+}
+
+static char *
+form_args (struct itbl_entry *e)
+{
+ static char s[31];
+ char c = 0, *p = s;
+ struct itbl_field *f;
+
+ ASSERT (e);
+ for (f = e->fields; f; f = f->next)
+ {
+ switch (f->type)
+ {
+ case e_dreg:
+ c = 'd';
+ break;
+ case e_creg:
+ c = 't';
+ break;
+ case e_greg:
+ c = 's';
+ break;
+ case e_immed:
+ c = 'i';
+ break;
+ case e_addr:
+ c = 'a';
+ break;
+ default:
+ c = 0; /* ignore; unknown field type */
+ }
+ if (c)
+ {
+ if (p != s)
+ *p++ = ',';
+ *p++ = c;
+ }
+ }
+ *p = 0;
+ return s;
+}
+#endif /* !STAND_ALONE */
+
+
+/* Get processor's register name from val */
+
+unsigned long
+itbl_get_reg_val (char *name)
+{
+ e_type t;
+ e_processor p;
+ int r = 0;
+ for (p = e_p0; p < e_nprocs; p++)
+ for (t = e_regtype0; t < e_nregtypes; t++)
+ {
+ if (r = itbl_get_val (p, t, name), r)
+ return r;
+ }
+ return 0;
+}
+
+char *
+itbl_get_name (e_processor processor, e_type type, unsigned long val)
+{
+ struct itbl_entry *r;
+ /* type depends on instruction passed */
+ r = find_entry_byval (processor, type, val, 0);
+ if (r)
+ return r->name;
+ else
+ return 0; /* error; invalid operand */
+}
+
+/* Get processor's register value from name */
+
+unsigned long
+itbl_get_val (e_processor processor, e_type type, char *name)
+{
+ struct itbl_entry *r;
+ /* type depends on instruction passed */
+ r = find_entry_byname (processor, type, name);
+ if (r)
+ return r->value;
+ else
+ return 0; /* error; invalid operand */
+}
+
+
+/* Assemble instruction "name" with operands "s".
+ * name - name of instruction
+ * s - operands
+ * returns - long word for assembled instruction */
+
+unsigned long
+itbl_assemble (char *name, char *s)
+{
+ unsigned long opcode;
+ struct itbl_entry *e;
+ struct itbl_field *f;
+ char *n;
+ int processor;
+
+ if (!name || !*name)
+ return 0; /* error! must have a opcode name/expr */
+
+ /* find entry in list of instructions for all processors */
+ for (processor = 0; processor < e_nprocs; processor++)
+ {
+ e = find_entry_byname (processor, e_insn, name);
+ if (e)
+ break;
+ }
+ if (!e)
+ return 0; /* opcode not in table; invalid instrustion */
+ opcode = build_opcode (e);
+
+ /* parse opcode's args (if any) */
+ for (f = e->fields; f; f = f->next) /* for each arg, ... */
+ {
+ struct itbl_entry *r;
+ unsigned long value;
+ if (!s || !*s)
+ return 0; /* error - not enough operands */
+ n = itbl_get_field (&s);
+ /* n should be in form $n or 0xhhh (are symbol names valid?? */
+ switch (f->type)
+ {
+ case e_dreg:
+ case e_creg:
+ case e_greg:
+ /* Accept either a string name
+ * or '$' followed by the register number */
+ if (*n == '$')
+ {
+ n++;
+ value = strtol (n, 0, 10);
+ /* FIXME! could have "0l"... then what?? */
+ if (value == 0 && *n != '0')
+ return 0; /* error; invalid operand */
+ }
+ else
+ {
+ r = find_entry_byname (e->processor, f->type, n);
+ if (r)
+ value = r->value;
+ else
+ return 0; /* error; invalid operand */
+ }
+ break;
+ case e_addr:
+ /* use assembler's symbol table to find symbol */
+ /* FIXME!! Do we need this?
+ if so, what about relocs??
+ my_getExpression (&imm_expr, s);
+ return 0; /-* error; invalid operand *-/
+ break;
+ */
+ /* If not a symbol, fall thru to IMMED */
+ case e_immed:
+ if (*n == '0' && *(n + 1) == 'x') /* hex begins 0x... */
+ {
+ n += 2;
+ value = strtol (n, 0, 16);
+ /* FIXME! could have "0xl"... then what?? */
+ }
+ else
+ {
+ value = strtol (n, 0, 10);
+ /* FIXME! could have "0l"... then what?? */
+ if (value == 0 && *n != '0')
+ return 0; /* error; invalid operand */
+ }
+ break;
+ default:
+ return 0; /* error; invalid field spec */
+ }
+ opcode |= apply_range (value, f->range);
+ }
+ if (s && *s)
+ return 0; /* error - too many operands */
+ return opcode; /* done! */
+}
+
+/* Disassemble instruction "insn".
+ * insn - instruction
+ * s - buffer to hold disassembled instruction
+ * returns - 1 if succeeded; 0 if failed
+ */
+
+int
+itbl_disassemble (char *s, unsigned long insn)
+{
+ e_processor processor;
+ struct itbl_entry *e;
+ struct itbl_field *f;
+
+ if (!ITBL_IS_INSN (insn))
+ return 0; /* error*/
+ processor = get_processor (ITBL_DECODE_PNUM (insn));
+
+ /* find entry in list */
+ e = find_entry_byval (processor, e_insn, insn, 0);
+ if (!e)
+ return 0; /* opcode not in table; invalid instrustion */
+ strcpy (s, e->name);
+
+ /* parse insn's args (if any) */
+ for (f = e->fields; f; f = f->next) /* for each arg, ... */
+ {
+ struct itbl_entry *r;
+ unsigned long value;
+
+ if (f == e->fields) /* first operand is preceeded by tab */
+ strcat (s, "\t");
+ else /* ','s separate following operands */
+ strcat (s, ",");
+ value = extract_range (insn, f->range);
+ /* n should be in form $n or 0xhhh (are symbol names valid?? */
+ switch (f->type)
+ {
+ case e_dreg:
+ case e_creg:
+ case e_greg:
+ /* Accept either a string name
+ * or '$' followed by the register number */
+ r = find_entry_byval (e->processor, f->type, value, &f->range);
+ if (r)
+ strcat (s, r->name);
+ else
+ sprintf (s, "%s$%d", s, value);
+ break;
+ case e_addr:
+ /* use assembler's symbol table to find symbol */
+ /* FIXME!! Do we need this?
+ * if so, what about relocs??
+ */
+ /* If not a symbol, fall thru to IMMED */
+ case e_immed:
+ sprintf (s, "%s0x%x", s, value);
+ break;
+ default:
+ return 0; /* error; invalid field spec */
+ }
+ }
+ return 1; /* done! */
+}
+
+/*======================================================================*/
+/*
+ * Local functions for manipulating private structures containing
+ * the names and format for the new instructions and registers
+ * for each processor.
+ */
+
+/* Calculate instruction's opcode and function values from entry */
+
+static unsigned long
+build_opcode (struct itbl_entry *e)
+{
+ unsigned long opcode;
+
+ opcode = apply_range (e->value, e->range);
+ opcode |= ITBL_ENCODE_PNUM (e->processor);
+ return opcode;
+}
+
+/* Calculate absolute value given the relative value and bit position range
+ * within the instruction.
+ * The range is inclusive where 0 is least significant bit.
+ * A range of { 24, 20 } will have a mask of
+ * bit 3 2 1
+ * pos: 1098 7654 3210 9876 5432 1098 7654 3210
+ * bin: 0000 0001 1111 0000 0000 0000 0000 0000
+ * hex: 0 1 f 0 0 0 0 0
+ * mask: 0x01f00000.
+ */
+
+static unsigned long
+apply_range (unsigned long rval, struct itbl_range r)
+{
+ unsigned long mask;
+ unsigned long aval;
+ int len = MAX_BITPOS - r.sbit;
+
+ ASSERT (r.sbit >= r.ebit);
+ ASSERT (MAX_BITPOS >= r.sbit);
+ ASSERT (r.ebit >= 0);
+
+ /* create mask by truncating 1s by shifting */
+ mask = 0xffffffff << len;
+ mask = mask >> len;
+ mask = mask >> r.ebit;
+ mask = mask << r.ebit;
+
+ aval = (rval << r.ebit) & mask;
+ return aval;
+}
+
+/* Calculate relative value given the absolute value and bit position range
+ * within the instruction. */
+
+static unsigned long
+extract_range (unsigned long aval, struct itbl_range r)
+{
+ unsigned long mask;
+ unsigned long rval;
+ int len = MAX_BITPOS - r.sbit;
+
+ /* create mask by truncating 1s by shifting */
+ mask = 0xffffffff << len;
+ mask = mask >> len;
+ mask = mask >> r.ebit;
+ mask = mask << r.ebit;
+
+ rval = (aval & mask) >> r.ebit;
+ return rval;
+}
+
+/* Extract processor's assembly instruction field name from s;
+ * forms are "n args" "n,args" or "n" */
+/* Return next argument from string pointer "s" and advance s.
+ * delimiters are " ,\0" */
+
+char *
+itbl_get_field (char **S)
+{
+ static char n[128];
+ char *p, *ps, *s;
+ int len;
+
+ s = *S;
+ if (!s || !*s)
+ return 0;
+ p = s + strlen (s);
+ if (ps = strchr (s, ','), ps)
+ p = ps;
+ if (ps = strchr (s, ' '), ps)
+ p = min (p, ps);
+ if (ps = strchr (s, '\0'), ps)
+ p = min (p, ps);
+ if (p == 0)
+ return 0; /* error! */
+ len = p - s;
+ ASSERT (128 > len + 1);
+ strncpy (n, s, len);
+ n[len] = 0;
+ if (s[len] == '\0')
+ s = 0; /* no more args */
+ else
+ s += len + 1; /* advance to next arg */
+
+ *S = s;
+ return n;
+}
+
+/* Search entries for a given processor and type
+ * to find one matching the name "n".
+ * Return a pointer to the entry */
+
+static struct itbl_entry *
+find_entry_byname (e_processor processor,
+ e_type type, char *n)
+{
+ struct itbl_entry *e, **es;
+
+ es = get_entries (processor, type);
+ for (e = *es; e; e = e->next) /* for each entry, ... */
+ {
+ if (!strcmp (e->name, n))
+ return e;
+ }
+ return 0;
+}
+
+/* Search entries for a given processor and type
+ * to find one matching the value "val" for the range "r".
+ * Return a pointer to the entry.
+ * This function is used for disassembling fields of an instruction.
+ */
+
+static struct itbl_entry *
+find_entry_byval (e_processor processor, e_type type,
+ unsigned long val, struct itbl_range *r)
+{
+ struct itbl_entry *e, **es;
+ unsigned long eval;
+
+ es = get_entries (processor, type);
+ for (e = *es; e; e = e->next) /* for each entry, ... */
+ {
+ if (processor != e->processor)
+ continue;
+ /* For insns, we might not know the range of the opcode,
+ * so a range of 0 will allow this routine to match against
+ * the range of the entry to be compared with.
+ * This could cause ambiguities.
+ * For operands, we get an extracted value and a range.
+ */
+ /* if range is 0, mask val against the range of the compared entry. */
+ if (r == 0) /* if no range passed, must be whole 32-bits
+ * so create 32-bit value from entry's range */
+ {
+ eval = apply_range (e->value, e->range);
+ val &= apply_range (0xffffffff, e->range);
+ }
+ else if (r->sbit == e->range.sbit && r->ebit == e->range.ebit
+ || e->range.sbit == 0 && e->range.ebit == 0)
+ {
+ eval = apply_range (e->value, *r);
+ val = apply_range (val, *r);
+ }
+ else
+ continue;
+ if (val == eval)
+ return e;
+ }
+ return 0;
+}
+
+/* Return a pointer to the list of entries for a given processor and type. */
+
+static struct itbl_entry **
+get_entries (e_processor processor, e_type type)
+{
+ return &entries[processor][type];
+}
+
+/* Return an integral value for the processor passed from yyparse. */
+
+static e_processor
+get_processor (int yyproc)
+{
+ /* translate from yacc's processor to enum */
+ if (yyproc >= e_p0 && yyproc < e_nprocs)
+ return (e_processor) yyproc;
+ return e_invproc; /* error; invalid processor */
+}
+
+/* Return an integral value for the entry type passed from yyparse. */
+
+static e_type
+get_type (int yytype)
+{
+ switch (yytype)
+ {
+ /* translate from yacc's type to enum */
+ case INSN:
+ return e_insn;
+ case DREG:
+ return e_dreg;
+ case CREG:
+ return e_creg;
+ case GREG:
+ return e_greg;
+ case ADDR:
+ return e_addr;
+ case IMMED:
+ return e_immed;
+ default:
+ return e_invtype; /* error; invalid type */
+ }
+}
+
+
+/* Allocate and initialize an entry */
+
+static struct itbl_entry *
+alloc_entry (e_processor processor, e_type type,
+ char *name, unsigned long value)
+{
+ struct itbl_entry *e, **es;
+ if (!name)
+ return 0;
+ e = (struct itbl_entry *) malloc (sizeof (struct itbl_entry));
+ if (e)
+ {
+ memset (e, 0, sizeof (struct itbl_entry));
+ e->name = (char *) malloc (sizeof (strlen (name)) + 1);
+ if (e->name)
+ strcpy (e->name, name);
+ e->processor = processor;
+ e->type = type;
+ e->value = value;
+ es = get_entries (e->processor, e->type);
+ e->next = *es;
+ *es = e;
+ }
+ return e;
+}
+
+/* Allocate and initialize an entry's field */
+
+static struct itbl_field *
+alloc_field (e_type type, int sbit, int ebit,
+ unsigned long flags)
+{
+ struct itbl_field *f;
+ f = (struct itbl_field *) malloc (sizeof (struct itbl_field));
+ if (f)
+ {
+ memset (f, 0, sizeof (struct itbl_field));
+ f->type = type;
+ f->range.sbit = sbit;
+ f->range.ebit = ebit;
+ f->flags = flags;
+ }
+ return f;
+}
diff --git a/gas/itbl-ops.h b/gas/itbl-ops.h
new file mode 100644
index 0000000000..2946eff006
--- /dev/null
+++ b/gas/itbl-ops.h
@@ -0,0 +1,109 @@
+/* itbl-ops.h
+ Copyright (C) 1997 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* External functions, constants and defines for itbl support */
+
+#include "ansidecl.h"
+
+/* Include file notes: "expr.h" needed before targ-*.h,
+ * "targ-env.h" includes the chain of target dependant headers,
+ * "targ-cpu.h" has the HAVE_ITBL_CPU define, and
+ * as.h includes them all */
+#include "as.h"
+
+#ifdef HAVE_ITBL_CPU
+#include "itbl-cpu.h"
+#endif
+
+/* Defaults for definitions required by generic code */
+#ifndef ITBL_NUMBER_OF_PROCESSORS
+#define ITBL_NUMBER_OF_PROCESSORS 1
+#endif
+
+#ifndef ITBL_MAX_BITPOS
+#define ITBL_MAX_BITPOS 31
+#endif
+
+#ifndef ITBL_TYPE
+#define ITBL_TYPE unsigned long
+#endif
+
+#ifndef ITBL_IS_INSN
+#define ITBL_IS_INSN(insn) 1
+#endif
+
+#ifndef ITBL_DECODE_PNUM
+#define ITBL_DECODE_PNUM(insn) 0
+#endif
+
+#ifndef ITBL_ENCODE_PNUM
+#define ITBL_ENCODE_PNUM(pnum) 0
+#endif
+
+typedef ITBL_TYPE t_insn;
+
+/* types of entries */
+typedef enum
+ {
+ e_insn,
+ e_dreg,
+ e_regtype0 = e_dreg,
+ e_creg,
+ e_greg,
+ e_addr,
+ e_nregtypes = e_greg + 1,
+ e_immed,
+ e_ntypes,
+ e_invtype /* invalid type */
+ } e_type;
+
+typedef enum
+ {
+ e_p0,
+ e_nprocs = NUMBER_OF_PROCESSORS,
+ e_invproc /* invalid processor */
+ } e_processor;
+
+/* 0 means an instruction table was not specified. */
+extern int itbl_have_entries;
+
+/* These routines are visible to the main part of the assembler */
+
+int itbl_parse PARAMS ((char *insntbl));
+void itbl_init PARAMS ((void));
+char *itbl_get_field PARAMS ((char **s));
+unsigned long itbl_assemble PARAMS ((char *name, char *operands));
+int itbl_disassemble PARAMS ((char *str, unsigned long insn));
+int itbl_parse PARAMS ((char *tbl)); /* parses insn tbl */
+unsigned long itbl_get_reg_val PARAMS ((char *name));
+unsigned long itbl_get_val PARAMS ((e_processor processor, e_type type,
+ char *name));
+char *itbl_get_name PARAMS ((e_processor processor, e_type type,
+ unsigned long val));
+
+/* These routines are called by the table parser used to build the
+ dynamic list of new processor instructions and registers. */
+
+struct itbl_entry *itbl_add_reg PARAMS ((int yyproc, int yytype,
+ char *regname, int regnum));
+struct itbl_entry *itbl_add_insn PARAMS ((int yyproc, char *name,
+ unsigned long value, int sbit, int ebit, unsigned long flags));
+struct itbl_field *itbl_add_operand PARAMS ((struct itbl_entry * e, int yytype,
+ int sbit, int ebit, unsigned long flags));
diff --git a/gas/itbl-parse.y b/gas/itbl-parse.y
new file mode 100644
index 0000000000..7966ee8fe1
--- /dev/null
+++ b/gas/itbl-parse.y
@@ -0,0 +1,459 @@
+/* itbl-parse.y
+ Copyright (C) 1997 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+%{
+
+/*
+
+Yacc grammar for instruction table entries.
+
+=======================================================================
+Original Instruction table specification document:
+
+ MIPS Coprocessor Table Specification
+ ====================================
+
+This document describes the format of the MIPS coprocessor table. The
+table specifies a list of valid functions, data registers and control
+registers that can be used in coprocessor instructions. This list,
+together with the coprocessor instruction classes listed below,
+specifies the complete list of coprocessor instructions that will
+be recognized and assembled by the GNU assembler. In effect,
+this makes the GNU assembler table-driven, where the table is
+specified by the programmer.
+
+The table is an ordinary text file that the GNU assembler reads when
+it starts. Using the information in the table, the assembler
+generates an internal list of valid coprocessor registers and
+functions. The assembler uses this internal list in addition to the
+standard MIPS registers and instructions which are built-in to the
+assembler during code generation.
+
+To specify the coprocessor table when invoking the GNU assembler, use
+the command line option "--itbl file", where file is the
+complete name of the table, including path and extension.
+
+Examples:
+
+ gas -t cop.tbl test.s -o test.o
+ gas -t /usr/local/lib/cop.tbl test.s -o test.o
+ gas --itbl d:\gnu\data\cop.tbl test.s -o test.o
+
+Only one table may be supplied during a single invocation of
+the assembler.
+
+
+Instruction classes
+===================
+
+Below is a list of the valid coprocessor instruction classes for
+any given coprocessor "z". These instructions are already recognized
+by the assembler, and are listed here only for reference.
+
+Class format instructions
+-------------------------------------------------
+Class1:
+ op base rt offset
+ LWCz rt,offset (base)
+ SWCz rt,offset (base)
+Class2:
+ COPz sub rt rd 0
+ MTCz rt,rd
+ MFCz rt,rd
+ CTCz rt,rd
+ CFCz rt,rd
+Class3:
+ COPz CO cofun
+ COPz cofun
+Class4:
+ COPz BC br offset
+ BCzT offset
+ BCzF offset
+Class5:
+ COPz sub rt rd 0
+ DMFCz rt,rd
+ DMTCz rt,rd
+Class6:
+ op base rt offset
+ LDCz rt,offset (base)
+ SDCz rt,offset (base)
+Class7:
+ COPz BC br offset
+ BCzTL offset
+ BCzFL offset
+
+The coprocessor table defines coprocessor-specific registers that can
+be used with all of the above classes of instructions, where
+appropriate. It also defines additional coprocessor-specific
+functions for Class3 (COPz cofun) instructions, Thus, the table allows
+the programmer to use convenient mnemonics and operands for these
+functions, instead of the COPz mmenmonic and cofun operand.
+
+The names of the MIPS general registers and their aliases are defined
+by the assembler and will be recognized as valid register names by the
+assembler when used (where allowed) in coprocessor instructions.
+However, the names and values of all coprocessor data and control
+register mnemonics must be specified in the coprocessor table.
+
+
+Table Grammar
+=============
+
+Here is the grammar for the coprocessor table:
+
+ table -> entry*
+
+ entry -> [z entrydef] [comment] '\n'
+
+ entrydef -> type name val
+ entrydef -> 'insn' name val funcdef ; type of entry (instruction)
+
+ z -> 'p'['0'..'3'] ; processor number
+ type -> ['dreg' | 'creg' | 'greg' ] ; type of entry (register)
+ ; 'dreg', 'creg' or 'greg' specifies a data, control, or general
+ ; register mnemonic, respectively
+ name -> [ltr|dec]* ; mnemonic of register/function
+ val -> [dec|hex] ; register/function number (integer constant)
+
+ funcdef -> frange flags fields
+ ; bitfield range for opcode
+ ; list of fields' formats
+ fields -> field*
+ field -> [','] ftype frange flags
+ flags -> ['*' flagexpr]
+ flagexpr -> '[' flagexpr ']'
+ flagexpr -> val '|' flagexpr
+ ftype -> [ type | 'immed' | 'addr' ]
+ ; 'immed' specifies an immediate value; see grammar for "val" above
+ ; 'addr' specifies a C identifier; name of symbol to be resolved at
+ ; link time
+ frange -> ':' val '-' val ; starting to ending bit positions, where
+ ; where 0 is least significant bit
+ frange -> (null) ; default range of 31-0 will be assumed
+
+ comment -> [';'|'#'] [char]*
+ char -> any printable character
+ ltr -> ['a'..'z'|'A'..'Z']
+ dec -> ['0'..'9']* ; value in decimal
+ hex -> '0x'['0'..'9' | 'a'..'f' | 'A'..'F']* ; value in hexidecimal
+
+
+Examples
+========
+
+Example 1:
+
+The table:
+
+ p1 dreg d1 1 ; data register "d1" for COP1 has value 1
+ p1 creg c3 3 ; ctrl register "c3" for COP1 has value 3
+ p3 func fill 0x1f:24-20 ; function "fill" for COP3 has value 31 and
+ ; no fields
+
+will allow the assembler to accept the following coprocessor instructions:
+
+ LWC1 d1,0x100 ($2)
+ fill
+
+Here, the general purpose register "$2", and instruction "LWC1", are standard
+mnemonics built-in to the MIPS assembler.
+
+
+Example 2:
+
+The table:
+
+ p3 dreg d3 3 ; data register "d3" for COP3 has value 3
+ p3 creg c2 22 ; control register "c2" for COP3 has value 22
+ p3 func fee 0x1f:24-20 dreg:17-13 creg:12-8 immed:7-0
+ ; function "fee" for COP3 has value 31, and 3 fields
+ ; consisting of a data register, a control register,
+ ; and an immediate value.
+
+will allow the assembler to accept the following coprocessor instruction:
+
+ fee d3,c2,0x1
+
+and will emit the object code:
+
+ 31-26 25 24-20 19-18 17-13 12-8 7-0
+ COPz CO fun dreg creg immed
+ 010011 1 11111 00 00011 10110 00000001
+
+ 0x4ff07601
+
+
+Example 3:
+
+The table:
+
+ p3 dreg d3 3 ; data register "d3" for COP3 has value 3
+ p3 creg c2 22 ; control register "c2" for COP3 has value 22
+ p3 func fuu 0x01f00001 dreg:17-13 creg:12-8
+
+will allow the assembler to accept the following coprocessor
+instruction:
+
+ fuu d3,c2
+
+and will emit the object code:
+
+ 31-26 25 24-20 19-18 17-13 12-8 7-0
+ COPz CO fun dreg creg
+ 010011 1 11111 00 00011 10110 00000001
+
+ 0x4ff07601
+
+In this way, the programmer can force arbitrary bits of an instruction
+to have predefined values.
+
+=======================================================================
+Additional notes:
+
+Encoding of ranges:
+To handle more than one bit position range within an instruction,
+use 0s to mask out the ranges which don't apply.
+May decide to modify the syntax to allow commas separate multiple
+ranges within an instruction (range','range).
+
+Changes in grammar:
+ The number of parms argument to the function entry
+was deleted from the original format such that we now count the fields.
+
+----
+FIXME! should really change lexical analyzer
+to recognize 'dreg' etc. in context sensative way.
+Currently function names or mnemonics may be incorrectly parsed as keywords
+
+FIXME! hex is ambiguous with any digit
+
+*/
+
+#include <stdio.h>
+#include "itbl-ops.h"
+
+/* #define DEBUG */
+
+#ifdef DEBUG
+#ifndef DBG_LVL
+#define DBG_LVL 1
+#endif
+#else
+#define DBG_LVL 0
+#endif
+
+#if DBG_LVL >= 1
+#define DBG(x) printf x
+#else
+#define DBG(x)
+#endif
+
+#if DBG_LVL >= 2
+#define DBGL2(x) printf x
+#else
+#define DBGL2(x)
+#endif
+
+static int sbit, ebit;
+static struct itbl_entry *insn=0;
+extern int insntbl_line;
+int yyparse PARAMS ((void));
+int yylex PARAMS ((void));
+static int yyerror PARAMS ((const char *));
+
+%}
+
+%union
+ {
+ char *str;
+ int num;
+ int processor;
+ unsigned long val;
+ }
+
+%token DREG CREG GREG IMMED ADDR INSN NUM ID NL PNUM
+%type <val> value flags flagexpr
+%type <num> number NUM ftype regtype pnum PNUM
+%type <str> ID name
+
+%start insntbl
+
+%%
+
+insntbl:
+ entrys
+ ;
+
+entrys:
+ entry entrys
+ |
+ ;
+
+entry:
+ pnum regtype name value NL
+ {
+ DBG (("line %d: entry pnum=%d type=%d name=%s value=x%x\n",
+ insntbl_line, $1, $2, $3, $4));
+ itbl_add_reg ($1, $2, $3, $4);
+ }
+ | pnum INSN name value range flags
+ {
+ DBG (("line %d: entry pnum=%d type=INSN name=%s value=x%x",
+ insntbl_line, $1, $3, $4));
+ DBG ((" sbit=%d ebit=%d flags=0x%x\n", sbit, ebit, $6));
+ insn=itbl_add_insn ($1, $3, $4, sbit, ebit, $6);
+ }
+ fieldspecs NL
+ | NL
+ | error NL
+ ;
+
+fieldspecs:
+ ',' fieldspec fieldspecs
+ | fieldspec fieldspecs
+ |
+ ;
+
+ftype:
+ regtype
+ {
+ DBGL2 (("ftype\n"));
+ $$ = $1;
+ }
+ | ADDR
+ {
+ DBGL2 (("addr\n"));
+ $$ = ADDR;
+ }
+ | IMMED
+ {
+ DBGL2 (("immed\n"));
+ $$ = IMMED;
+ }
+ ;
+
+fieldspec:
+ ftype range flags
+ {
+ DBG (("line %d: field type=%d sbit=%d ebit=%d, flags=0x%x\n",
+ insntbl_line, $1, sbit, ebit, $3));
+ itbl_add_operand (insn, $1, sbit, ebit, $3);
+ }
+ ;
+
+flagexpr:
+ NUM '|' flagexpr
+ {
+ $$ = $1 | $3;
+ }
+ | '[' flagexpr ']'
+ {
+ $$ = $2;
+ }
+ | NUM
+ {
+ $$ = $1;
+ }
+ ;
+
+flags:
+ '*' flagexpr
+ {
+ DBGL2 (("flags=%d\n", $2));
+ $$ = $2;
+ }
+ |
+ {
+ $$ = 0;
+ }
+ ;
+
+range:
+ ':' NUM '-' NUM
+ {
+ DBGL2 (("range %d %d\n", $2, $4));
+ sbit = $2;
+ ebit = $4;
+ }
+ |
+ {
+ sbit = 31;
+ ebit = 0;
+ }
+ ;
+
+pnum:
+ PNUM
+ {
+ DBGL2 (("pnum=%d\n",$1));
+ $$ = $1;
+ }
+ ;
+
+regtype:
+ DREG
+ {
+ DBGL2 (("dreg\n"));
+ $$ = DREG;
+ }
+ | CREG
+ {
+ DBGL2 (("creg\n"));
+ $$ = CREG;
+ }
+ | GREG
+ {
+ DBGL2 (("greg\n"));
+ $$ = GREG;
+ }
+ ;
+
+name:
+ ID
+ {
+ DBGL2 (("name=%s\n",$1));
+ $$ = $1;
+ }
+ ;
+
+number:
+ NUM
+ {
+ DBGL2 (("num=%d\n",$1));
+ $$ = $1;
+ }
+ ;
+
+value:
+ NUM
+ {
+ DBGL2 (("val=x%x\n",$1));
+ $$ = $1;
+ }
+ ;
+%%
+
+static int
+yyerror (msg)
+ const char *msg;
+{
+ printf ("line %d: %s\n", insntbl_line, msg);
+ return 0;
+}
diff --git a/gas/link.cmd b/gas/link.cmd
new file mode 100644
index 0000000000..a035ca87da
--- /dev/null
+++ b/gas/link.cmd
@@ -0,0 +1,10 @@
+ALIGN=1024
+RESNUM 0x0000, 0x8000
+; Putting in .lit1 gives errors.
+ORDER .data=0x80002000, .data1, .lit, .bss
+; Let's put this on the command line so it goes first, which is what
+; GDB expects.
+; LOAD /s2/amd/29k/lib/crt0.o
+LOAD /s2/amd/29k/lib/libqcb0h.lib
+LOAD /s2/amd/29k/lib/libscb0h.lib
+LOAD /s2/amd/29k/lib/libacb0h.lib
diff --git a/gas/listing.c b/gas/listing.c
new file mode 100644
index 0000000000..e2b173be7d
--- /dev/null
+++ b/gas/listing.c
@@ -0,0 +1,1420 @@
+/* listing.c - mainting assembly listings
+ Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 1999
+ Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GAS 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 more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+/*
+ Contributed by Steve Chamberlain
+ sac@cygnus.com
+
+
+ A listing page looks like:
+
+ LISTING_HEADER sourcefilename pagenumber
+ TITLE LINE
+ SUBTITLE LINE
+ linenumber address data source
+ linenumber address data source
+ linenumber address data source
+ linenumber address data source
+
+ If not overridden, the listing commands are:
+
+ .title "stuff"
+ Put "stuff" onto the title line
+ .sbttl "stuff"
+ Put stuff onto the subtitle line
+
+ If these commands come within 10 lines of the top of the page, they
+ will affect the page they are on, as well as any subsequent page
+
+ .eject
+ Thow a page
+ .list
+ Increment the enable listing counter
+ .nolist
+ Decrement the enable listing counter
+
+ .psize Y[,X]
+ Set the paper size to X wide and Y high. Setting a psize Y of
+ zero will suppress form feeds except where demanded by .eject
+
+ If the counter goes below zero, listing is suppressed.
+
+
+ Listings are a maintained by read calling various listing_<foo>
+ functions. What happens most is that the macro NO_LISTING is not
+ defined (from the Makefile), then the macro LISTING_NEWLINE expands
+ into a call to listing_newline. The call is done from read.c, every
+ time it sees a newline, and -l is on the command line.
+
+ The function listing_newline remembers the frag associated with the
+ newline, and creates a new frag - note that this is wasteful, but not
+ a big deal, since listing slows things down a lot anyway. The
+ function also rememebers when the filename changes.
+
+ When all the input has finished, and gas has had a chance to settle
+ down, the listing is output. This is done by running down the list of
+ frag/source file records, and opening the files as needed and printing
+ out the bytes and chars associated with them.
+
+ The only things which the architecture can change about the listing
+ are defined in these macros:
+
+ LISTING_HEADER The name of the architecture
+ LISTING_WORD_SIZE The make of the number of bytes in a word, this determines
+ the clumping of the output data. eg a value of
+ 2 makes words look like 1234 5678, whilst 1
+ would make the same value look like 12 34 56
+ 78
+ LISTING_LHS_WIDTH Number of words of above size for the lhs
+
+ LISTING_LHS_WIDTH_SECOND Number of words for the data on the lhs
+ for the second line
+
+ LISTING_LHS_CONT_LINES Max number of lines to use up for a continutation
+ LISTING_RHS_WIDTH Number of chars from the input file to print
+ on a line
+*/
+
+#include <ctype.h>
+
+#include "as.h"
+#include <obstack.h>
+#include "input-file.h"
+#include "subsegs.h"
+
+#ifndef NO_LISTING
+
+#ifndef LISTING_HEADER
+#define LISTING_HEADER "GAS LISTING"
+#endif
+#ifndef LISTING_WORD_SIZE
+#define LISTING_WORD_SIZE 4
+#endif
+#ifndef LISTING_LHS_WIDTH
+#define LISTING_LHS_WIDTH 1
+#endif
+#ifndef LISTING_LHS_WIDTH_SECOND
+#define LISTING_LHS_WIDTH_SECOND 1
+#endif
+#ifndef LISTING_RHS_WIDTH
+#define LISTING_RHS_WIDTH 100
+#endif
+#ifndef LISTING_LHS_CONT_LINES
+#define LISTING_LHS_CONT_LINES 4
+#endif
+
+/* This structure remembers which .s were used */
+typedef struct file_info_struct
+{
+ struct file_info_struct * next;
+ char * filename;
+ long pos;
+ unsigned int linenum;
+ int at_end;
+}
+file_info_type;
+
+/* This structure rememebrs which line from which file goes into which
+ frag */
+struct list_info_struct
+{
+ /* Frag which this line of source is nearest to */
+ fragS * frag;
+
+ /* The actual line in the source file */
+ unsigned int line;
+ /* Pointer to the file info struct for the file which this line
+ belongs to */
+ file_info_type * file;
+
+ /* The expanded text of any macro that may have been executing. */
+ char * line_contents;
+
+ /* Next in list */
+ struct list_info_struct * next;
+
+ /* Pointer to the file info struct for the high level language
+ source line that belongs here */
+ file_info_type * hll_file;
+ /* High level language source line */
+ unsigned int hll_line;
+
+ /* Pointer to any error message associated with this line */
+ char * message;
+
+ enum
+ {
+ EDICT_NONE,
+ EDICT_SBTTL,
+ EDICT_TITLE,
+ EDICT_NOLIST,
+ EDICT_LIST,
+ EDICT_NOLIST_NEXT,
+ EDICT_EJECT
+ } edict;
+ char * edict_arg;
+
+ /* Nonzero if this line is to be omitted because it contains
+ debugging information. This can become a flags field if we come
+ up with more information to store here. */
+ int debugging;
+};
+
+typedef struct list_info_struct list_info_type;
+
+
+int listing_lhs_width = LISTING_LHS_WIDTH;
+int listing_lhs_width_second = LISTING_LHS_WIDTH_SECOND;
+int listing_lhs_cont_lines = LISTING_LHS_CONT_LINES;
+int listing_rhs_width = LISTING_RHS_WIDTH;
+
+struct list_info_struct * listing_tail;
+
+static file_info_type * file_info_head;
+static file_info_type * last_open_file_info;
+static FILE * last_open_file;
+static struct list_info_struct * head;
+static int paper_width = 200;
+static int paper_height = 60;
+
+extern int listing;
+
+/* File to output listings to. */
+static FILE * list_file;
+
+/* This static array is used to keep the text of data to be printed
+ before the start of the line. */
+
+#define MAX_BYTES \
+ (((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width \
+ + ((((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width_second) \
+ * listing_lhs_cont_lines) \
+ + 20)
+
+static char * data_buffer;
+
+/* Prototypes. */
+static void listing_message PARAMS ((const char *name, const char *message));
+static file_info_type * file_info PARAMS ((const char *file_name));
+static void new_frag PARAMS ((void));
+static char * buffer_line PARAMS ((file_info_type *file,
+ char *line, unsigned int size));
+static void listing_page PARAMS ((list_info_type *list));
+static unsigned int calc_hex PARAMS ((list_info_type *list));
+static void print_lines PARAMS ((list_info_type *, unsigned int,
+ char *, unsigned int));
+static void list_symbol_table PARAMS ((void));
+static void print_source PARAMS ((file_info_type *current_file,
+ list_info_type *list,
+ char *buffer,
+ unsigned int width));
+static int debugging_pseudo PARAMS ((list_info_type *, const char *));
+static void listing_listing PARAMS ((char *name));
+
+
+static void
+listing_message (name, message)
+ const char *name;
+ const char *message;
+{
+ unsigned int l = strlen (name) + strlen (message) + 1;
+ char *n = (char *) xmalloc (l);
+ strcpy (n, name);
+ strcat (n, message);
+ if (listing_tail != (list_info_type *) NULL)
+ {
+ listing_tail->message = n;
+ }
+}
+
+void
+listing_warning (message)
+ const char *message;
+{
+ listing_message (_("Warning:"), message);
+}
+
+void
+listing_error (message)
+ const char *message;
+{
+ listing_message (_("Error:"), message);
+}
+
+static file_info_type *
+file_info (file_name)
+ const char *file_name;
+{
+ /* Find an entry with this file name */
+ file_info_type *p = file_info_head;
+
+ while (p != (file_info_type *) NULL)
+ {
+ if (strcmp (p->filename, file_name) == 0)
+ return p;
+ p = p->next;
+ }
+
+ /* Make new entry */
+
+ p = (file_info_type *) xmalloc (sizeof (file_info_type));
+ p->next = file_info_head;
+ file_info_head = p;
+ p->filename = xmalloc ((unsigned long) strlen (file_name) + 1);
+ strcpy (p->filename, file_name);
+ p->pos = 0;
+ p->linenum = 0;
+ p->at_end = 0;
+
+ return p;
+}
+
+
+static void
+new_frag ()
+{
+
+ frag_wane (frag_now);
+ frag_new (0);
+
+}
+
+void
+listing_newline (ps)
+ char *ps;
+{
+ char *file;
+ unsigned int line;
+ static unsigned int last_line = 0xffff;
+ static char *last_file = NULL;
+ list_info_type *new = NULL;
+
+ if (listing == 0)
+ return;
+
+ if (now_seg == absolute_section)
+ return;
+
+#ifdef OBJ_ELF
+ /* In ELF, anything in a section beginning with .debug or .line is
+ considered to be debugging information. This includes the
+ statement which switches us into the debugging section, which we
+ can only set after we are already in the debugging section. */
+ if ((listing & LISTING_NODEBUG) != 0
+ && listing_tail != NULL
+ && ! listing_tail->debugging)
+ {
+ const char *segname;
+
+ segname = segment_name (now_seg);
+ if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0
+ || strncmp (segname, ".line", sizeof ".line" - 1) == 0)
+ listing_tail->debugging = 1;
+ }
+#endif
+
+ as_where (&file, &line);
+ if (ps == NULL)
+ {
+ if (line == last_line && !(last_file && file && strcmp (file, last_file)))
+ return;
+
+ new = (list_info_type *) xmalloc (sizeof (list_info_type));
+
+ /* Detect if we are reading from stdin by examining the file
+ name returned by as_where().
+
+ [FIXME: We rely upon the name in the strcmp below being the
+ same as the one used by input_scrub_new_file(), if that is
+ not true, then this code will fail].
+
+ If we are reading from stdin, then we need to save each input line
+ here (assuming of course that we actually have a line of input to read),
+ so that it can be displayed in the listing that is produced at the end
+ of the assembly. */
+ if (strcmp (file, _("{standard input}")) == 0
+ && input_line_pointer != NULL)
+ {
+ char * copy;
+ int len;
+ int seen_quote = 0;
+
+ for (copy = input_line_pointer - 1;
+ * copy && (seen_quote
+ || (! is_end_of_line [(unsigned char) * copy]));
+ copy ++)
+ if (* copy == '"' && copy[-1] != '\\')
+ seen_quote = ! seen_quote;
+
+ len = (copy - input_line_pointer) + 2;
+
+ copy = xmalloc (len);
+
+ if (copy != NULL)
+ {
+ char * src = input_line_pointer - 1;
+ char * dest = copy;
+
+ while (--len)
+ {
+ char c = * src ++;
+
+ /* Omit control characters in the listing. */
+ if (isascii (c) && ! iscntrl (c))
+ * dest ++ = c;
+ }
+
+ *dest = 0;
+ }
+
+ new->line_contents = copy;
+ }
+ else
+ new->line_contents = NULL;
+ }
+ else
+ {
+ new = (list_info_type *) xmalloc (sizeof (list_info_type));
+ new->line_contents = ps;
+ }
+
+ last_line = line;
+ last_file = file;
+
+ new_frag ();
+
+ if (listing_tail)
+ listing_tail->next = new;
+ else
+ head = new;
+
+ listing_tail = new;
+
+ new->frag = frag_now;
+ new->line = line;
+ new->file = file_info (file);
+ new->next = (list_info_type *) NULL;
+ new->message = (char *) NULL;
+ new->edict = EDICT_NONE;
+ new->hll_file = (file_info_type *) NULL;
+ new->hll_line = 0;
+ new->debugging = 0;
+
+ new_frag ();
+
+#ifdef OBJ_ELF
+ /* In ELF, anything in a section beginning with .debug or .line is
+ considered to be debugging information. */
+ if ((listing & LISTING_NODEBUG) != 0)
+ {
+ const char *segname;
+
+ segname = segment_name (now_seg);
+ if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0
+ || strncmp (segname, ".line", sizeof ".line" - 1) == 0)
+ new->debugging = 1;
+ }
+#endif
+}
+
+/* Attach all current frags to the previous line instead of the
+ current line. This is called by the MIPS backend when it discovers
+ that it needs to add some NOP instructions; the added NOP
+ instructions should go with the instruction that has the delay, not
+ with the new instruction. */
+
+void
+listing_prev_line ()
+{
+ list_info_type *l;
+ fragS *f;
+
+ if (head == (list_info_type *) NULL
+ || head == listing_tail)
+ return;
+
+ new_frag ();
+
+ for (l = head; l->next != listing_tail; l = l->next)
+ ;
+
+ for (f = frchain_now->frch_root; f != (fragS *) NULL; f = f->fr_next)
+ if (f->line == listing_tail)
+ f->line = l;
+
+ listing_tail->frag = frag_now;
+ new_frag ();
+}
+
+/*
+ This function returns the next source line from the file supplied,
+ truncated to size. It appends a fake line to the end of each input
+ file to make
+*/
+
+static char *
+buffer_line (file, line, size)
+ file_info_type * file;
+ char *line;
+ unsigned int size;
+{
+ unsigned int count = 0;
+ int c;
+
+ char *p = line;
+
+ /* If we couldn't open the file, return an empty line */
+ if (file->at_end)
+ return "";
+
+ /* Check the cache and see if we last used this file. */
+ if (!last_open_file_info || file != last_open_file_info)
+ {
+ if (last_open_file)
+ {
+ last_open_file_info->pos = ftell (last_open_file);
+ fclose (last_open_file);
+ }
+
+ last_open_file_info = file;
+ last_open_file = fopen (file->filename, "r");
+ if (last_open_file == NULL)
+ {
+ file->at_end = 1;
+ return "";
+ }
+
+ /* Seek to where we were last time this file was open. */
+ if (file->pos)
+ fseek(last_open_file, file->pos, SEEK_SET);
+ }
+
+ c = fgetc (last_open_file);
+
+ size -= 1; /* leave room for null */
+
+ while (c != EOF && c != '\n')
+ {
+ if (count < size)
+ *p++ = c;
+ count++;
+
+ c = fgetc (last_open_file);
+
+ }
+ if (c == EOF)
+ {
+ file->at_end = 1;
+ *p++ = '.';
+ *p++ = '.';
+ *p++ = '.';
+ }
+ file->linenum++;
+ *p++ = 0;
+ return line;
+}
+
+
+static const char *fn;
+
+static unsigned int eject; /* Eject pending */
+static unsigned int page; /* Current page number */
+static char *title; /* current title */
+static char *subtitle; /* current subtitle */
+static unsigned int on_page; /* number of lines printed on current page */
+
+
+static void
+listing_page (list)
+ list_info_type *list;
+{
+ /* Grope around, see if we can see a title or subtitle edict coming up
+ soon (we look down 10 lines of the page and see if it's there)*/
+ if ((eject || (on_page >= (unsigned int) paper_height)) && paper_height != 0)
+ {
+ unsigned int c = 10;
+ int had_title = 0;
+ int had_subtitle = 0;
+
+ page++;
+
+ while (c != 0 && list)
+ {
+ if (list->edict == EDICT_SBTTL && !had_subtitle)
+ {
+ had_subtitle = 1;
+ subtitle = list->edict_arg;
+ }
+ if (list->edict == EDICT_TITLE && !had_title)
+ {
+ had_title = 1;
+ title = list->edict_arg;
+ }
+ list = list->next;
+ c--;
+ }
+
+
+ if (page > 1)
+ {
+ fprintf (list_file, "\f");
+ }
+
+ fprintf (list_file, "%s %s \t\t\tpage %d\n", LISTING_HEADER, fn, page);
+ fprintf (list_file, "%s\n", title);
+ fprintf (list_file, "%s\n", subtitle);
+ on_page = 3;
+ eject = 0;
+ }
+}
+
+
+static unsigned int
+calc_hex (list)
+ list_info_type * list;
+{
+ int data_buffer_size;
+ list_info_type *first = list;
+ unsigned int address = ~ (unsigned int) 0;
+ fragS *frag;
+ fragS *frag_ptr;
+ unsigned int byte_in_frag;
+
+ /* Find first frag which says it belongs to this line */
+ frag = list->frag;
+ while (frag && frag->line != list)
+ frag = frag->fr_next;
+
+ frag_ptr = frag;
+
+ data_buffer_size = 0;
+
+ /* Dump all the frags which belong to this line */
+ while (frag_ptr != (fragS *) NULL && frag_ptr->line == first)
+ {
+ /* Print as many bytes from the fixed part as is sensible */
+ byte_in_frag = 0;
+ while ((offsetT) byte_in_frag < frag_ptr->fr_fix
+ && data_buffer_size < MAX_BYTES - 3)
+ {
+ if (address == ~ (unsigned int) 0)
+ {
+ address = frag_ptr->fr_address;
+ }
+
+ sprintf (data_buffer + data_buffer_size,
+ "%02X",
+ (frag_ptr->fr_literal[byte_in_frag]) & 0xff);
+ data_buffer_size += 2;
+ byte_in_frag++;
+ }
+ {
+ unsigned int var_rep_max = byte_in_frag;
+ unsigned int var_rep_idx = byte_in_frag;
+
+ /* Print as many bytes from the variable part as is sensible */
+ while (((offsetT) byte_in_frag
+ < frag_ptr->fr_fix + frag_ptr->fr_var * frag_ptr->fr_offset)
+ && data_buffer_size < MAX_BYTES - 3)
+ {
+ if (address == ~ (unsigned int) 0)
+ {
+ address = frag_ptr->fr_address;
+ }
+ sprintf (data_buffer + data_buffer_size,
+ "%02X",
+ (frag_ptr->fr_literal[var_rep_idx]) & 0xff);
+#if 0
+ data_buffer[data_buffer_size++] = '*';
+ data_buffer[data_buffer_size++] = '*';
+#endif
+ data_buffer_size += 2;
+
+ var_rep_idx++;
+ byte_in_frag++;
+
+ if ((offsetT) var_rep_idx >= frag_ptr->fr_fix + frag_ptr->fr_var)
+ var_rep_idx = var_rep_max;
+ }
+ }
+
+ frag_ptr = frag_ptr->fr_next;
+ }
+ data_buffer[data_buffer_size] = '\0';
+ return address;
+}
+
+
+
+
+
+
+static void
+print_lines (list, lineno, string, address)
+ list_info_type *list;
+ unsigned int lineno;
+ char *string;
+ unsigned int address;
+{
+ unsigned int idx;
+ unsigned int nchars;
+ unsigned int lines;
+ unsigned int byte_in_word = 0;
+ char *src = data_buffer;
+
+ /* Print the stuff on the first line */
+ listing_page (list);
+ nchars = (LISTING_WORD_SIZE * 2 + 1) * listing_lhs_width;
+
+ /* Print the hex for the first line */
+ if (address == ~ (unsigned int) 0)
+ {
+ fprintf (list_file, "% 4d ", lineno);
+ for (idx = 0; idx < nchars; idx++)
+ fprintf (list_file, " ");
+
+ fprintf (list_file, "\t%s\n", string ? string : "");
+
+ on_page ++;
+
+ listing_page (0);
+
+ return;
+ }
+
+ if (had_errors ())
+ fprintf (list_file, "% 4d ???? ", lineno);
+ else
+ fprintf (list_file, "% 4d %04x ", lineno, address);
+
+ /* And the data to go along with it */
+ idx = 0;
+
+ while (*src && idx < nchars)
+ {
+ fprintf (list_file, "%c%c", src[0], src[1]);
+ src += 2;
+ byte_in_word++;
+
+ if (byte_in_word == LISTING_WORD_SIZE)
+ {
+ fprintf (list_file, " ");
+ idx++;
+ byte_in_word = 0;
+ }
+
+ idx += 2;
+ }
+
+ for (; idx < nchars; idx++)
+ fprintf (list_file, " ");
+
+ fprintf (list_file, "\t%s\n", string ? string : "");
+ on_page++;
+ listing_page (list);
+
+ if (list->message)
+ {
+ fprintf (list_file, "**** %s\n", list->message);
+ listing_page (list);
+ on_page++;
+ }
+
+ for (lines = 0;
+ lines < (unsigned int) listing_lhs_cont_lines
+ && *src;
+ lines ++)
+ {
+ nchars = ((LISTING_WORD_SIZE * 2) + 1)
+ * listing_lhs_width_second - 1;
+ idx = 0;
+
+ /* Print any more lines of data, but more compactly */
+ fprintf (list_file, "% 4d ", lineno);
+
+ while (*src && idx < nchars)
+ {
+ fprintf (list_file, "%c%c", src[0], src[1]);
+ src += 2;
+ idx += 2;
+ byte_in_word++;
+
+ if (byte_in_word == LISTING_WORD_SIZE)
+ {
+ fprintf (list_file, " ");
+ idx++;
+ byte_in_word = 0;
+ }
+ }
+
+ fprintf (list_file, "\n");
+ on_page ++;
+ listing_page (list);
+ }
+}
+
+
+static void
+list_symbol_table ()
+{
+ extern symbolS *symbol_rootP;
+ int got_some = 0;
+
+ symbolS *ptr;
+ eject = 1;
+ listing_page (0);
+
+ for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
+ {
+ if (SEG_NORMAL (S_GET_SEGMENT (ptr))
+ || S_GET_SEGMENT (ptr) == absolute_section)
+ {
+#ifdef BFD_ASSEMBLER
+ /* Don't report section symbols. They are not interesting. */
+ if (ptr->bsym->flags & BSF_SECTION_SYM)
+ continue;
+#endif
+ if (S_GET_NAME (ptr))
+ {
+ char buf[30], fmt[8];
+ valueT val = S_GET_VALUE (ptr);
+
+ /* @@ Note that this is dependent on the compilation options,
+ not solely on the target characteristics. */
+ if (sizeof (val) == 4 && sizeof (int) == 4)
+ sprintf (buf, "%08lx", (unsigned long) val);
+ else if (sizeof (val) <= sizeof (unsigned long))
+ {
+ sprintf (fmt, "%%0%lulx",
+ (unsigned long) (sizeof (val) * 2));
+ sprintf (buf, fmt, (unsigned long) val);
+ }
+#if defined (BFD64)
+ else if (sizeof (val) > 4)
+ sprintf_vma (buf, val);
+#endif
+ else
+ abort ();
+
+ if (!got_some)
+ {
+ fprintf (list_file, "DEFINED SYMBOLS\n");
+ on_page++;
+ got_some = 1;
+ }
+
+ if (ptr->sy_frag && ptr->sy_frag->line)
+ {
+ fprintf (list_file, "%20s:%-5d %s:%s %s\n",
+ ptr->sy_frag->line->file->filename,
+ ptr->sy_frag->line->line,
+ segment_name (S_GET_SEGMENT (ptr)),
+ buf, S_GET_NAME (ptr));
+ }
+ else
+ {
+ fprintf (list_file, "%33s:%s %s\n",
+ segment_name (S_GET_SEGMENT (ptr)),
+ buf, S_GET_NAME (ptr));
+ }
+
+ on_page ++;
+ listing_page (0);
+ }
+ }
+
+ }
+ if (!got_some)
+ {
+ fprintf (list_file, "NO DEFINED SYMBOLS\n");
+ on_page++;
+ }
+ fprintf (list_file, "\n");
+ on_page++;
+ listing_page (0);
+
+ got_some = 0;
+
+ for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
+ {
+ if (S_GET_NAME (ptr) && strlen (S_GET_NAME (ptr)) != 0)
+ {
+ if (S_GET_SEGMENT (ptr) == undefined_section)
+ {
+ if (!got_some)
+ {
+ got_some = 1;
+ fprintf (list_file, "UNDEFINED SYMBOLS\n");
+ on_page++;
+ listing_page (0);
+ }
+ fprintf (list_file, "%s\n", S_GET_NAME (ptr));
+ on_page++;
+ listing_page (0);
+ }
+ }
+ }
+ if (!got_some)
+ {
+ fprintf (list_file, "NO UNDEFINED SYMBOLS\n");
+ on_page++;
+ listing_page (0);
+ }
+}
+
+static void
+print_source (current_file, list, buffer, width)
+ file_info_type *current_file;
+ list_info_type *list;
+ char *buffer;
+ unsigned int width;
+{
+ if (!current_file->at_end)
+ {
+ while (current_file->linenum < list->hll_line
+ && !current_file->at_end)
+ {
+ char *p = buffer_line (current_file, buffer, width);
+ fprintf (list_file, "%4u:%-13s **** %s\n", current_file->linenum,
+ current_file->filename, p);
+ on_page++;
+ listing_page (list);
+ }
+ }
+}
+
+/* Sometimes the user doesn't want to be bothered by the debugging
+ records inserted by the compiler, see if the line is suspicious. */
+
+static int
+debugging_pseudo (list, line)
+ list_info_type *list;
+ const char *line;
+{
+ static int in_debug;
+ int was_debug;
+
+ if (list->debugging)
+ {
+ in_debug = 1;
+ return 1;
+ }
+
+ was_debug = in_debug;
+ in_debug = 0;
+
+ while (isspace ((unsigned char) *line))
+ line++;
+
+ if (*line != '.')
+ {
+#ifdef OBJ_ELF
+ /* The ELF compiler sometimes emits blank lines after switching
+ out of a debugging section. If the next line drops us back
+ into debugging information, then don't print the blank line.
+ This is a hack for a particular compiler behaviour, not a
+ general case. */
+ if (was_debug
+ && *line == '\0'
+ && list->next != NULL
+ && list->next->debugging)
+ {
+ in_debug = 1;
+ return 1;
+ }
+#endif
+
+ return 0;
+ }
+
+ line++;
+
+ if (strncmp (line, "def", 3) == 0)
+ return 1;
+ if (strncmp (line, "val", 3) == 0)
+ return 1;
+ if (strncmp (line, "scl", 3) == 0)
+ return 1;
+ if (strncmp (line, "line", 4) == 0)
+ return 1;
+ if (strncmp (line, "endef", 5) == 0)
+ return 1;
+ if (strncmp (line, "ln", 2) == 0)
+ return 1;
+ if (strncmp (line, "type", 4) == 0)
+ return 1;
+ if (strncmp (line, "size", 4) == 0)
+ return 1;
+ if (strncmp (line, "dim", 3) == 0)
+ return 1;
+ if (strncmp (line, "tag", 3) == 0)
+ return 1;
+
+ if (strncmp (line, "stabs", 5) == 0)
+ return 1;
+ if (strncmp (line, "stabn", 5) == 0)
+ return 1;
+
+ return 0;
+}
+
+static void
+listing_listing (name)
+ char *name;
+{
+ list_info_type *list = head;
+ file_info_type *current_hll_file = (file_info_type *) NULL;
+ char *message;
+ char *buffer;
+ char *p;
+ int show_listing = 1;
+ unsigned int width;
+
+ buffer = xmalloc (listing_rhs_width);
+ data_buffer = xmalloc (MAX_BYTES);
+ eject = 1;
+ list = head;
+
+ while (list != (list_info_type *) NULL && 0)
+ {
+ if (list->next)
+ list->frag = list->next->frag;
+ list = list->next;
+
+ }
+
+ list = head->next;
+
+
+ while (list)
+ {
+ int list_line;
+
+ width = listing_rhs_width > paper_width ? paper_width :
+ listing_rhs_width;
+
+ list_line = list->line;
+ switch (list->edict)
+ {
+ case EDICT_LIST:
+ /* Skip all lines up to the current. */
+ list_line--;
+ break;
+ case EDICT_NOLIST:
+ show_listing--;
+ break;
+ case EDICT_NOLIST_NEXT:
+ break;
+ case EDICT_EJECT:
+ break;
+ case EDICT_NONE:
+ break;
+ case EDICT_TITLE:
+ title = list->edict_arg;
+ break;
+ case EDICT_SBTTL:
+ subtitle = list->edict_arg;
+ break;
+ default:
+ abort ();
+ }
+
+ if (show_listing <= 0)
+ {
+ while (list->file->linenum < list_line
+ && !list->file->at_end)
+ p = buffer_line (list->file, buffer, width);
+ }
+
+ if (list->edict == EDICT_LIST)
+ {
+ /* Enable listing for the single line that caused the enable. */
+ list_line++;
+ show_listing++;
+ }
+
+ if (show_listing > 0)
+ {
+ /* Scan down the list and print all the stuff which can be done
+ with this line (or lines). */
+ message = 0;
+
+ if (list->hll_file)
+ {
+ current_hll_file = list->hll_file;
+ }
+
+ if (current_hll_file && list->hll_line && (listing & LISTING_HLL))
+ {
+ print_source (current_hll_file, list, buffer, width);
+ }
+
+ if (list->line_contents)
+ {
+ if (!((listing & LISTING_NODEBUG)
+ && debugging_pseudo (list, list->line_contents)))
+ {
+ print_lines (list,
+ list->file->linenum == 0 ? list->line : list->file->linenum,
+ list->line_contents, calc_hex (list));
+ }
+ free (list->line_contents);
+ list->line_contents = NULL;
+ }
+ else
+ {
+ while (list->file->linenum < list_line
+ && !list->file->at_end)
+ {
+ unsigned int address;
+
+ p = buffer_line (list->file, buffer, width);
+
+ if (list->file->linenum < list_line)
+ address = ~ (unsigned int) 0;
+ else
+ address = calc_hex (list);
+
+ if (!((listing & LISTING_NODEBUG)
+ && debugging_pseudo (list, p)))
+ print_lines (list, list->file->linenum, p, address);
+ }
+ }
+
+ if (list->edict == EDICT_EJECT)
+ {
+ eject = 1;
+ }
+ }
+
+ if (list->edict == EDICT_NOLIST_NEXT)
+ --show_listing;
+
+ list = list->next;
+ }
+
+ free (buffer);
+ free (data_buffer);
+ data_buffer = NULL;
+}
+
+void
+listing_print (name)
+ char *name;
+{
+ int using_stdout;
+
+ title = "";
+ subtitle = "";
+
+ if (name == NULL)
+ {
+ list_file = stdout;
+ using_stdout = 1;
+ }
+ else
+ {
+ list_file = fopen (name, "w");
+ if (list_file != NULL)
+ using_stdout = 0;
+ else
+ {
+ as_perror (_("can't open list file: %s"), name);
+ list_file = stdout;
+ using_stdout = 1;
+ }
+ }
+
+ if (listing & LISTING_NOFORM)
+ {
+ paper_height = 0;
+ }
+
+ if (listing & LISTING_LISTING)
+ {
+ listing_listing (name);
+ }
+
+ if (listing & LISTING_SYMBOLS)
+ {
+ list_symbol_table ();
+ }
+
+ if (! using_stdout)
+ {
+ if (fclose (list_file) == EOF)
+ as_perror (_("error closing list file: %s"), name);
+ }
+
+ if (last_open_file)
+ {
+ fclose (last_open_file);
+ }
+}
+
+
+void
+listing_file (name)
+ const char *name;
+{
+ fn = name;
+}
+
+void
+listing_eject (ignore)
+ int ignore;
+{
+ if (listing)
+ listing_tail->edict = EDICT_EJECT;
+}
+
+void
+listing_flags (ignore)
+ int ignore;
+{
+ while ((*input_line_pointer++) && (*input_line_pointer != '\n'))
+ input_line_pointer++;
+
+}
+
+/* Turn listing on or off. An argument of 0 means to turn off
+ listing. An argument of 1 means to turn on listing. An argument
+ of 2 means to turn off listing, but as of the next line; that is,
+ the current line should be listed, but the next line should not. */
+
+void
+listing_list (on)
+ int on;
+{
+ if (listing)
+ {
+ switch (on)
+ {
+ case 0:
+ if (listing_tail->edict == EDICT_LIST)
+ listing_tail->edict = EDICT_NONE;
+ else
+ listing_tail->edict = EDICT_NOLIST;
+ break;
+ case 1:
+ if (listing_tail->edict == EDICT_NOLIST
+ || listing_tail->edict == EDICT_NOLIST_NEXT)
+ listing_tail->edict = EDICT_NONE;
+ else
+ listing_tail->edict = EDICT_LIST;
+ break;
+ case 2:
+ listing_tail->edict = EDICT_NOLIST_NEXT;
+ break;
+ default:
+ abort ();
+ }
+ }
+}
+
+
+void
+listing_psize (width_only)
+ int width_only;
+{
+ if (! width_only)
+ {
+ paper_height = get_absolute_expression ();
+
+ if (paper_height < 0 || paper_height > 1000)
+ {
+ paper_height = 0;
+ as_warn (_("strange paper height, set to no form"));
+ }
+
+ if (*input_line_pointer != ',')
+ {
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ ++input_line_pointer;
+ }
+
+ paper_width = get_absolute_expression ();
+
+ demand_empty_rest_of_line ();
+}
+
+void
+listing_nopage (ignore)
+ int ignore;
+{
+ paper_height = 0;
+}
+
+void
+listing_title (depth)
+ int depth;
+{
+ int quoted;
+ char *start;
+ char *ttl;
+ unsigned int length;
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != '\"')
+ quoted = 0;
+ else
+ {
+ quoted = 1;
+ ++input_line_pointer;
+ }
+
+ start = input_line_pointer;
+
+ while (*input_line_pointer)
+ {
+ if (quoted
+ ? *input_line_pointer == '\"'
+ : is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ if (listing)
+ {
+ length = input_line_pointer - start;
+ ttl = xmalloc (length + 1);
+ memcpy (ttl, start, length);
+ ttl[length] = 0;
+ listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
+ listing_tail->edict_arg = ttl;
+ }
+ if (quoted)
+ input_line_pointer++;
+ demand_empty_rest_of_line ();
+ return;
+ }
+ else if (*input_line_pointer == '\n')
+ {
+ as_bad (_("New line in title"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+ else
+ {
+ input_line_pointer++;
+ }
+ }
+}
+
+
+
+void
+listing_source_line (line)
+ unsigned int line;
+{
+ if (listing)
+ {
+ new_frag ();
+ listing_tail->hll_line = line;
+ new_frag ();
+ }
+}
+
+void
+listing_source_file (file)
+ const char *file;
+{
+ if (listing)
+ listing_tail->hll_file = file_info (file);
+}
+
+
+
+#else
+
+
+/* Dummy functions for when compiled without listing enabled */
+
+void
+listing_flags (ignore)
+ int ignore;
+{
+ s_ignore (0);
+}
+
+void
+listing_list (on)
+ int on;
+{
+ s_ignore (0);
+}
+
+void
+listing_eject (ignore)
+ int ignore;
+{
+ s_ignore (0);
+}
+
+void
+listing_psize (ignore)
+ int ignore;
+{
+ s_ignore (0);
+}
+
+void
+listing_nopage (ignore)
+ int ignore;
+{
+ s_ignore (0);
+}
+
+void
+listing_title (depth)
+ int depth;
+{
+ s_ignore (0);
+}
+
+void
+listing_file (name)
+ const char *name;
+{
+
+}
+
+void
+listing_newline (name)
+ char *name;
+{
+
+}
+
+void
+listing_source_line (n)
+ unsigned int n;
+{
+
+}
+void
+listing_source_file (n)
+ const char *n;
+{
+
+}
+
+#endif
diff --git a/gas/listing.h b/gas/listing.h
new file mode 100644
index 0000000000..c0d5c373e5
--- /dev/null
+++ b/gas/listing.h
@@ -0,0 +1,67 @@
+/* This file is listing.h
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 1997
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#ifndef __listing_h__
+#define __listing_h__
+
+#define LISTING_LISTING 1
+#define LISTING_SYMBOLS 2
+#define LISTING_NOFORM 4
+#define LISTING_HLL 8
+#define LISTING_NODEBUG 16
+#define LISTING_NOCOND 32
+#define LISTING_MACEXP 64
+
+#define LISTING_DEFAULT (LISTING_LISTING | LISTING_HLL | LISTING_SYMBOLS)
+
+#ifndef NO_LISTING
+#define LISTING_NEWLINE() { if (listing) listing_newline(NULL); }
+#else
+#define LISTING_NEWLINE() {;}
+#endif
+#define LISTING_EOF() LISTING_NEWLINE()
+
+#define LISTING_SKIP_COND() ((listing & LISTING_NOCOND) != 0)
+
+void listing_eject PARAMS ((int));
+void listing_error PARAMS ((const char *message));
+void listing_file PARAMS ((const char *name));
+void listing_flags PARAMS ((int));
+void listing_list PARAMS ((int on));
+void listing_newline PARAMS ((char *ps));
+void listing_prev_line PARAMS ((void));
+void listing_print PARAMS ((char *name));
+void listing_psize PARAMS ((int));
+void listing_nopage PARAMS ((int));
+void listing_source_file PARAMS ((const char *));
+void listing_source_line PARAMS ((unsigned int));
+void listing_title PARAMS ((int depth));
+void listing_warning PARAMS ((const char *message));
+void listing_width PARAMS ((unsigned int x));
+
+extern int listing_lhs_width;
+extern int listing_lhs_width_second;
+extern int listing_lhs_cont_lines;
+extern int listing_rhs_width;
+
+#endif /* __listing_h__ */
+
+/* end of listing.h */
diff --git a/gas/literal.c b/gas/literal.c
new file mode 100644
index 0000000000..a3f8fc4da1
--- /dev/null
+++ b/gas/literal.c
@@ -0,0 +1,95 @@
+/* as.c - GAS literal pool management.
+ Copyright (C) 1994 Free Software Foundation, Inc.
+ Written by Ken Raeburn (raeburn@cygnus.com).
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This isn't quite a "constant" pool. Some of the values may get
+ adjusted at run time, e.g., for symbolic relocations when shared
+ libraries are in use. It's more of a "literal" pool.
+
+ On the Alpha, this should be used for .lita and .lit8. (Is there
+ ever a .lit4?) On the MIPS, it could be used for .lit4 as well.
+
+ The expressions passed here should contain either constants or symbols,
+ not a combination of both. Typically, the constant pool is accessed
+ with some sort of GP register, so the size of the pool must be kept down
+ if possible. The exception is section offsets -- if you're storing a
+ pointer to the start of .data, for example, and your machine provides
+ for 16-bit signed addends, you might want to store .data+32K, so that
+ you can access all of the first 64K of .data with the one pointer.
+
+ This isn't a requirement, just a guideline that can help keep .o file
+ size down. */
+
+#include "as.h"
+#include "subsegs.h"
+
+#if defined (BFD_ASSEMBLER) && defined (NEED_LITERAL_POOL)
+
+valueT
+add_to_literal_pool (sym, addend, sec, size)
+ symbolS *sym;
+ valueT addend;
+ segT sec;
+ int size;
+{
+ segT current_section = now_seg;
+ int current_subsec = now_subseg;
+ valueT offset;
+ bfd_reloc_code_real_type reloc_type;
+ char *p;
+ segment_info_type *seginfo = seg_info (sec);
+ fixS *fixp;
+
+ offset = 0;
+ /* @@ This assumes all entries in a given section will be of the same
+ size... Probably correct, but unwise to rely on. */
+ /* This must always be called with the same subsegment. */
+ if (seginfo->frchainP)
+ for (fixp = seginfo->frchainP->fix_root;
+ fixp != (fixS *) NULL;
+ fixp = fixp->fx_next, offset += size)
+ {
+ if (fixp->fx_addsy == sym && fixp->fx_offset == addend)
+ return offset;
+ }
+
+ subseg_set (sec, 0);
+ p = frag_more (size);
+ memset (p, 0, size);
+
+ switch (size)
+ {
+ case 4:
+ reloc_type = BFD_RELOC_32;
+ break;
+ case 8:
+ reloc_type = BFD_RELOC_64;
+ break;
+ default:
+ abort ();
+ }
+ fix_new (frag_now, p - frag_now->fr_literal, size, sym, addend, 0,
+ reloc_type);
+
+ subseg_set (current_section, current_subsec);
+ offset = seginfo->literal_pool_size;
+ seginfo->literal_pool_size += size;
+ return offset;
+}
+#endif /* BFD_ASSEMBLER */
diff --git a/gas/mac-as.r b/gas/mac-as.r
new file mode 100644
index 0000000000..f36c033cb0
--- /dev/null
+++ b/gas/mac-as.r
@@ -0,0 +1,42 @@
+/* Resources for GNU AS. */
+
+#include "SysTypes.r"
+
+/* Version resources. */
+
+resource 'vers' (1) {
+ 0,
+ 0,
+ 0,
+ 0,
+ verUs,
+ VERSION_STRING,
+ VERSION_STRING " (C) 1986-95 FSF, Inc."
+};
+
+resource 'vers' (2, purgeable) {
+ 0,
+ 0,
+ 0,
+ 0,
+ verUs,
+ VERSION_STRING,
+ "GAS " VERSION_STRING " for MPW"
+};
+
+#ifdef WANT_CFRG
+
+#include "CodeFragmentTypes.r"
+
+resource 'cfrg' (0) {
+ {
+ kPowerPC,
+ kFullLib,
+ kNoVersionNum, kNoVersionNum,
+ 0,0,
+ kIsApp, kOnDiskFlat, kZeroOffset, kWholeFork,
+ PROG_NAME
+ }
+};
+
+#endif /* WANT_CFRG */
diff --git a/gas/macro.c b/gas/macro.c
new file mode 100644
index 0000000000..9d92ff4f1b
--- /dev/null
+++ b/gas/macro.c
@@ -0,0 +1,1259 @@
+/* macro.c - macro support for gas and gasp
+ Copyright (C) 1994, 95, 96, 97, 1998 Free Software Foundation, Inc.
+
+ Written by Steve and Judy Chamberlain of Cygnus Support,
+ sac@cygnus.com
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include "config.h"
+
+/* AIX requires this to be the first thing in the file. */
+#ifdef __GNUC__
+# ifndef alloca
+# ifdef __STDC__
+extern void *alloca ();
+# else
+extern char *alloca ();
+# endif
+# endif
+#else
+# if HAVE_ALLOCA_H
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca /* predefined by HP cc +Olibcalls */
+# if !defined (__STDC__) && !defined (__hpux)
+extern char *alloca ();
+# else
+extern void *alloca ();
+# endif /* __STDC__, __hpux */
+# endif /* alloca */
+# endif /* _AIX */
+# endif /* HAVE_ALLOCA_H */
+#endif
+
+#include <stdio.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#include <ctype.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include "libiberty.h"
+#include "sb.h"
+#include "hash.h"
+#include "macro.h"
+
+#include "asintl.h"
+
+/* The routines in this file handle macro definition and expansion.
+ They are called by both gasp and gas. */
+
+/* Structures used to store macros.
+
+ Each macro knows its name and included text. It gets built with a
+ list of formal arguments, and also keeps a hash table which points
+ into the list to speed up formal search. Each formal knows its
+ name and its default value. Each time the macro is expanded, the
+ formals get the actual values attatched to them. */
+
+/* describe the formal arguments to a macro */
+
+typedef struct formal_struct
+ {
+ struct formal_struct *next; /* next formal in list */
+ sb name; /* name of the formal */
+ sb def; /* the default value */
+ sb actual; /* the actual argument (changed on each expansion) */
+ int index; /* the index of the formal 0..formal_count-1 */
+ }
+formal_entry;
+
+/* Other values found in the index field of a formal_entry. */
+#define QUAL_INDEX (-1)
+#define NARG_INDEX (-2)
+#define LOCAL_INDEX (-3)
+
+/* describe the macro. */
+
+typedef struct macro_struct
+ {
+ sb sub; /* substitution text. */
+ int formal_count; /* number of formal args. */
+ formal_entry *formals; /* pointer to list of formal_structs */
+ struct hash_control *formal_hash; /* hash table of formals. */
+ }
+macro_entry;
+
+/* Internal functions. */
+
+static int get_token PARAMS ((int, sb *, sb *));
+static int getstring PARAMS ((int, sb *, sb *));
+static int get_any_string PARAMS ((int, sb *, sb *, int, int));
+static int do_formals PARAMS ((macro_entry *, int, sb *));
+static int get_apost_token PARAMS ((int, sb *, sb *, int));
+static int sub_actual
+ PARAMS ((int, sb *, sb *, struct hash_control *, int, sb *, int));
+static const char *macro_expand_body
+ PARAMS ((sb *, sb *, formal_entry *, struct hash_control *, int, int));
+static const char *macro_expand PARAMS ((int, sb *, macro_entry *, sb *, int));
+
+#define ISWHITE(x) ((x) == ' ' || (x) == '\t')
+
+#define ISSEP(x) \
+ ((x) == ' ' || (x) == '\t' || (x) == ',' || (x) == '"' || (x) == ';' \
+ || (x) == ')' || (x) == '(' \
+ || ((macro_alternate || macro_mri) && ((x) == '<' || (x) == '>')))
+
+#define ISBASE(x) \
+ ((x) == 'b' || (x) == 'B' \
+ || (x) == 'q' || (x) == 'Q' \
+ || (x) == 'h' || (x) == 'H' \
+ || (x) == 'd' || (x) == 'D')
+
+/* The macro hash table. */
+
+static struct hash_control *macro_hash;
+
+/* Whether any macros have been defined. */
+
+int macro_defined;
+
+/* Whether we are in GASP alternate mode. */
+
+static int macro_alternate;
+
+/* Whether we are in MRI mode. */
+
+static int macro_mri;
+
+/* Whether we should strip '@' characters. */
+
+static int macro_strip_at;
+
+/* Function to use to parse an expression. */
+
+static int (*macro_expr) PARAMS ((const char *, int, sb *, int *));
+
+/* Number of macro expansions that have been done. */
+
+static int macro_number;
+
+/* Initialize macro processing. */
+
+void
+macro_init (alternate, mri, strip_at, expr)
+ int alternate;
+ int mri;
+ int strip_at;
+ int (*expr) PARAMS ((const char *, int, sb *, int *));
+{
+ macro_hash = hash_new ();
+ macro_defined = 0;
+ macro_alternate = alternate;
+ macro_mri = mri;
+ macro_strip_at = strip_at;
+ macro_expr = expr;
+}
+
+/* Switch in and out of MRI mode on the fly. */
+
+void
+macro_mri_mode (mri)
+ int mri;
+{
+ macro_mri = mri;
+}
+
+/* Read input lines till we get to a TO string.
+ Increase nesting depth if we get a FROM string.
+ Put the results into sb at PTR.
+ Add a new input line to an sb using GET_LINE.
+ Return 1 on success, 0 on unexpected EOF. */
+
+int
+buffer_and_nest (from, to, ptr, get_line)
+ const char *from;
+ const char *to;
+ sb *ptr;
+ int (*get_line) PARAMS ((sb *));
+{
+ int from_len = strlen (from);
+ int to_len = strlen (to);
+ int depth = 1;
+ int line_start = ptr->len;
+
+ int more = get_line (ptr);
+
+ while (more)
+ {
+ /* Try and find the first pseudo op on the line */
+ int i = line_start;
+
+ if (! macro_alternate && ! macro_mri)
+ {
+ /* With normal syntax we can suck what we want till we get
+ to the dot. With the alternate, labels have to start in
+ the first column, since we cant tell what's a label and
+ whats a pseudoop */
+
+ /* Skip leading whitespace */
+ while (i < ptr->len && ISWHITE (ptr->ptr[i]))
+ i++;
+
+ /* Skip over a label */
+ while (i < ptr->len
+ && (isalnum ((unsigned char) ptr->ptr[i])
+ || ptr->ptr[i] == '_'
+ || ptr->ptr[i] == '$'))
+ i++;
+
+ /* And a colon */
+ if (i < ptr->len
+ && ptr->ptr[i] == ':')
+ i++;
+
+ }
+ /* Skip trailing whitespace */
+ while (i < ptr->len && ISWHITE (ptr->ptr[i]))
+ i++;
+
+ if (i < ptr->len && (ptr->ptr[i] == '.'
+ || macro_alternate
+ || macro_mri))
+ {
+ if (ptr->ptr[i] == '.')
+ i++;
+ if (strncasecmp (ptr->ptr + i, from, from_len) == 0)
+ depth++;
+ if (strncasecmp (ptr->ptr + i, to, to_len) == 0)
+ {
+ depth--;
+ if (depth == 0)
+ {
+ /* Reset the string to not include the ending rune */
+ ptr->len = line_start;
+ break;
+ }
+ }
+ }
+
+ /* Add a CR to the end and keep running */
+ sb_add_char (ptr, '\n');
+ line_start = ptr->len;
+ more = get_line (ptr);
+ }
+
+ /* Return 1 on success, 0 on unexpected EOF. */
+ return depth == 0;
+}
+
+/* Pick up a token. */
+
+static int
+get_token (idx, in, name)
+ int idx;
+ sb *in;
+ sb *name;
+{
+ if (idx < in->len
+ && (isalpha ((unsigned char) in->ptr[idx])
+ || in->ptr[idx] == '_'
+ || in->ptr[idx] == '$'))
+ {
+ sb_add_char (name, in->ptr[idx++]);
+ while (idx < in->len
+ && (isalnum ((unsigned char) in->ptr[idx])
+ || in->ptr[idx] == '_'
+ || in->ptr[idx] == '$'))
+ {
+ sb_add_char (name, in->ptr[idx++]);
+ }
+ }
+ /* Ignore trailing & */
+ if (macro_alternate && idx < in->len && in->ptr[idx] == '&')
+ idx++;
+ return idx;
+}
+
+/* Pick up a string. */
+
+static int
+getstring (idx, in, acc)
+ int idx;
+ sb *in;
+ sb *acc;
+{
+ idx = sb_skip_white (idx, in);
+
+ while (idx < in->len
+ && (in->ptr[idx] == '"'
+ || (in->ptr[idx] == '<' && (macro_alternate || macro_mri))
+ || (in->ptr[idx] == '\'' && macro_alternate)))
+ {
+ if (in->ptr[idx] == '<')
+ {
+ int nest = 0;
+ idx++;
+ while ((in->ptr[idx] != '>' || nest)
+ && idx < in->len)
+ {
+ if (in->ptr[idx] == '!')
+ {
+ idx++ ;
+ sb_add_char (acc, in->ptr[idx++]);
+ }
+ else
+ {
+ if (in->ptr[idx] == '>')
+ nest--;
+ if (in->ptr[idx] == '<')
+ nest++;
+ sb_add_char (acc, in->ptr[idx++]);
+ }
+ }
+ idx++;
+ }
+ else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
+ {
+ char tchar = in->ptr[idx];
+ idx++;
+ while (idx < in->len)
+ {
+ if (macro_alternate && in->ptr[idx] == '!')
+ {
+ idx++ ;
+ sb_add_char (acc, in->ptr[idx++]);
+ }
+ else
+ {
+ if (in->ptr[idx] == tchar)
+ {
+ idx++;
+ if (idx >= in->len || in->ptr[idx] != tchar)
+ break;
+ }
+ sb_add_char (acc, in->ptr[idx]);
+ idx++;
+ }
+ }
+ }
+ }
+
+ return idx;
+}
+
+/* Fetch string from the input stream,
+ rules:
+ 'Bxyx<whitespace> -> return 'Bxyza
+ %<char> -> return string of decimal value of x
+ "<string>" -> return string
+ xyx<whitespace> -> return xyz
+*/
+
+static int
+get_any_string (idx, in, out, expand, pretend_quoted)
+ int idx;
+ sb *in;
+ sb *out;
+ int expand;
+ int pretend_quoted;
+{
+ sb_reset (out);
+ idx = sb_skip_white (idx, in);
+
+ if (idx < in->len)
+ {
+ if (in->len > 2 && in->ptr[idx+1] == '\'' && ISBASE (in->ptr[idx]))
+ {
+ while (!ISSEP (in->ptr[idx]))
+ sb_add_char (out, in->ptr[idx++]);
+ }
+ else if (in->ptr[idx] == '%'
+ && macro_alternate
+ && expand)
+ {
+ int val;
+ char buf[20];
+ /* Turns the next expression into a string */
+ idx = (*macro_expr) (_("% operator needs absolute expression"),
+ idx + 1,
+ in,
+ &val);
+ sprintf(buf, "%d", val);
+ sb_add_string (out, buf);
+ }
+ else if (in->ptr[idx] == '"'
+ || (in->ptr[idx] == '<' && (macro_alternate || macro_mri))
+ || (macro_alternate && in->ptr[idx] == '\''))
+ {
+ if (macro_alternate
+ && ! macro_strip_at
+ && expand)
+ {
+ /* Keep the quotes */
+ sb_add_char (out, '\"');
+
+ idx = getstring (idx, in, out);
+ sb_add_char (out, '\"');
+ }
+ else
+ {
+ idx = getstring (idx, in, out);
+ }
+ }
+ else
+ {
+ while (idx < in->len
+ && (in->ptr[idx] == '"'
+ || in->ptr[idx] == '\''
+ || pretend_quoted
+ || (in->ptr[idx] != ' '
+ && in->ptr[idx] != '\t'
+ && in->ptr[idx] != ','
+ && (in->ptr[idx] != '<'
+ || (! macro_alternate && ! macro_mri)))))
+ {
+ if (in->ptr[idx] == '"'
+ || in->ptr[idx] == '\'')
+ {
+ char tchar = in->ptr[idx];
+ sb_add_char (out, in->ptr[idx++]);
+ while (idx < in->len
+ && in->ptr[idx] != tchar)
+ sb_add_char (out, in->ptr[idx++]);
+ if (idx == in->len)
+ return idx;
+ }
+ sb_add_char (out, in->ptr[idx++]);
+ }
+ }
+ }
+
+ return idx;
+}
+
+/* Pick up the formal parameters of a macro definition. */
+
+static int
+do_formals (macro, idx, in)
+ macro_entry *macro;
+ int idx;
+ sb *in;
+{
+ formal_entry **p = &macro->formals;
+
+ macro->formal_count = 0;
+ macro->formal_hash = hash_new ();
+ while (idx < in->len)
+ {
+ formal_entry *formal;
+
+ formal = (formal_entry *) xmalloc (sizeof (formal_entry));
+
+ sb_new (&formal->name);
+ sb_new (&formal->def);
+ sb_new (&formal->actual);
+
+ idx = sb_skip_white (idx, in);
+ idx = get_token (idx, in, &formal->name);
+ if (formal->name.len == 0)
+ break;
+ idx = sb_skip_white (idx, in);
+ if (formal->name.len)
+ {
+ /* This is a formal */
+ if (idx < in->len && in->ptr[idx] == '=')
+ {
+ /* Got a default */
+ idx = get_any_string (idx + 1, in, &formal->def, 1, 0);
+ }
+ }
+
+ /* Add to macro's hash table */
+ hash_jam (macro->formal_hash, sb_terminate (&formal->name), formal);
+
+ formal->index = macro->formal_count;
+ idx = sb_skip_comma (idx, in);
+ macro->formal_count++;
+ *p = formal;
+ p = &formal->next;
+ *p = NULL;
+ }
+
+ if (macro_mri)
+ {
+ formal_entry *formal;
+ const char *name;
+
+ /* Add a special NARG formal, which macro_expand will set to the
+ number of arguments. */
+ formal = (formal_entry *) xmalloc (sizeof (formal_entry));
+
+ sb_new (&formal->name);
+ sb_new (&formal->def);
+ sb_new (&formal->actual);
+
+ /* The same MRI assemblers which treat '@' characters also use
+ the name $NARG. At least until we find an exception. */
+ if (macro_strip_at)
+ name = "$NARG";
+ else
+ name = "NARG";
+
+ sb_add_string (&formal->name, name);
+
+ /* Add to macro's hash table */
+ hash_jam (macro->formal_hash, name, formal);
+
+ formal->index = NARG_INDEX;
+ *p = formal;
+ formal->next = NULL;
+ }
+
+ return idx;
+}
+
+/* Define a new macro. Returns NULL on success, otherwise returns an
+ error message. If NAMEP is not NULL, *NAMEP is set to the name of
+ the macro which was defined. */
+
+const char *
+define_macro (idx, in, label, get_line, namep)
+ int idx;
+ sb *in;
+ sb *label;
+ int (*get_line) PARAMS ((sb *));
+ const char **namep;
+{
+ macro_entry *macro;
+ sb name;
+ const char *namestr;
+
+ macro = (macro_entry *) xmalloc (sizeof (macro_entry));
+ sb_new (&macro->sub);
+ sb_new (&name);
+
+ macro->formal_count = 0;
+ macro->formals = 0;
+
+ idx = sb_skip_white (idx, in);
+ if (! buffer_and_nest ("MACRO", "ENDM", &macro->sub, get_line))
+ return _("unexpected end of file in macro definition");
+ if (label != NULL && label->len != 0)
+ {
+ sb_add_sb (&name, label);
+ if (idx < in->len && in->ptr[idx] == '(')
+ {
+ /* It's the label: MACRO (formals,...) sort */
+ idx = do_formals (macro, idx + 1, in);
+ if (in->ptr[idx] != ')')
+ return _("missing ) after formals");
+ }
+ else
+ {
+ /* It's the label: MACRO formals,... sort */
+ idx = do_formals (macro, idx, in);
+ }
+ }
+ else
+ {
+ idx = get_token (idx, in, &name);
+ idx = sb_skip_comma (idx, in);
+ idx = do_formals (macro, idx, in);
+ }
+
+ /* and stick it in the macro hash table */
+ for (idx = 0; idx < name.len; idx++)
+ if (isupper ((unsigned char) name.ptr[idx]))
+ name.ptr[idx] = tolower (name.ptr[idx]);
+ namestr = sb_terminate (&name);
+ hash_jam (macro_hash, namestr, (PTR) macro);
+
+ macro_defined = 1;
+
+ if (namep != NULL)
+ *namep = namestr;
+
+ return NULL;
+}
+
+/* Scan a token, and then skip KIND. */
+
+static int
+get_apost_token (idx, in, name, kind)
+ int idx;
+ sb *in;
+ sb *name;
+ int kind;
+{
+ idx = get_token (idx, in, name);
+ if (idx < in->len
+ && in->ptr[idx] == kind
+ && (! macro_mri || macro_strip_at)
+ && (! macro_strip_at || kind == '@'))
+ idx++;
+ return idx;
+}
+
+/* Substitute the actual value for a formal parameter. */
+
+static int
+sub_actual (start, in, t, formal_hash, kind, out, copyifnotthere)
+ int start;
+ sb *in;
+ sb *t;
+ struct hash_control *formal_hash;
+ int kind;
+ sb *out;
+ int copyifnotthere;
+{
+ int src;
+ formal_entry *ptr;
+
+ src = get_apost_token (start, in, t, kind);
+ /* See if it's in the macro's hash table, unless this is
+ macro_strip_at and kind is '@' and the token did not end in '@'. */
+ if (macro_strip_at
+ && kind == '@'
+ && (src == start || in->ptr[src - 1] != '@'))
+ ptr = NULL;
+ else
+ ptr = (formal_entry *) hash_find (formal_hash, sb_terminate (t));
+ if (ptr)
+ {
+ if (ptr->actual.len)
+ {
+ sb_add_sb (out, &ptr->actual);
+ }
+ else
+ {
+ sb_add_sb (out, &ptr->def);
+ }
+ }
+ else if (kind == '&')
+ {
+ /* Doing this permits people to use & in macro bodies. */
+ sb_add_char (out, '&');
+ }
+ else if (copyifnotthere)
+ {
+ sb_add_sb (out, t);
+ }
+ else
+ {
+ sb_add_char (out, '\\');
+ sb_add_sb (out, t);
+ }
+ return src;
+}
+
+/* Expand the body of a macro. */
+
+static const char *
+macro_expand_body (in, out, formals, formal_hash, comment_char, locals)
+ sb *in;
+ sb *out;
+ formal_entry *formals;
+ struct hash_control *formal_hash;
+ int comment_char;
+ int locals;
+{
+ sb t;
+ int src = 0;
+ int inquote = 0;
+ formal_entry *loclist = NULL;
+
+ sb_new (&t);
+
+ while (src < in->len)
+ {
+ if (in->ptr[src] == '&')
+ {
+ sb_reset (&t);
+ if (macro_mri)
+ {
+ if (src + 1 < in->len && in->ptr[src + 1] == '&')
+ src = sub_actual (src + 2, in, &t, formal_hash, '\'', out, 1);
+ else
+ sb_add_char (out, in->ptr[src++]);
+ }
+ else
+ {
+ /* FIXME: Why do we do this? */
+ src = sub_actual (src + 1, in, &t, formal_hash, '&', out, 0);
+ }
+ }
+ else if (in->ptr[src] == '\\')
+ {
+ src++;
+ if (in->ptr[src] == comment_char && comment_char != '\0')
+ {
+ /* This is a comment, just drop the rest of the line */
+ while (src < in->len
+ && in->ptr[src] != '\n')
+ src++;
+ }
+ else if (in->ptr[src] == '(')
+ {
+ /* Sub in till the next ')' literally */
+ src++;
+ while (src < in->len && in->ptr[src] != ')')
+ {
+ sb_add_char (out, in->ptr[src++]);
+ }
+ if (in->ptr[src] == ')')
+ src++;
+ else
+ return _("missplaced )");
+ }
+ else if (in->ptr[src] == '@')
+ {
+ /* Sub in the macro invocation number */
+
+ char buffer[10];
+ src++;
+ sprintf (buffer, "%05d", macro_number);
+ sb_add_string (out, buffer);
+ }
+ else if (in->ptr[src] == '&')
+ {
+ /* This is a preprocessor variable name, we don't do them
+ here */
+ sb_add_char (out, '\\');
+ sb_add_char (out, '&');
+ src++;
+ }
+ else if (macro_mri
+ && isalnum ((unsigned char) in->ptr[src]))
+ {
+ int ind;
+ formal_entry *f;
+
+ if (isdigit ((unsigned char) in->ptr[src]))
+ ind = in->ptr[src] - '0';
+ else if (isupper ((unsigned char) in->ptr[src]))
+ ind = in->ptr[src] - 'A' + 10;
+ else
+ ind = in->ptr[src] - 'a' + 10;
+ ++src;
+ for (f = formals; f != NULL; f = f->next)
+ {
+ if (f->index == ind - 1)
+ {
+ if (f->actual.len != 0)
+ sb_add_sb (out, &f->actual);
+ else
+ sb_add_sb (out, &f->def);
+ break;
+ }
+ }
+ }
+ else
+ {
+ sb_reset (&t);
+ src = sub_actual (src, in, &t, formal_hash, '\'', out, 0);
+ }
+ }
+ else if ((macro_alternate || macro_mri)
+ && (isalpha ((unsigned char) in->ptr[src])
+ || in->ptr[src] == '_'
+ || in->ptr[src] == '$')
+ && (! inquote
+ || ! macro_strip_at
+ || (src > 0 && in->ptr[src - 1] == '@')))
+ {
+ if (! locals
+ || src + 5 >= in->len
+ || strncasecmp (in->ptr + src, "LOCAL", 5) != 0
+ || ! ISWHITE (in->ptr[src + 5]))
+ {
+ sb_reset (&t);
+ src = sub_actual (src, in, &t, formal_hash,
+ (macro_strip_at && inquote) ? '@' : '\'',
+ out, 1);
+ }
+ else
+ {
+ formal_entry *f;
+
+ src = sb_skip_white (src + 5, in);
+ while (in->ptr[src] != '\n' && in->ptr[src] != comment_char)
+ {
+ static int loccnt;
+ char buf[20];
+ const char *err;
+
+ f = (formal_entry *) xmalloc (sizeof (formal_entry));
+ sb_new (&f->name);
+ sb_new (&f->def);
+ sb_new (&f->actual);
+ f->index = LOCAL_INDEX;
+ f->next = loclist;
+ loclist = f;
+
+ src = get_token (src, in, &f->name);
+ ++loccnt;
+ sprintf (buf, "LL%04x", loccnt);
+ sb_add_string (&f->actual, buf);
+
+ err = hash_jam (formal_hash, sb_terminate (&f->name), f);
+ if (err != NULL)
+ return err;
+
+ src = sb_skip_comma (src, in);
+ }
+ }
+ }
+ else if (comment_char != '\0'
+ && in->ptr[src] == comment_char
+ && src + 1 < in->len
+ && in->ptr[src + 1] == comment_char
+ && !inquote)
+ {
+ /* Two comment chars in a row cause the rest of the line to
+ be dropped. */
+ while (src < in->len && in->ptr[src] != '\n')
+ src++;
+ }
+ else if (in->ptr[src] == '"'
+ || (macro_mri && in->ptr[src] == '\''))
+ {
+ inquote = !inquote;
+ sb_add_char (out, in->ptr[src++]);
+ }
+ else if (in->ptr[src] == '@' && macro_strip_at)
+ {
+ ++src;
+ if (src < in->len
+ && in->ptr[src] == '@')
+ {
+ sb_add_char (out, '@');
+ ++src;
+ }
+ }
+ else if (macro_mri
+ && in->ptr[src] == '='
+ && src + 1 < in->len
+ && in->ptr[src + 1] == '=')
+ {
+ formal_entry *ptr;
+
+ sb_reset (&t);
+ src = get_token (src + 2, in, &t);
+ ptr = (formal_entry *) hash_find (formal_hash, sb_terminate (&t));
+ if (ptr == NULL)
+ {
+ /* FIXME: We should really return a warning string here,
+ but we can't, because the == might be in the MRI
+ comment field, and, since the nature of the MRI
+ comment field depends upon the exact instruction
+ being used, we don't have enough information here to
+ figure out whether it is or not. Instead, we leave
+ the == in place, which should cause a syntax error if
+ it is not in a comment. */
+ sb_add_char (out, '=');
+ sb_add_char (out, '=');
+ sb_add_sb (out, &t);
+ }
+ else
+ {
+ if (ptr->actual.len)
+ {
+ sb_add_string (out, "-1");
+ }
+ else
+ {
+ sb_add_char (out, '0');
+ }
+ }
+ }
+ else
+ {
+ sb_add_char (out, in->ptr[src++]);
+ }
+ }
+
+ sb_kill (&t);
+
+ while (loclist != NULL)
+ {
+ formal_entry *f;
+
+ f = loclist->next;
+ hash_delete (formal_hash, sb_terminate (&loclist->name));
+ sb_kill (&loclist->name);
+ sb_kill (&loclist->def);
+ sb_kill (&loclist->actual);
+ free (loclist);
+ loclist = f;
+ }
+
+ return NULL;
+}
+
+/* Assign values to the formal parameters of a macro, and expand the
+ body. */
+
+static const char *
+macro_expand (idx, in, m, out, comment_char)
+ int idx;
+ sb *in;
+ macro_entry *m;
+ sb *out;
+ int comment_char;
+{
+ sb t;
+ formal_entry *ptr;
+ formal_entry *f;
+ int is_positional = 0;
+ int is_keyword = 0;
+ int narg = 0;
+ const char *err;
+
+ sb_new (&t);
+
+ /* Reset any old value the actuals may have */
+ for (f = m->formals; f; f = f->next)
+ sb_reset (&f->actual);
+ f = m->formals;
+ while (f != NULL && f->index < 0)
+ f = f->next;
+
+ if (macro_mri)
+ {
+ /* The macro may be called with an optional qualifier, which may
+ be referred to in the macro body as \0. */
+ if (idx < in->len && in->ptr[idx] == '.')
+ {
+ formal_entry *n;
+
+ n = (formal_entry *) xmalloc (sizeof (formal_entry));
+ sb_new (&n->name);
+ sb_new (&n->def);
+ sb_new (&n->actual);
+ n->index = QUAL_INDEX;
+
+ n->next = m->formals;
+ m->formals = n;
+
+ idx = get_any_string (idx + 1, in, &n->actual, 1, 0);
+ }
+ }
+
+ /* Peel off the actuals and store them away in the hash tables' actuals */
+ idx = sb_skip_white (idx, in);
+ while (idx < in->len && in->ptr[idx] != comment_char)
+ {
+ int scan;
+
+ /* Look and see if it's a positional or keyword arg */
+ scan = idx;
+ while (scan < in->len
+ && !ISSEP (in->ptr[scan])
+ && !(macro_mri && in->ptr[scan] == '\'')
+ && (!macro_alternate && in->ptr[scan] != '='))
+ scan++;
+ if (scan < in->len && !macro_alternate && in->ptr[scan] == '=')
+ {
+ is_keyword = 1;
+
+ /* It's OK to go from positional to keyword. */
+
+ /* This is a keyword arg, fetch the formal name and
+ then the actual stuff */
+ sb_reset (&t);
+ idx = get_token (idx, in, &t);
+ if (in->ptr[idx] != '=')
+ return _("confusion in formal parameters");
+
+ /* Lookup the formal in the macro's list */
+ ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t));
+ if (!ptr)
+ return _("macro formal argument does not exist");
+ else
+ {
+ /* Insert this value into the right place */
+ sb_reset (&ptr->actual);
+ idx = get_any_string (idx + 1, in, &ptr->actual, 0, 0);
+ if (ptr->actual.len > 0)
+ ++narg;
+ }
+ }
+ else
+ {
+ /* This is a positional arg */
+ is_positional = 1;
+ if (is_keyword)
+ return _("can't mix positional and keyword arguments");
+
+ if (!f)
+ {
+ formal_entry **pf;
+ int c;
+
+ if (!macro_mri)
+ return _("too many positional arguments");
+
+ f = (formal_entry *) xmalloc (sizeof (formal_entry));
+ sb_new (&f->name);
+ sb_new (&f->def);
+ sb_new (&f->actual);
+ f->next = NULL;
+
+ c = -1;
+ for (pf = &m->formals; *pf != NULL; pf = &(*pf)->next)
+ if ((*pf)->index >= c)
+ c = (*pf)->index + 1;
+ if (c == -1)
+ c = 0;
+ *pf = f;
+ f->index = c;
+ }
+
+ sb_reset (&f->actual);
+ idx = get_any_string (idx, in, &f->actual, 1, 0);
+ if (f->actual.len > 0)
+ ++narg;
+ do
+ {
+ f = f->next;
+ }
+ while (f != NULL && f->index < 0);
+ }
+
+ if (! macro_mri)
+ idx = sb_skip_comma (idx, in);
+ else
+ {
+ if (in->ptr[idx] == ',')
+ ++idx;
+ if (ISWHITE (in->ptr[idx]))
+ break;
+ }
+ }
+
+ if (macro_mri)
+ {
+ char buffer[20];
+
+ sb_reset (&t);
+ sb_add_string (&t, macro_strip_at ? "$NARG" : "NARG");
+ ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t));
+ sb_reset (&ptr->actual);
+ sprintf (buffer, "%d", narg);
+ sb_add_string (&ptr->actual, buffer);
+ }
+
+ err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash,
+ comment_char, 1);
+ if (err != NULL)
+ return err;
+
+ /* Discard any unnamed formal arguments. */
+ if (macro_mri)
+ {
+ formal_entry **pf;
+
+ pf = &m->formals;
+ while (*pf != NULL)
+ {
+ if ((*pf)->name.len != 0)
+ pf = &(*pf)->next;
+ else
+ {
+ sb_kill (&(*pf)->name);
+ sb_kill (&(*pf)->def);
+ sb_kill (&(*pf)->actual);
+ f = (*pf)->next;
+ free (*pf);
+ *pf = f;
+ }
+ }
+ }
+
+ sb_kill (&t);
+ macro_number++;
+
+ return NULL;
+}
+
+/* Check for a macro. If one is found, put the expansion into
+ *EXPAND. COMMENT_CHAR is the comment character--this is used by
+ gasp. Return 1 if a macro is found, 0 otherwise. */
+
+int
+check_macro (line, expand, comment_char, error)
+ const char *line;
+ sb *expand;
+ int comment_char;
+ const char **error;
+{
+ const char *s;
+ char *copy, *cs;
+ macro_entry *macro;
+ sb line_sb;
+
+ if (! isalpha ((unsigned char) *line)
+ && *line != '_'
+ && *line != '$'
+ && (! macro_mri || *line != '.'))
+ return 0;
+
+ s = line + 1;
+ while (isalnum ((unsigned char) *s)
+ || *s == '_'
+ || *s == '$')
+ ++s;
+
+ copy = (char *) alloca (s - line + 1);
+ memcpy (copy, line, s - line);
+ copy[s - line] = '\0';
+ for (cs = copy; *cs != '\0'; cs++)
+ if (isupper ((unsigned char) *cs))
+ *cs = tolower (*cs);
+
+ macro = (macro_entry *) hash_find (macro_hash, copy);
+
+ if (macro == NULL)
+ return 0;
+
+ /* Wrap the line up in an sb. */
+ sb_new (&line_sb);
+ while (*s != '\0' && *s != '\n' && *s != '\r')
+ sb_add_char (&line_sb, *s++);
+
+ sb_new (expand);
+ *error = macro_expand (0, &line_sb, macro, expand, comment_char);
+
+ sb_kill (&line_sb);
+
+ return 1;
+}
+
+/* Delete a macro. */
+
+void
+delete_macro (name)
+ const char *name;
+{
+ hash_delete (macro_hash, name);
+}
+
+/* Handle the MRI IRP and IRPC pseudo-ops. These are handled as a
+ combined macro definition and execution. This returns NULL on
+ success, or an error message otherwise. */
+
+const char *
+expand_irp (irpc, idx, in, out, get_line, comment_char)
+ int irpc;
+ int idx;
+ sb *in;
+ sb *out;
+ int (*get_line) PARAMS ((sb *));
+ int comment_char;
+{
+ const char *mn;
+ sb sub;
+ formal_entry f;
+ struct hash_control *h;
+ const char *err;
+
+ if (irpc)
+ mn = "IRPC";
+ else
+ mn = "IRP";
+
+ idx = sb_skip_white (idx, in);
+
+ sb_new (&sub);
+ if (! buffer_and_nest (mn, "ENDR", &sub, get_line))
+ return _("unexpected end of file in irp or irpc");
+
+ sb_new (&f.name);
+ sb_new (&f.def);
+ sb_new (&f.actual);
+
+ idx = get_token (idx, in, &f.name);
+ if (f.name.len == 0)
+ return _("missing model parameter");
+
+ h = hash_new ();
+ err = hash_jam (h, sb_terminate (&f.name), &f);
+ if (err != NULL)
+ return err;
+
+ f.index = 1;
+ f.next = NULL;
+
+ sb_reset (out);
+
+ idx = sb_skip_comma (idx, in);
+ if (idx >= in->len || in->ptr[idx] == comment_char)
+ {
+ /* Expand once with a null string. */
+ err = macro_expand_body (&sub, out, &f, h, comment_char, 0);
+ if (err != NULL)
+ return err;
+ }
+ else
+ {
+ if (irpc && in->ptr[idx] == '"')
+ ++idx;
+ while (idx < in->len && in->ptr[idx] != comment_char)
+ {
+ if (!irpc)
+ idx = get_any_string (idx, in, &f.actual, 1, 0);
+ else
+ {
+ if (in->ptr[idx] == '"')
+ {
+ int nxt;
+
+ nxt = sb_skip_white (idx + 1, in);
+ if (nxt >= in->len || in->ptr[nxt] == comment_char)
+ {
+ idx = nxt;
+ break;
+ }
+ }
+ sb_reset (&f.actual);
+ sb_add_char (&f.actual, in->ptr[idx]);
+ ++idx;
+ }
+ err = macro_expand_body (&sub, out, &f, h, comment_char, 0);
+ if (err != NULL)
+ return err;
+ if (!irpc)
+ idx = sb_skip_comma (idx, in);
+ else
+ idx = sb_skip_white (idx, in);
+ }
+ }
+
+ hash_die (h);
+ sb_kill (&sub);
+
+ return NULL;
+}
diff --git a/gas/macro.h b/gas/macro.h
new file mode 100644
index 0000000000..cdeea4ad3b
--- /dev/null
+++ b/gas/macro.h
@@ -0,0 +1,53 @@
+/* macro.h - header file for macro support for gas and gasp
+ Copyright (C) 1994, 95, 96, 97, 1998 Free Software Foundation, Inc.
+
+ Written by Steve and Judy Chamberlain of Cygnus Support,
+ sac@cygnus.com
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#ifndef MACRO_H
+
+#define MACRO_H
+
+#include "ansidecl.h"
+#include "sb.h"
+
+/* Whether any macros have been defined. */
+
+extern int macro_defined;
+
+/* The macro nesting level. */
+
+extern int macro_nest;
+
+extern int buffer_and_nest
+ PARAMS ((const char *, const char *, sb *, int (*) PARAMS ((sb *))));
+extern void macro_init
+ PARAMS ((int alternate, int mri, int strip_at,
+ int (*) PARAMS ((const char *, int, sb *, int *))));
+extern void macro_mri_mode PARAMS ((int));
+extern const char *define_macro
+ PARAMS ((int idx, sb *in, sb *label, int (*get_line) PARAMS ((sb *)),
+ const char **namep));
+extern int check_macro PARAMS ((const char *, sb *, int, const char **));
+extern void delete_macro PARAMS ((const char *));
+extern const char *expand_irp
+ PARAMS ((int, int, sb *, sb *, int (*) PARAMS ((sb *)), int));
+
+#endif
diff --git a/gas/makefile.vms b/gas/makefile.vms
new file mode 100644
index 0000000000..f4c30d47dd
--- /dev/null
+++ b/gas/makefile.vms
@@ -0,0 +1,124 @@
+#
+# makefile for gas
+#
+# Created by Klaus K"ampf, kkaempf@progis.de
+#
+CC=gcc
+ifeq ($(ARCH),ALPHA)
+ifeq ($(CC),gcc)
+DEFS=
+CFLAGS=/include=([],[-.bfd],[.config],[-.include],[-])$(DEFS)
+LFLAGS=
+LIBS=,GNU_CC_LIBRARY:libgcc/lib,sys$$library:vaxcrtl.olb/lib,GNU_CC_LIBRARY:crt0.obj
+else
+DEFS=/define=("table_size_of_flonum_powers_of_ten"="tabsiz_flonum_powers_of_ten",\
+"_bfd_generic_get_section_contents_in_window"="_bfd_generic_get_win_section_cont",\
+"_elf_section_from_bfd_section"="_bfd_elf_sec_from_bfd_sec","const=")
+CFLAGS=/noopt/nodebug/include=([],[-.bfd],[.config],[-.include],[-])$(DEFS)\
+/warnings=disable=(missingreturn,implicitfunc,ptrmismatch,undefescap,longextern,duptypespec)
+LFLAGS=
+LIBS=,sys$$library:vaxcrtl.olb/lib
+endif
+
+else # ARCH not ALPHA
+
+ifeq ($(CC),gcc)
+DEFS=
+CFLAGS=/include=([],[.config],[-.include],[-])$(DEFS)
+LFLAGS=
+LIBS=,GNU_CC_LIBRARY:libgcc/lib,sys$$library:vaxcrtl.olb/lib,GNU_CC_LIBRARY:crtbegin.obj,GNU_CC_LIBRARY:crtend.obj
+#LIBS=,gnu_cc:[000000]gcclib.olb/lib,sys$$library:vaxcrtl.olb/lib
+else
+error DECC is broken on VAX
+DEFS=/define=("table_size_of_flonum_powers_of_ten"="tabsiz_flonum_powers_of_ten","const=")
+CFLAGS=/noopt/debug/include=([],[.config],[-.include],[-])$(DEFS)\
+/warnings=disable=(missingreturn,implicitfunc,ptrmismatch,undefescap,longextern,duptypespec)
+LFLAGS=
+LIBS=,sys$$library:vaxcrtl.olb/lib
+endif
+endif
+
+
+OBJS=targ-cpu.obj,obj-format.obj,atof-targ.obj,app.obj,as.obj,atof-generic.obj,\
+ bignum-copy.obj,cond.obj,depend.obj,expr.obj,flonum-konst.obj,flonum-copy.obj,\
+ flonum-mult.obj,frags.obj,hash.obj,input-file.obj,input-scrub.obj,\
+ literal.obj,messages.obj,output-file.obj,read.obj,subsegs.obj,symbols.obj,\
+ write.obj,listing.obj,ecoff.obj,stabs.obj,sb.obj,macro.obj,ehopt.obj
+
+GASPOBJS = gasp.obj,macro.obj,sb.obj,hash.obj
+
+LIBIBERTY = [-.libiberty]libiberty.olb
+
+ifeq ($(ARCH),ALPHA)
+LIBBFD = [-.bfd]libbfd.olb
+LIBOPCODES = [-.opcodes]libopcodes.olb
+BFDDEP = [-.bfd]bfd.h
+else
+LIBBFD =
+LIBOPCODES =
+BFDDEP =
+endif
+
+all: config.status $(BFDDEP) as.exe gasp.exe
+
+as.exe: $(OBJS) $(LIBOPCODES) $(LIBBFD) $(LIBIBERTY)
+ifeq ($(ARCH),ALPHA)
+ link$(LFLAGS)/exe=$@ $(OBJS),$(LIBOPCODES)/lib,$(LIBBFD)/lib,$(LIBIBERTY)/lib$(LIBS)
+else
+ link$(LFLAGS)/exe=$@ $(OBJS),$(LIBIBERTY)/lib$(LIBS)
+endif
+
+gasp.exe: $(GASPOBJS) $(LIBBFD) $(LIBIBERTY)
+ifeq ($(ARCH),ALPHA)
+ link$(LFLAGS)/exe=$@ $(GASPOBJS),$(LIBBFD)/lib,$(LIBIBERTY)/lib$(LIBS)
+else
+ link$(LFLAGS)/exe=$@ $(GASPOBJS),$(LIBIBERTY)/lib$(LIBS)
+endif
+
+config.status:
+ $$ @config-gas
+
+ifeq ($(ARCH),ALPHA)
+CPU=alpha
+OBJFORMAT=evax
+FLTFORMAT=ieee
+else
+CPU=vax
+OBJFORMAT=vms
+FLTFORMAT=vax
+endif
+
+targ-cpu.c: [.config]tc-$(CPU).c
+ copy $< $@
+targ-cpu.h: [.config]tc-$(CPU).h
+ copy $< $@
+targ-env.h: [.config]te-generic.h
+ copy $< $@
+obj-format.h: [.config]obj-$(OBJFORMAT).h
+ copy $< $@
+obj-format.c: [.config]obj-$(OBJFORMAT).c
+ copy $< $@
+atof-targ.c: [.config]atof-$(FLTFORMAT).c
+ copy $< $@
+
+targ-cpu.obj: targ-cpu.c targ-cpu.h [.config]atof-vax.c
+
+[-.bfd]bfd.h:
+ $(CD) [-.bfd]
+ gmake -f makefile.vms "CC=$(CC)"
+ $(CD) [-.gas]
+
+install: as.exe gasp.exe
+ $(CP) $^ GNU_ROOT\:[BIN]
+
+clean:
+ $$ purge
+ $(RM) *.obj;
+ $(RM) *.exe;
+ $(RM) atof-targ.c;
+ $(RM) obj-format.c;
+ $(RM) obj-format.h;
+ $(RM) targ-env.h;
+ $(RM) targ-cpu.h;
+ $(RM) targ-cpu.c;
+ $(RM) config.status;
diff --git a/gas/messages.c b/gas/messages.c
new file mode 100644
index 0000000000..e4b7ad00a1
--- /dev/null
+++ b/gas/messages.c
@@ -0,0 +1,541 @@
+/* messages.c - error reporter -
+ Copyright (C) 1987, 91, 92, 93, 94, 95, 96, 97, 1998
+ Free Software Foundation, Inc.
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include "as.h"
+
+#include <stdio.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#ifdef USE_STDARG
+#include <stdarg.h>
+#endif
+
+#ifdef USE_VARARGS
+#include <varargs.h>
+#endif
+
+#if !defined (USE_STDARG) && !defined (USE_VARARGS)
+/* Roll our own. */
+#define va_alist REST
+#define va_dcl
+typedef int * va_list;
+#define va_start(ARGS) ARGS = &REST
+#define va_end(ARGS)
+#endif
+
+static void identify PARAMS ((char *));
+static void as_show_where PARAMS ((void));
+static void as_warn_internal PARAMS ((char *, unsigned int, char *));
+static void as_bad_internal PARAMS ((char *, unsigned int, char *));
+
+/*
+ * Despite the rest of the comments in this file, (FIXME-SOON),
+ * here is the current scheme for error messages etc:
+ *
+ * as_fatal() is used when gas is quite confused and
+ * continuing the assembly is pointless. In this case we
+ * exit immediately with error status.
+ *
+ * as_bad() is used to mark errors that result in what we
+ * presume to be a useless object file. Say, we ignored
+ * something that might have been vital. If we see any of
+ * these, assembly will continue to the end of the source,
+ * no object file will be produced, and we will terminate
+ * with error status. The new option, -Z, tells us to
+ * produce an object file anyway but we still exit with
+ * error status. The assumption here is that you don't want
+ * this object file but we could be wrong.
+ *
+ * as_warn() is used when we have an error from which we
+ * have a plausible error recovery. eg, masking the top
+ * bits of a constant that is longer than will fit in the
+ * destination. In this case we will continue to assemble
+ * the source, although we may have made a bad assumption,
+ * and we will produce an object file and return normal exit
+ * status (ie, no error). The new option -X tells us to
+ * treat all as_warn() errors as as_bad() errors. That is,
+ * no object file will be produced and we will exit with
+ * error status. The idea here is that we don't kill an
+ * entire make because of an error that we knew how to
+ * correct. On the other hand, sometimes you might want to
+ * stop the make at these points.
+ *
+ * as_tsktsk() is used when we see a minor error for which
+ * our error recovery action is almost certainly correct.
+ * In this case, we print a message and then assembly
+ * continues as though no error occurred.
+ */
+
+static void
+identify (file)
+ char *file;
+{
+ static int identified;
+ if (identified)
+ return;
+ identified++;
+
+ if (!file)
+ {
+ unsigned int x;
+ as_where (&file, &x);
+ }
+
+ if (file)
+ fprintf (stderr, "%s: ", file);
+ fprintf (stderr, _("Assembler messages:\n"));
+}
+
+static int warning_count; /* Count of number of warnings issued */
+
+int
+had_warnings ()
+{
+ return (warning_count);
+}
+
+/* Nonzero if we've hit a 'bad error', and should not write an obj file,
+ and exit with a nonzero error code */
+
+static int error_count;
+
+int
+had_errors ()
+{
+ return (error_count);
+}
+
+
+/* Print the current location to stderr. */
+
+static void
+as_show_where ()
+{
+ char *file;
+ unsigned int line;
+
+ as_where (&file, &line);
+ identify (file);
+ if (file)
+ fprintf (stderr, "%s:%u: ", file, line);
+}
+
+/*
+ * a s _ p e r r o r
+ *
+ * Like perror(3), but with more info.
+ */
+
+void
+as_perror (gripe, filename)
+ const char *gripe; /* Unpunctuated error theme. */
+ const char *filename;
+{
+ const char *errtxt;
+
+ as_show_where ();
+ fprintf (stderr, gripe, filename);
+#ifdef BFD_ASSEMBLER
+ errtxt = bfd_errmsg (bfd_get_error ());
+#else
+ errtxt = xstrerror (errno);
+#endif
+ fprintf (stderr, ": %s\n", errtxt);
+ errno = 0;
+#ifdef BFD_ASSEMBLER
+ bfd_set_error (bfd_error_no_error);
+#endif
+}
+
+/*
+ * a s _ t s k t s k ()
+ *
+ * Send to stderr a string as a warning, and locate warning
+ * in input file(s).
+ * Please only use this for when we have some recovery action.
+ * Please explain in string (which may have '\n's) what recovery was done.
+ */
+
+#ifdef USE_STDARG
+void
+as_tsktsk (const char *format,...)
+{
+ va_list args;
+
+ as_show_where ();
+ va_start (args, format);
+ vfprintf (stderr, format, args);
+ va_end (args);
+ (void) putc ('\n', stderr);
+} /* as_tsktsk() */
+#else
+void
+as_tsktsk (format, va_alist)
+ const char *format;
+ va_dcl
+{
+ va_list args;
+
+ as_show_where ();
+ va_start (args);
+ vfprintf (stderr, format, args);
+ va_end (args);
+ (void) putc ('\n', stderr);
+} /* as_tsktsk() */
+#endif /* not NO_STDARG */
+
+/* The common portion of as_warn and as_warn_where. */
+
+static void
+as_warn_internal (file, line, buffer)
+ char *file;
+ unsigned int line;
+ char *buffer;
+{
+ ++warning_count;
+
+ if (file == NULL)
+ as_where (&file, &line);
+
+ identify (file);
+ if (file)
+ fprintf (stderr, "%s:%u: ", file, line);
+ fprintf (stderr, _("Warning: "));
+ fputs (buffer, stderr);
+ (void) putc ('\n', stderr);
+#ifndef NO_LISTING
+ listing_warning (buffer);
+#endif
+}
+
+/*
+ * a s _ w a r n ()
+ *
+ * Send to stderr a string as a warning, and locate warning
+ * in input file(s).
+ * Please only use this for when we have some recovery action.
+ * Please explain in string (which may have '\n's) what recovery was done.
+ */
+
+#ifdef USE_STDARG
+void
+as_warn (const char *format,...)
+{
+ va_list args;
+ char buffer[2000];
+
+ if (!flag_no_warnings)
+ {
+ va_start (args, format);
+ vsprintf (buffer, format, args);
+ va_end (args);
+ as_warn_internal ((char *) NULL, 0, buffer);
+ }
+} /* as_warn() */
+#else
+/*VARARGS1 */
+void
+as_warn (format, va_alist)
+ const char *format;
+ va_dcl
+{
+ va_list args;
+ char buffer[2000];
+
+ if (!flag_no_warnings)
+ {
+ va_start (args);
+ vsprintf (buffer, format, args);
+ va_end (args);
+ as_warn_internal ((char *) NULL, 0, buffer);
+ }
+} /* as_warn() */
+#endif /* not NO_STDARG */
+
+/* as_warn_where, like as_bad but the file name and line number are
+ passed in. Unfortunately, we have to repeat the function in order
+ to handle the varargs correctly and portably. */
+
+#ifdef USE_STDARG
+void
+as_warn_where (char *file, unsigned int line, const char *format,...)
+{
+ va_list args;
+ char buffer[2000];
+
+ if (!flag_no_warnings)
+ {
+ va_start (args, format);
+ vsprintf (buffer, format, args);
+ va_end (args);
+ as_warn_internal (file, line, buffer);
+ }
+} /* as_warn() */
+#else
+/*VARARGS1 */
+void
+as_warn_where (file, line, format, va_alist)
+ char *file;
+ unsigned int line;
+ const char *format;
+ va_dcl
+{
+ va_list args;
+ char buffer[2000];
+
+ if (!flag_no_warnings)
+ {
+ va_start (args);
+ vsprintf (buffer, format, args);
+ va_end (args);
+ as_warn_internal (file, line, buffer);
+ }
+} /* as_warn() */
+#endif /* not NO_STDARG */
+
+/* The common portion of as_bad and as_bad_where. */
+
+static void
+as_bad_internal (file, line, buffer)
+ char *file;
+ unsigned int line;
+ char *buffer;
+{
+ ++error_count;
+
+ if (file == NULL)
+ as_where (&file, &line);
+
+ identify (file);
+ if (file)
+ fprintf (stderr, "%s:%u: ", file, line);
+ fprintf (stderr, _("Error: "));
+ fputs (buffer, stderr);
+ (void) putc ('\n', stderr);
+#ifndef NO_LISTING
+ listing_error (buffer);
+#endif
+}
+
+/*
+ * a s _ b a d ()
+ *
+ * Send to stderr a string as a warning, and locate warning in input file(s).
+ * Please us when there is no recovery, but we want to continue processing
+ * but not produce an object file.
+ * Please explain in string (which may have '\n's) what recovery was done.
+ */
+
+#ifdef USE_STDARG
+void
+as_bad (const char *format,...)
+{
+ va_list args;
+ char buffer[2000];
+
+ va_start (args, format);
+ vsprintf (buffer, format, args);
+ va_end (args);
+
+ as_bad_internal ((char *) NULL, 0, buffer);
+}
+
+#else
+/*VARARGS1 */
+void
+as_bad (format, va_alist)
+ const char *format;
+ va_dcl
+{
+ va_list args;
+ char buffer[2000];
+
+ va_start (args);
+ vsprintf (buffer, format, args);
+ va_end (args);
+
+ as_bad_internal ((char *) NULL, 0, buffer);
+}
+#endif /* not NO_STDARG */
+
+/* as_bad_where, like as_bad but the file name and line number are
+ passed in. Unfortunately, we have to repeat the function in order
+ to handle the varargs correctly and portably. */
+
+#ifdef USE_STDARG
+void
+as_bad_where (char *file, unsigned int line, const char *format,...)
+{
+ va_list args;
+ char buffer[2000];
+
+ va_start (args, format);
+ vsprintf (buffer, format, args);
+ va_end (args);
+
+ as_bad_internal (file, line, buffer);
+}
+
+#else
+/*VARARGS1 */
+void
+as_bad_where (file, line, format, va_alist)
+ char *file;
+ unsigned int line;
+ const char *format;
+ va_dcl
+{
+ va_list args;
+ char buffer[2000];
+
+ va_start (args);
+ vsprintf (buffer, format, args);
+ va_end (args);
+
+ as_bad_internal (file, line, buffer);
+}
+#endif /* not NO_STDARG */
+
+/*
+ * a s _ f a t a l ()
+ *
+ * Send to stderr a string as a fatal message, and print location of error in
+ * input file(s).
+ * Please only use this for when we DON'T have some recovery action.
+ * It xexit()s with a warning status.
+ */
+
+#ifdef USE_STDARG
+void
+as_fatal (const char *format,...)
+{
+ va_list args;
+
+ as_show_where ();
+ va_start (args, format);
+ fprintf (stderr, _("Fatal error: "));
+ vfprintf (stderr, format, args);
+ (void) putc ('\n', stderr);
+ va_end (args);
+ xexit (EXIT_FAILURE);
+} /* as_fatal() */
+#else
+/*VARARGS1*/
+void
+as_fatal (format, va_alist)
+ char *format;
+ va_dcl
+{
+ va_list args;
+
+ as_show_where ();
+ va_start (args);
+ fprintf (stderr, _("Fatal error: "));
+ vfprintf (stderr, format, args);
+ (void) putc ('\n', stderr);
+ va_end (args);
+ xexit (EXIT_FAILURE);
+} /* as_fatal() */
+#endif /* not NO_STDARG */
+
+/*
+ * as_assert: Indicate assertion failure.
+ * Arguments: Filename, line number, optional function name.
+ */
+
+void
+as_assert (file, line, fn)
+ const char *file, *fn;
+ int line;
+{
+ as_show_where ();
+ fprintf (stderr, _("Internal error!\n"));
+ if (fn)
+ fprintf (stderr, _("Assertion failure in %s at %s line %d.\n"),
+ fn, file, line);
+ else
+ fprintf (stderr, _("Assertion failure at %s line %d.\n"), file, line);
+ fprintf (stderr, _("Please report this bug.\n"));
+ xexit (EXIT_FAILURE);
+}
+
+/* as_abort: Print a friendly message saying how totally hosed we are,
+ and exit without producing a core file. */
+void
+as_abort (file, line, fn)
+ const char *file, *fn;
+ int line;
+{
+ as_show_where ();
+ if (fn)
+ fprintf (stderr, _("Internal error, aborting at %s line %d in %s\n"),
+ file, line, fn);
+ else
+ fprintf (stderr, _("Internal error, aborting at %s line %d\n"),
+ file, line);
+ fprintf (stderr, _("Please report this bug.\n"));
+ xexit (EXIT_FAILURE);
+}
+
+/* Support routines. */
+
+void
+fprint_value (file, val)
+ FILE *file;
+ valueT val;
+{
+ if (sizeof (val) <= sizeof (long))
+ {
+ fprintf (file, "%ld", (long) val);
+ return;
+ }
+#ifdef BFD_ASSEMBLER
+ if (sizeof (val) <= sizeof (bfd_vma))
+ {
+ fprintf_vma (file, val);
+ return;
+ }
+#endif
+ abort ();
+}
+
+void
+sprint_value (buf, val)
+ char *buf;
+ valueT val;
+{
+ if (sizeof (val) <= sizeof (long))
+ {
+ sprintf (buf, "%ld", (long) val);
+ return;
+ }
+#ifdef BFD_ASSEMBLER
+ if (sizeof (val) <= sizeof (bfd_vma))
+ {
+ sprintf_vma (buf, val);
+ return;
+ }
+#endif
+ abort ();
+}
+
+/* end of messages.c */
diff --git a/gas/mpw-config.in b/gas/mpw-config.in
new file mode 100644
index 0000000000..9e29b1d945
--- /dev/null
+++ b/gas/mpw-config.in
@@ -0,0 +1,115 @@
+# Configuration fragment for GAS.
+
+Set target_arch `echo {target_canonical} | sed -e 's/-.*-.*//'`
+
+If "{target_arch}" =~ /powerpc/
+ Set short_arch_name "ppc"
+ Set target_cpu "powerpc"
+Else
+ Set short_arch_name "{target_arch}"
+End If
+
+# The following works for many configurations, though not all.
+
+Set obj_format `echo {target_canonical} | sed -e 's/.*-.*-//'`
+Set target_os `echo {target_canonical} | sed -e 's/.*-.*-//'`
+
+Set bfd_gas no
+
+Set TDEFINES ""
+
+Set EXTRA_OBJECTS ""
+
+# Default emulation.
+
+Set em generic
+
+If "{target_canonical}" =~ /m68k-apple-macos/
+ Set obj_format "coff"
+ Set TDEFINES '-d M68KCOFF'
+ Set EXTRA_OBJECTS '"{o}"m68k-parse.c.o'
+
+Else If "{target_canonical}" =~ /powerpc-apple-macos/
+ Set obj_format "coff"
+ Set bfd_gas yes
+ Set em macos
+
+Else If "{target_canonical}" =~ /i386-\Option-x-go32/
+ Set obj_format "coff"
+ Set TDEFINES '-d I386COFF'
+
+Else If "{target_canonical}" =~ /m68k-\Option-x-coff/
+ Set TDEFINES '-d M68KCOFF'
+
+Else If "{target_canonical}" =~ /mips-idt-ecoff/
+ Set bfd_gas yes
+ Set TDEFINES '-d TARGET_BYTES_BIG_ENDIAN=1'
+
+Else If "{target_canonical}" =~ /mips-\Option-x-\Option-x/
+ # Assume other OSes etc use ELF
+ Set obj_format "elf"
+ Set bfd_gas yes
+ Set TDEFINES '-d TARGET_BYTES_BIG_ENDIAN=1'
+ forward-include "{srcroot}"bfd:elf-bfd.h 'bfd/elf-bfd.h'
+
+Else If "{target_canonical}" =~ /sh-\Option-x-hms/
+ Set obj_format "coff"
+ forward-include "{srcroot}"opcodes:sh-opc.h 'opcodes/sh-opc.h'
+End If
+
+forward-include "{srcdir}"config:tc-{short_arch_name}.c targ-cpu.c
+forward-include "{srcdir}"config:tc-{short_arch_name}.h targ-cpu.h
+
+forward-include "{srcdir}"config:obj-{obj_format}.c obj-format.c
+forward-include "{srcdir}"config:obj-{obj_format}.h obj-format.h
+
+forward-include "{srcdir}"config:te-{em}.h targ-env.h
+
+# Special cases for float handling.
+
+If "{target_arch}" =~ /ns32k/
+ forward-include "{srcdir}"config:atof-ns32k.c atof-targ.c
+Else If "{target_arch}" =~ /tahoe/
+ forward-include "{srcdir}"config:atof-tahoe.c atof-targ.c
+Else If "{target_arch}" =~ /vax/
+ forward-include "{srcdir}"config:atof-vax.c atof-targ.c
+Else
+ # Use IEEE by default.
+ forward-include "{srcdir}"config:atof-ieee.c atof-targ.c
+End If
+
+Echo '# From mpw-config.in' > "{o}"mk.tmp
+Echo "TDEFINES = " {TDEFINES} >> "{o}"mk.tmp
+Echo "EXTRA_OBJECTS = " {EXTRA_OBJECTS} >> "{o}"mk.tmp
+# (We use the -n option here so as not to get extra spaces inserted)
+Echo -n 'TARG_CPU_DEP = {TARG_CPU_DEP_' >> "{o}"mk.tmp
+Echo -n {short_arch_name} >> "{o}"mk.tmp
+Echo -n '}' >> "{o}"mk.tmp
+Echo '# End from mpw-config.in' >> "{o}"mk.tmp
+
+Echo '/* conf. Generated by mpw-configure. */' > "{o}"conf.new
+Echo -n '#define TARGET_CPU "' >> "{o}"conf.new
+Echo -n "{target_cpu}" >> "{o}"conf.new
+Echo '"' >> "{o}"conf.new
+Echo -n '#define TARGET_OS "' >> "{o}"conf.new
+Echo -n "{target_os}" >> "{o}"conf.new
+Echo '"' >> "{o}"conf.new
+Echo -n '#define TARGET_ALIAS "' >> "{o}"conf.new
+Echo -n "{target_alias}" >> "{o}"conf.new
+Echo '"' >> "{o}"conf.new
+Echo -n '#define TARGET_CANONICAL "' >> "{o}"conf.new
+Echo -n "{target_canonical}" >> "{o}"conf.new
+Echo '"' >> "{o}"conf.new
+Echo '#include "mpw.h"' >> "{o}"conf.new
+If "{bfd_gas}" =~ /yes/
+ Echo "#define BFD_ASSEMBLER" >> "{o}"conf.new
+Else
+ Echo "#define MANY_SEGMENTS" >> "{o}"conf.new
+End If
+Echo '#define CR_EOL' >> "{o}"conf.new
+Echo '#define OBJ_COFF_OMIT_TIMESTAMP' >> "{o}"conf.new
+Echo '#define LOSING_COMPILER' >> "{o}"conf.new
+
+MoveIfChange "{o}"conf.new "{o}"conf
+
+sed -e "s/@srcdir@/{srcdir}/" "{srcdir}"gdbinit.in > "{o}"_gdbinit
diff --git a/gas/mpw-make.sed b/gas/mpw-make.sed
new file mode 100644
index 0000000000..16f12a5055
--- /dev/null
+++ b/gas/mpw-make.sed
@@ -0,0 +1,100 @@
+# Sed commands that finish translating the GAS Unix Makefile to MPW syntax.
+
+/^# @target_frag@/a\
+\
+HDEFINES = \
+LOCAL_LOADLIBES = \
+
+/^srcroot = /s/^/#/
+/^target_alias = /s/^/#/
+
+/INCLUDES/s/-i "{srcdir}":\([a-z]*\)/-i "{topsrcdir}"\1/
+/INCLUDES/s/-i "{srcdir}"\.\./-i "{topsrcdir}"/
+
+/^INCLUDES = .*$/s/$/ -i "{topsrcdir}"include:mpw: -i ::extra-include:/
+
+/$(TARG_CPU_DEP_@target_cpu_type@)/s/$(TARG_CPU_DEP_@target_cpu_type@)/{TARG_CPU_DEP}/
+
+/@OPCODES_LIB@/s/@OPCODES_LIB@/::opcodes:libopcodes.o/
+/@BFDLIB@/s/@BFDLIB@/::bfd:libbfd.o/
+
+# Point at the libraries directly.
+/@OPCODES_DEP@/s/@OPCODES_DEP@/::opcodes:libopcodes.o/
+/@BFDDEP@/s/@BFDDEP@/::bfd:libbfd.o/
+
+# Don't need this.
+/@HLDFLAGS@/s/@HLDFLAGS@//
+
+/extra_objects@/s/extra_objects@/{EXTRA_OBJECTS}/
+
+/LOADLIBES/s/{LOADLIBES}/{EXTRALIBS}/
+
+/@ALL_OBJ_DEPS@/s/@ALL_OBJ_DEPS@/::bfd:bfd.h/
+
+# This causes problems - not sure why.
+/^tags TAGS/,/etags /d
+
+/^make-gas.com/s/^/#/
+
+/true/s/ ; @true$//
+
+# Remove references to conf.in, we don't need them.
+/conf\.in/s/conf\.in//g
+
+# Use _gdbinit everywhere instead of .gdbinit.
+/gdbinit/s/\.gdbinit/_gdbinit/g
+
+/atof-targ/s/"{s}"atof-targ\.c/"{o}"atof-targ.c/g
+/config/s/"{s}"config\.h/"{o}"config.h/g
+/config/s/^config\.h/"{o}"config.h/
+/obj-format/s/"{s}"obj-format\.c/"{o}"obj-format.c/g
+/obj-format/s/"{s}"obj-format\.h/"{o}"obj-format.h/g
+/targ-cpu/s/"{s}"targ-cpu\.c/"{o}"targ-cpu.c/g
+/targ-cpu/s/"{s}"targ-cpu\.h/"{o}"targ-cpu.h/g
+/targ-env/s/"{s}"targ-env\.h/"{o}"targ-env.h/g
+
+/m68k-parse.c/s/"{s}"m68k-parse\.c/"{o}"m68k-parse.c/g
+/m68k-parse.c/s/^m68k-parse\.c/"{o}"m68k-parse.c/
+
+# Whack out the config.h dependency, it only causes excess rebuilds.
+/{OBJS}/s/{OBJS} \\Option-f "{o}"config.h/{OBJS} \\Option-f/
+/gasp.c/s/gasp\.c "{o}"config.h/gasp.c/
+
+# ALL_CFLAGS includes TDEFINES, which is not desirable at link time.
+/CC_LD/s/ALL_CFLAGS/CFLAGS/g
+
+# The resource file is called mac-as.r.
+/as.new.r/s/as\.new\.r/mac-as.r/
+/gasp.new.r/s/gasp\.new\.r/mac-as.r/
+
+# ...and the PROG_NAME doesn't have a .new in it.
+/PROG_NAME/s/PROG_NAME='"'as.new'"'/PROG_NAME='"'as'"'/
+/PROG_NAME/s/PROG_NAME='"'gasp.new'"'/PROG_NAME='"'gasp'"'/
+
+# Whack out recursive makes, they won't work.
+/^[ ][ ]*srcroot=/,/^[ ][ ]*(cd /d
+
+# Work around quoting problems by using multiple echo commands.
+/'#define GAS_VERSION "{VERSION}"'/c\
+ Echo -n '#define GAS_VERSION "' >> "{o}"config.new\
+ Echo -n "{VERSION}" >> "{o}"config.new\
+ Echo -n '"' >> "{o}"config.new
+
+# Add a "stamps" target.
+$a\
+stamps \\Option-f config-stamp\
+
+/^install \\Option-f/,/^$/c\
+install \\Option-f all install-only\
+\
+install-only \\Option-f\
+ NewFolderRecursive "{bindir}"\
+ Duplicate -y :as.new "{bindir}"as\
+ Duplicate -y :gasp.new "{bindir}"gasp\
+
+
+# Whack out config-rebuilding targets, they won't work.
+/^Makefile \\Option-f/,/^$/d
+/^config.status \\Option-f/,/^$/d
+
+/^"{o}"config.h \\Option-f/s/^/#/
diff --git a/gas/obj.h b/gas/obj.h
new file mode 100644
index 0000000000..b95e75c96e
--- /dev/null
+++ b/gas/obj.h
@@ -0,0 +1,81 @@
+/* obj.h - defines the object dependent hooks for all object
+ format backends.
+
+ Copyright (C) 1987, 90, 91, 92, 93, 95, 96, 97, 1999
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+char *obj_default_output_file_name PARAMS ((void));
+void obj_emit_relocations PARAMS ((char **where, fixS * fixP,
+ relax_addressT segment_address_in_file));
+void obj_emit_strings PARAMS ((char **where));
+void obj_emit_symbols PARAMS ((char **where, symbolS * symbols));
+#ifndef obj_read_begin_hook
+void obj_read_begin_hook PARAMS ((void));
+#endif
+#ifndef BFD_ASSEMBLER
+void obj_crawl_symbol_chain PARAMS ((object_headers * headers));
+void obj_header_append PARAMS ((char **where, object_headers * headers));
+#ifndef obj_pre_write_hook
+void obj_pre_write_hook PARAMS ((object_headers * headers));
+#endif
+#endif
+
+#ifndef obj_symbol_new_hook
+void obj_symbol_new_hook PARAMS ((symbolS * symbolP));
+#endif
+
+void obj_symbol_to_chars PARAMS ((char **where, symbolS * symbolP));
+
+extern const pseudo_typeS obj_pseudo_table[];
+
+#ifdef BFD_ASSEMBLER
+struct format_ops {
+ int flavor;
+ unsigned dfl_leading_underscore : 1;
+ unsigned emit_section_symbols : 1;
+ void (*frob_symbol) PARAMS ((symbolS *, int *));
+ void (*frob_file) PARAMS ((void));
+ void (*frob_file_after_relocs) PARAMS ((void));
+ bfd_vma (*s_get_size) PARAMS ((symbolS *));
+ void (*s_set_size) PARAMS ((symbolS *, bfd_vma));
+ bfd_vma (*s_get_align) PARAMS ((symbolS *));
+ void (*s_set_align) PARAMS ((symbolS *, bfd_vma));
+ void (*copy_symbol_attributes) PARAMS ((symbolS *, symbolS *));
+ void (*generate_asm_lineno) PARAMS ((void));
+ void (*process_stab) PARAMS ((segT, int, const char *, int, int, int));
+ int (*sec_sym_ok_for_reloc) PARAMS ((asection *));
+ void (*pop_insert) PARAMS ((void));
+ /* For configurations using ECOFF_DEBUGGING, this callback is used. */
+ void (*ecoff_set_ext) PARAMS ((symbolS *, struct ecoff_extr *));
+
+ void (*read_begin_hook) PARAMS ((void));
+ void (*symbol_new_hook) PARAMS ((symbolS *));
+};
+
+extern const struct format_ops elf_format_ops;
+extern const struct format_ops ecoff_format_ops;
+extern const struct format_ops coff_format_ops;
+
+#ifndef this_format
+COMMON const struct format_ops *this_format;
+#endif
+#endif
+
+/* end of obj.h */
diff --git a/gas/output-file.c b/gas/output-file.c
new file mode 100644
index 0000000000..b05af48a53
--- /dev/null
+++ b/gas/output-file.c
@@ -0,0 +1,156 @@
+/* output-file.c - Deal with the output file
+ Copyright (C) 1987, 90, 91, 93, 92, 94, 95, 96, 1998
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+
+#include "as.h"
+
+#include "output-file.h"
+
+#ifdef BFD_HEADERS
+#define USE_BFD
+#endif
+
+#ifdef BFD_ASSEMBLER
+#define USE_BFD
+#ifndef TARGET_MACH
+#define TARGET_MACH 0
+#endif
+#endif
+
+#ifdef USE_BFD
+#include "bfd.h"
+bfd *stdoutput;
+
+void
+output_file_create (name)
+ char *name;
+{
+ if (name[0] == '-' && name[1] == '\0')
+ {
+ as_fatal (_("Can't open a bfd on stdout %s "), name);
+ }
+ else if (!(stdoutput = bfd_openw (name, TARGET_FORMAT)))
+ {
+ as_perror (_("FATAL: Can't create %s"), name);
+ exit (EXIT_FAILURE);
+ }
+ bfd_set_format (stdoutput, bfd_object);
+#ifdef BFD_ASSEMBLER
+ bfd_set_arch_mach (stdoutput, TARGET_ARCH, TARGET_MACH);
+#endif
+ if (flag_traditional_format)
+ stdoutput->flags |= BFD_TRADITIONAL_FORMAT;
+}
+
+void
+output_file_close (filename)
+ char *filename;
+{
+#ifdef BFD_ASSEMBLER
+ /* Close the bfd. */
+ if (bfd_close (stdoutput) == 0)
+ {
+ bfd_perror (filename);
+ as_perror (_("FATAL: Can't close %s\n"), filename);
+ exit (EXIT_FAILURE);
+ }
+#else
+ /* Close the bfd without getting bfd to write out anything by itself */
+ if (bfd_close_all_done (stdoutput) == 0)
+ {
+ as_perror (_("FATAL: Can't close %s\n"), filename);
+ exit (EXIT_FAILURE);
+ }
+#endif
+ stdoutput = NULL; /* Trust nobody! */
+}
+
+#ifndef BFD_ASSEMBLER
+void
+output_file_append (where, length, filename)
+ char *where;
+ long length;
+ char *filename;
+{
+ abort ();
+}
+#endif
+
+#else
+
+static FILE *stdoutput;
+
+void
+output_file_create (name)
+ char *name;
+{
+ if (name[0] == '-' && name[1] == '\0')
+ {
+ stdoutput = stdout;
+ return;
+ }
+
+ stdoutput = fopen (name, "wb");
+
+ /* Some systems don't grok "b" in fopen modes. */
+ if (stdoutput == NULL)
+ stdoutput = fopen (name, "w");
+
+ if (stdoutput == NULL)
+ {
+ as_perror (_("FATAL: Can't create %s"), name);
+ exit (EXIT_FAILURE);
+ }
+}
+
+void
+output_file_close (filename)
+ char *filename;
+{
+ if (EOF == fclose (stdoutput))
+ {
+ as_perror (_("FATAL: Can't close %s"), filename);
+ exit (EXIT_FAILURE);
+ }
+ stdoutput = NULL; /* Trust nobody! */
+}
+
+void
+output_file_append (where, length, filename)
+ char *where;
+ long length;
+ char *filename;
+{
+ for (; length; length--, where++)
+ {
+ (void) putc (*where, stdoutput);
+ if (ferror (stdoutput))
+ /* if ( EOF == (putc( *where, stdoutput )) ) */
+ {
+ as_perror (_("Failed to emit an object byte"), filename);
+ as_fatal (_("Can't continue"));
+ }
+ }
+}
+
+#endif
+
+/* end of output-file.c */
diff --git a/gas/output-file.h b/gas/output-file.h
new file mode 100644
index 0000000000..942f1efe3e
--- /dev/null
+++ b/gas/output-file.h
@@ -0,0 +1,25 @@
+/* This file is output-file.h
+
+ Copyright (C) 1987-1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+void output_file_append PARAMS ((char *where, long length, char *filename));
+void output_file_close PARAMS ((char *filename));
+void output_file_create PARAMS ((char *name));
+
+/* end of output-file.h */
diff --git a/gas/po/Make-in b/gas/po/Make-in
new file mode 100644
index 0000000000..0552db1fee
--- /dev/null
+++ b/gas/po/Make-in
@@ -0,0 +1,251 @@
+# Makefile for program source directory in GNU NLS utilities package.
+# Copyright (C) 1995, 1996, 1997 by Ulrich Drepper <drepper@gnu.ai.mit.edu>
+#
+# This file file be copied and used freely without restrictions. It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+
+SHELL = /bin/sh
+@SET_MAKE@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+datadir = $(prefix)/@DATADIRNAME@
+localedir = $(datadir)/locale
+gnulocaledir = $(prefix)/share/locale
+gettextsrcdir = $(prefix)/share/gettext/po
+subdir = po
+
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+
+CC = @CC@
+GENCAT = @GENCAT@
+GMSGFMT = PATH=../src:$$PATH @GMSGFMT@
+MSGFMT = @MSGFMT@
+XGETTEXT = PATH=../src:$$PATH @XGETTEXT@
+MSGMERGE = PATH=../src:$$PATH msgmerge
+
+DEFS = @DEFS@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+
+INCLUDES = -I.. -I$(top_srcdir)/intl
+
+COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS)
+
+SOURCES = cat-id-tbl.c
+POFILES = @POFILES@
+GMOFILES = @GMOFILES@
+DISTFILES = ChangeLog Makefile.in.in POTFILES.in $(PACKAGE).pot \
+stamp-cat-id $(POFILES) $(GMOFILES) $(SOURCES)
+
+POTFILES = \
+
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+INSTOBJEXT = @INSTOBJEXT@
+
+.SUFFIXES:
+.SUFFIXES: .c .o .po .pox .gmo .mo .msg .cat
+
+.c.o:
+ $(COMPILE) $<
+
+.po.pox:
+ $(MAKE) $(PACKAGE).pot
+ $(MSGMERGE) $< $(srcdir)/$(PACKAGE).pot -o $*.pox
+
+.po.mo:
+ $(MSGFMT) -o $@ $<
+
+.po.gmo:
+ file=$(srcdir)/`echo $* | sed 's,.*/,,'`.gmo \
+ && rm -f $$file && $(GMSGFMT) -o $$file $<
+
+.po.cat:
+ sed -f ../intl/po2msg.sed < $< > $*.msg \
+ && rm -f $@ && $(GENCAT) $@ $*.msg
+
+
+all: all-@USE_NLS@
+
+all-yes: $(CATALOGS) @MAINT@ $(PACKAGE).pot
+all-no:
+
+$(srcdir)/$(PACKAGE).pot: $(POTFILES)
+ $(XGETTEXT) --default-domain=$(PACKAGE) --directory=$(top_srcdir) \
+ --add-comments --keyword=_ --keyword=N_ \
+ --files-from=$(srcdir)/POTFILES.in
+ rm -f $(srcdir)/$(PACKAGE).pot
+ mv $(PACKAGE).po $(srcdir)/$(PACKAGE).pot
+
+$(srcdir)/cat-id-tbl.c: stamp-cat-id; @:
+$(srcdir)/stamp-cat-id: $(PACKAGE).pot
+ rm -f cat-id-tbl.tmp
+ sed -f ../intl/po2tbl.sed $(srcdir)/$(PACKAGE).pot \
+ | sed -e "s/@PACKAGE NAME@/$(PACKAGE)/" > cat-id-tbl.tmp
+ if cmp -s cat-id-tbl.tmp $(srcdir)/cat-id-tbl.c; then \
+ rm cat-id-tbl.tmp; \
+ else \
+ echo cat-id-tbl.c changed; \
+ rm -f $(srcdir)/cat-id-tbl.c; \
+ mv cat-id-tbl.tmp $(srcdir)/cat-id-tbl.c; \
+ fi
+ cd $(srcdir) && rm -f stamp-cat-id && echo timestamp > stamp-cat-id
+
+
+install: install-exec install-data
+install-exec:
+install-info:
+install-data: install-data-@USE_NLS@
+install-data-no: all
+install-data-yes: all
+ if test -r $(MKINSTALLDIRS); then \
+ $(MKINSTALLDIRS) $(datadir); \
+ else \
+ $(top_srcdir)/mkinstalldirs $(datadir); \
+ fi
+ @catalogs='$(CATALOGS)'; \
+ for cat in $$catalogs; do \
+ cat=`basename $$cat`; \
+ case "$$cat" in \
+ *.gmo) destdir=$(gnulocaledir);; \
+ *) destdir=$(localedir);; \
+ esac; \
+ lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
+ dir=$$destdir/$$lang/LC_MESSAGES; \
+ if test -r $(MKINSTALLDIRS); then \
+ $(MKINSTALLDIRS) $$dir; \
+ else \
+ $(top_srcdir)/mkinstalldirs $$dir; \
+ fi; \
+ if test -r $$cat; then \
+ $(INSTALL_DATA) $$cat $$dir/$(PACKAGE)$(INSTOBJEXT); \
+ echo "installing $$cat as $$dir/$(PACKAGE)$(INSTOBJEXT)"; \
+ else \
+ $(INSTALL_DATA) $(srcdir)/$$cat $$dir/$(PACKAGE)$(INSTOBJEXT); \
+ echo "installing $(srcdir)/$$cat as" \
+ "$$dir/$(PACKAGE)$(INSTOBJEXT)"; \
+ fi; \
+ if test -r $$cat.m; then \
+ $(INSTALL_DATA) $$cat.m $$dir/$(PACKAGE)$(INSTOBJEXT).m; \
+ echo "installing $$cat.m as $$dir/$(PACKAGE)$(INSTOBJEXT).m"; \
+ else \
+ if test -r $(srcdir)/$$cat.m ; then \
+ $(INSTALL_DATA) $(srcdir)/$$cat.m \
+ $$dir/$(PACKAGE)$(INSTOBJEXT).m; \
+ echo "installing $(srcdir)/$$cat as" \
+ "$$dir/$(PACKAGE)$(INSTOBJEXT).m"; \
+ else \
+ true; \
+ fi; \
+ fi; \
+ done
+ if test "$(PACKAGE)" = "gettext"; then \
+ if test -r $(MKINSTALLDIRS); then \
+ $(MKINSTALLDIRS) $(gettextsrcdir); \
+ else \
+ $(top_srcdir)/mkinstalldirs $(gettextsrcdir); \
+ fi; \
+ $(INSTALL_DATA) $(srcdir)/Makefile.in.in \
+ $(gettextsrcdir)/Makefile.in.in; \
+ else \
+ : ; \
+ fi
+
+# Define this as empty until I found a useful application.
+installcheck:
+
+uninstall:
+ catalogs='$(CATALOGS)'; \
+ for cat in $$catalogs; do \
+ cat=`basename $$cat`; \
+ lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
+ rm -f $(localedir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT); \
+ rm -f $(localedir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT).m; \
+ rm -f $(gnulocaledir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT); \
+ rm -f $(gnulocaledir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT).m; \
+ done
+ rm -f $(gettextsrcdir)/po-Makefile.in.in
+
+check: all
+
+cat-id-tbl.o: ../intl/libgettext.h
+
+dvi info tags TAGS ID:
+
+mostlyclean:
+ rm -f core core.* *.pox $(PACKAGE).po *.old.po cat-id-tbl.tmp
+ rm -fr *.o
+
+clean: mostlyclean
+
+distclean: clean
+ rm -f Makefile Makefile.in POTFILES *.mo *.msg *.cat *.cat.m
+
+maintainer-clean: distclean
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+ rm -f $(GMOFILES)
+
+distdir = ../$(PACKAGE)-$(VERSION)/$(subdir)
+dist distdir: update-po $(DISTFILES)
+ dists="$(DISTFILES)"; \
+ for file in $$dists; do \
+ ln $(srcdir)/$$file $(distdir) 2> /dev/null \
+ || cp -p $(srcdir)/$$file $(distdir); \
+ done
+
+update-po: Makefile
+ $(MAKE) $(PACKAGE).pot
+ PATH=`pwd`/../src:$$PATH; \
+ cd $(srcdir); \
+ catalogs='$(CATALOGS)'; \
+ for cat in $$catalogs; do \
+ cat=`basename $$cat`; \
+ lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
+ mv $$lang.po $$lang.old.po; \
+ echo "$$lang:"; \
+ if $(MSGMERGE) $$lang.old.po $(PACKAGE).pot -o $$lang.po; then \
+ rm -f $$lang.old.po; \
+ else \
+ echo "msgmerge for $$cat failed!"; \
+ rm -f $$lang.po; \
+ mv $$lang.old.po $$lang.po; \
+ fi; \
+ done
+
+POTFILES: POTFILES.in
+ ( if test 'x$(srcdir)' != 'x.'; then \
+ posrcprefix='$(top_srcdir)/'; \
+ else \
+ posrcprefix="../"; \
+ fi; \
+ rm -f $@-t $@ \
+ && (sed -e '/^#/d' -e '/^[ ]*$$/d' \
+ -e "s@.*@ $$posrcprefix& \\\\@" < $(srcdir)/$@.in \
+ | sed -e '$$s/\\$$//') > $@-t \
+ && chmod a-w $@-t \
+ && mv $@-t $@ )
+
+POTFILES.in: @MAINT@ ../Makefile
+ cd .. && $(MAKE) po/POTFILES.in
+
+Makefile: Make-in ../config.status POTFILES
+ cd .. \
+ && CONFIG_FILES=$(subdir)/Makefile.in:$(subdir)/Make-in \
+ CONFIG_HEADERS= $(SHELL) ./config.status
+
+# Tell versions [3.59,3.63) of GNU make not to export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/gas/po/POTFILES.in b/gas/po/POTFILES.in
new file mode 100644
index 0000000000..0023b7ad94
--- /dev/null
+++ b/gas/po/POTFILES.in
@@ -0,0 +1,193 @@
+config/tc-hppa.c
+config/tc-m32r.c
+config/aout_gnu.h
+config/atof-ieee.c
+config/atof-tahoe.c
+config/atof-vax.c
+config/e-i386coff.c
+config/e-i386elf.c
+config/e-mipsecoff.c
+config/e-mipself.c
+config/itbl-mips.h
+config/m68k-parse.h
+config/m88k-opcode.h
+config/obj-aout.c
+config/obj-aout.h
+config/obj-bout.c
+config/obj-bout.h
+config/obj-coff.c
+config/obj-coff.h
+config/obj-ecoff.c
+config/obj-ecoff.h
+config/obj-elf.c
+config/obj-elf.h
+config/obj-evax.c
+config/obj-evax.h
+config/obj-generic.c
+config/obj-generic.h
+config/obj-hp300.c
+config/obj-hp300.h
+config/obj-ieee.c
+config/obj-ieee.h
+config/obj-multi.c
+config/obj-multi.h
+config/obj-som.c
+config/obj-som.h
+config/obj-vms.c
+config/obj-vms.h
+config/tc-a29k.c
+config/tc-a29k.h
+config/tc-alpha.c
+config/tc-alpha.h
+config/tc-arc.c
+config/tc-arc.h
+config/tc-arm.c
+config/tc-arm.h
+config/tc-d10v.c
+config/tc-d10v.h
+config/tc-d30v.c
+config/tc-d30v.h
+config/tc-mcore.c
+config/tc-fr30.c
+config/tc-fr30.h
+config/tc-generic.c
+config/tc-generic.h
+config/tc-h8300.c
+config/tc-h8300.h
+config/tc-h8500.c
+config/tc-h8500.h
+config/tc-mips.c
+config/tc-hppa.h
+config/tc-i386.c
+config/tc-i386.h
+config/tc-i860.c
+config/tc-i860.h
+config/tc-i960.c
+config/tc-i960.h
+config/tc-mn10300.c
+config/tc-m32r.h
+config/tc-m68851.h
+config/tc-m68k.c
+config/tc-m68k.h
+config/tc-m88k.c
+config/tc-m88k.h
+config/tc-mcore.h
+config/tc-mips.h
+config/tc-mn10200.c
+config/tc-mn10200.h
+config/tc-mn10300.h
+config/tc-ns32k.c
+config/tc-ns32k.h
+config/tc-ppc.c
+config/tc-ppc.h
+config/tc-sh.c
+config/tc-sh.h
+config/tc-sparc.c
+config/tc-sparc.h
+config/tc-tahoe.c
+config/tc-tahoe.h
+config/tc-tic30.c
+config/tc-tic30.h
+config/tc-tic80.c
+config/tc-tic80.h
+config/tc-v850.c
+config/tc-v850.h
+config/tc-vax.c
+config/tc-vax.h
+config/tc-w65.c
+config/tc-w65.h
+config/tc-z8k.c
+config/tc-z8k.h
+config/te-386bsd.h
+config/te-aux.h
+config/te-delt88.h
+config/te-delta.h
+config/te-dpx2.h
+config/te-dynix.h
+config/te-epoc-pe.h
+config/te-generic.h
+config/te-go32.h
+config/te-hp300.h
+config/te-hppa.h
+config/te-i386aix.h
+config/te-ic960.h
+config/te-linux.h
+config/te-lnews.h
+config/te-lynx.h
+config/te-mach.h
+config/te-macos.h
+config/te-multi.h
+config/te-nbsd.h
+config/te-nbsd532.h
+config/te-pc532mach.h
+config/te-pe.h
+config/te-ppcnw.h
+config/te-psos.h
+config/te-riscix.h
+config/te-sparcaout.h
+config/te-sun3.h
+config/te-svr4.h
+config/te-sysv32.h
+config/vax-inst.h
+config/vms-a-conf.h
+config/vms-conf.h
+app.c
+as.c
+as.h
+asintl.h
+atof-generic.c
+bignum-copy.c
+bignum.h
+bit_fix.h
+cgen.c
+cgen.h
+cond.c
+debug.c
+depend.c
+ecoff.c
+ecoff.h
+ehopt.c
+emul-target.h
+emul.h
+expr.c
+expr.h
+flonum-copy.c
+flonum-konst.c
+flonum-mult.c
+flonum.h
+frags.c
+frags.h
+gasp.c
+hash.c
+hash.h
+input-file.c
+input-file.h
+input-scrub.c
+itbl-ops.c
+itbl-ops.h
+listing.c
+listing.h
+literal.c
+macro.c
+macro.h
+messages.c
+obj.h
+output-file.c
+output-file.h
+read.c
+read.h
+sb.c
+sb.h
+stabs.c
+struc-symbol.h
+subsegs.c
+subsegs.h
+symbols.c
+symbols.h
+tc.h
+write.c
+write.h
+testsuite/gas/all/itbl-test.c
+testsuite/gas/mips/elf_e_flags.c
+testsuite/gas/tic80/relocs1.c
+testsuite/gas/tic80/relocs2.c
diff --git a/gas/po/gas.pot b/gas/po/gas.pot
new file mode 100644
index 0000000000..cd9abba518
--- /dev/null
+++ b/gas/po/gas.pot
@@ -0,0 +1,3853 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 1999-04-18 18:31-0400\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: ENCODING\n"
+
+#: app.c:435 app.c:449
+msgid "end of file in comment"
+msgstr ""
+
+#: app.c:528
+msgid "end of file in string: inserted '\"'"
+msgstr ""
+
+#: app.c:594
+#, c-format
+msgid "Unknown escape '\\%c' in string: Ignored"
+msgstr ""
+
+#: app.c:603
+msgid "End of file in string: '\"' inserted"
+msgstr ""
+
+#: app.c:723
+msgid "end of file not at end of a line; newline inserted"
+msgstr ""
+
+#: app.c:869
+msgid "end of file in multiline comment"
+msgstr ""
+
+#: app.c:918
+msgid "end of file after a one-character quote; \\0 inserted"
+msgstr ""
+
+#: app.c:926
+msgid "end of file in escape character"
+msgstr ""
+
+#: app.c:938
+msgid "Missing close quote: (assumed)"
+msgstr ""
+
+#: app.c:997 app.c:1051 app.c:1120
+msgid "end of file in comment; newline inserted"
+msgstr ""
+
+#: app.c:1061
+msgid "EOF in Comment: Newline inserted"
+msgstr ""
+
+#: as.c:121
+#, c-format
+msgid "GNU assembler version %s (%s) using BFD version %s"
+msgstr ""
+
+#: as.c:124
+#, c-format
+msgid "GNU assembler version %s (%s)"
+msgstr ""
+
+#: as.c:133
+#, c-format
+msgid "Usage: %s [option...] [asmfile...]\n"
+msgstr ""
+
+#: as.c:135
+msgid ""
+"Options:\n"
+" -a[sub-option...]\tturn on listings\n"
+" Sub-options [default hls]:\n"
+" c omit false conditionals\n"
+" d omit debugging directives\n"
+" h include high-level source\n"
+" l include assembly\n"
+" m include macro expansions\n"
+" n omit forms processing\n"
+" s include symbols\n"
+" =file set listing file name (must be last sub-option)\n"
+msgstr ""
+
+#: as.c:148
+msgid ""
+" -D\t\t produce assembler debugging messages\n"
+" --defsym SYM=VAL define symbol SYM to given value\n"
+" -f\t\t skip whitespace and comment preprocessing\n"
+" --gstabs\t generate stabs debugging information\n"
+" --help\t\t show this message and exit\n"
+" -I DIR\t\t add DIR to search list for .include directives\n"
+" -J\t\t don't warn about signed overflow\n"
+" -K\t\t warn when differences altered for long displacements\n"
+" -L,--keep-locals keep local symbols (e.g. starting with `L')\n"
+msgstr ""
+
+#: as.c:159
+msgid ""
+" -M,--mri\t assemble in MRI compatibility mode\n"
+" --MD FILE\t write dependency information in FILE (default none)\n"
+" -nocpp\t\t ignored\n"
+" -o OBJFILE\t name the object-file output OBJFILE (default a.out)\n"
+" -R\t\t fold data section into text section\n"
+" --statistics\t print various measured statistics from execution\n"
+" --strip-local-absolute strip local absolute symbols\n"
+" --traditional-format\t Use same format as native assembler when possible\n"
+" --version\t\t print assembler version number and exit\n"
+" -W\t\t\t suppress warnings\n"
+" --itbl INSTTBL\t extend instruction set to include instructions\n"
+"\t\t\t matching the specifications defined in file INSTTBL\n"
+" -w\t\t\t ignored\n"
+" -X\t\t\t ignored\n"
+" -Z\t\t\t generate object file even after errors\n"
+msgstr ""
+
+#: as.c:176
+msgid ""
+" --listing-lhs-width\t set the width in words of the output data column "
+"of\n"
+"\t\t\t the listing\n"
+" --listing-lhs-width2\t set the width in words of the continuation lines\n"
+"\t\t\t of the output data column; ignored if smaller than\n"
+"\t\t\t the width of the first line\n"
+" --listing-rhs-width\t set the max width in characters of the lines from\n"
+"\t\t\t the source file\n"
+" --listing-cont-lines\t set the maximum number of continuation lines used\n"
+"\t\t\t for the output data column of the listing\n"
+msgstr ""
+
+#: as.c:189 gasp.c:3583
+msgid ""
+"\n"
+"Report bugs to bug-gnu-utils@gnu.org\n"
+msgstr ""
+
+#: as.c:226
+msgid "missing emulation mode name"
+msgstr ""
+
+#: as.c:241
+#, c-format
+msgid "unrecognized emulation name `%s'"
+msgstr ""
+
+#. This output is intended to follow the GNU standards document.
+#: as.c:459
+#, c-format
+msgid "GNU assembler %s\n"
+msgstr ""
+
+#: as.c:460
+msgid "Copyright 1997 Free Software Foundation, Inc.\n"
+msgstr ""
+
+#: as.c:461 gasp.c:3677
+msgid ""
+"This program is free software; you may redistribute it under the terms of\n"
+"the GNU General Public License. This program has absolutely no warranty.\n"
+msgstr ""
+
+#: as.c:464
+#, c-format
+msgid "This assembler was configured for a target of `%s'.\n"
+msgstr ""
+
+#: as.c:471
+msgid "multiple emulation names specified"
+msgstr ""
+
+#: as.c:473
+msgid "emulations not handled in this configuration"
+msgstr ""
+
+#: as.c:478
+#, c-format
+msgid "alias = %s\n"
+msgstr ""
+
+#: as.c:479
+#, c-format
+msgid "canonical = %s\n"
+msgstr ""
+
+#: as.c:480
+#, c-format
+msgid "cpu-type = %s\n"
+msgstr ""
+
+#: as.c:482
+#, c-format
+msgid "format = %s\n"
+msgstr ""
+
+#: as.c:485
+#, c-format
+msgid "bfd-target = %s\n"
+msgstr ""
+
+#: as.c:498
+msgid "bad defsym; format is --defsym name=value"
+msgstr ""
+
+#: as.c:518
+msgid "No file name following -t option\n"
+msgstr ""
+
+#: as.c:534
+#, c-format
+msgid "Failed to read instruction table %s\n"
+msgstr ""
+
+#: as.c:634
+#, c-format
+msgid "invalid listing option `%c'"
+msgstr ""
+
+#: as.c:856
+#, c-format
+msgid "%s: total time in assembly: %ld.%06ld\n"
+msgstr ""
+
+#: as.c:859
+#, c-format
+msgid "%s: data size %ld\n"
+msgstr ""
+
+#.
+#. * We have a GROSS internal error.
+#. * This should never happen.
+#.
+#: atof-generic.c:438 config/tc-a29k.c:544 config/tc-i860.c:335
+#: config/tc-i860.c:708 config/tc-m68k.c:3045 config/tc-m68k.c:3074
+#: config/tc-sparc.c:2157
+msgid "failed sanity check."
+msgstr ""
+
+#: cond.c:75
+msgid "invalid identifier for \".ifdef\""
+msgstr ""
+
+#: cond.c:128
+msgid "non-constant expression in \".if\" statement"
+msgstr ""
+
+#: cond.c:224
+msgid "bad format for ifc or ifnc"
+msgstr ""
+
+#: cond.c:257
+msgid "\".endif\" without \".if\""
+msgstr ""
+
+#: cond.c:287
+msgid ".else without matching .if - ignored"
+msgstr ""
+
+#: cond.c:292
+msgid "duplicate \"else\" - ignored"
+msgstr ""
+
+#: cond.c:295
+msgid "here is the previous \"else\""
+msgstr ""
+
+#: cond.c:298
+msgid "here is the previous \"if\""
+msgstr ""
+
+#: cond.c:343
+msgid ".ifeqs syntax error"
+msgstr ""
+
+#: cond.c:430
+msgid "end of macro inside conditional"
+msgstr ""
+
+#: cond.c:432
+msgid "end of file inside conditional"
+msgstr ""
+
+#: cond.c:435
+msgid "here is the start of the unterminated conditional"
+msgstr ""
+
+#: cond.c:439
+msgid "here is the \"else\" of the unterminated conditional"
+msgstr ""
+
+#: config/obj-aout.c:157
+#, c-format
+msgid "Attempt to put a common symbol into set %s"
+msgstr ""
+
+#: config/obj-aout.c:161
+#, c-format
+msgid "Attempt to put an undefined symbol into set %s"
+msgstr ""
+
+#: config/obj-aout.c:192 config/obj-elf.c:1527 ecoff.c:3663
+#, c-format
+msgid "Symbol `%s' can not be both weak and common"
+msgstr ""
+
+#: config/obj-aout.c:250 config/obj-coff.c:1766
+msgid "unresolved relocation"
+msgstr ""
+
+#: config/obj-aout.c:252 config/obj-coff.c:1768
+#, c-format
+msgid "bad relocation: symbol `%s' not in symbol table"
+msgstr ""
+
+#: config/obj-aout.c:339
+#, c-format
+msgid "%s: bad type for weak symbol"
+msgstr ""
+
+#: config/obj-aout.c:453 config/obj-coff.c:2700 write.c:1796
+#, c-format
+msgid "%s: global symbols not supported in common sections"
+msgstr ""
+
+#: config/obj-aout.c:520
+#, c-format
+msgid "Local symbol %s never defined."
+msgstr ""
+
+#: config/obj-aout.c:608
+msgid "subsegment index too high"
+msgstr ""
+
+#: config/obj-bout.c:312 config/obj-vms.c:566
+#, c-format
+msgid "Local symbol %s never defined"
+msgstr ""
+
+#: config/obj-coff.c:133
+#, c-format
+msgid "Inserting \"%s\" into structure table failed: %s"
+msgstr ""
+
+#: config/obj-coff.c:452 config/obj-coff.c:2113
+msgid ".ln pseudo-op inside .def/.endef: ignored."
+msgstr ""
+
+#: config/obj-coff.c:512 config/obj-coff.c:2170
+msgid ".def pseudo-op used inside of .def/.endef: ignored."
+msgstr ""
+
+#: config/obj-coff.c:558 config/obj-coff.c:2223
+msgid ".endef pseudo-op used outside of .def/.endef: ignored."
+msgstr ""
+
+#: config/obj-coff.c:592
+#, c-format
+msgid "`%s' symbol without preceding function"
+msgstr ""
+
+#: config/obj-coff.c:634 config/obj-coff.c:2298
+#, c-format
+msgid "unexpected storage class %d"
+msgstr ""
+
+#: config/obj-coff.c:736 config/obj-coff.c:2405
+msgid ".dim pseudo-op used outside of .def/.endef: ignored."
+msgstr ""
+
+#: config/obj-coff.c:756 config/obj-coff.c:2425
+msgid "badly formed .dim directive ignored"
+msgstr ""
+
+#: config/obj-coff.c:807 config/obj-coff.c:2488
+msgid ".size pseudo-op used outside of .def/.endef ignored."
+msgstr ""
+
+#: config/obj-coff.c:823 config/obj-coff.c:2504
+msgid ".scl pseudo-op used outside of .def/.endef ignored."
+msgstr ""
+
+#: config/obj-coff.c:841 config/obj-coff.c:2522
+msgid ".tag pseudo-op used outside of .def/.endef ignored."
+msgstr ""
+
+#: config/obj-coff.c:860 config/obj-coff.c:2540
+#, c-format
+msgid "tag not found for .tag %s"
+msgstr ""
+
+#: config/obj-coff.c:875 config/obj-coff.c:2555
+msgid ".type pseudo-op used outside of .def/.endef ignored."
+msgstr ""
+
+#: config/obj-coff.c:897 config/obj-coff.c:2577
+msgid ".val pseudo-op used outside of .def/.endef ignored."
+msgstr ""
+
+#: config/obj-coff.c:1026 config/obj-coff.c:2773
+msgid "mismatched .eb"
+msgstr ""
+
+#: config/obj-coff.c:1044 config/obj-coff.c:2813
+msgid "C_EFCN symbol out of scope"
+msgstr ""
+
+#. STYP_INFO
+#. STYP_LIB
+#. STYP_OVER
+#: config/obj-coff.c:1253
+#, c-format
+msgid "unsupported section attribute '%c'"
+msgstr ""
+
+#: config/obj-coff.c:1258 config/obj-coff.c:3516 config/tc-ppc.c:3778
+#, c-format
+msgid "unknown section attribute '%c'"
+msgstr ""
+
+#: config/obj-coff.c:1280 config/tc-ppc.c:3796 read.c:2478
+#, c-format
+msgid "error setting flags for \"%s\": %s"
+msgstr ""
+
+#: config/obj-coff.c:1399
+#, c-format
+msgid "0x%lx: \"%s\" type = %ld, class = %d, segment = %d\n"
+msgstr ""
+
+#: config/obj-coff.c:1593 config/obj-ieee.c:69
+msgid "Out of step\n"
+msgstr ""
+
+#: config/obj-coff.c:2028
+msgid "bfd_coff_swap_scnhdr_out failed"
+msgstr ""
+
+#: config/obj-coff.c:2255
+msgid "`.bf' symbol without preceding function\n"
+msgstr ""
+
+#: config/obj-coff.c:3216 config/obj-ieee.c:522 output-file.c:52
+#: output-file.c:119
+#, c-format
+msgid "FATAL: Can't create %s"
+msgstr ""
+
+#: config/obj-coff.c:3390
+#, c-format
+msgid "Can't close %s: %s"
+msgstr ""
+
+#: config/obj-coff.c:3424
+#, c-format
+msgid "Too many new sections; can't add \"%s\""
+msgstr ""
+
+#: config/obj-coff.c:3834 config/tc-m88k.c:1260 config/tc-sparc.c:3015
+msgid "Expected comma after name"
+msgstr ""
+
+#: config/obj-coff.c:3840 read.c:1934
+msgid "Missing size expression"
+msgstr ""
+
+#: config/obj-coff.c:3846
+#, c-format
+msgid "lcomm length (%d.) <0! Ignored."
+msgstr ""
+
+#: config/obj-coff.c:3874 read.c:2160
+#, c-format
+msgid "Symbol %s already defined"
+msgstr ""
+
+#: config/obj-coff.c:3968 config/tc-i960.c:3201
+#, c-format
+msgid "No 'bal' entry point for leafproc %s"
+msgstr ""
+
+#: config/obj-coff.c:4047 write.c:2501
+#, c-format
+msgid "Negative of non-absolute symbol %s"
+msgstr ""
+
+#: config/obj-coff.c:4068 write.c:2515
+msgid "callj to difference of 2 symbols"
+msgstr ""
+
+#: config/obj-coff.c:4114
+#, c-format
+msgid "Can't emit reloc {- %s-seg symbol \"%s\"} @ file address %ld."
+msgstr ""
+
+#. This is a COBR instruction. They have only a 13-bit
+#. displacement and are only to be used for local branches:
+#. flag as error, don't generate relocation.
+#: config/obj-coff.c:4204 config/tc-i960.c:3221 write.c:2659
+msgid "can't use COBR format with external label"
+msgstr ""
+
+#: config/obj-coff.c:4278
+#, c-format
+msgid "Value of %ld too large for field of %d bytes at 0x%lx"
+msgstr ""
+
+#: config/obj-coff.c:4292 write.c:2747
+#, c-format
+msgid "Signed .word overflow; switch may be too large; %ld at 0x%lx"
+msgstr ""
+
+#: config/obj-ecoff.c:239
+msgid "Can't set GP value"
+msgstr ""
+
+#: config/obj-ecoff.c:246
+msgid "Can't set register masks"
+msgstr ""
+
+#: config/obj-elf.c:274 config/tc-sparc.c:3156 config/tc-v850.c:263
+msgid "Expected comma after symbol-name"
+msgstr ""
+
+#: config/obj-elf.c:281 config/tc-arc.c:778 config/tc-sparc.c:3163
+#, c-format
+msgid ".COMMon length (%d.) <0! Ignored."
+msgstr ""
+
+#: config/obj-elf.c:291 config/tc-alpha.c:3429 config/tc-sparc.c:3173
+#: config/tc-v850.c:285
+msgid "Ignoring attempt to re-define symbol"
+msgstr ""
+
+#: config/obj-elf.c:299 config/tc-arc.c:796 config/tc-sparc.c:3181
+#: config/tc-v850.c:295
+#, c-format
+msgid "Length of .comm \"%s\" is already %ld. Not changed to %d."
+msgstr ""
+
+#: config/obj-elf.c:322 config/tc-arc.c:815 config/tc-v850.c:322
+msgid "Common alignment negative; 0 assumed"
+msgstr ""
+
+#: config/obj-elf.c:341 config/tc-m32r.c:1298 config/tc-ppc.c:1389
+#: config/tc-v850.c:385
+msgid "Common alignment not a power of 2"
+msgstr ""
+
+#: config/obj-elf.c:404 config/tc-arc.c:875 config/tc-sparc.c:3305
+#: config/tc-v850.c:563
+#, c-format
+msgid "bad .common segment %s"
+msgstr ""
+
+#: config/obj-elf.c:589
+msgid "Missing section name"
+msgstr ""
+
+#: config/obj-elf.c:654
+msgid "Bad .section directive: want a,w,x in string"
+msgstr ""
+
+#: config/obj-elf.c:703
+msgid "Unrecognized section type"
+msgstr ""
+
+#: config/obj-elf.c:717
+msgid "Bad .section directive - character following name is not '#'"
+msgstr ""
+
+#: config/obj-elf.c:749
+msgid "Unrecognized section attribute"
+msgstr ""
+
+#: config/obj-elf.c:770
+#, c-format
+msgid "Setting incorrect section type for %s"
+msgstr ""
+
+#: config/obj-elf.c:780
+#, c-format
+msgid "Setting incorrect section attributes for %s"
+msgstr ""
+
+#: config/obj-elf.c:905
+msgid ".previous without corresponding .section; ignored"
+msgstr ""
+
+#: config/obj-elf.c:954
+#, c-format
+msgid "multiple .symver directives for symbol `%s'"
+msgstr ""
+
+#: config/obj-elf.c:963
+msgid "expected comma after name in .symver"
+msgstr ""
+
+#: config/obj-elf.c:984
+#, c-format
+msgid "missing version name in `%s' for symbol `%s'"
+msgstr ""
+
+#: config/obj-elf.c:1187 config/obj-som.c:148 config/obj-som.c:193
+msgid "Expected quoted string"
+msgstr ""
+
+#: config/obj-elf.c:1208
+#, c-format
+msgid "expected comma after name `%s' in .size directive"
+msgstr ""
+
+#: config/obj-elf.c:1217
+msgid "missing expression in .size directive"
+msgstr ""
+
+#: config/obj-elf.c:1283
+#, c-format
+msgid "ignoring unrecognized symbol type \"%s\""
+msgstr ""
+
+#: config/obj-elf.c:1453
+msgid ".size expression too complicated to fix up"
+msgstr ""
+
+#: config/obj-elf.c:1484
+#, c-format
+msgid ""
+"invalid attempt to declare external version name as default in symbol `%s'"
+msgstr ""
+
+#: config/obj-elf.c:1610
+#, c-format
+msgid "Failed to set up debugging information: %s"
+msgstr ""
+
+#: config/obj-elf.c:1626
+#, c-format
+msgid "Can't start writing .mdebug section: %s"
+msgstr ""
+
+#: config/obj-elf.c:1634
+#, c-format
+msgid "Could not write .mdebug section: %s"
+msgstr ""
+
+#: config/obj-ieee.c:460
+msgid "too many sections"
+msgstr ""
+
+#: config/obj-som.c:131
+msgid "Only one .version pseudo-op per file!"
+msgstr ""
+
+#: config/obj-som.c:157
+#, c-format
+msgid "FATAL: Attaching version header %s"
+msgstr ""
+
+#: config/obj-som.c:176
+msgid "Only one .copyright pseudo-op per file!"
+msgstr ""
+
+#: config/obj-som.c:202
+#, c-format
+msgid "FATAL: Attaching copyright header %s"
+msgstr ""
+
+#: config/obj-vms.c:464
+#, c-format
+msgid "compiler emitted zero-size common symbol `%s' already defined"
+msgstr ""
+
+#: config/obj-vms.c:474
+#, c-format
+msgid "compiler redefined zero-size common symbol `%s'"
+msgstr ""
+
+#: config/obj-vms.c:597
+#, c-format
+msgid "Couldn't create VMS object file \"%s\""
+msgstr ""
+
+#: config/obj-vms.c:623
+msgid "I/O error writing VMS object file (length prefix)"
+msgstr ""
+
+#: config/obj-vms.c:637
+msgid "I/O error writing VMS object file"
+msgstr ""
+
+#: config/obj-vms.c:1240
+msgid "Couldn't find source file \"%s\", status=%%X%x"
+msgstr ""
+
+#: config/obj-vms.c:1749 config/obj-vms.c:2937
+#, c-format
+msgid "debugger forward reference error, dbx type %d"
+msgstr ""
+
+#: config/obj-vms.c:1825
+#, c-format
+msgid "Variable descriptor %d too complicated. Defined as `void *'."
+msgstr ""
+
+#: config/obj-vms.c:2144
+msgid ""
+"***Warning - the assembly code generated by the compiler has placed \n"
+" global constant(s) in the text psect. These will not be available to \n"
+" other modules, since this is not the correct way to handle this. You \n"
+" have two options: 1) get a patched compiler that does not put global \n"
+" constants in the text psect, or 2) remove the 'const' keyword from \n"
+" definitions of global variables in your source module(s). Don't say \n"
+" I didn't warn you! \n"
+msgstr ""
+
+#: config/obj-vms.c:2463
+#, c-format
+msgid "debugginer output: %d is an unknown untyped variable."
+msgstr ""
+
+#: config/obj-vms.c:2681
+#, c-format
+msgid "debugger output: structure element `%s' has undefined type"
+msgstr ""
+
+#: config/obj-vms.c:2792
+#, c-format
+msgid "debugger output: %d is an unknown type of variable."
+msgstr ""
+
+#: config/obj-vms.c:2926
+#, c-format
+msgid "debugger output: Unable to resolve %d circular references."
+msgstr ""
+
+#: config/obj-vms.c:3131
+#, c-format
+msgid "Module name truncated: %s\n"
+msgstr ""
+
+#: config/obj-vms.c:3410
+#, c-format
+msgid "Symbol %s replaced by %s\n"
+msgstr ""
+
+#. impossible
+#: config/obj-vms.c:3694
+#, c-format
+msgid "Unknown VMS psect type (%ld)"
+msgstr ""
+
+#: config/obj-vms.c:3735
+#, c-format
+msgid "Globalsymbol attribute for symbol %s was unexpected."
+msgstr ""
+
+#: config/obj-vms.c:3885
+msgid "Invalid data type for globalvalue"
+msgstr ""
+
+#: config/obj-vms.c:3897
+#, c-format
+msgid "Invalid globalvalue of %s"
+msgstr ""
+
+#: config/obj-vms.c:4247
+msgid "Couldn't find fixup fragment when checking for indirect reference"
+msgstr ""
+
+#: config/obj-vms.c:4591 config/obj-vms.c:4733
+msgid "Fixup data addsy and subsy don't have the same type"
+msgstr ""
+
+#: config/obj-vms.c:4595 config/obj-vms.c:4737
+msgid "Fixup data addsy and subsy don't have an appropriate type"
+msgstr ""
+
+#: config/obj-vms.c:4598 config/obj-vms.c:4740
+msgid "Fixup data is erroneously \"pcrel\""
+msgstr ""
+
+#: config/obj-vms.c:4614 config/obj-vms.c:4759
+msgid "Fixup datum is not a longword"
+msgstr ""
+
+#: config/obj-vms.c:4618 config/obj-vms.c:4763
+msgid "Fixup datum is not \"fixP->fx_addsy\""
+msgstr ""
+
+#: config/obj-vms.c:4834
+#, c-format
+msgid ""
+"g++ wrote an extern reference to `%s' as a routine.\n"
+"I will fix it, but I hope that it was note really a routine."
+msgstr ""
+
+#: config/obj-vms.c:4966
+msgid "Can't handle global xtors symbols yet."
+msgstr ""
+
+#: config/obj-vms.c:4969
+#, c-format
+msgid "Unknown %s"
+msgstr ""
+
+#.
+#. * Error otherwise.
+#.
+#: config/obj-vms.c:5054
+#, c-format
+msgid "unhandled stab type %d"
+msgstr ""
+
+#: config/tc-a29k.c:160 config/tc-sparc.c:3357
+msgid "Unknown segment type"
+msgstr ""
+
+#. Probably a memory allocation problem? Give up now.
+#: config/tc-a29k.c:330 config/tc-hppa.c:1354 config/tc-i860.c:202
+#: config/tc-mips.c:1102 config/tc-mips.c:1144 config/tc-sparc.c:715
+msgid "Broken assembler. No assembly attempted."
+msgstr ""
+
+#: config/tc-a29k.c:375 config/tc-arc.c:534 config/tc-d10v.c:481
+#: config/tc-d30v.c:540 config/tc-h8300.c:305 config/tc-h8500.c:297
+#: config/tc-mcore.c:380 config/tc-mn10200.c:936 config/tc-mn10300.c:1307
+#: config/tc-ppc.c:1844 config/tc-sh.c:478 config/tc-tic80.c:291
+#: config/tc-v850.c:2033 config/tc-w65.c:257 config/tc-z8k.c:341
+msgid "missing operand"
+msgstr ""
+
+#: config/tc-a29k.c:415 config/tc-hppa.c:1471 config/tc-i860.c:407
+#: config/tc-i860.c:423 config/tc-sparc.c:1191 config/tc-sparc.c:1197
+#, c-format
+msgid "Unknown opcode: `%s'"
+msgstr ""
+
+#: config/tc-a29k.c:420
+#, c-format
+msgid "Unknown opcode `%s'."
+msgstr ""
+
+#: config/tc-a29k.c:452
+#, c-format
+msgid "Too many operands: %s"
+msgstr ""
+
+#: config/tc-a29k.c:474 config/tc-a29k.c:505
+#, c-format
+msgid "Immediate value of %ld is too large"
+msgstr ""
+
+#: config/tc-a29k.c:892 config/tc-i860.c:940
+#, c-format
+msgid "bad relocation type: 0x%02x"
+msgstr ""
+
+#: config/tc-a29k.c:916
+#, c-format
+msgid "need %o3\n"
+msgstr ""
+
+#: config/tc-a29k.c:932
+msgid "a29k_convert_frag\n"
+msgstr ""
+
+#: config/tc-a29k.c:941
+msgid "a29k_estimate_size_before_relax\n"
+msgstr ""
+
+#: config/tc-a29k.c:1092
+#, c-format
+msgid "label \"$%d\" redefined"
+msgstr ""
+
+#: config/tc-a29k.c:1165
+msgid "Invalid expression after %%%%\n"
+msgstr ""
+
+#: config/tc-a29k.c:1176
+msgid "Invalid register in & expression"
+msgstr ""
+
+#: config/tc-alpha.c:722
+#, c-format
+msgid "internal error: can't hash opcode `%s': %s"
+msgstr ""
+
+#: config/tc-alpha.c:756
+#, c-format
+msgid "internal error: can't hash macro `%s': %s"
+msgstr ""
+
+#: config/tc-alpha.c:832 config/tc-i960.c:2711
+msgid "syntax error"
+msgstr ""
+
+#: config/tc-alpha.c:905 config/tc-arm.c:4982 config/tc-h8300.c:1413
+#: config/tc-h8500.c:1222 config/tc-hppa.c:3651 config/tc-i860.c:813
+#: config/tc-m68k.c:4003 config/tc-m88k.c:1106 config/tc-ns32k.c:1588
+#: config/tc-sparc.c:2433 config/tc-z8k.c:1355
+msgid "Bad call to MD_ATOF()"
+msgstr ""
+
+#: config/tc-alpha.c:955
+#, c-format
+msgid "Unknown CPU identifier `%s'"
+msgstr ""
+
+#: config/tc-alpha.c:999
+msgid ""
+"Alpha options:\n"
+"-32addr\t\t\ttreat addresses as 32-bit values\n"
+"-F\t\t\tlack floating point instructions support\n"
+"-mev4 | -mev45 | -mev5 | -mev56 | -mpca56 | -mev6 | -mall\n"
+"\t\t\tspecify variant of Alpha architecture\n"
+"-m21064 | -m21066 | -m21164 | -m21164a | -m21164pc | -m21264\n"
+"\t\t\tthese variants include PALcode opcodes\n"
+msgstr ""
+
+#: config/tc-alpha.c:1009
+msgid ""
+"VMS options:\n"
+"-+\t\t\thash encode (don't truncate) names longer than 64 characters\n"
+"-H\t\t\tshow new symbol after hash truncation\n"
+msgstr ""
+
+#: config/tc-alpha.c:1165
+#, c-format
+msgid "unhandled relocation type %s"
+msgstr ""
+
+#: config/tc-alpha.c:1178
+msgid "non-absolute expression in constant field"
+msgstr ""
+
+#: config/tc-alpha.c:1192
+#, c-format
+msgid "type %d reloc done?\n"
+msgstr ""
+
+#: config/tc-alpha.c:1243 config/tc-alpha.c:1250 config/tc-mips.c:7777
+msgid "Used $at without \".set noat\""
+msgstr ""
+
+#: config/tc-alpha.c:1407
+#, c-format
+msgid "cannot represent `%s' relocation in object file"
+msgstr ""
+
+#: config/tc-alpha.c:1414
+#, c-format
+msgid "internal error? cannot generate `%s' relocation"
+msgstr ""
+
+#: config/tc-alpha.c:1468
+#, c-format
+msgid "frame reg expected, using $%d."
+msgstr ""
+
+#: config/tc-alpha.c:1793
+#, c-format
+msgid "operand out of range (%s not between %d and %d)"
+msgstr ""
+
+#: config/tc-alpha.c:1890 config/tc-arc.c:547 config/tc-d10v.c:570
+#: config/tc-d30v.c:623 config/tc-mn10200.c:991 config/tc-mn10300.c:1382
+#: config/tc-ppc.c:1810 config/tc-ppc.c:1917 config/tc-ppc.c:1929
+#: config/tc-v850.c:1819 config/tc-v850.c:1842 config/tc-v850.c:2055
+msgid "too many fixups"
+msgstr ""
+
+#: config/tc-alpha.c:2015 config/tc-alpha.c:2073
+#, c-format
+msgid "inappropriate arguments for opcode `%s'"
+msgstr ""
+
+#: config/tc-alpha.c:2017 config/tc-alpha.c:2075
+#, c-format
+msgid "opcode `%s' not supported for target %s"
+msgstr ""
+
+#: config/tc-alpha.c:2021 config/tc-alpha.c:2078
+#, c-format
+msgid "unknown opcode `%s'"
+msgstr ""
+
+#: config/tc-alpha.c:2130
+msgid "can not resolve expression"
+msgstr ""
+
+#: config/tc-alpha.c:2268 config/tc-alpha.c:2445
+msgid "overflow in literal (.lita) table"
+msgstr ""
+
+#: config/tc-alpha.c:2275 config/tc-alpha.c:2297 config/tc-alpha.c:2458
+#: config/tc-alpha.c:2680 config/tc-alpha.c:2727 config/tc-alpha.c:2775
+#: config/tc-alpha.c:2864 config/tc-alpha.c:3065 config/tc-alpha.c:3166
+msgid "macro requires $at register while noat in effect"
+msgstr ""
+
+#: config/tc-alpha.c:2277 config/tc-alpha.c:2299 config/tc-alpha.c:2460
+msgid "macro requires $at while $at in use"
+msgstr ""
+
+#: config/tc-alpha.c:2407 expr.c:82 read.c:3101
+msgid "bignum invalid; zero assumed"
+msgstr ""
+
+#: config/tc-alpha.c:2409 expr.c:84 read.c:3103 read.c:3432 read.c:4328
+msgid "floating point number invalid; zero assumed"
+msgstr ""
+
+#: config/tc-alpha.c:2414
+msgid "can't handle expression"
+msgstr ""
+
+#: config/tc-alpha.c:2451
+msgid "overflow in literal (.lit8) table"
+msgstr ""
+
+#: config/tc-alpha.c:3400 config/tc-ppc.c:1338 config/tc-ppc.c:3542
+#: read.c:1358
+#, c-format
+msgid ".COMMon length (%ld.) <0! Ignored."
+msgstr ""
+
+#: config/tc-alpha.c:3438 config/tc-alpha.c:3447 config/tc-ppc.c:3579
+#: read.c:1379
+#, c-format
+msgid "Length of .comm \"%s\" is already %ld. Not changed to %ld."
+msgstr ""
+
+#: config/tc-alpha.c:3549 ecoff.c:3105
+msgid ".ent directive has no name"
+msgstr ""
+
+#: config/tc-alpha.c:3557
+msgid "nested .ent directives"
+msgstr ""
+
+#: config/tc-alpha.c:3593 ecoff.c:3053
+msgid ".end directive has no name"
+msgstr ""
+
+#: config/tc-alpha.c:3602
+msgid ".end directive names different symbol than .ent"
+msgstr ""
+
+#: config/tc-alpha.c:3676
+#, c-format
+msgid "Invalid argument %d to .prologue."
+msgstr ""
+
+#: config/tc-alpha.c:3704
+msgid "ECOFF debugging is disabled."
+msgstr ""
+
+#: config/tc-alpha.c:3725
+msgid "Unknown section directive"
+msgstr ""
+
+#: config/tc-alpha.c:3762
+msgid ".ent directive has no symbol"
+msgstr ""
+
+#: config/tc-alpha.c:3790
+msgid "Bad .frame directive 1./2. param"
+msgstr ""
+
+#: config/tc-alpha.c:3802
+msgid "Bad .frame directive 3./4. param"
+msgstr ""
+
+#: config/tc-alpha.c:3827
+msgid ".pdesc directive not in link (.link) section"
+msgstr ""
+
+#: config/tc-alpha.c:3835
+msgid ".pdesc has no matching .ent"
+msgstr ""
+
+#: config/tc-alpha.c:3845
+msgid ".pdesc directive has no entry symbol"
+msgstr ""
+
+#: config/tc-alpha.c:3857
+msgid "No comma after .pdesc <entryname>"
+msgstr ""
+
+#: config/tc-alpha.c:3880
+msgid "unknown procedure kind"
+msgstr ""
+
+#: config/tc-alpha.c:3975
+msgid ".name directive not in link (.link) section"
+msgstr ""
+
+#: config/tc-alpha.c:3983
+msgid ".name directive has no symbol"
+msgstr ""
+
+#: config/tc-alpha.c:4018
+msgid "No symbol after .linkage"
+msgstr ""
+
+#: config/tc-alpha.c:4047
+msgid "No symbol after .code_address"
+msgstr ""
+
+#: config/tc-alpha.c:4082 ecoff.c:3269
+msgid "Bad .mask directive"
+msgstr ""
+
+#: config/tc-alpha.c:4104 ecoff.c:3200
+msgid "Bad .fmask directive"
+msgstr ""
+
+#: config/tc-alpha.c:4275 read.c:2123 read.c:2675 stabs.c:460
+#, c-format
+msgid "Expected comma after name \"%s\""
+msgstr ""
+
+#. symbolP->sy_other = (signed char) temp;
+#: config/tc-alpha.c:4286
+#, c-format
+msgid "unhandled: .proc %s,%d"
+msgstr ""
+
+#: config/tc-alpha.c:4321
+#, c-format
+msgid "Tried to .set unrecognized mode `%s'"
+msgstr ""
+
+#. not fatal, but it might not work in the end
+#: config/tc-alpha.c:4338
+msgid "File overrides no-base-register option."
+msgstr ""
+
+#: config/tc-alpha.c:4355
+#, c-format
+msgid "Bad base register, using $%d."
+msgstr ""
+
+#: config/tc-alpha.c:4377
+#, c-format
+msgid "Alignment too large: %d. assumed"
+msgstr ""
+
+#: config/tc-alpha.c:4381 config/tc-d30v.c:2163
+msgid "Alignment negative: 0 assumed"
+msgstr ""
+
+#: config/tc-alpha.c:4694
+#, c-format
+msgid "Chose GP value of %lx\n"
+msgstr ""
+
+#: config/tc-arc.c:136
+msgid ""
+"ARC options:\n"
+"-EB\t\t\tgenerate big endian output\n"
+"-EL\t\t\tgenerate little endian output\n"
+msgstr ""
+
+#: config/tc-arc.c:154 config/tc-arc.c:177 config/tc-arc.c:921
+#: config/tc-hppa.c:1316 config/tc-hppa.c:6410 config/tc-hppa.c:6416
+#: config/tc-hppa.c:6422 config/tc-mn10300.c:890 config/tc-mn10300.c:2023
+msgid "could not set architecture and machine"
+msgstr ""
+
+#: config/tc-arc.c:174
+msgid "virtual memory exhausted"
+msgstr ""
+
+#: config/tc-arc.c:253 config/tc-mn10200.c:1354 config/tc-mn10300.c:1930
+#: config/tc-ppc.c:1095 config/tc-v850.c:1618
+#, c-format
+msgid "operand out of range (%s not between %ld and %ld)"
+msgstr ""
+
+#: config/tc-arc.c:388
+#, c-format
+msgid "unknown syntax format character `%c'"
+msgstr ""
+
+#: config/tc-arc.c:487
+msgid "too many suffixes"
+msgstr ""
+
+#: config/tc-arc.c:532 config/tc-d10v.c:479 config/tc-d30v.c:538
+#: config/tc-mn10200.c:933 config/tc-mn10300.c:1304 config/tc-ppc.c:1842
+#: config/tc-tic80.c:287 config/tc-v850.c:2030
+msgid "illegal operand"
+msgstr ""
+
+#: config/tc-arc.c:619 config/tc-mn10200.c:1032 config/tc-mn10300.c:1452
+#: config/tc-ppc.c:1966 config/tc-v850.c:2108
+#, c-format
+msgid "junk at end of line: `%s'"
+msgstr ""
+
+#: config/tc-arc.c:659
+msgid "8 byte instruction in delay slot"
+msgstr ""
+
+#: config/tc-arc.c:661
+msgid "8 byte jump instruction with delay slot"
+msgstr ""
+
+#: config/tc-arc.c:669
+msgid "conditional branch follows set of flags"
+msgstr ""
+
+#: config/tc-arc.c:748 config/tc-arm.c:6041
+#, c-format
+msgid "bad instruction `%s'"
+msgstr ""
+
+#: config/tc-arc.c:771
+msgid "expected comma after symbol-name"
+msgstr ""
+
+#: config/tc-arc.c:788
+msgid "ignoring attempt to re-define symbol"
+msgstr ""
+
+#: config/tc-arc.c:803
+msgid "expected comma after common length"
+msgstr ""
+
+#: config/tc-arc.c:896
+msgid ".cpu command must appear before any instructions"
+msgstr ""
+
+#: config/tc-arc.c:915
+msgid ".cpu conflicts with previous value"
+msgstr ""
+
+#: config/tc-arc.c:926
+msgid "bad .cpu op"
+msgstr ""
+
+#: config/tc-arc.c:950 config/tc-ppc.c:2615
+msgid "missing rename string"
+msgstr ""
+
+#: config/tc-arc.c:962
+msgid "invalid symbol to rename to"
+msgstr ""
+
+#: config/tc-arc.c:1009 config/tc-d10v.c:274 config/tc-d30v.c:353
+#: config/tc-mips.c:9317 config/tc-mn10200.c:356 config/tc-ppc.c:4363
+#: config/tc-sh.c:1187 config/tc-v850.c:1276
+msgid "bad call to md_atof"
+msgstr ""
+
+#: config/tc-arc.c:1096
+#, c-format
+msgid "missing ')' in %-op"
+msgstr ""
+
+#: config/tc-arc.c:1130
+msgid "expression too complex for %%st"
+msgstr ""
+
+#: config/tc-arc.c:1324 config/tc-arm.c:2937 config/tc-d10v.c:1448
+#: config/tc-d30v.c:1810 config/tc-mips.c:3361 config/tc-mips.c:4317
+#: config/tc-mips.c:5102 config/tc-mips.c:5648 config/tc-ppc.c:4698
+#: config/tc-v850.c:2339
+msgid "expression too complex"
+msgstr ""
+
+#: config/tc-arc.c:1390 config/tc-ppc.c:4801 config/tc-v850.c:2383
+msgid "unresolved expression that must be resolved"
+msgstr ""
+
+#: config/tc-arc.c:1454 config/tc-sparc.c:2880
+#, c-format
+msgid "internal error: can't export reloc type %d (`%s')"
+msgstr ""
+
+#: config/tc-arm.c:983
+msgid "Literal Pool Overflow"
+msgstr ""
+
+#: config/tc-arm.c:1103
+msgid "Invalid syntax for .req directive."
+msgstr ""
+
+#: config/tc-arm.c:1139
+msgid "Nothing to put in the pool\n"
+msgstr ""
+
+#: config/tc-arm.c:1151
+msgid "Inserting implicit pool at change of section"
+msgstr ""
+
+#: config/tc-arm.c:1183 config/tc-mips.c:10603 read.c:2017
+#, c-format
+msgid "Alignment too large: %d. assumed."
+msgstr ""
+
+#: config/tc-arm.c:1186 read.c:2022
+msgid "Alignment negative. 0 assumed."
+msgstr ""
+
+#: config/tc-arm.c:1251
+msgid "selected processor does not support THUMB opcodes"
+msgstr ""
+
+#: config/tc-arm.c:1263
+msgid "selected processor does not support ARM opcodes"
+msgstr ""
+
+#: config/tc-arm.c:1272
+#, c-format
+msgid "invalid instruction size selected (%d)"
+msgstr ""
+
+#: config/tc-arm.c:1307
+#, c-format
+msgid "invalid operand to .code directive (%d) (expecting 16 or 32)"
+msgstr ""
+
+#: config/tc-arm.c:1319
+msgid "Garbage following instruction"
+msgstr ""
+
+#. In the few cases where we might be able to accept something else
+#. this error can be overridden
+#: config/tc-arm.c:1367
+#, c-format
+msgid "Register expected, not '%.100s'"
+msgstr ""
+
+#. In the few cases where we might be able to accept something else
+#. this error can be overridden
+#: config/tc-arm.c:1393
+msgid "<psr(f)> expected"
+msgstr ""
+
+#: config/tc-arm.c:1424
+msgid "Illegal co-processor number"
+msgstr ""
+
+#: config/tc-arm.c:1431
+msgid "Bad or missing co-processor number"
+msgstr ""
+
+#: config/tc-arm.c:1456
+msgid "bad or missing expression"
+msgstr ""
+
+#: config/tc-arm.c:1462
+msgid "immediate co-processor expression too large"
+msgstr ""
+
+#. In the few cases where we might be able to accept something else
+#. this error can be overridden
+#: config/tc-arm.c:1487
+msgid "Co-processor register expected"
+msgstr ""
+
+#. In the few cases where we might be able to accept something else
+#. this error can be overridden
+#: config/tc-arm.c:1511
+msgid "Floating point register expected"
+msgstr ""
+
+#: config/tc-arm.c:1529
+msgid "immediate expression expected"
+msgstr ""
+
+#: config/tc-arm.c:1544
+msgid "co-processor address must be word aligned"
+msgstr ""
+
+#: config/tc-arm.c:1550
+msgid "offset too large"
+msgstr ""
+
+#: config/tc-arm.c:1600
+msgid "pc may not be used in post-increment"
+msgstr ""
+
+#: config/tc-arm.c:1616 config/tc-arm.c:2727
+msgid "pre-indexed expression expected"
+msgstr ""
+
+#: config/tc-arm.c:1630 config/tc-arm.c:2740 config/tc-arm.c:3089
+msgid "missing ]"
+msgstr ""
+
+#: config/tc-arm.c:1641
+msgid "pc may not be used with write-back"
+msgstr ""
+
+#: config/tc-arm.c:1696
+msgid "<psr> expected"
+msgstr ""
+
+#: config/tc-arm.c:1758 config/tc-arm.c:2378
+msgid "Register or shift expression expected"
+msgstr ""
+
+#: config/tc-arm.c:1772 config/tc-arm.c:2090 config/tc-arm.c:2345
+#: config/tc-arm.c:2365
+msgid "Invalid constant"
+msgstr ""
+
+#: config/tc-arm.c:1783
+msgid "Error: unrecognised syntax for second argument to msr instruction"
+msgstr ""
+
+#: config/tc-arm.c:1833
+msgid "rdhi, rdlo and rm must all be different"
+msgstr ""
+
+#: config/tc-arm.c:1890
+msgid "rd and rm should be different in mul"
+msgstr ""
+
+#: config/tc-arm.c:1947
+msgid "rd and rm should be different in mla"
+msgstr ""
+
+#: config/tc-arm.c:2074
+msgid "bad_segment"
+msgstr ""
+
+#: config/tc-arm.c:2121 config/tc-arm.c:2199
+msgid "Shift expression expected"
+msgstr ""
+
+#: config/tc-arm.c:2163
+msgid "Invalid immediate shift"
+msgstr ""
+
+#: config/tc-arm.c:2192
+msgid "shift requires register or #expression"
+msgstr ""
+
+#: config/tc-arm.c:2193
+msgid "shift requires #expression"
+msgstr ""
+
+#: config/tc-arm.c:2336 config/tc-arm.c:2770
+msgid "Constant expression expected"
+msgstr ""
+
+#: config/tc-arm.c:2432
+msgid "Invalid floating point immediate expression"
+msgstr ""
+
+#: config/tc-arm.c:2435
+msgid "Floating point register or immediate expression expected"
+msgstr ""
+
+#: config/tc-arm.c:2574
+msgid "address offset too large"
+msgstr ""
+
+#: config/tc-arm.c:2645
+msgid "Processor does not support halfwords or signed bytes"
+msgstr ""
+
+#: config/tc-arm.c:2667
+msgid "Address expected"
+msgstr ""
+
+#: config/tc-arm.c:2698 config/tc-arm.c:2712 config/tc-arm.c:2750
+msgid "destination register same as write-back base\n"
+msgstr ""
+
+#: config/tc-arm.c:2790
+msgid "literal pool insertion failed"
+msgstr ""
+
+#: config/tc-arm.c:2826
+msgid "Pre-increment instruction with translate"
+msgstr ""
+
+#: config/tc-arm.c:2868
+msgid "Bad range in register list"
+msgstr ""
+
+#: config/tc-arm.c:2876 config/tc-arm.c:2885 config/tc-arm.c:2927
+#, c-format
+msgid "Warning: Duplicated register (r%d) in register list"
+msgstr ""
+
+#: config/tc-arm.c:2888
+msgid "Warning: Register range not in ascending order"
+msgstr ""
+
+#: config/tc-arm.c:2900
+msgid "Missing `}'"
+msgstr ""
+
+#: config/tc-arm.c:2916
+msgid "invalid register mask"
+msgstr ""
+
+#: config/tc-arm.c:2977
+msgid "r15 not allowed as base register"
+msgstr ""
+
+#: config/tc-arm.c:3047 config/tc-arm.c:3061
+msgid "r15 not allowed in swap"
+msgstr ""
+
+#: config/tc-arm.c:3158
+msgid "Use of r15 in bx has undefined behaviour"
+msgstr ""
+
+#: config/tc-arm.c:3417 config/tc-v850.c:1921 config/tc-v850.c:1942
+msgid "constant expression expected"
+msgstr ""
+
+#: config/tc-arm.c:3423
+msgid "Constant value required for number of registers"
+msgstr ""
+
+#: config/tc-arm.c:3431
+msgid "number of registers must be in the range [1:4]"
+msgstr ""
+
+#: config/tc-arm.c:3493
+msgid "R15 not allowed as base register with write-back"
+msgstr ""
+
+#: config/tc-arm.c:3745
+msgid "lo register required"
+msgstr ""
+
+#: config/tc-arm.c:3753
+msgid "hi register required"
+msgstr ""
+
+#: config/tc-arm.c:3823
+msgid "dest and source1 must be the same register"
+msgstr ""
+
+#: config/tc-arm.c:3830
+msgid "subtract valid only on lo regs"
+msgstr ""
+
+#: config/tc-arm.c:3854
+msgid "invalid Hi register with immediate"
+msgstr ""
+
+#: config/tc-arm.c:3881 config/tc-arm.c:3914 config/tc-arm.c:3924
+msgid "immediate value out of range"
+msgstr ""
+
+#: config/tc-arm.c:3892
+msgid "invalid immediate value for stack adjust"
+msgstr ""
+
+#: config/tc-arm.c:3903
+msgid "invalid immediate for address calculation"
+msgstr ""
+
+#: config/tc-arm.c:3990
+msgid "source1 and dest must be same register"
+msgstr ""
+
+#: config/tc-arm.c:4025
+msgid "Invalid immediate for shift"
+msgstr ""
+
+#: config/tc-arm.c:4104
+msgid "only lo regs allowed with immediate"
+msgstr ""
+
+#: config/tc-arm.c:4123
+msgid "invalid immediate"
+msgstr ""
+
+#: config/tc-arm.c:4178
+msgid "expected ']'"
+msgstr ""
+
+#: config/tc-arm.c:4245
+msgid "byte or halfword not valid for base register"
+msgstr ""
+
+#: config/tc-arm.c:4250
+msgid "R15 based store not allowed"
+msgstr ""
+
+#: config/tc-arm.c:4255
+msgid "Invalid base register for register offset"
+msgstr ""
+
+#: config/tc-arm.c:4273
+msgid "invalid offset"
+msgstr ""
+
+#: config/tc-arm.c:4284
+msgid "invalid base register in load/store"
+msgstr ""
+
+#: config/tc-arm.c:4308 config/tc-arm.c:5471 config/tc-arm.c:5480
+#: config/tc-arm.c:5487 config/tc-arm.c:5494 config/tc-arm.c:5501
+msgid "Invalid offset"
+msgstr ""
+
+#: config/tc-arm.c:4386
+msgid "dest and source1 one must be the same register"
+msgstr ""
+
+#: config/tc-arm.c:4394
+msgid "Rs and Rd must be different in MUL"
+msgstr ""
+
+#: config/tc-arm.c:4539
+msgid ""
+"Inserted missing '!': load/store multiple always writes back base register"
+msgstr ""
+
+#: config/tc-arm.c:4555 config/tc-arm.c:4657
+msgid "Expression too complex"
+msgstr ""
+
+#: config/tc-arm.c:4561
+msgid "only lo-regs valid in load/store multiple"
+msgstr ""
+
+#: config/tc-arm.c:4608
+msgid "Syntax: ldrs[b] Rd, [Rb, Ro]"
+msgstr ""
+
+#: config/tc-arm.c:4673
+msgid "invalid register list to push/pop instruction"
+msgstr ""
+
+#: config/tc-arm.c:4811
+msgid "Virtual memory exhausted"
+msgstr ""
+
+#: config/tc-arm.c:5203
+#, c-format
+msgid "invalid constant (%x) after fixup\n"
+msgstr ""
+
+#: config/tc-arm.c:5215 config/tc-arm.c:5236
+#, c-format
+msgid "bad immediate value for offset (%d)"
+msgstr ""
+
+#: config/tc-arm.c:5234 config/tc-arm.c:5257
+msgid "invalid literal constant: pool needs to be closer\n"
+msgstr ""
+
+#: config/tc-arm.c:5274
+msgid "shift expression is too large"
+msgstr ""
+
+#: config/tc-arm.c:5292 config/tc-arm.c:5301
+msgid "Invalid swi expression"
+msgstr ""
+
+#: config/tc-arm.c:5311
+msgid "Invalid expression in load/store multiple"
+msgstr ""
+
+#: config/tc-arm.c:5341 config/tc-arm.c:5357 config/tc-mips.c:10430
+msgid "Branch out of range"
+msgstr ""
+
+#: config/tc-arm.c:5376
+msgid "Branch with link out of range"
+msgstr ""
+
+#: config/tc-arm.c:5443
+msgid "Illegal value for co-processor offset"
+msgstr ""
+
+#: config/tc-arm.c:5466
+#, c-format
+msgid "Invalid offset, target not word aligned (0x%08X)"
+msgstr ""
+
+#: config/tc-arm.c:5537
+msgid "Invalid immediate for stack address calculation"
+msgstr ""
+
+#: config/tc-arm.c:5546
+#, c-format
+msgid "Invalid immediate for address calculation (value = 0x%08X)"
+msgstr ""
+
+#: config/tc-arm.c:5555
+msgid "Invalid 8bit immediate"
+msgstr ""
+
+#: config/tc-arm.c:5563
+msgid "Invalid 3bit immediate"
+msgstr ""
+
+#: config/tc-arm.c:5579
+#, c-format
+msgid "Invalid immediate: %d is too large"
+msgstr ""
+
+#: config/tc-arm.c:5593
+#, c-format
+msgid "Illegal Thumb shift value: %d"
+msgstr ""
+
+#: config/tc-arm.c:5607
+#, c-format
+msgid "Bad relocation fixup type (%d)\n"
+msgstr ""
+
+#: config/tc-arm.c:5676
+msgid "Literal referenced across section boundry (Implicit dump?)"
+msgstr ""
+
+#: config/tc-arm.c:5695
+#, c-format
+msgid "Internal_relocation (type %d) not fixed up (IMMEDIATE)"
+msgstr ""
+
+#: config/tc-arm.c:5701
+#, c-format
+msgid "Internal_relocation (type %d) not fixed up (OFFSET_IMM)"
+msgstr ""
+
+#: config/tc-arm.c:5724
+#, c-format
+msgid "Can not represent %s relocation in this object file format (%d)"
+msgstr ""
+
+#: config/tc-arm.c:5742 config/tc-mips.c:11909 config/tc-sh.c:2277
+#, c-format
+msgid "Can not represent %s relocation in this object file format"
+msgstr ""
+
+#: config/tc-arm.c:5755
+msgid "md_estimate_size_before_relax\n"
+msgstr ""
+
+#: config/tc-arm.c:5825
+#, c-format
+msgid "No operator -- statement `%s'\n"
+msgstr ""
+
+#: config/tc-arm.c:5875 config/tc-arm.c:5927
+#, c-format
+msgid "Opcode `%s' must have suffix from <%s>\n"
+msgstr ""
+
+#: config/tc-arm.c:5900
+msgid "Warning: Use of the 'nv' conditional is deprecated\n"
+msgstr ""
+
+#: config/tc-arm.c:6019
+#, c-format
+msgid "register '%s' does not exist\n"
+msgstr ""
+
+#: config/tc-arm.c:6025
+#, c-format
+msgid "ignoring redefinition of register alias '%s'"
+msgstr ""
+
+#: config/tc-arm.c:6030
+#, c-format
+msgid ""
+"ignoring redefinition of register alias '%s' to non-existant register '%s'"
+msgstr ""
+
+#: config/tc-arm.c:6034
+msgid "ignoring incomplete .req pseuso op"
+msgstr ""
+
+#: config/tc-arm.c:6210
+#, c-format
+msgid "Unrecognised APCS switch -m%s"
+msgstr ""
+
+#: config/tc-arm.c:6336 config/tc-arm.c:6347 config/tc-arm.c:6358
+#: config/tc-arm.c:6363
+#, c-format
+msgid "Invalid architecture variant -m%s"
+msgstr ""
+
+#: config/tc-arm.c:6370
+#, c-format
+msgid "Invalid processor variant -m%s"
+msgstr ""
+
+#: config/tc-arm.c:6392
+msgid ""
+" ARM Specific Assembler Options:\n"
+" -m[arm][<processor name>] select processor variant\n"
+" -m[arm]v[2|2a|3|3m|4|4t] select architecture variant\n"
+" -mthumb only allow Thumb instructions\n"
+" -mthumb-interwork mark the assembled code as supporting "
+"interworking\n"
+" -mall allow any instruction\n"
+" -mfpa10, -mfpa11 select floating point architecture\n"
+" -mfpe-old don't allow floating-point multiple "
+"instructions\n"
+" -mno-fpu don't allow any floating-point instructions.\n"
+msgstr ""
+
+#: config/tc-arm.c:6403
+msgid " -k generate PIC code.\n"
+msgstr ""
+
+#: config/tc-arm.c:6407
+msgid ""
+" -mapcs-32, -mapcs-26 specify which ARM Procedure Calling Standard to "
+"use\n"
+msgstr ""
+
+#: config/tc-arm.c:6410
+msgid " -mapcs-float floating point args are passed in FP regs\n"
+msgstr ""
+
+#: config/tc-arm.c:6413
+msgid ""
+" -mapcs-reentrant the code is position independent/reentrant\n"
+msgstr ""
+
+#: config/tc-arm.c:6418
+msgid " -moabi support the old ELF ABI\n"
+msgstr ""
+
+#: config/tc-arm.c:6423
+msgid ""
+" -EB assemble code for a big endian cpu\n"
+" -EL assemble code for a little endian cpu\n"
+msgstr ""
+
+#: config/tc-arm.c:6596
+#, c-format
+msgid "%s: unexpected function type: %d"
+msgstr ""
+
+#: config/tc-d10v.c:218
+msgid ""
+"D10V options:\n"
+"-O optimize. Will do some operations in parallel.\n"
+msgstr ""
+
+#: config/tc-d10v.c:521 config/tc-d10v.c:603 config/tc-d30v.c:639
+#, c-format
+msgid "operand out of range: %d"
+msgstr ""
+
+#: config/tc-d10v.c:664
+msgid "Instruction must be executed in parallel with another instruction."
+msgstr ""
+
+#: config/tc-d10v.c:716
+msgid "Instruction must be executed in parallel"
+msgstr ""
+
+#: config/tc-d10v.c:719
+msgid "Long instructions may not be combined."
+msgstr ""
+
+#: config/tc-d10v.c:759
+msgid "One of these instructions may not be executed in parallel."
+msgstr ""
+
+#: config/tc-d10v.c:764 config/tc-d30v.c:843
+msgid "Two IU instructions may not be executed in parallel"
+msgstr ""
+
+#: config/tc-d10v.c:766 config/tc-d10v.c:774 config/tc-d10v.c:789
+#: config/tc-d10v.c:802 config/tc-d30v.c:844 config/tc-d30v.c:853
+msgid "Swapping instruction order"
+msgstr ""
+
+#: config/tc-d10v.c:772 config/tc-d30v.c:850
+msgid "Two MU instructions may not be executed in parallel"
+msgstr ""
+
+#: config/tc-d10v.c:793 config/tc-d30v.c:869
+msgid "IU instruction may not be in the left container"
+msgstr ""
+
+#: config/tc-d10v.c:806 config/tc-d30v.c:882
+msgid "MU instruction may not be in the right container"
+msgstr ""
+
+#: config/tc-d10v.c:810 config/tc-d30v.c:890
+msgid "unknown execution type passed to write_2_short()"
+msgstr ""
+
+#: config/tc-d10v.c:1023 config/tc-d10v.c:1037 config/tc-h8300.c:1279
+#: config/tc-h8500.c:1122 config/tc-mcore.c:709 config/tc-sh.c:1040
+#: config/tc-z8k.c:1223
+msgid "can't find opcode "
+msgstr ""
+
+#: config/tc-d10v.c:1050 config/tc-d10v.c:1068 config/tc-d30v.c:1368
+msgid "Unable to mix instructions as specified"
+msgstr ""
+
+#: config/tc-d10v.c:1116 config/tc-d30v.c:1503
+#, c-format
+msgid "unknown opcode: %s"
+msgstr ""
+
+#: config/tc-d10v.c:1197 config/tc-d10v.c:1343 config/tc-tic80.c:537
+msgid "bad opcode or operands"
+msgstr ""
+
+#: config/tc-d10v.c:1246 config/tc-m68k.c:4110
+msgid "value out of range"
+msgstr ""
+
+#: config/tc-d10v.c:1318
+msgid "illegal operand - register name found where none expected"
+msgstr ""
+
+#: config/tc-d10v.c:1354 config/tc-tic80.c:548
+msgid "Register number must be EVEN"
+msgstr ""
+
+#: config/tc-d10v.c:1385 config/tc-d30v.c:1754 config/tc-mn10200.c:1234
+#: config/tc-mn10300.c:1786 config/tc-ppc.c:4997 config/tc-v850.c:2254
+#, c-format
+msgid "reloc %d not supported by object file format"
+msgstr ""
+
+#: config/tc-d10v.c:1498
+#, c-format
+msgid "line %d: rep or repi must include at least 4 instructions"
+msgstr ""
+
+#: config/tc-d10v.c:1517 config/tc-d30v.c:1935
+#, c-format
+msgid "line %d: unknown relocation type: 0x%x"
+msgstr ""
+
+#: config/tc-d30v.c:184
+#, c-format
+msgid "Register name %s conflicts with symbol of the same name"
+msgstr ""
+
+#: config/tc-d30v.c:276
+msgid ""
+"\n"
+"D30V options:\n"
+"-O Make adjacent short instructions parallel if "
+"possible.\n"
+"-n Warn about all NOPs inserted by the assembler.\n"
+"-N\t\t\tWarn about NOPs inserted after word multiplies.\n"
+"-c Warn about symbols whoes names match register "
+"names.\n"
+"-C Opposite of -C. -c is the default.\n"
+msgstr ""
+
+#: config/tc-d30v.c:450
+msgid "unexpected 12-bit reloc type"
+msgstr ""
+
+#: config/tc-d30v.c:457
+msgid "unexpected 18-bit reloc type"
+msgstr ""
+
+#: config/tc-d30v.c:701
+#, c-format
+msgid "%s NOP inserted"
+msgstr ""
+
+#: config/tc-d30v.c:702
+msgid "sequential"
+msgstr ""
+
+#: config/tc-d30v.c:702
+msgid "parallel"
+msgstr ""
+
+#: config/tc-d30v.c:839
+msgid "Instructions may not be executed in parallel"
+msgstr ""
+
+#: config/tc-d30v.c:852 config/tc-d30v.c:859 config/tc-d30v.c:875
+#: config/tc-d30v.c:884
+#, c-format
+msgid "Executing %s in IU may not work"
+msgstr ""
+
+#: config/tc-d30v.c:871
+#, c-format
+msgid "special left instruction `%s' kills instruction `%s' in right container"
+msgstr ""
+
+#: config/tc-d30v.c:1250 config/tc-d30v.c:1267
+msgid "Cannot assemble instruction"
+msgstr ""
+
+#: config/tc-d30v.c:1252
+msgid "First opcode is long. Unable to mix instructions as specified."
+msgstr ""
+
+#: config/tc-d30v.c:1320
+msgid "word of NOPs added between word multiply and load"
+msgstr ""
+
+#: config/tc-d30v.c:1322
+msgid "word of NOPs added between word multiply and 16-bit multiply"
+msgstr ""
+
+#: config/tc-d30v.c:1352
+msgid "Instruction uses long version, so it cannot be mixed as specified"
+msgstr ""
+
+#: config/tc-d30v.c:1436 config/tc-d30v.c:1473
+#, c-format
+msgid "unknown condition code: %s"
+msgstr ""
+
+#: config/tc-d30v.c:1466
+#, c-format
+msgid "cmpu doesn't support condition code %s"
+msgstr ""
+
+#: config/tc-d30v.c:1514
+#, c-format
+msgid "operands for opcode `%s' do not match any valid format"
+msgstr ""
+
+#: config/tc-d30v.c:1727
+msgid "Odd numbered register used as target of multi-register instruction"
+msgstr ""
+
+#: config/tc-d30v.c:1824
+#, c-format
+msgid "line %d: unable to place address of symbol '%s' into a byte"
+msgstr ""
+
+#: config/tc-d30v.c:1827
+#, c-format
+msgid "line %d: unable to place value %x into a byte"
+msgstr ""
+
+#: config/tc-d30v.c:1835
+#, c-format
+msgid "line %d: unable to place address of symbol '%s' into a short"
+msgstr ""
+
+#: config/tc-d30v.c:1838
+#, c-format
+msgid "line %d: unable to place value %x into a short"
+msgstr ""
+
+#: config/tc-d30v.c:1846
+#, c-format
+msgid "line %d: unable to place address of symbol '%s' into a quad"
+msgstr ""
+
+#: config/tc-d30v.c:2016
+#, c-format
+msgid "value too large to fit in %d bits"
+msgstr ""
+
+#: config/tc-d30v.c:2159
+#, c-format
+msgid "Alignment too large: %d assumed"
+msgstr ""
+
+#: config/tc-h8300.c:254 config/tc-h8300.c:262
+msgid "Reg not valid for H8/300"
+msgstr ""
+
+#: config/tc-h8300.c:423 config/tc-h8300.c:426 config/tc-h8300.c:429
+#: config/tc-h8300.c:433
+msgid "Invalid register list for ldm/stm\n"
+msgstr ""
+
+#: config/tc-h8300.c:490 config/tc-h8300.c:553 config/tc-h8300.c:560
+msgid "Wrong size pointer register for architecture."
+msgstr ""
+
+#: config/tc-h8300.c:518 config/tc-h8300.c:527 config/tc-h8300.c:537
+msgid "expected @(exp, reg16)"
+msgstr ""
+
+#: config/tc-h8300.c:617
+msgid "expect :8 or :16 here"
+msgstr ""
+
+#: config/tc-h8300.c:823
+#, c-format
+msgid "operand %s0x%lx out of range."
+msgstr ""
+
+#: config/tc-h8300.c:910
+msgid "Can't work out size of operand.\n"
+msgstr ""
+
+#: config/tc-h8300.c:964
+#, c-format
+msgid "Opcode `%s' with these operand types not available in H8/300 mode"
+msgstr ""
+
+#: config/tc-h8300.c:1016 config/tc-h8300.c:1036
+msgid "Need #1 or #2 here"
+msgstr ""
+
+#: config/tc-h8300.c:1031
+msgid "#4 not valid on H8/300."
+msgstr ""
+
+#: config/tc-h8300.c:1112 config/tc-h8300.c:1150
+#, c-format
+msgid "branch operand has odd offset (%lx)\n"
+msgstr ""
+
+#: config/tc-h8300.c:1191
+msgid "destination operand must be 16 bit register"
+msgstr ""
+
+#: config/tc-h8300.c:1201
+msgid "source operand must be 8 bit register"
+msgstr ""
+
+#: config/tc-h8300.c:1209
+msgid "destination operand must be 16bit absolute address"
+msgstr ""
+
+#: config/tc-h8300.c:1216
+msgid "destination operand must be 8 bit register"
+msgstr ""
+
+#: config/tc-h8300.c:1225
+msgid "source operand must be 16bit absolute address"
+msgstr ""
+
+#: config/tc-h8300.c:1233
+msgid "invalid operands"
+msgstr ""
+
+#: config/tc-h8300.c:1290 config/tc-h8500.c:1129 config/tc-mips.c:8513
+#: config/tc-sh.c:1047 config/tc-w65.c:759 config/tc-z8k.c:1235
+msgid "unknown opcode"
+msgstr ""
+
+#: config/tc-h8300.c:1336
+msgid "mismatch between opcode size and operand size"
+msgstr ""
+
+#: config/tc-h8300.c:1348 config/tc-h8500.c:1157 config/tc-sh.c:1144
+#: config/tc-w65.c:791 config/tc-z8k.c:1290
+msgid "call to tc_crawl_symbol_chain \n"
+msgstr ""
+
+#: config/tc-h8300.c:1362 config/tc-h8500.c:1171 config/tc-sh.c:1151
+#: config/tc-w65.c:805 config/tc-z8k.c:1304
+msgid "call to tc_headers_hook \n"
+msgstr ""
+
+#: config/tc-h8300.c:1451 config/tc-h8500.c:1260 config/tc-z8k.c:1415
+msgid "call to tc_aout_fix_to_chars \n"
+msgstr ""
+
+#: config/tc-h8300.c:1461 config/tc-z8k.c:1425
+msgid "call to md_convert_frag \n"
+msgstr ""
+
+#: config/tc-h8300.c:1506 config/tc-z8k.c:1500
+msgid "call tomd_estimate_size_before_relax \n"
+msgstr ""
+
+#: config/tc-h8500.c:337
+msgid ":24 not valid for this opcode"
+msgstr ""
+
+#: config/tc-h8500.c:344
+msgid "expect :8,:16 or :24"
+msgstr ""
+
+#: config/tc-h8500.c:401
+msgid "syntax error in reg list"
+msgstr ""
+
+#: config/tc-h8500.c:419
+msgid "missing final register in range"
+msgstr ""
+
+#: config/tc-h8500.c:506 config/tc-h8500.c:513 config/tc-h8500.c:519
+msgid "expected @(exp, Rn)"
+msgstr ""
+
+#: config/tc-h8500.c:535
+msgid "@Rn+ needs word register"
+msgstr ""
+
+#: config/tc-h8500.c:545
+msgid "@Rn needs word register"
+msgstr ""
+
+#: config/tc-h8500.c:845 config/tc-sh.c:844
+#, c-format
+msgid "unhandled %d\n"
+msgstr ""
+
+#: config/tc-h8500.c:873 config/tc-sh.c:865
+#, c-format
+msgid "operand must be absolute in range %d..%d"
+msgstr ""
+
+#: config/tc-h8500.c:963 config/tc-sh.c:986
+#, c-format
+msgid "failed for %d\n"
+msgstr ""
+
+#: config/tc-h8500.c:1145 config/tc-sh.c:1082 config/tc-w65.c:779
+msgid "invalid operands for opcode"
+msgstr ""
+
+#: config/tc-hppa.c:1114
+msgid "Missing .exit\n"
+msgstr ""
+
+#: config/tc-hppa.c:1117
+msgid "Missing .procend\n"
+msgstr ""
+
+#: config/tc-hppa.c:1126
+msgid "Not in a space.\n"
+msgstr ""
+
+#: config/tc-hppa.c:1129
+msgid "Not in a subspace.\n"
+msgstr ""
+
+#: config/tc-hppa.c:1291
+msgid "Invalid field selector. Assuming F%%."
+msgstr ""
+
+#: config/tc-hppa.c:1322
+msgid "-R option not supported on this target."
+msgstr ""
+
+#: config/tc-hppa.c:1336
+#, c-format
+msgid "Internal error: can't hash `%s': %s\n"
+msgstr ""
+
+#: config/tc-hppa.c:1344 config/tc-i860.c:191 config/tc-sparc.c:704
+#, c-format
+msgid "internal error: losing opcode: `%s' \"%s\"\n"
+msgstr ""
+
+#: config/tc-hppa.c:1406 config/tc-hppa.c:6539 config/tc-hppa.c:6591
+msgid "Missing function name for .PROC (corrupted label chain)"
+msgstr ""
+
+#: config/tc-hppa.c:1409 config/tc-hppa.c:6594
+msgid "Missing function name for .PROC"
+msgstr ""
+
+#: config/tc-hppa.c:1518 config/tc-hppa.c:4430
+msgid "could not update architecture and machine"
+msgstr ""
+
+#: config/tc-hppa.c:1714
+msgid "Invalid Indexed Load Completer."
+msgstr ""
+
+#: config/tc-hppa.c:1723
+msgid "Invalid Indexed Load Completer Syntax."
+msgstr ""
+
+#: config/tc-hppa.c:1756
+msgid "Invalid Short Load/Store Completer."
+msgstr ""
+
+#: config/tc-hppa.c:1807 config/tc-hppa.c:1812
+msgid "Invalid Store Bytes Short Completer"
+msgstr ""
+
+#: config/tc-hppa.c:1822 config/tc-hppa.c:1866
+#, c-format
+msgid "Invalid Compare/Subtract Condition: %c"
+msgstr ""
+
+#: config/tc-hppa.c:1840 config/tc-hppa.c:2375
+msgid "Invalid Compare/Subtract Condition."
+msgstr ""
+
+#: config/tc-hppa.c:1881
+msgid "Invalid Compare/Subtract Condition"
+msgstr ""
+
+#: config/tc-hppa.c:1970 config/tc-hppa.c:2062
+#, c-format
+msgid "Invalid Add Condition: %s"
+msgstr ""
+
+#: config/tc-hppa.c:2132 config/tc-hppa.c:2245
+msgid "Invalid Logical Instruction Condition."
+msgstr ""
+
+#: config/tc-hppa.c:2301
+msgid "Invalid Shift/Extract/Deposit Condition."
+msgstr ""
+
+#: config/tc-hppa.c:2337
+#, c-format
+msgid "Invalid Bit Branch Condition: %c"
+msgstr ""
+
+#: config/tc-hppa.c:2776 config/tc-hppa.c:2791
+#, c-format
+msgid "Invalid CBit Specification: %s"
+msgstr ""
+
+#: config/tc-hppa.c:2977 config/tc-hppa.c:3010 config/tc-hppa.c:3047
+msgid "Branch to unaligned address"
+msgstr ""
+
+#: config/tc-hppa.c:3147
+msgid "Invalid SFU identifier"
+msgstr ""
+
+#: config/tc-hppa.c:3207
+msgid "Invalid COPR identifier"
+msgstr ""
+
+#: config/tc-hppa.c:3447 config/tc-hppa.c:3473 config/tc-hppa.c:3498
+#: config/tc-hppa.c:3523 config/tc-hppa.c:3548
+msgid "Invalid register for single precision fmpyadd or fmpysub"
+msgstr ""
+
+#: config/tc-hppa.c:3572
+msgid "Invalid Floating Point Operand Format."
+msgstr ""
+
+#: config/tc-hppa.c:3595
+#, c-format
+msgid "Invalid operands %s"
+msgstr ""
+
+#: config/tc-hppa.c:4130
+msgid "Unknown relocation encountered in md_apply_fix."
+msgstr ""
+
+#: config/tc-hppa.c:4140
+#, c-format
+msgid "no hppa_fixup entry for this fixup (fixP = 0x%x, type = 0x%x)\n"
+msgstr ""
+
+#: config/tc-hppa.c:4282 config/tc-hppa.c:4307
+#, c-format
+msgid "Undefined register: '%s'."
+msgstr ""
+
+#: config/tc-hppa.c:4345
+#, c-format
+msgid "Non-absolute symbol: '%s'."
+msgstr ""
+
+#: config/tc-hppa.c:4360
+#, c-format
+msgid "Undefined absolute constant: '%s'."
+msgstr ""
+
+#: config/tc-hppa.c:4469
+#, c-format
+msgid "Invalid FP Compare Condition: %s"
+msgstr ""
+
+#: config/tc-hppa.c:4526
+#, c-format
+msgid "Invalid FTEST completer: %s"
+msgstr ""
+
+#: config/tc-hppa.c:4593 config/tc-hppa.c:4632
+#, c-format
+msgid "Invalid FP Operand Format: %3s"
+msgstr ""
+
+#: config/tc-hppa.c:4713
+msgid "Bad segment in expression."
+msgstr ""
+
+#: config/tc-hppa.c:4772
+msgid "Bad segment (should be absolute)."
+msgstr ""
+
+#: config/tc-hppa.c:4871
+#, c-format
+msgid "Invalid argument location: %s\n"
+msgstr ""
+
+#: config/tc-hppa.c:4902
+#, c-format
+msgid "Invalid argument description: %d"
+msgstr ""
+
+#: config/tc-hppa.c:4925
+#, c-format
+msgid "Invalid Nullification: (%c)"
+msgstr ""
+
+#: config/tc-hppa.c:5657
+#, c-format
+msgid "Invalid .CALL argument: %s"
+msgstr ""
+
+#: config/tc-hppa.c:5776
+msgid ".callinfo is not within a procedure definition"
+msgstr ""
+
+#: config/tc-hppa.c:5796
+#, c-format
+msgid "FRAME parameter must be a multiple of 8: %d\n"
+msgstr ""
+
+#: config/tc-hppa.c:5815
+msgid "Value for ENTRY_GR must be in the range 3..18\n"
+msgstr ""
+
+#: config/tc-hppa.c:5827
+msgid "Value for ENTRY_FR must be in the range 12..21\n"
+msgstr ""
+
+#: config/tc-hppa.c:5837
+msgid "Value for ENTRY_SR must be 3\n"
+msgstr ""
+
+#: config/tc-hppa.c:5893
+#, c-format
+msgid "Invalid .CALLINFO argument: %s"
+msgstr ""
+
+#: config/tc-hppa.c:5983
+msgid "The .ENTER pseudo-op is not supported"
+msgstr ""
+
+#: config/tc-hppa.c:5997
+msgid "Misplaced .entry. Ignored."
+msgstr ""
+
+#: config/tc-hppa.c:6001
+msgid "Missing .callinfo."
+msgstr ""
+
+#: config/tc-hppa.c:6049
+msgid ".REG must use a label"
+msgstr ""
+
+#: config/tc-hppa.c:6051
+msgid ".EQU must use a label"
+msgstr ""
+
+#: config/tc-hppa.c:6102
+msgid ".EXIT must appear within a procedure"
+msgstr ""
+
+#: config/tc-hppa.c:6106
+msgid "Missing .callinfo"
+msgstr ""
+
+#: config/tc-hppa.c:6110
+msgid "No .ENTRY for this .EXIT"
+msgstr ""
+
+#: config/tc-hppa.c:6137
+#, c-format
+msgid "Cannot define export symbol: %s\n"
+msgstr ""
+
+#: config/tc-hppa.c:6190
+#, c-format
+msgid "Using ENTRY rather than CODE in export directive for %s"
+msgstr ""
+
+#: config/tc-hppa.c:6291
+#, c-format
+msgid "Undefined .EXPORT/.IMPORT argument (ignored): %s"
+msgstr ""
+
+#: config/tc-hppa.c:6373
+msgid "Missing label name on .LABEL"
+msgstr ""
+
+#: config/tc-hppa.c:6378
+msgid "extra .LABEL arguments ignored."
+msgstr ""
+
+#: config/tc-hppa.c:6393
+msgid "The .LEAVE pseudo-op is not supported"
+msgstr ""
+
+#: config/tc-hppa.c:6426
+msgid "Unrecognized .LEVEL argument\n"
+msgstr ""
+
+#: config/tc-hppa.c:6460
+#, c-format
+msgid "Cannot define static symbol: %s\n"
+msgstr ""
+
+#: config/tc-hppa.c:6493
+msgid "Nested procedures"
+msgstr ""
+
+#: config/tc-hppa.c:6503
+msgid "Cannot allocate unwind descriptor\n"
+msgstr ""
+
+#: config/tc-hppa.c:6598
+msgid "misplaced .procend"
+msgstr ""
+
+#: config/tc-hppa.c:6601
+msgid "Missing .callinfo for this procedure"
+msgstr ""
+
+#: config/tc-hppa.c:6604
+msgid "Missing .EXIT for a .ENTRY"
+msgstr ""
+
+#: config/tc-hppa.c:6704
+msgid "Invalid .SPACE argument"
+msgstr ""
+
+#: config/tc-hppa.c:6752
+msgid "Can't change spaces within a procedure definition. Ignored"
+msgstr ""
+
+#: config/tc-hppa.c:6879
+#, c-format
+msgid "Undefined space: '%s' Assuming space number = 0."
+msgstr ""
+
+#: config/tc-hppa.c:6921
+msgid "Must be in a space before changing or declaring subspaces.\n"
+msgstr ""
+
+#: config/tc-hppa.c:6925
+msgid "Can't change subspaces within a procedure definition. Ignored"
+msgstr ""
+
+#: config/tc-hppa.c:6961
+msgid "Parameters of an existing subspace can't be modified"
+msgstr ""
+
+#: config/tc-hppa.c:7014
+msgid "Alignment must be a power of 2"
+msgstr ""
+
+#: config/tc-hppa.c:7056
+msgid "FIRST not supported as a .SUBSPACE argument"
+msgstr ""
+
+#: config/tc-hppa.c:7058
+msgid "Invalid .SUBSPACE argument"
+msgstr ""
+
+#: config/tc-hppa.c:7098
+msgid "Ignoring subspace decl due to ELF BFD bugs."
+msgstr ""
+
+#: config/tc-hppa.c:7261
+#, c-format
+msgid "Internal error: Unable to find containing space for %s."
+msgstr ""
+
+#: config/tc-hppa.c:7302
+#, c-format
+msgid "Out of memory: could not allocate new space chain entry: %s\n"
+msgstr ""
+
+#: config/tc-hppa.c:7388
+#, c-format
+msgid "Out of memory: could not allocate new subspace chain entry: %s\n"
+msgstr ""
+
+#: config/tc-hppa.c:8044
+#, c-format
+msgid "Symbol '%s' could not be created."
+msgstr ""
+
+#: config/tc-hppa.c:8048
+msgid "No memory for symbol name."
+msgstr ""
+
+#: config/tc-i386.c:502
+msgid "same type of prefix used twice"
+msgstr ""
+
+#: config/tc-i386.c:536
+msgid "Bad argument to syntax directive."
+msgstr ""
+
+#: config/tc-i386.c:619 config/tc-m68k.c:3630
+#, c-format
+msgid "Internal Error: Can't hash %s: %s"
+msgstr ""
+
+#: config/tc-i386.c:850
+msgid "Unknown"
+msgstr ""
+
+#: config/tc-i386.c:898 config/tc-i386.c:4360 config/tc-m68k.c:762
+#, c-format
+msgid "Can not do %d byte pc-relative relocation"
+msgstr ""
+
+#: config/tc-i386.c:908 config/tc-i386.c:4363 config/tc-m68k.c:769
+#, c-format
+msgid "Can not do %d byte relocation"
+msgstr ""
+
+#: config/tc-i386.c:1009 config/tc-i386.c:1095
+#, c-format
+msgid "no such 386 instruction: `%s'"
+msgstr ""
+
+#: config/tc-i386.c:1018
+#, c-format
+msgid "invalid character %s in mnemonic"
+msgstr ""
+
+#: config/tc-i386.c:1025
+msgid "expecting prefix; got nothing"
+msgstr ""
+
+#: config/tc-i386.c:1027
+msgid "expecting mnemonic; got nothing"
+msgstr ""
+
+#: config/tc-i386.c:1045
+#, c-format
+msgid "redundant %s prefix"
+msgstr ""
+
+#: config/tc-i386.c:1104
+#, c-format
+msgid "expecting string instruction after `%s'"
+msgstr ""
+
+#: config/tc-i386.c:1127
+#, c-format
+msgid "invalid character %s before operand %d"
+msgstr ""
+
+#: config/tc-i386.c:1141
+#, c-format
+msgid "unbalanced parenthesis in operand %d."
+msgstr ""
+
+#: config/tc-i386.c:1144
+#, c-format
+msgid "unbalanced brackets in operand %d."
+msgstr ""
+
+#: config/tc-i386.c:1153
+#, c-format
+msgid "invalid character %s in operand %d"
+msgstr ""
+
+#: config/tc-i386.c:1180
+#, c-format
+msgid "spurious operands; (%d operands/instruction max)"
+msgstr ""
+
+#: config/tc-i386.c:1201
+msgid "expecting operand after ','; got nothing"
+msgstr ""
+
+#: config/tc-i386.c:1206
+msgid "expecting operand before ','; got nothing"
+msgstr ""
+
+#. we found no match
+#: config/tc-i386.c:1433
+#, c-format
+msgid "suffix or operands invalid for `%s'"
+msgstr ""
+
+#. Warn them that a data or address size prefix doesn't affect
+#. assembly of the next line of code.
+#: config/tc-i386.c:1442
+#, c-format
+msgid "stand-alone `%s' prefix"
+msgstr ""
+
+#: config/tc-i386.c:1466 config/tc-i386.c:1481
+msgid "`%s' operand %d must use `%%es' segment"
+msgstr ""
+
+#: config/tc-i386.c:1547 config/tc-i386.c:1586 config/tc-i386.c:1613
+msgid "using `%%%s' instead of `%%%s' due to `%c' suffix"
+msgstr ""
+
+#: config/tc-i386.c:1558 config/tc-i386.c:1575 config/tc-i386.c:1602
+msgid "`%%%s' not allowed with `%s%c'"
+msgstr ""
+
+#: config/tc-i386.c:1642 config/tc-i386.c:1662
+msgid "no instruction mnemonic suffix given; can't determine immediate size"
+msgstr ""
+
+#: config/tc-i386.c:1687
+msgid ""
+"no instruction mnemonic suffix given and no register operands; can't size "
+"instruction"
+msgstr ""
+
+#. reversed arguments on faddp, fsubp, etc.
+#: config/tc-i386.c:1800
+msgid "translating to `%s %%%s,%%%s'"
+msgstr ""
+
+#. extraneous `l' suffix on fp insn
+#: config/tc-i386.c:1807
+msgid "translating to `%s %%%s'"
+msgstr ""
+
+#: config/tc-i386.c:2033
+msgid "you can't `pop %%cs'"
+msgstr ""
+
+#. UnixWare fsub no args is alias for fsubp, fadd -> faddp, etc
+#: config/tc-i386.c:2064
+#, c-format
+msgid "translating to `%sp'"
+msgstr ""
+
+#: config/tc-i386.c:2095 config/tc-i386.c:2198 config/tc-i386.c:2258
+msgid "skipping prefixes on this instruction"
+msgstr ""
+
+#: config/tc-i386.c:2115 config/tc-i386.c:2222 config/tc-i386.c:2271
+msgid "16-bit jump out of range"
+msgstr ""
+
+#: config/tc-i386.c:2217
+#, c-format
+msgid "`%s' only takes byte displacement; %ld shortened to %d"
+msgstr ""
+
+#: config/tc-i386.c:2280
+#, c-format
+msgid "can't handle non absolute segment in `%s'"
+msgstr ""
+
+#: config/tc-i386.c:2537
+msgid "Only 1 or 2 immediate operands are allowed"
+msgstr ""
+
+#: config/tc-i386.c:2568 config/tc-i386.c:2797
+msgid "GOT relocations not supported in 16 bit mode"
+msgstr ""
+
+#: config/tc-i386.c:2589 config/tc-i386.c:2818
+msgid "Bad reloc specifier in expression"
+msgstr ""
+
+#: config/tc-i386.c:2606 config/tc-i386.c:2851
+#, c-format
+msgid "Ignoring junk `%s' after expression"
+msgstr ""
+
+#. missing or bad expr becomes absolute 0
+#: config/tc-i386.c:2613
+#, c-format
+msgid "Missing or invalid immediate expression `%s' taken as 0"
+msgstr ""
+
+#: config/tc-i386.c:2648 config/tc-i386.c:2870
+#, c-format
+msgid "Unimplemented segment type %d in operand"
+msgstr ""
+
+#: config/tc-i386.c:2691
+#, c-format
+msgid "expecting scale factor of 1, 2, 4, or 8: got `%s'"
+msgstr ""
+
+#: config/tc-i386.c:2697
+#, c-format
+msgid "scale factor of %d without an index register"
+msgstr ""
+
+#: config/tc-i386.c:3045 config/tc-i386.c:3051 config/tc-i386.c:3060
+#, c-format
+msgid "bad segment name `%s'"
+msgstr ""
+
+#: config/tc-i386.c:3226 config/tc-i386.c:3481
+#, c-format
+msgid "too many memory references for `%s'"
+msgstr ""
+
+#: config/tc-i386.c:3337 config/tc-i386.c:3350 config/tc-i386.c:3662
+#: config/tc-i386.c:3675
+#, c-format
+msgid "`%s' is not a valid %s bit base/index expression"
+msgstr ""
+
+#: config/tc-i386.c:3434
+#, c-format
+msgid "bad memory operand `%s'"
+msgstr ""
+
+#: config/tc-i386.c:3449
+#, c-format
+msgid "Junk `%s' after register"
+msgstr ""
+
+#: config/tc-i386.c:3590
+#, c-format
+msgid "expecting `,' or `)' after index register in `%s'"
+msgstr ""
+
+#: config/tc-i386.c:3607
+#, c-format
+msgid "expecting `)' after scale factor in `%s'"
+msgstr ""
+
+#: config/tc-i386.c:3614
+#, c-format
+msgid "expecting index register or scale factor after `,'; got '%c'"
+msgstr ""
+
+#: config/tc-i386.c:3621
+#, c-format
+msgid "expecting `,' or `)' after base register in `%s'"
+msgstr ""
+
+#. it's not a memory operand; argh!
+#: config/tc-i386.c:3684
+#, c-format
+msgid "invalid char %s beginning operand %d `%s'"
+msgstr ""
+
+#: config/tc-i386.c:4087
+msgid "Bad call to md_atof ()"
+msgstr ""
+
+#: config/tc-i386.c:4148 config/tc-i386.c:4161
+#, c-format
+msgid "bad register name `%s'"
+msgstr ""
+
+#: config/tc-i386.c:4215
+msgid "-m\t\t\tdo long jump\n"
+msgstr ""
+
+#: config/tc-i386.c:4255
+msgid "GOT already in symbol table"
+msgstr ""
+
+#: config/tc-i386.c:4395 config/tc-mcore.c:2017 config/tc-sh.c:2415
+#, c-format
+msgid "Cannot represent relocation type %s"
+msgstr ""
+
+#: config/tc-i860.c:157 config/tc-i860.c:161
+msgid "Unknown temporary pseudo register"
+msgstr ""
+
+#: config/tc-i860.c:183 config/tc-mips.c:1099 config/tc-sparc.c:696
+#, c-format
+msgid "internal error: can't hash `%s': %s\n"
+msgstr ""
+
+#: config/tc-i860.c:341
+#, c-format
+msgid "Expanded opcode after delayed branch: `%s'"
+msgstr ""
+
+#: config/tc-i860.c:343
+#, c-format
+msgid "Expanded opcode in dual mode: `%s'"
+msgstr ""
+
+#: config/tc-i860.c:580
+msgid "Fsr1 equals fdest with Pipelining"
+msgstr ""
+
+#: config/tc-i860.c:631
+msgid "5-bit immediate too large"
+msgstr ""
+
+#: config/tc-i860.c:725
+msgid "Illegal operands"
+msgstr ""
+
+#: config/tc-i860.c:749 config/tc-sparc.c:2338
+msgid "bad segment"
+msgstr ""
+
+#: config/tc-i860.c:878
+#, c-format
+msgid "26-bit branch w/o pc relative set: 0x%08x"
+msgstr ""
+
+#. align pcrel offset, see manual
+#. check for overflow
+#: config/tc-i860.c:882
+#, c-format
+msgid "26-bit branch offset overflow: 0x%08x"
+msgstr ""
+
+#: config/tc-i860.c:891 config/tc-i860.c:922
+#, c-format
+msgid "16-bit immediate 4-byte alignment error: 0x%08x"
+msgstr ""
+
+#: config/tc-i860.c:896 config/tc-i860.c:927
+#, c-format
+msgid "16-bit immediate 2-byte alignment error: 0x%08x"
+msgstr ""
+
+#: config/tc-i860.c:904
+#, c-format
+msgid "16-bit branch offset overflow: 0x%08x"
+msgstr ""
+
+#: config/tc-i860.c:912
+#, c-format
+msgid "16-bit immediate 16-byte alignment error: 0x%08x"
+msgstr ""
+
+#: config/tc-i860.c:917
+#, c-format
+msgid "16-bit immediate 8-byte alignment error: 0x%08x"
+msgstr ""
+
+#: config/tc-i860.c:933
+#, c-format
+msgid "16-bit immediate overflow: 0x%08x"
+msgstr ""
+
+#: config/tc-i860.c:951
+msgid "md_number_to_disp\n"
+msgstr ""
+
+#: config/tc-i860.c:961
+msgid "i860_number_to_field\n"
+msgstr ""
+
+#: config/tc-i860.c:1001
+msgid "i860_convert_frag\n"
+msgstr ""
+
+#: config/tc-i860.c:1010
+msgid "i860_estimate_size_before_relax\n"
+msgstr ""
+
+#: config/tc-i960.c:544
+#, c-format
+msgid "Hashing returned \"%s\"."
+msgstr ""
+
+#. Offset of last character in opcode mnemonic
+#: config/tc-i960.c:578
+msgid "branch prediction invalid on this opcode"
+msgstr ""
+
+#: config/tc-i960.c:621
+#, c-format
+msgid "invalid opcode, \"%s\"."
+msgstr ""
+
+#: config/tc-i960.c:626
+#, c-format
+msgid "improper number of operands. expecting %d, got %d"
+msgstr ""
+
+#: config/tc-i960.c:771 config/tc-m32r.c:1873
+msgid "Bad call to md_atof()"
+msgstr ""
+
+#: config/tc-i960.c:861
+#, c-format
+msgid "Fixup of %ld too large for field width of %d"
+msgstr ""
+
+#: config/tc-i960.c:979
+#, c-format
+msgid "invalid architecture %s"
+msgstr ""
+
+#: config/tc-i960.c:999
+msgid "I960 options:\n"
+msgstr ""
+
+#: config/tc-i960.c:1002
+msgid ""
+"\n"
+"\t\t\tspecify variant of 960 architecture\n"
+"-b\t\t\tadd code to collect statistics about branches taken\n"
+"-link-relax\t\tpreserve individual alignment directives so linker\n"
+"\t\t\tcan do relaxing (b.out format only)\n"
+"-no-relax\t\tdon't alter compare-and-branch instructions for\n"
+"\t\t\tlong displacements\n"
+msgstr ""
+
+#: config/tc-i960.c:1400
+msgid "too many operands"
+msgstr ""
+
+#: config/tc-i960.c:1460 config/tc-i960.c:1690
+msgid "expression syntax error"
+msgstr ""
+
+#: config/tc-i960.c:1498
+msgid "attempt to branch into different segment"
+msgstr ""
+
+#: config/tc-i960.c:1502
+#, c-format
+msgid "target of %s instruction must be a label"
+msgstr ""
+
+#: config/tc-i960.c:1542
+msgid "unmatched '['"
+msgstr ""
+
+#: config/tc-i960.c:1553
+msgid "garbage after index spec ignored"
+msgstr ""
+
+#. We never moved: there was no opcode either!
+#: config/tc-i960.c:1620
+msgid "missing opcode"
+msgstr ""
+
+#: config/tc-i960.c:1928
+msgid "invalid constant"
+msgstr ""
+
+#: config/tc-i960.c:2041
+msgid "invalid index register"
+msgstr ""
+
+#: config/tc-i960.c:2064
+msgid "invalid scale factor"
+msgstr ""
+
+#: config/tc-i960.c:2247
+msgid "unaligned register"
+msgstr ""
+
+#: config/tc-i960.c:2270
+msgid "no such sfr in this architecture"
+msgstr ""
+
+#: config/tc-i960.c:2308
+msgid "illegal literal"
+msgstr ""
+
+#. Should not happen: see block comment above
+#: config/tc-i960.c:2541
+#, c-format
+msgid "Trying to 'bal' to %s"
+msgstr ""
+
+#: config/tc-i960.c:2552
+msgid "Looks like a proc, but can't tell what kind.\n"
+msgstr ""
+
+#: config/tc-i960.c:2584
+msgid "should have 1 or 2 operands"
+msgstr ""
+
+#: config/tc-i960.c:2593 config/tc-i960.c:2612
+#, c-format
+msgid "Redefining leafproc %s"
+msgstr ""
+
+#: config/tc-i960.c:2642
+msgid "should have two operands"
+msgstr ""
+
+#: config/tc-i960.c:2652
+msgid "'entry_num' must be absolute number in [0,31]"
+msgstr ""
+
+#: config/tc-i960.c:2661
+#, c-format
+msgid "Redefining entrynum for sysproc %s"
+msgstr ""
+
+#: config/tc-i960.c:2772
+msgid "architecture of opcode conflicts with that of earlier instruction(s)"
+msgstr ""
+
+#: config/tc-i960.c:2793
+msgid "big endian mode is not supported"
+msgstr ""
+
+#: config/tc-i960.c:2795
+#, c-format
+msgid "ignoring unrecognized .endian type `%s'"
+msgstr ""
+
+#: config/tc-i960.c:3052
+#, c-format
+msgid "leafproc symbol '%s' undefined"
+msgstr ""
+
+#: config/tc-i960.c:3062
+#, c-format
+msgid "Warning: making leafproc entries %s and %s both global\n"
+msgstr ""
+
+#: config/tc-i960.c:3169
+msgid "option --link-relax is only supported in b.out format"
+msgstr ""
+
+#: config/tc-i960.c:3212
+msgid "callj to difference of two symbols"
+msgstr ""
+
+#. Pretend that we do not recognise this option.
+#: config/tc-m32r.c:232
+#, c-format
+msgid "%s: unrecognised option: -hidden\n"
+msgstr ""
+
+#: config/tc-m32r.c:265
+msgid " M32R specific command line options:\n"
+msgstr ""
+
+#: config/tc-m32r.c:287
+msgid ""
+" -warn-unmatched-high warn when an (s)high reloc has no matching low "
+"reloc\n"
+msgstr ""
+
+#: config/tc-m32r.c:289
+msgid " -no-warn-unmatched-high do not warn about missing low relocs\n"
+msgstr ""
+
+#: config/tc-m32r.c:291
+msgid " -Wuh synonym for -warn-unmatched-high\n"
+msgstr ""
+
+#: config/tc-m32r.c:293
+msgid " -Wnuh synonym for -no-warn-unmatched-high\n"
+msgstr ""
+
+#: config/tc-m32r.c:297
+msgid " -relax create linker relaxable code\n"
+msgstr ""
+
+#: config/tc-m32r.c:299
+msgid " -cpu-desc provide runtime cpu description file\n"
+msgstr ""
+
+#: config/tc-m32r.c:429 read.c:2734 read.c:4799
+#, c-format
+msgid "symbol `%s' already defined"
+msgstr ""
+
+#: config/tc-m32r.c:700
+msgid "Instructions write to the same destination register."
+msgstr ""
+
+#: config/tc-m32r.c:708
+msgid "Instructions do not use parallel execution pipelines."
+msgstr ""
+
+#: config/tc-m32r.c:715
+msgid "Instructions share the same execution pipeline"
+msgstr ""
+
+#: config/tc-m32r.c:784 config/tc-m32r.c:870
+#, c-format
+msgid "not a 16 bit instruction '%s'"
+msgstr ""
+
+#: config/tc-m32r.c:791 config/tc-m32r.c:877 config/tc-m32r.c:1038
+#, c-format
+msgid "unknown instruction '%s'"
+msgstr ""
+
+#: config/tc-m32r.c:799 config/tc-m32r.c:884 config/tc-m32r.c:1045
+#, c-format
+msgid "instruction '%s' is for the M32RX only"
+msgstr ""
+
+#: config/tc-m32r.c:807 config/tc-m32r.c:892
+#, c-format
+msgid "instruction '%s' cannot be executed in parallel."
+msgstr ""
+
+#: config/tc-m32r.c:854 config/tc-m32r.c:917 config/tc-m32r.c:1098
+msgid "internal error: lookup/get operands failed"
+msgstr ""
+
+#: config/tc-m32r.c:902
+#, c-format
+msgid "'%s': only the NOP instruction can be issued in parallel on the m32r"
+msgstr ""
+
+#: config/tc-m32r.c:931
+#, c-format
+msgid ""
+"%s: output of 1st instruction is the same as an input to 2nd instruction - "
+"is this intentional ?"
+msgstr ""
+
+#: config/tc-m32r.c:935
+#, c-format
+msgid ""
+"%s: output of 2nd instruction is the same as an input to 1st instruction - "
+"is this intentional ?"
+msgstr ""
+
+#: config/tc-m32r.c:1264 config/tc-ppc.c:1330 config/tc-ppc.c:3534 read.c:1349
+msgid "Expected comma after symbol-name: rest of line ignored."
+msgstr ""
+
+#: config/tc-m32r.c:1273
+#, c-format
+msgid ".SCOMMon length (%ld.) <0! Ignored."
+msgstr ""
+
+#: config/tc-m32r.c:1287 config/tc-ppc.c:1352 config/tc-ppc.c:2261
+#: config/tc-ppc.c:3558
+msgid "ignoring bad alignment"
+msgstr ""
+
+#: config/tc-m32r.c:1313 config/tc-ppc.c:1363 config/tc-ppc.c:3570 read.c:1369
+#: read.c:2083
+#, c-format
+msgid "Ignoring attempt to re-define symbol `%s'."
+msgstr ""
+
+#: config/tc-m32r.c:1322
+#, c-format
+msgid "Length of .scomm \"%s\" is already %ld. Not changed to %ld."
+msgstr ""
+
+#: config/tc-m32r.c:1566
+msgid "Addend to unresolved symbol not on word boundary."
+msgstr ""
+
+#: config/tc-m32r.c:1795
+msgid "Unmatched high/shigh reloc"
+msgstr ""
+
+#: config/tc-m68k.c:636
+msgid "Unknown PC relative instruction"
+msgstr ""
+
+#: config/tc-m68k.c:764
+#, c-format
+msgid "Can not do %d byte pc-relative pic relocation"
+msgstr ""
+
+#: config/tc-m68k.c:771
+#, c-format
+msgid "Can not do %d byte pic relocation"
+msgstr ""
+
+#: config/tc-m68k.c:875 config/tc-mips.c:11891
+#, c-format
+msgid "Cannot make %s relocation PC relative"
+msgstr ""
+
+#: config/tc-m68k.c:987 config/tc-tahoe.c:1505 config/tc-vax.c:1773
+msgid "No operator"
+msgstr ""
+
+#: config/tc-m68k.c:1017 config/tc-tahoe.c:1522 config/tc-vax.c:1790
+msgid "Unknown operator"
+msgstr ""
+
+#: config/tc-m68k.c:1764
+msgid "invalid instruction for this architecture; needs "
+msgstr ""
+
+#: config/tc-m68k.c:1769
+msgid "fpu (68040, 68060 or 68881/68882)"
+msgstr ""
+
+#: config/tc-m68k.c:1772
+msgid "mmu (68030 or 68851)"
+msgstr ""
+
+#: config/tc-m68k.c:1775
+msgid "68020 or higher"
+msgstr ""
+
+#: config/tc-m68k.c:1778
+msgid "68000 or higher"
+msgstr ""
+
+#: config/tc-m68k.c:1781
+msgid "68010 or higher"
+msgstr ""
+
+#: config/tc-m68k.c:1809
+msgid "operands mismatch"
+msgstr ""
+
+#: config/tc-m68k.c:1866 config/tc-m68k.c:1872 config/tc-m68k.c:1878
+msgid "operand out of range"
+msgstr ""
+
+#: config/tc-m68k.c:1935
+#, c-format
+msgid "Bignum too big for %c format; truncated"
+msgstr ""
+
+#: config/tc-m68k.c:2003
+msgid "displacement too large for this architecture; needs 68020 or higher"
+msgstr ""
+
+#: config/tc-m68k.c:2113
+msgid ""
+"scale factor invalid on this architecture; needs cpu32 or 68020 or higher"
+msgstr ""
+
+#: config/tc-m68k.c:2167
+msgid "Forcing byte displacement"
+msgstr ""
+
+#: config/tc-m68k.c:2169
+msgid "byte displacement out of range"
+msgstr ""
+
+#: config/tc-m68k.c:2216 config/tc-m68k.c:2254
+msgid "invalid operand mode for this architecture; needs 68020 or higher"
+msgstr ""
+
+#: config/tc-m68k.c:2240 config/tc-m68k.c:2274
+msgid ":b not permitted; defaulting to :w"
+msgstr ""
+
+#: config/tc-m68k.c:2356
+msgid "unsupported byte value; use a different suffix"
+msgstr ""
+
+#: config/tc-m68k.c:2370
+msgid "unknown/incorrect operand"
+msgstr ""
+
+#: config/tc-m68k.c:2403 config/tc-m68k.c:2411 config/tc-m68k.c:2418
+#: config/tc-m68k.c:2425
+msgid "out of range"
+msgstr ""
+
+#: config/tc-m68k.c:2475
+msgid "Can't use long branches on 68000/68010/5200"
+msgstr ""
+
+#: config/tc-m68k.c:2563
+msgid "Expression out of range, using 0"
+msgstr ""
+
+#: config/tc-m68k.c:2668 config/tc-m68k.c:2684
+msgid "Floating point register in register list"
+msgstr ""
+
+#: config/tc-m68k.c:2674
+msgid "Wrong register in floating-point reglist"
+msgstr ""
+
+#: config/tc-m68k.c:2690
+msgid "incorrect register in reglist"
+msgstr ""
+
+#: config/tc-m68k.c:2696
+msgid "wrong register in floating-point reglist"
+msgstr ""
+
+#: config/tc-m68k.c:2772
+msgid "failed sanity check"
+msgstr ""
+
+#. ERROR
+#: config/tc-m68k.c:3108
+msgid "Extra )"
+msgstr ""
+
+#. ERROR
+#: config/tc-m68k.c:3119
+msgid "Missing )"
+msgstr ""
+
+#: config/tc-m68k.c:3136
+msgid "Missing operand"
+msgstr ""
+
+#: config/tc-m68k.c:3427
+#, c-format
+msgid "%s -- statement `%s' ignored"
+msgstr ""
+
+#: config/tc-m68k.c:3471
+#, c-format
+msgid "Don't know how to figure width of %c in md_assemble()"
+msgstr ""
+
+#: config/tc-m68k.c:3639 config/tc-m68k.c:3675
+#, c-format
+msgid "Internal Error: Can't find %s in hash table"
+msgstr ""
+
+#: config/tc-m68k.c:3642 config/tc-m68k.c:3678
+#, c-format
+msgid "Internal Error: Can't hash %s: %s"
+msgstr ""
+
+#: config/tc-m68k.c:3804
+#, c-format
+msgid "unrecognized default cpu `%s' ???"
+msgstr ""
+
+#: config/tc-m68k.c:3816
+msgid "68040 and 68851 specified; mmu instructions may assemble incorrectly"
+msgstr ""
+
+#: config/tc-m68k.c:3836
+msgid "options for 68881 and no-68881 both given"
+msgstr ""
+
+#: config/tc-m68k.c:3838
+msgid "options for 68851 and no-68851 both given"
+msgstr ""
+
+#: config/tc-m68k.c:3909
+#, c-format
+msgid "text label `%s' aligned to odd boundary"
+msgstr ""
+
+#: config/tc-m68k.c:4126
+msgid "invalid byte branch offset"
+msgstr ""
+
+#: config/tc-m68k.c:4183
+msgid "short branch with zero offset: use :w"
+msgstr ""
+
+#: config/tc-m68k.c:4229
+msgid "Long branch offset not supported."
+msgstr ""
+
+#: config/tc-m68k.c:4290
+#, c-format
+msgid "Internal error (long PC-relative operand) for insn 0x%04x at 0x%lx"
+msgstr ""
+
+#: config/tc-m68k.c:4321
+msgid "displacement doesn't fit in one byte"
+msgstr ""
+
+#: config/tc-m68k.c:4434
+msgid "Long branch offset to extern symbol not supported."
+msgstr ""
+
+#: config/tc-m68k.c:4783 config/tc-m68k.c:4794
+msgid "expression out of range: defaulting to 1"
+msgstr ""
+
+#: config/tc-m68k.c:4826
+msgid "expression out of range: defaulting to 0"
+msgstr ""
+
+#: config/tc-m68k.c:4859 config/tc-m68k.c:4871
+#, c-format
+msgid "Can't deal with expression; defaulting to %ld"
+msgstr ""
+
+#: config/tc-m68k.c:4885
+msgid "expression doesn't fit in BYTE"
+msgstr ""
+
+#: config/tc-m68k.c:4889
+msgid "expression doesn't fit in WORD"
+msgstr ""
+
+#: config/tc-m68k.c:4982
+#, c-format
+msgid "%s: unrecognized processor name"
+msgstr ""
+
+#: config/tc-m68k.c:5047
+msgid "bad coprocessor id"
+msgstr ""
+
+#: config/tc-m68k.c:5053
+msgid "unrecognized fopt option"
+msgstr ""
+
+#: config/tc-m68k.c:5187
+#, c-format
+msgid "option `%s' may not be negated"
+msgstr ""
+
+#: config/tc-m68k.c:5198
+#, c-format
+msgid "option `%s' not recognized"
+msgstr ""
+
+#: config/tc-m68k.c:5231
+msgid "bad format of OPT NEST=depth"
+msgstr ""
+
+#: config/tc-m68k.c:5294
+msgid "missing label"
+msgstr ""
+
+#: config/tc-m68k.c:5318 config/tc-m68k.c:5347
+msgid "bad register list"
+msgstr ""
+
+#: config/tc-m68k.c:5320
+#, c-format
+msgid "bad register list: %s"
+msgstr ""
+
+#: config/tc-m68k.c:5418
+msgid "restore without save"
+msgstr ""
+
+#: config/tc-m68k.c:5595 config/tc-m68k.c:5944
+msgid "syntax error in structured control directive"
+msgstr ""
+
+#: config/tc-m68k.c:5646
+msgid "missing condition code in structured control directive"
+msgstr ""
+
+#: config/tc-m68k.c:5978
+msgid "missing then"
+msgstr ""
+
+#: config/tc-m68k.c:6060
+msgid "else without matching if"
+msgstr ""
+
+#: config/tc-m68k.c:6094
+msgid "endi without matching if"
+msgstr ""
+
+#: config/tc-m68k.c:6135
+msgid "break outside of structured loop"
+msgstr ""
+
+#: config/tc-m68k.c:6174
+msgid "next outside of structured loop"
+msgstr ""
+
+#: config/tc-m68k.c:6226
+msgid "missing ="
+msgstr ""
+
+#: config/tc-m68k.c:6264
+msgid "missing to or downto"
+msgstr ""
+
+#: config/tc-m68k.c:6300 config/tc-m68k.c:6334 config/tc-m68k.c:6544
+msgid "missing do"
+msgstr ""
+
+#: config/tc-m68k.c:6437
+msgid "endf without for"
+msgstr ""
+
+#: config/tc-m68k.c:6493
+msgid "until without repeat"
+msgstr ""
+
+#: config/tc-m68k.c:6580
+msgid "endw without while"
+msgstr ""
+
+#: config/tc-m68k.c:6696
+#, c-format
+msgid "unrecognized option `%s'"
+msgstr ""
+
+#: config/tc-m68k.c:6741
+#, c-format
+msgid "unrecognized architecture specification `%s'"
+msgstr ""
+
+#: config/tc-m68k.c:6811
+msgid ""
+"680X0 options:\n"
+"-l\t\t\tuse 1 word for refs to undefined symbols [default 2]\n"
+"-m68000 | -m68008 | -m68010 | -m68020 | -m68030 | -m68040 | -m68060\n"
+" | -m68302 | -m68331 | -m68332 | -m68333 | -m68340 | -m68360\n"
+" | -mcpu32 | -m5200\n"
+"\t\t\tspecify variant of 680X0 architecture [default 68020]\n"
+"-m68881 | -m68882 | -mno-68881 | -mno-68882\n"
+"\t\t\ttarget has/lacks floating-point coprocessor\n"
+"\t\t\t[default yes for 68020, 68030, and cpu32]\n"
+msgstr ""
+
+#: config/tc-m68k.c:6821
+msgid ""
+"-m68851 | -mno-68851\n"
+"\t\t\ttarget has/lacks memory-management unit coprocessor\n"
+"\t\t\t[default yes for 68020 and up]\n"
+"-pic, -k\t\tgenerate position independent code\n"
+"-S\t\t\tturn jbsr into jsr\n"
+"--register-prefix-optional\n"
+"\t\t\trecognize register names without prefix character\n"
+"--bitwise-or\t\tdo not treat `|' as a comment character\n"
+msgstr ""
+
+#: config/tc-m68k.c:6830
+msgid ""
+"--base-size-default-16\tbase reg without size is 16 bits\n"
+"--base-size-default-32\tbase reg without size is 32 bits (default)\n"
+"--disp-size-default-16\tdisplacement with unknown size is 16 bits\n"
+"--disp-size-default-32\tdisplacement with unknown size is 32 bits (default)\n"
+msgstr ""
+
+#: config/tc-m68k.c:6865
+#, c-format
+msgid "Error %s in %s\n"
+msgstr ""
+
+#: config/tc-m68k.c:6869
+#, c-format
+msgid "Opcode(%d.%s): "
+msgstr ""
+
+#: config/tc-m88k.c:206
+#, c-format
+msgid "Can't hash instruction '%s':%s"
+msgstr ""
+
+#: config/tc-m88k.c:258
+#, c-format
+msgid "Invalid mnemonic '%s'"
+msgstr ""
+
+#: config/tc-m88k.c:278
+msgid "Parameter syntax error"
+msgstr ""
+
+#: config/tc-m88k.c:333
+msgid "Unknown relocation type"
+msgstr ""
+
+#. Having this here repeats the warning somtimes.
+#. But can't we stand that?
+#: config/tc-m88k.c:446
+msgid "Use of obsolete instruction"
+msgstr ""
+
+#: config/tc-m88k.c:563
+msgid "Expression truncated to 16 bits"
+msgstr ""
+
+#: config/tc-m88k.c:629 config/tc-m88k.c:651
+msgid "Expression truncated to 5 bits"
+msgstr ""
+
+#: config/tc-m88k.c:873
+msgid "Expression truncated to 9 bits"
+msgstr ""
+
+#: config/tc-m88k.c:895
+msgid "Removed lower 2 bits of expression"
+msgstr ""
+
+#: config/tc-m88k.c:1034
+msgid "Bad relocation type"
+msgstr ""
+
+#: config/tc-m88k.c:1047
+msgid "md_number_to_disp not defined"
+msgstr ""
+
+#: config/tc-m88k.c:1057
+msgid "md_number_to_field not defined"
+msgstr ""
+
+#: config/tc-m88k.c:1170
+msgid "Relaxation should never occur"
+msgstr ""
+
+#: config/tc-m88k.c:1267 config/tc-sparc.c:3024 read.c:1940
+#, c-format
+msgid "BSS length (%d.) <0! Ignored."
+msgstr ""
+
+#: config/tc-m88k.c:1311
+#, c-format
+msgid "Ignoring attempt to re-define symbol %s."
+msgstr ""
+
+#: config/tc-mcore.c:273
+#, c-format
+msgid "register expected, but saw '%.6s'"
+msgstr ""
+
+#: config/tc-mcore.c:357
+#, c-format
+msgid "control register expected, but saw '%.6s'"
+msgstr ""
+
+#: config/tc-mcore.c:513
+msgid "more than 65K literal pools"
+msgstr ""
+
+#: config/tc-mcore.c:567
+msgid "missing ']'"
+msgstr ""
+
+#: config/tc-mcore.c:607
+msgid "operand must be a constant"
+msgstr ""
+
+#: config/tc-mcore.c:609
+#, c-format
+msgid "operand must be absolute in range %d..%d, not %d"
+msgstr ""
+
+#: config/tc-mcore.c:646
+msgid "operand must be a multiple of 4"
+msgstr ""
+
+#: config/tc-mcore.c:653
+msgid "operand must be a multiple of 2"
+msgstr ""
+
+#: config/tc-mcore.c:667 config/tc-mcore.c:1177 config/tc-mcore.c:1231
+msgid "base register expected"
+msgstr ""
+
+#: config/tc-mcore.c:716
+#, c-format
+msgid "unknown opcode \"%s\""
+msgstr ""
+
+#: config/tc-mcore.c:759
+msgid "invalid register: r15 illegal"
+msgstr ""
+
+#: config/tc-mcore.c:808
+msgid "M340 specific opcode used when assembling for M210"
+msgstr ""
+
+#: config/tc-mcore.c:827 config/tc-mcore.c:866 config/tc-mcore.c:885
+#: config/tc-mcore.c:904 config/tc-mcore.c:931 config/tc-mcore.c:960
+#: config/tc-mcore.c:997 config/tc-mcore.c:1032 config/tc-mcore.c:1051
+#: config/tc-mcore.c:1070 config/tc-mcore.c:1102 config/tc-mcore.c:1124
+#: config/tc-mcore.c:1180 config/tc-mcore.c:1234 config/tc-mcore.c:1269
+#: config/tc-mcore.c:1323 config/tc-mcore.c:1345 config/tc-mcore.c:1368
+msgid "second operand missing"
+msgstr ""
+
+#: config/tc-mcore.c:842
+msgid "destination register must be r1"
+msgstr ""
+
+#: config/tc-mcore.c:863
+msgid "source register must be r1"
+msgstr ""
+
+#: config/tc-mcore.c:926 config/tc-mcore.c:983
+msgid "immediate is not a power of two"
+msgstr ""
+
+#: config/tc-mcore.c:954
+msgid "translating bgeni to movi"
+msgstr ""
+
+#: config/tc-mcore.c:991
+msgid "translating mgeni to movi"
+msgstr ""
+
+#: config/tc-mcore.c:1023
+msgid "translating bmaski to movi"
+msgstr ""
+
+#: config/tc-mcore.c:1097
+#, c-format
+msgid "displacement too large (%d)"
+msgstr ""
+
+#: config/tc-mcore.c:1111
+msgid "Invalid register: r0 and r15 illegal"
+msgstr ""
+
+#: config/tc-mcore.c:1138
+msgid "bad starting register: r0 and r15 invalid"
+msgstr ""
+
+#: config/tc-mcore.c:1151
+msgid "ending register must be r15"
+msgstr ""
+
+#: config/tc-mcore.c:1171
+msgid "bad base register: must be r0"
+msgstr ""
+
+#: config/tc-mcore.c:1189
+msgid "first register must be r4"
+msgstr ""
+
+#: config/tc-mcore.c:1200
+msgid "last register must be r7"
+msgstr ""
+
+#: config/tc-mcore.c:1237
+msgid "reg-reg expected"
+msgstr ""
+
+#: config/tc-mcore.c:1342
+msgid "second operand must be 1"
+msgstr ""
+
+#: config/tc-mcore.c:1363
+msgid "zero used as immediate value"
+msgstr ""
+
+#: config/tc-mcore.c:1374
+#, c-format
+msgid "unimplemented opcode \"%s\""
+msgstr ""
+
+#: config/tc-mcore.c:1444 config/tc-w65.c:856
+msgid "Bad call to MD_NTOF()"
+msgstr ""
+
+#: config/tc-mcore.c:1513
+#, c-format
+msgid "unrecognised cpu type '%s'"
+msgstr ""
+
+#: config/tc-mcore.c:1535
+msgid ""
+"MCORE specific options:\n"
+" -{no-}jsri2bsr\t disable/enable jsri to bsr transformation (def: on)\n"
+" -{no-}sifilter\t disable/enable silicon filter behavior (def: off)\n"
+" -relax\t\t alter jump instructions for long displacements\n"
+msgstr ""
+
diff --git a/gas/read.c b/gas/read.c
new file mode 100644
index 0000000000..7fee24161e
--- /dev/null
+++ b/gas/read.c
@@ -0,0 +1,5054 @@
+/* read.c - read a source file -
+ Copyright (C) 1986, 87, 90, 91, 92, 93, 94, 95, 96, 97, 98, 1999
+ Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GAS 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 more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#if 0
+#define MASK_CHAR (0xFF) /* If your chars aren't 8 bits, you will
+ change this a bit. But then, GNU isn't
+ spozed to run on your machine anyway.
+ (RMS is so shortsighted sometimes.)
+ */
+#else
+#define MASK_CHAR ((int)(unsigned char)-1)
+#endif
+
+
+/* This is the largest known floating point format (for now). It will
+ grow when we do 4361 style flonums. */
+
+#define MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT (16)
+
+/* Routines that read assembler source text to build spagetti in memory.
+ Another group of these functions is in the expr.c module. */
+
+/* for isdigit() */
+#include <ctype.h>
+
+#include "as.h"
+#include "subsegs.h"
+#include "sb.h"
+#include "macro.h"
+#include "obstack.h"
+#include "listing.h"
+#include "ecoff.h"
+
+#ifndef TC_START_LABEL
+#define TC_START_LABEL(x,y) (x==':')
+#endif
+
+/* The NOP_OPCODE is for the alignment fill value.
+ * fill it a nop instruction so that the disassembler does not choke
+ * on it
+ */
+#ifndef NOP_OPCODE
+#define NOP_OPCODE 0x00
+#endif
+
+char *input_line_pointer; /*->next char of source file to parse. */
+
+#if BITS_PER_CHAR != 8
+/* The following table is indexed by[(char)] and will break if
+ a char does not have exactly 256 states (hopefully 0:255!)! */
+die horribly;
+#endif
+
+#ifndef LEX_AT
+/* The m88k unfortunately uses @ as a label beginner. */
+#define LEX_AT 0
+#endif
+
+#ifndef LEX_BR
+/* The RS/6000 assembler uses {,},[,] as parts of symbol names. */
+#define LEX_BR 0
+#endif
+
+#ifndef LEX_PCT
+/* The Delta 68k assembler permits % inside label names. */
+#define LEX_PCT 0
+#endif
+
+#ifndef LEX_QM
+/* The PowerPC Windows NT assemblers permits ? inside label names. */
+#define LEX_QM 0
+#endif
+
+#ifndef LEX_DOLLAR
+/* The a29k assembler does not permits labels to start with $. */
+#define LEX_DOLLAR 3
+#endif
+
+#ifndef LEX_TILDE
+/* The Delta 68k assembler permits ~ at start of label names. */
+#define LEX_TILDE 0
+#endif
+
+/* used by is_... macros. our ctype[] */
+char lex_type[256] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ABCDEFGHIJKLMNO */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* PQRSTUVWXYZ[\]^_ */
+ 0, 0, 0, 0, LEX_DOLLAR, LEX_PCT, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, LEX_QM, /* 0123456789:;<=>? */
+ LEX_AT, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, 0, 3, /* PQRSTUVWXYZ[\]^_ */
+ 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* `abcdefghijklmno */
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, LEX_TILDE, 0, /* pqrstuvwxyz{|}~. */
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
+};
+
+
+/*
+ * In: a character.
+ * Out: 1 if this character ends a line.
+ */
+#define Z_ (0)
+char is_end_of_line[256] =
+{
+#ifdef CR_EOL
+ 99, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, 99, Z_, Z_, 99, Z_, Z_, /* @abcdefghijklmno */
+#else
+ 99, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, 99, Z_, Z_, Z_, Z_, Z_, /* @abcdefghijklmno */
+#endif
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* */
+#ifdef TC_HPPA
+ Z_,99, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* _!"#$%&'()*+,-./ */
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* 0123456789:;<=>? */
+#else
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* */
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, 99, Z_, Z_, Z_, Z_, /* 0123456789:;<=>? */
+#endif
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* */
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* */
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* */
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* */
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* */
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* */
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* */
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* */
+ Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, Z_, /* */
+};
+#undef Z_
+
+/* Functions private to this file. */
+
+static char *buffer; /* 1st char of each buffer of lines is here. */
+static char *buffer_limit; /*->1 + last char in buffer. */
+
+/* TARGET_BYTES_BIG_ENDIAN is required to be defined to either 0 or 1 in the
+ tc-<CPU>.h file. See the "Porting GAS" section of the internals manual. */
+int target_big_endian = TARGET_BYTES_BIG_ENDIAN;
+
+static char *old_buffer; /* JF a hack */
+static char *old_input;
+static char *old_limit;
+
+/* Variables for handling include file directory table. */
+
+char **include_dirs; /* Table of pointers to directories to
+ search for .include's */
+int include_dir_count; /* How many are in the table */
+int include_dir_maxlen = 1;/* Length of longest in table */
+
+#ifndef WORKING_DOT_WORD
+struct broken_word *broken_words;
+int new_broken_words;
+#endif
+
+/* The current offset into the absolute section. We don't try to
+ build frags in the absolute section, since no data can be stored
+ there. We just keep track of the current offset. */
+addressT abs_section_offset;
+
+/* If this line had an MRI style label, it is stored in this variable.
+ This is used by some of the MRI pseudo-ops. */
+symbolS *line_label;
+
+/* This global variable is used to support MRI common sections. We
+ translate such sections into a common symbol. This variable is
+ non-NULL when we are in an MRI common section. */
+symbolS *mri_common_symbol;
+
+/* In MRI mode, after a dc.b pseudo-op with an odd number of bytes, we
+ need to align to an even byte boundary unless the next pseudo-op is
+ dc.b, ds.b, or dcb.b. This variable is set to 1 if an alignment
+ may be needed. */
+static int mri_pending_align;
+
+#ifndef NO_LISTING
+#ifdef OBJ_ELF
+/* This variable is set to be non-zero if the next string we see might
+ be the name of the source file in DWARF debugging information. See
+ the comment in emit_expr for the format we look for. */
+static int dwarf_file_string;
+#endif
+#endif
+
+static void cons_worker PARAMS ((int, int));
+static int scrub_from_string PARAMS ((char **));
+static void do_align PARAMS ((int, char *, int, int));
+static void s_align PARAMS ((int, int));
+static int hex_float PARAMS ((int, char *));
+static void do_org PARAMS ((segT, expressionS *, int));
+char *demand_copy_string PARAMS ((int *lenP));
+static segT get_segmented_expression PARAMS ((expressionS *expP));
+static segT get_known_segmented_expression PARAMS ((expressionS * expP));
+static void pobegin PARAMS ((void));
+static int get_line_sb PARAMS ((sb *));
+static void generate_file_debug PARAMS ((void));
+
+
+void
+read_begin ()
+{
+ const char *p;
+
+ pobegin ();
+ obj_read_begin_hook ();
+
+ /* Something close -- but not too close -- to a multiple of 1024.
+ The debugging malloc I'm using has 24 bytes of overhead. */
+ obstack_begin (&notes, chunksize);
+ obstack_begin (&cond_obstack, chunksize);
+
+ /* Use machine dependent syntax */
+ for (p = line_separator_chars; *p; p++)
+ is_end_of_line[(unsigned char) *p] = 1;
+ /* Use more. FIXME-SOMEDAY. */
+
+ if (flag_mri)
+ lex_type['?'] = 3;
+}
+
+/* set up pseudo-op tables */
+
+static struct hash_control *po_hash;
+
+static const pseudo_typeS potable[] =
+{
+ {"abort", s_abort, 0},
+ {"align", s_align_ptwo, 0},
+ {"ascii", stringer, 0},
+ {"asciz", stringer, 1},
+ {"balign", s_align_bytes, 0},
+ {"balignw", s_align_bytes, -2},
+ {"balignl", s_align_bytes, -4},
+/* block */
+ {"byte", cons, 1},
+ {"comm", s_comm, 0},
+ {"common", s_mri_common, 0},
+ {"common.s", s_mri_common, 1},
+ {"data", s_data, 0},
+ {"dc", cons, 2},
+ {"dc.b", cons, 1},
+ {"dc.d", float_cons, 'd'},
+ {"dc.l", cons, 4},
+ {"dc.s", float_cons, 'f'},
+ {"dc.w", cons, 2},
+ {"dc.x", float_cons, 'x'},
+ {"dcb", s_space, 2},
+ {"dcb.b", s_space, 1},
+ {"dcb.d", s_float_space, 'd'},
+ {"dcb.l", s_space, 4},
+ {"dcb.s", s_float_space, 'f'},
+ {"dcb.w", s_space, 2},
+ {"dcb.x", s_float_space, 'x'},
+ {"ds", s_space, 2},
+ {"ds.b", s_space, 1},
+ {"ds.d", s_space, 8},
+ {"ds.l", s_space, 4},
+ {"ds.p", s_space, 12},
+ {"ds.s", s_space, 4},
+ {"ds.w", s_space, 2},
+ {"ds.x", s_space, 12},
+ {"debug", s_ignore, 0},
+#ifdef S_SET_DESC
+ {"desc", s_desc, 0},
+#endif
+/* dim */
+ {"double", float_cons, 'd'},
+/* dsect */
+ {"eject", listing_eject, 0}, /* Formfeed listing */
+ {"else", s_else, 0},
+ {"elsec", s_else, 0},
+ {"end", s_end, 0},
+ {"endc", s_endif, 0},
+ {"endfunc", s_func, 1},
+ {"endif", s_endif, 0},
+/* endef */
+ {"equ", s_set, 0},
+ {"equiv", s_set, 1},
+ {"err", s_err, 0},
+ {"exitm", s_mexit, 0},
+/* extend */
+ {"extern", s_ignore, 0}, /* We treat all undef as ext */
+ {"appfile", s_app_file, 1},
+ {"appline", s_app_line, 0},
+ {"fail", s_fail, 0},
+ {"file", s_app_file, 0},
+ {"fill", s_fill, 0},
+ {"float", float_cons, 'f'},
+ {"format", s_ignore, 0},
+ {"func", s_func, 0},
+ {"global", s_globl, 0},
+ {"globl", s_globl, 0},
+ {"hword", cons, 2},
+ {"if", s_if, (int) O_ne},
+ {"ifc", s_ifc, 0},
+ {"ifdef", s_ifdef, 0},
+ {"ifeq", s_if, (int) O_eq},
+ {"ifeqs", s_ifeqs, 0},
+ {"ifge", s_if, (int) O_ge},
+ {"ifgt", s_if, (int) O_gt},
+ {"ifle", s_if, (int) O_le},
+ {"iflt", s_if, (int) O_lt},
+ {"ifnc", s_ifc, 1},
+ {"ifndef", s_ifdef, 1},
+ {"ifne", s_if, (int) O_ne},
+ {"ifnes", s_ifeqs, 1},
+ {"ifnotdef", s_ifdef, 1},
+ {"include", s_include, 0},
+ {"int", cons, 4},
+ {"irp", s_irp, 0},
+ {"irep", s_irp, 0},
+ {"irpc", s_irp, 1},
+ {"irepc", s_irp, 1},
+ {"lcomm", s_lcomm, 0},
+ {"lflags", listing_flags, 0}, /* Listing flags */
+ {"linkonce", s_linkonce, 0},
+ {"list", listing_list, 1}, /* Turn listing on */
+ {"llen", listing_psize, 1},
+ {"long", cons, 4},
+ {"lsym", s_lsym, 0},
+ {"macro", s_macro, 0},
+ {"mexit", s_mexit, 0},
+ {"mri", s_mri, 0},
+ {".mri", s_mri, 0}, /* Special case so .mri works in MRI mode. */
+ {"name", s_ignore, 0},
+ {"noformat", s_ignore, 0},
+ {"nolist", listing_list, 0}, /* Turn listing off */
+ {"nopage", listing_nopage, 0},
+ {"octa", cons, 16},
+ {"offset", s_struct, 0},
+ {"org", s_org, 0},
+ {"p2align", s_align_ptwo, 0},
+ {"p2alignw", s_align_ptwo, -2},
+ {"p2alignl", s_align_ptwo, -4},
+ {"page", listing_eject, 0},
+ {"plen", listing_psize, 0},
+ {"print", s_print, 0},
+ {"psize", listing_psize, 0}, /* set paper size */
+ {"purgem", s_purgem, 0},
+ {"quad", cons, 8},
+ {"rep", s_rept, 0},
+ {"rept", s_rept, 0},
+ {"rva", s_rva, 4},
+ {"sbttl", listing_title, 1}, /* Subtitle of listing */
+/* scl */
+/* sect */
+ {"set", s_set, 0},
+ {"short", cons, 2},
+ {"single", float_cons, 'f'},
+/* size */
+ {"space", s_space, 0},
+ {"skip", s_space, 0},
+ {"sleb128", s_leb128, 1},
+ {"spc", s_ignore, 0},
+ {"stabd", s_stab, 'd'},
+ {"stabn", s_stab, 'n'},
+ {"stabs", s_stab, 's'},
+ {"string", stringer, 1},
+ {"struct", s_struct, 0},
+/* tag */
+ {"text", s_text, 0},
+
+ /* This is for gcc to use. It's only just been added (2/94), so gcc
+ won't be able to use it for a while -- probably a year or more.
+ But once this has been released, check with gcc maintainers
+ before deleting it or even changing the spelling. */
+ {"this_GCC_requires_the_GNU_assembler", s_ignore, 0},
+ /* If we're folding case -- done for some targets, not necessarily
+ all -- the above string in an input file will be converted to
+ this one. Match it either way... */
+ {"this_gcc_requires_the_gnu_assembler", s_ignore, 0},
+
+ {"title", listing_title, 0}, /* Listing title */
+ {"ttl", listing_title, 0},
+/* type */
+ {"uleb128", s_leb128, 0},
+/* use */
+/* val */
+ {"xcom", s_comm, 0},
+ {"xdef", s_globl, 0},
+ {"xref", s_ignore, 0},
+ {"xstabs", s_xstab, 's'},
+ {"word", cons, 2},
+ {"zero", s_space, 0},
+ {NULL} /* end sentinel */
+};
+
+static int pop_override_ok = 0;
+static const char *pop_table_name;
+
+void
+pop_insert (table)
+ const pseudo_typeS *table;
+{
+ const char *errtxt;
+ const pseudo_typeS *pop;
+ for (pop = table; pop->poc_name; pop++)
+ {
+ errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop);
+ if (errtxt && (!pop_override_ok || strcmp (errtxt, "exists")))
+ as_fatal (_("error constructing %s pseudo-op table: %s"), pop_table_name,
+ errtxt);
+ }
+}
+
+#ifndef md_pop_insert
+#define md_pop_insert() pop_insert(md_pseudo_table)
+#endif
+
+#ifndef obj_pop_insert
+#define obj_pop_insert() pop_insert(obj_pseudo_table)
+#endif
+
+static void
+pobegin ()
+{
+ po_hash = hash_new ();
+
+ /* Do the target-specific pseudo ops. */
+ pop_table_name = "md";
+ md_pop_insert ();
+
+ /* Now object specific. Skip any that were in the target table. */
+ pop_table_name = "obj";
+ pop_override_ok = 1;
+ obj_pop_insert ();
+
+ /* Now portable ones. Skip any that we've seen already. */
+ pop_table_name = "standard";
+ pop_insert (potable);
+}
+
+#define HANDLE_CONDITIONAL_ASSEMBLY() \
+ if (ignore_input ()) \
+ { \
+ while (! is_end_of_line[(unsigned char) *input_line_pointer++]) \
+ if (input_line_pointer == buffer_limit) \
+ break; \
+ continue; \
+ }
+
+
+/* This function is used when scrubbing the characters between #APP
+ and #NO_APP. */
+
+static char *scrub_string;
+static char *scrub_string_end;
+
+static int
+scrub_from_string (from)
+ char **from;
+{
+ int size;
+
+ *from = scrub_string;
+ size = scrub_string_end - scrub_string;
+ scrub_string = scrub_string_end;
+ return size;
+}
+
+/* read_a_source_file()
+ *
+ * We read the file, putting things into a web that
+ * represents what we have been reading.
+ */
+void
+read_a_source_file (name)
+ char *name;
+{
+ register char c;
+ register char *s; /* string of symbol, '\0' appended */
+ register int temp;
+ pseudo_typeS *pop;
+
+ buffer = input_scrub_new_file (name);
+
+ listing_file (name);
+ listing_newline (NULL);
+ register_dependency (name);
+
+ /* Generate debugging information before we've read anything in to denote
+ this file as the "main" source file and not a subordinate one
+ (e.g. N_SO vs N_SOL in stabs). */
+ generate_file_debug ();
+
+ while ((buffer_limit = input_scrub_next_buffer (&input_line_pointer)) != 0)
+ { /* We have another line to parse. */
+ know (buffer_limit[-1] == '\n'); /* Must have a sentinel. */
+ contin: /* JF this goto is my fault I admit it.
+ Someone brave please re-write the whole
+ input section here? Pleeze??? */
+ while (input_line_pointer < buffer_limit)
+ {
+ /* We have more of this buffer to parse. */
+
+ /*
+ * We now have input_line_pointer->1st char of next line.
+ * If input_line_pointer [-1] == '\n' then we just
+ * scanned another line: so bump line counters.
+ */
+ if (is_end_of_line[(unsigned char) input_line_pointer[-1]])
+ {
+#ifdef md_start_line_hook
+ md_start_line_hook ();
+#endif
+
+ if (input_line_pointer[-1] == '\n')
+ bump_line_counters ();
+
+ line_label = NULL;
+
+ if (flag_m68k_mri
+#ifdef LABELS_WITHOUT_COLONS
+ || 1
+#endif
+ )
+ {
+ /* Text at the start of a line must be a label, we
+ run down and stick a colon in. */
+ if (is_name_beginner (*input_line_pointer))
+ {
+ char *line_start = input_line_pointer;
+ char c;
+ int mri_line_macro;
+
+ LISTING_NEWLINE ();
+ HANDLE_CONDITIONAL_ASSEMBLY ();
+
+ c = get_symbol_end ();
+
+ /* In MRI mode, the EQU and MACRO pseudoops must
+ be handled specially. */
+ mri_line_macro = 0;
+ if (flag_m68k_mri)
+ {
+ char *rest = input_line_pointer + 1;
+
+ if (*rest == ':')
+ ++rest;
+ if (*rest == ' ' || *rest == '\t')
+ ++rest;
+ if ((strncasecmp (rest, "EQU", 3) == 0
+ || strncasecmp (rest, "SET", 3) == 0)
+ && (rest[3] == ' ' || rest[3] == '\t'))
+ {
+ input_line_pointer = rest + 3;
+ equals (line_start,
+ strncasecmp (rest, "SET", 3) == 0);
+ continue;
+ }
+ if (strncasecmp (rest, "MACRO", 5) == 0
+ && (rest[5] == ' '
+ || rest[5] == '\t'
+ || is_end_of_line[(unsigned char) rest[5]]))
+ mri_line_macro = 1;
+ }
+
+ /* In MRI mode, we need to handle the MACRO
+ pseudo-op specially: we don't want to put the
+ symbol in the symbol table. */
+ if (! mri_line_macro)
+ line_label = colon (line_start);
+ else
+ line_label = symbol_create (line_start,
+ absolute_section,
+ (valueT) 0,
+ &zero_address_frag);
+
+ *input_line_pointer = c;
+ if (c == ':')
+ input_line_pointer++;
+ }
+ }
+ }
+
+ /*
+ * We are at the begining of a line, or similar place.
+ * We expect a well-formed assembler statement.
+ * A "symbol-name:" is a statement.
+ *
+ * Depending on what compiler is used, the order of these tests
+ * may vary to catch most common case 1st.
+ * Each test is independent of all other tests at the (top) level.
+ * PLEASE make a compiler that doesn't use this assembler.
+ * It is crufty to waste a compiler's time encoding things for this
+ * assembler, which then wastes more time decoding it.
+ * (And communicating via (linear) files is silly!
+ * If you must pass stuff, please pass a tree!)
+ */
+ if ((c = *input_line_pointer++) == '\t'
+ || c == ' '
+ || c == '\f'
+ || c == 0)
+ {
+ c = *input_line_pointer++;
+ }
+ know (c != ' '); /* No further leading whitespace. */
+
+#ifndef NO_LISTING
+ /* If listing is on, and we are expanding a macro, then give
+ the listing code the contents of the expanded line. */
+ if (listing)
+ {
+ if ((listing & LISTING_MACEXP) && macro_nest > 0)
+ {
+ char *copy;
+ int len;
+
+ /* Find the end of the current expanded macro line. */
+ for (s = input_line_pointer-1; *s ; ++s)
+ if (is_end_of_line[(unsigned char) *s])
+ break;
+
+ /* Copy it for safe keeping. Also give an indication of
+ how much macro nesting is involved at this point. */
+ len = s - (input_line_pointer-1);
+ copy = (char *) xmalloc (len + macro_nest + 2);
+ memset (copy, '>', macro_nest);
+ copy[macro_nest] = ' ';
+ memcpy (copy + macro_nest + 1, input_line_pointer-1, len);
+ copy[macro_nest+1+len] = '\0';
+
+ /* Install the line with the listing facility. */
+ listing_newline (copy);
+ }
+ else
+ listing_newline (NULL);
+ }
+#endif
+
+ /*
+ * C is the 1st significant character.
+ * Input_line_pointer points after that character.
+ */
+ if (is_name_beginner (c))
+ {
+ /* want user-defined label or pseudo/opcode */
+ HANDLE_CONDITIONAL_ASSEMBLY ();
+
+ s = --input_line_pointer;
+ c = get_symbol_end (); /* name's delimiter */
+ /*
+ * C is character after symbol.
+ * That character's place in the input line is now '\0'.
+ * S points to the beginning of the symbol.
+ * [In case of pseudo-op, s->'.'.]
+ * Input_line_pointer->'\0' where c was.
+ */
+ if (TC_START_LABEL(c, input_line_pointer))
+ {
+ if (flag_m68k_mri)
+ {
+ char *rest = input_line_pointer + 1;
+
+ /* In MRI mode, \tsym: set 0 is permitted. */
+
+ if (*rest == ':')
+ ++rest;
+ if (*rest == ' ' || *rest == '\t')
+ ++rest;
+ if ((strncasecmp (rest, "EQU", 3) == 0
+ || strncasecmp (rest, "SET", 3) == 0)
+ && (rest[3] == ' ' || rest[3] == '\t'))
+ {
+ input_line_pointer = rest + 3;
+ equals (s, 1);
+ continue;
+ }
+ }
+
+ line_label = colon (s); /* user-defined label */
+ *input_line_pointer++ = ':'; /* Put ':' back for error messages' sake. */
+ /* Input_line_pointer->after ':'. */
+ SKIP_WHITESPACE ();
+
+
+ }
+ else if (c == '='
+ || ((c == ' ' || c == '\t')
+ && input_line_pointer[1] == '='
+#ifdef TC_EQUAL_IN_INSN
+ && ! TC_EQUAL_IN_INSN (c, input_line_pointer)
+#endif
+ ))
+ {
+ equals (s, 1);
+ demand_empty_rest_of_line ();
+ }
+ else
+ { /* expect pseudo-op or machine instruction */
+ pop = NULL;
+
+#define IGNORE_OPCODE_CASE
+#ifdef IGNORE_OPCODE_CASE
+ {
+ char *s2 = s;
+ while (*s2)
+ {
+ if (isupper ((unsigned char) *s2))
+ *s2 = tolower (*s2);
+ s2++;
+ }
+ }
+#endif
+
+ if (flag_m68k_mri
+#ifdef NO_PSEUDO_DOT
+ || 1
+#endif
+ )
+ {
+ /* The MRI assembler and the m88k use pseudo-ops
+ without a period. */
+ pop = (pseudo_typeS *) hash_find (po_hash, s);
+ if (pop != NULL && pop->poc_handler == NULL)
+ pop = NULL;
+ }
+
+ if (pop != NULL
+ || (! flag_m68k_mri && *s == '.'))
+ {
+ /*
+ * PSEUDO - OP.
+ *
+ * WARNING: c has next char, which may be end-of-line.
+ * We lookup the pseudo-op table with s+1 because we
+ * already know that the pseudo-op begins with a '.'.
+ */
+
+ if (pop == NULL)
+ pop = (pseudo_typeS *) hash_find (po_hash, s + 1);
+
+ /* In MRI mode, we may need to insert an
+ automatic alignment directive. What a hack
+ this is. */
+ if (mri_pending_align
+ && (pop == NULL
+ || ! ((pop->poc_handler == cons
+ && pop->poc_val == 1)
+ || (pop->poc_handler == s_space
+ && pop->poc_val == 1)
+#ifdef tc_conditional_pseudoop
+ || tc_conditional_pseudoop (pop)
+#endif
+ || pop->poc_handler == s_if
+ || pop->poc_handler == s_ifdef
+ || pop->poc_handler == s_ifc
+ || pop->poc_handler == s_ifeqs
+ || pop->poc_handler == s_else
+ || pop->poc_handler == s_endif
+ || pop->poc_handler == s_globl
+ || pop->poc_handler == s_ignore)))
+ {
+ do_align (1, (char *) NULL, 0, 0);
+ mri_pending_align = 0;
+ if (line_label != NULL)
+ {
+ line_label->sy_frag = frag_now;
+ S_SET_VALUE (line_label, frag_now_fix ());
+ }
+ }
+
+ /* Print the error msg now, while we still can */
+ if (pop == NULL)
+ {
+ as_bad (_("Unknown pseudo-op: `%s'"), s);
+ *input_line_pointer = c;
+ s_ignore (0);
+ continue;
+ }
+
+ /* Put it back for error messages etc. */
+ *input_line_pointer = c;
+ /* The following skip of whitespace is compulsory.
+ A well shaped space is sometimes all that separates
+ keyword from operands. */
+ if (c == ' ' || c == '\t')
+ input_line_pointer++;
+ /*
+ * Input_line is restored.
+ * Input_line_pointer->1st non-blank char
+ * after pseudo-operation.
+ */
+ (*pop->poc_handler) (pop->poc_val);
+
+ /* If that was .end, just get out now. */
+ if (pop->poc_handler == s_end)
+ goto quit;
+ }
+ else
+ {
+ int inquote = 0;
+
+ /* WARNING: c has char, which may be end-of-line. */
+ /* Also: input_line_pointer->`\0` where c was. */
+ *input_line_pointer = c;
+ while (!is_end_of_line[(unsigned char) *input_line_pointer]
+ || inquote
+#ifdef TC_EOL_IN_INSN
+ || TC_EOL_IN_INSN (input_line_pointer)
+#endif
+ )
+ {
+ if (flag_m68k_mri && *input_line_pointer == '\'')
+ inquote = ! inquote;
+ input_line_pointer++;
+ }
+
+ c = *input_line_pointer;
+ *input_line_pointer = '\0';
+
+ generate_lineno_debug ();
+
+ if (macro_defined)
+ {
+ sb out;
+ const char *err;
+
+ if (check_macro (s, &out, '\0', &err))
+ {
+ if (err != NULL)
+ as_bad (err);
+ *input_line_pointer++ = c;
+ input_scrub_include_sb (&out,
+ input_line_pointer);
+ sb_kill (&out);
+ buffer_limit =
+ input_scrub_next_buffer (&input_line_pointer);
+ continue;
+ }
+ }
+
+ if (mri_pending_align)
+ {
+ do_align (1, (char *) NULL, 0, 0);
+ mri_pending_align = 0;
+ if (line_label != NULL)
+ {
+ line_label->sy_frag = frag_now;
+ S_SET_VALUE (line_label, frag_now_fix ());
+ }
+ }
+
+ md_assemble (s); /* Assemble 1 instruction. */
+
+ *input_line_pointer++ = c;
+
+ /* We resume loop AFTER the end-of-line from
+ this instruction. */
+ } /* if (*s=='.') */
+ } /* if c==':' */
+ continue;
+ } /* if (is_name_beginner(c) */
+
+
+ /* Empty statement? */
+ if (is_end_of_line[(unsigned char) c])
+ continue;
+
+ if ((LOCAL_LABELS_DOLLAR || LOCAL_LABELS_FB)
+ && isdigit ((unsigned char) c))
+ {
+ /* local label ("4:") */
+ char *backup = input_line_pointer;
+
+ HANDLE_CONDITIONAL_ASSEMBLY ();
+
+ temp = c - '0';
+
+ while (isdigit ((unsigned char) *input_line_pointer))
+ {
+ temp = (temp * 10) + *input_line_pointer - '0';
+ ++input_line_pointer;
+ } /* read the whole number */
+
+ if (LOCAL_LABELS_DOLLAR
+ && *input_line_pointer == '$'
+ && *(input_line_pointer + 1) == ':')
+ {
+ input_line_pointer += 2;
+
+ if (dollar_label_defined (temp))
+ {
+ as_fatal (_("label \"%d$\" redefined"), temp);
+ }
+
+ define_dollar_label (temp);
+ colon (dollar_label_name (temp, 0));
+ continue;
+ }
+
+ if (LOCAL_LABELS_FB
+ && *input_line_pointer++ == ':')
+ {
+ fb_label_instance_inc (temp);
+ colon (fb_label_name (temp, 0));
+ continue;
+ }
+
+ input_line_pointer = backup;
+ } /* local label ("4:") */
+
+ if (c && strchr (line_comment_chars, c))
+ { /* Its a comment. Better say APP or NO_APP */
+ char *ends;
+ char *new_buf;
+ char *new_tmp;
+ unsigned int new_length;
+ char *tmp_buf = 0;
+
+ bump_line_counters ();
+ s = input_line_pointer;
+ if (strncmp (s, "APP\n", 4))
+ continue; /* We ignore it */
+ s += 4;
+
+ ends = strstr (s, "#NO_APP\n");
+
+ if (!ends)
+ {
+ unsigned int tmp_len;
+ unsigned int num;
+
+ /* The end of the #APP wasn't in this buffer. We
+ keep reading in buffers until we find the #NO_APP
+ that goes with this #APP There is one. The specs
+ guarentee it. . . */
+ tmp_len = buffer_limit - s;
+ tmp_buf = xmalloc (tmp_len + 1);
+ memcpy (tmp_buf, s, tmp_len);
+ do
+ {
+ new_tmp = input_scrub_next_buffer (&buffer);
+ if (!new_tmp)
+ break;
+ else
+ buffer_limit = new_tmp;
+ input_line_pointer = buffer;
+ ends = strstr (buffer, "#NO_APP\n");
+ if (ends)
+ num = ends - buffer;
+ else
+ num = buffer_limit - buffer;
+
+ tmp_buf = xrealloc (tmp_buf, tmp_len + num);
+ memcpy (tmp_buf + tmp_len, buffer, num);
+ tmp_len += num;
+ }
+ while (!ends);
+
+ input_line_pointer = ends ? ends + 8 : NULL;
+
+ s = tmp_buf;
+ ends = s + tmp_len;
+
+ }
+ else
+ {
+ input_line_pointer = ends + 8;
+ }
+
+ scrub_string = s;
+ scrub_string_end = ends;
+
+ new_length = ends - s;
+ new_buf = (char *) xmalloc (new_length);
+ new_tmp = new_buf;
+ for (;;)
+ {
+ int space;
+ int size;
+
+ space = (new_buf + new_length) - new_tmp;
+ size = do_scrub_chars (scrub_from_string, new_tmp, space);
+
+ if (size < space)
+ {
+ new_tmp += size;
+ break;
+ }
+
+ new_buf = xrealloc (new_buf, new_length + 100);
+ new_tmp = new_buf + new_length;
+ new_length += 100;
+ }
+
+ if (tmp_buf)
+ free (tmp_buf);
+ old_buffer = buffer;
+ old_input = input_line_pointer;
+ old_limit = buffer_limit;
+ buffer = new_buf;
+ input_line_pointer = new_buf;
+ buffer_limit = new_tmp;
+ continue;
+ }
+
+ HANDLE_CONDITIONAL_ASSEMBLY ();
+
+#ifdef tc_unrecognized_line
+ if (tc_unrecognized_line (c))
+ continue;
+#endif
+
+ /* as_warn("Junk character %d.",c); Now done by ignore_rest */
+ input_line_pointer--; /* Report unknown char as ignored. */
+ ignore_rest_of_line ();
+ } /* while (input_line_pointer<buffer_limit) */
+
+#ifdef md_after_pass_hook
+ md_after_pass_hook ();
+#endif
+
+ if (old_buffer)
+ {
+ free (buffer);
+ bump_line_counters ();
+ if (old_input != 0)
+ {
+ buffer = old_buffer;
+ input_line_pointer = old_input;
+ buffer_limit = old_limit;
+ old_buffer = 0;
+ goto contin;
+ }
+ }
+ } /* while (more buffers to scan) */
+
+ quit:
+
+#ifdef md_cleanup
+ md_cleanup();
+#endif
+ input_scrub_close (); /* Close the input file */
+}
+
+/* For most MRI pseudo-ops, the line actually ends at the first
+ nonquoted space. This function looks for that point, stuffs a null
+ in, and sets *STOPCP to the character that used to be there, and
+ returns the location.
+
+ Until I hear otherwise, I am going to assume that this is only true
+ for the m68k MRI assembler. */
+
+char *
+mri_comment_field (stopcp)
+ char *stopcp;
+{
+#ifdef TC_M68K
+
+ char *s;
+ int inquote = 0;
+
+ know (flag_m68k_mri);
+
+ for (s = input_line_pointer;
+ ((! is_end_of_line[(unsigned char) *s] && *s != ' ' && *s != '\t')
+ || inquote);
+ s++)
+ {
+ if (*s == '\'')
+ inquote = ! inquote;
+ }
+ *stopcp = *s;
+ *s = '\0';
+ return s;
+
+#else
+
+ char *s;
+
+ for (s = input_line_pointer; ! is_end_of_line[(unsigned char) *s]; s++)
+ ;
+ *stopcp = *s;
+ *s = '\0';
+ return s;
+
+#endif
+
+}
+
+/* Skip to the end of an MRI comment field. */
+
+void
+mri_comment_end (stop, stopc)
+ char *stop;
+ int stopc;
+{
+ know (flag_mri);
+
+ input_line_pointer = stop;
+ *stop = stopc;
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+}
+
+void
+s_abort (ignore)
+ int ignore;
+{
+ as_fatal (_(".abort detected. Abandoning ship."));
+}
+
+/* Guts of .align directive. N is the power of two to which to align.
+ FILL may be NULL, or it may point to the bytes of the fill pattern.
+ LEN is the length of whatever FILL points to, if anything. MAX is
+ the maximum number of characters to skip when doing the alignment,
+ or 0 if there is no maximum. */
+
+static void
+do_align (n, fill, len, max)
+ int n;
+ char *fill;
+ int len;
+ int max;
+{
+ char default_fill;
+
+#ifdef md_do_align
+ md_do_align (n, fill, len, max, just_record_alignment);
+#endif
+
+ if (fill == NULL)
+ {
+ int maybe_text;
+
+#ifdef BFD_ASSEMBLER
+ if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
+ maybe_text = 1;
+ else
+ maybe_text = 0;
+#else
+ if (now_seg != data_section && now_seg != bss_section)
+ maybe_text = 1;
+ else
+ maybe_text = 0;
+#endif
+
+ if (maybe_text)
+ default_fill = NOP_OPCODE;
+ else
+ default_fill = 0;
+ fill = &default_fill;
+ len = 1;
+ }
+
+ /* Only make a frag if we HAVE to. . . */
+ if (n != 0 && !need_pass_2)
+ {
+ if (len <= 1)
+ frag_align (n, *fill, max);
+ else
+ frag_align_pattern (n, fill, len, max);
+ }
+
+#ifdef md_do_align
+ just_record_alignment:
+#endif
+
+ record_alignment (now_seg, n);
+}
+
+/* Handle the .align pseudo-op. A positive ARG is a default alignment
+ (in bytes). A negative ARG is the negative of the length of the
+ fill pattern. BYTES_P is non-zero if the alignment value should be
+ interpreted as the byte boundary, rather than the power of 2. */
+
+static void
+s_align (arg, bytes_p)
+ int arg;
+ int bytes_p;
+{
+ register unsigned int align;
+ char *stop = NULL;
+ char stopc;
+ offsetT fill = 0;
+ int max;
+ int fill_p;
+
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
+
+ if (is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ if (arg < 0)
+ align = 0;
+ else
+ align = arg; /* Default value from pseudo-op table */
+ }
+ else
+ {
+ align = get_absolute_expression ();
+ SKIP_WHITESPACE ();
+ }
+
+ if (bytes_p)
+ {
+ /* Convert to a power of 2. */
+ if (align != 0)
+ {
+ unsigned int i;
+
+ for (i = 0; (align & 1) == 0; align >>= 1, ++i)
+ ;
+ if (align != 1)
+ as_bad (_("Alignment not a power of 2"));
+ align = i;
+ }
+ }
+
+ if (align > 15)
+ {
+ align = 15;
+ as_bad (_("Alignment too large: %u assumed"), align);
+ }
+
+ if (*input_line_pointer != ',')
+ {
+ fill_p = 0;
+ max = 0;
+ }
+ else
+ {
+ ++input_line_pointer;
+ if (*input_line_pointer == ',')
+ fill_p = 0;
+ else
+ {
+ fill = get_absolute_expression ();
+ SKIP_WHITESPACE ();
+ fill_p = 1;
+ }
+
+ if (*input_line_pointer != ',')
+ max = 0;
+ else
+ {
+ ++input_line_pointer;
+ max = get_absolute_expression ();
+ }
+ }
+
+ if (! fill_p)
+ {
+ if (arg < 0)
+ as_warn (_("expected fill pattern missing"));
+ do_align (align, (char *) NULL, 0, max);
+ }
+ else
+ {
+ int fill_len;
+
+ if (arg >= 0)
+ fill_len = 1;
+ else
+ fill_len = - arg;
+ if (fill_len <= 1)
+ {
+ char fill_char;
+
+ fill_char = fill;
+ do_align (align, &fill_char, fill_len, max);
+ }
+ else
+ {
+ char ab[16];
+
+ if ((size_t) fill_len > sizeof ab)
+ abort ();
+ md_number_to_chars (ab, fill, fill_len);
+ do_align (align, ab, fill_len, max);
+ }
+ }
+
+ demand_empty_rest_of_line ();
+
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+}
+
+/* Handle the .align pseudo-op on machines where ".align 4" means
+ align to a 4 byte boundary. */
+
+void
+s_align_bytes (arg)
+ int arg;
+{
+ s_align (arg, 1);
+}
+
+/* Handle the .align pseudo-op on machines where ".align 4" means align
+ to a 2**4 boundary. */
+
+void
+s_align_ptwo (arg)
+ int arg;
+{
+ s_align (arg, 0);
+}
+
+void
+s_comm (ignore)
+ int ignore;
+{
+ register char *name;
+ register char c;
+ register char *p;
+ offsetT temp;
+ register symbolS *symbolP;
+ char *stop = NULL;
+ char stopc;
+
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ /* just after name is now '\0' */
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("Expected comma after symbol-name: rest of line ignored."));
+ ignore_rest_of_line ();
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+ return;
+ }
+ input_line_pointer++; /* skip ',' */
+ if ((temp = get_absolute_expression ()) < 0)
+ {
+ as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) temp);
+ ignore_rest_of_line ();
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+ return;
+ }
+ *p = 0;
+ symbolP = symbol_find_or_make (name);
+ *p = c;
+ if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
+ {
+ as_bad (_("Ignoring attempt to re-define symbol `%s'."),
+ S_GET_NAME (symbolP));
+ ignore_rest_of_line ();
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+ return;
+ }
+ if (S_GET_VALUE (symbolP))
+ {
+ if (S_GET_VALUE (symbolP) != (valueT) temp)
+ as_bad (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."),
+ S_GET_NAME (symbolP),
+ (long) S_GET_VALUE (symbolP),
+ (long) temp);
+ }
+ else
+ {
+ S_SET_VALUE (symbolP, (valueT) temp);
+ S_SET_EXTERNAL (symbolP);
+ }
+#ifdef OBJ_VMS
+ {
+ extern int flag_one;
+ if ( (!temp) || !flag_one)
+ S_GET_OTHER(symbolP) = const_flag;
+ }
+#endif /* not OBJ_VMS */
+ know (symbolP->sy_frag == &zero_address_frag);
+
+ demand_empty_rest_of_line ();
+
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+} /* s_comm() */
+
+/* The MRI COMMON pseudo-op. We handle this by creating a common
+ symbol with the appropriate name. We make s_space do the right
+ thing by increasing the size. */
+
+void
+s_mri_common (small)
+ int small;
+{
+ char *name;
+ char c;
+ char *alc = NULL;
+ symbolS *sym;
+ offsetT align;
+ char *stop = NULL;
+ char stopc;
+
+ if (! flag_mri)
+ {
+ s_comm (0);
+ return;
+ }
+
+ stop = mri_comment_field (&stopc);
+
+ SKIP_WHITESPACE ();
+
+ name = input_line_pointer;
+ if (! isdigit ((unsigned char) *name))
+ c = get_symbol_end ();
+ else
+ {
+ do
+ {
+ ++input_line_pointer;
+ }
+ while (isdigit ((unsigned char) *input_line_pointer));
+ c = *input_line_pointer;
+ *input_line_pointer = '\0';
+
+ if (line_label != NULL)
+ {
+ alc = (char *) xmalloc (strlen (S_GET_NAME (line_label))
+ + (input_line_pointer - name)
+ + 1);
+ sprintf (alc, "%s%s", name, S_GET_NAME (line_label));
+ name = alc;
+ }
+ }
+
+ sym = symbol_find_or_make (name);
+ *input_line_pointer = c;
+ if (alc != NULL)
+ free (alc);
+
+ if (*input_line_pointer != ',')
+ align = 0;
+ else
+ {
+ ++input_line_pointer;
+ align = get_absolute_expression ();
+ }
+
+ if (S_IS_DEFINED (sym) && ! S_IS_COMMON (sym))
+ {
+ as_bad (_("attempt to re-define symbol `%s'"), S_GET_NAME (sym));
+ ignore_rest_of_line ();
+ mri_comment_end (stop, stopc);
+ return;
+ }
+
+ S_SET_EXTERNAL (sym);
+ mri_common_symbol = sym;
+
+#ifdef S_SET_ALIGN
+ if (align != 0)
+ S_SET_ALIGN (sym, align);
+#endif
+
+ if (line_label != NULL)
+ {
+ line_label->sy_value.X_op = O_symbol;
+ line_label->sy_value.X_add_symbol = sym;
+ line_label->sy_value.X_add_number = S_GET_VALUE (sym);
+ line_label->sy_frag = &zero_address_frag;
+ S_SET_SEGMENT (line_label, expr_section);
+ }
+
+ /* FIXME: We just ignore the small argument, which distinguishes
+ COMMON and COMMON.S. I don't know what we can do about it. */
+
+ /* Ignore the type and hptype. */
+ if (*input_line_pointer == ',')
+ input_line_pointer += 2;
+ if (*input_line_pointer == ',')
+ input_line_pointer += 2;
+
+ demand_empty_rest_of_line ();
+
+ mri_comment_end (stop, stopc);
+}
+
+void
+s_data (ignore)
+ int ignore;
+{
+ segT section;
+ register int temp;
+
+ temp = get_absolute_expression ();
+ if (flag_readonly_data_in_text)
+ {
+ section = text_section;
+ temp += 1000;
+ }
+ else
+ section = data_section;
+
+ subseg_set (section, (subsegT) temp);
+
+#ifdef OBJ_VMS
+ const_flag = 0;
+#endif
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the .appfile pseudo-op. This is automatically generated by
+ do_scrub_chars when a preprocessor # line comment is seen with a
+ file name. This default definition may be overridden by the object
+ or CPU specific pseudo-ops. This function is also the default
+ definition for .file; the APPFILE argument is 1 for .appfile, 0 for
+ .file. */
+
+void
+s_app_file (appfile)
+ int appfile;
+{
+ register char *s;
+ int length;
+
+ /* Some assemblers tolerate immediately following '"' */
+ if ((s = demand_copy_string (&length)) != 0)
+ {
+ /* If this is a fake .appfile, a fake newline was inserted into
+ the buffer. Passing -2 to new_logical_line tells it to
+ account for it. */
+ int may_omit
+ = (! new_logical_line (s, appfile ? -2 : -1) && appfile);
+
+ /* In MRI mode, the preprocessor may have inserted an extraneous
+ backquote. */
+ if (flag_m68k_mri
+ && *input_line_pointer == '\''
+ && is_end_of_line[(unsigned char) input_line_pointer[1]])
+ ++input_line_pointer;
+
+ demand_empty_rest_of_line ();
+ if (! may_omit)
+ {
+#ifdef LISTING
+ if (listing)
+ listing_source_file (s);
+#endif
+ register_dependency (s);
+#ifdef obj_app_file
+ obj_app_file (s);
+#endif
+ }
+ }
+}
+
+/* Handle the .appline pseudo-op. This is automatically generated by
+ do_scrub_chars when a preprocessor # line comment is seen. This
+ default definition may be overridden by the object or CPU specific
+ pseudo-ops. */
+
+void
+s_app_line (ignore)
+ int ignore;
+{
+ int l;
+
+ /* The given number is that of the next line. */
+ l = get_absolute_expression () - 1;
+ if (l < 0)
+ /* Some of the back ends can't deal with non-positive line numbers.
+ Besides, it's silly. */
+ as_warn (_("Line numbers must be positive; line number %d rejected."), l+1);
+ else
+ {
+ new_logical_line ((char *) NULL, l);
+#ifdef LISTING
+ if (listing)
+ listing_source_line (l);
+#endif
+ }
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the .end pseudo-op. Actually, the real work is done in
+ read_a_source_file. */
+
+void
+s_end (ignore)
+ int ignore;
+{
+ if (flag_mri)
+ {
+ /* The MRI assembler permits the start symbol to follow .end,
+ but we don't support that. */
+ SKIP_WHITESPACE ();
+ if (! is_end_of_line[(unsigned char) *input_line_pointer]
+ && *input_line_pointer != '*'
+ && *input_line_pointer != '!')
+ as_warn (_("start address not supported"));
+ }
+}
+
+/* Handle the .err pseudo-op. */
+
+void
+s_err (ignore)
+ int ignore;
+{
+ as_bad (_(".err encountered"));
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the MRI fail pseudo-op. */
+
+void
+s_fail (ignore)
+ int ignore;
+{
+ offsetT temp;
+ char *stop = NULL;
+ char stopc;
+
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
+
+ temp = get_absolute_expression ();
+ if (temp >= 500)
+ as_warn (_(".fail %ld encountered"), (long) temp);
+ else
+ as_bad (_(".fail %ld encountered"), (long) temp);
+
+ demand_empty_rest_of_line ();
+
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+}
+
+void
+s_fill (ignore)
+ int ignore;
+{
+ expressionS rep_exp;
+ long size = 1;
+ register long fill = 0;
+ char *p;
+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+ get_known_segmented_expression (&rep_exp);
+ if (*input_line_pointer == ',')
+ {
+ input_line_pointer++;
+ size = get_absolute_expression ();
+ if (*input_line_pointer == ',')
+ {
+ input_line_pointer++;
+ fill = get_absolute_expression ();
+ }
+ }
+
+ /* This is to be compatible with BSD 4.2 AS, not for any rational reason. */
+#define BSD_FILL_SIZE_CROCK_8 (8)
+ if (size > BSD_FILL_SIZE_CROCK_8)
+ {
+ as_warn (_(".fill size clamped to %d."), BSD_FILL_SIZE_CROCK_8);
+ size = BSD_FILL_SIZE_CROCK_8;
+ }
+ if (size < 0)
+ {
+ as_warn (_("Size negative: .fill ignored."));
+ size = 0;
+ }
+ else if (rep_exp.X_op == O_constant && rep_exp.X_add_number <= 0)
+ {
+ if (rep_exp.X_add_number < 0)
+ as_warn (_("Repeat < 0, .fill ignored"));
+ size = 0;
+ }
+
+ if (size && !need_pass_2)
+ {
+ if (rep_exp.X_op == O_constant)
+ {
+ p = frag_var (rs_fill, (int) size, (int) size,
+ (relax_substateT) 0, (symbolS *) 0,
+ (offsetT) rep_exp.X_add_number,
+ (char *) 0);
+ }
+ else
+ {
+ /* We don't have a constant repeat count, so we can't use
+ rs_fill. We can get the same results out of rs_space,
+ but its argument is in bytes, so we must multiply the
+ repeat count by size. */
+
+ symbolS *rep_sym;
+ rep_sym = make_expr_symbol (&rep_exp);
+ if (size != 1)
+ {
+ expressionS size_exp;
+ size_exp.X_op = O_constant;
+ size_exp.X_add_number = size;
+
+ rep_exp.X_op = O_multiply;
+ rep_exp.X_add_symbol = rep_sym;
+ rep_exp.X_op_symbol = make_expr_symbol (&size_exp);
+ rep_exp.X_add_number = 0;
+ rep_sym = make_expr_symbol (&rep_exp);
+ }
+
+ p = frag_var (rs_space, (int) size, (int) size,
+ (relax_substateT) 0, rep_sym, (offsetT) 0, (char *) 0);
+ }
+ memset (p, 0, (unsigned int) size);
+ /* The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX
+ * flavoured AS. The following bizzare behaviour is to be
+ * compatible with above. I guess they tried to take up to 8
+ * bytes from a 4-byte expression and they forgot to sign
+ * extend. Un*x Sux. */
+#define BSD_FILL_SIZE_CROCK_4 (4)
+ md_number_to_chars (p, (valueT) fill,
+ (size > BSD_FILL_SIZE_CROCK_4
+ ? BSD_FILL_SIZE_CROCK_4
+ : (int) size));
+ /* Note: .fill (),0 emits no frag (since we are asked to .fill 0 bytes)
+ * but emits no error message because it seems a legal thing to do.
+ * It is a degenerate case of .fill but could be emitted by a compiler.
+ */
+ }
+ demand_empty_rest_of_line ();
+}
+
+void
+s_globl (ignore)
+ int ignore;
+{
+ char *name;
+ int c;
+ symbolS *symbolP;
+ char *stop = NULL;
+ char stopc;
+
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
+
+ do
+ {
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ symbolP = symbol_find_or_make (name);
+ *input_line_pointer = c;
+ SKIP_WHITESPACE ();
+ S_SET_EXTERNAL (symbolP);
+ if (c == ',')
+ {
+ input_line_pointer++;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '\n')
+ c = '\n';
+ }
+ }
+ while (c == ',');
+
+ demand_empty_rest_of_line ();
+
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+}
+
+/* Handle the MRI IRP and IRPC pseudo-ops. */
+
+void
+s_irp (irpc)
+ int irpc;
+{
+ char *file;
+ unsigned int line;
+ sb s;
+ const char *err;
+ sb out;
+
+ as_where (&file, &line);
+
+ sb_new (&s);
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ sb_add_char (&s, *input_line_pointer++);
+
+ sb_new (&out);
+
+ err = expand_irp (irpc, 0, &s, &out, get_line_sb, '\0');
+ if (err != NULL)
+ as_bad_where (file, line, "%s", err);
+
+ sb_kill (&s);
+
+ input_scrub_include_sb (&out, input_line_pointer);
+ sb_kill (&out);
+ buffer_limit = input_scrub_next_buffer (&input_line_pointer);
+}
+
+/* Handle the .linkonce pseudo-op. This tells the assembler to mark
+ the section to only be linked once. However, this is not supported
+ by most object file formats. This takes an optional argument,
+ which is what to do about duplicates. */
+
+void
+s_linkonce (ignore)
+ int ignore;
+{
+ enum linkonce_type type;
+
+ SKIP_WHITESPACE ();
+
+ type = LINKONCE_DISCARD;
+
+ if (! is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ char *s;
+ char c;
+
+ s = input_line_pointer;
+ c = get_symbol_end ();
+ if (strcasecmp (s, "discard") == 0)
+ type = LINKONCE_DISCARD;
+ else if (strcasecmp (s, "one_only") == 0)
+ type = LINKONCE_ONE_ONLY;
+ else if (strcasecmp (s, "same_size") == 0)
+ type = LINKONCE_SAME_SIZE;
+ else if (strcasecmp (s, "same_contents") == 0)
+ type = LINKONCE_SAME_CONTENTS;
+ else
+ as_warn (_("unrecognized .linkonce type `%s'"), s);
+
+ *input_line_pointer = c;
+ }
+
+#ifdef obj_handle_link_once
+ obj_handle_link_once (type);
+#else /* ! defined (obj_handle_link_once) */
+#ifdef BFD_ASSEMBLER
+ {
+ flagword flags;
+
+ if ((bfd_applicable_section_flags (stdoutput) & SEC_LINK_ONCE) == 0)
+ as_warn (_(".linkonce is not supported for this object file format"));
+
+ flags = bfd_get_section_flags (stdoutput, now_seg);
+ flags |= SEC_LINK_ONCE;
+ switch (type)
+ {
+ default:
+ abort ();
+ case LINKONCE_DISCARD:
+ flags |= SEC_LINK_DUPLICATES_DISCARD;
+ break;
+ case LINKONCE_ONE_ONLY:
+ flags |= SEC_LINK_DUPLICATES_ONE_ONLY;
+ break;
+ case LINKONCE_SAME_SIZE:
+ flags |= SEC_LINK_DUPLICATES_SAME_SIZE;
+ break;
+ case LINKONCE_SAME_CONTENTS:
+ flags |= SEC_LINK_DUPLICATES_SAME_CONTENTS;
+ break;
+ }
+ if (! bfd_set_section_flags (stdoutput, now_seg, flags))
+ as_bad (_("bfd_set_section_flags: %s"),
+ bfd_errmsg (bfd_get_error ()));
+ }
+#else /* ! defined (BFD_ASSEMBLER) */
+ as_warn (_(".linkonce is not supported for this object file format"));
+#endif /* ! defined (BFD_ASSEMBLER) */
+#endif /* ! defined (obj_handle_link_once) */
+
+ demand_empty_rest_of_line ();
+}
+
+static void
+s_lcomm_internal (needs_align, bytes_p)
+ /* 1 if this was a ".bss" directive, which may require a 3rd argument
+ (alignment); 0 if it was an ".lcomm" (2 args only) */
+ int needs_align;
+ /* 1 if the alignment value should be interpreted as the byte boundary,
+ rather than the power of 2. */
+ int bytes_p;
+{
+ register char *name;
+ register char c;
+ register char *p;
+ register int temp;
+ register symbolS *symbolP;
+ segT current_seg = now_seg;
+ subsegT current_subseg = now_subseg;
+ const int max_alignment = 15;
+ int align = 0;
+ segT bss_seg = bss_section;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE ();
+
+ /* Accept an optional comma after the name. The comma used to be
+ required, but Irix 5 cc does not generate it. */
+ if (*input_line_pointer == ',')
+ {
+ ++input_line_pointer;
+ SKIP_WHITESPACE ();
+ }
+
+ if (*input_line_pointer == '\n')
+ {
+ as_bad (_("Missing size expression"));
+ return;
+ }
+
+ if ((temp = get_absolute_expression ()) < 0)
+ {
+ as_warn (_("BSS length (%d.) <0! Ignored."), temp);
+ ignore_rest_of_line ();
+ return;
+ }
+
+#if defined (TC_MIPS) || defined (TC_ALPHA)
+ if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour
+ || OUTPUT_FLAVOR == bfd_target_elf_flavour)
+ {
+ /* For MIPS and Alpha ECOFF or ELF, small objects are put in .sbss. */
+ if (temp <= bfd_get_gp_size (stdoutput))
+ {
+ bss_seg = subseg_new (".sbss", 1);
+ seg_info (bss_seg)->bss = 1;
+#ifdef BFD_ASSEMBLER
+ if (! bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
+ as_warn (_("error setting flags for \".sbss\": %s"),
+ bfd_errmsg (bfd_get_error ()));
+#endif
+ }
+ }
+#endif
+ if (!needs_align)
+ {
+ /* FIXME. This needs to be machine independent. */
+ if (temp >= 8)
+ align = 3;
+ else if (temp >= 4)
+ align = 2;
+ else if (temp >= 2)
+ align = 1;
+ else
+ align = 0;
+
+#ifdef OBJ_EVAX
+ /* FIXME: This needs to be done in a more general fashion. */
+ align = 3;
+#endif
+
+ record_alignment(bss_seg, align);
+ }
+
+ if (needs_align)
+ {
+ align = 0;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("Expected comma after size"));
+ ignore_rest_of_line ();
+ return;
+ }
+ input_line_pointer++;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '\n')
+ {
+ as_bad (_("Missing alignment"));
+ return;
+ }
+ align = get_absolute_expression ();
+ if (bytes_p)
+ {
+ /* Convert to a power of 2. */
+ if (align != 0)
+ {
+ unsigned int i;
+
+ for (i = 0; (align & 1) == 0; align >>= 1, ++i)
+ ;
+ if (align != 1)
+ as_bad (_("Alignment not a power of 2"));
+ align = i;
+ }
+ }
+ if (align > max_alignment)
+ {
+ align = max_alignment;
+ as_warn (_("Alignment too large: %d. assumed."), align);
+ }
+ else if (align < 0)
+ {
+ align = 0;
+ as_warn (_("Alignment negative. 0 assumed."));
+ }
+ record_alignment (bss_seg, align);
+ } /* if needs align */
+ else
+ {
+ /* Assume some objects may require alignment on some systems. */
+#if defined (TC_ALPHA) && ! defined (VMS)
+ if (temp > 1)
+ {
+ align = ffs (temp) - 1;
+ if (temp % (1 << align))
+ abort ();
+ }
+#endif
+ }
+
+ *p = 0;
+ symbolP = symbol_find_or_make (name);
+ *p = c;
+
+ if (
+#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
+ S_GET_OTHER (symbolP) == 0 &&
+ S_GET_DESC (symbolP) == 0 &&
+#endif /* OBJ_AOUT or OBJ_BOUT */
+ (S_GET_SEGMENT (symbolP) == bss_seg
+ || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
+ {
+ char *pfrag;
+
+ subseg_set (bss_seg, 1);
+
+ if (align)
+ frag_align (align, 0, 0);
+ /* detach from old frag */
+ if (S_GET_SEGMENT (symbolP) == bss_seg)
+ symbolP->sy_frag->fr_symbol = NULL;
+
+ symbolP->sy_frag = frag_now;
+ pfrag = frag_var (rs_org, 1, 1, (relax_substateT)0, symbolP,
+ (offsetT) temp, (char *) 0);
+ *pfrag = 0;
+
+ S_SET_SEGMENT (symbolP, bss_seg);
+
+#ifdef OBJ_COFF
+ /* The symbol may already have been created with a preceding
+ ".globl" directive -- be careful not to step on storage class
+ in that case. Otherwise, set it to static. */
+ if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
+ {
+ S_SET_STORAGE_CLASS (symbolP, C_STAT);
+ }
+#endif /* OBJ_COFF */
+
+#ifdef S_SET_SIZE
+ S_SET_SIZE (symbolP, temp);
+#endif
+ }
+ else
+ as_bad (_("Ignoring attempt to re-define symbol `%s'."),
+ S_GET_NAME (symbolP));
+
+ subseg_set (current_seg, current_subseg);
+
+ demand_empty_rest_of_line ();
+} /* s_lcomm_internal() */
+
+void
+s_lcomm (needs_align)
+ int needs_align;
+{
+ s_lcomm_internal (needs_align, 0);
+}
+
+void s_lcomm_bytes (needs_align)
+ int needs_align;
+{
+ s_lcomm_internal (needs_align, 1);
+}
+
+void
+s_lsym (ignore)
+ int ignore;
+{
+ register char *name;
+ register char c;
+ register char *p;
+ expressionS exp;
+ register symbolS *symbolP;
+
+ /* we permit ANY defined expression: BSD4.2 demands constants */
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
+ {
+ *p = 0;
+ as_bad (_("Expected comma after name \"%s\""), name);
+ *p = c;
+ ignore_rest_of_line ();
+ return;
+ }
+ input_line_pointer++;
+ expression (&exp);
+ if (exp.X_op != O_constant
+ && exp.X_op != O_register)
+ {
+ as_bad (_("bad expression"));
+ ignore_rest_of_line ();
+ return;
+ }
+ *p = 0;
+ symbolP = symbol_find_or_make (name);
+
+ /* FIXME-SOON I pulled a (&& symbolP->sy_other == 0 &&
+ symbolP->sy_desc == 0) out of this test because coff doesn't have
+ those fields, and I can't see when they'd ever be tripped. I
+ don't think I understand why they were here so I may have
+ introduced a bug. As recently as 1.37 didn't have this test
+ anyway. xoxorich. */
+
+ if (S_GET_SEGMENT (symbolP) == undefined_section
+ && S_GET_VALUE (symbolP) == 0)
+ {
+ /* The name might be an undefined .global symbol; be sure to
+ keep the "external" bit. */
+ S_SET_SEGMENT (symbolP,
+ (exp.X_op == O_constant
+ ? absolute_section
+ : reg_section));
+ S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
+ }
+ else
+ {
+ as_bad (_("Symbol %s already defined"), name);
+ }
+ *p = c;
+ demand_empty_rest_of_line ();
+} /* s_lsym() */
+
+/* Read a line into an sb. */
+
+static int
+get_line_sb (line)
+ sb *line;
+{
+ char quote1, quote2, inquote;
+
+ if (input_line_pointer[-1] == '\n')
+ bump_line_counters ();
+
+ if (input_line_pointer >= buffer_limit)
+ {
+ buffer_limit = input_scrub_next_buffer (&input_line_pointer);
+ if (buffer_limit == 0)
+ return 0;
+ }
+
+ /* If app.c sets any other characters to LEX_IS_STRINGQUOTE, this
+ code needs to be changed. */
+ if (! flag_m68k_mri)
+ quote1 = '"';
+ else
+ quote1 = '\0';
+
+ quote2 = '\0';
+ if (flag_m68k_mri)
+ quote2 = '\'';
+#ifdef LEX_IS_STRINGQUOTE
+ quote2 = '\'';
+#endif
+
+ inquote = '\0';
+ while (! is_end_of_line[(unsigned char) *input_line_pointer]
+ || (inquote != '\0' && *input_line_pointer != '\n'))
+ {
+ if (inquote == *input_line_pointer)
+ inquote = '\0';
+ else if (inquote == '\0')
+ {
+ if (*input_line_pointer == quote1)
+ inquote = quote1;
+ else if (*input_line_pointer == quote2)
+ inquote = quote2;
+ }
+ sb_add_char (line, *input_line_pointer++);
+ }
+ while (input_line_pointer < buffer_limit
+ && is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ if (input_line_pointer[-1] == '\n')
+ bump_line_counters ();
+ ++input_line_pointer;
+ }
+ return 1;
+}
+
+/* Define a macro. This is an interface to macro.c, which is shared
+ between gas and gasp. */
+
+void
+s_macro (ignore)
+ int ignore;
+{
+ char *file;
+ unsigned int line;
+ sb s;
+ sb label;
+ const char *err;
+ const char *name;
+
+ as_where (&file, &line);
+
+ sb_new (&s);
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ sb_add_char (&s, *input_line_pointer++);
+
+ sb_new (&label);
+ if (line_label != NULL)
+ sb_add_string (&label, S_GET_NAME (line_label));
+
+ err = define_macro (0, &s, &label, get_line_sb, &name);
+ if (err != NULL)
+ as_bad_where (file, line, "%s", err);
+ else
+ {
+ if (line_label != NULL)
+ {
+ S_SET_SEGMENT (line_label, undefined_section);
+ S_SET_VALUE (line_label, 0);
+ line_label->sy_frag = &zero_address_frag;
+ }
+
+ if (((flag_m68k_mri
+#ifdef NO_PSEUDO_DOT
+ || 1
+#endif
+ )
+ && hash_find (po_hash, name) != NULL)
+ || (! flag_m68k_mri
+ && *name == '.'
+ && hash_find (po_hash, name + 1) != NULL))
+ as_warn (_("attempt to redefine pseudo-op `%s' ignored"),
+ name);
+ }
+
+ sb_kill (&s);
+}
+
+/* Handle the .mexit pseudo-op, which immediately exits a macro
+ expansion. */
+
+void
+s_mexit (ignore)
+ int ignore;
+{
+ cond_exit_macro (macro_nest);
+ buffer_limit = input_scrub_next_buffer (&input_line_pointer);
+}
+
+/* Switch in and out of MRI mode. */
+
+void
+s_mri (ignore)
+ int ignore;
+{
+ int on, old_flag;
+
+ on = get_absolute_expression ();
+ old_flag = flag_mri;
+ if (on != 0)
+ {
+ flag_mri = 1;
+#ifdef TC_M68K
+ flag_m68k_mri = 1;
+#endif
+ macro_mri_mode (1);
+ }
+ else
+ {
+ flag_mri = 0;
+ flag_m68k_mri = 0;
+ macro_mri_mode (0);
+ }
+
+ /* Operator precedence changes in m68k MRI mode, so we need to
+ update the operator rankings. */
+ expr_set_precedence ();
+
+#ifdef MRI_MODE_CHANGE
+ if (on != old_flag)
+ MRI_MODE_CHANGE (on);
+#endif
+
+ demand_empty_rest_of_line ();
+}
+
+/* Handle changing the location counter. */
+
+static void
+do_org (segment, exp, fill)
+ segT segment;
+ expressionS *exp;
+ int fill;
+{
+ if (segment != now_seg && segment != absolute_section)
+ as_bad (_("invalid segment \"%s\"; segment \"%s\" assumed"),
+ segment_name (segment), segment_name (now_seg));
+
+ if (now_seg == absolute_section)
+ {
+ if (fill != 0)
+ as_warn (_("ignoring fill value in absolute section"));
+ if (exp->X_op != O_constant)
+ {
+ as_bad (_("only constant offsets supported in absolute section"));
+ exp->X_add_number = 0;
+ }
+ abs_section_offset = exp->X_add_number;
+ }
+ else
+ {
+ char *p;
+
+ p = frag_var (rs_org, 1, 1, (relax_substateT) 0, exp->X_add_symbol,
+ exp->X_add_number, (char *) NULL);
+ *p = fill;
+ }
+}
+
+void
+s_org (ignore)
+ int ignore;
+{
+ register segT segment;
+ expressionS exp;
+ register long temp_fill;
+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+ /* The m68k MRI assembler has a different meaning for .org. It
+ means to create an absolute section at a given address. We can't
+ support that--use a linker script instead. */
+ if (flag_m68k_mri)
+ {
+ as_bad (_("MRI style ORG pseudo-op not supported"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ /* Don't believe the documentation of BSD 4.2 AS. There is no such
+ thing as a sub-segment-relative origin. Any absolute origin is
+ given a warning, then assumed to be segment-relative. Any
+ segmented origin expression ("foo+42") had better be in the right
+ segment or the .org is ignored.
+
+ BSD 4.2 AS warns if you try to .org backwards. We cannot because
+ we never know sub-segment sizes when we are reading code. BSD
+ will crash trying to emit negative numbers of filler bytes in
+ certain .orgs. We don't crash, but see as-write for that code.
+
+ Don't make frag if need_pass_2==1. */
+ segment = get_known_segmented_expression (&exp);
+ if (*input_line_pointer == ',')
+ {
+ input_line_pointer++;
+ temp_fill = get_absolute_expression ();
+ }
+ else
+ temp_fill = 0;
+
+ if (!need_pass_2)
+ do_org (segment, &exp, temp_fill);
+
+ demand_empty_rest_of_line ();
+} /* s_org() */
+
+/* Handle parsing for the MRI SECT/SECTION pseudo-op. This should be
+ called by the obj-format routine which handles section changing
+ when in MRI mode. It will create a new section, and return it. It
+ will set *TYPE to the section type: one of 'C' (code), 'D' (data),
+ 'M' (mixed), or 'R' (romable). If BFD_ASSEMBLER is defined, the
+ flags will be set in the section. */
+
+void
+s_mri_sect (type)
+ char *type;
+{
+#ifdef TC_M68K
+
+ char *name;
+ char c;
+ segT seg;
+
+ SKIP_WHITESPACE ();
+
+ name = input_line_pointer;
+ if (! isdigit ((unsigned char) *name))
+ c = get_symbol_end ();
+ else
+ {
+ do
+ {
+ ++input_line_pointer;
+ }
+ while (isdigit ((unsigned char) *input_line_pointer));
+ c = *input_line_pointer;
+ *input_line_pointer = '\0';
+ }
+
+ name = xstrdup (name);
+
+ *input_line_pointer = c;
+
+ seg = subseg_new (name, 0);
+
+ if (*input_line_pointer == ',')
+ {
+ int align;
+
+ ++input_line_pointer;
+ align = get_absolute_expression ();
+ record_alignment (seg, align);
+ }
+
+ *type = 'C';
+ if (*input_line_pointer == ',')
+ {
+ c = *++input_line_pointer;
+ c = toupper ((unsigned char) c);
+ if (c == 'C' || c == 'D' || c == 'M' || c == 'R')
+ *type = c;
+ else
+ as_bad (_("unrecognized section type"));
+ ++input_line_pointer;
+
+#ifdef BFD_ASSEMBLER
+ {
+ flagword flags;
+
+ flags = SEC_NO_FLAGS;
+ if (*type == 'C')
+ flags = SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE;
+ else if (*type == 'D' || *type == 'M')
+ flags = SEC_ALLOC | SEC_LOAD | SEC_DATA;
+ else if (*type == 'R')
+ flags = SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_READONLY | SEC_ROM;
+ if (flags != SEC_NO_FLAGS)
+ {
+ if (! bfd_set_section_flags (stdoutput, seg, flags))
+ as_warn (_("error setting flags for \"%s\": %s"),
+ bfd_section_name (stdoutput, seg),
+ bfd_errmsg (bfd_get_error ()));
+ }
+ }
+#endif
+ }
+
+ /* Ignore the HP type. */
+ if (*input_line_pointer == ',')
+ input_line_pointer += 2;
+
+ demand_empty_rest_of_line ();
+
+#else /* ! TC_M68K */
+#ifdef TC_I960
+
+ char *name;
+ char c;
+ segT seg;
+
+ SKIP_WHITESPACE ();
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+
+ name = xstrdup (name);
+
+ *input_line_pointer = c;
+
+ seg = subseg_new (name, 0);
+
+ if (*input_line_pointer != ',')
+ *type = 'C';
+ else
+ {
+ char *sectype;
+
+ ++input_line_pointer;
+ SKIP_WHITESPACE ();
+ sectype = input_line_pointer;
+ c = get_symbol_end ();
+ if (*sectype == '\0')
+ *type = 'C';
+ else if (strcasecmp (sectype, "text") == 0)
+ *type = 'C';
+ else if (strcasecmp (sectype, "data") == 0)
+ *type = 'D';
+ else if (strcasecmp (sectype, "romdata") == 0)
+ *type = 'R';
+ else
+ as_warn (_("unrecognized section type `%s'"), sectype);
+ *input_line_pointer = c;
+ }
+
+ if (*input_line_pointer == ',')
+ {
+ char *seccmd;
+
+ ++input_line_pointer;
+ SKIP_WHITESPACE ();
+ seccmd = input_line_pointer;
+ c = get_symbol_end ();
+ if (strcasecmp (seccmd, "absolute") == 0)
+ {
+ as_bad (_("absolute sections are not supported"));
+ *input_line_pointer = c;
+ ignore_rest_of_line ();
+ return;
+ }
+ else if (strcasecmp (seccmd, "align") == 0)
+ {
+ int align;
+
+ *input_line_pointer = c;
+ align = get_absolute_expression ();
+ record_alignment (seg, align);
+ }
+ else
+ {
+ as_warn (_("unrecognized section command `%s'"), seccmd);
+ *input_line_pointer = c;
+ }
+ }
+
+ demand_empty_rest_of_line ();
+
+#else /* ! TC_I960 */
+ /* The MRI assembler seems to use different forms of .sect for
+ different targets. */
+ as_bad ("MRI mode not supported for this target");
+ ignore_rest_of_line ();
+#endif /* ! TC_I960 */
+#endif /* ! TC_M68K */
+}
+
+/* Handle the .print pseudo-op. */
+
+void
+s_print (ignore)
+ int ignore;
+{
+ char *s;
+ int len;
+
+ s = demand_copy_C_string (&len);
+ printf ("%s\n", s);
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the .purgem pseudo-op. */
+
+void
+s_purgem (ignore)
+ int ignore;
+{
+ if (is_it_end_of_statement ())
+ {
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ do
+ {
+ char *name;
+ char c;
+
+ SKIP_WHITESPACE ();
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ delete_macro (name);
+ *input_line_pointer = c;
+ SKIP_WHITESPACE ();
+ }
+ while (*input_line_pointer++ == ',');
+
+ --input_line_pointer;
+ demand_empty_rest_of_line ();
+}
+
+/* Handle the .rept pseudo-op. */
+
+void
+s_rept (ignore)
+ int ignore;
+{
+ int count;
+ sb one;
+ sb many;
+
+ count = get_absolute_expression ();
+
+ sb_new (&one);
+ if (! buffer_and_nest ("REPT", "ENDR", &one, get_line_sb))
+ {
+ as_bad (_("rept without endr"));
+ return;
+ }
+
+ sb_new (&many);
+ while (count-- > 0)
+ sb_add_sb (&many, &one);
+
+ sb_kill (&one);
+
+ input_scrub_include_sb (&many, input_line_pointer);
+ sb_kill (&many);
+ buffer_limit = input_scrub_next_buffer (&input_line_pointer);
+}
+
+/* Handle the .equ, .equiv and .set directives. If EQUIV is 1, then
+ this is .equiv, and it is an error if the symbol is already
+ defined. */
+
+void
+s_set (equiv)
+ int equiv;
+{
+ register char *name;
+ register char delim;
+ register char *end_name;
+ register symbolS *symbolP;
+
+ /*
+ * Especial apologies for the random logic:
+ * this just grew, and could be parsed much more simply!
+ * Dean in haste.
+ */
+ name = input_line_pointer;
+ delim = get_symbol_end ();
+ end_name = input_line_pointer;
+ *end_name = delim;
+ SKIP_WHITESPACE ();
+
+ if (*input_line_pointer != ',')
+ {
+ *end_name = 0;
+ as_bad (_("Expected comma after name \"%s\""), name);
+ *end_name = delim;
+ ignore_rest_of_line ();
+ return;
+ }
+
+ input_line_pointer++;
+ *end_name = 0;
+
+ if (name[0] == '.' && name[1] == '\0')
+ {
+ /* Turn '. = mumble' into a .org mumble */
+ register segT segment;
+ expressionS exp;
+
+ segment = get_known_segmented_expression (&exp);
+
+ if (!need_pass_2)
+ do_org (segment, &exp, 0);
+
+ *end_name = delim;
+ return;
+ }
+
+ if ((symbolP = symbol_find (name)) == NULL
+ && (symbolP = md_undefined_symbol (name)) == NULL)
+ {
+#ifndef NO_LISTING
+ /* When doing symbol listings, play games with dummy fragments living
+ outside the normal fragment chain to record the file and line info
+ for this symbol. */
+ if (listing & LISTING_SYMBOLS)
+ {
+ extern struct list_info_struct *listing_tail;
+ fragS *dummy_frag = (fragS *) xmalloc (sizeof(fragS));
+ memset (dummy_frag, 0, sizeof(fragS));
+ dummy_frag->fr_type = rs_fill;
+ dummy_frag->line = listing_tail;
+ symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
+ dummy_frag->fr_symbol = symbolP;
+ }
+ else
+#endif
+ symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
+
+#ifdef OBJ_COFF
+ /* "set" symbols are local unless otherwise specified. */
+ SF_SET_LOCAL (symbolP);
+#endif /* OBJ_COFF */
+
+ } /* make a new symbol */
+
+ symbol_table_insert (symbolP);
+
+ *end_name = delim;
+
+ if (equiv
+ && S_IS_DEFINED (symbolP)
+ && S_GET_SEGMENT (symbolP) != reg_section)
+ as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
+
+ pseudo_set (symbolP);
+ demand_empty_rest_of_line ();
+} /* s_set() */
+
+void
+s_space (mult)
+ int mult;
+{
+ expressionS exp;
+ expressionS val;
+ char *p = 0;
+ char *stop = NULL;
+ char stopc;
+ int bytes;
+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
+
+ /* In m68k MRI mode, we need to align to a word boundary, unless
+ this is ds.b. */
+ if (flag_m68k_mri && mult > 1)
+ {
+ if (now_seg == absolute_section)
+ {
+ abs_section_offset += abs_section_offset & 1;
+ if (line_label != NULL)
+ S_SET_VALUE (line_label, abs_section_offset);
+ }
+ else if (mri_common_symbol != NULL)
+ {
+ valueT val;
+
+ val = S_GET_VALUE (mri_common_symbol);
+ if ((val & 1) != 0)
+ {
+ S_SET_VALUE (mri_common_symbol, val + 1);
+ if (line_label != NULL)
+ {
+ know (line_label->sy_value.X_op == O_symbol);
+ know (line_label->sy_value.X_add_symbol == mri_common_symbol);
+ line_label->sy_value.X_add_number += 1;
+ }
+ }
+ }
+ else
+ {
+ do_align (1, (char *) NULL, 0, 0);
+ if (line_label != NULL)
+ {
+ line_label->sy_frag = frag_now;
+ S_SET_VALUE (line_label, frag_now_fix ());
+ }
+ }
+ }
+
+ bytes = mult;
+
+ expression (&exp);
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == ',')
+ {
+ ++input_line_pointer;
+ expression (&val);
+ }
+ else
+ {
+ val.X_op = O_constant;
+ val.X_add_number = 0;
+ }
+
+ if (val.X_op != O_constant
+ || val.X_add_number < - 0x80
+ || val.X_add_number > 0xff
+ || (mult != 0 && mult != 1 && val.X_add_number != 0))
+ {
+ if (exp.X_op != O_constant)
+ as_bad (_("Unsupported variable size or fill value"));
+ else
+ {
+ offsetT i;
+
+ if (mult == 0)
+ mult = 1;
+ bytes = mult * exp.X_add_number;
+ for (i = 0; i < exp.X_add_number; i++)
+ emit_expr (&val, mult);
+ }
+ }
+ else
+ {
+ if (exp.X_op == O_constant)
+ {
+ long repeat;
+
+ repeat = exp.X_add_number;
+ if (mult)
+ repeat *= mult;
+ bytes = repeat;
+ if (repeat <= 0)
+ {
+ if (! flag_mri)
+ as_warn (_(".space repeat count is zero, ignored"));
+ else if (repeat < 0)
+ as_warn (_(".space repeat count is negative, ignored"));
+ goto getout;
+ }
+
+ /* If we are in the absolute section, just bump the offset. */
+ if (now_seg == absolute_section)
+ {
+ abs_section_offset += repeat;
+ goto getout;
+ }
+
+ /* If we are secretly in an MRI common section, then
+ creating space just increases the size of the common
+ symbol. */
+ if (mri_common_symbol != NULL)
+ {
+ S_SET_VALUE (mri_common_symbol,
+ S_GET_VALUE (mri_common_symbol) + repeat);
+ goto getout;
+ }
+
+ if (!need_pass_2)
+ p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0,
+ (offsetT) repeat, (char *) 0);
+ }
+ else
+ {
+ if (now_seg == absolute_section)
+ {
+ as_bad (_("space allocation too complex in absolute section"));
+ subseg_set (text_section, 0);
+ }
+ if (mri_common_symbol != NULL)
+ {
+ as_bad (_("space allocation too complex in common section"));
+ mri_common_symbol = NULL;
+ }
+ if (!need_pass_2)
+ p = frag_var (rs_space, 1, 1, (relax_substateT) 0,
+ make_expr_symbol (&exp), (offsetT) 0, (char *) 0);
+ }
+
+ if (p)
+ *p = val.X_add_number;
+ }
+
+ getout:
+
+ /* In MRI mode, after an odd number of bytes, we must align to an
+ even word boundary, unless the next instruction is a dc.b, ds.b
+ or dcb.b. */
+ if (flag_mri && (bytes & 1) != 0)
+ mri_pending_align = 1;
+
+ demand_empty_rest_of_line ();
+
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+}
+
+/* This is like s_space, but the value is a floating point number with
+ the given precision. This is for the MRI dcb.s pseudo-op and
+ friends. */
+
+void
+s_float_space (float_type)
+ int float_type;
+{
+ offsetT count;
+ int flen;
+ char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
+ char *stop = NULL;
+ char stopc;
+
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
+
+ count = get_absolute_expression ();
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("missing value"));
+ ignore_rest_of_line ();
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+ return;
+ }
+
+ ++input_line_pointer;
+
+ SKIP_WHITESPACE ();
+
+ /* Skip any 0{letter} that may be present. Don't even check if the
+ * letter is legal. */
+ if (input_line_pointer[0] == '0'
+ && isalpha ((unsigned char) input_line_pointer[1]))
+ input_line_pointer += 2;
+
+ /* Accept :xxxx, where the x's are hex digits, for a floating point
+ with the exact digits specified. */
+ if (input_line_pointer[0] == ':')
+ {
+ flen = hex_float (float_type, temp);
+ if (flen < 0)
+ {
+ ignore_rest_of_line ();
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+ return;
+ }
+ }
+ else
+ {
+ char *err;
+
+ err = md_atof (float_type, temp, &flen);
+ know (flen <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
+ know (flen > 0);
+ if (err)
+ {
+ as_bad (_("Bad floating literal: %s"), err);
+ ignore_rest_of_line ();
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+ return;
+ }
+ }
+
+ while (--count >= 0)
+ {
+ char *p;
+
+ p = frag_more (flen);
+ memcpy (p, temp, (unsigned int) flen);
+ }
+
+ demand_empty_rest_of_line ();
+
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+}
+
+/* Handle the .struct pseudo-op, as found in MIPS assemblers. */
+
+void
+s_struct (ignore)
+ int ignore;
+{
+ char *stop = NULL;
+ char stopc;
+
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
+ abs_section_offset = get_absolute_expression ();
+ subseg_set (absolute_section, 0);
+ demand_empty_rest_of_line ();
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+}
+
+void
+s_text (ignore)
+ int ignore;
+{
+ register int temp;
+
+ temp = get_absolute_expression ();
+ subseg_set (text_section, (subsegT) temp);
+ demand_empty_rest_of_line ();
+#ifdef OBJ_VMS
+ const_flag &= ~IN_DEFAULT_SECTION;
+#endif
+} /* s_text() */
+
+
+void
+demand_empty_rest_of_line ()
+{
+ SKIP_WHITESPACE ();
+ if (is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ input_line_pointer++;
+ }
+ else
+ {
+ ignore_rest_of_line ();
+ }
+ /* Return having already swallowed end-of-line. */
+} /* Return pointing just after end-of-line. */
+
+void
+ignore_rest_of_line () /* For suspect lines: gives warning. */
+{
+ if (!is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ if (isprint ((unsigned char) *input_line_pointer))
+ as_bad (_("Rest of line ignored. First ignored character is `%c'."),
+ *input_line_pointer);
+ else
+ as_bad (_("Rest of line ignored. First ignored character valued 0x%x."),
+ *input_line_pointer);
+ while (input_line_pointer < buffer_limit
+ && !is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ input_line_pointer++;
+ }
+ }
+ input_line_pointer++; /* Return pointing just after end-of-line. */
+ know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
+}
+
+void
+discard_rest_of_line ()
+{
+ while (input_line_pointer < buffer_limit
+ && !is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ input_line_pointer++;
+ }
+ input_line_pointer++; /* Return pointing just after end-of-line. */
+ know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
+}
+
+/*
+ * pseudo_set()
+ *
+ * In: Pointer to a symbol.
+ * Input_line_pointer->expression.
+ *
+ * Out: Input_line_pointer->just after any whitespace after expression.
+ * Tried to set symbol to value of expression.
+ * Will change symbols type, value, and frag;
+ */
+void
+pseudo_set (symbolP)
+ symbolS *symbolP;
+{
+ expressionS exp;
+#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
+ int ext;
+#endif /* OBJ_AOUT or OBJ_BOUT */
+
+ know (symbolP); /* NULL pointer is logic error. */
+#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
+ ext = S_IS_EXTERNAL (symbolP);
+#endif /* OBJ_AOUT or OBJ_BOUT */
+
+ (void) expression (&exp);
+
+ if (exp.X_op == O_illegal)
+ as_bad (_("illegal expression; zero assumed"));
+ else if (exp.X_op == O_absent)
+ as_bad (_("missing expression; zero assumed"));
+ else if (exp.X_op == O_big)
+ {
+ if (exp.X_add_number > 0)
+ as_bad (_("bignum invalid; zero assumed"));
+ else
+ as_bad (_("floating point number invalid; zero assumed"));
+ }
+ else if (exp.X_op == O_subtract
+ && (S_GET_SEGMENT (exp.X_add_symbol)
+ == S_GET_SEGMENT (exp.X_op_symbol))
+ && SEG_NORMAL (S_GET_SEGMENT (exp.X_add_symbol))
+ && exp.X_add_symbol->sy_frag == exp.X_op_symbol->sy_frag)
+ {
+ exp.X_op = O_constant;
+ exp.X_add_number = (S_GET_VALUE (exp.X_add_symbol)
+ - S_GET_VALUE (exp.X_op_symbol));
+ }
+
+ switch (exp.X_op)
+ {
+ case O_illegal:
+ case O_absent:
+ case O_big:
+ exp.X_add_number = 0;
+ /* Fall through. */
+ case O_constant:
+ S_SET_SEGMENT (symbolP, absolute_section);
+#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
+ if (ext)
+ S_SET_EXTERNAL (symbolP);
+ else
+ S_CLEAR_EXTERNAL (symbolP);
+#endif /* OBJ_AOUT or OBJ_BOUT */
+ S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
+ if (exp.X_op != O_constant)
+ symbolP->sy_frag = &zero_address_frag;
+ break;
+
+ case O_register:
+ S_SET_SEGMENT (symbolP, reg_section);
+ S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
+ symbolP->sy_frag = &zero_address_frag;
+ break;
+
+ case O_symbol:
+ if (S_GET_SEGMENT (exp.X_add_symbol) == undefined_section
+ || exp.X_add_number != 0)
+ symbolP->sy_value = exp;
+ else
+ {
+ symbolS *s = exp.X_add_symbol;
+
+ S_SET_SEGMENT (symbolP, S_GET_SEGMENT (s));
+#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
+ if (ext)
+ S_SET_EXTERNAL (symbolP);
+ else
+ S_CLEAR_EXTERNAL (symbolP);
+#endif /* OBJ_AOUT or OBJ_BOUT */
+ S_SET_VALUE (symbolP,
+ exp.X_add_number + S_GET_VALUE (s));
+ symbolP->sy_frag = s->sy_frag;
+ copy_symbol_attributes (symbolP, s);
+ }
+ break;
+
+ default:
+ /* The value is some complex expression.
+ FIXME: Should we set the segment to anything? */
+ symbolP->sy_value = exp;
+ break;
+ }
+}
+
+/*
+ * cons()
+ *
+ * CONStruct more frag of .bytes, or .words etc.
+ * Should need_pass_2 be 1 then emit no frag(s).
+ * This understands EXPRESSIONS.
+ *
+ * Bug (?)
+ *
+ * This has a split personality. We use expression() to read the
+ * value. We can detect if the value won't fit in a byte or word.
+ * But we can't detect if expression() discarded significant digits
+ * in the case of a long. Not worth the crocks required to fix it.
+ */
+
+/* Select a parser for cons expressions. */
+
+/* Some targets need to parse the expression in various fancy ways.
+ You can define TC_PARSE_CONS_EXPRESSION to do whatever you like
+ (for example, the HPPA does this). Otherwise, you can define
+ BITFIELD_CONS_EXPRESSIONS to permit bitfields to be specified, or
+ REPEAT_CONS_EXPRESSIONS to permit repeat counts. If none of these
+ are defined, which is the normal case, then only simple expressions
+ are permitted. */
+
+static void
+parse_mri_cons PARAMS ((expressionS *exp, unsigned int nbytes));
+
+#ifndef TC_PARSE_CONS_EXPRESSION
+#ifdef BITFIELD_CONS_EXPRESSIONS
+#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_bitfield_cons (EXP, NBYTES)
+static void
+parse_bitfield_cons PARAMS ((expressionS *exp, unsigned int nbytes));
+#endif
+#ifdef REPEAT_CONS_EXPRESSIONS
+#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_repeat_cons (EXP, NBYTES)
+static void
+parse_repeat_cons PARAMS ((expressionS *exp, unsigned int nbytes));
+#endif
+
+/* If we haven't gotten one yet, just call expression. */
+#ifndef TC_PARSE_CONS_EXPRESSION
+#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) expression (EXP)
+#endif
+#endif
+
+/* worker to do .byte etc statements */
+/* clobbers input_line_pointer, checks */
+/* end-of-line. */
+static void
+cons_worker (nbytes, rva)
+ register int nbytes; /* 1=.byte, 2=.word, 4=.long */
+ int rva;
+{
+ int c;
+ expressionS exp;
+ char *stop = NULL;
+ char stopc;
+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
+
+ if (is_it_end_of_statement ())
+ {
+ demand_empty_rest_of_line ();
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+ return;
+ }
+
+#ifdef md_cons_align
+ md_cons_align (nbytes);
+#endif
+
+ c = 0;
+ do
+ {
+ if (flag_m68k_mri)
+ parse_mri_cons (&exp, (unsigned int) nbytes);
+ else
+ TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes);
+
+ if (rva)
+ {
+ if (exp.X_op == O_symbol)
+ exp.X_op = O_symbol_rva;
+ else
+ as_fatal (_("rva without symbol"));
+ }
+ emit_expr (&exp, (unsigned int) nbytes);
+ ++c;
+ }
+ while (*input_line_pointer++ == ',');
+
+ /* In MRI mode, after an odd number of bytes, we must align to an
+ even word boundary, unless the next instruction is a dc.b, ds.b
+ or dcb.b. */
+ if (flag_mri && nbytes == 1 && (c & 1) != 0)
+ mri_pending_align = 1;
+
+ input_line_pointer--; /* Put terminator back into stream. */
+
+ demand_empty_rest_of_line ();
+
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+}
+
+
+void
+cons (size)
+ int size;
+{
+ cons_worker (size, 0);
+}
+
+void
+s_rva (size)
+ int size;
+{
+ cons_worker (size, 1);
+}
+
+/* Put the contents of expression EXP into the object file using
+ NBYTES bytes. If need_pass_2 is 1, this does nothing. */
+
+void
+emit_expr (exp, nbytes)
+ expressionS *exp;
+ unsigned int nbytes;
+{
+ operatorT op;
+ register char *p;
+ valueT extra_digit = 0;
+
+ /* Don't do anything if we are going to make another pass. */
+ if (need_pass_2)
+ return;
+
+#ifndef NO_LISTING
+#ifdef OBJ_ELF
+ /* When gcc emits DWARF 1 debugging pseudo-ops, a line number will
+ appear as a four byte positive constant in the .line section,
+ followed by a 2 byte 0xffff. Look for that case here. */
+ {
+ static int dwarf_line = -1;
+
+ if (strcmp (segment_name (now_seg), ".line") != 0)
+ dwarf_line = -1;
+ else if (dwarf_line >= 0
+ && nbytes == 2
+ && exp->X_op == O_constant
+ && (exp->X_add_number == -1 || exp->X_add_number == 0xffff))
+ listing_source_line ((unsigned int) dwarf_line);
+ else if (nbytes == 4
+ && exp->X_op == O_constant
+ && exp->X_add_number >= 0)
+ dwarf_line = exp->X_add_number;
+ else
+ dwarf_line = -1;
+ }
+
+ /* When gcc emits DWARF 1 debugging pseudo-ops, a file name will
+ appear as a 2 byte TAG_compile_unit (0x11) followed by a 2 byte
+ AT_sibling (0x12) followed by a four byte address of the sibling
+ followed by a 2 byte AT_name (0x38) followed by the name of the
+ file. We look for that case here. */
+ {
+ static int dwarf_file = 0;
+
+ if (strcmp (segment_name (now_seg), ".debug") != 0)
+ dwarf_file = 0;
+ else if (dwarf_file == 0
+ && nbytes == 2
+ && exp->X_op == O_constant
+ && exp->X_add_number == 0x11)
+ dwarf_file = 1;
+ else if (dwarf_file == 1
+ && nbytes == 2
+ && exp->X_op == O_constant
+ && exp->X_add_number == 0x12)
+ dwarf_file = 2;
+ else if (dwarf_file == 2
+ && nbytes == 4)
+ dwarf_file = 3;
+ else if (dwarf_file == 3
+ && nbytes == 2
+ && exp->X_op == O_constant
+ && exp->X_add_number == 0x38)
+ dwarf_file = 4;
+ else
+ dwarf_file = 0;
+
+ /* The variable dwarf_file_string tells stringer that the string
+ may be the name of the source file. */
+ if (dwarf_file == 4)
+ dwarf_file_string = 1;
+ else
+ dwarf_file_string = 0;
+ }
+#endif
+#endif
+
+ if (check_eh_frame (exp, &nbytes))
+ return;
+
+ op = exp->X_op;
+
+ /* Allow `.word 0' in the absolute section. */
+ if (now_seg == absolute_section)
+ {
+ if (op != O_constant || exp->X_add_number != 0)
+ as_bad (_("attempt to store value in absolute section"));
+ abs_section_offset += nbytes;
+ return;
+ }
+
+ /* Handle a negative bignum. */
+ if (op == O_uminus
+ && exp->X_add_number == 0
+ && exp->X_add_symbol->sy_value.X_op == O_big
+ && exp->X_add_symbol->sy_value.X_add_number > 0)
+ {
+ int i;
+ unsigned long carry;
+
+ exp = &exp->X_add_symbol->sy_value;
+
+ /* Negate the bignum: one's complement each digit and add 1. */
+ carry = 1;
+ for (i = 0; i < exp->X_add_number; i++)
+ {
+ unsigned long next;
+
+ next = (((~ (generic_bignum[i] & LITTLENUM_MASK))
+ & LITTLENUM_MASK)
+ + carry);
+ generic_bignum[i] = next & LITTLENUM_MASK;
+ carry = next >> LITTLENUM_NUMBER_OF_BITS;
+ }
+
+ /* We can ignore any carry out, because it will be handled by
+ extra_digit if it is needed. */
+
+ extra_digit = (valueT) -1;
+ op = O_big;
+ }
+
+ if (op == O_absent || op == O_illegal)
+ {
+ as_warn (_("zero assumed for missing expression"));
+ exp->X_add_number = 0;
+ op = O_constant;
+ }
+ else if (op == O_big && exp->X_add_number <= 0)
+ {
+ as_bad (_("floating point number invalid; zero assumed"));
+ exp->X_add_number = 0;
+ op = O_constant;
+ }
+ else if (op == O_register)
+ {
+ as_warn (_("register value used as expression"));
+ op = O_constant;
+ }
+
+ p = frag_more ((int) nbytes);
+
+#ifndef WORKING_DOT_WORD
+ /* If we have the difference of two symbols in a word, save it on
+ the broken_words list. See the code in write.c. */
+ if (op == O_subtract && nbytes == 2)
+ {
+ struct broken_word *x;
+
+ x = (struct broken_word *) xmalloc (sizeof (struct broken_word));
+ x->next_broken_word = broken_words;
+ broken_words = x;
+ x->seg = now_seg;
+ x->subseg = now_subseg;
+ x->frag = frag_now;
+ x->word_goes_here = p;
+ x->dispfrag = 0;
+ x->add = exp->X_add_symbol;
+ x->sub = exp->X_op_symbol;
+ x->addnum = exp->X_add_number;
+ x->added = 0;
+ new_broken_words++;
+ return;
+ }
+#endif
+
+ /* If we have an integer, but the number of bytes is too large to
+ pass to md_number_to_chars, handle it as a bignum. */
+ if (op == O_constant && nbytes > sizeof (valueT))
+ {
+ valueT val;
+ int gencnt;
+
+ if (! exp->X_unsigned && exp->X_add_number < 0)
+ extra_digit = (valueT) -1;
+ val = (valueT) exp->X_add_number;
+ gencnt = 0;
+ do
+ {
+ generic_bignum[gencnt] = val & LITTLENUM_MASK;
+ val >>= LITTLENUM_NUMBER_OF_BITS;
+ ++gencnt;
+ }
+ while (val != 0);
+ op = exp->X_op = O_big;
+ exp->X_add_number = gencnt;
+ }
+
+ if (op == O_constant)
+ {
+ register valueT get;
+ register valueT use;
+ register valueT mask;
+ valueT hibit;
+ register valueT unmask;
+
+ /* JF << of >= number of bits in the object is undefined. In
+ particular SPARC (Sun 4) has problems */
+ if (nbytes >= sizeof (valueT))
+ {
+ mask = 0;
+ if (nbytes > sizeof (valueT))
+ hibit = 0;
+ else
+ hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1);
+ }
+ else
+ {
+ /* Don't store these bits. */
+ mask = ~(valueT) 0 << (BITS_PER_CHAR * nbytes);
+ hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1);
+ }
+
+ unmask = ~mask; /* Do store these bits. */
+
+#ifdef NEVER
+ "Do this mod if you want every overflow check to assume SIGNED 2's complement data.";
+ mask = ~(unmask >> 1); /* Includes sign bit now. */
+#endif
+
+ get = exp->X_add_number;
+ use = get & unmask;
+ if ((get & mask) != 0
+ && ((get & mask) != mask
+ || (get & hibit) == 0))
+ { /* Leading bits contain both 0s & 1s. */
+ as_warn (_("Value 0x%lx truncated to 0x%lx."),
+ (unsigned long) get, (unsigned long) use);
+ }
+ /* put bytes in right order. */
+ md_number_to_chars (p, use, (int) nbytes);
+ }
+ else if (op == O_big)
+ {
+ unsigned int size;
+ LITTLENUM_TYPE *nums;
+
+ know (nbytes % CHARS_PER_LITTLENUM == 0);
+
+ size = exp->X_add_number * CHARS_PER_LITTLENUM;
+ if (nbytes < size)
+ {
+ as_warn (_("Bignum truncated to %d bytes"), nbytes);
+ size = nbytes;
+ }
+
+ if (target_big_endian)
+ {
+ while (nbytes > size)
+ {
+ md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM);
+ nbytes -= CHARS_PER_LITTLENUM;
+ p += CHARS_PER_LITTLENUM;
+ }
+
+ nums = generic_bignum + size / CHARS_PER_LITTLENUM;
+ while (size > 0)
+ {
+ --nums;
+ md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM);
+ size -= CHARS_PER_LITTLENUM;
+ p += CHARS_PER_LITTLENUM;
+ }
+ }
+ else
+ {
+ nums = generic_bignum;
+ while (size > 0)
+ {
+ md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM);
+ ++nums;
+ size -= CHARS_PER_LITTLENUM;
+ p += CHARS_PER_LITTLENUM;
+ nbytes -= CHARS_PER_LITTLENUM;
+ }
+
+ while (nbytes > 0)
+ {
+ md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM);
+ nbytes -= CHARS_PER_LITTLENUM;
+ p += CHARS_PER_LITTLENUM;
+ }
+ }
+ }
+ else
+ {
+ memset (p, 0, nbytes);
+
+ /* Now we need to generate a fixS to record the symbol value.
+ This is easy for BFD. For other targets it can be more
+ complex. For very complex cases (currently, the HPPA and
+ NS32K), you can define TC_CONS_FIX_NEW to do whatever you
+ want. For simpler cases, you can define TC_CONS_RELOC to be
+ the name of the reloc code that should be stored in the fixS.
+ If neither is defined, the code uses NO_RELOC if it is
+ defined, and otherwise uses 0. */
+
+#ifdef BFD_ASSEMBLER
+#ifdef TC_CONS_FIX_NEW
+ TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp);
+#else
+ {
+ bfd_reloc_code_real_type r;
+
+ switch (nbytes)
+ {
+ case 1:
+ r = BFD_RELOC_8;
+ break;
+ case 2:
+ r = BFD_RELOC_16;
+ break;
+ case 4:
+ r = BFD_RELOC_32;
+ break;
+ case 8:
+ r = BFD_RELOC_64;
+ break;
+ default:
+ as_bad (_("unsupported BFD relocation size %u"), nbytes);
+ r = BFD_RELOC_32;
+ break;
+ }
+ fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp,
+ 0, r);
+ }
+#endif
+#else
+#ifdef TC_CONS_FIX_NEW
+ TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp);
+#else
+ /* Figure out which reloc number to use. Use TC_CONS_RELOC if
+ it is defined, otherwise use NO_RELOC if it is defined,
+ otherwise use 0. */
+#ifndef TC_CONS_RELOC
+#ifdef NO_RELOC
+#define TC_CONS_RELOC NO_RELOC
+#else
+#define TC_CONS_RELOC 0
+#endif
+#endif
+ fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp, 0,
+ TC_CONS_RELOC);
+#endif /* TC_CONS_FIX_NEW */
+#endif /* BFD_ASSEMBLER */
+ }
+}
+
+#ifdef BITFIELD_CONS_EXPRESSIONS
+
+/* i960 assemblers, (eg, asm960), allow bitfields after ".byte" as
+ w:x,y:z, where w and y are bitwidths and x and y are values. They
+ then pack them all together. We do a little better in that we allow
+ them in words, longs, etc. and we'll pack them in target byte order
+ for you.
+
+ The rules are: pack least significat bit first, if a field doesn't
+ entirely fit, put it in the next unit. Overflowing the bitfield is
+ explicitly *not* even a warning. The bitwidth should be considered
+ a "mask".
+
+ To use this function the tc-XXX.h file should define
+ BITFIELD_CONS_EXPRESSIONS. */
+
+static void
+parse_bitfield_cons (exp, nbytes)
+ expressionS *exp;
+ unsigned int nbytes;
+{
+ unsigned int bits_available = BITS_PER_CHAR * nbytes;
+ char *hold = input_line_pointer;
+
+ (void) expression (exp);
+
+ if (*input_line_pointer == ':')
+ { /* bitfields */
+ long value = 0;
+
+ for (;;)
+ {
+ unsigned long width;
+
+ if (*input_line_pointer != ':')
+ {
+ input_line_pointer = hold;
+ break;
+ } /* next piece is not a bitfield */
+
+ /* In the general case, we can't allow
+ full expressions with symbol
+ differences and such. The relocation
+ entries for symbols not defined in this
+ assembly would require arbitrary field
+ widths, positions, and masks which most
+ of our current object formats don't
+ support.
+
+ In the specific case where a symbol
+ *is* defined in this assembly, we
+ *could* build fixups and track it, but
+ this could lead to confusion for the
+ backends. I'm lazy. I'll take any
+ SEG_ABSOLUTE. I think that means that
+ you can use a previous .set or
+ .equ type symbol. xoxorich. */
+
+ if (exp->X_op == O_absent)
+ {
+ as_warn (_("using a bit field width of zero"));
+ exp->X_add_number = 0;
+ exp->X_op = O_constant;
+ } /* implied zero width bitfield */
+
+ if (exp->X_op != O_constant)
+ {
+ *input_line_pointer = '\0';
+ as_bad (_("field width \"%s\" too complex for a bitfield"), hold);
+ *input_line_pointer = ':';
+ demand_empty_rest_of_line ();
+ return;
+ } /* too complex */
+
+ if ((width = exp->X_add_number) > (BITS_PER_CHAR * nbytes))
+ {
+ as_warn (_("field width %lu too big to fit in %d bytes: truncated to %d bits"),
+ width, nbytes, (BITS_PER_CHAR * nbytes));
+ width = BITS_PER_CHAR * nbytes;
+ } /* too big */
+
+ if (width > bits_available)
+ {
+ /* FIXME-SOMEDAY: backing up and reparsing is wasteful. */
+ input_line_pointer = hold;
+ exp->X_add_number = value;
+ break;
+ } /* won't fit */
+
+ hold = ++input_line_pointer; /* skip ':' */
+
+ (void) expression (exp);
+ if (exp->X_op != O_constant)
+ {
+ char cache = *input_line_pointer;
+
+ *input_line_pointer = '\0';
+ as_bad (_("field value \"%s\" too complex for a bitfield"), hold);
+ *input_line_pointer = cache;
+ demand_empty_rest_of_line ();
+ return;
+ } /* too complex */
+
+ value |= ((~(-1 << width) & exp->X_add_number)
+ << ((BITS_PER_CHAR * nbytes) - bits_available));
+
+ if ((bits_available -= width) == 0
+ || is_it_end_of_statement ()
+ || *input_line_pointer != ',')
+ {
+ break;
+ } /* all the bitfields we're gonna get */
+
+ hold = ++input_line_pointer;
+ (void) expression (exp);
+ } /* forever loop */
+
+ exp->X_add_number = value;
+ exp->X_op = O_constant;
+ exp->X_unsigned = 1;
+ } /* if looks like a bitfield */
+} /* parse_bitfield_cons() */
+
+#endif /* BITFIELD_CONS_EXPRESSIONS */
+
+/* Handle an MRI style string expression. */
+
+static void
+parse_mri_cons (exp, nbytes)
+ expressionS *exp;
+ unsigned int nbytes;
+{
+ if (*input_line_pointer != '\''
+ && (input_line_pointer[1] != '\''
+ || (*input_line_pointer != 'A'
+ && *input_line_pointer != 'E')))
+ TC_PARSE_CONS_EXPRESSION (exp, nbytes);
+ else
+ {
+ unsigned int scan;
+ unsigned int result = 0;
+
+ /* An MRI style string. Cut into as many bytes as will fit into
+ a nbyte chunk, left justify if necessary, and separate with
+ commas so we can try again later. */
+ if (*input_line_pointer == 'A')
+ ++input_line_pointer;
+ else if (*input_line_pointer == 'E')
+ {
+ as_bad (_("EBCDIC constants are not supported"));
+ ++input_line_pointer;
+ }
+
+ input_line_pointer++;
+ for (scan = 0; scan < nbytes; scan++)
+ {
+ if (*input_line_pointer == '\'')
+ {
+ if (input_line_pointer[1] == '\'')
+ {
+ input_line_pointer++;
+ }
+ else
+ break;
+ }
+ result = (result << 8) | (*input_line_pointer++);
+ }
+
+ /* Left justify */
+ while (scan < nbytes)
+ {
+ result <<= 8;
+ scan++;
+ }
+ /* Create correct expression */
+ exp->X_op = O_constant;
+ exp->X_add_number = result;
+ /* Fake it so that we can read the next char too */
+ if (input_line_pointer[0] != '\'' ||
+ (input_line_pointer[0] == '\'' && input_line_pointer[1] == '\''))
+ {
+ input_line_pointer -= 2;
+ input_line_pointer[0] = ',';
+ input_line_pointer[1] = '\'';
+ }
+ else
+ input_line_pointer++;
+ }
+}
+
+#ifdef REPEAT_CONS_EXPRESSIONS
+
+/* Parse a repeat expression for cons. This is used by the MIPS
+ assembler. The format is NUMBER:COUNT; NUMBER appears in the
+ object file COUNT times.
+
+ To use this for a target, define REPEAT_CONS_EXPRESSIONS. */
+
+static void
+parse_repeat_cons (exp, nbytes)
+ expressionS *exp;
+ unsigned int nbytes;
+{
+ expressionS count;
+ register int i;
+
+ expression (exp);
+
+ if (*input_line_pointer != ':')
+ {
+ /* No repeat count. */
+ return;
+ }
+
+ ++input_line_pointer;
+ expression (&count);
+ if (count.X_op != O_constant
+ || count.X_add_number <= 0)
+ {
+ as_warn (_("Unresolvable or nonpositive repeat count; using 1"));
+ return;
+ }
+
+ /* The cons function is going to output this expression once. So we
+ output it count - 1 times. */
+ for (i = count.X_add_number - 1; i > 0; i--)
+ emit_expr (exp, nbytes);
+}
+
+#endif /* REPEAT_CONS_EXPRESSIONS */
+
+/* Parse a floating point number represented as a hex constant. This
+ permits users to specify the exact bits they want in the floating
+ point number. */
+
+static int
+hex_float (float_type, bytes)
+ int float_type;
+ char *bytes;
+{
+ int length;
+ int i;
+
+ switch (float_type)
+ {
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ length = 4;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ length = 8;
+ break;
+
+ case 'x':
+ case 'X':
+ length = 12;
+ break;
+
+ case 'p':
+ case 'P':
+ length = 12;
+ break;
+
+ default:
+ as_bad (_("Unknown floating type type '%c'"), float_type);
+ return -1;
+ }
+
+ /* It would be nice if we could go through expression to parse the
+ hex constant, but if we get a bignum it's a pain to sort it into
+ the buffer correctly. */
+ i = 0;
+ while (hex_p (*input_line_pointer) || *input_line_pointer == '_')
+ {
+ int d;
+
+ /* The MRI assembler accepts arbitrary underscores strewn about
+ through the hex constant, so we ignore them as well. */
+ if (*input_line_pointer == '_')
+ {
+ ++input_line_pointer;
+ continue;
+ }
+
+ if (i >= length)
+ {
+ as_warn (_("Floating point constant too large"));
+ return -1;
+ }
+ d = hex_value (*input_line_pointer) << 4;
+ ++input_line_pointer;
+ while (*input_line_pointer == '_')
+ ++input_line_pointer;
+ if (hex_p (*input_line_pointer))
+ {
+ d += hex_value (*input_line_pointer);
+ ++input_line_pointer;
+ }
+ if (target_big_endian)
+ bytes[i] = d;
+ else
+ bytes[length - i - 1] = d;
+ ++i;
+ }
+
+ if (i < length)
+ {
+ if (target_big_endian)
+ memset (bytes + i, 0, length - i);
+ else
+ memset (bytes, 0, length - i);
+ }
+
+ return length;
+}
+
+/*
+ * float_cons()
+ *
+ * CONStruct some more frag chars of .floats .ffloats etc.
+ * Makes 0 or more new frags.
+ * If need_pass_2 == 1, no frags are emitted.
+ * This understands only floating literals, not expressions. Sorry.
+ *
+ * A floating constant is defined by atof_generic(), except it is preceded
+ * by 0d 0f 0g or 0h. After observing the STRANGE way my BSD AS does its
+ * reading, I decided to be incompatible. This always tries to give you
+ * rounded bits to the precision of the pseudo-op. Former AS did premature
+ * truncatation, restored noisy bits instead of trailing 0s AND gave you
+ * a choice of 2 flavours of noise according to which of 2 floating-point
+ * scanners you directed AS to use.
+ *
+ * In: input_line_pointer->whitespace before, or '0' of flonum.
+ *
+ */
+
+void
+float_cons (float_type)
+ /* Clobbers input_line-pointer, checks end-of-line. */
+ register int float_type; /* 'f':.ffloat ... 'F':.float ... */
+{
+ register char *p;
+ int length; /* Number of chars in an object. */
+ register char *err; /* Error from scanning floating literal. */
+ char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
+
+ if (is_it_end_of_statement ())
+ {
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+ do
+ {
+ /* input_line_pointer->1st char of a flonum (we hope!). */
+ SKIP_WHITESPACE ();
+
+ /* Skip any 0{letter} that may be present. Don't even check if the
+ * letter is legal. Someone may invent a "z" format and this routine
+ * has no use for such information. Lusers beware: you get
+ * diagnostics if your input is ill-conditioned.
+ */
+ if (input_line_pointer[0] == '0'
+ && isalpha ((unsigned char) input_line_pointer[1]))
+ input_line_pointer += 2;
+
+ /* Accept :xxxx, where the x's are hex digits, for a floating
+ point with the exact digits specified. */
+ if (input_line_pointer[0] == ':')
+ {
+ ++input_line_pointer;
+ length = hex_float (float_type, temp);
+ if (length < 0)
+ {
+ ignore_rest_of_line ();
+ return;
+ }
+ }
+ else
+ {
+ err = md_atof (float_type, temp, &length);
+ know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
+ know (length > 0);
+ if (err)
+ {
+ as_bad (_("Bad floating literal: %s"), err);
+ ignore_rest_of_line ();
+ return;
+ }
+ }
+
+ if (!need_pass_2)
+ {
+ int count;
+
+ count = 1;
+
+#ifdef REPEAT_CONS_EXPRESSIONS
+ if (*input_line_pointer == ':')
+ {
+ expressionS count_exp;
+
+ ++input_line_pointer;
+ expression (&count_exp);
+ if (count_exp.X_op != O_constant
+ || count_exp.X_add_number <= 0)
+ {
+ as_warn (_("unresolvable or nonpositive repeat count; using 1"));
+ }
+ else
+ count = count_exp.X_add_number;
+ }
+#endif
+
+ while (--count >= 0)
+ {
+ p = frag_more (length);
+ memcpy (p, temp, (unsigned int) length);
+ }
+ }
+ SKIP_WHITESPACE ();
+ }
+ while (*input_line_pointer++ == ',');
+
+ --input_line_pointer; /* Put terminator back into stream. */
+ demand_empty_rest_of_line ();
+} /* float_cons() */
+
+/* Return the size of a LEB128 value */
+
+static inline int
+sizeof_sleb128 (value)
+ offsetT value;
+{
+ register int size = 0;
+ register unsigned byte;
+
+ do
+ {
+ byte = (value & 0x7f);
+ /* Sadly, we cannot rely on typical arithmetic right shift behaviour.
+ Fortunately, we can structure things so that the extra work reduces
+ to a noop on systems that do things "properly". */
+ value = (value >> 7) | ~(-(offsetT)1 >> 7);
+ size += 1;
+ }
+ while (!(((value == 0) && ((byte & 0x40) == 0))
+ || ((value == -1) && ((byte & 0x40) != 0))));
+
+ return size;
+}
+
+static inline int
+sizeof_uleb128 (value)
+ valueT value;
+{
+ register int size = 0;
+ register unsigned byte;
+
+ do
+ {
+ byte = (value & 0x7f);
+ value >>= 7;
+ size += 1;
+ }
+ while (value != 0);
+
+ return size;
+}
+
+int
+sizeof_leb128 (value, sign)
+ valueT value;
+ int sign;
+{
+ if (sign)
+ return sizeof_sleb128 ((offsetT) value);
+ else
+ return sizeof_uleb128 (value);
+}
+
+/* Output a LEB128 value. */
+
+static inline int
+output_sleb128 (p, value)
+ char *p;
+ offsetT value;
+{
+ register char *orig = p;
+ register int more;
+
+ do
+ {
+ unsigned byte = (value & 0x7f);
+
+ /* Sadly, we cannot rely on typical arithmetic right shift behaviour.
+ Fortunately, we can structure things so that the extra work reduces
+ to a noop on systems that do things "properly". */
+ value = (value >> 7) | ~(-(offsetT)1 >> 7);
+
+ more = !((((value == 0) && ((byte & 0x40) == 0))
+ || ((value == -1) && ((byte & 0x40) != 0))));
+ if (more)
+ byte |= 0x80;
+
+ *p++ = byte;
+ }
+ while (more);
+
+ return p - orig;
+}
+
+static inline int
+output_uleb128 (p, value)
+ char *p;
+ valueT value;
+{
+ char *orig = p;
+
+ do
+ {
+ unsigned byte = (value & 0x7f);
+ value >>= 7;
+ if (value != 0)
+ /* More bytes to follow. */
+ byte |= 0x80;
+
+ *p++ = byte;
+ }
+ while (value != 0);
+
+ return p - orig;
+}
+
+int
+output_leb128 (p, value, sign)
+ char *p;
+ valueT value;
+ int sign;
+{
+ if (sign)
+ return output_sleb128 (p, (offsetT) value);
+ else
+ return output_uleb128 (p, value);
+}
+
+/* Do the same for bignums. We combine sizeof with output here in that
+ we don't output for NULL values of P. It isn't really as critical as
+ for "normal" values that this be streamlined. */
+
+static int
+output_big_sleb128 (p, bignum, size)
+ char *p;
+ LITTLENUM_TYPE *bignum;
+ int size;
+{
+ char *orig = p;
+ valueT val = 0;
+ int loaded = 0;
+ unsigned byte;
+
+ /* Strip leading sign extensions off the bignum. */
+ while (size > 0 && bignum[size-1] == (LITTLENUM_TYPE)-1)
+ size--;
+
+ do
+ {
+ if (loaded < 7 && size > 0)
+ {
+ val |= (*bignum << loaded);
+ loaded += 8 * CHARS_PER_LITTLENUM;
+ size--;
+ bignum++;
+ }
+
+ byte = val & 0x7f;
+ loaded -= 7;
+ val >>= 7;
+
+ if (size == 0)
+ {
+ if ((val == 0 && (byte & 0x40) == 0)
+ || (~(val | ~(((valueT)1 << loaded) - 1)) == 0
+ && (byte & 0x40) != 0))
+ byte |= 0x80;
+ }
+
+ if (orig)
+ *p = byte;
+ p++;
+ }
+ while (byte & 0x80);
+
+ return p - orig;
+}
+
+static int
+output_big_uleb128 (p, bignum, size)
+ char *p;
+ LITTLENUM_TYPE *bignum;
+ int size;
+{
+ char *orig = p;
+ valueT val = 0;
+ int loaded = 0;
+ unsigned byte;
+
+ /* Strip leading zeros off the bignum. */
+ /* XXX: Is this needed? */
+ while (size > 0 && bignum[size-1] == 0)
+ size--;
+
+ do
+ {
+ if (loaded < 7 && size > 0)
+ {
+ val |= (*bignum << loaded);
+ loaded += 8 * CHARS_PER_LITTLENUM;
+ size--;
+ bignum++;
+ }
+
+ byte = val & 0x7f;
+ loaded -= 7;
+ val >>= 7;
+
+ if (size > 0 || val)
+ byte |= 0x80;
+
+ if (orig)
+ *p = byte;
+ p++;
+ }
+ while (byte & 0x80);
+
+ return p - orig;
+}
+
+static inline int
+output_big_leb128 (p, bignum, size, sign)
+ char *p;
+ LITTLENUM_TYPE *bignum;
+ int size, sign;
+{
+ if (sign)
+ return output_big_sleb128 (p, bignum, size);
+ else
+ return output_big_uleb128 (p, bignum, size);
+}
+
+/* Generate the appropriate fragments for a given expression to emit a
+ leb128 value. */
+
+void
+emit_leb128_expr(exp, sign)
+ expressionS *exp;
+ int sign;
+{
+ operatorT op = exp->X_op;
+
+ if (op == O_absent || op == O_illegal)
+ {
+ as_warn (_("zero assumed for missing expression"));
+ exp->X_add_number = 0;
+ op = O_constant;
+ }
+ else if (op == O_big && exp->X_add_number <= 0)
+ {
+ as_bad (_("floating point number invalid; zero assumed"));
+ exp->X_add_number = 0;
+ op = O_constant;
+ }
+ else if (op == O_register)
+ {
+ as_warn (_("register value used as expression"));
+ op = O_constant;
+ }
+
+ if (op == O_constant)
+ {
+ /* If we've got a constant, emit the thing directly right now. */
+
+ valueT value = exp->X_add_number;
+ int size;
+ char *p;
+
+ size = sizeof_leb128 (value, sign);
+ p = frag_more (size);
+ output_leb128 (p, value, sign);
+ }
+ else if (op == O_big)
+ {
+ /* O_big is a different sort of constant. */
+
+ int size;
+ char *p;
+
+ size = output_big_leb128 (NULL, generic_bignum, exp->X_add_number, sign);
+ p = frag_more (size);
+ output_big_leb128 (p, generic_bignum, exp->X_add_number, sign);
+ }
+ else
+ {
+ /* Otherwise, we have to create a variable sized fragment and
+ resolve things later. */
+
+ frag_var (rs_leb128, sizeof_uleb128 (~(valueT)0), 0, sign,
+ make_expr_symbol (exp), 0, (char *) NULL);
+ }
+}
+
+/* Parse the .sleb128 and .uleb128 pseudos. */
+
+void
+s_leb128 (sign)
+ int sign;
+{
+ expressionS exp;
+
+ do {
+ expression (&exp);
+ emit_leb128_expr (&exp, sign);
+ } while (*input_line_pointer++ == ',');
+
+ input_line_pointer--;
+ demand_empty_rest_of_line ();
+}
+
+/*
+ * stringer()
+ *
+ * We read 0 or more ',' seperated, double-quoted strings.
+ *
+ * Caller should have checked need_pass_2 is FALSE because we don't check it.
+ */
+
+
+void
+stringer (append_zero) /* Worker to do .ascii etc statements. */
+ /* Checks end-of-line. */
+ register int append_zero; /* 0: don't append '\0', else 1 */
+{
+ register unsigned int c;
+ char *start;
+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+ /*
+ * The following awkward logic is to parse ZERO or more strings,
+ * comma separated. Recall a string expression includes spaces
+ * before the opening '\"' and spaces after the closing '\"'.
+ * We fake a leading ',' if there is (supposed to be)
+ * a 1st, expression. We keep demanding expressions for each
+ * ','.
+ */
+ if (is_it_end_of_statement ())
+ {
+ c = 0; /* Skip loop. */
+ ++input_line_pointer; /* Compensate for end of loop. */
+ }
+ else
+ {
+ c = ','; /* Do loop. */
+ }
+ while (c == ',' || c == '<' || c == '"')
+ {
+ SKIP_WHITESPACE ();
+ switch (*input_line_pointer)
+ {
+ case '\"':
+ ++input_line_pointer; /*->1st char of string. */
+ start = input_line_pointer;
+ while (is_a_char (c = next_char_of_string ()))
+ {
+ FRAG_APPEND_1_CHAR (c);
+ }
+ if (append_zero)
+ {
+ FRAG_APPEND_1_CHAR (0);
+ }
+ know (input_line_pointer[-1] == '\"');
+
+#ifndef NO_LISTING
+#ifdef OBJ_ELF
+ /* In ELF, when gcc is emitting DWARF 1 debugging output, it
+ will emit .string with a filename in the .debug section
+ after a sequence of constants. See the comment in
+ emit_expr for the sequence. emit_expr will set
+ dwarf_file_string to non-zero if this string might be a
+ source file name. */
+ if (strcmp (segment_name (now_seg), ".debug") != 0)
+ dwarf_file_string = 0;
+ else if (dwarf_file_string)
+ {
+ c = input_line_pointer[-1];
+ input_line_pointer[-1] = '\0';
+ listing_source_file (start);
+ input_line_pointer[-1] = c;
+ }
+#endif
+#endif
+
+ break;
+ case '<':
+ input_line_pointer++;
+ c = get_single_number ();
+ FRAG_APPEND_1_CHAR (c);
+ if (*input_line_pointer != '>')
+ {
+ as_bad (_("Expected <nn>"));
+ }
+ input_line_pointer++;
+ break;
+ case ',':
+ input_line_pointer++;
+ break;
+ }
+ SKIP_WHITESPACE ();
+ c = *input_line_pointer;
+ }
+
+ demand_empty_rest_of_line ();
+} /* stringer() */
+
+/* FIXME-SOMEDAY: I had trouble here on characters with the
+ high bits set. We'll probably also have trouble with
+ multibyte chars, wide chars, etc. Also be careful about
+ returning values bigger than 1 byte. xoxorich. */
+
+unsigned int
+next_char_of_string ()
+{
+ register unsigned int c;
+
+ c = *input_line_pointer++ & CHAR_MASK;
+ switch (c)
+ {
+ case '\"':
+ c = NOT_A_CHAR;
+ break;
+
+ case '\n':
+ as_warn (_("Unterminated string: Newline inserted."));
+ bump_line_counters ();
+ break;
+
+#ifndef NO_STRING_ESCAPES
+ case '\\':
+ switch (c = *input_line_pointer++)
+ {
+ case 'b':
+ c = '\b';
+ break;
+
+ case 'f':
+ c = '\f';
+ break;
+
+ case 'n':
+ c = '\n';
+ break;
+
+ case 'r':
+ c = '\r';
+ break;
+
+ case 't':
+ c = '\t';
+ break;
+
+ case 'v':
+ c = '\013';
+ break;
+
+ case '\\':
+ case '"':
+ break; /* As itself. */
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ long number;
+ int i;
+
+ for (i = 0, number = 0; isdigit (c) && i < 3; c = *input_line_pointer++, i++)
+ {
+ number = number * 8 + c - '0';
+ }
+ c = number & 0xff;
+ }
+ --input_line_pointer;
+ break;
+
+ case 'x':
+ case 'X':
+ {
+ long number;
+
+ number = 0;
+ c = *input_line_pointer++;
+ while (isxdigit (c))
+ {
+ if (isdigit (c))
+ number = number * 16 + c - '0';
+ else if (isupper (c))
+ number = number * 16 + c - 'A' + 10;
+ else
+ number = number * 16 + c - 'a' + 10;
+ c = *input_line_pointer++;
+ }
+ c = number & 0xff;
+ --input_line_pointer;
+ }
+ break;
+
+ case '\n':
+ /* To be compatible with BSD 4.2 as: give the luser a linefeed!! */
+ as_warn (_("Unterminated string: Newline inserted."));
+ c = '\n';
+ bump_line_counters ();
+ break;
+
+ default:
+
+#ifdef ONLY_STANDARD_ESCAPES
+ as_bad (_("Bad escaped character in string, '?' assumed"));
+ c = '?';
+#endif /* ONLY_STANDARD_ESCAPES */
+
+ break;
+ } /* switch on escaped char */
+ break;
+#endif /* ! defined (NO_STRING_ESCAPES) */
+
+ default:
+ break;
+ } /* switch on char */
+ return (c);
+} /* next_char_of_string() */
+
+static segT
+get_segmented_expression (expP)
+ register expressionS *expP;
+{
+ register segT retval;
+
+ retval = expression (expP);
+ if (expP->X_op == O_illegal
+ || expP->X_op == O_absent
+ || expP->X_op == O_big)
+ {
+ as_bad (_("expected address expression; zero assumed"));
+ expP->X_op = O_constant;
+ expP->X_add_number = 0;
+ retval = absolute_section;
+ }
+ return retval;
+}
+
+static segT
+get_known_segmented_expression (expP)
+ register expressionS *expP;
+{
+ register segT retval;
+
+ if ((retval = get_segmented_expression (expP)) == undefined_section)
+ {
+ /* There is no easy way to extract the undefined symbol from the
+ expression. */
+ if (expP->X_add_symbol != NULL
+ && S_GET_SEGMENT (expP->X_add_symbol) != expr_section)
+ as_warn (_("symbol \"%s\" undefined; zero assumed"),
+ S_GET_NAME (expP->X_add_symbol));
+ else
+ as_warn (_("some symbol undefined; zero assumed"));
+ retval = absolute_section;
+ expP->X_op = O_constant;
+ expP->X_add_number = 0;
+ }
+ know (retval == absolute_section || SEG_NORMAL (retval));
+ return (retval);
+} /* get_known_segmented_expression() */
+
+offsetT
+get_absolute_expression ()
+{
+ expressionS exp;
+
+ expression (&exp);
+ if (exp.X_op != O_constant)
+ {
+ if (exp.X_op != O_absent)
+ as_bad (_("bad or irreducible absolute expression; zero assumed"));
+ exp.X_add_number = 0;
+ }
+ return exp.X_add_number;
+}
+
+char /* return terminator */
+get_absolute_expression_and_terminator (val_pointer)
+ long *val_pointer; /* return value of expression */
+{
+ /* FIXME: val_pointer should probably be offsetT *. */
+ *val_pointer = (long) get_absolute_expression ();
+ return (*input_line_pointer++);
+}
+
+/*
+ * demand_copy_C_string()
+ *
+ * Like demand_copy_string, but return NULL if the string contains any '\0's.
+ * Give a warning if that happens.
+ */
+char *
+demand_copy_C_string (len_pointer)
+ int *len_pointer;
+{
+ register char *s;
+
+ if ((s = demand_copy_string (len_pointer)) != 0)
+ {
+ register int len;
+
+ for (len = *len_pointer; len > 0; len--)
+ {
+ if (*s == 0)
+ {
+ s = 0;
+ len = 1;
+ *len_pointer = 0;
+ as_bad (_("This string may not contain \'\\0\'"));
+ }
+ }
+ }
+ return s;
+}
+
+/*
+ * demand_copy_string()
+ *
+ * Demand string, but return a safe (=private) copy of the string.
+ * Return NULL if we can't read a string here.
+ */
+char *
+demand_copy_string (lenP)
+ int *lenP;
+{
+ register unsigned int c;
+ register int len;
+ char *retval;
+
+ len = 0;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '\"')
+ {
+ input_line_pointer++; /* Skip opening quote. */
+
+ while (is_a_char (c = next_char_of_string ()))
+ {
+ obstack_1grow (&notes, c);
+ len++;
+ }
+ /* JF this next line is so demand_copy_C_string will return a
+ null terminated string. */
+ obstack_1grow (&notes, '\0');
+ retval = obstack_finish (&notes);
+ }
+ else
+ {
+ as_warn (_("Missing string"));
+ retval = NULL;
+ ignore_rest_of_line ();
+ }
+ *lenP = len;
+ return (retval);
+} /* demand_copy_string() */
+
+/*
+ * is_it_end_of_statement()
+ *
+ * In: Input_line_pointer->next character.
+ *
+ * Do: Skip input_line_pointer over all whitespace.
+ *
+ * Out: 1 if input_line_pointer->end-of-line.
+*/
+int
+is_it_end_of_statement ()
+{
+ SKIP_WHITESPACE ();
+ return (is_end_of_line[(unsigned char) *input_line_pointer]);
+} /* is_it_end_of_statement() */
+
+void
+equals (sym_name, reassign)
+ char *sym_name;
+ int reassign;
+{
+ register symbolS *symbolP; /* symbol we are working with */
+ char *stop = NULL;
+ char stopc;
+
+ input_line_pointer++;
+ if (*input_line_pointer == '=')
+ input_line_pointer++;
+
+ while (*input_line_pointer == ' ' || *input_line_pointer == '\t')
+ input_line_pointer++;
+
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
+
+ if (sym_name[0] == '.' && sym_name[1] == '\0')
+ {
+ /* Turn '. = mumble' into a .org mumble */
+ register segT segment;
+ expressionS exp;
+
+ segment = get_known_segmented_expression (&exp);
+ if (!need_pass_2)
+ do_org (segment, &exp, 0);
+ }
+ else
+ {
+ symbolP = symbol_find_or_make (sym_name);
+ /* Permit register names to be redefined. */
+ if (! reassign
+ && S_IS_DEFINED (symbolP)
+ && S_GET_SEGMENT (symbolP) != reg_section)
+ as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
+ pseudo_set (symbolP);
+ }
+
+ if (flag_mri)
+ {
+ ignore_rest_of_line (); /* check garbage after the expression */
+ mri_comment_end (stop, stopc);
+ }
+} /* equals() */
+
+/* .include -- include a file at this point. */
+
+/* ARGSUSED */
+void
+s_include (arg)
+ int arg;
+{
+ char *newbuf;
+ char *filename;
+ int i;
+ FILE *try;
+ char *path;
+
+ if (! flag_m68k_mri)
+ {
+ filename = demand_copy_string (&i);
+ if (filename == NULL)
+ {
+ /* demand_copy_string has already printed an error and
+ called ignore_rest_of_line. */
+ return;
+ }
+ }
+ else
+ {
+ SKIP_WHITESPACE ();
+ i = 0;
+ while (! is_end_of_line[(unsigned char) *input_line_pointer]
+ && *input_line_pointer != ' '
+ && *input_line_pointer != '\t')
+ {
+ obstack_1grow (&notes, *input_line_pointer);
+ ++input_line_pointer;
+ ++i;
+ }
+ obstack_1grow (&notes, '\0');
+ filename = obstack_finish (&notes);
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ ++input_line_pointer;
+ }
+ demand_empty_rest_of_line ();
+ path = xmalloc ((unsigned long) i + include_dir_maxlen + 5 /* slop */ );
+ for (i = 0; i < include_dir_count; i++)
+ {
+ strcpy (path, include_dirs[i]);
+ strcat (path, "/");
+ strcat (path, filename);
+ if (0 != (try = fopen (path, "r")))
+ {
+ fclose (try);
+ goto gotit;
+ }
+ }
+ free (path);
+ path = filename;
+gotit:
+ /* malloc Storage leak when file is found on path. FIXME-SOMEDAY. */
+ register_dependency (path);
+ newbuf = input_scrub_include_file (path, input_line_pointer);
+ buffer_limit = input_scrub_next_buffer (&input_line_pointer);
+} /* s_include() */
+
+void
+add_include_dir (path)
+ char *path;
+{
+ int i;
+
+ if (include_dir_count == 0)
+ {
+ include_dirs = (char **) xmalloc (2 * sizeof (*include_dirs));
+ include_dirs[0] = "."; /* Current dir */
+ include_dir_count = 2;
+ }
+ else
+ {
+ include_dir_count++;
+ include_dirs = (char **) realloc (include_dirs,
+ include_dir_count * sizeof (*include_dirs));
+ }
+
+ include_dirs[include_dir_count - 1] = path; /* New one */
+
+ i = strlen (path);
+ if (i > include_dir_maxlen)
+ include_dir_maxlen = i;
+} /* add_include_dir() */
+
+/* Output debugging information to denote the source file. */
+
+static void
+generate_file_debug ()
+{
+ if (debug_type == DEBUG_STABS)
+ stabs_generate_asm_file ();
+}
+
+/* Output line number debugging information for the current source line. */
+
+void
+generate_lineno_debug ()
+{
+#ifdef ECOFF_DEBUGGING
+ /* ECOFF assemblers automatically generate debugging information.
+ FIXME: This should probably be handled elsewhere. */
+ if (debug_type == DEBUG_UNSPECIFIED)
+ {
+ if (ECOFF_DEBUGGING && ecoff_no_current_file ())
+ debug_type = DEBUG_ECOFF;
+ else
+ debug_type = DEBUG_NONE;
+ }
+#endif
+
+ switch (debug_type)
+ {
+ case DEBUG_UNSPECIFIED:
+ case DEBUG_NONE:
+ break;
+ case DEBUG_STABS:
+ stabs_generate_asm_lineno ();
+ break;
+ case DEBUG_ECOFF:
+ ecoff_generate_asm_lineno ();
+ break;
+ case DEBUG_DWARF:
+ case DEBUG_DWARF2:
+ /* FIXME. */
+ break;
+ }
+}
+
+/* Output debugging information to mark a function entry point or end point.
+ END_P is zero for .func, and non-zero for .endfunc. */
+
+void
+s_func (end_p)
+ int end_p;
+{
+ do_s_func (end_p, NULL);
+}
+
+/* Subroutine of s_func so targets can choose a different default prefix.
+ If DEFAULT_PREFIX is NULL, use the target's "leading char". */
+
+void
+do_s_func (end_p, default_prefix)
+ int end_p;
+ const char *default_prefix;
+{
+ /* Record the current function so that we can issue an error message for
+ misplaced .func,.endfunc, and also so that .endfunc needs no
+ arguments. */
+ static char *current_name;
+ static char *current_label;
+
+ if (end_p)
+ {
+ if (current_name == NULL)
+ {
+ as_bad (_("missing .func"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ if (debug_type == DEBUG_STABS)
+ stabs_generate_asm_endfunc (current_name, current_label);
+
+ current_name = current_label = NULL;
+ }
+ else /* ! end_p */
+ {
+ char *name,*label;
+ char delim1,delim2;
+
+ if (current_name != NULL)
+ {
+ as_bad (_(".endfunc missing for previous .func"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ name = input_line_pointer;
+ delim1 = get_symbol_end ();
+ name = xstrdup (name);
+ *input_line_pointer = delim1;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
+ {
+ if (default_prefix)
+ asprintf (&label, "%s%s", default_prefix, name);
+ else
+ {
+ char leading_char = 0;
+#ifdef BFD_ASSEMBLER
+ leading_char = bfd_get_symbol_leading_char (stdoutput);
+#endif
+ /* Missing entry point, use function's name with the leading
+ char prepended. */
+ if (leading_char)
+ asprintf (&label, "%c%s", leading_char, name);
+ else
+ label = name;
+ }
+ }
+ else
+ {
+ ++input_line_pointer;
+ SKIP_WHITESPACE ();
+ label = input_line_pointer;
+ delim2 = get_symbol_end ();
+ label = xstrdup (label);
+ *input_line_pointer = delim2;
+ }
+
+ if (debug_type == DEBUG_STABS)
+ stabs_generate_asm_func (name, label);
+
+ current_name = name;
+ current_label = label;
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+void
+s_ignore (arg)
+ int arg;
+{
+ while (!is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ ++input_line_pointer;
+ }
+ ++input_line_pointer;
+}
+
+
+void
+read_print_statistics (file)
+ FILE *file;
+{
+ hash_print_statistics (file, "pseudo-op table", po_hash);
+}
+
+/* end of read.c */
diff --git a/gas/read.h b/gas/read.h
new file mode 100644
index 0000000000..61e20172be
--- /dev/null
+++ b/gas/read.h
@@ -0,0 +1,166 @@
+/* read.h - of read.c
+ Copyright (C) 1986, 90, 92, 93, 94, 95, 96, 1997
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+extern char *input_line_pointer;/* -> char we are parsing now. */
+
+#define PERMIT_WHITESPACE /* Define to make whitespace be allowed in */
+/* many syntactically unnecessary places. */
+/* Normally undefined. For compatibility */
+/* with ancient GNU cc. */
+/* #undef PERMIT_WHITESPACE */
+
+#ifdef PERMIT_WHITESPACE
+#define SKIP_WHITESPACE() {if (* input_line_pointer == ' ') ++ input_line_pointer;}
+#else
+#define SKIP_WHITESPACE() know(*input_line_pointer != ' ' )
+#endif
+
+
+#define LEX_NAME (1) /* may continue a name */
+#define LEX_BEGIN_NAME (2) /* may begin a name */
+
+#define is_name_beginner(c) \
+ ( lex_type[(unsigned char) (c)] & LEX_BEGIN_NAME )
+#define is_part_of_name(c) \
+ ( lex_type[(unsigned char) (c)] & LEX_NAME )
+
+#ifndef is_a_char
+#define CHAR_MASK (0xff)
+#define NOT_A_CHAR (CHAR_MASK+1)
+#define is_a_char(c) (((unsigned)(c)) <= CHAR_MASK)
+#endif /* is_a_char() */
+
+extern char lex_type[];
+extern char is_end_of_line[];
+
+extern int is_it_end_of_statement PARAMS ((void));
+
+extern int target_big_endian;
+
+/* These are initialized by the CPU specific target files (tc-*.c). */
+extern const char comment_chars[];
+extern const char line_comment_chars[];
+extern const char line_separator_chars[];
+
+/* Table of -I directories. */
+extern char **include_dirs;
+extern int include_dir_count;
+extern int include_dir_maxlen;
+
+/* The offset in the absolute section. */
+extern addressT abs_section_offset;
+
+/* The label on a line, used by some of the pseudo-ops. */
+extern symbolS *line_label;
+
+/* This is used to support MRI common sections. */
+extern symbolS *mri_common_symbol;
+
+/* Possible arguments to .linkonce. */
+enum linkonce_type
+{
+ LINKONCE_UNSET = 0,
+ LINKONCE_DISCARD,
+ LINKONCE_ONE_ONLY,
+ LINKONCE_SAME_SIZE,
+ LINKONCE_SAME_CONTENTS
+};
+
+extern void pop_insert PARAMS ((const pseudo_typeS *));
+extern unsigned int get_stab_string_offset
+ PARAMS ((const char *string, const char *stabstr_secname));
+extern char *demand_copy_C_string PARAMS ((int *len_pointer));
+extern char get_absolute_expression_and_terminator
+ PARAMS ((long *val_pointer));
+extern offsetT get_absolute_expression PARAMS ((void));
+extern unsigned int next_char_of_string PARAMS ((void));
+extern void s_mri_sect PARAMS ((char *));
+extern char *mri_comment_field PARAMS ((char *));
+extern void mri_comment_end PARAMS ((char *, int));
+extern void add_include_dir PARAMS ((char *path));
+extern void cons PARAMS ((int nbytes));
+extern void demand_empty_rest_of_line PARAMS ((void));
+extern void emit_expr PARAMS ((expressionS *exp, unsigned int nbytes));
+extern void emit_leb128_expr PARAMS ((expressionS *, int));
+extern void equals PARAMS ((char *sym_name, int reassign));
+extern void float_cons PARAMS ((int float_type));
+extern void ignore_rest_of_line PARAMS ((void));
+extern void discard_rest_of_line PARAMS ((void));
+extern int output_leb128 PARAMS ((char *, valueT, int sign));
+extern void pseudo_set PARAMS ((symbolS * symbolP));
+extern void read_a_source_file PARAMS ((char *name));
+extern void read_begin PARAMS ((void));
+extern void read_print_statistics PARAMS ((FILE *));
+extern int sizeof_leb128 PARAMS ((valueT, int sign));
+extern void stabs_generate_asm_file PARAMS ((void));
+extern void stabs_generate_asm_lineno PARAMS ((void));
+extern void stabs_generate_asm_func PARAMS ((const char *, const char *));
+extern void stabs_generate_asm_endfunc PARAMS ((const char *, const char *));
+
+extern void generate_lineno_debug PARAMS ((void));
+
+extern void s_abort PARAMS ((int));
+extern void s_align_bytes PARAMS ((int arg));
+extern void s_align_ptwo PARAMS ((int));
+extern void s_app_file PARAMS ((int));
+extern void s_app_line PARAMS ((int));
+extern void s_comm PARAMS ((int));
+extern void s_data PARAMS ((int));
+extern void s_desc PARAMS ((int));
+extern void s_else PARAMS ((int arg));
+extern void s_end PARAMS ((int arg));
+extern void s_endif PARAMS ((int arg));
+extern void s_err PARAMS ((int));
+extern void s_fail PARAMS ((int));
+extern void s_fill PARAMS ((int));
+extern void s_float_space PARAMS ((int mult));
+extern void s_func PARAMS ((int));
+extern void do_s_func PARAMS ((int, const char *));
+extern void s_globl PARAMS ((int arg));
+extern void s_if PARAMS ((int arg));
+extern void s_ifc PARAMS ((int arg));
+extern void s_ifdef PARAMS ((int arg));
+extern void s_ifeqs PARAMS ((int arg));
+extern void s_ignore PARAMS ((int arg));
+extern void s_include PARAMS ((int arg));
+extern void s_irp PARAMS ((int arg));
+extern void s_lcomm PARAMS ((int needs_align));
+extern void s_lcomm_bytes PARAMS ((int needs_align));
+extern void s_leb128 PARAMS ((int sign));
+extern void s_linkonce PARAMS ((int));
+extern void s_lsym PARAMS ((int));
+extern void s_macro PARAMS ((int));
+extern void s_mexit PARAMS ((int));
+extern void s_mri PARAMS ((int));
+extern void s_mri_common PARAMS ((int));
+extern void s_org PARAMS ((int));
+extern void s_print PARAMS ((int));
+extern void s_purgem PARAMS ((int));
+extern void s_rept PARAMS ((int));
+extern void s_set PARAMS ((int));
+extern void s_space PARAMS ((int mult));
+extern void s_stab PARAMS ((int what));
+extern void s_struct PARAMS ((int));
+extern void s_text PARAMS ((int));
+extern void stringer PARAMS ((int append_zero));
+extern void s_xstab PARAMS ((int what));
+extern void s_rva PARAMS ((int));
+
+/* end of read.h */
diff --git a/gas/sb.c b/gas/sb.c
new file mode 100644
index 0000000000..6ec23fcdb9
--- /dev/null
+++ b/gas/sb.c
@@ -0,0 +1,289 @@
+/* sb.c - string buffer manipulation routines
+ Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+
+ Written by Steve and Judy Chamberlain of Cygnus Support,
+ sac@cygnus.com
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include "config.h"
+#include <stdio.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#include "libiberty.h"
+#include "sb.h"
+
+/* These routines are about manipulating strings.
+
+ They are managed in things called `sb's which is an abbreviation
+ for string buffers. An sb has to be created, things can be glued
+ on to it, and at the end of it's life it should be freed. The
+ contents should never be pointed at whilst it is still growing,
+ since it could be moved at any time
+
+ eg:
+ sb_new (&foo);
+ sb_grow... (&foo,...);
+ use foo->ptr[*];
+ sb_kill (&foo);
+
+*/
+
+#define dsize 5
+
+static void sb_check PARAMS ((sb *, int));
+
+/* Statistics of sb structures. */
+
+int string_count[sb_max_power_two];
+
+/* Free list of sb structures. */
+
+static sb_list_vector free_list;
+
+/* initializes an sb. */
+
+void
+sb_build (ptr, size)
+ sb *ptr;
+ int size;
+{
+ /* see if we can find one to allocate */
+ sb_element *e;
+
+ if (size > sb_max_power_two)
+ abort ();
+
+ e = free_list.size[size];
+ if (!e)
+ {
+ /* nothing there, allocate one and stick into the free list */
+ e = (sb_element *) xmalloc (sizeof (sb_element) + (1 << size));
+ e->next = free_list.size[size];
+ e->size = 1 << size;
+ free_list.size[size] = e;
+ string_count[size]++;
+ }
+
+ /* remove from free list */
+
+ free_list.size[size] = e->next;
+
+ /* copy into callers world */
+ ptr->ptr = e->data;
+ ptr->pot = size;
+ ptr->len = 0;
+ ptr->item = e;
+}
+
+
+void
+sb_new (ptr)
+ sb *ptr;
+{
+ sb_build (ptr, dsize);
+}
+
+/* deallocate the sb at ptr */
+
+void
+sb_kill (ptr)
+ sb *ptr;
+{
+ /* return item to free list */
+ ptr->item->next = free_list.size[ptr->pot];
+ free_list.size[ptr->pot] = ptr->item;
+}
+
+/* add the sb at s to the end of the sb at ptr */
+
+void
+sb_add_sb (ptr, s)
+ sb *ptr;
+ sb *s;
+{
+ sb_check (ptr, s->len);
+ memcpy (ptr->ptr + ptr->len, s->ptr, s->len);
+ ptr->len += s->len;
+}
+
+/* make sure that the sb at ptr has room for another len characters,
+ and grow it if it doesn't. */
+
+static void
+sb_check (ptr, len)
+ sb *ptr;
+ int len;
+{
+ if (ptr->len + len >= 1 << ptr->pot)
+ {
+ sb tmp;
+ int pot = ptr->pot;
+ while (ptr->len + len >= 1 << pot)
+ pot++;
+ sb_build (&tmp, pot);
+ sb_add_sb (&tmp, ptr);
+ sb_kill (ptr);
+ *ptr = tmp;
+ }
+}
+
+/* make the sb at ptr point back to the beginning. */
+
+void
+sb_reset (ptr)
+ sb *ptr;
+{
+ ptr->len = 0;
+}
+
+/* add character c to the end of the sb at ptr. */
+
+void
+sb_add_char (ptr, c)
+ sb *ptr;
+ int c;
+{
+ sb_check (ptr, 1);
+ ptr->ptr[ptr->len++] = c;
+}
+
+/* add null terminated string s to the end of sb at ptr. */
+
+void
+sb_add_string (ptr, s)
+ sb *ptr;
+ const char *s;
+{
+ int len = strlen (s);
+ sb_check (ptr, len);
+ memcpy (ptr->ptr + ptr->len, s, len);
+ ptr->len += len;
+}
+
+/* add string at s of length len to sb at ptr */
+
+void
+sb_add_buffer (ptr, s, len)
+ sb *ptr;
+ const char *s;
+ int len;
+{
+ sb_check (ptr, len);
+ memcpy (ptr->ptr + ptr->len, s, len);
+ ptr->len += len;
+}
+
+/* print the sb at ptr to the output file */
+
+void
+sb_print (outfile, ptr)
+ FILE *outfile;
+ sb *ptr;
+{
+ int i;
+ int nc = 0;
+
+ for (i = 0; i < ptr->len; i++)
+ {
+ if (nc)
+ {
+ fprintf (outfile, ",");
+ }
+ fprintf (outfile, "%d", ptr->ptr[i]);
+ nc = 1;
+ }
+}
+
+void
+sb_print_at (outfile, idx, ptr)
+ FILE *outfile;
+ int idx;
+ sb *ptr;
+{
+ int i;
+ for (i = idx; i < ptr->len; i++)
+ putc (ptr->ptr[i], outfile);
+}
+
+/* put a null at the end of the sb at in and return the start of the
+ string, so that it can be used as an arg to printf %s. */
+
+char *
+sb_name (in)
+ sb *in;
+{
+ /* stick a null on the end of the string */
+ sb_add_char (in, 0);
+ return in->ptr;
+}
+
+/* like sb_name, but don't include the null byte in the string. */
+
+char *
+sb_terminate (in)
+ sb *in;
+{
+ sb_add_char (in, 0);
+ --in->len;
+ return in->ptr;
+}
+
+/* start at the index idx into the string in sb at ptr and skip
+ whitespace. return the index of the first non whitespace character */
+
+int
+sb_skip_white (idx, ptr)
+ int idx;
+ sb *ptr;
+{
+ while (idx < ptr->len
+ && (ptr->ptr[idx] == ' '
+ || ptr->ptr[idx] == '\t'))
+ idx++;
+ return idx;
+}
+
+/* start at the index idx into the sb at ptr. skips whitespace,
+ a comma and any following whitespace. returnes the index of the
+ next character. */
+
+int
+sb_skip_comma (idx, ptr)
+ int idx;
+ sb *ptr;
+{
+ while (idx < ptr->len
+ && (ptr->ptr[idx] == ' '
+ || ptr->ptr[idx] == '\t'))
+ idx++;
+
+ if (idx < ptr->len
+ && ptr->ptr[idx] == ',')
+ idx++;
+
+ while (idx < ptr->len
+ && (ptr->ptr[idx] == ' '
+ || ptr->ptr[idx] == '\t'))
+ idx++;
+
+ return idx;
+}
diff --git a/gas/sb.h b/gas/sb.h
new file mode 100644
index 0000000000..7e6daf167d
--- /dev/null
+++ b/gas/sb.h
@@ -0,0 +1,99 @@
+/* sb.h - header file for string buffer manipulation routines
+ Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+
+ Written by Steve and Judy Chamberlain of Cygnus Support,
+ sac@cygnus.com
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#ifndef SB_H
+
+#define SB_H
+
+#include <stdio.h>
+#include "ansidecl.h"
+
+/* string blocks
+
+ I had a couple of choices when deciding upon this data structure.
+ gas uses null terminated strings for all its internal work. This
+ often means that parts of the program that want to examine
+ substrings have to manipulate the data in the string to do the
+ right thing (a common operation is to single out a bit of text by
+ saving away the character after it, nulling it out, operating on
+ the substring and then replacing the character which was under the
+ null). This is a pain and I remember a load of problems that I had with
+ code in gas which almost got this right. Also, it's harder to grow and
+ allocate null terminated strings efficiently.
+
+ Obstacks provide all the functionality needed, but are too
+ complicated, hence the sb.
+
+ An sb is allocated by the caller, and is initialzed to point to an
+ sb_element. sb_elements are kept on a free lists, and used when
+ needed, replaced onto the free list when unused.
+ */
+
+#define sb_max_power_two 30 /* don't allow strings more than
+ 2^sb_max_power_two long */
+/* structure of an sb */
+typedef struct sb
+ {
+ char *ptr; /* points to the current block. */
+ int len; /* how much is used. */
+ int pot; /* the maximum length is 1<<pot */
+ struct le *item;
+ }
+sb;
+
+/* Structure of the free list object of an sb */
+typedef struct le
+ {
+ struct le *next;
+ int size;
+ char data[1];
+ }
+sb_element;
+
+/* The free list */
+typedef struct
+ {
+ sb_element *size[sb_max_power_two];
+ } sb_list_vector;
+
+extern int string_count[sb_max_power_two];
+
+extern void sb_build PARAMS ((sb *, int));
+extern void sb_new PARAMS ((sb *));
+extern void sb_kill PARAMS ((sb *));
+extern void sb_add_sb PARAMS ((sb *, sb *));
+extern void sb_reset PARAMS ((sb *));
+extern void sb_add_char PARAMS ((sb *, int));
+extern void sb_add_string PARAMS ((sb *, const char *));
+extern void sb_add_buffer PARAMS ((sb *, const char *, int));
+extern void sb_print PARAMS ((FILE *, sb *));
+extern void sb_print_at PARAMS ((FILE *, int, sb *));
+extern char *sb_name PARAMS ((sb *));
+extern char *sb_terminate PARAMS ((sb *));
+extern int sb_skip_white PARAMS ((int, sb *));
+extern int sb_skip_comma PARAMS ((int, sb *));
+
+/* Actually in input-scrub.c. */
+extern void input_scrub_include_sb PARAMS ((sb *, char *));
+
+#endif /* SB_H */
diff --git a/gas/stabs.c b/gas/stabs.c
new file mode 100644
index 0000000000..db7e1bfb6d
--- /dev/null
+++ b/gas/stabs.c
@@ -0,0 +1,632 @@
+/* Generic stabs parsing for gas.
+ Copyright (C) 1989, 90, 91, 93, 94, 95, 96, 97, 1998
+ Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2,
+or (at your option) any later version.
+
+GAS 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 more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#include "as.h"
+#include "obstack.h"
+#include "subsegs.h"
+#include "ecoff.h"
+
+/* We need this, despite the apparent object format dependency, since
+ it defines stab types, which all object formats can use now. */
+
+#include "aout/stab_gnu.h"
+
+static void s_stab_generic PARAMS ((int, char *, char *));
+static void generate_asm_file PARAMS ((int, char *));
+
+/* Allow backends to override the names used for the stab sections. */
+#ifndef STAB_SECTION_NAME
+#define STAB_SECTION_NAME ".stab"
+#endif
+
+#ifndef STAB_STRING_SECTION_NAME
+#define STAB_STRING_SECTION_NAME ".stabstr"
+#endif
+
+/* Non-zero if we're in the middle of a .func function, in which case
+ stabs_generate_asm_lineno emits function relative line number stabs.
+ Otherwise it emits line number stabs with absolute addresses. Note that
+ both cases only apply to assembler code assembled with -gstabs. */
+static int in_dot_func_p;
+
+/* Label at start of current function if in_dot_func_p != 0. */
+static const char *current_function_label;
+
+/*
+ * Handle .stabX directives, which used to be open-coded.
+ * So much creeping featurism overloaded the semantics that we decided
+ * to put all .stabX thinking in one place. Here.
+ *
+ * We try to make any .stabX directive legal. Other people's AS will often
+ * do assembly-time consistency checks: eg assigning meaning to n_type bits
+ * and "protecting" you from setting them to certain values. (They also zero
+ * certain bits before emitting symbols. Tut tut.)
+ *
+ * If an expression is not absolute we either gripe or use the relocation
+ * information. Other people's assemblers silently forget information they
+ * don't need and invent information they need that you didn't supply.
+ */
+
+/*
+ * Build a string dictionary entry for a .stabX symbol.
+ * The symbol is added to the .<secname>str section.
+ */
+
+#ifndef SEPARATE_STAB_SECTIONS
+#define SEPARATE_STAB_SECTIONS 0
+#endif
+
+unsigned int
+get_stab_string_offset (string, stabstr_secname)
+ const char *string;
+ const char *stabstr_secname;
+{
+ unsigned int length;
+ unsigned int retval;
+ segT save_seg;
+ subsegT save_subseg;
+ segT seg;
+ char *p;
+
+ if (! SEPARATE_STAB_SECTIONS)
+ abort ();
+
+ length = strlen (string);
+
+ save_seg = now_seg;
+ save_subseg = now_subseg;
+
+ /* Create the stab string section. */
+ seg = subseg_new (stabstr_secname, 0);
+
+ retval = seg_info (seg)->stabu.stab_string_size;
+ if (retval <= 0)
+ {
+ /* Make sure the first string is empty. */
+ p = frag_more (1);
+ *p = 0;
+ retval = seg_info (seg)->stabu.stab_string_size = 1;
+#ifdef BFD_ASSEMBLER
+ bfd_set_section_flags (stdoutput, seg, SEC_READONLY | SEC_DEBUGGING);
+ if (seg->name == stabstr_secname)
+ seg->name = xstrdup (stabstr_secname);
+#endif
+ }
+
+ if (length > 0)
+ { /* Ordinary case. */
+ p = frag_more (length + 1);
+ strcpy (p, string);
+
+ seg_info (seg)->stabu.stab_string_size += length + 1;
+ }
+ else
+ retval = 0;
+
+ subseg_set (save_seg, save_subseg);
+
+ return retval;
+}
+
+#ifdef AOUT_STABS
+#ifndef OBJ_PROCESS_STAB
+#define OBJ_PROCESS_STAB(SEG,W,S,T,O,D) aout_process_stab(W,S,T,O,D)
+#endif
+
+static void aout_process_stab PARAMS ((int, const char *, int, int, int));
+
+static void
+aout_process_stab (what, string, type, other, desc)
+ int what;
+ const char *string;
+ int type, other, desc;
+{
+ /* Put the stab information in the symbol table. */
+ symbolS *symbol;
+
+ /* Create the symbol now, but only insert it into the symbol chain
+ after any symbols mentioned in the value expression get into the
+ symbol chain. This is to avoid "continuation symbols" (where one
+ ends in "\" and the debug info is continued in the next .stabs
+ directive) from being separated by other random symbols. */
+ symbol = symbol_create (string, undefined_section, 0,
+ (struct frag *) NULL);
+ if (what == 's' || what == 'n')
+ {
+ /* Pick up the value from the input line. */
+ symbol->sy_frag = &zero_address_frag;
+ pseudo_set (symbol);
+ }
+ else
+ {
+ /* .stabd sets the name to NULL. Why? */
+ S_SET_NAME (symbol, NULL);
+ symbol->sy_frag = frag_now;
+ S_SET_VALUE (symbol, (valueT) frag_now_fix ());
+ }
+
+ symbol_append (symbol, symbol_lastP, &symbol_rootP, &symbol_lastP);
+
+ S_SET_TYPE (symbol, type);
+ S_SET_OTHER (symbol, other);
+ S_SET_DESC (symbol, desc);
+}
+#endif
+
+/* This can handle different kinds of stabs (s,n,d) and different
+ kinds of stab sections. */
+
+static void
+s_stab_generic (what, stab_secname, stabstr_secname)
+ int what;
+ char *stab_secname;
+ char *stabstr_secname;
+{
+ long longint;
+ char *string;
+ int type;
+ int other;
+ int desc;
+
+ /* The general format is:
+ .stabs "STRING",TYPE,OTHER,DESC,VALUE
+ .stabn TYPE,OTHER,DESC,VALUE
+ .stabd TYPE,OTHER,DESC
+ At this point input_line_pointer points after the pseudo-op and
+ any trailing whitespace. The argument what is one of 's', 'n' or
+ 'd' indicating which type of .stab this is. */
+
+ if (what != 's')
+ string = "";
+ else
+ {
+ int length;
+
+ string = demand_copy_C_string (&length);
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == ',')
+ input_line_pointer++;
+ else
+ {
+ as_warn (_(".stabs: Missing comma"));
+ ignore_rest_of_line ();
+ return;
+ }
+ }
+
+ if (get_absolute_expression_and_terminator (&longint) != ',')
+ {
+ as_warn (_(".stab%c: Missing comma"), what);
+ ignore_rest_of_line ();
+ return;
+ }
+ type = longint;
+
+ if (get_absolute_expression_and_terminator (&longint) != ',')
+ {
+ as_warn (_(".stab%c: Missing comma"), what);
+ ignore_rest_of_line ();
+ return;
+ }
+ other = longint;
+
+ desc = get_absolute_expression ();
+ if (what == 's' || what == 'n')
+ {
+ if (*input_line_pointer != ',')
+ {
+ as_warn (_(".stab%c: Missing comma"), what);
+ ignore_rest_of_line ();
+ return;
+ }
+ input_line_pointer++;
+ SKIP_WHITESPACE ();
+ }
+
+#ifdef TC_PPC
+#ifdef OBJ_ELF
+ /* Solaris on PowerPC has decided that .stabd can take 4 arguments, so if we were
+ given 4 arguments, make it a .stabn */
+ else if (what == 'd')
+ {
+ char *save_location = input_line_pointer;
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == ',')
+ {
+ input_line_pointer++;
+ what = 'n';
+ }
+ else
+ input_line_pointer = save_location;
+ }
+#endif /* OBJ_ELF */
+#endif /* TC_PPC */
+
+#ifndef NO_LISTING
+ if (listing)
+ {
+ switch (type)
+ {
+ case N_SLINE:
+ listing_source_line ((unsigned int) desc);
+ break;
+ case N_SO:
+ case N_SOL:
+ listing_source_file (string);
+ break;
+ }
+ }
+#endif /* ! NO_LISTING */
+
+ /* We have now gathered the type, other, and desc information. For
+ .stabs or .stabn, input_line_pointer is now pointing at the
+ value. */
+
+ if (SEPARATE_STAB_SECTIONS)
+ /* Output the stab information in a separate section. This is used
+ at least for COFF and ELF. */
+ {
+ segT saved_seg = now_seg;
+ subsegT saved_subseg = now_subseg;
+ fragS *saved_frag = frag_now;
+ valueT dot;
+ segT seg;
+ unsigned int stroff;
+ char *p;
+
+ static segT cached_sec;
+ static char *cached_secname;
+
+ dot = frag_now_fix ();
+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+ if (cached_secname && !strcmp (cached_secname, stab_secname))
+ {
+ seg = cached_sec;
+ subseg_set (seg, 0);
+ }
+ else
+ {
+ seg = subseg_new (stab_secname, 0);
+ if (cached_secname)
+ free (cached_secname);
+ cached_secname = xstrdup (stab_secname);
+ cached_sec = seg;
+ }
+
+ if (! seg_info (seg)->hadone)
+ {
+#ifdef BFD_ASSEMBLER
+ bfd_set_section_flags (stdoutput, seg,
+ SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
+#endif
+#ifdef INIT_STAB_SECTION
+ INIT_STAB_SECTION (seg);
+#endif
+ seg_info (seg)->hadone = 1;
+ }
+
+ stroff = get_stab_string_offset (string, stabstr_secname);
+ if (what == 's')
+ {
+ /* release the string */
+ obstack_free (&notes, string);
+ }
+
+ /* At least for now, stabs in a special stab section are always
+ output as 12 byte blocks of information. */
+ p = frag_more (8);
+ md_number_to_chars (p, (valueT) stroff, 4);
+ md_number_to_chars (p + 4, (valueT) type, 1);
+ md_number_to_chars (p + 5, (valueT) other, 1);
+ md_number_to_chars (p + 6, (valueT) desc, 2);
+
+ if (what == 's' || what == 'n')
+ {
+ /* Pick up the value from the input line. */
+ cons (4);
+ input_line_pointer--;
+ }
+ else
+ {
+ const char *fake;
+ symbolS *symbol;
+ expressionS exp;
+
+ /* Arrange for a value representing the current location. */
+ fake = FAKE_LABEL_NAME;
+ symbol = symbol_new (fake, saved_seg, dot, saved_frag);
+
+ exp.X_op = O_symbol;
+ exp.X_add_symbol = symbol;
+ exp.X_add_number = 0;
+
+ emit_expr (&exp, 4);
+ }
+
+#ifdef OBJ_PROCESS_STAB
+ OBJ_PROCESS_STAB (seg, what, string, type, other, desc);
+#endif
+
+ subseg_set (saved_seg, saved_subseg);
+ }
+ else
+ {
+#ifdef OBJ_PROCESS_STAB
+ OBJ_PROCESS_STAB (0, what, string, type, other, desc);
+#else
+ abort ();
+#endif
+ }
+
+ demand_empty_rest_of_line ();
+}
+
+/* Regular stab directive. */
+
+void
+s_stab (what)
+ int what;
+{
+ s_stab_generic (what, STAB_SECTION_NAME, STAB_STRING_SECTION_NAME);
+}
+
+/* "Extended stabs", used in Solaris only now. */
+
+void
+s_xstab (what)
+ int what;
+{
+ int length;
+ char *stab_secname, *stabstr_secname;
+ static char *saved_secname, *saved_strsecname;
+
+ /* @@ MEMORY LEAK: This allocates a copy of the string, but in most
+ cases it will be the same string, so we could release the storage
+ back to the obstack it came from. */
+ stab_secname = demand_copy_C_string (&length);
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == ',')
+ input_line_pointer++;
+ else
+ {
+ as_bad (_("comma missing in .xstabs"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ /* To get the name of the stab string section, simply add "str" to
+ the stab section name. */
+ if (saved_secname == 0 || strcmp (saved_secname, stab_secname))
+ {
+ stabstr_secname = (char *) xmalloc (strlen (stab_secname) + 4);
+ strcpy (stabstr_secname, stab_secname);
+ strcat (stabstr_secname, "str");
+ if (saved_secname)
+ {
+ free (saved_secname);
+ free (saved_strsecname);
+ }
+ saved_secname = stab_secname;
+ saved_strsecname = stabstr_secname;
+ }
+ s_stab_generic (what, saved_secname, saved_strsecname);
+}
+
+#ifdef S_SET_DESC
+
+/* Frob invented at RMS' request. Set the n_desc of a symbol. */
+
+void
+s_desc (ignore)
+ int ignore;
+{
+ char *name;
+ char c;
+ char *p;
+ symbolS *symbolP;
+ int temp;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
+ {
+ *p = 0;
+ as_bad (_("Expected comma after name \"%s\""), name);
+ *p = c;
+ ignore_rest_of_line ();
+ }
+ else
+ {
+ input_line_pointer++;
+ temp = get_absolute_expression ();
+ *p = 0;
+ symbolP = symbol_find_or_make (name);
+ *p = c;
+ S_SET_DESC (symbolP, temp);
+ }
+ demand_empty_rest_of_line ();
+} /* s_desc() */
+
+#endif /* defined (S_SET_DESC) */
+
+/* Generate stabs debugging information to denote the main source file. */
+
+void
+stabs_generate_asm_file ()
+{
+ char *file;
+ unsigned int lineno;
+
+ as_where (&file, &lineno);
+ generate_asm_file (N_SO, file);
+}
+
+/* Generate stabs debugging information to denote the source file.
+ TYPE is one of N_SO, N_SOL. */
+
+static void
+generate_asm_file (type, file)
+ int type;
+ char *file;
+{
+ static char *last_file;
+ static int label_count;
+ char *hold;
+ char buf[100];
+ char sym[30];
+
+ /* Rather than try to do this in some efficient fashion, we just
+ generate a string and then parse it again. That lets us use the
+ existing stabs hook, which expect to see a string, rather than
+ inventing new ones. */
+
+ hold = input_line_pointer;
+
+ if (last_file == NULL
+ || strcmp (last_file, file) != 0)
+ {
+ sprintf (sym, "%sF%d", FAKE_LABEL_NAME, label_count);
+ ++label_count;
+
+ sprintf (buf, "\"%s\",%d,0,0,%s\n", file, type, sym);
+ input_line_pointer = buf;
+ s_stab ('s');
+ colon (sym);
+
+ if (last_file != NULL)
+ free (last_file);
+ last_file = xstrdup (file);
+ }
+
+ input_line_pointer = hold;
+}
+
+/* Generate stabs debugging information for the current line. This is
+ used to produce debugging information for an assembler file. */
+
+void
+stabs_generate_asm_lineno ()
+{
+ static int label_count;
+ char *hold;
+ char *file;
+ unsigned int lineno;
+ char *buf;
+ char sym[30];
+
+ /* Rather than try to do this in some efficient fashion, we just
+ generate a string and then parse it again. That lets us use the
+ existing stabs hook, which expect to see a string, rather than
+ inventing new ones. */
+
+ hold = input_line_pointer;
+
+ as_where (&file, &lineno);
+
+ generate_asm_file (N_SOL, file);
+
+ sprintf (sym, "%sL%d", FAKE_LABEL_NAME, label_count);
+ ++label_count;
+
+ if (in_dot_func_p)
+ {
+ buf = (char *) alloca (100 + strlen (current_function_label));
+ sprintf (buf, "%d,0,%d,%s-%s\n", N_SLINE, lineno,
+ sym, current_function_label);
+ }
+ else
+ {
+ buf = (char *) alloca (100);
+ sprintf (buf, "%d,0,%d,%s\n", N_SLINE, lineno, sym);
+ }
+ input_line_pointer = buf;
+ s_stab ('n');
+ colon (sym);
+
+ input_line_pointer = hold;
+}
+
+/* Emit a function stab.
+ All assembler functions are assumed to have return type `void'. */
+
+void
+stabs_generate_asm_func (funcname, startlabname)
+ const char *funcname;
+ const char *startlabname;
+{
+ static int void_emitted_p;
+ char *hold = input_line_pointer;
+ char *buf;
+ char *file;
+ unsigned int lineno;
+
+ if (! void_emitted_p)
+ {
+ input_line_pointer = "\"void:t1=1\",128,0,0,0";
+ s_stab ('s');
+ void_emitted_p = 1;
+ }
+
+ as_where (&file, &lineno);
+ asprintf (&buf, "\"%s:F1\",%d,0,%d,%s",
+ funcname, N_FUN, lineno + 1, startlabname);
+ input_line_pointer = buf;
+ s_stab ('s');
+ free (buf);
+
+ input_line_pointer = hold;
+ current_function_label = xstrdup (startlabname);
+ in_dot_func_p = 1;
+}
+
+/* Emit a stab to record the end of a function. */
+
+void
+stabs_generate_asm_endfunc (funcname, startlabname)
+ const char *funcname;
+ const char *startlabname;
+{
+ static int label_count;
+ char *hold = input_line_pointer;
+ char *buf;
+ char sym[30];
+
+ sprintf (sym, "%sendfunc%d", FAKE_LABEL_NAME, label_count);
+ ++label_count;
+ colon (sym);
+
+ asprintf (&buf, "\"\",%d,0,0,%s-%s", N_FUN, sym, startlabname);
+ input_line_pointer = buf;
+ s_stab ('s');
+ free (buf);
+
+ input_line_pointer = hold;
+ in_dot_func_p = 0;
+ current_function_label = NULL;
+}
diff --git a/gas/stamp-h.in b/gas/stamp-h.in
new file mode 100644
index 0000000000..9788f70238
--- /dev/null
+++ b/gas/stamp-h.in
@@ -0,0 +1 @@
+timestamp
diff --git a/gas/struc-symbol.h b/gas/struc-symbol.h
new file mode 100644
index 0000000000..aeb0405067
--- /dev/null
+++ b/gas/struc-symbol.h
@@ -0,0 +1,166 @@
+/* struct_symbol.h - Internal symbol structure
+ Copyright (C) 1987, 92, 93, 94, 95, 1998 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#ifndef __struc_symbol_h__
+#define __struc_symbol_h__
+
+#ifdef BFD_ASSEMBLER
+/* The BFD code wants to walk the list in both directions. */
+#undef SYMBOLS_NEED_BACKPOINTERS
+#define SYMBOLS_NEED_BACKPOINTERS
+#endif
+
+/* our version of an nlist node */
+struct symbol
+{
+#ifndef BFD_ASSEMBLER
+ /* The (4-origin) position of sy_name in the symbol table of the object
+ file. This will be 0 for (nameless) .stabd symbols.
+
+ Not used until write_object_file() time. */
+ unsigned long sy_name_offset;
+
+ /* What we write in .o file (if permitted). */
+ obj_symbol_type sy_symbol;
+
+ /* The 24 bit symbol number. Symbol numbers start at 0 and are unsigned. */
+ long sy_number;
+#else
+ /* BFD symbol */
+ asymbol *bsym;
+#endif
+
+ /* The value of the symbol. */
+ expressionS sy_value;
+
+ /* Forwards and (optionally) backwards chain pointers. */
+ struct symbol *sy_next;
+#ifdef SYMBOLS_NEED_BACKPOINTERS
+ struct symbol *sy_previous;
+#endif /* SYMBOLS_NEED_BACKPOINTERS */
+
+ /* Pointer to the frag this symbol is attached to, if any.
+ Otherwise, NULL. */
+ struct frag *sy_frag;
+
+ unsigned int written : 1;
+ /* Whether symbol value has been completely resolved (used during
+ final pass over symbol table). */
+ unsigned int sy_resolved : 1;
+ /* Whether the symbol value is currently being resolved (used to
+ detect loops in symbol dependencies). */
+ unsigned int sy_resolving : 1;
+ /* Whether the symbol value is used in a reloc. This is used to
+ ensure that symbols used in relocs are written out, even if they
+ are local and would otherwise not be. */
+ unsigned int sy_used_in_reloc : 1;
+
+ /* Whether the symbol is used as an operand or in an expression.
+ NOTE: Not all the backends keep this information accurate;
+ backends which use this bit are responsible for setting it when
+ a symbol is used in backend routines. */
+ unsigned int sy_used : 1;
+
+ /* This is set if the symbol is defined in an MRI common section.
+ We handle such sections as single common symbols, so symbols
+ defined within them must be treated specially by the relocation
+ routines. */
+ unsigned int sy_mri_common : 1;
+
+#ifdef OBJ_SYMFIELD_TYPE
+ OBJ_SYMFIELD_TYPE sy_obj;
+#endif
+
+#ifdef TC_SYMFIELD_TYPE
+ TC_SYMFIELD_TYPE sy_tc;
+#endif
+
+#ifdef TARGET_SYMBOL_FIELDS
+ TARGET_SYMBOL_FIELDS
+#endif
+};
+
+typedef struct symbol symbolS;
+
+#ifndef WORKING_DOT_WORD
+struct broken_word
+ {
+ /* Linked list -- one of these structures per ".word x-y+C"
+ expression. */
+ struct broken_word *next_broken_word;
+ /* Segment and subsegment for broken word. */
+ segT seg;
+ subsegT subseg;
+ /* Which frag is this broken word in? */
+ fragS *frag;
+ /* Where in the frag is it? */
+ char *word_goes_here;
+ /* Where to add the break. */
+ fragS *dispfrag; /* where to add the break */
+ /* Operands of expression. */
+ symbolS *add;
+ symbolS *sub;
+ offsetT addnum;
+
+ int added; /* nasty thing happend yet? */
+ /* 1: added and has a long-jump */
+ /* 2: added but uses someone elses long-jump */
+
+ /* Pointer to broken_word with a similar long-jump. */
+ struct broken_word *use_jump;
+ };
+extern struct broken_word *broken_words;
+#endif /* ndef WORKING_DOT_WORD */
+
+/*
+ * Current means for getting from symbols to segments and vice verse.
+ * This will change for infinite-segments support (e.g. COFF).
+ */
+extern const segT N_TYPE_seg[]; /* subseg.c */
+
+#define SEGMENT_TO_SYMBOL_TYPE(seg) ( seg_N_TYPE [(int) (seg)] )
+extern const short seg_N_TYPE[];/* subseg.c */
+
+#define N_REGISTER 30 /* Fake N_TYPE value for SEG_REGISTER */
+
+void symbol_clear_list_pointers PARAMS ((symbolS * symbolP));
+
+#ifdef SYMBOLS_NEED_BACKPOINTERS
+
+void symbol_insert PARAMS ((symbolS * addme, symbolS * target,
+ symbolS ** rootP, symbolS ** lastP));
+void symbol_remove PARAMS ((symbolS * symbolP, symbolS ** rootP,
+ symbolS ** lastP));
+
+#define symbol_previous(s) ((s)->sy_previous)
+
+#endif /* SYMBOLS_NEED_BACKPOINTERS */
+
+void verify_symbol_chain PARAMS ((symbolS * rootP, symbolS * lastP));
+void verify_symbol_chain_2 PARAMS ((symbolS * symP));
+
+void symbol_append PARAMS ((symbolS * addme, symbolS * target,
+ symbolS ** rootP, symbolS ** lastP));
+
+#define symbol_next(s) ((s)->sy_next)
+
+#endif /* __struc_symbol_h__ */
+
+/* end of struc-symbol.h */
diff --git a/gas/subsegs.c b/gas/subsegs.c
new file mode 100644
index 0000000000..bdf28688bd
--- /dev/null
+++ b/gas/subsegs.c
@@ -0,0 +1,618 @@
+/* subsegs.c - subsegments -
+ Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 1997
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/*
+ * Segments & sub-segments.
+ */
+
+#include "as.h"
+
+#include "subsegs.h"
+#include "obstack.h"
+
+frchainS *frchain_root, *frchain_now;
+
+static struct obstack frchains;
+
+#ifndef BFD_ASSEMBLER
+#ifdef MANY_SEGMENTS
+segment_info_type segment_info[SEG_MAXIMUM_ORDINAL];
+
+#else
+/* Commented in "subsegs.h". */
+frchainS *data0_frchainP, *bss0_frchainP;
+
+#endif /* MANY_SEGMENTS */
+char const *const seg_name[] =
+{
+ "absolute",
+#ifdef MANY_SEGMENTS
+ "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9",
+ "e10", "e11", "e12", "e13", "e14", "e15", "e16", "e17", "e18", "e19",
+ "e20", "e21", "e22", "e23", "e24", "e25", "e26", "e27", "e28", "e29",
+ "e30", "e31", "e32", "e33", "e34", "e35", "e36", "e37", "e38", "e39",
+#else
+ "text",
+ "data",
+ "bss",
+#endif /* MANY_SEGMENTS */
+ "unknown",
+ "ASSEMBLER-INTERNAL-LOGIC-ERROR!",
+ "expr",
+ "debug",
+ "transfert vector preload",
+ "transfert vector postload",
+ "register",
+ "",
+}; /* Used by error reporters, dumpers etc. */
+#else /* BFD_ASSEMBLER */
+
+/* Gas segment information for bfd_abs_section_ptr and
+ bfd_und_section_ptr. */
+static segment_info_type *abs_seg_info;
+static segment_info_type *und_seg_info;
+
+#endif /* BFD_ASSEMBLER */
+
+static void subseg_set_rest PARAMS ((segT, subsegT));
+
+static fragS dummy_frag;
+
+static frchainS absolute_frchain;
+
+void
+subsegs_begin ()
+{
+ /* Check table(s) seg_name[], seg_N_TYPE[] is in correct order */
+#if !defined (MANY_SEGMENTS) && !defined (BFD_ASSEMBLER)
+ know (SEG_ABSOLUTE == 0);
+ know (SEG_TEXT == 1);
+ know (SEG_DATA == 2);
+ know (SEG_BSS == 3);
+ know (SEG_UNKNOWN == 4);
+ know (SEG_GOOF == 5);
+ know (SEG_EXPR == 6);
+ know (SEG_DEBUG == 7);
+ know (SEG_NTV == 8);
+ know (SEG_PTV == 9);
+ know (SEG_REGISTER == 10);
+ know (SEG_MAXIMUM_ORDINAL == SEG_REGISTER);
+#endif
+
+ obstack_begin (&frchains, chunksize);
+#if __GNUC__ >= 2
+ obstack_alignment_mask (&frchains) = __alignof__ (frchainS) - 1;
+#endif
+
+ frchain_root = NULL;
+ frchain_now = NULL; /* Warn new_subseg() that we are booting. */
+
+ frag_now = &dummy_frag;
+
+#ifndef BFD_ASSEMBLER
+ now_subseg = 42; /* Lie for 1st call to subseg_new. */
+#ifdef MANY_SEGMENTS
+ {
+ int i;
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ {
+ subseg_set (i, 0);
+ segment_info[i].frchainP = frchain_now;
+ }
+ }
+#else
+ subseg_set (SEG_DATA, 0); /* .data 0 */
+ data0_frchainP = frchain_now;
+
+ subseg_set (SEG_BSS, 0);
+ bss0_frchainP = frchain_now;
+
+#endif /* ! MANY_SEGMENTS */
+#endif /* ! BFD_ASSEMBLER */
+
+ absolute_frchain.frch_seg = absolute_section;
+ absolute_frchain.frch_subseg = 0;
+#ifdef BFD_ASSEMBLER
+ absolute_frchain.fix_root = absolute_frchain.fix_tail = 0;
+#endif
+ absolute_frchain.frch_frag_now = &zero_address_frag;
+ absolute_frchain.frch_root = absolute_frchain.frch_last = &zero_address_frag;
+}
+
+/*
+ * subseg_change()
+ *
+ * Change the subsegment we are in, BUT DO NOT MAKE A NEW FRAG for the
+ * subsegment. If we are already in the correct subsegment, change nothing.
+ * This is used eg as a worker for subseg_set [which does make a new frag_now]
+ * and for changing segments after we have read the source. We construct eg
+ * fixSs even after the source file is read, so we do have to keep the
+ * segment context correct.
+ */
+void
+subseg_change (seg, subseg)
+ register segT seg;
+ register int subseg;
+{
+ now_seg = seg;
+ now_subseg = subseg;
+
+ if (now_seg == absolute_section)
+ return;
+
+#ifdef BFD_ASSEMBLER
+ {
+ segment_info_type *seginfo;
+ seginfo = (segment_info_type *) bfd_get_section_userdata (stdoutput, seg);
+ if (! seginfo)
+ {
+ seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
+ memset ((PTR) seginfo, 0, sizeof (*seginfo));
+ seginfo->fix_root = NULL;
+ seginfo->fix_tail = NULL;
+ seginfo->bfd_section = seg;
+ seginfo->sym = 0;
+ if (seg == bfd_abs_section_ptr)
+ abs_seg_info = seginfo;
+ else if (seg == bfd_und_section_ptr)
+ und_seg_info = seginfo;
+ else
+ bfd_set_section_userdata (stdoutput, seg, (PTR) seginfo);
+ }
+ }
+#else
+#ifdef MANY_SEGMENTS
+ seg_fix_rootP = &segment_info[seg].fix_root;
+ seg_fix_tailP = &segment_info[seg].fix_tail;
+#else
+ if (seg == SEG_DATA)
+ {
+ seg_fix_rootP = &data_fix_root;
+ seg_fix_tailP = &data_fix_tail;
+ }
+ else if (seg == SEG_TEXT)
+ {
+ seg_fix_rootP = &text_fix_root;
+ seg_fix_tailP = &text_fix_tail;
+ }
+ else
+ {
+ know (seg == SEG_BSS);
+ seg_fix_rootP = &bss_fix_root;
+ seg_fix_tailP = &bss_fix_tail;
+ }
+
+#endif
+#endif
+}
+
+static void
+subseg_set_rest (seg, subseg)
+ segT seg;
+ subsegT subseg;
+{
+ register frchainS *frcP; /* crawl frchain chain */
+ register frchainS **lastPP; /* address of last pointer */
+ frchainS *newP; /* address of new frchain */
+
+ mri_common_symbol = NULL;
+
+ if (frag_now && frchain_now)
+ frchain_now->frch_frag_now = frag_now;
+
+ assert (frchain_now == 0
+ || now_seg == undefined_section
+ || now_seg == absolute_section
+ || frchain_now->frch_last == frag_now);
+
+ subseg_change (seg, (int) subseg);
+
+ if (seg == absolute_section)
+ {
+ frchain_now = &absolute_frchain;
+ frag_now = &zero_address_frag;
+ return;
+ }
+
+ assert (frchain_now == 0
+ || now_seg == undefined_section
+ || frchain_now->frch_last == frag_now);
+
+ /*
+ * Attempt to find or make a frchain for that sub seg.
+ * Crawl along chain of frchainSs, begins @ frchain_root.
+ * If we need to make a frchainS, link it into correct
+ * position of chain rooted in frchain_root.
+ */
+ for (frcP = *(lastPP = &frchain_root);
+ frcP && frcP->frch_seg <= seg;
+ frcP = *(lastPP = &frcP->frch_next))
+ {
+ if (frcP->frch_seg == seg
+ && frcP->frch_subseg >= subseg)
+ {
+ break;
+ }
+ }
+ /*
+ * frcP: Address of the 1st frchainS in correct segment with
+ * frch_subseg >= subseg.
+ * We want to either use this frchainS, or we want
+ * to insert a new frchainS just before it.
+ *
+ * If frcP==NULL, then we are at the end of the chain
+ * of frchainS-s. A NULL frcP means we fell off the end
+ * of the chain looking for a
+ * frch_subseg >= subseg, so we
+ * must make a new frchainS.
+ *
+ * If we ever maintain a pointer to
+ * the last frchainS in the chain, we change that pointer
+ * ONLY when frcP==NULL.
+ *
+ * lastPP: Address of the pointer with value frcP;
+ * Never NULL.
+ * May point to frchain_root.
+ *
+ */
+ if (!frcP
+ || (frcP->frch_seg > seg
+ || frcP->frch_subseg > subseg)) /* Kinky logic only works with 2 segments. */
+ {
+ /*
+ * This should be the only code that creates a frchainS.
+ */
+ newP = (frchainS *) obstack_alloc (&frchains, sizeof (frchainS));
+ newP->frch_subseg = subseg;
+ newP->frch_seg = seg;
+#ifdef BFD_ASSEMBLER
+ newP->fix_root = NULL;
+ newP->fix_tail = NULL;
+#endif
+ obstack_begin (&newP->frch_obstack, chunksize);
+#if __GNUC__ >= 2
+ obstack_alignment_mask (&newP->frch_obstack) = __alignof__ (fragS) - 1;
+#endif
+ newP->frch_frag_now = frag_alloc (&newP->frch_obstack);
+ newP->frch_frag_now->fr_type = rs_fill;
+
+ newP->frch_root = newP->frch_last = newP->frch_frag_now;
+
+ *lastPP = newP;
+ newP->frch_next = frcP; /* perhaps NULL */
+
+#ifdef BFD_ASSEMBLER
+ {
+ segment_info_type *seginfo;
+ seginfo = seg_info (seg);
+ if (seginfo && seginfo->frchainP == frcP)
+ seginfo->frchainP = newP;
+ }
+#endif
+
+ frcP = newP;
+ }
+ /*
+ * Here with frcP pointing to the frchainS for subseg.
+ */
+ frchain_now = frcP;
+ frag_now = frcP->frch_frag_now;
+
+ assert (frchain_now->frch_last == frag_now);
+}
+
+/*
+ * subseg_set(segT, subsegT)
+ *
+ * If you attempt to change to the current subsegment, nothing happens.
+ *
+ * In: segT, subsegT code for new subsegment.
+ * frag_now -> incomplete frag for current subsegment.
+ * If frag_now==NULL, then there is no old, incomplete frag, so
+ * the old frag is not closed off.
+ *
+ * Out: now_subseg, now_seg updated.
+ * Frchain_now points to the (possibly new) struct frchain for this
+ * sub-segment.
+ * Frchain_root updated if needed.
+ */
+
+#ifndef BFD_ASSEMBLER
+
+segT
+subseg_new (segname, subseg)
+ const char *segname;
+ subsegT subseg;
+{
+ int i;
+
+ for (i = 0; i < (int) SEG_MAXIMUM_ORDINAL; i++)
+ {
+ const char *s;
+
+ s = segment_name ((segT) i);
+ if (strcmp (segname, s) == 0
+ || (segname[0] == '.'
+ && strcmp (segname + 1, s) == 0))
+ {
+ subseg_set ((segT) i, subseg);
+ return (segT) i;
+ }
+#ifdef obj_segment_name
+ s = obj_segment_name ((segT) i);
+ if (strcmp (segname, s) == 0
+ || (segname[0] == '.'
+ && strcmp (segname + 1, s) == 0))
+ {
+ subseg_set ((segT) i, subseg);
+ return (segT) i;
+ }
+#endif
+ }
+
+#ifdef obj_add_segment
+ {
+ segT new_seg;
+ new_seg = obj_add_segment (segname);
+ subseg_set (new_seg, subseg);
+ return new_seg;
+ }
+#else
+ as_bad (_("Attempt to switch to nonexistent segment \"%s\""), segname);
+ return now_seg;
+#endif
+}
+
+void
+subseg_set (seg, subseg) /* begin assembly for a new sub-segment */
+ register segT seg; /* SEG_DATA or SEG_TEXT */
+ register subsegT subseg;
+{
+#ifndef MANY_SEGMENTS
+ know (seg == SEG_DATA
+ || seg == SEG_TEXT
+ || seg == SEG_BSS
+ || seg == SEG_ABSOLUTE);
+#endif
+
+ if (seg != now_seg || subseg != now_subseg)
+ { /* we just changed sub-segments */
+ subseg_set_rest (seg, subseg);
+ }
+ mri_common_symbol = NULL;
+}
+
+#else /* BFD_ASSEMBLER */
+
+segT
+subseg_get (segname, force_new)
+ const char *segname;
+ int force_new;
+{
+ segT secptr;
+ segment_info_type *seginfo;
+ const char *now_seg_name = (now_seg
+ ? bfd_get_section_name (stdoutput, now_seg)
+ : 0);
+
+ if (!force_new
+ && now_seg_name
+ && (now_seg_name == segname
+ || !strcmp (now_seg_name, segname)))
+ return now_seg;
+
+ if (!force_new)
+ secptr = bfd_make_section_old_way (stdoutput, segname);
+ else
+ secptr = bfd_make_section_anyway (stdoutput, segname);
+
+ seginfo = seg_info (secptr);
+ if (! seginfo)
+ {
+ /* Check whether output_section is set first because secptr may
+ be bfd_abs_section_ptr. */
+ if (secptr->output_section != secptr)
+ secptr->output_section = secptr;
+ seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
+ memset ((PTR) seginfo, 0, sizeof (*seginfo));
+ seginfo->fix_root = NULL;
+ seginfo->fix_tail = NULL;
+ seginfo->bfd_section = secptr;
+ if (secptr == bfd_abs_section_ptr)
+ abs_seg_info = seginfo;
+ else if (secptr == bfd_und_section_ptr)
+ und_seg_info = seginfo;
+ else
+ bfd_set_section_userdata (stdoutput, secptr, (PTR) seginfo);
+ seginfo->frchainP = NULL;
+ seginfo->lineno_list_head = seginfo->lineno_list_tail = NULL;
+ seginfo->sym = NULL;
+ seginfo->dot = NULL;
+ }
+ return secptr;
+}
+
+segT
+subseg_new (segname, subseg)
+ const char *segname;
+ subsegT subseg;
+{
+ segT secptr;
+ segment_info_type *seginfo;
+
+ secptr = subseg_get (segname, 0);
+ subseg_set_rest (secptr, subseg);
+ seginfo = seg_info (secptr);
+ if (! seginfo->frchainP)
+ seginfo->frchainP = frchain_now;
+ return secptr;
+}
+
+/* Like subseg_new, except a new section is always created, even if
+ a section with that name already exists. */
+segT
+subseg_force_new (segname, subseg)
+ const char *segname;
+ subsegT subseg;
+{
+ segT secptr;
+ segment_info_type *seginfo;
+
+ secptr = subseg_get (segname, 1);
+ subseg_set_rest (secptr, subseg);
+ seginfo = seg_info (secptr);
+ if (! seginfo->frchainP)
+ seginfo->frchainP = frchain_now;
+ return secptr;
+}
+
+void
+subseg_set (secptr, subseg)
+ segT secptr;
+ subsegT subseg;
+{
+ if (! (secptr == now_seg && subseg == now_subseg))
+ subseg_set_rest (secptr, subseg);
+ mri_common_symbol = NULL;
+}
+
+#ifndef obj_sec_sym_ok_for_reloc
+#define obj_sec_sym_ok_for_reloc(SEC) 0
+#endif
+
+/* Get the gas information we are storing for a section. */
+
+segment_info_type *
+seg_info (sec)
+ segT sec;
+{
+ if (sec == bfd_abs_section_ptr)
+ return abs_seg_info;
+ else if (sec == bfd_und_section_ptr)
+ return und_seg_info;
+ else
+ return (segment_info_type *) bfd_get_section_userdata (stdoutput, sec);
+}
+
+symbolS *
+section_symbol (sec)
+ segT sec;
+{
+ segment_info_type *seginfo = seg_info (sec);
+ symbolS *s;
+
+ if (seginfo == 0)
+ abort ();
+ if (seginfo->sym)
+ return seginfo->sym;
+
+#ifndef EMIT_SECTION_SYMBOLS
+#define EMIT_SECTION_SYMBOLS 1
+#endif
+
+ if (! EMIT_SECTION_SYMBOLS
+#ifdef BFD_ASSEMBLER
+ || symbol_table_frozen
+#endif
+ )
+ {
+ /* Here we know it won't be going into the symbol table. */
+ s = symbol_create (sec->name, sec, 0, &zero_address_frag);
+ }
+ else
+ {
+ s = symbol_find_base (sec->name, 0);
+ if (s == NULL)
+ s = symbol_new (sec->name, sec, 0, &zero_address_frag);
+ else
+ {
+ if (S_GET_SEGMENT (s) == undefined_section)
+ {
+ S_SET_SEGMENT (s, sec);
+ s->sy_frag = &zero_address_frag;
+ }
+ }
+ }
+
+ S_CLEAR_EXTERNAL (s);
+
+ /* Use the BFD section symbol, if possible. */
+ if (obj_sec_sym_ok_for_reloc (sec))
+ s->bsym = sec->symbol;
+
+ seginfo->sym = s;
+ return s;
+}
+
+#endif /* BFD_ASSEMBLER */
+
+void
+subsegs_print_statistics (file)
+ FILE *file;
+{
+ frchainS *frchp;
+ fprintf (file, "frag chains:\n");
+ for (frchp = frchain_root; frchp; frchp = frchp->frch_next)
+ {
+ int count = 0;
+ fragS *fragp;
+
+ /* If frch_subseg is non-zero, it's probably been chained onto
+ the end of a previous subsection. Don't count it again. */
+ if (frchp->frch_subseg != 0)
+ continue;
+
+ /* Skip gas-internal sections. */
+ if (segment_name (frchp->frch_seg)[0] == '*')
+ continue;
+
+ for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next)
+ {
+#if 0
+ switch (fragp->fr_type)
+ {
+ case rs_fill:
+ fprintf (file, "f"); break;
+ case rs_align:
+ fprintf (file, "a"); break;
+ case rs_align_code:
+ fprintf (file, "c"); break;
+ case rs_org:
+ fprintf (file, "o"); break;
+ case rs_machine_dependent:
+ fprintf (file, "m"); break;
+ case rs_space:
+ fprintf (file, "s"); break;
+ case 0:
+ fprintf (file, "0"); break;
+ default:
+ fprintf (file, "?"); break;
+ }
+#endif
+ count++;
+ }
+ fprintf (file, "\n");
+ fprintf (file, "\t%p %-10s\t%10d frags\n", frchp,
+ segment_name (frchp->frch_seg), count);
+ }
+}
+
+/* end of subsegs.c */
diff --git a/gas/subsegs.h b/gas/subsegs.h
new file mode 100644
index 0000000000..4840d5b5c2
--- /dev/null
+++ b/gas/subsegs.h
@@ -0,0 +1,159 @@
+/* subsegs.h -> subsegs.c
+ Copyright (C) 1987, 92, 93, 94, 95, 96, 1998 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/*
+ * For every sub-segment the user mentions in the ASsembler program,
+ * we make one struct frchain. Each sub-segment has exactly one struct frchain
+ * and vice versa.
+ *
+ * Struct frchain's are forward chained (in ascending order of sub-segment
+ * code number). The chain runs through frch_next of each subsegment.
+ * This makes it hard to find a subsegment's frags
+ * if programmer uses a lot of them. Most programs only use text0 and
+ * data0, so they don't suffer. At least this way:
+ * (1) There are no "arbitrary" restrictions on how many subsegments
+ * can be programmed;
+ * (2) Subsegments' frchain-s are (later) chained together in the order in
+ * which they are emitted for object file viz text then data.
+ *
+ * From each struct frchain dangles a chain of struct frags. The frags
+ * represent code fragments, for that sub-segment, forward chained.
+ */
+
+#include "obstack.h"
+
+struct frchain /* control building of a frag chain */
+{ /* FRCH = FRagment CHain control */
+ struct frag *frch_root; /* 1st struct frag in chain, or NULL */
+ struct frag *frch_last; /* last struct frag in chain, or NULL */
+ struct frchain *frch_next; /* next in chain of struct frchain-s */
+ segT frch_seg; /* SEG_TEXT or SEG_DATA. */
+ subsegT frch_subseg; /* subsegment number of this chain */
+#ifdef BFD_ASSEMBLER
+ fixS *fix_root; /* Root of fixups for this subsegment. */
+ fixS *fix_tail; /* Last fixup for this subsegment. */
+#endif
+ struct obstack frch_obstack; /* for objects in this frag chain */
+ fragS *frch_frag_now; /* frag_now for this subsegment */
+};
+
+typedef struct frchain frchainS;
+
+/* All subsegments' chains hang off here. NULL means no frchains yet. */
+extern frchainS *frchain_root;
+
+/* Frchain we are assembling into now. That is, the current segment's
+ frag chain, even if it contains no (complete) frags. */
+extern frchainS *frchain_now;
+
+
+typedef struct segment_info_struct
+{
+ frchainS *frchainP;
+ unsigned int hadone : 1;
+
+ /* This field is set if this is a .bss section which does not really
+ have any contents. Once upon a time a .bss section did not have
+ any frags, but that is no longer true. This field prevent the
+ SEC_HAS_CONTENTS flag from being set for the section even if
+ there are frags. */
+ unsigned int bss : 1;
+
+ int user_stuff;
+
+ /* Fixups for this segment. If BFD_ASSEMBLER, this is only valid
+ after the frchains are run together. */
+ fixS *fix_root;
+ fixS *fix_tail;
+
+#if defined (MANY_SEGMENTS) && !defined (BFD_ASSEMBLER)
+ struct internal_scnhdr scnhdr;
+ enum linkonce_type linkonce;
+ const char *name;
+#endif
+
+ symbolS *dot;
+
+ struct lineno_list *lineno_list_head;
+ struct lineno_list *lineno_list_tail;
+
+#ifdef BFD_ASSEMBLER
+ /* Which BFD section does this gas segment correspond to? */
+ asection *bfd_section;
+
+ /* NULL, or pointer to the gas symbol that is the section symbol for
+ this section. sym->bsym and bfd_section->symbol should be the same. */
+ symbolS *sym;
+#endif
+
+ union
+ {
+ /* Current size of section holding stabs strings. */
+ unsigned long stab_string_size;
+ /* Initial frag for ELF. */
+ char *p;
+ }
+ stabu;
+
+#ifdef NEED_LITERAL_POOL
+ unsigned long literal_pool_size;
+#endif
+
+#ifdef TC_SEGMENT_INFO_TYPE
+ TC_SEGMENT_INFO_TYPE tc_segment_info_data;
+#endif
+} segment_info_type;
+
+#ifdef BFD_ASSEMBLER
+
+extern segment_info_type *seg_info PARAMS ((segT));
+extern symbolS *section_symbol PARAMS ((segT));
+
+#else /* ! BFD_ASSEMBLER */
+
+#ifdef MANY_SEGMENTS
+
+extern segment_info_type segment_info[];
+
+#define seg_info(SEC) (&segment_info[SEC])
+
+#else
+
+/* Sentinel for frchain crawling. Points to the 1st data-segment
+ frchain. (Which is pointed to by the last text-segment frchain.) */
+extern frchainS *data0_frchainP;
+extern frchainS *bss0_frchainP;
+
+/* Dummy so stuff can compile. Should never be used. */
+struct seg_info_trash {
+ struct {
+ unsigned stab_string_size : 1;
+ } stabu;
+ unsigned hadone : 1;
+};
+#define seg_info(S) (abort (), (struct seg_info_trash *) 0)
+
+#endif
+
+#endif /* ! BFD_ASSEMBLER */
+
+extern void subsegs_print_statistics PARAMS ((FILE *));
+
+/* end of subsegs.h */
diff --git a/gas/symbols.c b/gas/symbols.c
new file mode 100644
index 0000000000..a1cde6a7de
--- /dev/null
+++ b/gas/symbols.c
@@ -0,0 +1,1785 @@
+/* symbols.c -symbol table-
+ Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 97, 1998
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* #define DEBUG_SYMS / * to debug symbol list maintenance */
+
+#include <ctype.h>
+
+#include "as.h"
+
+#include "obstack.h" /* For "symbols.h" */
+#include "subsegs.h"
+
+/* This is non-zero if symbols are case sensitive, which is the
+ default. */
+int symbols_case_sensitive = 1;
+
+#ifndef WORKING_DOT_WORD
+extern int new_broken_words;
+#endif
+
+/* symbol-name => struct symbol pointer */
+static struct hash_control *sy_hash;
+
+/* Below are commented in "symbols.h". */
+symbolS *symbol_rootP;
+symbolS *symbol_lastP;
+symbolS abs_symbol;
+
+#ifdef DEBUG_SYMS
+#define debug_verify_symchain verify_symbol_chain
+#else
+#define debug_verify_symchain(root, last) ((void) 0)
+#endif
+
+struct obstack notes;
+
+static void fb_label_init PARAMS ((void));
+static long dollar_label_instance PARAMS ((long));
+static long fb_label_instance PARAMS ((long));
+
+static void print_binary PARAMS ((FILE *, const char *, expressionS *));
+
+/* symbol_new()
+
+ Return a pointer to a new symbol. Die if we can't make a new
+ symbol. Fill in the symbol's values. Add symbol to end of symbol
+ chain.
+
+ This function should be called in the general case of creating a
+ symbol. However, if the output file symbol table has already been
+ set, and you are certain that this symbol won't be wanted in the
+ output file, you can call symbol_create. */
+
+symbolS *
+symbol_new (name, segment, valu, frag)
+ const char *name;
+ segT segment;
+ valueT valu;
+ fragS *frag;
+{
+ symbolS *symbolP = symbol_create (name, segment, valu, frag);
+
+ /*
+ * Link to end of symbol chain.
+ */
+#ifdef BFD_ASSEMBLER
+ {
+ extern int symbol_table_frozen;
+ if (symbol_table_frozen)
+ abort ();
+ }
+#endif
+ symbol_append (symbolP, symbol_lastP, &symbol_rootP, &symbol_lastP);
+
+ return symbolP;
+}
+
+symbolS *
+symbol_create (name, segment, valu, frag)
+ const char *name; /* It is copied, the caller can destroy/modify */
+ segT segment; /* Segment identifier (SEG_<something>) */
+ valueT valu; /* Symbol value */
+ fragS *frag; /* Associated fragment */
+{
+ unsigned int name_length;
+ char *preserved_copy_of_name;
+ symbolS *symbolP;
+
+ name_length = strlen (name) + 1; /* +1 for \0 */
+ obstack_grow (&notes, name, name_length);
+ preserved_copy_of_name = obstack_finish (&notes);
+#ifdef STRIP_UNDERSCORE
+ if (preserved_copy_of_name[0] == '_')
+ preserved_copy_of_name++;
+#endif
+
+#ifdef tc_canonicalize_symbol_name
+ preserved_copy_of_name =
+ tc_canonicalize_symbol_name (preserved_copy_of_name);
+#endif
+
+ if (! symbols_case_sensitive)
+ {
+ unsigned char *s;
+
+ for (s = (unsigned char *) preserved_copy_of_name; *s != '\0'; s++)
+ if (islower (*s))
+ *s = toupper (*s);
+ }
+
+ symbolP = (symbolS *) obstack_alloc (&notes, sizeof (symbolS));
+
+ /* symbol must be born in some fixed state. This seems as good as any. */
+ memset (symbolP, 0, sizeof (symbolS));
+
+#ifdef BFD_ASSEMBLER
+ symbolP->bsym = bfd_make_empty_symbol (stdoutput);
+ if (symbolP->bsym == NULL)
+ as_perror ("%s", "bfd_make_empty_symbol");
+ symbolP->bsym->udata.p = (PTR) symbolP;
+#endif
+ S_SET_NAME (symbolP, preserved_copy_of_name);
+
+ S_SET_SEGMENT (symbolP, segment);
+ S_SET_VALUE (symbolP, valu);
+ symbol_clear_list_pointers (symbolP);
+
+ symbolP->sy_frag = frag;
+#ifndef BFD_ASSEMBLER
+ symbolP->sy_number = ~0;
+ symbolP->sy_name_offset = (unsigned int) ~0;
+#endif
+
+ obj_symbol_new_hook (symbolP);
+
+#ifdef tc_symbol_new_hook
+ tc_symbol_new_hook (symbolP);
+#endif
+
+ return symbolP;
+}
+
+
+/*
+ * colon()
+ *
+ * We have just seen "<name>:".
+ * Creates a struct symbol unless it already exists.
+ *
+ * Gripes if we are redefining a symbol incompatibly (and ignores it).
+ *
+ */
+symbolS *
+colon (sym_name) /* just seen "x:" - rattle symbols & frags */
+ const char *sym_name; /* symbol name, as a cannonical string */
+ /* We copy this string: OK to alter later. */
+{
+ register symbolS *symbolP; /* symbol we are working with */
+
+ /* Sun local labels go out of scope whenever a non-local symbol is
+ defined. */
+ if (LOCAL_LABELS_DOLLAR)
+ {
+ int local;
+
+#ifdef BFD_ASSEMBLER
+ local = bfd_is_local_label_name (stdoutput, sym_name);
+#else
+ local = LOCAL_LABEL (sym_name);
+#endif
+
+ if (! local)
+ dollar_label_clear ();
+ }
+
+#ifndef WORKING_DOT_WORD
+ if (new_broken_words)
+ {
+ struct broken_word *a;
+ int possible_bytes;
+ fragS *frag_tmp;
+ char *frag_opcode;
+
+ extern const int md_short_jump_size;
+ extern const int md_long_jump_size;
+ possible_bytes = (md_short_jump_size
+ + new_broken_words * md_long_jump_size);
+
+ frag_tmp = frag_now;
+ frag_opcode = frag_var (rs_broken_word,
+ possible_bytes,
+ possible_bytes,
+ (relax_substateT) 0,
+ (symbolS *) broken_words,
+ (offsetT) 0,
+ NULL);
+
+ /* We want to store the pointer to where to insert the jump table in the
+ fr_opcode of the rs_broken_word frag. This requires a little
+ hackery. */
+ while (frag_tmp
+ && (frag_tmp->fr_type != rs_broken_word
+ || frag_tmp->fr_opcode))
+ frag_tmp = frag_tmp->fr_next;
+ know (frag_tmp);
+ frag_tmp->fr_opcode = frag_opcode;
+ new_broken_words = 0;
+
+ for (a = broken_words; a && a->dispfrag == 0; a = a->next_broken_word)
+ a->dispfrag = frag_tmp;
+ }
+#endif /* WORKING_DOT_WORD */
+
+ if ((symbolP = symbol_find (sym_name)) != 0)
+ {
+#ifdef RESOLVE_SYMBOL_REDEFINITION
+ if (RESOLVE_SYMBOL_REDEFINITION (symbolP))
+ return symbolP;
+#endif
+ /*
+ * Now check for undefined symbols
+ */
+ if (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP))
+ {
+ if (S_GET_VALUE (symbolP) == 0)
+ {
+ symbolP->sy_frag = frag_now;
+#ifdef OBJ_VMS
+ S_SET_OTHER(symbolP, const_flag);
+#endif
+ S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
+ S_SET_SEGMENT (symbolP, now_seg);
+#ifdef N_UNDF
+ know (N_UNDF == 0);
+#endif /* if we have one, it better be zero. */
+
+ }
+ else
+ {
+ /*
+ * There are still several cases to check:
+ * A .comm/.lcomm symbol being redefined as
+ * initialized data is OK
+ * A .comm/.lcomm symbol being redefined with
+ * a larger size is also OK
+ *
+ * This only used to be allowed on VMS gas, but Sun cc
+ * on the sparc also depends on it.
+ */
+
+ if (((!S_IS_DEBUG (symbolP)
+ && (!S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP))
+ && S_IS_EXTERNAL (symbolP))
+ || S_GET_SEGMENT (symbolP) == bss_section)
+ && (now_seg == data_section
+ || now_seg == S_GET_SEGMENT (symbolP)))
+ {
+ /*
+ * Select which of the 2 cases this is
+ */
+ if (now_seg != data_section)
+ {
+ /*
+ * New .comm for prev .comm symbol.
+ * If the new size is larger we just
+ * change its value. If the new size
+ * is smaller, we ignore this symbol
+ */
+ if (S_GET_VALUE (symbolP)
+ < ((unsigned) frag_now_fix ()))
+ {
+ S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
+ }
+ }
+ else
+ {
+ /* It is a .comm/.lcomm being converted to initialized
+ data. */
+ symbolP->sy_frag = frag_now;
+#ifdef OBJ_VMS
+ S_SET_OTHER(symbolP, const_flag);
+#endif
+ S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
+ S_SET_SEGMENT (symbolP, now_seg); /* keep N_EXT bit */
+ }
+ }
+ else
+ {
+#if defined (S_GET_OTHER) && defined (S_GET_DESC)
+ as_fatal (_("Symbol \"%s\" is already defined as \"%s\"/%d.%d.%ld."),
+ sym_name,
+ segment_name (S_GET_SEGMENT (symbolP)),
+ S_GET_OTHER (symbolP), S_GET_DESC (symbolP),
+ (long) S_GET_VALUE (symbolP));
+#else
+ as_fatal (_("Symbol \"%s\" is already defined as \"%s\"/%ld."),
+ sym_name,
+ segment_name (S_GET_SEGMENT (symbolP)),
+ (long) S_GET_VALUE (symbolP));
+#endif
+ }
+ } /* if the undefined symbol has no value */
+ }
+ else
+ {
+ /* Don't blow up if the definition is the same */
+ if (!(frag_now == symbolP->sy_frag
+ && S_GET_VALUE (symbolP) == frag_now_fix ()
+ && S_GET_SEGMENT (symbolP) == now_seg))
+ as_fatal (_("Symbol %s already defined."), sym_name);
+ } /* if this symbol is not yet defined */
+
+ }
+ else
+ {
+ symbolP = symbol_new (sym_name, now_seg, (valueT) frag_now_fix (),
+ frag_now);
+#ifdef OBJ_VMS
+ S_SET_OTHER (symbolP, const_flag);
+#endif /* OBJ_VMS */
+
+ symbol_table_insert (symbolP);
+ } /* if we have seen this symbol before */
+
+ if (mri_common_symbol != NULL)
+ {
+ /* This symbol is actually being defined within an MRI common
+ section. This requires special handling. */
+ symbolP->sy_value.X_op = O_symbol;
+ symbolP->sy_value.X_add_symbol = mri_common_symbol;
+ symbolP->sy_value.X_add_number = S_GET_VALUE (mri_common_symbol);
+ symbolP->sy_frag = &zero_address_frag;
+ S_SET_SEGMENT (symbolP, expr_section);
+ symbolP->sy_mri_common = 1;
+ }
+
+#ifdef tc_frob_label
+ tc_frob_label (symbolP);
+#endif
+#ifdef obj_frob_label
+ obj_frob_label (symbolP);
+#endif
+
+ return symbolP;
+}
+
+
+/*
+ * symbol_table_insert()
+ *
+ * Die if we can't insert the symbol.
+ *
+ */
+
+void
+symbol_table_insert (symbolP)
+ symbolS *symbolP;
+{
+ register const char *error_string;
+
+ know (symbolP);
+ know (S_GET_NAME (symbolP));
+
+ if ((error_string = hash_jam (sy_hash, S_GET_NAME (symbolP), (PTR) symbolP)))
+ {
+ as_fatal (_("Inserting \"%s\" into symbol table failed: %s"),
+ S_GET_NAME (symbolP), error_string);
+ } /* on error */
+} /* symbol_table_insert() */
+
+/*
+ * symbol_find_or_make()
+ *
+ * If a symbol name does not exist, create it as undefined, and insert
+ * it into the symbol table. Return a pointer to it.
+ */
+symbolS *
+symbol_find_or_make (name)
+ const char *name;
+{
+ register symbolS *symbolP;
+
+ symbolP = symbol_find (name);
+
+ if (symbolP == NULL)
+ {
+ symbolP = symbol_make (name);
+
+ symbol_table_insert (symbolP);
+ } /* if symbol wasn't found */
+
+ return (symbolP);
+} /* symbol_find_or_make() */
+
+symbolS *
+symbol_make (name)
+ CONST char *name;
+{
+ symbolS *symbolP;
+
+ /* Let the machine description default it, e.g. for register names. */
+ symbolP = md_undefined_symbol ((char *) name);
+
+ if (!symbolP)
+ symbolP = symbol_new (name, undefined_section, (valueT) 0, &zero_address_frag);
+
+ return (symbolP);
+} /* symbol_make() */
+
+/*
+ * symbol_find()
+ *
+ * Implement symbol table lookup.
+ * In: A symbol's name as a string: '\0' can't be part of a symbol name.
+ * Out: NULL if the name was not in the symbol table, else the address
+ * of a struct symbol associated with that name.
+ */
+
+symbolS *
+symbol_find (name)
+ CONST char *name;
+{
+#ifdef STRIP_UNDERSCORE
+ return (symbol_find_base (name, 1));
+#else /* STRIP_UNDERSCORE */
+ return (symbol_find_base (name, 0));
+#endif /* STRIP_UNDERSCORE */
+} /* symbol_find() */
+
+symbolS *
+symbol_find_base (name, strip_underscore)
+ CONST char *name;
+ int strip_underscore;
+{
+ if (strip_underscore && *name == '_')
+ name++;
+
+#ifdef tc_canonicalize_symbol_name
+ {
+ char *copy;
+
+ copy = (char *) alloca (strlen (name) + 1);
+ strcpy (copy, name);
+ name = tc_canonicalize_symbol_name (copy);
+ }
+#endif
+
+ if (! symbols_case_sensitive)
+ {
+ unsigned char *copy;
+
+ copy = (unsigned char *) alloca (strlen (name) + 1);
+ strcpy (copy, name);
+ name = (const char *) copy;
+ for (; *copy != '\0'; copy++)
+ if (islower (*copy))
+ *copy = toupper (*copy);
+ }
+
+ return ((symbolS *) hash_find (sy_hash, name));
+}
+
+/*
+ * Once upon a time, symbols were kept in a singly linked list. At
+ * least coff needs to be able to rearrange them from time to time, for
+ * which a doubly linked list is much more convenient. Loic did these
+ * as macros which seemed dangerous to me so they're now functions.
+ * xoxorich.
+ */
+
+/* Link symbol ADDME after symbol TARGET in the chain. */
+void
+symbol_append (addme, target, rootPP, lastPP)
+ symbolS *addme;
+ symbolS *target;
+ symbolS **rootPP;
+ symbolS **lastPP;
+{
+ if (target == NULL)
+ {
+ know (*rootPP == NULL);
+ know (*lastPP == NULL);
+ addme->sy_next = NULL;
+#ifdef SYMBOLS_NEED_BACKPOINTERS
+ addme->sy_previous = NULL;
+#endif
+ *rootPP = addme;
+ *lastPP = addme;
+ return;
+ } /* if the list is empty */
+
+ if (target->sy_next != NULL)
+ {
+#ifdef SYMBOLS_NEED_BACKPOINTERS
+ target->sy_next->sy_previous = addme;
+#endif /* SYMBOLS_NEED_BACKPOINTERS */
+ }
+ else
+ {
+ know (*lastPP == target);
+ *lastPP = addme;
+ } /* if we have a next */
+
+ addme->sy_next = target->sy_next;
+ target->sy_next = addme;
+
+#ifdef SYMBOLS_NEED_BACKPOINTERS
+ addme->sy_previous = target;
+#endif /* SYMBOLS_NEED_BACKPOINTERS */
+
+ debug_verify_symchain (symbol_rootP, symbol_lastP);
+}
+
+/* Set the chain pointers of SYMBOL to null. */
+void
+symbol_clear_list_pointers (symbolP)
+ symbolS *symbolP;
+{
+ symbolP->sy_next = NULL;
+#ifdef SYMBOLS_NEED_BACKPOINTERS
+ symbolP->sy_previous = NULL;
+#endif
+}
+
+#ifdef SYMBOLS_NEED_BACKPOINTERS
+/* Remove SYMBOLP from the list. */
+void
+symbol_remove (symbolP, rootPP, lastPP)
+ symbolS *symbolP;
+ symbolS **rootPP;
+ symbolS **lastPP;
+{
+ if (symbolP == *rootPP)
+ {
+ *rootPP = symbolP->sy_next;
+ } /* if it was the root */
+
+ if (symbolP == *lastPP)
+ {
+ *lastPP = symbolP->sy_previous;
+ } /* if it was the tail */
+
+ if (symbolP->sy_next != NULL)
+ {
+ symbolP->sy_next->sy_previous = symbolP->sy_previous;
+ } /* if not last */
+
+ if (symbolP->sy_previous != NULL)
+ {
+ symbolP->sy_previous->sy_next = symbolP->sy_next;
+ } /* if not first */
+
+ debug_verify_symchain (*rootPP, *lastPP);
+}
+
+/* Link symbol ADDME before symbol TARGET in the chain. */
+void
+symbol_insert (addme, target, rootPP, lastPP)
+ symbolS *addme;
+ symbolS *target;
+ symbolS **rootPP;
+ symbolS **lastPP;
+{
+ if (target->sy_previous != NULL)
+ {
+ target->sy_previous->sy_next = addme;
+ }
+ else
+ {
+ know (*rootPP == target);
+ *rootPP = addme;
+ } /* if not first */
+
+ addme->sy_previous = target->sy_previous;
+ target->sy_previous = addme;
+ addme->sy_next = target;
+
+ debug_verify_symchain (*rootPP, *lastPP);
+}
+
+#endif /* SYMBOLS_NEED_BACKPOINTERS */
+
+void
+verify_symbol_chain (rootP, lastP)
+ symbolS *rootP;
+ symbolS *lastP;
+{
+ symbolS *symbolP = rootP;
+
+ if (symbolP == NULL)
+ return;
+
+ for (; symbol_next (symbolP) != NULL; symbolP = symbol_next (symbolP))
+ {
+#ifdef SYMBOLS_NEED_BACKPOINTERS
+ assert (symbolP->sy_next->sy_previous == symbolP);
+#else
+ /* Walk the list anyways, to make sure pointers are still good. */
+ ;
+#endif /* SYMBOLS_NEED_BACKPOINTERS */
+ }
+
+ assert (lastP == symbolP);
+}
+
+void
+verify_symbol_chain_2 (sym)
+ symbolS *sym;
+{
+ symbolS *p = sym, *n = sym;
+#ifdef SYMBOLS_NEED_BACKPOINTERS
+ while (symbol_previous (p))
+ p = symbol_previous (p);
+#endif
+ while (symbol_next (n))
+ n = symbol_next (n);
+ verify_symbol_chain (p, n);
+}
+
+/* Resolve the value of a symbol. This is called during the final
+ pass over the symbol table to resolve any symbols with complex
+ values. */
+
+valueT
+resolve_symbol_value (symp, finalize)
+ symbolS *symp;
+ int finalize;
+{
+ int resolved;
+ valueT final_val;
+ segT final_seg;
+
+ if (symp->sy_resolved)
+ {
+ if (symp->sy_value.X_op == O_constant)
+ return (valueT) symp->sy_value.X_add_number;
+ else
+ return 0;
+ }
+
+ resolved = 0;
+ final_seg = S_GET_SEGMENT (symp);
+
+ if (symp->sy_resolving)
+ {
+ if (finalize)
+ as_bad (_("Symbol definition loop encountered at %s"), S_GET_NAME (symp));
+ final_val = 0;
+ resolved = 1;
+ }
+ else
+ {
+ symbolS *add_symbol, *op_symbol;
+ offsetT left, right;
+ segT seg_left, seg_right;
+ operatorT op;
+
+ symp->sy_resolving = 1;
+
+ /* Help out with CSE. */
+ add_symbol = symp->sy_value.X_add_symbol;
+ op_symbol = symp->sy_value.X_op_symbol;
+ final_val = symp->sy_value.X_add_number;
+ op = symp->sy_value.X_op;
+
+ switch (op)
+ {
+ default:
+ BAD_CASE (op);
+ break;
+
+ case O_absent:
+ final_val = 0;
+ /* Fall through. */
+
+ case O_constant:
+ final_val += symp->sy_frag->fr_address;
+ if (final_seg == expr_section)
+ final_seg = absolute_section;
+ resolved = 1;
+ break;
+
+ case O_symbol:
+ case O_symbol_rva:
+ left = resolve_symbol_value (add_symbol, finalize);
+ do_symbol:
+
+ if (symp->sy_mri_common)
+ {
+ /* This is a symbol inside an MRI common section. The
+ relocation routines are going to handle it specially.
+ Don't change the value. */
+ resolved = add_symbol->sy_resolved;
+ break;
+ }
+
+ if (finalize && final_val == 0)
+ copy_symbol_attributes (symp, add_symbol);
+
+ /* If we have equated this symbol to an undefined symbol, we
+ keep X_op set to O_symbol, and we don't change
+ X_add_number. This permits the routine which writes out
+ relocation to detect this case, and convert the
+ relocation to be against the symbol to which this symbol
+ is equated. */
+ if (! S_IS_DEFINED (add_symbol) || S_IS_COMMON (add_symbol))
+ {
+ if (finalize)
+ {
+ S_SET_SEGMENT (symp, S_GET_SEGMENT (add_symbol));
+ symp->sy_value.X_op = O_symbol;
+ symp->sy_value.X_add_symbol = add_symbol;
+ symp->sy_value.X_add_number = final_val;
+ }
+ final_val = 0;
+ resolved = add_symbol->sy_resolved;
+ goto exit_dont_set_value;
+ }
+ else
+ {
+ final_val += symp->sy_frag->fr_address + left;
+ if (final_seg == expr_section || final_seg == undefined_section)
+ final_seg = S_GET_SEGMENT (add_symbol);
+ }
+
+ resolved = add_symbol->sy_resolved;
+ break;
+
+ case O_uminus:
+ case O_bit_not:
+ case O_logical_not:
+ left = resolve_symbol_value (add_symbol, finalize);
+
+ if (op == O_uminus)
+ left = -left;
+ else if (op == O_logical_not)
+ left = !left;
+ else
+ left = ~left;
+
+ final_val += left + symp->sy_frag->fr_address;
+ if (final_seg == expr_section || final_seg == undefined_section)
+ final_seg = absolute_section;
+
+ resolved = add_symbol->sy_resolved;
+ break;
+
+ case O_multiply:
+ case O_divide:
+ case O_modulus:
+ case O_left_shift:
+ case O_right_shift:
+ case O_bit_inclusive_or:
+ case O_bit_or_not:
+ case O_bit_exclusive_or:
+ case O_bit_and:
+ case O_add:
+ case O_subtract:
+ case O_eq:
+ case O_ne:
+ case O_lt:
+ case O_le:
+ case O_ge:
+ case O_gt:
+ case O_logical_and:
+ case O_logical_or:
+ left = resolve_symbol_value (add_symbol, finalize);
+ right = resolve_symbol_value (op_symbol, finalize);
+ seg_left = S_GET_SEGMENT (add_symbol);
+ seg_right = S_GET_SEGMENT (op_symbol);
+
+ /* Simplify addition or subtraction of a constant by folding the
+ constant into X_add_number. */
+ if (op == O_add || op == O_subtract)
+ {
+ if (seg_right == absolute_section)
+ {
+ if (op == O_add)
+ final_val += right;
+ else
+ final_val -= right;
+ op = O_symbol;
+ op_symbol = NULL;
+ goto do_symbol;
+ }
+ else if (seg_left == absolute_section && op == O_add)
+ {
+ op = O_symbol;
+ final_val += left;
+ add_symbol = op_symbol;
+ left = right;
+ op_symbol = NULL;
+ goto do_symbol;
+ }
+ }
+
+ /* Subtraction is permitted if both operands are in the same
+ section. Otherwise, both operands must be absolute. We
+ already handled the case of addition or subtraction of a
+ constant above. This will probably need to be changed
+ for an object file format which supports arbitrary
+ expressions, such as IEEE-695. */
+ /* Don't emit messages unless we're finalizing the symbol value,
+ otherwise we may get the same message multiple times. */
+ if ((seg_left != absolute_section || seg_right != absolute_section)
+ && (op != O_subtract || seg_left != seg_right)
+ && finalize)
+ {
+ char *file;
+ unsigned int line;
+
+ if (expr_symbol_where (symp, &file, &line))
+ {
+ if (seg_left == undefined_section)
+ as_bad_where (file, line,
+ _("undefined symbol %s in operation"),
+ S_GET_NAME (symp->sy_value.X_add_symbol));
+ if (seg_right == undefined_section)
+ as_bad_where (file, line,
+ _("undefined symbol %s in operation"),
+ S_GET_NAME (symp->sy_value.X_op_symbol));
+ if (seg_left != undefined_section
+ && seg_right != undefined_section)
+ as_bad_where (file, line, _("invalid section for operation"));
+ }
+ else
+ {
+ if (seg_left == undefined_section)
+ as_bad (_("undefined symbol %s in operation setting %s"),
+ S_GET_NAME (symp->sy_value.X_add_symbol),
+ S_GET_NAME (symp));
+ if (seg_right == undefined_section)
+ as_bad (_("undefined symbol %s in operation setting %s"),
+ S_GET_NAME (symp->sy_value.X_op_symbol),
+ S_GET_NAME (symp));
+ if (seg_left != undefined_section
+ && seg_right != undefined_section)
+ as_bad (_("invalid section for operation setting %s"),
+ S_GET_NAME (symp));
+ }
+ }
+
+ /* Check for division by zero. */
+ if ((op == O_divide || op == O_modulus) && right == 0)
+ {
+ /* If seg_right is not absolute_section, then we've
+ already issued a warning about using a bad symbol. */
+ if (seg_right == absolute_section && finalize)
+ {
+ char *file;
+ unsigned int line;
+
+ if (expr_symbol_where (symp, &file, &line))
+ as_bad_where (file, line, _("division by zero"));
+ else
+ as_bad (_("division by zero when setting %s"),
+ S_GET_NAME (symp));
+ }
+
+ right = 1;
+ }
+
+ switch (symp->sy_value.X_op)
+ {
+ case O_multiply: left *= right; break;
+ case O_divide: left /= right; break;
+ case O_modulus: left %= right; break;
+ case O_left_shift: left <<= right; break;
+ case O_right_shift: left >>= right; break;
+ case O_bit_inclusive_or: left |= right; break;
+ case O_bit_or_not: left |= ~right; break;
+ case O_bit_exclusive_or: left ^= right; break;
+ case O_bit_and: left &= right; break;
+ case O_add: left += right; break;
+ case O_subtract: left -= right; break;
+ case O_eq: left = left == right ? ~ (offsetT) 0 : 0; break;
+ case O_ne: left = left != right ? ~ (offsetT) 0 : 0; break;
+ case O_lt: left = left < right ? ~ (offsetT) 0 : 0; break;
+ case O_le: left = left <= right ? ~ (offsetT) 0 : 0; break;
+ case O_ge: left = left >= right ? ~ (offsetT) 0 : 0; break;
+ case O_gt: left = left > right ? ~ (offsetT) 0 : 0; break;
+ case O_logical_and: left = left && right; break;
+ case O_logical_or: left = left || right; break;
+ default: abort ();
+ }
+
+ final_val += symp->sy_frag->fr_address + left;
+ if (final_seg == expr_section || final_seg == undefined_section)
+ final_seg = absolute_section;
+ resolved = (add_symbol->sy_resolved && op_symbol->sy_resolved);
+ break;
+
+ case O_register:
+ case O_big:
+ case O_illegal:
+ /* Give an error (below) if not in expr_section. We don't
+ want to worry about expr_section symbols, because they
+ are fictional (they are created as part of expression
+ resolution), and any problems may not actually mean
+ anything. */
+ break;
+ }
+
+ symp->sy_resolving = 0;
+ }
+
+ if (finalize)
+ {
+ S_SET_VALUE (symp, final_val);
+
+#if defined (OBJ_AOUT) && ! defined (BFD_ASSEMBLER)
+ /* The old a.out backend does not handle S_SET_SEGMENT correctly
+ for a stab symbol, so we use this bad hack. */
+ if (final_seg != S_GET_SEGMENT (symp))
+#endif
+ S_SET_SEGMENT (symp, final_seg);
+ }
+
+exit_dont_set_value:
+ /* Don't worry if we can't resolve an expr_section symbol. */
+ if (finalize)
+ {
+ if (resolved)
+ symp->sy_resolved = 1;
+ else if (S_GET_SEGMENT (symp) != expr_section)
+ {
+ as_bad (_("can't resolve value for symbol \"%s\""), S_GET_NAME (symp));
+ symp->sy_resolved = 1;
+ }
+ }
+
+ return final_val;
+}
+
+/* Dollar labels look like a number followed by a dollar sign. Eg, "42$".
+ They are *really* local. That is, they go out of scope whenever we see a
+ label that isn't local. Also, like fb labels, there can be multiple
+ instances of a dollar label. Therefor, we name encode each instance with
+ the instance number, keep a list of defined symbols separate from the real
+ symbol table, and we treat these buggers as a sparse array. */
+
+static long *dollar_labels;
+static long *dollar_label_instances;
+static char *dollar_label_defines;
+static unsigned long dollar_label_count;
+static unsigned long dollar_label_max;
+
+int
+dollar_label_defined (label)
+ long label;
+{
+ long *i;
+
+ know ((dollar_labels != NULL) || (dollar_label_count == 0));
+
+ for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
+ if (*i == label)
+ return dollar_label_defines[i - dollar_labels];
+
+ /* if we get here, label isn't defined */
+ return 0;
+} /* dollar_label_defined() */
+
+static long
+dollar_label_instance (label)
+ long label;
+{
+ long *i;
+
+ know ((dollar_labels != NULL) || (dollar_label_count == 0));
+
+ for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
+ if (*i == label)
+ return (dollar_label_instances[i - dollar_labels]);
+
+ /* If we get here, we haven't seen the label before, therefore its instance
+ count is zero. */
+ return 0;
+}
+
+void
+dollar_label_clear ()
+{
+ memset (dollar_label_defines, '\0', (unsigned int) dollar_label_count);
+}
+
+#define DOLLAR_LABEL_BUMP_BY 10
+
+void
+define_dollar_label (label)
+ long label;
+{
+ long *i;
+
+ for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
+ if (*i == label)
+ {
+ ++dollar_label_instances[i - dollar_labels];
+ dollar_label_defines[i - dollar_labels] = 1;
+ return;
+ }
+
+ /* if we get to here, we don't have label listed yet. */
+
+ if (dollar_labels == NULL)
+ {
+ dollar_labels = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long));
+ dollar_label_instances = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long));
+ dollar_label_defines = xmalloc (DOLLAR_LABEL_BUMP_BY);
+ dollar_label_max = DOLLAR_LABEL_BUMP_BY;
+ dollar_label_count = 0;
+ }
+ else if (dollar_label_count == dollar_label_max)
+ {
+ dollar_label_max += DOLLAR_LABEL_BUMP_BY;
+ dollar_labels = (long *) xrealloc ((char *) dollar_labels,
+ dollar_label_max * sizeof (long));
+ dollar_label_instances = (long *) xrealloc ((char *) dollar_label_instances,
+ dollar_label_max * sizeof (long));
+ dollar_label_defines = xrealloc (dollar_label_defines, dollar_label_max);
+ } /* if we needed to grow */
+
+ dollar_labels[dollar_label_count] = label;
+ dollar_label_instances[dollar_label_count] = 1;
+ dollar_label_defines[dollar_label_count] = 1;
+ ++dollar_label_count;
+}
+
+/*
+ * dollar_label_name()
+ *
+ * Caller must copy returned name: we re-use the area for the next name.
+ *
+ * The mth occurence of label n: is turned into the symbol "Ln^Am"
+ * where n is the label number and m is the instance number. "L" makes
+ * it a label discarded unless debugging and "^A"('\1') ensures no
+ * ordinary symbol SHOULD get the same name as a local label
+ * symbol. The first "4:" is "L4^A1" - the m numbers begin at 1.
+ *
+ * fb labels get the same treatment, except that ^B is used in place of ^A.
+ */
+
+char * /* Return local label name. */
+dollar_label_name (n, augend)
+ register long n; /* we just saw "n$:" : n a number */
+ register int augend; /* 0 for current instance, 1 for new instance */
+{
+ long i;
+ /* Returned to caller, then copied. used for created names ("4f") */
+ static char symbol_name_build[24];
+ register char *p;
+ register char *q;
+ char symbol_name_temporary[20]; /* build up a number, BACKWARDS */
+
+ know (n >= 0);
+ know (augend == 0 || augend == 1);
+ p = symbol_name_build;
+ *p++ = 'L';
+
+ /* Next code just does sprintf( {}, "%d", n); */
+ /* label number */
+ q = symbol_name_temporary;
+ for (*q++ = 0, i = n; i; ++q)
+ {
+ *q = i % 10 + '0';
+ i /= 10;
+ }
+ while ((*p = *--q) != '\0')
+ ++p;
+
+ *p++ = 1; /* ^A */
+
+ /* instance number */
+ q = symbol_name_temporary;
+ for (*q++ = 0, i = dollar_label_instance (n) + augend; i; ++q)
+ {
+ *q = i % 10 + '0';
+ i /= 10;
+ }
+ while ((*p++ = *--q) != '\0');;
+
+ /* The label, as a '\0' ended string, starts at symbol_name_build. */
+ return symbol_name_build;
+}
+
+/*
+ * Sombody else's idea of local labels. They are made by "n:" where n
+ * is any decimal digit. Refer to them with
+ * "nb" for previous (backward) n:
+ * or "nf" for next (forward) n:.
+ *
+ * We do a little better and let n be any number, not just a single digit, but
+ * since the other guy's assembler only does ten, we treat the first ten
+ * specially.
+ *
+ * Like someone else's assembler, we have one set of local label counters for
+ * entire assembly, not one set per (sub)segment like in most assemblers. This
+ * implies that one can refer to a label in another segment, and indeed some
+ * crufty compilers have done just that.
+ *
+ * Since there could be a LOT of these things, treat them as a sparse array.
+ */
+
+#define FB_LABEL_SPECIAL (10)
+
+static long fb_low_counter[FB_LABEL_SPECIAL];
+static long *fb_labels;
+static long *fb_label_instances;
+static long fb_label_count;
+static long fb_label_max;
+
+/* this must be more than FB_LABEL_SPECIAL */
+#define FB_LABEL_BUMP_BY (FB_LABEL_SPECIAL + 6)
+
+static void
+fb_label_init ()
+{
+ memset ((void *) fb_low_counter, '\0', sizeof (fb_low_counter));
+} /* fb_label_init() */
+
+/* add one to the instance number of this fb label */
+void
+fb_label_instance_inc (label)
+ long label;
+{
+ long *i;
+
+ if (label < FB_LABEL_SPECIAL)
+ {
+ ++fb_low_counter[label];
+ return;
+ }
+
+ if (fb_labels != NULL)
+ {
+ for (i = fb_labels + FB_LABEL_SPECIAL;
+ i < fb_labels + fb_label_count; ++i)
+ {
+ if (*i == label)
+ {
+ ++fb_label_instances[i - fb_labels];
+ return;
+ } /* if we find it */
+ } /* for each existing label */
+ }
+
+ /* if we get to here, we don't have label listed yet. */
+
+ if (fb_labels == NULL)
+ {
+ fb_labels = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long));
+ fb_label_instances = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long));
+ fb_label_max = FB_LABEL_BUMP_BY;
+ fb_label_count = FB_LABEL_SPECIAL;
+
+ }
+ else if (fb_label_count == fb_label_max)
+ {
+ fb_label_max += FB_LABEL_BUMP_BY;
+ fb_labels = (long *) xrealloc ((char *) fb_labels,
+ fb_label_max * sizeof (long));
+ fb_label_instances = (long *) xrealloc ((char *) fb_label_instances,
+ fb_label_max * sizeof (long));
+ } /* if we needed to grow */
+
+ fb_labels[fb_label_count] = label;
+ fb_label_instances[fb_label_count] = 1;
+ ++fb_label_count;
+}
+
+static long
+fb_label_instance (label)
+ long label;
+{
+ long *i;
+
+ if (label < FB_LABEL_SPECIAL)
+ {
+ return (fb_low_counter[label]);
+ }
+
+ if (fb_labels != NULL)
+ {
+ for (i = fb_labels + FB_LABEL_SPECIAL;
+ i < fb_labels + fb_label_count; ++i)
+ {
+ if (*i == label)
+ {
+ return (fb_label_instances[i - fb_labels]);
+ } /* if we find it */
+ } /* for each existing label */
+ }
+
+ /* We didn't find the label, so this must be a reference to the
+ first instance. */
+ return 0;
+}
+
+/*
+ * fb_label_name()
+ *
+ * Caller must copy returned name: we re-use the area for the next name.
+ *
+ * The mth occurence of label n: is turned into the symbol "Ln^Bm"
+ * where n is the label number and m is the instance number. "L" makes
+ * it a label discarded unless debugging and "^B"('\2') ensures no
+ * ordinary symbol SHOULD get the same name as a local label
+ * symbol. The first "4:" is "L4^B1" - the m numbers begin at 1.
+ *
+ * dollar labels get the same treatment, except that ^A is used in place of ^B. */
+
+char * /* Return local label name. */
+fb_label_name (n, augend)
+ long n; /* we just saw "n:", "nf" or "nb" : n a number */
+ long augend; /* 0 for nb, 1 for n:, nf */
+{
+ long i;
+ /* Returned to caller, then copied. used for created names ("4f") */
+ static char symbol_name_build[24];
+ register char *p;
+ register char *q;
+ char symbol_name_temporary[20]; /* build up a number, BACKWARDS */
+
+ know (n >= 0);
+ know (augend == 0 || augend == 1);
+ p = symbol_name_build;
+ *p++ = 'L';
+
+ /* Next code just does sprintf( {}, "%d", n); */
+ /* label number */
+ q = symbol_name_temporary;
+ for (*q++ = 0, i = n; i; ++q)
+ {
+ *q = i % 10 + '0';
+ i /= 10;
+ }
+ while ((*p = *--q) != '\0')
+ ++p;
+
+ *p++ = 2; /* ^B */
+
+ /* instance number */
+ q = symbol_name_temporary;
+ for (*q++ = 0, i = fb_label_instance (n) + augend; i; ++q)
+ {
+ *q = i % 10 + '0';
+ i /= 10;
+ }
+ while ((*p++ = *--q) != '\0');;
+
+ /* The label, as a '\0' ended string, starts at symbol_name_build. */
+ return (symbol_name_build);
+} /* fb_label_name() */
+
+/*
+ * decode name that may have been generated by foo_label_name() above. If
+ * the name wasn't generated by foo_label_name(), then return it unaltered.
+ * This is used for error messages.
+ */
+
+char *
+decode_local_label_name (s)
+ char *s;
+{
+ char *p;
+ char *symbol_decode;
+ int label_number;
+ int instance_number;
+ char *type;
+ const char *message_format = _("\"%d\" (instance number %d of a %s label)");
+
+ if (s[0] != 'L')
+ return s;
+
+ for (label_number = 0, p = s + 1; isdigit ((unsigned char) *p); ++p)
+ label_number = (10 * label_number) + *p - '0';
+
+ if (*p == 1)
+ type = "dollar";
+ else if (*p == 2)
+ type = "fb";
+ else
+ return s;
+
+ for (instance_number = 0, p++; isdigit ((unsigned char) *p); ++p)
+ instance_number = (10 * instance_number) + *p - '0';
+
+ symbol_decode = obstack_alloc (&notes, strlen (message_format) + 30);
+ sprintf (symbol_decode, message_format, label_number, instance_number, type);
+
+ return symbol_decode;
+}
+
+/* Get the value of a symbol. */
+
+valueT
+S_GET_VALUE (s)
+ symbolS *s;
+{
+ if (!s->sy_resolved && s->sy_value.X_op != O_constant)
+ resolve_symbol_value (s, 1);
+ if (s->sy_value.X_op != O_constant)
+ {
+ static symbolS *recur;
+
+ /* FIXME: In non BFD assemblers, S_IS_DEFINED and S_IS_COMMON
+ may call S_GET_VALUE. We use a static symbol to avoid the
+ immediate recursion. */
+ if (recur == s)
+ return (valueT) s->sy_value.X_add_number;
+ recur = s;
+ if (! s->sy_resolved
+ || s->sy_value.X_op != O_symbol
+ || (S_IS_DEFINED (s) && ! S_IS_COMMON (s)))
+ as_bad (_("Attempt to get value of unresolved symbol %s"),
+ S_GET_NAME (s));
+ recur = NULL;
+ }
+ return (valueT) s->sy_value.X_add_number;
+}
+
+/* Set the value of a symbol. */
+
+void
+S_SET_VALUE (s, val)
+ symbolS *s;
+ valueT val;
+{
+ s->sy_value.X_op = O_constant;
+ s->sy_value.X_add_number = (offsetT) val;
+ s->sy_value.X_unsigned = 0;
+}
+
+void
+copy_symbol_attributes (dest, src)
+ symbolS *dest, *src;
+{
+#ifdef BFD_ASSEMBLER
+ /* In an expression, transfer the settings of these flags.
+ The user can override later, of course. */
+#define COPIED_SYMFLAGS (BSF_FUNCTION | BSF_OBJECT)
+ dest->bsym->flags |= src->bsym->flags & COPIED_SYMFLAGS;
+#endif
+
+#ifdef OBJ_COPY_SYMBOL_ATTRIBUTES
+ OBJ_COPY_SYMBOL_ATTRIBUTES (dest, src);
+#endif
+}
+
+#ifdef BFD_ASSEMBLER
+
+int
+S_IS_FUNCTION (s)
+ symbolS *s;
+{
+ flagword flags = s->bsym->flags;
+
+ return (flags & BSF_FUNCTION) != 0;
+}
+
+int
+S_IS_EXTERNAL (s)
+ symbolS *s;
+{
+ flagword flags = s->bsym->flags;
+
+ /* sanity check */
+ if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL))
+ abort ();
+
+ return (flags & BSF_GLOBAL) != 0;
+}
+
+int
+S_IS_WEAK (s)
+ symbolS *s;
+{
+ return (s->bsym->flags & BSF_WEAK) != 0;
+}
+
+int
+S_IS_COMMON (s)
+ symbolS *s;
+{
+ return bfd_is_com_section (s->bsym->section);
+}
+
+int
+S_IS_DEFINED (s)
+ symbolS *s;
+{
+ return s->bsym->section != undefined_section;
+}
+
+int
+S_IS_DEBUG (s)
+ symbolS *s;
+{
+ if (s->bsym->flags & BSF_DEBUGGING)
+ return 1;
+ return 0;
+}
+
+int
+S_IS_LOCAL (s)
+ symbolS *s;
+{
+ flagword flags = s->bsym->flags;
+ const char *name;
+
+ /* sanity check */
+ if ((flags & BSF_LOCAL) && (flags & BSF_GLOBAL))
+ abort ();
+
+ if (bfd_get_section (s->bsym) == reg_section)
+ return 1;
+
+ if (flag_strip_local_absolute
+ && (flags & BSF_GLOBAL) == 0
+ && bfd_get_section (s->bsym) == absolute_section)
+ return 1;
+
+ name = S_GET_NAME (s);
+ return (name != NULL
+ && ! S_IS_DEBUG (s)
+ && (strchr (name, '\001')
+ || strchr (name, '\002')
+ || (! flag_keep_locals
+ && (bfd_is_local_label (stdoutput, s->bsym)
+ || (flag_mri
+ && name[0] == '?'
+ && name[1] == '?')))));
+}
+
+int
+S_IS_EXTERN (s)
+ symbolS *s;
+{
+ return S_IS_EXTERNAL (s);
+}
+
+int
+S_IS_STABD (s)
+ symbolS *s;
+{
+ return S_GET_NAME (s) == 0;
+}
+
+CONST char *
+S_GET_NAME (s)
+ symbolS *s;
+{
+ return s->bsym->name;
+}
+
+segT
+S_GET_SEGMENT (s)
+ symbolS *s;
+{
+ return s->bsym->section;
+}
+
+void
+S_SET_SEGMENT (s, seg)
+ symbolS *s;
+ segT seg;
+{
+ /* Don't reassign section symbols. The direct reason is to prevent seg
+ faults assigning back to const global symbols such as *ABS*, but it
+ shouldn't happen anyway. */
+
+ if (s->bsym->flags & BSF_SECTION_SYM)
+ {
+ if (s->bsym->section != seg)
+ abort();
+ }
+ else
+ s->bsym->section = seg;
+}
+
+void
+S_SET_EXTERNAL (s)
+ symbolS *s;
+{
+ if ((s->bsym->flags & BSF_WEAK) != 0)
+ {
+ /* Let .weak override .global. */
+ return;
+ }
+ s->bsym->flags |= BSF_GLOBAL;
+ s->bsym->flags &= ~(BSF_LOCAL|BSF_WEAK);
+}
+
+void
+S_CLEAR_EXTERNAL (s)
+ symbolS *s;
+{
+ if ((s->bsym->flags & BSF_WEAK) != 0)
+ {
+ /* Let .weak override. */
+ return;
+ }
+ s->bsym->flags |= BSF_LOCAL;
+ s->bsym->flags &= ~(BSF_GLOBAL|BSF_WEAK);
+}
+
+void
+S_SET_WEAK (s)
+ symbolS *s;
+{
+ s->bsym->flags |= BSF_WEAK;
+ s->bsym->flags &= ~(BSF_GLOBAL|BSF_LOCAL);
+}
+
+void
+S_SET_NAME (s, name)
+ symbolS *s;
+ char *name;
+{
+ s->bsym->name = name;
+}
+#endif /* BFD_ASSEMBLER */
+
+void
+symbol_begin ()
+{
+ symbol_lastP = NULL;
+ symbol_rootP = NULL; /* In case we have 0 symbols (!!) */
+ sy_hash = hash_new ();
+
+ memset ((char *) (&abs_symbol), '\0', sizeof (abs_symbol));
+#ifdef BFD_ASSEMBLER
+#if defined (EMIT_SECTION_SYMBOLS) || !defined (RELOC_REQUIRES_SYMBOL)
+ abs_symbol.bsym = bfd_abs_section.symbol;
+#endif
+#else
+ /* Can't initialise a union. Sigh. */
+ S_SET_SEGMENT (&abs_symbol, absolute_section);
+#endif
+ abs_symbol.sy_value.X_op = O_constant;
+ abs_symbol.sy_frag = &zero_address_frag;
+
+ if (LOCAL_LABELS_FB)
+ fb_label_init ();
+}
+
+
+int indent_level;
+
+/* Maximum indent level.
+ Available for modification inside a gdb session. */
+int max_indent_level = 8;
+
+#if 0
+
+static void
+indent ()
+{
+ printf ("%*s", indent_level * 4, "");
+}
+
+#endif
+
+void
+print_symbol_value_1 (file, sym)
+ FILE *file;
+ symbolS *sym;
+{
+ const char *name = S_GET_NAME (sym);
+ if (!name || !name[0])
+ name = "(unnamed)";
+ fprintf (file, "sym %lx %s", (unsigned long) sym, name);
+ if (sym->sy_frag != &zero_address_frag)
+ fprintf (file, " frag %lx", (long) sym->sy_frag);
+ if (sym->written)
+ fprintf (file, " written");
+ if (sym->sy_resolved)
+ fprintf (file, " resolved");
+ else if (sym->sy_resolving)
+ fprintf (file, " resolving");
+ if (sym->sy_used_in_reloc)
+ fprintf (file, " used-in-reloc");
+ if (sym->sy_used)
+ fprintf (file, " used");
+ if (S_IS_LOCAL (sym))
+ fprintf (file, " local");
+ if (S_IS_EXTERN (sym))
+ fprintf (file, " extern");
+ if (S_IS_DEBUG (sym))
+ fprintf (file, " debug");
+ if (S_IS_DEFINED (sym))
+ fprintf (file, " defined");
+ fprintf (file, " %s", segment_name (S_GET_SEGMENT (sym)));
+ if (sym->sy_resolved)
+ {
+ segT s = S_GET_SEGMENT (sym);
+
+ if (s != undefined_section
+ && s != expr_section)
+ fprintf (file, " %lx", (long) S_GET_VALUE (sym));
+ }
+ else if (indent_level < max_indent_level
+ && S_GET_SEGMENT (sym) != undefined_section)
+ {
+ indent_level++;
+ fprintf (file, "\n%*s<", indent_level * 4, "");
+ print_expr_1 (file, &sym->sy_value);
+ fprintf (file, ">");
+ indent_level--;
+ }
+ fflush (file);
+}
+
+void
+print_symbol_value (sym)
+ symbolS *sym;
+{
+ indent_level = 0;
+ print_symbol_value_1 (stderr, sym);
+ fprintf (stderr, "\n");
+}
+
+static void
+print_binary (file, name, exp)
+ FILE *file;
+ const char * name;
+ expressionS *exp;
+{
+ indent_level++;
+ fprintf (file, "%s\n%*s<", name, indent_level * 4, "");
+ print_symbol_value_1 (file, exp->X_add_symbol);
+ fprintf (file, ">\n%*s<", indent_level * 4, "");
+ print_symbol_value_1 (file, exp->X_op_symbol);
+ fprintf (file, ">");
+ indent_level--;
+}
+
+void
+print_expr_1 (file, exp)
+ FILE *file;
+ expressionS *exp;
+{
+ fprintf (file, "expr %lx ", (long) exp);
+ switch (exp->X_op)
+ {
+ case O_illegal:
+ fprintf (file, "illegal");
+ break;
+ case O_absent:
+ fprintf (file, "absent");
+ break;
+ case O_constant:
+ fprintf (file, "constant %lx", (long) exp->X_add_number);
+ break;
+ case O_symbol:
+ indent_level++;
+ fprintf (file, "symbol\n%*s<", indent_level * 4, "");
+ print_symbol_value_1 (file, exp->X_add_symbol);
+ fprintf (file, ">");
+ maybe_print_addnum:
+ if (exp->X_add_number)
+ fprintf (file, "\n%*s%lx", indent_level * 4, "",
+ (long) exp->X_add_number);
+ indent_level--;
+ break;
+ case O_register:
+ fprintf (file, "register #%d", (int) exp->X_add_number);
+ break;
+ case O_big:
+ fprintf (file, "big");
+ break;
+ case O_uminus:
+ fprintf (file, "uminus -<");
+ indent_level++;
+ print_symbol_value_1 (file, exp->X_add_symbol);
+ fprintf (file, ">");
+ goto maybe_print_addnum;
+ case O_bit_not:
+ fprintf (file, "bit_not");
+ break;
+ case O_multiply:
+ print_binary (file, "multiply", exp);
+ break;
+ case O_divide:
+ print_binary (file, "divide", exp);
+ break;
+ case O_modulus:
+ print_binary (file, "modulus", exp);
+ break;
+ case O_left_shift:
+ print_binary (file, "lshift", exp);
+ break;
+ case O_right_shift:
+ print_binary (file, "rshift", exp);
+ break;
+ case O_bit_inclusive_or:
+ print_binary (file, "bit_ior", exp);
+ break;
+ case O_bit_exclusive_or:
+ print_binary (file, "bit_xor", exp);
+ break;
+ case O_bit_and:
+ print_binary (file, "bit_and", exp);
+ break;
+ case O_eq:
+ print_binary (file, "eq", exp);
+ break;
+ case O_ne:
+ print_binary (file, "ne", exp);
+ break;
+ case O_lt:
+ print_binary (file, "lt", exp);
+ break;
+ case O_le:
+ print_binary (file, "le", exp);
+ break;
+ case O_ge:
+ print_binary (file, "ge", exp);
+ break;
+ case O_gt:
+ print_binary (file, "gt", exp);
+ break;
+ case O_logical_and:
+ print_binary (file, "logical_and", exp);
+ break;
+ case O_logical_or:
+ print_binary (file, "logical_or", exp);
+ break;
+ case O_add:
+ indent_level++;
+ fprintf (file, "add\n%*s<", indent_level * 4, "");
+ print_symbol_value_1 (file, exp->X_add_symbol);
+ fprintf (file, ">\n%*s<", indent_level * 4, "");
+ print_symbol_value_1 (file, exp->X_op_symbol);
+ fprintf (file, ">");
+ goto maybe_print_addnum;
+ case O_subtract:
+ indent_level++;
+ fprintf (file, "subtract\n%*s<", indent_level * 4, "");
+ print_symbol_value_1 (file, exp->X_add_symbol);
+ fprintf (file, ">\n%*s<", indent_level * 4, "");
+ print_symbol_value_1 (file, exp->X_op_symbol);
+ fprintf (file, ">");
+ goto maybe_print_addnum;
+ default:
+ fprintf (file, "{unknown opcode %d}", (int) exp->X_op);
+ break;
+ }
+ fflush (stdout);
+}
+
+void
+print_expr (exp)
+ expressionS *exp;
+{
+ print_expr_1 (stderr, exp);
+ fprintf (stderr, "\n");
+}
+
+void
+symbol_print_statistics (file)
+ FILE *file;
+{
+ hash_print_statistics (file, "symbol table", sy_hash);
+}
+
+/* end of symbols.c */
diff --git a/gas/symbols.h b/gas/symbols.h
new file mode 100644
index 0000000000..c6efbdb34d
--- /dev/null
+++ b/gas/symbols.h
@@ -0,0 +1,90 @@
+/* symbols.h -
+ Copyright (C) 1987, 90, 92, 93, 94, 95, 1997 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+extern struct obstack notes; /* eg FixS live here. */
+
+extern struct obstack cond_obstack; /* this is where we track .ifdef/.endif
+ (if we do that at all). */
+
+extern symbolS *symbol_rootP; /* all the symbol nodes */
+extern symbolS *symbol_lastP; /* last struct symbol we made, or NULL */
+
+extern symbolS abs_symbol;
+
+extern int symbol_table_frozen;
+
+/* This is non-zero if symbols are case sensitive, which is the
+ default. */
+extern int symbols_case_sensitive;
+
+char *decode_local_label_name PARAMS ((char *s));
+symbolS *symbol_find PARAMS ((CONST char *name));
+symbolS *symbol_find_base PARAMS ((CONST char *name, int strip_underscore));
+symbolS *symbol_find_or_make PARAMS ((const char *name));
+symbolS *symbol_make PARAMS ((CONST char *name));
+symbolS *symbol_new PARAMS ((CONST char *name, segT segment, valueT value,
+ fragS * frag));
+symbolS *symbol_create PARAMS ((CONST char *name, segT segment, valueT value,
+ fragS * frag));
+symbolS *colon PARAMS ((const char *sym_name));
+void local_colon PARAMS ((int n));
+void symbol_begin PARAMS ((void));
+void symbol_print_statistics PARAMS ((FILE *));
+void symbol_table_insert PARAMS ((symbolS * symbolP));
+valueT resolve_symbol_value PARAMS ((symbolS *, int));
+
+void print_symbol_value PARAMS ((symbolS *));
+void print_expr PARAMS ((expressionS *));
+void print_expr_1 PARAMS ((FILE *, expressionS *));
+void print_symbol_value_1 PARAMS ((FILE *, symbolS *));
+
+int dollar_label_defined PARAMS ((long l));
+void dollar_label_clear PARAMS ((void));
+void define_dollar_label PARAMS ((long l));
+char *dollar_label_name PARAMS ((long l, int augend));
+
+void fb_label_instance_inc PARAMS ((long label));
+char *fb_label_name PARAMS ((long n, long augend));
+
+extern void copy_symbol_attributes PARAMS ((symbolS *, symbolS *));
+
+/* Get and set the values of symbols. These used to be macros. */
+extern valueT S_GET_VALUE PARAMS ((symbolS *));
+extern void S_SET_VALUE PARAMS ((symbolS *, valueT));
+
+#ifdef BFD_ASSEMBLER
+extern int S_IS_EXTERNAL PARAMS ((symbolS *));
+extern int S_IS_WEAK PARAMS ((symbolS *));
+extern int S_IS_COMMON PARAMS ((symbolS *));
+extern int S_IS_DEFINED PARAMS ((symbolS *));
+extern int S_IS_DEBUG PARAMS ((symbolS *));
+extern int S_IS_LOCAL PARAMS ((symbolS *));
+extern int S_IS_EXTERN PARAMS ((symbolS *));
+extern int S_IS_STABD PARAMS ((symbolS *));
+extern CONST char *S_GET_NAME PARAMS ((symbolS *));
+extern segT S_GET_SEGMENT PARAMS ((symbolS *));
+extern void S_SET_SEGMENT PARAMS ((symbolS *, segT));
+extern void S_SET_EXTERNAL PARAMS ((symbolS *));
+extern void S_SET_NAME PARAMS ((symbolS *, char *));
+extern void S_CLEAR_EXTERNAL PARAMS ((symbolS *));
+extern void S_SET_WEAK PARAMS ((symbolS *));
+#endif
+
+/* end of symbols.h */
diff --git a/gas/tc.h b/gas/tc.h
new file mode 100644
index 0000000000..4e4046ccc1
--- /dev/null
+++ b/gas/tc.h
@@ -0,0 +1,112 @@
+/* tc.h - target cpu dependent
+
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* In theory (mine, at least!) the machine dependent part of the assembler
+ should only have to include one file. This one. -- JF */
+
+extern const pseudo_typeS md_pseudo_table[];
+
+/* JF moved this here from as.h under the theory that nobody except MACHINE.c
+ and write.c care about it anyway. */
+
+struct relax_type
+{
+ /* Forward reach. Signed number. > 0. */
+ long rlx_forward;
+ /* Backward reach. Signed number. < 0. */
+ long rlx_backward;
+
+ /* Bytes length of this address. */
+ unsigned char rlx_length;
+
+ /* Next longer relax-state. 0 means there is no 'next' relax-state. */
+ relax_substateT rlx_more;
+};
+
+typedef struct relax_type relax_typeS;
+
+extern const int md_reloc_size; /* Size of a relocation record */
+
+char *md_atof PARAMS ((int what_statement_type, char *literalP, int *sizeP));
+#ifndef md_estimate_size_before_relax
+int md_estimate_size_before_relax PARAMS ((fragS * fragP, segT segment));
+#endif
+int md_parse_option PARAMS ((int c, char *arg));
+void md_show_usage PARAMS ((FILE *));
+long md_pcrel_from PARAMS ((fixS * fixP));
+short tc_coff_fix2rtype PARAMS ((fixS * fixP));
+void md_assemble PARAMS ((char *str));
+void md_begin PARAMS ((void));
+#ifndef md_create_long_jump
+void md_create_long_jump PARAMS ((char *ptr, addressT from_addr,
+ addressT to_addr, fragS * frag,
+ symbolS * to_symbol));
+#endif
+#ifndef md_create_short_jump
+void md_create_short_jump PARAMS ((char *ptr, addressT from_addr,
+ addressT to_addr, fragS * frag,
+ symbolS * to_symbol));
+#endif
+void md_number_to_chars PARAMS ((char *buf, valueT val, int n));
+
+#ifndef md_operand
+void md_operand PARAMS ((expressionS * expressionP));
+#endif
+
+#ifdef MD_APPLY_FIX3
+int md_apply_fix3 PARAMS ((fixS * fixP, valueT *val, segT seg));
+#endif
+#ifdef BFD_ASSEMBLER
+int md_apply_fix PARAMS ((fixS * fixP, valueT *val));
+#ifndef md_convert_frag
+void md_convert_frag PARAMS ((bfd * headers, segT sec, fragS * fragP));
+#endif
+#ifndef tc_headers_hook
+void tc_headers_hook PARAMS ((segT *, fixS *));
+#endif
+#ifndef RELOC_EXPANSION_POSSIBLE
+extern arelent *tc_gen_reloc PARAMS ((asection *, fixS *));
+#else
+extern arelent **tc_gen_reloc PARAMS ((asection *, fixS *));
+#endif
+#else /* not BFD_ASSEMBLER */
+void md_apply_fix PARAMS ((fixS * fixP, long val));
+#ifndef md_convert_frag
+void md_convert_frag PARAMS ((object_headers * headers, segT, fragS * fragP));
+#endif
+
+#ifndef tc_crawl_symbol_chain
+void tc_crawl_symbol_chain PARAMS ((object_headers * headers));
+#endif /* tc_crawl_symbol_chain */
+
+#ifndef tc_headers_hook
+void tc_headers_hook PARAMS ((object_headers * headers));
+#endif /* tc_headers_hook */
+#endif /* BFD_ASSEMBLER */
+
+#ifndef md_section_align
+valueT md_section_align PARAMS ((segT seg, valueT size));
+#endif
+
+#ifndef md_undefined_symbol
+symbolS *md_undefined_symbol PARAMS ((char *name));
+#endif
+
+/* end of tc.h */
diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog
new file mode 100644
index 0000000000..d8f865680e
--- /dev/null
+++ b/gas/testsuite/ChangeLog
@@ -0,0 +1,2333 @@
+1999-05-02 Nick Clifton <nickc@cygnus.com>
+
+ * gas/mcore/allinsn.d: Update to match latest assembler
+ operations.
+
+1999-04-16 DJ Delorie <dj@cygnus.com>
+
+ * gas/i386/amd.s: Add NOPs to align for coff targets
+ * gas/i386/amd.d: and check for them.
+
+Thu Apr 15 15:03:43 1999 Jeffrey A Law (law@cygnus.com)
+
+ * gas/hppa/basic/basic.exp (do_coprmem): No longer expected to file.
+
+Wed Apr 14 13:43:06 1999 Jeffrey A Law (law@cygnus.com)
+
+ * gas/hppa/basic/branch.s: Do not use immediate value where we
+ really want a register.
+ * gas/hppa/basic/coprmem.s: Likewise.
+ * gas/hppa/basic/fmemLRbug.s: Likewise.
+ * gas/hppa/basic/coprmem.s: Likewise.
+ * gas/hppa/basic/spop.s: Likewise.
+ * gas/hppa/basic/imem.s: Likewise.
+ * gas/hppa/parse/badfmpyadd.s: Likewise.
+ * gas/hppa/parse/calldatabug.s: Likewise.
+ * gas/hppa/parse/entrybug.s: Likewise.
+ * gas/hppa/parse/exprbug.s: Likewise.
+ * gas/hppa/parse/fixup7bug.s: Likewise.
+ * gas/hppa/parse/labelbug.s: Likewise.
+ * gas/hppa/reloc/applybug.s: Likewise.
+ * gas/hppa/reloc/funcrelocbug.s: Likewise.
+ * gas/hppa/reloc/labelopbug.s: Likewise.
+ * gas/hppa/reloc/longcall.s: Likewise.
+ * gas/hppa/reloc/plabelbug.s: Likewise.
+ * gas/hppa/reloc/reduce.s: Likewise.
+ * gas/hppa/reloc/reduce2.s: Likewise.
+ * gas/hppa/reloc/reduce3.s: Likewise.
+ * gas/hppa/unsorted/brlenbug.s: Likewise.
+ * gas/hppa/unsorted/importbug.s: Likewise.
+ * gas/hppa/unsorted/lasbeldiffs.s: Likewise.
+
+ * gas/hppa/basic/basic.exp (do_imem): Handle multiple encodings
+ for loads and stores using reg + small d addresses.
+ No longer expect failure for mis-parse of imm %reg.
+
+1999-04-13 Doug Evans <devans@casey.cygnus.com>
+
+ * gas/m32r/m32rx.d (cmpu__rach): Fix expected output.
+ * gas/m32r/m32rx.s (bc__add,add__bc): Explicitly specify short branch
+ so branch relaxation restrictions won't interfere with parallelization
+ attempts.
+
+1999-04-08 Nick Clifton <nickc@cygnus.com>
+
+ * gas/mcore: New Directory.
+ * gas/mcore/allinsn.exp: New File: Expect file for MCore assembly
+ tests.
+ * gas/mcore/allinsn.s: New File: Source file for MCore assembly
+ tests.
+ * gas/mcore/allinsn.d: New File: Expected output file for MCore
+ assembly tests.
+
+1999-03-20 Doug Evans <devans@casey.cygnus.com>
+
+ * gas/m32r/m32rx.[sd]: Fix a few more testcases.
+
+1999-03-16 Martin Hunt <hunt@cygnus.com>
+
+ * gas/d30v/d30.exp (run_list_test): Add new tests,
+ label, guard-debug, serial, warn_oddreg, bittest, and mul.
+
+ * gas/d30v/opt.s: Fix some warnings and add a few labels
+ to keep things from parallelizing where we don't want them to.
+
+ * gas/d30v/reloc.s: Fix warning.
+
+ * gas/d30v/opt.d, reloc.d, inst.d: Rebuild.
+
+ * gas/d30v/label.s: New test. Check that labels are aligned
+ on 8-byte boundaries.
+
+ * gas/d30v/guard-debug.s: New test. Test output with "-g".
+
+ * gas/d30v/serial.s: New test. Check for warnings with
+ illegal serial instructions.
+
+ * gas/d30v/warn_oddreg.s: New test. CHeck for warnings when
+ odd-numbered registers are used for some instructions.
+
+ * gas/d30v/bittest.s: New test. Check for bit operation
+ instructions (BCLR, BNOT, BSET, BTST) in the IU.
+
+ * gas/d30v/mul.s: New test. Check for restricted sequences
+ in a bunch of different multiply instructions.
+
+ * gas/vtable/vtable.exp (run_list_test): Don't
+ run test on D30V.
+
+1999-03-05 Nick Clifton <nickc@cygnus.com>
+
+ * gas/all/gas.exp: Expect strongarm-coff target to fail cofftag
+ test.
+
+1999-02-13 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * gas/mips/mips.exp: Run the new tests, below.
+ * gas/mips/elf_e_flags1.d, gas/mips/elf_e_flags2.d,
+ gas/mips/elf_e_flags3.d, gas/mips/elf_e_flags4.d: New files.
+ * gas/mips/elf_e_flags.c, gas/mips/elf_e_flags.s: New files.
+
+ * lib/gas-defs.exp (run_dump_test): Document. It's not
+ really trivial.
+
+ * lib/gas-defs.exp (run_dump_test): Clean up logic for guessing
+ $program (the dump tool).
+
+1999-02-10 Doug Evans <devans@casey.cygnus.com>
+
+ * gas/m32r/allinsn.d: Prefix all | with \.
+ (push,pop): Fix expected output.
+ * gas/m32r/relax-1.d: Emitted nops are serial, not parallel.
+ * gas/m32r/fslot.d: Prefix all | with \.
+
+1999-02-08 Nick Clifton <nickc@cygnus.com>
+
+ * gas/vtable/inherit0.s: Do not use '@' prefix to .type operator.
+ Some ports use it as a comment initiator.
+
+ * gas/vtable/entry1.d: Do not look for an addend. Some ports use
+ REL relocations and so do not have one.
+
+1998-12-18 Nick Clifton <nickc@cygnus.com>
+
+ * gas/fr30/allinsn.s: Fix to match latest assembler syntax.
+ * gas/fr30/allinsn.d: Fix to match latest assembler output
+
+1998-12-03 Nick Clifton <nickc@cygnus.com>
+
+ * gas/fr30/allinsn.d: Updated to match latest assembler output.
+
+1998-12-02 Nick Clifton <nickc@cygnus.com>
+
+ * gas/fr30/allinsn.s: Replace illegal insns with legal versions.
+
+ * gas/fr30/allinsn.d: Update to match latest assembler output.
+
+Thu Nov 19 15:59:51 1998 Dave Brolley <brolley@cygnus.com>
+
+ * gas/fr30/allinsn.s: Reorder insns for better simulation.
+
+Thu Nov 19 07:50:44 1998 Doug Evans <devans@charmed.cygnus.com>
+
+ * gas/mips/sync.[sd]: New testcase.
+ * gas/mips/mips.exp: Run it.
+
+Wed Nov 18 11:27:56 1998 Dave Brolley <brolley@cygnus.com>
+
+ * gas/fr30/allinsn.s (dmov): Correct hex literals.
+
+Tue Nov 17 15:24:20 1998 Nick Clifton <nickc@cygnus.com>
+
+ * gas/fr30/allinsn.s: Moved currently un-assembliable instructions
+ to end of file.
+
+ * gas/fr30/allinsn.d: Added disassembly of currently assembliable
+ opcodes.
+
+Mon Nov 16 16:50:27 1998 Nick Clifton <nickc@cygnus.com>
+
+ * gas/fr30/allinsn.s: Fix syntax errors.
+
+Mon Nov 16 19:27:52 1998 Dave Brolley <brolley@cygnus.com>
+
+ * gas/fr30/allinsn.s: Fixed more typos.
+
+Fri Nov 13 13:15:01 1998 Nick Clifton <nickc@cygnus.com>
+
+ * gas/fr30/allinsn.s: Fixed typos and added some tests of upper
+ case vs lower case.
+
+Tue Nov 10 14:54:47 1998 Nick Clifton <nickc@cygnus.com>
+
+ * gas/fr30/allinsn.s: New file.
+ * gas/fr30/allinsn.d: New file.
+ * gas/fr30/allinsn.exp: New file.
+ * gas/fr30/fr30.exp: New file.
+
+Mon Nov 2 20:16:50 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * gas/m32r/fslot.[sd]: New testcase.
+ * gas/m32r/m32r.exp: Run it.
+
+Tue Oct 20 11:35:06 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * gas/i386/i386.exp: Run AMD insn test.
+ * gas/i386/amd.s: New test.
+ * gas/i386/amd.d: New test results.
+
+Sun Sep 20 01:00:01 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * gas/vtable/inherit1.l: Require only the word GAS somewere in the
+ first line of the listing.
+
+Tue Sep 1 10:20:03 1998 Richard Henderson <rth@cygnus.com>
+
+ * gas/ppc/astest.d: Adjust regexps to match a 64-bit host.
+ * gas/ppc/astest2.d: Likewise.
+
+Mon Aug 31 13:25:07 1998 Richard Henderson <rth@cygnus.com>
+
+ * gas/vtable/{entry0.d,entry1.d,inherit0.d}: Fix pattern matching
+ of whitespace for 64-bit hosts.
+
+Mon Aug 31 12:45:49 1998 Richard Henderson <rth@cygnus.com>
+
+ * gas/vtable/vtable.exp: New.
+ * gas/vtable/{entry0.s,entry0.d}: New.
+ * gas/vtable/{entry1.s,entry1.d}: New.
+ * gas/vtable/{inherit0.s,inherit0.d}: New.
+ * gas/vtable/{inherit1.s,inherit1.l}: New.
+
+Thu Aug 20 23:18:06 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/i386/white.l: Revert patch of August 12.
+
+Wed Aug 12 11:54:37 1998 Jeffrey A Law (law@cygnus.com)
+
+ * gas/mn10300/udf.s: New test.
+ * gas/mn10300/basic.exp: Run it.
+
+Wed Aug 12 13:25:38 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * gas/i386/general.l: Test andb $~0x80,foo.
+ * gas/i386/general.s: Update.
+
+ * gas/i386/white.l: Expect warning for stand-alone ss prefix.
+
+Tue Jul 21 12:46:59 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * gas/i386/white.s: Add some more whitespace tests.
+ * gas/i386/white.l: Update accordingly.
+
+Mon Jul 13 18:15:11 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * gas/i386/*: All new i386 testsuite.
+
+1998-07-02 Ken Raeburn <raeburn@cygnus.com>
+
+ * lib/gas-defs.exp (gas_init): Complain if target name isn't in
+ canonical form.
+
+Wed Jul 1 15:35:09 1998 Nick Clifton <nickc@cygnus.com>
+
+ * gas/all/gas.exp: Expect ARM and Thumb cofftag test to fail.
+
+Wed Jul 1 17:31:39 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/ppc/simpshft.s: Add alignment so that it works on AIX.
+ * gas/ppc/simpshft.d: Change accordingly. Only dump the .text
+ section.
+
+Tue Jun 23 15:14:43 1998 Nick Clifton <nickc@cygnus.com>
+
+ * gas/v850/hilo2.s: Use r1 as the destination of the movea
+ instruction, since r0 is read only.
+
+ * gas/v850/basic.exp: Fix names of special area relocations.
+ Set -mwarn-signed-overflow flag when running range.s test.
+
+Sun Jun 21 12:44:43 1998 Nick Clifton <nickc@cygnus.com>
+
+ * gas/d30v/reloc.d: Updated to match latest assembler output.
+
+Wed Jun 17 14:02:10 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * gas/mips/delay.d: Add -mcpu=NNNN to gas flags to let test case
+ run on differently targeted assembler.
+ * gas/mips/{ld-ilocks-addr32,ld-svr4pic.d}: Ditto.
+ * gas/mips/{ld-xgot.d,lif-svr4pic.d,lif-xgot.d}: Same.
+ * gas/mips/{mips16.d,mips4.d,nodelay.d}: Again.
+ * gas/mips/{trunc.d,uld.d,ulh-xgot.d,usd.d}: And then some.
+
+ * gas/mips/ld-ilocks.d: Removed disassembler flags to let target
+ defaults go unmodified. Replaced $f4/$f5 with $fp[45], as the
+ original `ld.d' had. Find `ld.s'.
+ * gas/mips/mul-ilocks.d: Nearly ditto.
+
+Thu Jun 11 16:50:46 1998 Nick Clifton <nickc@cygnus.com>
+
+ * gas/d30v/inst.d: Expect repeati instrucitons to be combined.
+
+ * gas/d30v/inst.s: Add nop to keep assembled instructions at
+ expected addresses.
+
+Mon Jun 8 18:47:11 1998 Nick Clifton <nickc@cygnus.com>
+
+ * gas/d30v/array.d: Updated to match latest assembler results.
+ * gas/d30v/reloc.d: Partially updated to match latest assembler
+ results.
+
+Fri Jun 5 19:15:59 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * gas/m68k/operands.s: For all pc relative addresses change tstl
+ to pea since the former does not allow pcrel on m68000. Do not
+ make label foo global, so that references to it can be relaxed on
+ ELF targets.
+ * gas/m68k/operands.d, gas/m68k/op68000.d: Updated.
+
+Tue Jun 2 15:08:36 1998 Geoff Keating <geoffk@ozemail.com.au>
+
+ * gas/ppc/ppc.exp: Run simpshft test.
+ * gas/ppc/simpshft.d: New file.
+ * gas/ppc/simpshft.s: New file.
+
+Mon Jun 1 17:00:22 1998 Jeffrey A Law (law@cygnus.com)
+
+ * gas/mips/div-ilocks.d: Handle both "break" instruction variants.
+ * gas/mips/{div.d, mul-ilocks.d, mul.d}: Likewise.
+
+Fri May 29 12:07:35 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mips/mips.exp: Adjust ilocks initialization to match current
+ assembler defaults more closely.
+
+ * gas/sh/fp.s: Remove ftst/nan. The assembler no longer supports
+ the instruction.
+ * gas/sh/basic.exp: Adjust accordingly.
+
+Wed May 27 15:26:51 1998 Nick Clifton <nickc@cygnus.com>
+
+ * gas/d30v/align.d: Updated to match latest assembler output.
+ * gas/d30v/inst.d: Updated to match latest assembler output.
+ * gas/d30v/inst.s: Updated to match latest assembler rules.
+ * gas/d30v/opt.d: Updated to match latest assembler output.
+
+Fri May 22 15:56:51 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * gas/m32r/allinsn.d: Handle 64 bit bfd_vma.
+ * gas/m32r/uppercase.d: Likewise.
+
+Thu May 21 15:03:06 1998 Nick Clifton <nickc@cygnus.com>
+
+ * gas/arm/thumb.s: Add period to start of labels to prevent
+ assembler thinking that they are function entry points.
+
+Tue May 19 18:17:10 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mips/mips16.d: Correct to reflect bug fix to disassembler.
+
+Mon May 18 13:11:45 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * gas/mips/{div,ld,mul}.d: Add assembler -mcpu= flag to match
+ disassembler.
+
+Fri May 15 14:51:01 1998 Gavin Koch <gavin@cygnus.com>
+
+ * gas/mips/mips.exp: Distinguish chains with 32-bit addresses.
+ * gas/mips/ld-ilocks-addr32.d : New.
+
+Wed May 13 15:06:31 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * gas/m32r/uppercase.[sd]: Test for HIGH,SHIGH,LOW,SDA.
+
+Thu May 7 13:05:25 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * gas/mips/break20.[sd]: New tests for 20-bit operand break and
+ sddbp instructions.
+ * gas/mips/trap20.[sd]: New tests for 20-bit operand trap
+ instructions.
+ * gas/mips/mips.exp: Run them.
+
+Thu Apr 30 11:55:01 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * gas/d30v/{inst,array,opt,reloc}.d: Accept <symbol+offset> labels
+ in disassembly, where the offset is in hex and has a "0x" prefix.
+
+Tue Apr 28 16:38:34 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * gas/mips/lineno.[sd]: Assembly source line number test.
+ * gas/mips/mips.exp: Added lineno test.
+
+Wed Apr 8 18:45:17 1998 Jeffrey A Law (law@cygnus.com)
+
+ * gas/testsuite/all/gas.exp: No longer expect failures for
+ difference of undefined symbols on mn10x00 targets.
+
+Mon Mar 23 10:47:33 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * gas/all/align.s: Back out ".section text" change below;
+ use ".text" again.
+ * gas/macros/semi.s: Ditto.
+
+Fri Mar 20 18:51:49 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * gas/all/align.s: Identify ".text" section explicitly.
+ * gas/macros/semi.s: Ditto.
+
+
+
+Mon Mar 2 13:30:40 1998 Doug Evans <devans@seba.cygnus.com>
+
+ * gas/m32r/allinsn.[sd] (ldi8a,ldi16a): Delete.
+ (ldi16): Improve test.
+ (nop): Fix test.
+
+Thu Feb 12 20:12:39 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * gasp/macro.out: Adjust to reflect the fact that keyword
+ arguments are now permitted after positional arguments.
+
+Wed Feb 4 15:27:44 1998 Nick Clifton <nickc@cygnus.com>
+
+ * gas/arm/arm7t.d: Update to match latest assembler output.
+
+Wed Feb 4 15:40:00 1998 Geoffrey Keating <geoffk@ozemail.com.au>
+
+ * gas/ppc/ppc.exp: New file.
+ * gas/ppc/astest.s, gas/ppc/astest.d: New test.
+ * gas/ppc/astest2.s, gas/ppc/astest2.d: New test.
+
+Sun Feb 1 21:43:54 1998 Jeffrey A Law (law@cygnus.com)
+
+ * gas/mips/4010.s: Pad test code out to a 16byte boundary.
+ * gas/mips/4010.d: Corresponding changes.
+ * gas/mips/4100.s: Pad test code out to a 16byte boundary.
+ * gas/mips/4100.d: Corresponding changes.
+ * gas/mips/4650.s: Pad test code out to a 16byte boundary.
+ * gas/mips/4650.d: Corresponding changes.
+
+Fri Jan 30 14:09:13 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mri/moveml.d: Add test comments, fix regexps.
+
+Thu Jan 29 13:34:49 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * gas/m32r/{allinsn,high-1}.d: Allow # constant prefix to be missing.
+
+Thu Jan 29 09:43:50 1998 Richard Henderson <rth@cygnus.com>
+
+ * gas/m68k/mri_moveml.[sd]: Moved to ...
+ * gas/mri/moveml.[sd]: ... here.
+ * gas/mri/mri.exp: Run it.
+
+Tue Jan 27 21:55:44 1998 Jeffrey A Law (law@cygnus.com)
+
+ * gas/mips/4010.s: Add 4010 tests.
+ * gas/mips/4010.d: Expected output.
+ * gas/mips/4100.s: Add 4010 tests.
+ * gas/mips/4100.d: Expected output.
+ * gas/mips/4650.s: Add 4010 tests.
+ * gas/mips/4650.d: Expected output.
+ * gas/mips/mips.exp: Run the new tests.
+ * gas/mips/*.d: Pass the right processor model to objdump.
+ Fix minor cases where expected output was wrong due to opcode
+ conflicts.
+
+Tue Jan 27 05:35:02 1998 Richard Henderson <rth@cygnus.com>
+
+ * gas/m68k/mri_moveml.[sd]: New testcase.
+
+Thu Jan 22 17:29:07 1998 Nick Clifton <nickc@cygnus.com>
+
+ * gas/m32r/high-1.d: Add hash prefix to constants.
+
+ * gas/m32r/allinsn.s: Add hash prefix to some constants.
+ * gas/m32r/allinsn.d: Add hash prefix to constants.
+
+Wed Jan 21 21:24:08 1998 Manfred Hollstein <manfred@s-direktnet.de>
+
+ * gas/m88k/init.d: Fix hexadecimal offsets.
+
+Wed Jan 14 17:49:22 1998 Nick Clifton <nickc@cygnus.com>
+
+ * gas/m32r/uppercase.d: Fix white space matching.
+ * gas/m32r/relax-1.d: Fix white space matching.
+
+Wed Jan 14 15:44:32 1998 Jeffrey A Law (law@cygnus.com)
+
+ * gas/mips/div.d: Update for recent assembler changes.
+ * gas/mips/div-ilocks.d: Likewise.
+
+Wed Jan 14 11:13:06 1998 Doug Evans <devans@seba.cygnus.com>
+
+ * gas/m32r/allinsn.d (cmpui): Update output to new format.
+
+Thu Dec 18 11:10:42 1997 Nick Clifton <nickc@cygnus.com>
+
+ * gas/arm/inst.d: Updated to match latest disassembler changes.
+
+ * gas/arm/arm7t.d: Updated to match latest disassembler changes.
+
+Tue Dec 16 22:19:25 1997 Ken Raeburn <raeburn@cygnus.com>
+
+ * gas/mips/lb-xgot.d, gas/mips/rol.d, gas/mips/jal-svr4pic.d,
+ gas/mips/jal-xgot.d: Add assembler option to select a specific
+ target chip, the R3000.
+ * gas/mips/lb-xgot-ilocks.d: New test, specifically selecting
+ R3900.
+ * gas/mips/mips.exp: Run it.
+
+ * gas/ieee-fp/x930509a.exp: Don't run IEEE FP tests for Vax
+ targets.
+
+Wed Oct 15 10:40:14 1997 Jeffrey A Law (law@cygnus.com)
+
+ * gas/ieee-fp/x930509a.s: Tweak slightly to work on the PA.
+
+ * gas/hppa/unsorted/unsorted.exp: Update for recent disassembler
+ changes.
+
+Thu Oct 9 18:10:44 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * gas/sparc/set64.[sd]: `set' doesn't take negative arguments.
+
+Thu Oct 9 12:59:55 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/arm/arm7t.d: Update for recent disassembler changes.
+ * gas/h8300/ffxx1.d: Likewise.
+
+Wed Oct 8 16:22:50 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * gas/sparc/reloc64.[sd]: Add testcases for %hix,%lox.
+
+Wed Oct 8 15:12:35 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/sparc/synth.d: Update for recent disassembler changes.
+ * gas/sparc/synth64.d: Likewise.
+
+ * gas/mips/beq.s: Add .text to .globl to mark the symbol to as a
+ function symbol.
+ * gas/mips/jal.s: Likewise.
+
+Tue Oct 7 13:30:30 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * gas/sparc/reloc64.[sd]: New testcase.
+ * gas/sparc/sparc.exp: Run it.
+
+Sat Oct 4 19:14:24 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/ieee-fp/x930509a.exp: Accept m68k listing format.
+
+Fri Oct 3 15:46:05 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/ieee-fp/x930509a.exp: Remove setup_xfail; it should now
+ work. Correct for big endian and for tabs in input file.
+
+ * gas/alpha/fp.exp: Check for alpha-*-osf*, not alpha-*-osf1*.
+ * gas/alpha/fp.s: Change comment characters from ! to #.
+
+Thu Sep 18 11:17:53 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * gas/sparc/splet.d: Update to new objdump output format.
+ * gas/sparc/{asi.d,membar.d,prefetch.d,rdpr.d,wrpr.d}: Likewise.
+ * gas/sparc/set64.[ds]: New testcase.
+ * gas/sparc/splet-2.[ds]: New testcase.
+ * gas/sparc/sparc.exp: Run them.
+
+Tue Sep 16 15:27:08 1997 Ken Raeburn <raeburn@cygnus.com>
+
+ Merge changes from Martin Hunt:
+
+ * gas/d30v/inst.s: Add some new tests.
+
+ * gas/d30v/{inst, opt, reloc}.d: Update results with
+ new disassembler changes.
+
+ * gas/d30v/inst.[sd]: Update examples for d*i instructions.
+
+ * gas/d30v/*.d: Update all test results because
+ of new ".s" and ".l" extensions.
+
+ * gas/d30v/inst.[sd]: Correct entry for mulx2h.
+ * gas/d30v/opt.[sd]: Correct st2w instruction.
+
+ * gas/d30v/align.d: Change expected output.
+
+ * gas/d30v/reloc.[sd]: Add test case.
+
+ * gas/d30v/array.[sd]: New test case.
+
+ * gas/d30v/opt.[sd]: Added more test cases.
+
+ * gas/d30v/opt.s: Add test cases.
+ * gas/d30v/reloc.s: Fix a test case.
+ * gas/d30v/{opt,reloc}.d: Regenerate.
+
+Mon Sep 8 14:21:23 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * gas/m32r/high-1.[ds]: New testcase.
+ * gas/m32r/m32r.exp: Run it.
+
+Mon Aug 25 11:04:24 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * gas/m32r/relax-1.[ds]: New testcase.
+ * gas/m32r/m32r.exp: Run it.
+
+Thu Aug 14 23:49:49 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * gas/arc: New directory
+ * gas/arc/{arc.exp,alias.[sd],branch.[sd],flag.[sd],insn3.[sd],j.[sd],
+ ld.[sd],math.[sd],sshift.[sd],st.[sd],warn.{exp,s}}: New files.
+
+Wed Aug 6 00:33:30 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/default.exp: Set AS and GASP to as-new, not as.new.
+
+Tue Aug 5 12:33:23 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/default.exp: Set NM to nm-new, not nm.new, to match
+ recent change in binutils build directory.
+
+Thu Jul 31 15:21:51 1997 Jeffrey A Law (law@cygnus.com)
+
+ * gas/v850/range.s: New test.
+ * gas/v850/basic.exp: Run it.
+
+Tue Jul 29 14:35:02 1997 Jeffrey A Law (law@cygnus.com)
+
+ * gas/v850/hilo2.s: New test.
+ * gas/v850/fepsw.s: New test.
+ * gas/v850/basic.exp: Run them.
+
+Tue Jul 15 13:03:17 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * gas/m32r/uppercase.[sd]: New testcase.
+ * gas/m32r/m32r.exp: New file.
+
+Mon Jun 16 14:32:11 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/m68k/pcrel.d: Update for m68k disassembler changes.
+ * gas/m68k/operands.d: Likewise.
+
+Mon Jun 2 16:50:03 1997 Nick Clifton <nickc@cygnus.com>
+
+ * gas/arm/arm.exp: Added changes from armT-970328-branch.
+
+Mon Jun 2 12:09:02 1997 Gavin Koch <gavin@cygnus.com>
+
+ * gas/mips/mips.exp: The r3900 has interlocks for mul, but
+ not div.
+
+Mon Jun 2 12:03:32 1997 Gavin Koch <gavin@.cygnus.com>
+
+ * gas/mips/mul.{d,s}: End the tests with no-ops.
+
+Mon Jun 2 11:48:58 1997 Gavin Koch <gavin@cygnus.com>
+
+ * lib/gas-defs.exp (regexp_diff): Improve messages when one
+ file is shorter than the other.
+
+Wed May 7 16:18:30 1997 Manfred Hollstein <manfred@s-direktnet.de>
+
+ * gas/m88k/init.{s,d}: New checks for proper padding of
+ .init sections.
+ * gas/m88k/m88.exp: Run them.
+
+ * gas/m68k/t2.d: New file for check of presence of section
+ symbols on the m68k-motorola-sysv.
+ * gas/m68k/all.exp: Run t2 if [istarget m68*-motorola-sysv].
+
+Wed May 7 16:12:24 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/all/gas.exp: Don't run cofftag test for m88k-coff.
+
+ * gas/mips/lifloat.s: Update for recent changes to floating point
+ handling.
+ * gas/mips/lif-empic.d, gas/mips/lif-svr4pic.d: Likewise.
+ * gas/mips/lif-xgot.d, gas/mips/lifloat.d: Likewise.
+
+ * gas/mips/mips.exp: Handle Irix 6 like Irix 5.
+
+Sat Apr 19 23:16:35 1997 Niklas Hallqvist <niklas@petra.appli.se>
+
+ * gas/mips/mips.exp: Handle OpenBSD like NetBSD.
+
+Wed Apr 16 12:20:24 1997 Martin Hunt <hunt@cygnus.com>
+
+ * gas/d30v/d30.exp: Add optimizer test case.
+ * gas/d30v/opt.s: Add conditional compilation tests.
+ * gas/d30v/opt.d: Rebuild.
+
+Tue Apr 15 18:10:01 1997 Gavin Koch <gavin@cygnus.com>
+
+ * gas/mips/{delay.d,nodelay.d}: added.
+
+Mon Apr 7 12:57:45 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * gas/m32r/allinsn.d: Update to new objdump output style.
+
+Fri Apr 4 13:19:39 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/all/float.s: Put a tab before .text, to keep the PA happy.
+
+ * gas/arm/arm.exp: Only run inst and arm7t on targets which can
+ handle -EL. Add setup_xfail for thumb.
+
+ * gas/h8300/ffxx1.d: Don't fail if BFD is 64 bits.
+
+Thu Apr 3 18:26:56 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * gas/m32r/allinsn.{exp,s.d}: New testcases.
+
+Thu Mar 27 00:42:28 1997 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * gas/d30v/d30.exp: Add test case reloc.
+ * gas/d30v/reloc.[sd]: New files to test relocations.
+
+Sat Mar 15 17:21:46 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/arm/inst.d: Update for disassembler changes.
+ * gas/arm/arm7t.d: Likewise.
+
+Tue Mar 11 13:31:56 1997 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * gas/m68k/op68000.d: Update for recent assembler bug fix.
+
+Wed Mar 5 13:01:24 1997 Jeffrey A Law (law@cygnus.com)
+
+ * gas/all/gas.exp: xfail a couple tests for the mn10300.
+
+Mon Mar 3 11:41:00 1997 Fred Fish <fnf@cygnus.com>
+
+ * gas/tic80/{add.d, float.d, regops2.d, relocs1.d, relocs1b.d,
+ relocs2.d, relocs2b.d}: Adjust to objdump format tweaks.
+
+Thu Feb 27 15:21:46 1997 Fred Fish <fnf@cygnus.com>
+
+ * gas/tic80/{align.d, align.lst, align.s} New test for the
+ ".align" pseudop.
+ * gas/tic80/tic80.exp: Run the align test.
+
+Wed Feb 26 20:36:46 1997 Fred Fish <fnf@cygnus.com>
+
+ * gas/tic80/{float.d, float.lst, float.s}: New tests for
+ simple floating point operands.
+ * gas/tic80/tic80.exp: Run the float test.
+
+Wed Feb 26 15:16:04 1997 Fred Fish <fnf@cygnus.com>
+
+ * gas/tic80/{regops2.d, regops2.lst, regops2.s, regops3.d,
+ regops3.lst, regops3.s, regops4.d, regops4.lst, regops4.s}:
+ New tests for :m and :s operand modifiers.
+ * gas/tic80/tic80.exp: Run the regops2, regops3, and regops4 tests.
+
+Tue Feb 25 13:45:55 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/macros/semi.s: Force the final alignment to use a fill value
+ of 0.
+
+ * gas/all/cond.s, gas/all/cond.d: New test.
+ * gas/all/gas.exp: Run it.
+
+Mon Feb 24 10:52:12 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * lib/gas-defs.exp(gas_init): Added new parameter for script
+ name.
+
+Mon Feb 24 10:40:28 1997 Fred Fish <fnf@cygnus.com>
+
+ * gas/tic80/{add.d, bitnum.d, ccode.d, cregops.d, endmask.d,
+ regops.d, relocs1.d,
+ (relocs1.c): Add file for reference.
+ (relocs1b.d): Split reloc table contents test to different test file.
+ (relocs2.c): Add test that uses various types (char, short, int, ...) of
+ static and global variables with data shuffling to generate lots of ld/st
+ instructions for the different types.
+ (relocs2.d): New file, expected code for relocs2 test.
+ (relocs2.lst): New file, TI assembler listing for reference.
+ (relocs2.s): New file, assembly source for relocs2 test.
+ (relocs2b.d): New file, expected reloc table contents for relocs2 test.
+ (tic80.exp): Run the relocs1b, relocs2, and relocs2b tests.
+
+Sun Feb 23 17:54:00 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * gas/all/itbl-test.c(main): Update function calls.
+ Remove parameters from itbl_get_reg_val and
+ change itbl_get_insn_name to itbl_get_field.
+
+Sun Feb 23 17:22:00 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * gas/mips/itbl: Add comments.
+ * gas/mips/itbl.s: Add comments. Prefix register names with $.
+ * gas/all/itbl: Generic table for testing for itbl support.
+ * gas/all/itbl.s: Generic assembly for testing for itbl support.
+ * gas/mips/itbl-test.c: Moved to gas/all.
+ * gas/all/itbl-test.c: Moved from gas/mips.
+
+Sat Feb 22 20:24:23 1997 Fred Fish <fnf@cygnus.com>
+
+ * gas/tic80/{add.lst, bitnum.lst, ccode.lst, cregops.lst,
+ endmask.lst, regops.lst}: Remove ^M's from end of lines.
+ * gas/tic80/bitnum.s: Add comment to each line showing value
+ that symbolic BITNUM assembles to. Add coverage for raw
+ numeric values for the BITNUM operand.
+ * gas/tic80/bitnum.d: Update due to bitnum.s changes.
+ * gas/tic80/regops.d: Update due to opcode library additions
+ of floating point test BITNUM values that are ambiguous with
+ the integral ones.
+ * gas/tic80/relocs1.s: New test case that tests simple relocs.
+ * gas/tic80/relocs1.d: Expected output for above.
+ * gas/tic80/relocs1.lst: TI assembler listing for above.
+ * gas/tic80/tic80.exp: Add relocs1 test.
+
+Fri Feb 21 14:23:14 1997 Martin M. Hunt <hunt@pizza.cygnus.com>
+
+ * gas/d30v/{align.d, align.s, d30.exp, guard.d, guard.s,
+ inst.d, inst.s, opt.d, opt.s}: Test files for D30V.
+
+Wed Feb 19 00:55:29 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/macros/semi.s, gas/macros/semi.d: New test.
+ * gas/macros/macros.exp: Run it.
+ * gas/mri/semi.s, gas/mri/semi.d: New test.
+ * gas/mri/mri.exp: Run it.
+
+Tue Feb 18 13:37:06 1997 Jeffrey A Law (law@cygnus.com)
+
+ * gas/hppa/unsorted/unsorted.exp (align4 tests): Tweak expected
+ output.
+
+Fri Feb 14 17:56:27 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/all/align.d, gas/all/align.s: New test.
+ * gas/all/gas.exp: Run it.
+
+Thu Feb 13 14:44:05 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mips/mips16.d: Correct PC relative instruction bytes.
+
+Wed Feb 12 12:33:08 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mips/lif-svr4pic.d: Pass -EB when running the assembler.
+ * gas/mips/lif-xgot.d: Likewise.
+ * gas/mips/ulh-svr4pic.d: Likewise.
+ * gas/mips/ulh-xgot.d: Likewise.
+
+ * gas/mips/mips16.d: Update for yet another change in disassembly
+ output (this one is spacing only).
+
+Tue Feb 11 14:45:39 1997 Fred Fish <fnf@cygnus.com>
+
+ * gas/tic80/{add.d, add.lst, add.s, bitnum.d, bitnum.lst, bitnum.s,
+ ccode.d, ccode.lst, ccode.s, cregops.d, cregops.lst, cregops.s,
+ endmask.d, endmask.lst, endmask.s, regops.d, regops.lst, regops.s,
+ tic80.exp}: New files for TIc80 test cases.
+
+Tue Feb 11 15:46:27 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mips/mips16.d: Update for change in disassembly output.
+
+Mon Feb 10 22:24:00 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * gas/mips/itbl-test.c: Add copyright message and fix indentation.
+
+Mon Feb 10 17:54:00 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * gas/mips/itbl-test.c: New file. Stand-alone assembler and
+ dissassembler for itbl support.
+
+Mon Feb 10 17:20:00 1997 Dawn Perchik <dawn@cygnus.com>
+
+ * gas/mips/itbl: New file. Instruction Spec for testing --itbl
+ option.
+ * gas/mips/itbl.s: New file. Assembly with ne2w instructions
+ specified in itbl.
+
+Fri Feb 7 16:42:53 1997 Bob Manson <manson@charmed.cygnus.com>
+
+ * gasp/gasp.exp: Use prune_warnings instead of prune_system_crud.
+ * lib/gas-defs.exp: Ditto.
+
+Mon Feb 3 15:46:05 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/arm/inst.d, gas/arm/arm7t.d: Pass --prefix-addresses to
+ objdump. Update for current relocation printing style.
+
+Thu Jan 30 11:57:33 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mips/mips16.d: Update for disassembler changes.
+
+Thu Jan 23 03:15:06 1997 Angela Marie Thomas (angela@cygnus.com)
+
+ * gas/mips/mips.exp: set ilocks for all 4100/4300
+
+Thu Jan 2 16:49:17 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mips/mips16.s, gas/mips/mips16.d: New test.
+ * gas/mips/mips.exp: Run mips16 test.
+
+ * gas/mips/mips.exp: Run dli test unconditionally.
+ * gas/mips/dli.s: Add text symbol. Add nops to round to 16 byte
+ boundary.
+ * gas/mips/dli.d: Corresponding changes.
+
+Tue Dec 31 13:03:16 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/sparc/synth.d: Use --prefix-addresses for objdump.
+ * gas/sparc/synth64.d: Likewise.
+
+Tue Dec 24 16:30:58 1996 Angela Marie Thomas (angela@cygnus.com)
+
+ * gas/mips/*-ilocks.d: Fix regexps to resemble disassembled output.
+
+Fri Dec 13 13:05:33 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mips/*.[sd]: Add explicit nops, sometimes controlled by
+ .ifdef, to accomodate change to avoid default alignment on
+ embedded systems.
+
+Wed Dec 11 09:26:01 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/mn10200/basic.exp (do_movb): Fix bit pattern for
+ "movb dm,(an)".
+
+Tue Dec 10 13:01:05 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/mn10300/basic.exp: Update after endianness changes to
+ the assembler.
+
+ * gas/mn10200/{mov1.s,mov2.s,mov3.s,mov4.s,movx.s}: New tests.
+ * gas/mn10200/{movb.s, movbu.s}: Likewise.
+ * gas/mn10200/basic.exp: Run them.
+
+Mon Dec 9 17:08:38 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/mn10200/*.s: New tests for the mn10200 assembler.
+ * gas/mn10200/basic.exp: Run them.
+
+Fri Dec 6 15:35:04 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/mn10300/*.s: Remove '$' register prefixing.
+
+Mon Nov 25 16:35:33 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * gas/sparc-solaris/addend.exp: Fix patterns, you can't assume
+ \r will be present.
+
+Mon Nov 25 13:45:02 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/m68k/*.d: Update for disassembler changes.
+ * gas/mri/*.d: Likewise.
+
+Mon Nov 25 11:38:37 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/mn10300/*.s: Use '$' as register prefix for
+ all register operands.
+
+Thu Nov 21 11:52:54 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/all/gas.exp: xfail a couple tests for the mn10300.
+
+Wed Nov 20 11:31:41 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/mn10300/other.s: Update for correct syntax on a
+ few instructions (those with register lists).
+ * gas/mn10300/basic.exp: Corresponding changes.
+
+Tue Nov 19 13:36:57 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/mn10300/movm.s: Update for correct syntax.
+ * gas/mn10300/basic.exp: Update expected movm bit patterns.
+
+Fri Nov 15 13:57:42 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/mn10300/other.s: Put parens around register
+ argument in calls and jmp instructions.
+
+Wed Nov 13 13:16:04 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/h8300/ffxx1.d: Update for recent disassembler changes.
+
+Mon Nov 11 16:03:24 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/hppa/reloc/reloc.exp: Pass "--prefix-addresses" to objdump
+ as needed.
+ * gas/hppa/unsorted/unsorted.exp: Likewise.
+
+Thu Nov 7 00:27:52 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/mn10300/basic.exp: Check opcode insertion for
+ extended instructions.
+ * gas/mn10300/extend.s: Tweak constants for better
+ testsuite coverage.
+
+Wed Nov 6 13:50:07 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/mn10300/basic.exp: Test insertion of operands
+ into call and jmp instructions with 32bit offsets.
+ Fix typo in bit test patterns.
+ * gas/mn10300/other.s: Tweak constants to improve
+ testsuite coverage.
+
+ * gas/mn10300/basic.exp: Test insertion of 32bit operand
+ in calls, btst, bclr & bset instructions.
+
+ * gas/mn10300/*.s: Tweak constants in 32bit insns for
+ better testing coverage.
+ * gas/mn10300/basic.exp: Test insertion of most 32bit
+ operands.
+
+Tue Nov 5 13:33:12 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/mn10300/basic.exp: Check bit patterns for indexed mov,
+ movbu, movhu instructions. Check bit patterns for more bit
+ operations. Check bit patterns for various 16bit call, retf
+ and ret instructions.
+ * gas/mn10300/other.s: Update operands for better test coverage.
+
+Mon Nov 4 12:55:11 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/mn10300/basic.exp: Check bit patterns for a couple more
+ mov and cmp instructions.
+
+Tue Oct 29 17:05:43 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mips/*.d: Update for disassembler changes.
+
+Wed Oct 16 22:39:50 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/v850/reloc.s: New tests.
+ * gas/v850/basic.exp: Run them.
+
+Mon Oct 14 13:52:55 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mips: Add symbols to several testsuites, since the ELF
+ assembler now always builds a symbol table, which means that
+ objdump will no longer report `No symbols in FILE'. Change the
+ expected output accordingly.
+
+Thu Oct 10 13:11:48 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/mn10300/basic.exp: Check bit patterns for instructions
+ with a single 8bit or 16bit immediate operand.
+
+ * gas/mn10300/basic.exp: Check bit patterns for many
+ instructions. Add missing test in do_mov1.
+ * gas/mn10300/mov1.s: Add missing test.
+
+Wed Oct 9 14:15:18 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/mn10300/{add.s, bcc.s, bit.s, cmp.s, ext.s}: New tests.
+ * gas/mn10300/{extend.s logical.s, loop.s, mov1.s}: Likewise.
+ * gas/mn10300/{mov2.s, mov3.s, mov4.s, movbu.s}: Likewise.
+ * gas/mn10300/{movhu.s, movm.s, muldiv.s, other.s}: Likewise.
+ * gas/mn10300/{shift.s, sub.s}: Likewise.
+ * gas/mn10300/basic.exp: Run them.
+
+Thu Oct 3 09:57:03 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/mn10200, gas/mn10300: New directories for Matsushita
+ mn10200 and mn10300 tests.
+
+Tue Oct 1 15:38:28 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * lib/gas-defs.exp (gas_version): Fix for current version
+ printing.
+
+Sun Sep 29 07:55:58 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * gas/sparc/splet.d: Fix typo in cpusha result.
+
+Mon Sep 23 12:33:31 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/m68k/fmoveml.s, gas/m68k/fmoveml.d: Add tests for fmovemx.
+
+Wed Sep 18 12:14:06 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/all/cofftag.s: Use .p2align rather than .align.
+
+Fri Sep 13 15:28:04 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/h8300/macs.s: Add "stmac" instructions.
+ * gas/h8300/basic.exp: Test them.
+
+Thu Sep 12 10:28:44 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * gas/arm/thumb.s (back): Check assembly of Thumb BL.
+
+Mon Sep 9 14:37:00 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mips/mips4.s, gas/mips/mips4.d: Use $fccN for condition code
+ registers.
+
+Fri Sep 6 18:23:54 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * gas/mips/dli.{s,d}: More test cases added.
+
+Wed Sep 4 11:47:29 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * gas/mips/mips.exp: Add check for dli macro instruction.
+ * gas/mips/dli.{s,d}: Added.
+
+Sat Aug 31 01:25:03 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/v850/basic.exp (do_mem): Check bit patterns for short
+ load/store instructions. Remove xfails for short load/store
+ instructions.
+ * gas/v850/mem.s: Offsets for short load/store operands
+ are unsigned.
+
+ * gas/v850/basic.exp (do_branch): Check offsets in branch insns.
+ (do_jumps): Likewise.
+
+Fri Aug 30 00:37:55 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/v850/misc.s: Tweak register numbers for better testing.
+ * gas/v850/basic.exp (do_misc): Corresponding changes.
+
+ * gas/v850/hilo.s: New testfile.
+ * gas/v850/basic.exp: Run hilo tests.
+
+Thu Aug 29 11:32:23 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * gas/arm/arm7t.d: Explicitly force little-endian assembly.
+
+Fri Aug 23 11:02:55 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/v850/basic.exp (do_move): Test instruction bit patterns.
+ * gas/v850/move.s: Tweak constants for better testing.
+
+ * gas/v850/basic.exp (do_mem): Test instruction bit patterns.
+ xfail sst and sld tests.
+ (do_mov): Remove bogus xfail.
+ * gas/v850/mem.s: sst and sld instructions can only index from
+ "ep" register.
+
+ * gas/v850/basic.exp (do_logical): Test instruction bit patterns.
+ Update addresses.
+ * gas/v850/logical.s: Tweak constants for better testing.
+
+ * gas/v850/basic.exp (do_jump): Test instruction bit patterns,
+ but not displacements (yet).
+
+ * gas/v850/basic.exp (do_compare): Test instruction bit patterns.
+
+ * gas/v850/basic.exp (do_branch): Test instruction bit patterns,
+ but not displacements (yet).
+
+ * gas/v850/basic.exp (do_bit): Test instruction bit patterns.
+
+ * gas/v850/basic.exp (do_arith): Test instruction bit patterns.
+ * gas/v850/arith.s: Tweak constants for better testing.
+
+ * gas/v850/basic.exp (do_misc): No longer expect failures
+ assembling "ldsr" and "stsr" opcodes.
+ * gas/v850/misc.s: Re-enable assembling of "ldsr" and "stsr"
+ opcodes.
+
+ * gas/v850/basic.exp (do_misc): No longer expect failures
+ assembling "trap" opcodes.
+ * gas/v850/misc.s: Re-enable assembling of "trap" opcodes.
+
+ * gas/v850: New directory with v850 tests.
+
+Fri Aug 16 00:19:10 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/hppa/basic/purge.s: Use "%sr4" on pitlb, pitlbe
+ fic and fice instructions to test 3bit space identifiers.
+ * gas/hppa/basic/system.s: Similarly for iitlba and
+ iitlbp.
+ * gas/hppa/basic/basic.exp: Corresponding changes.
+
+Thu Aug 15 16:25:05 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * gas/arm/arm.exp: Change inst.s test to check objdump.
+ * gas/arm/inst.d: Added.
+
+Thu Aug 15 16:06:02 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * gas/arm/thumb.s: Added.
+ * gas/arm/immed.s: Added.
+ * gas/arm/arch4t.s: Added.
+ * gas/arm/arm.exp: Updated to run the new tests.
+
+Tue Aug 6 11:06:29 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/h8300/misch.s: Reenable "eepmov.w" test.
+ * gas/h8300/miscs.s: Likewise.
+ * gas/h8300/h8300.exp: Check for correct assembly of "eepmov.w"
+ on the H8/300H and H8/S. Don't expect it to fail.
+
+Wed Jul 31 10:57:44 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * gas/sparc/asi.s: Update ASI_AS_IF_USER_{PRIMARY,SECONDARY}_LITTLE.
+
+Wed Jul 31 15:55:12 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * gas/arm/arm7t.s: Added.
+ * gas/arm/arm7t.d: Added.
+ * gas/arm/arm.exp: Updated to run the new test.
+
+Mon Jul 8 14:27:39 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/m68k/pcrel.d: Rename from schwab.d.
+ * gas/m68k/pcrel.s: Rename from schwab.s.
+
+Mon Jul 8 14:23:26 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * gas/m68k/schwab.d: Correct for ELF format.
+ * gas/m68k/all.exp: Run "schwab" test for all targets.
+
+Thu Jul 4 14:23:36 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ Avoid DOS file naming problems:
+ * gas/h8300/branch.s: Rename from branches.s.
+ * gas/h8300/branchh.s: Rename from branchesh.s.
+ * gas/h8300/branchs.s: Rename from branchess.s.
+ * gas/h8300/rotsh.s: Rename from rotshift.s.
+ * gas/h8300/rotshh.s: Rename from rotshifth.s.
+ * gas/h8300/rotshs.s: Rename from rotshifts.s.
+ * gas/h8300/h8300.exp: Corresponding changes.
+
+Thu Jul 4 14:01:46 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * gas/mips/mips.exp: Add new tests for processors with interlocks
+ on div and mul.
+ * gas/mips/div-ilocks.d: Added.
+ * gas/mips/mul-ilocks.d: Added.
+
+Wed Jul 3 14:20:04 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/all/gas.exp: Remove setup_xfail for h8300*-*-* for two tests
+ which now pass.
+ * gas/h8300/h8300.exp: Fix regexp of mov32bug test to work on a 64
+ bit host.
+
+Sat Jun 29 18:21:51 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/all/gas.exp: Add setup_xfail for vax*-*-vms* for 930509a
+ test.
+ * gas/vax/quad.exp: Expect a nop after the movq.
+
+Tue Jun 18 12:39:49 1996 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * gas/h8300/cbranchh.s: Switch into h8300h mode.
+ * gas/h8300/h8300.exp (H8/300H misc tests): Fix test names.
+
+ * gas/h8300/{addsubs.s,bitops1s.s,bitops2s.s}: New tests for the
+ H8/S.
+ * gas/h8300/{bitops3.s,bitops4.s,cbranchs.s,logicals.s}: Likewise.
+ * gas/h8300/{branchess.s,compares.s,macs.s,decimals.s}: Likewise.
+ * gas/h8300/{incdecs.s,divmuls.s,miscs.s,multiples.s}: Likewise.
+ * gas/h8300/{movbs.s,movws.s,movls.s,pushpops.s}: Likewise.
+ * gas/h8300/{rotshifts.s,extends.s}: Likewise.
+ * gas/h8300/h8300.exp: Run them.
+
+Mon Jun 10 14:14:40 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/all/cofftag.s, gas/all/cofftag.d: New test for COFF enum tag
+ with the same name as a global variable.
+ * gas/all/gas.exp: Run cofftag test for any COFF target.
+
+Thu Jun 6 12:30:05 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/m68k/all.exp: Pass -m68020 when assembling the disperr.s
+ test.
+
+Fri May 31 10:11:13 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/h8300/h8300.exp: Fix add.l test for H8/300H.
+
+Wed May 29 16:35:43 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mips/jal-xgot.d: Correct for 64 bit output.
+
+Thu Apr 25 19:31:59 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * gas/sparc/sparc.exp: Only run sparclet tests if sparclet.
+
+Wed Apr 24 17:06:18 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/m68k/op68000.d: Add statements now caught by gas.
+
+Mon Apr 22 16:45:12 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * gas/sparc/splet.[ds]: New tests for sparclet extensions.
+ * gas/sparc/sparc.exp: Run them.
+
+Mon Apr 15 17:25:18 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mips/la.d: Updated for April 5 MIPS assembler changes.
+ * gas/mips/lb.d, gas/mips/ld.d, gas/mips/sb.d: Likewise.
+ * gas/mips/uld.d, gas/mips/ulh.d, gas/mips/ulw.d: Likewise.
+ * gas/mips/usd.d, gas/mips/ush.d, gas/mips/usw.d: Likewise.
+
+Wed Apr 10 14:27:51 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/h8300/mov32bug.s: New test.
+ * gas/h8300/h8300.exp: Run it.
+
+Fri Apr 5 10:13:28 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/h8300/{addsubh.s,bitops1h.s,bitops2h.s}: New h8300h tests.
+ * gas/h8300/{bitops3h.s,bitops4h.s,branchesh.s}: New h8300h tests.
+ * gas/h8300/{cbranchh.s,compareh.s,decimalh.s}: New h8300h tests.
+ * gas/h8300/{divmulh.s,incdech.s,logicalh.s}: New h8300h tests.
+ * gas/h8300/{misch.s,movbh.s,movwh.s}: New h8300h tests.
+ * gas/h8300/{pushpoph.s,rotshifth.s}: New h8300h tests.
+ * gas/h8300/h8300.exp: Run them.
+
+ * gas/h8300/{movb.s,movw.s}: Correct predecrement syntax.
+
+ * gas/h8300/h8300.exp: Fix typos in bitops4 and movb tests.
+
+ * gas/h8300/{addsub.s,bitops1.s,bitops2.s}: New h8300 tests.
+ * gas/h8300/{bitops3.s,bitops4.s,branches.s}: New h8300 tests.
+ * gas/h8300/{cbranch.s,compare.s,decimal.s}: New h8300 tests.
+ * gas/h8300/{divmul.s,incdec.s,logical.s}: New h8300 tests.
+ * gas/h8300/{misc.s,movb.s,movw.s}: New h8300 tests.
+ * gas/h8300/{pushpop.s,rotshift.s}: New h8300 tests.
+ * gas/h8300/h8300.exp: Run them.
+
+Fri Mar 15 17:16:24 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/sparc/synth.d: Don't require sparc in the file format, since
+ it won't be there on SunOS.
+
+Thu Mar 7 14:51:23 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * gas/sparc/synth.[ds]: New testcase.
+ * gas/sparc/sparc.exp: Run it.
+
+Fri Mar 1 12:01:48 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/all/gas.exp: xfail difference of two undefined symbols
+ and difference of forward references for the h8300.
+
+Thu Feb 22 16:40:31 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mips/lb-xgot.d: Correct.
+
+Mon Feb 19 02:43:36 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * gas/sparc/{asi,membar,prefetch,rdpr,synth64,wrpr}.d: Pass -Av9
+ to gas.
+ * gas/sparc/addend.exp: Execute for any sparc cpu.
+ * gas/sparc/{mismatch.exp,mism-1.s}: New test.
+
+Wed Feb 14 13:49:59 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mips/jal-xgot.d, gas/mips/la-xgot.d: New tests.
+ * gas/mips/lb-xgot.d, gas/mips/ld-xgot.d: New tests.
+ * gas/mips/lif-xgot.d, gas/mips/ulh-xgot.d: New tests.
+ * gas/mips/mips.exp: Run new tests if svr4pic.
+
+Sat Jan 27 13:27:45 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * lib/gas-dg.exp (gas-dg-test): Delete default_flags and libs args.
+
+Fri Jan 26 14:24:01 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/hppa/unsorted/unsorted.exp: Update for objdump changes.
+
+Wed Jan 10 12:40:31 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mips/*.d: Update for changes to disassembler.
+
+Wed Jan 3 22:59:53 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mips/ulh-svr4pic.d: Update for tc-mips.c load_address
+ change.
+
+Fri Nov 17 10:32:25 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mri/immconst.d: New test.
+ * gas/mri/mri.exp: Run it.
+ * gas/mri/constants.s: Test immediate constants.
+ * gas/mri/constants.d: Corresponding change.
+
+ * gas/m68k/link.s: Add nop to pad to eight byte boundary.
+ * gas/m68k/link.d: Corresponding change.
+
+Sun Nov 12 21:28:11 1995 Jeffrey A Law (law@cygnus.com)
+
+ * gas/hppa/unsorted/brlenbug.s: New test.
+ * gas/hppa/unsorted/unsorted.exp: Run it.
+
+Sun Nov 5 12:49:27 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mips/beq.s: Declare text_label global.
+ * gas/mips/jal.s: Likewise.
+
+Fri Nov 3 12:35:07 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/m68k/link.s: Use "&" instead of "#" for immediate values.
+
+ * gas/m68k/fmoveml.s, gas/m68k/fmoveml.d: New test.
+ * gas/m68k/all.exp: Run it.
+
+Thu Nov 2 23:11:05 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/m68k/link.s, gas/m68k/link.d: New test.
+ * gas/m68k/all.exp: Run it.
+
+Tue Oct 24 10:57:20 1995 Jeffrey A Law (law@cygnus.com)
+
+ * gas/hppa/basic/basic.exp: Test lci and syncdma instructions.
+ * gas/hppa/basic/system.s: Corresponding changes.
+
+Fri Oct 6 17:13:35 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * gas/m68k/operands.d: Don't require a fixed number of leading
+ zeros in any number.
+
+ * gas/m68k/operands.s, gas/m68k/bitfield.s: Use "&" instead of "#"
+ for immediate values.
+
+Fri Oct 6 10:54:13 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * gas/arm/arm.exp: Renamed from gas.exp.
+ * gas/arm/le-fpconst.[sd]: New testcase.
+
+Fri Sep 29 15:12:10 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mri/mri.exp: Only run tests for m68k target.
+
+Mon Sep 25 12:31:46 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mri/mri.exp: Add setup_xfail for arm*-*-* for constants
+ test.
+
+Thu Sep 21 01:26:08 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/sh/fp.s (fmac): Update for new assembly syntax.
+
+Mon Sep 18 14:04:34 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * lib/gas-defs.exp (gas_run): Call prune_system_crud.
+ (run_dump_test, objdump): Likewise.
+
+Thu Sep 14 13:10:10 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * gas/sparc/{wrdr.[ds],rdpr.[ds]}: New tests.
+ * gas/sparc/sparc.exp: Run them.
+
+Wed Sep 13 16:35:51 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in, configure.in: Remove; the testsuite is now run
+ directly from the gas Makefile.
+
+Mon Sep 11 11:44:23 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mri/empty.s: New file.
+ * gas/mri/mri.exp: Test assembling empty.s.
+ * gas/mri/comment.s: Add a couple more comment variants.
+
+ * gas/mri/mri.exp: Add xfail for the expr test for all hppa
+ targets.
+
+Wed Sep 6 21:39:23 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mri/comment.s, gas/mri/comment.d: New test.
+ * gas/mri/mri.exp: Run it.
+ * gas/mri/expr.s: Remove whitespace in operand field.
+ * gas/mri/for.s: Add comments for further testing.
+ * gas/macros/test2.s: Put in an upper case ELSE to test case
+ insensitivity.
+
+Wed Aug 30 16:12:03 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * gas/sparc/{prefetch.[ds],synth64.[ds]}: New tests.
+
+Tue Aug 29 18:59:33 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * gas/sparc/sparc.exp: New file.
+ * gas/sparc/{asi.[ds],membar.[ds]}: New tests.
+
+Mon Aug 21 14:39:29 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/macros/*: New tests for macros.
+
+ * gas/mri/common.s: Use data, not .data.
+
+ * gasp/pl3.out: Update for changes in commented source output when
+ LOCAL is used.
+
+Sat Aug 19 17:36:17 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * gasp/gasp.exp (gasp_test): Call prune_system_crud on the output
+ of diff.
+ * lib/gas-defs.exp: Define prune_system_crud if it is not already
+ defined.
+
+Fri Aug 18 11:09:38 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * gasp/mri/*.out: Use ;, not !, for the comment character.
+
+Wed Aug 16 12:24:12 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mri/mri.exp: Change hppa*-*-* expected failures to only
+ expect failure for targets which use SOM.
+
+ * lib/gas-defs.exp (run_dump_test): If the program to run does not
+ exist, mark the test as untested.
+
+ * gas/mri/mri.exp: Add setup_xfail for i960 b.out targets for
+ common test.
+
+ * lib/gas-defs.exp (run_dump_test): Name the output file dump.o,
+ rather than using an implicit a.out.
+
+ * gas/mri/for.s: Add nop to round out to four byte boundary.
+ * gas/mri/repeat.s: Likewise.
+ * gas/mri/while.s: Likewise.
+ * gas/mri/for.d: Expected added nop.
+ * gas/mri/repeat.d: Likewise.
+ * gas/mri/while.d: Likewise.
+
+ * gas/mips/*.d: Change all test names to say MIPS.
+
+Tue Aug 15 15:42:33 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mri/for.d, gas/mri/for.s: New test.
+ * gas/mri/if.d, gas/mri/if.s: New test.
+ * gas/mri/repeat.d, gas/mri/repeat.s: New test.
+ * gas/mri/while.d, gas/mri/while.s: New test.
+ * gas/mri/mri.exp: Run the new tests.
+
+Mon Aug 14 16:03:07 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mri/expr.d: Permit leading zeroes, in case we're using a
+ 64-bit BFD.
+
+ * gasp/mri/*: New tests.
+ * gasp/gasp.exp: Run them. Also, clean up the test names used in
+ pass and fail.
+
+Sun Aug 13 00:39:24 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/sh/basic.exp: Update now that we know the right
+ bit patters for the new sts instructions.
+
+Thu Aug 10 00:46:21 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mri/char.d: Fix for little endian machines.
+ * gas/mri/float.d: Likewise.
+
+Wed Aug 9 15:34:36 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/all/struct.s, gas/all/struct.d: New test.
+ * gas/all/gas.exp: Run it.
+
+Tue Aug 8 17:11:39 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mri/common.s, gas/mri/common.d: New test.
+ * gas/mri/mri.exp: Run it.
+
+Mon Aug 7 22:39:28 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mri/mri.exp: Add setup_xfail for a29k*-*-* for constants
+ test.
+
+ * gasp/crash1.out, gasp/macro.out, gasp/sfunc.out: Complete
+ truncated files, so that the tests pass.
+
+ * gas/mri/mri.exp: Add setup_xfail for hppa*-*-* for equ,
+ constants, and expr.
+
+ * gas/m68k/all.exp: Run schwab test on hpux*, not just hpux. Run
+ on vxworks*, not just vxworks5.1.
+
+ * lib/gas-defs.exp (fail_phase, pass_phase): Remove.
+ (run_dump_test): Just call pass or fail.
+
+ * gas/m68k/operands.s, gas/m68k/operands.d: New test.
+ * gas/m68k/op68000.d: New test.
+ * gas/m68k/cas.s, gas/m68k/cas.d: New test.
+ * gas/m68k/bitfield.s, gas/m68k/bitfield.d: New test.
+ * gas/m68k/schwab.d: Run objdump with -j .text. Adjust for
+ changes to disassembler.
+ * gas/m68k/all.exp: Run new tests. Run schwab test for
+ m68k-*-coff*.
+
+Mon Aug 7 03:01:32 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/sh/*: New tests for the hitachi-sh.
+
+Tue Aug 1 18:02:47 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mri/*: New tests for MRI mode.
+
+ * lib/gas-defs.exp (run_dump_test): Support using objcopy. Dump
+ program executions to the log file before running them. Use the
+ simple program name, rather than the path to the binary being run,
+ in pass/fail messages.
+ (regexp_diff): If the regexp file has the special comment #pass,
+ stop checking at that point.
+ * config/default.exp: Set NM, NMFLAGS, OBJCOPY, and OBJCOPYFLAGS,
+ if they are not already set.
+
+Tue Aug 1 11:41:30 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * Makefile.in: Remove superfluous runtest gasp.
+
+Mon Jul 31 18:19:26 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * gasp/*: New.
+ * Makefile.in: Use gasp tests.
+ * config/default.exp: Add gasp stuff.
+
+Thu Jul 20 18:56:48 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/all/gas.exp: Disable tests that are not appropriate for
+ the PA.
+
+Thu Jul 13 18:22:49 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * gas/m68k/all.exp: Run schwab test for m68k vxworks5.1.
+
+Wed Jun 21 21:28:57 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * gas/m68k/schwab.*: New test based on a test case from Andreas
+ Schwab.
+ * gas/m68k/all.exp: Run it for some aout configurations.
+
+Mon Jun 12 22:27:18 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/parse/badfmpyadd.s: New test.
+ * gas/hppa/parse/parse.exp: Run it.
+
+Sun May 21 20:26:18 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/unsorted/unsorted.exp: Disable align4 tests for
+ ELF targets.
+
+Wed May 10 14:28:16 1995 Richard Earnshaw (rearnsha@armltd.co.uk)
+
+ * arm/arm7dm.s: New file -- tests for ARM7DM instructions.
+ * arm/arm6.s: Correct bogus tests.
+ * arm/gas.exp (arm6.s): Is now a valid test.
+ (arm7dm.s): New test.
+ * arm/float.s: Add load/store multiple floating point instruction
+ tests.
+
+Wed May 3 13:14:44 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/reloc/longcall.s: New test.
+ * gas/hppa/reloc/reloc.exp: Run it.
+
+Tue May 2 16:37:48 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * gas/mips/ld.d: Modified for gas delay-slot fixes.
+
+Sat Apr 29 23:35:18 1995 Doug Evans <dje@chestnut.cygnus.com>
+
+ * lib/gas-dg.exp: New file.
+
+Tue Apr 11 13:57:52 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * gas/mips/mips4.d: Allow more than exactly 8 zeros in bc1*
+ targets.
+
+Mon Apr 10 15:36:39 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * lib/gas-defs.exp (pass_phase): New proc.
+ (run_dump_test): Note passing or failing of each phase of this
+ test, instead of failure of phases or passing of complete test.
+ Ensure test file name is in reported message.
+
+Sat Apr 8 12:46:33 1995 Doug Evans <dje@chestnut.cygnus.com>
+
+ * lib/gas-defs.exp (run_dump_test): Handle arguments with paths.
+ Always resolve testcase status before returning.
+ If `slurp_options' fails, return and don't do test.
+ (slurp_options): Fix "can't open" error message.
+ Return -1 to indicate error.
+
+Mon Mar 20 22:45:30 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/unsorted/common.s: New test.
+ * gas/hppa/unsorted/unsorted.exp: Run it.
+
+Fri Mar 10 19:07:09 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * gas/h8300/ffxx1.s: Add .word 0 at the end to eliminate
+ uncertainty as to whether there should be trailing bytes in the
+ output file.
+ * gas/h8300/ffxx1.d: Adjust reloc values to permit an addend value
+ of 0x00000000ffffffff on 64-bit hosts. (I'm not sure if this is
+ correct.) End with "..." to match trailing zero bytes.
+
+Wed Mar 8 15:50:34 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mips/mips4.d, gas/mips/mips4.s: New files.
+ * gas/mips/mips.exp: Run new test.
+
+Thu Feb 23 17:58:50 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/basic/fmemLRbug.s: Add indexing variants.
+ * gas/hppa/basic/basic.exp: Test them.
+
+Wed Feb 15 15:43:26 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/mips/uld.d: New file.
+ * gas/mips/uld.s: New file.
+ * gas/mips/usd.d: New file.
+ * gas/mips/usd.s: New file.
+ * gas/mips/mips.exp: Run new tests.
+
+Thu Feb 9 10:57:39 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/reloc/applybug.s: New test.
+ * gas/hppa/reloc/reloc.exp (do_applybug_test): Run it.
+
+Thu Feb 2 00:34:55 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/reloc/picreloc.s: New test.
+ * gas/hppa/reloc/reloc.exp (do_pic_relocation_test): Run it.
+
+Fri Jan 27 14:02:02 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * gas/h8300/ffxx1.d, gas/h8300/ffxx1.s, gas/h8300/cmpsi2.s,
+ gas/h8300/h8300.exp: New tests.
+
+Mon Jan 23 21:44:26 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/basic/basic.exp (do_system): Update.
+
+Wed Jan 11 17:20:25 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * gas/mips/mips.exp: Don't run the memory-access tests if the
+ format is a.out, because the generated code is different from what
+ is used with other formats.
+
+Tue Jan 10 11:42:13 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/unsorted/unsorted.exp (align4.s): Fix glitch in
+ regexp to avoid losing without a controlling tty.
+
+Fri Dec 30 18:08:20 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * gas/i386/pushw.l: Fixed whitespace to match current listing
+ style.
+
+ * gas/all/gas.exp: Mark test p1480.s expected to pass, even with
+ listings enabled.
+
+Thu Dec 15 18:14:27 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * Makefile.in (AS_FOR_TARGET, OBJDUMP_FOR_TARGET): Don't set.
+ (uninstall): Don't set OBJDUMP and OBJDUMPFLAGS in site.exp.
+ * config/default.exp: Default OBJDUMP and OBJDUMPFLAGS. Use
+ findfile and transform procedures to determine objdump program
+ name.
+
+ * gas/mips/abs.s, gas/mips/div.s: Force some padding at the end,
+ in case the format doesn't automatically require it.
+ * gas/mips/beq.d, gas/mips/jal.d: Handle MIPS_JMP as an alternate
+ name for the reloc type.
+
+ * lib/gas-defs.exp (file_contents, verbose_eval): New procs.
+ (run_dump_test): If verbosity level is over 3, print out dump
+ command and its output.
+
+Tue Dec 13 18:21:09 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * gas/mips/jal-svr4pic.d: Fix 0-strings to work with 64-bit hosted
+ disassembly.
+
+Fri Dec 9 19:54:04 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * gas/all/gas.exp (comment.s test): Make the "\r" optional, since
+ it depends on tty modes.
+
+ * lib/gas-defs.exp (gas_start): Try using -nottycopy instead of
+ -nottyinit.
+
+ * gas/arm/gas.exp: The arm6 test should report errors, for now.
+
+Thu Dec 8 20:19:09 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * lib/gas-defs.exp: Use -i in expect_after command.
+
+Wed Dec 7 16:49:14 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * gas/mips/mul.d,jal.d: Fix 0-strings to work with 64-bit hosted
+ disassembly.
+
+ * gas/ieee-fp: Renamed from ieee.fp.
+
+ * lib/gas-defs.exp: Make sure timeout is at least 2 minutes.
+
+Wed Nov 30 10:48:00 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/parse: Renamed from gas/hppa/more.parse.
+
+Mon Nov 28 00:40:26 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/more.parse/parse.exp (nosubspace.s): No longer expected
+ to fail. Fix comments for the test. Tweak test name.
+
+Tue Nov 22 23:38:20 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/reloc/reloc.exp: Minor tweaks to match current PA ELF
+ output.
+
+Fri Nov 18 17:56:57 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * gas/mips/ld.d: Adjust to work for both big and little endian
+ code.
+ * gas/mips/ld.s, gas/mips/lif-empic.d: Likewise.
+ * gas/mips/lifloat.d, gas/mips/ulh-empic.d: Likewise.
+ * gas/mips/ulh.d, gas/mips/ulw.d, gas/mips/ush.d: Likewise.
+ * gas/mips/usw.d: Likewise.
+
+Tue Nov 15 11:09:57 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/unsorted/align4.s: New test.
+ * gas/hppa/unsorted/unsorted.exp: Run it.
+
+ * gas/hppa/unsorted/unsorted.exp (importbug): Tweak to match
+ current expected PA ELF output.
+ * gas/hppa/reloc/reloc.exp (do_r_no_reloc): Likewise.
+ (do_plabel_relocation_test): Likewise.
+
+Thu Nov 3 18:14:09 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * gas/all/p1480.s: Use larger constant, so expression can have a
+ positive value.
+ * gas/all/gas.exp: Expect p1480.s without listings to pass.
+
+Thu Nov 3 15:43:46 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * gas/mips/ulh.d, gas/mips/ulw.d, gas/mips/ush.d, gas/mips/usw.d:
+ Correct test cases.
+
+Thu Oct 20 00:55:13 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/reloc/blebug3.s: New test.
+ * gas/hppa/reloc/reloc.exp: Run it.
+
+Mon Oct 17 02:33:53 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/reloc/reduce3.s: New test.
+ * gas/hppa/reloc/reloc.exp: Run it.
+
+Sun Oct 16 22:25:56 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/reloc/reloc.exp (r_no_reloc): Tweak output to match
+ current reality.
+
+Wed Sep 28 21:21:34 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/reloc/reduce.s: Renamed from relocreduce.s
+ * gas/hppa/reloc/reduce2.s: Renamed from relocreduce2.s
+ * gas/hppa/reloc/r_no_reloc.s: Renamed from r_no_relocbug.s
+ * gas/hppa/reloc/reloc.exp: Changed accordingly.
+
+Wed Sep 28 13:25:10 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * gas/mips/beq.d, gas/mips/beq.s: Test that unconditional branch
+ overflows are correctly converted to jumps.
+
+Mon Sep 26 17:41:43 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * gas/mips: Add test cases for PIC code, both SVR4 style and
+ -membedded-pic style.
+
+Fri Sep 23 14:45:42 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * gas/mips: New directory with MIPS specific test cases.
+
+ * lib/gas-defs.exp (run_dump_test): Permit the .d file to specify
+ the name of the source file to assemble.
+ (regexp_diff): Put the reason for failure in the log file.
+
+Wed Sep 21 13:44:21 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * lib/gas-defs.exp: Don't try to use shell redirection, since TCL
+ doesn't support it. Redirect stdout using > instead of 1>, and
+ don't bother to redirect stderr since TCL redirects it anyhow.
+ (run_dump_test): Pass appropriate arguments to program, defaulting
+ to -r.
+
+Sat Sep 17 01:04:56 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * gas/vax: New directory.
+ * gas/vax/{quad.s,quad.exp}: New test, for immediate quadword
+ values.
+
+Mon Sep 12 22:19:11 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/reloc/r_no_relocbug.s: New test.
+ * gas/hppa/reloc/reloc.exp: Run it.
+
+ * gas/hppa/reloc/reloc.exp (do_function_reloc_bug): Update
+ expected output.
+
+Sun Sep 04 17:58:10 1994 Richard Earnshaw (rwe@pegasus.esprit.ec.org)
+
+ * gas/arm/*: New subtree. Add ARM tests.
+
+Mon Aug 8 12:13:31 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/unsorted/unsorted.exp: Accept any character
+ between foo's type and foo itself.
+
+Fri Jul 15 19:09:25 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * lib/gas-defs.exp (run_dump_test): New routine for running the
+ assembler, running objdump or nm (not fully supported) on the
+ resulting object file, and comparing the results against a file of
+ regular expressions in the test suite, all in one command.
+ Options for the assembler and objdump are read from comments at
+ the start of the .d file.
+ (fail_phase, slurp_options): New auxiliary routines.
+ (regexp_diff): Always return a value. Fix bugs in actually doing
+ the regexp test.
+
+ * gas/sun4/addend.exp: Use run_dump_test.
+ * gas/sun4/addend.d: Fix regular expressions so that they work.
+
+Thu Jul 7 11:55:33 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/reloc/relocreduce2.s: More relocation reduction tests.
+ * gas/hppa/reloc/reloc.exp: Run them.
+
+Thu Jun 30 18:49:25 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config/default.exp: Look for "as.new" in "$base_dir/..", where
+ it got compiled, not in "$base_dir".
+ * config/unknown.exp: Deleted.
+
+Sun Jun 26 13:23:54 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/lib/gas-defs.exp (gas_finish): Call "close" and "wait"
+ before exiting. Enclose both calls inside a "catch".
+ (objdump_finish): Likewise.
+
+Fri Jun 10 10:23:35 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/reloc/reloc.exp (roundmode test): Tweak expected output
+ for SOM to match current testcase.
+
+Thu Jun 2 19:46:58 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * gas/i386/{pushw.s,pushw.l}: New test.
+ * gas/i386/all.exp: Run it.
+
+ * Makefile.in (distclean): Remove site config files and gas.sum.
+
+Fri May 27 12:24:18 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * gas/m68k/disperr.s: Use % for registers.
+
+ * gas/m68k-coff/gas.exp: Expect failure for p2389a.s.
+
+Tue May 17 14:53:08 1994 Bill Cox (bill@rtl.cygnus.com)
+
+ * lib/gas-defs.exp: Replace error proc calls with perror calls.
+
+Mon May 16 13:19:16 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/reloc/reloc.exp: Tweak expected output to match new
+ ELF code.
+ * gas/hppa/reloc/roundmode.s: Avoid "S" and "D" modes, ELF does
+ not support them.
+ * gas/hppa/unsorted/unsorted.exp: Tweak expected output to match
+ new ELF code.
+
+Thu May 5 17:27:54 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * config/default.exp: Renamed from unix-gas.exp.
+
+Mon Apr 11 10:31:00 1994 Bill Cox (bill@rtl.cygnus.com)
+
+ * Makefile.in (check): Set TCL_LIBRARY for runtest.
+
+Mon Apr 11 07:54:10 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/more.parse/callinfobug.s: Add missing name for
+ procedure.
+
+ * gas/hppa/reloc/funcrelocbug.s: Place the trampoline in the
+ $DATA$ rather than $LIT$ subspace.
+
+Sun Mar 27 14:05:33 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/reloc/funcrelocbug.s: New test.
+ * gas/hppa/reloc/reloc.exp: Run it.
+
+Thu Mar 17 13:38:04 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/unsorted/importbug.s: New test.
+ * gas/hppa/unsorted/unsorted.exp: Run it.
+
+Wed Mar 16 11:57:07 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/more.parse/regpopbug.s: Add trivial .equ test.
+
+ * gas/hppa/unsorted/globalbug.s: New test (expected to fail).
+ * gas/hppa/unsorted/unsorted.exp: Run it.
+
+ * gas/hppa/more.parse/callinfobug.s: New test.
+ * gas/hppa/omre.parse/parse.exp: Run it.
+
+ * gas/hppa/more.parse/regpopbug.s: New test.
+ * gas/hppa/more.parse/parse.exp: Run it.
+
+Mon Feb 28 14:10:04 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * lib/gas-defs.exp (objdump): New proc.
+ (objdump_start): Deleted unused proc.
+ (objdump_start_common): Merged into objdump_start_no_subdir.
+
+ * gas/alpha/fp.exp: Use objdump instead of
+ objdump_start_no_subdir, since the former actually waits for
+ objdump to finish. Specify .rdata section only. Make comment
+ indicate Alpha architecture rather than SPARC.
+ * gas/alpha/fp.d: Omit .reginfo patterns. Just use "." to match
+ against ASCII code 0x2a ("*", special in regexp).
+ * gas/sun4/addend.exp: Use objdump instead of
+ objdump_start_no_subdir.
+
+Thu Feb 24 07:11:57 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/more.parse/parse.exp (no subspace test): Only expect
+ a failure if gas is not producing an ELF object.
+
+Mon Feb 14 09:24:03 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/basic/fmemLRbug.s: New test.
+ * gas/hppa/basic/basic.exp: Run it.
+
+Thu Feb 10 00:34:26 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * gas/alpha/fp.*: New files.
+ * lib/gas-defs.exp (regexp_diff): Report noted mismatch at
+ verbosity level 3 or above only.
+
+Mon Feb 7 15:53:10 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/*/*.exp: Change xfails to check for PA ELF rather than
+ PA OSF1.
+
+Fri Feb 4 23:42:14 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/more.parse/xmpyubug.s: New test.
+ * gas/hppa/more.parse/parse.exp: Run it.
+
+Fri Feb 4 17:13:20 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * lib/gas-defs.exp (regexp_diff): New procedure, vaguely based on
+ "simple_diff" from linker test suite.
+ * gas/sun4/addend.exp: Use it.
+ * gas/sun4/addend.d: New file.
+
+Sun Jan 30 23:34:58 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * gas/all/gas.exp: Adjust regexp for x930509.s for current listing
+ format.
+
+Thu Jan 20 16:44:51 1994 Rob Savoye (rob@darkstar.cygnus.com)
+
+ * gas/all/gas.exp, lib/gas-defs.exp, sun4/addend.exp,
+ sparc-solaris/addend.exp: Tweaked to fix a few bugs and to run
+ well under either version of expect.
+
+Mon Jan 17 00:25:03 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/basic/fp_misc.s: Delete copr instruction. It's tested
+ elsewhere now.
+ * gas/hppa/basic/{copr, coprmem, spop}.s: New tests.
+ * gas/hppa/basic/basic.exp: Run them.
+
+Thu Jan 13 11:59:22 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/all/gas.exp: No longer expect difference of forward
+ references to fail.
+ * gas/all/x930509.s: Fix testcase to match how the expect code was
+ written.
+
+Wed Jan 12 13:41:10 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/reloc/reloc.exp: Fix typo in last change. Latest test
+ for cross-subspace call bugs is no longer expected to fail.
+
+ * gas/hppa/more.parse/procbug.s: Add test for another bug relating
+ to having a function's label follow the .PROC directive.
+
+Tue Jan 11 21:47:48 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/reloc/reloc.exp: Add test for cross-subspace call bug
+ found while working on multiple $CODE$ subspace support.
+
+Mon Jan 10 09:54:15 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/more.parse/parse.exp: procbug.s is no longer expected
+ to fail.
+ * gas/hppa/more.parse/procbug.s: Add missing .procend.
+
+Mon Jan 3 10:07:47 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/more.parse/labelbug.s: Add testcase for bug in last
+ app.c change.
+
+Wed Dec 29 11:32:39 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/more.parse/labelbug.s: Add more colonless label tests.
+
+Wed Dec 15 08:24:31 1993 Ken Raeburn (raeburn@rtl.cygnus.com)
+
+ * Makefile.in (site.exp): Don't set ASFLAGS. Quote value of
+ OBJDUMPFLAGS in case it's empty. Use temporary names until the
+ end; make creating site.exp the final step.
+ (check): Pass in ASFLAGS.
+
+ * gas/all/gas.exp: Use all_ones proc. Change regexp for matching
+ C comments to avoid bugs in latest expect code.
+
+Wed Dec 8 14:30:14 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/m68k/disperr.s: New test.
+ * gas/m68k/all.exp: Run it.
+
+Sun Dec 5 19:24:57 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/reloc/roundmode.s: New test.
+ * gas/hppa/reloc/reloc.exp: Run it. Fix typo in last change.
+
+Wed Dec 1 10:44:18 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/reloc/reloc.exp: Run the first half of bogus R_EXIT
+ test for ELF.
+
+Tue Nov 30 13:43:21 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/more.parse/parse.exp: Test for error on for subspace
+ directive is an XFAIL for SOM assmeblers.
+
+ * gas/hppa/reloc/reloc.exp: Remove XFAIL for relocation on
+ cross-subspace call test.
+
+Sun Nov 28 12:12:50 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/more.parse/appbug.s: New test.
+ * gas/hppa/more.parse/parse.exp: Run it.
+
+ * gas/hppa/unsorted/align3.s: New test.
+ * gas/hppa/unsorted/unsorted.exp: Run it.
+
+Sat Nov 27 22:50:01 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/all/p2425.s: Insert a tab before assembler directives so
+ that the directives are not interpreted as labels.
+
+ * gas/hppa/basic/weird.s: Sync with GDB version.
+
+ * gas/hppa/more.parse/labelbug.s: New test.
+
+ * gas/hppa/more.parse/parse.exp: Run it.
+
+Wed Nov 24 01:25:03 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/reloc/fixupbug.s: New test.
+ * gas/hppa/reloc/reloc.exp: Run it.
+
+ * gas/hppa/reloc/exitbug.s: New test.
+ * gas/hppa/reloc/reloc.exp: Run it.
+
+Sun Nov 21 22:11:10 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/reloc/reloc.exp: Minor fixes so that SOM & ELF can
+ share the same test code.
+ * gas/hppa/reloc/relocreduce.s: Likewise.
+
+ * gas/hppa/basic/fmem.s: Add quadword FP store instructions.
+ * gas/hppa/basic/basic.exp: Test quadword FP store instructions.
+
+Sun Nov 7 00:31:41 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/reloc/reloc.exp: No longer expect failure for
+ field selector on ble instruction test.
+
+ * gas/hppa/basic/basic.exp: No longer expect failures for
+ system instruction tests now that probei is fixed.
+
+Sat Nov 6 22:45:08 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/reloc/selectorbug.s: New test.
+ * gas/hppa/reloc/reloc.exp: Run it.
+
+Thu Nov 4 17:01:30 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/unsorted/fragbug.s: New test.
+ * gas/hppa/unsorted/unsorted.exp: Run it.
+
+Thu Nov 04 09:09:49 1993 Jeffrey Wheat (cassidy@cygnus.com)
+
+ * Makefile.in: Changed RUNTESTFLAGS to RUNTEST_FLAGS
+
+Tue Nov 2 22:12:30 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/more.parse/{defbug.s, stdreg.s}: New tests.
+ * gas/hppa/more.parse/parse.exp: Run them.
+
+Mon Nov 1 23:37:58 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/reloc/reloc.exp (reloc_reduce): Correct offsets at
+ which specific relocations are expected to be found.
+
+Sat Oct 30 14:12:31 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/unsorted/unsorted.exp (ss_align): Remove OSF xfail.
+
+ * gas/hppa/more.parse/parse.exp: Add new test.
+ * gas/hppa/more.parse/ssbug.s: New test to make sure non-default
+ sections are handled correctly.
+
+ * gas/all/gas.exp: Disable (and fail) p1480.s for all PA targets.
+
+Fri Oct 29 16:29:06 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/more.parse/calldatabug.s: Colonize.
+ * gas/hppa/more.parse/parse.exp: Fix typos.
+
+Thu Oct 28 21:40:06 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * gas/hppa/{basic, more.parse, reloc, unsorted}: New directories.
+ * gas/hppa/*/*.exp: New test drivers.
+ * gas/hppa/*/*.s: New test files.
+
+Mon Oct 25 09:40:59 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ * gas/sun4: New directory.
+ * gas/sun4/addend.s,addend.exp: New test case.
+ * gas/sparc-solaris/addend.s,addend.exp: Solaris version of same
+ test case.
+
+ * gas/all/gas.exp: Check `*' in C comments.
+
+ * lib/gas-defs.exp (all_ones): New procedure, for a predicate to
+ simplify some tests.
+ (want_no_output): Return zero or nonzero, depending on success or
+ failure.
+ (gas_test_old): Return value from want_no_output.
+ (objdump_start_common): Split off from objdump_start.
+ (objdump_start_no_subdir): New procedure.
+
+Wed Oct 20 07:25:48 1993 Ken Raeburn (raeburn@rover.cygnus.com)
+
+ * gas/all/diff1.s, gas/m68k/pic1.s: New tests.
+ * gas/all/gas.exp, gas/m68k/all.exp: Run them.
+
+ * Makefile.in (OBJDUMP_FOR_TARGET): Define similar to
+ AS_FOR_TARGET.
+ (check): Don't pass ASFLAGS variable.
+ (site.exp): Put ASFLAGS, OBJDUMP, OBJDUMPFLAGS into site.exp.
+
+ From Jeff Law:
+
+ * lib/gas-defs.exp (objdump_start, objdump_finish): New functions
+ so that tests can parse the output of objdump looking for errors
+ in relocation entires, file headers and the like.
+
+Thu Sep 23 16:20:34 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * gas/ieee.fp/x930509a.exp: Currently expected to fail always.
+ * gas/all/gas.exp (p1480.s, x930509.s): Ditto. Break up gas_test
+ call so it no longer performs multiple tests.
+ * gas/m68k/all.exp (t2.s): Don't bother with listings.
+ (p2410.s): Don't pass unwanted arguments to gas_test_error.
+
+Wed Aug 25 16:50:08 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * lib/do*: Remove RCS id strings.
+
+Mon May 17 15:09:45 1993 Ken Raeburn (raeburn@deneb.cygnus.com)
+
+ * gas/all/float.s, gas/all/p1480.s, gas/m68k/p2410.s: New tests.
+ * gas/all/gas.exp, gas/m68k/all.exp: Run them.
+ * gas/i386: New directory.
+
+Mon May 10 14:50:20 1993 Ken Raeburn (raeburn@deneb.cygnus.com)
+
+ * Added directory structure, to categorize tests by targets.
+ * Added new tests all/x930509.s, ieee.fp/x930509a.s, m68k/p2663.s,
+ and refined some to examine the assembler listing output.
+ * lib/gas-defs.exp: Renamed gas_start to gas_run. Added some
+ expect_after patterns.
+ (gas_start, gas_finish): New procs, for tests that examine process
+ output.
+ * config/unix-gas.exp: Invoke gas_init directly, instead of
+ requiring test .exp files do it.
+
+Wed Apr 21 01:24:16 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * gas/gas.exp: Handle new tests, and changes to testing procs.
+
+ * lib/gas-defs.exp (want_no_output): New proc; success iff output
+ is empty.
+ (gas_test_old): Functionally same as old gas_test.
+ (gas_test_ignore_stdout): Rewritten to use want_no_output.
+ (gas_test): New argument lists set of options to be tried in
+ combinations. Option with trailing ">" indicates standard output
+ should be ignored.
+
+ * gas/p2425a.s: Use %-form for registers, so this test can be run
+ on m68k-coff targets too.
+
+ * gas/p2430a.s: New test case, whitespace &c matches customer
+ report more closely. Gets different results from p2430.s; this is
+ bad, and not yet tested for.
+
+Mon Apr 5 12:27:19 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ * gas/p2389a.s, gas/p2411.s, gas/t2.s: New test cases.
+ * lib/run: New script.
+ * gas/gas-defs.exp (gas_start): Takes new args, assembler options
+ and redirection options. Use "run" script so redirection works.
+ (gas_test): Now takes assembler options as separate arg from input
+ file name.
+ (gas_test_ignore_stdout): New proc. Discards output.
+ (gas_test_error): New proc. Expects assembler to generate output.
+ (target_cpu_family setting): Handle i486->i386 also.
+
+ * lib/do*: Scripts moved here from gas/testscripts. May be useful
+ someday for writing more test cases; not currently used.
+
+Tue Mar 30 11:45:27 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * gas/sol-gcc.s, gas/sol-cc.s, gas/p2425a.s, gas/p2389.s: New test
+ cases.
+ * gas/gas.exp: Enable them for appropriate targets. Removed some
+ useless comments &c. Changed m68k target test to be more general.
+
+ * lib/gas-defs.exp (gas_exit, gas_init): New procs.
+ * gas/gas.exp: Call gas_init.
+
+Mon Mar 29 00:00:00 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * Test suite created.
+
diff --git a/gas/testsuite/config/default.exp b/gas/testsuite/config/default.exp
new file mode 100644
index 0000000000..4134a03030
--- /dev/null
+++ b/gas/testsuite/config/default.exp
@@ -0,0 +1,46 @@
+load_lib gas-defs.exp
+
+global AS
+if ![info exists AS] then {
+ set AS [findfile $base_dir/../as-new "../as-new" [transform as]]
+}
+
+global GASP
+if ![info exists GASP] then {
+ set GASP [findfile $base_dir/../gasp-new "../gasp-new" [transform gasp]]
+}
+
+global ASFLAGS
+if ![info exists ASFLAGS] then {
+ set ASFLAGS ""
+}
+
+if ![info exists OBJDUMP] then {
+ set OBJDUMP [findfile $base_dir/../../binutils/objdump \
+ $base_dir/../../binutils/objdump \
+ [transform objdump]]
+}
+
+if ![info exists OBJDUMPFLAGS] then {
+ set OBJDUMPFLAGS {}
+}
+
+if ![info exists NM] then {
+ set NM [findfile $base_dir/../../binutils/nm-new \
+ $base_dir/../../binutils/nm-new \
+ [transform nm]]
+}
+
+if ![info exists NMFLAGS] then {
+ set NMFLAGS {}
+}
+
+if ![info exists OBJCOPY] then {
+ set OBJCOPY [findfile $base_dir/../../binutils/objcopy]
+}
+
+if ![info exists OBJCOPYFLAGS] then {
+ set OBJCOPYFLAGS {}
+}
+
+gas_init
diff --git a/gas/testsuite/gas/all/align.d b/gas/testsuite/gas/all/align.d
new file mode 100644
index 0000000000..86ede6186a
--- /dev/null
+++ b/gas/testsuite/gas/all/align.d
@@ -0,0 +1,12 @@
+#objdump: -s -j .text
+#name: align
+
+# Test the alignment pseudo-op.
+
+.*: .*
+
+Contents of section .text:
+ 0000 ff00ff01 ff020202 ffff0303 04040404 ................
+ 0010 ffffffff 05050505 ff090a0a 0a0a0a0a ................
+ 0020 ff00ff01 ff020202 ffff0303 04040404 ................
+ 0030 ffffffff 05050505 ff090a0a 0a0a0a0a ................
diff --git a/gas/testsuite/gas/all/align.s b/gas/testsuite/gas/all/align.s
new file mode 100644
index 0000000000..9ccca130cc
--- /dev/null
+++ b/gas/testsuite/gas/all/align.s
@@ -0,0 +1,61 @@
+/* Test the alignment pseudo-ops. */
+ .text
+
+ .byte 0xff
+ .p2align 1,0
+
+ .byte 0xff
+ .p2align 1,1
+
+ .byte 0xff
+ .p2align 2,2
+
+ .byte 0xff
+ .byte 0xff
+ .p2alignw 2,0x0303
+
+ .p2align 3,4
+ .byte 0xff
+ .byte 0xff
+ .byte 0xff
+ .byte 0xff
+ .p2alignl 3,0x05050505
+
+ .p2align 1,6
+ .p2align 1,7
+
+ .byte 0xff
+ .p2align 3,8,5
+ .byte 9
+ .p2align 3,0xa
+
+ .byte 0xff
+ .balign 2,0
+
+ .byte 0xff
+ .balign 2,1
+
+ .byte 0xff
+ .balign 4,2
+
+ .byte 0xff
+ .byte 0xff
+ .balignw 4,0x0303
+
+ .balign 8,4
+ .byte 0xff
+ .byte 0xff
+ .byte 0xff
+ .byte 0xff
+ .balignl 8,0x05050505
+
+ .balign 2,6
+ .balign 2,7
+
+ .byte 0xff
+ .balign 8,8,5
+ .byte 9
+ .balign 8,0xa
+
+ .p2align 5
+ .balign 32
diff --git a/gas/testsuite/gas/all/cofftag.d b/gas/testsuite/gas/all/cofftag.d
new file mode 100644
index 0000000000..59898b621e
--- /dev/null
+++ b/gas/testsuite/gas/all/cofftag.d
@@ -0,0 +1,25 @@
+#objdump: -t
+#name: cofftag
+
+.*: file format .*
+
+SYMBOL TABLE:
+\[ 0\]\(sec -2\)\(fl 0x00\)\(ty 0\)\(scl 103\) \(nx 1\) 0x0+0000 foo.c
+File
+\[ 2\]\(sec 1\)\(fl 0x00\)\(ty 0\)\(scl 6\) \(nx 0\) 0x0+0000 gcc2_compiled.
+\[ 3\]\(sec 1\)\(fl 0x00\)\(ty 0\)\(scl 6\) \(nx 0\) 0x0+0000 ___gnu_compiled_c
+\[ 4\]\(sec -2\)\(fl 0x00\)\(ty a\)\(scl 15\) \(nx 1\) 0x0+0000 _token
+AUX lnno 0 size 0x4 tagndx 0 endndx 10
+\[ 6\]\(sec -1\)\(fl 0x00\)\(ty b\)\(scl 16\) \(nx 0\) 0x0+0000 _operator
+\[ 7\]\(sec -1\)\(fl 0x00\)\(ty b\)\(scl 16\) \(nx 0\) 0x0+0001 _flags
+\[ 8\]\(sec -1\)\(fl 0x00\)\(ty 0\)\(scl 102\) \(nx 1\) 0x0+0004 .eos
+AUX lnno 0 size 0x4 tagndx 4
+\[ 10\]\(sec 1\)\(fl 0x00\)\(ty 0\)\(scl 3\) \(nx 1\) 0x[0-9a-f]+ .text
+AUX scnlen 0x[0-9a-f]+ nreloc 0 nlnno 0
+\[ 12\]\(sec 2\)\(fl 0x00\)\(ty 0\)\(scl 3\) \(nx 1\) 0x[0-9a-f]+ .data
+AUX scnlen 0x[0-9a-f]+ nreloc 0 nlnno 0
+\[ 14\]\(sec 3\)\(fl 0x00\)\(ty 0\)\(scl 3\) \(nx 1\) 0x[0-9a-f]+ .bss
+AUX scnlen 0x[0-9a-f]+ nreloc 0 nlnno 0
+\[ 16\]\(sec 2\)\(fl 0x00\)\(ty 2\)\(scl 2\) \(nx 0\) 0x0+0000 _token
+\[ 17\]\(sec 2\)\(fl 0x00\)\(ty a\)\(scl 2\) \(nx 1\) 0x[0-9a-f]+ _what
+AUX lnno 0 size 0x4 tagndx 4
diff --git a/gas/testsuite/gas/all/cofftag.s b/gas/testsuite/gas/all/cofftag.s
new file mode 100644
index 0000000000..8156599b12
--- /dev/null
+++ b/gas/testsuite/gas/all/cofftag.s
@@ -0,0 +1,57 @@
+/* This file was compiled from this C source:
+ char token =0;
+ enum token {
+ operator,
+ flags
+ };
+
+ enum token what= operator;
+ */
+
+ .file "foo.c"
+gcc2_compiled.:
+___gnu_compiled_c:
+.globl _token
+.data
+_token:
+ .byte 0
+.text
+ .def _token
+ .scl 15
+ .type 012
+ .size 4
+ .endef
+ .def _operator
+ .val 0
+ .scl 16
+ .type 013
+ .endef
+ .def _flags
+ .val 1
+ .scl 16
+ .type 013
+ .endef
+ .def .eos
+ .val 4
+ .scl 102
+ .tag _token
+ .size 4
+ .endef
+.globl _what
+.data
+ .p2align 2
+_what:
+ .long 0
+.text
+ .def _token
+ .val _token
+ .scl 2
+ .type 02
+ .endef
+ .def _what
+ .val _what
+ .scl 2
+ .tag _token
+ .size 4
+ .type 012
+ .endef
diff --git a/gas/testsuite/gas/all/comment.s b/gas/testsuite/gas/all/comment.s
new file mode 100644
index 0000000000..76bc641a75
--- /dev/null
+++ b/gas/testsuite/gas/all/comment.s
@@ -0,0 +1,3 @@
+# This test file is to see whether comments get written into listings
+# correctly. The file has no real contents.
+/* C comments too! */
diff --git a/gas/testsuite/gas/all/cond.d b/gas/testsuite/gas/all/cond.d
new file mode 100644
index 0000000000..4ee3942efb
--- /dev/null
+++ b/gas/testsuite/gas/all/cond.d
@@ -0,0 +1,20 @@
+# This should match the output of gas -alc cond.s.
+
+.*cond.s.*
+
+
+ 1[ ]+.if 0
+ 8[ ]+.else
+ 9[ ]+.if 1
+ 10[ ]+.endc
+ 11 0000 0[02]00 ?000[02][ ]+.long[ ]+2
+ 12[ ]+.if 0
+ 14[ ]+.else
+ 15 0004 0[04]00 ?000[04][ ]+.long[ ]+4
+ 16[ ]+.endc
+ 17[ ]+.endc
+ 18 0008 0000 ?0000[ ]+.p2align 5,0
+ 18[ ]+0000 ?0000
+ 18[ ]+0000 ?0000
+ 18[ ]+0000 ?0000
+ 18[ ]+0000 ?0000
diff --git a/gas/testsuite/gas/all/cond.s b/gas/testsuite/gas/all/cond.s
new file mode 100644
index 0000000000..39583211e6
--- /dev/null
+++ b/gas/testsuite/gas/all/cond.s
@@ -0,0 +1,18 @@
+ .if 0
+ .if 1
+ .endc
+ .long 0
+ .if 0
+ .long 1
+ .endc
+ .else
+ .if 1
+ .endc
+ .long 2
+ .if 0
+ .long 3
+ .else
+ .long 4
+ .endc
+ .endc
+ .p2align 5,0
diff --git a/gas/testsuite/gas/all/diff1.s b/gas/testsuite/gas/all/diff1.s
new file mode 100644
index 0000000000..10a89fdc4e
--- /dev/null
+++ b/gas/testsuite/gas/all/diff1.s
@@ -0,0 +1,5 @@
+# Difference of two undefined symbols.
+# The assembler should reject this.
+ .text
+ .globl _foo
+_foo: .long _a - _b
diff --git a/gas/testsuite/gas/all/float.s b/gas/testsuite/gas/all/float.s
new file mode 100644
index 0000000000..b098cad1cc
--- /dev/null
+++ b/gas/testsuite/gas/all/float.s
@@ -0,0 +1,4 @@
+ .text
+foo: .single 0r1.2345e+06
+ .single 0f3.14159
+ .double 0r2.718282
diff --git a/gas/testsuite/gas/all/gas.exp b/gas/testsuite/gas/all/gas.exp
new file mode 100644
index 0000000000..9544551d60
--- /dev/null
+++ b/gas/testsuite/gas/all/gas.exp
@@ -0,0 +1,145 @@
+#
+# These tests should be valid on all targets.
+#
+
+# I think currently all targets fail this one when listings are enabled.
+gas_test "p2425.s" "" "" "pcrel values in assignment"
+
+# p1480.s uses a ".space" directive which for most assemblers means
+# "allocate some space". On the PA it means "switch into this space".
+#
+# Therefore this test (as it is currently written) is completely bogus
+# for any PA target. Do not bother trying to run it and just claim
+# it fails.
+if [istarget hppa*-*-*] then {
+ setup_xfail *-*-*
+ fail "simplifiable double subtraction"
+} else {
+ gas_test "p1480.s" "" "-a>" "simplifiable double subtraction"
+}
+
+gas_test "float.s" "" "" "simple FP constants"
+
+# This test is meaningless for the PA; the difference of two undefined
+# symbols is something that is (and must be) supported on the PA.
+if ![istarget hppa*-*-*] then {
+ gas_test_error "diff1.s" "" "difference of two undefined symbols"
+}
+
+proc do_comment {} {
+ set testname "comment.s: comments in listings"
+ set x1 0
+ set x2 0
+ set x3 0
+ set white {[ \t]*}
+ gas_start "comment.s" "-al"
+ while 1 {
+# Apparently CRLF is received when using ptys for subprocesses; hence the
+# \r\n for line 3.
+ expect {
+ -re "^ +1\[ \t\]+# This\[^\n\]*\n" { set x1 1 }
+ -re "^ +2\[ \t\]+# correctly\[^\n\]*\n" { set x2 1 }
+ -re "^ +3\[ \t\]+/. C comments too. ./\r?\n" { set x3 1 }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+ gas_finish
+ if [all_ones $x1 $x2 $x3] then { pass $testname } else { fail $testname }
+}
+
+do_comment
+
+#
+# Test x930509a -- correct assembly of differences involving forward
+# references.
+#
+
+proc do_930509a {} {
+ set testname "difference between forward references"
+ set x 0
+ gas_start "x930509.s" "-al"
+ while 1 {
+# We need to accomodate both byte orders here.
+# If ".long" means an 8-byte value on some target someday, this test will have
+# to be fixed.
+ expect {
+ -re "^ +1 .... 0000 *0000" { fail $testname; set x 1 }
+ -re "^ +1 .... 0400 *0000" { pass $testname; set x 1 }
+ -re "^ +1 .... 0000 *0004" { pass $testname; set x 1 }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+ gas_finish
+ if !$x then { fail $testname }
+}
+
+# This test is meaningless for the PA; the difference of two symbols
+# must not be resolved by the assembler.
+if ![istarget hppa*-*-*] then {
+ # the vax fails because VMS can apparently actually handle this
+ # case in relocs, so gas doesn't handle it itself.
+ setup_xfail "vax*-*-vms*"
+ setup_xfail "mn10300*-*-*"
+ setup_xfail "mn10200*-*-*"
+ do_930509a
+}
+
+case $target_triplet in {
+ { hppa*-*-* } { }
+ default {
+ run_dump_test struct
+ run_dump_test align
+ }
+}
+
+# This test is for any COFF target.
+# We omit m88k COFF because it uses weird pseudo-op names.
+# We omit the ARM toolchains because they define locals to
+# start with '.', which eliminates .eos, .text etc from the output.
+if { ([istarget *-*-coff*] && ![istarget m88*-*-*] && ![istarget *arm*-*-coff] && ![istarget thumb*-*-coff]) \
+ ||([istarget *-*-pe*] && ![istarget arm*-*-pe*] && ![istarget thumb*-*-pe*]) \
+ || [istarget a29k-*-udi*] \
+ || [istarget a29k-*-ebmon*] \
+ || [istarget a29k-*-sym*] \
+ || [istarget a29k-*-vxworks*] \
+ || [istarget i*86-*-aix*] \
+ || [istarget i*86-*-sco*] \
+ || [istarget i*86-*-isc*] \
+ || [istarget i*86-*-go32*] \
+ || [istarget i*86-*-cygwin*] \
+ || [istarget i*86-*-*nt] \
+ || ([istarget i960-*-vxworks5.*] && ![istarget i960-*-vxworks5.0*]) } {
+ run_dump_test cofftag
+}
+
+# Test omitting conditionals from listings.
+proc test_cond {} {
+ global comp_output
+ global srcdir
+ global subdir
+
+ set testname "conditional listings"
+ gas_run cond.s -alc ">dump.out"
+ if ![string match "" $comp_output] {
+ send_log "$comp_output\n"
+ fail $testname
+ } else {
+ if { [regexp_diff dump.out $srcdir/$subdir/cond.d] } {
+ fail $testname
+ } else {
+ pass $testname
+ }
+ }
+}
+
+test_cond
+
+# FIXME: this is here cause of a bug in DejaGnu 1.1.1. When it is no longer
+# in use, then this can be removed.
+if [info exists errorInfo] then {
+ unset errorInfo
+}
diff --git a/gas/testsuite/gas/all/itbl b/gas/testsuite/gas/all/itbl
new file mode 100644
index 0000000000..ac66dfbfe4
--- /dev/null
+++ b/gas/testsuite/gas/all/itbl
@@ -0,0 +1,20 @@
+
+ ; Test case for assembler option "itbl".
+ ; Run as "as --itbl itbl itbl.s"
+ ; or with stand-alone test case "itbl-test itbl itbl.s".
+ ; The "p<n>" represent processors of a multi-processor system.
+
+ p1 dreg d1 1 ; data register "d1" for COP1 has value 1
+ p1 creg c3 3 ; ctrl register "c3" for COP1 has value 3
+ p3 insn fie 0x1e:24-20 ; function "fill" for COP3 has value 31
+ p3 dreg d3 3 ; data register "d3" for COP3 has value 3
+ p3 creg c2 22 ; control register "c2" for COP3 has value 22
+ p3 insn fee 0x1e:24-20,dreg:17-13,creg:12-8,immed:7-0
+
+ p3 dreg d3 3 ; data register "d3" for COP3 has value 3
+ p3 creg c2 22 ; control register "c2" for COP3 has value 22
+ p3 insn fum 0x01e00001 dreg:17-13 creg:12-8
+ p3 insn foh 0xf:24-21 dreg:20-16 immed:15-0
+
+ p3 insn pig 0x1:24-21*[0x100|0x2], dreg:20-16, immed:15-0*0x10000
+
diff --git a/gas/testsuite/gas/all/itbl-test.c b/gas/testsuite/gas/all/itbl-test.c
new file mode 100644
index 0000000000..023f5d95be
--- /dev/null
+++ b/gas/testsuite/gas/all/itbl-test.c
@@ -0,0 +1,129 @@
+
+
+/* itbl-test.c
+
+ Copyright (C) 1997 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* Stand-alone test for instruction specification table support.
+ Run using "itbl-test <itbl> <asm.s>"
+ where <itbl> is the name of the instruction table,
+ and <asm.s> is the name of the assembler fie. */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "itbl-ops.h"
+
+static int test_reg (e_processor processor, e_type type, char *name,
+ unsigned long val);
+
+int
+main (int argc, char **argv)
+{
+ unsigned int insn;
+ FILE *fas;
+ int aline = 0;
+ char s[81], *name;
+
+ if (argc < 3)
+ {
+ printf ("usage: %s itbl asm.s\n", argv[0]);
+ exit (0);
+ }
+ if (itbl_parse (argv[1]) != 0)
+ {
+ printf ("failed to parse itbl\n");
+ exit (0);
+ }
+
+ fas = fopen (argv[2], "r");
+ if (fas == 0)
+ {
+ printf ("failed to open asm file %s\n", argv[2]);
+ exit (0);
+ }
+ while (fgets (s, 80, fas))
+ {
+ char *p;
+ aline++;
+
+ if (p = strchr (s, ';'), p) /* strip comments */
+ *p = 0;
+ if (p = strchr (s, '#'), p) /* strip comments */
+ *p = 0;
+ p = s + strlen (s) - 1;
+ while (p >= s && (*p == ' ' || *p == '\t' || *p == '\n')) /* strip trailing spaces */
+ p--;
+ *(p + 1) = 0;
+ p = s;
+ while (*p && (*p == ' ' || *p == '\t' || *p == '\n')) /* strip leading spaces */
+ p++;
+ if (!*p)
+ continue;
+
+ name = itbl_get_field (&p);
+ insn = itbl_assemble (name, p);
+ if (insn == 0)
+ printf ("line %d: Invalid instruction (%s)\n", aline, s);
+ else
+ {
+ char buf[128];
+ printf ("line %d: insn(%s) = 0x%x)\n", aline, s, insn);
+ if (!itbl_disassemble (buf, insn))
+ printf ("line %d: Can't disassemble instruction "
+ "(0x%x)\n", aline, insn);
+ else
+ printf ("line %d: disasm(0x%x) = %s)\n", aline, insn, buf);
+ }
+ }
+
+ test_reg (1, e_dreg, "d1", 1);
+ test_reg (3, e_creg, "c2", 22);
+ test_reg (3, e_dreg, "d3", 3);
+
+ return 0;
+}
+
+static int
+test_reg (e_processor processor, e_type type, char *name,
+ unsigned long val)
+{
+ char *n;
+ unsigned long v;
+
+ n = itbl_get_name (processor, type, val);
+ if (!n || strcmp (n, name))
+ printf ("Error - reg name not found for proessor=%d, type=%d, val=%d\n",
+ processor, type, val);
+ else
+ printf ("name=%s found for processor=%d, type=%d, val=%d\n",
+ n, processor, type, val);
+
+ /* We require that names be unique amoung processors and types. */
+ v = itbl_get_reg_val (name);
+ if (!v || v != val)
+ printf ("Error - reg val not found for processor=%d, type=%d, name=%s\n",
+ processor, type, name);
+ else
+ printf ("val=0x%x found for processor=%d, type=%d, name=%s\n",
+ v, processor, type, name);
+ return 0;
+}
diff --git a/gas/testsuite/gas/all/itbl.s b/gas/testsuite/gas/all/itbl.s
new file mode 100644
index 0000000000..9351aa4bb3
--- /dev/null
+++ b/gas/testsuite/gas/all/itbl.s
@@ -0,0 +1,13 @@
+
+ ; Test case for assembler option "itbl".
+ ; Run as "as --itbl itbl itbl.s"
+ ; or with stand-alone test case "itbl-test itbl itbl.s".
+
+ ; Assemble processor instructions as defined in "itbl".
+
+ fee $d3,$c2,0x1 ; 0x4ff07601
+ fie ; 0x4ff00000
+ foh $2,0x100
+ fum $d3,$c2 ; 0x4ff07601
+ pig $2,0x100
+
diff --git a/gas/testsuite/gas/all/p1480.s b/gas/testsuite/gas/all/p1480.s
new file mode 100644
index 0000000000..9d0ba81a16
--- /dev/null
+++ b/gas/testsuite/gas/all/p1480.s
@@ -0,0 +1,3 @@
+start: .long 0, 1, 2, 3, 4, 5, 6, 7
+ .space 0x80 - (. - start)
+foo: .long 42
diff --git a/gas/testsuite/gas/all/p2425.s b/gas/testsuite/gas/all/p2425.s
new file mode 100644
index 0000000000..1c9dc95852
--- /dev/null
+++ b/gas/testsuite/gas/all/p2425.s
@@ -0,0 +1,6 @@
+ .text
+ .globl _frobnitz
+_frobnitz:
+ .long 1, 2, 3, 4, 5, 6, 7, GRUMP, 42
+ GRUMP=.-_frobnitz
+ HALFGRUMP=GRUMP/2
diff --git a/gas/testsuite/gas/all/struct.d b/gas/testsuite/gas/all/struct.d
new file mode 100644
index 0000000000..8dc5dd48c1
--- /dev/null
+++ b/gas/testsuite/gas/all/struct.d
@@ -0,0 +1,8 @@
+#nm: --extern-only
+#name: struct
+
+# Test the .struct pseudo-op.
+
+0+00 A w1
+0+02 A w2
+0+04 A w3
diff --git a/gas/testsuite/gas/all/struct.s b/gas/testsuite/gas/all/struct.s
new file mode 100644
index 0000000000..9ecfd0bcc8
--- /dev/null
+++ b/gas/testsuite/gas/all/struct.s
@@ -0,0 +1,10 @@
+ .globl w1
+ .globl w2
+ .globl w3
+ .long 0
+ .struct 0
+w1: .short 0
+w2: .short 0
+w3: .short 0
+ .text
+ .long 0
diff --git a/gas/testsuite/gas/all/x930509.s b/gas/testsuite/gas/all/x930509.s
new file mode 100644
index 0000000000..1299991bf9
--- /dev/null
+++ b/gas/testsuite/gas/all/x930509.s
@@ -0,0 +1,3 @@
+ .long L2-L1
+L1: .long 0x1234
+L2: .long 0x5678
diff --git a/gas/testsuite/gas/alpha/fp.d b/gas/testsuite/gas/alpha/fp.d
new file mode 100644
index 0000000000..9e6f7e9a5c
--- /dev/null
+++ b/gas/testsuite/gas/alpha/fp.d
@@ -0,0 +1,7 @@
+
+.*: file format ecoff-littlealpha
+
+Contents of section .rdata:
+ 0000 71a37909 4f930a40 5441789a cd4b881b q.y.O..@TAx..K..
+ 0010 2a404f93 790971a3 789a5440 5441789a .@O.y.q.x.T@TAx.
+ 0020 00000000 00000000 00000000 00000000 ................
diff --git a/gas/testsuite/gas/alpha/fp.exp b/gas/testsuite/gas/alpha/fp.exp
new file mode 100644
index 0000000000..05ec881cfe
--- /dev/null
+++ b/gas/testsuite/gas/alpha/fp.exp
@@ -0,0 +1,15 @@
+#
+# Alpha OSF/1 tests
+#
+
+if [istarget alpha-*-osf*] then {
+ set testname "fp constants (part 2)"
+ if [gas_test_old "fp.s" "" "fp constants (part 1)"] then {
+ objdump "-s -j .rdata > a.dump"
+ if { [regexp_diff "a.dump" "$srcdir/$subdir/fp.d"] == 0 } then {
+ pass $testname
+ } else {
+ fail $testname
+ }
+ }
+}
diff --git a/gas/testsuite/gas/alpha/fp.s b/gas/testsuite/gas/alpha/fp.s
new file mode 100644
index 0000000000..7cebbbe16c
--- /dev/null
+++ b/gas/testsuite/gas/alpha/fp.s
@@ -0,0 +1,14 @@
+ .rdata
+# These three formats are 8 bytes each.
+ .t_floating 3.32192809488736218171e0
+# .byte 0x71, 0xa3, 0x79, 0x09, 0x4f, 0x93, 0x0a, 0x40
+ .d_floating 3.32192809488736218171e0
+# .byte 0x54, 0x41, 0x78, 0x9a, 0xcd, 0x4b, 0x88, 0x1b
+ .g_floating 3.32192809488736218171e0
+# .byte 0x2a, 0x40, 0x4f, 0x93, 0x79, 0x09, 0x71, 0xa3
+# The next two are four bytes each.
+ .s_floating 3.32192809488736218171e0
+# .byte 0x78, 0x9a, 0x54, 0x40, 0, 0, 0, 0
+ .f_floating 3.32192809488736218171e0
+# .byte 0x54, 0x41, 0x78, 0x9a, 0, 0, 0, 0
+ .long 0, 0, 0, 0
diff --git a/gas/testsuite/gas/arc/alias.d b/gas/testsuite/gas/arc/alias.d
new file mode 100644
index 0000000000..b51acf63e9
--- /dev/null
+++ b/gas/testsuite/gas/arc/alias.d
@@ -0,0 +1,68 @@
+#objdump: -dr
+#name: @OC@
+
+# Test the @OC@ insn.
+
+.*: +file format elf32-.*arc
+
+Disassembly of section .text:
+00000000 @IC+0@008200 @OC@ r0,r1
+00000004 @IC+3@6e3800 @OC@ fp,sp
+00000008 @IC+0@1ffe00 @OC@ r0,0
+0000000c @IC+0@3fffff @OC@ r1,-1
+00000010 @IC+7@e10400 @OC@ 0,r2
+00000014 @IC+7@e187ff @OC@ -1,r3
+00000018 @IC+0@9ffeff @OC@ r4,255
+0000001c @IC+7@e28aff @OC@ 255,r5
+00000020 @IC+0@dfff00 @OC@ r6,-256
+00000024 @IC+7@e38f00 @OC@ -256,r7
+00000028 @IC+1@1f7c00 @OC@ r8,256
+00000030 @IC+1@3f7c00 @OC@ r9,-257
+00000038 @IC+7@c51400 @OC@ 511,r10
+00000040 @IC+1@7f7c00 @OC@ r11,1111638594
+00000048 @IC+7@c61800 @OC@ 305419896,r12
+00000050 @IC+7@ff7cff @OC@ 255,256
+00000058 @IC+7@dffeff @OC@ 256,255
+00000060 @IC+0@1f7c00 @OC@ r0,0
+ RELOC: 00000064 R_ARC_32 foo
+00000068 @IC+0@008200 @OC@ r0,r1
+0000006c @IC+0@620800 @OC@ r3,r4
+00000070 @IC+0@c38e01 @OC@.eq r6,r7
+00000074 @IC+1@251401 @OC@.eq r9,r10
+00000078 @IC+1@869a02 @OC@.ne r12,r13
+0000007c @IC+1@e82002 @OC@.ne r15,r16
+00000080 @IC+2@49a603 @OC@.p r18,r19
+00000084 @IC+2@ab2c03 @OC@.p r21,r22
+00000088 @IC+3@0cb204 @OC@.n r24,r25
+0000008c @IC+3@6e3804 @OC@.n fp,sp
+00000090 @IC+3@cfbe05 @OC@.c ilink2,blink
+00000094 @IC+4@314405 @OC@.c r33,r34
+00000098 @IC+4@92ca05 @OC@.c r36,r37
+0000009c @IC+4@f45006 @OC@.nc r39,r40
+000000a0 @IC+5@55d606 @OC@.nc r42,r43
+000000a4 @IC+5@b75c06 @OC@.nc r45,r46
+000000a8 @IC+6@18e207 @OC@.v r48,r49
+000000ac @IC+6@7a6807 @OC@.v r51,r52
+000000b0 @IC+6@dbee08 @OC@.nv r54,r55
+000000b4 @IC+7@3d7408 @OC@.nv r57,r58
+000000b8 @IC+7@9e7809 @OC@.gt lp_count,lp_count
+000000bc @IC+0@1f7c0a @OC@.ge r0,0
+000000c4 @IC+7@c0820b @OC@.lt 1,r1
+000000cc @IC+7@df7c0c @OC@.le 2,2
+000000d4 @IC+0@61860d @OC@.hi r3,r3
+000000d8 @IC+0@82080e @OC@.ls r4,r4
+000000dc @IC+0@a28a0f @OC@.pnz r5,r5
+000000e0 @IC+0@008300 @OC@.f r0,r1
+000000e4 @IC+0@5efa01 @OC@.f r2,1
+000000e8 @IC+7@a18601 @OC@.f 1,r3
+000000ec @IC+7@a20800 @OC@.f 0,r4
+000000f0 @IC+0@bf7d00 @OC@.f r5,512
+000000f8 @IC+7@c30d00 @OC@.f 512,r6
+00000100 @IC+7@df7d00 @OC@.f 512,512
+00000108 @IC+0@008301 @OC@.eq.f r0,r1
+0000010c @IC+0@3f7d02 @OC@.ne.f r1,0
+00000114 @IC+7@c1050b @OC@.lt.f 0,r2
+0000011c @IC+7@c10509 @OC@.gt.f 1,r2
+00000124 @IC+0@1f7d0c @OC@.le.f r0,512
+0000012c @IC+7@c1050a @OC@.ge.f 512,r2
+00000134 @IC+7@df7d04 @OC@.n.f 512,512
diff --git a/gas/testsuite/gas/arc/alias.s b/gas/testsuite/gas/arc/alias.s
new file mode 100644
index 0000000000..d524440f98
--- /dev/null
+++ b/gas/testsuite/gas/arc/alias.s
@@ -0,0 +1,76 @@
+# @OC@ test
+
+# reg,reg
+ @OC@ r0,r1
+ @OC@ fp,sp
+
+# shimm values
+ @OC@ r0,0
+ @OC@ r1,-1
+ @OC@ 0,r2
+ @OC@ -1,r3
+ @OC@ r4,255
+ @OC@ 255,r5
+ @OC@ r6,-256
+ @OC@ -256,r7
+
+# limm values
+ @OC@ r8,256
+ @OC@ r9,-257
+ @OC@ 511,r10
+ @OC@ r11,0x42424242
+ @OC@ 0x12345678,r12
+
+# shimm and limm
+ @OC@ 255,256
+ @OC@ 256,255
+
+# symbols
+ @OC@ r0,foo
+
+# conditional execution
+ @OC@.al r0,r1
+ @OC@.ra r3,r4
+ @OC@.eq r6,r7
+ @OC@.z r9,r10
+ @OC@.ne r12,r13
+ @OC@.nz r15,r16
+ @OC@.pl r18,r19
+ @OC@.p r21,r22
+ @OC@.mi r24,r25
+ @OC@.n r27,r28
+ @OC@.cs r30,r31
+ @OC@.c r33,r34
+ @OC@.lo r36,r37
+ @OC@.cc r39,r40
+ @OC@.nc r42,r43
+ @OC@.hs r45,r46
+ @OC@.vs r48,r49
+ @OC@.v r51,r52
+ @OC@.vc r54,r55
+ @OC@.nv r57,r58
+ @OC@.gt r60,r60
+ @OC@.ge r0,0
+ @OC@.lt 1,r1
+ @OC@.le 2,2
+ @OC@.hi r3,r3
+ @OC@.ls r4,r4
+ @OC@.pnz r5,r5
+
+# flag setting
+ @OC@.f r0,r1
+ @OC@.f r2,1
+ @OC@.f 1,r3
+ @OC@.f 0,r4
+ @OC@.f r5,512
+ @OC@.f 512,r6
+ @OC@.f 512,512
+
+# conditional execution + flag setting
+ @OC@.eq.f r0,r1
+ @OC@.ne.f r1,0
+ @OC@.lt.f 0,r2
+ @OC@.gt.f 1,r2
+ @OC@.le.f r0,512
+ @OC@.ge.f 512,r2
+ @OC@.n.f 512,512
diff --git a/gas/testsuite/gas/arc/arc.exp b/gas/testsuite/gas/arc/arc.exp
new file mode 100644
index 0000000000..b0984535e2
--- /dev/null
+++ b/gas/testsuite/gas/arc/arc.exp
@@ -0,0 +1,114 @@
+# ARC gas testsuite
+
+# Test an insn from a template .s/.d.
+# The best way to create the .d file is to run the tests without it, let
+# dejagnu crash, run as.new on the just built .s file, run objdump -dr on
+# the result of that, copy the result into the .d file, and edit in the
+# necessary patterns (@OC@, etc.). Sounds complicated but it's easy. The
+# catch is that we assume a working assembler is used to build it. That's
+# obviously not entirely kosher, but once the .d file is created one can
+# verify it's contents over time.
+#
+# Template patterns:
+# @OC@ - placeholder for the opcode
+# @IC+?@ - place holder for the insn code
+# @I3+??@ - place holder for the operation code of code 3 insns.
+
+proc test_template_insn { cpu tmpl opcode icode } {
+ global srcdir subdir objdir
+
+ # Change @OC@ in the template file to $opcode
+
+ set in_fd [open $srcdir/$subdir/$tmpl.s r]
+ set out_fd [open $objdir/$opcode.s w]
+ # FIXME: check return codes
+
+ puts $out_fd "\t.cpu $cpu\n"
+ while { [gets $in_fd line] >= 0 } {
+ regsub "@OC@" $line $opcode line
+ puts $out_fd $line
+ }
+
+ close $in_fd
+ close $out_fd
+
+ # Create output template.
+
+ set in_fd [open $srcdir/$subdir/$tmpl.d r]
+ set out_fd [open $objdir/$opcode.d w]
+ # FIXME: check return codes
+
+ while { [gets $in_fd line] >= 0 } {
+ regsub "@OC@" $line $opcode line
+ #send_user "$line\n"
+ if [string match "*@IC+?@*" $line] {
+ # Insert the opcode. It occupies the top 5 bits.
+ regexp "^(.*)@IC\\+(.)@(.*)$" $line junk leftpart n rightpart
+ set n [expr ($icode << 3) + $n]
+ set n [format "%02x" $n]
+ puts $out_fd "$leftpart$n$rightpart"
+ } elseif [string match "*@I3+??@*" $line] {
+ # Insert insn 3 code (register C field)
+ # b15=8/0, b8=1/0 (their respective hex values in the objdump)
+ regexp "^(.*)@I3\\+(.)(.)@(.*)$" $line junk leftpart b15 b8 rightpart
+ set n [expr ($icode << 1) + ($b15 << 4) + ($b8 << 0)]
+ set n [format "%02x" $n]
+ puts $out_fd "$leftpart$n$rightpart"
+ } else {
+ puts $out_fd $line
+ }
+ }
+
+ close $in_fd
+ close $out_fd
+
+ # Finally, run the test.
+
+ run_dump_test $objdir/$opcode
+
+ # "make clean" won't delete these, so for now we must.
+ catch "exec rm -f $objdir/$opcode.s $objdir/$opcode.d"
+}
+
+# Run the tests.
+
+if [istarget arc*-*-*] then {
+
+ test_template_insn base math adc 9
+ test_template_insn base math add 8
+ test_template_insn base math and 12
+ test_template_insn base math bic 14
+ test_template_insn base math or 13
+ test_template_insn base math sbc 11
+ test_template_insn base math sub 10
+ test_template_insn base math xor 15
+
+ test_template_insn base alias mov 12
+ test_template_insn base alias rlc 9
+ test_template_insn base alias asl 8
+# `lsl' gets dumped as `asl' so this must be tested elsewhere.
+# test_template_insn base alias lsl 8
+
+ test_template_insn base sshift asr 1
+ test_template_insn base sshift lsr 2
+ test_template_insn base sshift ror 3
+ test_template_insn base sshift rrc 4
+
+ test_template_insn base branch b 4
+ test_template_insn base branch bl 5
+ test_template_insn base branch lp 6
+
+ run_dump_test "j"
+
+ test_template_insn base insn3 sexb 5
+ test_template_insn base insn3 sexw 6
+ test_template_insn base insn3 extb 7
+ test_template_insn base insn3 extw 8
+
+ run_dump_test "flag"
+# run_dump_test "nop"
+
+ run_dump_test "ld"
+ run_dump_test "st"
+
+}
diff --git a/gas/testsuite/gas/arc/branch.d b/gas/testsuite/gas/arc/branch.d
new file mode 100644
index 0000000000..4c9b014b1b
--- /dev/null
+++ b/gas/testsuite/gas/arc/branch.d
@@ -0,0 +1,45 @@
+#objdump: -dr
+#name: @OC@
+
+# Test the @OC@ insn.
+
+.*: +file format elf32-.*arc
+
+Disassembly of section .text:
+00000000 <text_label> @IC+7@ffff80 @OC@ 00000000 <text_label>
+00000004 <text_label\+4> @IC+7@ffff00 @OC@ 00000000 <text_label>
+00000008 <text_label\+8> @IC+7@fffe80 @OC@ 00000000 <text_label>
+0000000c <text_label\+c> @IC+7@fffe01 @OC@eq 00000000 <text_label>
+00000010 <text_label\+10> @IC+7@fffd81 @OC@eq 00000000 <text_label>
+00000014 <text_label\+14> @IC+7@fffd02 @OC@ne 00000000 <text_label>
+00000018 <text_label\+18> @IC+7@fffc82 @OC@ne 00000000 <text_label>
+0000001c <text_label\+1c> @IC+7@fffc03 @OC@p 00000000 <text_label>
+00000020 <text_label\+20> @IC+7@fffb83 @OC@p 00000000 <text_label>
+00000024 <text_label\+24> @IC+7@fffb04 @OC@n 00000000 <text_label>
+00000028 <text_label\+28> @IC+7@fffa84 @OC@n 00000000 <text_label>
+0000002c <text_label\+2c> @IC+7@fffa05 @OC@c 00000000 <text_label>
+00000030 <text_label\+30> @IC+7@fff985 @OC@c 00000000 <text_label>
+00000034 <text_label\+34> @IC+7@fff905 @OC@c 00000000 <text_label>
+00000038 <text_label\+38> @IC+7@fff886 @OC@nc 00000000 <text_label>
+0000003c <text_label\+3c> @IC+7@fff806 @OC@nc 00000000 <text_label>
+00000040 <text_label\+40> @IC+7@fff786 @OC@nc 00000000 <text_label>
+00000044 <text_label\+44> @IC+7@fff707 @OC@v 00000000 <text_label>
+00000048 <text_label\+48> @IC+7@fff687 @OC@v 00000000 <text_label>
+0000004c <text_label\+4c> @IC+7@fff608 @OC@nv 00000000 <text_label>
+00000050 <text_label\+50> @IC+7@fff588 @OC@nv 00000000 <text_label>
+00000054 <text_label\+54> @IC+7@fff509 @OC@gt 00000000 <text_label>
+00000058 <text_label\+58> @IC+7@fff48a @OC@ge 00000000 <text_label>
+0000005c <text_label\+5c> @IC+7@fff40b @OC@lt 00000000 <text_label>
+00000060 <text_label\+60> @IC+7@fff38c @OC@le 00000000 <text_label>
+00000064 <text_label\+64> @IC+7@fff30d @OC@hi 00000000 <text_label>
+00000068 <text_label\+68> @IC+7@fff28e @OC@ls 00000000 <text_label>
+0000006c <text_label\+6c> @IC+7@fff20f @OC@pnz 00000000 <text_label>
+00000070 <text_label\+70> @IC+7@ffff80 @OC@ 00000070 <text_label\+70>
+ RELOC: 00000070 R_ARC_B22_PCREL external_text_label
+00000074 <text_label\+74> @IC+0@000000 @OC@ 00000078 <text_label\+78>
+00000078 <text_label\+78> @IC+7@fff0a0 @OC@.d 00000000 <text_label>
+0000007c <text_label\+7c> @IC+7@fff000 @OC@ 00000000 <text_label>
+00000080 <text_label\+80> @IC+7@ffefc0 @OC@.jd 00000000 <text_label>
+00000084 <text_label\+84> @IC+7@ffef21 @OC@eq.d 00000000 <text_label>
+00000088 <text_label\+88> @IC+7@ffee82 @OC@ne 00000000 <text_label>
+0000008c <text_label\+8c> @IC+7@ffee46 @OC@nc.jd 00000000 <text_label>
diff --git a/gas/testsuite/gas/arc/branch.s b/gas/testsuite/gas/arc/branch.s
new file mode 100644
index 0000000000..8bf1618ffc
--- /dev/null
+++ b/gas/testsuite/gas/arc/branch.s
@@ -0,0 +1,47 @@
+# @OC@ test
+
+text_label:
+
+# Condition tests
+ @OC@ text_label
+ @OC@al text_label
+ @OC@ra text_label
+ @OC@eq text_label
+ @OC@z text_label
+ @OC@ne text_label
+ @OC@nz text_label
+ @OC@pl text_label
+ @OC@p text_label
+ @OC@mi text_label
+ @OC@n text_label
+ @OC@cs text_label
+ @OC@c text_label
+ @OC@lo text_label
+ @OC@cc text_label
+ @OC@nc text_label
+ @OC@hs text_label
+ @OC@vs text_label
+ @OC@v text_label
+ @OC@vc text_label
+ @OC@nv text_label
+ @OC@gt text_label
+ @OC@ge text_label
+ @OC@lt text_label
+ @OC@le text_label
+ @OC@hi text_label
+ @OC@ls text_label
+ @OC@pnz text_label
+
+ @OC@ external_text_label
+
+ @OC@ 0
+
+# Delay slots
+ @OC@.d text_label
+ @OC@.nd text_label
+ @OC@.jd text_label
+
+# Condition tests and delay slots
+ @OC@eq.d text_label
+ @OC@ne.nd text_label
+ @OC@cc.jd text_label
diff --git a/gas/testsuite/gas/arc/flag.d b/gas/testsuite/gas/arc/flag.d
new file mode 100644
index 0000000000..68f36d39f1
--- /dev/null
+++ b/gas/testsuite/gas/arc/flag.d
@@ -0,0 +1,29 @@
+#objdump: -dr
+#name: flag
+
+# Test the flag macro.
+
+.*: +file format elf32-.*arc
+
+No symbols in "a.out".
+Disassembly of section .text:
+00000000 1fa00000 flag r0
+00000004 1fbf8001 flag 1
+00000008 1fbf8002 flag 2
+0000000c 1fbf8004 flag 4
+00000010 1fbf8008 flag 8
+00000014 1fbf8010 flag 16
+00000018 1fbf8020 flag 32
+0000001c 1fbf8040 flag 64
+00000020 1fbf8080 flag 128
+00000024 1fbf0000 flag -2147483647
+0000002c 1fa0000b flag.lt r0
+00000030 1fbf0009 flag.gt 1
+00000038 1fbf0009 flag.gt 2
+00000040 1fbf0009 flag.gt 4
+00000048 1fbf0009 flag.gt 8
+00000050 1fbf0009 flag.gt 16
+00000058 1fbf0009 flag.gt 32
+00000060 1fbf0009 flag.gt 64
+00000068 1fbf0009 flag.gt 128
+00000070 1fbf000a flag.ge -2147483647
diff --git a/gas/testsuite/gas/arc/flag.s b/gas/testsuite/gas/arc/flag.s
new file mode 100644
index 0000000000..7067aa5465
--- /dev/null
+++ b/gas/testsuite/gas/arc/flag.s
@@ -0,0 +1,27 @@
+# flag test
+
+ flag r0
+
+ flag 1
+ flag 2
+ flag 4
+ flag 8
+ flag 16
+ flag 32
+ flag 64
+ flag 128
+
+ flag 0x80000001
+
+ flag.lt r0
+
+ flag.gt 1
+ flag.gt 2
+ flag.gt 4
+ flag.gt 8
+ flag.gt 16
+ flag.gt 32
+ flag.gt 64
+ flag.gt 128
+
+ flag.ge 0x80000001
diff --git a/gas/testsuite/gas/arc/insn3.d b/gas/testsuite/gas/arc/insn3.d
new file mode 100644
index 0000000000..c0207a77a4
--- /dev/null
+++ b/gas/testsuite/gas/arc/insn3.d
@@ -0,0 +1,44 @@
+#objdump: -dr
+#name: @OC@
+
+# Test the @OC@ insn.
+
+.*: +file format elf32-.*arc
+
+Disassembly of section .text:
+00000000 1800@I3+80@00 @OC@ r0,r1
+00000004 1b6e@I3+00@00 @OC@ fp,sp
+00000008 181f@I3+80@00 @OC@ r0,0
+0000000c 183f@I3+81@ff @OC@ r1,-1
+00000010 1fe1@I3+00@00 @OC@ 0,r2
+00000014 1fe1@I3+81@ff @OC@ -1,r3
+00000018 189f@I3+80@ff @OC@ r4,255
+0000001c 1fe2@I3+80@ff @OC@ 255,r5
+00000020 18df@I3+81@00 @OC@ r6,-256
+00000024 1fe3@I3+81@00 @OC@ -256,r7
+00000028 191f@I3+00@00 @OC@ r8,256
+00000030 193f@I3+00@00 @OC@ r9,-257
+00000038 1fc5@I3+00@00 @OC@ 511,r10
+00000040 197f@I3+00@00 @OC@ r11,1111638594
+00000048 1fc6@I3+00@00 @OC@ 305419896,r12
+00000050 1fff@I3+00@ff @OC@ 255,256
+00000058 1fdf@I3+80@ff @OC@ 256,255
+00000060 181f@I3+00@00 @OC@ r0,0
+ RELOC: 00000064 R_ARC_32 foo
+00000068 1945@I3+80@01 @OC@.eq r10,r11
+0000006c 1986@I3+80@02 @OC@.ne r12,r13
+00000070 19df@I3+00@0b @OC@.lt r14,0
+00000078 19ff@I3+00@09 @OC@.gt r15,512
+00000080 1800@I3+81@00 @OC@.f r0,r1
+00000084 185e@I3+80@01 @OC@.f r2,1
+00000088 1fa2@I3+00@00 @OC@.f 0,r4
+0000008c 18bf@I3+01@00 @OC@.f r5,512
+00000094 1fc3@I3+01@00 @OC@.f 512,r6
+0000009c 1fdf@I3+01@00 @OC@.f 512,512
+000000a4 1800@I3+81@01 @OC@.eq.f r0,r1
+000000a8 183f@I3+01@02 @OC@.ne.f r1,0
+000000b0 1fc1@I3+01@0b @OC@.lt.f 0,r2
+000000b8 1fc1@I3+01@09 @OC@.gt.f 1,r2
+000000c0 181f@I3+01@0c @OC@.le.f r0,512
+000000c8 1fc1@I3+01@0a @OC@.ge.f 512,r2
+000000d0 1fdf@I3+01@04 @OC@.n.f 512,512
diff --git a/gas/testsuite/gas/arc/insn3.s b/gas/testsuite/gas/arc/insn3.s
new file mode 100644
index 0000000000..f12fb88355
--- /dev/null
+++ b/gas/testsuite/gas/arc/insn3.s
@@ -0,0 +1,52 @@
+# Insn 3 @OC@ test
+
+# reg,reg
+ @OC@ r0,r1
+ @OC@ fp,sp
+
+# shimm values
+ @OC@ r0,0
+ @OC@ r1,-1
+ @OC@ 0,r2
+ @OC@ -1,r3
+ @OC@ r4,255
+ @OC@ 255,r5
+ @OC@ r6,-256
+ @OC@ -256,r7
+
+# limm values
+ @OC@ r8,256
+ @OC@ r9,-257
+ @OC@ 511,r10
+ @OC@ r11,0x42424242
+ @OC@ 0x12345678,r12
+
+# shimm and limm
+ @OC@ 255,256
+ @OC@ 256,255
+
+# symbols
+ @OC@ r0,foo
+
+# conditional execution
+ @OC@.eq r10,r11
+ @OC@.ne r12,r13
+ @OC@.lt r14,0
+ @OC@.gt r15,512
+
+# flag setting
+ @OC@.f r0,r1
+ @OC@.f r2,1
+ @OC@.f 0,r4
+ @OC@.f r5,512
+ @OC@.f 512,r6
+ @OC@.f 512,512
+
+# conditional execution + flag setting
+ @OC@.eq.f r0,r1
+ @OC@.ne.f r1,0
+ @OC@.lt.f 0,r2
+ @OC@.gt.f 1,r2
+ @OC@.le.f r0,512
+ @OC@.ge.f 512,r2
+ @OC@.n.f 512,512
diff --git a/gas/testsuite/gas/arc/j.d b/gas/testsuite/gas/arc/j.d
new file mode 100644
index 0000000000..af103f0d1a
--- /dev/null
+++ b/gas/testsuite/gas/arc/j.d
@@ -0,0 +1,75 @@
+#objdump: -dr
+#name: j
+
+# Test the j insn.
+
+.*: +file format elf32-.*arc
+
+Disassembly of section .text:
+00000000 <text_label> 38000000 j r0
+00000004 <text_label\+4> 38000020 j.d r0
+00000008 <text_label\+8> 38000040 j.jd r0
+0000000c <text_label\+c> 38000000 j r0
+00000010 <text_label\+10> 38008000 j r1
+00000014 <text_label\+14> 38008020 j.d r1
+00000018 <text_label\+18> 38008040 j.jd r1
+0000001c <text_label\+1c> 38008000 j r1
+00000020 <text_label\+20> 381f0000 j 0
+ RELOC: 00000024 R_ARC_32 .text
+00000028 <text_label\+28> 381f0000 j 0
+ RELOC: 0000002c R_ARC_32 .text
+00000030 <text_label\+30> 381f0000 j 0
+ RELOC: 00000034 R_ARC_32 .text
+00000038 <text_label\+38> 381f0001 jeq 0
+ RELOC: 0000003c R_ARC_32 .text
+00000040 <text_label\+40> 381f0001 jeq 0
+ RELOC: 00000044 R_ARC_32 .text
+00000048 <text_label\+48> 381f0002 jne 0
+ RELOC: 0000004c R_ARC_32 .text
+00000050 <text_label\+50> 381f0002 jne 0
+ RELOC: 00000054 R_ARC_32 .text
+00000058 <text_label\+58> 381f0003 jp 0
+ RELOC: 0000005c R_ARC_32 .text
+00000060 <text_label\+60> 381f0003 jp 0
+ RELOC: 00000064 R_ARC_32 .text
+00000068 <text_label\+68> 381f0004 jn 0
+ RELOC: 0000006c R_ARC_32 .text
+00000070 <text_label\+70> 381f0004 jn 0
+ RELOC: 00000074 R_ARC_32 .text
+00000078 <text_label\+78> 381f0005 jc 0
+ RELOC: 0000007c R_ARC_32 .text
+00000080 <text_label\+80> 381f0005 jc 0
+ RELOC: 00000084 R_ARC_32 .text
+00000088 <text_label\+88> 381f0005 jc 0
+ RELOC: 0000008c R_ARC_32 .text
+00000090 <text_label\+90> 381f0006 jnc 0
+ RELOC: 00000094 R_ARC_32 .text
+00000098 <text_label\+98> 381f0006 jnc 0
+ RELOC: 0000009c R_ARC_32 .text
+000000a0 <text_label\+a0> 381f0006 jnc 0
+ RELOC: 000000a4 R_ARC_32 .text
+000000a8 <text_label\+a8> 381f0007 jv 0
+ RELOC: 000000ac R_ARC_32 .text
+000000b0 <text_label\+b0> 381f0007 jv 0
+ RELOC: 000000b4 R_ARC_32 .text
+000000b8 <text_label\+b8> 381f0008 jnv 0
+ RELOC: 000000bc R_ARC_32 .text
+000000c0 <text_label\+c0> 381f0008 jnv 0
+ RELOC: 000000c4 R_ARC_32 .text
+000000c8 <text_label\+c8> 381f0009 jgt 0
+ RELOC: 000000cc R_ARC_32 .text
+000000d0 <text_label\+d0> 381f000a jge 0
+ RELOC: 000000d4 R_ARC_32 .text
+000000d8 <text_label\+d8> 381f000b jlt 0
+ RELOC: 000000dc R_ARC_32 .text
+000000e0 <text_label\+e0> 381f000c jle 0
+ RELOC: 000000e4 R_ARC_32 .text
+000000e8 <text_label\+e8> 381f000d jhi 0
+ RELOC: 000000ec R_ARC_32 .text
+000000f0 <text_label\+f0> 381f000e jls 0
+ RELOC: 000000f4 R_ARC_32 .text
+000000f8 <text_label\+f8> 381f000f jpnz 0
+ RELOC: 000000fc R_ARC_32 .text
+00000100 <text_label\+100> 381f0000 j 0
+ RELOC: 00000104 R_ARC_32 external_text_label
+00000108 <text_label\+108> 381f0000 j 0
diff --git a/gas/testsuite/gas/arc/j.s b/gas/testsuite/gas/arc/j.s
new file mode 100644
index 0000000000..0161af215f
--- /dev/null
+++ b/gas/testsuite/gas/arc/j.s
@@ -0,0 +1,45 @@
+# j test
+
+text_label:
+ j r0
+ j.d r0
+ j.jd r0
+ j.nd r0
+
+ j.f [r1]
+ j.d.f [r1]
+ j.jd.f [r1]
+ j.nd.f [r1]
+
+ j text_label
+ jal text_label
+ jra text_label
+ jeq text_label
+ jz text_label
+ jne text_label
+ jnz text_label
+ jpl text_label
+ jp text_label
+ jmi text_label
+ jn text_label
+ jcs text_label
+ jc text_label
+ jlo text_label
+ jcc text_label
+ jnc text_label
+ jhs text_label
+ jvs text_label
+ jv text_label
+ jvc text_label
+ jnv text_label
+ jgt text_label
+ jge text_label
+ jlt text_label
+ jle text_label
+ jhi text_label
+ jls text_label
+ jpnz text_label
+
+ j external_text_label
+
+ j 0
diff --git a/gas/testsuite/gas/arc/ld.d b/gas/testsuite/gas/arc/ld.d
new file mode 100644
index 0000000000..d6dd0a1a5d
--- /dev/null
+++ b/gas/testsuite/gas/arc/ld.d
@@ -0,0 +1,30 @@
+#objdump: -dr
+#name: ld/lr
+
+# Test the ld/lr insn.
+
+.*: +file format elf32-.*arc
+
+Disassembly of section .text:
+00000000 08008000 ld r0,\[r1\]
+00000004 00418800 ld r2,\[r3,r4\]
+00000008 08a30001 ld r5,\[r6,1\]
+0000000c 08e401ff ld r7,\[r8,-1\]
+00000010 092500ff ld r9,\[r10,255\]
+00000014 09660100 ld r11,\[r12,-256\]
+00000018 01a77c00 ld r13,\[r14,256\]
+00000020 01e87c00 ld r15,\[r16,-257\]
+00000028 023f3800 ld r17,\[305419896,sp\]
+00000030 0a7f0000 ld r19,\[0\]
+ RELOC: 00000034 R_ARC_32 foo
+00000038 0a9f0000 ld r20,\[4\]
+ RELOC: 0000003c R_ARC_32 foo
+00000040 081f8400 ldb r0,\[0\]
+00000044 081f8800 ldw r0,\[0\]
+00000048 081f8200 ld.x r0,\[0\]
+0000004c 081f9000 ld.a r0,\[0\]
+00000050 081fc000 ld.di r0,\[0\]
+00000054 08005600 ldb.x.a.di r0,\[r0\]
+00000058 0800a000 lr r0,\[r1\]
+0000005c 085fa000 lr r2,\[status\]
+00000060 087f2000 lr r3,\[305419896\]
diff --git a/gas/testsuite/gas/arc/ld.s b/gas/testsuite/gas/arc/ld.s
new file mode 100644
index 0000000000..aa26719df1
--- /dev/null
+++ b/gas/testsuite/gas/arc/ld.s
@@ -0,0 +1,24 @@
+# ld/lr test
+
+ ld r0,[r1]
+ ld r2,[r3,r4]
+ ld r5,[r6,1]
+ ld r7,[r8,-1]
+ ld r9,[r10,255]
+ ld r11,[r12,-256]
+ ld r13,[r14,256]
+ ld r15,[r16,-257]
+ ld r17,[0x12345678,r28]
+ ld r19,[foo]
+ ld r20,[foo+4]
+
+ ldb r0,[0]
+ ldw r0,[0]
+ ld.x r0,[0]
+ ld.a r0,[0]
+ ld.di r0,[0]
+ ldb.x.a.di r0,[r0]
+
+ lr r0,[r1]
+ lr r2,[status]
+ lr r3,[0x12345678]
diff --git a/gas/testsuite/gas/arc/math.d b/gas/testsuite/gas/arc/math.d
new file mode 100644
index 0000000000..ccb79c5ca7
--- /dev/null
+++ b/gas/testsuite/gas/arc/math.d
@@ -0,0 +1,78 @@
+#objdump: -dr
+#name: @OC@
+
+# Test the @OC@ insn.
+
+.*: +file format elf32-.*arc
+
+Disassembly of section .text:
+00000000 @IC+0@008400 @OC@ r0,r1,r2
+00000004 @IC+3@4db800 @OC@ r26,fp,sp
+00000008 @IC+3@af3e00 @OC@ ilink1,ilink2,blink
+0000000c @IC+7@5df800 @OC@ r58,r59,lp_count
+00000010 @IC+0@00fe00 @OC@ r0,r1,0
+00000014 @IC+0@1f8400 @OC@ r0,0,r2
+00000018 @IC+7@e08400 @OC@ 0,r1,r2
+0000001c @IC+0@00ffff @OC@ r0,r1,-1
+00000020 @IC+0@1f85ff @OC@ r0,-1,r2
+00000024 @IC+7@e085ff @OC@ -1,r1,r2
+00000028 @IC+0@00feff @OC@ r0,r1,255
+0000002c @IC+0@1f84ff @OC@ r0,255,r2
+00000030 @IC+7@e084ff @OC@ 255,r1,r2
+00000034 @IC+0@00ff00 @OC@ r0,r1,-256
+00000038 @IC+0@1f8500 @OC@ r0,-256,r2
+0000003c @IC+7@e08500 @OC@ -256,r1,r2
+00000040 @IC+0@00fc00 @OC@ r0,r1,256
+00000048 @IC+0@1f0400 @OC@ r0,-257,r2
+00000050 @IC+7@c08400 @OC@ 511,r1,r2
+00000058 @IC+0@1f0400 @OC@ r0,1111638594,r2
+00000060 @IC+7@c0fc00 @OC@ 305419896,r1,305419896
+00000068 @IC+0@1ffcff @OC@ r0,255,256
+00000070 @IC+0@1f7eff @OC@ r0,256,255
+00000078 @IC+7@e0fcff @OC@ 255,r1,256
+00000080 @IC+7@ff04ff @OC@ 255,256,r2
+00000088 @IC+7@c0feff @OC@ 256,r1,255
+00000090 @IC+7@df84ff @OC@ 256,255,r2
+00000098 @IC+0@00fc00 @OC@ r0,r1,0
+ RELOC: 0000009c R_ARC_32 foo
+000000a0 @IC+0@008400 @OC@ r0,r1,r2
+000000a4 @IC+0@620a00 @OC@ r3,r4,r5
+000000a8 @IC+0@c39001 @OC@.eq r6,r7,r8
+000000ac @IC+1@251601 @OC@.eq r9,r10,r11
+000000b0 @IC+1@869c02 @OC@.ne r12,r13,r14
+000000b4 @IC+1@e82202 @OC@.ne r15,r16,r17
+000000b8 @IC+2@49a803 @OC@.p r18,r19,r20
+000000bc @IC+2@ab2e03 @OC@.p r21,r22,r23
+000000c0 @IC+3@0cb404 @OC@.n r24,r25,r26
+000000c4 @IC+3@6e3a04 @OC@.n fp,sp,ilink1
+000000c8 @IC+3@cfc005 @OC@.c ilink2,blink,r32
+000000cc @IC+4@314605 @OC@.c r33,r34,r35
+000000d0 @IC+4@92cc05 @OC@.c r36,r37,r38
+000000d4 @IC+4@f45206 @OC@.nc r39,r40,r41
+000000d8 @IC+5@55d806 @OC@.nc r42,r43,r44
+000000dc @IC+5@b75e06 @OC@.nc r45,r46,r47
+000000e0 @IC+6@18e407 @OC@.v r48,r49,r50
+000000e4 @IC+6@7a6a07 @OC@.v r51,r52,r53
+000000e8 @IC+6@dbf008 @OC@.nv r54,r55,r56
+000000ec @IC+7@3d7608 @OC@.nv r57,r58,r59
+000000f0 @IC+7@9e0009 @OC@.gt lp_count,lp_count,r0
+000000f4 @IC+0@007c0a @OC@.ge r0,r0,0
+000000fc @IC+0@3f020b @OC@.lt r1,1,r1
+00000104 @IC+7@c0840c @OC@.le 2,r1,r2
+0000010c @IC+0@7f060d @OC@.hi r3,3,r3
+00000114 @IC+7@df080e @OC@.ls 4,4,r4
+0000011c @IC+7@c2fc0f @OC@.pnz 5,r5,5
+00000124 @IC+0@008500 @OC@.f r0,r1,r2
+00000128 @IC+0@00fa01 @OC@.f r0,r1,1
+0000012c @IC+0@1e8401 @OC@.f r0,1,r2
+00000130 @IC+7@a08400 @OC@.f 0,r1,r2
+00000134 @IC+0@00fd00 @OC@.f r0,r1,512
+0000013c @IC+0@1f0500 @OC@.f r0,512,r2
+00000144 @IC+7@c08500 @OC@.f 512,r1,r2
+0000014c @IC+0@008501 @OC@.eq.f r0,r1,r2
+00000150 @IC+0@00fd02 @OC@.ne.f r0,r1,0
+00000158 @IC+0@1f050b @OC@.lt.f r0,0,r2
+00000160 @IC+7@c08509 @OC@.gt.f 0,r1,r2
+00000168 @IC+0@00fd0c @OC@.le.f r0,r1,512
+00000170 @IC+0@1f050a @OC@.ge.f r0,512,r2
+00000178 @IC+7@c08504 @OC@.n.f 512,r1,r2
diff --git a/gas/testsuite/gas/arc/math.s b/gas/testsuite/gas/arc/math.s
new file mode 100644
index 0000000000..775169a8a5
--- /dev/null
+++ b/gas/testsuite/gas/arc/math.s
@@ -0,0 +1,89 @@
+# @OC@ test
+
+# Stay away from operands with duplicate arguments (eg: add r0,r1,r1).
+# They will be disassembled as they're macro counterparts (eg: asl r0,r1).
+
+# reg,reg,reg
+ @OC@ r0,r1,r2
+ @OC@ r26,fp,sp
+ @OC@ ilink1,ilink2,blink
+ @OC@ r58,r59,lp_count
+
+# shimm values
+ @OC@ r0,r1,0
+ @OC@ r0,0,r2
+ @OC@ 0,r1,r2
+ @OC@ r0,r1,-1
+ @OC@ r0,-1,r2
+ @OC@ -1,r1,r2
+ @OC@ r0,r1,255
+ @OC@ r0,255,r2
+ @OC@ 255,r1,r2
+ @OC@ r0,r1,-256
+ @OC@ r0,-256,r2
+ @OC@ -256,r1,r2
+
+# limm values
+ @OC@ r0,r1,256
+ @OC@ r0,-257,r2
+ @OC@ 511,r1,r2
+ @OC@ r0,0x42424242,r2
+ @OC@ 0x12345678,r1,0x12345678
+
+# shimm and limm
+ @OC@ r0,255,256
+ @OC@ r0,256,255
+ @OC@ 255,r1,256
+ @OC@ 255,256,r2
+ @OC@ 256,r1,255
+ @OC@ 256,255,r2
+
+# symbols
+ @OC@ r0,r1,foo
+
+# conditional execution
+ @OC@.al r0,r1,r2
+ @OC@.ra r3,r4,r5
+ @OC@.eq r6,r7,r8
+ @OC@.z r9,r10,r11
+ @OC@.ne r12,r13,r14
+ @OC@.nz r15,r16,r17
+ @OC@.pl r18,r19,r20
+ @OC@.p r21,r22,r23
+ @OC@.mi r24,r25,r26
+ @OC@.n r27,r28,r29
+ @OC@.cs r30,r31,r32
+ @OC@.c r33,r34,r35
+ @OC@.lo r36,r37,r38
+ @OC@.cc r39,r40,r41
+ @OC@.nc r42,r43,r44
+ @OC@.hs r45,r46,r47
+ @OC@.vs r48,r49,r50
+ @OC@.v r51,r52,r53
+ @OC@.vc r54,r55,r56
+ @OC@.nv r57,r58,r59
+ @OC@.gt r60,r60,r0
+ @OC@.ge r0,r0,0
+ @OC@.lt r1,1,r1
+ @OC@.le 2,r1,r2
+ @OC@.hi r3,3,r3
+ @OC@.ls 4,4,r4
+ @OC@.pnz 5,r5,5
+
+# flag setting
+ @OC@.f r0,r1,r2
+ @OC@.f r0,r1,1
+ @OC@.f r0,1,r2
+ @OC@.f 0,r1,r2
+ @OC@.f r0,r1,512
+ @OC@.f r0,512,r2
+ @OC@.f 512,r1,r2
+
+# conditional execution + flag setting
+ @OC@.eq.f r0,r1,r2
+ @OC@.ne.f r0,r1,0
+ @OC@.lt.f r0,0,r2
+ @OC@.gt.f 0,r1,r2
+ @OC@.le.f r0,r1,512
+ @OC@.ge.f r0,512,r2
+ @OC@.n.f 512,r1,r2
diff --git a/gas/testsuite/gas/arc/sshift.d b/gas/testsuite/gas/arc/sshift.d
new file mode 100644
index 0000000000..c0207a77a4
--- /dev/null
+++ b/gas/testsuite/gas/arc/sshift.d
@@ -0,0 +1,44 @@
+#objdump: -dr
+#name: @OC@
+
+# Test the @OC@ insn.
+
+.*: +file format elf32-.*arc
+
+Disassembly of section .text:
+00000000 1800@I3+80@00 @OC@ r0,r1
+00000004 1b6e@I3+00@00 @OC@ fp,sp
+00000008 181f@I3+80@00 @OC@ r0,0
+0000000c 183f@I3+81@ff @OC@ r1,-1
+00000010 1fe1@I3+00@00 @OC@ 0,r2
+00000014 1fe1@I3+81@ff @OC@ -1,r3
+00000018 189f@I3+80@ff @OC@ r4,255
+0000001c 1fe2@I3+80@ff @OC@ 255,r5
+00000020 18df@I3+81@00 @OC@ r6,-256
+00000024 1fe3@I3+81@00 @OC@ -256,r7
+00000028 191f@I3+00@00 @OC@ r8,256
+00000030 193f@I3+00@00 @OC@ r9,-257
+00000038 1fc5@I3+00@00 @OC@ 511,r10
+00000040 197f@I3+00@00 @OC@ r11,1111638594
+00000048 1fc6@I3+00@00 @OC@ 305419896,r12
+00000050 1fff@I3+00@ff @OC@ 255,256
+00000058 1fdf@I3+80@ff @OC@ 256,255
+00000060 181f@I3+00@00 @OC@ r0,0
+ RELOC: 00000064 R_ARC_32 foo
+00000068 1945@I3+80@01 @OC@.eq r10,r11
+0000006c 1986@I3+80@02 @OC@.ne r12,r13
+00000070 19df@I3+00@0b @OC@.lt r14,0
+00000078 19ff@I3+00@09 @OC@.gt r15,512
+00000080 1800@I3+81@00 @OC@.f r0,r1
+00000084 185e@I3+80@01 @OC@.f r2,1
+00000088 1fa2@I3+00@00 @OC@.f 0,r4
+0000008c 18bf@I3+01@00 @OC@.f r5,512
+00000094 1fc3@I3+01@00 @OC@.f 512,r6
+0000009c 1fdf@I3+01@00 @OC@.f 512,512
+000000a4 1800@I3+81@01 @OC@.eq.f r0,r1
+000000a8 183f@I3+01@02 @OC@.ne.f r1,0
+000000b0 1fc1@I3+01@0b @OC@.lt.f 0,r2
+000000b8 1fc1@I3+01@09 @OC@.gt.f 1,r2
+000000c0 181f@I3+01@0c @OC@.le.f r0,512
+000000c8 1fc1@I3+01@0a @OC@.ge.f 512,r2
+000000d0 1fdf@I3+01@04 @OC@.n.f 512,512
diff --git a/gas/testsuite/gas/arc/sshift.s b/gas/testsuite/gas/arc/sshift.s
new file mode 100644
index 0000000000..e2fa661fa5
--- /dev/null
+++ b/gas/testsuite/gas/arc/sshift.s
@@ -0,0 +1,52 @@
+# Single shift @OC@ test
+
+# reg,reg
+ @OC@ r0,r1
+ @OC@ fp,sp
+
+# shimm values
+ @OC@ r0,0
+ @OC@ r1,-1
+ @OC@ 0,r2
+ @OC@ -1,r3
+ @OC@ r4,255
+ @OC@ 255,r5
+ @OC@ r6,-256
+ @OC@ -256,r7
+
+# limm values
+ @OC@ r8,256
+ @OC@ r9,-257
+ @OC@ 511,r10
+ @OC@ r11,0x42424242
+ @OC@ 0x12345678,r12
+
+# shimm and limm
+ @OC@ 255,256
+ @OC@ 256,255
+
+# symbols
+ @OC@ r0,foo
+
+# conditional execution
+ @OC@.eq r10,r11
+ @OC@.ne r12,r13
+ @OC@.lt r14,0
+ @OC@.gt r15,512
+
+# flag setting
+ @OC@.f r0,r1
+ @OC@.f r2,1
+ @OC@.f 0,r4
+ @OC@.f r5,512
+ @OC@.f 512,r6
+ @OC@.f 512,512
+
+# conditional execution + flag setting
+ @OC@.eq.f r0,r1
+ @OC@.ne.f r1,0
+ @OC@.lt.f 0,r2
+ @OC@.gt.f 1,r2
+ @OC@.le.f r0,512
+ @OC@.ge.f 512,r2
+ @OC@.n.f 512,512
diff --git a/gas/testsuite/gas/arc/st.d b/gas/testsuite/gas/arc/st.d
new file mode 100644
index 0000000000..cca99a8339
--- /dev/null
+++ b/gas/testsuite/gas/arc/st.d
@@ -0,0 +1,25 @@
+#objdump: -dr
+#name: st/sr
+
+# Test the st/sr insn.
+
+.*: +file format elf32-.*arc
+
+Disassembly of section .text:
+00000000 10008000 st r0,\[r1\]
+00000004 10030a01 st r5,\[r6,1\]
+00000008 10040fff st r7,\[r8,-1\]
+0000000c 100512ff st r9,\[r10,255\]
+00000010 10061700 st r11,\[r12,-256\]
+00000014 101f2600 st r19,\[0\]
+ RELOC: 00000018 R_ARC_32 foo
+0000001c 101f2800 st r20,\[4\]
+ RELOC: 00000020 R_ARC_32 foo
+00000024 105f0000 stb r0,\[0\]
+0000002c 109f0000 stw r0,\[0\]
+00000034 111f0000 st.a r0,\[0\]
+0000003c 141f0000 st.di r0,\[0\]
+00000044 15400000 stb.a.di r0,\[r0\]
+00000048 12008000 sr r0,\[r1\]
+0000004c 121f8400 sr r2,\[status\]
+00000050 121f0600 sr r3,\[305419896\]
diff --git a/gas/testsuite/gas/arc/st.s b/gas/testsuite/gas/arc/st.s
new file mode 100644
index 0000000000..10af198a78
--- /dev/null
+++ b/gas/testsuite/gas/arc/st.s
@@ -0,0 +1,19 @@
+# st/sr test
+
+ st r0,[r1]
+ st r5,[r6,1]
+ st r7,[r8,-1]
+ st r9,[r10,255]
+ st r11,[r12,-256]
+ st r19,[foo]
+ st r20,[foo+4]
+
+ stb r0,[0]
+ stw r0,[0]
+ st.a r0,[0]
+ st.di r0,[0]
+ stb.a.di r0,[r0]
+
+ sr r0,[r1]
+ sr r2,[status]
+ sr r3,[0x12345678]
diff --git a/gas/testsuite/gas/arc/warn.exp b/gas/testsuite/gas/arc/warn.exp
new file mode 100644
index 0000000000..79ff1263d5
--- /dev/null
+++ b/gas/testsuite/gas/arc/warn.exp
@@ -0,0 +1,13 @@
+# Test assembler warnings.
+
+if [istarget arc*-*-*] {
+
+ load_lib gas-dg.exp
+
+ dg-init
+
+ dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/warn*.s]] "" ""
+
+ dg-finish
+
+}
diff --git a/gas/testsuite/gas/arc/warn.s b/gas/testsuite/gas/arc/warn.s
new file mode 100644
index 0000000000..6fcb43725f
--- /dev/null
+++ b/gas/testsuite/gas/arc/warn.s
@@ -0,0 +1,14 @@
+; Test ARC specific assembler warnings
+;
+; { dg-do assemble { target arc-*-* } }
+
+ b.d foo
+ mov r0,256 ; { dg-warning "8 byte instruction in delay slot" "8 byte insn in delay slot" }
+
+ j.d foo ; { dg-warning "8 byte jump instruction with delay slot" "8 byte jump with delay slot" }
+ mov r0,r1
+
+ sub.f 0,r0,r2
+ beq foo ; { dg-warning "conditional branch follows set of flags" "cc set/branch nop test" }
+
+foo:
diff --git a/gas/testsuite/gas/arm/arch4t.s b/gas/testsuite/gas/arm/arch4t.s
new file mode 100644
index 0000000000..8d28f7f3ec
--- /dev/null
+++ b/gas/testsuite/gas/arm/arch4t.s
@@ -0,0 +1,21 @@
+.text
+.align 0
+
+ bx r0
+ bxeq r1
+
+foo:
+ ldrh r3, foo
+ ldrsh r4, [r5]
+ ldrsb r4, [r1, r3]
+ ldrsh r1, [r4, r4]!
+ ldreqsb r1, [r5, -r3]
+ ldrneh r2, [r6], r7
+ ldrccsh r2, [r7], +r8
+ ldrsb r2, [r3, #255]
+ ldrsh r1, [r4, #-250]
+ ldrsb r1, [r5, #+240]
+
+ strh r2, bar
+ strneh r3, [r3]
+bar:
diff --git a/gas/testsuite/gas/arm/arm.exp b/gas/testsuite/gas/arm/arm.exp
new file mode 100644
index 0000000000..f21c54df31
--- /dev/null
+++ b/gas/testsuite/gas/arm/arm.exp
@@ -0,0 +1,34 @@
+#
+# Some ARM tests
+#
+if [istarget arm-*-*] then {
+ run_dump_test "inst"
+
+ gas_test "arm3.s" "" $stdoptlist "Arm 3 instructions"
+
+ gas_test "arm6.s" "" $stdoptlist "Arm 6 instructions"
+
+ gas_test "arm7dm.s" "" $stdoptlist "Arm 7DM instructions"
+
+ run_dump_test "arm7t"
+
+ gas_test "thumb.s" "" $stdoptlist "Thumb instructions"
+
+ gas_test "arch4t.s" "" $stdoptlist "Arm architecture 4t instructions"
+
+ gas_test "copro.s" "" $stdoptlist "Co processor instructions"
+
+ gas_test "immed.s" "" $stdoptlist "immediate expressions"
+
+ gas_test "float.s" "" $stdoptlist "Core floating point instructions"
+}
+
+# Not all arm targets are bi-endian, so only run this test on ones
+# we know that are. FIXME: We should probably also key off armeb/armel.
+
+if [istarget arm-*-pe] {
+ run_dump_test "le-fpconst"
+
+ # Since big-endian numbers have the normal format, this doesn't exist.
+ #run_dump_test "be-fpconst"
+}
diff --git a/gas/testsuite/gas/arm/arm3.s b/gas/testsuite/gas/arm/arm3.s
new file mode 100644
index 0000000000..ebcf915ccb
--- /dev/null
+++ b/gas/testsuite/gas/arm/arm3.s
@@ -0,0 +1,6 @@
+.text
+.align 0
+ swp r0, r1, [r8]
+ swpb r2, r3, [r3]
+ swpgeb r4, r1, [r4]
+
diff --git a/gas/testsuite/gas/arm/arm6.s b/gas/testsuite/gas/arm/arm6.s
new file mode 100644
index 0000000000..4b517129c6
--- /dev/null
+++ b/gas/testsuite/gas/arm/arm6.s
@@ -0,0 +1,12 @@
+.text
+.align 0
+
+ mrs r8, cpsr
+ mrseq r9, cpsr_all
+ mrs r2, spsr
+
+ msr cpsr, r1
+ msrne cpsr_flg, #0xf0000000
+ msr spsr_flg, r8
+ msr spsr_all, r9
+
diff --git a/gas/testsuite/gas/arm/arm7dm.s b/gas/testsuite/gas/arm/arm7dm.s
new file mode 100644
index 0000000000..7496c70e98
--- /dev/null
+++ b/gas/testsuite/gas/arm/arm7dm.s
@@ -0,0 +1,12 @@
+.text
+.align 0
+
+ smull r0, r1, r2, r3
+ umull r0, r1, r2, r3
+ smlal r0, r1, r2, r3
+ umlal r0, r1, r4, r3
+
+ smullne r0, r1, r3, r4
+ smulls r1, r0, r9, r11
+ umlaleqs r2, r9, r4, r9
+ smlalge r14, r10, r8, r14
diff --git a/gas/testsuite/gas/arm/arm7t.d b/gas/testsuite/gas/arm/arm7t.d
new file mode 100644
index 0000000000..143a161cd2
--- /dev/null
+++ b/gas/testsuite/gas/arm/arm7t.d
@@ -0,0 +1,68 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: ARM arm7t
+#as: -marm7t -EL
+
+# Test the halfword and signextend memory transfers:
+
+.*: +file format .*arm.*
+
+Disassembly of section .text:
+00000000 <[^>]*> e1d100b0 ? ldrh r0, \[r1\]
+00000004 <[^>]*> e1f100b0 ? ldrh r0, \[r1\]!
+00000008 <[^>]*> e19100b2 ? ldrh r0, \[r1, r2\]
+0000000c <[^>]*> e1b100b2 ? ldrh r0, \[r1, r2\]!
+00000010 <[^>]*> e1d100bc ? ldrh r0, \[r1, #12\]
+00000014 <[^>]*> e1f100bc ? ldrh r0, \[r1, #12\]!
+00000018 <[^>]*> e15100bc ? ldrh r0, \[r1, -#12\]
+0000001c <[^>]*> e09100b2 ? ldrh r0, \[r1\], r2
+00000020 <[^>]*> e3a00cff ? mov r0, #65280
+00000024 <[^>]*> e1df0bb4 ? ldrh r0, 000000e0 <\$\$lit_1>
+00000028 <[^>]*> e1df0abc ? ldrh r0, 000000dc <.L2>
+0000002c <[^>]*> e1c100b0 ? strh r0, \[r1\]
+00000030 <[^>]*> e1e100b0 ? strh r0, \[r1\]!
+00000034 <[^>]*> e18100b2 ? strh r0, \[r1, r2\]
+00000038 <[^>]*> e1a100b2 ? strh r0, \[r1, r2\]!
+0000003c <[^>]*> e1c100bc ? strh r0, \[r1, #12\]
+00000040 <[^>]*> e1e100bc ? strh r0, \[r1, #12\]!
+00000044 <[^>]*> e14100bc ? strh r0, \[r1, -#12\]
+00000048 <[^>]*> e08100b2 ? strh r0, \[r1\], r2
+0000004c <[^>]*> e1cf08b8 ? strh r0, 000000dc <.L2>
+00000050 <[^>]*> e1d100d0 ? ldrsb r0, \[r1\]
+00000054 <[^>]*> e1f100d0 ? ldrsb r0, \[r1\]!
+00000058 <[^>]*> e19100d2 ? ldrsb r0, \[r1, r2\]
+0000005c <[^>]*> e1b100d2 ? ldrsb r0, \[r1, r2\]!
+00000060 <[^>]*> e1d100dc ? ldrsb r0, \[r1, #12\]
+00000064 <[^>]*> e1f100dc ? ldrsb r0, \[r1, #12\]!
+00000068 <[^>]*> e15100dc ? ldrsb r0, \[r1, -#12\]
+0000006c <[^>]*> e09100d2 ? ldrsb r0, \[r1\], r2
+00000070 <[^>]*> e3a000de ? mov r0, #222
+00000074 <[^>]*> e1df06d0 ? ldrsb r0, 000000dc <.L2>
+00000078 <[^>]*> e1d100f0 ? ldrsh r0, \[r1\]
+0000007c <[^>]*> e1f100f0 ? ldrsh r0, \[r1\]!
+00000080 <[^>]*> e19100f2 ? ldrsh r0, \[r1, r2\]
+00000084 <[^>]*> e1b100f2 ? ldrsh r0, \[r1, r2\]!
+00000088 <[^>]*> e1d100fc ? ldrsh r0, \[r1, #12\]
+0000008c <[^>]*> e1f100fc ? ldrsh r0, \[r1, #12\]!
+00000090 <[^>]*> e15100fc ? ldrsh r0, \[r1, -#12\]
+00000094 <[^>]*> e09100f2 ? ldrsh r0, \[r1\], r2
+00000098 <[^>]*> e3a00cff ? mov r0, #65280
+0000009c <[^>]*> e1df03fc ? ldrsh r0, 000000e0 <\$\$lit_1>
+000000a0 <[^>]*> e1df03f4 ? ldrsh r0, 000000dc <.L2>
+000000a4 <[^>]*> e19100b2 ? ldrh r0, \[r1, r2\]
+000000a8 <[^>]*> 119100b2 ? ldrneh r0, \[r1, r2\]
+000000ac <[^>]*> 819100b2 ? ldrhih r0, \[r1, r2\]
+000000b0 <[^>]*> b19100b2 ? ldrlth r0, \[r1, r2\]
+000000b4 <[^>]*> e19100f2 ? ldrsh r0, \[r1, r2\]
+000000b8 <[^>]*> 119100f2 ? ldrnesh r0, \[r1, r2\]
+000000bc <[^>]*> 819100f2 ? ldrhish r0, \[r1, r2\]
+000000c0 <[^>]*> b19100f2 ? ldrltsh r0, \[r1, r2\]
+000000c4 <[^>]*> e19100d2 ? ldrsb r0, \[r1, r2\]
+000000c8 <[^>]*> 119100d2 ? ldrnesb r0, \[r1, r2\]
+000000cc <[^>]*> 819100d2 ? ldrhisb r0, \[r1, r2\]
+000000d0 <[^>]*> b19100d2 ? ldrltsb r0, \[r1, r2\]
+000000d4 <[^>]*> e1df00f4 ? ldrsh r0, 000000e0 <\$\$lit_1>
+000000d8 <[^>]*> e1df00f4 ? ldrsh r0, 000000e4 <\$\$lit_1\+0x4>
+000000dc <[^>]*> 00000000 ? andeq r0, r0, r0
+[ ]*dc:.*.LC0
+000000e0 <[^>]*> 0000c0de ? .*
+000000e4 <[^>]*> 0000dead ? .*
diff --git a/gas/testsuite/gas/arm/arm7t.s b/gas/testsuite/gas/arm/arm7t.s
new file mode 100644
index 0000000000..656e90e033
--- /dev/null
+++ b/gas/testsuite/gas/arm/arm7t.s
@@ -0,0 +1,79 @@
+ .section .rdata
+ .align 0
+.LC0:
+ .ascii "some data\000"
+
+ .text
+ .align 0
+
+loadhalfwords:
+ ldrh r0, [r1]
+ ldrh r0, [r1]!
+ ldrh r0, [r1, r2]
+ ldrh r0, [r1, r2]!
+ ldrh r0, [r1,#0x0C]
+ ldrh r0, [r1,#0x0C]!
+ ldrh r0, [r1,#-0x0C]
+ ldrh r0, [r1], r2
+ ldrh r0, =0xFF00
+ ldrh r0, =0xC0DE
+ ldrh r0, .L2
+
+storehalfwords:
+ strh r0, [r1]
+ strh r0, [r1]!
+ strh r0, [r1, r2]
+ strh r0, [r1, r2]!
+ strh r0, [r1,#0x0C]
+ strh r0, [r1,#0x0C]!
+ strh r0, [r1,#-0x0C]
+ strh r0, [r1], r2
+ strh r0, .L2
+
+loadsignedbytes:
+ ldrsb r0, [r1]
+ ldrsb r0, [r1]!
+ ldrsb r0, [r1, r2]
+ ldrsb r0, [r1, r2]!
+ ldrsb r0, [r1,#0x0C]
+ ldrsb r0, [r1,#0x0C]!
+ ldrsb r0, [r1,#-0x0C]
+ ldrsb r0, [r1], r2
+ ldrsb r0, =0xDE
+ ldrsb r0, .L2
+
+loadsignedhalfwords:
+ ldrsh r0, [r1]
+ ldrsh r0, [r1]!
+ ldrsh r0, [r1, r2]
+ ldrsh r0, [r1, r2]!
+ ldrsh r0, [r1, #0x0C]
+ ldrsh r0, [r1, #0x0C]!
+ ldrsh r0, [r1, #-0x0C]
+ ldrsh r0, [r1], r2
+ ldrsh r0, =0xFF00
+ ldrsh r0, =0xC0DE
+ ldrsh r0, .L2
+
+misc:
+ ldralh r0, [r1, r2]
+ ldrneh r0, [r1, r2]
+ ldrhih r0, [r1, r2]
+ ldrlth r0, [r1, r2]
+
+ ldralsh r0, [r1, r2]
+ ldrnesh r0, [r1, r2]
+ ldrhish r0, [r1, r2]
+ ldrltsh r0, [r1, r2]
+
+ ldralsb r0, [r1, r2]
+ ldrnesb r0, [r1, r2]
+ ldrhisb r0, [r1, r2]
+ ldrltsb r0, [r1, r2]
+
+ ldrsh r0, =0xC0DE
+ ldrsh r0, =0xDEAD
+
+ .align
+.L2:
+ .word .LC0
diff --git a/gas/testsuite/gas/arm/copro.s b/gas/testsuite/gas/arm/copro.s
new file mode 100644
index 0000000000..46c9b920df
--- /dev/null
+++ b/gas/testsuite/gas/arm/copro.s
@@ -0,0 +1,24 @@
+.text
+.align 0
+ cdp p1, 4, cr1, cr2, cr3
+ cdpeq 4, 3, c1, c4, cr5, 5
+
+ ldc 5, cr9, [r3]
+ ldcl 1, cr14, [r1, #32]
+ ldcmi 0, cr0, [r2, #1020]!
+ ldcpll p7, c1, [r3], #64
+ ldc p0, c8, foo
+foo:
+
+ stc 5, cr0, [r3]
+ stcl 3, cr15, [r0, #8]
+ stceq p4, cr12, [r2, #100]!
+ stccc p6, c8, [r4], #48
+ stc p1, c7, bar
+bar:
+
+ mrc 2, 3, r5, c1, c2
+ mrcge p4, 5, r15, cr1, cr2, 7
+
+ mcr p7, 1, r15, cr1, cr1
+ mcrlt 5, 1, r8, cr2, cr9, 0
diff --git a/gas/testsuite/gas/arm/float.s b/gas/testsuite/gas/arm/float.s
new file mode 100644
index 0000000000..48aee965cb
--- /dev/null
+++ b/gas/testsuite/gas/arm/float.s
@@ -0,0 +1,162 @@
+.text
+.align 0
+ mvfe f0, f1
+ mvfeqe f3, f5
+ mvfeqd f4, #1.0
+ mvfs f4, f7
+ mvfsp f0, f1
+ mvfdm f3, f4
+ mvfez f7, f7
+
+ adfe f0, f1, #2.0
+ adfeqe f1, f2, #0.5
+ adfsm f3, f4, f5
+
+ sufd f0, f0, #2.0
+ sufs f1, f2, #10.0
+ sufneez f3, f4, f5
+
+ rsfs f1, f1, #0.0
+ rsfdp f3, f0, #5.0
+ rsfled f7, f6, f0
+
+ mufd f0, f0, f0
+ mufez f1, f2, #3.0
+ mufals f0, f0, #4.0
+
+ dvfd f0, f0, #1.0000
+ dvfez f0, f1, #10e0
+ dvfmism f3, f4, f5
+
+ rdfe f0, f1, #1.0e1
+ rdfs f3, f7, #0f1
+ rdfccdp f4, f4, f3
+
+ powd f0, f2, f3
+ pows f1, f3, #0e1e1
+ powcsez f4, f7, #1
+
+ rpws f7, f6, f7
+ rpweqd f0, f1, f2
+ rpwem f2, f2, f3
+
+ rmfd f1, f2, #3
+ rmfvss f3, f4, f4
+ rmfep f4, f7, f0
+
+ fmls f0, f1, f2
+ fmleqs f1, f3, f5
+ fmlplsz f4, f6, f0
+
+ fdvs f1, f3, #10
+ fdvsp f0, f1, f2
+ fdvhssm f4, f4, f4
+
+ frds f1, f1, #1.0
+ frdgts f2, f1, f0
+ frdgtsz f4, f4, f5
+
+ pold f0, f1, f2
+ polsz f4, f6, #3.0
+ poleqe f5, f6, f7
+
+ mnfs f0, f1
+ mnfd f0, #3.0
+ mnfez f0, #4.0
+ mnfeqez f0, f5
+ mnfsp f0, f4
+ mnfdm f1, f7
+
+ absd f0, f1
+ abssp f1, #3.0
+ abseqe f4, f5
+
+ rnds f1, f2
+ rndd f3, f4
+ rndeqez f6, #4.0
+
+ sqts f5, f5
+ sqtdp f6, f6
+ sqtplez f7, f6
+
+ logs f0, #10
+ loge f0, #0f10
+ lognedz f0, f1
+
+ lgne f1, f2
+ lgndz f1, f3
+ lgnvcs f3, f4
+
+ exps f1, f3
+ expem f3, #10.0
+ exppld f6, f7
+
+ sind f0, f1
+ sinsm f1, f2
+ singte f4, #5
+
+ cosd f1, f3
+ cosem f4, f5
+ cosnedp f6, f1
+
+ tane f1, f5
+ tansz f4, f7
+ tangedz f1, #4.0
+
+ asne f4, f5
+ asnsp f6, #5e-1
+ asnmidz f5, f5
+
+ acss f5, f6
+ acsd f6, f0
+ acshsem f1, #0.05e1
+
+ atne f0, f5
+ atnsz f1, #5
+ atnltd f3, f2
+
+ urde f5, f4
+ nrme f6, f5
+ nrmpldz f7, f5
+
+ fltsp f0, r8
+ flte f1, r0
+ flteqdz f5, r7
+
+ fix r0, f1
+ fixz r1, f7
+ fixcsm r5, f5
+
+ wfc r0
+ wfs r1
+ rfseq r2
+ rfc r4
+
+ cmf f0, #1
+ cmf f1, f2
+ cmfeq f0, f1
+
+ cnf f0, #3
+ cnf f1, #0.5
+ cnfvs f3, f4
+
+ cmfe f0, f1
+ cmfeeq f1, f2
+ cmfeqe f3, #5.0
+
+ cnfe f1, f3
+ cnfeeq f3, f4
+ cnfeqe f4, f7
+ cnfale f4, #5.0
+
+ lfm f0, 4, [r0]
+ lfm f0, 4, [r0, #0]
+ lfm f1, 4, [r1, #64]
+ sfm f2, 4, [r14, #1020]!
+ sfmeq f7, 3, [r8], #-1020
+
+ lfmfd f6, 2, [r15]
+ sfmea f7, 1, [r8]!
+ lfmeqea f5, 4, [r6]
+ sfmnefd f4, 3, [r2]
+ sfmnefd f4, 3, [r2]!
diff --git a/gas/testsuite/gas/arm/immed.s b/gas/testsuite/gas/arm/immed.s
new file mode 100644
index 0000000000..5d2092be18
--- /dev/null
+++ b/gas/testsuite/gas/arm/immed.s
@@ -0,0 +1,11 @@
+@ Tests for complex immediate expressions - none of these need
+@ relocations
+ .text
+bar:
+ mov r0, #0
+ mov r0, #(. - bar - 8)
+ ldr r0, bar
+ ldr r0, [pc, # (bar - . -8)]
+ .space 4096
+ mov r0, #(. - bar - 8) & 0xff
+ ldr r0, [pc, # (bar - . -8) & 0xff]
diff --git a/gas/testsuite/gas/arm/inst.d b/gas/testsuite/gas/arm/inst.d
new file mode 100644
index 0000000000..decb8f01b7
--- /dev/null
+++ b/gas/testsuite/gas/arm/inst.d
@@ -0,0 +1,168 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: ARM basic instructions
+#as: -marm2 -EL
+
+# Test the standard ARM instructions:
+
+.*: +file format .*arm.*
+
+Disassembly of section .text:
+00000000 <[^>]*> e3a00000 ? mov r0, #0
+00000004 <[^>]*> e1a01002 ? mov r1, r2
+00000008 <[^>]*> e1a03184 ? mov r3, r4, lsl #3
+0000000c <[^>]*> e1a05736 ? mov r5, r6, lsr r7
+00000010 <[^>]*> e1a08a59 ? mov r8, r9, asr sl
+00000014 <[^>]*> e1a0bd1c ? mov fp, ip, lsl sp
+00000018 <[^>]*> e1a0e06f ? mov lr, pc, rrx
+0000001c <[^>]*> e1a01002 ? mov r1, r2
+00000020 <[^>]*> 01a02003 ? moveq r2, r3
+00000024 <[^>]*> 11a04005 ? movne r4, r5
+00000028 <[^>]*> b1a06007 ? movlt r6, r7
+0000002c <[^>]*> a1a08009 ? movge r8, r9
+00000030 <[^>]*> d1a0a00b ? movle sl, fp
+00000034 <[^>]*> c1a0c00d ? movgt ip, sp
+00000038 <[^>]*> 31a01002 ? movcc r1, r2
+0000003c <[^>]*> 21a01003 ? movcs r1, r3
+00000040 <[^>]*> 41a03006 ? movmi r3, r6
+00000044 <[^>]*> 51a07009 ? movpl r7, r9
+00000048 <[^>]*> 61a01008 ? movvs r1, r8
+0000004c <[^>]*> 71a09fa1 ? movvc r9, r1, lsr #31
+00000050 <[^>]*> 81a0800f ? movhi r8, pc
+00000054 <[^>]*> 91a0f00e ? movls pc, lr
+00000058 <[^>]*> 21a09008 ? movcs r9, r8
+0000005c <[^>]*> 31a01003 ? movcc r1, r3
+00000060 <[^>]*> e1b00008 ? movs r0, r8
+00000064 <[^>]*> 31b00007 ? movccs r0, r7
+00000068 <[^>]*> e281000a ? add r0, r1, #10
+0000006c <[^>]*> e0832004 ? add r2, r3, r4
+00000070 <[^>]*> e0865287 ? add r5, r6, r7, lsl #5
+00000074 <[^>]*> e0821113 ? add r1, r2, r3, lsl r1
+00000078 <[^>]*> e201000a ? and r0, r1, #10
+0000007c <[^>]*> e0032004 ? and r2, r3, r4
+00000080 <[^>]*> e0065287 ? and r5, r6, r7, lsl #5
+00000084 <[^>]*> e0021113 ? and r1, r2, r3, lsl r1
+00000088 <[^>]*> e221000a ? eor r0, r1, #10
+0000008c <[^>]*> e0232004 ? eor r2, r3, r4
+00000090 <[^>]*> e0265287 ? eor r5, r6, r7, lsl #5
+00000094 <[^>]*> e0221113 ? eor r1, r2, r3, lsl r1
+00000098 <[^>]*> e241000a ? sub r0, r1, #10
+0000009c <[^>]*> e0432004 ? sub r2, r3, r4
+000000a0 <[^>]*> e0465287 ? sub r5, r6, r7, lsl #5
+000000a4 <[^>]*> e0421113 ? sub r1, r2, r3, lsl r1
+000000a8 <[^>]*> e2a1000a ? adc r0, r1, #10
+000000ac <[^>]*> e0a32004 ? adc r2, r3, r4
+000000b0 <[^>]*> e0a65287 ? adc r5, r6, r7, lsl #5
+000000b4 <[^>]*> e0a21113 ? adc r1, r2, r3, lsl r1
+000000b8 <[^>]*> e2c1000a ? sbc r0, r1, #10
+000000bc <[^>]*> e0c32004 ? sbc r2, r3, r4
+000000c0 <[^>]*> e0c65287 ? sbc r5, r6, r7, lsl #5
+000000c4 <[^>]*> e0c21113 ? sbc r1, r2, r3, lsl r1
+000000c8 <[^>]*> e261000a ? rsb r0, r1, #10
+000000cc <[^>]*> e0632004 ? rsb r2, r3, r4
+000000d0 <[^>]*> e0665287 ? rsb r5, r6, r7, lsl #5
+000000d4 <[^>]*> e0621113 ? rsb r1, r2, r3, lsl r1
+000000d8 <[^>]*> e2e1000a ? rsc r0, r1, #10
+000000dc <[^>]*> e0e32004 ? rsc r2, r3, r4
+000000e0 <[^>]*> e0e65287 ? rsc r5, r6, r7, lsl #5
+000000e4 <[^>]*> e0e21113 ? rsc r1, r2, r3, lsl r1
+000000e8 <[^>]*> e381000a ? orr r0, r1, #10
+000000ec <[^>]*> e1832004 ? orr r2, r3, r4
+000000f0 <[^>]*> e1865287 ? orr r5, r6, r7, lsl #5
+000000f4 <[^>]*> e1821113 ? orr r1, r2, r3, lsl r1
+000000f8 <[^>]*> e3c1000a ? bic r0, r1, #10
+000000fc <[^>]*> e1c32004 ? bic r2, r3, r4
+00000100 <[^>]*> e1c65287 ? bic r5, r6, r7, lsl #5
+00000104 <[^>]*> e1c21113 ? bic r1, r2, r3, lsl r1
+00000108 <[^>]*> e3e0000a ? mvn r0, #10
+0000010c <[^>]*> e1e02004 ? mvn r2, r4
+00000110 <[^>]*> e1e05287 ? mvn r5, r7, lsl #5
+00000114 <[^>]*> e1e01113 ? mvn r1, r3, lsl r1
+00000118 <[^>]*> e310000a ? tst r0, #10
+0000011c <[^>]*> e1120004 ? tst r2, r4
+00000120 <[^>]*> e1150287 ? tst r5, r7, lsl #5
+00000124 <[^>]*> e1110113 ? tst r1, r3, lsl r1
+00000128 <[^>]*> e330000a ? teq r0, #10
+0000012c <[^>]*> e1320004 ? teq r2, r4
+00000130 <[^>]*> e1350287 ? teq r5, r7, lsl #5
+00000134 <[^>]*> e1310113 ? teq r1, r3, lsl r1
+00000138 <[^>]*> e350000a ? cmp r0, #10
+0000013c <[^>]*> e1520004 ? cmp r2, r4
+00000140 <[^>]*> e1550287 ? cmp r5, r7, lsl #5
+00000144 <[^>]*> e1510113 ? cmp r1, r3, lsl r1
+00000148 <[^>]*> e370000a ? cmn r0, #10
+0000014c <[^>]*> e1720004 ? cmn r2, r4
+00000150 <[^>]*> e1750287 ? cmn r5, r7, lsl #5
+00000154 <[^>]*> e1710113 ? cmn r1, r3, lsl r1
+00000158 <[^>]*> e330f00a ? teqp r0, #10
+0000015c <[^>]*> e132f004 ? teqp r2, r4
+00000160 <[^>]*> e135f287 ? teqp r5, r7, lsl #5
+00000164 <[^>]*> e131f113 ? teqp r1, r3, lsl r1
+00000168 <[^>]*> e370f00a ? cmnp r0, #10
+0000016c <[^>]*> e172f004 ? cmnp r2, r4
+00000170 <[^>]*> e175f287 ? cmnp r5, r7, lsl #5
+00000174 <[^>]*> e171f113 ? cmnp r1, r3, lsl r1
+00000178 <[^>]*> e350f00a ? cmpp r0, #10
+0000017c <[^>]*> e152f004 ? cmpp r2, r4
+00000180 <[^>]*> e155f287 ? cmpp r5, r7, lsl #5
+00000184 <[^>]*> e151f113 ? cmpp r1, r3, lsl r1
+00000188 <[^>]*> e310f00a ? tstp r0, #10
+0000018c <[^>]*> e112f004 ? tstp r2, r4
+00000190 <[^>]*> e115f287 ? tstp r5, r7, lsl #5
+00000194 <[^>]*> e111f113 ? tstp r1, r3, lsl r1
+00000198 <[^>]*> e0000291 ? mul r0, r1, r2
+0000019c <[^>]*> e0110392 ? muls r1, r2, r3
+000001a0 <[^>]*> 10000091 ? mulne r0, r1, r0
+000001a4 <[^>]*> 90190798 ? mullss r9, r8, r7
+000001a8 <[^>]*> e021ba99 ? mla r1, r9, sl, fp
+000001ac <[^>]*> e033c994 ? mlas r3, r4, r9, ip
+000001b0 <[^>]*> b029d798 ? mlalt r9, r8, r7, sp
+000001b4 <[^>]*> a034e391 ? mlages r4, r1, r3, lr
+000001b8 <[^>]*> e5910000 ? ldr r0, \[r1\]
+000001bc <[^>]*> e7911002 ? ldr r1, \[r1, r2\]
+000001c0 <[^>]*> e7b32004 ? ldr r2, \[r3, r4\]!
+000001c4 <[^>]*> e5922020 ? ldr r2, \[r2, #32\]
+000001c8 <[^>]*> e7932424 ? ldr r2, \[r3, r4, lsr #8\]
+000001cc <[^>]*> 07b54484 ? ldreq r4, \[r5, r4, lsl #9\]!
+000001d0 <[^>]*> 14954006 ? ldrne r4, \[r5\], #6
+000001d4 <[^>]*> e6b21003 ? ldrt r1, \[r2\], r3
+000001d8 <[^>]*> e6942425 ? ldr r2, \[r4\], r5, lsr #8
+000001dc <[^>]*> e51f0008 ? ldr r0, 000001dc <[^>]*>
+000001e0 <[^>]*> e5d43000 ? ldrb r3, \[r4\]
+000001e4 <[^>]*> 14f85000 ? ldrnebt r5, \[r8\]
+000001e8 <[^>]*> e5810000 ? str r0, \[r1\]
+000001ec <[^>]*> e7811002 ? str r1, \[r1, r2\]
+000001f0 <[^>]*> e7a33004 ? str r3, \[r3, r4\]!
+000001f4 <[^>]*> e5822020 ? str r2, \[r2, #32\]
+000001f8 <[^>]*> e7832424 ? str r2, \[r3, r4, lsr #8\]
+000001fc <[^>]*> 07a54484 ? streq r4, \[r5, r4, lsl #9\]!
+00000200 <[^>]*> 14854006 ? strne r4, \[r5\], #6
+00000204 <[^>]*> e6821003 ? str r1, \[r2\], r3
+00000208 <[^>]*> e6a42425 ? strt r2, \[r4\], r5, lsr #8
+0000020c <[^>]*> e50f1004 ? str r1, 00000210 <[^>]*>
+00000210 <[^>]*> e5c71000 ? strb r1, \[r7\]
+00000214 <[^>]*> e4e02000 ? strbt r2, \[r0\]
+00000218 <[^>]*> e8900002 ? ldmia r0, {r1}
+0000021c <[^>]*> 09920038 ? ldmeqib r2, {r3, r4, r5}
+00000220 <[^>]*> e853ffff ? ldmda r3, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, sp, lr, pc}\^
+00000224 <[^>]*> e93b05ff ? ldmdb fp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, sl}
+00000228 <[^>]*> e99100f7 ? ldmib r1, {r0, r1, r2, r4, r5, r6, r7}
+0000022c <[^>]*> e89201f8 ? ldmia r2, {r3, r4, r5, r6, r7, r8}
+00000230 <[^>]*> e9130003 ? ldmdb r3, {r0, r1}
+00000234 <[^>]*> e8740300 ? ldmda r4!, {r8, r9}\^
+00000238 <[^>]*> e8800002 ? stmia r0, {r1}
+0000023c <[^>]*> 09820038 ? stmeqib r2, {r3, r4, r5}
+00000240 <[^>]*> e843ffff ? stmda r3, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, sp, lr, pc}\^
+00000244 <[^>]*> e92a05ff ? stmdb sl!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, sl}
+00000248 <[^>]*> e8010007 ? stmda r1, {r0, r1, r2}
+0000024c <[^>]*> e9020018 ? stmdb r2, {r3, r4}
+00000250 <[^>]*> e8830003 ? stmia r3, {r0, r1}
+00000254 <[^>]*> e9e40300 ? stmib r4!, {r8, r9}\^
+00000258 <[^>]*> ef123456 ? swi 0x00123456
+0000025c <[^>]*> 2f000033 ? swics 0x00000033
+00000260 <[^>]*> ebfffffe ? bl 00000260 <[^>]*>
+[ ]*260:.*_wombat.*
+00000264 <[^>]*> 5bffffe9 ? blpl 00000210 <bar>
+00000268 <[^>]*> eafffffe ? b 00000268 <[^>]*>
+[ ]*268:.*_wibble.*
+0000026c <[^>]*> dafffffe ? ble 0000026c <[^>]*>
+[ ]*26c:.*testerfunc.*
diff --git a/gas/testsuite/gas/arm/inst.s b/gas/testsuite/gas/arm/inst.s
new file mode 100644
index 0000000000..ff092c9256
--- /dev/null
+++ b/gas/testsuite/gas/arm/inst.s
@@ -0,0 +1,189 @@
+@ Test file for ARM/GAS -- basic instructions
+
+.text
+.align
+ mov r0, #0
+ mov r1, r2
+ mov r3, r4, lsl #3
+ mov r5, r6, lsr r7
+ mov r8, r9, asr r10
+ mov r11, r12, asl r13
+ mov r14, r15, rrx
+ moval r1, r2
+ moveq r2, r3
+ movne r4, r5
+ movlt r6, r7
+ movge r8, r9
+ movle r10, r11
+ movgt r12, r13
+ movcc r1, r2
+ movcs r1, r3
+ movmi r3, r6
+ movpl r7, r9
+ movvs r1, r8
+ movvc r9, r1, lsr #31
+ movhi r8, r15
+ movls r15, r14
+ movhs r9, r8
+ movul r1, r3
+ movs r0, r8
+ movuls r0, r7
+
+ add r0, r1, #10
+ add r2, r3, r4
+ add r5, r6, r7, asl #5
+ add r1, r2, r3, lsl r1
+
+ and r0, r1, #10
+ and r2, r3, r4
+ and r5, r6, r7, asl #5
+ and r1, r2, r3, lsl r1
+
+ eor r0, r1, #10
+ eor r2, r3, r4
+ eor r5, r6, r7, asl #5
+ eor r1, r2, r3, lsl r1
+
+ sub r0, r1, #10
+ sub r2, r3, r4
+ sub r5, r6, r7, asl #5
+ sub r1, r2, r3, lsl r1
+
+ adc r0, r1, #10
+ adc r2, r3, r4
+ adc r5, r6, r7, asl #5
+ adc r1, r2, r3, lsl r1
+
+ sbc r0, r1, #10
+ sbc r2, r3, r4
+ sbc r5, r6, r7, asl #5
+ sbc r1, r2, r3, lsl r1
+
+ rsb r0, r1, #10
+ rsb r2, r3, r4
+ rsb r5, r6, r7, asl #5
+ rsb r1, r2, r3, lsl r1
+
+ rsc r0, r1, #10
+ rsc r2, r3, r4
+ rsc r5, r6, r7, asl #5
+ rsc r1, r2, r3, lsl r1
+
+ orr r0, r1, #10
+ orr r2, r3, r4
+ orr r5, r6, r7, asl #5
+ orr r1, r2, r3, lsl r1
+
+ bic r0, r1, #10
+ bic r2, r3, r4
+ bic r5, r6, r7, asl #5
+ bic r1, r2, r3, lsl r1
+
+ mvn r0, #10
+ mvn r2, r4
+ mvn r5, r7, asl #5
+ mvn r1, r3, lsl r1
+
+ tst r0, #10
+ tst r2, r4
+ tst r5, r7, asl #5
+ tst r1, r3, lsl r1
+
+ teq r0, #10
+ teq r2, r4
+ teq r5, r7, asl #5
+ teq r1, r3, lsl r1
+
+ cmp r0, #10
+ cmp r2, r4
+ cmp r5, r7, asl #5
+ cmp r1, r3, lsl r1
+
+ cmn r0, #10
+ cmn r2, r4
+ cmn r5, r7, asl #5
+ cmn r1, r3, lsl r1
+
+ teqp r0, #10
+ teqp r2, r4
+ teqp r5, r7, asl #5
+ teqp r1, r3, lsl r1
+
+ cmnp r0, #10
+ cmnp r2, r4
+ cmnp r5, r7, asl #5
+ cmnp r1, r3, lsl r1
+
+ cmpp r0, #10
+ cmpp r2, r4
+ cmpp r5, r7, asl #5
+ cmpp r1, r3, lsl r1
+
+ tstp r0, #10
+ tstp r2, r4
+ tstp r5, r7, asl #5
+ tstp r1, r3, lsl r1
+
+ mul r0, r1, r2
+ muls r1, r2, r3
+ mulne r0, r1, r0
+ mullss r9, r8, r7
+
+ mla r1, r9, r10, r11
+ mlas r3, r4, r9, r12
+ mlalt r9, r8, r7, r13
+ mlages r4, r1, r3, r14
+
+ ldr r0, [r1]
+ ldr r1, [r1, r2]
+ ldr r2, [r3, r4]!
+ ldr r2, [r2, #32]
+ ldr r2, [r3, r4, lsr #8]
+ ldreq r4, [r5, r4, asl #9]!
+ ldrne r4, [r5], #6
+ ldrt r1, [r2], r3
+ ldr r2, [r4], r5, lsr #8
+foo:
+ ldr r0, foo
+ ldrb r3, [r4]
+ ldrnebt r5, [r8]
+
+ str r0, [r1]
+ str r1, [r1, r2]
+ str r3, [r3, r4]!
+ str r2, [r2, #32]
+ str r2, [r3, r4, lsr #8]
+ streq r4, [r5, r4, asl #9]!
+ strne r4, [r5], #6
+ str r1, [r2], r3
+ strt r2, [r4], r5, lsr #8
+ str r1, bar
+bar:
+ stralb r1, [r7]
+ strbt r2, [r0]
+
+ ldmia r0, {r1}
+ ldmeqib r2, {r3, r4, r5}
+ ldmalda r3, {r0-r15}^
+ ldmdb r11!, {r0-r8, r10}
+ ldmed r1, {r0, r1, r2}|0xf0
+ ldmfd r2, {r3, r4}+{r5, r6, r7, r8}
+ ldmea r3, 3
+ ldmfa r4!, {r8, r9}^
+
+ stmia r0, {r1}
+ stmeqib r2, {r3, r4, r5}
+ stmalda r3, {r0-r15}^
+ stmdb r10!, {r0-r8, r10}
+ stmed r1, {r0, r1, r2}
+ stmfd r2, {r3, r4}
+ stmea r3, 3
+ stmfa r4!, {r8, r9}^
+
+ swi 0x123456
+ swihs 0x33
+
+ bl _wombat
+ blpl bar
+ b _wibble
+ ble testerfunc
diff --git a/gas/testsuite/gas/arm/le-fpconst.d b/gas/testsuite/gas/arm/le-fpconst.d
new file mode 100644
index 0000000000..354e0e0c9f
--- /dev/null
+++ b/gas/testsuite/gas/arm/le-fpconst.d
@@ -0,0 +1,8 @@
+#objdump: -s
+#as: -EL
+#name: arm little-endian fpconst
+
+.*: +file format .*arm.*
+
+Contents of section .text:
+ 0000 cdcc8c3f 00000000 9999f13f 9a999999 .*
diff --git a/gas/testsuite/gas/arm/le-fpconst.s b/gas/testsuite/gas/arm/le-fpconst.s
new file mode 100644
index 0000000000..8a3c3d7014
--- /dev/null
+++ b/gas/testsuite/gas/arm/le-fpconst.s
@@ -0,0 +1,8 @@
+# Test fp constants.
+# These need ARM specific support because 8 byte fp constants in little
+# endian mode are represented abnormally.
+
+ .text
+ .float 1.1
+ .float 0
+ .double 1.1
diff --git a/gas/testsuite/gas/arm/thumb.s b/gas/testsuite/gas/arm/thumb.s
new file mode 100644
index 0000000000..ea4b82d143
--- /dev/null
+++ b/gas/testsuite/gas/arm/thumb.s
@@ -0,0 +1,193 @@
+ .text
+ .code 16
+.foo:
+ lsl r2, r1, #3
+ lsr r3, r4, #31
+wibble/data:
+ asr r7, r0, #5
+
+ lsl r1, r2, #0
+ lsr r3, r4, #0
+ asr r4, r5, #0
+
+ lsr r6, r7, #32
+ asr r0, r1, #32
+
+ add r1, r2, r3
+ add r2, r4, #2
+ sub r3, r5, r7
+ sub r2, r4, #7
+
+ mov r4, #255
+ cmp r3, #250
+ add r6, #123
+ sub r5, #128
+
+ and r3, r5
+ eor r4, r6
+ lsl r1, r0
+ lsr r2, r3
+ asr r4, r6
+ adc r5, r7
+ sbc r0, r4
+ ror r1, r4
+ tst r2, r5
+ neg r1, r1
+ cmp r2, r3
+ cmn r1, r4
+ orr r0, r3
+ mul r4, r5
+ bic r5, r7
+ mvn r5, r5
+
+ add r1, r13
+ add r12, r2
+ add r9, r9
+ cmp r1, r14
+ cmp r8, r0
+ cmp r12, r14
+ mov r0, r9
+ mov r9, r4
+ mov r8, r8
+ bx r7
+ bx r8
+ .align 0
+ bx pc
+
+ ldr r3, [pc, #128]
+ ldr r4, bar
+
+ str r0, [r1, r2]
+ strb r1, [r2, r4]
+ ldr r5, [r6, r7]
+ ldrb r2, [r4, r5]
+
+ .align 0
+bar:
+ strh r1, [r2, r3]
+ ldrh r3, [r4, r0]
+ ldsb r1, [r6, r7]
+ ldsh r2, [r0, r5]
+
+ str r3, [r3, #124]
+ ldr r1, [r4, #124]
+ ldr r5, [r5]
+ strb r1, [r5, #31]
+ strb r1, [r4, #5]
+ strb r2, [r6]
+
+ strh r4, [r5, #62]
+ ldrh r5, [r0, #4]
+ ldrh r3, [r2]
+
+ str r3, [r13, #1020]
+ ldr r1, [r13, #44]
+ ldr r2, [r13]
+
+ add r7, r15, #1020
+ add r4, r13, #512
+
+ add r13, #268
+ add r13, #-104
+ sub r13, #268
+ sub r13, #-108
+
+ push {r0, r1, r2, r4}
+ push {r0, r3-r7, lr}
+ pop {r3, r4, r7}
+ pop {r0-r7, r15}
+
+ stmia r3!, {r0, r1, r4-r7}
+ ldmia r0!, {r1-r7}
+
+ beq bar
+ bne bar
+ bcs bar
+ bcc bar
+ bmi bar
+ bpl bar
+ bvs bar
+ bvc bar
+ bhi bar
+ bls bar
+ bge bar
+ bgt bar
+ blt bar
+ bgt bar
+ ble bar
+ bhi bar
+ blo bar
+ bul bar
+
+close:
+ lsl r4, r5, #near - close
+near:
+ add r2, r3, #near - close
+
+ add sp, sp, #127 << 2
+ sub sp, sp, #127 << 2
+ add r0, sp, #255 << 2
+ add r0, pc, #255 << 2
+
+ add sp, sp, #bar - .foo
+ sub sp, sp, #bar - .foo
+ add r0, sp, #bar - .foo
+ add r0, pc, #bar - .foo
+
+ add r1, #bar - .foo
+ mov r6, #bar - .foo
+ cmp r7, #bar - .foo
+
+ nop
+ nop
+
+ .arm
+.localbar:
+ b .localbar
+ b .wombat
+ bl .localbar
+ bl .wombat
+
+ bx r0
+ swi 0x123456
+
+ .thumb
+ @ The following will be disassembled incorrectly if we do not
+ @ have a Thumb symbol defined before the first Thumb instruction:
+morethumb:
+ adr r0, forwardonly
+
+ b .foo
+ b .wombat
+ bl .foo
+ bl .wombat
+
+ bx r0
+
+ swi 0xff
+ .align 0
+forwardonly:
+ beq .wombat
+ bne .wombat
+ bcs .wombat
+ bcc .wombat
+ bmi .wombat
+ bpl .wombat
+ bvs .wombat
+ bvc .wombat
+ bhi .wombat
+ bls .wombat
+ bge .wombat
+ bgt .wombat
+ blt .wombat
+ bgt .wombat
+ ble .wombat
+ bhi .wombat
+ blo .wombat
+ bul .wombat
+
+.back:
+ bl .local
+ .space (1 << 11) @ leave space to force long offsets
+.local:
+ bl .back
diff --git a/gas/testsuite/gas/d30v/align.d b/gas/testsuite/gas/d30v/align.d
new file mode 100644
index 0000000000..466768f5dc
--- /dev/null
+++ b/gas/testsuite/gas/d30v/align.d
@@ -0,0 +1,17 @@
+#objdump: -dr
+#name: D30V alignment test
+#as:
+
+.*: +file format elf32-d30v
+
+Disassembly of section .text:
+
+0+0000 <start>:
+ 0: 08815a80 00f00000 abs r21, r42 || nop
+ 8: 08815a80 00f00000 abs r21, r42 || nop
+ 10: 08815a80 00f00000 abs r21, r42 || nop
+ 18: 00f00000 00f00000 abs r21, r42 || nop
+ 20: 08815a80 00f00000 abs r21, r42 || nop
+ 28: 08815a80 00f00000 abs r21, r42 || nop
+ 30: 08815a80 00f00000 abs r21, r42 || nop
+ ...
diff --git a/gas/testsuite/gas/d30v/align.s b/gas/testsuite/gas/d30v/align.s
new file mode 100644
index 0000000000..ef0039c694
--- /dev/null
+++ b/gas/testsuite/gas/d30v/align.s
@@ -0,0 +1,28 @@
+# tests proper handling of aligns on D30V
+
+ .text
+ .align 3
+start:
+ abs r21,r42
+ .align 3
+ abs r21,r42
+ .align 4
+ abs r21,r42
+ .align 4
+ abs r21,r42
+
+ .data
+ .long 0xdeadbeef
+
+ .text
+ abs r21,r42
+
+ .data
+ .align 4
+ .long 0xdeadbeef
+
+ .text
+ .align 3
+ abs r21,r42
+ .end
+
diff --git a/gas/testsuite/gas/d30v/array.d b/gas/testsuite/gas/d30v/array.d
new file mode 100644
index 0000000000..e81bc3394e
--- /dev/null
+++ b/gas/testsuite/gas/d30v/array.d
@@ -0,0 +1,31 @@
+#objdump: -dr
+#name: D30V array test
+#as:
+
+.*: +file format elf32-d30v
+
+Disassembly of section .text:
+
+0+0000 <__foo-0x48>:
+ 0: 880820c0 80000048 add.l r2, r3, 0x48
+ 0: R_D30V_32 .text
+ 8: 880820c0 80000049 add.l r2, r3, 0x49
+ 8: R_D30V_32 .text
+ 10: 880820c0 8000004a add.l r2, r3, 0x4a
+ 10: R_D30V_32 .text
+ 18: 880820c0 8000004b add.l r2, r3, 0x4b
+ 18: R_D30V_32 .text
+ 20: 880820c0 8000004c add.l r2, r3, 0x4c
+ 20: R_D30V_32 .text
+ 28: 880820c0 8000004d add.l r2, r3, 0x4d
+ 28: R_D30V_32 .text
+ 30: 880820c0 8000004e add.l r2, r3, 0x4e
+ 30: R_D30V_32 .text
+ 38: 880820c0 8000004f add.l r2, r3, 0x4f
+ 38: R_D30V_32 .text
+ 40: 880820c0 80000050 add.l r2, r3, 0x50
+ 40: R_D30V_32 .text
+
+0+0048 <__foo>:
+ 48: 12345678 12345678 .long 0x12345678 || .long 0x12345678
+ 50: 12345678 00000000 .long 0x12345678 || bra.s r0
diff --git a/gas/testsuite/gas/d30v/array.s b/gas/testsuite/gas/d30v/array.s
new file mode 100644
index 0000000000..3a187dd5af
--- /dev/null
+++ b/gas/testsuite/gas/d30v/array.s
@@ -0,0 +1,15 @@
+# D30V array test
+ .text
+ add r2, r3 , __foo
+ add r2, r3 , __foo+1
+ add r2, r3 , __foo+2
+ add r2, r3 , __foo+3
+ add r2, r3 , __foo+4
+ add r2, r3 , __foo+5
+ add r2, r3 , __foo+6
+ add r2, r3 , __foo+7
+ add r2, r3 , __foo+8
+__foo:
+ .int 0x12345678
+ .int 0x12345678
+ .int 0x12345678
diff --git a/gas/testsuite/gas/d30v/bittest.d b/gas/testsuite/gas/d30v/bittest.d
new file mode 100644
index 0000000000..b96ab46cb8
--- /dev/null
+++ b/gas/testsuite/gas/d30v/bittest.d
@@ -0,0 +1,20 @@
+#objdump: -dr
+#name: D30V bittest opt
+#as: -WO
+
+.*: +file format elf32-d30v
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 00f00000 84401083 nop -> ldw.s r1, @\(r2, r3\)
+ 8: 04406144 00f00000 ldw.s r6, @\(r5, r4\) || nop
+ 10: 00f00000 82201083 nop -> bset r1, r2, r3
+ 18: 80f00000 02001083 nop <- btst f1, r2, r3
+ 20: 00f00000 02301083 nop || bclr r1, r2, r3
+ 28: 00f00000 82101083 nop -> bnot r1, r2, r3
+ 30: 02101083 80f00000 bnot r1, r2, r3 -> nop
+ 38: 047c0105 02201083 moddec r4, 0x5 || bset r1, r2, r3
+ 40: 02201083 847c0105 bset r1, r2, r3 -> moddec r4, 0x5
+ 48: 02201083 08c04146 bset r1, r2, r3 || joinll.s r4, r5, r6
+ 50: 02201083 08c04146 bset r1, r2, r3 || joinll.s r4, r5, r6 \ No newline at end of file
diff --git a/gas/testsuite/gas/d30v/bittest.l b/gas/testsuite/gas/d30v/bittest.l
new file mode 100644
index 0000000000..75d1b7ed54
--- /dev/null
+++ b/gas/testsuite/gas/d30v/bittest.l
@@ -0,0 +1,56 @@
+.*: Assembler messages:
+.*: Warning: Swapping instruction order
+.*: Warning: Executing bset in IU may not work
+.*: Warning: Executing btst in IU may not work
+.*: Warning: Executing bclr in IU may not work
+.*: Warning: Executing bnot in IU may not work
+.*: Warning: Executing bset in IU may not work
+.*: Warning: Swapping instruction order
+GAS LISTING .*
+
+
+ 1 # bittest.s
+ 2 #
+ 3 # Bit operation instructions \(BCLR, BNOT, BSET, BTST\) should not be placed in IU.
+ 4 # If the user specifically indicates they should be in the IU, GAS will
+ 5 # generate warnings. The reason why this is not an error is that those instructions
+ 6 # will fail in IU only occasionally. Thus GAS should pack them in MU for
+ 7 # safety, and it just needs to draw attention when a violation is given.
+ 8
+ 9
+ 10 0000 00F00000 nop -> ldw R1, @\(R2,R3\)
+ 10 84401083
+ 11 0008 04406144 nop || ldw R6, @\(R5,R4\)
+.* Warning:Swapping instruction order
+ 11 00F00000
+ 12
+ 13 0010 00F00000 nop -> BSET R1, R2, R3
+.* Warning:Executing bset in IU may not work
+ 13 82201083
+ 14 0018 80F00000 nop <- BTST F1, R2, R3
+.* Warning:Executing btst in IU may not work
+ 14 02001083
+ 15 0020 00F00000 nop || BCLR R1, R2, R3
+.* Warning:Executing bclr in IU may not work
+ 15 02301083
+ 16 0028 00F00000 nop -> BNOT R1, R2, R3
+.* Warning:Executing bnot in IU may not work
+ 16 82101083
+ 17 0030 02101083 BNOT r1, r2, r3 -> nop
+ 17 80F00000
+ 18
+ 19 0038 047C0105 bset r1, r2, r3 || moddec r4, 5
+.* Warning:Swapping instruction order
+ 19 02201083
+ 20
+ 21 bset r1, r2, r3
+ 22 0040 02201083 moddec r4, 5
+ 22 847C0105
+ 23
+ 24 bset r1, r2, r3
+ 25 0048 02201083 joinll r4, r5, r6
+ 25 88C04146
+ 26
+ 27 joinll r4, r5, r6
+ 28 0050 82201083 bset r1, r2, r3
+ 28 08C04146
diff --git a/gas/testsuite/gas/d30v/bittest.s b/gas/testsuite/gas/d30v/bittest.s
new file mode 100644
index 0000000000..b79a56c95c
--- /dev/null
+++ b/gas/testsuite/gas/d30v/bittest.s
@@ -0,0 +1,28 @@
+# bittest.s
+#
+# Bit operation instructions (BCLR, BNOT, BSET, BTST) should not be placed in IU.
+# If the user specifically indicates they should be in the IU, GAS will
+# generate warnings. The reason why this is not an error is that those instructions
+# will fail in IU only occasionally. Thus GAS should pack them in MU for
+# safety, and it just needs to draw attention when a violation is given.
+
+
+ nop -> ldw R1, @(R2,R3)
+ nop || ldw R6, @(R5,R4)
+
+ nop -> BSET R1, R2, R3
+ nop <- BTST F1, R2, R3
+ nop || BCLR R1, R2, R3
+ nop -> BNOT R1, R2, R3
+ BNOT r1, r2, r3 -> nop
+
+ bset r1, r2, r3 || moddec r4, 5
+
+ bset r1, r2, r3
+ moddec r4, 5
+
+ bset r1, r2, r3
+ joinll r4, r5, r6
+
+ joinll r4, r5, r6
+ bset r1, r2, r3
diff --git a/gas/testsuite/gas/d30v/d30.exp b/gas/testsuite/gas/d30v/d30.exp
new file mode 100644
index 0000000000..275b0e06df
--- /dev/null
+++ b/gas/testsuite/gas/d30v/d30.exp
@@ -0,0 +1,35 @@
+#
+# D30V assembler tests
+#
+
+proc run_list_test { name opts } {
+ global srcdir subdir
+ set testname "D30V $name"
+ set file $srcdir/$subdir/$name
+ gas_run ${name}.s $opts ">&dump.out"
+ if {[regexp_diff "dump.out" "${file}.l"] } {
+ fail $testname
+ verbose "output is [file_contents "dump.out"]" 2
+ return
+ }
+ pass $testname
+}
+
+if {[istarget d30v-*-*]} {
+ run_dump_test "inst"
+ run_dump_test "align"
+ run_dump_test "guard"
+ run_dump_test "guard-debug"
+ run_dump_test "reloc"
+ run_dump_test "opt"
+ run_dump_test "array"
+ run_dump_test "label"
+ run_list_test "warn_oddreg" "-al"
+ run_list_test "bittest" "-al"
+ run_dump_test "bittest"
+ run_list_test "serial" "-al"
+ run_list_test "serial2" "-al"
+ run_list_test "serial2O" "-al -O"
+ run_dump_test "mul"
+}
+
diff --git a/gas/testsuite/gas/d30v/guard-debug.d b/gas/testsuite/gas/d30v/guard-debug.d
new file mode 100644
index 0000000000..e9a154c851
--- /dev/null
+++ b/gas/testsuite/gas/d30v/guard-debug.d
@@ -0,0 +1,25 @@
+#objdump: -ldr
+#name: D30V debug (-g) test
+#as: -g
+
+.*: +file format elf32-d30v
+
+Disassembly of section .text:
+
+00000000 <.text>:
+.*:[0-9]+
+ 0: 08001083 00f00000 add.s r1, r2, r3 || nop
+.*:[0-9]+
+ 8: 08001083 00f00000 add.s r1, r2, r3 || nop
+.*:[0-9]+
+ 10: 18001083 00f00000 add.s/tx r1, r2, r3 || nop
+.*:[0-9]+
+ 18: 28001083 00f00000 add.s/fx r1, r2, r3 || nop
+.*:[0-9]+
+ 20: 38001083 00f00000 add.s/xt r1, r2, r3 || nop
+.*:[0-9]+
+ 28: 48001083 00f00000 add.s/xf r1, r2, r3 || nop
+.*:[0-9]+
+ 30: 58001083 00f00000 add.s/tt r1, r2, r3 || nop
+.*:[0-9]+
+ 38: 68001083 00f00000 add.s/tf r1, r2, r3 || nop
diff --git a/gas/testsuite/gas/d30v/guard-debug.s b/gas/testsuite/gas/d30v/guard-debug.s
new file mode 100644
index 0000000000..3f20f7b187
--- /dev/null
+++ b/gas/testsuite/gas/d30v/guard-debug.s
@@ -0,0 +1,17 @@
+# Same as guard.s but here we are testing debug (-g) assembly
+# On the D30V, assembling with -g should disable the VLIW packing
+# and put only one instruction per line.
+
+ .text
+
+ add r1,r2,r3
+ add/al r1,r2,r3
+ add/tx r1,r2,r3
+ add/fx r1,r2,r3
+ add/xt r1,r2,r3
+ add/xf r1,r2,r3
+ add/tt r1,r2,r3
+ add/tf r1,r2,r3
+
+
+
diff --git a/gas/testsuite/gas/d30v/guard.d b/gas/testsuite/gas/d30v/guard.d
new file mode 100644
index 0000000000..0cfa2da7ae
--- /dev/null
+++ b/gas/testsuite/gas/d30v/guard.d
@@ -0,0 +1,17 @@
+#objdump: -dr
+#name: D30V guarded execution test
+#as:
+
+.*: +file format elf32-d30v
+
+Disassembly of section .text:
+
+0+0000 <.text>:
+ 0: 08001083 88001083 add.s r1, r2, r3 -> add.s r1, r2, r3
+ 8: 18001083 a8001083 add.s/tx r1, r2, r3 -> add.s/fx r1, r2, r3
+ 10: 38001083 c8001083 add.s/xt r1, r2, r3 -> add.s/xf r1, r2, r3
+ 18: 58001083 e8001083 add.s/tt r1, r2, r3 -> add.s/tf r1, r2, r3
+ 20: 08001083 88001083 add.s r1, r2, r3 -> add.s r1, r2, r3
+ 28: 18001083 a8001083 add.s/tx r1, r2, r3 -> add.s/fx r1, r2, r3
+ 30: 38001083 c8001083 add.s/xt r1, r2, r3 -> add.s/xf r1, r2, r3
+ 38: 58001083 e8001083 add.s/tt r1, r2, r3 -> add.s/tf r1, r2, r3
diff --git a/gas/testsuite/gas/d30v/guard.s b/gas/testsuite/gas/d30v/guard.s
new file mode 100644
index 0000000000..ed9cd30bb4
--- /dev/null
+++ b/gas/testsuite/gas/d30v/guard.s
@@ -0,0 +1,24 @@
+# D30V guarded execution assembly test
+
+ .text
+
+ add r1,r2,r3
+ add/al r1,r2,r3
+ add/tx r1,r2,r3
+ add/fx r1,r2,r3
+ add/xt r1,r2,r3
+ add/xf r1,r2,r3
+ add/tt r1,r2,r3
+ add/tf r1,r2,r3
+
+# check case sensitivity too
+ ADD r1,r2,r3
+ ADD/AL r1,r2,r3
+ ADD/tx r1,r2,r3
+ add/FX r1,r2,r3
+ ADD/XT r1,r2,r3
+ ADD/XF r1,r2,r3
+ add/TT r1,r2,r3
+ ADD/tf r1,r2,r3
+
+
diff --git a/gas/testsuite/gas/d30v/inst.d b/gas/testsuite/gas/d30v/inst.d
new file mode 100644
index 0000000000..9861cbf6cf
--- /dev/null
+++ b/gas/testsuite/gas/d30v/inst.d
@@ -0,0 +1,256 @@
+#objdump: -dr
+#name: D30V basic instruction test
+#as:
+
+.*: +file format elf32-d30v
+
+Disassembly of section .text:
+
+00000000 <start>:
+ 0: 08815a80 88001083 abs r21, r42 -> add.s r1, r2, r3
+ 8: 080b2cda 00f00000 add.s r50, r51, 0x1a || nop
+ 10: 880b2cf7 8ab1beef add.l r50, r51, 0xdeadbeef
+ 18: 08101083 881b2cda add2h.s r1, r2, r3 -> add2h.s r50, r51, 0x1a
+ 20: 881b2cf7 8ab1beef add2h.l r50, r51, 0xdeadbeef
+ 28: 08401083 884b2cda addc.s r1, r2, r3 -> addc.s r50, r51, 0x1a
+ 30: 884b2cf7 8ab1beef addc.l r50, r51, 0xdeadbeef
+ 38: 09001083 890b2cda addhlll.s r1, r2, r3 -> addhlll.s r50, r51, 0x1a
+ 40: 890b2cf7 8ab1beef addhlll.l r50, r51, 0xdeadbeef
+ 48: 09101083 891b2cda addhllh.s r1, r2, r3 -> addhllh.s r50, r51, 0x1a
+ 50: 891b2cf7 8ab1beef addhllh.l r50, r51, 0xdeadbeef
+ 58: 09201083 892b2cda addhlhl.s r1, r2, r3 -> addhlhl.s r50, r51, 0x1a
+ 60: 892b2cf7 8ab1beef addhlhl.l r50, r51, 0xdeadbeef
+ 68: 09301083 893b2cda addhlhh.s r1, r2, r3 -> addhlhh.s r50, r51, 0x1a
+ 70: 893b2cf7 8ab1beef addhlhh.l r50, r51, 0xdeadbeef
+ 78: 09401083 894b2cda addhhll.s r1, r2, r3 -> addhhll.s r50, r51, 0x1a
+ 80: 894b2cf7 8ab1beef addhhll.l r50, r51, 0xdeadbeef
+ 88: 09501083 895b2cda addhhlh.s r1, r2, r3 -> addhhlh.s r50, r51, 0x1a
+ 90: 895b2cf7 8ab1beef addhhlh.l r50, r51, 0xdeadbeef
+ 98: 09601083 896b2cda addhhhl.s r1, r2, r3 -> addhhhl.s r50, r51, 0x1a
+ a0: 896b2cf7 8ab1beef addhhhl.l r50, r51, 0xdeadbeef
+ a8: 09701083 897b2cda addhhhh.s r1, r2, r3 -> addhhhh.s r50, r51, 0x1a
+ b0: 897b2cf7 8ab1beef addhhhh.l r50, r51, 0xdeadbeef
+ b8: 08601083 886b2cda adds.s r1, r2, r3 -> adds.s r50, r51, 0x1a
+ c0: 886b2cf7 8ab1beef adds.l r50, r51, 0xdeadbeef
+ c8: 08701083 887b2cda adds2h.s r1, r2, r3 -> adds2h.s r50, r51, 0x1a
+ d0: 887b2cf7 8ab1beef adds2h.l r50, r51, 0xdeadbeef
+ d8: 03801083 838b2cda and.s r1, r2, r3 -> and.s r50, r51, 0x1a
+ e0: 838b2cf7 8ab1beef and.l r50, r51, 0xdeadbeef
+ e8: 02800042 82883105 andfg f0, f1, f2 -> andfg f3, s, 0x5
+ f0: 08a01083 88a84146 avg.s r1, r2, r3 -> avg.s r4, r5, 0x6
+ f8: 88ab2cf7 8ab1beef avg.l r50, r51, 0xdeadbeef
+ 100: 08b01083 88b84146 avg2h.s r1, r2, r3 -> avg2h.s r4, r5, 0x6
+ 108: 88bb2cf7 8ab1beef avg2h.l r50, r51, 0xdeadbeef
+ 110: 02301083 82384146 bclr r1, r2, r3 -> bclr r4, r5, 0x6
+ 118: 02101083 82185cc6 bnot r1, r2, r3 -> bnot r5, r51, 0x6
+ 120: 00000029 00f00000 bra.s r41 || nop
+ 128: 00080008 00f00000 bra.s 40 \(168 <start\+0x168>\) || nop
+ 130: 00081e01 00f00000 bra.s f008 \(f138 <start\+0xf138>\) || nop
+ 138: 0046902a 00f00000 bratnz.s r41, r42 || nop
+ 140: 804c1000 8000f00d bratnz.l r1, f00d \(f14d <start\+0xf14d>\)
+ 148: 804c1037 8ab1f00d bratnz.l r1, -21520ff3 \(deadf155 <start\+0xdeadf155>\)
+ 150: 0042902a 00f00000 bratzr.s r41, r42 || nop
+ 158: 80481000 8000f00d bratzr.l r1, f00d \(f165 <start\+0xf165>\)
+ 160: 80481037 8ab1f00d bratzr.l r1, -21520ff3 \(deadf16d <start\+0xdeadf16d>\)
+ 168: 02201083 82285cc6 bset r1, r2, r3 -> bset r5, r51, 0x6
+ 170: 00200029 00f00000 bsr.s r41 || nop
+ 178: 00281e01 00f00000 bsr.s f008 \(f180 <start\+0xf180>\) || nop
+ 180: 80280037 8ab1f00d bsr.l -21520ff3 \(deadf18d <start\+0xdeadf18d>\)
+ 188: 0066902a 00f00000 bsrtnz.s r41, r42 || nop
+ 190: 806c1000 8000f00d bsrtnz.l r1, f00d \(f19d <start\+0xf19d>\)
+ 198: 806c1037 8ab1f00d bsrtnz.l r1, -21520ff3 \(deadf1a5 <start\+0xdeadf1a5>\)
+ 1a0: 0062902a 00f00000 bsrtzr.s r41, r42 || nop
+ 1a8: 80681000 8000f00d bsrtzr.l r1, f00d \(f1b5 <start\+0xf1b5>\)
+ 1b0: 80681037 8ab1f00d bsrtzr.l r1, -21520ff3 \(deadf1bd <start\+0xdeadf1bd>\)
+ 1b8: 02001083 82085cc6 btst f1, r2, r3 -> btst v, r51, 0x6
+ 1c0: 02c000c1 82c09515 cmpeq.s f0, r3, r1 -> cmpne.s f1, r20, r21
+ 1c8: 02c127e0 82c1b0c4 cmpgt.s f2, r31, r32 -> cmpge.s f3, r3, r4
+ 1d0: 02c240c4 82c2d0c4 cmplt.s s, r3, r4 -> cmple.s v, r3, r4
+ 1d8: 02c360c4 82c3f0c4 cmpps.s va, r3, r4 -> cmpng.s c, r3, r4
+ 1e0: 02d127e0 82d1b0c4 cmpugt.s f2, r31, r32 -> cmpuge.s f3, r3, r4
+ 1e8: 02d240c4 82d2d0c4 cmpult.s s, r3, r4 -> cmpule.s v, r3, r4
+ 1f0: 01001008 81081020 dbra.s r1, r8 -> dbra.s r1, 100 \(2f0 <start\+0x2f0>\)
+ 1f8: 81081037 8ab1f00d dbra.l r1, -21520ff3 \(deadf205 <start\+0xdeadf205>\)
+ 200: 0140201f 81482020 dbrai.s 10, r31 -> dbrai.s 10, 100 \(300 <start\+0x300>\)
+ 208: 81482037 8ab1f00d dbrai.l 10, -21520ff3 \(deadf215 <start\+0xdeadf215>\)
+ 210: 01201008 00f00000 dbsr.s r1, r8 || nop
+ 218: 01281020 00f00000 dbsr.s r1, 100 \(318 <start\+0x318>\) || nop
+ 220: 81281037 8ab1f00d dbsr.l r1, -21520ff3 \(deadf22d <start\+0xdeadf22d>\)
+ 228: 0160401f 00f00000 dbsri.s 20, r31 || nop
+ 230: 01684020 00f00000 dbsri.s 20, 100 \(330 <start\+0x330>\) || nop
+ 238: 81684037 8ab1f00d dbsri.l 20, -21520ff3 \(deadf245 <start\+0xdeadf245>\)
+ 240: 01101020 00f00000 djmp.s r1, r32 || nop
+ 248: 81181000 8000f00d djmp.l r1, f00d <start\+0xf00d>
+ 250: 81181037 8ab1f00d djmp.l r1, deadf00d <start\+0xdeadf00d>
+ 258: 01506020 00f00000 djmpi.s 30, r32 || nop
+ 260: 81586000 8000f00d djmpi.l 30, f00d <start\+0xf00d>
+ 268: 81586037 8ab1f00d djmpi.l 30, deadf00d <start\+0xdeadf00d>
+ 270: 01301020 00f00000 djsr.s r1, r32 || nop
+ 278: 81381000 8000f00d djsr.l r1, f00d <start\+0xf00d>
+ 280: 81381037 8ab1f00d djsr.l r1, deadf00d <start\+0xdeadf00d>
+ 288: 01702020 00f00000 djsri.s 10, r32 || nop
+ 290: 81784000 8000f00d djsri.l 20, f00d <start\+0xf00d>
+ 298: 81788037 8ab1f00d djsri.l 40, deadf00d <start\+0xdeadf00d>
+ 2a0: 00100029 00f00000 jmp.s r41 || nop
+ 2a8: 00181e01 00f00000 jmp.s f008 <start\+0xf008> || nop
+ 2b0: 80180037 8ab1f00d jmp.l deadf00d <start\+0xdeadf00d>
+ 2b8: 0056902a 00f00000 jmptnz.s r41, r42 || nop
+ 2c0: 805c1000 8000f00d jmptnz.l r1, f00d <start\+0xf00d>
+ 2c8: 805c1037 8ab1f00d jmptnz.l r1, deadf00d <start\+0xdeadf00d>
+ 2d0: 0052902a 00f00000 jmptzr.s r41, r42 || nop
+ 2d8: 80581000 8000f00d jmptzr.l r1, f00d <start\+0xf00d>
+ 2e0: 80581037 8ab1f00d jmptzr.l r1, deadf00d <start\+0xdeadf00d>
+ 2e8: 08c01084 88c8108f joinll.s r1, r2, r4 -> joinll.s r1, r2, 0xf
+ 2f0: 88c810b7 8ab1f00d joinll.l r1, r2, 0xdeadf00d
+ 2f8: 08d01084 88d8108f joinlh.s r1, r2, r4 -> joinlh.s r1, r2, 0xf
+ 300: 88d810b7 8ab1f00d joinlh.l r1, r2, 0xdeadf00d
+ 308: 08e01084 88e8108f joinhl.s r1, r2, r4 -> joinhl.s r1, r2, 0xf
+ 310: 88e810b7 8ab1f00d joinhl.l r1, r2, 0xdeadf00d
+ 318: 08f01084 88f8108f joinhh.s r1, r2, r4 -> joinhh.s r1, r2, 0xf
+ 320: 88f810b7 8ab1f00d joinhh.l r1, r2, 0xdeadf00d
+ 328: 00300029 00f00000 jsr.s r41 || nop
+ 330: 00381e01 00f00000 jsr.s f008 <start\+0xf008> || nop
+ 338: 80380037 8ab1f00d jsr.l deadf00d <start\+0xdeadf00d>
+ 340: 0076902a 00f00000 jsrtnz.s r41, r42 || nop
+ 348: 807c1000 8000f00d jsrtnz.l r1, f00d <start\+0xf00d>
+ 350: 807c1037 8ab1f00d jsrtnz.l r1, deadf00d <start\+0xdeadf00d>
+ 358: 0072902a 00f00000 jsrtzr.s r41, r42 || nop
+ 360: 80781000 8000f00d jsrtzr.l r1, f00d <start\+0xf00d>
+ 368: 80781037 8ab1f00d jsrtzr.l r1, deadf00d <start\+0xdeadf00d>
+ 370: 043061c8 843461c8 ld2h.s r6, @\(r7, r8\) -> ld2h.s r6, @\(r7\+, r8\)
+ 378: 043c61c8 843861da ld2h.s r6, @\(r7-, r8\) -> ld2h.s r6, @\(r7, 0x1a\)
+ 380: 843861c0 80001234 ld2h.l r6, @\(r7, 0x1234\)
+ 388: 046061c8 846461c8 ld2w.s r6, @\(r7, r8\) -> ld2w.s r6, @\(r7\+, r8\)
+ 390: 046c61c8 846861da ld2w.s r6, @\(r7-, r8\) -> ld2w.s r6, @\(r7, 0x1a\)
+ 398: 846861c0 80001234 ld2w.l r6, @\(r7, 0x1234\)
+ 3a0: 045061c8 845461c8 ld4bh.s r6, @\(r7, r8\) -> ld4bh.s r6, @\(r7\+, r8\)
+ 3a8: 045c61c8 845861da ld4bh.s r6, @\(r7-, r8\) -> ld4bh.s r6, @\(r7, 0x1a\)
+ 3b0: 845861c0 80001234 ld4bh.l r6, @\(r7, 0x1234\)
+ 3b8: 04d061c8 84d461c8 ld4bhu.s r6, @\(r7, r8\) -> ld4bhu.s r6, @\(r7\+, r8\)
+ 3c0: 04dc61c8 84d861da ld4bhu.s r6, @\(r7-, r8\) -> ld4bhu.s r6, @\(r7, 0x1a\)
+ 3c8: 84d861c0 80001234 ld4bhu.l r6, @\(r7, 0x1234\)
+ 3d0: 040061c8 840461c8 ldb.s r6, @\(r7, r8\) -> ldb.s r6, @\(r7\+, r8\)
+ 3d8: 040c61c8 840861da ldb.s r6, @\(r7-, r8\) -> ldb.s r6, @\(r7, 0x1a\)
+ 3e0: 840861c0 80001234 ldb.l r6, @\(r7, 0x1234\)
+ 3e8: 049061c8 849461c8 ldbu.s r6, @\(r7, r8\) -> ldbu.s r6, @\(r7\+, r8\)
+ 3f0: 049c61c8 849861da ldbu.s r6, @\(r7-, r8\) -> ldbu.s r6, @\(r7, 0x1a\)
+ 3f8: 849861c0 80001234 ldbu.l r6, @\(r7, 0x1234\)
+ 400: 042061c8 842461c8 ldh.s r6, @\(r7, r8\) -> ldh.s r6, @\(r7\+, r8\)
+ 408: 042c61c8 842861da ldh.s r6, @\(r7-, r8\) -> ldh.s r6, @\(r7, 0x1a\)
+ 410: 842861c0 80001234 ldh.l r6, @\(r7, 0x1234\)
+ 418: 041061c8 841461c8 ldhh.s r6, @\(r7, r8\) -> ldhh.s r6, @\(r7\+, r8\)
+ 420: 041c61c8 841861da ldhh.s r6, @\(r7-, r8\) -> ldhh.s r6, @\(r7, 0x1a\)
+ 428: 841861c0 80001234 ldhh.l r6, @\(r7, 0x1234\)
+ 430: 04a061c8 84a461c8 ldhu.s r6, @\(r7, r8\) -> ldhu.s r6, @\(r7\+, r8\)
+ 438: 04ac61c8 84a861da ldhu.s r6, @\(r7-, r8\) -> ldhu.s r6, @\(r7, 0x1a\)
+ 440: 84a861c0 80001234 ldhu.l r6, @\(r7, 0x1234\)
+ 448: 044061c8 844461c8 ldw.s r6, @\(r7, r8\) -> ldw.s r6, @\(r7\+, r8\)
+ 450: 044c61c8 844861da ldw.s r6, @\(r7-, r8\) -> ldw.s r6, @\(r7, 0x1a\)
+ 458: 844861c0 80001234 ldw.l r6, @\(r7, 0x1234\)
+ 460: 8b48109f 0b401084 mac0 r1, r2, 0x1f <- mac0 r1, r2, r4
+ 468: 8b4c109f 0b441084 mac1 r1, r2, 0x1f <- mac1 r1, r2, r4
+ 470: 8b58109f 0b501084 macs0 r1, r2, 0x1f <- macs0 r1, r2, r4
+ 478: 8b5c109f 0b541084 macs1 r1, r2, 0x1f <- macs1 r1, r2, r4
+ 480: 047c004a 8474004a moddec r1, 0xa -> modinc r1, 0xa
+ 488: 8b68109f 0b601084 msub0 r1, r2, 0x1f <- msub0 r1, r2, r4
+ 490: 8b6c109f 0b641084 msub1 r1, r2, 0x1f <- msub1 r1, r2, r4
+ 498: 8b08108a 0b001084 mul r1, r2, 0xa <- mul r1, r2, r4
+ 4a0: 8b78109f 0b701084 msubs0 r1, r2, 0x1f <- msubs0 r1, r2, r4
+ 4a8: 8b7c109f 0b741084 msubs1 r1, r2, 0x1f <- msubs1 r1, r2, r4
+ 4b0: 00f00000 00f00000 nop || nop
+ 4b8: 8a08108a 0a001084 mul2h r1, r2, 0xa <- mul2h r1, r2, r4
+ 4c0: 8a48108a 0a401084 mulhxll r1, r2, 0xa <- mulhxll r1, r2, r4
+ 4c8: 8a58108a 0a501084 mulhxlh r1, r2, 0xa <- mulhxlh r1, r2, r4
+ 4d0: 8a68108a 0a601084 mulhxhl r1, r2, 0xa <- mulhxhl r1, r2, r4
+ 4d8: 8a78108a 0a701084 mulhxhh r1, r2, 0xa <- mulhxhh r1, r2, r4
+ 4e0: 8b900044 0a108084 mulxs a0, r1, r4 <- mulx2h r8, r2, r4
+ 4e8: 8b88108a 0b800044 mulx a1, r2, 0xa <- mulx a0, r1, r4
+ 4f0: 8bf8204a 0bf01004 mvfacc r2, a1, 0xa <- mvfacc r1, a0, r4
+ 4f8: 8b98108a 0a18808a mulxs a1, r2, 0xa <- mulx2h r8, r2, 0xa
+ 500: 01e0a080 81e0a1c0 mvfsys r10, pc -> mvfsys r10, rpt_c
+ 508: 01e0a000 81e0a002 mvfsys r10, psw -> mvfsys r10, pswh
+ 510: 01e0a001 81e0a003 mvfsys r10, pswl -> mvfsys r10, f0
+ 518: 01e0a103 8af01084 mvfsys r10, s -> mvtacc a1, r2, r4
+ 520: 00e07280 80e00280 mvtsys rpt_c, r10 -> mvtsys psw, r10
+ 528: 00e00282 80e00281 mvtsys pswh, r10 -> mvtsys pswl, r10
+ 530: 00e00283 80e03283 mvtsys f0, r10 -> mvtsys f3, r10
+ 538: 00e04283 80e05283 mvtsys s, r10 -> mvtsys v, r10
+ 540: 00e06283 80e07283 mvtsys va, r10 -> mvtsys c, r10
+ 548: 00f00000 83901080 nop -> not r1, r2
+ 550: 02901080 83a01084 notfg f1, f2 -> or.s r1, r2, r4
+ 558: 03a8109a 00f00000 or.s r1, r2, 0x1a || nop
+ 560: 83a810b7 8ab1f00d or.l r1, r2, 0xdeadf00d
+ 568: 02a01084 82a84081 orfg f1, f2, s -> orfg s, f2, 0x1
+ 570: 00800000 00f00000 reit || nop
+ 578: 01801002 00f00000 repeat.s r1, r2 || nop
+ 580: 81884000 8000dead repeat.l r4, dead \(e42d <start\+0xe42d>\)
+ 588: 81884037 8ab1f00d repeat.l r4, -21520ff3 \(deadf595 <start\+0xdeadf595>\)
+ 590: 01a0a001 81a8a200 repeati.s a \(59a <start\+0x59a>\), r1 -> repeati.s a \(59a <start\+0x59a>\), 1000 \(1590 <start\+0x1590>\)
+ 598: 00f00000 00f00000 nop || nop
+ 5a0: 03401084 8348108a rot r1, r2, r4 -> rot r1, r2, 0xa
+ 5a8: 03501084 8358108a rot2h r1, r2, r4 -> rot2h r1, r2, 0xa
+ 5b0: 8a88108a 0a801084 sat r1, r2, 0xa <- sat r1, r2, r4
+ 5b8: 8a98108a 0a901084 sat2h r1, r2, 0xa <- sat2h r1, r2, r4
+ 5c0: 8bc8108a 0bc01084 sathl r1, r2, 0xa <- sathl r1, r2, r4
+ 5c8: 8bd8108a 0bd01084 sathh r1, r2, 0xa <- sathh r1, r2, r4
+ 5d0: 8aa8108a 0aa01084 satz r1, r2, 0xa <- satz r1, r2, r4
+ 5d8: 8ab8108a 0ab01084 satz2h r1, r2, 0xa <- satz2h r1, r2, r4
+ 5e0: 03001084 8308108a sra r1, r2, r4 -> sra r1, r2, 0xa
+ 5e8: 03101084 8318108a sra2h r1, r2, r4 -> sra2h r1, r2, 0xa
+ 5f0: 03601084 8368108a src r1, r2, r4 -> src r1, r2, 0xa
+ 5f8: 03201084 8328108a srl r1, r2, r4 -> srl r1, r2, 0xa
+ 600: 03301084 8338108a srl2h r1, r2, r4 -> srl2h r1, r2, 0xa
+ 608: 053061c8 853461c8 st2h.s r6, @\(r7, r8\) -> st2h.s r6, @\(r7\+, r8\)
+ 610: 053c61c8 853861da st2h.s r6, @\(r7-, r8\) -> st2h.s r6, @\(r7, 0x1a\)
+ 618: 853861c0 80001234 st2h.l r6, @\(r7, 0x1234\)
+ 620: 056061c8 856461c8 st2w.s r6, @\(r7, r8\) -> st2w.s r6, @\(r7\+, r8\)
+ 628: 056c61c8 856861da st2w.s r6, @\(r7-, r8\) -> st2w.s r6, @\(r7, 0x1a\)
+ 630: 856861c0 80001234 st2w.l r6, @\(r7, 0x1234\)
+ 638: 055061c8 855461c8 st4hb.s r6, @\(r7, r8\) -> st4hb.s r6, @\(r7\+, r8\)
+ 640: 055c61c8 855861da st4hb.s r6, @\(r7-, r8\) -> st4hb.s r6, @\(r7, 0x1a\)
+ 648: 855861c0 80001234 st4hb.l r6, @\(r7, 0x1234\)
+ 650: 050061c8 850461c8 stb.s r6, @\(r7, r8\) -> stb.s r6, @\(r7\+, r8\)
+ 658: 050c61c8 850861da stb.s r6, @\(r7-, r8\) -> stb.s r6, @\(r7, 0x1a\)
+ 660: 850861c0 80001234 stb.l r6, @\(r7, 0x1234\)
+ 668: 052061c8 852461c8 sth.s r6, @\(r7, r8\) -> sth.s r6, @\(r7\+, r8\)
+ 670: 052c61c8 852861da sth.s r6, @\(r7-, r8\) -> sth.s r6, @\(r7, 0x1a\)
+ 678: 852861c0 80001234 sth.l r6, @\(r7, 0x1234\)
+ 680: 051061c8 851461c8 sthh.s r6, @\(r7, r8\) -> sthh.s r6, @\(r7\+, r8\)
+ 688: 051c61c8 851861da sthh.s r6, @\(r7-, r8\) -> sthh.s r6, @\(r7, 0x1a\)
+ 690: 851861c0 80001234 sthh.l r6, @\(r7, 0x1234\)
+ 698: 054061c8 854461c8 stw.s r6, @\(r7, r8\) -> stw.s r6, @\(r7\+, r8\)
+ 6a0: 054c61c8 854861da stw.s r6, @\(r7-, r8\) -> stw.s r6, @\(r7, 0x1a\)
+ 6a8: 854861c0 80001234 stw.l r6, @\(r7, 0x1234\)
+ 6b0: 08201083 882b2cda sub.s r1, r2, r3 -> sub.s r50, r51, 0x1a
+ 6b8: 882b2cf7 8ab1beef sub.l r50, r51, 0xdeadbeef
+ 6c0: 08301083 883b2cda sub2h.s r1, r2, r3 -> sub2h.s r50, r51, 0x1a
+ 6c8: 883b2cf7 8ab1beef sub2h.l r50, r51, 0xdeadbeef
+ 6d0: 08501083 885b2cda subb.s r1, r2, r3 -> subb.s r50, r51, 0x1a
+ 6d8: 885b2cf7 8ab1beef subb.l r50, r51, 0xdeadbeef
+ 6e0: 09801083 898b2cda subhlll.s r1, r2, r3 -> subhlll.s r50, r51, 0x1a
+ 6e8: 898b2cf7 8ab1beef subhlll.l r50, r51, 0xdeadbeef
+ 6f0: 09901083 899b2cda subhllh.s r1, r2, r3 -> subhllh.s r50, r51, 0x1a
+ 6f8: 899b2cf7 8ab1beef subhllh.l r50, r51, 0xdeadbeef
+ 700: 09a01083 89ab2cda subhlhl.s r1, r2, r3 -> subhlhl.s r50, r51, 0x1a
+ 708: 89ab2cf7 8ab1beef subhlhl.l r50, r51, 0xdeadbeef
+ 710: 09b01083 89bb2cda subhlhh.s r1, r2, r3 -> subhlhh.s r50, r51, 0x1a
+ 718: 89bb2cf7 8ab1beef subhlhh.l r50, r51, 0xdeadbeef
+ 720: 09c01083 89cb2cda subhhll.s r1, r2, r3 -> subhhll.s r50, r51, 0x1a
+ 728: 89cb2cf7 8ab1beef subhhll.l r50, r51, 0xdeadbeef
+ 730: 09d01083 89db2cda subhhlh.s r1, r2, r3 -> subhhlh.s r50, r51, 0x1a
+ 738: 89db2cf7 8ab1beef subhhlh.l r50, r51, 0xdeadbeef
+ 740: 09e01083 89eb2cda subhhhl.s r1, r2, r3 -> subhhhl.s r50, r51, 0x1a
+ 748: 89eb2cf7 8ab1beef subhhhl.l r50, r51, 0xdeadbeef
+ 750: 09f01083 89fb2cda subhhhh.s r1, r2, r3 -> subhhhh.s r50, r51, 0x1a
+ 758: 89fb2cf7 8ab1beef subhhhh.l r50, r51, 0xdeadbeef
+ 760: 00900001 00f00000 trap.s r1 || nop
+ 768: 0098000a 00f00000 trap.s 0xa || nop
+ 770: 03b01084 83b8108a xor.s r1, r2, r4 -> xor.s r1, r2, 0xa
+ 778: 83b810b7 8ab1f00d xor.l r1, r2, 0xdeadf00d
+ 780: 02b01084 82b8110a xorfg f1, f2, s -> xorfg f1, s, 0xa
+ 788: 00f00000 80f00000 nop -> nop
+ 790: 00f00000 80f00000 nop -> nop
+ 798: 00f00000 00f00000 nop || nop
+ 7a0: 80f00000 00f00000 nop <- nop
+ 7a8: 03901080 00f00000 not r1, r2 || nop
+ 7b0: 039020c0 80f00000 not r2, r3 -> nop
diff --git a/gas/testsuite/gas/d30v/inst.s b/gas/testsuite/gas/d30v/inst.s
new file mode 100644
index 0000000000..ee6611eb11
--- /dev/null
+++ b/gas/testsuite/gas/d30v/inst.s
@@ -0,0 +1,504 @@
+# test all instructions
+
+start:
+ abs r21,r42
+
+ add r1,r2,r3
+ add r50,r51,0x1a
+ add r50,r51,0xdeadbeef
+
+ add2h r1,r2,r3
+ add2h r50,r51,0x1a
+ add2h r50,r51,0xdeadbeef
+
+ addc r1,r2,r3
+ addc r50,r51,0x1a
+ addc r50,r51,0xdeadbeef
+
+ addhlll r1,r2,r3
+ addhlll r50,r51,0x1a
+ addhlll r50,r51,0xdeadbeef
+
+ addhllh r1,r2,r3
+ addhllh r50,r51,0x1a
+ addhllh r50,r51,0xdeadbeef
+
+ addhlhl r1,r2,r3
+ addhlhl r50,r51,0x1a
+ addhlhl r50,r51,0xdeadbeef
+
+ addhlhh r1,r2,r3
+ addhlhh r50,r51,0x1a
+ addhlhh r50,r51,0xdeadbeef
+
+ addhhll r1,r2,r3
+ addhhll r50,r51,0x1a
+ addhhll r50,r51,0xdeadbeef
+
+ addhhlh r1,r2,r3
+ addhhlh r50,r51,0x1a
+ addhhlh r50,r51,0xdeadbeef
+
+ addhhhl r1,r2,r3
+ addhhhl r50,r51,0x1a
+ addhhhl r50,r51,0xdeadbeef
+
+ addhhhh r1,r2,r3
+ addhhhh r50,r51,0x1a
+ addhhhh r50,r51,0xdeadbeef
+
+ adds r1,r2,r3
+ adds r50,r51,0x1a
+ adds r50,r51,0xdeadbeef
+
+ adds2h r1,r2,r3
+ adds2h r50,r51,0x1a
+ adds2h r50,r51,0xdeadbeef
+
+ and r1,r2,r3
+ and r50,r51,0x1a
+ and r50,r51,0xdeadbeef
+
+ andfg f0,f1,f2
+ andfg f3,f4,5
+
+ avg r1,r2,r3
+ avg r4,r5,6
+ avg r50,r51,0xdeadbeef
+
+ avg2h r1,r2,r3
+ avg2h r4,r5,6
+ avg2h r50,r51,0xdeadbeef
+
+ bclr r1,r2,r3
+ bclr r4,r5,6
+
+ bnot r1,r2,r3
+ bnot r5,r51,6
+
+ bra r41
+ bra 0x40
+ bra 0xf00d
+
+ bratnz r41,r42
+ bratnz r1,0xf00d
+ bratnz r1,0xdeadf00d
+
+ bratzr r41,r42
+ bratzr r1,0xf00d
+ bratzr r1,0xdeadf00d
+
+ bset r1,r2,r3
+ bset r5,r51,6
+
+ bsr r41
+ bsr 0xf00d
+ bsr 0xdeadf00d
+
+ bsrtnz r41,r42
+ bsrtnz r1,0xf00d
+ bsrtnz r1,0xdeadf00d
+
+ bsrtzr r41,r42
+ bsrtzr r1,0xf00d
+ bsrtzr r1,0xdeadf00d
+
+ btst f1,r2,r3
+ btst f5,r51,6
+
+ cmpeq f0,r3,r1
+ cmpne f1,r20,r21
+ cmpgt f2,r31,r32
+ cmpge f3,r3,r4
+ cmplt f4,r3,r4
+ cmple f5,r3,r4
+ cmpps f6,r3,r4
+ cmpng f7,r3,r4
+
+ cmpugt f2,r31,r32
+ cmpuge f3,r3,r4
+ cmpult f4,r3,r4
+ cmpule f5,r3,r4
+
+ dbra r1,r8
+ dbra r1,0x100
+ dbra r1,0xdeadf00d
+
+ dbrai 0x10,r31
+ dbrai 0x10,0x100
+ dbrai 0x10,0xdeadf00d
+
+ dbsr r1,r8 || nop
+ dbsr r1,0x100 || nop
+ dbsr r1,0xdeadf00d
+
+ dbsri 0x20,r31 || nop
+ dbsri 0x20,0x100 || nop
+ dbsri 0x20,0xdeadf00d
+
+ djmp r1,r32
+ djmp r1,0xf00d
+ djmp r1,0xdeadf00d
+
+ djmpi 0x30,r32
+ djmpi 0x30,0xf00d
+ djmpi 0x30,0xdeadf00d
+
+ djsr r1,r32
+ djsr r1,0xf00d
+ djsr r1,0xdeadf00d
+
+ djsri 0x10,r32
+ djsri 0x20,0xf00d
+ djsri 0x40,0xdeadf00d
+
+ jmp r41
+ jmp 0xf00d
+ jmp 0xdeadf00d
+
+ jmptnz r41,r42
+ jmptnz r1,0xf00d
+ jmptnz r1,0xdeadf00d
+
+ jmptzr r41,r42
+ jmptzr r1,0xf00d
+ jmptzr r1,0xdeadf00d
+
+ joinll r1,r2,r4
+ joinll r1,r2,0xf
+ joinll r1,r2,0xdeadf00d
+
+ joinlh r1,r2,r4
+ joinlh r1,r2,0xf
+ joinlh r1,r2,0xdeadf00d
+
+ joinhl r1,r2,r4
+ joinhl r1,r2,0xf
+ joinhl r1,r2,0xdeadf00d
+
+ joinhh r1,r2,r4
+ joinhh r1,r2,0xf
+ joinhh r1,r2,0xdeadf00d
+
+ jsr r41
+ jsr 0xf00d
+ jsr 0xdeadf00d
+
+ jsrtnz r41,r42
+ jsrtnz r1,0xf00d
+ jsrtnz r1,0xdeadf00d
+
+ jsrtzr r41,r42
+ jsrtzr r1,0xf00d
+ jsrtzr r1,0xdeadf00d
+
+ ld2h r6,@(r7,r8)
+ ld2h r6,@(r7+,r8)
+ ld2h r6,@(r7-,r8)
+ ld2h r6,@(r7,0x1a)
+ ld2h r6,@(r7,0x1234)
+
+ ld2w r6,@(r7,r8)
+ ld2w r6,@(r7+,r8)
+ ld2w r6,@(r7-,r8)
+ ld2w r6,@(r7,0x1a)
+ ld2w r6,@(r7,0x1234)
+
+ ld4bh r6,@(r7,r8)
+ ld4bh r6,@(r7+,r8)
+ ld4bh r6,@(r7-,r8)
+ ld4bh r6,@(r7,0x1a)
+ ld4bh r6,@(r7,0x1234)
+
+ ld4bhu r6,@(r7,r8)
+ ld4bhu r6,@(r7+,r8)
+ ld4bhu r6,@(r7-,r8)
+ ld4bhu r6,@(r7,0x1a)
+ ld4bhu r6,@(r7,0x1234)
+
+ ldb r6,@(r7,r8)
+ ldb r6,@(r7+,r8)
+ ldb r6,@(r7-,r8)
+ ldb r6,@(r7,0x1a)
+ ldb r6,@(r7,0x1234)
+
+ ldbu r6,@(r7,r8)
+ ldbu r6,@(r7+,r8)
+ ldbu r6,@(r7-,r8)
+ ldbu r6,@(r7,0x1a)
+ ldbu r6,@(r7,0x1234)
+
+ ldh r6,@(r7,r8)
+ ldh r6,@(r7+,r8)
+ ldh r6,@(r7-,r8)
+ ldh r6,@(r7,0x1a)
+ ldh r6,@(r7,0x1234)
+
+ ldhh r6,@(r7,r8)
+ ldhh r6,@(r7+,r8)
+ ldhh r6,@(r7-,r8)
+ ldhh r6,@(r7,0x1a)
+ ldhh r6,@(r7,0x1234)
+
+ ldhu r6,@(r7,r8)
+ ldhu r6,@(r7+,r8)
+ ldhu r6,@(r7-,r8)
+ ldhu r6,@(r7,0x1a)
+ ldhu r6,@(r7,0x1234)
+
+ ldw r6,@(r7,r8)
+ ldw r6,@(r7+,r8)
+ ldw r6,@(r7-,r8)
+ ldw r6,@(r7,0x1a)
+ ldw r6,@(r7,0x1234)
+
+ mac0 r1,r2,r4
+ mac0 r1,r2,0x1f
+ mac1 r1,r2,r4
+ mac1 r1,r2,0x1f
+
+ macs0 r1,r2,r4
+ macs0 r1,r2,0x1f
+ macs1 r1,r2,r4
+ macs1 r1,r2,0x1f
+
+ moddec r1,0xa
+
+ modinc r1,0xa
+
+ msub0 r1,r2,r4
+ msub0 r1,r2,0x1f
+ msub1 r1,r2,r4
+ msub1 r1,r2,0x1f
+
+ mul r1,r2,r4
+ mul r1,r2,0xa
+
+ msubs0 r1,r2,r4
+ msubs0 r1,r2,0x1f
+ msubs1 r1,r2,r4
+ msubs1 r1,r2,0x1f
+
+ mul2h r1,r2,r4
+ mul2h r1,r2,0xa
+
+ mulhxll r1,r2,r4
+ mulhxll r1,r2,0xa
+
+ mulhxlh r1,r2,r4
+ mulhxlh r1,r2,0xa
+
+ mulhxhl r1,r2,r4
+ mulhxhl r1,r2,0xa
+
+ mulhxhh r1,r2,r4
+ mulhxhh r1,r2,0xa
+
+ mulx2h r8,r2,r4
+ mulxs a0,r1,r4
+
+ mulx a0,r1,r4
+ mulx a1,r2,0xa
+
+ mvfacc r1,a0,r4
+ mvfacc r2,a1,0xa
+
+ mulx2h r8,r2,0xa
+ mulxs a1,r2,0xa
+
+ mvfsys r10,pc
+ mvfsys r10,rpt_c
+ mvfsys r10,psw
+ mvfsys r10,pswh
+ mvfsys r10,pswl
+ mvfsys r10,f0
+ mvfsys r10,S
+
+ mvtacc a1,r2,r4
+
+ mvtsys rpt_c, r10
+ mvtsys psw, r10
+ mvtsys pswh, r10
+ mvtsys pswl, r10
+ mvtsys f0, r10
+ mvtsys f3, r10
+ mvtsys S, r10
+ mvtsys V, r10
+ mvtsys VA, r10
+ mvtsys C, r10
+
+ nop
+
+ not r1,r2
+
+ notfg f1,f2
+
+ or r1,r2,r4
+ or r1,r2,0x1a
+ or r1,r2,0xdeadf00d
+
+ orfg f1,f2,f4
+ orfg f4,f2,0x1
+
+ reit
+
+ repeat r1,r2
+ repeat r4,0xdead
+ repeat r4,0xdeadf00d
+
+ repeati 0xa,r1
+ repeati 0xa,0x1001
+
+ nop || nop
+
+ rot r1,r2,r4
+ rot r1,r2,0xa
+
+ rot2h r1,r2,r4
+ rot2h r1,r2,0xa
+
+ sat r1,r2,r4
+ sat r1,r2,0xa
+
+ sat2h r1,r2,r4
+ sat2h r1,r2,0xa
+
+ sathl r1,r2,r4
+ sathl r1,r2,0xa
+
+ sathh r1,r2,r4
+ sathh r1,r2,0xa
+
+ satz r1,r2,r4
+ satz r1,r2,0xa
+
+ satz2h r1,r2,r4
+ satz2h r1,r2,0xa
+
+ sra r1,r2,r4
+ sra r1,r2,0xa
+
+ sra2h r1,r2,r4
+ sra2h r1,r2,0xa
+
+ src r1,r2,r4
+ src r1,r2,0xa
+
+ srl r1,r2,r4
+ srl r1,r2,0xa
+
+ srl2h r1,r2,r4
+ srl2h r1,r2,0xa
+
+
+ st2h r6,@(r7,r8)
+ st2h r6,@(r7+,r8)
+ st2h r6,@(r7-,r8)
+ st2h r6,@(r7,0x1a)
+ st2h r6,@(r7,0x1234)
+
+ st2w r6,@(r7,r8)
+ st2w r6,@(r7+,r8)
+ st2w r6,@(r7-,r8)
+ st2w r6,@(r7,0x1a)
+ st2w r6,@(r7,0x1234)
+
+ st4hb r6,@(r7,r8)
+ st4hb r6,@(r7+,r8)
+ st4hb r6,@(r7-,r8)
+ st4hb r6,@(r7,0x1a)
+ st4hb r6,@(r7,0x1234)
+
+ stb r6,@(r7,r8)
+ stb r6,@(r7+,r8)
+ stb r6,@(r7-,r8)
+ stb r6,@(r7,0x1a)
+ stb r6,@(r7,0x1234)
+
+ sth r6,@(r7,r8)
+ sth r6,@(r7+,r8)
+ sth r6,@(r7-,r8)
+ sth r6,@(r7,0x1a)
+ sth r6,@(r7,0x1234)
+
+ sthh r6,@(r7,r8)
+ sthh r6,@(r7+,r8)
+ sthh r6,@(r7-,r8)
+ sthh r6,@(r7,0x1a)
+ sthh r6,@(r7,0x1234)
+
+ stw r6,@(r7,r8)
+ stw r6,@(r7+,r8)
+ stw r6,@(r7-,r8)
+ stw r6,@(r7,0x1a)
+ stw r6,@(r7,0x1234)
+
+ sub r1,r2,r3
+ sub r50,r51,0x1a
+ sub r50,r51,0xdeadbeef
+
+ sub2h r1,r2,r3
+ sub2h r50,r51,0x1a
+ sub2h r50,r51,0xdeadbeef
+
+ subb r1,r2,r3
+ subb r50,r51,0x1a
+ subb r50,r51,0xdeadbeef
+
+ subhlll r1,r2,r3
+ subhlll r50,r51,0x1a
+ subhlll r50,r51,0xdeadbeef
+
+ subhllh r1,r2,r3
+ subhllh r50,r51,0x1a
+ subhllh r50,r51,0xdeadbeef
+
+ subhlhl r1,r2,r3
+ subhlhl r50,r51,0x1a
+ subhlhl r50,r51,0xdeadbeef
+
+ subhlhh r1,r2,r3
+ subhlhh r50,r51,0x1a
+ subhlhh r50,r51,0xdeadbeef
+
+ subhhll r1,r2,r3
+ subhhll r50,r51,0x1a
+ subhhll r50,r51,0xdeadbeef
+
+ subhhlh r1,r2,r3
+ subhhlh r50,r51,0x1a
+ subhhlh r50,r51,0xdeadbeef
+
+ subhhhl r1,r2,r3
+ subhhhl r50,r51,0x1a
+ subhhhl r50,r51,0xdeadbeef
+
+ subhhhh r1,r2,r3
+ subhhhh r50,r51,0x1a
+ subhhhh r50,r51,0xdeadbeef
+
+ trap r1
+ trap 0xa
+
+ xor r1,r2,r4
+ xor r1,r2,0xa
+ xor r1,r2,0xdeadf00d
+
+ xorfg f1,f2,f4
+ xorfg f1,f4,0xa
+
+# VLIW syntax test
+ nop
+ nop
+ nop -> nop
+ nop || nop
+ nop <- nop
+
+# try changing sections
+ not r1,r2
+ .section .foo
+ add r10,r12,6
+ .text
+ not r2,r3
+ nop
+ \ No newline at end of file
diff --git a/gas/testsuite/gas/d30v/label-debug.d b/gas/testsuite/gas/d30v/label-debug.d
new file mode 100644
index 0000000000..e429f81e0f
--- /dev/null
+++ b/gas/testsuite/gas/d30v/label-debug.d
@@ -0,0 +1,24 @@
+#objdump: -ldr
+#name: D30V debug (-g) test
+#as: -g
+
+.*: +file format elf32-d30v
+
+Disassembly of section .text:
+
+00000000 <_abc-0x18>:
+.*label-debug.s:4
+ 0: 10080003 00f00000 bra.s\/tx 18 \(18 <_abc>\) \|\| nop
+.*label-debug.s:5
+ 8: 00f00000 00f00000 nop || nop
+ 10: 0e000004 00f00000 .long 0xe000004 || nop
+
+00000018 <_abc>:
+.*label-debug.s:8
+ 18: 00f00000 00f00000 nop || nop
+.*label-debug.s:9
+ 20: 00f00000 00f00000 nop || nop
+.*label-debug.s:10
+ 28: 00f00000 00f00000 nop || nop
+.*label-debug.s:11
+ 30: 00f00000 00f00000 nop || nop
diff --git a/gas/testsuite/gas/d30v/label-debug.s b/gas/testsuite/gas/d30v/label-debug.s
new file mode 100644
index 0000000000..9640aa49bd
--- /dev/null
+++ b/gas/testsuite/gas/d30v/label-debug.s
@@ -0,0 +1,11 @@
+# labels should be aligned on 8-byte boundries
+
+ .text
+ bra.s/tx _abc || nop
+ nop || nop
+ .word 0x0e000004
+_abc:
+ nop
+ nop
+ nop
+ nop
diff --git a/gas/testsuite/gas/d30v/label.d b/gas/testsuite/gas/d30v/label.d
new file mode 100644
index 0000000000..66cfcdab74
--- /dev/null
+++ b/gas/testsuite/gas/d30v/label.d
@@ -0,0 +1,16 @@
+#objdump: -dr
+#name: D30V label alignment test
+#as:
+
+.*: +file format elf32-d30v
+
+Disassembly of section .text:
+
+00000000 <_abc-0x18>:
+ 0: 10080003 00f00000 bra.s/tx 18 (18 <_abc>) || nop
+ 8: 00f00000 00f00000 nop || nop
+ 10: 0e000004 00f00000 .long 0xe000004 || nop
+
+00000018 <_abc>:
+ 18: 00f00000 80f00000 nop -> nop
+ 20: 00f00000 80f00000 nop -> nop
diff --git a/gas/testsuite/gas/d30v/label.s b/gas/testsuite/gas/d30v/label.s
new file mode 100644
index 0000000000..9640aa49bd
--- /dev/null
+++ b/gas/testsuite/gas/d30v/label.s
@@ -0,0 +1,11 @@
+# labels should be aligned on 8-byte boundries
+
+ .text
+ bra.s/tx _abc || nop
+ nop || nop
+ .word 0x0e000004
+_abc:
+ nop
+ nop
+ nop
+ nop
diff --git a/gas/testsuite/gas/d30v/mul.d b/gas/testsuite/gas/d30v/mul.d
new file mode 100644
index 0000000000..04e0a550b1
--- /dev/null
+++ b/gas/testsuite/gas/d30v/mul.d
@@ -0,0 +1,20 @@
+#objdump: -dr
+#name: D30V alignment test
+#as: -WO
+
+.*: +file format elf32-d30v
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 8a105187 0a1020c4 mulx2h r5, r6, r7 <- mulx2h r2, r3, r4
+ 8: 00f00000 0a10824a nop || mulx2h r8, r9, r10
+ 10: 00f00000 0a10b30d nop || mulx2h r11, r12, r13
+ 18: 8a111493 0a10e3d0 mulx2h r17, r18, r19 <- mulx2h r14, r15, r16
+ 20: 8a117619 0a114556 mulx2h r23, r24, r25 <- mulx2h r20, r21, r22
+ 28: 8b01d79f 0a11a6dc mul r29, r30, r31 <- mulx2h r26, r27, r28
+ 30: 8b005187 0b0020c4 mul r5, r6, r7 <- mul r2, r3, r4
+ 38: 8a10b30d 0a10824a mulx2h r11, r12, r13 <- mulx2h r8, r9, r10
+ 40: 80f00000 0b00e3d0 nop <- mul r14, r15, r16
+ 48: 00f00000 0a111493 nop || mulx2h r17, r18, r19
+ 50: 8b017619 0a114556 mul r23, r24, r25 <- mulx2h r20, r21, r22
diff --git a/gas/testsuite/gas/d30v/mul.s b/gas/testsuite/gas/d30v/mul.s
new file mode 100644
index 0000000000..fe67859506
--- /dev/null
+++ b/gas/testsuite/gas/d30v/mul.s
@@ -0,0 +1,19 @@
+# One of the rule on restricted sequence is consecutive IU instruction
+# IU: MUL, MAC, MACS, MSUB, MSUBS (a)
+# IU: MULHXpp, MULX2H, MUL2H (b)
+# This means that instructions in group (a) and in (b) should not be executed
+# in IU in consecutive cycles in the order (a)->(b). It does neither prohibit
+# executions in the reverse order (b)-> (a) nor consecutive execution of
+# group (a)->(a) or (b)->(b)
+
+ mulx2h r5,r6,r7 <- mulx2h r2,r3,r4
+ nop || mulx2h r8,r9,r10
+ nop || mulx2h r11,r12,r13
+ mulx2h r14,r15,r16
+ mulx2h r17,r18,r19
+ mulx2h r23,r24,r25 <- mulx2h r20,r21,r22
+ mul r29,r30,r31 <- mulx2h r26,r27,r28
+ mul r5, r6, r7 <- mul r2, r3, r4
+ mulx2h r11, r12, r13 <- mulx2h r8, r9, r10
+ mulx2h r17, r18, r19 <- mul r14, r15, r16
+ mul r23, r24, r25 <- mulx2h r20, r21, r22
diff --git a/gas/testsuite/gas/d30v/opt.d b/gas/testsuite/gas/d30v/opt.d
new file mode 100644
index 0000000000..b4bfa9c12f
--- /dev/null
+++ b/gas/testsuite/gas/d30v/opt.d
@@ -0,0 +1,89 @@
+#objdump: -dr
+#name: D30V optimization test
+#as: -O
+
+.*: +file format elf32-d30v
+
+Disassembly of section .text:
+
+00000000 <start>:
+ 0: 08801080 08803100 abs r1, r2 || abs r3, r4
+ 8: 02900100 02901080 notfg f0, s || notfg f1, f2
+ 10: 08801080 02901080 abs r1, r2 || notfg f1, f2
+ 18: 08001083 82907000 add.s r1, r2, r3 -> notfg c, f0
+ 20: 08001083 829001c0 add.s r1, r2, r3 -> notfg f0, c
+ 28: 00080000 00f00000 bra.s 0 \(28 <start\+0x28>\) || nop
+ 30: 08801080 88801080 abs r1, r2 -> abs r1, r2
+ 38: 00080000 00f00000 bra.s 0 \(38 <start\+0x38>\) || nop
+ 40: 002bffff 00f00000 bsr.s -8 \(38 <start\+0x38>\) || nop
+ 48: 08801080 88801080 abs r1, r2 -> abs r1, r2
+ 50: 00280000 08801080 bsr.s 0 \(50 <start\+0x50>\) || abs r1, r2
+ 58: 04001083 85007209 ldb.s r1, @\(r2, r3\) -> stb.s r7, @\(r8, r9\)
+ 60: 05007209 84001083 stb.s r7, @\(r8, r9\) -> ldb.s r1, @\(r2, r3\)
+ 68: 04007209 84001083 ldb.s r7, @\(r8, r9\) -> ldb.s r1, @\(r2, r3\)
+ 70: 05007209 85001083 stb.s r7, @\(r8, r9\) -> stb.s r1, @\(r2, r3\)
+ 78: 080030c6 854820c0 add.s r3, r3, r6 -> stw.s r2, @\(r3, 0x0\)
+ 80: 02c28105 90180000 cmple.s f0, r4, r5 -> jmp.s/tx 0 <start>
+ 88: 02c28105 a0180000 cmple.s f0, r4, r5 -> jmp.s/fx 0 <start>
+ 90: 30180000 02c28105 jmp.s/xt 0 <start> || cmple.s f0, r4, r5
+ 98: 40180000 02c28105 jmp.s/xf 0 <start> || cmple.s f0, r4, r5
+ a0: 02c28105 d0180000 cmple.s f0, r4, r5 -> jmp.s/tt 0 <start>
+ a8: 02c28105 e0180000 cmple.s f0, r4, r5 -> jmp.s/tf 0 <start>
+ b0: 10180000 02c29105 jmp.s/tx 0 <start> || cmple.s f1, r4, r5
+ b8: 02c29105 b0180000 cmple.s f1, r4, r5 -> jmp.s/xt 0 <start>
+ c0: 08084001 82c28105 add.s r4, r0, 0x1 -> cmple.s f0, r4, r5
+ c8: 08084001 02c280c5 add.s r4, r0, 0x1 || cmple.s f0, r3, r5
+ d0: 04604006 886054d4 ld2w.s r4, @\(r0, r6\) -> adds.s r5, r19, r20
+ d8: 04604006 88603154 ld2w.s r4, @\(r0, r6\) -> adds.s r3, r5, r20
+ e0: 04604006 086064d4 ld2w.s r4, @\(r0, r6\) || adds.s r6, r19, r20
+ e8: 04604006 086074d4 ld2w.s r4, @\(r0, r6\) || adds.s r7, r19, r20
+ f0: 04604006 08607014 ld2w.s r4, @\(r0, r6\) || adds.s r7, r0, r20
+ f8: 05604006 086054d4 st2w.s r4, @\(r0, r6\) || adds.s r5, r19, r20
+ 100: 05604006 08603154 st2w.s r4, @\(r0, r6\) || adds.s r3, r5, r20
+ 108: 05604006 086064d4 st2w.s r4, @\(r0, r6\) || adds.s r6, r19, r20
+ 110: 05604006 086074d4 st2w.s r4, @\(r0, r6\) || adds.s r7, r19, r20
+ 118: 05604006 08607014 st2w.s r4, @\(r0, r6\) || adds.s r7, r0, r20
+ 120: 0560a0c4 85628aec st2w.s r10, @\(r3, r4\) -> st2w.s r40, @\(r43, r44\)
+ 128: 05401083 84429aab stw.s r1, @\(r2, r3\) -> ldw.s r41, @\(r42, r43\)
+ 130: 04401083 84029aab ldw.s r1, @\(r2, r3\) -> ldb.s r41, @\(r42, r43\)
+ 138: 0444418b 88689182 ldw.s r4, @\(r6\+, r11\) -> adds.s r9, r6, 0x2
+ 140: 044c418b 08689182 ldw.s r4, @\(r6-, r11\) || adds.s r9, r6, 0x2
+ 148: 054c418b 88689182 stw.s r4, @\(r6-, r11\) -> adds.s r9, r6, 0x2
+ 150: 0440418b 08689182 ldw.s r4, @\(r6, r11\) || adds.s r9, r6, 0x2
+ 158: 0440418b 08689182 ldw.s r4, @\(r6, r11\) || adds.s r9, r6, 0x2
+ 160: 00180000 00f00000 jmp.s 0 <start> || nop
+ 168: 00380000 08801080 jsr.s 0 <start> || abs r1, r2
+ 170: 08801080 00f00000 abs r1, r2 || nop
+ 178: 00080000 00f00000 bra.s 0 \(178 <start\+0x178>\) || nop
+ 180: 00280000 08801080 bsr.s 0 \(180 <start\+0x180>\) || abs r1, r2
+ 188: 08801080 00f00000 abs r1, r2 || nop
+
+00000190 <label1>:
+ 190: 05602083 89004146 st2w.s r2, @\(r2, r3\) -> addhlll.s r4, r5, r6
+
+00000198 <label2>:
+ 198: 05508209 8990a2cc st4hb.s r8, @\(r8, r9\) -> subhllh.s r10, r11, r12
+
+000001a0 <label3>:
+ 1a0: 0460e38f 8a610452 ld2w.s r14, @\(r14, r15\) -> mulhxhl r16, r17, r18
+
+000001a8 <label4>:
+ 1a8: 04413515 8a1165d8 ldw.s r19, @\(r20, r21\) -> mulx2h r22, r23, r24
+
+000001b0 <label5>:
+ 1b0: 0421969b 8a01c75e ldh.s r25, @\(r26, r27\) -> mul2h r28, r29, r30
+
+000001b8 <label6>:
+ 1b8: 80f00000 0b001083 nop <- mul r1, r2, r3
+ 1c0: 08007209 0a404146 add.s r7, r8, r9 || mulhxll r4, r5, r6
+
+000001c8 <label7>:
+ 1c8: 04405180 0b0020c4 ldw.s r5, @\(r6, r0\) || mul r2, r3, r4
+ 1d0: 80f00000 0b007209 nop <- mul r7, r8, r9
+ 1d8: 0440a2c0 00f00000 ldw.s r10, @\(r11, r0\) || nop
+ 1e0: 80f00000 0b00c34e nop <- mul r12, r13, r14
+ 1e8: 0440f400 0b4420c4 ldw.s r15, @\(r16, r0\) || mac1 r2, r3, r4
+ 1f0: 00f00000 00f00000 nop || nop
+ 1f8: 04405180 00f00000 ldw.s r5, @\(r6, r0\) || nop
+ 200: 80f00000 0b407209 nop <- mac0 r7, r8, r9
+ 208: 0440a2c0 8440a2c0 ldw.s r10, @\(r11, r0\) -> ldw.s r10, @\(r11, r0\)
diff --git a/gas/testsuite/gas/d30v/opt.s b/gas/testsuite/gas/d30v/opt.s
new file mode 100644
index 0000000000..573330027e
--- /dev/null
+++ b/gas/testsuite/gas/d30v/opt.s
@@ -0,0 +1,216 @@
+# D30V parallel optimization test
+# assemble with "-O"
+
+ .text
+start:
+ abs r1,r2
+ abs r3,r4
+
+ notfg f0,f4
+ notfg f1,f2
+
+ abs r1,r2
+ notfg f1,f2
+
+# both change C flag
+ add r1,r2,r3
+ notfg C,f0
+
+# one uses and one changes C flag
+ add r1,r2,r3
+ notfg f0,C
+
+ bra .
+ abs r1,r2
+
+ abs r1,r2
+ bra .
+
+ bsr .
+ abs r1,r2
+
+ abs r1,r2
+ abs r1,r2
+ bsr .
+
+ ldb r1,@(r2,r3)
+ stb r7,@(r8,r9)
+
+ stb r7,@(r8,r9)
+ ldb r1,@(r2,r3)
+
+ ldb r7,@(r8,r9)
+ ldb r1,@(r2,r3)
+
+ stb r7,@(r8,r9)
+ stb r1,@(r2,r3)
+
+ add r3, r3, r6
+ stw r2, @(r3, 0)
+
+# should be serial because of conditional execution
+ cmple f0,r4,r5
+ jmp/tx 0x0
+
+ cmple f0,r4,r5
+ jmp/fx 0x0
+
+ cmple f0,r4,r5
+ jmp/xt 0x0
+
+ cmple f0,r4,r5
+ jmp/xf 0x0
+
+ cmple f0,r4,r5
+ jmp/tt 0x0
+
+ cmple f0,r4,r5
+ jmp/tf 0x0
+
+ cmple f1,r4,r5
+ jmp/tx 0x0
+
+ cmple f1,r4,r5
+ jmp/xt 0x0
+
+ # serial because of the r4 dependency
+ add r4, r0, 1
+ cmple f0, r4, r5
+
+ # parallel
+ add r4, r0, 1
+ cmple f0, r3, r5
+
+ # serial because ld2w loads r5
+ ld2w r4,@(r0,r6)
+ adds r5,r19,r20
+
+ # serial because ld2w loads r5
+ ld2w r4,@(r0,r6)
+ adds r3,r5,r20
+
+ # parallel even though ld2w uses r6 and adds changes it
+ ld2w r4,@(r0,r6)
+ adds r6,r19,r20
+
+ # parallel
+ ld2w r4,@(r0,r6)
+ adds r7,r19,r20
+
+ # parallel
+ ld2w r4,@(r0,r6)
+ adds r7,r0,r20
+
+ # parallel even though st2w uses r5 and adds modifies it
+ st2w r4,@(r0,r6)
+ adds r5,r19,r20
+
+ # parallel, both use but don't modify r5
+ st2w r4,@(r0,r6)
+ adds r3,r5,r20
+
+ # parallel even though st2w uses r6 and adds changes it
+ st2w r4,@(r0,r6)
+ adds r6,r19,r20
+
+ # parallel
+ st2w r4,@(r0,r6)
+ adds r7,r19,r20
+
+ # parallel
+ st2w r4,@(r0,r6)
+ adds r7,r0,r20
+
+# test memory dependencies
+
+ # always serial because one could overwrite the other
+ st2w r10,@(r3,r4)
+ st2w r40,@(r43,r44)
+
+ # always serial
+ stw r1,@(r2,r3)
+ ldw r41,@(r42,r43)
+
+ # reads can happen in parallel but the current architecture
+ # doesn't support it
+ ldw r1,@(r2,r3)
+ ldb r41,@(r42,r43)
+
+# test post increment and decrement dependencies
+
+ # serial
+ ldw r4,@(r6+,r11)
+ adds r9,r6,2
+
+ # parallel, modification to r6 happens last
+ adds r9,r6,2
+ ldw r4,@(r6-,r11)
+
+ # serial
+ stw r4,@(r6-,r11)
+ adds r9,r6,2
+
+ # parallel
+ ldw r4,@(r6,r11)
+ adds r9,r6,2
+
+ # parallel
+ adds r9,r6,2
+ ldw r4,@(r6,r11)
+
+# if the first instruction is a jmp, don't parallelize
+ jmp 0
+ abs r1,r2
+
+ jsr 0
+ abs r1,r2
+
+ .align 3
+
+ bra 0
+ abs r1,r2
+
+ bsr 0
+ abs r1,r2
+
+# Explicitly prohibited from parallel execution.
+# The labels are here to prevent instruction pairs
+# from being merged with following pairs.
+
+label1:
+ st2w r2, @(r2, r3)
+ addhlll r4, r5, r6
+label2:
+ st4hb r8, @(r8, r9)
+ subhllh r10, r11, r12
+label3:
+ ld2w r14, @(r14, r15)
+ mulhxhl r16, r17, r18
+label4:
+ ldw r19, @(r20, r21)
+ mulx2h r22, r23, r24
+label5:
+ ldh r25, @(r26, r27)
+ mul2h r28, r29, r30
+
+# Insertion of NOPs required to prevent pipeline clashes.
+
+label6:
+ mul r1,r2,r3
+ mulhxll r4,r5,r6
+ add r7, r8, r9
+label7:
+
+ mul r2,r3,r4
+ ldw r5, @(r6,r0)
+
+ ldw r10, @(r11, r0) <- mul r7,r8,r9
+
+ mul r12,r13,r14 -> ldw r15, @(r16, r0)
+
+ mac1 r2,r3,r4
+ ldw r5, @(r6,r0)
+
+ ldw r10, @(r11, r0) <- mac0 r7,r8,r9
+ ldw r10, @(r11, r0)
+
diff --git a/gas/testsuite/gas/d30v/reloc.d b/gas/testsuite/gas/d30v/reloc.d
new file mode 100644
index 0000000000..1de2780b48
--- /dev/null
+++ b/gas/testsuite/gas/d30v/reloc.d
@@ -0,0 +1,93 @@
+#objdump: -dr
+#name: D30V relocation test
+#as:
+
+.*: +file format elf32-d30v
+
+Disassembly of section .text:
+
+00000000 <start>:
+ 0: 88082000 80000028 add.l r2, r0, 0x28
+ 0: R_D30V_32 .text
+ 8: 88084000 80000000 add.l r4, r0, 0x0
+ 8: R_D30V_32 .data
+ 10: 88084000 80000006 add.l r4, r0, 0x6
+ 10: R_D30V_32 .data
+ 18: 88084000 80000000 add.l r4, r0, 0x0
+ 18: R_D30V_32 unk
+ 20: 80080000 80000018 bra.l 18 \(38 <cont>\)
+
+00000028 <hello>:
+ 28: 48656c6c 6f20576f .long 0x48656c6c || .long 0x6f20576f
+ 30: 726c640a 00f00000 .long 0x726c640a || nop
+
+00000038 <cont>:
+ 38: 80180000 80000048 jmp.l 48 <cont2>
+ 38: R_D30V_32 .text
+ 40: 088020c0 00f00000 abs r2, r3 || nop
+
+00000048 <cont2>:
+ 48: 000bfff7 00f00000 bra.s -48 \(0 <start>\) || nop
+ 50: 00080205 00f00000 bra.s 1028 \(1078 <exit>\) || nop
+ 58: 00180000 00f00000 jmp.s 0 <start> || nop
+ 60: 006c1ffb 00f00000 bsrtnz.s r1, -28 \(38 <cont>\) || nop
+ 68: 006c1ffa 00f00000 bsrtnz.s r1, -30 \(38 <cont>\) || nop
+ 70: 004c1ff9 00f00000 bratnz.s r1, -38 \(38 <cont>\) || nop
+ 78: 004c1ff8 00f00000 bratnz.s r1, -40 \(38 <cont>\) || nop
+ 80: 005c1007 00f00000 jmptnz.s r1, 38 <cont> || nop
+ 80: R_D30V_15 .text
+ 88: 006c11f1 00f00000 bsrtnz.s r1, f88 \(1010 <foo>\) || nop
+ 90: 005c1000 00f00000 jmptnz.s r1, 0 <start> || nop
+ 90: R_D30V_15 unk
+ 98: 006c1000 00f00000 bsrtnz.s r1, 0 \(98 <cont2\+0x50>\) || nop
+ 98: R_D30V_15_PCREL unk
+ a0: 805c1000 80000000 jmptnz.l r1, 0 <start>
+ a0: R_D30V_32 unk
+ a8: 806c1000 80000000 bsrtnz.l r1, 0 \(a8 <cont2\+0x60>\)
+ a8: R_D30V_32_PCREL unk
+ b0: 000801ec 00f00000 bra.s f60 \(1010 <foo>\) || nop
+ b8: 80080000 80000f58 bra.l f58 \(1010 <foo>\)
+ c0: 000bffe8 00f00000 bra.s -c0 \(0 <start>\) || nop
+ c8: 80180000 80000000 jmp.l 0 <start>
+ c8: R_D30V_32 .text
+ d0: 80180000 80000000 jmp.l 0 <start>
+ d0: R_D30V_32 .text
+ d8: 00180000 00f00000 jmp.s 0 <start> || nop
+ d8: R_D30V_21 .text
+ e0: 00180202 00f00000 jmp.s 1010 <foo> || nop
+ e0: R_D30V_21 .text
+ e8: 000bffe3 00f00000 bra.s -e8 \(0 <start>\) || nop
+ f0: 80080000 80000000 bra.l 0 \(f0 <cont2\+0xa8>\)
+ f0: R_D30V_32_PCREL unknown
+ f8: 80180000 80000000 jmp.l 0 <start>
+ f8: R_D30V_32 unknown
+ 100: 00180000 00f00000 jmp.s 0 <start> || nop
+ 100: R_D30V_21 unknown
+ 108: 00080000 00f00000 bra.s 0 \(108 <cont2\+0xc0>\) || nop
+ 108: R_D30V_21_PCREL unknown
+ ...
+
+00001010 <foo>:
+ 1010: 08001000 00f00000 add.s r1, r0, r0 || nop
+ 1018: 846bc000 80001070 ld2w.l r60, @\(r0, 0x1070\)
+ 1018: R_D30V_32 .text
+ 1020: 0803e000 8028000b add.s r62, r0, r0 -> bsr.s 58 \(1078 <exit>\)
+ 1028: 002bfffd 00f00000 bsr.s -18 \(1010 <foo>\) || nop
+ 1030: 000bfe03 00f00000 bra.s -fe8 \(48 <cont2>\) || nop
+ 1038: 000bfe02 00f00000 bra.s -ff0 \(48 <cont2>\) || nop
+ 1040: 00280007 00f00000 bsr.s 38 \(1078 <exit>\) || nop
+ 1048: 0018020f 00f00000 jmp.s 1078 <exit> || nop
+ 1048: R_D30V_21 .text
+ 1050: 0018020f 00f00000 jmp.s 1078 <exit> || nop
+ 1050: R_D30V_21 .text
+ 1058: 0018020f 00f00000 jmp.s 1078 <exit> || nop
+ 1058: R_D30V_21 .text
+ 1060: 80280000 80000018 bsr.l 18 \(1078 <exit>\)
+ 1068: 80180000 80001078 jmp.l 1078 <exit>
+ 1068: R_D30V_32 .text
+
+00001070 <longzero>:
+ ...
+
+00001078 <exit>:
+ 1078: 0010003e 00f00000 jmp.s r62 || nop
diff --git a/gas/testsuite/gas/d30v/reloc.s b/gas/testsuite/gas/d30v/reloc.s
new file mode 100644
index 0000000000..2a99bf9447
--- /dev/null
+++ b/gas/testsuite/gas/d30v/reloc.s
@@ -0,0 +1,68 @@
+# D30V relocation test
+
+ .text
+start:
+ add r2, r0, hello
+ add r4, r0, bar
+ add r4, r0, bar2
+ add r4, r0, unk
+ bra cont
+hello: .ascii "Hello World\n"
+ .align 3
+cont: jmp cont2
+ abs r2,r3
+cont2:
+ bra start || nop
+ bra.s exit
+ jmp 0 || nop
+ bsrtnz.s r1,cont
+ bsrtnz r1,cont
+ bratnz.s r1,cont
+ bratnz r1,cont
+ jmptnz.s r1,cont
+ bsrtnz.s r1, foo
+ jmptnz.s r1, unk
+ bsrtnz.s r1, unk
+ jmptnz r1, unk
+ bsrtnz r1, unk
+ bra.s foo
+ bra foo
+ bra start
+ jmp start
+ jmp start
+ jmp.s start
+ jmp.s foo
+ bra start
+ bra unknown
+ jmp unknown
+ jmp.s unknown
+ bra.s unknown
+
+ .data
+bar: .asciz "XYZZY"
+bar2: .long 0xdeadbeef
+
+ .text
+ .space 0xF00,0
+
+foo:
+ add r1,r0,r0
+ ld2w r60, @(r0,longzero)
+ add r62,r0,r0
+ bsr.s exit
+ bsr.s foo
+ bra.s cont2
+ bra.s cont2
+ bsr.s exit
+ jmp.s exit
+ jmp.s exit
+ jmp.s exit
+ bsr exit
+ jmp exit
+
+longzero:
+ .quad 0
+
+ .text
+exit:
+ jmp r62
diff --git a/gas/testsuite/gas/d30v/serial.l b/gas/testsuite/gas/d30v/serial.l
new file mode 100644
index 0000000000..f7a5a67076
--- /dev/null
+++ b/gas/testsuite/gas/d30v/serial.l
@@ -0,0 +1,46 @@
+.*: Assembler messages:
+.*:6: Error: Unable to mix instructions as specified
+.*:7: Error: Unable to mix instructions as specified
+.*:8: Error: Unable to mix instructions as specified
+.*:9: Error: Unable to mix instructions as specified
+GAS LISTING .*
+
+
+ 1 # serial.s
+ 2 #
+ 3 # In the following examples, the right-subinstructions
+ 4 # will never be executed. GAS should detect this.
+ 5
+ 6 \?\?\?\? 000000F0 trap r21 -> add r2, r0, r0 ; right instruction will never be executed.
+\*\*\*\* Error:Unable to mix instructions as specified
+ 6 000000F0
+ 6 000000F0
+ 6 00000090
+ 6 001500F0
+ 7 \?\?\?\? 08002000 dbt -> add r2, r0, r0 ; ditto
+\*\*\*\* Error:Unable to mix instructions as specified
+ 7 00F00000
+ 7 00B00000
+ 7 00F00000
+ 8 \?\?\?\? 08002000 rtd -> add r2, r0, r0 ; ditto
+\*\*\*\* Error:Unable to mix instructions as specified
+ 8 00F00000
+ 8 00A00000
+ 8 00F00000
+ 9 \?\?\?\? 08002000 reit -> add r2, r0, r0 ; ditto
+\*\*\*\* Error:Unable to mix instructions as specified
+ 9 00F00000
+ 9 00800000
+ 9 00F00000
+ 10 \?\?\?\? 08002000 mvtsys psw, r1 -> add r2, r0, r0 ; OK
+ 10 00F00000
+ 10 00E00040
+ 10 88002000
+ 11 \?\?\?\? 00E00042 mvtsys pswh, r1 -> add r2, r0, r0 ; OK
+ 11 88002000
+ 12 \?\?\?\? 00E00041 mvtsys pswl, r1 -> add r2, r0, r0 ; OK
+ 12 88002000
+ 13 \?\?\?\? 00E00043 mvtsys f0, r1 -> add r2, r0, r0 ; OK
+ 13 88002000
+ 14 \?\?\?\? 00E0A040 mvtsys mod_s, r1 -> add r2, r0, r0 ; OK
+ 14 88002000
diff --git a/gas/testsuite/gas/d30v/serial.s b/gas/testsuite/gas/d30v/serial.s
new file mode 100644
index 0000000000..0995d634b8
--- /dev/null
+++ b/gas/testsuite/gas/d30v/serial.s
@@ -0,0 +1,14 @@
+# serial.s
+#
+# In the following examples, the right-subinstructions
+# will never be executed. GAS should detect this.
+
+ trap r21 -> add r2, r0, r0 ; right instruction will never be executed.
+ dbt -> add r2, r0, r0 ; ditto
+ rtd -> add r2, r0, r0 ; ditto
+ reit -> add r2, r0, r0 ; ditto
+ mvtsys psw, r1 -> add r2, r0, r0 ; OK
+ mvtsys pswh, r1 -> add r2, r0, r0 ; OK
+ mvtsys pswl, r1 -> add r2, r0, r0 ; OK
+ mvtsys f0, r1 -> add r2, r0, r0 ; OK
+ mvtsys mod_s, r1 -> add r2, r0, r0 ; OK
diff --git a/gas/testsuite/gas/d30v/serial2.l b/gas/testsuite/gas/d30v/serial2.l
new file mode 100644
index 0000000000..2de04dc2db
--- /dev/null
+++ b/gas/testsuite/gas/d30v/serial2.l
@@ -0,0 +1,138 @@
+.*: Assembler messages:
+.*:5: Error: Unable to mix instructions as specified
+.*:6: Error: Unable to mix instructions as specified
+.*:8: Error: Unable to mix instructions as specified
+.*:9: Error: Unable to mix instructions as specified
+.*:11: Error: Unable to mix instructions as specified
+.*:12: Error: Unable to mix instructions as specified
+.*:13: Error: Unable to mix instructions as specified
+.*:14: Error: Unable to mix instructions as specified
+.*:16: Error: Unable to mix instructions as specified
+.*:17: Error: Unable to mix instructions as specified
+.*:18: Error: Unable to mix instructions as specified
+.*:19: Error: Unable to mix instructions as specified
+.*:21: Error: Unable to mix instructions as specified
+.*:22: Error: Unable to mix instructions as specified
+.*:23: Error: Unable to mix instructions as specified
+.*:24: Error: Unable to mix instructions as specified
+.*:26: Error: Unable to mix instructions as specified
+.*:27: Error: Unable to mix instructions as specified
+.*:28: Error: Unable to mix instructions as specified
+.*:29: Error: Unable to mix instructions as specified
+GAS LISTING .*
+
+
+ 1 # D30V serial execution test
+ 2
+ 3 .text
+ 4
+ 5 \?\?\?\? 000000F0 bra -3 -> add r3,r0,0 ; Invalid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 5 000000F0
+ 5 000000F0
+ 5 0000000B
+ 5 FFFF00F0
+ 6 \?\?\?\? 08083000 bsr -3 -> add r3,r0,0 ; Invalid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 6 00F00000
+ 6 002BFFFF
+ 6 00F00000
+ 7
+ 8 \?\?\?\? 08083000 bra/tx -3 -> add r3,r0,0 ; Valid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 8 00F00000
+ 8 100BFFFF
+ 8 00F00000
+ 9 \?\?\?\? 08083000 bsr/tx -3 -> add r3,r0,0 ; Valid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 9 00F00000
+ 9 102BFFFF
+ 9 00F00000
+ 10
+ 11 \?\?\?\? 08083000 bsr -3 -> bsr -10 ; Invalid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 11 00F00000
+ 11 002BFFFF
+ 11 00F00000
+ 12 \?\?\?\? 002BFFFE bsr -3 -> bsr/xt -10 ; Invalid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 12 00F00000
+ 12 002BFFFF
+ 12 00F00000
+ 13 \?\?\?\? 302BFFFE bsr/tx -3 -> bsr -10 ; Valid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 13 00F00000
+ 13 102BFFFF
+ 13 00F00000
+ 14 \?\?\?\? 002BFFFE bsr/tx -3 -> bsr/fx -10 ; Valid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 14 00F00000
+ 14 102BFFFF
+ 14 00F00000
+ 15
+ 16 \?\?\?\? 202BFFFE bra -3 -> bra 10 ; Invalid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 16 00F00000
+ 16 000BFFFF
+ 16 00F00000
+ 17 \?\?\?\? 00080001 bra -3 -> bra/tx 10 ; Invalid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 17 00F00000
+ 17 000BFFFF
+ GAS LISTING .*
+
+
+ 17 00F00000
+ 18 \?\?\?\? 10080001 bra/tx -3 -> bra 10 ; Valid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 18 00F00000
+ 18 100BFFFF
+ 18 00F00000
+ 19 \?\?\?\? 00080001 bra/tx -3 -> bra/fx 10 ; Valid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 19 00F00000
+ 19 100BFFFF
+ 19 00F00000
+ 20
+ 21 \?\?\?\? 20080001 bsr -3 -> bra 10 ; Invalid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 21 00F00000
+ 21 002BFFFF
+ 21 00F00000
+ 22 \?\?\?\? 00080001 bsr -3 -> bra/tx 10 ; Invalid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 22 00F00000
+ 22 002BFFFF
+ 22 00F00000
+ 23 \?\?\?\? 10080001 bsr/tx -3 -> bra 10 ; Valid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 23 00F00000
+ 23 102BFFFF
+ 23 00F00000
+ 24 \?\?\?\? 00080001 bsr/tx -3 -> bra/fx 10 ; Valid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 24 00F00000
+ 24 102BFFFF
+ 24 00F00000
+ 25
+ 26 \?\?\?\? 20080001 bra -3 -> bsr 10 ; Invalid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 26 00F00000
+ 26 000BFFFF
+ 26 00F00000
+ 27 \?\?\?\? 00280001 bra -3 -> bsr/tx 10 ; Invalid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 27 00F00000
+ 27 000BFFFF
+ 27 00F00000
+ 28 \?\?\?\? 10280001 bra/tx -3 -> bsr 10 ; Valid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 28 00F00000
+ 28 100BFFFF
+ 28 00F00000
+ 29 \?\?\?\? 00280001 bra/tx -3 -> bsr/fx 10 ; Valid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 29 00F00000
+ 29 100BFFFF
+ 29 00F00000
+ 29 20280001
diff --git a/gas/testsuite/gas/d30v/serial2.s b/gas/testsuite/gas/d30v/serial2.s
new file mode 100644
index 0000000000..0453159022
--- /dev/null
+++ b/gas/testsuite/gas/d30v/serial2.s
@@ -0,0 +1,29 @@
+# D30V serial execution test
+
+ .text
+
+ bra -3 -> add r3,r0,0 ; Invalid
+ bsr -3 -> add r3,r0,0 ; Invalid
+
+ bra/tx -3 -> add r3,r0,0 ; Valid
+ bsr/tx -3 -> add r3,r0,0 ; Valid
+
+ bsr -3 -> bsr -10 ; Invalid
+ bsr -3 -> bsr/xt -10 ; Invalid
+ bsr/tx -3 -> bsr -10 ; Valid
+ bsr/tx -3 -> bsr/fx -10 ; Valid
+
+ bra -3 -> bra 10 ; Invalid
+ bra -3 -> bra/tx 10 ; Invalid
+ bra/tx -3 -> bra 10 ; Valid
+ bra/tx -3 -> bra/fx 10 ; Valid
+
+ bsr -3 -> bra 10 ; Invalid
+ bsr -3 -> bra/tx 10 ; Invalid
+ bsr/tx -3 -> bra 10 ; Valid
+ bsr/tx -3 -> bra/fx 10 ; Valid
+
+ bra -3 -> bsr 10 ; Invalid
+ bra -3 -> bsr/tx 10 ; Invalid
+ bra/tx -3 -> bsr 10 ; Valid
+ bra/tx -3 -> bsr/fx 10 ; Valid
diff --git a/gas/testsuite/gas/d30v/serial2O.l b/gas/testsuite/gas/d30v/serial2O.l
new file mode 100644
index 0000000000..d9eb05cb1a
--- /dev/null
+++ b/gas/testsuite/gas/d30v/serial2O.l
@@ -0,0 +1,99 @@
+.*: Assembler messages:
+.*:5: Error: Unable to mix instructions as specified
+.*:6: Error: Unable to mix instructions as specified
+.*:11: Error: Unable to mix instructions as specified
+.*:12: Error: Unable to mix instructions as specified
+.*:16: Error: Unable to mix instructions as specified
+.*:17: Error: Unable to mix instructions as specified
+.*:21: Error: Unable to mix instructions as specified
+.*:22: Error: Unable to mix instructions as specified
+.*:26: Error: Unable to mix instructions as specified
+.*:27: Error: Unable to mix instructions as specified
+GAS LISTING .*
+
+
+ 1 # D30V serial execution test
+ 2
+ 3 .text
+ 4
+ 5 \?\?\?\? 000000F0 bra -3 -> add r3,r0,0 ; Invalid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 5 000000F0
+ 5 000000F0
+ 5 0000000B
+ 5 FFFF00F0
+ 6 \?\?\?\? 08083000 bsr -3 -> add r3,r0,0 ; Invalid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 6 00F00000
+ 6 002BFFFF
+ 6 00F00000
+ 7
+ 8 \?\?\?\? 08083000 bra/tx -3 -> add r3,r0,0 ; Valid
+ 8 00F00000
+ 8 100BFFFF
+ 8 88083000
+ 9 \?\?\?\? 102BFFFF bsr/tx -3 -> add r3,r0,0 ; Valid
+ 9 88083000
+ 10
+ 11 \?\?\?\? 002BFFFF bsr -3 -> bsr -10 ; Invalid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 11 00F00000
+ 12 \?\?\?\? 002BFFFE bsr -3 -> bsr/xt -10 ; Invalid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 12 00F00000
+ 12 002BFFFF
+ 12 00F00000
+ 13 \?\?\?\? 302BFFFE bsr/tx -3 -> bsr -10 ; Valid
+ 13 00F00000
+ 13 102BFFFF
+ 13 802BFFFE
+ 14 \?\?\?\? 102BFFFF bsr/tx -3 -> bsr/fx -10 ; Valid
+ 14 A02BFFFE
+ 15
+ 16 \?\?\?\? 000BFFFF bra -3 -> bra 10 ; Invalid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 16 00F00000
+ 17 \?\?\?\? 00080001 bra -3 -> bra/tx 10 ; Invalid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 17 00F00000
+ 17 000BFFFF
+ 17 00F00000
+ 18 \?\?\?\? 10080001 bra/tx -3 -> bra 10 ; Valid
+ 18 00F00000
+ 18 100BFFFF
+ 18 80080001
+ 19 \?\?\?\? 100BFFFF bra/tx -3 -> bra/fx 10 ; Valid
+ 19 A0080001
+ 20
+ 21 \?\?\?\? 002BFFFF bsr -3 -> bra 10 ; Invalid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 21 00F00000
+ 22 \?\?\?\? 00080001 bsr -3 -> bra/tx 10 ; Invalid
+ GAS LISTING .*
+
+
+\*\*\*\* Error:Unable to mix instructions as specified
+ 22 00F00000
+ 22 002BFFFF
+ 22 00F00000
+ 23 \?\?\?\? 10080001 bsr/tx -3 -> bra 10 ; Valid
+ 23 00F00000
+ 23 102BFFFF
+ 23 80080001
+ 24 \?\?\?\? 102BFFFF bsr/tx -3 -> bra/fx 10 ; Valid
+ 24 A0080001
+ 25
+ 26 \?\?\?\? 000BFFFF bra -3 -> bsr 10 ; Invalid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 26 00F00000
+ 27 \?\?\?\? 00280001 bra -3 -> bsr/tx 10 ; Invalid
+\*\*\*\* Error:Unable to mix instructions as specified
+ 27 00F00000
+ 27 000BFFFF
+ 27 00F00000
+ 28 \?\?\?\? 10280001 bra/tx -3 -> bsr 10 ; Valid
+ 28 00F00000
+ 28 100BFFFF
+ 28 80280001
+ 29 \?\?\?\? 100BFFFF bra/tx -3 -> bsr/fx 10 ; Valid
+ 29 A0280001
diff --git a/gas/testsuite/gas/d30v/serial2O.s b/gas/testsuite/gas/d30v/serial2O.s
new file mode 100644
index 0000000000..0453159022
--- /dev/null
+++ b/gas/testsuite/gas/d30v/serial2O.s
@@ -0,0 +1,29 @@
+# D30V serial execution test
+
+ .text
+
+ bra -3 -> add r3,r0,0 ; Invalid
+ bsr -3 -> add r3,r0,0 ; Invalid
+
+ bra/tx -3 -> add r3,r0,0 ; Valid
+ bsr/tx -3 -> add r3,r0,0 ; Valid
+
+ bsr -3 -> bsr -10 ; Invalid
+ bsr -3 -> bsr/xt -10 ; Invalid
+ bsr/tx -3 -> bsr -10 ; Valid
+ bsr/tx -3 -> bsr/fx -10 ; Valid
+
+ bra -3 -> bra 10 ; Invalid
+ bra -3 -> bra/tx 10 ; Invalid
+ bra/tx -3 -> bra 10 ; Valid
+ bra/tx -3 -> bra/fx 10 ; Valid
+
+ bsr -3 -> bra 10 ; Invalid
+ bsr -3 -> bra/tx 10 ; Invalid
+ bsr/tx -3 -> bra 10 ; Valid
+ bsr/tx -3 -> bra/fx 10 ; Valid
+
+ bra -3 -> bsr 10 ; Invalid
+ bra -3 -> bsr/tx 10 ; Invalid
+ bra/tx -3 -> bsr 10 ; Valid
+ bra/tx -3 -> bsr/fx 10 ; Valid
diff --git a/gas/testsuite/gas/d30v/warn_oddreg.l b/gas/testsuite/gas/d30v/warn_oddreg.l
new file mode 100644
index 0000000000..f1fb43cb2c
--- /dev/null
+++ b/gas/testsuite/gas/d30v/warn_oddreg.l
@@ -0,0 +1,40 @@
+.*: Assembler messages:
+.*:5: Warning: Odd numbered register used as target of multi-register instruction
+.*:6: Warning: Odd numbered register used as target of multi-register instruction
+.*:7: Warning: Odd numbered register used as target of multi-register instruction
+.*:8: Warning: Odd numbered register used as target of multi-register instruction
+.*:9: Warning: Odd numbered register used as target of multi-register instruction
+.*:10: Warning: Odd numbered register used as target of multi-register instruction
+.*:11: Warning: Odd numbered register used as target of multi-register instruction
+.*:12: Warning: Odd numbered register used as target of multi-register instruction
+GAS LISTING .*
+
+
+ 1 # GAS should print a warning when an odd register is used as a target
+ 2 # of multi-word instructions: ld2w, ld4bh, ld4bhu, ld2h, st2w, st4hb, st2h,
+ 3 # and mulx2h
+ 4
+ 5 0000 05681000 st2w r1, @(r0, 0) || nop
+.* Warning:Odd numbered register used as target of multi-register instruction
+ 5 00F00000
+ 6 0008 04681000 ld2w r1, @(r0, 0) || nop
+.* Warning:Odd numbered register used as target of multi-register instruction
+ 6 00F00000
+ 7 0010 04581000 ld4bh r1, @(r0, 0) || nop
+.* Warning:Odd numbered register used as target of multi-register instruction
+ 7 00F00000
+ 8 0018 04D81000 ld4bhu r1, @(r0, 0) || nop
+.* Warning:Odd numbered register used as target of multi-register instruction
+ 8 00F00000
+ 9 0020 04381000 ld2h r1, @(r0, 0) || nop
+.* Warning:Odd numbered register used as target of multi-register instruction
+ 9 00F00000
+ 10 0028 05581000 st4hb r1, @(r0, 0) || nop
+.* Warning:Odd numbered register used as target of multi-register instruction
+ 10 00F00000
+ 11 0030 05381000 st2h r1, @(r0, 0) || nop
+.* Warning:Odd numbered register used as target of multi-register instruction
+ 11 00F00000
+ 12 0038 00F00000 nop || mulx2h r1, r5, r6
+.* Warning:Odd numbered register used as target of multi-register instruction
+ 12 0A101146
diff --git a/gas/testsuite/gas/d30v/warn_oddreg.s b/gas/testsuite/gas/d30v/warn_oddreg.s
new file mode 100644
index 0000000000..c09f750948
--- /dev/null
+++ b/gas/testsuite/gas/d30v/warn_oddreg.s
@@ -0,0 +1,12 @@
+# GAS should print a warning when an odd register is used as a target
+# of multi-word instructions: ld2w, ld4bh, ld4bhu, ld2h, st2w, st4hb, st2h,
+# and mulx2h
+
+st2w r1, @(r0, 0) || nop
+ld2w r1, @(r0, 0) || nop
+ld4bh r1, @(r0, 0) || nop
+ld4bhu r1, @(r0, 0) || nop
+ld2h r1, @(r0, 0) || nop
+st4hb r1, @(r0, 0) || nop
+st2h r1, @(r0, 0) || nop
+nop || mulx2h r1, r5, r6
diff --git a/gas/testsuite/gas/fr30/allinsn.d b/gas/testsuite/gas/fr30/allinsn.d
new file mode 100644
index 0000000000..2bac763d91
--- /dev/null
+++ b/gas/testsuite/gas/fr30/allinsn.d
@@ -0,0 +1,440 @@
+#as:
+#objdump: -dr
+#name: allinsn
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+0000 <add>:
+ 0: a6 01 add r0,r1
+ 2: a4 02 add 0x0,r2
+
+0+0004 <add2>:
+ 4: a5 f3 add2 -1,r3
+
+0+0006 <addc>:
+ 6: a7 45 addc r4,r5
+
+0+0008 <addn>:
+ 8: a2 67 addn r6,r7
+ a: a0 f8 addn 0xf,r8
+
+0+000c <addn2>:
+ c: a1 09 addn2 -16,r9
+
+0+000e <sub>:
+ e: ac ab sub r10,r11
+
+0+0010 <subc>:
+ 10: ad cd subc r12,r13
+
+0+0012 <subn>:
+ 12: ae ef subn r14,r15
+
+0+0014 <cmp>:
+ 14: aa de cmp r13,r14
+ 16: a8 1f cmp 0x1,r15
+
+0+0018 <cmp2>:
+ 18: a9 10 cmp2 -15,r0
+
+0+001a <and>:
+ 1a: 82 12 and r1,r2
+ 1c: 84 34 and r3,@r4
+
+0+001e <andh>:
+ 1e: 85 56 andh r5,@r6
+
+0+0020 <andb>:
+ 20: 86 78 andb r7,@r8
+
+0+0022 <or>:
+ 22: 92 9a or r9,r10
+ 24: 94 bc or r11,@r12
+
+0+0026 <orh>:
+ 26: 95 de orh r13,@r14
+
+0+0028 <orb>:
+ 28: 96 fd orb r15,@r13
+
+0+002a <eor>:
+ 2a: 9a ef eor r14,r15
+ 2c: 9c 01 eor r0,@r1
+
+0+002e <eorh>:
+ 2e: 9d 23 eorh r2,@r3
+
+0+0030 <eorb>:
+ 30: 9e 45 eorb r4,@r5
+
+0+0032 <bandl>:
+ 32: 80 f6 bandl 0xf,@r6
+
+0+0034 <nadh>:
+ 34: 81 77 bandh 0x7,@r7
+
+0+0036 <borl>:
+ 36: 90 38 borl 0x3,@r8
+
+0+0038 <borh>:
+ 38: 91 d9 borh 0xd,@r9
+
+0+003a <beorl>:
+ 3a: 98 fa beorl 0xf,@r10
+
+0+003c <beorh>:
+ 3c: 99 1b beorh 0x1,@r11
+
+0+003e <btstl>:
+ 3e: 88 0c btstl 0x0,@r12
+
+0+0040 <btsth>:
+ 40: 89 8d btsth 0x8,@r13
+
+0+0042 <mul>:
+ 42: af ef mul r14,r15
+
+0+0044 <mulu>:
+ 44: ab de mulu r13,r14
+
+0+0046 <muluh>:
+ 46: bb f0 muluh r15,r0
+
+0+0048 <mulh>:
+ 48: bf 12 mulh r1,r2
+
+0+004a <div0s>:
+ 4a: 97 43 div0s r3
+
+0+004c <div0u>:
+ 4c: 97 54 div0u r4
+
+0+004e <div1>:
+ 4e: 97 65 div1 r5
+
+0+0050 <div2>:
+ 50: 97 76 div2 r6
+
+0+0052 <div3>:
+ 52: 9f 60 div3
+
+0+0054 <div4s>:
+ 54: 9f 70 div4s
+
+0+0056 <lsl>:
+ 56: b6 78 lsl r7,r8
+ 58: b4 39 lsl 0x3,r9
+
+0+005a <lsl2>:
+ 5a: b5 0a lsl2 0x0,r10
+
+0+005c <lsr>:
+ 5c: b2 bc lsr r11,r12
+ 5e: b0 fd lsr 0xf,r13
+
+0+0060 <lsr2>:
+ 60: b1 fe lsr2 0xf,r14
+
+0+0062 <asr>:
+ 62: ba fd asr r15,r13
+ 64: b8 6e asr 0x6,r14
+
+0+0066 <asr2>:
+ 66: b9 7f asr2 0x7,r15
+
+0+0068 <ldi_8>:
+ 68: cf f2 ldi:8 0xff,r2
+
+0+006a <ld>:
+ 6a: 04 34 ld @r3,r4
+ 6c: 00 56 ld @\(r13,r5\),r6
+ 6e: 27 f7 ld @\(r14,508\),r7
+ 70: 03 f8 ld @\(r15,0x3c\),r8
+ 72: 07 09 ld @r15\+,r9
+ 74: 07 90 ld @r15\+,ps
+ 76: 07 80 ld @r15\+,tbr
+ 78: 07 81 ld @r15\+,rp
+ 7a: 07 82 ld @r15\+,ssp
+
+0+007c <lduh>:
+ 7c: 05 ab lduh @r10,r11
+ 7e: 01 cd lduh @\(r13,r12\),r13
+ 80: 48 0f lduh @\(r14,-256\),r15
+
+0+0082 <ldub>:
+ 82: 06 de ldub @r13,r14
+ 84: 02 f0 ldub @\(r13,r15\),r0
+ 86: 68 01 ldub @\(r14,-128\),r1
+
+0+0088 <st>:
+ 88: 14 32 st r2,@r3
+ 8a: 10 54 st r4,@\(r13,r5\)
+ 8c: 38 06 st r6,@\(r14,-512\)
+ 8e: 13 f7 st r7,@\(r15,0x3c\)
+ 90: 17 08 st r8,@-r15
+ 92: 17 84 st mdh,@-r15
+ 94: 17 90 st ps,@-r15
+
+0+0096 <sth>:
+ 96: 15 a9 sth r9,@r10
+ 98: 11 cb sth r11,@\(r13,r12\)
+ 9a: 54 0d sth r13,@\(r14,128\)
+
+0+009c <stb>:
+ 9c: 16 fe stb r14,@r15
+ 9e: 12 10 stb r0,@\(r13,r1\)
+ a0: 78 02 stb r2,@\(r14,-128\)
+
+0+00a2 <mov>:
+ a2: 8b 34 mov r3,r4
+ a4: b7 55 mov mdl,r5
+ a6: 17 16 mov ps,r6
+ a8: b3 37 mov r7,usp
+ aa: 07 18 mov r8,ps
+
+0+00ac <jmp>:
+ ac: 97 09 jmp @r9
+
+0+00ae <ret>:
+ ae: 97 20 ret
+
+0+00b0 <bra>:
+ b0: e0 a7 bra 0 \<add\>
+
+0+00b2 <bno>:
+ b2: e1 a6 bno 0 \<add\>
+
+0+00b4 <beq>:
+ b4: e2 a5 beq 0 \<add\>
+
+0+00b6 <bne>:
+ b6: e3 a4 bne 0 \<add\>
+
+0+00b8 <bc>:
+ b8: e4 a3 bc 0 \<add\>
+
+0+00ba <bnc>:
+ ba: e5 a2 bnc 0 \<add\>
+
+0+00bc <bn>:
+ bc: e6 a1 bn 0 \<add\>
+
+0+00be <bp>:
+ be: e7 a0 bp 0 \<add\>
+
+0+00c0 <bv>:
+ c0: e8 9f bv 0 \<add\>
+
+0+00c2 <bnv>:
+ c2: e9 9e bnv 0 \<add\>
+
+0+00c4 <blt>:
+ c4: ea 9d blt 0 \<add\>
+
+0+00c6 <bge>:
+ c6: eb 9c bge 0 \<add\>
+
+0+00c8 <ble>:
+ c8: ec 9b ble 0 \<add\>
+
+0+00ca <bgt>:
+ ca: ed 9a bgt 0 \<add\>
+
+0+00cc <bls>:
+ cc: ee 99 bls 0 \<add\>
+
+0+00ce <bhi>:
+ ce: ef 98 bhi 0 \<add\>
+
+0+00d0 <jmp_d>:
+ d0: 9f 0b jmp:d @r11
+ d2: 9f a0 nop
+
+0+00d4 <ret_d>:
+ d4: 9f 20 ret:d
+ d6: 9f a0 nop
+
+0+00d8 <bra_d>:
+ d8: f0 fb bra:d d0 \<jmp_d\>
+ da: 9f a0 nop
+
+0+00dc <bno_d>:
+ dc: f1 f9 bno:d d0 \<jmp_d\>
+ de: 9f a0 nop
+
+0+00e0 <beq_d>:
+ e0: f2 f7 beq:d d0 \<jmp_d\>
+ e2: 9f a0 nop
+
+0+00e4 <bne_d>:
+ e4: f3 f5 bne:d d0 \<jmp_d\>
+ e6: 9f a0 nop
+
+0+00e8 <bc_d>:
+ e8: f4 f3 bc:d d0 \<jmp_d\>
+ ea: 9f a0 nop
+
+0+00ec <bnc_d>:
+ ec: f5 f1 bnc:d d0 \<jmp_d\>
+ ee: 9f a0 nop
+
+0+00f0 <bn_d>:
+ f0: f6 ef bn:d d0 \<jmp_d\>
+ f2: 9f a0 nop
+
+0+00f4 <bp_d>:
+ f4: f7 ed bp:d d0 \<jmp_d\>
+ f6: 9f a0 nop
+
+0+00f8 <bv_d>:
+ f8: f8 eb bv:d d0 \<jmp_d\>
+ fa: 9f a0 nop
+
+0+00fc <bnv_d>:
+ fc: f9 e9 bnv:d d0 \<jmp_d\>
+ fe: 9f a0 nop
+
+0+0100 <blt_d>:
+ 100: fa e7 blt:d d0 \<jmp_d\>
+ 102: 9f a0 nop
+
+0+0104 <bge_d>:
+ 104: fb e5 bge:d d0 \<jmp_d\>
+ 106: 9f a0 nop
+
+0+0108 <ble_d>:
+ 108: fc e3 ble:d d0 \<jmp_d\>
+ 10a: 9f a0 nop
+
+0+010c <bgt_d>:
+ 10c: fd e1 bgt:d d0 \<jmp_d\>
+ 10e: 9f a0 nop
+
+0+0110 <bls_d>:
+ 110: fe df bls:d d0 \<jmp_d\>
+ 112: 9f a0 nop
+
+0+0114 <bhi_d>:
+ 114: ff dd bhi:d d0 \<jmp_d\>
+ 116: 9f a0 nop
+
+0+0118 <ldres>:
+ 118: bc 82 ldres @r2\+,0x8
+
+0+011a <stres>:
+ 11a: bd f3 stres 0xf,@r3\+
+
+0+011c <nop>:
+ 11c: 9f a0 nop
+
+0+011e <andccr>:
+ 11e: 83 ff andccr 0xff
+
+0+0120 <orccr>:
+ 120: 93 7d orccr 0x7d
+
+0+0122 <stilm>:
+ 122: 87 61 stilm 0x61
+
+0+0124 <addsp>:
+ 124: a3 80 addsp -512
+
+0+0126 <extsb>:
+ 126: 97 89 extsb r9
+
+0+0128 <extub>:
+ 128: 97 9a extub r10
+
+0+012a <extsh>:
+ 12a: 97 ab extsh r11
+
+0+012c <extuh>:
+ 12c: 97 bc extuh r12
+
+0+012e <enter>:
+ 12e: 0f ff enter 0x3fc
+
+0+0130 <leave>:
+ 130: 9f 90 leave
+
+0+0132 <xchb>:
+ 132: 8a ef xchb @r14,r15
+
+0+0134 <ldi_32>:
+ 134: 9f 80 12 34 ldi:32 0x12345678,r0
+ 138: 56 78
+
+0+013a <copop>:
+ 13a: 9f cf 01 34 copop 0xf,0x1,cr3,cr4
+ 13e: 9f cf 04 56 copop 0xf,0x4,cr5,cr6
+ 142: 9f cf ff 70 copop 0xf,0xff,cr7,cr0
+
+0+0146 <copld>:
+ 146: 9f d0 00 40 copld 0x0,0x0,r4,cr0
+
+0+014a <copst>:
+ 14a: 9f e7 02 15 copst 0x7,0x2,cr1,r5
+
+0+014e <copsv>:
+ 14e: 9f f8 03 26 copsv 0x8,0x3,cr2,r6
+
+0+0152 <ldm0>:
+ 152: 8c 8d ldm0 \(r0,r2,r3,r7\)
+
+0+0154 <ldm1>:
+ 154: 8d 89 ldm1 \(r8,r11,r15\)
+
+0+0156 <stm0>:
+ 156: 8e 30 stm0 \(r2,r3\)
+
+0+0158 <stm1>:
+ 158: 8f 06 stm1 \(r13,r14\)
+
+0+015a <call>:
+ 15a: d7 52 call 0 \<add\>
+ 15c: 97 1a call @r10
+
+0+015e <call_d>:
+ 15e: df 50 call:d 0 \<add\>
+ 160: 9f a0 nop
+ 162: 9f 1c call:d @r12
+ 164: 9f a0 nop
+
+0+0166 <dmov>:
+ 166: 08 22 dmov @0x88,r13
+ 168: 18 15 dmov r13,@0x54
+ 16a: 0c 11 dmov @0x44,@r13\+
+ 16c: 1c 00 dmov @r13\+,@0x0
+ 16e: 0b 0b dmov @0x2c,@-r15
+ 170: 1b 09 dmov @r15\+,@0x24
+
+0+0172 <dmovh>:
+ 172: 09 44 dmovh @0x88,r13
+ 174: 19 29 dmovh r13,@0x52
+ 176: 0d 1a dmovh @0x34,@r13\+
+ 178: 1d 29 dmovh @r13\+,@0x52
+
+0+017a <dmovb>:
+ 17a: 0a 91 dmovb @0x91,r13
+ 17c: 1a 53 dmovb r13,@0x53
+ 17e: 0e 47 dmovb @0x47,@r13\+
+ 180: 1e 00 dmovb @r13\+,@0x0
+
+0+0182 <ldi_20>:
+ 182: 9b f1 ff ff ldi:20 0xfffff,r1
+
+0+0186 <finish>:
+ 186: 9f 80 00 00 ldi:32 0x8000,r0
+ 18a: 80 00
+ 18c: b3 20 mov r0,ssp
+ 18e: 9f 80 00 00 ldi:32 0x1,r0
+ 192: 00 01
+ 194: 1f 0a int 0xa
+
+0+0196 <inte>:
+ 196: 9f 30 inte
+
+0+0198 <reti>:
+ 198: 97 30 reti
diff --git a/gas/testsuite/gas/fr30/allinsn.exp b/gas/testsuite/gas/fr30/allinsn.exp
new file mode 100644
index 0000000000..eccfe18782
--- /dev/null
+++ b/gas/testsuite/gas/fr30/allinsn.exp
@@ -0,0 +1,5 @@
+# FR30 assembler testsuite.
+
+if [istarget fr30*-*-*] {
+ run_dump_test "allinsn"
+}
diff --git a/gas/testsuite/gas/fr30/allinsn.s b/gas/testsuite/gas/fr30/allinsn.s
new file mode 100644
index 0000000000..683d24ae77
--- /dev/null
+++ b/gas/testsuite/gas/fr30/allinsn.s
@@ -0,0 +1,434 @@
+ .data
+foodata: .word 42
+ .text
+footext:
+ .global add
+add:
+ add r0, r1
+ add #0, r2
+ .global add2
+add2:
+ add2 #-1, r3
+ .global addc
+addc:
+ addc r4, r5
+ .global addn
+addn:
+ addn r6, r7
+ addn #15, r8
+ .global addn2
+addn2:
+ addn2 #-16, r9
+ .global sub
+sub:
+ sub r10, r11
+ .global subc
+subc:
+ subc r12, r13
+ .global subn
+subn:
+ subn r14, r15
+ .global cmp
+cmp:
+ cmp ac, fp
+ cmp #1, sp
+ .global cmp2
+cmp2:
+ cmp2 #-15, r0
+ .global and
+and:
+ and r1, r2
+ and r3, @r4
+ .global andh
+andh:
+ andh r5, @r6
+ .global andb
+andb:
+ andb r7, @r8
+ .global or
+or:
+ or r9, r10
+ or r11, @r12
+ .global orh
+orh:
+ orh r13, @r14
+ .global orb
+orb:
+ orb r15, @ac
+ .global eor
+eor:
+ eor fp, sp
+ eor r0, @r1
+ .global eorh
+eorh:
+ eorh r2, @r3
+ .global eorb
+eorb:
+ eorb r4, @r5
+ .global bandl
+bandl:
+ bandl #15, @r6
+ .global bandh
+nadh:
+ bandh #7, @r7
+ .global borl
+borl:
+ borl #3, @r8
+ .global borh
+borh:
+ borh #13, @r9
+ .global beorl
+beorl:
+ beorl #15, @r10
+ .global beorh
+beorh:
+ beorh #1, @r11
+ .global btstl
+btstl:
+ btstl #0, @r12
+ .global btsth
+btsth:
+ btsth #8, @r13
+ .global mul
+mul:
+ mul r14, r15
+ .global mulu
+mulu:
+ mulu ac, fp
+ .global muluh
+muluh:
+ muluh sp, r0
+ .global mulh
+mulh:
+ mulh r1, r2
+ .global div0s
+div0s:
+ div0s r3
+ .global div0u
+div0u:
+ div0u r4
+ .global div1
+div1:
+ div1 r5
+ .global div2
+div2:
+ div2 r6
+ .global div3
+div3:
+ div3
+ .global div4s
+div4s:
+ div4s
+ .global lsl
+lsl:
+ lsl r7, r8
+ lsl #3, r9
+ .global lsl2
+lsl2:
+ lsl2 #0, r10
+ .global lsr
+lsr:
+ lsr r11, r12
+ lsr #15, r13
+ .global lsr2
+lsr2:
+ lsr2 #15, r14
+ .global asr
+asr:
+ asr r15, ac
+ asr #6, fp
+ .global asr2
+asr2:
+ asr2 #7, sp
+ .global ldi_8
+ldi_8:
+ ldi:8 #0xff, r2
+ .global ld
+ld:
+ ld @r3, r4
+ ld @(R13, r5), r6
+ ld @(R14, 0x1fc), r7
+ ld @(R15, 0x3c), r8
+ ld @r15+, r9
+ ld @r15+, ps
+ ld @R15+, tbr
+ ld @r15+, rp
+ ld @R15+, ssp
+ .global lduh
+lduh:
+ lduh @r10, r11
+ lduh @(r13, r12), r13
+ lduh @(r14, #-256), r15
+ .global ldub
+ldub:
+ ldub @ac, fp
+ ldub @(r13, sp), r0
+ ldub @(r14, -128), r1
+ .global st
+st:
+ st r2, @r3
+ st r4, @(r13, r5)
+ st r6, @(r14, -512)
+ st r7, @(r15, 0x3c)
+ st r8, @ - r15
+ st MDH, @-r15
+ st PS, @ - r15
+ .global lsth
+sth:
+ sth r9, @r10
+ sth r11, @(r13, r12)
+ sth r13, @(r14, 128)
+ .global stb
+stb:
+ STB r14, @r15
+ stb r0, @(r13, r1)
+ STB r2, @(r14, -128)
+ .global mov
+mov:
+ mov r3, r4
+ MOV mdl, r5
+ mov ps, r6
+ mov r7, usp
+ mov r8, ps
+ .global jmp
+jmp:
+ jmp @r9
+ .global ret
+ret:
+ ret
+ .global bra
+bra:
+ bra footext
+ .global bno
+bno:
+ bno footext
+ .global beq
+beq:
+ beq footext
+ .global bne
+bne:
+ bne footext
+ .global bc
+bc:
+ bc footext
+ .global bnc
+bnc:
+ bnc footext
+ .global bn
+bn:
+ bn footext
+ .global bp
+bp:
+ bp footext
+ .global bv
+bv:
+ bv footext
+ .global bnv
+bnv:
+ bnv footext
+ .global blt
+blt:
+ blt footext
+ .global bge
+bge:
+ bge footext
+ .global ble
+ble:
+ ble footext
+ .global bgt
+bgt:
+ bgt footext
+ .global bls
+bls:
+ bls footext
+ .global bhi
+bhi:
+ bhi footext
+delay_footext:
+ .global jmp_d
+jmp_d:
+ jmp:d @r11
+ nop
+ .global ret_d
+ret_d:
+ ret:d
+ nop
+ .global bra_d
+bra_d:
+ bra:D delay_footext
+ nop
+ .global bno_d
+bno_d:
+ bno:d delay_footext
+ nop
+ .global beq_d
+beq_d:
+ beq:D delay_footext
+ nop
+ .global bne_d
+bne_d:
+ bne:d delay_footext
+ nop
+ .global bc_d
+bc_d:
+ bc:d delay_footext
+ nop
+ .global bnc_d
+bnc_d:
+ bnc:d delay_footext
+ nop
+ .global bn_d
+bn_d:
+ bn:d delay_footext
+ nop
+ .global bp_d
+bp_d:
+ bp:d delay_footext
+ nop
+ .global bv_d
+bv_d:
+ bv:d delay_footext
+ nop
+ .global bnv_d
+bnv_d:
+ bnv:d delay_footext
+ nop
+ .global blt_d
+blt_d:
+ blt:d delay_footext
+ nop
+ .global bge_d
+bge_d:
+ bge:d delay_footext
+ nop
+ .global ble_d
+ble_d:
+ ble:d delay_footext
+ nop
+ .global bgt_d
+bgt_d:
+ bgt:d delay_footext
+ nop
+ .global bls_d
+bls_d:
+ bls:d delay_footext
+ nop
+ .global bhi_d
+bhi_d:
+ bhi:d delay_footext
+ nop
+ .global ldres
+ldres:
+ ldres @r2+, #8
+ .global stres
+stres:
+ stres #15, @r3+
+ .global nop
+nop:
+ nop
+ .global andccr
+andccr:
+ andccr #255
+ .global orccr
+orccr:
+ orccr #125
+ .global stilm
+stilm:
+ stilm #97
+ .global addsp
+addsp:
+ addsp #-512
+ .global extsb
+extsb:
+ extsb r9
+ .global extub
+extub:
+ extub r10
+ .global extsh
+extsh:
+ extsh r11
+ .global extuh
+extuh:
+ extuh r12
+ .global enter
+enter:
+ enter #1020
+ .global leave
+leave:
+ leave
+ .global xchb
+xchb:
+ xchb @r14, r15
+ .global ldi_32
+ldi_32:
+ ldi:32 #0x12345678, r0
+ .global copop
+copop:
+ copop #15, #1, cr3, cr4
+ copop #15, #4, cr5, cr6
+ copop #15, #255, cr7, cr0
+ .global copld
+copld:
+ copld #0, #0, r4, cr0
+ .global copst
+copst:
+ copst #7, #2, cr1, r5
+ .global copsv
+copsv:
+ copsv #8, #3, cr2, r6
+ .global ldm0
+ldm0:
+ ldm0 (r0, r2, r3, r7)
+ .global ldm1
+ldm1:
+ ldm1 (r8, r11, r15)
+ .global stm0
+stm0:
+ stm0 (r2, r3)
+ .global stm1
+stm1:
+ stm1 (r13, r14)
+ .global call
+call:
+ call footext
+ call @r10
+ .global call_d
+call_d:
+ call:D footext
+ nop
+ call:d @r12
+ nop
+ .global dmov
+dmov:
+ dmov @0x88, r13
+ dmov r13, @0x54
+ dmov @0x44, @r13+
+ dmov @R13+, @0x2
+ dmov @0x2c, @-r15
+ dmov @r15+, @38
+ .global dmovh
+dmovh:
+ dmovh @0x88, r13
+ dmovh r13, @0x52
+ dmovh @0x34, @r13 +
+ dmovh @r13+, @0x52
+ .global dmovb
+dmovb:
+ dmovb @0x91, r13
+ dmovb r13, @0x53
+ dmovb @71, @r13+
+ dmovb @r13+, @0x0
+ .global ldi_20
+ldi_20:
+ ldi:20 #0x000fffff, r1
+finish:
+ ldi:32 #0x8000,r0
+ mov r0,ssp
+ ldi:32 #1,r0
+ int #10
+ .global inte
+inte:
+ inte
+ .global reti
+reti:
+ reti
diff --git a/gas/testsuite/gas/fr30/fr30.exp b/gas/testsuite/gas/fr30/fr30.exp
new file mode 100644
index 0000000000..06286b1ca9
--- /dev/null
+++ b/gas/testsuite/gas/fr30/fr30.exp
@@ -0,0 +1,5 @@
+# FR30 testcases
+
+if [istarget fr30*-*-*] {
+# run_dump_test "high-1"
+}
diff --git a/gas/testsuite/gas/h8300/addsub.s b/gas/testsuite/gas/h8300/addsub.s
new file mode 100644
index 0000000000..802b0d7621
--- /dev/null
+++ b/gas/testsuite/gas/h8300/addsub.s
@@ -0,0 +1,16 @@
+ .text
+h8300_add_sub:
+ add.b #16,r1l
+ add.b r1h,r1l
+ add.w r1,r2
+ adds #1,r4
+ adds #2,r5
+ addx r0l,r1l
+ addx #16,r2h
+ sub.b r0l,r1l
+ sub.w r0,r1
+ subs #1,r4
+ subs #2,r5
+ subx r0l,r1l
+ subx #16,r2h
+
diff --git a/gas/testsuite/gas/h8300/addsubh.s b/gas/testsuite/gas/h8300/addsubh.s
new file mode 100644
index 0000000000..1f885d3fc5
--- /dev/null
+++ b/gas/testsuite/gas/h8300/addsubh.s
@@ -0,0 +1,25 @@
+ .h8300h
+ .text
+h8300h_add_sub:
+ add.b #16,r1l
+ add.b r1h,r1l
+ add.w #32,r1
+ add.w r1,r2
+ add.l #64,er1
+ add.l er1,er2
+ adds #1,er4
+ adds #2,er5
+ adds #4,er6
+ addx r0l,r1l
+ addx #16,r2h
+ sub.b r0l,r1l
+ sub.w #16,r1
+ sub.w r0,r1
+ sub.l #64,er1
+ sub.l er1,er2
+ subs #1,er4
+ subs #2,er5
+ subs #4,er6
+ subx r0l,r1l
+ subx #16,r2h
+
diff --git a/gas/testsuite/gas/h8300/addsubs.s b/gas/testsuite/gas/h8300/addsubs.s
new file mode 100644
index 0000000000..b0b3699e45
--- /dev/null
+++ b/gas/testsuite/gas/h8300/addsubs.s
@@ -0,0 +1,25 @@
+ .h8300s
+ .text
+h8300s_add_sub:
+ add.b #16,r1l
+ add.b r1h,r1l
+ add.w #32,r1
+ add.w r1,r2
+ add.l #64,er1
+ add.l er1,er2
+ adds #1,er4
+ adds #2,er5
+ adds #4,er6
+ addx r0l,r1l
+ addx #16,r2h
+ sub.b r0l,r1l
+ sub.w #16,r1
+ sub.w r0,r1
+ sub.l #64,er1
+ sub.l er1,er2
+ subs #1,er4
+ subs #2,er5
+ subs #4,er6
+ subx r0l,r1l
+ subx #16,r2h
+
diff --git a/gas/testsuite/gas/h8300/bitops1.s b/gas/testsuite/gas/h8300/bitops1.s
new file mode 100644
index 0000000000..3c107a1b82
--- /dev/null
+++ b/gas/testsuite/gas/h8300/bitops1.s
@@ -0,0 +1,18 @@
+ .text
+h8300_bit_ops_1:
+ band #0,r0l
+ band #0,@r0
+ band #0,@64:8
+ bclr #0,r0l
+ bclr #0,@r0
+ bclr #0,@64:8
+ bclr r1l,r0l
+ bclr r1l,@r0
+ bclr r1l,@64:8
+ biand #0,r0l
+ biand #0,@r0
+ biand #0,@64:8
+ bild #0,r0l
+ bild #0,@r0
+ bild #0,@64:8
+
diff --git a/gas/testsuite/gas/h8300/bitops1h.s b/gas/testsuite/gas/h8300/bitops1h.s
new file mode 100644
index 0000000000..4139a590e8
--- /dev/null
+++ b/gas/testsuite/gas/h8300/bitops1h.s
@@ -0,0 +1,19 @@
+ .h8300h
+ .text
+h8300h_bit_ops_1:
+ band #0,r0l
+ band #0,@er0
+ band #0,@64:8
+ bclr #0,r0l
+ bclr #0,@er0
+ bclr #0,@64:8
+ bclr r1l,r0l
+ bclr r1l,@er0
+ bclr r1l,@64:8
+ biand #0,r0l
+ biand #0,@er0
+ biand #0,@64:8
+ bild #0,r0l
+ bild #0,@er0
+ bild #0,@64:8
+
diff --git a/gas/testsuite/gas/h8300/bitops1s.s b/gas/testsuite/gas/h8300/bitops1s.s
new file mode 100644
index 0000000000..c6599d41a9
--- /dev/null
+++ b/gas/testsuite/gas/h8300/bitops1s.s
@@ -0,0 +1,29 @@
+ .h8300s
+ .text
+h8300s_bit_ops_1:
+ band #0,r0l
+ band #0,@er0
+ band #0,@64:8
+ band #0,@128:16
+ band #0,@65536:32
+ bclr #0,r0l
+ bclr #0,@er0
+ bclr #0,@64:8
+ bclr #0,@128:16
+ bclr #0,@65536:32
+ bclr r1l,r0l
+ bclr r1l,@er0
+ bclr r1l,@64:8
+ bclr r1l,@128:16
+ bclr r1l,@65536:32
+ biand #0,r0l
+ biand #0,@er0
+ biand #0,@64:8
+ biand #0,@128:16
+ biand #0,@65536:32
+ bild #0,r0l
+ bild #0,@er0
+ bild #0,@64:8
+ bild #0,@128:16
+ bild #0,@65536:32
+
diff --git a/gas/testsuite/gas/h8300/bitops2.s b/gas/testsuite/gas/h8300/bitops2.s
new file mode 100644
index 0000000000..3996e5a469
--- /dev/null
+++ b/gas/testsuite/gas/h8300/bitops2.s
@@ -0,0 +1,15 @@
+ .text
+h8300_bit_ops_2:
+ bior #0,r0l
+ bior #0,@r0
+ bior #0,@64:8
+ bist #0,r0l
+ bist #0,@r0
+ bist #0,@64:8
+ bixor #0,r0l
+ bixor #0,@r0
+ bixor #0,@64:8
+ bld #0,r0l
+ bld #0,@r0
+ bld #0,@64:8
+
diff --git a/gas/testsuite/gas/h8300/bitops2h.s b/gas/testsuite/gas/h8300/bitops2h.s
new file mode 100644
index 0000000000..22be74e4b7
--- /dev/null
+++ b/gas/testsuite/gas/h8300/bitops2h.s
@@ -0,0 +1,16 @@
+ .h8300h
+ .text
+h8300h_bit_ops_2:
+ bior #0,r0l
+ bior #0,@er0
+ bior #0,@64:8
+ bist #0,r0l
+ bist #0,@er0
+ bist #0,@64:8
+ bixor #0,r0l
+ bixor #0,@er0
+ bixor #0,@64:8
+ bld #0,r0l
+ bld #0,@er0
+ bld #0,@64:8
+
diff --git a/gas/testsuite/gas/h8300/bitops2s.s b/gas/testsuite/gas/h8300/bitops2s.s
new file mode 100644
index 0000000000..94705201f0
--- /dev/null
+++ b/gas/testsuite/gas/h8300/bitops2s.s
@@ -0,0 +1,23 @@
+ .h8300s
+ .text
+h8300s_bit_ops_2:
+ bior #0,r0l
+ bior #0,@er0
+ bior #0,@64:8
+ bior #0,@128:16
+ bior #0,@65536:32
+ bist #0,r0l
+ bist #0,@er0
+ bist #0,@64:8
+ bist #0,@128:16
+ bist #0,@65536:32
+ bixor #0,r0l
+ bixor #0,@er0
+ bixor #0,@64:8
+ bixor #0,@128:16
+ bixor #0,@65536:32
+ bld #0,r0l
+ bld #0,@er0
+ bld #0,@64:8
+ bld #0,@128:16
+ bld #0,@65536:32
diff --git a/gas/testsuite/gas/h8300/bitops3.s b/gas/testsuite/gas/h8300/bitops3.s
new file mode 100644
index 0000000000..78c9bfb482
--- /dev/null
+++ b/gas/testsuite/gas/h8300/bitops3.s
@@ -0,0 +1,15 @@
+ .text
+h8300_bit_ops_3:
+ bnot #0,r0l
+ bnot #0,@r0
+ bnot #0,@64:8
+ bnot r1l,r0l
+ bnot r1l,@r0
+ bnot r1l,@64:8
+ bset #0,r0l
+ bset #0,@r0
+ bset #0,@64:8
+ bset r1l,r0l
+ bset r1l,@r0
+ bset r1l,@64:8
+
diff --git a/gas/testsuite/gas/h8300/bitops3h.s b/gas/testsuite/gas/h8300/bitops3h.s
new file mode 100644
index 0000000000..fdeda60908
--- /dev/null
+++ b/gas/testsuite/gas/h8300/bitops3h.s
@@ -0,0 +1,16 @@
+ .h8300h
+ .text
+h8300h_bit_ops_3:
+ bnot #0,r0l
+ bnot #0,@er0
+ bnot #0,@64:8
+ bnot r1l,r0l
+ bnot r1l,@er0
+ bnot r1l,@64:8
+ bset #0,r0l
+ bset #0,@er0
+ bset #0,@64:8
+ bset r1l,r0l
+ bset r1l,@er0
+ bset r1l,@64:8
+
diff --git a/gas/testsuite/gas/h8300/bitops3s.s b/gas/testsuite/gas/h8300/bitops3s.s
new file mode 100644
index 0000000000..7c64e06d78
--- /dev/null
+++ b/gas/testsuite/gas/h8300/bitops3s.s
@@ -0,0 +1,24 @@
+ .h8300s
+ .text
+h8300s_bit_ops_3:
+ bnot #0,r0l
+ bnot #0,@er0
+ bnot #0,@64:8
+ bnot #0,@128:16
+ bnot #0,@65536:32
+ bnot r1l,r0l
+ bnot r1l,@er0
+ bnot r1l,@64:8
+ bnot r1l,@128:16
+ bnot r1l,@65536:32
+ bset #0,r0l
+ bset #0,@er0
+ bset #0,@64:8
+ bset #0,@128:16
+ bset #0,@65536:32
+ bset r1l,r0l
+ bset r1l,@er0
+ bset r1l,@64:8
+ bset r1l,@128:16
+ bset r1l,@65536:32
+
diff --git a/gas/testsuite/gas/h8300/bitops4.s b/gas/testsuite/gas/h8300/bitops4.s
new file mode 100644
index 0000000000..f7e66d8b25
--- /dev/null
+++ b/gas/testsuite/gas/h8300/bitops4.s
@@ -0,0 +1,18 @@
+ .text
+h8300_bit_ops_4:
+ bor #0,r0l
+ bor #0,@r0
+ bor #0,@64:8
+ bst #0,r0l
+ bst #0,@r0
+ bst #0,@64:8
+ btst #0,r0l
+ btst #0,@r0
+ btst #0,@64:8
+ btst r1l,r0l
+ btst r1l,@r0
+ btst r1l,@64:8
+ bxor #0,r0l
+ bxor #0,@r0
+ bxor #0,@64:8
+
diff --git a/gas/testsuite/gas/h8300/bitops4h.s b/gas/testsuite/gas/h8300/bitops4h.s
new file mode 100644
index 0000000000..ed35e17dcb
--- /dev/null
+++ b/gas/testsuite/gas/h8300/bitops4h.s
@@ -0,0 +1,19 @@
+ .h8300h
+ .text
+h8300h_bit_ops_4:
+ bor #0,r0l
+ bor #0,@er0
+ bor #0,@64:8
+ bst #0,r0l
+ bst #0,@er0
+ bst #0,@64:8
+ btst #0,r0l
+ btst #0,@er0
+ btst #0,@64:8
+ btst r1l,r0l
+ btst r1l,@er0
+ btst r1l,@64:8
+ bxor #0,r0l
+ bxor #0,@er0
+ bxor #0,@64:8
+
diff --git a/gas/testsuite/gas/h8300/bitops4s.s b/gas/testsuite/gas/h8300/bitops4s.s
new file mode 100644
index 0000000000..e8f47b6dc2
--- /dev/null
+++ b/gas/testsuite/gas/h8300/bitops4s.s
@@ -0,0 +1,29 @@
+ .h8300s
+ .text
+h8300s_bit_ops_4:
+ bor #0,r0l
+ bor #0,@er0
+ bor #0,@64:8
+ bor #0,@128:16
+ bor #0,@65536:32
+ bst #0,r0l
+ bst #0,@er0
+ bst #0,@64:8
+ bst #0,@128:16
+ bst #0,@65536:32
+ btst #0,r0l
+ btst #0,@er0
+ btst #0,@64:8
+ btst #0,@128:16
+ btst #0,@65536:32
+ btst r1l,r0l
+ btst r1l,@er0
+ btst r1l,@64:8
+ btst r1l,@128:16
+ btst r1l,@65536:32
+ bxor #0,r0l
+ bxor #0,@er0
+ bxor #0,@64:8
+ bxor #0,@128:16
+ bxor #0,@65536:32
+
diff --git a/gas/testsuite/gas/h8300/branch.s b/gas/testsuite/gas/h8300/branch.s
new file mode 100644
index 0000000000..25806153c4
--- /dev/null
+++ b/gas/testsuite/gas/h8300/branch.s
@@ -0,0 +1,10 @@
+ .text
+h8300_branches:
+ bsr h8300_branches
+ jmp h8300_branches
+ jmp @r0
+ jmp @@16:8
+ jsr h8300_branches
+ jsr @r0
+ jsr @@16:8
+
diff --git a/gas/testsuite/gas/h8300/branchh.s b/gas/testsuite/gas/h8300/branchh.s
new file mode 100644
index 0000000000..7cbc62f3e2
--- /dev/null
+++ b/gas/testsuite/gas/h8300/branchh.s
@@ -0,0 +1,12 @@
+ .h8300h
+ .text
+h8300h_branches:
+ bsr h8300h_branches:8
+ bsr h8300h_branches:16
+ jmp h8300h_branches
+ jmp @er0
+ jmp @@16:8
+ jsr h8300h_branches
+ jsr @er0
+ jsr @@16:8
+
diff --git a/gas/testsuite/gas/h8300/branchs.s b/gas/testsuite/gas/h8300/branchs.s
new file mode 100644
index 0000000000..8f33e17967
--- /dev/null
+++ b/gas/testsuite/gas/h8300/branchs.s
@@ -0,0 +1,12 @@
+ .h8300s
+ .text
+h8300s_branches:
+ bsr h8300s_branches:8
+ bsr h8300s_branches:16
+ jmp h8300s_branches
+ jmp @er0
+ jmp @@16:8
+ jsr h8300s_branches
+ jsr @er0
+ jsr @@16:8
+
diff --git a/gas/testsuite/gas/h8300/cbranch.s b/gas/testsuite/gas/h8300/cbranch.s
new file mode 100644
index 0000000000..ae3d53ed88
--- /dev/null
+++ b/gas/testsuite/gas/h8300/cbranch.s
@@ -0,0 +1,23 @@
+ .text
+h8300_cbranch:
+ bra h8300_cbranch
+ bt h8300_cbranch
+ brn h8300_cbranch
+ bf h8300_cbranch
+ bhi h8300_cbranch
+ bls h8300_cbranch
+ bcc h8300_cbranch
+ bhs h8300_cbranch
+ bcs h8300_cbranch
+ blo h8300_cbranch
+ bne h8300_cbranch
+ beq h8300_cbranch
+ bvc h8300_cbranch
+ bvs h8300_cbranch
+ bpl h8300_cbranch
+ bmi h8300_cbranch
+ bge h8300_cbranch
+ blt h8300_cbranch
+ bgt h8300_cbranch
+ ble h8300_cbranch
+
diff --git a/gas/testsuite/gas/h8300/cbranchh.s b/gas/testsuite/gas/h8300/cbranchh.s
new file mode 100644
index 0000000000..a64e1a2aad
--- /dev/null
+++ b/gas/testsuite/gas/h8300/cbranchh.s
@@ -0,0 +1,44 @@
+ .text
+ .h8300h
+h8300h_cbranch:
+ bra h8300h_cbranch:8
+ bt h8300h_cbranch:8
+ brn h8300h_cbranch:8
+ bf h8300h_cbranch:8
+ bhi h8300h_cbranch:8
+ bls h8300h_cbranch:8
+ bcc h8300h_cbranch:8
+ bhs h8300h_cbranch:8
+ bcs h8300h_cbranch:8
+ blo h8300h_cbranch:8
+ bne h8300h_cbranch:8
+ beq h8300h_cbranch:8
+ bvc h8300h_cbranch:8
+ bvs h8300h_cbranch:8
+ bpl h8300h_cbranch:8
+ bmi h8300h_cbranch:8
+ bge h8300h_cbranch:8
+ blt h8300h_cbranch:8
+ bgt h8300h_cbranch:8
+ ble h8300h_cbranch:8
+ bra h8300h_cbranch:16
+ bt h8300h_cbranch:16
+ brn h8300h_cbranch:16
+ bf h8300h_cbranch:16
+ bhi h8300h_cbranch:16
+ bls h8300h_cbranch:16
+ bcc h8300h_cbranch:16
+ bhs h8300h_cbranch:16
+ bcs h8300h_cbranch:16
+ blo h8300h_cbranch:16
+ bne h8300h_cbranch:16
+ beq h8300h_cbranch:16
+ bvc h8300h_cbranch:16
+ bvs h8300h_cbranch:16
+ bpl h8300h_cbranch:16
+ bmi h8300h_cbranch:16
+ bge h8300h_cbranch:16
+ blt h8300h_cbranch:16
+ bgt h8300h_cbranch:16
+ ble h8300h_cbranch:16
+
diff --git a/gas/testsuite/gas/h8300/cbranchs.s b/gas/testsuite/gas/h8300/cbranchs.s
new file mode 100644
index 0000000000..14222ea772
--- /dev/null
+++ b/gas/testsuite/gas/h8300/cbranchs.s
@@ -0,0 +1,44 @@
+ .text
+ .h8300s
+h8300s_cbranch:
+ bra h8300s_cbranch:8
+ bt h8300s_cbranch:8
+ brn h8300s_cbranch:8
+ bf h8300s_cbranch:8
+ bhi h8300s_cbranch:8
+ bls h8300s_cbranch:8
+ bcc h8300s_cbranch:8
+ bhs h8300s_cbranch:8
+ bcs h8300s_cbranch:8
+ blo h8300s_cbranch:8
+ bne h8300s_cbranch:8
+ beq h8300s_cbranch:8
+ bvc h8300s_cbranch:8
+ bvs h8300s_cbranch:8
+ bpl h8300s_cbranch:8
+ bmi h8300s_cbranch:8
+ bge h8300s_cbranch:8
+ blt h8300s_cbranch:8
+ bgt h8300s_cbranch:8
+ ble h8300s_cbranch:8
+ bra h8300s_cbranch:16
+ bt h8300s_cbranch:16
+ brn h8300s_cbranch:16
+ bf h8300s_cbranch:16
+ bhi h8300s_cbranch:16
+ bls h8300s_cbranch:16
+ bcc h8300s_cbranch:16
+ bhs h8300s_cbranch:16
+ bcs h8300s_cbranch:16
+ blo h8300s_cbranch:16
+ bne h8300s_cbranch:16
+ beq h8300s_cbranch:16
+ bvc h8300s_cbranch:16
+ bvs h8300s_cbranch:16
+ bpl h8300s_cbranch:16
+ bmi h8300s_cbranch:16
+ bge h8300s_cbranch:16
+ blt h8300s_cbranch:16
+ bgt h8300s_cbranch:16
+ ble h8300s_cbranch:16
+
diff --git a/gas/testsuite/gas/h8300/cmpsi2.s b/gas/testsuite/gas/h8300/cmpsi2.s
new file mode 100644
index 0000000000..ef7f03aa92
--- /dev/null
+++ b/gas/testsuite/gas/h8300/cmpsi2.s
@@ -0,0 +1,28 @@
+# 1 "libgcc1.S"
+;; libgcc1 routines for the Hitachi h8/300 cpu.
+;; Contributed by Steve Chamberlain.
+;; sac@cygnus.com
+ .section .text
+ .align 2
+ .global ___cmpsi2
+___cmpsi2:
+ cmp.w r2 ,r0
+ bne .L2
+ cmp.w r3 ,r1
+ bne .L2
+ mov.w #1,r0
+ rts
+.L2:
+ cmp.w r0 ,r2
+ bgt .L4
+ bne .L3
+ cmp.w r1 ,r3
+ bls .L3
+.L4:
+ sub.w r0 ,r0
+ rts
+.L3:
+ mov.w #2,r0
+.L5:
+ rts
+ .end
diff --git a/gas/testsuite/gas/h8300/compare.s b/gas/testsuite/gas/h8300/compare.s
new file mode 100644
index 0000000000..60c1a417d7
--- /dev/null
+++ b/gas/testsuite/gas/h8300/compare.s
@@ -0,0 +1,6 @@
+ .text
+h8300_cmp:
+ cmp.b #0,r0l
+ cmp.b r0h,r0l
+ cmp.w r0,r1
+
diff --git a/gas/testsuite/gas/h8300/compareh.s b/gas/testsuite/gas/h8300/compareh.s
new file mode 100644
index 0000000000..c81e88e0c2
--- /dev/null
+++ b/gas/testsuite/gas/h8300/compareh.s
@@ -0,0 +1,10 @@
+ .h8300h
+ .text
+h8300h_cmp:
+ cmp.b #0,r0l
+ cmp.b r0h,r0l
+ cmp.w #32,r0
+ cmp.w r0,r1
+ cmp.l #64,er0
+ cmp.l er0,er1
+
diff --git a/gas/testsuite/gas/h8300/compares.s b/gas/testsuite/gas/h8300/compares.s
new file mode 100644
index 0000000000..e23f3fe8e9
--- /dev/null
+++ b/gas/testsuite/gas/h8300/compares.s
@@ -0,0 +1,10 @@
+ .h8300s
+ .text
+h8300s_cmp:
+ cmp.b #0,r0l
+ cmp.b r0h,r0l
+ cmp.w #32,r0
+ cmp.w r0,r1
+ cmp.l #64,er0
+ cmp.l er0,er1
+
diff --git a/gas/testsuite/gas/h8300/decimal.s b/gas/testsuite/gas/h8300/decimal.s
new file mode 100644
index 0000000000..8d4c0a0da9
--- /dev/null
+++ b/gas/testsuite/gas/h8300/decimal.s
@@ -0,0 +1,5 @@
+ .text
+h8300_decimal:
+ daa r0l
+ das r0l
+
diff --git a/gas/testsuite/gas/h8300/decimalh.s b/gas/testsuite/gas/h8300/decimalh.s
new file mode 100644
index 0000000000..939240568e
--- /dev/null
+++ b/gas/testsuite/gas/h8300/decimalh.s
@@ -0,0 +1,6 @@
+ .h8300h
+ .text
+h8300h_decimal:
+ daa r0l
+ das r0l
+
diff --git a/gas/testsuite/gas/h8300/decimals.s b/gas/testsuite/gas/h8300/decimals.s
new file mode 100644
index 0000000000..b7802fcf1a
--- /dev/null
+++ b/gas/testsuite/gas/h8300/decimals.s
@@ -0,0 +1,6 @@
+ .h8300s
+ .text
+h8300s_decimal:
+ daa r0l
+ das r0l
+
diff --git a/gas/testsuite/gas/h8300/divmul.s b/gas/testsuite/gas/h8300/divmul.s
new file mode 100644
index 0000000000..37372ce484
--- /dev/null
+++ b/gas/testsuite/gas/h8300/divmul.s
@@ -0,0 +1,5 @@
+ .text
+h8300_div_mul:
+ divxu r0l,r1
+ mulxu r0l,r1
+
diff --git a/gas/testsuite/gas/h8300/divmulh.s b/gas/testsuite/gas/h8300/divmulh.s
new file mode 100644
index 0000000000..db60f8f49a
--- /dev/null
+++ b/gas/testsuite/gas/h8300/divmulh.s
@@ -0,0 +1,12 @@
+ .h8300h
+ .text
+h8300h_div_mul:
+ divxu.b r0l,r1
+ divxu.w r0,er1
+ divxs.b r0l,r1
+ divxs.w r0,er1
+ mulxu.b r0l,r1
+ mulxu.w r0,er1
+ mulxs.b r0l,r1
+ mulxs.w r0,er1
+
diff --git a/gas/testsuite/gas/h8300/divmuls.s b/gas/testsuite/gas/h8300/divmuls.s
new file mode 100644
index 0000000000..db60f8f49a
--- /dev/null
+++ b/gas/testsuite/gas/h8300/divmuls.s
@@ -0,0 +1,12 @@
+ .h8300h
+ .text
+h8300h_div_mul:
+ divxu.b r0l,r1
+ divxu.w r0,er1
+ divxs.b r0l,r1
+ divxs.w r0,er1
+ mulxu.b r0l,r1
+ mulxu.w r0,er1
+ mulxs.b r0l,r1
+ mulxs.w r0,er1
+
diff --git a/gas/testsuite/gas/h8300/extendh.s b/gas/testsuite/gas/h8300/extendh.s
new file mode 100644
index 0000000000..c034c833ee
--- /dev/null
+++ b/gas/testsuite/gas/h8300/extendh.s
@@ -0,0 +1,8 @@
+ .h8300h
+ .text
+h8300h_extend:
+ exts.w r0
+ exts.l er0
+ extu.w r0
+ extu.l er0
+
diff --git a/gas/testsuite/gas/h8300/extends.s b/gas/testsuite/gas/h8300/extends.s
new file mode 100644
index 0000000000..a26e9ba70a
--- /dev/null
+++ b/gas/testsuite/gas/h8300/extends.s
@@ -0,0 +1,8 @@
+ .h8300s
+ .text
+h8300s_extend:
+ exts.w r0
+ exts.l er0
+ extu.w r0
+ extu.l er0
+
diff --git a/gas/testsuite/gas/h8300/ffxx1.d b/gas/testsuite/gas/h8300/ffxx1.d
new file mode 100644
index 0000000000..93455d5217
--- /dev/null
+++ b/gas/testsuite/gas/h8300/ffxx1.d
@@ -0,0 +1,23 @@
+#objdump: --prefix-addresses -dr
+#name: FFxx1
+
+# Test for FFxx:8 addressing.
+
+.*: file format .*h8300.*
+
+Disassembly of section .text:
+ ...
+ 0: 16 main
+0+0400 <main> f8 7f mov.b #0x7f,r0l
+0+0402 <main[+](0x|)2> 28 bb mov.b @0xbb:8,r0l
+0+0404 <main[+](0x|)4> 6a 88 ff b9 mov.b r0l,@0xffb9:16
+0+0408 <main[+](0x|)8> f8 01 mov.b #0x1,r0l
+0+040a <loop> 6a 88 ff bb mov.b r0l,@0xffbb:16
+0+040e <delay> 79 01 00 00 mov.w #0x0,r1
+0+0412 <deloop> 0b 01 adds #0x1,er1
+0+0414 <deloop[+](0x|)2> 46 00 bne .0 \(416\)
+ 415: DISP8 deloop[+]0xffffffff
+0+0416 <deloop[+](0x|)4> 12 88 rotl r0l
+0+0418 <deloop[+](0x|)6> 40 00 bra .0 \(41a\)
+ 419: DISP8 loop[+]0xffffffff
+ ...
diff --git a/gas/testsuite/gas/h8300/ffxx1.s b/gas/testsuite/gas/h8300/ffxx1.s
new file mode 100644
index 0000000000..53fc84160d
--- /dev/null
+++ b/gas/testsuite/gas/h8300/ffxx1.s
@@ -0,0 +1,20 @@
+ .equ p6ddr, 0xffb9 ;0x7f for output
+ .equ p6dr, 0xffbb
+ .equ seed, 0x01
+ .text
+ .org 0
+reset: .word main ;reset vector
+;
+ .org 0x400
+main: mov.b #0x7f,r0l ;port 6 ddr = 7F
+ mov.b @0xffbb:8,r0l ;***test***
+ mov.b r0l,@p6ddr:16
+;
+ mov.b #seed,r0l ;start with 0000001
+loop: mov.b r0l,@p6dr:16 ;output to port 6
+delay: mov.w #0x0000,r1
+deloop: adds.w #1,r1
+ bne deloop:8 ;not = 0
+ rotl r0l
+ bra loop:8
+ .word 0
diff --git a/gas/testsuite/gas/h8300/h8300.exp b/gas/testsuite/gas/h8300/h8300.exp
new file mode 100644
index 0000000000..2b7d41ec0b
--- /dev/null
+++ b/gas/testsuite/gas/h8300/h8300.exp
@@ -0,0 +1,2183 @@
+#
+# Some H8/300 tests
+#
+proc do_h8300_add_sub {} {
+ set testname "addsub.s: h8300 add/sub tests"
+ set x 0
+
+ gas_start "addsub.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 8910\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 0819\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 0912\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 0B04\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 0B85\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 0E89\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 9210\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000e 1889\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 1901\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 1B04\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 1B85\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 1E89\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0018 B210\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 13] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300_logical {} {
+ set testname "logical.s: h8300 logical tests"
+ set x 0
+
+ gas_start "logical.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 E910\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 1691\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 0610\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 C810\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 1498\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 0410\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c D810\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000e 1589\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 0510\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 1788\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 1708\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 11] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300_cbranch {} {
+ set testname "cbranch.s: h8300 conditional branch tests"
+ set x 0
+
+ gas_start "cbranch.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 4000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 4000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 4100\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 4100\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 4200\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 4300\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 4400\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000e 4400\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 4500\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 4500\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 4600\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 4700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0018 4800\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 4900\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001c 4A00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 4B00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 4C00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 4D00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0024 4E00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0026 4F00\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 20] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300_bitops1 {} {
+ set testname "bitops1.s: h8300 bitops tests #1"
+ set x 0
+
+ gas_start "bitops1.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 7608\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 7C007600\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 7E407600\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 7208\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 7D007200\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 7F407200\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 6298\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 7D006290\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 7F406290\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 7688\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 7C007680\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0024 7E407680\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0028 7788\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002a 7C007780\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002e 7E407780\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 15] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300_bitops2 {} {
+ set testname "bitops2.s: h8300 bitops tests #2"
+ set x 0
+
+ gas_start "bitops2.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 7488\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 7C007480\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 7E407480\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 6788\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 7D006780\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 7F406780\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 7588\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 7C007580\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 7E407580\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 7708\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 7C007700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0024 7E407700\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 12] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300_bitops3 {} {
+ set testname "bitops3.s: h8300 bitops tests #3"
+ set x 0
+
+ gas_start "bitops3.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 7108\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 7D007100\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 7F407100\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 6198\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 7D006190\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 7F406190\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 7008\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 7D007000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 7F407000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 6098\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 7D006090\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0024 7F406090\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 12] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300_bitops4 {} {
+ set testname "bitops4.s: h8300 bitops tests #4"
+ set x 0
+
+ gas_start "bitops4.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 7408\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 7C007400\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 7E407400\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 6708\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 7D006700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 7F406700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 7308\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 7C007300\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 7E407300\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 6398\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 7C006390\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0024 7E406390\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0028 7508\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002a 7C007500\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002e 7E407500\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 15] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300_branch {} {
+ set testname "branch.s: h8300 branch tests"
+ set x 0
+
+ gas_start "branch.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 5500\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 5A000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 5900\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 5B00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 5E000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000e 5D00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 5F00\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 7] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300_compare {} {
+ set testname "compare.s: h8300 compare tests"
+ set x 0
+
+ gas_start "compare.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 A800\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 1C08\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 1D01\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 3] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300_decimal {} {
+ set testname "decimal.s: h8300 decimal tests"
+ set x 0
+
+ gas_start "decimal.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 0F08\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 1F08\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 2] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300_incdec {} {
+ set testname "incdec.s: h8300 incdec tests"
+ set x 0
+
+ gas_start "incdec.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 1A08\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 0A08\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 2] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300_divmul {} {
+ set testname "divmul.s: h8300 divmul tests"
+ set x 0
+
+ gas_start "divmul.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 5181\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 5081\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 2] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300_misc {} {
+ set testname "misc.s: h8300 misc tests"
+ set x 0
+
+ gas_start "misc.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 7B5C598F\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 0700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 0308\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 5670\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 5470\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000e 0180\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 0208\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 8] then { pass $testname } else { fail $testname }
+
+ setup_xfail "h8300*-*-*"
+ fail "h8300 movfpe/movtpe tests"
+}
+
+proc do_h8300_movb {} {
+ set testname "movb.s: h8300 movb tests"
+ set x 0
+
+ gas_start "movb.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 0C89\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 F810\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 6818\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 6E180010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 6C18\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 2810\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000e 6A080000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 6898\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 6E980010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0018 6C98\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 3810\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001c 6A880000\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 12] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300_movw {} {
+ set testname "movw.s: h8300 movw tests"
+ set x 0
+
+ gas_start "movw.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 0D01\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 79000010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 6910\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 6F100010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 6D10\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000e 6B000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 6990\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 6F900010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0018 6D90\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 6B800000\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 10] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300_pushpop {} {
+ set testname "pushpop.s: h8300 pushpop tests"
+ set x 0
+
+ gas_start "pushpop.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 6D70\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 6DF0\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 2] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300_rotate_shift {} {
+ set testname "rotsh.s: h8300 rotate and shift tests"
+ set x 0
+
+ gas_start "rotsh.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 1288\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 1388\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 1208\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 1308\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 1088\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 1188\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 1008\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000e 1108\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 8] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300h_add_sub {} {
+ set testname "addsubh.s: h8300h add/sub tests"
+ set x 0
+
+ gas_start "addsubh.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 8910\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 0819\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 79110020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 0912\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 7A110000\[^\n\]*\n +\[0-9\]+ +0040\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 0A92\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 0B04\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 0B85\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 0B96\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0018 0E89\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 9210\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001c 1889\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 79310010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 1901\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0024 7A310000\[^\n\]*\n +\[0-9\]+ +0040\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002a 1A92\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002c 1B04\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002e 1B85\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 1B96\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0032 1E89\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0034 B210\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 21] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300h_logical {} {
+ set testname "logicalh.s: h8300h logical tests"
+ set x 0
+
+ gas_start "logicalh.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 E910\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 1691\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 79610020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 6611\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 7A610000\[^\n\]*\n +\[0-9\]+ +0040\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 01F06611\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 0610\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 C810\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0018 1498\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 79410020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 6411\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 7A410000\[^\n\]*\n +\[0-9\]+ +0040\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0026 01F06411\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002a 0410\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002c D810\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002e 1589\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 79510020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0034 6511\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0036 7A510000\[^\n\]*\n +\[0-9\]+ +0040\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003c 01F06511\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0040 0510\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0042 1788\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0044 1790\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0046 17B0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0048 1708\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004a 1710\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004c 1730\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 27] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300h_cbranch {} {
+ set testname "cbranchh.s: h8300h conditional branch tests"
+ set x 0
+
+ gas_start "cbranchh.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 4000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 4000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 4100\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 4100\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 4200\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 4300\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 4400\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000e 4400\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 4500\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 4500\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 4600\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 4700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0018 4800\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 4900\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001c 4A00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 4B00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 4C00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 4D00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0024 4E00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0026 4F00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0028 58000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002c 58000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 58100000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0034 58100000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0038 58200000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003c 58300000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0040 58400000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0044 58400000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0048 58500000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004c 58500000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0050 58600000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0054 58700000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0058 58800000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 005c 58900000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0060 58A00000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0064 58B00000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0068 58C00000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 006c 58D00000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0070 58E00000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0074 58F00000\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 40] then { pass $testname } else { fail $testname }
+}
+proc do_h8300h_bitops1 {} {
+ set testname "bitops1h.s: h8300h bitops tests #1"
+ set x 0
+
+ gas_start "bitops1h.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 7608\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 7C007600\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 7E407600\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 7208\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 7D007200\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 7F407200\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 6298\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 7D006290\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 7F406290\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 7688\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 7C007680\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0024 7E407680\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0028 7788\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002a 7C007780\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002e 7E407780\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 15] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300h_bitops2 {} {
+ set testname "bitops2h.s: h8300h bitops tests #2"
+ set x 0
+
+ gas_start "bitops2h.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 7488\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 7C007480\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 7E407480\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 6788\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 7D006780\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 7F406780\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 7588\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 7C007580\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 7E407580\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 7708\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 7C007700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0024 7E407700\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 12] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300h_bitops3 {} {
+ set testname "bitops3h.s: h8300h bitops tests #3"
+ set x 0
+
+ gas_start "bitops3h.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 7108\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 7D007100\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 7F407100\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 6198\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 7D006190\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 7F406190\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 7008\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 7D007000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 7F407000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 6098\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 7D006090\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0024 7F406090\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 12] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300h_bitops4 {} {
+ set testname "bitops4h.s: h8300h bitops tests #4"
+ set x 0
+
+ gas_start "bitops4h.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 7408\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 7C007400\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 7E407400\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 6708\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 7D006700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 7F406700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 7308\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 7C007300\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 7E407300\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 6398\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 7C006390\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0024 7E406390\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0028 7508\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002a 7C007500\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002e 7E407500\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 15] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300h_branch {} {
+ set testname "branchh.s: h8300h branch tests"
+ set x 0
+
+ gas_start "branchh.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 5500\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 5C000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 5A000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 5900\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 5B00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000e 5E000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 5D00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 5F00\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 8] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300h_compare {} {
+ set testname "compareh.s: h8300h compare tests"
+ set x 0
+
+ gas_start "compareh.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 A800\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 1C08\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 79200020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 1D01\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 7A200000\[^\n\]*\n +\[0-9\]+ +0040\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 1F81\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 6] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300h_decimal {} {
+ set testname "decimalh.s: h8300h decimal tests"
+ set x 0
+
+ gas_start "decimalh.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 0F08\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 1F08\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 2] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300h_incdec {} {
+ set testname "incdech.s: h8300h incdec tests"
+ set x 0
+
+ gas_start "incdech.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 1A08\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 1B50\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 1BD0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 1B70\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 1BF0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 0A08\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 0B50\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000e 0BD0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 0B70\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 0BF0\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 10] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300h_divmul {} {
+ set testname "divmulh.s: h8300h divmul tests"
+ set x 0
+
+ gas_start "divmulh.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 5181\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 5301\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 01D05181\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 01D05301\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 5081\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000e 5201\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 01C05081\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 01C05201\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 8] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300h_misc {} {
+ set testname "misch.s: h8300h misc tests"
+ set x 0
+
+ gas_start "misch.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 7B5C598F\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 7BD4598F\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 0700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 0308\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 01406900\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 01406F00\[^\n\]*\n +\[0-9\]+ +0010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 01407800\[^\n\]*\n +\[0-9\]+ +6B200000\[^\n\]*\n +\[0-9\]+ +0020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 01406D00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0024 01406B00\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002a 01406B20\[^\n\]*\n +\[0-9\]+ +00000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0032 0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0034 5670\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0036 5470\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0038 0180\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003a 0208\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003c 01406980\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0040 01406F80\[^\n\]*\n +\[0-9\]+ +0010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0046 01407800\[^\n\]*\n +\[0-9\]+ +6BA00000\[^\n\]*\n +\[0-9\]+ +0020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0050 01406D80\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0054 01406B80\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 005a 01406BA0\[^\n\]*\n +\[0-9\]+ +00000000\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 21] then { pass $testname } else { fail $testname }
+
+ setup_xfail "h8300*-*-*"
+ fail "h8300h movfpe/movtpe tests"
+}
+
+proc do_h8300h_movb {} {
+ set testname "movbh.s: h8300h movb tests"
+ set x 0
+
+ gas_start "movbh.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 0C89\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 F810\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 6818\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 6E180010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 78106A28\[^\n\]*\n +\[0-9\]+ +00000020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 6C18\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 2810\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 6A080000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 6A280000\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 6898\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 6E980010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0026 78106AA8\[^\n\]*\n +\[0-9\]+ +00000020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002e 6C98\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 3810\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0032 6A880000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0036 6AA80000\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 16] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300h_movw {} {
+ set testname "movwh.s: h8300h movw tests"
+ set x 0
+
+ gas_start "movwh.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 0D01\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 79000010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 6910\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 6F100010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 78106B20\[^\n\]*\n +\[0-9\]+ +00000020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 6D10\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 6B000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 6B200000\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 6990\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 6F900010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0026 78106BA0\[^\n\]*\n +\[0-9\]+ +00000020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002e 6D90\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 6B800000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0034 6BA00000\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 14] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300h_movl {} {
+ set testname "movlh.s: h8300h movl tests"
+ set x 0
+
+ gas_start "movlh.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 0F81\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 7A000000\[^\n\]*\n +\[0-9\]+ +0040\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 01006910\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 01006F10\[^\n\]*\n +\[0-9\]+ +0010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 01007810\[^\n\]*\n +\[0-9\]+ +6B200000\[^\n\]*\n +\[0-9\]+ +0020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001c 01006D10\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 01006B00\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0026 01006B20\[^\n\]*\n +\[0-9\]+ +00000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002e 01006990\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0032 01006F90\[^\n\]*\n +\[0-9\]+ +0010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0038 01007890\[^\n\]*\n +\[0-9\]+ +6BA00000\[^\n\]*\n +\[0-9\]+ +0020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0042 01006D90\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0046 01006B80\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004c 01006BA0\[^\n\]*\n +\[0-9\]+ +00000000\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 14] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300h_pushpop {} {
+ set testname "pushpoph.s: h8300h pushpop tests"
+ set x 0
+
+ gas_start "pushpoph.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 6D70\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 01006D70\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 6DF0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 01006DF0\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 4] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300h_rotate_shift {} {
+ set testname "rotshh.s: h8300h rotate and shift tests"
+ set x 0
+
+ gas_start "rotshh.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 1288\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 1290\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 12B0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 1388\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 1390\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 13B0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 1208\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000e 1210\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 1230\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 1308\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 1310\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 1330\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0018 1088\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 1090\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001c 10B0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 1188\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 1190\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 11B0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0024 1008\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0026 1010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0028 1030\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002a 1108\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002c 1110\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002e 1130\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 24] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300h_extend {} {
+ set testname "extendh.s: h8300h extend tests"
+ set x 0
+
+ gas_start "extendh.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 17D0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 17F0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 1750\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 1770\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 4] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_add_sub {} {
+ set testname "addsubs.s: h8300s add/sub tests"
+ set x 0
+
+ gas_start "addsubs.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 8910\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 0819\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 79110020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 0912\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 7A110000\[^\n\]*\n +\[0-9\]+ +0040\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 0A92\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 0B04\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 0B85\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 0B96\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0018 0E89\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 9210\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001c 1889\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 79310010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 1901\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0024 7A310000\[^\n\]*\n +\[0-9\]+ +0040\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002a 1A92\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002c 1B04\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002e 1B85\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 1B96\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0032 1E89\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0034 B210\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 21] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_logical {} {
+ set testname "logicals.s: h8300s logical tests"
+ set x 0
+
+ gas_start "logicals.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 E910\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 1691\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 79610020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 6611\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 7A610000\[^\n\]*\n +\[0-9\]+ +0040\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 01F06611\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 0610\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 01410610\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a C810\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001c 1498\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 79410020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 6411\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0024 7A410000\[^\n\]*\n +\[0-9\]+ +0040\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002a 01F06411\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002e 0410\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 01410410\[^\n\]*\n" { set x [expr $x+1] }
+
+ -re " +\[0-9\]+ 0034 D810\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0036 1589\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0038 79510020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003c 6511\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003e 7A510000\[^\n\]*\n +\[0-9\]+ +0040\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0044 01F06511\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0048 0510\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004a 01410510\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004e 1788\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0050 1790\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0052 17B0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0054 1708\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0056 1710\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0058 1730\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 30] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_cbranch {} {
+ set testname "cbranchs.s: h8300s conditional branch tests"
+ set x 0
+
+ gas_start "cbranchs.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 4000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 4000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 4100\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 4100\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 4200\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 4300\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 4400\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000e 4400\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 4500\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 4500\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 4600\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 4700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0018 4800\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 4900\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001c 4A00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 4B00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 4C00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 4D00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0024 4E00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0026 4F00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0028 58000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002c 58000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 58100000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0034 58100000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0038 58200000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003c 58300000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0040 58400000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0044 58400000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0048 58500000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004c 58500000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0050 58600000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0054 58700000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0058 58800000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 005c 58900000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0060 58A00000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0064 58B00000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0068 58C00000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 006c 58D00000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0070 58E00000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0074 58F00000\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 40] then { pass $testname } else { fail $testname }
+}
+proc do_h8300s_bitops1 {} {
+ set testname "bitops1s.s: h8300s bitops tests #1"
+ set x 0
+
+ gas_start "bitops1s.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 7608\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 7C007600\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 7E407600\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 6A100080\[^\n\]*\n +\[0-9\]+ +7600" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 6A300001\[^\n\]*\n +\[0-9\]+ +00007600" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0018 7208\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 7D007200\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 7F407200\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 6A180080\[^\n\]*\n +\[0-9\]+ +7200" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0028 6A380001\[^\n\]*\n +\[0-9\]+ +00007200" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 6298\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0032 7D006290\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0036 7F406290\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003a 6A180080\[^\n\]*\n +\[0-9\]+ +6290" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0040 6A380001\[^\n\]*\n +\[0-9\]+ +00006290" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0048 7688\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004a 7C007680\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004e 7E407680\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0052 6A100080\[^\n\]*\n +\[0-9\]+ +7680" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0058 6A300001\[^\n\]*\n +\[0-9\]+ +00007680" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0060 7788\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0062 7C007780\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0066 7E407780\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 006a 6A100080\[^\n\]*\n +\[0-9\]+ +7780" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0070 6A300001\[^\n\]*\n +\[0-9\]+ +00007780" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 25] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_bitops2 {} {
+ set testname "bitops2s.s: h8300s bitops tests #2"
+ set x 0
+
+ gas_start "bitops2s.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 7488\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 7C007480\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 7E407480\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 6A100080\[^\n\]*\n +\[0-9\]+ +7480" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 6A300001\[^\n\]*\n +\[0-9\]+ +00007480" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0018 6788\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 7D006780\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 7F406780\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 6A180080\[^\n\]*\n +\[0-9\]+ +6780" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0028 6A380001\[^\n\]*\n +\[0-9\]+ +00006780" { set x [expr $x+1] }
+
+ -re " +\[0-9\]+ 0030 7588\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0032 7C007580\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0036 7E407580\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003a 6A100080\[^\n\]*\n +\[0-9\]+ +7580" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0040 6A300001\[^\n\]*\n +\[0-9\]+ +00007580" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0048 7708\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004a 7C007700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004e 7E407700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0052 6A100080\[^\n\]*\n +\[0-9\]+ +7700" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0058 6A300001\[^\n\]*\n +\[0-9\]+ +00007700" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 20] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_bitops3 {} {
+ set testname "bitops3s.s: h8300s bitops tests #3"
+ set x 0
+
+ gas_start "bitops3s.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 7108\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 7D007100\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 7F407100\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 6A180080\[^\n\]*\n +\[0-9\]+ +7100" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 6A380001\[^\n\]*\n +\[0-9\]+ +00007100" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0018 6198\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 7D006190\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 7F406190\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 6A180080\[^\n\]*\n +\[0-9\]+ +6190" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0028 6A380001\[^\n\]*\n +\[0-9\]+ +00006190" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 7008\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0032 7D007000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0036 7F407000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003a 6A180080\[^\n\]*\n +\[0-9\]+ +7000" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0040 6A380001\[^\n\]*\n +\[0-9\]+ +00007000" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0048 6098\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004a 7D006090\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004e 7F406090\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0052 6A180080\[^\n\]*\n +\[0-9\]+ +6090" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0058 6A380001\[^\n\]*\n +\[0-9\]+ +00006090" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 20] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_bitops4 {} {
+ set testname "bitops4s.s: h8300s bitops tests #4"
+ set x 0
+
+ gas_start "bitops4s.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 7408\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 7C007400\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 7E407400\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 6A100080\[^\n\]*\n +\[0-9\]+ +7400" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 6A300001\[^\n\]*\n +\[0-9\]+ +00007400" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0018 6708\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 7D006700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 7F406700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 6A180080\[^\n\]*\n +\[0-9\]+ +6700" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0028 6A380001\[^\n\]*\n +\[0-9\]+ +00006700" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 7308\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0032 7C007300\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0036 7E407300\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003a 6A100080\[^\n\]*\n +\[0-9\]+ +7300" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0040 6A300001\[^\n\]*\n +\[0-9\]+ +00007300" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0048 6398\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004a 7C006390\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004e 7E406390\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0052 6A100080\[^\n\]*\n +\[0-9\]+ +6390" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0058 6A300001\[^\n\]*\n +\[0-9\]+ +00006390" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0060 7508\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0062 7C007500\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0066 7E407500\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 006a 6A100080\[^\n\]*\n +\[0-9\]+ +7500" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0070 6A300001\[^\n\]*\n +\[0-9\]+ +00007500" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 25] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_branch {} {
+ set testname "branchs.s: h8300s branch tests"
+ set x 0
+
+ gas_start "branchs.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 5500\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 5C000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 5A000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 5900\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 5B00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000e 5E000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 5D00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 5F00\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 8] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_compare {} {
+ set testname "compares.s: h8300s compare tests"
+ set x 0
+
+ gas_start "compares.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 A800\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 1C08\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 79200020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 1D01\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 7A200000\[^\n\]*\n +\[0-9\]+ +0040\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 1F81\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 6] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_decimal {} {
+ set testname "decimals.s: h8300s decimal tests"
+ set x 0
+
+ gas_start "decimals.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 0F08\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 1F08\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 2] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_incdec {} {
+ set testname "incdecs.s: h8300s incdec tests"
+ set x 0
+
+ gas_start "incdecs.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 1A08\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 1B50\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 1BD0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 1B70\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 1BF0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 0A08\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 0B50\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000e 0BD0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 0B70\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 0BF0\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 10] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_divmul {} {
+ set testname "divmuls.s: h8300s divmul tests"
+ set x 0
+
+ gas_start "divmuls.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 5181\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 5301\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 01D05181\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 01D05301\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 5081\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000e 5201\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 01C05081\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 01C05201\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 8] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_misc {} {
+ set testname "miscs.s: h8300s misc tests"
+ set x 0
+
+ gas_start "miscs.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 7B5C598F\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 7BD4598F\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 0700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 0308\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 01410700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 0318\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 01406900\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 01406F00\[^\n\]*\n +\[0-9\]+ +0010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001c 01407800\[^\n\]*\n +\[0-9\]+ +6B200000\[^\n\]*\n +\[0-9\]+ +0020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0026 01406D00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002a 01406B00\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 01406B20\[^\n\]*\n +\[0-9\]+ +00000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0038 01416900\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003c 01416F00\[^\n\]*\n +\[0-9\]+ +0010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0042 01417800\[^\n\]*\n +\[0-9\]+ +6B200000\[^\n\]*\n +\[0-9\]+ +0020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004c 01416D00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0050 01416B00\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0056 01416B20\[^\n\]*\n +\[0-9\]+ +00000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 005e 0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0060 5670\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0062 5470\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0064 0180\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0066 0208\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0068 0218\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 006a 01406980\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 006e 01406F80\[^\n\]*\n +\[0-9\]+ +0010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0074 01407800\[^\n\]*\n +\[0-9\]+ +6BA00000\[^\n\]*\n +\[0-9\]+ +0020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 007e 01406D80\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0082 01406B80\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0088 01406BA0\[^\n\]*\n +\[0-9\]+ +00000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0090 01416980\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0094 01416F80\[^\n\]*\n +\[0-9\]+ +0010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 009a 01417800\[^\n\]*\n +\[0-9\]+ +6BA00000\[^\n\]*\n +\[0-9\]+ +0020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 00a4 01416D80\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 00a8 01416B80\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 00ae 01416BA0\[^\n\]*\n +\[0-9\]+ +00000000\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 36] then { pass $testname } else { fail $testname }
+
+ setup_xfail "h8300*-*-*"
+ fail "h8300s movfpe/movtpe tests"
+}
+
+proc do_h8300s_movb {} {
+ set testname "movbs.s: h8300s movb tests"
+ set x 0
+
+ gas_start "movbs.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 0C89\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 F810\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 6818\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 6E180010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 78106A28\[^\n\]*\n +\[0-9\]+ +00000020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 6C18\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 2810\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 6A080000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 6A280000\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 6898\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 6E980010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0026 78106AA8\[^\n\]*\n +\[0-9\]+ +00000020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002e 6C98\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 3810\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0032 6A880000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0036 6AA80000\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 16] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_movw {} {
+ set testname "movws.s: h8300s movw tests"
+ set x 0
+
+ gas_start "movws.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 0D01\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 79000010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 6910\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 6F100010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 78106B20\[^\n\]*\n +\[0-9\]+ +00000020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 6D10\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 6B000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 6B200000\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 6990\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 6F900010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0026 78106BA0\[^\n\]*\n +\[0-9\]+ +00000020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002e 6D90\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 6B800000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0034 6BA00000\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 14] then { pass $testname } else { fail $testname }
+}
+
+
+proc do_h8300s_movl {} {
+ set testname "movls.s: h8300s movl tests"
+ set x 0
+
+ gas_start "movls.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 0F81\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 7A000000\[^\n\]*\n +\[0-9\]+ +0040\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 01006910\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 01006F10\[^\n\]*\n +\[0-9\]+ +0010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 01007810\[^\n\]*\n +\[0-9\]+ +6B200000\[^\n\]*\n +\[0-9\]+ +0020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001c 01006D10\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 01006B00\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0026 01006B20\[^\n\]*\n +\[0-9\]+ +00000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002e 01006990\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0032 01006F90\[^\n\]*\n +\[0-9\]+ +0010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0038 01007890\[^\n\]*\n +\[0-9\]+ +6BA00000\[^\n\]*\n +\[0-9\]+ +0020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0042 01006D90\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0046 01006B80\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004c 01006BA0\[^\n\]*\n +\[0-9\]+ +00000000\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 14] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_pushpop {} {
+ set testname "pushpops.s: h8300s pushpop tests"
+ set x 0
+
+ gas_start "pushpops.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 6D70\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 01006D70\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 6DF0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 01006DF0\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 4] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_rotate_shift {} {
+ set testname "rotshs.s: h8300s rotate and shift tests"
+ set x 0
+
+ gas_start "rotshs.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 1288\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 12C8\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 1290\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 12D0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 12B0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 12F0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 1388\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000e 13C8\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 1390\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 13D0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 13B0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 13F0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0018 1208\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 1248\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001c 1210\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 1250\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 1230\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 1270\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0024 1308\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0026 1348\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0028 1310\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002a 1350\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002c 1330\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002e 1370\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 1088\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0032 10C8\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0034 1090\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0036 10D0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0038 10B0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003a 10F0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003c 1188\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003e 11C8\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0040 1190\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0042 11D0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0044 11B0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0046 11F0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0048 1008\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004a 1048\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004c 1010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004e 1050\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0050 1030\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0052 1070\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0054 1108\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0056 1148\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0058 1110\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 005a 1150\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 005c 1130\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 005e 1170\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 48] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_extend {} {
+ set testname "extends.s: h8300s extend tests"
+ set x 0
+
+ gas_start "extends.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 17D0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 17F0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 1750\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 1770\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 4] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_mac {} {
+ set testname "macs.s: h8300s mac tests"
+ set x 0
+
+ gas_start "macs.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 01A0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 0320\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 0331\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 01606D01\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 0220\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 0231\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 6] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_multiple {} {
+ set testname "multiples.s: h8300s multiple tests"
+ set x 0
+
+ gas_start "multiples.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 01106D71\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 01206D72\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 01306D73\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 01106DF0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 01206DF0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 01306DF0\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 6] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300h_mov32bug {} {
+ set testname "mov32bug.s: h8300h mov32bug test"
+ set x 0
+
+ if [gas_test_old "mov32bug.s" "" "Proper relocation for mov.l (part 1)"] then {
+ objdump_start_no_subdir "a.out" "-r"
+
+ while 1 {
+ expect {
+ -re "00000002\[^\n\]*32\[^\n\]*_a.0x0*88ca6c00\[^\n\]*\n"
+ { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ objdump_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 1] then { pass $testname } else { fail $testname }
+}
+
+if [istarget h8300*-*-*] then {
+ # Test the basic h8300 instruction parser
+ do_h8300_add_sub
+ do_h8300_logical
+ do_h8300_cbranch
+ do_h8300_bitops1
+ do_h8300_bitops2
+ do_h8300_bitops3
+ do_h8300_bitops4
+ do_h8300_branch
+ do_h8300_compare
+ do_h8300_decimal
+ do_h8300_incdec
+ do_h8300_divmul
+ do_h8300_misc
+ do_h8300_movb
+ do_h8300_movw
+ do_h8300_pushpop
+ do_h8300_rotate_shift
+
+ # Now test the h8300h instruction parser
+ do_h8300h_add_sub
+ do_h8300h_logical
+ do_h8300h_cbranch
+ do_h8300h_bitops1
+ do_h8300h_bitops2
+ do_h8300h_bitops3
+ do_h8300h_bitops4
+ do_h8300h_branch
+ do_h8300h_compare
+ do_h8300h_decimal
+ do_h8300h_incdec
+ do_h8300h_divmul
+ do_h8300h_misc
+ do_h8300h_movb
+ do_h8300h_movw
+ do_h8300h_movl
+ do_h8300_pushpop
+ do_h8300h_rotate_shift
+ do_h8300h_extend
+
+ # Now test the h8300s instruction parser
+ do_h8300s_add_sub
+ do_h8300s_logical
+ do_h8300s_cbranch
+ do_h8300s_bitops1
+ do_h8300s_bitops2
+ do_h8300s_bitops3
+ do_h8300s_bitops4
+ do_h8300s_branch
+ do_h8300s_compare
+ do_h8300s_decimal
+ do_h8300s_incdec
+ do_h8300s_divmul
+ do_h8300s_misc
+ do_h8300s_movb
+ do_h8300s_movw
+ do_h8300s_movl
+ do_h8300_pushpop
+ do_h8300s_rotate_shift
+ do_h8300s_extend
+ do_h8300s_mac
+ do_h8300s_multiple
+
+ do_h8300h_mov32bug
+
+ # Now some random tests
+ set svr4pic [expr [istarget *-*-elf*] || [istarget *-*-irix5*] ]
+ set empic [expr [istarget *-*-ecoff*] || [istarget *-*-ultrix*] || [istarget *-*-irix\[1-4\]*] ]
+ set aout [expr [istarget *-*-bsd*] || [istarget *-*-netbsd*]]
+
+ run_dump_test "ffxx1"
+ gas_test "cmpsi2.s" "" "" "cmpsi2.s"
+}
diff --git a/gas/testsuite/gas/h8300/incdec.s b/gas/testsuite/gas/h8300/incdec.s
new file mode 100644
index 0000000000..2618827731
--- /dev/null
+++ b/gas/testsuite/gas/h8300/incdec.s
@@ -0,0 +1,5 @@
+ .text
+h8300_incdec:
+ dec r0l
+ inc r0l
+
diff --git a/gas/testsuite/gas/h8300/incdech.s b/gas/testsuite/gas/h8300/incdech.s
new file mode 100644
index 0000000000..bb93fc54b3
--- /dev/null
+++ b/gas/testsuite/gas/h8300/incdech.s
@@ -0,0 +1,14 @@
+ .h8300h
+ .text
+h8300h_incdec:
+ dec.b r0l
+ dec.w #1,r0
+ dec.w #2,r0
+ dec.l #1,er0
+ dec.l #2,er0
+ inc.b r0l
+ inc.w #1,r0
+ inc.w #2,r0
+ inc.l #1,er0
+ inc.l #2,er0
+
diff --git a/gas/testsuite/gas/h8300/incdecs.s b/gas/testsuite/gas/h8300/incdecs.s
new file mode 100644
index 0000000000..2345708b02
--- /dev/null
+++ b/gas/testsuite/gas/h8300/incdecs.s
@@ -0,0 +1,14 @@
+ .h8300s
+ .text
+h8300s_incdec:
+ dec.b r0l
+ dec.w #1,r0
+ dec.w #2,r0
+ dec.l #1,er0
+ dec.l #2,er0
+ inc.b r0l
+ inc.w #1,r0
+ inc.w #2,r0
+ inc.l #1,er0
+ inc.l #2,er0
+
diff --git a/gas/testsuite/gas/h8300/logical.s b/gas/testsuite/gas/h8300/logical.s
new file mode 100644
index 0000000000..3f7e3b7145
--- /dev/null
+++ b/gas/testsuite/gas/h8300/logical.s
@@ -0,0 +1,14 @@
+ .text
+h8300_logical:
+ and #16,r1l
+ and r1l,r1h
+ andc #16,ccr
+ or #16,r0l
+ or r1l,r0l
+ orc #16,ccr
+ xor #16,r0l
+ xor r0l,r1l
+ xorc #16,ccr
+ neg r0l
+ not r0l
+
diff --git a/gas/testsuite/gas/h8300/logicalh.s b/gas/testsuite/gas/h8300/logicalh.s
new file mode 100644
index 0000000000..9e95f11d45
--- /dev/null
+++ b/gas/testsuite/gas/h8300/logicalh.s
@@ -0,0 +1,31 @@
+ .h8300h
+ .text
+h8300h_logical:
+ and.b #16,r1l
+ and.b r1l,r1h
+ and.w #32,r1
+ and.w r1,r1
+ and.l #64,er1
+ and.l er1,er1
+ andc #16,ccr
+ or.b #16,r0l
+ or.b r1l,r0l
+ or.w #32,r1
+ or.w r1,r1
+ or.l #64,er1
+ or.l er1,er1
+ orc #16,ccr
+ xor.b #16,r0l
+ xor.b r0l,r1l
+ xor.w #32,r1
+ xor.w r1,r1
+ xor.l #64,er1
+ xor.l er1,er1
+ xorc #16,ccr
+ neg.b r0l
+ neg.w r0
+ neg.l er0
+ not.b r0l
+ not.w r0
+ not.l er0
+
diff --git a/gas/testsuite/gas/h8300/logicals.s b/gas/testsuite/gas/h8300/logicals.s
new file mode 100644
index 0000000000..c3c4cbaaf0
--- /dev/null
+++ b/gas/testsuite/gas/h8300/logicals.s
@@ -0,0 +1,34 @@
+ .h8300s
+ .text
+h8300s_logical:
+ and.b #16,r1l
+ and.b r1l,r1h
+ and.w #32,r1
+ and.w r1,r1
+ and.l #64,er1
+ and.l er1,er1
+ andc #16,ccr
+ andc #16,exr
+ or.b #16,r0l
+ or.b r1l,r0l
+ or.w #32,r1
+ or.w r1,r1
+ or.l #64,er1
+ or.l er1,er1
+ orc #16,ccr
+ orc #16,exr
+ xor.b #16,r0l
+ xor.b r0l,r1l
+ xor.w #32,r1
+ xor.w r1,r1
+ xor.l #64,er1
+ xor.l er1,er1
+ xorc #16,ccr
+ xorc #16,exr
+ neg.b r0l
+ neg.w r0
+ neg.l er0
+ not.b r0l
+ not.w r0
+ not.l er0
+
diff --git a/gas/testsuite/gas/h8300/macs.s b/gas/testsuite/gas/h8300/macs.s
new file mode 100644
index 0000000000..e2df6ddb65
--- /dev/null
+++ b/gas/testsuite/gas/h8300/macs.s
@@ -0,0 +1,11 @@
+ .h8300s
+ .text
+h8300s_mac:
+ clrmac
+ ldmac er0,mach
+ ldmac er1,macl
+ mac @er0+,@er1+
+ stmac mach,er0
+ stmac macl,er1
+
+
diff --git a/gas/testsuite/gas/h8300/misc.s b/gas/testsuite/gas/h8300/misc.s
new file mode 100644
index 0000000000..1f6f8084b6
--- /dev/null
+++ b/gas/testsuite/gas/h8300/misc.s
@@ -0,0 +1,13 @@
+ .text
+h8300_misc:
+ eepmov
+ ldc #0,ccr
+ ldc r0l,ccr
+; movfpe 16:16,r0l
+; movtpe r0l,16:16
+ nop
+ rte
+ rts
+ sleep
+ stc ccr,r0l
+
diff --git a/gas/testsuite/gas/h8300/misch.s b/gas/testsuite/gas/h8300/misch.s
new file mode 100644
index 0000000000..f7ecb3de07
--- /dev/null
+++ b/gas/testsuite/gas/h8300/misch.s
@@ -0,0 +1,27 @@
+ .h8300h
+ .text
+h8300h_misc:
+ eepmov.b
+ eepmov.w
+ ldc.b #0,ccr
+ ldc.b r0l,ccr
+ ldc.w @er0,ccr
+ ldc.w @(16:16,er0),ccr
+ ldc.w @(32:24,er0),ccr
+ ldc.w @er0+,ccr
+ ldc.w @h8300h_misc:16,ccr
+ ldc.w @h8300h_misc:24,ccr
+; movfpe 16:16,r0l
+; movtpe r0l,16:16
+ nop
+ rte
+ rts
+ sleep
+ stc.b ccr,r0l
+ stc.w ccr,@er0
+ stc.w ccr,@(16:16,er0)
+ stc.w ccr,@(32:24,er0)
+ stc.w ccr,@-er0
+ stc.w ccr,@h8300h_misc:16
+ stc.w ccr,@h8300h_misc:24
+
diff --git a/gas/testsuite/gas/h8300/miscs.s b/gas/testsuite/gas/h8300/miscs.s
new file mode 100644
index 0000000000..d37a1770c7
--- /dev/null
+++ b/gas/testsuite/gas/h8300/miscs.s
@@ -0,0 +1,41 @@
+ .h8300s
+ .text
+h8300s_misc:
+ eepmov.b
+ eepmov.w
+ ldc.b #0,ccr
+ ldc.b r0l,ccr
+ ldc.b #0,exr
+ ldc.b r0l,exr
+ ldc.w @er0,ccr
+ ldc.w @(16:16,er0),ccr
+ ldc.w @(32:32,er0),ccr
+ ldc.w @er0+,ccr
+ ldc.w @h8300s_misc:16,ccr
+ ldc.w @h8300s_misc:32,ccr
+ ldc.w @er0,exr
+ ldc.w @(16:16,er0),exr
+ ldc.w @(32:32,er0),exr
+ ldc.w @er0+,exr
+ ldc.w @h8300s_misc:16,exr
+ ldc.w @h8300s_misc:32,exr
+; movfpe 16:16,r0l
+; movtpe r0l,16:16
+ nop
+ rte
+ rts
+ sleep
+ stc.b ccr,r0l
+ stc.b exr,r0l
+ stc.w ccr,@er0
+ stc.w ccr,@(16:16,er0)
+ stc.w ccr,@(32:32,er0)
+ stc.w ccr,@-er0
+ stc.w ccr,@h8300s_misc:16
+ stc.w ccr,@h8300s_misc:32
+ stc.w exr,@er0
+ stc.w exr,@(16:16,er0)
+ stc.w exr,@(32:32,er0)
+ stc.w exr,@-er0
+ stc.w exr,@h8300s_misc:16
+ stc.w exr,@h8300s_misc:32
diff --git a/gas/testsuite/gas/h8300/mov32bug.s b/gas/testsuite/gas/h8300/mov32bug.s
new file mode 100644
index 0000000000..68393e3f54
--- /dev/null
+++ b/gas/testsuite/gas/h8300/mov32bug.s
@@ -0,0 +1,4 @@
+ .h8300h
+ .global _a
+blah:
+ mov.l #_a-2000000000,er2
diff --git a/gas/testsuite/gas/h8300/movb.s b/gas/testsuite/gas/h8300/movb.s
new file mode 100644
index 0000000000..fa040c0a7b
--- /dev/null
+++ b/gas/testsuite/gas/h8300/movb.s
@@ -0,0 +1,15 @@
+ .text
+h8300_movb:
+ mov.b r0l,r1l
+ mov.b #16,r0l
+ mov.b @r1,r0l
+ mov.b @(16:16,r1),r0l
+ mov.b @r1+,r0l
+ mov.b @16:8,r0l
+ mov.b @h8300_movb:16,r0l
+ mov.b r0l,@r1
+ mov.b r0l,@(16:16,r1)
+ mov.b r0l,@-r1
+ mov.b r0l,@16:8
+ mov.b r0l,@h8300_movb:16
+
diff --git a/gas/testsuite/gas/h8300/movbh.s b/gas/testsuite/gas/h8300/movbh.s
new file mode 100644
index 0000000000..7d711f8512
--- /dev/null
+++ b/gas/testsuite/gas/h8300/movbh.s
@@ -0,0 +1,20 @@
+ .h8300h
+ .text
+h8300h_movb:
+ mov.b r0l,r1l
+ mov.b #16,r0l
+ mov.b @er1,r0l
+ mov.b @(16:16,er1),r0l
+ mov.b @(32:24,er1),r0l
+ mov.b @er1+,r0l
+ mov.b @16:8,r0l
+ mov.b @h8300h_movb:16,r0l
+ mov.b @h8300h_movb:24,r0l
+ mov.b r0l,@er1
+ mov.b r0l,@(16:16,er1)
+ mov.b r0l,@(32:24,er1)
+ mov.b r0l,@-er1
+ mov.b r0l,@16:8
+ mov.b r0l,@h8300h_movb:16
+ mov.b r0l,@h8300h_movb:24
+
diff --git a/gas/testsuite/gas/h8300/movbs.s b/gas/testsuite/gas/h8300/movbs.s
new file mode 100644
index 0000000000..925002c811
--- /dev/null
+++ b/gas/testsuite/gas/h8300/movbs.s
@@ -0,0 +1,20 @@
+ .h8300s
+ .text
+h8300s_movb:
+ mov.b r0l,r1l
+ mov.b #16,r0l
+ mov.b @er1,r0l
+ mov.b @(16:16,er1),r0l
+ mov.b @(32:32,er1),r0l
+ mov.b @er1+,r0l
+ mov.b @16:8,r0l
+ mov.b @h8300s_movb:16,r0l
+ mov.b @h8300s_movb:32,r0l
+ mov.b r0l,@er1
+ mov.b r0l,@(16:16,er1)
+ mov.b r0l,@(32:32,er1)
+ mov.b r0l,@-er1
+ mov.b r0l,@16:8
+ mov.b r0l,@h8300s_movb:16
+ mov.b r0l,@h8300s_movb:32
+
diff --git a/gas/testsuite/gas/h8300/movlh.s b/gas/testsuite/gas/h8300/movlh.s
new file mode 100644
index 0000000000..0cc78e8d36
--- /dev/null
+++ b/gas/testsuite/gas/h8300/movlh.s
@@ -0,0 +1,18 @@
+ .h8300h
+ .text
+h8300h_movl:
+ mov.l er0,er1
+ mov.l #64,er0
+ mov.l @er1,er0
+ mov.l @(16:16,er1),er0
+ mov.l @(32:24,er1),er0
+ mov.l @er1+,er0
+ mov.l @h8300h_movl:16,er0
+ mov.l @h8300h_movl:24,er0
+ mov.l er0,@er1
+ mov.l er0,@(16:16,er1)
+ mov.l er0,@(32:24,er1)
+ mov.l er0,@-er1
+ mov.l er0,@h8300h_movl:16
+ mov.l er0,@h8300h_movl:24
+
diff --git a/gas/testsuite/gas/h8300/movls.s b/gas/testsuite/gas/h8300/movls.s
new file mode 100644
index 0000000000..4643767738
--- /dev/null
+++ b/gas/testsuite/gas/h8300/movls.s
@@ -0,0 +1,18 @@
+ .h8300s
+ .text
+h8300s_movl:
+ mov.l er0,er1
+ mov.l #64,er0
+ mov.l @er1,er0
+ mov.l @(16:16,er1),er0
+ mov.l @(32:32,er1),er0
+ mov.l @er1+,er0
+ mov.l @h8300s_movl:16,er0
+ mov.l @h8300s_movl:32,er0
+ mov.l er0,@er1
+ mov.l er0,@(16:16,er1)
+ mov.l er0,@(32:32,er1)
+ mov.l er0,@-er1
+ mov.l er0,@h8300s_movl:16
+ mov.l er0,@h8300s_movl:32
+
diff --git a/gas/testsuite/gas/h8300/movw.s b/gas/testsuite/gas/h8300/movw.s
new file mode 100644
index 0000000000..0cc64f8d52
--- /dev/null
+++ b/gas/testsuite/gas/h8300/movw.s
@@ -0,0 +1,13 @@
+ .text
+h8300_movw:
+ mov.w r0,r1
+ mov.w #16,r0
+ mov.w @r1,r0
+ mov.w @(16:16,r1),r0
+ mov.w @r1+,r0
+ mov.w @h8300_movw:16,r0
+ mov.w r0,@r1
+ mov.w r0,@(16:16,r1)
+ mov.w r0,@-r1
+ mov.w r0,@h8300_movw:16
+
diff --git a/gas/testsuite/gas/h8300/movwh.s b/gas/testsuite/gas/h8300/movwh.s
new file mode 100644
index 0000000000..595057cb3d
--- /dev/null
+++ b/gas/testsuite/gas/h8300/movwh.s
@@ -0,0 +1,18 @@
+ .h8300h
+ .text
+h8300h_movw:
+ mov.w r0,r1
+ mov.w #16,r0
+ mov.w @er1,r0
+ mov.w @(16:16,er1),r0
+ mov.w @(32:24,er1),r0
+ mov.w @er1+,r0
+ mov.w @h8300h_movw:16,r0
+ mov.w @h8300h_movw:24,r0
+ mov.w r0,@er1
+ mov.w r0,@(16:16,er1)
+ mov.w r0,@(32:24,er1)
+ mov.w r0,@-er1
+ mov.w r0,@h8300h_movw:16
+ mov.w r0,@h8300h_movw:24
+
diff --git a/gas/testsuite/gas/h8300/movws.s b/gas/testsuite/gas/h8300/movws.s
new file mode 100644
index 0000000000..a4f21df254
--- /dev/null
+++ b/gas/testsuite/gas/h8300/movws.s
@@ -0,0 +1,18 @@
+ .h8300s
+ .text
+h8300s_movw:
+ mov.w r0,r1
+ mov.w #16,r0
+ mov.w @er1,r0
+ mov.w @(16:16,er1),r0
+ mov.w @(32:32,er1),r0
+ mov.w @er1+,r0
+ mov.w @h8300s_movw:16,r0
+ mov.w @h8300s_movw:32,r0
+ mov.w r0,@er1
+ mov.w r0,@(16:16,er1)
+ mov.w r0,@(32:32,er1)
+ mov.w r0,@-er1
+ mov.w r0,@h8300s_movw:16
+ mov.w r0,@h8300s_movw:32
+
diff --git a/gas/testsuite/gas/h8300/multiples.s b/gas/testsuite/gas/h8300/multiples.s
new file mode 100644
index 0000000000..52079b6d21
--- /dev/null
+++ b/gas/testsuite/gas/h8300/multiples.s
@@ -0,0 +1,10 @@
+ .h8300s
+ .text
+h8300s_multiple:
+ ldm.l @sp+,er0-er1
+ ldm.l @sp+,er0-er2
+ ldm.l @sp+,er0-er3
+ stm.l er0-er1,@-sp
+ stm.l er0-er2,@-sp
+ stm.l er0-er3,@-sp
+
diff --git a/gas/testsuite/gas/h8300/pushpop.s b/gas/testsuite/gas/h8300/pushpop.s
new file mode 100644
index 0000000000..941b735753
--- /dev/null
+++ b/gas/testsuite/gas/h8300/pushpop.s
@@ -0,0 +1,5 @@
+ .text
+h8300_push_pop:
+ pop r0
+ push r0
+
diff --git a/gas/testsuite/gas/h8300/pushpoph.s b/gas/testsuite/gas/h8300/pushpoph.s
new file mode 100644
index 0000000000..6049639f56
--- /dev/null
+++ b/gas/testsuite/gas/h8300/pushpoph.s
@@ -0,0 +1,8 @@
+ .h8300h
+ .text
+h8300h_push_pop:
+ pop.w r0
+ pop.l er0
+ push.w r0
+ push.l er0
+
diff --git a/gas/testsuite/gas/h8300/pushpops.s b/gas/testsuite/gas/h8300/pushpops.s
new file mode 100644
index 0000000000..741df04ecc
--- /dev/null
+++ b/gas/testsuite/gas/h8300/pushpops.s
@@ -0,0 +1,8 @@
+ .h8300s
+ .text
+h8300s_push_pop:
+ pop.w r0
+ pop.l er0
+ push.w r0
+ push.l er0
+
diff --git a/gas/testsuite/gas/h8300/rotsh.s b/gas/testsuite/gas/h8300/rotsh.s
new file mode 100644
index 0000000000..a9aa87df95
--- /dev/null
+++ b/gas/testsuite/gas/h8300/rotsh.s
@@ -0,0 +1,11 @@
+ .text
+h8300_rotate_shift:
+ rotl r0l
+ rotr r0l
+ rotxl r0l
+ rotxr r0l
+ shal r0l
+ shar r0l
+ shll r0l
+ shlr r0l
+
diff --git a/gas/testsuite/gas/h8300/rotshh.s b/gas/testsuite/gas/h8300/rotshh.s
new file mode 100644
index 0000000000..c7abe40a28
--- /dev/null
+++ b/gas/testsuite/gas/h8300/rotshh.s
@@ -0,0 +1,27 @@
+ .h8300h
+ .text
+h8300h_rotate_shift:
+ rotl.b r0l
+ rotl.w r0
+ rotl.l er0
+ rotr.b r0l
+ rotr.w r0
+ rotr.l er0
+ rotxl.b r0l
+ rotxl.w r0
+ rotxl.l er0
+ rotxr.b r0l
+ rotxr.w r0
+ rotxr.l er0
+ shal.b r0l
+ shal.w r0
+ shal.l er0
+ shar.b r0l
+ shar.w r0
+ shar.l er0
+ shll.b r0l
+ shll.w r0
+ shll.l er0
+ shlr.b r0l
+ shlr.w r0
+ shlr.l er0
diff --git a/gas/testsuite/gas/h8300/rotshs.s b/gas/testsuite/gas/h8300/rotshs.s
new file mode 100644
index 0000000000..36c41cb59c
--- /dev/null
+++ b/gas/testsuite/gas/h8300/rotshs.s
@@ -0,0 +1,51 @@
+ .h8300s
+ .text
+h8300s_rotate_shift:
+ rotl.b r0l
+ rotl.b #2,r0l
+ rotl.w r0
+ rotl.w #2,r0
+ rotl.l er0
+ rotl.l #2,er0
+ rotr.b r0l
+ rotr.b #2,r0l
+ rotr.w r0
+ rotr.w #2,r0
+ rotr.l er0
+ rotr.l #2,er0
+ rotxl.b r0l
+ rotxl.b #2,r0l
+ rotxl.w r0
+ rotxl.w #2,r0
+ rotxl.l er0
+ rotxl.l #2,er0
+ rotxr.b r0l
+ rotxr.b #2,r0l
+ rotxr.w r0
+ rotxr.w #2,r0
+ rotxr.l er0
+ rotxr.l #2,er0
+ shal.b r0l
+ shal.b #2,r0l
+ shal.w r0
+ shal.w #2,r0
+ shal.l er0
+ shal.l #2,er0
+ shar.b r0l
+ shar.b #2,r0l
+ shar.w r0
+ shar.w #2,r0
+ shar.l er0
+ shar.l #2,er0
+ shll.b r0l
+ shll.b #2,r0l
+ shll.w r0
+ shll.w #2,r0
+ shll.l er0
+ shll.l #2,er0
+ shlr.b r0l
+ shlr.b #2,r0l
+ shlr.w r0
+ shlr.w #2,r0
+ shlr.l er0
+ shlr.l #2,er0
diff --git a/gas/testsuite/gas/hppa/README b/gas/testsuite/gas/hppa/README
new file mode 100644
index 0000000000..a6b174a3bc
--- /dev/null
+++ b/gas/testsuite/gas/hppa/README
@@ -0,0 +1,34 @@
+Notes on how the HPPA testsuite is organized:
+
+basic.parse -- this directory contains the basic instruction parsing
+tests and a simple .stab parsing test. This would be where you'd
+add code to make sure new instructions are parsed correctly, new
+completers (such as cache hits) are parsed correctly, etc.
+
+It's also a reasonable place to make sure parsing of the various
+assembler directives is handled correctly. If you're going to add
+such code, try to be reasonably complete. Add test code for each
+basic directive and test all (or a noteworthy) subset of arguments.
+
+It should only be necessary to have an assembler to run these tests;
+calling objdump_start or something similar should not be done from
+this directory.
+
+
+more.parse -- this is where you should put additional parsing tests, such
+as tests to check mode selector parsing, string parsing, expression parsing,
+etc. It's also a reasonable place to put parsing tests which are not complete
+enough (whatever that means) for basic.parse.
+
+It should only be necessary to have an assembler to run these tests;
+calling objdump_start or something similar should not be done from
+this directory.
+
+
+reloc -- this is where you tests which examine relocations produced
+by GAS belong. To run these tests you must have a functioning objdump.
+
+
+unsorted -- this is where everything else goes. As groups of related tests
+end up in this directory, they should be broken out into a new class of
+tests.
diff --git a/gas/testsuite/gas/hppa/basic/add.s b/gas/testsuite/gas/hppa/basic/add.s
new file mode 100644
index 0000000000..4d1d4cd6d7
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/add.s
@@ -0,0 +1,100 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic add/sh?add instruction tests.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+ add %r4,%r5,%r6
+ add,= %r4,%r5,%r6
+ add,< %r4,%r5,%r6
+ add,<= %r4,%r5,%r6
+ add,nuv %r4,%r5,%r6
+ add,znv %r4,%r5,%r6
+ add,sv %r4,%r5,%r6
+ add,od %r4,%r5,%r6
+ add,tr %r4,%r5,%r6
+ add,<> %r4,%r5,%r6
+ add,>= %r4,%r5,%r6
+ add,> %r4,%r5,%r6
+ add,uv %r4,%r5,%r6
+ add,vnz %r4,%r5,%r6
+ add,nsv %r4,%r5,%r6
+ add,ev %r4,%r5,%r6
+
+ addl %r4,%r5,%r6
+ addl,= %r4,%r5,%r6
+ addl,< %r4,%r5,%r6
+ addl,<= %r4,%r5,%r6
+ addl,nuv %r4,%r5,%r6
+ addl,znv %r4,%r5,%r6
+ addl,sv %r4,%r5,%r6
+ addl,od %r4,%r5,%r6
+ addl,tr %r4,%r5,%r6
+ addl,<> %r4,%r5,%r6
+ addl,>= %r4,%r5,%r6
+ addl,> %r4,%r5,%r6
+ addl,uv %r4,%r5,%r6
+ addl,vnz %r4,%r5,%r6
+ addl,nsv %r4,%r5,%r6
+ addl,ev %r4,%r5,%r6
+
+ addo %r4,%r5,%r6
+ addo,= %r4,%r5,%r6
+ addo,< %r4,%r5,%r6
+ addo,<= %r4,%r5,%r6
+ addo,nuv %r4,%r5,%r6
+ addo,znv %r4,%r5,%r6
+ addo,sv %r4,%r5,%r6
+ addo,od %r4,%r5,%r6
+ addo,tr %r4,%r5,%r6
+ addo,<> %r4,%r5,%r6
+ addo,>= %r4,%r5,%r6
+ addo,> %r4,%r5,%r6
+ addo,uv %r4,%r5,%r6
+ addo,vnz %r4,%r5,%r6
+ addo,nsv %r4,%r5,%r6
+ addo,ev %r4,%r5,%r6
+
+ addc %r4,%r5,%r6
+ addc,= %r4,%r5,%r6
+ addc,< %r4,%r5,%r6
+ addc,<= %r4,%r5,%r6
+ addc,nuv %r4,%r5,%r6
+ addc,znv %r4,%r5,%r6
+ addc,sv %r4,%r5,%r6
+ addc,od %r4,%r5,%r6
+ addc,tr %r4,%r5,%r6
+ addc,<> %r4,%r5,%r6
+ addc,>= %r4,%r5,%r6
+ addc,> %r4,%r5,%r6
+ addc,uv %r4,%r5,%r6
+ addc,vnz %r4,%r5,%r6
+ addc,nsv %r4,%r5,%r6
+ addc,ev %r4,%r5,%r6
+
+ addco %r4,%r5,%r6
+ addco,= %r4,%r5,%r6
+ addco,< %r4,%r5,%r6
+ addco,<= %r4,%r5,%r6
+ addco,nuv %r4,%r5,%r6
+ addco,znv %r4,%r5,%r6
+ addco,sv %r4,%r5,%r6
+ addco,od %r4,%r5,%r6
+ addco,tr %r4,%r5,%r6
+ addco,<> %r4,%r5,%r6
+ addco,>= %r4,%r5,%r6
+ addco,> %r4,%r5,%r6
+ addco,uv %r4,%r5,%r6
+ addco,vnz %r4,%r5,%r6
+ addco,nsv %r4,%r5,%r6
+ addco,ev %r4,%r5,%r6
diff --git a/gas/testsuite/gas/hppa/basic/addi.s b/gas/testsuite/gas/hppa/basic/addi.s
new file mode 100644
index 0000000000..b036b80160
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/addi.s
@@ -0,0 +1,83 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic immediate instruction tests.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+ addi 123,%r5,%r6
+ addi,= 123,%r5,%r6
+ addi,< 123,%r5,%r6
+ addi,<= 123,%r5,%r6
+ addi,nuv 123,%r5,%r6
+ addi,znv 123,%r5,%r6
+ addi,sv 123,%r5,%r6
+ addi,od 123,%r5,%r6
+ addi,tr 123,%r5,%r6
+ addi,<> 123,%r5,%r6
+ addi,>= 123,%r5,%r6
+ addi,> 123,%r5,%r6
+ addi,uv 123,%r5,%r6
+ addi,vnz 123,%r5,%r6
+ addi,nsv 123,%r5,%r6
+ addi,ev 123,%r5,%r6
+
+ addio 123,%r5,%r6
+ addio,= 123,%r5,%r6
+ addio,< 123,%r5,%r6
+ addio,<= 123,%r5,%r6
+ addio,nuv 123,%r5,%r6
+ addio,znv 123,%r5,%r6
+ addio,sv 123,%r5,%r6
+ addio,od 123,%r5,%r6
+ addio,tr 123,%r5,%r6
+ addio,<> 123,%r5,%r6
+ addio,>= 123,%r5,%r6
+ addio,> 123,%r5,%r6
+ addio,uv 123,%r5,%r6
+ addio,vnz 123,%r5,%r6
+ addio,nsv 123,%r5,%r6
+ addio,ev 123,%r5,%r6
+
+ addit 123,%r5,%r6
+ addit,= 123,%r5,%r6
+ addit,< 123,%r5,%r6
+ addit,<= 123,%r5,%r6
+ addit,nuv 123,%r5,%r6
+ addit,znv 123,%r5,%r6
+ addit,sv 123,%r5,%r6
+ addit,od 123,%r5,%r6
+ addit,tr 123,%r5,%r6
+ addit,<> 123,%r5,%r6
+ addit,>= 123,%r5,%r6
+ addit,> 123,%r5,%r6
+ addit,uv 123,%r5,%r6
+ addit,vnz 123,%r5,%r6
+ addit,nsv 123,%r5,%r6
+ addit,ev 123,%r5,%r6
+
+ addito 123,%r5,%r6
+ addito,= 123,%r5,%r6
+ addito,< 123,%r5,%r6
+ addito,<= 123,%r5,%r6
+ addito,nuv 123,%r5,%r6
+ addito,znv 123,%r5,%r6
+ addito,sv 123,%r5,%r6
+ addito,od 123,%r5,%r6
+ addito,tr 123,%r5,%r6
+ addito,<> 123,%r5,%r6
+ addito,>= 123,%r5,%r6
+ addito,> 123,%r5,%r6
+ addito,uv 123,%r5,%r6
+ addito,vnz 123,%r5,%r6
+ addito,nsv 123,%r5,%r6
+ addito,ev 123,%r5,%r6
diff --git a/gas/testsuite/gas/hppa/basic/basic.exp b/gas/testsuite/gas/hppa/basic/basic.exp
new file mode 100644
index 0000000000..a9ba5ea9e2
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/basic.exp
@@ -0,0 +1,2262 @@
+# Copyright (C) 1993, 1996, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, 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 more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# DejaGnu@cygnus.com
+
+# Written by the Center for Software Science at the Univeristy of Utah
+# and by Cygnus Support.
+
+proc do_imem {} {
+ set testname "imem.s: integer memory loads and stores"
+ set x 0
+
+ gas_start "imem.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 489A0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0000 0C80109A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 449A0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 0C80105A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 409A0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 0C80101A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 689A0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 0C9A1280\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 649A0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 0C9A1240\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 609A0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 0C9A1200\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 4C9A0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c 6C9A0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 0C85009A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 0C85209A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 0C8500BA\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c 0C8520BA\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 0C85005A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 0C85205A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 0C85007A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c 0C85207A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 0C85001A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 0C85201A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 0C85003A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004c 0C85203A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0050 0C85019A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0054 0C85219A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0058 0C8501BA\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 005c 0C8521BA\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0060 0C8501DA\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0064 0C8521DA\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0068 0C8501FA\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 006c 0C8521FA\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0070 0C80109A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0074 0C8030BA\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0078 0C8010BA\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 007c 0C80105A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0080 0C80307A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0084 0C80107A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0088 0C80101A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 008c 0C80303A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0090 0C80103A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0094 0C80119A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0098 0C8031BA\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 009c 0C8011BA\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a0 0C8011DA\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a4 0C8031FA\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a8 0C8011FA\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00ac 0C9A1280\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b0 0C9A32A0\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b4 0C9A12A0\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b8 0C9A1240\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00bc 0C9A3260\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c0 0C9A1260\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c4 0C9A1200\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c8 0C9A3220\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00cc 0C9A1220\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d0 0C9A1380\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d4 0C9A33A0\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d8 0C9A13A0\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00dc 0C9A1300\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e0 0C9A1300\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e4 0C9A3300\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e8 0C9A1320\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00ec 0C9A3320\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==60] then { pass $testname } else { fail $testname }
+}
+
+proc do_immed {} {
+ set testname "immed.s: immediate tests"
+ set x 0
+
+ gas_start "immed.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 375A000A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 234DFBD5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 28ADFBD5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==3] then { pass $testname } else { fail $testname }
+}
+
+proc do_branch {} {
+ set testname "branch.s: branch tests"
+ set x 0
+
+ gas_start "branch.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 E85F1FF5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 E85F1FEF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 E81F1FE5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c E81F1FDF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 E85F3FD5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 E85F3FCF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 E8444000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c E8444002\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 E8044000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 E8044002\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 E840C000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c E840C002\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 E040446C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 E040446E\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 E440446C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c E440446E\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 CB441FF5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 CB443FED\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 CB445FE5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004c CB447FDD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0050 CB449FD5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0054 CB44BFCD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0058 CB44DFC5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 005c CB44FFBD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0060 CB441FB7\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0064 CB443FAF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0068 CB445FA7\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 006c CB447F9F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0070 CB449F97\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0074 CB44BF8F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0078 CB44DF87\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 007c CB44FF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0080 CF4A1FF5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0084 CF4A3FED\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0088 CF4A5FE5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 008c CF4A7FDD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0090 CF4A9FD5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0094 CF4ABFCD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0098 CF4ADFC5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 009c CF4AFFBD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a0 CF4A1FB7\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a4 CF4A3FAF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a8 CF4A5FA7\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00ac CF4A7F9F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b0 CF4A9F97\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b4 CF4ABF8F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b8 CF4ADF87\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00bc CF4AFF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c0 80801FF5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c4 80803FED\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c8 80805FE5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00cc 80807FDD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d0 80809FD5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d4 8080BFCD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d8 8080DFC5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00dc 8080FFBD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e0 88801FB5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e4 88803FAD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e8 88805FA5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00ec 88807F9D\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00f0 88809F95\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00f4 8880BF8D\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00f8 8880DF85\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00fc 8880FF7D\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0100 80801F77\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0104 80803F6F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0108 80805F67\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 010c 80807F5F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0110 80809F57\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0114 8080BF4F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0118 8080DF47\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 011c 8080FF3F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0120 88801F37\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0124 88803F2F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0128 88805F27\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 012c 88807F1F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0130 88809F17\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0134 8880BF0F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0138 8880DF07\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 013c 8880FEFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0140 84801FF5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0144 84805FED\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0148 84807FE5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 014c 84809FDD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0150 8480BFD5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0154 8480DFCD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0158 8480FFC5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 015c 8C801FBD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0160 8C803FB5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0164 8C805FAD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0168 8C807FA5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 016c 8C809F9D\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0170 8C80BF95\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0174 8C80DF8D\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0178 8C80FE85\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 017c 84801F7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0180 84803F77\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0184 84805F6F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0188 84807F67\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 018c 84809F5F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0190 8480BF57\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0194 8480DF4F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0198 8480FF47\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 019c 8C801F3F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01a0 8C803F37\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01a4 8C805F2F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01a8 8C807F27\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01ac 8C809F1F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01b0 8C80BF17\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01b4 8C80DF0F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01b8 8C80FF07\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01bc A0811FF5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01c0 A0813FED\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01c4 A0815FE5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01c8 A0817FDD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01cc A0819FD5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01d0 A081BFCD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01d4 A081DFC5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01d8 A081FFBD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01dc A8811FB5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01e0 A8813FAD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01e4 A8815FA5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01e8 A8817F9D\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01ec A8819F95\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01f0 A881BF8D\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01f4 A881DF85\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01f8 A881FF7D\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01fc A0811F77\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0200 A0813F6F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0204 A0815F67\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0208 A0817F5F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 020c A0819F57\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0210 A081BF4F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0214 A081DF47\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0218 A081FF3F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 021c A8811F37\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0220 A8813F2F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0224 A8815F27\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0228 A8817F1F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 022c A8819F17\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0230 A881BF0F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0234 A881DF07\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0238 A881FEFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 023c A49F1FF5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0240 A49F3FED\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0244 A49F5FE5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0248 A49F7FDD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 024c A49F9FD5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0250 A49FBFCD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0254 A49FDFC5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0258 A49FFFBD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 025c AC9F1FB5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0260 AC9F3FAD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0264 AC9F5FA5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0268 AC9F7F9D\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 026c AC9F9F95\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0270 AC9FBF8D\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0274 AC9FDF85\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0278 AC9FFC85\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 027c A49F1F77\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0280 A49F3F6F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0284 A49F5F67\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0288 A49F7F5F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 028c A49F9F57\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0290 A49FBF4F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0294 A49FDF47\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0298 A49FFF3F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 029c AC9F1F37\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 02a0 AC9F3F2F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 02a4 AC9F5F27\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 02a8 AC9F7F1F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 02ac AC9F9F17\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 02b0 AC9FBF0F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 02b4 AC9FDF07\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 02b8 AC9FFEFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 02bc C0045FF5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 02c0 C004DFED\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 02c4 C0045FE7\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 02c8 C004DFDF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 02cc C4A45FD5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 02d0 C4A4DFCD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 02d4 C4A45FC7\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 02d8 C4A4DFBF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==183] then { pass $testname } else { fail $testname }
+}
+
+proc do_add {} {
+ set testname "add.s: add tests"
+ set x 0
+
+ gas_start "add.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 08A40606\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 08A42606\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 08A44606\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 08A46606\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 08A48606\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 08A4A606\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 08A4C606\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c 08A4E606\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 08A41606\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 08A43606\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 08A45606\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c 08A47606\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 08A49606\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 08A4B606\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 08A4D606\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c 08A4F606\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 08A40A06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 08A42A06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 08A44A06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004c 08A46A06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0050 08A48A06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0054 08A4AA06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0058 08A4CA06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 005c 08A4EA06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0060 08A41A06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0064 08A43A06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0068 08A45A06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 006c 08A47A06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0070 08A49A06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0074 08A4BA06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0078 08A4DA06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 007c 08A4FA06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0080 08A40E06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0084 08A42E06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0088 08A44E06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 008c 08A46E06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0090 08A48E06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0094 08A4AE06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0098 08A4CE06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 009c 08A4EE06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a0 08A41E06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a4 08A43E06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a8 08A45E06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00ac 08A47E06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b0 08A49E06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b4 08A4BE06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b8 08A4DE06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00bc 08A4FE06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c0 08A40706\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c4 08A42706\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c8 08A44706\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00cc 08A46706\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d0 08A48706\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d4 08A4A706\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d8 08A4C706\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00dc 08A4E706\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e0 08A41706\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e4 08A43706\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e8 08A45706\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00ec 08A47706\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00f0 08A49706\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00f4 08A4B706\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00f8 08A4D706\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00fc 08A4F706\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0100 08A40F06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0104 08A42F06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0108 08A44F06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 010c 08A46F06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0110 08A48F06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0114 08A4AF06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0118 08A4CF06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 011c 08A4EF06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0120 08A41F06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0124 08A43F06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0128 08A45F06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 012c 08A47F06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0130 08A49F06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0134 08A4BF06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0138 08A4DF06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 013c 08A4FF06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==80] then { pass $testname } else { fail $testname }
+}
+
+proc do_sh1add {} {
+ set testname "sh1add.s: sh1add tests"
+ set x 0
+
+ gas_start "sh1add.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 08A40646\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 08A42646\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 08A44646\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 08A46646\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 08A48646\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 08A4A646\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 08A4C646\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c 08A4E646\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 08A41646\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 08A43646\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 08A45646\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c 08A47646\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 08A49646\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 08A4B646\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 08A4D646\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c 08A4F646\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 08A40A46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 08A42A46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 08A44A46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004c 08A46A46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0050 08A48A46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0054 08A4AA46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0058 08A4CA46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 005c 08A4EA46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0060 08A41A46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0064 08A43A46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0068 08A45A46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 006c 08A47A46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0070 08A49A46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0074 08A4BA46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0078 08A4DA46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 007c 08A4FA46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0080 08A40E46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0084 08A42E46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0088 08A44E46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 008c 08A46E46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0090 08A48E46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0094 08A4AE46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0098 08A4CE46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 009c 08A4EE46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a0 08A41E46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a4 08A43E46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a8 08A45E46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00ac 08A47E46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b0 08A49E46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b4 08A4BE46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b8 08A4DE46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00bc 08A4FE46\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==48] then { pass $testname } else { fail $testname }
+}
+
+proc do_sh2add {} {
+ set testname "sh2add.s: sh2add tests"
+ set x 0
+
+ gas_start "sh2add.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 08A40686\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 08A42686\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 08A44686\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 08A46686\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 08A48686\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 08A4A686\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 08A4C686\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c 08A4E686\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 08A41686\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 08A43686\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 08A45686\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c 08A47686\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 08A49686\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 08A4B686\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 08A4D686\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c 08A4F686\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 08A40A86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 08A42A86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 08A44A86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004c 08A46A86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0050 08A48A86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0054 08A4AA86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0058 08A4CA86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 005c 08A4EA86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0060 08A41A86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0064 08A43A86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0068 08A45A86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 006c 08A47A86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0070 08A49A86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0074 08A4BA86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0078 08A4DA86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 007c 08A4FA86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0080 08A40E86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0084 08A42E86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0088 08A44E86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 008c 08A46E86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0090 08A48E86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0094 08A4AE86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0098 08A4CE86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 009c 08A4EE86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a0 08A41E86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a4 08A43E86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a8 08A45E86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00ac 08A47E86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b0 08A49E86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b4 08A4BE86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b8 08A4DE86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00bc 08A4FE86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==48] then { pass $testname } else { fail $testname }
+}
+
+proc do_sh3add {} {
+ set testname "sh3add.s: sh3add tests"
+ set x 0
+
+ gas_start "sh3add.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 08A406C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 08A426C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 08A446C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 08A466C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 08A486C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 08A4A6C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 08A4C6C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c 08A4E6C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 08A416C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 08A436C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 08A456C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c 08A476C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 08A496C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 08A4B6C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 08A4D6C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c 08A4F6C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 08A40AC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 08A42AC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 08A44AC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004c 08A46AC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0050 08A48AC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0054 08A4AAC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0058 08A4CAC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 005c 08A4EAC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0060 08A41AC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0064 08A43AC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0068 08A45AC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 006c 08A47AC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0070 08A49AC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0074 08A4BAC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0078 08A4DAC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 007c 08A4FAC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0080 08A40EC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0084 08A42EC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0088 08A44EC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 008c 08A46EC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0090 08A48EC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0094 08A4AEC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0098 08A4CEC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 009c 08A4EEC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a0 08A41EC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a4 08A43EC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a8 08A45EC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00ac 08A47EC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b0 08A49EC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b4 08A4BEC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b8 08A4DEC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00bc 08A4FEC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==48] then { pass $testname } else { fail $testname }
+}
+
+proc do_sub {} {
+ set testname "sub.s: sub tests"
+ set x 0
+
+ gas_start "sub.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 08A40406\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 08A42406\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 08A44406\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 08A46406\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 08A48406\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 08A4A406\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 08A4C406\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c 08A4E406\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 08A41406\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 08A43406\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 08A45406\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c 08A47406\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 08A49406\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 08A4B406\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 08A4D406\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c 08A4F406\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 08A40C06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 08A42C06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 08A44C06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004c 08A46C06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0050 08A48C06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0054 08A4AC06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0058 08A4CC06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 005c 08A4EC06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0060 08A41C06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0064 08A43C06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0068 08A45C06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 006c 08A47C06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0070 08A49C06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0074 08A4BC06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0078 08A4DC06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 007c 08A4FC06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0080 08A40506\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0084 08A42506\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0088 08A44506\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 008c 08A46506\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0090 08A48506\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0094 08A4A506\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0098 08A4C506\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 009c 08A4E506\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a0 08A41506\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a4 08A43506\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a8 08A45506\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00ac 08A47506\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b0 08A49506\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b4 08A4B506\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b8 08A4D506\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00bc 08A4F506\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c0 08A40D06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c4 08A42D06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c8 08A44D06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00cc 08A46D06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d0 08A48D06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d4 08A4AD06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d8 08A4CD06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00dc 08A4ED06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e0 08A41D06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e4 08A43D06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e8 08A45D06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00ec 08A47D06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00f0 08A49D06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00f4 08A4BD06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00f8 08A4DD06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00fc 08A4FD06\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0100 08A404C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0104 08A424C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0108 08A444C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 010c 08A464C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0110 08A484C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0114 08A4A4C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0118 08A4C4C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 011c 08A4E4C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0120 08A414C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0124 08A434C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0128 08A454C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 012c 08A474C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0130 08A494C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0134 08A4B4C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0138 08A4D4C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 013c 08A4F4C6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0140 08A40CC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0144 08A42CC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0148 08A44CC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 014c 08A46CC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0150 08A48CC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0154 08A4ACC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0158 08A4CCC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 015c 08A4ECC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0160 08A41CC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0164 08A43CC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0168 08A45CC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 016c 08A47CC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0170 08A49CC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0174 08A4BCC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0178 08A4DCC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 017c 08A4FCC6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==96] then { pass $testname } else { fail $testname }
+}
+
+proc do_ds {} {
+ set testname "ds.s: ds tests"
+ set x 0
+
+ gas_start "ds.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 08A40446\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 08A42446\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 08A44446\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 08A46446\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 08A48446\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 08A4A446\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 08A4C446\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c 08A4E446\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 08A41446\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 08A43446\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 08A45446\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c 08A47446\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 08A49446\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 08A4B446\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 08A4D446\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c 08A4F446\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==16] then { pass $testname } else { fail $testname }
+}
+
+proc do_comclr {} {
+ set testname "comclr.s: comclr tests"
+ set x 0
+
+ gas_start "comclr.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 08A40886\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 08A42886\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 08A44886\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 08A46886\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 08A48886\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 08A4A886\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 08A4C886\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c 08A4E886\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 08A41886\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 08A43886\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 08A45886\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c 08A47886\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 08A49886\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 08A4B886\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 08A4D886\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c 08A4F886\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 90A600F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 90A620F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 90A640F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004c 90A660F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0050 90A680F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0054 90A6A0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0058 90A6C0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 005c 90A6E0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0060 90A610F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0064 90A630F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0068 90A650F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 006c 90A670F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0070 90A690F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0074 90A6B0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0078 90A6D0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 007c 90A6F0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==32] then { pass $testname } else { fail $testname }
+}
+
+proc do_logical {} {
+ set testname "logical.s: logical tests"
+ set x 0
+
+ gas_start "logical.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 08A40246\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 08A42246\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 08A44246\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 08A46246\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 08A4E246\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 08A41246\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 08A43246\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c 08A45246\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 08A47246\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 08A4F246\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 08A40286\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c 08A42286\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 08A44286\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 08A46286\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 08A4E286\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c 08A41286\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 08A43286\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 08A45286\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 08A47286\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004c 08A4F286\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0050 08A40206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0054 08A42206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0058 08A44206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 005c 08A46206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0060 08A4E206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0064 08A41206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0068 08A43206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 006c 08A45206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0070 08A47206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0074 08A4F206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0078 08A40006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 007c 08A42006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0080 08A44006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0084 08A46006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0088 08A4E006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 008c 08A41006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0090 08A43006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0094 08A45006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0098 08A47006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 009c 08A4F006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==40] then { pass $testname } else { fail $testname }
+}
+
+proc do_unit {} {
+ set testname "unit.s: unit tests"
+ set x 0
+
+ gas_start "unit.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 08A40386\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 08A44386\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 08A46386\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 08A48386\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 08A4C386\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 08A4E386\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 08A41386\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c 08A45386\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 08A47386\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 08A49386\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 08A4D386\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c 08A4F386\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 08A40986\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 08A44986\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 08A46986\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c 08A48986\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 08A4C986\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 08A4E986\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 08A41986\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004c 08A45986\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0050 08A47986\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0054 08A49986\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0058 08A4D986\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 005c 08A4F986\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0060 08A409C6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0064 08A449C6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0068 08A469C6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 006c 08A489C6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0070 08A4C9C6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0074 08A4E9C6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0078 08A419C6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 007c 08A459C6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0080 08A479C6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0084 08A499C6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0088 08A4D9C6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 008c 08A4F9C6\[^\n]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==36] then { pass $testname } else { fail $testname }
+}
+
+proc do_dcor {} {
+ set testname "dcor.s: dcor tests"
+ set x 0
+
+ gas_start "dcor.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 08800B85\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 08804B85\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 08806B85\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 08808B85\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 0880CB85\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 0880EB85\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 08801B85\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c 08805B85\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 08807B85\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 08809B85\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 0880DB85\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c 0880FB85\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 08800BC5\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 08804BC5\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 08806BC5\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c 08808BC5\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 0880CBC5\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 0880EBC5\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 08801BC5\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004c 08805BC5\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0050 08807BC5\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0054 08809BC5\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0058 0880DBC5\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 005c 0880FBC5\[^\n]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==24] then { pass $testname } else { fail $testname }
+}
+
+proc do_addi {} {
+ set testname "addi.s: addi tests"
+ set x 0
+
+ gas_start "addi.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 B4A600F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 B4A620F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 B4A640F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c B4A660F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 B4A680F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 B4A6A0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 B4A6C0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c B4A6E0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 B4A610F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 B4A630F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 B4A650F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c B4A670F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 B4A690F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 B4A6B0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 B4A6D0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c B4A6F0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 B4A608F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 B4A628F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 B4A648F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004c B4A668F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0050 B4A688F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0054 B4A6A8F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0058 B4A6C8F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 005c B4A6E8F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0060 B4A618F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0064 B4A638F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0068 B4A658F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 006c B4A678F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0070 B4A698F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0074 B4A6B8F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0078 B4A6D8F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 007c B4A6F8F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0080 B0A600F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0084 B0A620F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0088 B0A640F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 008c B0A660F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0090 B0A680F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0094 B0A6A0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0098 B0A6C0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 009c B0A6E0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a0 B0A610F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a4 B0A630F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a8 B0A650F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00ac B0A670F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b0 B0A690F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b4 B0A6B0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b8 B0A6D0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00bc B0A6F0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c0 B0A608F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c4 B0A628F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c8 B0A648F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00cc B0A668F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d0 B0A688F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d4 B0A6A8F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d8 B0A6C8F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00dc B0A6E8F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e0 B0A618F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e4 B0A638F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e8 B0A658F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00ec B0A678F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00f0 B0A698F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00f4 B0A6B8F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00f8 B0A6D8F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00fc B0A6F8F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==64] then { pass $testname } else { fail $testname }
+}
+
+proc do_subi {} {
+ set testname "subi.s: subi tests"
+ set x 0
+
+ gas_start "subi.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 94A600F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 94A620F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 94A640F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 94A660F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 94A680F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 94A6A0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 94A6C0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c 94A6E0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 94A610F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 94A630F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 94A650F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c 94A670F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 94A690F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 94A6B0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 94A6D0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c 94A6F0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 94A608F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 94A628F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 94A648F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004c 94A668F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0050 94A688F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0054 94A6A8F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0058 94A6C8F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 005c 94A6E8F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0060 94A618F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0064 94A638F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0068 94A658F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 006c 94A678F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0070 94A698F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0074 94A6B8F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0078 94A6D8F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 007c 94A6F8F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==32] then { pass $testname } else { fail $testname }
+}
+
+proc do_shift {} {
+ set testname "shift.s: shift tests"
+ set x 0
+
+ gas_start "shift.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 D0A40006\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 D0A42006\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 D0A44006\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c D0A46006\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 D0A48006\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 D0A4A006\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 D0A4C006\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c D0A4E006\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 D0A40B46\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 D0A42B46\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 D0A44B46\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c D0A46B46\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 D0A48B46\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 D0A4AB46\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 D0A4CB46\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c D0A4EB46\[^\n]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==16] then { pass $testname } else { fail $testname }
+}
+
+proc do_extract {} {
+ set testname "extract.s: extract tests"
+ set x 0
+
+ gas_start "extract.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 D08618B6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 D08638B6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 D08658B6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c D08678B6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 D08698B6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 D086B8B6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 D086D8B6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c D086F8B6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 D0861CB6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 D0863CB6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 D0865CB6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c D0867CB6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 D0869CB6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 D086BCB6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 D086DCB6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c D086FCB6\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 D086101B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 D086301B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 D086501B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004c D086701B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0050 D086901B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0054 D086B01B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0058 D086D01B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 005c D086F01B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0060 D086141B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0064 D086341B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0068 D086541B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 006c D086741B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0070 D086941B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0074 D086B41B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0078 D086D41B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 007c D086F41B\[^\n]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==32] then { pass $testname } else { fail $testname }
+}
+
+proc do_deposit {} {
+ set testname "deposit.s: deposit tests"
+ set x 0
+
+ gas_start "deposit.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 D4C40B56\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 D4C42B56\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 D4C44B56\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c D4C46B56\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 D4C48B56\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 D4C4AB56\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 D4C4CB56\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c D4C4EB56\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 D4C40F56\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 D4C42F56\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 D4C44F56\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c D4C46F56\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 D4C48F56\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 D4C4AF56\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 D4C4CF56\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c D4C4EF56\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 D4C4001B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 D4C4201B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 D4C4401B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004c D4C4601B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0050 D4C4801B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0054 D4C4A01B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0058 D4C4C01B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 005c D4C4E01B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0060 D4C4041B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0064 D4C4241B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0068 D4C4441B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 006c D4C4641B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0070 D4C4841B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0074 D4C4A41B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0078 D4C4C41B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 007c D4C4E41B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0080 D4DF141B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0084 D4DF341B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0088 D4DF541B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 008c D4DF741B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0090 D4DF941B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0094 D4DFB41B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0098 D4DFD41B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 009c D4DFF41B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a0 D4DF101B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a4 D4DF301B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a8 D4DF501B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00ac D4DF701B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b0 D4DF901B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b4 D4DFB01B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b8 D4DFD01B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00bc D4DFF01B\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c0 D4DF1F76\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c4 D4DF3F76\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c8 D4DF5F76\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00cc D4DF7F76\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d0 D4DF9F76\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d4 D4DFBF76\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d8 D4DFDF76\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00dc D4DFFF76\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e0 D4DF1B76\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e4 D4DF3B76\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e8 D4DF5B76\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00ec D4DF7B76\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00f0 D4DF9B76\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00f4 D4DFBB76\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00f8 D4DFDB76\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00fc D4DFFB76\[^\n]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==64] then { pass $testname } else { fail $testname }
+}
+
+proc do_system {} {
+ set testname "system.s: system tests"
+ set x 0
+
+ gas_start "system.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 00018005\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 00000C00\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 00000CA0\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 00050D64\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 00050E64\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 00041860\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 00A010A4\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c 00041820\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 01441840\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 000004A4\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 014008A4\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c 00000400\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 00100400\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 140004D2\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 04A61187\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c 04A13187\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 04A611C7\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 04A131C7\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 04A41346\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004c 04A41366\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0050 04A41306\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0054 04A41326\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0058 04A41306\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 005c 04A41040\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0060 04A42040\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0064 04A41000\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0068 04A42000\[^\n]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==27] then { pass $testname } else { fail $testname }
+}
+
+proc do_purge {} {
+ set testname "purge.s: purge tests"
+ set x 0
+
+ gas_start "purge.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 04A41200\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 04A41220\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 04A42200\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 04A42220\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 04A41240\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 04A41260\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 04A42240\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c 04A42260\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 04A41380\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 04A413A0\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 04A41280\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c 04A412A0\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 04A42280\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 04A422A0\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 04A412C0\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c 04A412E0\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 04A422C0\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 04A422E0\[^\n]*\n" { set x [expr $x+1] }
+
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==18] then { pass $testname } else { fail $testname }
+}
+
+proc do_fp_misc {} {
+ set testname "fp_misc.s: fp_misc tests"
+ set x 0
+
+ gas_start "fp_misc.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 30002420\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==1] then { pass $testname } else { fail $testname }
+}
+
+proc do_fmem {} {
+ set testname "fmem.s: fmem tests"
+ set x 0
+
+ gas_start "fmem.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 24A40006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 24A42006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 24A40026\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 24A42026\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 2CA40006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 2CA42006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 2CA40026\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c 2CA42026\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 24A40206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 24A42206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 24A40226\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c 24A42226\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 2CA40206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 2CA42206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 2CA40226\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c 2CA42226\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 3CA40206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 3CA42206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 3CA40226\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004c 3CA42226\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0050 24A01006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0054 24A03026\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0058 24A01026\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 005c 2CA01006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0060 2CA03026\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0064 2CA01026\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0068 24A01206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 006c 24A03226\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0070 24A01226\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0074 2CA01206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0078 2CA03226\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 007c 2CA01226\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0080 3CA01206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0084 3CA03226\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0088 3CA01226\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==35] then { pass $testname } else { fail $testname }
+}
+
+proc do_fp_comp {} {
+ set testname "fp_comp.s: fp_comp tests"
+ set x 0
+
+ gas_start "fp_comp.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 30A0400A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 30A0480A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 30A0580A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 32804018\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 32804818\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 30A0600A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 30A0680A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c 30A0780A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 32806018\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 32806818\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 30A0800A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c 30A0880A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 30A0980A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 32808018\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 32808818\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c 30A0A00A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 30A0A80A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 30A0B80A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 3280A018\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004c 3280A818\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0050 3088060C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0054 30880E0C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0058 30881E0C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 005c 3298061C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0060 32980E1C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0064 32981E1C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0068 3088260C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 006c 30882E0C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0070 30883E0C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0074 3298261C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0078 32982E1C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 007c 32983E1C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0080 3088460C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0084 30884E0C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0088 30885E0C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 008c 3298461C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0090 32984E1C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0094 32985E1C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0098 3088660C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 009c 30886E0C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a0 30887E0C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a4 3298661C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a8 32986E1C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00ac 32987E1C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b0 3088860C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b4 30888E0C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b8 30889E0C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00bc 3298861C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c0 32988E1C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c4 32989E1C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c8 180120E2\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00cc 1A11A4D2\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d0 980120E2\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d4 9A11A4D2\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d8 38854706\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==55] then { pass $testname } else { fail $testname }
+}
+
+proc do_fp_conv {} {
+ set testname "fp_conv.s: fp_conv tests"
+ set x 0
+
+ gas_start "fp_conv.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 30A0020A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 30A0220A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 30A0620A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 30A00A0A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 30A02A0A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 30A06A0A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 30A01A0A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c 30A03A0A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 30A07A0A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 32800218\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 32802218\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c 32806218\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 32800A18\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 32802A18\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 32806A18\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c 32801A18\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 32803A18\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 32807A18\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 30A0820A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004c 30A0A20A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0050 30A0E20A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0054 30A08A0A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0058 30A0AA0A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 005c 30A0EA0A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0060 30A09A0A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0064 30A0BA0A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0068 30A0FA0A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 006c 32808218\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0070 3280A218\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0074 3280E218\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0078 32808A18\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 007c 3280AA18\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0080 3280EA18\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0084 32809A18\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0088 3280BA18\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 008c 3280FA18\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0090 30A1020A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0094 30A1220A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0098 30A1620A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 009c 30A10A0A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a0 30A12A0A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a4 30A16A0A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a8 30A11A0A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00ac 30A13A0A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b0 30A17A0A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b4 32810218\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b8 32812218\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00bc 32816218\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c0 32810A18\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c4 32812A18\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c8 32816A18\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00cc 32811A18\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d0 32813A18\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d4 32817A18\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d8 30A1820A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00dc 30A1A20A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e0 30A1E20A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e4 30A18A0A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e8 30A1AA0A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00ec 30A1EA0A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00f0 30A19A0A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00f4 30A1BA0A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00f8 30A1FA0A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00fc 32818218\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0100 3281A218\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0104 3281E218\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0108 32818A18\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 010c 3281AA18\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0110 3281EA18\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0114 32819A18\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0118 3281BA18\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 011c 3281FA18\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==72] then { pass $testname } else { fail $testname }
+}
+
+proc do_fp_fcmp {} {
+ set testname "fp_fcmp.s: fp_fcmp tests"
+ set x 0
+
+ gas_start "fp_fcmp.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 30850400\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 30850401\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 30850402\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 30850403\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 30850404\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 30850405\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 30850406\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c 30850407\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 30850408\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 30850409\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 3085040A\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c 3085040B\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 3085040C\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 3085040D\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 3085040E\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c 3085040F\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 30850410\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 30850411\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 30850412\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004c 30850413\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0050 30850414\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0054 30850415\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0058 30850416\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 005c 30850417\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0060 30850418\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0064 30850419\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0068 3085041A\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 006c 3085041B\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0070 3085041C\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0074 3085041D\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0078 3085041E\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 007c 3085041F\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0080 30850C00\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0084 30850C01\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0088 30850C02\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 008c 30850C03\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0090 30850C04\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0094 30850C05\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0098 30850C06\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 009c 30850C07\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a0 30850C08\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a4 30850C09\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a8 30850C0A\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00ac 30850C0B\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b0 30850C0C\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b4 30850C0D\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b8 30850C0E\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00bc 30850C0F\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c0 30850C10\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c4 30850C11\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c8 30850C12\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00cc 30850C13\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d0 30850C14\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d4 30850C15\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d8 30850C16\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00dc 30850C17\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e0 30850C18\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e4 30850C19\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e8 30850C1A\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00ec 30850C1B\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00f0 30850C1C\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00f4 30850C1D\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00f8 30850C1E\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00fc 30850C1F\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0100 30851C00\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0104 30851C01\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0108 30851C02\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 010c 30851C03\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0110 30851C04\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0114 30851C05\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0118 30851C06\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 011c 30851C07\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0120 30851C08\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0124 30851C09\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0128 30851C0A\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 012c 30851C0B\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0130 30851C0C\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0134 30851C0D\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0138 30851C0E\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 013c 30851C0F\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0140 30851C10\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0144 30851C11\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0148 30851C12\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 014c 30851C13\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0150 30851C14\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0154 30851C15\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0158 30851C16\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 015c 30851C17\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0160 30851C18\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0164 30851C19\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0168 30851C1A\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 016c 30851C1B\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0170 30851C1C\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0174 30851C1D\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0178 30851C1E\[^\n\]*\n" {set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 017c 30851C1F\[^\n\]*\n" {set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==96] then { pass $testname } else { fail $testname }
+}
+
+proc do_special {} {
+ set testname "special.s: special tests"
+ set x 0
+
+ gas_start "special.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 04A41680\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 04A416A0\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 04A41A80\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 04A41AA0\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==4] then { pass $testname } else { fail $testname }
+}
+
+proc do_spop {} {
+ set testname "spop.s: spop tests"
+ set x 0
+
+ # This tickles a bug in the expression parser.
+ gas_start "spop.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 10000105\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 10001913\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 10000125\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 10001933\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 10002B05\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 10039B05\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 10002B25\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c 10039B25\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 10A00505\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 10A01D13\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 10A00525\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c 10A01D33\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 10C50705\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 10C51F13\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 10C50725\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c 10C51F33\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==16] then { pass $testname } else { fail $testname }
+}
+
+proc do_copr {} {
+ set testname "copr.s: copr tests"
+ set x 0
+
+ gas_start "copr.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 30000105\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 30000713\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 30000125\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 30000733\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==4] then { pass $testname } else { fail $testname }
+}
+
+proc do_coprmem {} {
+ set testname "coprmem.s: copr memory tests"
+ set x 0
+
+ gas_start "coprmem.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 2485011A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 2485211A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 2485013A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 2485213A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 2C85011A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 2C85211A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 2C85013A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c 2C85213A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 2485031A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 2485231A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 2485033A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c 2485233A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 2C85031A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 2C85231A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 2C85033A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c 2C85233A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 2480111A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 2480313A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 2480113A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004c 2C80111A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0050 2C80313A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0054 2C80113A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0058 2480131A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 005c 2480333A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0060 2480133A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0064 2C80131A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0068 2C80333A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 006c 2C80133A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==28] then { pass $testname } else { fail $testname }
+}
+
+proc do_fmem_LR_tests {} {
+ set testname "fmemLRbug.s: LR register selection on fp mem instructions"
+ set x 0
+
+ gas_start "fmemLRbug.s" "-al"
+
+ # Make sure we correctly handle field selectors.
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 27401246\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 27481206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 27501206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 2F401206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 2F481206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 2F501206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 27401046\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c 27481006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 27501006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 2F401006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 2F481006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c 2F501006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 27401246\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 27481206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 27501206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c 2F401206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 2F481206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 2F501206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 27401046\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004c 27481006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0050 27501006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0054 2F401006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0058 2F481006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 005c 2F501006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0060 27590246\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0064 27590206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0068 27590206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 006c 2F590206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0070 2F590206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0074 2F590206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0078 27590046\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 007c 27590006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0080 27590006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0084 2F590006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0088 2F590006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 008c 2F590006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0090 27590246\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0094 27590206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0098 27590206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 009c 2F590206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a0 2F590206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a4 2F590206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a8 27590046\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00ac 27590006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b0 27590006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b4 2F590006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b8 2F590006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00bc 2F590006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c0 E840C000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c4 08000240\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==50] then { pass $testname } else { fail $testname }
+}
+
+if [istarget hppa*-*-*] then {
+ # Test the basic instruction parser.
+ do_imem
+ do_immed
+ do_branch
+ do_add
+ do_sh1add
+ do_sh2add
+ do_sh3add
+ do_sub
+ do_ds
+ do_comclr
+ do_logical
+ do_unit
+ do_dcor
+ do_addi
+ do_subi
+ do_shift
+ do_extract
+ do_deposit
+ do_system
+ do_purge
+ do_fp_misc
+ do_fmem
+ do_fp_comp
+ do_fp_conv
+ do_fp_fcmp
+ do_special
+ do_spop
+ do_copr
+ do_coprmem
+
+ # The "weird.s" file from the gdb testsuite. Simply verify it
+ # assembles.
+ gas_test "weird.s" "" "" "stabs parsing"
+
+ # Test that we correctly assemble some FP memory tests which
+ # L/R register selects. (Regression test for a bug Tege found).
+ do_fmem_LR_tests
+}
diff --git a/gas/testsuite/gas/hppa/basic/branch.s b/gas/testsuite/gas/hppa/basic/branch.s
new file mode 100644
index 0000000000..a1f839dd68
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/branch.s
@@ -0,0 +1,227 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; More branching instructions than you ever knew what to do with.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+branch_tests:
+ bl branch_tests,%r2
+ bl,n branch_tests,%r2
+ b branch_tests
+ b,n branch_tests
+ gate branch_tests,%r2
+ gate,n branch_tests,%r2
+ blr %r4,%r2
+ blr,n %r4,%r2
+ blr %r4,%r0
+ blr,n %r4,%r0
+ bv %r0(%r2)
+ bv,n %r0(%r2)
+ be 0x1234(%sr1,%r2)
+ be,n 0x1234(%sr1,%r2)
+ ble 0x1234(%sr1,%r2)
+ ble,n 0x1234(%sr1,%r2)
+
+movb_tests:
+ movb %r4,%r26,movb_tests
+ movb,= %r4,%r26,movb_tests
+ movb,< %r4,%r26,movb_tests
+ movb,od %r4,%r26,movb_tests
+ movb,tr %r4,%r26,movb_tests
+ movb,<> %r4,%r26,movb_tests
+ movb,>= %r4,%r26,movb_tests
+ movb,ev %r4,%r26,movb_tests
+movb_nullified_tests:
+ movb,n %r4,%r26,movb_tests
+ movb,=,n %r4,%r26,movb_tests
+ movb,<,n %r4,%r26,movb_tests
+ movb,od,n %r4,%r26,movb_tests
+ movb,tr,n %r4,%r26,movb_tests
+ movb,<>,n %r4,%r26,movb_tests
+ movb,>=,n %r4,%r26,movb_tests
+ movb,ev,n %r4,%r26,movb_tests
+
+movib_tests:
+ movib 5,%r26,movib_tests
+ movib,= 5,%r26,movib_tests
+ movib,< 5,%r26,movib_tests
+ movib,od 5,%r26,movib_tests
+ movib,tr 5,%r26,movib_tests
+ movib,<> 5,%r26,movib_tests
+ movib,>= 5,%r26,movib_tests
+ movib,ev 5,%r26,movib_tests
+movib_nullified_tests:
+ movib,n 5,%r26,movib_tests
+ movib,=,n 5,%r26,movib_tests
+ movib,<,n 5,%r26,movib_tests
+ movib,od,n 5,%r26,movib_tests
+ movib,tr,n 5,%r26,movib_tests
+ movib,<>,n 5,%r26,movib_tests
+ movib,>=,n 5,%r26,movib_tests
+ movib,ev,n 5,%r26,movib_tests
+
+comb_tests:
+ comb %r0,%r4,comb_tests
+ comb,= %r0,%r4,comb_tests
+ comb,< %r0,%r4,comb_tests
+ comb,<= %r0,%r4,comb_tests
+ comb,<< %r0,%r4,comb_tests
+ comb,<<= %r0,%r4,comb_tests
+ comb,sv %r0,%r4,comb_tests
+ comb,od %r0,%r4,comb_tests
+ comb,tr %r0,%r4,comb_tests
+ comb,<> %r0,%r4,comb_tests
+ comb,>= %r0,%r4,comb_tests
+ comb,> %r0,%r4,comb_tests
+ comb,>>= %r0,%r4,comb_tests
+ comb,>> %r0,%r4,comb_tests
+ comb,nsv %r0,%r4,comb_tests
+ comb,ev %r0,%r4,comb_tests
+comb_nullified_tests:
+ comb,n %r0,%r4,comb_tests
+ comb,=,n %r0,%r4,comb_tests
+ comb,<,n %r0,%r4,comb_tests
+ comb,<=,n %r0,%r4,comb_tests
+ comb,<<,n %r0,%r4,comb_tests
+ comb,<<=,n %r0,%r4,comb_tests
+ comb,sv,n %r0,%r4,comb_tests
+ comb,od,n %r0,%r4,comb_tests
+ comb,tr,n %r0,%r4,comb_tests
+ comb,<>,n %r0,%r4,comb_tests
+ comb,>=,n %r0,%r4,comb_tests
+ comb,>,n %r0,%r4,comb_tests
+ comb,>>=,n %r0,%r4,comb_tests
+ comb,>>,n %r0,%r4,comb_tests
+ comb,nsv,n %r0,%r4,comb_tests
+ comb,ev,n %r0,%r4,comb_tests
+
+comib_tests:
+ comib 0,%r4,comib_tests
+ comib,< 0,%r4,comib_tests
+ comib,<= 0,%r4,comib_tests
+ comib,<< 0,%r4,comib_tests
+ comib,<<= 0,%r4,comib_tests
+ comib,sv 0,%r4,comib_tests
+ comib,od 0,%r4,comib_tests
+ comib,tr 0,%r4,comib_tests
+ comib,<> 0,%r4,comib_tests
+ comib,>= 0,%r4,comib_tests
+ comib,> 0,%r4,comib_tests
+ comib,>>= 0,%r4,comib_tests
+ comib,>> 0,%r4,comib_tests
+ comib,nsv 0,%r4,comib_tests
+ comib,ev 0,%r4,comb_tests
+
+comib_nullified_tests:
+ comib,n 0,%r4,comib_tests
+ comib,=,n 0,%r4,comib_tests
+ comib,<,n 0,%r4,comib_tests
+ comib,<=,n 0,%r4,comib_tests
+ comib,<<,n 0,%r4,comib_tests
+ comib,<<=,n 0,%r4,comib_tests
+ comib,sv,n 0,%r4,comib_tests
+ comib,od,n 0,%r4,comib_tests
+ comib,tr,n 0,%r4,comib_tests
+ comib,<>,n 0,%r4,comib_tests
+ comib,>=,n 0,%r4,comib_tests
+ comib,>,n 0,%r4,comib_tests
+ comib,>>=,n 0,%r4,comib_tests
+ comib,>>,n 0,%r4,comib_tests
+ comib,nsv,n 0,%r4,comib_tests
+ comib,ev,n 0,%r4,comib_tests
+
+
+
+addb_tests:
+ addb %r1,%r4,addb_tests
+ addb,= %r1,%r4,addb_tests
+ addb,< %r1,%r4,addb_tests
+ addb,<= %r1,%r4,addb_tests
+ addb,nuv %r1,%r4,addb_tests
+ addb,znv %r1,%r4,addb_tests
+ addb,sv %r1,%r4,addb_tests
+ addb,od %r1,%r4,addb_tests
+ addb,tr %r1,%r4,addb_tests
+ addb,<> %r1,%r4,addb_tests
+ addb,>= %r1,%r4,addb_tests
+ addb,> %r1,%r4,addb_tests
+ addb,uv %r1,%r4,addb_tests
+ addb,vnz %r1,%r4,addb_tests
+ addb,nsv %r1,%r4,addb_tests
+ addb,ev %r1,%r4,addb_tests
+addb_nullified_tests:
+ addb,n %r1,%r4,addb_tests
+ addb,=,n %r1,%r4,addb_tests
+ addb,<,n %r1,%r4,addb_tests
+ addb,<=,n %r1,%r4,addb_tests
+ addb,nuv,n %r1,%r4,addb_tests
+ addb,znv,n %r1,%r4,addb_tests
+ addb,sv,n %r1,%r4,addb_tests
+ addb,od,n %r1,%r4,addb_tests
+ addb,tr,n %r1,%r4,addb_tests
+ addb,<>,n %r1,%r4,addb_tests
+ addb,>=,n %r1,%r4,addb_tests
+ addb,>,n %r1,%r4,addb_tests
+ addb,uv,n %r1,%r4,addb_tests
+ addb,vnz,n %r1,%r4,addb_tests
+ addb,nsv,n %r1,%r4,addb_tests
+ addb,ev,n %r1,%r4,addb_tests
+
+addib_tests:
+ addib -1,%r4,addib_tests
+ addib,= -1,%r4,addib_tests
+ addib,< -1,%r4,addib_tests
+ addib,<= -1,%r4,addib_tests
+ addib,nuv -1,%r4,addib_tests
+ addib,znv -1,%r4,addib_tests
+ addib,sv -1,%r4,addib_tests
+ addib,od -1,%r4,addib_tests
+ addib,tr -1,%r4,addib_tests
+ addib,<> -1,%r4,addib_tests
+ addib,>= -1,%r4,addib_tests
+ addib,> -1,%r4,addib_tests
+ addib,uv -1,%r4,addib_tests
+ addib,vnz -1,%r4,addib_tests
+ addib,nsv -1,%r4,addib_tests
+ addib,ev -1,%r4,comb_tests
+
+addib_nullified_tests:
+ addib,n -1,%r4,addib_tests
+ addib,=,n -1,%r4,addib_tests
+ addib,<,n -1,%r4,addib_tests
+ addib,<=,n -1,%r4,addib_tests
+ addib,nuv,n -1,%r4,addib_tests
+ addib,znv,n -1,%r4,addib_tests
+ addib,sv,n -1,%r4,addib_tests
+ addib,od,n -1,%r4,addib_tests
+ addib,tr,n -1,%r4,addib_tests
+ addib,<>,n -1,%r4,addib_tests
+ addib,>=,n -1,%r4,addib_tests
+ addib,>,n -1,%r4,addib_tests
+ addib,uv,n -1,%r4,addib_tests
+ addib,vnz,n -1,%r4,addib_tests
+ addib,nsv,n -1,%r4,addib_tests
+ addib,ev,n -1,%r4,addib_tests
+
+
+; Needs to check lots of stuff (like corner bit cases)
+bb_tests:
+ bvb,< %r4,bb_tests
+ bvb,>= %r4,bb_tests
+ bvb,<,n %r4,bb_tests
+ bvb,>=,n %r4,bb_tests
+ bb,< %r4,5,bb_tests
+ bb,>= %r4,5,bb_tests
+ bb,<,n %r4,5,bb_tests
+ bb,>=,n %r4,5,bb_tests
+
diff --git a/gas/testsuite/gas/hppa/basic/comclr.s b/gas/testsuite/gas/hppa/basic/comclr.s
new file mode 100644
index 0000000000..a8e5aa6bef
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/comclr.s
@@ -0,0 +1,50 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic immediate instruction tests.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+ comclr %r4,%r5,%r6
+ comclr,= %r4,%r5,%r6
+ comclr,< %r4,%r5,%r6
+ comclr,<= %r4,%r5,%r6
+ comclr,<< %r4,%r5,%r6
+ comclr,<<= %r4,%r5,%r6
+ comclr,sv %r4,%r5,%r6
+ comclr,od %r4,%r5,%r6
+ comclr,tr %r4,%r5,%r6
+ comclr,<> %r4,%r5,%r6
+ comclr,>= %r4,%r5,%r6
+ comclr,> %r4,%r5,%r6
+ comclr,>>= %r4,%r5,%r6
+ comclr,>> %r4,%r5,%r6
+ comclr,nsv %r4,%r5,%r6
+ comclr,ev %r4,%r5,%r6
+
+ comiclr 123,%r5,%r6
+ comiclr,= 123,%r5,%r6
+ comiclr,< 123,%r5,%r6
+ comiclr,<= 123,%r5,%r6
+ comiclr,<< 123,%r5,%r6
+ comiclr,<<= 123,%r5,%r6
+ comiclr,sv 123,%r5,%r6
+ comiclr,od 123,%r5,%r6
+ comiclr,tr 123,%r5,%r6
+ comiclr,<> 123,%r5,%r6
+ comiclr,>= 123,%r5,%r6
+ comiclr,> 123,%r5,%r6
+ comiclr,>>= 123,%r5,%r6
+ comiclr,>> 123,%r5,%r6
+ comiclr,nsv 123,%r5,%r6
+ comiclr,ev 123,%r5,%r6
+
diff --git a/gas/testsuite/gas/hppa/basic/copr.s b/gas/testsuite/gas/hppa/basic/copr.s
new file mode 100644
index 0000000000..77cb6a271f
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/copr.s
@@ -0,0 +1,19 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+copr_tests:
+ copr,4,5
+ copr,4,115
+ copr,4,5,n
+ copr,4,115,n
diff --git a/gas/testsuite/gas/hppa/basic/coprmem.s b/gas/testsuite/gas/hppa/basic/coprmem.s
new file mode 100644
index 0000000000..7eff1516bd
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/coprmem.s
@@ -0,0 +1,55 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic copr memory tests which also test the various
+; addressing modes and completers.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+;
+copr_indexing_load
+
+ cldwx,4 %r5(%sr0,%r4),%r26
+ cldwx,4,s %r5(%sr0,%r4),%r26
+ cldwx,4,m %r5(%sr0,%r4),%r26
+ cldwx,4,sm %r5(%sr0,%r4),%r26
+ clddx,4 %r5(%sr0,%r4),%r26
+ clddx,4,s %r5(%sr0,%r4),%r26
+ clddx,4,m %r5(%sr0,%r4),%r26
+ clddx,4,sm %r5(%sr0,%r4),%r26
+
+copr_indexing_store
+ cstwx,4 %r26,%r5(%sr0,%r4)
+ cstwx,4,s %r26,%r5(%sr0,%r4)
+ cstwx,4,m %r26,%r5(%sr0,%r4)
+ cstwx,4,sm %r26,%r5(%sr0,%r4)
+ cstdx,4 %r26,%r5(%sr0,%r4)
+ cstdx,4,s %r26,%r5(%sr0,%r4)
+ cstdx,4,m %r26,%r5(%sr0,%r4)
+ cstdx,4,sm %r26,%r5(%sr0,%r4)
+
+copr_short_memory
+ cldws,4 0(%sr0,%r4),%r26
+ cldws,4,mb 0(%sr0,%r4),%r26
+ cldws,4,ma 0(%sr0,%r4),%r26
+ cldds,4 0(%sr0,%r4),%r26
+ cldds,4,mb 0(%sr0,%r4),%r26
+ cldds,4,ma 0(%sr0,%r4),%r26
+ cstws,4 %r26,0(%sr0,%r4)
+ cstws,4,mb %r26,0(%sr0,%r4)
+ cstws,4,ma %r26,0(%sr0,%r4)
+ cstds,4 %r26,0(%sr0,%r4)
+ cstds,4,mb %r26,0(%sr0,%r4)
+ cstds,4,ma %r26,0(%sr0,%r4)
+
+; gas fucks this up thinks it gets the expression 4 modulo 5
+; cldwx,4 %r5(0,%r4),%r%r26
diff --git a/gas/testsuite/gas/hppa/basic/dcor.s b/gas/testsuite/gas/hppa/basic/dcor.s
new file mode 100644
index 0000000000..8474554813
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/dcor.s
@@ -0,0 +1,41 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic immediate instruction tests.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+ dcor %r4,%r5
+ dcor,sbz %r4,%r5
+ dcor,shz %r4,%r5
+ dcor,sdc %r4,%r5
+ dcor,sbc %r4,%r5
+ dcor,shc %r4,%r5
+ dcor,tr %r4,%r5
+ dcor,nbz %r4,%r5
+ dcor,nhz %r4,%r5
+ dcor,ndc %r4,%r5
+ dcor,nbc %r4,%r5
+ dcor,nhc %r4,%r5
+
+ idcor %r4,%r5
+ idcor,sbz %r4,%r5
+ idcor,shz %r4,%r5
+ idcor,sdc %r4,%r5
+ idcor,sbc %r4,%r5
+ idcor,shc %r4,%r5
+ idcor,tr %r4,%r5
+ idcor,nbz %r4,%r5
+ idcor,nhz %r4,%r5
+ idcor,ndc %r4,%r5
+ idcor,nbc %r4,%r5
+ idcor,nhc %r4,%r5
diff --git a/gas/testsuite/gas/hppa/basic/deposit.s b/gas/testsuite/gas/hppa/basic/deposit.s
new file mode 100644
index 0000000000..70853b3699
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/deposit.s
@@ -0,0 +1,88 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic immediate instruction tests.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+ zdep %r4,5,10,%r6
+ zdep,= %r4,5,10,%r6
+ zdep,< %r4,5,10,%r6
+ zdep,od %r4,5,10,%r6
+ zdep,tr %r4,5,10,%r6
+ zdep,<> %r4,5,10,%r6
+ zdep,>= %r4,5,10,%r6
+ zdep,ev %r4,5,10,%r6
+
+ dep %r4,5,10,%r6
+ dep,= %r4,5,10,%r6
+ dep,< %r4,5,10,%r6
+ dep,od %r4,5,10,%r6
+ dep,tr %r4,5,10,%r6
+ dep,<> %r4,5,10,%r6
+ dep,>= %r4,5,10,%r6
+ dep,ev %r4,5,10,%r6
+
+ zvdep %r4,5,%r6
+ zvdep,= %r4,5,%r6
+ zvdep,< %r4,5,%r6
+ zvdep,od %r4,5,%r6
+ zvdep,tr %r4,5,%r6
+ zvdep,<> %r4,5,%r6
+ zvdep,>= %r4,5,%r6
+ zvdep,ev %r4,5,%r6
+
+ vdep %r4,5,%r6
+ vdep,= %r4,5,%r6
+ vdep,< %r4,5,%r6
+ vdep,od %r4,5,%r6
+ vdep,tr %r4,5,%r6
+ vdep,<> %r4,5,%r6
+ vdep,>= %r4,5,%r6
+ vdep,ev %r4,5,%r6
+
+ vdepi -1,5,%r6
+ vdepi,= -1,5,%r6
+ vdepi,< -1,5,%r6
+ vdepi,od -1,5,%r6
+ vdepi,tr -1,5,%r6
+ vdepi,<> -1,5,%r6
+ vdepi,>= -1,5,%r6
+ vdepi,ev -1,5,%r6
+
+ zvdepi -1,5,%r6
+ zvdepi,= -1,5,%r6
+ zvdepi,< -1,5,%r6
+ zvdepi,od -1,5,%r6
+ zvdepi,tr -1,5,%r6
+ zvdepi,<> -1,5,%r6
+ zvdepi,>= -1,5,%r6
+ zvdepi,ev -1,5,%r6
+
+ depi -1,4,10,%r6
+ depi,= -1,4,10,%r6
+ depi,< -1,4,10,%r6
+ depi,od -1,4,10,%r6
+ depi,tr -1,4,10,%r6
+ depi,<> -1,4,10,%r6
+ depi,>= -1,4,10,%r6
+ depi,ev -1,4,10,%r6
+
+ zdepi -1,4,10,%r6
+ zdepi,= -1,4,10,%r6
+ zdepi,< -1,4,10,%r6
+ zdepi,od -1,4,10,%r6
+ zdepi,tr -1,4,10,%r6
+ zdepi,<> -1,4,10,%r6
+ zdepi,>= -1,4,10,%r6
+ zdepi,ev -1,4,10,%r6
+
diff --git a/gas/testsuite/gas/hppa/basic/ds.s b/gas/testsuite/gas/hppa/basic/ds.s
new file mode 100644
index 0000000000..5831e2618e
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/ds.s
@@ -0,0 +1,32 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic immediate instruction tests.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+ ds %r4,%r5,%r6
+ ds,= %r4,%r5,%r6
+ ds,< %r4,%r5,%r6
+ ds,<= %r4,%r5,%r6
+ ds,<< %r4,%r5,%r6
+ ds,<<= %r4,%r5,%r6
+ ds,sv %r4,%r5,%r6
+ ds,od %r4,%r5,%r6
+ ds,tr %r4,%r5,%r6
+ ds,<> %r4,%r5,%r6
+ ds,>= %r4,%r5,%r6
+ ds,> %r4,%r5,%r6
+ ds,>>= %r4,%r5,%r6
+ ds,>> %r4,%r5,%r6
+ ds,nsv %r4,%r5,%r6
+ ds,ev %r4,%r5,%r6
diff --git a/gas/testsuite/gas/hppa/basic/extract.s b/gas/testsuite/gas/hppa/basic/extract.s
new file mode 100644
index 0000000000..29030f4d48
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/extract.s
@@ -0,0 +1,51 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic immediate instruction tests.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+ extru %r4,5,10,%r6
+ extru,= %r4,5,10,%r6
+ extru,< %r4,5,10,%r6
+ extru,od %r4,5,10,%r6
+ extru,tr %r4,5,10,%r6
+ extru,<> %r4,5,10,%r6
+ extru,>= %r4,5,10,%r6
+ extru,ev %r4,5,10,%r6
+
+ extrs %r4,5,10,%r6
+ extrs,= %r4,5,10,%r6
+ extrs,< %r4,5,10,%r6
+ extrs,od %r4,5,10,%r6
+ extrs,tr %r4,5,10,%r6
+ extrs,<> %r4,5,10,%r6
+ extrs,>= %r4,5,10,%r6
+ extrs,ev %r4,5,10,%r6
+
+ vextru %r4,5,%r6
+ vextru,= %r4,5,%r6
+ vextru,< %r4,5,%r6
+ vextru,od %r4,5,%r6
+ vextru,tr %r4,5,%r6
+ vextru,<> %r4,5,%r6
+ vextru,>= %r4,5,%r6
+ vextru,ev %r4,5,%r6
+
+ vextrs %r4,5,%r6
+ vextrs,= %r4,5,%r6
+ vextrs,< %r4,5,%r6
+ vextrs,od %r4,5,%r6
+ vextrs,tr %r4,5,%r6
+ vextrs,<> %r4,5,%r6
+ vextrs,>= %r4,5,%r6
+ vextrs,ev %r4,5,%r6
diff --git a/gas/testsuite/gas/hppa/basic/fmem.s b/gas/testsuite/gas/hppa/basic/fmem.s
new file mode 100644
index 0000000000..b730b40011
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/fmem.s
@@ -0,0 +1,52 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic immediate instruction tests.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+ fldwx %r4(%sr0,%r5),%fr6
+ fldwx,s %r4(%sr0,%r5),%fr6
+ fldwx,m %r4(%sr0,%r5),%fr6
+ fldwx,sm %r4(%sr0,%r5),%fr6
+ flddx %r4(%sr0,%r5),%fr6
+ flddx,s %r4(%sr0,%r5),%fr6
+ flddx,m %r4(%sr0,%r5),%fr6
+ flddx,sm %r4(%sr0,%r5),%fr6
+ fstwx %fr6,%r4(%sr0,%r5)
+ fstwx,s %fr6,%r4(%sr0,%r5)
+ fstwx,m %fr6,%r4(%sr0,%r5)
+ fstwx,sm %fr6,%r4(%sr0,%r5)
+ fstdx %fr6,%r4(%sr0,%r5)
+ fstdx,s %fr6,%r4(%sr0,%r5)
+ fstdx,m %fr6,%r4(%sr0,%r5)
+ fstdx,sm %fr6,%r4(%sr0,%r5)
+ fstqx %fr6,%r4(%sr0,%r5)
+ fstqx,s %fr6,%r4(%sr0,%r5)
+ fstqx,m %fr6,%r4(%sr0,%r5)
+ fstqx,sm %fr6,%r4(%sr0,%r5)
+
+ fldws 0(%sr0,%r5),%fr6
+ fldws,mb 0(%sr0,%r5),%fr6
+ fldws,ma 0(%sr0,%r5),%fr6
+ fldds 0(%sr0,%r5),%fr6
+ fldds,mb 0(%sr0,%r5),%fr6
+ fldds,ma 0(%sr0,%r5),%fr6
+ fstws %fr6,0(%sr0,%r5)
+ fstws,mb %fr6,0(%sr0,%r5)
+ fstws,ma %fr6,0(%sr0,%r5)
+ fstds %fr6,0(%sr0,%r5)
+ fstds,mb %fr6,0(%sr0,%r5)
+ fstds,ma %fr6,0(%sr0,%r5)
+ fstqs %fr6,0(%sr0,%r5)
+ fstqs,mb %fr6,0(%sr0,%r5)
+ fstqs,ma %fr6,0(%sr0,%r5)
diff --git a/gas/testsuite/gas/hppa/basic/fmemLRbug.s b/gas/testsuite/gas/hppa/basic/fmemLRbug.s
new file mode 100644
index 0000000000..f1330bb628
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/fmemLRbug.s
@@ -0,0 +1,76 @@
+ .code
+ .export f
+f
+ .proc
+ .callinfo frame=0,no_calls
+ .entry
+
+ fstws %fr6R,0(%r26)
+ fstws %fr6L,4(%r26)
+ fstws %fr6,8(%r26)
+
+ fstds %fr6R,0(%r26)
+ fstds %fr6L,4(%r26)
+ fstds %fr6,8(%r26)
+
+ fldws 0(%r26),%fr6R
+ fldws 4(%r26),%fr6L
+ fldws 8(%r26),%fr6
+
+ fldds 0(%r26),%fr6R
+ fldds 4(%r26),%fr6L
+ fldds 8(%r26),%fr6
+
+ fstws %fr6R,0(%sr0,%r26)
+ fstws %fr6L,4(%sr0,%r26)
+ fstws %fr6,8(%sr0,%r26)
+
+ fstds %fr6R,0(%sr0,%r26)
+ fstds %fr6L,4(%sr0,%r26)
+ fstds %fr6,8(%sr0,%r26)
+
+ fldws 0(%sr0,%r26),%fr6R
+ fldws 4(%sr0,%r26),%fr6L
+ fldws 8(%sr0,%r26),%fr6
+
+ fldds 0(%sr0,%r26),%fr6R
+ fldds 4(%sr0,%r26),%fr6L
+ fldds 8(%sr0,%r26),%fr6
+
+ fstwx %fr6R,%r25(%r26)
+ fstwx %fr6L,%r25(%r26)
+ fstwx %fr6,%r25(%r26)
+
+ fstdx %fr6R,%r25(%r26)
+ fstdx %fr6L,%r25(%r26)
+ fstdx %fr6,%r25(%r26)
+
+ fldwx %r25(%r26),%fr6R
+ fldwx %r25(%r26),%fr6L
+ fldwx %r25(%r26),%fr6
+
+ flddx %r25(%r26),%fr6R
+ flddx %r25(%r26),%fr6L
+ flddx %r25(%r26),%fr6
+
+ fstwx %fr6R,%r25(%sr0,%r26)
+ fstwx %fr6L,%r25(%sr0,%r26)
+ fstwx %fr6,%r25(%sr0,%r26)
+
+ fstdx %fr6R,%r25(%sr0,%r26)
+ fstdx %fr6L,%r25(%sr0,%r26)
+ fstdx %fr6,%r25(%sr0,%r26)
+
+ fldwx %r25(%sr0,%r26),%fr6R
+ fldwx %r25(%sr0,%r26),%fr6L
+ fldwx %r25(%sr0,%r26),%fr6
+
+ flddx %r25(%sr0,%r26),%fr6R
+ flddx %r25(%sr0,%r26),%fr6L
+ flddx %r25(%sr0,%r26),%fr6
+
+ bv %r0(%r2)
+ nop
+
+ .exit
+ .procend
diff --git a/gas/testsuite/gas/hppa/basic/fp_comp.s b/gas/testsuite/gas/hppa/basic/fp_comp.s
new file mode 100644
index 0000000000..c1017f7db9
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/fp_comp.s
@@ -0,0 +1,81 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic immediate instruction tests.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+ fcpy,sgl %fr5,%fr10
+ fcpy,dbl %fr5,%fr10
+ fcpy,quad %fr5,%fr10
+ fcpy,sgl %fr20,%fr24
+ fcpy,dbl %fr20,%fr24
+
+ fabs,sgl %fr5,%fr10
+ fabs,dbl %fr5,%fr10
+ fabs,quad %fr5,%fr10
+ fabs,sgl %fr20,%fr24
+ fabs,dbl %fr20,%fr24
+
+ fsqrt,sgl %fr5,%fr10
+ fsqrt,dbl %fr5,%fr10
+ fsqrt,quad %fr5,%fr10
+ fsqrt,sgl %fr20,%fr24
+ fsqrt,dbl %fr20,%fr24
+
+ frnd,sgl %fr5,%fr10
+ frnd,dbl %fr5,%fr10
+ frnd,quad %fr5,%fr10
+ frnd,sgl %fr20,%fr24
+ frnd,dbl %fr20,%fr24
+
+ fadd,sgl %fr4,%fr8,%fr12
+ fadd,dbl %fr4,%fr8,%fr12
+ fadd,quad %fr4,%fr8,%fr12
+ fadd,sgl %fr20,%fr24,%fr28
+ fadd,dbl %fr20,%fr24,%fr28
+ fadd,quad %fr20,%fr24,%fr28
+
+ fsub,sgl %fr4,%fr8,%fr12
+ fsub,dbl %fr4,%fr8,%fr12
+ fsub,quad %fr4,%fr8,%fr12
+ fsub,sgl %fr20,%fr24,%fr28
+ fsub,dbl %fr20,%fr24,%fr28
+ fsub,quad %fr20,%fr24,%fr28
+
+ fmpy,sgl %fr4,%fr8,%fr12
+ fmpy,dbl %fr4,%fr8,%fr12
+ fmpy,quad %fr4,%fr8,%fr12
+ fmpy,sgl %fr20,%fr24,%fr28
+ fmpy,dbl %fr20,%fr24,%fr28
+ fmpy,quad %fr20,%fr24,%fr28
+
+ fdiv,sgl %fr4,%fr8,%fr12
+ fdiv,dbl %fr4,%fr8,%fr12
+ fdiv,quad %fr4,%fr8,%fr12
+ fdiv,sgl %fr20,%fr24,%fr28
+ fdiv,dbl %fr20,%fr24,%fr28
+ fdiv,quad %fr20,%fr24,%fr28
+
+ frem,sgl %fr4,%fr8,%fr12
+ frem,dbl %fr4,%fr8,%fr12
+ frem,quad %fr4,%fr8,%fr12
+ frem,sgl %fr20,%fr24,%fr28
+ frem,dbl %fr20,%fr24,%fr28
+ frem,quad %fr20,%fr24,%fr28
+
+ fmpyadd,sgl %fr16,%fr17,%fr18,%fr19,%fr20
+ fmpyadd,dbl %fr16,%fr17,%fr18,%fr19,%fr20
+ fmpysub,sgl %fr16,%fr17,%fr18,%fr19,%fr20
+ fmpysub,dbl %fr16,%fr17,%fr18,%fr19,%fr20
+
+ xmpyu %fr4,%fr5,%fr6
diff --git a/gas/testsuite/gas/hppa/basic/fp_conv.s b/gas/testsuite/gas/hppa/basic/fp_conv.s
new file mode 100644
index 0000000000..5a44cb1637
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/fp_conv.s
@@ -0,0 +1,92 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic immediate instruction tests.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+ fcnvff,sgl,sgl %fr5,%fr10
+ fcnvff,sgl,dbl %fr5,%fr10
+ fcnvff,sgl,quad %fr5,%fr10
+ fcnvff,dbl,sgl %fr5,%fr10
+ fcnvff,dbl,dbl %fr5,%fr10
+ fcnvff,dbl,quad %fr5,%fr10
+ fcnvff,quad,sgl %fr5,%fr10
+ fcnvff,quad,dbl %fr5,%fr10
+ fcnvff,quad,quad %fr5,%fr10
+ fcnvff,sgl,sgl %fr20,%fr24
+ fcnvff,sgl,dbl %fr20,%fr24
+ fcnvff,sgl,quad %fr20,%fr24
+ fcnvff,dbl,sgl %fr20,%fr24
+ fcnvff,dbl,dbl %fr20,%fr24
+ fcnvff,dbl,quad %fr20,%fr24
+ fcnvff,quad,sgl %fr20,%fr24
+ fcnvff,quad,dbl %fr20,%fr24
+ fcnvff,quad,quad %fr20,%fr24
+
+ fcnvxf,sgl,sgl %fr5,%fr10
+ fcnvxf,sgl,dbl %fr5,%fr10
+ fcnvxf,sgl,quad %fr5,%fr10
+ fcnvxf,dbl,sgl %fr5,%fr10
+ fcnvxf,dbl,dbl %fr5,%fr10
+ fcnvxf,dbl,quad %fr5,%fr10
+ fcnvxf,quad,sgl %fr5,%fr10
+ fcnvxf,quad,dbl %fr5,%fr10
+ fcnvxf,quad,quad %fr5,%fr10
+ fcnvxf,sgl,sgl %fr20,%fr24
+ fcnvxf,sgl,dbl %fr20,%fr24
+ fcnvxf,sgl,quad %fr20,%fr24
+ fcnvxf,dbl,sgl %fr20,%fr24
+ fcnvxf,dbl,dbl %fr20,%fr24
+ fcnvxf,dbl,quad %fr20,%fr24
+ fcnvxf,quad,sgl %fr20,%fr24
+ fcnvxf,quad,dbl %fr20,%fr24
+ fcnvxf,quad,quad %fr20,%fr24
+
+ fcnvfx,sgl,sgl %fr5,%fr10
+ fcnvfx,sgl,dbl %fr5,%fr10
+ fcnvfx,sgl,quad %fr5,%fr10
+ fcnvfx,dbl,sgl %fr5,%fr10
+ fcnvfx,dbl,dbl %fr5,%fr10
+ fcnvfx,dbl,quad %fr5,%fr10
+ fcnvfx,quad,sgl %fr5,%fr10
+ fcnvfx,quad,dbl %fr5,%fr10
+ fcnvfx,quad,quad %fr5,%fr10
+ fcnvfx,sgl,sgl %fr20,%fr24
+ fcnvfx,sgl,dbl %fr20,%fr24
+ fcnvfx,sgl,quad %fr20,%fr24
+ fcnvfx,dbl,sgl %fr20,%fr24
+ fcnvfx,dbl,dbl %fr20,%fr24
+ fcnvfx,dbl,quad %fr20,%fr24
+ fcnvfx,quad,sgl %fr20,%fr24
+ fcnvfx,quad,dbl %fr20,%fr24
+ fcnvfx,quad,quad %fr20,%fr24
+
+ fcnvfxt,sgl,sgl %fr5,%fr10
+ fcnvfxt,sgl,dbl %fr5,%fr10
+ fcnvfxt,sgl,quad %fr5,%fr10
+ fcnvfxt,dbl,sgl %fr5,%fr10
+ fcnvfxt,dbl,dbl %fr5,%fr10
+ fcnvfxt,dbl,quad %fr5,%fr10
+ fcnvfxt,quad,sgl %fr5,%fr10
+ fcnvfxt,quad,dbl %fr5,%fr10
+ fcnvfxt,quad,quad %fr5,%fr10
+ fcnvfxt,sgl,sgl %fr20,%fr24
+ fcnvfxt,sgl,dbl %fr20,%fr24
+ fcnvfxt,sgl,quad %fr20,%fr24
+ fcnvfxt,dbl,sgl %fr20,%fr24
+ fcnvfxt,dbl,dbl %fr20,%fr24
+ fcnvfxt,dbl,quad %fr20,%fr24
+ fcnvfxt,quad,sgl %fr20,%fr24
+ fcnvfxt,quad,dbl %fr20,%fr24
+ fcnvfxt,quad,quad %fr20,%fr24
+
diff --git a/gas/testsuite/gas/hppa/basic/fp_fcmp.s b/gas/testsuite/gas/hppa/basic/fp_fcmp.s
new file mode 100644
index 0000000000..fbd092c1a7
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/fp_fcmp.s
@@ -0,0 +1,114 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic immediate instruction tests.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+ fcmp,sgl,false? %fr4,%fr5
+ fcmp,sgl,false %fr4,%fr5
+ fcmp,sgl,? %fr4,%fr5
+ fcmp,sgl,!<=> %fr4,%fr5
+ fcmp,sgl,= %fr4,%fr5
+ fcmp,sgl,=T %fr4,%fr5
+ fcmp,sgl,?= %fr4,%fr5
+ fcmp,sgl,!<> %fr4,%fr5
+ fcmp,sgl,!?>= %fr4,%fr5
+ fcmp,sgl,< %fr4,%fr5
+ fcmp,sgl,?< %fr4,%fr5
+ fcmp,sgl,!>= %fr4,%fr5
+ fcmp,sgl,!?> %fr4,%fr5
+ fcmp,sgl,<= %fr4,%fr5
+ fcmp,sgl,?<= %fr4,%fr5
+ fcmp,sgl,!> %fr4,%fr5
+ fcmp,sgl,!?<= %fr4,%fr5
+ fcmp,sgl,> %fr4,%fr5
+ fcmp,sgl,?> %fr4,%fr5
+ fcmp,sgl,!<= %fr4,%fr5
+ fcmp,sgl,!?< %fr4,%fr5
+ fcmp,sgl,>= %fr4,%fr5
+ fcmp,sgl,?>= %fr4,%fr5
+ fcmp,sgl,!< %fr4,%fr5
+ fcmp,sgl,!?= %fr4,%fr5
+ fcmp,sgl,<> %fr4,%fr5
+ fcmp,sgl,!= %fr4,%fr5
+ fcmp,sgl,!=T %fr4,%fr5
+ fcmp,sgl,!? %fr4,%fr5
+ fcmp,sgl,<=> %fr4,%fr5
+ fcmp,sgl,true? %fr4,%fr5
+ fcmp,sgl,true %fr4,%fr5
+
+ fcmp,dbl,false? %fr4,%fr5
+ fcmp,dbl,false %fr4,%fr5
+ fcmp,dbl,? %fr4,%fr5
+ fcmp,dbl,!<=> %fr4,%fr5
+ fcmp,dbl,= %fr4,%fr5
+ fcmp,dbl,=T %fr4,%fr5
+ fcmp,dbl,?= %fr4,%fr5
+ fcmp,dbl,!<> %fr4,%fr5
+ fcmp,dbl,!?>= %fr4,%fr5
+ fcmp,dbl,< %fr4,%fr5
+ fcmp,dbl,?< %fr4,%fr5
+ fcmp,dbl,!>= %fr4,%fr5
+ fcmp,dbl,!?> %fr4,%fr5
+ fcmp,dbl,<= %fr4,%fr5
+ fcmp,dbl,?<= %fr4,%fr5
+ fcmp,dbl,!> %fr4,%fr5
+ fcmp,dbl,!?<= %fr4,%fr5
+ fcmp,dbl,> %fr4,%fr5
+ fcmp,dbl,?> %fr4,%fr5
+ fcmp,dbl,!<= %fr4,%fr5
+ fcmp,dbl,!?< %fr4,%fr5
+ fcmp,dbl,>= %fr4,%fr5
+ fcmp,dbl,?>= %fr4,%fr5
+ fcmp,dbl,!< %fr4,%fr5
+ fcmp,dbl,!?= %fr4,%fr5
+ fcmp,dbl,<> %fr4,%fr5
+ fcmp,dbl,!= %fr4,%fr5
+ fcmp,dbl,!=T %fr4,%fr5
+ fcmp,dbl,!? %fr4,%fr5
+ fcmp,dbl,<=> %fr4,%fr5
+ fcmp,dbl,true? %fr4,%fr5
+ fcmp,dbl,true %fr4,%fr5
+
+ fcmp,quad,false? %fr4,%fr5
+ fcmp,quad,false %fr4,%fr5
+ fcmp,quad,? %fr4,%fr5
+ fcmp,quad,!<=> %fr4,%fr5
+ fcmp,quad,= %fr4,%fr5
+ fcmp,quad,=T %fr4,%fr5
+ fcmp,quad,?= %fr4,%fr5
+ fcmp,quad,!<> %fr4,%fr5
+ fcmp,quad,!?>= %fr4,%fr5
+ fcmp,quad,< %fr4,%fr5
+ fcmp,quad,?< %fr4,%fr5
+ fcmp,quad,!>= %fr4,%fr5
+ fcmp,quad,!?> %fr4,%fr5
+ fcmp,quad,<= %fr4,%fr5
+ fcmp,quad,?<= %fr4,%fr5
+ fcmp,quad,!> %fr4,%fr5
+ fcmp,quad,!?<= %fr4,%fr5
+ fcmp,quad,> %fr4,%fr5
+ fcmp,quad,?> %fr4,%fr5
+ fcmp,quad,!<= %fr4,%fr5
+ fcmp,quad,!?< %fr4,%fr5
+ fcmp,quad,>= %fr4,%fr5
+ fcmp,quad,?>= %fr4,%fr5
+ fcmp,quad,!< %fr4,%fr5
+ fcmp,quad,!?= %fr4,%fr5
+ fcmp,quad,<> %fr4,%fr5
+ fcmp,quad,!= %fr4,%fr5
+ fcmp,quad,!=T %fr4,%fr5
+ fcmp,quad,!? %fr4,%fr5
+ fcmp,quad,<=> %fr4,%fr5
+ fcmp,quad,true? %fr4,%fr5
+ fcmp,quad,true %fr4,%fr5
diff --git a/gas/testsuite/gas/hppa/basic/fp_misc.s b/gas/testsuite/gas/hppa/basic/fp_misc.s
new file mode 100644
index 0000000000..356ac04488
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/fp_misc.s
@@ -0,0 +1,18 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic immediate instruction tests.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+fpu_misc_tests:
+ ftest
diff --git a/gas/testsuite/gas/hppa/basic/imem.s b/gas/testsuite/gas/hppa/basic/imem.s
new file mode 100644
index 0000000000..3c49c121d1
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/imem.s
@@ -0,0 +1,93 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .EXPORT integer_memory_tests,CODE
+ .EXPORT integer_indexing_load,CODE
+ .EXPORT integer_load_short_memory,CODE
+ .EXPORT integer_store_short_memory,CODE
+ .EXPORT main,CODE
+ .EXPORT main,ENTRY,PRIV_LEV=3,RTNVAL=GR
+; Basic integer memory tests which also test the various
+; addressing modes and completers.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+;
+integer_memory_tests:
+ ldw 0(%sr0,%r4),%r26
+ ldh 0(%sr0,%r4),%r26
+ ldb 0(%sr0,%r4),%r26
+ stw %r26,0(%sr0,%r4)
+ sth %r26,0(%sr0,%r4)
+ stb %r26,0(%sr0,%r4)
+
+; Should make sure pre/post modes are recognized correctly.
+ ldwm 0(%sr0,%r4),%r26
+ stwm %r26,0(%sr0,%r4)
+
+integer_indexing_load:
+ ldwx %r5(%sr0,%r4),%r26
+ ldwx,s %r5(%sr0,%r4),%r26
+ ldwx,m %r5(%sr0,%r4),%r26
+ ldwx,sm %r5(%sr0,%r4),%r26
+ ldhx %r5(%sr0,%r4),%r26
+ ldhx,s %r5(%sr0,%r4),%r26
+ ldhx,m %r5(%sr0,%r4),%r26
+ ldhx,sm %r5(%sr0,%r4),%r26
+ ldbx %r5(%sr0,%r4),%r26
+ ldbx,s %r5(%sr0,%r4),%r26
+ ldbx,m %r5(%sr0,%r4),%r26
+ ldbx,sm %r5(%sr0,%r4),%r26
+ ldwax %r5(%r4),%r26
+ ldwax,s %r5(%r4),%r26
+ ldwax,m %r5(%r4),%r26
+ ldwax,sm %r5(%r4),%r26
+ ldcwx %r5(%sr0,%r4),%r26
+ ldcwx,s %r5(%sr0,%r4),%r26
+ ldcwx,m %r5(%sr0,%r4),%r26
+ ldcwx,sm %r5(%sr0,%r4),%r26
+
+integer_load_short_memory:
+ ldws 0(%sr0,%r4),%r26
+ ldws,mb 0(%sr0,%r4),%r26
+ ldws,ma 0(%sr0,%r4),%r26
+ ldhs 0(%sr0,%r4),%r26
+ ldhs,mb 0(%sr0,%r4),%r26
+ ldhs,ma 0(%sr0,%r4),%r26
+ ldbs 0(%sr0,%r4),%r26
+ ldbs,mb 0(%sr0,%r4),%r26
+ ldbs,ma 0(%sr0,%r4),%r26
+ ldwas 0(%r4),%r26
+ ldwas,mb 0(%r4),%r26
+ ldwas,ma 0(%r4),%r26
+ ldcws 0(%sr0,%r4),%r26
+ ldcws,mb 0(%sr0,%r4),%r26
+ ldcws,ma 0(%sr0,%r4),%r26
+
+integer_store_short_memory:
+ stws %r26,0(%sr0,%r4)
+ stws,mb %r26,0(%sr0,%r4)
+ stws,ma %r26,0(%sr0,%r4)
+ sths %r26,0(%sr0,%r4)
+ sths,mb %r26,0(%sr0,%r4)
+ sths,ma %r26,0(%sr0,%r4)
+ stbs %r26,0(%sr0,%r4)
+ stbs,mb %r26,0(%sr0,%r4)
+ stbs,ma %r26,0(%sr0,%r4)
+ stwas %r26,0(%r4)
+ stwas,mb %r26,0(%r4)
+ stwas,ma %r26,0(%r4)
+ stbys %r26,0(%sr0,%r4)
+ stbys,b %r26,0(%sr0,%r4)
+ stbys,e %r26,0(%sr0,%r4)
+ stbys,b,m %r26,0(%sr0,%r4)
+ stbys,e,m %r26,0(%sr0,%r4)
diff --git a/gas/testsuite/gas/hppa/basic/immed.s b/gas/testsuite/gas/hppa/basic/immed.s
new file mode 100644
index 0000000000..dd27d2fe03
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/immed.s
@@ -0,0 +1,21 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic immediate instruction tests.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+immediate_tests:
+ ldo 5(%r26),%r26
+ ldil L%0xdeadbeef,%r26
+ addil L%0xdeadbeef,%r5
+
diff --git a/gas/testsuite/gas/hppa/basic/logical.s b/gas/testsuite/gas/hppa/basic/logical.s
new file mode 100644
index 0000000000..771059ed0b
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/logical.s
@@ -0,0 +1,60 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic immediate instruction tests.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+ or %r4,%r5,%r6
+ or,= %r4,%r5,%r6
+ or,< %r4,%r5,%r6
+ or,<= %r4,%r5,%r6
+ or,od %r4,%r5,%r6
+ or,tr %r4,%r5,%r6
+ or,<> %r4,%r5,%r6
+ or,>= %r4,%r5,%r6
+ or,> %r4,%r5,%r6
+ or,ev %r4,%r5,%r6
+
+ xor %r4,%r5,%r6
+ xor,= %r4,%r5,%r6
+ xor,< %r4,%r5,%r6
+ xor,<= %r4,%r5,%r6
+ xor,od %r4,%r5,%r6
+ xor,tr %r4,%r5,%r6
+ xor,<> %r4,%r5,%r6
+ xor,>= %r4,%r5,%r6
+ xor,> %r4,%r5,%r6
+ xor,ev %r4,%r5,%r6
+
+ and %r4,%r5,%r6
+ and,= %r4,%r5,%r6
+ and,< %r4,%r5,%r6
+ and,<= %r4,%r5,%r6
+ and,od %r4,%r5,%r6
+ and,tr %r4,%r5,%r6
+ and,<> %r4,%r5,%r6
+ and,>= %r4,%r5,%r6
+ and,> %r4,%r5,%r6
+ and,ev %r4,%r5,%r6
+
+ andcm %r4,%r5,%r6
+ andcm,= %r4,%r5,%r6
+ andcm,< %r4,%r5,%r6
+ andcm,<= %r4,%r5,%r6
+ andcm,od %r4,%r5,%r6
+ andcm,tr %r4,%r5,%r6
+ andcm,<> %r4,%r5,%r6
+ andcm,>= %r4,%r5,%r6
+ andcm,> %r4,%r5,%r6
+ andcm,ev %r4,%r5,%r6
+
diff --git a/gas/testsuite/gas/hppa/basic/purge.s b/gas/testsuite/gas/hppa/basic/purge.s
new file mode 100644
index 0000000000..2319f90839
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/purge.s
@@ -0,0 +1,35 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic immediate instruction tests.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+ pdtlb %r4(%sr0,%r5)
+ pdtlb,m %r4(%sr0,%r5)
+ pitlb %r4(%sr4,%r5)
+ pitlb,m %r4(%sr4,%r5)
+ pdtlbe %r4(%sr0,%r5)
+ pdtlbe,m %r4(%sr0,%r5)
+ pitlbe %r4(%sr4,%r5)
+ pitlbe,m %r4(%sr4,%r5)
+ pdc %r4(%sr0,%r5)
+ pdc,m %r4(%sr0,%r5)
+ fdc %r4(%sr0,%r5)
+ fdc,m %r4(%sr0,%r5)
+ fic %r4(%sr4,%r5)
+ fic,m %r4(%sr4,%r5)
+ fdce %r4(%sr0,%r5)
+ fdce,m %r4(%sr0,%r5)
+ fice %r4(%sr4,%r5)
+ fice,m %r4(%sr4,%r5)
+
diff --git a/gas/testsuite/gas/hppa/basic/sh1add.s b/gas/testsuite/gas/hppa/basic/sh1add.s
new file mode 100644
index 0000000000..325d6cc129
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/sh1add.s
@@ -0,0 +1,67 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic immediate instruction tests.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+ sh1add %r4,%r5,%r6
+ sh1add,= %r4,%r5,%r6
+ sh1add,< %r4,%r5,%r6
+ sh1add,<= %r4,%r5,%r6
+ sh1add,nuv %r4,%r5,%r6
+ sh1add,znv %r4,%r5,%r6
+ sh1add,sv %r4,%r5,%r6
+ sh1add,od %r4,%r5,%r6
+ sh1add,tr %r4,%r5,%r6
+ sh1add,<> %r4,%r5,%r6
+ sh1add,>= %r4,%r5,%r6
+ sh1add,> %r4,%r5,%r6
+ sh1add,uv %r4,%r5,%r6
+ sh1add,vnz %r4,%r5,%r6
+ sh1add,nsv %r4,%r5,%r6
+ sh1add,ev %r4,%r5,%r6
+
+ sh1addl %r4,%r5,%r6
+ sh1addl,= %r4,%r5,%r6
+ sh1addl,< %r4,%r5,%r6
+ sh1addl,<= %r4,%r5,%r6
+ sh1addl,nuv %r4,%r5,%r6
+ sh1addl,znv %r4,%r5,%r6
+ sh1addl,sv %r4,%r5,%r6
+ sh1addl,od %r4,%r5,%r6
+ sh1addl,tr %r4,%r5,%r6
+ sh1addl,<> %r4,%r5,%r6
+ sh1addl,>= %r4,%r5,%r6
+ sh1addl,> %r4,%r5,%r6
+ sh1addl,uv %r4,%r5,%r6
+ sh1addl,vnz %r4,%r5,%r6
+ sh1addl,nsv %r4,%r5,%r6
+ sh1addl,ev %r4,%r5,%r6
+
+ sh1addo %r4,%r5,%r6
+ sh1addo,= %r4,%r5,%r6
+ sh1addo,< %r4,%r5,%r6
+ sh1addo,<= %r4,%r5,%r6
+ sh1addo,nuv %r4,%r5,%r6
+ sh1addo,znv %r4,%r5,%r6
+ sh1addo,sv %r4,%r5,%r6
+ sh1addo,od %r4,%r5,%r6
+ sh1addo,tr %r4,%r5,%r6
+ sh1addo,<> %r4,%r5,%r6
+ sh1addo,>= %r4,%r5,%r6
+ sh1addo,> %r4,%r5,%r6
+ sh1addo,uv %r4,%r5,%r6
+ sh1addo,vnz %r4,%r5,%r6
+ sh1addo,nsv %r4,%r5,%r6
+ sh1addo,ev %r4,%r5,%r6
+
diff --git a/gas/testsuite/gas/hppa/basic/sh2add.s b/gas/testsuite/gas/hppa/basic/sh2add.s
new file mode 100644
index 0000000000..d19c99b77d
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/sh2add.s
@@ -0,0 +1,67 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic immediate instruction tests.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+ sh2add %r4,%r5,%r6
+ sh2add,= %r4,%r5,%r6
+ sh2add,< %r4,%r5,%r6
+ sh2add,<= %r4,%r5,%r6
+ sh2add,nuv %r4,%r5,%r6
+ sh2add,znv %r4,%r5,%r6
+ sh2add,sv %r4,%r5,%r6
+ sh2add,od %r4,%r5,%r6
+ sh2add,tr %r4,%r5,%r6
+ sh2add,<> %r4,%r5,%r6
+ sh2add,>= %r4,%r5,%r6
+ sh2add,> %r4,%r5,%r6
+ sh2add,uv %r4,%r5,%r6
+ sh2add,vnz %r4,%r5,%r6
+ sh2add,nsv %r4,%r5,%r6
+ sh2add,ev %r4,%r5,%r6
+
+ sh2addl %r4,%r5,%r6
+ sh2addl,= %r4,%r5,%r6
+ sh2addl,< %r4,%r5,%r6
+ sh2addl,<= %r4,%r5,%r6
+ sh2addl,nuv %r4,%r5,%r6
+ sh2addl,znv %r4,%r5,%r6
+ sh2addl,sv %r4,%r5,%r6
+ sh2addl,od %r4,%r5,%r6
+ sh2addl,tr %r4,%r5,%r6
+ sh2addl,<> %r4,%r5,%r6
+ sh2addl,>= %r4,%r5,%r6
+ sh2addl,> %r4,%r5,%r6
+ sh2addl,uv %r4,%r5,%r6
+ sh2addl,vnz %r4,%r5,%r6
+ sh2addl,nsv %r4,%r5,%r6
+ sh2addl,ev %r4,%r5,%r6
+
+ sh2addo %r4,%r5,%r6
+ sh2addo,= %r4,%r5,%r6
+ sh2addo,< %r4,%r5,%r6
+ sh2addo,<= %r4,%r5,%r6
+ sh2addo,nuv %r4,%r5,%r6
+ sh2addo,znv %r4,%r5,%r6
+ sh2addo,sv %r4,%r5,%r6
+ sh2addo,od %r4,%r5,%r6
+ sh2addo,tr %r4,%r5,%r6
+ sh2addo,<> %r4,%r5,%r6
+ sh2addo,>= %r4,%r5,%r6
+ sh2addo,> %r4,%r5,%r6
+ sh2addo,uv %r4,%r5,%r6
+ sh2addo,vnz %r4,%r5,%r6
+ sh2addo,nsv %r4,%r5,%r6
+ sh2addo,ev %r4,%r5,%r6
+
diff --git a/gas/testsuite/gas/hppa/basic/sh3add.s b/gas/testsuite/gas/hppa/basic/sh3add.s
new file mode 100644
index 0000000000..a51e6e3642
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/sh3add.s
@@ -0,0 +1,67 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic immediate instruction tests.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+ sh3add %r4,%r5,%r6
+ sh3add,= %r4,%r5,%r6
+ sh3add,< %r4,%r5,%r6
+ sh3add,<= %r4,%r5,%r6
+ sh3add,nuv %r4,%r5,%r6
+ sh3add,znv %r4,%r5,%r6
+ sh3add,sv %r4,%r5,%r6
+ sh3add,od %r4,%r5,%r6
+ sh3add,tr %r4,%r5,%r6
+ sh3add,<> %r4,%r5,%r6
+ sh3add,>= %r4,%r5,%r6
+ sh3add,> %r4,%r5,%r6
+ sh3add,uv %r4,%r5,%r6
+ sh3add,vnz %r4,%r5,%r6
+ sh3add,nsv %r4,%r5,%r6
+ sh3add,ev %r4,%r5,%r6
+
+ sh3addl %r4,%r5,%r6
+ sh3addl,= %r4,%r5,%r6
+ sh3addl,< %r4,%r5,%r6
+ sh3addl,<= %r4,%r5,%r6
+ sh3addl,nuv %r4,%r5,%r6
+ sh3addl,znv %r4,%r5,%r6
+ sh3addl,sv %r4,%r5,%r6
+ sh3addl,od %r4,%r5,%r6
+ sh3addl,tr %r4,%r5,%r6
+ sh3addl,<> %r4,%r5,%r6
+ sh3addl,>= %r4,%r5,%r6
+ sh3addl,> %r4,%r5,%r6
+ sh3addl,uv %r4,%r5,%r6
+ sh3addl,vnz %r4,%r5,%r6
+ sh3addl,nsv %r4,%r5,%r6
+ sh3addl,ev %r4,%r5,%r6
+
+ sh3addo %r4,%r5,%r6
+ sh3addo,= %r4,%r5,%r6
+ sh3addo,< %r4,%r5,%r6
+ sh3addo,<= %r4,%r5,%r6
+ sh3addo,nuv %r4,%r5,%r6
+ sh3addo,znv %r4,%r5,%r6
+ sh3addo,sv %r4,%r5,%r6
+ sh3addo,od %r4,%r5,%r6
+ sh3addo,tr %r4,%r5,%r6
+ sh3addo,<> %r4,%r5,%r6
+ sh3addo,>= %r4,%r5,%r6
+ sh3addo,> %r4,%r5,%r6
+ sh3addo,uv %r4,%r5,%r6
+ sh3addo,vnz %r4,%r5,%r6
+ sh3addo,nsv %r4,%r5,%r6
+ sh3addo,ev %r4,%r5,%r6
+
diff --git a/gas/testsuite/gas/hppa/basic/shift.s b/gas/testsuite/gas/hppa/basic/shift.s
new file mode 100644
index 0000000000..5cc621dbb3
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/shift.s
@@ -0,0 +1,34 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic immediate instruction tests.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+ vshd %r4,%r5,%r6
+ vshd,= %r4,%r5,%r6
+ vshd,< %r4,%r5,%r6
+ vshd,od %r4,%r5,%r6
+ vshd,tr %r4,%r5,%r6
+ vshd,<> %r4,%r5,%r6
+ vshd,>= %r4,%r5,%r6
+ vshd,ev %r4,%r5,%r6
+
+ shd %r4,%r5,5,%r6
+ shd,= %r4,%r5,5,%r6
+ shd,< %r4,%r5,5,%r6
+ shd,od %r4,%r5,5,%r6
+ shd,tr %r4,%r5,5,%r6
+ shd,<> %r4,%r5,5,%r6
+ shd,>= %r4,%r5,5,%r6
+ shd,ev %r4,%r5,5,%r6
+
diff --git a/gas/testsuite/gas/hppa/basic/special.s b/gas/testsuite/gas/hppa/basic/special.s
new file mode 100644
index 0000000000..d341667bb2
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/special.s
@@ -0,0 +1,15 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ gfw %r4(%sr0,%r5)
+ gfw,m %r4(%sr0,%r5)
+ gfr %r4(%sr0,%r5)
+ gfr,m %r4(%sr0,%r5)
diff --git a/gas/testsuite/gas/hppa/basic/spop.s b/gas/testsuite/gas/hppa/basic/spop.s
new file mode 100644
index 0000000000..9076a95b6b
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/spop.s
@@ -0,0 +1,34 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+spop_tests:
+ spop0,4,5
+ spop0,4,115
+ spop0,4,5,n
+ spop0,4,115,n
+ spop1,4,5 %r5
+ spop1,4,115 %r5
+ spop1,4,5,n %r5
+ spop1,4,115,n %r5
+ spop2,4,5 %r5
+ spop2,4,115 %r5
+ spop2,4,5,n %r5
+ spop2,4,115,n %r5
+ spop3,4,5 %r5,%r6
+ spop3,4,115 %r5,%r6
+ spop3,4,5,n %r5,%r6
+ spop3,4,115,n %r5,%r6
+
+; Gas fucks this up... Thinks it has the expression 5 mod r5.
+; spop1,4,5 %r5
diff --git a/gas/testsuite/gas/hppa/basic/sub.s b/gas/testsuite/gas/hppa/basic/sub.s
new file mode 100644
index 0000000000..64ff0df506
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/sub.s
@@ -0,0 +1,117 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic immediate instruction tests.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+ sub %r4,%r5,%r6
+ sub,= %r4,%r5,%r6
+ sub,< %r4,%r5,%r6
+ sub,<= %r4,%r5,%r6
+ sub,<< %r4,%r5,%r6
+ sub,<<= %r4,%r5,%r6
+ sub,sv %r4,%r5,%r6
+ sub,od %r4,%r5,%r6
+ sub,tr %r4,%r5,%r6
+ sub,<> %r4,%r5,%r6
+ sub,>= %r4,%r5,%r6
+ sub,> %r4,%r5,%r6
+ sub,>>= %r4,%r5,%r6
+ sub,>> %r4,%r5,%r6
+ sub,nsv %r4,%r5,%r6
+ sub,ev %r4,%r5,%r6
+
+ subo %r4,%r5,%r6
+ subo,= %r4,%r5,%r6
+ subo,< %r4,%r5,%r6
+ subo,<= %r4,%r5,%r6
+ subo,<< %r4,%r5,%r6
+ subo,<<= %r4,%r5,%r6
+ subo,sv %r4,%r5,%r6
+ subo,od %r4,%r5,%r6
+ subo,tr %r4,%r5,%r6
+ subo,<> %r4,%r5,%r6
+ subo,>= %r4,%r5,%r6
+ subo,> %r4,%r5,%r6
+ subo,>>= %r4,%r5,%r6
+ subo,>> %r4,%r5,%r6
+ subo,nsv %r4,%r5,%r6
+ subo,ev %r4,%r5,%r6
+
+ subb %r4,%r5,%r6
+ subb,= %r4,%r5,%r6
+ subb,< %r4,%r5,%r6
+ subb,<= %r4,%r5,%r6
+ subb,<< %r4,%r5,%r6
+ subb,<<= %r4,%r5,%r6
+ subb,sv %r4,%r5,%r6
+ subb,od %r4,%r5,%r6
+ subb,tr %r4,%r5,%r6
+ subb,<> %r4,%r5,%r6
+ subb,>= %r4,%r5,%r6
+ subb,> %r4,%r5,%r6
+ subb,>>= %r4,%r5,%r6
+ subb,>> %r4,%r5,%r6
+ subb,nsv %r4,%r5,%r6
+ subb,ev %r4,%r5,%r6
+
+ subbo %r4,%r5,%r6
+ subbo,= %r4,%r5,%r6
+ subbo,< %r4,%r5,%r6
+ subbo,<= %r4,%r5,%r6
+ subbo,<< %r4,%r5,%r6
+ subbo,<<= %r4,%r5,%r6
+ subbo,sv %r4,%r5,%r6
+ subbo,od %r4,%r5,%r6
+ subbo,tr %r4,%r5,%r6
+ subbo,<> %r4,%r5,%r6
+ subbo,>= %r4,%r5,%r6
+ subbo,> %r4,%r5,%r6
+ subbo,>>= %r4,%r5,%r6
+ subbo,>> %r4,%r5,%r6
+ subbo,nsv %r4,%r5,%r6
+ subbo,ev %r4,%r5,%r6
+
+ subt %r4,%r5,%r6
+ subt,= %r4,%r5,%r6
+ subt,< %r4,%r5,%r6
+ subt,<= %r4,%r5,%r6
+ subt,<< %r4,%r5,%r6
+ subt,<<= %r4,%r5,%r6
+ subt,sv %r4,%r5,%r6
+ subt,od %r4,%r5,%r6
+ subt,tr %r4,%r5,%r6
+ subt,<> %r4,%r5,%r6
+ subt,>= %r4,%r5,%r6
+ subt,> %r4,%r5,%r6
+ subt,>>= %r4,%r5,%r6
+ subt,>> %r4,%r5,%r6
+ subt,nsv %r4,%r5,%r6
+ subt,ev %r4,%r5,%r6
+
+ subto %r4,%r5,%r6
+ subto,= %r4,%r5,%r6
+ subto,< %r4,%r5,%r6
+ subto,<= %r4,%r5,%r6
+ subto,<< %r4,%r5,%r6
+ subto,<<= %r4,%r5,%r6
+ subto,sv %r4,%r5,%r6
+ subto,od %r4,%r5,%r6
+ subto,tr %r4,%r5,%r6
+ subto,<> %r4,%r5,%r6
+ subto,>= %r4,%r5,%r6
+ subto,> %r4,%r5,%r6
+ subto,>>= %r4,%r5,%r6
+ subto,>> %r4,%r5,%r6
+ subto,nsv %r4,%r5,%r6
+ subto,ev %r4,%r5,%r6
diff --git a/gas/testsuite/gas/hppa/basic/subi.s b/gas/testsuite/gas/hppa/basic/subi.s
new file mode 100644
index 0000000000..063267c87f
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/subi.s
@@ -0,0 +1,49 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic immediate instruction tests.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+ subi 123,%r5,%r6
+ subi,= 123,%r5,%r6
+ subi,< 123,%r5,%r6
+ subi,<= 123,%r5,%r6
+ subi,<< 123,%r5,%r6
+ subi,<<= 123,%r5,%r6
+ subi,sv 123,%r5,%r6
+ subi,od 123,%r5,%r6
+ subi,tr 123,%r5,%r6
+ subi,<> 123,%r5,%r6
+ subi,>= 123,%r5,%r6
+ subi,> 123,%r5,%r6
+ subi,>>= 123,%r5,%r6
+ subi,>> 123,%r5,%r6
+ subi,nsv 123,%r5,%r6
+ subi,ev 123,%r5,%r6
+
+ subio 123,%r5,%r6
+ subio,= 123,%r5,%r6
+ subio,< 123,%r5,%r6
+ subio,<= 123,%r5,%r6
+ subio,<< 123,%r5,%r6
+ subio,<<= 123,%r5,%r6
+ subio,sv 123,%r5,%r6
+ subio,od 123,%r5,%r6
+ subio,tr 123,%r5,%r6
+ subio,<> 123,%r5,%r6
+ subio,>= 123,%r5,%r6
+ subio,> 123,%r5,%r6
+ subio,>>= 123,%r5,%r6
+ subio,>> 123,%r5,%r6
+ subio,nsv 123,%r5,%r6
+ subio,ev 123,%r5,%r6
diff --git a/gas/testsuite/gas/hppa/basic/system.s b/gas/testsuite/gas/hppa/basic/system.s
new file mode 100644
index 0000000000..1b2e7bf176
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/system.s
@@ -0,0 +1,46 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic immediate instruction tests.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+ break 5,12
+ rfi
+ rfir
+ ssm 5,%r4
+ rsm 5,%r4
+ mtsm %r4
+ ldsid (%sr0,%r5),%r4
+ mtsp %r4,%sr0
+ mtctl %r4,%cr10
+ mfsp %sr0,%r4
+ mfctl %cr10,%r4
+ sync
+ syncdma
+ diag 1234
+
+ prober (%sr0,%r5),%r6,%r7
+ proberi (%sr0,%r5),1,%r7
+ probew (%sr0,%r5),%r6,%r7
+ probewi (%sr0,%r5),1,%r7
+
+ lpa %r4(%sr0,%r5),%r6
+ lpa,m %r4(%sr0,%r5),%r6
+ lha %r4(%sr0,%r5),%r6
+ lha,m %r4(%sr0,%r5),%r6
+ lci %r4(%sr0,%r5),%r6
+
+ idtlba %r4,(%sr0,%r5)
+ iitlba %r4,(%sr4,%r5)
+ idtlbp %r4,(%sr0,%r5)
+ iitlbp %r4,(%sr4,%r5)
diff --git a/gas/testsuite/gas/hppa/basic/unit.s b/gas/testsuite/gas/hppa/basic/unit.s
new file mode 100644
index 0000000000..b69b10ee9d
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/unit.s
@@ -0,0 +1,55 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic immediate instruction tests.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+
+ uxor %r4,%r5,%r6
+ uxor,sbz %r4,%r5,%r6
+ uxor,shz %r4,%r5,%r6
+ uxor,sdc %r4,%r5,%r6
+ uxor,sbc %r4,%r5,%r6
+ uxor,shc %r4,%r5,%r6
+ uxor,tr %r4,%r5,%r6
+ uxor,nbz %r4,%r5,%r6
+ uxor,nhz %r4,%r5,%r6
+ uxor,ndc %r4,%r5,%r6
+ uxor,nbc %r4,%r5,%r6
+ uxor,nhc %r4,%r5,%r6
+
+ uaddcm %r4,%r5,%r6
+ uaddcm,sbz %r4,%r5,%r6
+ uaddcm,shz %r4,%r5,%r6
+ uaddcm,sdc %r4,%r5,%r6
+ uaddcm,sbc %r4,%r5,%r6
+ uaddcm,shc %r4,%r5,%r6
+ uaddcm,tr %r4,%r5,%r6
+ uaddcm,nbz %r4,%r5,%r6
+ uaddcm,nhz %r4,%r5,%r6
+ uaddcm,ndc %r4,%r5,%r6
+ uaddcm,nbc %r4,%r5,%r6
+ uaddcm,nhc %r4,%r5,%r6
+
+ uaddcmt %r4,%r5,%r6
+ uaddcmt,sbz %r4,%r5,%r6
+ uaddcmt,shz %r4,%r5,%r6
+ uaddcmt,sdc %r4,%r5,%r6
+ uaddcmt,sbc %r4,%r5,%r6
+ uaddcmt,shc %r4,%r5,%r6
+ uaddcmt,tr %r4,%r5,%r6
+ uaddcmt,nbz %r4,%r5,%r6
+ uaddcmt,nhz %r4,%r5,%r6
+ uaddcmt,ndc %r4,%r5,%r6
+ uaddcmt,nbc %r4,%r5,%r6
+ uaddcmt,nhc %r4,%r5,%r6
diff --git a/gas/testsuite/gas/hppa/basic/weird.s b/gas/testsuite/gas/hppa/basic/weird.s
new file mode 100644
index 0000000000..6df4ea165a
--- /dev/null
+++ b/gas/testsuite/gas/hppa/basic/weird.s
@@ -0,0 +1,870 @@
+ .stabs "weird.c",0x64,0,0,Label0
+Label0:
+ .stabs "inttype:t1=bu4;0;32;",0x80,0,0,0
+
+
+ .stabs "sym32: !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+
+ .stabs "type32:t32= !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+
+
+ .stabs "attr104:G404=@h !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr105:G405=@i !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+
+ .stabs "var0:G300=@a8;1",0x20,0,0, 0
+ .export var0
+ .data
+ .align 4
+var0:
+ .long 42
+
+ .stabs "sym33:! !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym35:# !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym36:$ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym37:% !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym38:& !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym39:' !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym40:( !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym41:) !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym42:* !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym43:+ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym44:, !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym45:- !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+
+ .export attr122
+ .data
+ .align 4
+attr122:
+ .long 42
+ .export attr123
+ .data
+ .align 4
+attr123:
+ .long 42
+ .export attr124
+ .data
+ .align 4
+attr124:
+ .long 42
+
+ .stabs "sym46:. !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym47:/ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym48:0 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym49:1 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym50:2 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+
+ .stabs "attr96:G396=@` !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr97:G397=@a !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr98:G398=@b !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr99:G399=@c !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+
+ .stabs "sym51:3 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym52:4 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym53:5 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym54:6 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym55:7 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym56:8 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym57:9 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym58:: !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym59:; !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym60:< !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym61:= !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym62:> !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym63:? !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym64:@ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym65:A !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym66:B !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym67:C !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym68:D !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym69:E !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym70:F !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym71:G !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym72:H !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym73:I !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym74:J !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym75:K !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym76:L !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym77:M !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym78:N !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym79:O !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym80:P !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym81:Q !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym82:R !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym83:S !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym84:T !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym85:U !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym86:V !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym87:W !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym88:X !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym89:Y !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym90:Z !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym91:[ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+
+ .stabs "sym93:] !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym94:^ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym95:_ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym96:` !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym97:a !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym98:b !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym99:c !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym100:d !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym101:e !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym102:f !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym103:g !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym104:h !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym105:i !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym106:j !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym107:k !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym108:l !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym109:m !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym110:n !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym111:o !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym112:p !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym113:q !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym114:r !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym115:s !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym116:t !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym117:u !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym118:v !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym119:w !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym120:x !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym121:y !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym122:z !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym123:{ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym124:| !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym125:} !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "sym126:~ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+
+ .stabs "type33:t33=! !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type35:t35=# !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type36:t36=$ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type37:t37=% !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type38:t38=& !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type39:t39=' !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type40:t40=( !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type41:t41=) !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type42:t42=* !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type43:t43=+ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type44:t44=, !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type45:t45=- !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type46:t46=. !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type47:t47=/ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type48:t48=0 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type49:t49=1 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type50:t50=2 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type51:t51=3 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type52:t52=4 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type53:t53=5 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type54:t54=6 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type55:t55=7 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type56:t56=8 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type57:t57=9 !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type58:t58=: !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type59:t59=; !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type60:t60=< !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type61:t61== !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type62:t62=> !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type63:t63=? !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type64:t64=@ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type65:t65=A !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type66:t66=B !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type67:t67=C !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+
+ .export attr66
+ .data
+ .align 4
+attr66:
+ .long 42
+ .export attr67
+ .data
+ .align 4
+attr67:
+ .long 42
+ .export attr68
+ .data
+ .align 4
+attr68:
+ .long 42
+ .export attr69
+ .data
+ .align 4
+attr69:
+ .long 42
+
+ .stabs "type68:t68=D !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type69:t69=E !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type70:t70=F !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type71:t71=G !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type72:t72=H !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type73:t73=I !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type74:t74=J !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type75:t75=K !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type76:t76=L !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type77:t77=M !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type78:t78=N !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type79:t79=O !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type80:t80=P !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type81:t81=Q !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type82:t82=R !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type83:t83=S !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type84:t84=T !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type85:t85=U !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type86:t86=V !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type87:t87=W !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+
+ .stabs "attr69:G369=@E !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr70:G370=@F !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr71:G371=@G !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+
+ .stabs "type88:t88=X !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type89:t89=Y !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type90:t90=Z !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type91:t91=[ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+
+ .stabs "type93:t93=] !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type94:t94=^ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type95:t95=_ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type96:t96=` !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type97:t97=a !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type98:t98=b !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type99:t99=c !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type100:t100=d !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type101:t101=e !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type102:t102=f !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type103:t103=g !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type104:t104=h !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type105:t105=i !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type106:t106=j !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type107:t107=k !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type108:t108=l !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type109:t109=m !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type110:t110=n !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type111:t111=o !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type112:t112=p !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type113:t113=q !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type114:t114=r !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type115:t115=s !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type116:t116=t !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type117:t117=u !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type118:t118=v !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type119:t119=w !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type120:t120=x !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type121:t121=y !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type122:t122=z !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type123:t123={ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type124:t124=| !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type125:t125=} !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type126:t126=~ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+
+ .stabs "attr32:G332=@ !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr33:G333=@! !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr35:G334=@# !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+
+ .stabs "primary:G200=ered:0,green:1,blue:2,;", 0x20,0,0, 0
+
+ .stabs "attr36:G335=@$ !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+
+ .export primary
+ .data
+ .align 4
+primary:
+ .long 42
+
+ .stabs "attr37:G337=@% !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+
+ .stabs "const69:c=e1,69", 0x80,0,0, 0
+
+ .stabs "const70:c=e190=bs2;0;16;,70", 0x80,0,0, 0
+
+ .stabs "attr38:G338=@& !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+
+ .stabs "bad_neg0type:t201=s8field0:1,0,32;field2:-534,32,64;field3:-1,96,32;;", 0x80,0,0, 0
+
+ .stabs "bad_neg0:G201", 0x20,0,0, 0
+
+ .export bad_neg0
+ .data
+ .align 4
+bad_neg0:
+ .long 42
+ .long 43, 44, 45
+
+ .stabs "attr39:G339=@' !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr41:G341=@) !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr42:G342=@* !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr43:G343=@+ !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr44:G344=@, !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr46:G346=@. !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr47:G347=@/ !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr58:G358=@: !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+
+ .stabs "attr59:G359=@;@ !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+
+ .stabs "attr60:G360=@< !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr61:G361=@= !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr62:G362=@> !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr63:G363=@? !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr64:G364=@@ !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr65:G365=@A !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr66:G366=@B !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr67:G367=@C !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr68:G368=@D !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr72:G372=@H !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr73:G373=@I !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr74:G374=@J !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr75:G375=@K !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr76:G376=@L !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr77:G377=@M !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr78:G378=@N !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr79:G379=@O !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr80:G380=@P !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr81:G381=@Q !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr82:G382=@R !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr83:G383=@S !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr84:G384=@T !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr85:G385=@U !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr86:G386=@V !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr87:G387=@W !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr88:G388=@X !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr89:G389=@Y !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr90:G390=@Z !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr91:G391=@[ !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+
+ .stabs "attr93:G393=@] !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+
+
+ .export _common0
+ .data
+ .align 4
+_common0:
+ .long 42
+ .long 24
+ .long 22
+ .export common0
+ .data
+ .align 4
+common0:
+ .long 42
+ .long 24
+ .long 22
+ .stabs "common0",0xe2,0,0,0
+ .stabs "common0var0:S1", 0x20,0,0, 0
+ .stabs "common0var1:S1", 0x20,0,0, 4
+ .stabs "common0var2:S1", 0x20,0,0, 8
+ .stabs "common0",0xe4,0,0,0
+
+ .stabs "attr94:G394=@^ !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr95:G395=@_ !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr100:G400=@d !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr101:G401=@e !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr102:G402=@f !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr103:G403=@g !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr106:G406=@j !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr107:G407=@k !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr108:G408=@l !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr109:G409=@m !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr110:G410=@n !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr111:G411=@o !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr112:G412=@p !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr113:G413=@q !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr114:G414=@r !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr115:G415=@s !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr116:G416=@t !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr117:G417=@u !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr118:G418=@v !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr119:G419=@w !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr120:G420=@x !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr121:G421=@y !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr122:G422=@z !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr123:G423=@{ !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr124:G424=@| !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr125:G425=@} !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+ .stabs "attr126:G426=@~ !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
+
+ .export attr32
+ .data
+ .align 4
+attr32:
+ .long 42
+ .export attr33
+ .data
+ .align 4
+attr33:
+ .long 42
+ .export attr35
+ .data
+ .align 4
+attr35:
+ .long 42
+ .export attr36
+ .data
+ .align 4
+attr36:
+ .long 42
+ .export attr37
+ .data
+ .align 4
+attr37:
+ .long 42
+ .export attr38
+ .data
+ .align 4
+attr38:
+ .long 42
+ .export attr39
+ .data
+ .align 4
+attr39:
+ .long 42
+ .export attr41
+ .data
+ .align 4
+attr41:
+ .long 42
+ .export attr42
+ .data
+ .align 4
+attr42:
+ .long 42
+ .export attr43
+ .data
+ .align 4
+attr43:
+ .long 42
+ .export attr44
+ .data
+ .align 4
+attr44:
+ .long 42
+ .export attr46
+ .data
+ .align 4
+attr46:
+ .long 42
+ .export attr47
+ .data
+ .align 4
+attr47:
+ .long 42
+ .export attr58
+ .data
+ .align 4
+attr58:
+ .long 42
+ .export attr59
+ .data
+ .align 4
+attr59:
+ .long 42
+ .export attr60
+ .data
+ .align 4
+attr60:
+ .long 42
+ .export attr61
+ .data
+ .align 4
+attr61:
+ .long 42
+ .export attr62
+ .data
+ .align 4
+attr62:
+ .long 42
+ .export attr63
+ .data
+ .align 4
+attr63:
+ .long 42
+ .export attr64
+ .data
+ .align 4
+attr64:
+ .long 42
+ .export attr65
+ .data
+ .align 4
+attr65:
+ .long 42
+ .export attr70
+ .data
+ .align 4
+attr70:
+ .long 42
+ .export attr71
+ .data
+ .align 4
+attr71:
+ .long 42
+ .export attr72
+ .data
+ .align 4
+attr72:
+ .long 42
+ .export attr73
+ .data
+ .align 4
+attr73:
+ .long 42
+ .export attr74
+ .data
+ .align 4
+attr74:
+ .long 42
+ .export attr75
+ .data
+ .align 4
+attr75:
+ .long 42
+ .export attr76
+ .data
+ .align 4
+attr76:
+ .long 42
+ .export attr77
+ .data
+ .align 4
+attr77:
+ .long 42
+ .export attr78
+ .data
+ .align 4
+attr78:
+ .long 42
+ .export attr79
+ .data
+ .align 4
+attr79:
+ .long 42
+ .export attr80
+ .data
+ .align 4
+attr80:
+ .long 42
+ .export attr81
+ .data
+ .align 4
+attr81:
+ .long 42
+ .export attr82
+ .data
+ .align 4
+attr82:
+ .long 42
+ .export attr83
+ .data
+ .align 4
+attr83:
+ .long 42
+ .export attr84
+ .data
+ .align 4
+attr84:
+ .long 42
+
+ .stabs "float72type:t202=R87;9;", 0x80,0,0, 0
+
+ .stabs "int256var:G203=bu32;0;256;", 0x20,0,0, 0
+ .export int256var
+ .data
+ .align 4
+int256var:
+ .long 42
+ .long 0x2b, 0x2c, 0x2d, 0x2d, 0x2c, 0x2b, 0x2a
+
+
+ .stabs "consth:c=e1,4294967296", 0x80,0,0, 0
+
+ .stabs "consth2:c=e1,-734723985732642758928475678987234563284937456", 0x80,0,0, 0
+
+ .stabs "bad_neg0const:c=S201,128,128,11222211343434345656565677888877", 0x80,0,0, 0
+
+ .stabs "bad_type0:t(-3,7)", 0x80,0,0, 0
+ .stabs "bad_type1:t(42,6)", 0x80,0,0, 0
+
+ .stabs "array_index0:t205=r1;0;5;", 0x80,0,0, 0
+ .stabs "array0:G206=a205;1", 0x20,0,0, 0
+ .export array0
+ .data
+ .align 4
+array0:
+ .long 42
+ .long 43, 44, 45, 46, 47
+
+ .stabs "array_index1:t207=", 0x80,0,0, 0
+ .stabs "array1:G208=aeai1_red:0,ai1_green:1,ai1_blue:2,;;1", 0x20,0,0, 0
+ .export array1
+ .data
+ .align 4
+array1:
+ .long 42
+ .long 43, 44
+
+ .stabs "inttype_one:t209=1", 0x80,0,0, 0
+ .stabs "inttype_two:t210=1", 0x80,0,0, 0
+ .stabs "one_var:G209", 0x20,0,0, 0
+ .export one_var
+ .data
+ .align 4
+one_var:
+ .long 42
+ .stabs "two_var:G210", 0x20,0,0, 0
+ .export two_var
+ .data
+ .align 4
+two_var:
+ .long 42
+
+ .stabs "intp:t211=*1", 0x80,0,0, 0
+ .stabs "pointer_to_int_var:G212=*1", 0x80,0,0, 0
+ .stabs "intp_var:G211", 0x20,0,0, 0
+ .export intp_var
+ .data
+ .align 4
+intp_var:
+ .long 42
+
+ .stabs "unrecog_const:c=xjksdflskd33,4;473;", 0x80,0,0, 0
+
+ .export attr85
+ .data
+ .align 4
+attr85:
+ .long 42
+ .export attr86
+ .data
+ .align 4
+attr86:
+ .long 42
+ .export attr87
+ .data
+ .align 4
+attr87:
+ .long 42
+ .export attr88
+ .data
+ .align 4
+attr88:
+ .long 42
+ .export attr89
+ .data
+ .align 4
+attr89:
+ .long 42
+ .export attr90
+ .data
+ .align 4
+attr90:
+ .long 42
+ .export attr91
+ .data
+ .align 4
+attr91:
+ .long 42
+ .export attr92
+ .data
+ .align 4
+attr92:
+ .long 42
+ .export attr93
+ .data
+ .align 4
+attr93:
+ .long 42
+ .export attr94
+ .data
+ .align 4
+attr94:
+ .long 42
+ .export attr95
+ .data
+ .align 4
+attr95:
+ .long 42
+ .export attr96
+ .data
+ .align 4
+attr96:
+ .long 42
+ .export attr97
+ .data
+ .align 4
+attr97:
+ .long 42
+ .export attr98
+ .data
+ .align 4
+attr98:
+ .long 42
+ .export attr99
+ .data
+ .align 4
+attr99:
+ .long 42
+ .export attr100
+ .data
+ .align 4
+attr100:
+ .long 42
+ .export attr101
+ .data
+ .align 4
+attr101:
+ .long 42
+ .export attr102
+ .data
+ .align 4
+attr102:
+ .long 42
+ .export attr103
+ .data
+ .align 4
+attr103:
+ .long 42
+ .export attr104
+ .data
+ .align 4
+attr104:
+ .long 42
+ .export attr105
+ .data
+ .align 4
+attr105:
+ .long 42
+ .export attr106
+ .data
+ .align 4
+attr106:
+ .long 42
+ .export attr107
+ .data
+ .align 4
+attr107:
+ .long 42
+ .export attr108
+ .data
+ .align 4
+attr108:
+ .long 42
+ .export attr109
+ .data
+ .align 4
+attr109:
+ .long 42
+ .export attr110
+ .data
+ .align 4
+attr110:
+ .long 42
+ .export attr111
+ .data
+ .align 4
+attr111:
+ .long 42
+ .export attr112
+ .data
+ .align 4
+attr112:
+ .long 42
+ .export attr113
+ .data
+ .align 4
+attr113:
+ .long 42
+ .export attr114
+ .data
+ .align 4
+attr114:
+ .long 42
+ .export attr115
+ .data
+ .align 4
+attr115:
+ .long 42
+ .export attr116
+ .data
+ .align 4
+attr116:
+ .long 42
+ .export attr117
+ .data
+ .align 4
+attr117:
+ .long 42
+ .export attr118
+ .data
+ .align 4
+attr118:
+ .long 42
+ .export attr119
+ .data
+ .align 4
+attr119:
+ .long 42
+ .export attr120
+ .data
+ .align 4
+attr120:
+ .long 42
+ .export attr121
+ .data
+ .align 4
+attr121:
+ .long 42
+ .export attr125
+ .data
+ .align 4
+attr125:
+ .long 42
+ .export attr126
+ .data
+ .align 4
+attr126:
+ .long 42
+
+ .stabs "var1:G301=@s32;1",0x20,0,0, 0
+ .export var1
+ .data
+ .align 4
+var1:
+ .long 42
+ .stabs "var2:G302=@p42;1",0x20,0,0, 0
+ .export var2
+ .data
+ .align 4
+var2:
+ .long 42
+ .stabs "var3:G303=@P;1",0x20,0,0, 0
+ .export var3
+ .data
+ .align 4
+var3:
+ .long 42
+
+
+
+
+
+
+
+
+
+
+
+
+ .stabs "v_comb:G448=s24!2,020,445=s12!1,120,444=s4x:1,0,32;;;$vb444:446=*444,0;a:/01,32,32;;;0264,447=s12!1,120,444;$vb444:446,0;b:/01,32,32;;;comb:/01,128,32;;", 0x20,0,0, 0
+
+ .export v_comb
+ .align 1
+v_comb:
+ .long v_comb_shared
+ .long 43
+ .long v_comb_shared
+ .long 44
+ .long 45
+v_comb_shared:
+ .long 42
+
+ .stabs "sym92:\\ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "type92:t92=\\ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",0x80,0,0,0
+ .stabs "attr92:G392=@\\ !#$%&'()*+,-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~;1",0x20,0,0, 0
diff --git a/gas/testsuite/gas/hppa/parse/align1.s b/gas/testsuite/gas/hppa/parse/align1.s
new file mode 100644
index 0000000000..df81e96dee
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/align1.s
@@ -0,0 +1,41 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 1
+ .align 8
+ nop
+; "8" assumed if no alignment given.
+ .align
+ nop
+ .align 4096
+ nop
+
+
+ .SPACE $PRIVATE$
+ .SUBSPA $BSS$
+
+ .ALIGN 8
+$L00BSS:
+home_buff:
+ .BLOCK 1024
+ .ALIGN 8
+current_buff:
+ .BLOCK 1024
+ .ALIGN 4
+lock_file:
+ .BLOCK 4
+ .ALIGN 8
+L332.name:
+ .BLOCK 30
+ .ALIGN 4
+L352.last_case_wa:
+ .BLOCK 4
+
+
diff --git a/gas/testsuite/gas/hppa/parse/align2.s b/gas/testsuite/gas/hppa/parse/align2.s
new file mode 100644
index 0000000000..af734c8139
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/align2.s
@@ -0,0 +1,15 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 3
+
+
+
+
diff --git a/gas/testsuite/gas/hppa/parse/appbug.s b/gas/testsuite/gas/hppa/parse/appbug.s
new file mode 100644
index 0000000000..7a37f9ee57
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/appbug.s
@@ -0,0 +1 @@
+# 1 "crt0.s"
diff --git a/gas/testsuite/gas/hppa/parse/badfmpyadd.s b/gas/testsuite/gas/hppa/parse/badfmpyadd.s
new file mode 100644
index 0000000000..fd1c1f813c
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/badfmpyadd.s
@@ -0,0 +1,33 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .IMPORT $global$,DATA
+ .IMPORT $$dyncall,MILLICODE
+; gcc_compiled.:
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .EXPORT foobar,ENTRY,PRIV_LEV=3,ARGW0=FR,ARGW1=FU,ARGW2=FR,ARGW3=FU,RTNVAL=FR
+foobar
+ .PROC
+ .CALLINFO FRAME=0,NO_CALLS
+ .ENTRY
+ ldo -64(%r30),%r20
+ addil LR'x-$global$,%r27
+ fldds 8(%r20),%fr4
+ fldds 0(%r20),%fr22
+ ldo RR'x-$global$(%r1),%r19
+ fmpysub,sgl %fr5L,%fr7L,%fr5L,%fr22L,%fr4L
+ bv %r0(%r2)
+ fstds %fr5,0(%r19)
+ .EXIT
+ .PROCEND
+ .SPACE $PRIVATE$
+ .SUBSPA $BSS$
+
+x .comm 8
+y .comm 8
diff --git a/gas/testsuite/gas/hppa/parse/block1.s b/gas/testsuite/gas/hppa/parse/block1.s
new file mode 100644
index 0000000000..317699f1c8
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/block1.s
@@ -0,0 +1,18 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $DATA$
+
+foo:
+ .block
+bar:
+ .block 0x7fffffff
+com:
+
+
+
diff --git a/gas/testsuite/gas/hppa/parse/block2.s b/gas/testsuite/gas/hppa/parse/block2.s
new file mode 100644
index 0000000000..1a3b5f14ed
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/block2.s
@@ -0,0 +1,15 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $DATA$
+
+foo:
+ .block -1
+
+
+
diff --git a/gas/testsuite/gas/hppa/parse/calldatabug.s b/gas/testsuite/gas/hppa/parse/calldatabug.s
new file mode 100644
index 0000000000..6c80cf4677
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/calldatabug.s
@@ -0,0 +1,189 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .IMPORT $global$,DATA
+ .IMPORT $$dyncall,MILLICODE
+; gcc_compiled.:
+ .IMPORT printf,CODE
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+LC$0000:
+ .STRING "%d %lf %d\x0a\x00"
+ .align 4
+ .EXPORT error__3AAAiidi
+ .EXPORT error__3AAAiidi,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=FR,ARGW4=FU,RTNVAL=GR
+error__3AAAiidi:
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,128(%r30)
+ stw %r9,8(%r4)
+ stw %r8,12(%r4)
+ stw %r7,16(%r4)
+ stw %r6,20(%r4)
+ stw %r5,24(%r4)
+ copy %r26,%r5
+ ldo -8(%r0),%r6
+ ldo -32(%r4),%r19
+ add %r19,%r6,%r7
+ stw %r25,0(%r7)
+ ldo -12(%r0),%r8
+ ldo -32(%r4),%r19
+ add %r19,%r8,%r9
+ stw %r24,0(%r9)
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -24(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldo -28(%r0),%r21
+ ldo -32(%r4),%r22
+ add %r22,%r21,%r21
+ ldw 0(%r21),%r22
+ stw %r22,-52(%r30)
+ ldil L'LC$0000,%r26
+ ldo R'LC$0000(%r26),%r26
+ ldw 0(%r19),%r25
+ fldds 0(%r20),%fr7
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=FR,ARGW3=FU
+ bl printf,%r2
+ nop
+ bl,n L$0002,%r0
+ bl,n L$0001,%r0
+L$0002:
+L$0001:
+ ldw 8(%r4),%r9
+ ldw 12(%r4),%r8
+ ldw 16(%r4),%r7
+ ldw 20(%r4),%r6
+ ldw 24(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .align 4
+ .EXPORT ok__3AAAidi
+ .EXPORT ok__3AAAidi,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=FR,ARGW3=FU,RTNVAL=GR
+ok__3AAAidi:
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,128(%r30)
+ stw %r9,8(%r4)
+ stw %r8,12(%r4)
+ stw %r7,16(%r4)
+ stw %r6,20(%r4)
+ stw %r5,24(%r4)
+ copy %r26,%r5
+ ldo -8(%r0),%r6
+ ldo -32(%r4),%r19
+ add %r19,%r6,%r7
+ stw %r25,0(%r7)
+ ldo -16(%r0),%r8
+ ldo -32(%r4),%r19
+ add %r19,%r8,%r9
+ fstds %fr7,0(%r9)
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -16(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldo -20(%r0),%r21
+ ldo -32(%r4),%r22
+ add %r22,%r21,%r21
+ ldw 0(%r21),%r22
+ stw %r22,-52(%r30)
+ ldil L'LC$0000,%r26
+ ldo R'LC$0000(%r26),%r26
+ ldw 0(%r19),%r25
+ fldds 0(%r20),%fr7
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=FR,ARGW3=FU
+ bl printf,%r2
+ nop
+ bl,n L$0004,%r0
+ bl,n L$0003,%r0
+L$0004:
+L$0003:
+ ldw 8(%r4),%r9
+ ldw 12(%r4),%r8
+ ldw 16(%r4),%r7
+ ldw 20(%r4),%r6
+ ldw 24(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .IMPORT __main,CODE
+ .align 8
+LC$0001:
+ ; .double 5.50000000000000000000e+00
+ .word 1075183616 ; = 0x40160000
+ .word 0 ; = 0x0
+ .align 4
+ .EXPORT main
+ .EXPORT main,PRIV_LEV=3,RTNVAL=GR
+main:
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,128(%r30)
+ .CALL
+ bl __main,%r2
+ nop
+ ldo -24(%r0),%r19
+ ldo -32(%r30),%r20
+ add %r20,%r19,%r19
+ ldil L'LC$0001,%r20
+ ldo R'LC$0001(%r20),%r21
+ ldw 0(%r21),%r22
+ ldw 4(%r21),%r23
+ stw %r22,0(%r19)
+ stw %r23,4(%r19)
+ ldo 3(%r0),%r19
+ stw %r19,-60(%r30)
+ ldo 8(%r4),%r26
+ ldo 1(%r0),%r25
+ ldo 4(%r0),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl error__3AAAiidi,%r2
+ nop
+ ldo 3(%r0),%r19
+ stw %r19,-52(%r30)
+ ldo 8(%r4),%r26
+ ldo 1(%r0),%r25
+ ldil L'LC$0001,%r19
+ ldo R'LC$0001(%r19),%r20
+ fldds 0(%r20),%fr7
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=FR,ARGW3=FU
+ bl ok__3AAAidi,%r2
+ nop
+ copy %r0,%r28
+ bl,n L$0005,%r0
+ bl,n L$0005,%r0
+L$0005:
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+
diff --git a/gas/testsuite/gas/hppa/parse/callinfobug.s b/gas/testsuite/gas/hppa/parse/callinfobug.s
new file mode 100644
index 0000000000..c08c773606
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/callinfobug.s
@@ -0,0 +1,8 @@
+ .space $TEXT$
+ .subspa $CODE$
+ .align 4
+ .export divu,millicode
+ .proc
+ .callinfo millicode
+divu
+ .procend
diff --git a/gas/testsuite/gas/hppa/parse/defbug.s b/gas/testsuite/gas/hppa/parse/defbug.s
new file mode 100644
index 0000000000..064caf4d3d
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/defbug.s
@@ -0,0 +1,18 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .import _seterrno
+ .export vfork ! .label vfork ! .proc! .callinfo no_calls! .entry ! .label __vfork ! mtsp %r0,%sr0! ldil L%0xc0000004,%r1! ble R%0xc0000004(%sr0,%r1)! ldi 66 ,%r22 ! b,n yyy! b,n __vfork ! b _seterrno! copy %r28,%r26! .label yyy
+ add,= %r0,%r29,%r0
+ copy %r0,%r28
+ bv,n (%r2)
+ .exit
+ .procend
diff --git a/gas/testsuite/gas/hppa/parse/entrybug.s b/gas/testsuite/gas/hppa/parse/entrybug.s
new file mode 100644
index 0000000000..c4fe7a4368
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/entrybug.s
@@ -0,0 +1,24 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .IMPORT $global$,DATA
+ .IMPORT $$dyncall,MILLICODE
+; gcc_compiled.:
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .PARAM foo,RTNVAL=GR
+foo:
+ .PROC
+ .CALLINFO FRAME=128,NO_CALLS,ENTRY_GR=1,ENTRY_FR=11
+ .ENTRY
+ bv,n %r0(%r2)
+ .EXIT
+ .PROCEND
+ .SPACE $TEXT$
+ .SUBSPA $LIT$
+
diff --git a/gas/testsuite/gas/hppa/parse/exportbug.s b/gas/testsuite/gas/hppa/parse/exportbug.s
new file mode 100644
index 0000000000..4966415040
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/exportbug.s
@@ -0,0 +1,14 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .EXPORT main,ENTRY,PRIV_LEV=3,RTNVAL=GR
+
+
diff --git a/gas/testsuite/gas/hppa/parse/exprbug.s b/gas/testsuite/gas/hppa/parse/exprbug.s
new file mode 100644
index 0000000000..07bad422d2
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/exprbug.s
@@ -0,0 +1,39 @@
+ .space $TEXT$
+ .subspa $CODE$
+
+ .align 8
+ .export icode,data
+icode:
+ .proc
+ .callinfo frame=0,no_calls
+ .entry
+ bv,n %r0(%r2)
+ .exit
+ nop
+ .procend
+
+ ;
+ ; FIRST, argv array of pointers to args, 1st is same as path.
+ ;
+ .align 8
+ic_argv:
+ .word ic_argv1-icode ; second, pointer to 1st argument
+ .word ic_path-icode ; first, pointer to init path
+ .word 0 ; fourth, NULL argv terminator (pad)
+ .word 0 ; third, NULL argv terminator
+
+ic_path:
+ .blockz 4096 ; must be multiple of 4 bytes
+ .word 0 ; in case full string is used
+ .word 0 ; this will be the string terminator
+
+ic_argv1:
+ .blockz 4096 ; must be multiple of 4 bytes
+ .word 0 ; in case full string is used
+ .word 0 ; this will be the string terminator
+
+ .export szicode,data
+szicode:
+ .word szicode-icode
+ .word 0 ; must have at least one filler at end
+
diff --git a/gas/testsuite/gas/hppa/parse/fixup7bug.s b/gas/testsuite/gas/hppa/parse/fixup7bug.s
new file mode 100644
index 0000000000..23c8740c62
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/fixup7bug.s
@@ -0,0 +1,6192 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .IMPORT $global$,DATA
+ .IMPORT $$dyncall,MILLICODE
+; gcc_compiled.:
+ .IMPORT xmalloc,CODE
+ .IMPORT _obstack_newchunk,CODE
+ .IMPORT memset,CODE
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .EXPORT alloc_type,CODE
+ .EXPORT alloc_type,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR
+alloc_type:
+ .PROC
+ .CALLINFO FRAME=192,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,192(%r30)
+ stw %r7,32(%r4)
+ stw %r6,36(%r4)
+ stw %r5,40(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ comiclr,= 0,%r20,%r0
+ bl L$0002,%r0
+ nop
+ ldo 52(%r0),%r26
+ .CALL ARGW0=GR
+ bl xmalloc,%r2
+ nop
+ copy %r28,%r7
+ bl,n L$0003,%r0
+L$0002:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldo 120(%r19),%r20
+ stw %r20,8(%r4)
+ ldw 8(%r4),%r19
+ stw %r19,12(%r4)
+ ldo 52(%r0),%r19
+ stw %r19,16(%r4)
+ ldw 12(%r4),%r19
+ ldw 12(%r4),%r20
+ ldw 16(%r19),%r19
+ ldw 12(%r20),%r20
+ sub %r19,%r20,%r19
+ ldw 16(%r4),%r20
+ comclr,< %r19,%r20,%r0
+ bl L$0004,%r0
+ nop
+ ldw 12(%r4),%r26
+ ldw 16(%r4),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl _obstack_newchunk,%r2
+ nop
+ copy %r0,%r19
+ bl,n L$0005,%r0
+L$0004:
+ copy %r0,%r19
+L$0005:
+ ldw 12(%r4),%r19
+ ldw 12(%r4),%r20
+ ldw 12(%r20),%r21
+ ldw 16(%r4),%r22
+ add %r21,%r22,%r20
+ copy %r20,%r21
+ stw %r21,12(%r19)
+ ldw 8(%r4),%r19
+ stw %r19,20(%r4)
+ ldw 20(%r4),%r19
+ ldw 8(%r19),%r20
+ stw %r20,24(%r4)
+ ldw 20(%r4),%r19
+ ldw 12(%r19),%r20
+ ldw 24(%r4),%r19
+ comclr,= %r20,%r19,%r0
+ bl L$0006,%r0
+ nop
+ ldw 20(%r4),%r19
+ ldw 40(%r19),%r20
+ copy %r20,%r21
+ depi -1,1,1,%r21
+ stw %r21,40(%r19)
+L$0006:
+ ldw 20(%r4),%r19
+ ldw 20(%r4),%r20
+ ldw 20(%r4),%r21
+ ldw 12(%r20),%r20
+ ldw 24(%r21),%r21
+ add %r20,%r21,%r20
+ ldw 20(%r4),%r21
+ ldw 24(%r21),%r22
+ uaddcm %r0,%r22,%r21
+ and %r20,%r21,%r20
+ copy %r20,%r21
+ stw %r21,12(%r19)
+ ldw 20(%r4),%r19
+ ldw 20(%r4),%r20
+ ldw 12(%r19),%r19
+ ldw 4(%r20),%r20
+ sub %r19,%r20,%r19
+ ldw 20(%r4),%r20
+ ldw 20(%r4),%r21
+ ldw 16(%r20),%r20
+ ldw 4(%r21),%r21
+ sub %r20,%r21,%r20
+ comclr,> %r19,%r20,%r0
+ bl L$0007,%r0
+ nop
+ ldw 20(%r4),%r19
+ ldw 20(%r4),%r20
+ ldw 16(%r20),%r21
+ stw %r21,12(%r19)
+ copy %r21,%r19
+ bl,n L$0008,%r0
+L$0007:
+ copy %r0,%r19
+L$0008:
+ ldw 20(%r4),%r19
+ ldw 20(%r4),%r20
+ ldw 12(%r20),%r21
+ stw %r21,8(%r19)
+ ldw 24(%r4),%r7
+L$0003:
+ copy %r7,%r26
+ copy %r0,%r25
+ ldo 52(%r0),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl memset,%r2
+ nop
+ stw %r0,0(%r7)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,12(%r7)
+ ldo -1(%r0),%r19
+ stw %r19,44(%r7)
+ copy %r7,%r28
+ bl,n L$0001,%r0
+L$0001:
+ ldw 32(%r4),%r7
+ ldw 36(%r4),%r6
+ ldw 40(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .align 4
+ .EXPORT make_pointer_type,CODE
+ .EXPORT make_pointer_type,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,RTNVAL=GR
+make_pointer_type:
+ .PROC
+ .CALLINFO FRAME=192,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,192(%r30)
+ stw %r9,16(%r4)
+ stw %r8,20(%r4)
+ stw %r7,24(%r4)
+ stw %r6,28(%r4)
+ stw %r5,32(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -8(%r0),%r7
+ ldo -32(%r4),%r19
+ add %r19,%r7,%r8
+ stw %r25,0(%r8)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 20(%r19),%r9
+ comiclr,<> 0,%r9,%r0
+ bl L$0010,%r0
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ comiclr,= 0,%r20,%r0
+ bl L$0011,%r0
+ nop
+ copy %r9,%r28
+ bl,n L$0009,%r0
+ bl,n L$0012,%r0
+L$0011:
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 0(%r19),%r20
+ comiclr,= 0,%r20,%r0
+ bl L$0013,%r0
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ stw %r9,0(%r19)
+ copy %r9,%r28
+ bl,n L$0009,%r0
+L$0013:
+L$0012:
+L$0010:
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0015,%r0
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 0(%r19),%r20
+ comiclr,= 0,%r20,%r0
+ bl L$0014,%r0
+ nop
+ bl,n L$0015,%r0
+L$0015:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 12(%r19),%r26
+ .CALL ARGW0=GR
+ bl alloc_type,%r2
+ nop
+ copy %r28,%r9
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0016,%r0
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ stw %r9,0(%r19)
+L$0016:
+ bl,n L$0017,%r0
+L$0014:
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 0(%r19),%r9
+ ldw 12(%r9),%r19
+ stw %r19,8(%r4)
+ copy %r9,%r26
+ copy %r0,%r25
+ ldo 52(%r0),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl memset,%r2
+ nop
+ ldw 8(%r4),%r19
+ stw %r19,12(%r9)
+L$0017:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,16(%r9)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ stw %r9,20(%r19)
+ ldo 4(%r0),%r19
+ stw %r19,8(%r9)
+ ldo 1(%r0),%r19
+ stw %r19,0(%r9)
+ ldh 32(%r9),%r19
+ copy %r19,%r20
+ depi -1,31,1,%r20
+ sth %r20,32(%r9)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 20(%r19),%r20
+ comiclr,= 0,%r20,%r0
+ bl L$0018,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ stw %r9,20(%r19)
+L$0018:
+ copy %r9,%r28
+ bl,n L$0009,%r0
+L$0009:
+ ldw 16(%r4),%r9
+ ldw 20(%r4),%r8
+ ldw 24(%r4),%r7
+ ldw 28(%r4),%r6
+ ldw 32(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .align 4
+ .EXPORT lookup_pointer_type,CODE
+ .EXPORT lookup_pointer_type,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR
+lookup_pointer_type:
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,128(%r30)
+ stw %r6,8(%r4)
+ stw %r5,12(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r26
+ copy %r0,%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl make_pointer_type,%r2
+ nop
+ bl,n L$0019,%r0
+L$0019:
+ ldw 8(%r4),%r6
+ ldw 12(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .align 4
+ .EXPORT make_reference_type,CODE
+ .EXPORT make_reference_type,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,RTNVAL=GR
+make_reference_type:
+ .PROC
+ .CALLINFO FRAME=192,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,192(%r30)
+ stw %r9,16(%r4)
+ stw %r8,20(%r4)
+ stw %r7,24(%r4)
+ stw %r6,28(%r4)
+ stw %r5,32(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -8(%r0),%r7
+ ldo -32(%r4),%r19
+ add %r19,%r7,%r8
+ stw %r25,0(%r8)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 24(%r19),%r9
+ comiclr,<> 0,%r9,%r0
+ bl L$0021,%r0
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ comiclr,= 0,%r20,%r0
+ bl L$0022,%r0
+ nop
+ copy %r9,%r28
+ bl,n L$0020,%r0
+ bl,n L$0023,%r0
+L$0022:
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 0(%r19),%r20
+ comiclr,= 0,%r20,%r0
+ bl L$0024,%r0
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ stw %r9,0(%r19)
+ copy %r9,%r28
+ bl,n L$0020,%r0
+L$0024:
+L$0023:
+L$0021:
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0026,%r0
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 0(%r19),%r20
+ comiclr,= 0,%r20,%r0
+ bl L$0025,%r0
+ nop
+ bl,n L$0026,%r0
+L$0026:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 12(%r19),%r26
+ .CALL ARGW0=GR
+ bl alloc_type,%r2
+ nop
+ copy %r28,%r9
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0027,%r0
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ stw %r9,0(%r19)
+L$0027:
+ bl,n L$0028,%r0
+L$0025:
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 0(%r19),%r9
+ ldw 12(%r9),%r19
+ stw %r19,8(%r4)
+ copy %r9,%r26
+ copy %r0,%r25
+ ldo 52(%r0),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl memset,%r2
+ nop
+ ldw 8(%r4),%r19
+ stw %r19,12(%r9)
+L$0028:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,16(%r9)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ stw %r9,24(%r19)
+ ldo 4(%r0),%r19
+ stw %r19,8(%r9)
+ ldo 16(%r0),%r19
+ stw %r19,0(%r9)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 24(%r19),%r20
+ comiclr,= 0,%r20,%r0
+ bl L$0029,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ stw %r9,24(%r19)
+L$0029:
+ copy %r9,%r28
+ bl,n L$0020,%r0
+L$0020:
+ ldw 16(%r4),%r9
+ ldw 20(%r4),%r8
+ ldw 24(%r4),%r7
+ ldw 28(%r4),%r6
+ ldw 32(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .align 4
+ .EXPORT lookup_reference_type,CODE
+ .EXPORT lookup_reference_type,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR
+lookup_reference_type:
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,128(%r30)
+ stw %r6,8(%r4)
+ stw %r5,12(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r26
+ copy %r0,%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl make_reference_type,%r2
+ nop
+ bl,n L$0030,%r0
+L$0030:
+ ldw 8(%r4),%r6
+ ldw 12(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .align 4
+ .EXPORT make_function_type,CODE
+ .EXPORT make_function_type,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,RTNVAL=GR
+make_function_type:
+ .PROC
+ .CALLINFO FRAME=192,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,192(%r30)
+ stw %r9,16(%r4)
+ stw %r8,20(%r4)
+ stw %r7,24(%r4)
+ stw %r6,28(%r4)
+ stw %r5,32(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -8(%r0),%r7
+ ldo -32(%r4),%r19
+ add %r19,%r7,%r8
+ stw %r25,0(%r8)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 28(%r19),%r9
+ comiclr,<> 0,%r9,%r0
+ bl L$0032,%r0
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ comiclr,= 0,%r20,%r0
+ bl L$0033,%r0
+ nop
+ copy %r9,%r28
+ bl,n L$0031,%r0
+ bl,n L$0034,%r0
+L$0033:
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 0(%r19),%r20
+ comiclr,= 0,%r20,%r0
+ bl L$0035,%r0
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ stw %r9,0(%r19)
+ copy %r9,%r28
+ bl,n L$0031,%r0
+L$0035:
+L$0034:
+L$0032:
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0037,%r0
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 0(%r19),%r20
+ comiclr,= 0,%r20,%r0
+ bl L$0036,%r0
+ nop
+ bl,n L$0037,%r0
+L$0037:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 12(%r19),%r26
+ .CALL ARGW0=GR
+ bl alloc_type,%r2
+ nop
+ copy %r28,%r9
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0038,%r0
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ stw %r9,0(%r19)
+L$0038:
+ bl,n L$0039,%r0
+L$0036:
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 0(%r19),%r9
+ ldw 12(%r9),%r19
+ stw %r19,8(%r4)
+ copy %r9,%r26
+ copy %r0,%r25
+ ldo 52(%r0),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl memset,%r2
+ nop
+ ldw 8(%r4),%r19
+ stw %r19,12(%r9)
+L$0039:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,16(%r9)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ stw %r9,28(%r19)
+ ldo 1(%r0),%r19
+ stw %r19,8(%r9)
+ ldo 6(%r0),%r19
+ stw %r19,0(%r9)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 28(%r19),%r20
+ comiclr,= 0,%r20,%r0
+ bl L$0040,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ stw %r9,28(%r19)
+L$0040:
+ copy %r9,%r28
+ bl,n L$0031,%r0
+L$0031:
+ ldw 16(%r4),%r9
+ ldw 20(%r4),%r8
+ ldw 24(%r4),%r7
+ ldw 28(%r4),%r6
+ ldw 32(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .align 4
+ .EXPORT lookup_function_type,CODE
+ .EXPORT lookup_function_type,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR
+lookup_function_type:
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,128(%r30)
+ stw %r6,8(%r4)
+ stw %r5,12(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r26
+ copy %r0,%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl make_function_type,%r2
+ nop
+ bl,n L$0041,%r0
+L$0041:
+ ldw 8(%r4),%r6
+ ldw 12(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .IMPORT smash_to_member_type,CODE
+ .align 4
+ .EXPORT lookup_member_type,CODE
+ .EXPORT lookup_member_type,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,RTNVAL=GR
+lookup_member_type:
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,128(%r30)
+ stw %r8,8(%r4)
+ stw %r7,12(%r4)
+ stw %r6,16(%r4)
+ stw %r5,20(%r4)
+ ldo 24(%r4),%r1
+ fstds,ma %fr12,8(%r1)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -8(%r0),%r7
+ ldo -32(%r4),%r19
+ add %r19,%r7,%r8
+ stw %r25,0(%r8)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 12(%r19),%r26
+ .CALL ARGW0=GR
+ bl alloc_type,%r2
+ nop
+ stw %r28,-16(%r30)
+ fldws -16(%r30),%fr12
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ fstws %fr12,-16(%r30)
+ ldw -16(%r30),%r26
+ ldw 0(%r19),%r25
+ ldw 0(%r20),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl smash_to_member_type,%r2
+ nop
+ fstws %fr12,-16(%r30)
+ ldw -16(%r30),%r28
+ bl,n L$0042,%r0
+L$0042:
+ ldw 8(%r4),%r8
+ ldw 12(%r4),%r7
+ ldw 16(%r4),%r6
+ ldw 20(%r4),%r5
+ ldo 24(%r4),%r1
+ fldds,ma 8(%r1),%fr12
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .align 4
+ .EXPORT allocate_stub_method,CODE
+ .EXPORT allocate_stub_method,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR
+allocate_stub_method:
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,128(%r30)
+ stw %r6,16(%r4)
+ stw %r5,20(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 12(%r19),%r26
+ .CALL ARGW0=GR
+ bl alloc_type,%r2
+ nop
+ stw %r28,8(%r4)
+ ldw 8(%r4),%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 0(%r20),%r21
+ stw %r21,16(%r19)
+ ldw 8(%r4),%r19
+ ldo 4(%r0),%r20
+ sth %r20,32(%r19)
+ ldw 8(%r4),%r19
+ ldo 15(%r0),%r20
+ stw %r20,0(%r19)
+ ldw 8(%r4),%r19
+ ldo 1(%r0),%r20
+ stw %r20,8(%r19)
+ ldw 8(%r4),%r28
+ bl,n L$0043,%r0
+L$0043:
+ ldw 16(%r4),%r6
+ ldw 20(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .IMPORT builtin_type_int,DATA
+ .align 4
+ .EXPORT create_array_type,CODE
+ .EXPORT create_array_type,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,RTNVAL=GR
+create_array_type:
+ .PROC
+ .CALLINFO FRAME=192,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,192(%r30)
+ stw %r10,56(%r4)
+ stw %r9,60(%r4)
+ stw %r8,64(%r4)
+ stw %r7,68(%r4)
+ stw %r6,72(%r4)
+ stw %r5,76(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -8(%r0),%r7
+ ldo -32(%r4),%r19
+ add %r19,%r7,%r8
+ stw %r25,0(%r8)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 12(%r19),%r26
+ .CALL ARGW0=GR
+ bl alloc_type,%r2
+ nop
+ stw %r28,8(%r4)
+ ldw 8(%r4),%r19
+ ldo 2(%r0),%r20
+ stw %r20,0(%r19)
+ ldw 8(%r4),%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 0(%r20),%r21
+ stw %r21,16(%r19)
+ ldw 8(%r4),%r19
+ ldo -8(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldo -4(%r0),%r21
+ ldo -32(%r4),%r23
+ add %r23,%r21,%r22
+ ldw 0(%r22),%r21
+ ldw 0(%r20),%r20
+ ldw 8(%r21),%r21
+ stw %r20,-16(%r30)
+ fldws -16(%r30),%fr5
+ stw %r21,-16(%r30)
+ fldws -16(%r30),%fr5R
+ xmpyu %fr5,%fr5R,%fr4
+ fstws %fr4R,-16(%r30)
+ ldw -16(%r30),%r24
+ stw %r24,8(%r19)
+ ldw 8(%r4),%r19
+ ldo 1(%r0),%r20
+ sth %r20,34(%r19)
+ ldw 8(%r4),%r9
+ ldw 8(%r4),%r19
+ ldw 12(%r19),%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0050,%r0
+ nop
+ ldw 8(%r4),%r19
+ ldw 12(%r19),%r20
+ ldo 120(%r20),%r19
+ stw %r19,16(%r4)
+ ldw 16(%r4),%r19
+ stw %r19,20(%r4)
+ ldo 16(%r0),%r19
+ stw %r19,24(%r4)
+ ldw 20(%r4),%r19
+ ldw 20(%r4),%r20
+ ldw 16(%r19),%r19
+ ldw 12(%r20),%r20
+ sub %r19,%r20,%r19
+ ldw 24(%r4),%r20
+ comclr,< %r19,%r20,%r0
+ bl L$0045,%r0
+ nop
+ ldw 20(%r4),%r26
+ ldw 24(%r4),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl _obstack_newchunk,%r2
+ nop
+ copy %r0,%r19
+ bl,n L$0046,%r0
+L$0045:
+ copy %r0,%r19
+L$0046:
+ ldw 20(%r4),%r19
+ ldw 20(%r4),%r20
+ ldw 12(%r20),%r21
+ ldw 24(%r4),%r22
+ add %r21,%r22,%r20
+ copy %r20,%r21
+ stw %r21,12(%r19)
+ ldw 16(%r4),%r19
+ stw %r19,28(%r4)
+ ldw 28(%r4),%r19
+ ldw 8(%r19),%r20
+ stw %r20,32(%r4)
+ ldw 28(%r4),%r19
+ ldw 12(%r19),%r20
+ ldw 32(%r4),%r19
+ comclr,= %r20,%r19,%r0
+ bl L$0047,%r0
+ nop
+ ldw 28(%r4),%r19
+ ldw 40(%r19),%r20
+ copy %r20,%r21
+ depi -1,1,1,%r21
+ stw %r21,40(%r19)
+L$0047:
+ ldw 28(%r4),%r19
+ ldw 28(%r4),%r20
+ ldw 28(%r4),%r21
+ ldw 12(%r20),%r20
+ ldw 24(%r21),%r21
+ add %r20,%r21,%r20
+ ldw 28(%r4),%r21
+ ldw 24(%r21),%r22
+ uaddcm %r0,%r22,%r21
+ and %r20,%r21,%r20
+ copy %r20,%r21
+ stw %r21,12(%r19)
+ ldw 28(%r4),%r19
+ ldw 28(%r4),%r20
+ ldw 12(%r19),%r19
+ ldw 4(%r20),%r20
+ sub %r19,%r20,%r19
+ ldw 28(%r4),%r20
+ ldw 28(%r4),%r21
+ ldw 16(%r20),%r20
+ ldw 4(%r21),%r21
+ sub %r20,%r21,%r20
+ comclr,> %r19,%r20,%r0
+ bl L$0048,%r0
+ nop
+ ldw 28(%r4),%r19
+ ldw 28(%r4),%r20
+ ldw 16(%r20),%r21
+ stw %r21,12(%r19)
+ copy %r21,%r19
+ bl,n L$0049,%r0
+L$0048:
+ copy %r0,%r19
+L$0049:
+ ldw 28(%r4),%r19
+ ldw 28(%r4),%r20
+ ldw 12(%r20),%r21
+ stw %r21,8(%r19)
+ ldw 32(%r4),%r10
+ bl,n L$0051,%r0
+L$0050:
+ ldo 16(%r0),%r26
+ .CALL ARGW0=GR
+ bl xmalloc,%r2
+ nop
+ copy %r28,%r10
+L$0051:
+ stw %r10,36(%r9)
+ ldw 8(%r4),%r19
+ ldw 12(%r19),%r26
+ .CALL ARGW0=GR
+ bl alloc_type,%r2
+ nop
+ stw %r28,12(%r4)
+ ldw 12(%r4),%r19
+ ldo 11(%r0),%r20
+ stw %r20,0(%r19)
+ ldw 12(%r4),%r19
+ addil L'builtin_type_int-$global$,%r27
+ ldw R'builtin_type_int-$global$(%r1),%r20
+ stw %r20,16(%r19)
+ ldw 12(%r4),%r19
+ ldo 4(%r0),%r20
+ stw %r20,8(%r19)
+ ldw 12(%r4),%r19
+ ldo 2(%r0),%r20
+ sth %r20,34(%r19)
+ ldw 12(%r4),%r9
+ ldw 12(%r4),%r19
+ ldw 12(%r19),%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0057,%r0
+ nop
+ ldw 12(%r4),%r19
+ ldw 12(%r19),%r20
+ ldo 120(%r20),%r19
+ stw %r19,36(%r4)
+ ldw 36(%r4),%r19
+ stw %r19,40(%r4)
+ ldo 32(%r0),%r19
+ stw %r19,44(%r4)
+ ldw 40(%r4),%r19
+ ldw 40(%r4),%r20
+ ldw 16(%r19),%r19
+ ldw 12(%r20),%r20
+ sub %r19,%r20,%r19
+ ldw 44(%r4),%r20
+ comclr,< %r19,%r20,%r0
+ bl L$0052,%r0
+ nop
+ ldw 40(%r4),%r26
+ ldw 44(%r4),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl _obstack_newchunk,%r2
+ nop
+ copy %r0,%r19
+ bl,n L$0053,%r0
+L$0052:
+ copy %r0,%r19
+L$0053:
+ ldw 40(%r4),%r19
+ ldw 40(%r4),%r20
+ ldw 12(%r20),%r21
+ ldw 44(%r4),%r22
+ add %r21,%r22,%r20
+ copy %r20,%r21
+ stw %r21,12(%r19)
+ ldw 36(%r4),%r19
+ stw %r19,48(%r4)
+ ldw 48(%r4),%r19
+ ldw 8(%r19),%r20
+ stw %r20,52(%r4)
+ ldw 48(%r4),%r19
+ ldw 12(%r19),%r20
+ ldw 52(%r4),%r19
+ comclr,= %r20,%r19,%r0
+ bl L$0054,%r0
+ nop
+ ldw 48(%r4),%r19
+ ldw 40(%r19),%r20
+ copy %r20,%r21
+ depi -1,1,1,%r21
+ stw %r21,40(%r19)
+L$0054:
+ ldw 48(%r4),%r19
+ ldw 48(%r4),%r20
+ ldw 48(%r4),%r21
+ ldw 12(%r20),%r20
+ ldw 24(%r21),%r21
+ add %r20,%r21,%r20
+ ldw 48(%r4),%r21
+ ldw 24(%r21),%r22
+ uaddcm %r0,%r22,%r21
+ and %r20,%r21,%r20
+ copy %r20,%r21
+ stw %r21,12(%r19)
+ ldw 48(%r4),%r19
+ ldw 48(%r4),%r20
+ ldw 12(%r19),%r19
+ ldw 4(%r20),%r20
+ sub %r19,%r20,%r19
+ ldw 48(%r4),%r20
+ ldw 48(%r4),%r21
+ ldw 16(%r20),%r20
+ ldw 4(%r21),%r21
+ sub %r20,%r21,%r20
+ comclr,> %r19,%r20,%r0
+ bl L$0055,%r0
+ nop
+ ldw 48(%r4),%r19
+ ldw 48(%r4),%r20
+ ldw 16(%r20),%r21
+ stw %r21,12(%r19)
+ copy %r21,%r19
+ bl,n L$0056,%r0
+L$0055:
+ copy %r0,%r19
+L$0056:
+ ldw 48(%r4),%r19
+ ldw 48(%r4),%r20
+ ldw 12(%r20),%r21
+ stw %r21,8(%r19)
+ ldw 52(%r4),%r10
+ bl,n L$0058,%r0
+L$0057:
+ ldo 32(%r0),%r26
+ .CALL ARGW0=GR
+ bl xmalloc,%r2
+ nop
+ copy %r28,%r10
+L$0058:
+ stw %r10,36(%r9)
+ ldw 12(%r4),%r19
+ ldw 36(%r19),%r20
+ stw %r0,0(%r20)
+ ldw 12(%r4),%r19
+ ldo 16(%r0),%r20
+ ldw 36(%r19),%r21
+ add %r20,%r21,%r19
+ ldo -8(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldo -1(%r20),%r21
+ stw %r21,0(%r19)
+ ldw 12(%r4),%r20
+ ldw 36(%r20),%r19
+ addil L'builtin_type_int-$global$,%r27
+ ldw R'builtin_type_int-$global$(%r1),%r20
+ stw %r20,8(%r19)
+ ldw 12(%r4),%r19
+ ldo 16(%r0),%r20
+ ldw 36(%r19),%r21
+ add %r20,%r21,%r19
+ addil L'builtin_type_int-$global$,%r27
+ ldw R'builtin_type_int-$global$(%r1),%r20
+ stw %r20,8(%r19)
+ ldw 8(%r4),%r19
+ ldw 36(%r19),%r20
+ ldw 12(%r4),%r19
+ stw %r19,8(%r20)
+ ldw 8(%r4),%r19
+ ldo -1(%r0),%r20
+ stw %r20,44(%r19)
+ ldw 8(%r4),%r28
+ bl,n L$0044,%r0
+L$0044:
+ ldw 56(%r4),%r10
+ ldw 60(%r4),%r9
+ ldw 64(%r4),%r8
+ ldw 68(%r4),%r7
+ ldw 72(%r4),%r6
+ ldw 76(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .align 4
+ .EXPORT smash_to_member_type,CODE
+ .EXPORT smash_to_member_type,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR
+smash_to_member_type:
+ .PROC
+ .CALLINFO FRAME=192,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,192(%r30)
+ stw %r10,16(%r4)
+ stw %r9,20(%r4)
+ stw %r8,24(%r4)
+ stw %r7,28(%r4)
+ stw %r6,32(%r4)
+ stw %r5,36(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -8(%r0),%r7
+ ldo -32(%r4),%r19
+ add %r19,%r7,%r8
+ stw %r25,0(%r8)
+ ldo -12(%r0),%r9
+ ldo -32(%r4),%r19
+ add %r19,%r9,%r10
+ stw %r24,0(%r10)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 12(%r19),%r20
+ stw %r20,8(%r4)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r26
+ copy %r0,%r25
+ ldo 52(%r0),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl memset,%r2
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 8(%r4),%r20
+ stw %r20,12(%r19)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldo -12(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 0(%r20),%r21
+ stw %r21,16(%r19)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldo -8(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 0(%r20),%r21
+ stw %r21,40(%r19)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldo 1(%r0),%r20
+ stw %r20,8(%r19)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldo 14(%r0),%r20
+ stw %r20,0(%r19)
+L$0059:
+ ldw 16(%r4),%r10
+ ldw 20(%r4),%r9
+ ldw 24(%r4),%r8
+ ldw 28(%r4),%r7
+ ldw 32(%r4),%r6
+ ldw 36(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .align 4
+ .EXPORT smash_to_method_type,CODE
+ .EXPORT smash_to_method_type,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+smash_to_method_type:
+ .PROC
+ .CALLINFO FRAME=192,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,192(%r30)
+ stw %r12,16(%r4)
+ stw %r11,20(%r4)
+ stw %r10,24(%r4)
+ stw %r9,28(%r4)
+ stw %r8,32(%r4)
+ stw %r7,36(%r4)
+ stw %r6,40(%r4)
+ stw %r5,44(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -8(%r0),%r7
+ ldo -32(%r4),%r19
+ add %r19,%r7,%r8
+ stw %r25,0(%r8)
+ ldo -12(%r0),%r9
+ ldo -32(%r4),%r19
+ add %r19,%r9,%r10
+ stw %r24,0(%r10)
+ ldo -16(%r0),%r11
+ ldo -32(%r4),%r19
+ add %r19,%r11,%r12
+ stw %r23,0(%r12)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 12(%r19),%r20
+ stw %r20,8(%r4)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r26
+ copy %r0,%r25
+ ldo 52(%r0),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl memset,%r2
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 8(%r4),%r20
+ stw %r20,12(%r19)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldo -12(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 0(%r20),%r21
+ stw %r21,16(%r19)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldo -8(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 0(%r20),%r21
+ stw %r21,40(%r19)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldo -16(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 0(%r20),%r21
+ stw %r21,48(%r19)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldo 1(%r0),%r20
+ stw %r20,8(%r19)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldo 15(%r0),%r20
+ stw %r20,0(%r19)
+L$0060:
+ ldw 16(%r4),%r12
+ ldw 20(%r4),%r11
+ ldw 24(%r4),%r10
+ ldw 28(%r4),%r9
+ ldw 32(%r4),%r8
+ ldw 36(%r4),%r7
+ ldw 40(%r4),%r6
+ ldw 44(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .IMPORT strncmp,CODE
+ .align 4
+LC$0000:
+ .STRING "struct \x00"
+ .align 4
+LC$0001:
+ .STRING "union \x00"
+ .align 4
+LC$0002:
+ .STRING "enum \x00"
+ .align 4
+ .EXPORT type_name_no_tag,CODE
+ .EXPORT type_name_no_tag,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR
+type_name_no_tag:
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,128(%r30)
+ stw %r6,8(%r4)
+ stw %r5,12(%r4)
+ copy %r26,%r5
+ ldw 4(%r5),%r6
+ comiclr,<> 0,%r6,%r0
+ bl L$0062,%r0
+ nop
+ ldw 0(%r5),%r19
+ comiclr,<> 4,%r19,%r0
+ bl L$0066,%r0
+ nop
+ comiclr,>= 4,%r19,%r0
+ bl L$0072,%r0
+ nop
+ comiclr,<> 3,%r19,%r0
+ bl L$0064,%r0
+ nop
+ bl,n L$0070,%r0
+L$0072:
+ comiclr,<> 5,%r19,%r0
+ bl L$0068,%r0
+ nop
+ bl,n L$0070,%r0
+L$0064:
+ copy %r6,%r26
+ ldil L'LC$0000,%r25
+ ldo R'LC$0000(%r25),%r25
+ ldo 7(%r0),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl strncmp,%r2
+ nop
+ copy %r28,%r19
+ comiclr,= 0,%r19,%r0
+ bl L$0065,%r0
+ nop
+ ldo 7(%r6),%r6
+L$0065:
+ bl,n L$0063,%r0
+L$0066:
+ copy %r6,%r26
+ ldil L'LC$0001,%r25
+ ldo R'LC$0001(%r25),%r25
+ ldo 6(%r0),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl strncmp,%r2
+ nop
+ copy %r28,%r19
+ comiclr,= 0,%r19,%r0
+ bl L$0067,%r0
+ nop
+ ldo 6(%r6),%r6
+L$0067:
+ bl,n L$0063,%r0
+L$0068:
+ copy %r6,%r26
+ ldil L'LC$0002,%r25
+ ldo R'LC$0002(%r25),%r25
+ ldo 5(%r0),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl strncmp,%r2
+ nop
+ copy %r28,%r19
+ comiclr,= 0,%r19,%r0
+ bl L$0069,%r0
+ nop
+ ldo 5(%r6),%r6
+L$0069:
+ bl,n L$0063,%r0
+L$0070:
+ bl,n L$0063,%r0
+L$0063:
+L$0062:
+ copy %r6,%r28
+ bl,n L$0061,%r0
+L$0061:
+ ldw 8(%r4),%r6
+ ldw 12(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .IMPORT current_language,DATA
+ .IMPORT strcmp,CODE
+ .align 4
+ .EXPORT lookup_primitive_typename,CODE
+ .EXPORT lookup_primitive_typename,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR
+lookup_primitive_typename:
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,128(%r30)
+ stw %r6,16(%r4)
+ stw %r5,20(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ addil L'current_language-$global$,%r27
+ ldw R'current_language-$global$(%r1),%r19
+ ldw 8(%r19),%r20
+ stw %r20,8(%r4)
+L$0074:
+ ldw 8(%r4),%r19
+ ldw 0(%r19),%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0075,%r0
+ nop
+ ldw 8(%r4),%r19
+ ldw 0(%r19),%r20
+ ldw 0(%r20),%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 4(%r19),%r26
+ ldw 0(%r20),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2
+ nop
+ copy %r28,%r19
+ comiclr,= 0,%r19,%r0
+ bl L$0077,%r0
+ nop
+ ldw 8(%r4),%r19
+ ldw 0(%r19),%r20
+ ldw 0(%r20),%r28
+ bl,n L$0073,%r0
+L$0077:
+L$0076:
+ ldw 8(%r4),%r19
+ ldo 4(%r19),%r20
+ stw %r20,8(%r4)
+ bl,n L$0074,%r0
+L$0075:
+ copy %r0,%r28
+ bl,n L$0073,%r0
+L$0073:
+ ldw 16(%r4),%r6
+ ldw 20(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .IMPORT lookup_symbol,CODE
+ .IMPORT error,CODE
+ .align 4
+LC$0003:
+ .STRING "No type named %s.\x00"
+ .align 4
+ .EXPORT lookup_typename,CODE
+ .EXPORT lookup_typename,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,RTNVAL=GR
+lookup_typename:
+ .PROC
+ .CALLINFO FRAME=192,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,192(%r30)
+ stw %r12,8(%r4)
+ stw %r11,12(%r4)
+ stw %r10,16(%r4)
+ stw %r9,20(%r4)
+ stw %r8,24(%r4)
+ stw %r7,28(%r4)
+ stw %r6,32(%r4)
+ stw %r5,36(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -8(%r0),%r7
+ ldo -32(%r4),%r19
+ add %r19,%r7,%r8
+ stw %r25,0(%r8)
+ ldo -12(%r0),%r9
+ ldo -32(%r4),%r19
+ add %r19,%r9,%r10
+ stw %r24,0(%r10)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -8(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ stw %r0,-52(%r30)
+ ldw 0(%r19),%r26
+ ldw 0(%r20),%r25
+ ldo 1(%r0),%r24
+ copy %r0,%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl lookup_symbol,%r2
+ nop
+ copy %r28,%r11
+ comiclr,<> 0,%r11,%r0
+ bl L$0080,%r0
+ nop
+ ldw 8(%r11),%r19
+ comiclr,= 8,%r19,%r0
+ bl L$0080,%r0
+ nop
+ bl,n L$0079,%r0
+L$0080:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r26
+ .CALL ARGW0=GR
+ bl lookup_primitive_typename,%r2
+ nop
+ copy %r28,%r12
+ comiclr,<> 0,%r12,%r0
+ bl L$0081,%r0
+ nop
+ copy %r12,%r28
+ bl,n L$0078,%r0
+ bl,n L$0082,%r0
+L$0081:
+ comiclr,= 0,%r12,%r0
+ bl L$0083,%r0
+ nop
+ ldo -12(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0083,%r0
+ nop
+ copy %r0,%r28
+ bl,n L$0078,%r0
+ bl,n L$0084,%r0
+L$0083:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldil L'LC$0003,%r26
+ ldo R'LC$0003(%r26),%r26
+ ldw 0(%r19),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl error,%r2
+ nop
+L$0084:
+L$0082:
+L$0079:
+ ldw 12(%r11),%r28
+ bl,n L$0078,%r0
+L$0078:
+ ldw 8(%r4),%r12
+ ldw 12(%r4),%r11
+ ldw 16(%r4),%r10
+ ldw 20(%r4),%r9
+ ldw 24(%r4),%r8
+ ldw 28(%r4),%r7
+ ldw 32(%r4),%r6
+ ldw 36(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .IMPORT alloca,CODE
+ .IMPORT strlen,CODE
+ .IMPORT strcpy,CODE
+ .align 4
+LC$0004:
+ .STRING "unsigned \x00"
+ .align 4
+ .EXPORT lookup_unsigned_typename,CODE
+ .EXPORT lookup_unsigned_typename,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR
+lookup_unsigned_typename:
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,128(%r30)
+ stw %r6,16(%r4)
+ stw %r5,20(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r26
+ .CALL ARGW0=GR
+ bl strlen,%r2
+ nop
+ copy %r28,%r19
+ ldo 10(%r19),%r20
+ ldo 7(%r20),%r21
+ copy %r21,%r19
+ ldo 63(%r19),%r20
+ extru %r20,25,26,%r19
+ zdep %r19,25,26,%r20
+ ldo -96(%r30),%r19
+ add %r30,%r20,%r30
+ ldo 7(%r19),%r20
+ extru %r20,28,29,%r19
+ zdep %r19,28,29,%r20
+ stw %r20,8(%r4)
+ ldw 8(%r4),%r26
+ ldil L'LC$0004,%r25
+ ldo R'LC$0004(%r25),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcpy,%r2
+ nop
+ ldw 8(%r4),%r20
+ ldo 9(%r20),%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ copy %r19,%r26
+ ldw 0(%r20),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcpy,%r2
+ nop
+ ldw 8(%r4),%r26
+ copy %r0,%r25
+ copy %r0,%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl lookup_typename,%r2
+ nop
+ bl,n L$0085,%r0
+L$0085:
+ ldw 16(%r4),%r6
+ ldw 20(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .align 4
+LC$0005:
+ .STRING "signed \x00"
+ .align 4
+ .EXPORT lookup_signed_typename,CODE
+ .EXPORT lookup_signed_typename,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR
+lookup_signed_typename:
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,128(%r30)
+ stw %r6,16(%r4)
+ stw %r5,20(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r26
+ .CALL ARGW0=GR
+ bl strlen,%r2
+ nop
+ copy %r28,%r19
+ ldo 8(%r19),%r20
+ ldo 7(%r20),%r21
+ copy %r21,%r19
+ ldo 63(%r19),%r20
+ extru %r20,25,26,%r19
+ zdep %r19,25,26,%r20
+ ldo -96(%r30),%r19
+ add %r30,%r20,%r30
+ ldo 7(%r19),%r20
+ extru %r20,28,29,%r19
+ zdep %r19,28,29,%r20
+ stw %r20,12(%r4)
+ ldw 12(%r4),%r26
+ ldil L'LC$0005,%r25
+ ldo R'LC$0005(%r25),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcpy,%r2
+ nop
+ ldw 12(%r4),%r20
+ ldo 7(%r20),%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ copy %r19,%r26
+ ldw 0(%r20),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcpy,%r2
+ nop
+ ldw 12(%r4),%r26
+ copy %r0,%r25
+ ldo 1(%r0),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl lookup_typename,%r2
+ nop
+ stw %r28,8(%r4)
+ ldw 8(%r4),%r19
+ comiclr,<> 0,%r19,%r0
+ bl L$0087,%r0
+ nop
+ ldw 8(%r4),%r28
+ bl,n L$0086,%r0
+L$0087:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r26
+ copy %r0,%r25
+ copy %r0,%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl lookup_typename,%r2
+ nop
+ bl,n L$0086,%r0
+L$0086:
+ ldw 16(%r4),%r6
+ ldw 20(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .align 4
+LC$0006:
+ .STRING "No struct type named %s.\x00"
+ .align 4
+LC$0007:
+ .STRING "This context has class, union or enum %s, not a struct.\x00"
+ .align 4
+ .EXPORT lookup_struct,CODE
+ .EXPORT lookup_struct,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,RTNVAL=GR
+lookup_struct:
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,128(%r30)
+ stw %r9,8(%r4)
+ stw %r8,12(%r4)
+ stw %r7,16(%r4)
+ stw %r6,20(%r4)
+ stw %r5,24(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -8(%r0),%r7
+ ldo -32(%r4),%r19
+ add %r19,%r7,%r8
+ stw %r25,0(%r8)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -8(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ stw %r0,-52(%r30)
+ ldw 0(%r19),%r26
+ ldw 0(%r20),%r25
+ ldo 2(%r0),%r24
+ copy %r0,%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl lookup_symbol,%r2
+ nop
+ copy %r28,%r9
+ comiclr,= 0,%r9,%r0
+ bl L$0089,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldil L'LC$0006,%r26
+ ldo R'LC$0006(%r26),%r26
+ ldw 0(%r19),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl error,%r2
+ nop
+L$0089:
+ ldw 12(%r9),%r19
+ ldw 0(%r19),%r20
+ comiclr,<> 3,%r20,%r0
+ bl L$0090,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldil L'LC$0007,%r26
+ ldo R'LC$0007(%r26),%r26
+ ldw 0(%r19),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl error,%r2
+ nop
+L$0090:
+ ldw 12(%r9),%r28
+ bl,n L$0088,%r0
+L$0088:
+ ldw 8(%r4),%r9
+ ldw 12(%r4),%r8
+ ldw 16(%r4),%r7
+ ldw 20(%r4),%r6
+ ldw 24(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .align 4
+LC$0008:
+ .STRING "No union type named %s.\x00"
+ .align 4
+LC$0009:
+ .STRING "This context has class, struct or enum %s, not a union.\x00"
+ .align 4
+ .EXPORT lookup_union,CODE
+ .EXPORT lookup_union,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,RTNVAL=GR
+lookup_union:
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,128(%r30)
+ stw %r9,8(%r4)
+ stw %r8,12(%r4)
+ stw %r7,16(%r4)
+ stw %r6,20(%r4)
+ stw %r5,24(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -8(%r0),%r7
+ ldo -32(%r4),%r19
+ add %r19,%r7,%r8
+ stw %r25,0(%r8)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -8(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ stw %r0,-52(%r30)
+ ldw 0(%r19),%r26
+ ldw 0(%r20),%r25
+ ldo 2(%r0),%r24
+ copy %r0,%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl lookup_symbol,%r2
+ nop
+ copy %r28,%r9
+ comiclr,= 0,%r9,%r0
+ bl L$0092,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldil L'LC$0008,%r26
+ ldo R'LC$0008(%r26),%r26
+ ldw 0(%r19),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl error,%r2
+ nop
+L$0092:
+ ldw 12(%r9),%r19
+ ldw 0(%r19),%r20
+ comiclr,<> 4,%r20,%r0
+ bl L$0093,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldil L'LC$0009,%r26
+ ldo R'LC$0009(%r26),%r26
+ ldw 0(%r19),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl error,%r2
+ nop
+L$0093:
+ ldw 12(%r9),%r28
+ bl,n L$0091,%r0
+L$0091:
+ ldw 8(%r4),%r9
+ ldw 12(%r4),%r8
+ ldw 16(%r4),%r7
+ ldw 20(%r4),%r6
+ ldw 24(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .align 4
+LC$0010:
+ .STRING "No enum type named %s.\x00"
+ .align 4
+LC$0011:
+ .STRING "This context has class, struct or union %s, not an enum.\x00"
+ .align 4
+ .EXPORT lookup_enum,CODE
+ .EXPORT lookup_enum,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,RTNVAL=GR
+lookup_enum:
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,128(%r30)
+ stw %r9,8(%r4)
+ stw %r8,12(%r4)
+ stw %r7,16(%r4)
+ stw %r6,20(%r4)
+ stw %r5,24(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -8(%r0),%r7
+ ldo -32(%r4),%r19
+ add %r19,%r7,%r8
+ stw %r25,0(%r8)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -8(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ stw %r0,-52(%r30)
+ ldw 0(%r19),%r26
+ ldw 0(%r20),%r25
+ ldo 2(%r0),%r24
+ copy %r0,%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl lookup_symbol,%r2
+ nop
+ copy %r28,%r9
+ comiclr,= 0,%r9,%r0
+ bl L$0095,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldil L'LC$0010,%r26
+ ldo R'LC$0010(%r26),%r26
+ ldw 0(%r19),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl error,%r2
+ nop
+L$0095:
+ ldw 12(%r9),%r19
+ ldw 0(%r19),%r20
+ comiclr,<> 5,%r20,%r0
+ bl L$0096,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldil L'LC$0011,%r26
+ ldo R'LC$0011(%r26),%r26
+ ldw 0(%r19),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl error,%r2
+ nop
+L$0096:
+ ldw 12(%r9),%r28
+ bl,n L$0094,%r0
+L$0094:
+ ldw 8(%r4),%r9
+ ldw 12(%r4),%r8
+ ldw 16(%r4),%r7
+ ldw 20(%r4),%r6
+ ldw 24(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .IMPORT strcat,CODE
+ .align 4
+LC$0012:
+ .STRING "<\x00"
+ .align 4
+LC$0013:
+ .STRING " >\x00"
+ .align 4
+LC$0014:
+ .STRING "No template type named %s.\x00"
+ .align 4
+ .EXPORT lookup_template_type,CODE
+ .EXPORT lookup_template_type,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,RTNVAL=GR
+lookup_template_type:
+ .PROC
+ .CALLINFO FRAME=192,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,192(%r30)
+ stw %r11,16(%r4)
+ stw %r10,20(%r4)
+ stw %r9,24(%r4)
+ stw %r8,28(%r4)
+ stw %r7,32(%r4)
+ stw %r6,36(%r4)
+ stw %r5,40(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -8(%r0),%r7
+ ldo -32(%r4),%r19
+ add %r19,%r7,%r8
+ stw %r25,0(%r8)
+ ldo -12(%r0),%r9
+ ldo -32(%r4),%r19
+ add %r19,%r9,%r10
+ stw %r24,0(%r10)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r26
+ .CALL ARGW0=GR
+ bl strlen,%r2
+ nop
+ copy %r28,%r11
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 4(%r19),%r26
+ .CALL ARGW0=GR
+ bl strlen,%r2
+ nop
+ copy %r28,%r19
+ add %r11,%r19,%r20
+ ldo 4(%r20),%r19
+ ldo 7(%r19),%r20
+ copy %r20,%r19
+ ldo 63(%r19),%r20
+ extru %r20,25,26,%r19
+ zdep %r19,25,26,%r20
+ ldo -96(%r30),%r19
+ add %r30,%r20,%r30
+ ldo 7(%r19),%r20
+ extru %r20,28,29,%r19
+ zdep %r19,28,29,%r20
+ stw %r20,12(%r4)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 12(%r4),%r26
+ ldw 0(%r19),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcpy,%r2
+ nop
+ ldw 12(%r4),%r26
+ ldil L'LC$0012,%r25
+ ldo R'LC$0012(%r25),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcat,%r2
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 12(%r4),%r26
+ ldw 4(%r19),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcat,%r2
+ nop
+ ldw 12(%r4),%r26
+ ldil L'LC$0013,%r25
+ ldo R'LC$0013(%r25),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcat,%r2
+ nop
+ ldo -12(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ stw %r0,-52(%r30)
+ ldw 12(%r4),%r26
+ ldw 0(%r19),%r25
+ ldo 1(%r0),%r24
+ copy %r0,%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl lookup_symbol,%r2
+ nop
+ stw %r28,8(%r4)
+ ldw 8(%r4),%r19
+ comiclr,= 0,%r19,%r0
+ bl L$0098,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldil L'LC$0014,%r26
+ ldo R'LC$0014(%r26),%r26
+ ldw 0(%r19),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl error,%r2
+ nop
+L$0098:
+ ldw 8(%r4),%r19
+ ldw 12(%r19),%r20
+ ldw 0(%r20),%r19
+ comiclr,<> 3,%r19,%r0
+ bl L$0099,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldil L'LC$0007,%r26
+ ldo R'LC$0007(%r26),%r26
+ ldw 0(%r19),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl error,%r2
+ nop
+L$0099:
+ ldw 8(%r4),%r19
+ ldw 12(%r19),%r28
+ bl,n L$0097,%r0
+L$0097:
+ ldw 16(%r4),%r11
+ ldw 20(%r4),%r10
+ ldw 24(%r4),%r9
+ ldw 28(%r4),%r8
+ ldw 32(%r4),%r7
+ ldw 36(%r4),%r6
+ ldw 40(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .IMPORT current_target,DATA
+ .IMPORT fflush,CODE
+ .IMPORT __iob,DATA
+ .IMPORT fprintf,CODE
+ .align 4
+LC$0015:
+ .STRING "Type \x00"
+ .IMPORT type_print,CODE
+ .align 4
+LC$0016:
+ .STRING "\x00"
+ .align 4
+LC$0017:
+ .STRING " is not a structure or union type.\x00"
+ .IMPORT check_stub_type,CODE
+ .align 4
+LC$0018:
+ .STRING " has no component named \x00"
+ .IMPORT fputs_filtered,CODE
+ .align 4
+LC$0019:
+ .STRING ".\x00"
+ .align 4
+ .EXPORT lookup_struct_elt_type,CODE
+ .EXPORT lookup_struct_elt_type,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,RTNVAL=GR
+lookup_struct_elt_type:
+ .PROC
+ .CALLINFO FRAME=192,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,192(%r30)
+ stw %r11,24(%r4)
+ stw %r10,28(%r4)
+ stw %r9,32(%r4)
+ stw %r8,36(%r4)
+ stw %r7,40(%r4)
+ stw %r6,44(%r4)
+ stw %r5,48(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -8(%r0),%r7
+ ldo -32(%r4),%r19
+ add %r19,%r7,%r8
+ stw %r25,0(%r8)
+ ldo -12(%r0),%r9
+ ldo -32(%r4),%r19
+ add %r19,%r9,%r10
+ stw %r24,0(%r10)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 0(%r19),%r20
+ comiclr,<> 1,%r20,%r0
+ bl L$0102,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 0(%r19),%r20
+ ldo 16(%r0),%r19
+ comclr,<> %r20,%r19,%r0
+ bl L$0102,%r0
+ nop
+ bl,n L$0101,%r0
+L$0102:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldw 16(%r20),%r21
+ stw %r21,0(%r19)
+L$0101:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 0(%r19),%r20
+ comiclr,<> 3,%r20,%r0
+ bl L$0103,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 0(%r19),%r20
+ comiclr,<> 4,%r20,%r0
+ bl L$0103,%r0
+ nop
+ addil L'current_target-$global$,%r27
+ ldw R'current_target-$global$(%r1),%r19
+ ldw 76(%r19),%r11
+ copy %r11,%r22
+ .CALL ARGW0=GR
+ bl $$dyncall,%r31
+ copy %r31,%r2
+ addil L'__iob-$global$+16,%r27
+ ldo R'__iob-$global$+16(%r1),%r26
+ .CALL ARGW0=GR
+ bl fflush,%r2
+ nop
+ addil L'__iob-$global$+32,%r27
+ ldo R'__iob-$global$+32(%r1),%r26
+ ldil L'LC$0015,%r25
+ ldo R'LC$0015(%r25),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl fprintf,%r2
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r26
+ ldil L'LC$0016,%r25
+ ldo R'LC$0016(%r25),%r25
+ addil L'__iob-$global$+32,%r27
+ ldo R'__iob-$global$+32(%r1),%r24
+ ldo -1(%r0),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl type_print,%r2
+ nop
+ ldil L'LC$0017,%r26
+ ldo R'LC$0017(%r26),%r26
+ .CALL ARGW0=GR
+ bl error,%r2
+ nop
+L$0103:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r26
+ .CALL ARGW0=GR
+ bl check_stub_type,%r2
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldh 34(%r19),%r20
+ extrs %r20,31,16,%r19
+ ldo -1(%r19),%r20
+ stw %r20,8(%r4)
+L$0104:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 48(%r19),%r20
+ ldh 0(%r20),%r21
+ extrs %r21,31,16,%r19
+ ldw 8(%r4),%r20
+ comclr,>= %r20,%r19,%r0
+ bl L$0105,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 8(%r4),%r20
+ zdep %r20,27,28,%r21
+ ldw 36(%r19),%r20
+ add %r21,%r20,%r19
+ ldw 12(%r19),%r20
+ stw %r20,12(%r4)
+ ldw 12(%r4),%r19
+ comiclr,<> 0,%r19,%r0
+ bl L$0107,%r0
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 12(%r4),%r26
+ ldw 0(%r19),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2
+ nop
+ copy %r28,%r19
+ comiclr,= 0,%r19,%r0
+ bl L$0107,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 8(%r4),%r20
+ zdep %r20,27,28,%r21
+ ldw 36(%r19),%r20
+ add %r21,%r20,%r19
+ ldw 8(%r19),%r28
+ bl,n L$0100,%r0
+L$0107:
+L$0106:
+ ldw 8(%r4),%r19
+ ldo -1(%r19),%r20
+ stw %r20,8(%r4)
+ bl,n L$0104,%r0
+L$0105:
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 48(%r19),%r20
+ ldh 0(%r20),%r21
+ extrs %r21,31,16,%r19
+ ldo -1(%r19),%r20
+ stw %r20,8(%r4)
+L$0108:
+ ldw 8(%r4),%r19
+ comiclr,<= 0,%r19,%r0
+ bl L$0109,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 8(%r4),%r20
+ zdep %r20,27,28,%r21
+ ldw 36(%r19),%r20
+ add %r21,%r20,%r19
+ ldo -8(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 8(%r19),%r26
+ ldw 0(%r20),%r25
+ copy %r0,%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl lookup_struct_elt_type,%r2
+ nop
+ stw %r28,16(%r4)
+ ldw 16(%r4),%r19
+ comiclr,<> 0,%r19,%r0
+ bl L$0111,%r0
+ nop
+ ldw 16(%r4),%r28
+ bl,n L$0100,%r0
+L$0111:
+L$0110:
+ ldw 8(%r4),%r19
+ ldo -1(%r19),%r20
+ stw %r20,8(%r4)
+ bl,n L$0108,%r0
+L$0109:
+ ldo -12(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0112,%r0
+ nop
+ copy %r0,%r28
+ bl,n L$0100,%r0
+L$0112:
+ addil L'current_target-$global$,%r27
+ ldw R'current_target-$global$(%r1),%r19
+ ldw 76(%r19),%r11
+ copy %r11,%r22
+ .CALL ARGW0=GR
+ bl $$dyncall,%r31
+ copy %r31,%r2
+ addil L'__iob-$global$+16,%r27
+ ldo R'__iob-$global$+16(%r1),%r26
+ .CALL ARGW0=GR
+ bl fflush,%r2
+ nop
+ addil L'__iob-$global$+32,%r27
+ ldo R'__iob-$global$+32(%r1),%r26
+ ldil L'LC$0015,%r25
+ ldo R'LC$0015(%r25),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl fprintf,%r2
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r26
+ ldil L'LC$0016,%r25
+ ldo R'LC$0016(%r25),%r25
+ addil L'__iob-$global$+32,%r27
+ ldo R'__iob-$global$+32(%r1),%r24
+ ldo -1(%r0),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl type_print,%r2
+ nop
+ addil L'__iob-$global$+32,%r27
+ ldo R'__iob-$global$+32(%r1),%r26
+ ldil L'LC$0018,%r25
+ ldo R'LC$0018(%r25),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl fprintf,%r2
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r26
+ addil L'__iob-$global$+32,%r27
+ ldo R'__iob-$global$+32(%r1),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl fputs_filtered,%r2
+ nop
+ ldil L'LC$0019,%r26
+ ldo R'LC$0019(%r26),%r26
+ .CALL ARGW0=GR
+ bl error,%r2
+ nop
+ ldo -1(%r0),%r28
+ bl,n L$0100,%r0
+L$0100:
+ ldw 24(%r4),%r11
+ ldw 28(%r4),%r10
+ ldw 32(%r4),%r9
+ ldw 36(%r4),%r8
+ ldw 40(%r4),%r7
+ ldw 44(%r4),%r6
+ ldw 48(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .align 4
+ .EXPORT fill_in_vptr_fieldno,CODE
+ .EXPORT fill_in_vptr_fieldno,ENTRY,PRIV_LEV=3,ARGW0=GR
+fill_in_vptr_fieldno:
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,128(%r30)
+ stw %r6,16(%r4)
+ stw %r5,20(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 44(%r19),%r20
+ comiclr,> 0,%r20,%r0
+ bl L$0114,%r0
+ nop
+ ldo 1(%r0),%r19
+ stw %r19,8(%r4)
+L$0115:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 48(%r19),%r20
+ ldh 0(%r20),%r21
+ extrs %r21,31,16,%r19
+ ldw 8(%r4),%r20
+ comclr,< %r20,%r19,%r0
+ bl L$0116,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 8(%r4),%r20
+ zdep %r20,27,28,%r21
+ ldw 36(%r19),%r20
+ add %r21,%r20,%r19
+ ldw 8(%r19),%r26
+ .CALL ARGW0=GR
+ bl fill_in_vptr_fieldno,%r2
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 8(%r4),%r20
+ zdep %r20,27,28,%r21
+ ldw 36(%r19),%r20
+ add %r21,%r20,%r19
+ ldw 8(%r19),%r20
+ ldw 44(%r20),%r19
+ comiclr,<= 0,%r19,%r0
+ bl L$0118,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldw 8(%r4),%r21
+ zdep %r21,27,28,%r22
+ ldw 36(%r20),%r21
+ add %r22,%r21,%r20
+ ldw 8(%r20),%r21
+ ldw 44(%r21),%r20
+ stw %r20,44(%r19)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldw 8(%r4),%r21
+ zdep %r21,27,28,%r22
+ ldw 36(%r20),%r21
+ add %r22,%r21,%r20
+ ldw 8(%r20),%r21
+ ldw 40(%r21),%r20
+ stw %r20,40(%r19)
+ bl,n L$0116,%r0
+L$0118:
+L$0117:
+ ldw 8(%r4),%r19
+ ldo 1(%r19),%r20
+ stw %r20,8(%r4)
+ bl,n L$0115,%r0
+L$0116:
+L$0114:
+L$0113:
+ ldw 16(%r4),%r6
+ ldw 20(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .EXPORT stub_noname_complaint,DATA
+ .align 4
+LC$0020:
+ .STRING "stub type has NULL name\x00"
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$
+
+ .align 4
+stub_noname_complaint:
+ .word LC$0020
+ .word 0
+ .word 0
+ .IMPORT complain,CODE
+ .IMPORT memcpy,CODE
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .EXPORT check_stub_type,CODE
+ .EXPORT check_stub_type,ENTRY,PRIV_LEV=3,ARGW0=GR
+check_stub_type:
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,128(%r30)
+ stw %r6,16(%r4)
+ stw %r5,20(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldh 32(%r19),%r20
+ ldo 4(%r0),%r21
+ and %r20,%r21,%r19
+ extrs %r19,31,16,%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0120,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r26
+ .CALL ARGW0=GR
+ bl type_name_no_tag,%r2
+ nop
+ stw %r28,8(%r4)
+ ldw 8(%r4),%r19
+ comiclr,= 0,%r19,%r0
+ bl L$0121,%r0
+ nop
+ addil L'stub_noname_complaint-$global$,%r27
+ ldo R'stub_noname_complaint-$global$(%r1),%r26
+ copy %r0,%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl complain,%r2
+ nop
+ bl,n L$0119,%r0
+L$0121:
+ stw %r0,-52(%r30)
+ ldw 8(%r4),%r26
+ copy %r0,%r25
+ ldo 2(%r0),%r24
+ copy %r0,%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl lookup_symbol,%r2
+ nop
+ stw %r28,12(%r4)
+ ldw 12(%r4),%r19
+ comiclr,<> 0,%r19,%r0
+ bl L$0122,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 12(%r4),%r20
+ ldw 0(%r19),%r26
+ ldw 12(%r20),%r25
+ ldo 52(%r0),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl memcpy,%r2
+ nop
+L$0122:
+L$0120:
+L$0119:
+ ldw 16(%r4),%r6
+ ldw 20(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .IMPORT gdb_mangle_name,CODE
+ .IMPORT cplus_demangle,CODE
+ .align 4
+LC$0021:
+ .STRING "Internal: Cannot demangle mangled name `%s'.\x00"
+ .IMPORT strchr,CODE
+ .IMPORT parse_and_eval_type,CODE
+ .IMPORT builtin_type_void,DATA
+ .IMPORT free,CODE
+ .align 4
+ .EXPORT check_stub_method,CODE
+ .EXPORT check_stub_method,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR
+check_stub_method:
+ .PROC
+ .CALLINFO FRAME=192,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,192(%r30)
+ stw %r11,64(%r4)
+ stw %r10,68(%r4)
+ stw %r9,72(%r4)
+ stw %r8,76(%r4)
+ stw %r7,80(%r4)
+ stw %r6,84(%r4)
+ stw %r5,88(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -8(%r0),%r7
+ ldo -32(%r4),%r19
+ add %r19,%r7,%r8
+ stw %r25,0(%r8)
+ ldo -12(%r0),%r9
+ ldo -32(%r4),%r19
+ add %r19,%r9,%r10
+ stw %r24,0(%r10)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -8(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldo -12(%r0),%r21
+ ldo -32(%r4),%r22
+ add %r22,%r21,%r21
+ ldw 0(%r19),%r26
+ ldw 0(%r20),%r25
+ ldw 0(%r21),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl gdb_mangle_name,%r2
+ nop
+ stw %r28,12(%r4)
+ ldw 12(%r4),%r26
+ ldo 3(%r0),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl cplus_demangle,%r2
+ nop
+ stw %r28,16(%r4)
+ stw %r0,28(%r4)
+ ldo 1(%r0),%r19
+ stw %r19,32(%r4)
+ ldw 16(%r4),%r19
+ comiclr,= 0,%r19,%r0
+ bl L$0124,%r0
+ nop
+ ldil L'LC$0021,%r26
+ ldo R'LC$0021(%r26),%r26
+ ldw 12(%r4),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl error,%r2
+ nop
+L$0124:
+ ldw 16(%r4),%r26
+ ldo 40(%r0),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strchr,%r2
+ nop
+ copy %r28,%r19
+ ldo 1(%r19),%r20
+ stw %r20,20(%r4)
+ ldw 20(%r4),%r19
+ stw %r19,24(%r4)
+L$0125:
+ ldw 24(%r4),%r19
+ ldb 0(%r19),%r20
+ extrs %r20,31,8,%r19
+ comiclr,<> 0,%r19,%r0
+ bl L$0126,%r0
+ nop
+ ldw 24(%r4),%r19
+ ldb 0(%r19),%r20
+ extrs %r20,31,8,%r19
+ ldo 40(%r0),%r20
+ comclr,= %r19,%r20,%r0
+ bl L$0127,%r0
+ nop
+ ldw 28(%r4),%r19
+ ldo 1(%r19),%r20
+ stw %r20,28(%r4)
+ bl,n L$0128,%r0
+L$0127:
+ ldw 24(%r4),%r19
+ ldb 0(%r19),%r20
+ extrs %r20,31,8,%r19
+ ldo 41(%r0),%r20
+ comclr,= %r19,%r20,%r0
+ bl L$0129,%r0
+ nop
+ ldw 28(%r4),%r19
+ ldo -1(%r19),%r20
+ stw %r20,28(%r4)
+ bl,n L$0130,%r0
+L$0129:
+ ldw 24(%r4),%r19
+ ldb 0(%r19),%r20
+ extrs %r20,31,8,%r19
+ ldo 44(%r0),%r20
+ comclr,= %r19,%r20,%r0
+ bl L$0131,%r0
+ nop
+ ldw 28(%r4),%r19
+ comiclr,= 0,%r19,%r0
+ bl L$0131,%r0
+ nop
+ ldw 32(%r4),%r19
+ ldo 1(%r19),%r20
+ stw %r20,32(%r4)
+L$0131:
+L$0130:
+L$0128:
+ ldw 24(%r4),%r19
+ ldo 1(%r19),%r20
+ stw %r20,24(%r4)
+ bl,n L$0125,%r0
+L$0126:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 12(%r19),%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0137,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 12(%r19),%r20
+ ldo 120(%r20),%r19
+ stw %r19,44(%r4)
+ ldw 44(%r4),%r19
+ stw %r19,48(%r4)
+ ldw 32(%r4),%r20
+ ldo 2(%r20),%r19
+ zdep %r19,29,30,%r20
+ stw %r20,52(%r4)
+ ldw 48(%r4),%r19
+ ldw 48(%r4),%r20
+ ldw 16(%r19),%r19
+ ldw 12(%r20),%r20
+ sub %r19,%r20,%r19
+ ldw 52(%r4),%r20
+ comclr,< %r19,%r20,%r0
+ bl L$0132,%r0
+ nop
+ ldw 48(%r4),%r26
+ ldw 52(%r4),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl _obstack_newchunk,%r2
+ nop
+ copy %r0,%r19
+ bl,n L$0133,%r0
+L$0132:
+ copy %r0,%r19
+L$0133:
+ ldw 48(%r4),%r19
+ ldw 48(%r4),%r20
+ ldw 12(%r20),%r21
+ ldw 52(%r4),%r22
+ add %r21,%r22,%r20
+ copy %r20,%r21
+ stw %r21,12(%r19)
+ ldw 44(%r4),%r19
+ stw %r19,56(%r4)
+ ldw 56(%r4),%r19
+ ldw 8(%r19),%r20
+ stw %r20,60(%r4)
+ ldw 56(%r4),%r19
+ ldw 12(%r19),%r20
+ ldw 60(%r4),%r19
+ comclr,= %r20,%r19,%r0
+ bl L$0134,%r0
+ nop
+ ldw 56(%r4),%r19
+ ldw 40(%r19),%r20
+ copy %r20,%r21
+ depi -1,1,1,%r21
+ stw %r21,40(%r19)
+L$0134:
+ ldw 56(%r4),%r19
+ ldw 56(%r4),%r20
+ ldw 56(%r4),%r21
+ ldw 12(%r20),%r20
+ ldw 24(%r21),%r21
+ add %r20,%r21,%r20
+ ldw 56(%r4),%r21
+ ldw 24(%r21),%r22
+ uaddcm %r0,%r22,%r21
+ and %r20,%r21,%r20
+ copy %r20,%r21
+ stw %r21,12(%r19)
+ ldw 56(%r4),%r19
+ ldw 56(%r4),%r20
+ ldw 12(%r19),%r19
+ ldw 4(%r20),%r20
+ sub %r19,%r20,%r19
+ ldw 56(%r4),%r20
+ ldw 56(%r4),%r21
+ ldw 16(%r20),%r20
+ ldw 4(%r21),%r21
+ sub %r20,%r21,%r20
+ comclr,> %r19,%r20,%r0
+ bl L$0135,%r0
+ nop
+ ldw 56(%r4),%r19
+ ldw 56(%r4),%r20
+ ldw 16(%r20),%r21
+ stw %r21,12(%r19)
+ copy %r21,%r19
+ bl,n L$0136,%r0
+L$0135:
+ copy %r0,%r19
+L$0136:
+ ldw 56(%r4),%r19
+ ldw 56(%r4),%r20
+ ldw 12(%r20),%r21
+ stw %r21,8(%r19)
+ ldw 60(%r4),%r11
+ bl,n L$0138,%r0
+L$0137:
+ ldw 32(%r4),%r20
+ ldo 2(%r20),%r19
+ zdep %r19,29,30,%r20
+ copy %r20,%r26
+ .CALL ARGW0=GR
+ bl xmalloc,%r2
+ nop
+ copy %r28,%r11
+L$0138:
+ stw %r11,36(%r4)
+ ldw 20(%r4),%r19
+ stw %r19,24(%r4)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r26
+ .CALL ARGW0=GR
+ bl lookup_pointer_type,%r2
+ nop
+ copy %r28,%r19
+ ldw 36(%r4),%r20
+ stw %r19,0(%r20)
+ ldo 1(%r0),%r19
+ stw %r19,32(%r4)
+ ldw 24(%r4),%r19
+ ldb 0(%r19),%r20
+ extrs %r20,31,8,%r19
+ ldo 41(%r0),%r20
+ comclr,<> %r19,%r20,%r0
+ bl L$0139,%r0
+ nop
+ stw %r0,28(%r4)
+L$0140:
+ ldw 24(%r4),%r19
+ ldb 0(%r19),%r20
+ extrs %r20,31,8,%r19
+ comiclr,<> 0,%r19,%r0
+ bl L$0141,%r0
+ nop
+ ldw 28(%r4),%r19
+ comiclr,>= 0,%r19,%r0
+ bl L$0142,%r0
+ nop
+ ldw 24(%r4),%r19
+ ldb 0(%r19),%r20
+ extrs %r20,31,8,%r19
+ ldo 44(%r0),%r20
+ comclr,<> %r19,%r20,%r0
+ bl L$0143,%r0
+ nop
+ ldw 24(%r4),%r19
+ ldb 0(%r19),%r20
+ extrs %r20,31,8,%r19
+ ldo 41(%r0),%r20
+ comclr,<> %r19,%r20,%r0
+ bl L$0143,%r0
+ nop
+ bl,n L$0142,%r0
+L$0143:
+ ldw 24(%r4),%r19
+ ldw 20(%r4),%r20
+ sub %r19,%r20,%r19
+ ldw 20(%r4),%r26
+ copy %r19,%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl parse_and_eval_type,%r2
+ nop
+ copy %r28,%r19
+ ldw 32(%r4),%r20
+ zdep %r20,29,30,%r21
+ ldw 36(%r4),%r22
+ add %r21,%r22,%r20
+ stw %r19,0(%r20)
+ ldw 32(%r4),%r19
+ ldo 1(%r19),%r20
+ stw %r20,32(%r4)
+ ldw 24(%r4),%r19
+ ldo 1(%r19),%r20
+ stw %r20,20(%r4)
+L$0142:
+ ldw 24(%r4),%r19
+ ldb 0(%r19),%r20
+ extrs %r20,31,8,%r19
+ ldo 40(%r0),%r20
+ comclr,= %r19,%r20,%r0
+ bl L$0144,%r0
+ nop
+ ldw 28(%r4),%r19
+ ldo 1(%r19),%r20
+ stw %r20,28(%r4)
+ bl,n L$0145,%r0
+L$0144:
+ ldw 24(%r4),%r19
+ ldb 0(%r19),%r20
+ extrs %r20,31,8,%r19
+ ldo 41(%r0),%r20
+ comclr,= %r19,%r20,%r0
+ bl L$0146,%r0
+ nop
+ ldw 28(%r4),%r19
+ ldo -1(%r19),%r20
+ stw %r20,28(%r4)
+L$0146:
+L$0145:
+ ldw 24(%r4),%r19
+ ldo 1(%r19),%r20
+ stw %r20,24(%r4)
+ bl,n L$0140,%r0
+L$0141:
+L$0139:
+ ldo -2(%r0),%r19
+ ldw 24(%r4),%r20
+ add %r19,%r20,%r19
+ ldb 0(%r19),%r20
+ extrs %r20,31,8,%r19
+ ldo 46(%r0),%r20
+ comclr,<> %r19,%r20,%r0
+ bl L$0147,%r0
+ nop
+ ldw 32(%r4),%r19
+ zdep %r19,29,30,%r20
+ ldw 36(%r4),%r21
+ add %r20,%r21,%r19
+ addil L'builtin_type_void-$global$,%r27
+ ldw R'builtin_type_void-$global$(%r1),%r20
+ stw %r20,0(%r19)
+ bl,n L$0148,%r0
+L$0147:
+ ldw 32(%r4),%r19
+ zdep %r19,29,30,%r20
+ ldw 36(%r4),%r21
+ add %r20,%r21,%r19
+ stw %r0,0(%r19)
+L$0148:
+ ldw 16(%r4),%r26
+ .CALL ARGW0=GR
+ bl free,%r2
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ ldw 48(%r20),%r19
+ ldo -8(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 0(%r20),%r21
+ zdep %r21,30,31,%r20
+ add %r20,%r21,%r20
+ zdep %r20,29,30,%r20
+ ldw 20(%r19),%r21
+ add %r20,%r21,%r19
+ ldw 8(%r19),%r20
+ stw %r20,8(%r4)
+ ldo -12(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ zdep %r20,29,30,%r19
+ add %r19,%r20,%r19
+ zdep %r19,29,30,%r19
+ ldw 8(%r4),%r20
+ add %r19,%r20,%r19
+ ldw 12(%r4),%r20
+ stw %r20,0(%r19)
+ ldo -12(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ zdep %r20,29,30,%r19
+ add %r19,%r20,%r19
+ zdep %r19,29,30,%r19
+ ldw 8(%r4),%r20
+ add %r19,%r20,%r19
+ ldw 4(%r19),%r20
+ stw %r20,40(%r4)
+ ldw 40(%r4),%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 0(%r20),%r21
+ stw %r21,40(%r19)
+ ldw 40(%r4),%r19
+ ldw 36(%r4),%r20
+ stw %r20,48(%r19)
+ ldw 40(%r4),%r19
+ ldw 40(%r4),%r20
+ ldh 32(%r20),%r21
+ copy %r21,%r20
+ depi 0,29,1,%r20
+ sth %r20,32(%r19)
+ ldo -12(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ zdep %r20,29,30,%r19
+ add %r19,%r20,%r19
+ zdep %r19,29,30,%r19
+ ldw 8(%r4),%r20
+ add %r19,%r20,%r19
+ ldw 16(%r19),%r20
+ copy %r20,%r21
+ depi 0,4,1,%r21
+ stw %r21,16(%r19)
+L$0123:
+ ldw 64(%r4),%r11
+ ldw 68(%r4),%r10
+ ldw 72(%r4),%r9
+ ldw 76(%r4),%r8
+ ldw 80(%r4),%r7
+ ldw 84(%r4),%r6
+ ldw 88(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .align 4
+ .EXPORT allocate_cplus_struct_type,CODE
+ .EXPORT allocate_cplus_struct_type,ENTRY,PRIV_LEV=3,ARGW0=GR
+allocate_cplus_struct_type:
+ .PROC
+ .CALLINFO FRAME=192,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,192(%r30)
+ stw %r8,32(%r4)
+ stw %r7,36(%r4)
+ stw %r6,40(%r4)
+ stw %r5,44(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ ldw 48(%r20),%r19
+ ldil L'cplus_struct_default,%r20
+ ldo R'cplus_struct_default(%r20),%r20
+ comclr,= %r19,%r20,%r0
+ bl L$0150,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r7
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 12(%r19),%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0156,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 12(%r19),%r20
+ ldo 120(%r20),%r19
+ stw %r19,8(%r4)
+ ldw 8(%r4),%r19
+ stw %r19,12(%r4)
+ ldo 24(%r0),%r19
+ stw %r19,16(%r4)
+ ldw 12(%r4),%r19
+ ldw 12(%r4),%r20
+ ldw 16(%r19),%r19
+ ldw 12(%r20),%r20
+ sub %r19,%r20,%r19
+ ldw 16(%r4),%r20
+ comclr,< %r19,%r20,%r0
+ bl L$0151,%r0
+ nop
+ ldw 12(%r4),%r26
+ ldw 16(%r4),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl _obstack_newchunk,%r2
+ nop
+ copy %r0,%r19
+ bl,n L$0152,%r0
+L$0151:
+ copy %r0,%r19
+L$0152:
+ ldw 12(%r4),%r19
+ ldw 12(%r4),%r20
+ ldw 12(%r20),%r21
+ ldw 16(%r4),%r22
+ add %r21,%r22,%r20
+ copy %r20,%r21
+ stw %r21,12(%r19)
+ ldw 8(%r4),%r19
+ stw %r19,20(%r4)
+ ldw 20(%r4),%r19
+ ldw 8(%r19),%r20
+ stw %r20,24(%r4)
+ ldw 20(%r4),%r19
+ ldw 12(%r19),%r20
+ ldw 24(%r4),%r19
+ comclr,= %r20,%r19,%r0
+ bl L$0153,%r0
+ nop
+ ldw 20(%r4),%r19
+ ldw 40(%r19),%r20
+ copy %r20,%r21
+ depi -1,1,1,%r21
+ stw %r21,40(%r19)
+L$0153:
+ ldw 20(%r4),%r19
+ ldw 20(%r4),%r20
+ ldw 20(%r4),%r21
+ ldw 12(%r20),%r20
+ ldw 24(%r21),%r21
+ add %r20,%r21,%r20
+ ldw 20(%r4),%r21
+ ldw 24(%r21),%r22
+ uaddcm %r0,%r22,%r21
+ and %r20,%r21,%r20
+ copy %r20,%r21
+ stw %r21,12(%r19)
+ ldw 20(%r4),%r19
+ ldw 20(%r4),%r20
+ ldw 12(%r19),%r19
+ ldw 4(%r20),%r20
+ sub %r19,%r20,%r19
+ ldw 20(%r4),%r20
+ ldw 20(%r4),%r21
+ ldw 16(%r20),%r20
+ ldw 4(%r21),%r21
+ sub %r20,%r21,%r20
+ comclr,> %r19,%r20,%r0
+ bl L$0154,%r0
+ nop
+ ldw 20(%r4),%r19
+ ldw 20(%r4),%r20
+ ldw 16(%r20),%r21
+ stw %r21,12(%r19)
+ copy %r21,%r19
+ bl,n L$0155,%r0
+L$0154:
+ copy %r0,%r19
+L$0155:
+ ldw 20(%r4),%r19
+ ldw 20(%r4),%r20
+ ldw 12(%r20),%r21
+ stw %r21,8(%r19)
+ ldw 24(%r4),%r8
+ bl,n L$0157,%r0
+L$0156:
+ ldo 24(%r0),%r26
+ .CALL ARGW0=GR
+ bl xmalloc,%r2
+ nop
+ copy %r28,%r8
+L$0157:
+ stw %r8,48(%r7)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 48(%r19),%r20
+ ldil L'cplus_struct_default,%r19
+ copy %r20,%r21
+ ldo R'cplus_struct_default(%r19),%r22
+ ldws,ma 4(%r22),%r19
+ ldws,ma 4(%r22),%r20
+ stws,ma %r19,4(%r21)
+ ldws,ma 4(%r22),%r19
+ stws,ma %r20,4(%r21)
+ ldws,ma 4(%r22),%r20
+ stws,ma %r19,4(%r21)
+ ldws,ma 4(%r22),%r19
+ stws,ma %r20,4(%r21)
+ ldws,ma 4(%r22),%r20
+ stws,ma %r19,4(%r21)
+ stw %r20,0(%r21)
+L$0150:
+L$0149:
+ ldw 32(%r4),%r8
+ ldw 36(%r4),%r7
+ ldw 40(%r4),%r6
+ ldw 44(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .IMPORT obsavestring,CODE
+ .align 4
+ .EXPORT init_type,CODE
+ .EXPORT init_type,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR
+init_type:
+ .PROC
+ .CALLINFO FRAME=192,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,192(%r30)
+ stw %r14,8(%r4)
+ stw %r13,12(%r4)
+ stw %r12,16(%r4)
+ stw %r11,20(%r4)
+ stw %r10,24(%r4)
+ stw %r9,28(%r4)
+ stw %r8,32(%r4)
+ stw %r7,36(%r4)
+ stw %r6,40(%r4)
+ stw %r5,44(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -8(%r0),%r7
+ ldo -32(%r4),%r19
+ add %r19,%r7,%r8
+ stw %r25,0(%r8)
+ ldo -12(%r0),%r9
+ ldo -32(%r4),%r19
+ add %r19,%r9,%r10
+ stw %r24,0(%r10)
+ ldo -16(%r0),%r11
+ ldo -32(%r4),%r19
+ add %r19,%r11,%r12
+ stw %r23,0(%r12)
+ ldo -20(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r26
+ .CALL ARGW0=GR
+ bl alloc_type,%r2
+ nop
+ copy %r28,%r13
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,0(%r13)
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,8(%r13)
+ ldo -12(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldh 32(%r13),%r20
+ ldh 2(%r19),%r19
+ or %r20,%r19,%r20
+ sth %r20,32(%r13)
+ ldo -16(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0159,%r0
+ nop
+ ldo -20(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0159,%r0
+ nop
+ ldo -16(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r14
+ ldo -16(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r26
+ .CALL ARGW0=GR
+ bl strlen,%r2
+ nop
+ copy %r28,%r19
+ ldo -20(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 0(%r20),%r21
+ ldo 120(%r21),%r20
+ ldw 0(%r14),%r26
+ copy %r19,%r25
+ copy %r20,%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl obsavestring,%r2
+ nop
+ copy %r28,%r19
+ stw %r19,4(%r13)
+ bl,n L$0160,%r0
+L$0159:
+ ldo -16(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,4(%r13)
+L$0160:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ comiclr,<> 3,%r20,%r0
+ bl L$0162,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ comiclr,<> 4,%r20,%r0
+ bl L$0162,%r0
+ nop
+ bl,n L$0161,%r0
+L$0162:
+ ldil L'cplus_struct_default,%r19
+ ldo R'cplus_struct_default(%r19),%r19
+ stw %r19,48(%r13)
+L$0161:
+ copy %r13,%r28
+ bl,n L$0158,%r0
+L$0158:
+ ldw 8(%r4),%r14
+ ldw 12(%r4),%r13
+ ldw 16(%r4),%r12
+ ldw 20(%r4),%r11
+ ldw 24(%r4),%r10
+ ldw 28(%r4),%r9
+ ldw 32(%r4),%r8
+ ldw 36(%r4),%r7
+ ldw 40(%r4),%r6
+ ldw 44(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .align 4
+LC$0022:
+ .STRING "internal error - invalid fundamental type id %d\x00"
+ .align 4
+LC$0023:
+ .STRING "internal error: unhandled type id %d\x00"
+ .align 4
+LC$0024:
+ .STRING "void\x00"
+ .align 4
+LC$0025:
+ .STRING "boolean\x00"
+ .align 4
+LC$0026:
+ .STRING "string\x00"
+ .align 4
+LC$0027:
+ .STRING "char\x00"
+ .align 4
+LC$0028:
+ .STRING "signed char\x00"
+ .align 4
+LC$0029:
+ .STRING "unsigned char\x00"
+ .align 4
+LC$0030:
+ .STRING "short\x00"
+ .align 4
+LC$0031:
+ .STRING "unsigned short\x00"
+ .align 4
+LC$0032:
+ .STRING "int\x00"
+ .align 4
+LC$0033:
+ .STRING "unsigned int\x00"
+ .align 4
+LC$0034:
+ .STRING "fixed decimal\x00"
+ .align 4
+LC$0035:
+ .STRING "long\x00"
+ .align 4
+LC$0036:
+ .STRING "unsigned long\x00"
+ .align 4
+LC$0037:
+ .STRING "long long\x00"
+ .align 4
+LC$0038:
+ .STRING "signed long long\x00"
+ .align 4
+LC$0039:
+ .STRING "unsigned long long\x00"
+ .align 4
+LC$0040:
+ .STRING "float\x00"
+ .align 4
+LC$0041:
+ .STRING "double\x00"
+ .align 4
+LC$0042:
+ .STRING "floating decimal\x00"
+ .align 4
+LC$0043:
+ .STRING "long double\x00"
+ .align 4
+LC$0044:
+ .STRING "complex\x00"
+ .align 4
+LC$0045:
+ .STRING "double complex\x00"
+ .align 4
+LC$0046:
+ .STRING "long double complex\x00"
+ .align 4
+ .EXPORT lookup_fundamental_type,CODE
+ .EXPORT lookup_fundamental_type,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,RTNVAL=GR
+lookup_fundamental_type:
+ .PROC
+ .CALLINFO FRAME=192,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,192(%r30)
+ stw %r12,32(%r4)
+ stw %r11,36(%r4)
+ stw %r10,40(%r4)
+ stw %r9,44(%r4)
+ stw %r8,48(%r4)
+ stw %r7,52(%r4)
+ stw %r6,56(%r4)
+ stw %r5,60(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -8(%r0),%r7
+ ldo -32(%r4),%r19
+ add %r19,%r7,%r8
+ stw %r25,0(%r8)
+ copy %r0,%r9
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ comiclr,<= 0,%r20,%r0
+ bl L$0165,%r0
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ ldo 25(%r0),%r19
+ comclr,<= %r20,%r19,%r0
+ bl L$0165,%r0
+ nop
+ bl,n L$0164,%r0
+L$0165:
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldil L'LC$0022,%r26
+ ldo R'LC$0022(%r26),%r26
+ ldw 0(%r19),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl error,%r2
+ nop
+ bl,n L$0166,%r0
+L$0164:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 196(%r19),%r20
+ comiclr,= 0,%r20,%r0
+ bl L$0167,%r0
+ nop
+ ldo 104(%r0),%r11
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r12
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldo 120(%r19),%r20
+ stw %r20,8(%r4)
+ ldw 8(%r4),%r19
+ stw %r19,12(%r4)
+ stw %r11,16(%r4)
+ ldw 12(%r4),%r19
+ ldw 12(%r4),%r20
+ ldw 16(%r19),%r19
+ ldw 12(%r20),%r20
+ sub %r19,%r20,%r19
+ ldw 16(%r4),%r20
+ comclr,< %r19,%r20,%r0
+ bl L$0168,%r0
+ nop
+ ldw 12(%r4),%r26
+ ldw 16(%r4),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl _obstack_newchunk,%r2
+ nop
+ copy %r0,%r19
+ bl,n L$0169,%r0
+L$0168:
+ copy %r0,%r19
+L$0169:
+ ldw 12(%r4),%r19
+ ldw 12(%r4),%r20
+ ldw 12(%r20),%r21
+ ldw 16(%r4),%r22
+ add %r21,%r22,%r20
+ copy %r20,%r21
+ stw %r21,12(%r19)
+ ldw 8(%r4),%r19
+ stw %r19,20(%r4)
+ ldw 20(%r4),%r19
+ ldw 8(%r19),%r20
+ stw %r20,24(%r4)
+ ldw 20(%r4),%r19
+ ldw 12(%r19),%r20
+ ldw 24(%r4),%r19
+ comclr,= %r20,%r19,%r0
+ bl L$0170,%r0
+ nop
+ ldw 20(%r4),%r19
+ ldw 40(%r19),%r20
+ copy %r20,%r21
+ depi -1,1,1,%r21
+ stw %r21,40(%r19)
+L$0170:
+ ldw 20(%r4),%r19
+ ldw 20(%r4),%r20
+ ldw 20(%r4),%r21
+ ldw 12(%r20),%r20
+ ldw 24(%r21),%r21
+ add %r20,%r21,%r20
+ ldw 20(%r4),%r21
+ ldw 24(%r21),%r22
+ uaddcm %r0,%r22,%r21
+ and %r20,%r21,%r20
+ copy %r20,%r21
+ stw %r21,12(%r19)
+ ldw 20(%r4),%r19
+ ldw 20(%r4),%r20
+ ldw 12(%r19),%r19
+ ldw 4(%r20),%r20
+ sub %r19,%r20,%r19
+ ldw 20(%r4),%r20
+ ldw 20(%r4),%r21
+ ldw 16(%r20),%r20
+ ldw 4(%r21),%r21
+ sub %r20,%r21,%r20
+ comclr,> %r19,%r20,%r0
+ bl L$0171,%r0
+ nop
+ ldw 20(%r4),%r19
+ ldw 20(%r4),%r20
+ ldw 16(%r20),%r21
+ stw %r21,12(%r19)
+ copy %r21,%r19
+ bl,n L$0172,%r0
+L$0171:
+ copy %r0,%r19
+L$0172:
+ ldw 20(%r4),%r19
+ ldw 20(%r4),%r20
+ ldw 12(%r20),%r21
+ stw %r21,8(%r19)
+ ldw 24(%r4),%r19
+ stw %r19,196(%r12)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 196(%r19),%r26
+ copy %r0,%r25
+ copy %r11,%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl memset,%r2
+ nop
+L$0167:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldo -8(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 0(%r20),%r21
+ zdep %r21,29,30,%r20
+ ldw 196(%r19),%r19
+ add %r20,%r19,%r10
+ ldw 0(%r10),%r9
+ comiclr,= 0,%r9,%r0
+ bl L$0173,%r0
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ addi,uv -26,%r20,%r0
+ blr,n %r20,%r0
+ b,n L$0175
+L$0202:
+ b L$0176
+ nop
+ b L$0177
+ nop
+ b L$0179
+ nop
+ b L$0180
+ nop
+ b L$0181
+ nop
+ b L$0182
+ nop
+ b L$0183
+ nop
+ b L$0184
+ nop
+ b L$0185
+ nop
+ b L$0186
+ nop
+ b L$0187
+ nop
+ b L$0189
+ nop
+ b L$0190
+ nop
+ b L$0191
+ nop
+ b L$0192
+ nop
+ b L$0193
+ nop
+ b L$0194
+ nop
+ b L$0195
+ nop
+ b L$0196
+ nop
+ b L$0198
+ nop
+ b L$0199
+ nop
+ b L$0200
+ nop
+ b L$0201
+ nop
+ b L$0178
+ nop
+ b L$0188
+ nop
+ b L$0197
+ nop
+L$0175:
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldil L'LC$0023,%r26
+ ldo R'LC$0023(%r26),%r26
+ ldw 0(%r19),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl error,%r2
+ nop
+ bl,n L$0174,%r0
+L$0176:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 9(%r0),%r26
+ ldo 1(%r0),%r25
+ copy %r0,%r24
+ ldil L'LC$0024,%r23
+ ldo R'LC$0024(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0177:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 7(%r0),%r26
+ ldo 4(%r0),%r25
+ ldo 1(%r0),%r24
+ ldil L'LC$0025,%r23
+ ldo R'LC$0025(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0178:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 12(%r0),%r26
+ ldo 1(%r0),%r25
+ copy %r0,%r24
+ ldil L'LC$0026,%r23
+ ldo R'LC$0026(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0179:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 7(%r0),%r26
+ ldo 1(%r0),%r25
+ copy %r0,%r24
+ ldil L'LC$0027,%r23
+ ldo R'LC$0027(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0180:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 7(%r0),%r26
+ ldo 1(%r0),%r25
+ ldo 2(%r0),%r24
+ ldil L'LC$0028,%r23
+ ldo R'LC$0028(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0181:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 7(%r0),%r26
+ ldo 1(%r0),%r25
+ ldo 1(%r0),%r24
+ ldil L'LC$0029,%r23
+ ldo R'LC$0029(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0182:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 7(%r0),%r26
+ ldo 2(%r0),%r25
+ copy %r0,%r24
+ ldil L'LC$0030,%r23
+ ldo R'LC$0030(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0183:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 7(%r0),%r26
+ ldo 2(%r0),%r25
+ ldo 2(%r0),%r24
+ ldil L'LC$0030,%r23
+ ldo R'LC$0030(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0184:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 7(%r0),%r26
+ ldo 2(%r0),%r25
+ ldo 1(%r0),%r24
+ ldil L'LC$0031,%r23
+ ldo R'LC$0031(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0185:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 7(%r0),%r26
+ ldo 4(%r0),%r25
+ copy %r0,%r24
+ ldil L'LC$0032,%r23
+ ldo R'LC$0032(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0186:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 7(%r0),%r26
+ ldo 4(%r0),%r25
+ ldo 2(%r0),%r24
+ ldil L'LC$0032,%r23
+ ldo R'LC$0032(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0187:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 7(%r0),%r26
+ ldo 4(%r0),%r25
+ ldo 1(%r0),%r24
+ ldil L'LC$0033,%r23
+ ldo R'LC$0033(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0188:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 7(%r0),%r26
+ ldo 4(%r0),%r25
+ copy %r0,%r24
+ ldil L'LC$0034,%r23
+ ldo R'LC$0034(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0189:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 7(%r0),%r26
+ ldo 4(%r0),%r25
+ copy %r0,%r24
+ ldil L'LC$0035,%r23
+ ldo R'LC$0035(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0190:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 7(%r0),%r26
+ ldo 4(%r0),%r25
+ ldo 2(%r0),%r24
+ ldil L'LC$0035,%r23
+ ldo R'LC$0035(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0191:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 7(%r0),%r26
+ ldo 4(%r0),%r25
+ ldo 1(%r0),%r24
+ ldil L'LC$0036,%r23
+ ldo R'LC$0036(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0192:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 7(%r0),%r26
+ ldo 8(%r0),%r25
+ copy %r0,%r24
+ ldil L'LC$0037,%r23
+ ldo R'LC$0037(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0193:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 7(%r0),%r26
+ ldo 8(%r0),%r25
+ ldo 2(%r0),%r24
+ ldil L'LC$0038,%r23
+ ldo R'LC$0038(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0194:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 7(%r0),%r26
+ ldo 8(%r0),%r25
+ ldo 1(%r0),%r24
+ ldil L'LC$0039,%r23
+ ldo R'LC$0039(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0195:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 8(%r0),%r26
+ ldo 4(%r0),%r25
+ copy %r0,%r24
+ ldil L'LC$0040,%r23
+ ldo R'LC$0040(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0196:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 8(%r0),%r26
+ ldo 8(%r0),%r25
+ copy %r0,%r24
+ ldil L'LC$0041,%r23
+ ldo R'LC$0041(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0197:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 8(%r0),%r26
+ ldo 8(%r0),%r25
+ copy %r0,%r24
+ ldil L'LC$0042,%r23
+ ldo R'LC$0042(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0198:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 8(%r0),%r26
+ ldo 16(%r0),%r25
+ copy %r0,%r24
+ ldil L'LC$0043,%r23
+ ldo R'LC$0043(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0199:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 8(%r0),%r26
+ ldo 8(%r0),%r25
+ copy %r0,%r24
+ ldil L'LC$0044,%r23
+ ldo R'LC$0044(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0200:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 8(%r0),%r26
+ ldo 16(%r0),%r25
+ copy %r0,%r24
+ ldil L'LC$0045,%r23
+ ldo R'LC$0045(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0201:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ stw %r20,-52(%r30)
+ ldo 8(%r0),%r26
+ ldo 16(%r0),%r25
+ copy %r0,%r24
+ ldil L'LC$0046,%r23
+ ldo R'LC$0046(%r23),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl init_type,%r2
+ nop
+ copy %r28,%r9
+ bl,n L$0174,%r0
+L$0174:
+ stw %r9,0(%r10)
+L$0173:
+L$0166:
+ copy %r9,%r28
+ bl,n L$0163,%r0
+L$0163:
+ ldw 32(%r4),%r12
+ ldw 36(%r4),%r11
+ ldw 40(%r4),%r10
+ ldw 44(%r4),%r9
+ ldw 48(%r4),%r8
+ ldw 52(%r4),%r7
+ ldw 56(%r4),%r6
+ ldw 60(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .IMPORT puts_filtered,CODE
+ .align 4
+LC$0047:
+ .STRING " \x00"
+ .IMPORT printf_filtered,CODE
+ .align 4
+LC$0048:
+ .STRING "1\x00"
+ .align 4
+LC$0049:
+ .STRING "0\x00"
+ .align 4
+print_bit_vector:
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,128(%r30)
+ stw %r8,16(%r4)
+ stw %r7,20(%r4)
+ stw %r6,24(%r4)
+ stw %r5,28(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -8(%r0),%r7
+ ldo -32(%r4),%r19
+ add %r19,%r7,%r8
+ stw %r25,0(%r8)
+ stw %r0,8(%r4)
+L$0204:
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 8(%r4),%r20
+ ldw 0(%r19),%r19
+ comclr,< %r20,%r19,%r0
+ bl L$0205,%r0
+ nop
+ ldw 8(%r4),%r19
+ ldw 8(%r4),%r20
+ comiclr,> 0,%r19,%r0
+ bl L$0208,%r0
+ nop
+ ldo 7(%r19),%r19
+L$0208:
+ extrs %r19,28,29,%r19
+ zdep %r19,28,29,%r21
+ sub %r20,%r21,%r19
+ comiclr,= 0,%r19,%r0
+ bl L$0207,%r0
+ nop
+ ldil L'LC$0047,%r26
+ ldo R'LC$0047(%r26),%r26
+ .CALL ARGW0=GR
+ bl puts_filtered,%r2
+ nop
+L$0207:
+ ldw 8(%r4),%r20
+ extrs %r20,28,29,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 0(%r20),%r21
+ add %r19,%r21,%r20
+ ldb 0(%r20),%r19
+ ldw 8(%r4),%r20
+ extru %r20,31,3,%r21
+ subi,>>= 31,%r21,%r20
+ copy %r0,%r20
+ mtsar %r20
+ vextrs %r19,32,%r19
+ extru %r19,31,1,%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0209,%r0
+ nop
+ ldil L'LC$0048,%r26
+ ldo R'LC$0048(%r26),%r26
+ .CALL ARGW0=GR
+ bl printf_filtered,%r2
+ nop
+ bl,n L$0210,%r0
+L$0209:
+ ldil L'LC$0049,%r26
+ ldo R'LC$0049(%r26),%r26
+ .CALL ARGW0=GR
+ bl printf_filtered,%r2
+ nop
+L$0210:
+L$0206:
+ ldw 8(%r4),%r19
+ ldo 1(%r19),%r20
+ stw %r20,8(%r4)
+ bl,n L$0204,%r0
+L$0205:
+L$0203:
+ ldw 16(%r4),%r8
+ ldw 20(%r4),%r7
+ ldw 24(%r4),%r6
+ ldw 28(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .IMPORT recursive_dump_type,CODE
+ .align 4
+print_arg_types:
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,128(%r30)
+ stw %r8,8(%r4)
+ stw %r7,12(%r4)
+ stw %r6,16(%r4)
+ stw %r5,20(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -8(%r0),%r7
+ ldo -32(%r4),%r19
+ add %r19,%r7,%r8
+ stw %r25,0(%r8)
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0212,%r0
+ nop
+L$0213:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 0(%r19),%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0214,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldo -8(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 0(%r20),%r21
+ ldo 2(%r21),%r20
+ ldw 0(%r19),%r26
+ copy %r20,%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl recursive_dump_type,%r2
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ ldo 4(%r20),%r21
+ stw %r21,0(%r19)
+ ldw 0(%r20),%r19
+ ldw 0(%r19),%r20
+ comiclr,= 9,%r20,%r0
+ bl L$0215,%r0
+ nop
+ bl,n L$0214,%r0
+L$0215:
+ bl,n L$0213,%r0
+L$0214:
+L$0212:
+L$0211:
+ ldw 8(%r4),%r8
+ ldw 12(%r4),%r7
+ ldw 16(%r4),%r6
+ ldw 20(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .IMPORT printfi_filtered,CODE
+ .align 4
+LC$0050:
+ .STRING "fn_fieldlists 0x%x\x0a\x00"
+ .align 4
+LC$0051:
+ .STRING "[%d] name '%s' (0x%x) length %d\x0a\x00"
+ .align 4
+LC$0052:
+ .STRING "[%d] physname '%s' (0x%x)\x0a\x00"
+ .align 4
+LC$0053:
+ .STRING "type 0x%x\x0a\x00"
+ .align 4
+LC$0054:
+ .STRING "args 0x%x\x0a\x00"
+ .align 4
+LC$0055:
+ .STRING "fcontext 0x%x\x0a\x00"
+ .align 4
+LC$0056:
+ .STRING "is_const %d\x0a\x00"
+ .align 4
+LC$0057:
+ .STRING "is_volatile %d\x0a\x00"
+ .align 4
+LC$0058:
+ .STRING "is_private %d\x0a\x00"
+ .align 4
+LC$0059:
+ .STRING "is_protected %d\x0a\x00"
+ .align 4
+LC$0060:
+ .STRING "is_stub %d\x0a\x00"
+ .align 4
+LC$0061:
+ .STRING "voffset %u\x0a\x00"
+ .align 4
+dump_fn_fieldlists:
+ .PROC
+ .CALLINFO FRAME=192,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,192(%r30)
+ stw %r8,24(%r4)
+ stw %r7,28(%r4)
+ stw %r6,32(%r4)
+ stw %r5,36(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -8(%r0),%r7
+ ldo -32(%r4),%r19
+ add %r19,%r7,%r8
+ stw %r25,0(%r8)
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 0(%r20),%r21
+ ldw 48(%r21),%r20
+ ldw 0(%r19),%r26
+ ldil L'LC$0050,%r25
+ ldo R'LC$0050(%r25),%r25
+ ldw 20(%r20),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ stw %r0,8(%r4)
+L$0217:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 48(%r19),%r20
+ ldh 2(%r20),%r21
+ extrs %r21,31,16,%r19
+ ldw 8(%r4),%r20
+ comclr,< %r20,%r19,%r0
+ bl L$0218,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ ldw 48(%r20),%r19
+ ldw 8(%r4),%r21
+ zdep %r21,30,31,%r20
+ add %r20,%r21,%r20
+ zdep %r20,29,30,%r20
+ ldw 20(%r19),%r21
+ add %r20,%r21,%r19
+ ldw 8(%r19),%r20
+ stw %r20,16(%r4)
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ ldo 2(%r20),%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 0(%r20),%r21
+ ldw 48(%r21),%r20
+ ldw 8(%r4),%r22
+ zdep %r22,30,31,%r21
+ add %r21,%r22,%r21
+ zdep %r21,29,30,%r21
+ ldw 20(%r20),%r22
+ add %r21,%r22,%r20
+ ldo -4(%r0),%r21
+ ldo -32(%r4),%r22
+ add %r22,%r21,%r21
+ ldw 0(%r21),%r22
+ ldw 48(%r22),%r21
+ ldw 8(%r4),%r23
+ zdep %r23,30,31,%r22
+ add %r22,%r23,%r22
+ zdep %r22,29,30,%r22
+ ldw 20(%r21),%r23
+ add %r22,%r23,%r21
+ ldw 0(%r21),%r22
+ stw %r22,-52(%r30)
+ ldo -4(%r0),%r21
+ ldo -32(%r4),%r22
+ add %r22,%r21,%r21
+ ldw 0(%r21),%r22
+ ldw 48(%r22),%r21
+ ldw 8(%r4),%r23
+ zdep %r23,30,31,%r22
+ add %r22,%r23,%r22
+ zdep %r22,29,30,%r22
+ ldw 20(%r21),%r23
+ add %r22,%r23,%r21
+ ldw 4(%r21),%r22
+ stw %r22,-56(%r30)
+ copy %r19,%r26
+ ldil L'LC$0051,%r25
+ ldo R'LC$0051(%r25),%r25
+ ldw 8(%r4),%r24
+ ldw 0(%r20),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl printfi_filtered,%r2
+ nop
+ stw %r0,12(%r4)
+L$0220:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ ldw 48(%r20),%r19
+ ldw 8(%r4),%r21
+ zdep %r21,30,31,%r20
+ add %r20,%r21,%r20
+ zdep %r20,29,30,%r20
+ ldw 20(%r19),%r21
+ add %r20,%r21,%r19
+ ldw 12(%r4),%r20
+ ldw 4(%r19),%r19
+ comclr,< %r20,%r19,%r0
+ bl L$0221,%r0
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ ldo 4(%r20),%r19
+ ldw 12(%r4),%r21
+ zdep %r21,29,30,%r20
+ add %r20,%r21,%r20
+ zdep %r20,29,30,%r20
+ ldw 16(%r4),%r21
+ add %r20,%r21,%r20
+ ldw 12(%r4),%r22
+ zdep %r22,29,30,%r21
+ add %r21,%r22,%r21
+ zdep %r21,29,30,%r21
+ ldw 16(%r4),%r22
+ add %r21,%r22,%r21
+ ldw 0(%r21),%r22
+ stw %r22,-52(%r30)
+ copy %r19,%r26
+ ldil L'LC$0052,%r25
+ ldo R'LC$0052(%r25),%r25
+ ldw 12(%r4),%r24
+ ldw 0(%r20),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ ldo 8(%r20),%r19
+ ldw 12(%r4),%r21
+ zdep %r21,29,30,%r20
+ add %r20,%r21,%r20
+ zdep %r20,29,30,%r20
+ ldw 16(%r4),%r21
+ add %r20,%r21,%r20
+ copy %r19,%r26
+ ldil L'LC$0053,%r25
+ ldo R'LC$0053(%r25),%r25
+ ldw 4(%r20),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldw 12(%r4),%r20
+ zdep %r20,29,30,%r19
+ add %r19,%r20,%r19
+ zdep %r19,29,30,%r19
+ ldw 16(%r4),%r20
+ add %r19,%r20,%r19
+ ldo -8(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 0(%r20),%r21
+ ldo 10(%r21),%r20
+ ldw 4(%r19),%r26
+ copy %r20,%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl recursive_dump_type,%r2
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ ldo 8(%r20),%r19
+ ldw 12(%r4),%r21
+ zdep %r21,29,30,%r20
+ add %r20,%r21,%r20
+ zdep %r20,29,30,%r20
+ ldw 16(%r4),%r22
+ add %r20,%r22,%r21
+ ldw 4(%r21),%r20
+ copy %r19,%r26
+ ldil L'LC$0054,%r25
+ ldo R'LC$0054(%r25),%r25
+ ldw 48(%r20),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldw 12(%r4),%r20
+ zdep %r20,29,30,%r19
+ add %r19,%r20,%r19
+ zdep %r19,29,30,%r19
+ ldw 16(%r4),%r21
+ add %r19,%r21,%r20
+ ldw 4(%r20),%r19
+ ldo -8(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 48(%r19),%r26
+ ldw 0(%r20),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl print_arg_types,%r2
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ ldo 8(%r20),%r19
+ ldw 12(%r4),%r21
+ zdep %r21,29,30,%r20
+ add %r20,%r21,%r20
+ zdep %r20,29,30,%r20
+ ldw 16(%r4),%r21
+ add %r20,%r21,%r20
+ copy %r19,%r26
+ ldil L'LC$0055,%r25
+ ldo R'LC$0055(%r25),%r25
+ ldw 12(%r20),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ ldo 8(%r20),%r19
+ ldw 12(%r4),%r21
+ zdep %r21,29,30,%r20
+ add %r20,%r21,%r20
+ zdep %r20,29,30,%r20
+ ldw 16(%r4),%r21
+ add %r20,%r21,%r20
+ ldw 16(%r20),%r21
+ extru %r21,0+1-1,1,%r20
+ copy %r19,%r26
+ ldil L'LC$0056,%r25
+ ldo R'LC$0056(%r25),%r25
+ copy %r20,%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ ldo 8(%r20),%r19
+ ldw 12(%r4),%r21
+ zdep %r21,29,30,%r20
+ add %r20,%r21,%r20
+ zdep %r20,29,30,%r20
+ ldw 16(%r4),%r21
+ add %r20,%r21,%r20
+ ldw 16(%r20),%r21
+ extru %r21,1+1-1,1,%r20
+ copy %r19,%r26
+ ldil L'LC$0057,%r25
+ ldo R'LC$0057(%r25),%r25
+ copy %r20,%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ ldo 8(%r20),%r19
+ ldw 12(%r4),%r21
+ zdep %r21,29,30,%r20
+ add %r20,%r21,%r20
+ zdep %r20,29,30,%r20
+ ldw 16(%r4),%r21
+ add %r20,%r21,%r20
+ ldw 16(%r20),%r21
+ extru %r21,2+1-1,1,%r20
+ copy %r19,%r26
+ ldil L'LC$0058,%r25
+ ldo R'LC$0058(%r25),%r25
+ copy %r20,%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ ldo 8(%r20),%r19
+ ldw 12(%r4),%r21
+ zdep %r21,29,30,%r20
+ add %r20,%r21,%r20
+ zdep %r20,29,30,%r20
+ ldw 16(%r4),%r21
+ add %r20,%r21,%r20
+ ldw 16(%r20),%r21
+ extru %r21,3+1-1,1,%r20
+ copy %r19,%r26
+ ldil L'LC$0059,%r25
+ ldo R'LC$0059(%r25),%r25
+ copy %r20,%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ ldo 8(%r20),%r19
+ ldw 12(%r4),%r21
+ zdep %r21,29,30,%r20
+ add %r20,%r21,%r20
+ zdep %r20,29,30,%r20
+ ldw 16(%r4),%r21
+ add %r20,%r21,%r20
+ ldw 16(%r20),%r21
+ extru %r21,4+1-1,1,%r20
+ copy %r19,%r26
+ ldil L'LC$0060,%r25
+ ldo R'LC$0060(%r25),%r25
+ copy %r20,%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ ldo 8(%r20),%r19
+ ldw 12(%r4),%r21
+ zdep %r21,29,30,%r20
+ add %r20,%r21,%r20
+ zdep %r20,29,30,%r20
+ ldw 16(%r4),%r21
+ add %r20,%r21,%r20
+ ldw 16(%r20),%r21
+ extru %r21,8+24-1,24,%r22
+ ldo -2(%r22),%r20
+ copy %r19,%r26
+ ldil L'LC$0061,%r25
+ ldo R'LC$0061(%r25),%r25
+ copy %r20,%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+L$0222:
+ ldw 12(%r4),%r19
+ ldo 1(%r19),%r20
+ stw %r20,12(%r4)
+ bl,n L$0220,%r0
+L$0221:
+L$0219:
+ ldw 8(%r4),%r19
+ ldo 1(%r19),%r20
+ stw %r20,8(%r4)
+ bl,n L$0217,%r0
+L$0218:
+L$0216:
+ ldw 24(%r4),%r8
+ ldw 28(%r4),%r7
+ ldw 32(%r4),%r6
+ ldw 36(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .align 4
+LC$0062:
+ .STRING "n_baseclasses %d\x0a\x00"
+ .align 4
+LC$0063:
+ .STRING "nfn_fields %d\x0a\x00"
+ .align 4
+LC$0064:
+ .STRING "nfn_fields_total %d\x0a\x00"
+ .align 4
+LC$0065:
+ .STRING "virtual_field_bits (%d bits at *0x%x)\x00"
+ .align 4
+LC$0066:
+ .STRING "\x0a\x00"
+ .align 4
+LC$0067:
+ .STRING "private_field_bits (%d bits at *0x%x)\x00"
+ .align 4
+LC$0068:
+ .STRING "protected_field_bits (%d bits at *0x%x)\x00"
+ .align 4
+print_cplus_stuff:
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,128(%r30)
+ stw %r8,16(%r4)
+ stw %r7,20(%r4)
+ stw %r6,24(%r4)
+ stw %r5,28(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -8(%r0),%r7
+ ldo -32(%r4),%r19
+ add %r19,%r7,%r8
+ stw %r25,0(%r8)
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldw 48(%r20),%r21
+ ldh 0(%r21),%r22
+ extrs %r22,31,16,%r20
+ ldw 0(%r19),%r26
+ ldil L'LC$0062,%r25
+ ldo R'LC$0062(%r25),%r25
+ copy %r20,%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldw 48(%r20),%r21
+ ldh 2(%r21),%r22
+ extrs %r22,31,16,%r20
+ ldw 0(%r19),%r26
+ ldil L'LC$0063,%r25
+ ldo R'LC$0063(%r25),%r25
+ copy %r20,%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 0(%r20),%r21
+ ldw 48(%r21),%r20
+ ldw 0(%r19),%r26
+ ldil L'LC$0064,%r25
+ ldo R'LC$0064(%r25),%r25
+ ldw 4(%r20),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 48(%r19),%r20
+ ldh 0(%r20),%r21
+ extrs %r21,31,16,%r19
+ comiclr,< 0,%r19,%r0
+ bl L$0224,%r0
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldw 48(%r20),%r21
+ ldh 0(%r21),%r22
+ extrs %r22,31,16,%r20
+ ldo -4(%r0),%r21
+ ldo -32(%r4),%r22
+ add %r22,%r21,%r21
+ ldw 0(%r21),%r22
+ ldw 48(%r22),%r21
+ ldw 0(%r19),%r26
+ ldil L'LC$0065,%r25
+ ldo R'LC$0065(%r25),%r25
+ copy %r20,%r24
+ ldw 8(%r21),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ ldw 48(%r20),%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldw 48(%r20),%r21
+ ldh 0(%r21),%r22
+ extrs %r22,31,16,%r20
+ ldw 8(%r19),%r26
+ copy %r20,%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl print_bit_vector,%r2
+ nop
+ ldil L'LC$0066,%r26
+ ldo R'LC$0066(%r26),%r26
+ .CALL ARGW0=GR
+ bl puts_filtered,%r2
+ nop
+L$0224:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldh 34(%r19),%r20
+ extrs %r20,31,16,%r19
+ comiclr,< 0,%r19,%r0
+ bl L$0225,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 48(%r19),%r20
+ ldw 12(%r20),%r19
+ comiclr,<> 0,%r19,%r0
+ bl L$0226,%r0
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldh 34(%r20),%r21
+ extrs %r21,31,16,%r20
+ ldo -4(%r0),%r21
+ ldo -32(%r4),%r22
+ add %r22,%r21,%r21
+ ldw 0(%r21),%r22
+ ldw 48(%r22),%r21
+ ldw 0(%r19),%r26
+ ldil L'LC$0067,%r25
+ ldo R'LC$0067(%r25),%r25
+ copy %r20,%r24
+ ldw 12(%r21),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ ldw 48(%r20),%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldh 34(%r20),%r21
+ extrs %r21,31,16,%r20
+ ldw 12(%r19),%r26
+ copy %r20,%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl print_bit_vector,%r2
+ nop
+ ldil L'LC$0066,%r26
+ ldo R'LC$0066(%r26),%r26
+ .CALL ARGW0=GR
+ bl puts_filtered,%r2
+ nop
+L$0226:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 48(%r19),%r20
+ ldw 16(%r20),%r19
+ comiclr,<> 0,%r19,%r0
+ bl L$0227,%r0
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldh 34(%r20),%r21
+ extrs %r21,31,16,%r20
+ ldo -4(%r0),%r21
+ ldo -32(%r4),%r22
+ add %r22,%r21,%r21
+ ldw 0(%r21),%r22
+ ldw 48(%r22),%r21
+ ldw 0(%r19),%r26
+ ldil L'LC$0068,%r25
+ ldo R'LC$0068(%r25),%r25
+ copy %r20,%r24
+ ldw 16(%r21),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ ldw 48(%r20),%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldh 34(%r20),%r21
+ extrs %r21,31,16,%r20
+ ldw 16(%r19),%r26
+ copy %r20,%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl print_bit_vector,%r2
+ nop
+ ldil L'LC$0066,%r26
+ ldo R'LC$0066(%r26),%r26
+ .CALL ARGW0=GR
+ bl puts_filtered,%r2
+ nop
+L$0227:
+L$0225:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 48(%r19),%r20
+ ldh 2(%r20),%r21
+ extrs %r21,31,16,%r19
+ comiclr,< 0,%r19,%r0
+ bl L$0228,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -8(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 0(%r19),%r26
+ ldw 0(%r20),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl dump_fn_fieldlists,%r2
+ nop
+L$0228:
+L$0223:
+ ldw 16(%r4),%r8
+ ldw 20(%r4),%r7
+ ldw 24(%r4),%r6
+ ldw 28(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .align 4
+LC$0069:
+ .STRING "type node 0x%x\x0a\x00"
+ .align 4
+LC$0070:
+ .STRING "name '%s' (0x%x)\x0a\x00"
+ .align 4
+LC$0071:
+ .STRING "<NULL>\x00"
+ .align 4
+LC$0072:
+ .STRING "code 0x%x \x00"
+ .align 4
+LC$0073:
+ .STRING "(TYPE_CODE_UNDEF)\x00"
+ .align 4
+LC$0074:
+ .STRING "(TYPE_CODE_PTR)\x00"
+ .align 4
+LC$0075:
+ .STRING "(TYPE_CODE_ARRAY)\x00"
+ .align 4
+LC$0076:
+ .STRING "(TYPE_CODE_STRUCT)\x00"
+ .align 4
+LC$0077:
+ .STRING "(TYPE_CODE_UNION)\x00"
+ .align 4
+LC$0078:
+ .STRING "(TYPE_CODE_ENUM)\x00"
+ .align 4
+LC$0079:
+ .STRING "(TYPE_CODE_FUNC)\x00"
+ .align 4
+LC$0080:
+ .STRING "(TYPE_CODE_INT)\x00"
+ .align 4
+LC$0081:
+ .STRING "(TYPE_CODE_FLT)\x00"
+ .align 4
+LC$0082:
+ .STRING "(TYPE_CODE_VOID)\x00"
+ .align 4
+LC$0083:
+ .STRING "(TYPE_CODE_SET)\x00"
+ .align 4
+LC$0084:
+ .STRING "(TYPE_CODE_RANGE)\x00"
+ .align 4
+LC$0085:
+ .STRING "(TYPE_CODE_PASCAL_ARRAY)\x00"
+ .align 4
+LC$0086:
+ .STRING "(TYPE_CODE_ERROR)\x00"
+ .align 4
+LC$0087:
+ .STRING "(TYPE_CODE_MEMBER)\x00"
+ .align 4
+LC$0088:
+ .STRING "(TYPE_CODE_METHOD)\x00"
+ .align 4
+LC$0089:
+ .STRING "(TYPE_CODE_REF)\x00"
+ .align 4
+LC$0090:
+ .STRING "(TYPE_CODE_CHAR)\x00"
+ .align 4
+LC$0091:
+ .STRING "(TYPE_CODE_BOOL)\x00"
+ .align 4
+LC$0092:
+ .STRING "(UNKNOWN TYPE CODE)\x00"
+ .align 4
+LC$0093:
+ .STRING "length %d\x0a\x00"
+ .align 4
+LC$0094:
+ .STRING "objfile 0x%x\x0a\x00"
+ .align 4
+LC$0095:
+ .STRING "target_type 0x%x\x0a\x00"
+ .align 4
+LC$0096:
+ .STRING "pointer_type 0x%x\x0a\x00"
+ .align 4
+LC$0097:
+ .STRING "reference_type 0x%x\x0a\x00"
+ .align 4
+LC$0098:
+ .STRING "function_type 0x%x\x0a\x00"
+ .align 4
+LC$0099:
+ .STRING "flags 0x%x\x00"
+ .align 4
+LC$0100:
+ .STRING " TYPE_FLAG_UNSIGNED\x00"
+ .align 4
+LC$0101:
+ .STRING " TYPE_FLAG_SIGNED\x00"
+ .align 4
+LC$0102:
+ .STRING " TYPE_FLAG_STUB\x00"
+ .align 4
+LC$0103:
+ .STRING "nfields %d 0x%x\x0a\x00"
+ .align 4
+LC$0104:
+ .STRING "[%d] bitpos %d bitsize %d type 0x%x name '%s' (0x%x)\x0a\x00"
+ .align 4
+LC$0105:
+ .STRING "vptr_basetype 0x%x\x0a\x00"
+ .align 4
+LC$0106:
+ .STRING "vptr_fieldno %d\x0a\x00"
+ .align 4
+LC$0107:
+ .STRING "arg_types 0x%x\x0a\x00"
+ .align 4
+LC$0108:
+ .STRING "cplus_stuff 0x%x\x0a\x00"
+ .align 4
+LC$0109:
+ .STRING "type_specific 0x%x\x00"
+ .align 4
+LC$0110:
+ .STRING " (unknown data form)\x00"
+ .align 4
+ .EXPORT recursive_dump_type,CODE
+ .EXPORT recursive_dump_type,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR
+recursive_dump_type:
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,128(%r30)
+ stw %r8,16(%r4)
+ stw %r7,20(%r4)
+ stw %r6,24(%r4)
+ stw %r5,28(%r4)
+ ldo -4(%r0),%r5
+ ldo -32(%r4),%r19
+ add %r19,%r5,%r6
+ stw %r26,0(%r6)
+ ldo -8(%r0),%r7
+ ldo -32(%r4),%r19
+ add %r19,%r7,%r8
+ stw %r25,0(%r8)
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 0(%r19),%r26
+ ldil L'LC$0069,%r25
+ ldo R'LC$0069(%r25),%r25
+ ldw 0(%r20),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldo -4(%r0),%r21
+ ldo -32(%r4),%r22
+ add %r22,%r21,%r21
+ ldw 0(%r21),%r22
+ ldw 4(%r22),%r21
+ ldo -4(%r0),%r22
+ ldo -32(%r4),%r24
+ add %r24,%r22,%r23
+ ldw 0(%r23),%r22
+ ldw 4(%r22),%r23
+ comiclr,= 0,%r23,%r0
+ bl L$0230,%r0
+ nop
+ ldil L'LC$0071,%r21
+ ldo R'LC$0071(%r21),%r21
+L$0230:
+ ldw 0(%r19),%r26
+ ldil L'LC$0070,%r25
+ ldo R'LC$0070(%r25),%r25
+ ldw 4(%r20),%r24
+ copy %r21,%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldw 0(%r19),%r26
+ ldil L'LC$0072,%r25
+ ldo R'LC$0072(%r25),%r25
+ ldw 0(%r20),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 0(%r19),%r20
+ addi,uv -19,%r20,%r0
+ blr,n %r20,%r0
+ b,n L$0251
+L$0252:
+ b L$0232
+ nop
+ b L$0233
+ nop
+ b L$0234
+ nop
+ b L$0235
+ nop
+ b L$0236
+ nop
+ b L$0237
+ nop
+ b L$0238
+ nop
+ b L$0239
+ nop
+ b L$0240
+ nop
+ b L$0241
+ nop
+ b L$0242
+ nop
+ b L$0243
+ nop
+ b L$0244
+ nop
+ b L$0245
+ nop
+ b L$0246
+ nop
+ b L$0247
+ nop
+ b L$0248
+ nop
+ b L$0249
+ nop
+ b L$0250
+ nop
+L$0232:
+ ldil L'LC$0073,%r26
+ ldo R'LC$0073(%r26),%r26
+ .CALL ARGW0=GR
+ bl printf_filtered,%r2
+ nop
+ bl,n L$0231,%r0
+L$0233:
+ ldil L'LC$0074,%r26
+ ldo R'LC$0074(%r26),%r26
+ .CALL ARGW0=GR
+ bl printf_filtered,%r2
+ nop
+ bl,n L$0231,%r0
+L$0234:
+ ldil L'LC$0075,%r26
+ ldo R'LC$0075(%r26),%r26
+ .CALL ARGW0=GR
+ bl printf_filtered,%r2
+ nop
+ bl,n L$0231,%r0
+L$0235:
+ ldil L'LC$0076,%r26
+ ldo R'LC$0076(%r26),%r26
+ .CALL ARGW0=GR
+ bl printf_filtered,%r2
+ nop
+ bl,n L$0231,%r0
+L$0236:
+ ldil L'LC$0077,%r26
+ ldo R'LC$0077(%r26),%r26
+ .CALL ARGW0=GR
+ bl printf_filtered,%r2
+ nop
+ bl,n L$0231,%r0
+L$0237:
+ ldil L'LC$0078,%r26
+ ldo R'LC$0078(%r26),%r26
+ .CALL ARGW0=GR
+ bl printf_filtered,%r2
+ nop
+ bl,n L$0231,%r0
+L$0238:
+ ldil L'LC$0079,%r26
+ ldo R'LC$0079(%r26),%r26
+ .CALL ARGW0=GR
+ bl printf_filtered,%r2
+ nop
+ bl,n L$0231,%r0
+L$0239:
+ ldil L'LC$0080,%r26
+ ldo R'LC$0080(%r26),%r26
+ .CALL ARGW0=GR
+ bl printf_filtered,%r2
+ nop
+ bl,n L$0231,%r0
+L$0240:
+ ldil L'LC$0081,%r26
+ ldo R'LC$0081(%r26),%r26
+ .CALL ARGW0=GR
+ bl printf_filtered,%r2
+ nop
+ bl,n L$0231,%r0
+L$0241:
+ ldil L'LC$0082,%r26
+ ldo R'LC$0082(%r26),%r26
+ .CALL ARGW0=GR
+ bl printf_filtered,%r2
+ nop
+ bl,n L$0231,%r0
+L$0242:
+ ldil L'LC$0083,%r26
+ ldo R'LC$0083(%r26),%r26
+ .CALL ARGW0=GR
+ bl printf_filtered,%r2
+ nop
+ bl,n L$0231,%r0
+L$0243:
+ ldil L'LC$0084,%r26
+ ldo R'LC$0084(%r26),%r26
+ .CALL ARGW0=GR
+ bl printf_filtered,%r2
+ nop
+ bl,n L$0231,%r0
+L$0244:
+ ldil L'LC$0085,%r26
+ ldo R'LC$0085(%r26),%r26
+ .CALL ARGW0=GR
+ bl printf_filtered,%r2
+ nop
+ bl,n L$0231,%r0
+L$0245:
+ ldil L'LC$0086,%r26
+ ldo R'LC$0086(%r26),%r26
+ .CALL ARGW0=GR
+ bl printf_filtered,%r2
+ nop
+ bl,n L$0231,%r0
+L$0246:
+ ldil L'LC$0087,%r26
+ ldo R'LC$0087(%r26),%r26
+ .CALL ARGW0=GR
+ bl printf_filtered,%r2
+ nop
+ bl,n L$0231,%r0
+L$0247:
+ ldil L'LC$0088,%r26
+ ldo R'LC$0088(%r26),%r26
+ .CALL ARGW0=GR
+ bl printf_filtered,%r2
+ nop
+ bl,n L$0231,%r0
+L$0248:
+ ldil L'LC$0089,%r26
+ ldo R'LC$0089(%r26),%r26
+ .CALL ARGW0=GR
+ bl printf_filtered,%r2
+ nop
+ bl,n L$0231,%r0
+L$0249:
+ ldil L'LC$0090,%r26
+ ldo R'LC$0090(%r26),%r26
+ .CALL ARGW0=GR
+ bl printf_filtered,%r2
+ nop
+ bl,n L$0231,%r0
+L$0250:
+ ldil L'LC$0091,%r26
+ ldo R'LC$0091(%r26),%r26
+ .CALL ARGW0=GR
+ bl printf_filtered,%r2
+ nop
+ bl,n L$0231,%r0
+L$0251:
+ ldil L'LC$0092,%r26
+ ldo R'LC$0092(%r26),%r26
+ .CALL ARGW0=GR
+ bl printf_filtered,%r2
+ nop
+ bl,n L$0231,%r0
+L$0231:
+ ldil L'LC$0066,%r26
+ ldo R'LC$0066(%r26),%r26
+ .CALL ARGW0=GR
+ bl puts_filtered,%r2
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldw 0(%r19),%r26
+ ldil L'LC$0093,%r25
+ ldo R'LC$0093(%r25),%r25
+ ldw 8(%r20),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldw 0(%r19),%r26
+ ldil L'LC$0094,%r25
+ ldo R'LC$0094(%r25),%r25
+ ldw 12(%r20),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldw 0(%r19),%r26
+ ldil L'LC$0095,%r25
+ ldo R'LC$0095(%r25),%r25
+ ldw 16(%r20),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 16(%r19),%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0253,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldo -8(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 0(%r20),%r21
+ ldo 2(%r21),%r20
+ ldw 16(%r19),%r26
+ copy %r20,%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl recursive_dump_type,%r2
+ nop
+L$0253:
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldw 0(%r19),%r26
+ ldil L'LC$0096,%r25
+ ldo R'LC$0096(%r25),%r25
+ ldw 20(%r20),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldw 0(%r19),%r26
+ ldil L'LC$0097,%r25
+ ldo R'LC$0097(%r25),%r25
+ ldw 24(%r20),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldw 0(%r19),%r26
+ ldil L'LC$0098,%r25
+ ldo R'LC$0098(%r25),%r25
+ ldw 28(%r20),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldh 32(%r20),%r21
+ extrs %r21,31,16,%r20
+ ldw 0(%r19),%r26
+ ldil L'LC$0099,%r25
+ ldo R'LC$0099(%r25),%r25
+ copy %r20,%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldh 32(%r19),%r20
+ extru %r20,31,1,%r19
+ extrs %r19,31,16,%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0254,%r0
+ nop
+ ldil L'LC$0100,%r26
+ ldo R'LC$0100(%r26),%r26
+ .CALL ARGW0=GR
+ bl puts_filtered,%r2
+ nop
+L$0254:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldh 32(%r19),%r20
+ ldo 2(%r0),%r21
+ and %r20,%r21,%r19
+ extrs %r19,31,16,%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0255,%r0
+ nop
+ ldil L'LC$0101,%r26
+ ldo R'LC$0101(%r26),%r26
+ .CALL ARGW0=GR
+ bl puts_filtered,%r2
+ nop
+L$0255:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldh 32(%r19),%r20
+ ldo 4(%r0),%r21
+ and %r20,%r21,%r19
+ extrs %r19,31,16,%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0256,%r0
+ nop
+ ldil L'LC$0102,%r26
+ ldo R'LC$0102(%r26),%r26
+ .CALL ARGW0=GR
+ bl puts_filtered,%r2
+ nop
+L$0256:
+ ldil L'LC$0066,%r26
+ ldo R'LC$0066(%r26),%r26
+ .CALL ARGW0=GR
+ bl puts_filtered,%r2
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldh 34(%r20),%r21
+ extrs %r21,31,16,%r20
+ ldo -4(%r0),%r21
+ ldo -32(%r4),%r23
+ add %r23,%r21,%r22
+ ldw 0(%r22),%r21
+ ldw 0(%r19),%r26
+ ldil L'LC$0103,%r25
+ ldo R'LC$0103(%r25),%r25
+ copy %r20,%r24
+ ldw 36(%r21),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl printfi_filtered,%r2
+ nop
+ stw %r0,8(%r4)
+L$0257:
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldh 34(%r19),%r20
+ extrs %r20,31,16,%r19
+ ldw 8(%r4),%r20
+ comclr,< %r20,%r19,%r0
+ bl L$0258,%r0
+ nop
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ ldo 2(%r20),%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldw 8(%r4),%r21
+ zdep %r21,27,28,%r22
+ ldw 36(%r20),%r21
+ add %r22,%r21,%r20
+ ldo -4(%r0),%r21
+ ldo -32(%r4),%r23
+ add %r23,%r21,%r22
+ ldw 0(%r22),%r21
+ ldw 8(%r4),%r22
+ zdep %r22,27,28,%r23
+ ldw 36(%r21),%r22
+ add %r23,%r22,%r21
+ ldw 4(%r21),%r22
+ stw %r22,-52(%r30)
+ ldo -4(%r0),%r21
+ ldo -32(%r4),%r23
+ add %r23,%r21,%r22
+ ldw 0(%r22),%r21
+ ldw 8(%r4),%r22
+ zdep %r22,27,28,%r23
+ ldw 36(%r21),%r22
+ add %r23,%r22,%r21
+ ldw 8(%r21),%r22
+ stw %r22,-56(%r30)
+ ldo -4(%r0),%r21
+ ldo -32(%r4),%r23
+ add %r23,%r21,%r22
+ ldw 0(%r22),%r21
+ ldw 8(%r4),%r22
+ zdep %r22,27,28,%r23
+ ldw 36(%r21),%r22
+ add %r23,%r22,%r21
+ ldw 12(%r21),%r22
+ stw %r22,-60(%r30)
+ ldo -4(%r0),%r21
+ ldo -32(%r4),%r23
+ add %r23,%r21,%r22
+ ldw 0(%r22),%r21
+ ldw 8(%r4),%r22
+ zdep %r22,27,28,%r23
+ ldw 36(%r21),%r22
+ add %r23,%r22,%r21
+ ldw 12(%r21),%r22
+ stw %r22,-64(%r30)
+ ldo -4(%r0),%r21
+ ldo -32(%r4),%r23
+ add %r23,%r21,%r22
+ ldw 0(%r22),%r21
+ ldw 8(%r4),%r22
+ zdep %r22,27,28,%r23
+ ldw 36(%r21),%r22
+ add %r23,%r22,%r21
+ ldw 12(%r21),%r22
+ comiclr,= 0,%r22,%r0
+ bl L$0260,%r0
+ nop
+ ldil L'LC$0071,%r21
+ ldo R'LC$0071(%r21),%r21
+ stw %r21,-64(%r30)
+L$0260:
+ copy %r19,%r26
+ ldil L'LC$0104,%r25
+ ldo R'LC$0104(%r25),%r25
+ ldw 8(%r4),%r24
+ ldw 0(%r20),%r23
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 8(%r4),%r20
+ zdep %r20,27,28,%r21
+ ldw 36(%r19),%r20
+ add %r21,%r20,%r19
+ ldw 8(%r19),%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0261,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 8(%r4),%r20
+ zdep %r20,27,28,%r21
+ ldw 36(%r19),%r20
+ add %r21,%r20,%r19
+ ldo -8(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 0(%r20),%r21
+ ldo 4(%r21),%r20
+ ldw 8(%r19),%r26
+ copy %r20,%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl recursive_dump_type,%r2
+ nop
+L$0261:
+L$0259:
+ ldw 8(%r4),%r19
+ ldo 1(%r19),%r20
+ stw %r20,8(%r4)
+ bl,n L$0257,%r0
+L$0258:
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldw 0(%r19),%r26
+ ldil L'LC$0105,%r25
+ ldo R'LC$0105(%r25),%r25
+ ldw 40(%r20),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 40(%r19),%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0262,%r0
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldo -8(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 0(%r20),%r21
+ ldo 2(%r21),%r20
+ ldw 40(%r19),%r26
+ copy %r20,%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl recursive_dump_type,%r2
+ nop
+L$0262:
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldw 0(%r19),%r26
+ ldil L'LC$0106,%r25
+ ldo R'LC$0106(%r25),%r25
+ ldw 44(%r20),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldw 0(%r19),%r20
+ ldw 0(%r20),%r19
+ comiclr,<> 6,%r19,%r0
+ bl L$0265,%r0
+ nop
+ comiclr,>= 6,%r19,%r0
+ bl L$0270,%r0
+ nop
+ comiclr,<> 3,%r19,%r0
+ bl L$0266,%r0
+ nop
+ bl,n L$0267,%r0
+L$0270:
+ comiclr,<> 15,%r19,%r0
+ bl L$0264,%r0
+ nop
+ bl,n L$0267,%r0
+L$0264:
+L$0265:
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldw 0(%r19),%r26
+ ldil L'LC$0107,%r25
+ ldo R'LC$0107(%r25),%r25
+ ldw 48(%r20),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldo -8(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 48(%r19),%r26
+ ldw 0(%r20),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl print_arg_types,%r2
+ nop
+ bl,n L$0263,%r0
+L$0266:
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldw 0(%r19),%r26
+ ldil L'LC$0108,%r25
+ ldo R'LC$0108(%r25),%r25
+ ldw 48(%r20),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -8(%r0),%r20
+ ldo -32(%r4),%r21
+ add %r21,%r20,%r20
+ ldw 0(%r19),%r26
+ ldw 0(%r20),%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl print_cplus_stuff,%r2
+ nop
+ bl,n L$0263,%r0
+L$0267:
+ ldo -8(%r0),%r19
+ ldo -32(%r4),%r20
+ add %r20,%r19,%r19
+ ldo -4(%r0),%r20
+ ldo -32(%r4),%r22
+ add %r22,%r20,%r21
+ ldw 0(%r21),%r20
+ ldw 0(%r19),%r26
+ ldil L'LC$0109,%r25
+ ldo R'LC$0109(%r25),%r25
+ ldw 48(%r20),%r24
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl printfi_filtered,%r2
+ nop
+ ldo -4(%r0),%r19
+ ldo -32(%r4),%r21
+ add %r21,%r19,%r20
+ ldw 0(%r20),%r19
+ ldw 48(%r19),%r20
+ comiclr,<> 0,%r20,%r0
+ bl L$0268,%r0
+ nop
+ ldil L'LC$0110,%r26
+ ldo R'LC$0110(%r26),%r26
+ .CALL ARGW0=GR
+ bl printf_filtered,%r2
+ nop
+L$0268:
+ ldil L'LC$0066,%r26
+ ldo R'LC$0066(%r26),%r26
+ .CALL ARGW0=GR
+ bl printf_filtered,%r2
+ nop
+ bl,n L$0263,%r0
+L$0263:
+L$0229:
+ ldw 16(%r4),%r8
+ ldw 20(%r4),%r7
+ ldw 24(%r4),%r6
+ ldw 28(%r4),%r5
+ ldo 8(%r4),%r30
+ ldw -28(%r30),%r2
+ bv %r0(%r2)
+ ldwm -8(%r30),%r4
+ .EXIT
+ .PROCEND
+ .SPACE $PRIVATE$
+ .SUBSPA $BSS$
+
+cplus_struct_default: .comm 24
+
diff --git a/gas/testsuite/gas/hppa/parse/global.s b/gas/testsuite/gas/hppa/parse/global.s
new file mode 100644
index 0000000000..550c4a5776
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/global.s
@@ -0,0 +1,15 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+ .IMPORT foo,data
+
+ .align 4
+; Official gas code will not accept sym-$global$.
+ addil L%foo-$global$,%r27
+
diff --git a/gas/testsuite/gas/hppa/parse/labelbug.s b/gas/testsuite/gas/hppa/parse/labelbug.s
new file mode 100644
index 0000000000..3f36a71f7e
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/labelbug.s
@@ -0,0 +1,35 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$, SORT=8
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; A comment. This should not be interpreted as a label, but both of the
+; following statements should.
+label_without_colon
+label_with_colon:
+
+; A problem tege found...
+; Input scrubbing in gas makes life a real nightmare for assemblers
+; in which the *position* within a line determines how to interpret
+; a stream a characters. These test one particular case where gas
+; had the tendency to delete the whitespace between the opcode and
+; operands if a label without a colon began a line, and the operands
+; started with a non-numeric character.
+L$1 add %r2,%r2,%r2
+L$2: add %r2,%r2,%r2
+L$3
+ add %r2,%r2,%r2
+
+L$4 add %r2,%r2,%r2
+L$5: add %r2,%r2,%r2
+L$6
+ add %r2,%r2,%r2
+
+; An instruction or pseudo-op may begin anywhere after column 0.
+ b,n label_without_colon
diff --git a/gas/testsuite/gas/hppa/parse/linesepbug.s b/gas/testsuite/gas/hppa/parse/linesepbug.s
new file mode 100644
index 0000000000..a819c153e9
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/linesepbug.s
@@ -0,0 +1,20 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; Basic immediate instruction tests.
+;
+; We could/should test some of the corner cases for register and
+; immediate fields. We should also check the assorted field
+; selectors to make sure they're handled correctly.
+
+foo:
+ .WORD 0 !.IMPORT $bar$,DATA
+
diff --git a/gas/testsuite/gas/hppa/parse/lselbug.s b/gas/testsuite/gas/hppa/parse/lselbug.s
new file mode 100644
index 0000000000..29cd997e28
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/lselbug.s
@@ -0,0 +1,18 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; In gas-1.36 the ldil instruction using parenthesis generated
+; garbage bits while the one without parens worked fine.
+ ldil L%(0x00040000 | 0x00000008 | 0x00000002),%r21
+ ldo L%(0x00040000 | 0x00000008 | 0x00000002) (%r21),%r21
+ ldil L%0x00040000 | 0x00000008 | 0x00000002,%r21
+ ldo L%0x00040000 | 0x00000008 | 0x00000002 (%r21),%r21
+
diff --git a/gas/testsuite/gas/hppa/parse/nosubspace.s b/gas/testsuite/gas/hppa/parse/nosubspace.s
new file mode 100644
index 0000000000..2904603c09
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/nosubspace.s
@@ -0,0 +1,21 @@
+ .SPACE $TEXT$
+
+ .align 4
+ .EXPORT mpn_add_n
+ .EXPORT mpn_add_n,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR
+mpn_add_n:
+ .PROC
+ .CALLINFO FRAME=0,NO_CALLS
+ .ENTRY
+
+ add %r0,%r0,%r0 ; reset cy
+Loop:
+ ldws,ma 4(0,%r25),%r20
+ ldws,ma 4(0,%r24),%r19
+
+ addc %r19,%r20,%r19
+ addib,<> -1,%r23,Loop
+ stws,ma %r19,4(0,%r26)
+
+ bv 0(2)
+ addc %r0,%r0,%r28
diff --git a/gas/testsuite/gas/hppa/parse/parse.exp b/gas/testsuite/gas/hppa/parse/parse.exp
new file mode 100644
index 0000000000..da4c2a7486
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/parse.exp
@@ -0,0 +1,222 @@
+# Copyright (C) 1993, 1996, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, 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 more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# DejaGnu@cygnus.com
+
+# Written by the Center for Software Science at the University of Utah
+# and by Cygnus Support.
+
+proc do_string_tests {} {
+ set testname "stringer.s: Test embedded quotes and octal escapes in strings"
+ set x 0
+
+ gas_start "stringer.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 23696E63\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 6C756465\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 6B2E6465\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 66220A00\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 09307831\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 3233\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==6] then { pass $testname } else { fail $testname }
+}
+
+proc do_lsel_test {} {
+ set testname "lselbugs.s: lselbug"
+ set x 0
+
+ gas_start "lselbug.s" "-al"
+
+ # Make sure we correctly handle field selectors.
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 22A04000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 36B50100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 22A04000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 36B50100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==4] then { pass $testname } else { fail $testname }
+}
+
+proc do_valid_align_tests {} {
+ set testname "align1.s: valid alignment tests"
+ set x 0
+
+ gas_start "align1.s" "-al"
+
+ # Make sure we correctly handle field selectors.
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 08000240\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 08000240\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 1000 08000240\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0000\[^\n\]*BLOCK\[^\n\]*1024\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0400\[^\n\]*BLOCK\[^\n\]*1024\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0800\[^\n\]*BLOCK\[^\n\]*4\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0804\[^\n\]*ALIGN\[^\n\]*8\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0808\[^\n\]*BLOCK\[^\n\]*30\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0826\[^\n\]*ALIGN\[^\n\]*4\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0828\[^\n\]*BLOCK\[^\n\]*4\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==10] then { pass $testname } else { fail $testname }
+}
+
+if [istarget hppa*-*-*] then {
+ # GAS-2.0 does not always parse ! as a line separator when it should.
+ setup_xfail hppa*-*-*
+ gas_test "linesepbug.s" "" "" "line separator bug"
+
+ # Make sure GAS accepts syntax for accessing static data.
+ gas_test "global.s" "" "" "check for sym-\$global\$ acceptance"
+
+ # GAS-2.0 (and 1.36 for that matter) can not handle a .proc which
+ # has no label before it.
+ gas_test "procbug.s" "" "" "Label following .proc"
+
+ # One is required to explicitly IMPORT any non-local symbol used
+ # in an assembly file. Make sure we give an error if we use
+ # an undefined symbol.
+ setup_xfail hppa*-*-*
+ gas_test_error "undefbug.s" "" "Check for error when using undefined symbol"
+
+ # This file has code and assembler directives before switching into any
+ # space/subspace pair. This should report an error for SOM (it is not
+ # an error for ELF. The file also has mismatched entry/exit and
+ # proc/procend pairs which are errors for both SOM and ELF.
+ gas_test_error "nosubspace.s" "" "Check for error(s) in input file "
+
+ # This file should return errors for both the ENTRY_GR and ENTRY_FR
+ # directives (they are out-of-range)
+ gas_test_error "entrybug.s" "" "Check for error on entry_gr and entry_fr"
+
+ # Make sure embedded quotes and octal escapes in strings work
+ do_string_tests
+
+ # Make sure we do not die on a .version directive
+ gas_test "versionbug.s" "" "" ".version directive"
+
+ # Make sure we give an error on a bogus .space directive.
+ # recent version of gas2 went into infinite loops printing
+ # errors on this test.
+ gas_test_error "spacebug.s" "" "Check for error on bogus .space directive"
+
+ # GAS should give an error for this test.
+ gas_test_error "calldatabug.s" "" "Check for invalid aguments on .call"
+
+ # Old versions of gas incorrectly gave errors on some valid .EXPORT lines
+ gas_test "exportbug.s" "" "" "syntax check for an old .EXPORT bug"
+
+ # Old versions of gas choked on this file for some reason
+ gas_test "fixup7bug.s" "" "" "check for old \"fixup7\" gas bug"
+
+ # Test an L% selector parsing bug which existed in gas-1.36
+ do_lsel_test
+
+ # First check how some valid alignments are handled.
+ do_valid_align_tests
+
+ # Now check to make sure an invalid argument is flagged as an error.
+ gas_test_error "align2.s" "" "Check for error on bogus argument to .align"
+
+ # GAS can't handle upper bound for a PA .block[z] directive
+ setup_xfail hppa*-*-*
+ gas_test "block1.s" "" "" "Check min/max values for .block"
+
+ # Now check for an invalid argument
+ gas_test_error "block2.s" "" "Check for error on bogus argument to .block"
+
+ # GAS-1.36 choked on this file.
+ # FIXME. Should check relocations made for this test!
+ gas_test "exprbug.s" "" "" "Check for sym1-sym2 acceptance"
+
+ # Bad things happen in the PA ELF backend (others too?) if a non-default
+ # section is created...
+ setup_xfail hppa*-*-*elf*
+ gas_test "ssbug.s" "" "" "Check for acceptance of non-default subspaces"
+
+ # To be compatable with certain "features" of the HP compiler
+ # non-existant registers should default to %r0.
+ gas_test "defbug.s" "" "" "Missing register should default to %%r0"
+
+ # Make sure GAS understands a reasonable set of standard predefined
+ # registers. eg %rp, %dp, %sp, etc.
+ gas_test "stdreg.s" "" "" "Test standard predefined registers"
+
+ # Make sure GAS will accept a label without a colon.
+ gas_test "labelbug.s" "" "" "Test label without colon"
+
+ # Make sure we grok # line directives.
+ gas_test "appbug.s" "" "" "Test acceptance of #line directives"
+
+ # Make sure we give errors if a floating point format is specified
+ # for an xmpyu instruction (integer multiple)
+ gas_test_error "xmpyubug.s" "" "Check for error on bogus argument to xmpyu"
+
+ # Make sure gas handles various kinds of .reg pseudo-ops
+ gas_test "regpopbug.s" "" "" "Test for bugs in .reg pseudo-op"
+
+ # Check some bugs that have appeared in parsing .callinfo directives
+ gas_test "callinfobug.s" "" "" "Test for bugs in .callinfo directive"
+
+ # Check for bogus registers in single precision fmpyadd/fmpysub
+ # instructions
+ gas_test_error "badfmpyadd.s" "" "Check for error on bad fmpyadd insn"
+}
+
diff --git a/gas/testsuite/gas/hppa/parse/procbug.s b/gas/testsuite/gas/hppa/parse/procbug.s
new file mode 100644
index 0000000000..5ae5057f64
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/procbug.s
@@ -0,0 +1,16 @@
+ .space $TEXT$
+ .subspa $CODE$
+ .align 4
+ .export divu,entry
+ .proc
+ .callinfo
+divu: stws,ma %r4,4(%r5) ; save registers on stack
+ .procend
+
+ .export divu2,entry
+ .proc
+ .callinfo
+ .entry
+divu2: stws,ma %r4,4(%r5) ; save registers on stack
+ .exit
+ .procend
diff --git a/gas/testsuite/gas/hppa/parse/regpopbug.s b/gas/testsuite/gas/hppa/parse/regpopbug.s
new file mode 100644
index 0000000000..46db262190
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/regpopbug.s
@@ -0,0 +1,17 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+r0 .reg %r0
+shift .reg %sar
+fpreg10 .reg %fr10
+shift2 .reg shift
+
+; Make sure we didn't botch .equ...
+yabba .equ r0 + shift
diff --git a/gas/testsuite/gas/hppa/parse/spacebug.s b/gas/testsuite/gas/hppa/parse/spacebug.s
new file mode 100644
index 0000000000..183b40138c
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/spacebug.s
@@ -0,0 +1,3 @@
+start: .long 0, 1, 2, 3, 4, 5, 6, 7
+ .space 0x20 - (. - start)
+foo: .long 42
diff --git a/gas/testsuite/gas/hppa/parse/ssbug.s b/gas/testsuite/gas/hppa/parse/ssbug.s
new file mode 100644
index 0000000000..1960e0d309
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/ssbug.s
@@ -0,0 +1,10 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SUBSPA $SHORTBSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=80
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+
+
diff --git a/gas/testsuite/gas/hppa/parse/stdreg.s b/gas/testsuite/gas/hppa/parse/stdreg.s
new file mode 100644
index 0000000000..e42978e241
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/stdreg.s
@@ -0,0 +1,27 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .export foo
+foo:
+ .proc
+ .callinfo no_calls
+ .entry
+ ldi 15,%sp
+ ldi 15,%rp
+ ldi 15,%dp
+ ldi 15,%ret0
+ ldi 15,%ret1
+ ldi 15,%arg0
+ ldi 15,%arg1
+ ldi 15,%arg2
+ ldi 15,%arg3
+ .exit
+ .procend
diff --git a/gas/testsuite/gas/hppa/parse/stringer.s b/gas/testsuite/gas/hppa/parse/stringer.s
new file mode 100644
index 0000000000..06c5e6dc27
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/stringer.s
@@ -0,0 +1,19 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$
+
+
+; GAS used to mis-parse the embedded quotes
+ .STRING "#include \"awk.def\"\x0a\x00"
+
+; Octal escapes used to consume > 3 chars which led to this
+; string being screwed in a big way.
+ .STRING "\0110x123"
+
+
diff --git a/gas/testsuite/gas/hppa/parse/undefbug.s b/gas/testsuite/gas/hppa/parse/undefbug.s
new file mode 100644
index 0000000000..d5eda92fd4
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/undefbug.s
@@ -0,0 +1,14 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ bl somewhere,%r2
+ nop
+
diff --git a/gas/testsuite/gas/hppa/parse/versionbug.s b/gas/testsuite/gas/hppa/parse/versionbug.s
new file mode 100644
index 0000000000..9fef1b73f4
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/versionbug.s
@@ -0,0 +1,9 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .VERSION "abc123"
+
diff --git a/gas/testsuite/gas/hppa/parse/xmpyubug.s b/gas/testsuite/gas/hppa/parse/xmpyubug.s
new file mode 100644
index 0000000000..3ee727478f
--- /dev/null
+++ b/gas/testsuite/gas/hppa/parse/xmpyubug.s
@@ -0,0 +1,17 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+; No format selector for xmpyu!
+ xmpyu,sgl %fr4,%fr5,%fr6
+ xmpyu,dbl %fr4,%fr5,%fr6
+ xmpyu,quad %fr4,%fr5,%fr6
+
+
diff --git a/gas/testsuite/gas/hppa/reloc/applybug.s b/gas/testsuite/gas/hppa/reloc/applybug.s
new file mode 100644
index 0000000000..f8ed6e8e20
--- /dev/null
+++ b/gas/testsuite/gas/hppa/reloc/applybug.s
@@ -0,0 +1,130 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .IMPORT $global$,DATA
+ .IMPORT $$dyncall,MILLICODE
+; gcc_compiled.:
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$
+
+ .align 4
+tab___2
+ .word L$0002
+ .word L$0003
+ .word L$0004
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .EXPORT execute,CODE
+ .EXPORT execute,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR
+execute
+ .PROC
+ .CALLINFO FRAME=0,NO_CALLS
+ .ENTRY
+ addil L'buf-$global$,%r27
+ ldo R'buf-$global$(%r1),%r20
+ ldil L'L$0002,%r19
+ movb,<> %r26,%r26,L$0002
+ ldo R'L$0002(%r19),%r22
+ copy %r0,%r21
+ addil L'tab___2-$global$,%r27
+ ldo R'tab___2-$global$(%r1),%r23
+ addil L'optab-$global$,%r27
+ ldo R'optab-$global$(%r1),%r20
+L$0009
+ sh2add %r21,%r23,%r19
+ ldh 2(%r19),%r19
+ ldo 1(%r21),%r21
+ sub %r19,%r22,%r19
+ comib,>= 2,%r21,L$0009
+ sths,ma %r19,2(%r20)
+ bv,n %r0(%r2)
+L$0002
+ ldi 120,%r19
+ stbs,ma %r19,1(%r20)
+ ldhs,ma 2(%r26),%r19
+ add %r22,%r19,%r19
+ bv,n %r0(%r19)
+L$0003
+ ldi 121,%r19
+ stbs,ma %r19,1(%r20)
+ ldhs,ma 2(%r26),%r19
+ add %r22,%r19,%r19
+ bv,n %r0(%r19)
+L$0004
+ ldi 122,%r19
+ stb %r19,0(%r20)
+ bv %r0(%r2)
+ stbs,mb %r0,1(%r20)
+ .EXIT
+ .PROCEND
+ .IMPORT __main,CODE
+ .IMPORT strcmp,CODE
+ .SPACE $TEXT$
+ .SUBSPA $LIT$
+
+ .align 4
+L$C0000
+ .STRING "xyxyz\x00"
+ .IMPORT abort,CODE
+ .IMPORT exit,CODE
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .EXPORT main,CODE
+ .EXPORT main,ENTRY,PRIV_LEV=3,RTNVAL=GR
+main
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ .CALL
+ bl __main,%r2
+ ldo 128(%r30),%r30
+ .CALL ARGW0=GR
+ bl execute,%r2
+ copy %r0,%r26
+ addil L'optab-$global$,%r27
+ copy %r1,%r19
+ ldo R'optab-$global$(%r19),%r21
+ ldh 2(%r21),%r20
+ ldh R'optab-$global$(%r19),%r19
+ addil L'p-$global$,%r27
+ copy %r1,%r22
+ sth %r20,R'p-$global$(%r22)
+ ldo R'p-$global$(%r22),%r26
+ sth %r20,4(%r26)
+ sth %r19,2(%r26)
+ ldh 4(%r21),%r19
+ .CALL ARGW0=GR
+ bl execute,%r2
+ sth %r19,6(%r26)
+ addil L'buf-$global$,%r27
+ copy %r1,%r19
+ ldo R'buf-$global$(%r19),%r26
+ ldil L'L$C0000,%r25
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2
+ ldo R'L$C0000(%r25),%r25
+ comib,=,n 0,%r28,L$0011
+ .CALL
+ bl abort,%r2
+ nop
+L$0011
+ .CALL ARGW0=GR
+ bl exit,%r2
+ copy %r0,%r26
+ nop
+ .EXIT
+ .PROCEND
+ .SPACE $PRIVATE$
+ .SUBSPA $BSS$
+
+optab .comm 10
+buf .comm 10
+p .comm 10
diff --git a/gas/testsuite/gas/hppa/reloc/blebug.s b/gas/testsuite/gas/hppa/reloc/blebug.s
new file mode 100644
index 0000000000..0930774739
--- /dev/null
+++ b/gas/testsuite/gas/hppa/reloc/blebug.s
@@ -0,0 +1,16 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .IMPORT $$dyncall,MILLICODE ; Code for dynamic function calls.
+
+_sigtramp:
+ ldil L%$$dyncall,%r2 ; whose address is in r22.
+ ble R%$$dyncall(%sr4,%r2)
diff --git a/gas/testsuite/gas/hppa/reloc/blebug2.s b/gas/testsuite/gas/hppa/reloc/blebug2.s
new file mode 100644
index 0000000000..9577b53cb8
--- /dev/null
+++ b/gas/testsuite/gas/hppa/reloc/blebug2.s
@@ -0,0 +1,14 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+
+ ldil L%0xc0001004,%r1
+ ble R%0xc0001004(%sr7,%r1)
diff --git a/gas/testsuite/gas/hppa/reloc/blebug3.s b/gas/testsuite/gas/hppa/reloc/blebug3.s
new file mode 100644
index 0000000000..5ee9b3b80a
--- /dev/null
+++ b/gas/testsuite/gas/hppa/reloc/blebug3.s
@@ -0,0 +1,14 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .import yabba,code
+
+ ble R%yabba(%sr4,%r0)
diff --git a/gas/testsuite/gas/hppa/reloc/exitbug.s b/gas/testsuite/gas/hppa/reloc/exitbug.s
new file mode 100644
index 0000000000..8898e358da
--- /dev/null
+++ b/gas/testsuite/gas/hppa/reloc/exitbug.s
@@ -0,0 +1,19 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .IMPORT $global$,DATA
+ .IMPORT $$dyncall,MILLICODE
+; gcc_compiled.:
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .EXPORT foo,CODE
+ .EXPORT foo,ENTRY,PRIV_LEV=3
+foo:
+ .PROC
+ .CALLINFO FRAME=0
+ .PROCEND
diff --git a/gas/testsuite/gas/hppa/reloc/fixupbug.s b/gas/testsuite/gas/hppa/reloc/fixupbug.s
new file mode 100644
index 0000000000..8a58d026d7
--- /dev/null
+++ b/gas/testsuite/gas/hppa/reloc/fixupbug.s
@@ -0,0 +1,19 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .SUBSPA $MILLICODE$,QUAD=0,ALIGN=8,ACCESS=44,SORT=8
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ b,n $$foo
+ nop
+ nop
+
+ .SPACE $TEXT$
+ .SUBSPA $MILLICODE$
+$$foo:
+ nop
diff --git a/gas/testsuite/gas/hppa/reloc/funcrelocbug.s b/gas/testsuite/gas/hppa/reloc/funcrelocbug.s
new file mode 100644
index 0000000000..46a43bc62b
--- /dev/null
+++ b/gas/testsuite/gas/hppa/reloc/funcrelocbug.s
@@ -0,0 +1,186 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .IMPORT $global$,DATA
+ .IMPORT $$dyncall,MILLICODE
+; gcc_compiled.:
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .EXPORT g,CODE
+ .EXPORT g,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,RTNVAL=GR
+g
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r3,%r1
+ copy %r30,%r3
+ stwm %r1,128(%r30)
+ stw %r26,-36(%r3)
+ stw %r25,-40(%r3)
+ stw %r24,-44(%r3)
+ ldw -36(%r3),%r26
+ ldw -40(%r3),%r25
+ ldw -44(%r3),%r19
+ copy %r19,%r22
+ .CALL ARGW0=GR
+ bl $$dyncall,%r31
+ copy %r31,%r2
+ copy %r28,%r19
+ comiclr,<> 0,%r19,%r0
+ bl,n L$0002,%r0
+ ldw -36(%r3),%r28
+ bl,n L$0001,%r0
+ bl,n L$0003,%r0
+L$0002
+ ldw -40(%r3),%r28
+ bl,n L$0001,%r0
+L$0003
+L$0001
+ ldw -20(%r3),%r2
+ ldo 64(%r3),%r30
+ ldwm -64(%r30),%r3
+ bv,n %r0(%r2)
+ .EXIT
+ .PROCEND
+ .align 4
+f2___4
+ .PROC
+ .CALLINFO FRAME=64,NO_CALLS,SAVE_SP,ENTRY_GR=3
+ .ENTRY
+ copy %r3,%r1
+ copy %r30,%r3
+ stwm %r1,64(%r30)
+ stw %r29,8(%r3)
+ stw %r26,-36(%r3)
+ stw %r25,-40(%r3)
+ ldw -36(%r3),%r19
+ ldw -40(%r3),%r20
+ comclr,>= %r20,%r19,%r19
+ ldi 1,%r19
+ copy %r19,%r28
+ bl,n L$0005,%r0
+L$0005
+ ldo 64(%r3),%r30
+ ldwm -64(%r30),%r3
+ bv,n %r0(%r2)
+ .EXIT
+ .PROCEND
+ .IMPORT abort,CODE
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$
+
+ .align 4
+L$TRAMP0000
+ ldw 36(%r22),%r21
+ bb,>=,n %r21,30,.+16
+ depi 0,31,2,%r21
+ ldw 4(%r21),%r19
+ ldw 0(%r21),%r21
+ ldsid (%r21),%r1
+ mtsp %r1,%sr0
+ be 0(%sr0,%r21)
+ ldw 40(%r22),%r29
+ .word 0
+ .word 0
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .EXPORT f,CODE
+ .EXPORT f,ENTRY,PRIV_LEV=3,RTNVAL=GR
+f
+ .PROC
+ .CALLINFO FRAME=192,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r3,%r1
+ copy %r30,%r3
+ stwm %r1,192(%r30)
+ ldo 16(%r3),%r19
+ addil L'L$TRAMP0000-$global$,%r27
+ ldo R'L$TRAMP0000-$global$(%r1),%r22
+ ldo 40(%r0),%r20
+ ldws,ma 4(%r22),%r21
+ addib,>= -4,%r20,.-4
+ stws,ma %r21,4(%r19)
+ ldil L'f2___4,%r20
+ ldo R'f2___4(%r20),%r19
+ stw %r19,52(%r3)
+ ldo 8(%r3),%r19
+ stw %r19,56(%r3)
+ ldo 16(%r3),%r19
+ ldo 48(%r3),%r20
+ fdc %r0(%r19)
+ fdc %r0(%r20)
+ sync
+ ldo 32(%r19),%r22
+ mfsp %sr0,%r21
+ ldsid (%r19),%r20
+ mtsp %r20,%sr0
+ fic %r0(%sr0,%r19)
+ fic %r0(%sr0,%r22)
+ sync
+ mtsp %r21,%sr0
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ ldo 16(%r3),%r19
+ ldi 1,%r26
+ ldi 2,%r25
+ copy %r19,%r24
+ .CALL ARGW0=NO,ARGW1=NO,ARGW2=NO,ARGW3=NO
+ bl g,%r2
+ nop
+ copy %r28,%r19
+ comiclr,<> 2,%r19,%r0
+ bl,n L$0006,%r0
+ .CALL ARGW0=NO,ARGW1=NO,ARGW2=NO,ARGW3=NO
+ bl abort,%r2
+ nop
+L$0006
+L$0004
+ ldw -20(%r3),%r2
+ ldo 64(%r3),%r30
+ ldwm -64(%r30),%r3
+ bv,n %r0(%r2)
+ .EXIT
+ .PROCEND
+ .IMPORT __main,CODE
+ .IMPORT exit,CODE
+ .align 4
+ .EXPORT main,CODE
+ .EXPORT main,ENTRY,PRIV_LEV=3,RTNVAL=GR
+main
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r3,%r1
+ copy %r30,%r3
+ stwm %r1,128(%r30)
+ .CALL ARGW0=NO,ARGW1=NO,ARGW2=NO,ARGW3=NO
+ bl __main,%r2
+ nop
+ .CALL ARGW0=NO,ARGW1=NO,ARGW2=NO,ARGW3=NO
+ bl f,%r2
+ nop
+ copy %r0,%r26
+ .CALL ARGW0=NO,ARGW1=NO,ARGW2=NO,ARGW3=NO
+ bl exit,%r2
+ nop
+L$0007
+ ldw -20(%r3),%r2
+ ldo 64(%r3),%r30
+ ldwm -64(%r30),%r3
+ bv,n %r0(%r2)
+ .EXIT
+ .PROCEND
diff --git a/gas/testsuite/gas/hppa/reloc/labelopbug.s b/gas/testsuite/gas/hppa/reloc/labelopbug.s
new file mode 100644
index 0000000000..3cdc421b22
--- /dev/null
+++ b/gas/testsuite/gas/hppa/reloc/labelopbug.s
@@ -0,0 +1,37 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .IMPORT $global$,DATA
+ .IMPORT $$dyncall,MILLICODE
+; gcc_compiled.:
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+s:
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ copy %r4,%r1
+ copy %r30,%r4
+ stwm %r1,128(%r30)
+ stw %r30,12(%r4)
+ ldil L'L$0007,%r19
+ ldo R'L$0007(%r19),%r19
+ comib,>= 0,%r26,L$0002
+ stw %r19,8(%r4)
+L$0003:
+L$0002:
+ b L$0001
+ ldo 1(%r0),%r28
+L$0007:
+ ldil L'L$0002,%r19
+ ldo R'L$0002(%r19),%r19
+ comb,= %r29,%r19,L$0002
+ ldo -8(%r4),%r4
+ .EXIT
+ .PROCEND
diff --git a/gas/testsuite/gas/hppa/reloc/longcall.s b/gas/testsuite/gas/hppa/reloc/longcall.s
new file mode 100644
index 0000000000..fc3996f0be
--- /dev/null
+++ b/gas/testsuite/gas/hppa/reloc/longcall.s
@@ -0,0 +1,40 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .IMPORT $global$,DATA
+ .IMPORT $$dyncall,MILLICODE
+; gcc_compiled.:
+ .IMPORT bar,CODE
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .EXPORT foo,CODE
+ .EXPORT foo,ENTRY,PRIV_LEV=3,RTNVAL=GR
+foo
+ .PROC
+ .CALLINFO FRAME=64,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ .CALL
+ bl bar,%r2
+ ldo 64(%r30),%r30
+ .blockz 262144
+ ldw -84(%r30),%r2
+ bv %r0(%r2)
+ ldo -64(%r30),%r30
+ .EXIT
+ .PROCEND
+ .align 4
+ .EXPORT bar,CODE
+ .EXPORT bar,ENTRY,PRIV_LEV=3,RTNVAL=GR
+bar
+ .PROC
+ .CALLINFO FRAME=0,NO_CALLS
+ .ENTRY
+ bv,n %r0(%r2)
+ .EXIT
+ .PROCEND
diff --git a/gas/testsuite/gas/hppa/reloc/picreloc.s b/gas/testsuite/gas/hppa/reloc/picreloc.s
new file mode 100644
index 0000000000..639a44c3ab
--- /dev/null
+++ b/gas/testsuite/gas/hppa/reloc/picreloc.s
@@ -0,0 +1,13 @@
+
+ .SPACE $TEXT$,SORT=8
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=0x2c,CODE_ONLY,SORT=24
+ .SPACE $PRIVATE$,SORT=16
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=0x1f,SORT=16
+bogo
+ .ALIGN 8
+ .WORD bogo+4 ; = 0x4
+ .STRING "\x00\x00\x00{\x00\x00\x01\xC8\x00\x00\x03\x15"
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$
+ .EXPORT bogo
+ .END
diff --git a/gas/testsuite/gas/hppa/reloc/plabelbug.s b/gas/testsuite/gas/hppa/reloc/plabelbug.s
new file mode 100644
index 0000000000..ee05b32e1f
--- /dev/null
+++ b/gas/testsuite/gas/hppa/reloc/plabelbug.s
@@ -0,0 +1,47 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .IMPORT $global$,DATA
+ .IMPORT $$dyncall,MILLICODE
+; gcc_compiled.:
+ .IMPORT abort,CODE
+ .EXPORT f,DATA
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$
+
+ .align 4
+f:
+ .word P%abort
+ .word P%abort
+ .IMPORT __main,CODE
+ .IMPORT printf,CODE
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+LC$0000:
+ .STRING "frob\x0a\x00"
+ .align 4
+ .EXPORT main,CODE
+ .EXPORT main,ENTRY,PRIV_LEV=3,RTNVAL=GR
+main:
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ stw %r2,-20(%r30)
+ ldo 128(%r30),%r30
+ .CALL
+ bl __main,%r2
+ nop
+ ldil L'LC$0000,%r26
+ .CALL ARGW0=GR
+ bl printf,%r2
+ ldo R'LC$0000(%r26),%r26
+ ldw -148(%r30),%r2
+ bv %r0(%r2)
+ ldo -128(%r30),%r30
+ .EXIT
+ .PROCEND
diff --git a/gas/testsuite/gas/hppa/reloc/r_no_reloc.s b/gas/testsuite/gas/hppa/reloc/r_no_reloc.s
new file mode 100644
index 0000000000..026f2d0823
--- /dev/null
+++ b/gas/testsuite/gas/hppa/reloc/r_no_reloc.s
@@ -0,0 +1,45 @@
+ .COPYRIGHT "MetaWare Incorporated, 1992"
+ .VERSION "hc2.6a -O1 t3.c\n"
+
+ .SPACE $PRIVATE$,SORT=16
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=0x1F,SORT=80,ZERO
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=0x1F,SORT=16
+
+ .SPACE $TEXT$,SORT=8
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=44,CODE_ONLY,SORT=24
+
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$
+ .ALIGN 8
+$L00DATA
+ .ALIGN 8
+ .EXPORT s
+s
+ .WORD 0x0
+ .BLOCKZ 786425
+ .BLOCKZ 7
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+L$001.3
+g .PROC
+ .CALLINFO FRAME=0,NO_CALLS
+ .ENTRY
+ ;ldo 120(%r0),%r28 --> to delay slot
+ bv %r0(%r2)
+ .EXIT
+ ldo 120(%r0),%r28
+ .PROCEND
+
+
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$
+ .ALIGN 4
+ .EXPORT l
+l
+ .WORD P'g
+ .IMPORT common,DATA ; common section, size=0
+ .IMPORT $global$,DATA
+ .EXPORT g,ENTRY,PRIV_LEV=3,RTNVAL=GR
+ .END
+
diff --git a/gas/testsuite/gas/hppa/reloc/reduce.s b/gas/testsuite/gas/hppa/reloc/reduce.s
new file mode 100644
index 0000000000..737752f211
--- /dev/null
+++ b/gas/testsuite/gas/hppa/reloc/reduce.s
@@ -0,0 +1,48 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .IMPORT $global$,DATA
+ .IMPORT $$dyncall,MILLICODE
+; gcc_compiled.:
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .PARAM foo,RTNVAL=GR
+foo:
+ .PROC
+ .CALLINFO FRAME=0,NO_CALLS
+ .ENTRY
+ bv,n %r0(%r2)
+ .EXIT
+ .PROCEND
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+LC$0000:
+ .word P%foo
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .EXPORT bar,CODE
+ .EXPORT bar,ENTRY,PRIV_LEV=3,RTNVAL=GR
+bar:
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP
+ .ENTRY
+ ldil L'LC$0000,%r19
+ ldw R'LC$0000(%r19),%r26
+ stw %r2,-20(%r30)
+ .CALL ARGW0=GR
+ bl foo,%r2
+ ldo 128(%r30),%r30
+ ldw -148(%r30),%r2
+ bv %r0(%r2)
+ ldo -128(%r30),%r30
+ .EXIT
+ .PROCEND
diff --git a/gas/testsuite/gas/hppa/reloc/reduce2.s b/gas/testsuite/gas/hppa/reloc/reduce2.s
new file mode 100644
index 0000000000..6c3fa3781c
--- /dev/null
+++ b/gas/testsuite/gas/hppa/reloc/reduce2.s
@@ -0,0 +1,80 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .IMPORT $global$,DATA
+ .IMPORT $$dyncall,MILLICODE
+; gcc_compiled.:
+ .SPACE $TEXT$
+ .SUBSPA $LIT$
+
+ .align 8
+L$P0000
+ .word 0x12345678
+ .word 0x0
+
+ .align 8
+L$C0000
+ .word 0x3ff00000
+ .word 0x0
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .EXPORT g,ENTRY,PRIV_LEV=3,RTNVAL=FR
+g
+ .PROC
+ .CALLINFO FRAME=0,NO_CALLS
+ .ENTRY
+ stw %r19,-32(%r30)
+ ldw T'L$C0000(%r19),%r20
+ bv %r0(%r2)
+ fldds 0(%r20),%fr4
+ .EXIT
+ .PROCEND
+ .IMPORT abort,CODE
+ .IMPORT exit,CODE
+ .SPACE $TEXT$
+ .SUBSPA $LIT$
+
+ .align 8
+L$C0001
+ .word 0x3ff00000
+ .word 0x0
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .EXPORT main,ENTRY,PRIV_LEV=3,RTNVAL=GR
+main
+ .PROC
+ .CALLINFO FRAME=128,CALLS,SAVE_RP,ENTRY_GR=3
+ .ENTRY
+ stw %r2,-20(%r30)
+ ldo 128(%r30),%r30
+ stw %r19,-32(%r30)
+ stw %r4,-128(%r30)
+
+ copy %r19,%r4
+ .CALL
+ bl g,%r2
+ copy %r4,%r19
+ copy %r4,%r19
+ ldw T'L$C0001(%r19),%r20
+ fldds 0(%r20),%fr8
+ fcmp,dbl,= %fr4,%fr8
+ ftest
+ add,tr %r0,%r0,%r0
+ b,n L$0003
+ .CALL
+ bl abort,%r2
+ nop
+L$0003
+ .CALL ARGW0=GR
+ bl exit,%r2
+ ldi 0,%r26
+ nop
+ .EXIT
+ .PROCEND
diff --git a/gas/testsuite/gas/hppa/reloc/reduce3.s b/gas/testsuite/gas/hppa/reloc/reduce3.s
new file mode 100644
index 0000000000..9671e784c3
--- /dev/null
+++ b/gas/testsuite/gas/hppa/reloc/reduce3.s
@@ -0,0 +1,51 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .IMPORT $global$,DATA
+ .IMPORT $$dyncall,MILLICODE
+; gcc_compiled.:
+ .EXPORT blah,DATA
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$
+
+ .align 8
+blah
+ ; .double 0e+00
+ .word 0 ; = 0x0
+ .word 0 ; = 0x0
+ .EXPORT foo,DATA
+ .align 8
+foo
+ ; .double 0e+00
+ .word 0 ; = 0x0
+ .word 0 ; = 0x0
+ .EXPORT yabba,DATA
+ .align 4
+yabba
+ .word 1
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .EXPORT bar,CODE
+ .EXPORT bar,ENTRY,PRIV_LEV=3,RTNVAL=GR
+bar
+ .PROC
+ .CALLINFO FRAME=64,NO_CALLS,SAVE_SP,ENTRY_GR=3
+ .ENTRY
+ copy %r3,%r1
+ copy %r30,%r3
+ stwm %r1,64(%r30)
+ addil L'yabba-$global$,%r27
+ ldo R'yabba-$global$(%r1),%r19
+ ldi 2,%r20
+ stw %r20,0(%r19)
+L$0001
+ ldo 64(%r3),%r30
+ ldwm -64(%r30),%r3
+ bv,n %r0(%r2)
+ .EXIT
+ .PROCEND
diff --git a/gas/testsuite/gas/hppa/reloc/reloc.exp b/gas/testsuite/gas/hppa/reloc/reloc.exp
new file mode 100644
index 0000000000..ccb236cba7
--- /dev/null
+++ b/gas/testsuite/gas/hppa/reloc/reloc.exp
@@ -0,0 +1,679 @@
+# Copyright (C) 1993, 1996, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, 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 more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# DejaGnu@cygnus.com
+
+# Written by the Center for Software Science at the University of Utah
+# and by Cygnus Support.
+
+proc do_ble_relocation_test {} {
+ set testname "blebug.s: Test for proper relocation for BLE (part 2)"
+ set x 0
+
+ if [gas_test_old "blebug.s" "" "Proper relocation for BLE (part 1)"] then {
+ objdump_start_no_subdir "a.out" "-r"
+
+ if ![istarget hppa*-*-*elf*] then {
+ # At one time both versions of the assembler would incorrectly use
+ # a PC-relative relocation for a BLE instruction.
+ while 1 {
+ expect {
+ -re "^00000004\[^\n\]*ABS_CALL\[^\n\]*\n" { set x 1 }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+ } else {
+ # At one time both versions of the assembler would incorrectly use
+ # a PC-relative relocation for a BLE instruction.
+ while 1 {
+ expect {
+ -re "^00000000\[^\n\]*DIR21L\[^\n\]*\n" { set x 1 }
+ -re "^00000004\[^\n\]*DIR17R\[^\n\]*\n" { set x 1 }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ objdump_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==1] then { pass $testname } else { fail $testname }
+}
+
+proc do_relocation_reduction_tests {} {
+ set testname "reduce.s: Test relocation reductions (part 2)"
+ set x 0
+
+ if [gas_test_old "reduce.s" "" "Relocation reductions (part1)"] then {
+ objdump_start_no_subdir "a.out" "-r"
+
+ # Check to make sure relocations involving procedure labels
+ # are not reduced to a relocation involving some other symbol.
+ # Doing so makes generating parameter relocation stubs impossible.
+ while 1 {
+ expect {
+ -re "^00000004\[^\n\]*PLABEL\[^\n\]*foo\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^00000014\[^\n\]*PCREL\[^\n\]*foo\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ objdump_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==2] then { pass $testname } else { fail $testname }
+
+ set testname "reduce2.s: More relocation reduction tests (part 2)"
+ set x 0
+
+ if [gas_test_old "reduce2.s" "" "More relocatoin reductions (part1)"] then {
+ objdump_start_no_subdir "a.out" "-r"
+
+ # Check to make sure DLT relative relocs are not reduced to sym+addend
+ # Doing so doesn't work as one might expect
+ while 1 {
+ expect {
+ -re "^00000004\[^\n\]*DLT\[^\n\]*L.C0000\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^0000001c\[^\n\]*DLT\[^\n\]*L.C0000\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^00000030\[^\n\]*DLT\[^\n\]*L.C0001\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^00000048\[^\n\]*DLT\[^\n\]*L.C0001\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ objdump_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==2] then { pass $testname } else { fail $testname }
+
+ set testname "reduce3.s: Test even more relocation reductions (part 2)"
+ set x 0
+
+ if [gas_test_old "reduce3.s" "" "Even more relocation reductions (part1)"] then {
+ objdump_start_no_subdir "a.out" "-r"
+
+ # Check to make sure relocations involving procedure labels
+ # are not reduced to a relocation involving some other symbol.
+ # Doing so makes generating parameter relocation stubs impossible.
+ while 1 {
+ expect {
+ -re "^0000000c\[^\n\]*yabba\[^\n\+\]*\n"
+ { set x [expr $x+1] }
+ -re "^0000000c\[^\n\]*yabba\+\[^\n\]*\n"
+ { set x 0; break }
+ -re "^00000010\[^\n\]*yabba\[^\n\+\]*\n"
+ { set x [expr $x+1] }
+ -re "^00000010\[^\n\]*yabba\+\[^\n\]*\n"
+ { set x 0; break }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ objdump_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==2] then { pass $testname } else { fail $testname }
+}
+
+proc do_ble_mode_selector_test {} {
+ set testname "blebug2.s: blebug2"
+ set x 0
+
+ gas_start "blebug2.s" "-al"
+
+ # GAS uses too many bits on the BLE instruction.
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 20202801\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 E420E008\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==2] then { pass $testname } else { fail $testname }
+}
+
+proc do_ble_relocation_test {} {
+ set testname "blebug3.s: blebug3"
+ set x 0
+
+ gas_start "blebug3.s" "-al"
+
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 E4002000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==1] then { pass $testname } else { fail $testname }
+}
+
+proc do_plabel_relocation_test {} {
+ set testname "plabelbug.s: Old gas-1.36 plabel bug (part 2)"
+ set x 0
+
+ if [gas_test_old "plabelbug.s" "" "Old gas-1.36 plabel bug (part 1)"] {
+ objdump_start_no_subdir "a.out" "-r"
+
+ # Check that we make PLABEL relocation entries when they're needed.
+ while 1 {
+ expect {
+ -re "^00000000\[^\n\]*PLABEL\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^00000004\[^\n\]*PLABEL\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ objdump_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==2] then { pass $testname } else { fail $testname }
+ }
+}
+
+proc do_selector_scope_test {} {
+ set testname "selectorbug.s: Test scope of field selector"
+ set x 0
+
+ if [gas_test_old "selectorbug.s" "" "Test scope of field selector (part 1)"] {
+ objdump_start_no_subdir "a.out" "-r"
+
+ # Check to make sure the relocation entry after the plabel is correct.
+ # If an old field selector was incorrectly "carried" over, then
+ # this test will fail.
+ if [istarget hppa*-*-*elf*] then {
+ while 1 {
+ expect {
+ -re "^00000014\[^\n\]*DIR32\[^\n\]*\n"
+ { set x 1 }
+ -re "^00000014\[^\n\]*PLABEL\[^\n\]*foo\[^\n\]*\n"
+ { set x 0 }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+ } else {
+ while 1 {
+ expect {
+ -re "^00000014\[^\n\]*DATA_ONE\[^\n\]*\n"
+ { set x 1 }
+ -re "^00000014\[^\n\]*PLABEL\[^\n\]*foo\[^\n\]*\n"
+ { set x 0 }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ objdump_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==1] then { pass $testname } else { fail $testname }
+ }
+}
+
+proc do_local_label_as_operand_test {} {
+ set testname "labelopbug.s: Test local label as operand (non-branching)"
+ set x 0
+
+ if [gas_test_old "labelopbug.s" "" "Local label as operand (part 1)"] {
+ objdump_start_no_subdir "a.out" "-r"
+
+ # Check to make sure we handle difference of local lables as an operand
+ # to a non-branching instruction correctly.
+ while 1 {
+ expect {
+ -re "^0000002c\[^\n\]*0x00000024\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^00000030\[^\n\]*0x00000024\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ objdump_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==2] then { pass $testname } else { fail $testname }
+ }
+}
+
+proc do_exit_relocation_test {} {
+ set testname "exitbug.s: Test for bogus R_EXIT relocation (part 2)"
+ set x 0
+
+ # Elf (osf) does not use ENTRY/EXIT relocations.
+ # I guess we could look at the unwind subspaces it builds...
+ # Until then, make sure it still assembles.
+ if [istarget hppa*-*-*elf*] then {
+ gas_test_old "exitbug.s" "" "Test for bogus R_EXIT relocation (part 1)"
+ return;
+ }
+
+ if [gas_test_old "exitbug.s" "" "Test for bogus R_EXIT relocation (part 1)"] {
+ objdump_start_no_subdir "a.out" "-r"
+
+ # Note that a match here is really a FAILURE!
+ while 1 {
+ expect {
+ -re "^00000000\[^\n\]*R_EXIT\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ objdump_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==0] then { pass $testname } else { fail $testname }
+ }
+}
+
+proc do_cross_space_fixup_test_1 {} {
+ set testname "fixupbug.s: Test cross space jump/call fixup bug (part 2)"
+ set x 0
+
+ # ELF (osf) doesn't really handle extra sections too well...
+ if [istarget hppa*-*-*elf*] then {
+ return;
+ }
+
+ if [gas_test_old "fixupbug.s" "" "Test cross space jump/call fixup bug (part 1)"] {
+ objdump_start_no_subdir "a.out" "-r"
+
+ # Make sure GAS generated a fixup/relocation for the cross-space
+ # branch/call
+ while 1 {
+ expect {
+ -re "^00000000\[^\n\]*PCREL_CALL\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ objdump_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==1] then { pass $testname } else { fail $testname }
+ }
+}
+
+proc do_cross_space_fixup_test_2 {} {
+ set testname "fixupbug.s: Test cross space jump/call fixup bug (part 3)"
+ set x 0
+
+ # ELF (osf) doesn't really handle extra sections too well...
+ if [istarget hppa*-*-*elf*] then {
+ return;
+ }
+
+ gas_start "fixupbug.s" "-al"
+
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 E8000002\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==1] then { pass $testname } else { fail $testname }
+}
+
+proc do_round_mode_test {} {
+ set testname "roundmode.s: Test switching of rounding modes (part 2)"
+ set x 0
+
+ if [gas_test_old "roundmode.s" "" "Test switch of rounding modes(part 1)"] {
+ objdump_start_no_subdir "a.out" "-r"
+
+ # Make sure GAS generated correct relocations to switch rounding modes.
+ # Also make sure (for SOM) that redundant rounding mode relocations
+ # were eliminated.
+ if [istarget hppa*-*-*elf*] then {
+ while 1 {
+ expect {
+ -re "^00000000\[^\n\]*DIR21L\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^00000004\[^\n\]*DIR14R\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^00000008\[^\n\]*DIR21L\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^0000000c\[^\n\]*DIR14R\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^00000010\[^\n\]*DIR21L\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^00000014\[^\n\]*DIR14R\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^00000018\[^\n\]*DIR21L\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^0000001c\[^\n\]*DIR14R\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+ } else {
+ while 1 {
+ expect {
+ -re "^00000000\[^\n\]*R_R_MODE\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^00000004\[^\n\]*R_R_MODE\[^\n\]*\n"
+ { fail $testname }
+ -re "^00000008\[^\n\]*R_N_MODE\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^0000000c\[^\n\]*R_N_MODE\[^\n\]*\n"
+ { fail $testname }
+ -re "^00000010\[^\n\]*R_R_MODE\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^00000014\[^\n\]*R_R_MODE\[^\n\]*\n"
+ { fail $testname }
+ -re "^0000001c\[^\n\]*R_R_MODE\[^\n\]*\n"
+ { fail $testname }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ objdump_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [istarget hppa*-*-*elf*] then {
+ if [expr $x==8] then { pass $testname } else { fail $testname }
+ } else {
+ if [expr $x==3] then { pass $testname } else { fail $testname }
+ }
+ }
+}
+
+proc do_function_reloc_bug {} {
+ set testname "funcrelocbug.s: Test for reloc bug in non-plabel function reference (part 2)"
+ set x 0
+
+ if [gas_test_old "funcrelocbug.s" "" "Test for reloc bug in non-plabel function reference (part 1)"] {
+ objdump_start_no_subdir "a.out" "-r"
+
+ # Make sure GAS generated a correct relocation for the reference.
+ # branch/call
+ while 1 {
+ expect {
+ -re "^000000cc\[^\n\]*f2___4\[^\n+\]*\n"
+ { set x [expr $x+1] }
+ -re "^000000d0\[^\n\]*f2___4\[^\n+\]*\n"
+ { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ objdump_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==2] then { pass $testname } else { fail $testname }
+
+ set testname "funcrelocbug.s: Test for reloc bug in non-plabel function reference (part3)"
+ set x 0
+
+ objdump_start_no_subdir "a.out" "--prefix-addresses -d"
+ # Make sure we didn't put anything in the instruction itself!
+ while 1 {
+ expect {
+ -re "^000000cc\[^\n\]*ldil 0,r20\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^000000d0\[^\n\]*ldo 0\[\(\]+r20\[\)\]+,r19\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ objdump_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==2] then { pass $testname } else { fail $testname }
+ }
+
+}
+
+proc do_r_no_reloc {} {
+ set testname "r_no_reloc.s: Test for reloc bug in 4-byte R_NO_RELCOATION fixups (part 2)"
+ set x 0
+
+ if [gas_test_old "r_no_reloc.s" "" "Test for reloc bug in 4-byte R_NO_RELOCATION fixups (part 1)"] {
+ objdump_start_no_subdir "a.out" "-r"
+
+ # Make sure GAS generated a correct relocation for the reference.
+ while 1 {
+ expect {
+ -re "^000c0004\[^\n\]*PLABEL\[^\n]*g\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ objdump_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==1] then { pass $testname } else { fail $testname }
+
+ }
+}
+
+proc do_pic_relocation_test {} {
+ set testname "picreloc.s: Test for proper PIC relocation (part 2)"
+ set x 0
+
+ # ELF (osf) doesn't really handle extra sections too well...
+ if [istarget hppa*-*-*elf*] then {
+ return;
+ }
+
+ gas_start "picreloc.s" "-al"
+
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 00000004\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==1] then { pass $testname } else { fail $testname }
+}
+
+proc do_apply_test {} {
+ set testname "applybug.s: Test for proper fixup appliation (part 2)"
+ set x 0
+
+ # ELF (osf) doesn't really handle extra sections too well...
+ if [istarget hppa*-*-*elf*] then {
+ return;
+ }
+
+ gas_start "applybug.s" "-al"
+
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 00000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 00000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 00000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==3] then { pass $testname } else { fail $testname }
+}
+if [istarget hppa*-*-*] then {
+ # Make sure we put the right relocation entry on a BLE instruction.
+ do_ble_relocation_test
+
+ # Make sure relocation reductions are not too agressive about
+ # adjusting relocations against some symbols.
+ do_relocation_reduction_tests
+
+ # Check that mode selectors on a ble instruction actually work.
+ do_ble_mode_selector_test
+
+ # Check that we take the -8 adjustment into account when zeroing
+ # out the displacement field in a ble instruction with a reloc
+ do_ble_relocation_test
+
+ # 1.36 simply didn't generate all the plabels it should have. Make
+ # sure gas-2 does.
+ do_plabel_relocation_test
+
+ # Make sure a field selector only effects the current instruction
+ # or assembler directive.
+ do_selector_scope_test
+
+ # This should really generate a relocation. It would make life much
+ # easier on the optimizing linker. Until then just make sure the
+ # difference is computed correctly.
+ do_local_label_as_operand_test
+
+ # GAS2 incorrectly generated R_EXIT relocations when .exit directives
+ # were not in the source code.
+ do_exit_relocation_test
+
+ # GAS2 incorrectly thought it could apply a fixup for a pc-relative
+ # branch/call which crossed different subspaces.
+ # Also check that the assembled instruction is correct
+ do_cross_space_fixup_test_1
+ do_cross_space_fixup_test_2
+
+ # Make sure we switch rounding modes correctly
+ do_round_mode_test
+
+ # Test for a bug found when a function was used in a non-branching
+ # instruction *without* a plabel (for portable runtime model)
+ do_function_reloc_bug
+
+ # Test for an off-by-one bug in the handling of 4-byte R_NO_RELOCATION
+ # fixups.
+ do_r_no_reloc
+
+ # Test a relocation problem which shows up when building shared
+ # libraries in SOM
+ do_pic_relocation_test
+
+ # Test a problem with md_apply_fix that was introduced when fixing
+ # the pic relocation test.
+ do_apply_test
+
+ # Make sure gas doesn't resolve long-calls which are to be fixed
+ # by the linker
+ gas_test "longcall.s" "" "" "Avoid resolving long-calls"
+}
diff --git a/gas/testsuite/gas/hppa/reloc/roundmode.s b/gas/testsuite/gas/hppa/reloc/roundmode.s
new file mode 100644
index 0000000000..5a87e638bc
--- /dev/null
+++ b/gas/testsuite/gas/hppa/reloc/roundmode.s
@@ -0,0 +1,23 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .IMPORT foo,data
+
+; Switch in/out of different rounding modes.
+; Also make sure we "optimize" away useless rounding mode relocations
+ addil LR'foo-0x12345,%r27
+ ldo RR'foo-0x12345(%r1),%r1
+ addil L'foo-0x12345,%r27
+ ldo R'foo-0x12345(%r1),%r1
+ addil LR'foo-0x12345,%r27
+ ldo RR'foo-0x12345(%r1),%r1
+ addil LR'foo-0x12345,%r27
+ ldo RR'foo-0x12345(%r1),%r1
diff --git a/gas/testsuite/gas/hppa/reloc/selectorbug.s b/gas/testsuite/gas/hppa/reloc/selectorbug.s
new file mode 100644
index 0000000000..6925d383f5
--- /dev/null
+++ b/gas/testsuite/gas/hppa/reloc/selectorbug.s
@@ -0,0 +1,28 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .IMPORT $global$,DATA
+ .IMPORT $$dyncall,MILLICODE
+; gcc_compiled.:
+ .EXPORT intVec_error_handler,DATA
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$
+
+intVec_error_handler:
+ .word P%default_intVec_error_handler__FPCc
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .EXPORT foo,CODE
+ .EXPORT foo,ENTRY,PRIV_LEV=3
+foo:
+ .PROC
+ .CALLINFO FRAME=0
+ .ENTRY
+ .stabd 68,0,41
+ .EXIT
+ .PROCEND
diff --git a/gas/testsuite/gas/hppa/unsorted/align3.s b/gas/testsuite/gas/hppa/unsorted/align3.s
new file mode 100644
index 0000000000..8bd24082cb
--- /dev/null
+++ b/gas/testsuite/gas/hppa/unsorted/align3.s
@@ -0,0 +1,20 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SPACE $TEXT$
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .blockz 4
+
+main:
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .PROC
+ .CALLINFO FRAME=0
+ .ENTRY
+ nop
+ .EXIT
+ .PROCEND
diff --git a/gas/testsuite/gas/hppa/unsorted/align4.s b/gas/testsuite/gas/hppa/unsorted/align4.s
new file mode 100644
index 0000000000..9f2f99bd0d
--- /dev/null
+++ b/gas/testsuite/gas/hppa/unsorted/align4.s
@@ -0,0 +1,4 @@
+ .space $TEXT$
+ .subspa $YABBA$
+ .subspa $MILLICODE$
+ .align 64
diff --git a/gas/testsuite/gas/hppa/unsorted/brlenbug.s b/gas/testsuite/gas/hppa/unsorted/brlenbug.s
new file mode 100644
index 0000000000..58e5c7eef8
--- /dev/null
+++ b/gas/testsuite/gas/hppa/unsorted/brlenbug.s
@@ -0,0 +1,3502 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .IMPORT $global$,DATA
+ .IMPORT $$dyncall,MILLICODE
+; gcc_compiled.:
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$
+
+ .align 4
+done___2
+ .word 0
+ .IMPORT memset,CODE
+ .EXPORT re_syntax_options,DATA
+ .align 4
+re_syntax_options
+ .word 0
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$
+
+ .align 4
+re_error_msg
+ .word 0
+ .word L$C0000
+ .word L$C0001
+ .word L$C0002
+ .word L$C0003
+ .word L$C0004
+ .word L$C0005
+ .word L$C0006
+ .word L$C0007
+ .word L$C0008
+ .word L$C0009
+ .word L$C0010
+ .word L$C0011
+ .word L$C0012
+ .word L$C0013
+ .word L$C0014
+ .word L$C0015
+ .SPACE $TEXT$
+ .SUBSPA $LIT$
+
+ .align 4
+L$C0015
+ .STRING "Unmatched ) or \\)\x00"
+ .align 4
+L$C0014
+ .STRING "Regular expression too big\x00"
+ .align 4
+L$C0013
+ .STRING "Premature end of regular expression\x00"
+ .align 4
+L$C0012
+ .STRING "Invalid preceding regular expression\x00"
+ .align 4
+L$C0011
+ .STRING "Memory exhausted\x00"
+ .align 4
+L$C0010
+ .STRING "Invalid range end\x00"
+ .align 4
+L$C0009
+ .STRING "Invalid content of \\{\\}\x00"
+ .align 4
+L$C0008
+ .STRING "Unmatched \\{\x00"
+ .align 4
+L$C0007
+ .STRING "Unmatched ( or \\(\x00"
+ .align 4
+L$C0006
+ .STRING "Unmatched [ or [^\x00"
+ .align 4
+L$C0005
+ .STRING "Invalid back reference\x00"
+ .align 4
+L$C0004
+ .STRING "Trailing backslash\x00"
+ .align 4
+L$C0003
+ .STRING "Invalid character class name\x00"
+ .align 4
+L$C0002
+ .STRING "Invalid collation character\x00"
+ .align 4
+L$C0001
+ .STRING "Invalid regular expression\x00"
+ .align 4
+L$C0000
+ .STRING "No match\x00"
+ .EXPORT re_max_failures,DATA
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$
+
+ .align 4
+re_max_failures
+ .word 2000
+ .IMPORT malloc,CODE
+ .IMPORT realloc,CODE
+ .IMPORT free,CODE
+ .IMPORT strcmp,CODE
+ .SPACE $TEXT$
+ .SUBSPA $LIT$
+
+ .align 4
+L$C0016
+ .STRING "alnum\x00"
+ .align 4
+L$C0017
+ .STRING "alpha\x00"
+ .align 4
+L$C0018
+ .STRING "blank\x00"
+ .align 4
+L$C0019
+ .STRING "cntrl\x00"
+ .align 4
+L$C0020
+ .STRING "digit\x00"
+ .align 4
+L$C0021
+ .STRING "graph\x00"
+ .align 4
+L$C0022
+ .STRING "lower\x00"
+ .align 4
+L$C0023
+ .STRING "print\x00"
+ .align 4
+L$C0024
+ .STRING "punct\x00"
+ .align 4
+L$C0025
+ .STRING "space\x00"
+ .align 4
+L$C0026
+ .STRING "upper\x00"
+ .align 4
+L$C0027
+ .STRING "xdigit\x00"
+ .IMPORT __alnum,DATA
+ .IMPORT __ctype2,DATA
+ .IMPORT __ctype,DATA
+ .IMPORT at_begline_loc_p,CODE
+ .IMPORT at_endline_loc_p,CODE
+ .IMPORT store_op1,CODE
+ .IMPORT insert_op1,CODE
+ .IMPORT store_op2,CODE
+ .IMPORT insert_op2,CODE
+ .IMPORT compile_range,CODE
+ .IMPORT group_in_compile_stack,CODE
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+regex_compile
+ .PROC
+ .CALLINFO FRAME=320,CALLS,SAVE_RP,ENTRY_GR=18
+ .ENTRY
+ stw %r2,-20(%r30) ;# 8989 reload_outsi+2/6
+ ldo 320(%r30),%r30 ;# 8991 addsi3/2
+ stw %r18,-168(%r30) ;# 8993 reload_outsi+2/6
+ stw %r17,-164(%r30) ;# 8995 reload_outsi+2/6
+ stw %r16,-160(%r30) ;# 8997 reload_outsi+2/6
+ stw %r15,-156(%r30) ;# 8999 reload_outsi+2/6
+ stw %r14,-152(%r30) ;# 9001 reload_outsi+2/6
+ stw %r13,-148(%r30) ;# 9003 reload_outsi+2/6
+ stw %r12,-144(%r30) ;# 9005 reload_outsi+2/6
+ stw %r11,-140(%r30) ;# 9007 reload_outsi+2/6
+ stw %r10,-136(%r30) ;# 9009 reload_outsi+2/6
+ stw %r9,-132(%r30) ;# 9011 reload_outsi+2/6
+ stw %r8,-128(%r30) ;# 9013 reload_outsi+2/6
+ stw %r7,-124(%r30) ;# 9015 reload_outsi+2/6
+ stw %r6,-120(%r30) ;# 9017 reload_outsi+2/6
+ stw %r5,-116(%r30) ;# 9019 reload_outsi+2/6
+ stw %r4,-112(%r30) ;# 9021 reload_outsi+2/6
+ stw %r3,-108(%r30) ;# 9023 reload_outsi+2/6
+ stw %r26,-276(%r30) ;# 4 reload_outsi+2/6
+ ldi 0,%r9 ;# 25 reload_outsi+2/2
+ ldi 0,%r8 ;# 28 reload_outsi+2/2
+ stw %r0,-260(%r30) ;# 34 reload_outsi+2/6
+ ldi 0,%r10 ;# 31 reload_outsi+2/2
+ ldi 640,%r26 ;# 37 reload_outsi+2/2
+ ldw -276(%r30),%r1 ;# 8774 reload_outsi+2/5
+ copy %r24,%r15 ;# 8 reload_outsi+2/1
+ stw %r1,-296(%r30) ;# 2325 reload_outsi+2/6
+ copy %r23,%r5 ;# 10 reload_outsi+2/1
+ addl %r1,%r25,%r16 ;# 19 addsi3/1
+ .CALL ARGW0=GR
+ bl malloc,%r2 ;# 39 call_value_internal_symref
+ ldw 20(%r5),%r14 ;# 22 reload_outsi+2/5
+ comib,<> 0,%r28,L$0021 ;# 48 bleu+1
+ stw %r28,-312(%r30) ;# 43 reload_outsi+2/6
+L$0953
+ bl L$0867,%r0 ;# 53 jump
+ ldi 12,%r28 ;# 51 reload_outsi+2/2
+L$0021
+ ldi 32,%r19 ;# 58 reload_outsi+2/2
+ stw %r19,-308(%r30) ;# 59 reload_outsi+2/6
+ stw %r0,-304(%r30) ;# 62 reload_outsi+2/6
+ stw %r15,12(%r5) ;# 65 reload_outsi+2/6
+ stw %r0,8(%r5) ;# 85 reload_outsi+2/6
+ stw %r0,24(%r5) ;# 88 reload_outsi+2/6
+ addil LR'done___2-$global$,%r27 ;# 92 pic2_lo_sum+1
+ ldw 28(%r5),%r19 ;# 68 reload_outsi+2/5
+ ldw RR'done___2-$global$(%r1),%r20 ;# 94 reload_outsi+2/5
+ depi 0,3,1,%r19 ;# 69 andsi3/2
+ depi 0,6,2,%r19 ;# 80 andsi3/2
+ comib,<> 0,%r20,L$0022 ;# 95 bleu+1
+ stw %r19,28(%r5) ;# 82 reload_outsi+2/6
+ addil LR're_syntax_table-$global$,%r27 ;# 99 pic2_lo_sum+1
+ ldo RR're_syntax_table-$global$(%r1),%r4 ;# 100 movhi-2
+ copy %r4,%r26 ;# 101 reload_outsi+2/1
+ ldi 0,%r25 ;# 102 reload_outsi+2/2
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl memset,%r2 ;# 104 call_value_internal_symref
+ ldi 256,%r24 ;# 103 reload_outsi+2/2
+ ldi 1,%r20 ;# 8732 movqi+1/2
+ ldo 97(%r4),%r19 ;# 8736 addsi3/2
+ ldo 122(%r4),%r4 ;# 8738 addsi3/2
+ stbs,ma %r20,1(%r19) ;# 115 movqi+1/6
+L$1155
+ comb,>=,n %r4,%r19,L$1155 ;# 121 bleu+1
+ stbs,ma %r20,1(%r19) ;# 115 movqi+1/6
+ ldi 1,%r21 ;# 8717 movqi+1/2
+ addil LR're_syntax_table-$global$,%r27 ;# 8712 pic2_lo_sum+1
+ ldo RR're_syntax_table-$global$(%r1),%r19 ;# 8715 movhi-2
+ ldo 65(%r19),%r20 ;# 8721 addsi3/2
+ ldo 90(%r19),%r19 ;# 8723 addsi3/2
+ stbs,ma %r21,1(%r20) ;# 138 movqi+1/6
+L$1156
+ comb,>=,n %r19,%r20,L$1156 ;# 144 bleu+1
+ stbs,ma %r21,1(%r20) ;# 138 movqi+1/6
+ ldi 48,%r20 ;# 151 reload_outsi+2/2
+ ldi 57,%r22 ;# 7976 reload_outsi+2/2
+ ldi 1,%r21 ;# 8707 movqi+1/2
+ addil LR're_syntax_table-$global$+48,%r27 ;# 8705 pic2_lo_sum+1
+ ldo RR're_syntax_table-$global$+48(%r1),%r19 ;# 8711 movhi-2
+L$0037
+ ldo 1(%r20),%r20 ;# 164 addsi3/2
+ comb,>= %r22,%r20,L$0037 ;# 167 bleu+1
+ stbs,ma %r21,1(%r19) ;# 161 movqi+1/6
+ addil LR're_syntax_table-$global$,%r27 ;# 174 pic2_lo_sum+1
+ ldo RR're_syntax_table-$global$(%r1),%r19 ;# 175 movhi-2
+ ldi 1,%r20 ;# 176 movqi+1/2
+ stb %r20,95(%r19) ;# 177 movqi+1/6
+ addil LR'done___2-$global$,%r27 ;# 178 pic2_lo_sum+1
+ ldi 1,%r19 ;# 180 reload_outsi+2/2
+ stw %r19,RR'done___2-$global$(%r1) ;# 181 reload_outsi+2/6
+L$0022
+ ldw 4(%r5),%r19 ;# 187 reload_outsi+2/5
+ comib,<>,n 0,%r19,L$0039 ;# 189 bleu+1
+ ldw 0(%r5),%r26 ;# 193 reload_outsi+2/5
+ comib,=,n 0,%r26,L$0040 ;# 195 bleu+1
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 205 call_value_internal_symref
+ ldi 32,%r25 ;# 203 reload_outsi+2/2
+ bl L$1157,%r0 ;# 211 jump
+ stw %r28,0(%r5) ;# 223 reload_outsi+2/6
+L$0040
+ .CALL ARGW0=GR
+ bl malloc,%r2 ;# 219 call_value_internal_symref
+ ldi 32,%r26 ;# 217 reload_outsi+2/2
+ stw %r28,0(%r5) ;# 223 reload_outsi+2/6
+L$1157
+ ldw 0(%r5),%r19 ;# 228 reload_outsi+2/5
+ comib,<> 0,%r19,L$0042 ;# 230 bleu+1
+ ldi 32,%r19 ;# 243 reload_outsi+2/2
+ .CALL ARGW0=GR
+ bl free,%r2 ;# 234 call_internal_symref
+ ldw -312(%r30),%r26 ;# 232 reload_outsi+2/5
+ bl L$0867,%r0 ;# 238 jump
+ ldi 12,%r28 ;# 51 reload_outsi+2/2
+L$0042
+ stw %r19,4(%r5) ;# 244 reload_outsi+2/6
+L$0039
+ ldw 0(%r5),%r6 ;# 249 reload_outsi+2/5
+ ldw -296(%r30),%r19 ;# 7981 reload_outsi+2/5
+ comclr,<> %r16,%r19,%r0 ;# 7982 bleu+1
+ bl L$0044,%r0
+ copy %r6,%r12 ;# 253 reload_outsi+2/1
+ ldw -296(%r30),%r19 ;# 2334 reload_outsi+2/5
+L$1178
+ ldbs,ma 1(%r19),%r7 ;# 277 zero_extendqisi2/2
+ comib,= 0,%r14,L$0047 ;# 282 bleu+1
+ stw %r19,-296(%r30) ;# 2337 reload_outsi+2/6
+ addl %r14,%r7,%r19 ;# 283 addsi3/1
+ ldb 0(%r19),%r7 ;# 286 zero_extendqisi2/2
+L$0047
+ ldo -10(%r7),%r19 ;# 7895 addsi3/2
+ addi,uv -115,%r19,%r0 ;# 7896 casesi0
+ blr,n %r19,%r0
+ b,n L$0076
+L$0863
+ bl L$0376,%r0
+ nop ;# 9092 switch_jump
+L$0954
+ bl L$0076,%r0
+ nop ;# 9095 switch_jump
+L$0955
+ bl L$0076,%r0
+ nop ;# 9098 switch_jump
+L$0956
+ bl L$0076,%r0
+ nop ;# 9101 switch_jump
+L$0957
+ bl L$0076,%r0
+ nop ;# 9104 switch_jump
+L$0958
+ bl L$0076,%r0
+ nop ;# 9107 switch_jump
+L$0959
+ bl L$0076,%r0
+ nop ;# 9110 switch_jump
+L$0960
+ bl L$0076,%r0
+ nop ;# 9113 switch_jump
+L$0961
+ bl L$0076,%r0
+ nop ;# 9116 switch_jump
+L$0962
+ bl L$0076,%r0
+ nop ;# 9119 switch_jump
+L$0963
+ bl L$0076,%r0
+ nop ;# 9122 switch_jump
+L$0964
+ bl L$0076,%r0
+ nop ;# 9125 switch_jump
+L$0965
+ bl L$0076,%r0
+ nop ;# 9128 switch_jump
+L$0966
+ bl L$0076,%r0
+ nop ;# 9131 switch_jump
+L$0967
+ bl L$0076,%r0
+ nop ;# 9134 switch_jump
+L$0968
+ bl L$0076,%r0
+ nop ;# 9137 switch_jump
+L$0969
+ bl L$0076,%r0
+ nop ;# 9140 switch_jump
+L$0970
+ bl L$0076,%r0
+ nop ;# 9143 switch_jump
+L$0971
+ bl L$0076,%r0
+ nop ;# 9146 switch_jump
+L$0972
+ bl L$0076,%r0
+ nop ;# 9149 switch_jump
+L$0973
+ bl L$0076,%r0
+ nop ;# 9152 switch_jump
+L$0974
+ bl L$0076,%r0
+ nop ;# 9155 switch_jump
+L$0975
+ bl L$0076,%r0
+ nop ;# 9158 switch_jump
+L$0976
+ bl L$0076,%r0
+ nop ;# 9161 switch_jump
+L$0977
+ bl L$0076,%r0
+ nop ;# 9164 switch_jump
+L$0978
+ bl L$0076,%r0
+ nop ;# 9167 switch_jump
+L$0979
+ bl L$0077,%r0 ;# 9170 switch_jump
+ ldw -296(%r30),%r26 ;# 2349 reload_outsi+2/5
+L$0980
+ bl L$0076,%r0
+ nop ;# 9173 switch_jump
+L$0981
+ bl L$0076,%r0
+ nop ;# 9176 switch_jump
+L$0982
+ bl L$0076,%r0
+ nop ;# 9179 switch_jump
+L$0983
+ bl L$0368,%r0
+ nop ;# 9182 switch_jump
+L$0984
+ bl L$0372,%r0
+ nop ;# 9185 switch_jump
+L$0985
+ bl L$0104,%r0
+ nop ;# 9188 switch_jump
+L$0986
+ bl L$1158,%r0 ;# 9191 switch_jump
+ ldi 1026,%r19 ;# 662 reload_outsi+2/2
+L$0987
+ bl L$0076,%r0
+ nop ;# 9194 switch_jump
+L$0988
+ bl L$0076,%r0
+ nop ;# 9197 switch_jump
+L$0989
+ bl L$0196,%r0 ;# 9200 switch_jump
+ ldw 0(%r5),%r4 ;# 8027 reload_outsi+2/5
+L$0990
+ bl L$0076,%r0
+ nop ;# 9203 switch_jump
+L$0991
+ bl L$0076,%r0
+ nop ;# 9206 switch_jump
+L$0992
+ bl L$0076,%r0
+ nop ;# 9209 switch_jump
+L$0993
+ bl L$0076,%r0
+ nop ;# 9212 switch_jump
+L$0994
+ bl L$0076,%r0
+ nop ;# 9215 switch_jump
+L$0995
+ bl L$0076,%r0
+ nop ;# 9218 switch_jump
+L$0996
+ bl L$0076,%r0
+ nop ;# 9221 switch_jump
+L$0997
+ bl L$0076,%r0
+ nop ;# 9224 switch_jump
+L$0998
+ bl L$0076,%r0
+ nop ;# 9227 switch_jump
+L$0999
+ bl L$0076,%r0
+ nop ;# 9230 switch_jump
+L$1000
+ bl L$0076,%r0
+ nop ;# 9233 switch_jump
+L$1001
+ bl L$0076,%r0
+ nop ;# 9236 switch_jump
+L$1002
+ bl L$0076,%r0
+ nop ;# 9239 switch_jump
+L$1003
+ bl L$0076,%r0
+ nop ;# 9242 switch_jump
+L$1004
+ bl L$0076,%r0
+ nop ;# 9245 switch_jump
+L$1005
+ bl L$0076,%r0
+ nop ;# 9248 switch_jump
+L$1006
+ bl L$0101,%r0 ;# 9251 switch_jump
+ ldi 1026,%r19 ;# 662 reload_outsi+2/2
+L$1007
+ bl L$0076,%r0
+ nop ;# 9254 switch_jump
+L$1008
+ bl L$0076,%r0
+ nop ;# 9257 switch_jump
+L$1009
+ bl L$0076,%r0
+ nop ;# 9260 switch_jump
+L$1010
+ bl L$0076,%r0
+ nop ;# 9263 switch_jump
+L$1011
+ bl L$0076,%r0
+ nop ;# 9266 switch_jump
+L$1012
+ bl L$0076,%r0
+ nop ;# 9269 switch_jump
+L$1013
+ bl L$0076,%r0
+ nop ;# 9272 switch_jump
+L$1014
+ bl L$0076,%r0
+ nop ;# 9275 switch_jump
+L$1015
+ bl L$0076,%r0
+ nop ;# 9278 switch_jump
+L$1016
+ bl L$0076,%r0
+ nop ;# 9281 switch_jump
+L$1017
+ bl L$0076,%r0
+ nop ;# 9284 switch_jump
+L$1018
+ bl L$0076,%r0
+ nop ;# 9287 switch_jump
+L$1019
+ bl L$0076,%r0
+ nop ;# 9290 switch_jump
+L$1020
+ bl L$0076,%r0
+ nop ;# 9293 switch_jump
+L$1021
+ bl L$0076,%r0
+ nop ;# 9296 switch_jump
+L$1022
+ bl L$0076,%r0
+ nop ;# 9299 switch_jump
+L$1023
+ bl L$0076,%r0
+ nop ;# 9302 switch_jump
+L$1024
+ bl L$0076,%r0
+ nop ;# 9305 switch_jump
+L$1025
+ bl L$0076,%r0
+ nop ;# 9308 switch_jump
+L$1026
+ bl L$0076,%r0
+ nop ;# 9311 switch_jump
+L$1027
+ bl L$0076,%r0
+ nop ;# 9314 switch_jump
+L$1028
+ bl L$0076,%r0
+ nop ;# 9317 switch_jump
+L$1029
+ bl L$0076,%r0
+ nop ;# 9320 switch_jump
+L$1030
+ bl L$0076,%r0
+ nop ;# 9323 switch_jump
+L$1031
+ bl L$0076,%r0
+ nop ;# 9326 switch_jump
+L$1032
+ bl L$0076,%r0
+ nop ;# 9329 switch_jump
+L$1033
+ bl L$0076,%r0
+ nop ;# 9332 switch_jump
+L$1034
+ bl L$0216,%r0 ;# 9335 switch_jump
+ ldw -296(%r30),%r19 ;# 2418 reload_outsi+2/5
+L$1035
+ bl L$0387,%r0 ;# 9338 switch_jump
+ ldw -296(%r30),%r19 ;# 3797 reload_outsi+2/5
+L$1036
+ bl L$0076,%r0
+ nop ;# 9341 switch_jump
+L$1037
+ bl L$0053,%r0 ;# 9344 switch_jump
+ ldw -276(%r30),%r1 ;# 8777 reload_outsi+2/5
+L$1038
+ bl L$0076,%r0
+ nop ;# 9347 switch_jump
+L$1039
+ bl L$0076,%r0
+ nop ;# 9350 switch_jump
+L$1040
+ bl L$0076,%r0
+ nop ;# 9353 switch_jump
+L$1041
+ bl L$0076,%r0
+ nop ;# 9356 switch_jump
+L$1042
+ bl L$0076,%r0
+ nop ;# 9359 switch_jump
+L$1043
+ bl L$0076,%r0
+ nop ;# 9362 switch_jump
+L$1044
+ bl L$0076,%r0
+ nop ;# 9365 switch_jump
+L$1045
+ bl L$0076,%r0
+ nop ;# 9368 switch_jump
+L$1046
+ bl L$0076,%r0
+ nop ;# 9371 switch_jump
+L$1047
+ bl L$0076,%r0
+ nop ;# 9374 switch_jump
+L$1048
+ bl L$0076,%r0
+ nop ;# 9377 switch_jump
+L$1049
+ bl L$0076,%r0
+ nop ;# 9380 switch_jump
+L$1050
+ bl L$0076,%r0
+ nop ;# 9383 switch_jump
+L$1051
+ bl L$0076,%r0
+ nop ;# 9386 switch_jump
+L$1052
+ bl L$0076,%r0
+ nop ;# 9389 switch_jump
+L$1053
+ bl L$0076,%r0
+ nop ;# 9392 switch_jump
+L$1054
+ bl L$0076,%r0
+ nop ;# 9395 switch_jump
+L$1055
+ bl L$0076,%r0
+ nop ;# 9398 switch_jump
+L$1056
+ bl L$0076,%r0
+ nop ;# 9401 switch_jump
+L$1057
+ bl L$0076,%r0
+ nop ;# 9404 switch_jump
+L$1058
+ bl L$0076,%r0
+ nop ;# 9407 switch_jump
+L$1059
+ bl L$0076,%r0
+ nop ;# 9410 switch_jump
+L$1060
+ bl L$0076,%r0
+ nop ;# 9413 switch_jump
+L$1061
+ bl L$0076,%r0
+ nop ;# 9416 switch_jump
+L$1062
+ bl L$0076,%r0
+ nop ;# 9419 switch_jump
+L$1063
+ bl L$0076,%r0
+ nop ;# 9422 switch_jump
+L$1064
+ bl L$0076,%r0
+ nop ;# 9425 switch_jump
+L$1065
+ bl L$0076,%r0
+ nop ;# 9428 switch_jump
+L$1066
+ bl L$0383,%r0 ;# 9431 switch_jump
+ ldi 4608,%r20 ;# 3778 reload_outsi+2/2
+L$1067
+ bl L$0380,%r0
+ nop ;# 9434 switch_jump
+L$1068
+ bl,n L$0076,%r0 ;# 7899 jump
+L$0053
+ ldw -296(%r30),%r25 ;# 2343 reload_outsi+2/5
+ ldo 1(%r1),%r19 ;# 306 addsi3/2
+ comb,=,n %r19,%r25,L$0055 ;# 308 bleu+1
+ bb,< %r15,28,L$0055 ;# 313 bleu+3
+ ldw -276(%r30),%r26 ;# 315 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl at_begline_loc_p,%r2 ;# 321 call_value_internal_symref
+ copy %r15,%r24 ;# 319 reload_outsi+2/1
+ extrs %r28,31,8,%r28 ;# 324 extendqisi2
+ comiclr,<> 0,%r28,%r0 ;# 326 bleu+1
+ bl,n L$0076,%r0
+L$0055
+ ldw 0(%r5),%r4 ;# 7986 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 7989 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 7987 subsi3/1
+ ldo 1(%r19),%r19 ;# 7988 addsi3/2
+ comb,>>=,n %r20,%r19,L$0060 ;# 7990 bleu+1
+ ldil L'65536,%r3 ;# 8701 reload_outsi+2/3
+L$0061
+ comclr,<> %r3,%r20,%r0 ;# 357 bleu+1
+ bl L$0944,%r0
+ zdep %r20,30,31,%r19 ;# 367 ashlsi3+1
+ comb,>>= %r3,%r19,L$0066 ;# 375 bleu+1
+ stw %r19,4(%r5) ;# 369 reload_outsi+2/6
+ stw %r3,4(%r5) ;# 378 reload_outsi+2/6
+L$0066
+ ldw 0(%r5),%r26 ;# 385 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 389 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 387 reload_outsi+2/5
+ comib,= 0,%r28,L$0953 ;# 397 bleu+1
+ stw %r28,0(%r5) ;# 393 reload_outsi+2/6
+ comb,= %r28,%r4,L$0059 ;# 407 bleu+1
+ sub %r6,%r4,%r19 ;# 409 subsi3/1
+ addl %r28,%r19,%r6 ;# 412 addsi3/1
+ sub %r12,%r4,%r19 ;# 413 subsi3/1
+ comib,= 0,%r10,L$0069 ;# 418 bleu+1
+ addl %r28,%r19,%r12 ;# 416 addsi3/1
+ sub %r10,%r4,%r19 ;# 419 subsi3/1
+ addl %r28,%r19,%r10 ;# 422 addsi3/1
+L$0069
+ comib,= 0,%r8,L$0070 ;# 425 bleu+1
+ sub %r8,%r4,%r19 ;# 426 subsi3/1
+ addl %r28,%r19,%r8 ;# 429 addsi3/1
+L$0070
+ comib,= 0,%r9,L$0059 ;# 432 bleu+1
+ sub %r9,%r4,%r19 ;# 433 subsi3/1
+ addl %r28,%r19,%r9 ;# 436 addsi3/1
+L$0059
+ ldw 0(%r5),%r4 ;# 337 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 341 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 338 subsi3/1
+ ldo 1(%r19),%r19 ;# 339 addsi3/2
+ comb,<< %r20,%r19,L$0061
+ nop ;# 343 bleu+1
+L$0060
+ ldi 8,%r19 ;# 458 movqi+1/2
+ bl L$0043,%r0 ;# 479 jump
+ stbs,ma %r19,1(%r6) ;# 459 movqi+1/6
+L$0077
+ comb,=,n %r16,%r26,L$0079 ;# 485 bleu+1
+ bb,< %r15,28,L$0079 ;# 490 bleu+3
+ copy %r16,%r25 ;# 494 reload_outsi+2/1
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl at_endline_loc_p,%r2 ;# 498 call_value_internal_symref
+ copy %r15,%r24 ;# 496 reload_outsi+2/1
+ extrs %r28,31,8,%r28 ;# 501 extendqisi2
+ comiclr,<> 0,%r28,%r0 ;# 503 bleu+1
+ bl,n L$0076,%r0
+L$0079
+ ldw 0(%r5),%r4 ;# 7994 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 7997 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 7995 subsi3/1
+ ldo 1(%r19),%r19 ;# 7996 addsi3/2
+ comb,>>=,n %r20,%r19,L$0084 ;# 7998 bleu+1
+ ldil L'65536,%r3 ;# 8699 reload_outsi+2/3
+L$0085
+ comclr,<> %r3,%r20,%r0 ;# 534 bleu+1
+ bl L$0944,%r0
+ zdep %r20,30,31,%r19 ;# 544 ashlsi3+1
+ comb,>>= %r3,%r19,L$0090 ;# 552 bleu+1
+ stw %r19,4(%r5) ;# 546 reload_outsi+2/6
+ stw %r3,4(%r5) ;# 555 reload_outsi+2/6
+L$0090
+ ldw 0(%r5),%r26 ;# 562 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 566 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 564 reload_outsi+2/5
+ comib,= 0,%r28,L$0953 ;# 574 bleu+1
+ stw %r28,0(%r5) ;# 570 reload_outsi+2/6
+ comb,= %r28,%r4,L$0083 ;# 584 bleu+1
+ sub %r6,%r4,%r19 ;# 586 subsi3/1
+ addl %r28,%r19,%r6 ;# 589 addsi3/1
+ sub %r12,%r4,%r19 ;# 590 subsi3/1
+ comib,= 0,%r10,L$0093 ;# 595 bleu+1
+ addl %r28,%r19,%r12 ;# 593 addsi3/1
+ sub %r10,%r4,%r19 ;# 596 subsi3/1
+ addl %r28,%r19,%r10 ;# 599 addsi3/1
+L$0093
+ comib,= 0,%r8,L$0094 ;# 602 bleu+1
+ sub %r8,%r4,%r19 ;# 603 subsi3/1
+ addl %r28,%r19,%r8 ;# 606 addsi3/1
+L$0094
+ comib,= 0,%r9,L$0083 ;# 609 bleu+1
+ sub %r9,%r4,%r19 ;# 610 subsi3/1
+ addl %r28,%r19,%r9 ;# 613 addsi3/1
+L$0083
+ ldw 0(%r5),%r4 ;# 514 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 518 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 515 subsi3/1
+ ldo 1(%r19),%r19 ;# 516 addsi3/2
+ comb,<< %r20,%r19,L$0085
+ nop ;# 520 bleu+1
+L$0084
+ ldi 9,%r19 ;# 635 movqi+1/2
+ bl L$0043,%r0 ;# 656 jump
+ stbs,ma %r19,1(%r6) ;# 636 movqi+1/6
+L$0877
+ bl L$0110,%r0 ;# 897 jump
+ stw %r21,-296(%r30) ;# 2391 reload_outsi+2/6
+L$0101
+L$1158
+ and %r15,%r19,%r19 ;# 663 andsi3/1
+ comiclr,= 0,%r19,%r0 ;# 665 bleu+1
+ bl,n L$0076,%r0
+L$0104
+ comib,<> 0,%r8,L$0105 ;# 674 bleu+1
+ ldi 0,%r13 ;# 711 reload_outsi+2/2
+ extrs,>= %r15,26,1,%r0 ;# 681 bleu+3
+ extrs,< %r15,27,1,%r0 ;# 700 movsi-4
+ nop
+ bl,n L$0076,%r0
+L$0105
+ ldi 0,%r11 ;# 714 reload_outsi+2/2
+ ldi 0,%r22 ;# 716 reload_outsi+2/2
+ ldi 43,%r24 ;# 8688 reload_outsi+2/2
+ ldi 63,%r23 ;# 8690 reload_outsi+2/2
+ ldi 42,%r28 ;# 8692 reload_outsi+2/2
+ ldi 2,%r19 ;# 8694 reload_outsi+2/2
+ and %r15,%r19,%r25 ;# 8695 andsi3/1
+ ldi 92,%r26 ;# 8697 reload_outsi+2/2
+L$0109
+ comb,= %r24,%r7,L$0112 ;# 727 bleu+1
+ copy %r11,%r19 ;# 8780 reload_outsi+2/1
+ depi -1,31,1,%r19 ;# 729 iorsi3+1/2
+ bl L$0113,%r0 ;# 731 jump
+ extrs %r19,31,8,%r19 ;# 730 extendqisi2
+L$0112
+ extrs %r11,31,8,%r19 ;# 734 extendqisi2
+L$0113
+L$1159
+ comb,= %r23,%r7,L$0114 ;# 744 bleu+1
+ copy %r19,%r11 ;# 737 reload_outsi+2/1
+ copy %r22,%r19 ;# 8783 reload_outsi+2/1
+ depi -1,31,1,%r19 ;# 746 iorsi3+1/2
+ bl L$0115,%r0 ;# 748 jump
+ extrs %r19,31,8,%r19 ;# 747 extendqisi2
+L$0114
+ extrs %r22,31,8,%r19 ;# 751 extendqisi2
+L$0115
+ ldw -296(%r30),%r21 ;# 2355 reload_outsi+2/5
+ comb,= %r16,%r21,L$0110 ;# 757 bleu+1
+ copy %r19,%r22 ;# 754 reload_outsi+2/1
+ copy %r21,%r20 ;# 8743 reload_outsi+2/1
+ ldbs,ma 1(%r20),%r7 ;# 776 zero_extendqisi2/2
+ comib,= 0,%r14,L$0118 ;# 781 bleu+1
+ stw %r20,-296(%r30) ;# 2364 reload_outsi+2/6
+ addl %r14,%r7,%r19 ;# 782 addsi3/1
+ ldb 0(%r19),%r7 ;# 785 zero_extendqisi2/2
+L$0118
+ comb,= %r28,%r7,L$0109
+ nop ;# 802 bleu+1
+ comib,<>,n 0,%r25,L$0869 ;# 807 bleu+1
+ comb,= %r24,%r7,L$1159 ;# 811 bleu+1
+ extrs %r11,31,8,%r19 ;# 734 extendqisi2
+ comb,= %r23,%r7,L$0109 ;# 815 bleu+1
+ ldw -296(%r30),%r19 ;# 2400 reload_outsi+2/5
+ bl,n L$1160,%r0 ;# 827 jump
+L$0869
+ comb,<> %r26,%r7,L$0126 ;# 831 bleu+1
+ ldw -296(%r30),%r19 ;# 2400 reload_outsi+2/5
+ comclr,<> %r16,%r20,%r0 ;# 835 bleu+1
+ bl L$0903,%r0
+ ldo 1(%r20),%r19 ;# 863 addsi3/2
+ ldb 1(%r21),%r3 ;# 860 zero_extendqisi2/2
+ comib,= 0,%r14,L$0129 ;# 865 bleu+1
+ stw %r19,-296(%r30) ;# 2379 reload_outsi+2/6
+ addl %r14,%r3,%r19 ;# 866 addsi3/1
+ ldb 0(%r19),%r3 ;# 869 zero_extendqisi2/2
+L$0129
+ comb,= %r24,%r3,L$0109 ;# 886 bleu+1
+ copy %r3,%r7 ;# 903 reload_outsi+2/1
+ comb,<> %r23,%r3,L$0877
+ nop ;# 890 bleu+1
+ bl,n L$0109,%r0 ;# 905 jump
+L$0126
+L$1160
+ ldo -1(%r19),%r19 ;# 910 addsi3/2
+ stw %r19,-296(%r30) ;# 2397 reload_outsi+2/6
+L$0110
+ comiclr,<> 0,%r8,%r0 ;# 927 bleu+1
+ bl L$1161,%r0
+ ldw -296(%r30),%r19 ;# 2328 reload_outsi+2/5
+ comib,=,n 0,%r22,L$0137 ;# 934 bleu+1
+ ldw 0(%r5),%r3 ;# 8002 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 8005 reload_outsi+2/5
+ sub %r6,%r3,%r19 ;# 8003 subsi3/1
+ ldo 3(%r19),%r19 ;# 8004 addsi3/2
+ comb,>>=,n %r20,%r19,L$0139 ;# 8006 bleu+1
+ ldil L'65536,%r4 ;# 8686 reload_outsi+2/3
+L$0140
+ comclr,<> %r4,%r20,%r0 ;# 961 bleu+1
+ bl L$0944,%r0
+ zdep %r20,30,31,%r19 ;# 971 ashlsi3+1
+ comb,>>= %r4,%r19,L$0145 ;# 979 bleu+1
+ stw %r19,4(%r5) ;# 973 reload_outsi+2/6
+ stw %r4,4(%r5) ;# 982 reload_outsi+2/6
+L$0145
+ ldw 0(%r5),%r26 ;# 989 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 993 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 991 reload_outsi+2/5
+ comib,= 0,%r28,L$0953 ;# 1001 bleu+1
+ stw %r28,0(%r5) ;# 997 reload_outsi+2/6
+ comb,= %r28,%r3,L$0138 ;# 1011 bleu+1
+ sub %r6,%r3,%r19 ;# 1013 subsi3/1
+ addl %r28,%r19,%r6 ;# 1016 addsi3/1
+ sub %r12,%r3,%r19 ;# 1017 subsi3/1
+ comib,= 0,%r10,L$0148 ;# 1022 bleu+1
+ addl %r28,%r19,%r12 ;# 1020 addsi3/1
+ sub %r10,%r3,%r19 ;# 1023 subsi3/1
+ addl %r28,%r19,%r10 ;# 1026 addsi3/1
+L$0148
+ comib,= 0,%r8,L$0149 ;# 1029 bleu+1
+ sub %r8,%r3,%r19 ;# 1030 subsi3/1
+ addl %r28,%r19,%r8 ;# 1033 addsi3/1
+L$0149
+ comib,= 0,%r9,L$0138 ;# 1036 bleu+1
+ sub %r9,%r3,%r19 ;# 1037 subsi3/1
+ addl %r28,%r19,%r9 ;# 1040 addsi3/1
+L$0138
+ ldw 0(%r5),%r3 ;# 941 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 945 reload_outsi+2/5
+ sub %r6,%r3,%r19 ;# 942 subsi3/1
+ ldo 3(%r19),%r19 ;# 943 addsi3/2
+ comb,<< %r20,%r19,L$0140
+ nop ;# 947 bleu+1
+L$0139
+ comib,= 0,%r14,L$0154 ;# 1063 bleu+1
+ ldw -296(%r30),%r19 ;# 2403 reload_outsi+2/5
+ ldb -2(%r19),%r19 ;# 1066 zero_extendqisi2/2
+ addl %r14,%r19,%r19 ;# 1067 addsi3/1
+ bl L$0947,%r0 ;# 1071 jump
+ ldb 0(%r19),%r19 ;# 1069 movqi+1/5
+L$0154
+ ldb -2(%r19),%r19 ;# 1075 movqi+1/5
+L$0947
+ comib,= 0,%r14,L$0156 ;# 1079 bleu+1
+ extrs %r19,31,8,%r20 ;# 1076 extendqisi2
+ ldb 46(%r14),%r19 ;# 1081 movqi+1/5
+ extrs %r19,31,8,%r19 ;# 1082 extendqisi2
+ comb,= %r19,%r20,L$0157 ;# 1084 bleu+1
+ ldi 17,%r26 ;# 1159 reload_outsi+2/2
+ bl,n L$1162,%r0 ;# 1085 jump
+L$0156
+ ldi 46,%r19 ;# 1089 reload_outsi+2/2
+ comb,<> %r19,%r20,L$1162 ;# 1091 bleu+1
+ ldi 17,%r26 ;# 1159 reload_outsi+2/2
+L$0157
+ comib,= 0,%r11,L$0153 ;# 1096 bleu+1
+ ldw -296(%r30),%r19 ;# 2409 reload_outsi+2/5
+ comb,<<= %r16,%r19,L$1162 ;# 1098 bleu+1
+ ldi 17,%r26 ;# 1159 reload_outsi+2/2
+ comib,=,n 0,%r14,L$0158 ;# 1100 bleu+1
+ ldb 0(%r19),%r19 ;# 1103 zero_extendqisi2/2
+ addl %r14,%r19,%r19 ;# 1104 addsi3/1
+L$0158
+ ldb 0(%r19),%r19 ;# 1112 movqi+1/5
+ comib,= 0,%r14,L$0160 ;# 1116 bleu+1
+ extrs %r19,31,8,%r20 ;# 1113 extendqisi2
+ ldb 10(%r14),%r19 ;# 1118 movqi+1/5
+ extrs %r19,31,8,%r19 ;# 1119 extendqisi2
+ comb,= %r19,%r20,L$0161 ;# 1121 bleu+1
+ ldi 17,%r26 ;# 1159 reload_outsi+2/2
+ bl,n L$1162,%r0 ;# 1122 jump
+L$0160
+ comib,<> 10,%r20,L$1162 ;# 1126 bleu+1
+ ldi 17,%r26 ;# 1159 reload_outsi+2/2
+L$0161
+ bb,< %r15,25,L$1162 ;# 1134 bleu+3
+ ldi 17,%r26 ;# 1159 reload_outsi+2/2
+ ldi 12,%r26 ;# 1140 reload_outsi+2/2
+ copy %r6,%r25 ;# 1142 reload_outsi+2/1
+ sub %r8,%r6,%r24 ;# 1137 subsi3/1
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl store_op1,%r2 ;# 1146 call_internal_symref
+ ldo -3(%r24),%r24 ;# 1144 addsi3/2
+ bl L$0162,%r0 ;# 1151 jump
+ ldi 1,%r13 ;# 1149 reload_outsi+2/2
+L$0153
+ ldi 17,%r26 ;# 1159 reload_outsi+2/2
+L$1162
+ copy %r6,%r25 ;# 1161 reload_outsi+2/1
+ sub %r8,%r6,%r24 ;# 1156 subsi3/1
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl store_op1,%r2 ;# 1165 call_internal_symref
+ ldo -6(%r24),%r24 ;# 1163 addsi3/2
+L$0162
+ ldo 3(%r6),%r6 ;# 1168 addsi3/2
+L$0137
+ ldw 0(%r5),%r3 ;# 8010 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 8013 reload_outsi+2/5
+ sub %r6,%r3,%r19 ;# 8011 subsi3/1
+ ldo 3(%r19),%r19 ;# 8012 addsi3/2
+ comb,>>=,n %r20,%r19,L$0164 ;# 8014 bleu+1
+ ldil L'65536,%r4 ;# 8684 reload_outsi+2/3
+L$0165
+ comclr,<> %r4,%r20,%r0 ;# 1195 bleu+1
+ bl L$0944,%r0
+ zdep %r20,30,31,%r19 ;# 1205 ashlsi3+1
+ comb,>>= %r4,%r19,L$0170 ;# 1213 bleu+1
+ stw %r19,4(%r5) ;# 1207 reload_outsi+2/6
+ stw %r4,4(%r5) ;# 1216 reload_outsi+2/6
+L$0170
+ ldw 0(%r5),%r26 ;# 1223 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 1227 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 1225 reload_outsi+2/5
+ comib,= 0,%r28,L$0953 ;# 1235 bleu+1
+ stw %r28,0(%r5) ;# 1231 reload_outsi+2/6
+ comb,= %r28,%r3,L$0163 ;# 1245 bleu+1
+ sub %r6,%r3,%r19 ;# 1247 subsi3/1
+ addl %r28,%r19,%r6 ;# 1250 addsi3/1
+ sub %r12,%r3,%r19 ;# 1251 subsi3/1
+ comib,= 0,%r10,L$0173 ;# 1256 bleu+1
+ addl %r28,%r19,%r12 ;# 1254 addsi3/1
+ sub %r10,%r3,%r19 ;# 1257 subsi3/1
+ addl %r28,%r19,%r10 ;# 1260 addsi3/1
+L$0173
+ comib,= 0,%r8,L$0174 ;# 1263 bleu+1
+ sub %r8,%r3,%r19 ;# 1264 subsi3/1
+ addl %r28,%r19,%r8 ;# 1267 addsi3/1
+L$0174
+ comib,= 0,%r9,L$0163 ;# 1270 bleu+1
+ sub %r9,%r3,%r19 ;# 1271 subsi3/1
+ addl %r28,%r19,%r9 ;# 1274 addsi3/1
+L$0163
+ ldw 0(%r5),%r3 ;# 1175 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 1179 reload_outsi+2/5
+ sub %r6,%r3,%r19 ;# 1176 subsi3/1
+ ldo 3(%r19),%r19 ;# 1177 addsi3/2
+ comb,<< %r20,%r19,L$0165
+ nop ;# 1181 bleu+1
+L$0164
+ ldi 14,%r26 ;# 8786 reload_outsi+2/2
+ comiclr,= 0,%r13,%r0 ;# 1310 beq-1/2
+ ldi 15,%r26
+ copy %r8,%r25 ;# 1312 reload_outsi+2/1
+ sub %r6,%r8,%r24 ;# 1314 subsi3/1
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl insert_op1,%r2 ;# 1318 call_internal_symref
+ copy %r6,%r23 ;# 1316 reload_outsi+2/1
+ ldi 0,%r9 ;# 1321 reload_outsi+2/2
+ comib,<> 0,%r11,L$0043 ;# 1326 bleu+1
+ ldo 3(%r6),%r6 ;# 1323 addsi3/2
+ ldw 0(%r5),%r3 ;# 8019 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 8022 reload_outsi+2/5
+ sub %r6,%r3,%r19 ;# 8020 subsi3/1
+ ldo 3(%r19),%r19 ;# 8021 addsi3/2
+ comb,>>=,n %r20,%r19,L$0182 ;# 8023 bleu+1
+ ldil L'65536,%r4 ;# 8682 reload_outsi+2/3
+L$0183
+ comb,= %r4,%r20,L$0944 ;# 1352 bleu+1
+ zdep %r20,30,31,%r19 ;# 1362 ashlsi3+1
+ comb,>>= %r4,%r19,L$0188 ;# 1370 bleu+1
+ stw %r19,4(%r5) ;# 1364 reload_outsi+2/6
+ stw %r4,4(%r5) ;# 1373 reload_outsi+2/6
+L$0188
+ ldw 0(%r5),%r26 ;# 1380 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 1384 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 1382 reload_outsi+2/5
+ comib,= 0,%r28,L$0953 ;# 1392 bleu+1
+ stw %r28,0(%r5) ;# 1388 reload_outsi+2/6
+ comb,= %r28,%r3,L$0181 ;# 1402 bleu+1
+ sub %r6,%r3,%r19 ;# 1404 subsi3/1
+ addl %r28,%r19,%r6 ;# 1407 addsi3/1
+ sub %r12,%r3,%r19 ;# 1408 subsi3/1
+ comib,= 0,%r10,L$0191 ;# 1413 bleu+1
+ addl %r28,%r19,%r12 ;# 1411 addsi3/1
+ sub %r10,%r3,%r19 ;# 1414 subsi3/1
+ addl %r28,%r19,%r10 ;# 1417 addsi3/1
+L$0191
+ comib,= 0,%r8,L$0192 ;# 1420 bleu+1
+ sub %r8,%r3,%r19 ;# 1421 subsi3/1
+ addl %r28,%r19,%r8 ;# 1424 addsi3/1
+L$0192
+ comib,= 0,%r9,L$0181 ;# 1427 bleu+1
+ sub %r9,%r3,%r19 ;# 1428 subsi3/1
+ addl %r28,%r19,%r9 ;# 1431 addsi3/1
+L$0181
+ ldw 0(%r5),%r3 ;# 1332 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 1336 reload_outsi+2/5
+ sub %r6,%r3,%r19 ;# 1333 subsi3/1
+ ldo 3(%r19),%r19 ;# 1334 addsi3/2
+ comb,<< %r20,%r19,L$0183
+ nop ;# 1338 bleu+1
+L$0182
+ ldi 18,%r26 ;# 1454 reload_outsi+2/2
+ copy %r8,%r25 ;# 1456 reload_outsi+2/1
+ ldi 3,%r24 ;# 1458 reload_outsi+2/2
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl insert_op1,%r2 ;# 1462 call_internal_symref
+ copy %r6,%r23 ;# 1460 reload_outsi+2/1
+ bl L$0043,%r0 ;# 1470 jump
+ ldo 3(%r6),%r6 ;# 1464 addsi3/2
+L$0196
+ ldw 4(%r5),%r20 ;# 8030 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 8028 subsi3/1
+ ldo 1(%r19),%r19 ;# 8029 addsi3/2
+ comb,>>= %r20,%r19,L$0201 ;# 8031 bleu+1
+ copy %r6,%r8 ;# 1475 reload_outsi+2/1
+ ldil L'65536,%r3 ;# 8680 reload_outsi+2/3
+L$0202
+ comb,= %r3,%r20,L$0944 ;# 1503 bleu+1
+ zdep %r20,30,31,%r19 ;# 1513 ashlsi3+1
+ comb,>>= %r3,%r19,L$0207 ;# 1521 bleu+1
+ stw %r19,4(%r5) ;# 1515 reload_outsi+2/6
+ stw %r3,4(%r5) ;# 1524 reload_outsi+2/6
+L$0207
+ ldw 0(%r5),%r26 ;# 1531 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 1535 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 1533 reload_outsi+2/5
+ comib,= 0,%r28,L$0953 ;# 1543 bleu+1
+ stw %r28,0(%r5) ;# 1539 reload_outsi+2/6
+ comb,= %r28,%r4,L$0200 ;# 1553 bleu+1
+ sub %r6,%r4,%r19 ;# 1555 subsi3/1
+ addl %r28,%r19,%r6 ;# 1558 addsi3/1
+ sub %r12,%r4,%r19 ;# 1559 subsi3/1
+ comib,= 0,%r10,L$0210 ;# 1564 bleu+1
+ addl %r28,%r19,%r12 ;# 1562 addsi3/1
+ sub %r10,%r4,%r19 ;# 1565 subsi3/1
+ addl %r28,%r19,%r10 ;# 1568 addsi3/1
+L$0210
+ comib,= 0,%r8,L$0211 ;# 1571 bleu+1
+ sub %r8,%r4,%r19 ;# 1572 subsi3/1
+ addl %r28,%r19,%r8 ;# 1575 addsi3/1
+L$0211
+ comib,= 0,%r9,L$0200 ;# 1578 bleu+1
+ sub %r9,%r4,%r19 ;# 1579 subsi3/1
+ addl %r28,%r19,%r9 ;# 1582 addsi3/1
+L$0200
+ ldw 0(%r5),%r4 ;# 1483 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 1487 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 1484 subsi3/1
+ ldo 1(%r19),%r19 ;# 1485 addsi3/2
+ comb,<< %r20,%r19,L$0202
+ nop ;# 1489 bleu+1
+L$0201
+ ldi 2,%r19 ;# 1604 movqi+1/2
+ bl L$0043,%r0 ;# 1617 jump
+ stbs,ma %r19,1(%r6) ;# 1605 movqi+1/6
+L$0216
+ comb,= %r16,%r19,L$0902 ;# 1626 bleu+1
+ ldi 0,%r13 ;# 1623 reload_outsi+2/2
+ ldw 0(%r5),%r3 ;# 8035 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 8038 reload_outsi+2/5
+ sub %r6,%r3,%r19 ;# 8036 subsi3/1
+ ldo 34(%r19),%r19 ;# 8037 addsi3/2
+ comb,>>= %r20,%r19,L$0219 ;# 8039 bleu+1
+ ldil L'65536,%r4 ;# 8678 reload_outsi+2/3
+L$0220
+ comb,= %r4,%r20,L$0944 ;# 1661 bleu+1
+ zdep %r20,30,31,%r19 ;# 1671 ashlsi3+1
+ comb,>>= %r4,%r19,L$0225 ;# 1679 bleu+1
+ stw %r19,4(%r5) ;# 1673 reload_outsi+2/6
+ stw %r4,4(%r5) ;# 1682 reload_outsi+2/6
+L$0225
+ ldw 0(%r5),%r26 ;# 1689 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 1693 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 1691 reload_outsi+2/5
+ comib,= 0,%r28,L$0953 ;# 1701 bleu+1
+ stw %r28,0(%r5) ;# 1697 reload_outsi+2/6
+ comb,= %r28,%r3,L$0218 ;# 1711 bleu+1
+ sub %r6,%r3,%r19 ;# 1713 subsi3/1
+ addl %r28,%r19,%r6 ;# 1716 addsi3/1
+ sub %r12,%r3,%r19 ;# 1717 subsi3/1
+ comib,= 0,%r10,L$0228 ;# 1722 bleu+1
+ addl %r28,%r19,%r12 ;# 1720 addsi3/1
+ sub %r10,%r3,%r19 ;# 1723 subsi3/1
+ addl %r28,%r19,%r10 ;# 1726 addsi3/1
+L$0228
+ comib,= 0,%r8,L$0229 ;# 1729 bleu+1
+ sub %r8,%r3,%r19 ;# 1730 subsi3/1
+ addl %r28,%r19,%r8 ;# 1733 addsi3/1
+L$0229
+ comib,= 0,%r9,L$0218 ;# 1736 bleu+1
+ sub %r9,%r3,%r19 ;# 1737 subsi3/1
+ addl %r28,%r19,%r9 ;# 1740 addsi3/1
+L$0218
+ ldw 0(%r5),%r3 ;# 1641 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 1645 reload_outsi+2/5
+ sub %r6,%r3,%r19 ;# 1642 subsi3/1
+ ldo 34(%r19),%r19 ;# 1643 addsi3/2
+ comb,<< %r20,%r19,L$0220
+ nop ;# 1647 bleu+1
+L$0219
+ ldw 0(%r5),%r4 ;# 8043 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 8046 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 8044 subsi3/1
+ ldo 1(%r19),%r19 ;# 8045 addsi3/2
+ comb,>>= %r20,%r19,L$0237 ;# 8047 bleu+1
+ copy %r6,%r8 ;# 1763 reload_outsi+2/1
+ ldil L'65536,%r3 ;# 8676 reload_outsi+2/3
+L$0238
+ comb,= %r3,%r20,L$0944 ;# 1791 bleu+1
+ zdep %r20,30,31,%r19 ;# 1801 ashlsi3+1
+ comb,>>= %r3,%r19,L$0243 ;# 1809 bleu+1
+ stw %r19,4(%r5) ;# 1803 reload_outsi+2/6
+ stw %r3,4(%r5) ;# 1812 reload_outsi+2/6
+L$0243
+ ldw 0(%r5),%r26 ;# 1819 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 1823 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 1821 reload_outsi+2/5
+ comib,= 0,%r28,L$0953 ;# 1831 bleu+1
+ stw %r28,0(%r5) ;# 1827 reload_outsi+2/6
+ comb,= %r28,%r4,L$0236 ;# 1841 bleu+1
+ sub %r6,%r4,%r19 ;# 1843 subsi3/1
+ addl %r28,%r19,%r6 ;# 1846 addsi3/1
+ sub %r12,%r4,%r19 ;# 1847 subsi3/1
+ comib,= 0,%r10,L$0246 ;# 1852 bleu+1
+ addl %r28,%r19,%r12 ;# 1850 addsi3/1
+ sub %r10,%r4,%r19 ;# 1853 subsi3/1
+ addl %r28,%r19,%r10 ;# 1856 addsi3/1
+L$0246
+ comib,= 0,%r8,L$0247 ;# 1859 bleu+1
+ sub %r8,%r4,%r19 ;# 1860 subsi3/1
+ addl %r28,%r19,%r8 ;# 1863 addsi3/1
+L$0247
+ comib,= 0,%r9,L$0236 ;# 1866 bleu+1
+ sub %r9,%r4,%r19 ;# 1867 subsi3/1
+ addl %r28,%r19,%r9 ;# 1870 addsi3/1
+L$0236
+ ldw 0(%r5),%r4 ;# 1771 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 1775 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 1772 subsi3/1
+ ldo 1(%r19),%r19 ;# 1773 addsi3/2
+ comb,<< %r20,%r19,L$0238
+ nop ;# 1777 bleu+1
+L$0237
+ copy %r6,%r22 ;# 1909 reload_outsi+2/1
+ ldo 1(%r6),%r6 ;# 1891 addsi3/2
+ ldw -296(%r30),%r19 ;# 2421 reload_outsi+2/5
+ ldb 0(%r19),%r19 ;# 1893 movqi+1/5
+ ldi 94,%r21 ;# 1896 reload_outsi+2/2
+ extrs %r19,31,8,%r19 ;# 1894 extendqisi2
+ comb,<> %r21,%r19,L$0251 ;# 1898 bleu+1
+ ldi 3,%r20 ;# 8051 movqi+1/2
+ ldi 4,%r20 ;# 1900 movqi+1/2
+L$0251
+ stb %r20,0(%r22) ;# 1911 movqi+1/6
+ ldw -296(%r30),%r20 ;# 2424 reload_outsi+2/5
+ ldb 0(%r20),%r19 ;# 1923 movqi+1/5
+ extrs %r19,31,8,%r19 ;# 1924 extendqisi2
+ comb,<> %r21,%r19,L$0254 ;# 1928 bleu+1
+ ldo 1(%r20),%r19 ;# 1930 addsi3/2
+ stw %r19,-296(%r30) ;# 2427 reload_outsi+2/6
+L$0254
+ ldw 0(%r5),%r4 ;# 8052 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 8055 reload_outsi+2/5
+ ldw -296(%r30),%r1 ;# 2433 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 8053 subsi3/1
+ ldo 1(%r19),%r19 ;# 8054 addsi3/2
+ comb,>>= %r20,%r19,L$0259 ;# 8056 bleu+1
+ stw %r1,-268(%r30) ;# 8789 reload_outsi+2/6
+ ldil L'65536,%r3 ;# 8674 reload_outsi+2/3
+L$0260
+ comb,= %r3,%r20,L$0944 ;# 1962 bleu+1
+ zdep %r20,30,31,%r19 ;# 1972 ashlsi3+1
+ comb,>>= %r3,%r19,L$0265 ;# 1980 bleu+1
+ stw %r19,4(%r5) ;# 1974 reload_outsi+2/6
+ stw %r3,4(%r5) ;# 1983 reload_outsi+2/6
+L$0265
+ ldw 0(%r5),%r26 ;# 1990 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 1994 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 1992 reload_outsi+2/5
+ comib,= 0,%r28,L$0953 ;# 2002 bleu+1
+ stw %r28,0(%r5) ;# 1998 reload_outsi+2/6
+ comb,= %r28,%r4,L$0258 ;# 2012 bleu+1
+ sub %r6,%r4,%r19 ;# 2014 subsi3/1
+ addl %r28,%r19,%r6 ;# 2017 addsi3/1
+ sub %r12,%r4,%r19 ;# 2018 subsi3/1
+ comib,= 0,%r10,L$0268 ;# 2023 bleu+1
+ addl %r28,%r19,%r12 ;# 2021 addsi3/1
+ sub %r10,%r4,%r19 ;# 2024 subsi3/1
+ addl %r28,%r19,%r10 ;# 2027 addsi3/1
+L$0268
+ comib,= 0,%r8,L$0269 ;# 2030 bleu+1
+ sub %r8,%r4,%r19 ;# 2031 subsi3/1
+ addl %r28,%r19,%r8 ;# 2034 addsi3/1
+L$0269
+ comib,= 0,%r9,L$0258 ;# 2037 bleu+1
+ sub %r9,%r4,%r19 ;# 2038 subsi3/1
+ addl %r28,%r19,%r9 ;# 2041 addsi3/1
+L$0258
+ ldw 0(%r5),%r4 ;# 1942 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 1946 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 1943 subsi3/1
+ ldo 1(%r19),%r19 ;# 1944 addsi3/2
+ comb,<< %r20,%r19,L$0260
+ nop ;# 1948 bleu+1
+L$0259
+ ldi 32,%r19 ;# 2063 movqi+1/2
+ stbs,ma %r19,1(%r6) ;# 2064 movqi+1/6
+ copy %r6,%r26 ;# 2077 reload_outsi+2/1
+ ldi 0,%r25 ;# 2079 reload_outsi+2/2
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl memset,%r2 ;# 2083 call_value_internal_symref
+ ldi 32,%r24 ;# 2081 reload_outsi+2/2
+ ldb -2(%r6),%r19 ;# 2087 zero_extendqisi2/2
+ comib,<> 4,%r19,L$0274 ;# 2089 bleu+1
+ ldi 93,%r17 ;# 8622 reload_outsi+2/2
+ bb,>=,n %r15,23,L$0274 ;# 2094 movsi-4
+ ldb 1(%r6),%r19 ;# 2097 movqi+1/5
+ depi -1,29,1,%r19 ;# 2099 iorsi3+1/2
+ stb %r19,1(%r6) ;# 2101 movqi+1/6
+L$0274
+ ldi 4,%r18 ;# 8628 reload_outsi+2/2
+ and %r15,%r18,%r1 ;# 8629 andsi3/1
+ stw %r1,-252(%r30) ;# 8792 reload_outsi+2/6
+ ldo -288(%r30),%r11 ;# 8632 addsi3/2
+L$0275
+ ldw -296(%r30),%r20 ;# 2436 reload_outsi+2/5
+L$1165
+ comb,= %r16,%r20,L$0902 ;# 2109 bleu+1
+ copy %r20,%r21 ;# 8745 reload_outsi+2/1
+ ldbs,ma 1(%r21),%r7 ;# 2134 zero_extendqisi2/2
+ comib,= 0,%r14,L$0280 ;# 2139 bleu+1
+ stw %r21,-296(%r30) ;# 2445 reload_outsi+2/6
+ addl %r14,%r7,%r19 ;# 2140 addsi3/1
+ ldb 0(%r19),%r7 ;# 2143 zero_extendqisi2/2
+L$0280
+ bb,>= %r15,31,L$0285 ;# 2159 movsi-4
+ ldi 92,%r19 ;# 2161 reload_outsi+2/2
+ comb,<>,n %r19,%r7,L$0285 ;# 2163 bleu+1
+ comb,= %r16,%r21,L$0903 ;# 2167 bleu+1
+ ldo 1(%r21),%r19 ;# 2195 addsi3/2
+ ldb 1(%r20),%r3 ;# 2192 zero_extendqisi2/2
+ comib,= 0,%r14,L$0288 ;# 2197 bleu+1
+ stw %r19,-296(%r30) ;# 2460 reload_outsi+2/6
+ addl %r14,%r3,%r19 ;# 2198 addsi3/1
+ ldb 0(%r19),%r3 ;# 2201 zero_extendqisi2/2
+L$0288
+ extru %r3,28,29,%r19 ;# 2216 lshrsi3/2
+ addl %r6,%r19,%r19 ;# 2219 addsi3/1
+ bl L$0948,%r0 ;# 2235 jump
+ extru %r3,31,3,%r20 ;# 2222 andsi3/1
+L$0285
+ comb,<>,n %r17,%r7,L$0293 ;# 2243 bleu+1
+ ldw -268(%r30),%r1 ;# 8798 reload_outsi+2/5
+ ldw -296(%r30),%r20 ;# 2466 reload_outsi+2/5
+ ldo 1(%r1),%r19 ;# 2244 addsi3/2
+ comb,<>,n %r19,%r20,L$0276 ;# 2246 bleu+1
+L$0293
+ comib,= 0,%r13,L$0294 ;# 2253 bleu+1
+ ldi 45,%r1 ;# 8801 reload_outsi+2/2
+ comb,<> %r1,%r7,L$1163 ;# 2257 bleu+1
+ ldw -296(%r30),%r20 ;# 2524 reload_outsi+2/5
+ ldw -296(%r30),%r19 ;# 2469 reload_outsi+2/5
+ ldb 0(%r19),%r19 ;# 2259 movqi+1/5
+ extrs %r19,31,8,%r19 ;# 2260 extendqisi2
+ comb,<>,n %r17,%r19,L$0895 ;# 2264 bleu+1
+L$0294
+ ldi 45,%r1 ;# 8804 reload_outsi+2/2
+ comb,<> %r1,%r7,L$1163 ;# 2280 bleu+1
+ ldw -296(%r30),%r20 ;# 2524 reload_outsi+2/5
+ ldw -276(%r30),%r1 ;# 8807 reload_outsi+2/5
+ ldo -2(%r20),%r19 ;# 2281 addsi3/2
+ comb,>>,n %r1,%r19,L$1179 ;# 2283 bleu+1
+ ldb -2(%r20),%r19 ;# 2285 movqi+1/5
+ ldi 91,%r1 ;# 8810 reload_outsi+2/2
+ extrs %r19,31,8,%r19 ;# 2286 extendqisi2
+ comb,= %r1,%r19,L$1163 ;# 2290 bleu+1
+ ldw -276(%r30),%r1 ;# 8813 reload_outsi+2/5
+L$1179
+ ldo -3(%r20),%r19 ;# 2294 addsi3/2
+ comb,>>,n %r1,%r19,L$0297 ;# 2296 bleu+1
+ ldb -3(%r20),%r19 ;# 2298 movqi+1/5
+ ldi 91,%r1 ;# 8816 reload_outsi+2/2
+ extrs %r19,31,8,%r19 ;# 2299 extendqisi2
+ comb,<> %r1,%r19,L$1164 ;# 2303 bleu+1
+ ldw -296(%r30),%r19 ;# 2487 reload_outsi+2/5
+ ldb -2(%r20),%r19 ;# 2305 movqi+1/5
+ ldi 94,%r20 ;# 2308 reload_outsi+2/2
+ extrs %r19,31,8,%r19 ;# 2306 extendqisi2
+ comb,= %r20,%r19,L$1163 ;# 2310 bleu+1
+ ldw -296(%r30),%r20 ;# 2524 reload_outsi+2/5
+L$0297
+ ldw -296(%r30),%r19 ;# 2487 reload_outsi+2/5
+L$1164
+ ldb 0(%r19),%r19 ;# 2315 movqi+1/5
+ extrs %r19,31,8,%r19 ;# 2316 extendqisi2
+ comb,<> %r17,%r19,L$0302 ;# 2320 bleu+1
+ ldw -296(%r30),%r20 ;# 2524 reload_outsi+2/5
+L$1163
+ ldb 0(%r20),%r19 ;# 2526 movqi+1/5
+ ldi 45,%r1 ;# 8819 reload_outsi+2/2
+ extrs %r19,31,8,%r19 ;# 2527 extendqisi2
+ comb,<>,n %r1,%r19,L$0300 ;# 2531 bleu+1
+ ldb 1(%r20),%r19 ;# 2535 movqi+1/5
+ extrs %r19,31,8,%r19 ;# 2536 extendqisi2
+ comb,=,n %r17,%r19,L$0300 ;# 2540 bleu+1
+ comb,= %r16,%r20,L$0922 ;# 2550 bleu+1
+ ldo 1(%r20),%r19 ;# 2559 addsi3/2
+ stw %r19,-296(%r30) ;# 2561 reload_outsi+2/6
+L$0302
+ stw %r6,-52(%r30) ;# 2588 reload_outsi+2/6
+ ldo -296(%r30),%r26 ;# 2590 addsi3/2
+ copy %r16,%r25 ;# 2592 reload_outsi+2/1
+ copy %r14,%r24 ;# 2594 reload_outsi+2/1
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl compile_range,%r2 ;# 2598 call_value_internal_symref
+ copy %r15,%r23 ;# 2596 reload_outsi+2/1
+ movb,= %r28,%r4,L$1165 ;# 2603 decrement_and_branch_until_zero+2/1
+ ldw -296(%r30),%r20 ;# 2436 reload_outsi+2/5
+ .CALL ARGW0=GR
+ bl free,%r2 ;# 2607 call_internal_symref
+ ldw -312(%r30),%r26 ;# 2605 reload_outsi+2/5
+ bl L$0867,%r0 ;# 2611 jump
+ copy %r4,%r28 ;# 2609 reload_outsi+2/1
+L$0300
+ ldw -252(%r30),%r1 ;# 8822 reload_outsi+2/5
+ comib,= 0,%r1,L$0309 ;# 2624 bleu+1
+ ldi 91,%r1 ;# 8825 reload_outsi+2/2
+ comb,<> %r1,%r7,L$1166 ;# 2628 bleu+1
+ ldi 0,%r13 ;# 3624 reload_outsi+2/2
+ ldw -296(%r30),%r20 ;# 2630 reload_outsi+2/5
+ ldb 0(%r20),%r19 ;# 2632 movqi+1/5
+ ldi 58,%r1 ;# 8828 reload_outsi+2/2
+ extrs %r19,31,8,%r19 ;# 2633 extendqisi2
+ comb,<>,n %r1,%r19,L$1166 ;# 2637 bleu+1
+ comb,= %r16,%r20,L$0922 ;# 2647 bleu+1
+ ldo 1(%r20),%r19 ;# 2656 addsi3/2
+ stw %r19,-296(%r30) ;# 2658 reload_outsi+2/6
+ comb,= %r16,%r19,L$0902 ;# 2689 bleu+1
+ ldi 0,%r3 ;# 2684 reload_outsi+2/2
+L$0317
+ ldw -296(%r30),%r19 ;# 2709 reload_outsi+2/5
+ comb,= %r16,%r19,L$0922 ;# 2711 bleu+1
+ ldo 1(%r19),%r20 ;# 2720 addsi3/2
+ stw %r20,-296(%r30) ;# 2722 reload_outsi+2/6
+ comib,= 0,%r14,L$0321 ;# 2729 bleu+1
+ ldb 0(%r19),%r7 ;# 2725 zero_extendqisi2/2
+ addl %r14,%r7,%r19 ;# 2730 addsi3/1
+ ldb 0(%r19),%r7 ;# 2733 zero_extendqisi2/2
+L$0321
+ ldi 58,%r1 ;# 8831 reload_outsi+2/2
+ comb,= %r1,%r7,L$1167 ;# 2750 bleu+1
+ addl %r11,%r3,%r19 ;# 2789 addsi3/1
+ comb,=,n %r17,%r7,L$1167 ;# 2754 bleu+1
+ comb,=,n %r16,%r20,L$1167 ;# 2758 bleu+1
+ comib,= 6,%r3,L$1167 ;# 2760 bleu+1
+ copy %r3,%r20 ;# 2770 reload_outsi+2/1
+ ldo 1(%r20),%r19 ;# 2771 addsi3/2
+ extru %r19,31,8,%r3 ;# 2772 zero_extendqisi2/1
+ addl %r11,%r20,%r20 ;# 2776 addsi3/1
+ bl L$0317,%r0 ;# 2783 jump
+ stb %r7,0(%r20) ;# 2778 movqi+1/6
+L$1167
+ comb,<> %r1,%r7,L$0328 ;# 2796 bleu+1
+ stb %r0,0(%r19) ;# 2791 movqi+1/6
+ ldw -296(%r30),%r19 ;# 2798 reload_outsi+2/5
+ ldb 0(%r19),%r19 ;# 2800 movqi+1/5
+ extrs %r19,31,8,%r19 ;# 2801 extendqisi2
+ comb,<> %r17,%r19,L$1168 ;# 2805 bleu+1
+ ldi 255,%r19 ;# 8069 reload_outsi+2/2
+ copy %r11,%r26 ;# 2813 reload_outsi+2/1
+ ldil LR'L$C0016,%r1 ;# 8835 add_high_const+3
+ ldo RR'L$C0016(%r1),%r1 ;# 8836 movhi-2
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2 ;# 2817 call_value_internal_symref
+ copy %r1,%r25 ;# 2815 reload_outsi+2/1
+ copy %r11,%r26 ;# 2829 reload_outsi+2/1
+ ldil LR'L$C0017,%r1 ;# 8837 add_high_const+3
+ ldo RR'L$C0017(%r1),%r1 ;# 8838 movhi-2
+ copy %r1,%r25 ;# 2831 reload_outsi+2/1
+ comiclr,<> 0,%r28,%r28 ;# 2821 scc
+ ldi 1,%r28
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2 ;# 2833 call_value_internal_symref
+ stw %r28,-244(%r30) ;# 8841 reload_outsi+2/6
+ copy %r11,%r26 ;# 2845 reload_outsi+2/1
+ ldil LR'L$C0018,%r1 ;# 8842 add_high_const+3
+ ldo RR'L$C0018(%r1),%r1 ;# 8843 movhi-2
+ copy %r1,%r25 ;# 2847 reload_outsi+2/1
+ comiclr,<> 0,%r28,%r28 ;# 2837 scc
+ ldi 1,%r28
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2 ;# 2849 call_value_internal_symref
+ stw %r28,-236(%r30) ;# 8846 reload_outsi+2/6
+ copy %r11,%r26 ;# 2861 reload_outsi+2/1
+ ldil LR'L$C0019,%r1 ;# 8847 add_high_const+3
+ ldo RR'L$C0019(%r1),%r1 ;# 8848 movhi-2
+ copy %r1,%r25 ;# 2863 reload_outsi+2/1
+ comiclr,<> 0,%r28,%r28 ;# 2853 scc
+ ldi 1,%r28
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2 ;# 2865 call_value_internal_symref
+ stw %r28,-228(%r30) ;# 8851 reload_outsi+2/6
+ copy %r11,%r26 ;# 2877 reload_outsi+2/1
+ ldil LR'L$C0020,%r1 ;# 8852 add_high_const+3
+ ldo RR'L$C0020(%r1),%r1 ;# 8853 movhi-2
+ copy %r1,%r25 ;# 2879 reload_outsi+2/1
+ comiclr,<> 0,%r28,%r28 ;# 2869 scc
+ ldi 1,%r28
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2 ;# 2881 call_value_internal_symref
+ stw %r28,-220(%r30) ;# 8856 reload_outsi+2/6
+ copy %r11,%r26 ;# 2893 reload_outsi+2/1
+ ldil LR'L$C0021,%r1 ;# 8857 add_high_const+3
+ ldo RR'L$C0021(%r1),%r1 ;# 8858 movhi-2
+ copy %r1,%r25 ;# 2895 reload_outsi+2/1
+ comiclr,<> 0,%r28,%r28 ;# 2885 scc
+ ldi 1,%r28
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2 ;# 2897 call_value_internal_symref
+ stw %r28,-212(%r30) ;# 8861 reload_outsi+2/6
+ copy %r11,%r26 ;# 2909 reload_outsi+2/1
+ ldil LR'L$C0022,%r1 ;# 8862 add_high_const+3
+ ldo RR'L$C0022(%r1),%r1 ;# 8863 movhi-2
+ copy %r1,%r25 ;# 2911 reload_outsi+2/1
+ comiclr,<> 0,%r28,%r28 ;# 2901 scc
+ ldi 1,%r28
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2 ;# 2913 call_value_internal_symref
+ stw %r28,-204(%r30) ;# 8866 reload_outsi+2/6
+ copy %r11,%r26 ;# 2925 reload_outsi+2/1
+ ldil LR'L$C0023,%r1 ;# 8867 add_high_const+3
+ ldo RR'L$C0023(%r1),%r1 ;# 8868 movhi-2
+ copy %r1,%r25 ;# 2927 reload_outsi+2/1
+ comiclr,<> 0,%r28,%r28 ;# 2917 scc
+ ldi 1,%r28
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2 ;# 2929 call_value_internal_symref
+ stw %r28,-196(%r30) ;# 8871 reload_outsi+2/6
+ copy %r11,%r26 ;# 2941 reload_outsi+2/1
+ ldil LR'L$C0024,%r1 ;# 8872 add_high_const+3
+ ldo RR'L$C0024(%r1),%r1 ;# 8873 movhi-2
+ copy %r1,%r25 ;# 2943 reload_outsi+2/1
+ comiclr,<> 0,%r28,%r28 ;# 2933 scc
+ ldi 1,%r28
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2 ;# 2945 call_value_internal_symref
+ stw %r28,-188(%r30) ;# 8876 reload_outsi+2/6
+ copy %r11,%r26 ;# 2957 reload_outsi+2/1
+ ldil LR'L$C0025,%r1 ;# 8877 add_high_const+3
+ ldo RR'L$C0025(%r1),%r1 ;# 8878 movhi-2
+ copy %r1,%r25 ;# 2959 reload_outsi+2/1
+ comiclr,<> 0,%r28,%r28 ;# 2949 scc
+ ldi 1,%r28
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2 ;# 2961 call_value_internal_symref
+ stw %r28,-180(%r30) ;# 8881 reload_outsi+2/6
+ copy %r11,%r26 ;# 2973 reload_outsi+2/1
+ ldil LR'L$C0026,%r19 ;# 2970 add_high_const+3
+ ldo RR'L$C0026(%r19),%r3 ;# 2971 movhi-2
+ copy %r3,%r25 ;# 2975 reload_outsi+2/1
+ comiclr,<> 0,%r28,%r28 ;# 2965 scc
+ ldi 1,%r28
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2 ;# 2977 call_value_internal_symref
+ stw %r28,-172(%r30) ;# 8884 reload_outsi+2/6
+ copy %r11,%r26 ;# 2989 reload_outsi+2/1
+ ldil LR'L$C0027,%r19 ;# 2986 add_high_const+3
+ ldo RR'L$C0027(%r19),%r4 ;# 2987 movhi-2
+ comiclr,<> 0,%r28,%r13 ;# 2981 scc
+ ldi 1,%r13
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2 ;# 2993 call_value_internal_symref
+ copy %r4,%r25 ;# 2991 reload_outsi+2/1
+ copy %r11,%r26 ;# 3005 reload_outsi+2/1
+ ldil LR'L$C0017,%r1 ;# 8885 add_high_const+3
+ ldo RR'L$C0017(%r1),%r1 ;# 8886 movhi-2
+ comiclr,<> 0,%r28,%r7 ;# 2997 scc
+ ldi 1,%r7
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2 ;# 3009 call_value_internal_symref
+ copy %r1,%r25 ;# 3007 reload_outsi+2/1
+ comib,= 0,%r28,L$0329 ;# 3013 bleu+1
+ copy %r11,%r26 ;# 3018 reload_outsi+2/1
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2 ;# 3022 call_value_internal_symref
+ copy %r3,%r25 ;# 3020 reload_outsi+2/1
+ comib,= 0,%r28,L$0329 ;# 3026 bleu+1
+ copy %r11,%r26 ;# 3031 reload_outsi+2/1
+ ldil LR'L$C0022,%r1 ;# 8887 add_high_const+3
+ ldo RR'L$C0022(%r1),%r1 ;# 8888 movhi-2
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2 ;# 3035 call_value_internal_symref
+ copy %r1,%r25 ;# 3033 reload_outsi+2/1
+ comib,= 0,%r28,L$0329 ;# 3039 bleu+1
+ copy %r11,%r26 ;# 3044 reload_outsi+2/1
+ ldil LR'L$C0020,%r1 ;# 8889 add_high_const+3
+ ldo RR'L$C0020(%r1),%r1 ;# 8890 movhi-2
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2 ;# 3048 call_value_internal_symref
+ copy %r1,%r25 ;# 3046 reload_outsi+2/1
+ comib,= 0,%r28,L$0329 ;# 3052 bleu+1
+ copy %r11,%r26 ;# 3057 reload_outsi+2/1
+ ldil LR'L$C0016,%r1 ;# 8891 add_high_const+3
+ ldo RR'L$C0016(%r1),%r1 ;# 8892 movhi-2
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2 ;# 3061 call_value_internal_symref
+ copy %r1,%r25 ;# 3059 reload_outsi+2/1
+ comib,= 0,%r28,L$0329 ;# 3065 bleu+1
+ copy %r11,%r26 ;# 3070 reload_outsi+2/1
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2 ;# 3074 call_value_internal_symref
+ copy %r4,%r25 ;# 3072 reload_outsi+2/1
+ comib,= 0,%r28,L$0329 ;# 3078 bleu+1
+ copy %r11,%r26 ;# 3083 reload_outsi+2/1
+ ldil LR'L$C0025,%r1 ;# 8893 add_high_const+3
+ ldo RR'L$C0025(%r1),%r1 ;# 8894 movhi-2
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2 ;# 3087 call_value_internal_symref
+ copy %r1,%r25 ;# 3085 reload_outsi+2/1
+ comib,= 0,%r28,L$0329 ;# 3091 bleu+1
+ copy %r11,%r26 ;# 3096 reload_outsi+2/1
+ ldil LR'L$C0023,%r1 ;# 8895 add_high_const+3
+ ldo RR'L$C0023(%r1),%r1 ;# 8896 movhi-2
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2 ;# 3100 call_value_internal_symref
+ copy %r1,%r25 ;# 3098 reload_outsi+2/1
+ comib,= 0,%r28,L$0329 ;# 3104 bleu+1
+ copy %r11,%r26 ;# 3109 reload_outsi+2/1
+ ldil LR'L$C0024,%r1 ;# 8897 add_high_const+3
+ ldo RR'L$C0024(%r1),%r1 ;# 8898 movhi-2
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2 ;# 3113 call_value_internal_symref
+ copy %r1,%r25 ;# 3111 reload_outsi+2/1
+ comib,= 0,%r28,L$0329 ;# 3117 bleu+1
+ copy %r11,%r26 ;# 3122 reload_outsi+2/1
+ ldil LR'L$C0021,%r1 ;# 8899 add_high_const+3
+ ldo RR'L$C0021(%r1),%r1 ;# 8900 movhi-2
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2 ;# 3126 call_value_internal_symref
+ copy %r1,%r25 ;# 3124 reload_outsi+2/1
+ comib,= 0,%r28,L$0329 ;# 3130 bleu+1
+ copy %r11,%r26 ;# 3135 reload_outsi+2/1
+ ldil LR'L$C0019,%r1 ;# 8901 add_high_const+3
+ ldo RR'L$C0019(%r1),%r1 ;# 8902 movhi-2
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2 ;# 3139 call_value_internal_symref
+ copy %r1,%r25 ;# 3137 reload_outsi+2/1
+ comib,= 0,%r28,L$0329 ;# 3143 bleu+1
+ copy %r11,%r26 ;# 3148 reload_outsi+2/1
+ ldil LR'L$C0018,%r1 ;# 8903 add_high_const+3
+ ldo RR'L$C0018(%r1),%r1 ;# 8904 movhi-2
+ .CALL ARGW0=GR,ARGW1=GR
+ bl strcmp,%r2 ;# 3152 call_value_internal_symref
+ copy %r1,%r25 ;# 3150 reload_outsi+2/1
+ comib,<>,n 0,%r28,L$0900 ;# 3156 bleu+1
+L$0329
+ ldw -296(%r30),%r19 ;# 3173 reload_outsi+2/5
+ comb,= %r16,%r19,L$0922 ;# 3175 bleu+1
+ ldo 1(%r19),%r19 ;# 3184 addsi3/2
+ comb,= %r16,%r19,L$0902 ;# 3214 bleu+1
+ stw %r19,-296(%r30) ;# 3186 reload_outsi+2/6
+ ldi 0,%r22 ;# 3227 reload_outsi+2/2
+ addil LR'__alnum-$global$,%r27 ;# 8596 pic2_lo_sum+1
+ copy %r1,%r2 ;# 8907 reload_outsi+2/1
+ addil LR'__ctype2-$global$,%r27 ;# 8598 pic2_lo_sum+1
+ copy %r1,%r23 ;# 8910 reload_outsi+2/1
+ addil LR'__ctype-$global$,%r27 ;# 8600 pic2_lo_sum+1
+ copy %r1,%r4 ;# 8913 reload_outsi+2/1
+ ldi 32,%r25 ;# 8605 reload_outsi+2/2
+ ldi 2,%r24 ;# 8607 reload_outsi+2/2
+ ldi 16,%r31 ;# 8609 reload_outsi+2/2
+ ldi 8,%r29 ;# 8611 reload_outsi+2/2
+ ldi 128,%r28 ;# 8613 reload_outsi+2/2
+ ldi 255,%r26 ;# 8615 reload_outsi+2/2
+ ldw -244(%r30),%r1 ;# 8916 reload_outsi+2/5
+L$1173
+ comib,=,n 0,%r1,L$0343 ;# 3240 bleu+1
+ stw %r22,RR'__alnum-$global$(%r2) ;# 3244 reload_outsi+2/6
+ ldw RR'__ctype2-$global$(%r23),%r19 ;# 3248 reload_outsi+2/5
+ ldw RR'__ctype-$global$(%r4),%r21 ;# 3260 reload_outsi+2/5
+ addl %r19,%r22,%r19 ;# 3253 addsi3/1
+ addl %r21,%r22,%r21 ;# 3265 addsi3/1
+ ldb 0(%r19),%r20 ;# 3255 movqi+1/5
+ ldb 0(%r21),%r19 ;# 3267 movqi+1/5
+ extru %r20,31,1,%r20 ;# 3256 andsi3/1
+ and %r19,%r18,%r19 ;# 3270 andsi3/1
+ or %r20,%r19,%r20 ;# 3278 xordi3-1
+ comib,<> 0,%r20,L$1169 ;# 3280 bleu+1
+ extru %r22,31,8,%r19 ;# 3330 zero_extendqisi2/1
+L$0343
+ ldw -236(%r30),%r1 ;# 8919 reload_outsi+2/5
+ comib,= 0,%r1,L$0344 ;# 3285 bleu+1
+ ldw RR'__ctype2-$global$(%r23),%r19 ;# 3289 reload_outsi+2/5
+ addl %r19,%r22,%r19 ;# 3290 addsi3/1
+ ldb 0(%r19),%r19 ;# 3292 movqi+1/5
+ bb,< %r19,31,L$1169 ;# 3296 bleu+3
+ extru %r22,31,8,%r19 ;# 3330 zero_extendqisi2/1
+L$0344
+ ldw -228(%r30),%r1 ;# 8922 reload_outsi+2/5
+ comib,=,n 0,%r1,L$0345 ;# 3301 bleu+1
+ comb,= %r25,%r22,L$1169 ;# 3305 bleu+1
+ extru %r22,31,8,%r19 ;# 3330 zero_extendqisi2/1
+ comib,= 9,%r22,L$1170 ;# 3307 bleu+1
+ extru %r19,28,29,%r21 ;# 3332 lshrsi3/2
+L$0345
+ ldw -220(%r30),%r1 ;# 8925 reload_outsi+2/5
+ comib,= 0,%r1,L$0341 ;# 3312 bleu+1
+ ldw RR'__ctype-$global$(%r4),%r19 ;# 3316 reload_outsi+2/5
+ addl %r19,%r22,%r19 ;# 3317 addsi3/1
+ ldb 0(%r19),%r19 ;# 3319 movqi+1/5
+ and %r19,%r25,%r19 ;# 3322 andsi3/1
+ comib,= 0,%r19,L$0341 ;# 3325 bleu+1
+ extru %r22,31,8,%r19 ;# 3330 zero_extendqisi2/1
+L$1169
+ extru %r19,28,29,%r21 ;# 3332 lshrsi3/2
+L$1170
+ addl %r6,%r21,%r21 ;# 3335 addsi3/1
+ extru %r19,31,3,%r19 ;# 3339 andsi3/1
+ subi 31,%r19,%r19 ;# 3340 subsi3/2
+ ldb 0(%r21),%r20 ;# 3343 movqi+1/5
+ mtsar %r19 ;# 8928 reload_outsi+2/7
+ vdepi -1,1,%r20 ;# 3348 vdepi_ior
+ stb %r20,0(%r21) ;# 3350 movqi+1/6
+L$0341
+ ldw -212(%r30),%r1 ;# 8931 reload_outsi+2/5
+ comib,= 0,%r1,L$0348 ;# 3354 bleu+1
+ ldw RR'__ctype-$global$(%r4),%r19 ;# 3358 reload_outsi+2/5
+ addl %r19,%r22,%r19 ;# 3359 addsi3/1
+ ldb 0(%r19),%r19 ;# 3361 movqi+1/5
+ and %r19,%r18,%r19 ;# 3364 andsi3/1
+ comib,<> 0,%r19,L$1171 ;# 3367 bleu+1
+ extru %r22,31,8,%r19 ;# 3426 zero_extendqisi2/1
+L$0348
+ ldw -204(%r30),%r1 ;# 8934 reload_outsi+2/5
+ comib,= 0,%r1,L$0349 ;# 3372 bleu+1
+ ldw RR'__ctype2-$global$(%r23),%r19 ;# 3376 reload_outsi+2/5
+ addl %r19,%r22,%r19 ;# 3377 addsi3/1
+ ldb 0(%r19),%r19 ;# 3379 movqi+1/5
+ and %r19,%r24,%r19 ;# 3382 andsi3/1
+ comib,<> 0,%r19,L$1171 ;# 3385 bleu+1
+ extru %r22,31,8,%r19 ;# 3426 zero_extendqisi2/1
+L$0349
+ ldw -196(%r30),%r1 ;# 8937 reload_outsi+2/5
+ comib,= 0,%r1,L$0350 ;# 3390 bleu+1
+ ldw RR'__ctype-$global$(%r4),%r19 ;# 3394 reload_outsi+2/5
+ addl %r19,%r22,%r19 ;# 3395 addsi3/1
+ ldb 0(%r19),%r19 ;# 3397 movqi+1/5
+ and %r19,%r24,%r19 ;# 3400 andsi3/1
+ comib,<> 0,%r19,L$1171 ;# 3403 bleu+1
+ extru %r22,31,8,%r19 ;# 3426 zero_extendqisi2/1
+L$0350
+ ldw -188(%r30),%r1 ;# 8940 reload_outsi+2/5
+ comib,= 0,%r1,L$0346 ;# 3408 bleu+1
+ ldw RR'__ctype2-$global$(%r23),%r19 ;# 3412 reload_outsi+2/5
+ addl %r19,%r22,%r19 ;# 3413 addsi3/1
+ ldb 0(%r19),%r19 ;# 3415 movqi+1/5
+ and %r19,%r18,%r19 ;# 3418 andsi3/1
+ comib,= 0,%r19,L$0346 ;# 3421 bleu+1
+ extru %r22,31,8,%r19 ;# 3426 zero_extendqisi2/1
+L$1171
+ extru %r19,28,29,%r21 ;# 3428 lshrsi3/2
+ addl %r6,%r21,%r21 ;# 3431 addsi3/1
+ extru %r19,31,3,%r19 ;# 3435 andsi3/1
+ subi 31,%r19,%r19 ;# 3436 subsi3/2
+ ldb 0(%r21),%r20 ;# 3439 movqi+1/5
+ mtsar %r19 ;# 8943 reload_outsi+2/7
+ vdepi -1,1,%r20 ;# 3444 vdepi_ior
+ stb %r20,0(%r21) ;# 3446 movqi+1/6
+L$0346
+ ldw -180(%r30),%r1 ;# 8946 reload_outsi+2/5
+ comib,= 0,%r1,L$0353 ;# 3450 bleu+1
+ ldw RR'__ctype-$global$(%r4),%r19 ;# 3454 reload_outsi+2/5
+ addl %r19,%r22,%r19 ;# 3455 addsi3/1
+ ldb 0(%r19),%r19 ;# 3457 movqi+1/5
+ and %r19,%r31,%r19 ;# 3460 andsi3/1
+ comib,<> 0,%r19,L$1172 ;# 3463 bleu+1
+ extru %r22,31,8,%r19 ;# 3520 zero_extendqisi2/1
+L$0353
+ ldw -172(%r30),%r1 ;# 8949 reload_outsi+2/5
+ comib,= 0,%r1,L$0354 ;# 3468 bleu+1
+ ldw RR'__ctype-$global$(%r4),%r19 ;# 3472 reload_outsi+2/5
+ addl %r19,%r22,%r19 ;# 3473 addsi3/1
+ ldb 0(%r19),%r19 ;# 3475 movqi+1/5
+ and %r19,%r29,%r19 ;# 3478 andsi3/1
+ comib,<> 0,%r19,L$1172 ;# 3481 bleu+1
+ extru %r22,31,8,%r19 ;# 3520 zero_extendqisi2/1
+L$0354
+ comib,= 0,%r13,L$0355 ;# 3486 bleu+1
+ ldw RR'__ctype-$global$(%r4),%r19 ;# 3490 reload_outsi+2/5
+ addl %r19,%r22,%r19 ;# 3491 addsi3/1
+ ldb 0(%r19),%r19 ;# 3493 movqi+1/5
+ bb,< %r19,31,L$1172 ;# 3497 bleu+3
+ extru %r22,31,8,%r19 ;# 3520 zero_extendqisi2/1
+L$0355
+ comib,= 0,%r7,L$0339 ;# 3502 bleu+1
+ ldw RR'__ctype-$global$(%r4),%r19 ;# 3506 reload_outsi+2/5
+ addl %r19,%r22,%r19 ;# 3507 addsi3/1
+ ldb 0(%r19),%r19 ;# 3509 movqi+1/5
+ and %r19,%r28,%r19 ;# 3512 andsi3/1
+ comib,= 0,%r19,L$0339 ;# 3515 bleu+1
+ extru %r22,31,8,%r19 ;# 3520 zero_extendqisi2/1
+L$1172
+ extru %r19,28,29,%r21 ;# 3522 lshrsi3/2
+ addl %r6,%r21,%r21 ;# 3525 addsi3/1
+ extru %r19,31,3,%r19 ;# 3529 andsi3/1
+ subi 31,%r19,%r19 ;# 3530 subsi3/2
+ ldb 0(%r21),%r20 ;# 3533 movqi+1/5
+ mtsar %r19 ;# 8952 reload_outsi+2/7
+ vdepi -1,1,%r20 ;# 3538 vdepi_ior
+ stb %r20,0(%r21) ;# 3540 movqi+1/6
+L$0339
+ ldo 1(%r22),%r22 ;# 3546 addsi3/2
+ comb,>=,n %r26,%r22,L$1173 ;# 3233 bleu+1
+ ldw -244(%r30),%r1 ;# 8916 reload_outsi+2/5
+ bl L$0275,%r0 ;# 3559 jump
+ ldi 1,%r13 ;# 3556 reload_outsi+2/2
+L$0328
+ ldi 255,%r19 ;# 8069 reload_outsi+2/2
+L$1168
+ comb,= %r19,%r3,L$0359 ;# 8070 bleu+1
+ copy %r19,%r21 ;# 8595 reload_outsi+2/1
+L$0360
+ ldo -1(%r3),%r20 ;# 3571 addsi3/2
+ ldw -296(%r30),%r19 ;# 3583 reload_outsi+2/5
+ extru %r20,31,8,%r3 ;# 3572 zero_extendqisi2/1
+ ldo -1(%r19),%r19 ;# 3584 addsi3/2
+ comb,<> %r21,%r3,L$0360 ;# 3577 bleu+1
+ stw %r19,-296(%r30) ;# 3588 reload_outsi+2/6
+L$0359
+ ldb 11(%r6),%r19 ;# 3599 movqi+1/5
+ depi -1,28,1,%r19 ;# 3601 iorsi3+1/2
+ stb %r19,11(%r6) ;# 3603 movqi+1/6
+ ldb 7(%r6),%r19 ;# 3606 movqi+1/5
+ ldi 0,%r13 ;# 3613 reload_outsi+2/2
+ depi -1,29,1,%r19 ;# 3608 iorsi3+1/2
+ bl L$0275,%r0 ;# 3618 jump
+ stb %r19,7(%r6) ;# 3610 movqi+1/6
+L$0309
+ ldi 0,%r13 ;# 3624 reload_outsi+2/2
+L$1166
+ extru %r7,21+8-1,8,%r19 ;# 3627 extzv
+ addl %r6,%r19,%r19 ;# 3630 addsi3/1
+ extru %r7,31,3,%r20 ;# 3633 andsi3/1
+L$0948
+ subi 31,%r20,%r20 ;# 3634 subsi3/2
+ ldb 0(%r19),%r21 ;# 3637 movqi+1/5
+ mtsar %r20 ;# 8955 reload_outsi+2/7
+ vdepi -1,1,%r21 ;# 3642 vdepi_ior
+ bl L$0275,%r0 ;# 3653 jump
+ stb %r21,0(%r19) ;# 3644 movqi+1/6
+L$0276
+ ldb -1(%r6),%r20 ;# 8074 movqi+1/5
+ extru %r20,31,8,%r19 ;# 8075 zero_extendqisi2/1
+ comib,= 0,%r19,L$0364 ;# 8076 bleu+1
+ addl %r19,%r6,%r19 ;# 8079 addsi3/1
+ ldb -1(%r19),%r19 ;# 8082 zero_extendqisi2/2
+ comib,<> 0,%r19,L$0364 ;# 8083 bleu+1
+ ldo -1(%r20),%r19 ;# 8242 addsi3/2
+ bl L$1183,%r0 ;# 8253 jump
+ stb %r19,-1(%r6) ;# 3688 movqi+1/6
+L$0365
+ ldo -1(%r19),%r19 ;# 3686 addsi3/2
+ stb %r19,-1(%r6) ;# 3688 movqi+1/6
+L$1183
+ extru %r19,31,8,%r19 ;# 3662 zero_extendqisi2/1
+ comib,= 0,%r19,L$0364 ;# 3664 bleu+1
+ addl %r19,%r6,%r19 ;# 3668 addsi3/1
+ ldb -1(%r19),%r19 ;# 3672 zero_extendqisi2/2
+ comib,=,n 0,%r19,L$0365 ;# 3674 bleu+1
+ ldb -1(%r6),%r19 ;# 3683 movqi+1/5
+L$0364
+ ldb -1(%r6),%r19 ;# 3700 zero_extendqisi2/2
+ bl L$0043,%r0 ;# 3705 jump
+ addl %r6,%r19,%r6 ;# 3701 addsi3/1
+L$0368
+ bb,>=,n %r15,18,L$0076 ;# 3713 movsi-4
+ bl L$1181,%r0 ;# 3721 jump
+ ldw 24(%r5),%r19 ;# 3861 reload_outsi+2/5
+L$0372
+ bb,>=,n %r15,18,L$0076 ;# 3730 movsi-4
+ bl,n L$0374,%r0 ;# 3738 jump
+L$0376
+ bb,>=,n %r15,20,L$0076 ;# 3747 movsi-4
+ bl,n L$0378,%r0 ;# 3755 jump
+L$0380
+ bb,>=,n %r15,16,L$0076 ;# 3764 movsi-4
+ bl,n L$0378,%r0 ;# 3772 jump
+L$0383
+ and %r15,%r20,%r19 ;# 3779 andsi3/1
+ comb,= %r20,%r19,L$1174 ;# 3783 bleu+1
+ ldi -1,%r4 ;# 5074 reload_outsi+2/2
+ bl,n L$0076,%r0 ;# 3791 jump
+L$0387
+ comb,=,n %r16,%r19,L$0903 ;# 3799 bleu+1
+ ldb 0(%r19),%r7 ;# 3831 zero_extendqisi2/2
+ ldo 1(%r19),%r19 ;# 3826 addsi3/2
+ stw %r19,-296(%r30) ;# 3828 reload_outsi+2/6
+ ldo -39(%r7),%r19 ;# 7446 addsi3/2
+ addi,uv -86,%r19,%r0 ;# 7447 casesi0
+ blr,n %r19,%r0
+ b,n L$0397
+L$0817
+ bl L$0759,%r0 ;# 9437 switch_jump
+ ldw 0(%r5),%r4 ;# 8204 reload_outsi+2/5
+L$1069
+ bl L$0395,%r0
+ nop ;# 9440 switch_jump
+L$1070
+ bl L$0422,%r0
+ nop ;# 9443 switch_jump
+L$1071
+ bl L$0397,%r0
+ nop ;# 9446 switch_jump
+L$1072
+ bl L$0811,%r0
+ nop ;# 9449 switch_jump
+L$1073
+ bl L$0397,%r0
+ nop ;# 9452 switch_jump
+L$1074
+ bl L$0397,%r0
+ nop ;# 9455 switch_jump
+L$1075
+ bl L$0397,%r0
+ nop ;# 9458 switch_jump
+L$1076
+ bl L$0397,%r0
+ nop ;# 9461 switch_jump
+L$1077
+ bl L$0397,%r0
+ nop ;# 9464 switch_jump
+L$1078
+ bl L$0787,%r0
+ nop ;# 9467 switch_jump
+L$1079
+ bl L$0787,%r0
+ nop ;# 9470 switch_jump
+L$1080
+ bl L$0787,%r0
+ nop ;# 9473 switch_jump
+L$1081
+ bl L$0787,%r0
+ nop ;# 9476 switch_jump
+L$1082
+ bl L$0787,%r0
+ nop ;# 9479 switch_jump
+L$1083
+ bl L$0787,%r0
+ nop ;# 9482 switch_jump
+L$1084
+ bl L$0787,%r0
+ nop ;# 9485 switch_jump
+L$1085
+ bl L$0787,%r0
+ nop ;# 9488 switch_jump
+L$1086
+ bl L$0787,%r0
+ nop ;# 9491 switch_jump
+L$1087
+ bl L$0397,%r0
+ nop ;# 9494 switch_jump
+L$1088
+ bl L$0397,%r0
+ nop ;# 9497 switch_jump
+L$1089
+ bl L$0659,%r0 ;# 9500 switch_jump
+ ldw 0(%r5),%r4 ;# 8164 reload_outsi+2/5
+L$1090
+ bl L$0397,%r0
+ nop ;# 9503 switch_jump
+L$1091
+ bl L$0679,%r0 ;# 9506 switch_jump
+ ldw 0(%r5),%r4 ;# 8172 reload_outsi+2/5
+L$1092
+ bl L$0811,%r0
+ nop ;# 9509 switch_jump
+L$1093
+ bl L$0397,%r0
+ nop ;# 9512 switch_jump
+L$1094
+ bl L$0397,%r0
+ nop ;# 9515 switch_jump
+L$1095
+ bl L$0719,%r0 ;# 9518 switch_jump
+ ldw 0(%r5),%r4 ;# 8188 reload_outsi+2/5
+L$1096
+ bl L$0397,%r0
+ nop ;# 9521 switch_jump
+L$1097
+ bl L$0397,%r0
+ nop ;# 9524 switch_jump
+L$1098
+ bl L$0397,%r0
+ nop ;# 9527 switch_jump
+L$1099
+ bl L$0397,%r0
+ nop ;# 9530 switch_jump
+L$1100
+ bl L$0397,%r0
+ nop ;# 9533 switch_jump
+L$1101
+ bl L$0397,%r0
+ nop ;# 9536 switch_jump
+L$1102
+ bl L$0397,%r0
+ nop ;# 9539 switch_jump
+L$1103
+ bl L$0397,%r0
+ nop ;# 9542 switch_jump
+L$1104
+ bl L$0397,%r0
+ nop ;# 9545 switch_jump
+L$1105
+ bl L$0397,%r0
+ nop ;# 9548 switch_jump
+L$1106
+ bl L$0397,%r0
+ nop ;# 9551 switch_jump
+L$1107
+ bl L$0397,%r0
+ nop ;# 9554 switch_jump
+L$1108
+ bl L$0397,%r0
+ nop ;# 9557 switch_jump
+L$1109
+ bl L$0397,%r0
+ nop ;# 9560 switch_jump
+L$1110
+ bl L$0397,%r0
+ nop ;# 9563 switch_jump
+L$1111
+ bl L$0397,%r0
+ nop ;# 9566 switch_jump
+L$1112
+ bl L$0397,%r0
+ nop ;# 9569 switch_jump
+L$1113
+ bl L$0397,%r0
+ nop ;# 9572 switch_jump
+L$1114
+ bl L$0397,%r0
+ nop ;# 9575 switch_jump
+L$1115
+ bl L$0397,%r0
+ nop ;# 9578 switch_jump
+L$1116
+ bl L$0639,%r0 ;# 9581 switch_jump
+ ldw 0(%r5),%r4 ;# 8156 reload_outsi+2/5
+L$1117
+ bl L$0397,%r0
+ nop ;# 9584 switch_jump
+L$1118
+ bl L$0397,%r0
+ nop ;# 9587 switch_jump
+L$1119
+ bl L$0397,%r0
+ nop ;# 9590 switch_jump
+L$1120
+ bl L$0397,%r0
+ nop ;# 9593 switch_jump
+L$1121
+ bl L$0397,%r0
+ nop ;# 9596 switch_jump
+L$1122
+ bl L$0397,%r0
+ nop ;# 9599 switch_jump
+L$1123
+ bl L$0397,%r0
+ nop ;# 9602 switch_jump
+L$1124
+ bl L$0397,%r0
+ nop ;# 9605 switch_jump
+L$1125
+ bl L$0739,%r0 ;# 9608 switch_jump
+ ldw 0(%r5),%r4 ;# 8196 reload_outsi+2/5
+L$1126
+ bl L$0397,%r0
+ nop ;# 9611 switch_jump
+L$1127
+ bl L$0699,%r0 ;# 9614 switch_jump
+ ldw 0(%r5),%r4 ;# 8180 reload_outsi+2/5
+L$1128
+ bl L$0397,%r0
+ nop ;# 9617 switch_jump
+L$1129
+ bl L$0397,%r0
+ nop ;# 9620 switch_jump
+L$1130
+ bl L$0397,%r0
+ nop ;# 9623 switch_jump
+L$1131
+ bl L$0397,%r0
+ nop ;# 9626 switch_jump
+L$1132
+ bl L$0397,%r0
+ nop ;# 9629 switch_jump
+L$1133
+ bl L$0397,%r0
+ nop ;# 9632 switch_jump
+L$1134
+ bl L$0397,%r0
+ nop ;# 9635 switch_jump
+L$1135
+ bl L$0397,%r0
+ nop ;# 9638 switch_jump
+L$1136
+ bl L$0397,%r0
+ nop ;# 9641 switch_jump
+L$1137
+ bl L$0397,%r0
+ nop ;# 9644 switch_jump
+L$1138
+ bl L$0397,%r0
+ nop ;# 9647 switch_jump
+L$1139
+ bl L$0397,%r0
+ nop ;# 9650 switch_jump
+L$1140
+ bl L$0397,%r0
+ nop ;# 9653 switch_jump
+L$1141
+ bl L$0397,%r0
+ nop ;# 9656 switch_jump
+L$1142
+ bl L$0397,%r0
+ nop ;# 9659 switch_jump
+L$1143
+ bl L$0397,%r0
+ nop ;# 9662 switch_jump
+L$1144
+ bl L$0397,%r0
+ nop ;# 9665 switch_jump
+L$1145
+ bl L$0397,%r0
+ nop ;# 9668 switch_jump
+L$1146
+ bl L$0397,%r0
+ nop ;# 9671 switch_jump
+L$1147
+ bl L$0397,%r0
+ nop ;# 9674 switch_jump
+L$1148
+ bl L$0619,%r0 ;# 9677 switch_jump
+ ldw 0(%r5),%r4 ;# 8148 reload_outsi+2/5
+L$1149
+ bl L$0397,%r0
+ nop ;# 9680 switch_jump
+L$1150
+ bl L$0397,%r0
+ nop ;# 9683 switch_jump
+L$1151
+ bl L$0397,%r0
+ nop ;# 9686 switch_jump
+L$1152
+ bl L$0506,%r0
+ nop ;# 9689 switch_jump
+L$1153
+ bl L$0472,%r0 ;# 9692 switch_jump
+ ldil L'33792,%r19 ;# 4724 add_high_const+3
+L$1154
+ bl,n L$0397,%r0 ;# 7450 jump
+L$0395
+ bb,<,n %r15,18,L$0397 ;# 3853 bleu+3
+ ldw 24(%r5),%r19 ;# 3861 reload_outsi+2/5
+L$1181
+ ldo 1(%r19),%r19 ;# 3862 addsi3/2
+ stw %r19,24(%r5) ;# 3866 reload_outsi+2/6
+ ldw -304(%r30),%r20 ;# 3871 reload_outsi+2/5
+ ldw -260(%r30),%r1 ;# 8958 reload_outsi+2/5
+ ldw -308(%r30),%r19 ;# 3873 reload_outsi+2/5
+ ldo 1(%r1),%r1 ;# 3868 addsi3/2
+ comb,<> %r19,%r20,L$0398 ;# 3875 bleu+1
+ stw %r1,-260(%r30) ;# 8961 reload_outsi+2/6
+ zdep %r20,28,29,%r25 ;# 3885 ashlsi3+1
+ sh1addl %r20,%r25,%r25 ;# 3886 ashlsi3-2
+ ldw -312(%r30),%r26 ;# 3890 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 3894 call_value_internal_symref
+ zdep %r25,29,30,%r25 ;# 3892 ashlsi3+1
+ comib,= 0,%r28,L$0953 ;# 3903 bleu+1
+ stw %r28,-312(%r30) ;# 3898 reload_outsi+2/6
+ ldw -308(%r30),%r19 ;# 3912 reload_outsi+2/5
+ zdep %r19,30,31,%r19 ;# 3914 ashlsi3+1
+ stw %r19,-308(%r30) ;# 3916 reload_outsi+2/6
+L$0398
+ ldw -304(%r30),%r20 ;# 3921 reload_outsi+2/5
+ ldw -312(%r30),%r21 ;# 3923 reload_outsi+2/5
+ ldw 0(%r5),%r19 ;# 3933 reload_outsi+2/5
+ sh2addl %r20,%r20,%r20 ;# 3928 ashlsi3-2
+ sh2addl %r20,%r21,%r21 ;# 3931 ashlsi3-2
+ sub %r12,%r19,%r19 ;# 3934 subsi3/1
+ stw %r19,0(%r21) ;# 3936 reload_outsi+2/6
+ ldw -304(%r30),%r19 ;# 3939 reload_outsi+2/5
+ ldw -312(%r30),%r20 ;# 3941 reload_outsi+2/5
+ sh2addl %r19,%r19,%r19 ;# 3946 ashlsi3-2
+ comib,= 0,%r10,L$0400 ;# 3951 bleu+1
+ sh2addl %r19,%r20,%r20 ;# 3949 ashlsi3-2
+ ldw 0(%r5),%r19 ;# 3953 reload_outsi+2/5
+ sub %r10,%r19,%r19 ;# 3954 subsi3/1
+ ldo 1(%r19),%r19 ;# 3955 addsi3/2
+ bl L$0401,%r0 ;# 3958 jump
+ stw %r19,4(%r20) ;# 3957 reload_outsi+2/6
+L$0400
+ stw %r0,4(%r20) ;# 3962 reload_outsi+2/6
+L$0401
+ ldw -304(%r30),%r20 ;# 3966 reload_outsi+2/5
+ ldw -312(%r30),%r21 ;# 3968 reload_outsi+2/5
+ ldw 0(%r5),%r19 ;# 3978 reload_outsi+2/5
+ sh2addl %r20,%r20,%r20 ;# 3973 ashlsi3-2
+ sh2addl %r20,%r21,%r21 ;# 3976 ashlsi3-2
+ sub %r6,%r19,%r19 ;# 3979 subsi3/1
+ stw %r19,12(%r21) ;# 3981 reload_outsi+2/6
+ ldw -304(%r30),%r19 ;# 3984 reload_outsi+2/5
+ ldw -312(%r30),%r20 ;# 3986 reload_outsi+2/5
+ ldw -260(%r30),%r1 ;# 8964 reload_outsi+2/5
+ sh2addl %r19,%r19,%r19 ;# 3991 ashlsi3-2
+ sh2addl %r19,%r20,%r20 ;# 3994 ashlsi3-2
+ ldi 255,%r19 ;# 3999 reload_outsi+2/2
+ comb,<< %r19,%r1,L$0402 ;# 4001 bleu+1
+ stw %r1,16(%r20) ;# 3996 reload_outsi+2/6
+ ldw -304(%r30),%r20 ;# 4005 reload_outsi+2/5
+ ldw -312(%r30),%r21 ;# 4007 reload_outsi+2/5
+ ldw 0(%r5),%r19 ;# 4017 reload_outsi+2/5
+ sh2addl %r20,%r20,%r20 ;# 4012 ashlsi3-2
+ sh2addl %r20,%r21,%r21 ;# 4015 ashlsi3-2
+ sub %r6,%r19,%r19 ;# 4018 subsi3/1
+ ldo 2(%r19),%r19 ;# 4019 addsi3/2
+ stw %r19,8(%r21) ;# 4021 reload_outsi+2/6
+ ldw 0(%r5),%r4 ;# 8087 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 8090 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 8088 subsi3/1
+ ldo 3(%r19),%r19 ;# 8089 addsi3/2
+ comb,>>=,n %r20,%r19,L$0407 ;# 8091 bleu+1
+ ldil L'65536,%r3 ;# 8593 reload_outsi+2/3
+L$0408
+ comb,= %r3,%r20,L$0944 ;# 4049 bleu+1
+ zdep %r20,30,31,%r19 ;# 4059 ashlsi3+1
+ comb,>>= %r3,%r19,L$0413 ;# 4067 bleu+1
+ stw %r19,4(%r5) ;# 4061 reload_outsi+2/6
+ stw %r3,4(%r5) ;# 4070 reload_outsi+2/6
+L$0413
+ ldw 0(%r5),%r26 ;# 4077 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 4081 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 4079 reload_outsi+2/5
+ comib,= 0,%r28,L$0953 ;# 4089 bleu+1
+ stw %r28,0(%r5) ;# 4085 reload_outsi+2/6
+ comb,= %r28,%r4,L$0406 ;# 4099 bleu+1
+ sub %r6,%r4,%r19 ;# 4101 subsi3/1
+ comib,= 0,%r10,L$0416 ;# 4110 bleu+1
+ addl %r28,%r19,%r6 ;# 4104 addsi3/1
+ sub %r10,%r4,%r19 ;# 4111 subsi3/1
+ addl %r28,%r19,%r10 ;# 4114 addsi3/1
+L$0416
+ comib,= 0,%r8,L$0417 ;# 4117 bleu+1
+ sub %r8,%r4,%r19 ;# 4118 subsi3/1
+ addl %r28,%r19,%r8 ;# 4121 addsi3/1
+L$0417
+ comib,= 0,%r9,L$0406 ;# 4124 bleu+1
+ sub %r9,%r4,%r19 ;# 4125 subsi3/1
+ addl %r28,%r19,%r9 ;# 4128 addsi3/1
+L$0406
+ ldw 0(%r5),%r4 ;# 4029 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 4033 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 4030 subsi3/1
+ ldo 3(%r19),%r19 ;# 4031 addsi3/2
+ comb,<< %r20,%r19,L$0408
+ nop ;# 4035 bleu+1
+L$0407
+ ldi 5,%r19 ;# 4150 movqi+1/2
+ stbs,ma %r19,1(%r6) ;# 4151 movqi+1/6
+ ldb -257(%r30),%r1 ;# 4156 movqi+1/5
+ stbs,ma %r1,1(%r6) ;# 8968 movqi+1/6
+ stbs,ma %r0,1(%r6) ;# 4159 movqi+1/6
+L$0402
+ ldi 0,%r10 ;# 4182 reload_outsi+2/2
+ ldi 0,%r8 ;# 4185 reload_outsi+2/2
+ copy %r6,%r12 ;# 4188 reload_outsi+2/1
+ ldw -304(%r30),%r19 ;# 4174 reload_outsi+2/5
+ ldi 0,%r9 ;# 4191 reload_outsi+2/2
+ ldo 1(%r19),%r19 ;# 4175 addsi3/2
+ bl L$0043,%r0 ;# 4193 jump
+ stw %r19,-304(%r30) ;# 4179 reload_outsi+2/6
+L$0422
+ bb,< %r15,18,L$0397 ;# 4201 bleu+3
+ ldw -304(%r30),%r19 ;# 4207 reload_outsi+2/5
+ comib,<>,n 0,%r19,L$0374 ;# 4209 bleu+1
+ bb,>=,n %r15,14,L$0950 ;# 4215 movsi-4
+ bl,n L$0397,%r0 ;# 4230 jump
+L$0374
+ comib,=,n 0,%r10,L$0427 ;# 4237 bleu+1
+ ldw 0(%r5),%r4 ;# 8095 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 8098 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 8096 subsi3/1
+ ldo 1(%r19),%r19 ;# 8097 addsi3/2
+ comb,>>=,n %r20,%r19,L$0432 ;# 8099 bleu+1
+ ldil L'65536,%r3 ;# 8591 reload_outsi+2/3
+L$0433
+ comb,= %r3,%r20,L$0944 ;# 4266 bleu+1
+ zdep %r20,30,31,%r19 ;# 4276 ashlsi3+1
+ comb,>>= %r3,%r19,L$0438 ;# 4284 bleu+1
+ stw %r19,4(%r5) ;# 4278 reload_outsi+2/6
+ stw %r3,4(%r5) ;# 4287 reload_outsi+2/6
+L$0438
+ ldw 0(%r5),%r26 ;# 4294 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 4298 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 4296 reload_outsi+2/5
+ comib,= 0,%r28,L$0953 ;# 4306 bleu+1
+ stw %r28,0(%r5) ;# 4302 reload_outsi+2/6
+ comb,= %r28,%r4,L$0431 ;# 4316 bleu+1
+ sub %r6,%r4,%r19 ;# 4318 subsi3/1
+ addl %r28,%r19,%r6 ;# 4321 addsi3/1
+ sub %r12,%r4,%r19 ;# 4322 subsi3/1
+ comib,= 0,%r10,L$0441 ;# 4327 bleu+1
+ addl %r28,%r19,%r12 ;# 4325 addsi3/1
+ sub %r10,%r4,%r19 ;# 4328 subsi3/1
+ addl %r28,%r19,%r10 ;# 4331 addsi3/1
+L$0441
+ comib,= 0,%r8,L$0442 ;# 4334 bleu+1
+ sub %r8,%r4,%r19 ;# 4335 subsi3/1
+ addl %r28,%r19,%r8 ;# 4338 addsi3/1
+L$0442
+ comib,= 0,%r9,L$0431 ;# 4341 bleu+1
+ sub %r9,%r4,%r19 ;# 4342 subsi3/1
+ addl %r28,%r19,%r9 ;# 4345 addsi3/1
+L$0431
+ ldw 0(%r5),%r4 ;# 4246 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 4250 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 4247 subsi3/1
+ ldo 1(%r19),%r19 ;# 4248 addsi3/2
+ comb,<< %r20,%r19,L$0433
+ nop ;# 4252 bleu+1
+L$0432
+ ldi 19,%r19 ;# 4367 movqi+1/2
+ stbs,ma %r19,1(%r6) ;# 4368 movqi+1/6
+ uaddcm %r6,%r10,%r24 ;# 4381 adddi3+1
+ ldi 13,%r26 ;# 4384 reload_outsi+2/2
+ copy %r10,%r25 ;# 4386 reload_outsi+2/1
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl store_op1,%r2 ;# 4390 call_internal_symref
+ ldo -3(%r24),%r24 ;# 4388 addsi3/2
+L$0427
+ ldw -304(%r30),%r19 ;# 4395 reload_outsi+2/5
+ comib,<>,n 0,%r19,L$0447 ;# 4397 bleu+1
+ bb,<,n %r15,14,L$0076 ;# 4403 bleu+3
+L$0950
+ .CALL ARGW0=GR
+ bl free,%r2 ;# 4414 call_internal_symref
+ ldw -312(%r30),%r26 ;# 4412 reload_outsi+2/5
+ bl L$0867,%r0 ;# 4418 jump
+ ldi 16,%r28 ;# 4416 reload_outsi+2/2
+L$0447
+ ldo -1(%r19),%r19 ;# 4427 addsi3/2
+ stw %r19,-304(%r30) ;# 4431 reload_outsi+2/6
+ ldw -312(%r30),%r20 ;# 4436 reload_outsi+2/5
+ sh2addl %r19,%r19,%r19 ;# 4441 ashlsi3-2
+ sh2addl %r19,%r20,%r20 ;# 4444 ashlsi3-2
+ ldw 0(%r5),%r21 ;# 4446 reload_outsi+2/5
+ ldw 0(%r20),%r19 ;# 4448 reload_outsi+2/5
+ ldw 4(%r20),%r20 ;# 4464 reload_outsi+2/5
+ comib,= 0,%r20,L$0450 ;# 4466 bleu+1
+ addl %r21,%r19,%r12 ;# 4449 addsi3/1
+ addl %r21,%r20,%r19 ;# 4483 addsi3/1
+ bl L$0451,%r0 ;# 4485 jump
+ ldo -1(%r19),%r10 ;# 4484 addsi3/2
+L$0450
+ ldi 0,%r10 ;# 4489 reload_outsi+2/2
+L$0451
+ ldw -304(%r30),%r19 ;# 4493 reload_outsi+2/5
+ ldw -312(%r30),%r20 ;# 4495 reload_outsi+2/5
+ ldw 0(%r5),%r21 ;# 4505 reload_outsi+2/5
+ sh2addl %r19,%r19,%r19 ;# 4500 ashlsi3-2
+ sh2addl %r19,%r20,%r20 ;# 4503 ashlsi3-2
+ ldw 12(%r20),%r19 ;# 4507 reload_outsi+2/5
+ ldw 16(%r20),%r7 ;# 4523 reload_outsi+2/5
+ addl %r21,%r19,%r8 ;# 4508 addsi3/1
+ ldi 255,%r19 ;# 4529 reload_outsi+2/2
+ comb,<< %r19,%r7,L$0043 ;# 4531 bleu+1
+ ldi 0,%r9 ;# 4526 reload_outsi+2/2
+ ldw 8(%r20),%r19 ;# 4550 reload_outsi+2/5
+ ldw -260(%r30),%r1 ;# 8971 reload_outsi+2/5
+ addl %r21,%r19,%r19 ;# 4551 addsi3/1
+ sub %r1,%r7,%r20 ;# 4557 subsi3/1
+ stb %r20,0(%r19) ;# 4559 movqi+1/6
+ ldw 0(%r5),%r4 ;# 8103 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 8106 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 8104 subsi3/1
+ ldo 3(%r19),%r19 ;# 8105 addsi3/2
+ comb,>>=,n %r20,%r19,L$0457 ;# 8107 bleu+1
+ ldil L'65536,%r3 ;# 8589 reload_outsi+2/3
+L$0458
+ comb,= %r3,%r20,L$0944 ;# 4587 bleu+1
+ zdep %r20,30,31,%r19 ;# 4597 ashlsi3+1
+ comb,>>= %r3,%r19,L$0463 ;# 4605 bleu+1
+ stw %r19,4(%r5) ;# 4599 reload_outsi+2/6
+ stw %r3,4(%r5) ;# 4608 reload_outsi+2/6
+L$0463
+ ldw 0(%r5),%r26 ;# 4615 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 4619 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 4617 reload_outsi+2/5
+ comib,= 0,%r28,L$0953 ;# 4627 bleu+1
+ stw %r28,0(%r5) ;# 4623 reload_outsi+2/6
+ comb,= %r28,%r4,L$0456 ;# 4637 bleu+1
+ sub %r6,%r4,%r19 ;# 4639 subsi3/1
+ addl %r28,%r19,%r6 ;# 4642 addsi3/1
+ sub %r12,%r4,%r19 ;# 4643 subsi3/1
+ comib,= 0,%r10,L$0466 ;# 4648 bleu+1
+ addl %r28,%r19,%r12 ;# 4646 addsi3/1
+ sub %r10,%r4,%r19 ;# 4649 subsi3/1
+ addl %r28,%r19,%r10 ;# 4652 addsi3/1
+L$0466
+ comib,= 0,%r8,L$0467 ;# 4655 bleu+1
+ sub %r8,%r4,%r19 ;# 4656 subsi3/1
+ addl %r28,%r19,%r8 ;# 4659 addsi3/1
+L$0467
+ comib,= 0,%r9,L$0456 ;# 4662 bleu+1
+ sub %r9,%r4,%r19 ;# 4663 subsi3/1
+ addl %r28,%r19,%r9 ;# 4666 addsi3/1
+L$0456
+ ldw 0(%r5),%r4 ;# 4567 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 4571 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 4568 subsi3/1
+ ldo 3(%r19),%r19 ;# 4569 addsi3/2
+ comb,<< %r20,%r19,L$0458
+ nop ;# 4573 bleu+1
+L$0457
+ ldi 6,%r19 ;# 4688 movqi+1/2
+ stbs,ma %r19,1(%r6) ;# 4689 movqi+1/6
+ stbs,ma %r7,1(%r6) ;# 4694 movqi+1/6
+ ldw -260(%r30),%r1 ;# 8974 reload_outsi+2/5
+ sub %r1,%r7,%r19 ;# 4700 subsi3/1
+ bl L$0043,%r0 ;# 4720 jump
+ stbs,ma %r19,1(%r6) ;# 4702 movqi+1/6
+L$0472
+ ldo R'33792(%r19),%r19 ;# 4725 movhi-2
+ and %r15,%r19,%r19 ;# 4726 andsi3/1
+ comib,<>,n 0,%r19,L$0397 ;# 4728 bleu+1
+L$0378
+ bb,<,n %r15,21,L$0076 ;# 4739 bleu+3
+ ldw 0(%r5),%r3 ;# 8111 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 8114 reload_outsi+2/5
+ sub %r6,%r3,%r19 ;# 8112 subsi3/1
+ ldo 3(%r19),%r19 ;# 8113 addsi3/2
+ comb,>>=,n %r20,%r19,L$0476 ;# 8115 bleu+1
+ ldil L'65536,%r4 ;# 8587 reload_outsi+2/3
+L$0477
+ comb,= %r4,%r20,L$0944 ;# 4768 bleu+1
+ zdep %r20,30,31,%r19 ;# 4778 ashlsi3+1
+ comb,>>= %r4,%r19,L$0482 ;# 4786 bleu+1
+ stw %r19,4(%r5) ;# 4780 reload_outsi+2/6
+ stw %r4,4(%r5) ;# 4789 reload_outsi+2/6
+L$0482
+ ldw 0(%r5),%r26 ;# 4796 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 4800 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 4798 reload_outsi+2/5
+ comib,= 0,%r28,L$0953 ;# 4808 bleu+1
+ stw %r28,0(%r5) ;# 4804 reload_outsi+2/6
+ comb,= %r28,%r3,L$0475 ;# 4818 bleu+1
+ sub %r6,%r3,%r19 ;# 4820 subsi3/1
+ addl %r28,%r19,%r6 ;# 4823 addsi3/1
+ sub %r12,%r3,%r19 ;# 4824 subsi3/1
+ comib,= 0,%r10,L$0485 ;# 4829 bleu+1
+ addl %r28,%r19,%r12 ;# 4827 addsi3/1
+ sub %r10,%r3,%r19 ;# 4830 subsi3/1
+ addl %r28,%r19,%r10 ;# 4833 addsi3/1
+L$0485
+ comib,= 0,%r8,L$0486 ;# 4836 bleu+1
+ sub %r8,%r3,%r19 ;# 4837 subsi3/1
+ addl %r28,%r19,%r8 ;# 4840 addsi3/1
+L$0486
+ comib,= 0,%r9,L$0475 ;# 4843 bleu+1
+ sub %r9,%r3,%r19 ;# 4844 subsi3/1
+ addl %r28,%r19,%r9 ;# 4847 addsi3/1
+L$0475
+ ldw 0(%r5),%r3 ;# 4748 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 4752 reload_outsi+2/5
+ sub %r6,%r3,%r19 ;# 4749 subsi3/1
+ ldo 3(%r19),%r19 ;# 4750 addsi3/2
+ comb,<< %r20,%r19,L$0477
+ nop ;# 4754 bleu+1
+L$0476
+ ldi 14,%r26 ;# 4873 reload_outsi+2/2
+ copy %r12,%r25 ;# 4875 reload_outsi+2/1
+ sub %r6,%r25,%r24 ;# 4870 subsi3/1
+ ldo 3(%r24),%r24 ;# 4877 addsi3/2
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl insert_op1,%r2 ;# 4881 call_internal_symref
+ copy %r6,%r23 ;# 4879 reload_outsi+2/1
+ ldi 0,%r9 ;# 4884 reload_outsi+2/2
+ comib,= 0,%r10,L$0490 ;# 4889 bleu+1
+ ldo 3(%r6),%r6 ;# 4886 addsi3/2
+ ldi 13,%r26 ;# 4894 reload_outsi+2/2
+ copy %r10,%r25 ;# 4896 reload_outsi+2/1
+ sub %r6,%r25,%r24 ;# 4891 subsi3/1
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl store_op1,%r2 ;# 4900 call_internal_symref
+ ldo -3(%r24),%r24 ;# 4898 addsi3/2
+L$0490
+ ldw 0(%r5),%r3 ;# 8119 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 8122 reload_outsi+2/5
+ sub %r6,%r3,%r19 ;# 8120 subsi3/1
+ ldo 3(%r19),%r19 ;# 8121 addsi3/2
+ comb,>>= %r20,%r19,L$0492 ;# 8123 bleu+1
+ copy %r6,%r10 ;# 4904 reload_outsi+2/1
+ ldil L'65536,%r4 ;# 8585 reload_outsi+2/3
+L$0493
+ comb,= %r4,%r20,L$0944 ;# 4929 bleu+1
+ zdep %r20,30,31,%r19 ;# 4939 ashlsi3+1
+ comb,>>= %r4,%r19,L$0498 ;# 4947 bleu+1
+ stw %r19,4(%r5) ;# 4941 reload_outsi+2/6
+ stw %r4,4(%r5) ;# 4950 reload_outsi+2/6
+L$0498
+ ldw 0(%r5),%r26 ;# 4957 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 4961 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 4959 reload_outsi+2/5
+ comib,= 0,%r28,L$0953 ;# 4969 bleu+1
+ stw %r28,0(%r5) ;# 4965 reload_outsi+2/6
+ comb,= %r28,%r3,L$0491 ;# 4979 bleu+1
+ sub %r6,%r3,%r19 ;# 4981 subsi3/1
+ comib,= 0,%r10,L$0501 ;# 4990 bleu+1
+ addl %r28,%r19,%r6 ;# 4984 addsi3/1
+ sub %r10,%r3,%r19 ;# 4991 subsi3/1
+ addl %r28,%r19,%r10 ;# 4994 addsi3/1
+L$0501
+ comib,= 0,%r8,L$0502 ;# 4997 bleu+1
+ sub %r8,%r3,%r19 ;# 4998 subsi3/1
+ addl %r28,%r19,%r8 ;# 5001 addsi3/1
+L$0502
+ comib,= 0,%r9,L$0491 ;# 5004 bleu+1
+ sub %r9,%r3,%r19 ;# 5005 subsi3/1
+ addl %r28,%r19,%r9 ;# 5008 addsi3/1
+L$0491
+ ldw 0(%r5),%r3 ;# 4909 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 4913 reload_outsi+2/5
+ sub %r6,%r3,%r19 ;# 4910 subsi3/1
+ ldo 3(%r19),%r19 ;# 4911 addsi3/2
+ comb,<< %r20,%r19,L$0493
+ nop ;# 4915 bleu+1
+L$0492
+ ldo 3(%r6),%r6 ;# 5030 addsi3/2
+ ldi 0,%r8 ;# 5033 reload_outsi+2/2
+ bl L$0043,%r0 ;# 5038 jump
+ copy %r6,%r12 ;# 5036 reload_outsi+2/1
+L$0506
+ bb,>= %r15,22,L$0397 ;# 5046 movsi-4
+ ldi 4608,%r20 ;# 5048 reload_outsi+2/2
+ and %r15,%r20,%r19 ;# 5049 andsi3/1
+ comb,= %r20,%r19,L$0397 ;# 5053 bleu+1
+ ldw -296(%r30),%r20 ;# 5055 reload_outsi+2/5
+ ldw -276(%r30),%r1 ;# 8977 reload_outsi+2/5
+ ldo -2(%r20),%r19 ;# 5056 addsi3/2
+ comb,<> %r1,%r19,L$1175 ;# 5058 bleu+1
+ ldi -1,%r4 ;# 5074 reload_outsi+2/2
+ comb,=,n %r16,%r20,L$0397 ;# 5062 bleu+1
+L$1174
+ ldw -296(%r30),%r20 ;# 5079 reload_outsi+2/5
+L$1175
+ copy %r4,%r11 ;# 5076 reload_outsi+2/1
+ comb,<> %r16,%r20,L$0517 ;# 5085 bleu+1
+ ldo -1(%r20),%r23 ;# 5080 addsi3/2
+ bb,>=,n %r15,19,L$0915 ;# 5092 movsi-4
+ bl L$1182,%r0 ;# 5107 jump
+ stw %r23,-296(%r30) ;# 5968 reload_outsi+2/6
+L$0517
+ ldo 1(%r20),%r19 ;# 5134 addsi3/2
+ stw %r19,-296(%r30) ;# 5136 reload_outsi+2/6
+ comib,= 0,%r14,L$0515 ;# 5143 bleu+1
+ ldb 0(%r20),%r7 ;# 5139 zero_extendqisi2/2
+ addl %r14,%r7,%r19 ;# 5144 addsi3/1
+ ldb 0(%r19),%r7 ;# 5147 zero_extendqisi2/2
+L$0515
+ addil LR'__ctype-$global$,%r27 ;# 8257 pic2_lo_sum+1
+ ldw RR'__ctype-$global$(%r1),%r21 ;# 8259 reload_outsi+2/5
+ addl %r21,%r7,%r19 ;# 8260 addsi3/1
+ ldb 0(%r19),%r19 ;# 8261 movqi+1/5
+ bb,>= %r19,29,L$0513 ;# 8265 movsi-4
+ ldi 4,%r20 ;# 8263 reload_outsi+2/2
+ copy %r20,%r22 ;# 8583 reload_outsi+2/1
+L$0522
+ comiclr,< -1,%r11,%r0 ;# 8128 movsicc+1/1
+ ldi 0,%r11
+ sh2addl %r11,%r11,%r19 ;# 5188 ashlsi3-2
+ sh1addl %r19,%r7,%r19 ;# 5191 ashlsi3-2
+ ldw -296(%r30),%r20 ;# 5194 reload_outsi+2/5
+ comb,= %r16,%r20,L$0513 ;# 5196 bleu+1
+ ldo -48(%r19),%r11 ;# 5192 addsi3/2
+ ldo 1(%r20),%r19 ;# 5215 addsi3/2
+ stw %r19,-296(%r30) ;# 5217 reload_outsi+2/6
+ comib,= 0,%r14,L$0520 ;# 5224 bleu+1
+ ldb 0(%r20),%r7 ;# 5220 zero_extendqisi2/2
+ addl %r14,%r7,%r19 ;# 5225 addsi3/1
+ ldb 0(%r19),%r7 ;# 5228 zero_extendqisi2/2
+L$0520
+ addl %r21,%r7,%r19 ;# 5166 addsi3/1
+ ldb 0(%r19),%r19 ;# 5168 movqi+1/5
+ and %r19,%r22,%r19 ;# 5172 andsi3/1
+ comib,<> 0,%r19,L$0522
+ nop ;# 5174 bleu+1
+L$0513
+ ldi 44,%r19 ;# 5252 reload_outsi+2/2
+ comb,<> %r19,%r7,L$0532 ;# 5254 bleu+1
+ ldw -296(%r30),%r20 ;# 5259 reload_outsi+2/5
+ comb,= %r16,%r20,L$0533 ;# 5261 bleu+1
+ ldo 1(%r20),%r19 ;# 5278 addsi3/2
+ stw %r19,-296(%r30) ;# 5280 reload_outsi+2/6
+ comib,= 0,%r14,L$0535 ;# 5287 bleu+1
+ ldb 0(%r20),%r7 ;# 5283 zero_extendqisi2/2
+ addl %r14,%r7,%r19 ;# 5288 addsi3/1
+ ldb 0(%r19),%r7 ;# 5291 zero_extendqisi2/2
+L$0535
+ addil LR'__ctype-$global$,%r27 ;# 8269 pic2_lo_sum+1
+ ldw RR'__ctype-$global$(%r1),%r21 ;# 8271 reload_outsi+2/5
+ addl %r21,%r7,%r19 ;# 8272 addsi3/1
+ ldb 0(%r19),%r19 ;# 8273 movqi+1/5
+ bb,>= %r19,29,L$0533 ;# 8277 movsi-4
+ ldi 4,%r20 ;# 8275 reload_outsi+2/2
+ copy %r20,%r22 ;# 8578 reload_outsi+2/1
+L$0542
+ comiclr,< -1,%r4,%r0 ;# 8132 movsicc+1/1
+ ldi 0,%r4
+ sh2addl %r4,%r4,%r19 ;# 5332 ashlsi3-2
+ sh1addl %r19,%r7,%r19 ;# 5335 ashlsi3-2
+ ldw -296(%r30),%r20 ;# 5338 reload_outsi+2/5
+ comb,= %r16,%r20,L$0533 ;# 5340 bleu+1
+ ldo -48(%r19),%r4 ;# 5336 addsi3/2
+ ldo 1(%r20),%r19 ;# 5359 addsi3/2
+ stw %r19,-296(%r30) ;# 5361 reload_outsi+2/6
+ comib,= 0,%r14,L$0540 ;# 5368 bleu+1
+ ldb 0(%r20),%r7 ;# 5364 zero_extendqisi2/2
+ addl %r14,%r7,%r19 ;# 5369 addsi3/1
+ ldb 0(%r19),%r7 ;# 5372 zero_extendqisi2/2
+L$0540
+ addl %r21,%r7,%r19 ;# 5310 addsi3/1
+ ldb 0(%r19),%r19 ;# 5312 movqi+1/5
+ and %r19,%r22,%r19 ;# 5316 andsi3/1
+ comib,<> 0,%r19,L$0542
+ nop ;# 5318 bleu+1
+L$0533
+ comiclr,< -1,%r4,%r0 ;# 8136 beq-1/4
+ zdepi -1,31,15,%r4
+ bl,n L$0553,%r0 ;# 5401 jump
+L$0532
+ copy %r11,%r4 ;# 5406 reload_outsi+2/1
+L$0553
+ comib,> 0,%r11,L$0951 ;# 5410 bleu+1
+ zdepi -1,31,15,%r19 ;# 5412 reload_outsi+2/4
+ comb,<,n %r19,%r4,L$0951 ;# 5414 bleu+1
+ comb,<,n %r4,%r11,L$0951 ;# 5416 bleu+1
+ bb,< %r15,19,L$1176 ;# 5451 bleu+3
+ ldi 125,%r19 ;# 5514 reload_outsi+2/2
+ ldi 92,%r19 ;# 5455 reload_outsi+2/2
+ comb,<> %r19,%r7,L$0915 ;# 5457 bleu+1
+ ldw -296(%r30),%r20 ;# 5473 reload_outsi+2/5
+ comb,= %r16,%r20,L$0922 ;# 5475 bleu+1
+ ldo 1(%r20),%r19 ;# 5484 addsi3/2
+ stw %r19,-296(%r30) ;# 5486 reload_outsi+2/6
+ comib,= 0,%r14,L$0558 ;# 5493 bleu+1
+ ldb 0(%r20),%r7 ;# 5489 zero_extendqisi2/2
+ addl %r14,%r7,%r19 ;# 5494 addsi3/1
+ ldb 0(%r19),%r7 ;# 5497 zero_extendqisi2/2
+L$0558
+ ldi 125,%r19 ;# 5514 reload_outsi+2/2
+L$1176
+ comb,=,n %r19,%r7,L$0566 ;# 5516 bleu+1
+L$0951
+ bb,<,n %r15,19,L$0511 ;# 5523 bleu+3
+ .CALL ARGW0=GR
+ bl free,%r2 ;# 5534 call_internal_symref
+ ldw -312(%r30),%r26 ;# 5532 reload_outsi+2/5
+ bl L$0867,%r0 ;# 5538 jump
+ ldi 10,%r28 ;# 5536 reload_outsi+2/2
+L$0566
+ comib,<>,n 0,%r8,L$0569 ;# 5545 bleu+1
+ bb,<,n %r15,26,L$0917 ;# 5552 bleu+3
+ bb,>=,n %r15,27,L$0511 ;# 5571 movsi-4
+ copy %r6,%r8 ;# 5574 reload_outsi+2/1
+L$0569
+ comib,<> 0,%r4,L$0574 ;# 5587 bleu+1
+ ldi 10,%r13 ;# 8980 reload_outsi+2/2
+ ldw 0(%r5),%r3 ;# 8139 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 8142 reload_outsi+2/5
+ sub %r6,%r3,%r19 ;# 8140 subsi3/1
+ ldo 3(%r19),%r19 ;# 8141 addsi3/2
+ comb,>>=,n %r20,%r19,L$0576 ;# 8143 bleu+1
+ ldil L'65536,%r4 ;# 8573 reload_outsi+2/3
+L$0577
+ comb,= %r4,%r20,L$0944 ;# 5613 bleu+1
+ zdep %r20,30,31,%r19 ;# 5623 ashlsi3+1
+ comb,>>= %r4,%r19,L$0582 ;# 5631 bleu+1
+ stw %r19,4(%r5) ;# 5625 reload_outsi+2/6
+ stw %r4,4(%r5) ;# 5634 reload_outsi+2/6
+L$0582
+ ldw 0(%r5),%r26 ;# 5641 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 5645 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 5643 reload_outsi+2/5
+ comib,= 0,%r28,L$0953 ;# 5653 bleu+1
+ stw %r28,0(%r5) ;# 5649 reload_outsi+2/6
+ comb,= %r28,%r3,L$0575 ;# 5663 bleu+1
+ sub %r6,%r3,%r19 ;# 5665 subsi3/1
+ addl %r28,%r19,%r6 ;# 5668 addsi3/1
+ sub %r12,%r3,%r19 ;# 5669 subsi3/1
+ comib,= 0,%r10,L$0585 ;# 5674 bleu+1
+ addl %r28,%r19,%r12 ;# 5672 addsi3/1
+ sub %r10,%r3,%r19 ;# 5675 subsi3/1
+ addl %r28,%r19,%r10 ;# 5678 addsi3/1
+L$0585
+ comib,= 0,%r8,L$0586 ;# 5681 bleu+1
+ sub %r8,%r3,%r19 ;# 5682 subsi3/1
+ addl %r28,%r19,%r8 ;# 5685 addsi3/1
+L$0586
+ comib,= 0,%r9,L$0575 ;# 5688 bleu+1
+ sub %r9,%r3,%r19 ;# 5689 subsi3/1
+ addl %r28,%r19,%r9 ;# 5692 addsi3/1
+L$0575
+ ldw 0(%r5),%r3 ;# 5593 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 5597 reload_outsi+2/5
+ sub %r6,%r3,%r19 ;# 5594 subsi3/1
+ ldo 3(%r19),%r19 ;# 5595 addsi3/2
+ comb,<< %r20,%r19,L$0577
+ nop ;# 5599 bleu+1
+L$0576
+ ldi 12,%r26 ;# 5718 reload_outsi+2/2
+ copy %r8,%r25 ;# 5720 reload_outsi+2/1
+ sub %r6,%r8,%r24 ;# 5722 subsi3/1
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl insert_op1,%r2 ;# 5726 call_internal_symref
+ copy %r6,%r23 ;# 5724 reload_outsi+2/1
+ bl L$0590,%r0 ;# 5730 jump
+ ldo 3(%r6),%r6 ;# 5728 addsi3/2
+L$0574
+ comiclr,> 2,%r4,%r0 ;# 8282 beq-1/2
+ ldi 20,%r13
+ ldw 0(%r5),%r3 ;# 8285 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 8288 reload_outsi+2/5
+ sub %r6,%r3,%r19 ;# 8286 subsi3/1
+ addl %r19,%r13,%r19 ;# 8287 addsi3/1
+ comb,>>=,n %r20,%r19,L$0868 ;# 8289 bleu+1
+ ldil L'65536,%r7 ;# 8571 reload_outsi+2/3
+L$0595
+ comb,= %r7,%r20,L$0944 ;# 5769 bleu+1
+ zdep %r20,30,31,%r19 ;# 5779 ashlsi3+1
+ comb,>>= %r7,%r19,L$0600 ;# 5787 bleu+1
+ stw %r19,4(%r5) ;# 5781 reload_outsi+2/6
+ stw %r7,4(%r5) ;# 5790 reload_outsi+2/6
+L$0600
+ ldw 0(%r5),%r26 ;# 5797 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 5801 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 5799 reload_outsi+2/5
+ comib,= 0,%r28,L$0953 ;# 5809 bleu+1
+ stw %r28,0(%r5) ;# 5805 reload_outsi+2/6
+ comb,= %r28,%r3,L$0593 ;# 5819 bleu+1
+ sub %r6,%r3,%r19 ;# 5821 subsi3/1
+ addl %r28,%r19,%r6 ;# 5824 addsi3/1
+ sub %r12,%r3,%r19 ;# 5825 subsi3/1
+ comib,= 0,%r10,L$0603 ;# 5830 bleu+1
+ addl %r28,%r19,%r12 ;# 5828 addsi3/1
+ sub %r10,%r3,%r19 ;# 5831 subsi3/1
+ addl %r28,%r19,%r10 ;# 5834 addsi3/1
+L$0603
+ comib,= 0,%r8,L$0604 ;# 5837 bleu+1
+ sub %r8,%r3,%r19 ;# 5838 subsi3/1
+ addl %r28,%r19,%r8 ;# 5841 addsi3/1
+L$0604
+ comib,= 0,%r9,L$0593 ;# 5844 bleu+1
+ sub %r9,%r3,%r19 ;# 5845 subsi3/1
+ addl %r28,%r19,%r9 ;# 5848 addsi3/1
+L$0593
+ ldw 0(%r5),%r3 ;# 5749 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 5753 reload_outsi+2/5
+ sub %r6,%r3,%r19 ;# 5750 subsi3/1
+ addl %r19,%r13,%r19 ;# 5751 addsi3/1
+ comb,<< %r20,%r19,L$0595
+ nop ;# 5755 bleu+1
+L$0868
+ comib,>= 1,%r4,L$0608 ;# 5872 bleu+1
+ ldo 5(%r6),%r19 ;# 5870 addsi3/2
+ sub %r19,%r8,%r19 ;# 5874 subsi3/1
+ bl L$0609,%r0 ;# 5876 jump
+ ldo 2(%r19),%r24 ;# 5875 addsi3/2
+L$0608
+ sub %r19,%r8,%r19 ;# 5879 subsi3/1
+ ldo -3(%r19),%r24 ;# 5880 addsi3/2
+L$0609
+ ldi 20,%r26 ;# 5885 reload_outsi+2/2
+ copy %r8,%r25 ;# 5887 reload_outsi+2/1
+ copy %r11,%r23 ;# 5891 reload_outsi+2/1
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl insert_op2,%r2 ;# 5893 call_internal_symref
+ stw %r6,-52(%r30) ;# 5883 reload_outsi+2/6
+ ldo 5(%r6),%r6 ;# 5895 addsi3/2
+ ldi 22,%r26 ;# 5900 reload_outsi+2/2
+ copy %r8,%r25 ;# 5902 reload_outsi+2/1
+ ldi 5,%r24 ;# 5904 reload_outsi+2/2
+ copy %r11,%r23 ;# 5906 reload_outsi+2/1
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl insert_op2,%r2 ;# 5908 call_internal_symref
+ stw %r6,-52(%r30) ;# 5898 reload_outsi+2/6
+ comib,>= 1,%r4,L$0590 ;# 5913 bleu+1
+ ldo 5(%r6),%r6 ;# 5910 addsi3/2
+ ldi 21,%r26 ;# 5921 reload_outsi+2/2
+ copy %r6,%r25 ;# 5923 reload_outsi+2/1
+ sub %r8,%r6,%r24 ;# 5917 subsi3/1
+ ldo 2(%r24),%r24 ;# 5925 addsi3/2
+ ldo -1(%r4),%r4 ;# 5919 addsi3/2
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl store_op2,%r2 ;# 5929 call_internal_symref
+ copy %r4,%r23 ;# 5927 reload_outsi+2/1
+ ldo 5(%r6),%r6 ;# 5931 addsi3/2
+ stw %r6,-52(%r30) ;# 5936 reload_outsi+2/6
+ ldi 22,%r26 ;# 5938 reload_outsi+2/2
+ copy %r8,%r25 ;# 5940 reload_outsi+2/1
+ sub %r6,%r8,%r24 ;# 5942 subsi3/1
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR
+ bl insert_op2,%r2 ;# 5946 call_internal_symref
+ copy %r4,%r23 ;# 5944 reload_outsi+2/1
+ ldo 5(%r6),%r6 ;# 5948 addsi3/2
+L$0590
+ bl L$0043,%r0 ;# 5963 jump
+ ldi 0,%r9 ;# 5956 reload_outsi+2/2
+L$0511
+ stw %r23,-296(%r30) ;# 5968 reload_outsi+2/6
+L$1182
+ ldw -296(%r30),%r20 ;# 5977 reload_outsi+2/5
+ comb,= %r16,%r20,L$0922 ;# 5979 bleu+1
+ ldo 1(%r20),%r21 ;# 5988 addsi3/2
+ ldb 0(%r20),%r20 ;# 5992 movqi+1/5
+ stw %r21,-296(%r30) ;# 5990 reload_outsi+2/6
+ comib,= 0,%r14,L$0612 ;# 5997 bleu+1
+ extru %r20,31,8,%r7 ;# 5993 zero_extendqisi2/1
+ addl %r14,%r7,%r19 ;# 5998 addsi3/1
+ ldb 0(%r19),%r7 ;# 6001 zero_extendqisi2/2
+L$0612
+ bb,< %r15,19,L$0076 ;# 6019 bleu+3
+ ldw -276(%r30),%r1 ;# 8983 reload_outsi+2/5
+ comb,>>= %r1,%r21,L$0076 ;# 6025 bleu+1
+ extrs %r20,31,8,%r20 ;# 6030 extendqisi2
+ ldi 92,%r19 ;# 6032 reload_outsi+2/2
+ comb,=,n %r19,%r20,L$0397 ;# 6034 bleu+1
+ bl,n L$0076,%r0 ;# 6042 jump
+L$0619
+ ldw 4(%r5),%r20 ;# 8151 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 8149 subsi3/1
+ ldo 1(%r19),%r19 ;# 8150 addsi3/2
+ comb,>>= %r20,%r19,L$0624 ;# 8152 bleu+1
+ copy %r6,%r8 ;# 6047 reload_outsi+2/1
+ ldil L'65536,%r3 ;# 8569 reload_outsi+2/3
+L$0625
+ comb,= %r3,%r20,L$0944 ;# 6075 bleu+1
+ zdep %r20,30,31,%r19 ;# 6085 ashlsi3+1
+ comb,>>= %r3,%r19,L$0630 ;# 6093 bleu+1
+ stw %r19,4(%r5) ;# 6087 reload_outsi+2/6
+ stw %r3,4(%r5) ;# 6096 reload_outsi+2/6
+L$0630
+ ldw 0(%r5),%r26 ;# 6103 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 6107 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 6105 reload_outsi+2/5
+ comiclr,<> 0,%r28,%r0 ;# 6115 bleu+1
+ bl L$0953,%r0
+ stw %r28,0(%r5) ;# 6111 reload_outsi+2/6
+ comb,= %r28,%r4,L$0623 ;# 6125 bleu+1
+ sub %r6,%r4,%r19 ;# 6127 subsi3/1
+ addl %r28,%r19,%r6 ;# 6130 addsi3/1
+ sub %r12,%r4,%r19 ;# 6131 subsi3/1
+ comib,= 0,%r10,L$0633 ;# 6136 bleu+1
+ addl %r28,%r19,%r12 ;# 6134 addsi3/1
+ sub %r10,%r4,%r19 ;# 6137 subsi3/1
+ addl %r28,%r19,%r10 ;# 6140 addsi3/1
+L$0633
+ comib,= 0,%r8,L$0634 ;# 6143 bleu+1
+ sub %r8,%r4,%r19 ;# 6144 subsi3/1
+ addl %r28,%r19,%r8 ;# 6147 addsi3/1
+L$0634
+ comib,= 0,%r9,L$0623 ;# 6150 bleu+1
+ sub %r9,%r4,%r19 ;# 6151 subsi3/1
+ addl %r28,%r19,%r9 ;# 6154 addsi3/1
+L$0623
+ ldw 0(%r5),%r4 ;# 6055 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 6059 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 6056 subsi3/1
+ ldo 1(%r19),%r19 ;# 6057 addsi3/2
+ comb,<< %r20,%r19,L$0625
+ nop ;# 6061 bleu+1
+L$0624
+ ldi 23,%r19 ;# 6176 movqi+1/2
+ bl L$0043,%r0 ;# 6189 jump
+ stbs,ma %r19,1(%r6) ;# 6177 movqi+1/6
+L$0639
+ ldw 4(%r5),%r20 ;# 8159 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 8157 subsi3/1
+ ldo 1(%r19),%r19 ;# 8158 addsi3/2
+ comb,>>= %r20,%r19,L$0644 ;# 8160 bleu+1
+ copy %r6,%r8 ;# 6194 reload_outsi+2/1
+ ldil L'65536,%r3 ;# 8567 reload_outsi+2/3
+L$0645
+ comb,= %r3,%r20,L$0944 ;# 6222 bleu+1
+ zdep %r20,30,31,%r19 ;# 6232 ashlsi3+1
+ comb,>>= %r3,%r19,L$0650 ;# 6240 bleu+1
+ stw %r19,4(%r5) ;# 6234 reload_outsi+2/6
+ stw %r3,4(%r5) ;# 6243 reload_outsi+2/6
+L$0650
+ ldw 0(%r5),%r26 ;# 6250 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 6254 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 6252 reload_outsi+2/5
+ comiclr,<> 0,%r28,%r0 ;# 6262 bleu+1
+ bl L$0953,%r0
+ stw %r28,0(%r5) ;# 6258 reload_outsi+2/6
+ comb,= %r28,%r4,L$0643 ;# 6272 bleu+1
+ sub %r6,%r4,%r19 ;# 6274 subsi3/1
+ addl %r28,%r19,%r6 ;# 6277 addsi3/1
+ sub %r12,%r4,%r19 ;# 6278 subsi3/1
+ comib,= 0,%r10,L$0653 ;# 6283 bleu+1
+ addl %r28,%r19,%r12 ;# 6281 addsi3/1
+ sub %r10,%r4,%r19 ;# 6284 subsi3/1
+ addl %r28,%r19,%r10 ;# 6287 addsi3/1
+L$0653
+ comib,= 0,%r8,L$0654 ;# 6290 bleu+1
+ sub %r8,%r4,%r19 ;# 6291 subsi3/1
+ addl %r28,%r19,%r8 ;# 6294 addsi3/1
+L$0654
+ comib,= 0,%r9,L$0643 ;# 6297 bleu+1
+ sub %r9,%r4,%r19 ;# 6298 subsi3/1
+ addl %r28,%r19,%r9 ;# 6301 addsi3/1
+L$0643
+ ldw 0(%r5),%r4 ;# 6202 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 6206 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 6203 subsi3/1
+ ldo 1(%r19),%r19 ;# 6204 addsi3/2
+ comb,<< %r20,%r19,L$0645
+ nop ;# 6208 bleu+1
+L$0644
+ ldi 24,%r19 ;# 6323 movqi+1/2
+ bl L$0043,%r0 ;# 6336 jump
+ stbs,ma %r19,1(%r6) ;# 6324 movqi+1/6
+L$0659
+ ldw 4(%r5),%r20 ;# 8167 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 8165 subsi3/1
+ ldo 1(%r19),%r19 ;# 8166 addsi3/2
+ comb,>>=,n %r20,%r19,L$0664 ;# 8168 bleu+1
+ ldil L'65536,%r3 ;# 8565 reload_outsi+2/3
+L$0665
+ comb,= %r3,%r20,L$0944 ;# 6366 bleu+1
+ zdep %r20,30,31,%r19 ;# 6376 ashlsi3+1
+ comb,>>= %r3,%r19,L$0670 ;# 6384 bleu+1
+ stw %r19,4(%r5) ;# 6378 reload_outsi+2/6
+ stw %r3,4(%r5) ;# 6387 reload_outsi+2/6
+L$0670
+ ldw 0(%r5),%r26 ;# 6394 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 6398 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 6396 reload_outsi+2/5
+ comiclr,<> 0,%r28,%r0 ;# 6406 bleu+1
+ bl L$0953,%r0
+ stw %r28,0(%r5) ;# 6402 reload_outsi+2/6
+ comb,= %r28,%r4,L$0663 ;# 6416 bleu+1
+ sub %r6,%r4,%r19 ;# 6418 subsi3/1
+ addl %r28,%r19,%r6 ;# 6421 addsi3/1
+ sub %r12,%r4,%r19 ;# 6422 subsi3/1
+ comib,= 0,%r10,L$0673 ;# 6427 bleu+1
+ addl %r28,%r19,%r12 ;# 6425 addsi3/1
+ sub %r10,%r4,%r19 ;# 6428 subsi3/1
+ addl %r28,%r19,%r10 ;# 6431 addsi3/1
+L$0673
+ comib,= 0,%r8,L$0674 ;# 6434 bleu+1
+ sub %r8,%r4,%r19 ;# 6435 subsi3/1
+ addl %r28,%r19,%r8 ;# 6438 addsi3/1
+L$0674
+ comib,= 0,%r9,L$0663 ;# 6441 bleu+1
+ sub %r9,%r4,%r19 ;# 6442 subsi3/1
+ addl %r28,%r19,%r9 ;# 6445 addsi3/1
+L$0663
+ ldw 0(%r5),%r4 ;# 6346 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 6350 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 6347 subsi3/1
+ ldo 1(%r19),%r19 ;# 6348 addsi3/2
+ comb,<< %r20,%r19,L$0665
+ nop ;# 6352 bleu+1
+L$0664
+ ldi 25,%r19 ;# 6467 movqi+1/2
+ bl L$0043,%r0 ;# 6480 jump
+ stbs,ma %r19,1(%r6) ;# 6468 movqi+1/6
+L$0679
+ ldw 4(%r5),%r20 ;# 8175 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 8173 subsi3/1
+ ldo 1(%r19),%r19 ;# 8174 addsi3/2
+ comb,>>=,n %r20,%r19,L$0684 ;# 8176 bleu+1
+ ldil L'65536,%r3 ;# 8563 reload_outsi+2/3
+L$0685
+ comb,= %r3,%r20,L$0944 ;# 6510 bleu+1
+ zdep %r20,30,31,%r19 ;# 6520 ashlsi3+1
+ comb,>>= %r3,%r19,L$0690 ;# 6528 bleu+1
+ stw %r19,4(%r5) ;# 6522 reload_outsi+2/6
+ stw %r3,4(%r5) ;# 6531 reload_outsi+2/6
+L$0690
+ ldw 0(%r5),%r26 ;# 6538 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 6542 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 6540 reload_outsi+2/5
+ comiclr,<> 0,%r28,%r0 ;# 6550 bleu+1
+ bl L$0953,%r0
+ stw %r28,0(%r5) ;# 6546 reload_outsi+2/6
+ comb,= %r28,%r4,L$0683 ;# 6560 bleu+1
+ sub %r6,%r4,%r19 ;# 6562 subsi3/1
+ addl %r28,%r19,%r6 ;# 6565 addsi3/1
+ sub %r12,%r4,%r19 ;# 6566 subsi3/1
+ comib,= 0,%r10,L$0693 ;# 6571 bleu+1
+ addl %r28,%r19,%r12 ;# 6569 addsi3/1
+ sub %r10,%r4,%r19 ;# 6572 subsi3/1
+ addl %r28,%r19,%r10 ;# 6575 addsi3/1
+L$0693
+ comib,= 0,%r8,L$0694 ;# 6578 bleu+1
+ sub %r8,%r4,%r19 ;# 6579 subsi3/1
+ addl %r28,%r19,%r8 ;# 6582 addsi3/1
+L$0694
+ comib,= 0,%r9,L$0683 ;# 6585 bleu+1
+ sub %r9,%r4,%r19 ;# 6586 subsi3/1
+ addl %r28,%r19,%r9 ;# 6589 addsi3/1
+L$0683
+ ldw 0(%r5),%r4 ;# 6490 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 6494 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 6491 subsi3/1
+ ldo 1(%r19),%r19 ;# 6492 addsi3/2
+ comb,<< %r20,%r19,L$0685
+ nop ;# 6496 bleu+1
+L$0684
+ ldi 26,%r19 ;# 6611 movqi+1/2
+ bl L$0043,%r0 ;# 6624 jump
+ stbs,ma %r19,1(%r6) ;# 6612 movqi+1/6
+L$0699
+ ldw 4(%r5),%r20 ;# 8183 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 8181 subsi3/1
+ ldo 1(%r19),%r19 ;# 8182 addsi3/2
+ comb,>>=,n %r20,%r19,L$0704 ;# 8184 bleu+1
+ ldil L'65536,%r3 ;# 8561 reload_outsi+2/3
+L$0705
+ comb,= %r3,%r20,L$0944 ;# 6654 bleu+1
+ zdep %r20,30,31,%r19 ;# 6664 ashlsi3+1
+ comb,>>= %r3,%r19,L$0710 ;# 6672 bleu+1
+ stw %r19,4(%r5) ;# 6666 reload_outsi+2/6
+ stw %r3,4(%r5) ;# 6675 reload_outsi+2/6
+L$0710
+ ldw 0(%r5),%r26 ;# 6682 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 6686 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 6684 reload_outsi+2/5
+ comiclr,<> 0,%r28,%r0 ;# 6694 bleu+1
+ bl L$0953,%r0
+ stw %r28,0(%r5) ;# 6690 reload_outsi+2/6
+ comb,= %r28,%r4,L$0703 ;# 6704 bleu+1
+ sub %r6,%r4,%r19 ;# 6706 subsi3/1
+ addl %r28,%r19,%r6 ;# 6709 addsi3/1
+ sub %r12,%r4,%r19 ;# 6710 subsi3/1
+ comib,= 0,%r10,L$0713 ;# 6715 bleu+1
+ addl %r28,%r19,%r12 ;# 6713 addsi3/1
+ sub %r10,%r4,%r19 ;# 6716 subsi3/1
+ addl %r28,%r19,%r10 ;# 6719 addsi3/1
+L$0713
+ comib,= 0,%r8,L$0714 ;# 6722 bleu+1
+ sub %r8,%r4,%r19 ;# 6723 subsi3/1
+ addl %r28,%r19,%r8 ;# 6726 addsi3/1
+L$0714
+ comib,= 0,%r9,L$0703 ;# 6729 bleu+1
+ sub %r9,%r4,%r19 ;# 6730 subsi3/1
+ addl %r28,%r19,%r9 ;# 6733 addsi3/1
+L$0703
+ ldw 0(%r5),%r4 ;# 6634 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 6638 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 6635 subsi3/1
+ ldo 1(%r19),%r19 ;# 6636 addsi3/2
+ comb,<< %r20,%r19,L$0705
+ nop ;# 6640 bleu+1
+L$0704
+ ldi 27,%r19 ;# 6755 movqi+1/2
+ bl L$0043,%r0 ;# 6768 jump
+ stbs,ma %r19,1(%r6) ;# 6756 movqi+1/6
+L$0719
+ ldw 4(%r5),%r20 ;# 8191 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 8189 subsi3/1
+ ldo 1(%r19),%r19 ;# 8190 addsi3/2
+ comb,>>=,n %r20,%r19,L$0724 ;# 8192 bleu+1
+ ldil L'65536,%r3 ;# 8559 reload_outsi+2/3
+L$0725
+ comb,= %r3,%r20,L$0944 ;# 6798 bleu+1
+ zdep %r20,30,31,%r19 ;# 6808 ashlsi3+1
+ comb,>>= %r3,%r19,L$0730 ;# 6816 bleu+1
+ stw %r19,4(%r5) ;# 6810 reload_outsi+2/6
+ stw %r3,4(%r5) ;# 6819 reload_outsi+2/6
+L$0730
+ ldw 0(%r5),%r26 ;# 6826 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 6830 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 6828 reload_outsi+2/5
+ comiclr,<> 0,%r28,%r0 ;# 6838 bleu+1
+ bl L$0953,%r0
+ stw %r28,0(%r5) ;# 6834 reload_outsi+2/6
+ comb,= %r28,%r4,L$0723 ;# 6848 bleu+1
+ sub %r6,%r4,%r19 ;# 6850 subsi3/1
+ addl %r28,%r19,%r6 ;# 6853 addsi3/1
+ sub %r12,%r4,%r19 ;# 6854 subsi3/1
+ comib,= 0,%r10,L$0733 ;# 6859 bleu+1
+ addl %r28,%r19,%r12 ;# 6857 addsi3/1
+ sub %r10,%r4,%r19 ;# 6860 subsi3/1
+ addl %r28,%r19,%r10 ;# 6863 addsi3/1
+L$0733
+ comib,= 0,%r8,L$0734 ;# 6866 bleu+1
+ sub %r8,%r4,%r19 ;# 6867 subsi3/1
+ addl %r28,%r19,%r8 ;# 6870 addsi3/1
+L$0734
+ comib,= 0,%r9,L$0723 ;# 6873 bleu+1
+ sub %r9,%r4,%r19 ;# 6874 subsi3/1
+ addl %r28,%r19,%r9 ;# 6877 addsi3/1
+L$0723
+ ldw 0(%r5),%r4 ;# 6778 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 6782 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 6779 subsi3/1
+ ldo 1(%r19),%r19 ;# 6780 addsi3/2
+ comb,<< %r20,%r19,L$0725
+ nop ;# 6784 bleu+1
+L$0724
+ ldi 28,%r19 ;# 6899 movqi+1/2
+ bl L$0043,%r0 ;# 6912 jump
+ stbs,ma %r19,1(%r6) ;# 6900 movqi+1/6
+L$0739
+ ldw 4(%r5),%r20 ;# 8199 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 8197 subsi3/1
+ ldo 1(%r19),%r19 ;# 8198 addsi3/2
+ comb,>>=,n %r20,%r19,L$0744 ;# 8200 bleu+1
+ ldil L'65536,%r3 ;# 8557 reload_outsi+2/3
+L$0745
+ comb,= %r3,%r20,L$0944 ;# 6942 bleu+1
+ zdep %r20,30,31,%r19 ;# 6952 ashlsi3+1
+ comb,>>= %r3,%r19,L$0750 ;# 6960 bleu+1
+ stw %r19,4(%r5) ;# 6954 reload_outsi+2/6
+ stw %r3,4(%r5) ;# 6963 reload_outsi+2/6
+L$0750
+ ldw 0(%r5),%r26 ;# 6970 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 6974 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 6972 reload_outsi+2/5
+ comiclr,<> 0,%r28,%r0 ;# 6982 bleu+1
+ bl L$0953,%r0
+ stw %r28,0(%r5) ;# 6978 reload_outsi+2/6
+ comb,= %r28,%r4,L$0743 ;# 6992 bleu+1
+ sub %r6,%r4,%r19 ;# 6994 subsi3/1
+ addl %r28,%r19,%r6 ;# 6997 addsi3/1
+ sub %r12,%r4,%r19 ;# 6998 subsi3/1
+ comib,= 0,%r10,L$0753 ;# 7003 bleu+1
+ addl %r28,%r19,%r12 ;# 7001 addsi3/1
+ sub %r10,%r4,%r19 ;# 7004 subsi3/1
+ addl %r28,%r19,%r10 ;# 7007 addsi3/1
+L$0753
+ comib,= 0,%r8,L$0754 ;# 7010 bleu+1
+ sub %r8,%r4,%r19 ;# 7011 subsi3/1
+ addl %r28,%r19,%r8 ;# 7014 addsi3/1
+L$0754
+ comib,= 0,%r9,L$0743 ;# 7017 bleu+1
+ sub %r9,%r4,%r19 ;# 7018 subsi3/1
+ addl %r28,%r19,%r9 ;# 7021 addsi3/1
+L$0743
+ ldw 0(%r5),%r4 ;# 6922 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 6926 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 6923 subsi3/1
+ ldo 1(%r19),%r19 ;# 6924 addsi3/2
+ comb,<< %r20,%r19,L$0745
+ nop ;# 6928 bleu+1
+L$0744
+ ldi 10,%r19 ;# 7043 movqi+1/2
+ bl L$0043,%r0 ;# 7056 jump
+ stbs,ma %r19,1(%r6) ;# 7044 movqi+1/6
+L$0759
+ ldw 4(%r5),%r20 ;# 8207 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 8205 subsi3/1
+ ldo 1(%r19),%r19 ;# 8206 addsi3/2
+ comb,>>=,n %r20,%r19,L$0764 ;# 8208 bleu+1
+ ldil L'65536,%r3 ;# 8555 reload_outsi+2/3
+L$0765
+ comb,= %r3,%r20,L$0944 ;# 7086 bleu+1
+ zdep %r20,30,31,%r19 ;# 7096 ashlsi3+1
+ comb,>>= %r3,%r19,L$0770 ;# 7104 bleu+1
+ stw %r19,4(%r5) ;# 7098 reload_outsi+2/6
+ stw %r3,4(%r5) ;# 7107 reload_outsi+2/6
+L$0770
+ ldw 0(%r5),%r26 ;# 7114 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 7118 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 7116 reload_outsi+2/5
+ comiclr,<> 0,%r28,%r0 ;# 7126 bleu+1
+ bl L$0953,%r0
+ stw %r28,0(%r5) ;# 7122 reload_outsi+2/6
+ comb,= %r28,%r4,L$0763 ;# 7136 bleu+1
+ sub %r6,%r4,%r19 ;# 7138 subsi3/1
+ addl %r28,%r19,%r6 ;# 7141 addsi3/1
+ sub %r12,%r4,%r19 ;# 7142 subsi3/1
+ comib,= 0,%r10,L$0773 ;# 7147 bleu+1
+ addl %r28,%r19,%r12 ;# 7145 addsi3/1
+ sub %r10,%r4,%r19 ;# 7148 subsi3/1
+ addl %r28,%r19,%r10 ;# 7151 addsi3/1
+L$0773
+ comib,= 0,%r8,L$0774 ;# 7154 bleu+1
+ sub %r8,%r4,%r19 ;# 7155 subsi3/1
+ addl %r28,%r19,%r8 ;# 7158 addsi3/1
+L$0774
+ comib,= 0,%r9,L$0763 ;# 7161 bleu+1
+ sub %r9,%r4,%r19 ;# 7162 subsi3/1
+ addl %r28,%r19,%r9 ;# 7165 addsi3/1
+L$0763
+ ldw 0(%r5),%r4 ;# 7066 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 7070 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 7067 subsi3/1
+ ldo 1(%r19),%r19 ;# 7068 addsi3/2
+ comb,<< %r20,%r19,L$0765
+ nop ;# 7072 bleu+1
+L$0764
+ ldi 11,%r19 ;# 7187 movqi+1/2
+ bl L$0043,%r0 ;# 7200 jump
+ stbs,ma %r19,1(%r6) ;# 7188 movqi+1/6
+L$0787
+ bb,< %r15,17,L$0076 ;# 7216 bleu+3
+ ldo -48(%r7),%r19 ;# 7224 addsi3/2
+ ldw -260(%r30),%r1 ;# 8986 reload_outsi+2/5
+ extru %r19,31,8,%r3 ;# 7225 zero_extendqisi2/1
+ comb,<< %r1,%r3,L$0939 ;# 7230 bleu+1
+ ldo -312(%r30),%r26 ;# 7244 addsi3/2
+ .CALL ARGW0=GR,ARGW1=GR
+ bl group_in_compile_stack,%r2 ;# 7248 call_value_internal_symref
+ copy %r3,%r25 ;# 7246 reload_outsi+2/1
+ extrs %r28,31,8,%r28 ;# 7251 extendqisi2
+ comib,<>,n 0,%r28,L$0076 ;# 7253 bleu+1
+ ldw 0(%r5),%r4 ;# 8212 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 8215 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 8213 subsi3/1
+ ldo 2(%r19),%r19 ;# 8214 addsi3/2
+ comb,>>= %r20,%r19,L$0795 ;# 8216 bleu+1
+ copy %r6,%r8 ;# 7260 reload_outsi+2/1
+ ldil L'65536,%r7 ;# 8553 reload_outsi+2/3
+L$0796
+ comb,= %r7,%r20,L$0944 ;# 7288 bleu+1
+ zdep %r20,30,31,%r19 ;# 7298 ashlsi3+1
+ comb,>>= %r7,%r19,L$0801 ;# 7306 bleu+1
+ stw %r19,4(%r5) ;# 7300 reload_outsi+2/6
+ stw %r7,4(%r5) ;# 7309 reload_outsi+2/6
+L$0801
+ ldw 0(%r5),%r26 ;# 7316 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 7320 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 7318 reload_outsi+2/5
+ comiclr,<> 0,%r28,%r0 ;# 7328 bleu+1
+ bl L$0953,%r0
+ stw %r28,0(%r5) ;# 7324 reload_outsi+2/6
+ comb,= %r28,%r4,L$0794 ;# 7338 bleu+1
+ sub %r6,%r4,%r19 ;# 7340 subsi3/1
+ addl %r28,%r19,%r6 ;# 7343 addsi3/1
+ sub %r12,%r4,%r19 ;# 7344 subsi3/1
+ comib,= 0,%r10,L$0804 ;# 7349 bleu+1
+ addl %r28,%r19,%r12 ;# 7347 addsi3/1
+ sub %r10,%r4,%r19 ;# 7350 subsi3/1
+ addl %r28,%r19,%r10 ;# 7353 addsi3/1
+L$0804
+ comib,= 0,%r8,L$0805 ;# 7356 bleu+1
+ sub %r8,%r4,%r19 ;# 7357 subsi3/1
+ addl %r28,%r19,%r8 ;# 7360 addsi3/1
+L$0805
+ comib,= 0,%r9,L$0794 ;# 7363 bleu+1
+ sub %r9,%r4,%r19 ;# 7364 subsi3/1
+ addl %r28,%r19,%r9 ;# 7367 addsi3/1
+L$0794
+ ldw 0(%r5),%r4 ;# 7268 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 7272 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 7269 subsi3/1
+ ldo 2(%r19),%r19 ;# 7270 addsi3/2
+ comb,<< %r20,%r19,L$0796
+ nop ;# 7274 bleu+1
+L$0795
+ ldi 7,%r19 ;# 7389 movqi+1/2
+ stbs,ma %r19,1(%r6) ;# 7390 movqi+1/6
+ bl L$0043,%r0 ;# 7405 jump
+ stbs,ma %r3,1(%r6) ;# 7393 movqi+1/6
+L$0811
+ bb,< %r15,30,L$0104
+ nop ;# 7414 bleu+3
+L$0397
+ comib,= 0,%r14,L$0815 ;# 7429 bleu+1
+ addl %r14,%r7,%r19 ;# 7430 addsi3/1
+ bl L$0816,%r0 ;# 7434 jump
+ ldb 0(%r19),%r19 ;# 7433 zero_extendqisi2/2
+L$0815
+ copy %r7,%r19 ;# 7438 reload_outsi+2/1
+L$0816
+ copy %r19,%r7 ;# 7441 reload_outsi+2/1
+L$0076
+ comib,=,n 0,%r9,L$0820 ;# 7460 bleu+1
+ ldb 0(%r9),%r20 ;# 7463 zero_extendqisi2/2
+ addl %r9,%r20,%r19 ;# 7464 addsi3/1
+ ldo 1(%r19),%r19 ;# 7465 addsi3/2
+ comb,<> %r6,%r19,L$0820 ;# 7467 bleu+1
+ ldi 255,%r19 ;# 7472 reload_outsi+2/2
+ comb,= %r19,%r20,L$0820 ;# 7474 bleu+1
+ ldw -296(%r30),%r21 ;# 7476 reload_outsi+2/5
+ ldb 0(%r21),%r19 ;# 7478 movqi+1/5
+ extrs %r19,31,8,%r20 ;# 7479 extendqisi2
+ ldi 42,%r19 ;# 7481 reload_outsi+2/2
+ comb,= %r19,%r20,L$0820 ;# 7483 bleu+1
+ ldi 94,%r19 ;# 7490 reload_outsi+2/2
+ comb,=,n %r19,%r20,L$0820 ;# 7492 bleu+1
+ bb,>= %r15,30,L$0821 ;# 7497 movsi-4
+ ldi 92,%r19 ;# 7504 reload_outsi+2/2
+ comb,<>,n %r19,%r20,L$0822 ;# 7506 bleu+1
+ ldb 1(%r21),%r19 ;# 7510 movqi+1/5
+ extrs %r19,31,8,%r20 ;# 7511 extendqisi2
+L$0821
+ ldi 43,%r19 ;# 7534 reload_outsi+2/2
+ comb,= %r19,%r20,L$0820 ;# 7536 bleu+1
+ ldi 63,%r19 ;# 7543 reload_outsi+2/2
+ comb,=,n %r19,%r20,L$0820 ;# 7545 bleu+1
+L$0822
+ bb,>=,n %r15,22,L$0819 ;# 7553 movsi-4
+ bb,>= %r15,19,L$0823 ;# 7558 movsi-4
+ ldw -296(%r30),%r19 ;# 7560 reload_outsi+2/5
+ ldb 0(%r19),%r19 ;# 7562 movqi+1/5
+ ldi 123,%r20 ;# 7565 reload_outsi+2/2
+ extrs %r19,31,8,%r19 ;# 7563 extendqisi2
+ comb,=,n %r20,%r19,L$0820 ;# 7567 bleu+1
+ ldw 0(%r5),%r4 ;# 8228 reload_outsi+2/5
+ bl,n L$1177,%r0 ;# 7568 jump
+L$0823
+ ldw -296(%r30),%r21 ;# 7572 reload_outsi+2/5
+ ldb 0(%r21),%r19 ;# 7574 movqi+1/5
+ ldi 92,%r20 ;# 7577 reload_outsi+2/2
+ extrs %r19,31,8,%r19 ;# 7575 extendqisi2
+ comb,<>,n %r20,%r19,L$0819 ;# 7579 bleu+1
+ ldb 1(%r21),%r19 ;# 7583 movqi+1/5
+ ldi 123,%r20 ;# 7586 reload_outsi+2/2
+ extrs %r19,31,8,%r19 ;# 7584 extendqisi2
+ comb,<>,n %r20,%r19,L$0819 ;# 7588 bleu+1
+L$0820
+ ldw 0(%r5),%r4 ;# 8220 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 8223 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 8221 subsi3/1
+ ldo 2(%r19),%r19 ;# 8222 addsi3/2
+ comb,>>= %r20,%r19,L$0829 ;# 8224 bleu+1
+ copy %r6,%r8 ;# 7596 reload_outsi+2/1
+ ldil L'65536,%r3 ;# 8551 reload_outsi+2/3
+L$0830
+ comb,= %r3,%r20,L$0944 ;# 7624 bleu+1
+ zdep %r20,30,31,%r19 ;# 7634 ashlsi3+1
+ comb,>>= %r3,%r19,L$0835 ;# 7642 bleu+1
+ stw %r19,4(%r5) ;# 7636 reload_outsi+2/6
+ stw %r3,4(%r5) ;# 7645 reload_outsi+2/6
+L$0835
+ ldw 0(%r5),%r26 ;# 7652 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 7656 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 7654 reload_outsi+2/5
+ comiclr,<> 0,%r28,%r0 ;# 7664 bleu+1
+ bl L$0953,%r0
+ stw %r28,0(%r5) ;# 7660 reload_outsi+2/6
+ comb,= %r28,%r4,L$0828 ;# 7674 bleu+1
+ sub %r6,%r4,%r19 ;# 7676 subsi3/1
+ addl %r28,%r19,%r6 ;# 7679 addsi3/1
+ sub %r12,%r4,%r19 ;# 7680 subsi3/1
+ comib,= 0,%r10,L$0838 ;# 7685 bleu+1
+ addl %r28,%r19,%r12 ;# 7683 addsi3/1
+ sub %r10,%r4,%r19 ;# 7686 subsi3/1
+ addl %r28,%r19,%r10 ;# 7689 addsi3/1
+L$0838
+ comib,= 0,%r8,L$0839 ;# 7692 bleu+1
+ sub %r8,%r4,%r19 ;# 7693 subsi3/1
+ addl %r28,%r19,%r8 ;# 7696 addsi3/1
+L$0839
+ comib,= 0,%r9,L$0828 ;# 7699 bleu+1
+ sub %r9,%r4,%r19 ;# 7700 subsi3/1
+ addl %r28,%r19,%r9 ;# 7703 addsi3/1
+L$0828
+ ldw 0(%r5),%r4 ;# 7604 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 7608 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 7605 subsi3/1
+ ldo 2(%r19),%r19 ;# 7606 addsi3/2
+ comb,<< %r20,%r19,L$0830
+ nop ;# 7610 bleu+1
+L$0829
+ ldi 1,%r19 ;# 7725 movqi+1/2
+ stbs,ma %r19,1(%r6) ;# 7726 movqi+1/6
+ stbs,ma %r0,1(%r6) ;# 7729 movqi+1/6
+ ldo -1(%r6),%r9 ;# 7741 addsi3/2
+L$0819
+ ldw 0(%r5),%r4 ;# 8228 reload_outsi+2/5
+L$1177
+ ldw 4(%r5),%r20 ;# 8231 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 8229 subsi3/1
+ ldo 1(%r19),%r19 ;# 8230 addsi3/2
+ comb,>>=,n %r20,%r19,L$0848 ;# 8232 bleu+1
+ ldil L'65536,%r3 ;# 8549 reload_outsi+2/3
+L$0849
+ comb,= %r3,%r20,L$0944 ;# 7771 bleu+1
+ zdep %r20,30,31,%r19 ;# 7781 ashlsi3+1
+ comb,>>= %r3,%r19,L$0854 ;# 7789 bleu+1
+ stw %r19,4(%r5) ;# 7783 reload_outsi+2/6
+ stw %r3,4(%r5) ;# 7792 reload_outsi+2/6
+L$0854
+ ldw 0(%r5),%r26 ;# 7799 reload_outsi+2/5
+ .CALL ARGW0=GR,ARGW1=GR
+ bl realloc,%r2 ;# 7803 call_value_internal_symref
+ ldw 4(%r5),%r25 ;# 7801 reload_outsi+2/5
+ comiclr,<> 0,%r28,%r0 ;# 7811 bleu+1
+ bl L$0953,%r0
+ stw %r28,0(%r5) ;# 7807 reload_outsi+2/6
+ comb,= %r28,%r4,L$0847 ;# 7821 bleu+1
+ sub %r6,%r4,%r19 ;# 7823 subsi3/1
+ addl %r28,%r19,%r6 ;# 7826 addsi3/1
+ sub %r12,%r4,%r19 ;# 7827 subsi3/1
+ comib,= 0,%r10,L$0857 ;# 7832 bleu+1
+ addl %r28,%r19,%r12 ;# 7830 addsi3/1
+ sub %r10,%r4,%r19 ;# 7833 subsi3/1
+ addl %r28,%r19,%r10 ;# 7836 addsi3/1
+L$0857
+ comib,= 0,%r8,L$0858 ;# 7839 bleu+1
+ sub %r8,%r4,%r19 ;# 7840 subsi3/1
+ addl %r28,%r19,%r8 ;# 7843 addsi3/1
+L$0858
+ comib,= 0,%r9,L$0847 ;# 7846 bleu+1
+ sub %r9,%r4,%r19 ;# 7847 subsi3/1
+ addl %r28,%r19,%r9 ;# 7850 addsi3/1
+L$0847
+ ldw 0(%r5),%r4 ;# 7751 reload_outsi+2/5
+ ldw 4(%r5),%r20 ;# 7755 reload_outsi+2/5
+ sub %r6,%r4,%r19 ;# 7752 subsi3/1
+ ldo 1(%r19),%r19 ;# 7753 addsi3/2
+ comb,<< %r20,%r19,L$0849
+ nop ;# 7757 bleu+1
+L$0848
+ stbs,ma %r7,1(%r6) ;# 7872 movqi+1/6
+ ldb 0(%r9),%r19 ;# 7885 movqi+1/5
+ ldo 1(%r19),%r19 ;# 7888 addsi3/2
+ stb %r19,0(%r9) ;# 7890 movqi+1/6
+L$0043
+ ldw -296(%r30),%r19 ;# 2328 reload_outsi+2/5
+L$1161
+ comclr,= %r16,%r19,%r0 ;# 258 bleu+1
+ bl L$1178,%r0
+ ldw -296(%r30),%r19 ;# 2334 reload_outsi+2/5
+L$0044
+ comib,= 0,%r10,L$0865 ;# 7913 bleu+1
+ ldi 13,%r26 ;# 7918 reload_outsi+2/2
+ copy %r10,%r25 ;# 7920 reload_outsi+2/1
+ sub %r6,%r25,%r24 ;# 7915 subsi3/1
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR
+ bl store_op1,%r2 ;# 7924 call_internal_symref
+ ldo -3(%r24),%r24 ;# 7922 addsi3/2
+L$0865
+ ldw -304(%r30),%r19 ;# 7928 reload_outsi+2/5
+ comib,<>,n 0,%r19,L$0866 ;# 7930 bleu+1
+ .CALL ARGW0=GR
+ bl free,%r2 ;# 7946 call_internal_symref
+ ldw -312(%r30),%r26 ;# 7944 reload_outsi+2/5
+ ldw 0(%r5),%r19 ;# 7949 reload_outsi+2/5
+ ldi 0,%r28 ;# 7955 reload_outsi+2/2
+ sub %r6,%r19,%r19 ;# 7950 subsi3/1
+ bl L$0867,%r0 ;# 7957 jump
+ stw %r19,8(%r5) ;# 7952 reload_outsi+2/6
+L$0895
+ .CALL ARGW0=GR
+ bl free,%r2 ;# 2269 call_internal_symref
+ ldw -312(%r30),%r26 ;# 2267 reload_outsi+2/5
+ bl L$0867,%r0 ;# 2273 jump
+ ldi 11,%r28 ;# 2271 reload_outsi+2/2
+L$0900
+ .CALL ARGW0=GR
+ bl free,%r2 ;# 3161 call_internal_symref
+ ldw -312(%r30),%r26 ;# 3159 reload_outsi+2/5
+ bl L$0867,%r0 ;# 3165 jump
+ ldi 4,%r28 ;# 3163 reload_outsi+2/2
+L$0902
+ .CALL ARGW0=GR
+ bl free,%r2 ;# 3218 call_internal_symref
+ ldw -312(%r30),%r26 ;# 3216 reload_outsi+2/5
+ bl L$0867,%r0 ;# 3222 jump
+ ldi 7,%r28 ;# 3220 reload_outsi+2/2
+L$0903
+ .CALL ARGW0=GR
+ bl free,%r2 ;# 3803 call_internal_symref
+ ldw -312(%r30),%r26 ;# 3801 reload_outsi+2/5
+ bl L$0867,%r0 ;# 3807 jump
+ ldi 5,%r28 ;# 3805 reload_outsi+2/2
+L$0915
+ .CALL ARGW0=GR
+ bl free,%r2 ;# 5461 call_internal_symref
+ ldw -312(%r30),%r26 ;# 5459 reload_outsi+2/5
+ bl L$0867,%r0 ;# 5465 jump
+ ldi 9,%r28 ;# 5463 reload_outsi+2/2
+L$0917
+ .CALL ARGW0=GR
+ bl free,%r2 ;# 5557 call_internal_symref
+ ldw -312(%r30),%r26 ;# 5555 reload_outsi+2/5
+ bl L$0867,%r0 ;# 5561 jump
+ ldi 13,%r28 ;# 5559 reload_outsi+2/2
+L$0922
+ bl L$0867,%r0 ;# 5983 jump
+ ldi 14,%r28 ;# 5981 reload_outsi+2/2
+L$0939
+ .CALL ARGW0=GR
+ bl free,%r2 ;# 7235 call_internal_symref
+ ldw -312(%r30),%r26 ;# 7233 reload_outsi+2/5
+ bl L$0867,%r0 ;# 7239 jump
+ ldi 6,%r28 ;# 7237 reload_outsi+2/2
+L$0944
+ bl L$0867,%r0 ;# 7775 jump
+ ldi 15,%r28 ;# 7773 reload_outsi+2/2
+L$0866
+ .CALL ARGW0=GR
+ bl free,%r2 ;# 7935 call_internal_symref
+ ldw -312(%r30),%r26 ;# 7933 reload_outsi+2/5
+ ldi 8,%r28 ;# 7937 reload_outsi+2/2
+L$0867
+ ldw -340(%r30),%r2 ;# 9026 reload_outsi+2/5
+ ldw -168(%r30),%r18 ;# 9028 reload_outsi+2/5
+ ldw -164(%r30),%r17 ;# 9030 reload_outsi+2/5
+ ldw -160(%r30),%r16 ;# 9032 reload_outsi+2/5
+ ldw -156(%r30),%r15 ;# 9034 reload_outsi+2/5
+ ldw -152(%r30),%r14 ;# 9036 reload_outsi+2/5
+ ldw -148(%r30),%r13 ;# 9038 reload_outsi+2/5
+ ldw -144(%r30),%r12 ;# 9040 reload_outsi+2/5
+ ldw -140(%r30),%r11 ;# 9042 reload_outsi+2/5
+ ldw -136(%r30),%r10 ;# 9044 reload_outsi+2/5
+ ldw -132(%r30),%r9 ;# 9046 reload_outsi+2/5
+ ldw -128(%r30),%r8 ;# 9048 reload_outsi+2/5
+ ldw -124(%r30),%r7 ;# 9050 reload_outsi+2/5
+ ldw -120(%r30),%r6 ;# 9052 reload_outsi+2/5
+ ldw -116(%r30),%r5 ;# 9054 reload_outsi+2/5
+ ldw -112(%r30),%r4 ;# 9056 reload_outsi+2/5
+ ldw -108(%r30),%r3 ;# 9058 reload_outsi+2/5
+ bv %r0(%r2) ;# 9061 return_internal
+ ldo -320(%r30),%r30 ;# 9060 addsi3/2
+ .EXIT
+ .PROCEND
+ .SPACE $PRIVATE$
+ .SUBSPA $BSS$
+
+ .align 1
+re_syntax_table
+ .block 256
diff --git a/gas/testsuite/gas/hppa/unsorted/common.s b/gas/testsuite/gas/hppa/unsorted/common.s
new file mode 100644
index 0000000000..d92b0cba70
--- /dev/null
+++ b/gas/testsuite/gas/hppa/unsorted/common.s
@@ -0,0 +1,8 @@
+ .text
+text_symbol:
+ .long 1
+ .long external_symbol
+ .data
+data_symbol:
+ .long 2
+common_symbol .comm 4
diff --git a/gas/testsuite/gas/hppa/unsorted/fragbug.s b/gas/testsuite/gas/hppa/unsorted/fragbug.s
new file mode 100644
index 0000000000..57341937e7
--- /dev/null
+++ b/gas/testsuite/gas/hppa/unsorted/fragbug.s
@@ -0,0 +1,3 @@
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+ nop
diff --git a/gas/testsuite/gas/hppa/unsorted/globalbug.s b/gas/testsuite/gas/hppa/unsorted/globalbug.s
new file mode 100644
index 0000000000..d0f05f64c0
--- /dev/null
+++ b/gas/testsuite/gas/hppa/unsorted/globalbug.s
@@ -0,0 +1,16 @@
+
+ .space $PRIVATE$
+ .subspa $GLOBAL$
+ .export $global$
+$global$
+ .space $TEXT$
+ .subspa $CODE$
+
+ .proc
+ .callinfo
+ivaaddr
+ nop
+ nop
+ addil L%ivaaddr-$global$,%dp
+ ldo R%ivaaddr-$global$(%r1),%r19
+ .procend
diff --git a/gas/testsuite/gas/hppa/unsorted/importbug.s b/gas/testsuite/gas/hppa/unsorted/importbug.s
new file mode 100644
index 0000000000..104afb6f26
--- /dev/null
+++ b/gas/testsuite/gas/hppa/unsorted/importbug.s
@@ -0,0 +1,42 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .IMPORT $global$,DATA
+ .IMPORT $$dyncall,MILLICODE
+; gcc_compiled.:
+ .EXPORT foo,DATA
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$
+
+ .align 4
+foo:
+ .word 0
+ .IMPORT __main,CODE
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+ .EXPORT main,CODE
+ .EXPORT main,ENTRY,PRIV_LEV=3,RTNVAL=GR
+main:
+ .PROC
+ .CALLINFO FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
+ .ENTRY
+ .import foo
+ stw %r2,-20(0,%r30)
+ copy %r3,%r1
+ copy %r30,%r3
+ stwm %r1,64(%r30)
+ .CALL
+ bl __main,%r2
+ nop
+L$0001:
+ ldw -20(%r3),%r2
+ ldo 64(%r3),%r30
+ ldwm -64(%r30),%r3
+ bv,n %r0(%r2)
+ .EXIT
+ .PROCEND
diff --git a/gas/testsuite/gas/hppa/unsorted/labeldiffs.s b/gas/testsuite/gas/hppa/unsorted/labeldiffs.s
new file mode 100644
index 0000000000..6ee66f9735
--- /dev/null
+++ b/gas/testsuite/gas/hppa/unsorted/labeldiffs.s
@@ -0,0 +1,40 @@
+; Should check to make sure something useful gets put on those .word
+; statements.
+ .space $TEXT$
+ .subspa $CODE$
+
+ .align 8
+ .export icode,data
+icode:
+ .proc
+ .callinfo frame=0,no_calls
+ .entry
+ bv,n %r0(%r2)
+ .exit
+ nop
+ .procend
+
+ ;
+ ; FIRST, argv array of pointers to args, 1st is same as path.
+ ;
+ .align 8
+ic_argv:
+ .word ic_argv1-icode ; second, pointer to 1st argument
+ .word ic_path-icode ; first, pointer to init path
+ .word 0 ; fourth, NULL argv terminator (pad)
+ .word 0 ; third, NULL argv terminator
+
+ic_path:
+ .blockz 4096 ; must be multiple of 4 bytes
+ .word 0 ; in case full string is used
+ .word 0 ; this will be the string terminator
+
+ic_argv1:
+ .blockz 4096 ; must be multiple of 4 bytes
+ .word 0 ; in case full string is used
+ .word 0 ; this will be the string terminator
+
+ .export szicode,data
+szicode:
+ .word szicode-icode
+ .word 0 ; must have at least one filler at end
diff --git a/gas/testsuite/gas/hppa/unsorted/locallabel.s b/gas/testsuite/gas/hppa/unsorted/locallabel.s
new file mode 100644
index 0000000000..7d5721edaa
--- /dev/null
+++ b/gas/testsuite/gas/hppa/unsorted/locallabel.s
@@ -0,0 +1,15 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+ .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+
+ .align 4
+
+Label:
+L$01234:
+
diff --git a/gas/testsuite/gas/hppa/unsorted/ss_align.s b/gas/testsuite/gas/hppa/unsorted/ss_align.s
new file mode 100644
index 0000000000..6e98eb2e69
--- /dev/null
+++ b/gas/testsuite/gas/hppa/unsorted/ss_align.s
@@ -0,0 +1,12 @@
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$,QUAD=1,ALIGN=64,ACCESS=31
+ .SPACE $TEXT$
+ .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+ .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .IMPORT $global$,DATA
+ .IMPORT $$dyncall,MILLICODE
+; gcc_compiled.:
+ .SPACE $PRIVATE$
+ .SUBSPA $DATA$
+sym1: .WORD 2
+
diff --git a/gas/testsuite/gas/hppa/unsorted/unsorted.exp b/gas/testsuite/gas/hppa/unsorted/unsorted.exp
new file mode 100644
index 0000000000..31300c70b2
--- /dev/null
+++ b/gas/testsuite/gas/hppa/unsorted/unsorted.exp
@@ -0,0 +1,258 @@
+# Copyright (C) 1993, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, 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 more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# DejaGnu@cygnus.com
+
+# Written by the Center for Software Science at the University of Utah
+# and by Cygnus Support.
+
+proc do_subspace_align_test {} {
+ set testname "ss_align.s: Test subspace alignment (part 2)"
+ set x 0
+
+ if [gas_test_old "ss_align.s" "" "subspace alignment (part 1)"] then {
+ objdump_start_no_subdir "a.out" "-h"
+
+ # Check the headers for the correct alignment value for the
+ # .data section (elf) or the $DATA$ subspace (som).
+ if [istarget hppa*-*-*elf*] then {
+ while 1 {
+ expect {
+ -re "data\[^\n\]* 2..6\[^\n\]*\n" { set x 1 }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+ } else {
+ while 1 {
+ expect {
+ -re "DATA\[^\n\]* 2..6\[^\n\]*\n" { set x 1 }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ objdump_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==1] then { pass $testname } else { fail $testname }
+ }
+}
+
+proc do_local_label_test {} {
+ set testname "locallabel.s: Elimination of local labels (part 2)"
+ set x 0
+
+ if [gas_test_old "locallabel.s" "" "Elimination of local labels (part1)"] {
+ objdump_start_no_subdir "a.out" "-t"
+
+ while 1 {
+ expect {
+ -re "^00000000\[^\n\]*Label\[^\n\]*\n" { set x 1 }
+ -re "^00000000\[^\n\]*L\$01234\[^\n\]*\n" { set x 0 }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ objdump_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==1] then { pass $testname } else { fail $testname }
+ }
+}
+
+proc do_frchain_test {} {
+ set testname "fragbug.s: Test bug in frag chaining (part 2)"
+ set x 0
+
+ if [gas_test_old "fragbug.s" "" "Test bug in frag chaining (part1)"] {
+ objdump_start_no_subdir "a.out" "--prefix-addresses -d"
+
+ while 1 {
+ expect {
+ -re "^0x00000000\[^\n\]*nop\[^\n\]*\n" { set x 1 }
+ -re "^0x00000004\[^\n\]*nop\[^\n\]*\n" { set x 0 }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ objdump_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==1] then { pass $testname } else { fail $testname }
+ }
+}
+
+proc do_align3_test {} {
+ set testname "align3.s: Test for alignment bug when switching subspaces (part2)"
+ set x 0
+
+ if [gas_test_old "align3.s" "" "Test for alignment bug when switching subspaces (part1)"] {
+ objdump_start_no_subdir "a.out" "--prefix-addresses -d"
+
+ while 1 {
+ expect {
+ -re "\[^\n\]* <main> nop\[^\n\]*\n" { set x 1 }
+ -re "\[^\n\]* <.*end_main> nop\[^\n\]*\n" { set x 1 }
+ -re "\[^\n\]* <main+.*> nop\[^\n\]*\n" { set x 0 }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ objdump_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==1] then { pass $testname } else { fail $testname }
+ }
+}
+
+proc do_align4_test {} {
+ set testname "align4.s: More subspace alignment tests (part2)"
+ set x 0
+
+ if [istarget hppa*-*-*elf*] then {
+ return
+ }
+
+ if [gas_test_old "align4.s" "" "More subspace alignment tests (part1)"] {
+ objdump_start_no_subdir "a.out" "-h"
+
+ while 1 {
+ expect {
+ -re "\[^\n\]*MILLICODE\[^\n\]*2..6\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "\[^\n\]*YABBA\[^\n\]*2..3\[^\n\]*\n"
+ { set x [expr $x+1] }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ objdump_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==2] then { pass $testname } else { fail $testname }
+ }
+}
+
+proc do_import_test {} {
+ set testname "importbug.s: Test for bug in .import directive (part2)"
+ set x 0
+
+ if [gas_test_old "importbug.s" "" "Test for bug in .import directive (part1)"] {
+ objdump_start_no_subdir "a.out" "--syms"
+
+ while 1 {
+ expect {
+ -re "\[^\n\]*.DATA..foo\[^\n\]*\n" { set x 1 }
+ -re "\[^\n\]*.data.*foo\[^\n\]*\n" { set x 1 }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ objdump_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==1] then { pass $testname } else { fail $testname }
+ }
+}
+
+proc do_common_test {} {
+ set testname "common.s: Test for bug in .comm handling (part2)"
+ set x 0
+
+ if [gas_test_old "common.s" "" "Test for bug in .comm handling (part1)"] {
+ objdump_start_no_subdir "a.out" "--syms"
+
+ while 1 {
+ expect {
+ -re "\[^\n\]*.COM.*common_symbol\[^\n\]*\n" { set x 1 }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ objdump_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==1] then { pass $testname } else { fail $testname }
+ }
+}
+
+if [istarget hppa*-*-*] then {
+ # Make sure subspace alignment requests from the subspace directives
+ # are honored
+ do_subspace_align_test
+
+ # Make sure the correct labels end up in the symbol table
+ do_local_label_test
+
+ # GAS-1.36 choked on this file.
+ gas_test "labeldiffs.s" "" "" "Difference of labels"
+
+ # Test a recent bug where frag chaining wasn't working correctly.
+ do_frchain_test
+
+ # Test bug where switching between subspaces creates bogus alignments
+ do_align3_test
+
+ # Test bug where switching between subspaces creates bogus alignments
+ do_align4_test
+
+ # Test a problem where $global$ is defined, then used within the
+ # same source file.
+ setup_xfail hppa*-*-*
+ gas_test "globalbug.s" "" "" "Use \$global\$ in file which defines it"
+
+ # Test that importing a defined symbol doesn't screw up the symbol's
+ # space/subspace.
+ do_import_test
+
+ # Test for a buglet in the handling of common symbols
+ do_common_test
+
+ # Test for an off-by-2 bug in range check for conditional branches
+ gas_test_error "brlenbug.s" "" "Check for error(s) in branch length"
+
+}
+
diff --git a/gas/testsuite/gas/i386/amd.d b/gas/testsuite/gas/i386/amd.d
new file mode 100644
index 0000000000..2fe8b0e8b2
--- /dev/null
+++ b/gas/testsuite/gas/i386/amd.d
@@ -0,0 +1,37 @@
+#objdump: -dw
+#name: i386 amd
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+000 <.text>:
+ 0: 0f 0d 03 [ ]*prefetch \(%ebx\)
+ 3: 0f 0d 0c 75 00 10 00 00 [ ]*prefetchw 0x1000\(,%esi,2\)
+ b: 0f 0e [ ]*femms
+ d: 0f 0f 00 bf [ ]*pavgusb \(%eax\),%mm0
+ 11: 0f 0f 48 02 1d [ ]*pf2id 0x2\(%eax\),%mm1
+ 16: 0f 0f 90 00 01 00 00 ae [ ]*pfacc 0x100\(%eax\),%mm2
+ 1e: 0f 0f 1e 9e [ ]*pfadd \(%esi\),%mm3
+ 22: 0f 0f 66 02 b0 [ ]*pfcmpeq 0x2\(%esi\),%mm4
+ 27: 0f 0f ae 90 90 00 00 90 [ ]*pfcmpge 0x9090\(%esi\),%mm5
+ 2f: 0f 0f 74 75 00 a0 [ ]*pfcmpgt 0x0\(%ebp,%esi,2\),%mm6
+ 35: 0f 0f 7c 75 02 a4 [ ]*pfmax 0x2\(%ebp,%esi,2\),%mm7
+ 3b: 0f 0f 84 75 90 90 90 90 94 [ ]*pfmin 0x90909090\(%ebp,%esi,2\),%mm0
+ 44: 0f 0f 0d 04 00 00 00 b4 [ ]*pfmul 0x4,%mm1
+ 4c: 2e 0f 0f 54 c3 07 96 [ ]*pfrcp %cs:0x7\(%ebx,%eax,8\),%mm2
+ 53: 0f 0f d8 a6 [ ]*pfrcpit1 %mm0,%mm3
+ 57: 0f 0f e1 b6 [ ]*pfrcpit2 %mm1,%mm4
+ 5b: 0f 0f ea a7 [ ]*pfrsqit1 %mm2,%mm5
+ 5f: 0f 0f f3 97 [ ]*pfrsqrt %mm3,%mm6
+ 63: 0f 0f fc 9a [ ]*pfsub %mm4,%mm7
+ 67: 0f 0f c5 aa [ ]*pfsubr %mm5,%mm0
+ 6b: 0f 0f ce 0d [ ]*pi2fd %mm6,%mm1
+ 6f: 0f 0f d7 b7 [ ]*pfmulhrw %mm7,%mm2
+ 73: 2e 0f [ ]*\(bad\)
+ 75: 0f 54 [ ]*\(bad\)
+ 77: c3 [ ]*ret
+ 78: 07 [ ]*pop %es
+ 79: c3 [ ]*ret
+ 7a: 90 [ ]*nop
+ 7b: 90 [ ]*nop
diff --git a/gas/testsuite/gas/i386/amd.s b/gas/testsuite/gas/i386/amd.s
new file mode 100644
index 0000000000..5e4d581f08
--- /dev/null
+++ b/gas/testsuite/gas/i386/amd.s
@@ -0,0 +1,33 @@
+#AMD 3DNow! instructions
+
+.text
+ prefetch (%ebx)
+ prefetchw 0x1000(,%esi,2)
+ femms
+ pavgusb (%eax),%mm0
+ pf2id 2(%eax),%mm1
+ pfacc 0x100(%eax),%mm2
+ pfadd (%esi),%mm3
+ pfcmpeq 2(%esi),%mm4
+ pfcmpge 0x9090(%esi),%mm5
+ pfcmpgt (%ebp,%esi,2),%mm6
+ pfmax 2(%ebp,%esi,2),%mm7
+ pfmin 0x90909090(%ebp,%esi,2),%mm0
+ pfmul 4,%mm1
+ pfrcp %cs:7(%ebx,%eax,8),%mm2
+ pfrcpit1 %mm0,%mm3
+ pfrcpit2 %mm1,%mm4
+ pfrsqit1 %mm2,%mm5
+ pfrsqrt %mm3,%mm6
+ pfsub %mm4,%mm7
+ pfsubr %mm5,%mm0
+ pi2fd %mm6,%mm1
+ pmulhrw %mm7,%mm2
+
+# This is a 3DNow! instruction, with a prefix, that isn't quite right
+# Everything's good bar the opcode suffix
+.byte 0x2e, 0x0f, 0x0f, 0x54, 0xc3, 0x07, 0xc3
+
+# to make us insensitive to alignment
+ nop
+ nop
diff --git a/gas/testsuite/gas/i386/float.l b/gas/testsuite/gas/i386/float.l
new file mode 100644
index 0000000000..6d6cadd740
--- /dev/null
+++ b/gas/testsuite/gas/i386/float.l
@@ -0,0 +1,81 @@
+.*: Assembler messages:
+.*:3: Warning:.*faddp.*
+.*:14: Warning:.*fsubp.*
+.*:25: Warning:.*fsubrp.*
+.*:36: Warning:.*fmulp.*
+.*:47: Warning:.*fdivp.*
+.*:58: Warning:.*fdivrp.*
+ 1 [ ]*.psize 0
+ 2 [ ]*.text
+ 3 0000 DEC1 [ ]*fadd
+.*Warning:.*faddp.*
+ 4 0002 D8C3 [ ]*fadd %st\(3\)
+ 5 0004 D8C3 [ ]*fadd %st\(3\),%st
+ 6 0006 DCC3 [ ]*fadd %st,%st\(3\)
+ 7 0008 D803 [ ]*fadds \(%ebx\)
+ 8 000a DC03 [ ]*faddl \(%ebx\)
+ 9 000c DE03 [ ]*fiadds \(%ebx\)
+ 10 000e DA03 [ ]*fiaddl \(%ebx\)
+ 11 0010 DEC1 [ ]*faddp
+ 12 0012 DEC3 [ ]*faddp %st\(3\)
+ 13 0014 DEC3 [ ]*faddp %st,%st\(3\)
+ 14 0016 DEE1 [ ]*fsub
+.*Warning:.*fsubp.*
+ 15 0018 D8E3 [ ]*fsub %st\(3\)
+ 16 001a D8E3 [ ]*fsub %st\(3\),%st
+ 17 001c DCE3 [ ]*fsub %st,%st\(3\)
+ 18 001e D823 [ ]*fsubs \(%ebx\)
+ 19 0020 DC23 [ ]*fsubl \(%ebx\)
+ 20 0022 DE23 [ ]*fisubs \(%ebx\)
+ 21 0024 DA23 [ ]*fisubl \(%ebx\)
+ 22 0026 DEE1 [ ]*fsubp
+ 23 0028 DEE3 [ ]*fsubp %st\(3\)
+ 24 002a DEE3 [ ]*fsubp %st,%st\(3\)
+ 25 002c DEE9 [ ]*fsubr
+.*Warning:.*fsubrp.*
+ 26 002e D8EB [ ]*fsubr %st\(3\)
+ 27 0030 D8EB [ ]*fsubr %st\(3\),%st
+ 28 0032 DCEB [ ]*fsubr %st,%st\(3\)
+ 29 0034 D82B [ ]*fsubrs \(%ebx\)
+ 30 0036 DC2B [ ]*fsubrl \(%ebx\)
+ 31 0038 DE2B [ ]*fisubrs \(%ebx\)
+ 32 003a DA2B [ ]*fisubrl \(%ebx\)
+ 33 003c DEE9 [ ]*fsubrp
+ 34 003e DEEB [ ]*fsubrp %st\(3\)
+ 35 0040 DEEB [ ]*fsubrp %st,%st\(3\)
+ 36 0042 DEC9 [ ]*fmul
+.*Warning:.*fmulp.*
+ 37 0044 D8CB [ ]*fmul %st\(3\)
+ 38 0046 D8CB [ ]*fmul %st\(3\),%st
+ 39 0048 DCCB [ ]*fmul %st,%st\(3\)
+ 40 004a D80B [ ]*fmuls \(%ebx\)
+ 41 004c DC0B [ ]*fmull \(%ebx\)
+ 42 004e DE0B [ ]*fimuls \(%ebx\)
+ 43 0050 DA0B [ ]*fimull \(%ebx\)
+ 44 0052 DEC9 [ ]*fmulp
+ 45 0054 DECB [ ]*fmulp %st\(3\)
+ 46 0056 DECB [ ]*fmulp %st,%st\(3\)
+ 47 0058 DEF1 [ ]*fdiv
+.*Warning:.*fdivp.*
+ 48 005a D8F3 [ ]*fdiv %st\(3\)
+ 49 005c D8F3 [ ]*fdiv %st\(3\),%st
+ 50 005e DCF3 [ ]*fdiv %st,%st\(3\)
+ 51 0060 D833 [ ]*fdivs \(%ebx\)
+ 52 0062 DC33 [ ]*fdivl \(%ebx\)
+ 53 0064 DE33 [ ]*fidivs \(%ebx\)
+ 54 0066 DA33 [ ]*fidivl \(%ebx\)
+ 55 0068 DEF1 [ ]*fdivp
+ 56 006a DEF3 [ ]*fdivp %st\(3\)
+ 57 006c DEF3 [ ]*fdivp %st,%st\(3\)
+ 58 006e DEF9 [ ]*fdivr
+.*Warning:.*fdivrp.*
+ 59 0070 D8FB [ ]*fdivr %st\(3\)
+ 60 0072 D8FB [ ]*fdivr %st\(3\),%st
+ 61 0074 DCFB [ ]*fdivr %st,%st\(3\)
+ 62 0076 D83B [ ]*fdivrs \(%ebx\)
+ 63 0078 DC3B [ ]*fdivrl \(%ebx\)
+ 64 007a DE3B [ ]*fidivrs \(%ebx\)
+ 65 007c DA3B [ ]*fidivrl \(%ebx\)
+ 66 007e DEF9 [ ]*fdivrp
+ 67 0080 DEFB [ ]*fdivrp %st\(3\)
+ 68 0082 DEFB [ ]*fdivrp %st,%st\(3\)
diff --git a/gas/testsuite/gas/i386/float.s b/gas/testsuite/gas/i386/float.s
new file mode 100644
index 0000000000..6bb09f8b89
--- /dev/null
+++ b/gas/testsuite/gas/i386/float.s
@@ -0,0 +1,68 @@
+.psize 0
+.text
+ fadd
+ fadd %st(3)
+ fadd %st(3),%st
+ fadd %st,%st(3)
+ fadds (%ebx)
+ faddl (%ebx)
+ fiadds (%ebx)
+ fiaddl (%ebx)
+ faddp
+ faddp %st(3)
+ faddp %st,%st(3)
+ fsub
+ fsub %st(3)
+ fsub %st(3),%st
+ fsub %st,%st(3)
+ fsubs (%ebx)
+ fsubl (%ebx)
+ fisubs (%ebx)
+ fisubl (%ebx)
+ fsubp
+ fsubp %st(3)
+ fsubp %st,%st(3)
+ fsubr
+ fsubr %st(3)
+ fsubr %st(3),%st
+ fsubr %st,%st(3)
+ fsubrs (%ebx)
+ fsubrl (%ebx)
+ fisubrs (%ebx)
+ fisubrl (%ebx)
+ fsubrp
+ fsubrp %st(3)
+ fsubrp %st,%st(3)
+ fmul
+ fmul %st(3)
+ fmul %st(3),%st
+ fmul %st,%st(3)
+ fmuls (%ebx)
+ fmull (%ebx)
+ fimuls (%ebx)
+ fimull (%ebx)
+ fmulp
+ fmulp %st(3)
+ fmulp %st,%st(3)
+ fdiv
+ fdiv %st(3)
+ fdiv %st(3),%st
+ fdiv %st,%st(3)
+ fdivs (%ebx)
+ fdivl (%ebx)
+ fidivs (%ebx)
+ fidivl (%ebx)
+ fdivp
+ fdivp %st(3)
+ fdivp %st,%st(3)
+ fdivr
+ fdivr %st(3)
+ fdivr %st(3),%st
+ fdivr %st,%st(3)
+ fdivrs (%ebx)
+ fdivrl (%ebx)
+ fidivrs (%ebx)
+ fidivrl (%ebx)
+ fdivrp
+ fdivrp %st(3)
+ fdivrp %st,%st(3)
diff --git a/gas/testsuite/gas/i386/general.l b/gas/testsuite/gas/i386/general.l
new file mode 100644
index 0000000000..a4034471ea
--- /dev/null
+++ b/gas/testsuite/gas/i386/general.l
@@ -0,0 +1,205 @@
+.*: Assembler messages:
+.*:10: Warning:.*
+.*:12: Warning:.*
+.*:19: Warning:.*
+.*:22: Warning:.*
+.*:81: Warning:.*
+.*:82: Warning:.*
+.*:83: Warning:.*
+.*:84: Warning:.*
+.*:85: Warning:.*
+.*:86: Warning:.*
+.*:87: Warning:.*
+.*:88: Warning:.*
+.*:89: Warning:.*
+.*:90: Warning:.*
+.*:91: Warning:.*
+.*:92: Warning:.*
+.*:93: Warning:.*
+.*:94: Warning:.*
+.*:95: Warning:.*
+.*:96: Warning:.*
+.*:97: Warning:.*
+.*:98: Warning:.*
+.*:99: Warning:.*
+.*:100: Warning:.*
+.*:101: Warning:.*
+.*:135: Warning:.*
+ 1 .psize 0
+ 2 .text
+ 3 # test various segment reg insns
+ 4 0000 1E push %ds
+ 5 0001 1E pushl %ds
+ 6 0002 1F pop %ds
+ 7 0003 1F popl %ds
+ 8 0004 8CD8 mov %ds,%eax
+ 9 0006 8CD8 movl %ds,%eax
+ 10 0008 8CD8 movl %ds,%ax
+.*Warning:.*
+ 11 000a 8ED8 mov %eax,%ds
+ 12 000c 8ED8 movl %ax,%ds
+.*Warning:.*
+ 13 000e 8ED8 movl %eax,%ds
+ 14
+ 15 0010 661E pushw %ds
+ 16 0012 661F popw %ds
+ 17 0014 668CD8 mov %ds,%ax
+ 18 0017 668CD8 movw %ds,%ax
+ 19 001a 668CD8 movw %ds,%eax
+.*Warning:.*
+ 20 001d 8ED8 mov %ax,%ds
+ 21 001f 8ED8 movw %ax,%ds
+ 22 0021 8ED8 movw %eax,%ds
+.*Warning:.*
+ 23
+ 24 # test various pushes
+ 25 0023 6A0A pushl \$10
+ 26 0025 666A0A pushw \$10
+ 27 0028 6A0A push \$10
+ 28 002a 68E80300 00 pushl \$1000
+ 29 002f 6668E803 pushw \$1000
+ 30 0033 68E80300 00 push \$1000
+ 31 0038 FF355700 0000 pushl 1f
+ 32 003e 66FF3557 000000 pushw 1f
+ 33 0045 FF355700 0000 push 1f
+ 34 004b FFB30C00 0000 push \(1f-.\)\(%ebx\)
+ 35 0051 FF350600 0000 push 1f-.
+ 36 # these, and others like them should have no operand size prefix
+ 37 0057 0F00D1 1: lldt %cx
+ 38 005a 0F01F0 lmsw %ax
+ 39
+ 40 # Just to make sure these don't become illegal due to over-enthusiastic
+ 41 # register checking
+ 42 005d 660FBEF8 movsbw %al,%di
+ 43 0061 0FBEC8 movsbl %al,%ecx
+ 44 0064 0FBFC8 movswl %ax,%ecx
+ 45 0067 660FB6F8 movzbw %al,%di
+ 46 006b 0FB6C8 movzbl %al,%ecx
+ 47 006e 0FB7C8 movzwl %ax,%ecx
+ 48
+ 49 0071 EC in %dx,%al
+ 50 0072 66ED in %dx,%ax
+ 51 0074 ED in %dx,%eax
+ 52 0075 EC in \(%dx\),%al
+ 53 0076 66ED in \(%dx\),%ax
+ 54 0078 ED in \(%dx\),%eax
+ 55 0079 EC inb %dx,%al
+ 56 007a 66ED inw %dx,%ax
+ 57 007c ED inl %dx,%eax
+ 58 007d EC inb %dx
+ 59 007e 66ED inw %dx
+ 60 0080 ED inl %dx
+ 61 0081 E4FF inb \$255
+ 62 0083 66E502 inw \$2
+ 63 0086 E504 inl \$4
+ 64 0088 EF outl %eax,%dx
+ 65 0089 E62A out %al, \$42
+ 66 008b 66E50D in \$13, %ax
+ 67 # These are used in AIX.
+ 68 008e 66ED inw \(%dx\)
+ 69 0090 66EF outw \(%dx\)
+ 70
+ 71 0092 A4 movsb
+ 72 0093 66A7 cmpsw
+ 73 0095 AF scasl
+ 74 0096 D7 xlatb
+ 75 0097 2EA5 movsl %cs:\(%esi\),%es:\(%edi\)
+ 76 0099 0F9303 setae \(%ebx\)
+ 77 009c 0F9303 setaeb \(%ebx\)
+ 78 009f 0F93C0 setae %al
+ 79
+ 80 #these should give warnings
+ 81 00a2 0C01 orb \$1,%ax
+.*Warning:.*
+ 82 00a4 0C01 orb \$1,%eax
+.*Warning:.*
+ 83 00a6 80CB01 orb \$1,%bx
+.*Warning:.*
+ 84 00a9 80CB01 orb \$1,%ebx
+.*Warning:.*
+ 85 00ac D9C1 fldl %st\(1\)
+.*Warning:.*
+ 86 00ae DDD2 fstl %st\(2\)
+.*Warning:.*
+ 87 00b0 DDDB fstpl %st\(3\)
+.*Warning:.*
+ 88 00b2 D8D4 fcoml %st\(4\)
+.*Warning:.*
+ 89 00b4 D8DD fcompl %st\(5\)
+.*Warning:.*
+ 90 00b6 DEC1 faddp %st\(1\),%st
+.*Warning:.*
+ 91 00b8 DECA fmulp %st\(2\),%st
+.*Warning:.*
+ 92 00ba DEE3 fsubp %st\(3\),%st
+.*Warning:.*
+ 93 00bc DEEC fsubrp %st\(4\),%st
+.*Warning:.*
+ 94 00be DEF5 fdivp %st\(5\),%st
+.*Warning:.*
+ 95 00c0 DEFE fdivrp %st\(6\),%st
+.*Warning:.*
+ 96 00c2 DEC1 fadd
+.*Warning:.*
+ 97 00c4 DEE1 fsub
+.*Warning:.*
+ 98 00c6 DEC9 fmul
+.*Warning:.*
+ 99 00c8 DEF1 fdiv
+.*Warning:.*
+ 100 00ca DEE9 fsubr
+.*Warning:.*
+ 101 00cc DEF9 fdivr
+.*Warning:.*
+ 102 #these should all be legal
+ 103 00ce 0FA31556 341200 btl %edx, 0x123456
+ 104 00d5 0FA3D0 btl %edx, %eax
+ 105 00d8 0C01 orb \$1,%al
+ 106 00da 80CB01 orb \$1,%bl
+ 107 00dd A1110000 00 movl 17,%eax
+ 108 00e2 A1110000 00 mov 17,%eax
+ 109 00e7 66ED inw %dx,%ax
+ 110 00e9 ED inl %dx,%eax
+ 111 00ea 66ED inw \(%dx\),%ax
+ 112 00ec ED inl \(%dx\),%eax
+ 113 00ed EC in \(%dx\),%al
+ 114 00ee 66ED in \(%dx\),%ax
+ 115 00f0 ED in \(%dx\),%eax
+ 116 00f1 0FB61437 movzbl \(%edi,%esi\),%edx
+ 117 00f5 0FB6451C movzbl 28\(%ebp\),%eax
+ 118 00f9 0FB6C0 movzbl %al,%eax
+ 119 00fc 0FB6F1 movzbl %cl,%esi
+ 120 00ff 26D7 xlat %es:\(%ebx\)
+ 121 0101 D7 xlat
+ 122 0102 D7 xlatb
+ 123 0103 DDD8 1: fstp %st\(0\)
+ 124 0105 E2FC loop 1b
+ 125 0107 F6F1 divb %cl
+ 126 0109 66F7F1 divw %cx
+ 127 010c F7F1 divl %ecx
+ 128 010e F6F1 div %cl
+ 129 0110 66F7F1 div %cx
+ 130 0113 F7F1 div %ecx
+ 131 0115 F6F1 div %cl,%al
+ 132 0117 66F7F1 div %cx,%ax
+ 133 011a F7F1 div %ecx,%eax
+ 134 011c 8EDE mov %si,%ds
+ 135 011e 8EDE movl %si,%ds # warning here
+.*Warning:.*
+ 136 0120 1E pushl %ds
+ 137 0121 1E push %ds
+ 138 0122 A0000000 00 mov 0,%al
+ 139 0127 66A10000 0100 mov 0x10000,%ax
+ 140 012d 89C3 mov %eax,%ebx
+ 141 012f 9C pushf
+ 142 0130 9C pushfl
+ 143 0131 669C pushfw
+ 144 0133 9D popf
+ 145 0134 9D popfl
+ 146 0135 669D popfw
+ 147 0137 89341D00 000000 mov %esi,\(,%ebx,1\)
+ 148 013e 80250000 00007F andb \$~0x80,foo
+ 149
+ 150 # Force a good alignment.
+ 151 0145 0000 .word 0
+ 152 0147 00 .byte 0
diff --git a/gas/testsuite/gas/i386/general.s b/gas/testsuite/gas/i386/general.s
new file mode 100644
index 0000000000..d73f489cfd
--- /dev/null
+++ b/gas/testsuite/gas/i386/general.s
@@ -0,0 +1,152 @@
+.psize 0
+.text
+# test various segment reg insns
+ push %ds
+ pushl %ds
+ pop %ds
+ popl %ds
+ mov %ds,%eax
+ movl %ds,%eax
+ movl %ds,%ax
+ mov %eax,%ds
+ movl %ax,%ds
+ movl %eax,%ds
+
+ pushw %ds
+ popw %ds
+ mov %ds,%ax
+ movw %ds,%ax
+ movw %ds,%eax
+ mov %ax,%ds
+ movw %ax,%ds
+ movw %eax,%ds
+
+# test various pushes
+ pushl $10
+ pushw $10
+ push $10
+ pushl $1000
+ pushw $1000
+ push $1000
+ pushl 1f
+ pushw 1f
+ push 1f
+ push (1f-.)(%ebx)
+ push 1f-.
+# these, and others like them should have no operand size prefix
+1: lldt %cx
+ lmsw %ax
+
+# Just to make sure these don't become illegal due to over-enthusiastic
+# register checking
+ movsbw %al,%di
+ movsbl %al,%ecx
+ movswl %ax,%ecx
+ movzbw %al,%di
+ movzbl %al,%ecx
+ movzwl %ax,%ecx
+
+ in %dx,%al
+ in %dx,%ax
+ in %dx,%eax
+ in (%dx),%al
+ in (%dx),%ax
+ in (%dx),%eax
+ inb %dx,%al
+ inw %dx,%ax
+ inl %dx,%eax
+ inb %dx
+ inw %dx
+ inl %dx
+ inb $255
+ inw $2
+ inl $4
+ outl %eax,%dx
+ out %al, $42
+ in $13, %ax
+# These are used in AIX.
+ inw (%dx)
+ outw (%dx)
+
+ movsb
+ cmpsw
+ scasl
+ xlatb
+ movsl %cs:(%esi),%es:(%edi)
+ setae (%ebx)
+ setaeb (%ebx)
+ setae %al
+
+#these should give warnings
+ orb $1,%ax
+ orb $1,%eax
+ orb $1,%bx
+ orb $1,%ebx
+ fldl %st(1)
+ fstl %st(2)
+ fstpl %st(3)
+ fcoml %st(4)
+ fcompl %st(5)
+ faddp %st(1),%st
+ fmulp %st(2),%st
+ fsubp %st(3),%st
+ fsubrp %st(4),%st
+ fdivp %st(5),%st
+ fdivrp %st(6),%st
+ fadd
+ fsub
+ fmul
+ fdiv
+ fsubr
+ fdivr
+#these should all be legal
+ btl %edx, 0x123456
+ btl %edx, %eax
+ orb $1,%al
+ orb $1,%bl
+ movl 17,%eax
+ mov 17,%eax
+ inw %dx,%ax
+ inl %dx,%eax
+ inw (%dx),%ax
+ inl (%dx),%eax
+ in (%dx),%al
+ in (%dx),%ax
+ in (%dx),%eax
+ movzbl (%edi,%esi),%edx
+ movzbl 28(%ebp),%eax
+ movzbl %al,%eax
+ movzbl %cl,%esi
+ xlat %es:(%ebx)
+ xlat
+ xlatb
+1: fstp %st(0)
+ loop 1b
+ divb %cl
+ divw %cx
+ divl %ecx
+ div %cl
+ div %cx
+ div %ecx
+ div %cl,%al
+ div %cx,%ax
+ div %ecx,%eax
+ mov %si,%ds
+ movl %si,%ds # warning here
+ pushl %ds
+ push %ds
+ mov 0,%al
+ mov 0x10000,%ax
+ mov %eax,%ebx
+ pushf
+ pushfl
+ pushfw
+ popf
+ popfl
+ popfw
+ mov %esi,(,%ebx,1)
+ andb $~0x80,foo
+
+ # Force a good alignment.
+ .word 0
+ .byte 0
diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp
new file mode 100644
index 0000000000..cef1ff7ac0
--- /dev/null
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -0,0 +1,34 @@
+#
+# i386 tests
+#
+proc run_list_test { name opts } {
+ global srcdir subdir
+ set testname "i386 $name"
+ set file $srcdir/$subdir/$name
+ gas_run ${name}.s $opts ">&dump.out"
+ if { [regexp_diff "dump.out" "${file}.l"] } then {
+ fail $testname
+ verbose "output is [file_contents "dump.out"]" 2
+ return
+ }
+ pass $testname
+}
+
+
+if [istarget "i*86-*-*"] then {
+
+ run_list_test "float" "-al"
+ run_list_test "general" "-al --listing-lhs-width=2"
+ run_list_test "inval" "-al"
+ run_list_test "modrm" "-al --listing-lhs-width=2"
+ run_dump_test "opcode"
+ run_dump_test "prefix"
+ run_dump_test "amd"
+
+ # The reloc and white tests require support for 8 and 16 bit
+ # relocs, so we only run them for ELF targets.
+ if {[istarget "*-*-elf*"] || [istarget "*-*-linux*"]} then {
+ run_dump_test "reloc"
+ run_list_test "white" "-al --listing-lhs-width=3"
+ }
+}
diff --git a/gas/testsuite/gas/i386/inval.l b/gas/testsuite/gas/i386/inval.l
new file mode 100644
index 0000000000..e789499185
--- /dev/null
+++ b/gas/testsuite/gas/i386/inval.l
@@ -0,0 +1,98 @@
+.*: Assembler messages:
+.*:3: Error: .*
+.*:4: Error: .*
+.*:5: Error: .*
+.*:6: Error: .*
+.*:7: Error: .*
+.*:8: Error: .*
+.*:9: Error: .*
+.*:10: Error: .*
+.*:11: Error: .*
+.*:12: Error: .*
+.*:13: Error: .*
+.*:14: Error: .*
+.*:15: Error: .*
+.*:16: Error: .*
+.*:17: Error: .*
+.*:18: Error: .*
+.*:19: Error: .*
+.*:20: Error: .*
+.*:21: Error: .*
+.*:22: Error: .*
+.*:23: Error: .*
+.*:24: Error: .*
+.*:25: Error: .*
+.*:26: Error: .*
+.*:27: Error: .*
+.*:28: Error: .*
+.*:29: Error: .*
+.*:30: Error: .*
+.*:31: Error: .*
+.*:32: Error: .*
+.*:33: Error: .*
+.*:34: Error: .*
+.*:35: Error: .*
+.*:36: Error: .*
+.*:37: Error: .*
+.*:38: Error: .*
+.*:39: Error: .*
+.*:40: Error: .*
+.*:41: Error: .*
+.*:42: Error: .*
+.*:43: Error: .*
+.*:44: Error: .*
+.*:45: Error: .*
+.*:46: Error: .*
+.*:47: Error: .*
+.*:48: Error: .*
+GAS LISTING .*
+
+
+ 1 [ ]* .text
+ 2 [ ]*# All the following should be illegal
+ 3 [ ]* mov \(%dx\),%al
+ 4 [ ]* mov \(%eax,%esp,2\),%al
+ 5 [ ]* setae %eax
+ 6 [ ]* pushb %ds
+ 7 [ ]* popb %ds
+ 8 [ ]* pushb %al
+ 9 [ ]* popb %al
+ 10 [ ]* pushb %ah
+ 11 [ ]* popb %ah
+ 12 [ ]* pushb %ax
+ 13 [ ]* popb %ax
+ 14 [ ]* pushb %eax
+ 15 [ ]* popb %eax
+ 16 [ ]* movb %ds,%ax
+ 17 [ ]* movb %ds,%eax
+ 18 [ ]* movb %ax,%ds
+ 19 [ ]* movb %eax,%ds
+ 20 [ ]* movdb %eax,%mm0
+ 21 [ ]* movqb 0,%mm0
+ 22 [ ]* ldsb 0,%eax
+ 23 [ ]* setnew 0
+ 24 [ ]* movdw %eax,%mm0
+ 25 [ ]* movqw 0,%mm0
+ 26 [ ]* div %cx,%al
+ 27 [ ]* div %cl,%ax
+ 28 [ ]* div %ecx,%al
+ 29 [ ]* imul 10,%bx,%ecx
+ 30 [ ]* imul 10,%bx,%al
+ 31 [ ]* popab
+ 32 [ ]* stil
+ 33 [ ]* aaab
+ 34 [ ]* cwdel
+ 35 [ ]* cwdw
+ 36 [ ]* callww 0
+ 37 [ ]*foo: jaw foo
+ 38 [ ]* jcxzw foo
+ 39 [ ]* jecxzl foo
+ 40 [ ]* loopb foo
+ 41 [ ]* xlatw %es:%bx
+ 42 [ ]* xlatl %es:%bx
+ 43 [ ]* intl 2
+ 44 [ ]* int3b
+ 45 [ ]* hltb
+ 46 [ ]* fstb %st\(0\)
+ 47 [ ]* fcompll 28\(%ebp\)
+ 48 [ ]* fldlw \(%eax\)
diff --git a/gas/testsuite/gas/i386/inval.s b/gas/testsuite/gas/i386/inval.s
new file mode 100644
index 0000000000..e37a18eac6
--- /dev/null
+++ b/gas/testsuite/gas/i386/inval.s
@@ -0,0 +1,48 @@
+ .text
+# All the following should be illegal
+ mov (%dx),%al
+ mov (%eax,%esp,2),%al
+ setae %eax
+ pushb %ds
+ popb %ds
+ pushb %al
+ popb %al
+ pushb %ah
+ popb %ah
+ pushb %ax
+ popb %ax
+ pushb %eax
+ popb %eax
+ movb %ds,%ax
+ movb %ds,%eax
+ movb %ax,%ds
+ movb %eax,%ds
+ movdb %eax,%mm0
+ movqb 0,%mm0
+ ldsb 0,%eax
+ setnew 0
+ movdw %eax,%mm0
+ movqw 0,%mm0
+ div %cx,%al
+ div %cl,%ax
+ div %ecx,%al
+ imul 10,%bx,%ecx
+ imul 10,%bx,%al
+ popab
+ stil
+ aaab
+ cwdel
+ cwdw
+ callww 0
+foo: jaw foo
+ jcxzw foo
+ jecxzl foo
+ loopb foo
+ xlatw %es:%bx
+ xlatl %es:%bx
+ intl 2
+ int3b
+ hltb
+ fstb %st(0)
+ fcompll 28(%ebp)
+ fldlw (%eax)
diff --git a/gas/testsuite/gas/i386/modrm.l b/gas/testsuite/gas/i386/modrm.l
new file mode 100644
index 0000000000..8a1bc7912f
--- /dev/null
+++ b/gas/testsuite/gas/i386/modrm.l
@@ -0,0 +1,1984 @@
+.*: Assembler messages:
+.*:128: Warning:.*
+.*:129: Warning:.*
+.*:130: Warning:.*
+.*:131: Warning:.*
+.*:132: Warning:.*
+.*:133: Warning:.*
+.*:134: Warning:.*
+.*:135: Warning:.*
+.*:192: Warning:.*
+.*:193: Warning:.*
+.*:194: Warning:.*
+.*:195: Warning:.*
+.*:196: Warning:.*
+.*:197: Warning:.*
+.*:198: Warning:.*
+.*:199: Warning:.*
+.*:256: Warning:.*
+.*:257: Warning:.*
+.*:258: Warning:.*
+.*:259: Warning:.*
+.*:260: Warning:.*
+.*:261: Warning:.*
+.*:262: Warning:.*
+.*:263: Warning:.*
+.*:384: Warning:.*
+.*:385: Warning:.*
+.*:386: Warning:.*
+.*:387: Warning:.*
+.*:388: Warning:.*
+.*:389: Warning:.*
+.*:390: Warning:.*
+.*:391: Warning:.*
+.*:448: Warning:.*
+.*:449: Warning:.*
+.*:450: Warning:.*
+.*:451: Warning:.*
+.*:452: Warning:.*
+.*:453: Warning:.*
+.*:454: Warning:.*
+.*:455: Warning:.*
+.*:512: Warning:.*
+.*:513: Warning:.*
+.*:514: Warning:.*
+.*:515: Warning:.*
+.*:516: Warning:.*
+.*:517: Warning:.*
+.*:518: Warning:.*
+.*:519: Warning:.*
+.*:640: Warning:.*
+.*:641: Warning:.*
+.*:642: Warning:.*
+.*:643: Warning:.*
+.*:644: Warning:.*
+.*:645: Warning:.*
+.*:646: Warning:.*
+.*:647: Warning:.*
+.*:704: Warning:.*
+.*:705: Warning:.*
+.*:706: Warning:.*
+.*:707: Warning:.*
+.*:708: Warning:.*
+.*:709: Warning:.*
+.*:710: Warning:.*
+.*:711: Warning:.*
+.*:768: Warning:.*
+.*:769: Warning:.*
+.*:770: Warning:.*
+.*:771: Warning:.*
+.*:772: Warning:.*
+.*:773: Warning:.*
+.*:774: Warning:.*
+.*:775: Warning:.*
+.*:812: Warning:.*
+.*:820: Warning:.*
+.*:828: Warning:.*
+.*:833: Warning:.*
+.*:834: Warning:.*
+.*:835: Warning:.*
+.*:961: Warning:.*
+.*:962: Warning:.*
+.*:963: Warning:.*
+.*:964: Warning:.*
+.*:965: Warning:.*
+.*:966: Warning:.*
+.*:967: Warning:.*
+.*:968: Warning:.*
+.*:1025: Warning:.*
+.*:1026: Warning:.*
+.*:1027: Warning:.*
+.*:1028: Warning:.*
+.*:1029: Warning:.*
+.*:1030: Warning:.*
+.*:1031: Warning:.*
+.*:1032: Warning:.*
+.*:1089: Warning:.*
+.*:1090: Warning:.*
+.*:1091: Warning:.*
+.*:1092: Warning:.*
+.*:1093: Warning:.*
+.*:1094: Warning:.*
+.*:1095: Warning:.*
+.*:1096: Warning:.*
+.*:1217: Warning:.*
+.*:1218: Warning:.*
+.*:1219: Warning:.*
+.*:1220: Warning:.*
+.*:1221: Warning:.*
+.*:1222: Warning:.*
+.*:1223: Warning:.*
+.*:1224: Warning:.*
+.*:1281: Warning:.*
+.*:1282: Warning:.*
+.*:1283: Warning:.*
+.*:1284: Warning:.*
+.*:1285: Warning:.*
+.*:1286: Warning:.*
+.*:1287: Warning:.*
+.*:1288: Warning:.*
+.*:1345: Warning:.*
+.*:1346: Warning:.*
+.*:1347: Warning:.*
+.*:1348: Warning:.*
+.*:1349: Warning:.*
+.*:1350: Warning:.*
+.*:1351: Warning:.*
+.*:1352: Warning:.*
+.*:1473: Warning:.*
+.*:1474: Warning:.*
+.*:1475: Warning:.*
+.*:1476: Warning:.*
+.*:1477: Warning:.*
+.*:1478: Warning:.*
+.*:1479: Warning:.*
+.*:1480: Warning:.*
+.*:1537: Warning:.*
+.*:1538: Warning:.*
+.*:1539: Warning:.*
+.*:1540: Warning:.*
+.*:1541: Warning:.*
+.*:1542: Warning:.*
+.*:1543: Warning:.*
+.*:1544: Warning:.*
+.*:1601: Warning:.*
+.*:1602: Warning:.*
+.*:1603: Warning:.*
+.*:1604: Warning:.*
+.*:1605: Warning:.*
+.*:1606: Warning:.*
+.*:1607: Warning:.*
+.*:1608: Warning:.*
+.*:1645: Warning:.*
+.*:1653: Warning:.*
+.*:1661: Warning:.*
+.*:1666: Warning:.*
+.*:1667: Warning:.*
+.*:1668: Warning:.*
+ 1 .psize 0
+ 2 .text
+ 3 0000 368C18 mov %ds,%ss:\(%eax\)
+ 4 0003 368C19 mov %ds,%ss:\(%ecx\)
+ 5 0006 368C1A mov %ds,%ss:\(%edx\)
+ 6 0009 368C1B mov %ds,%ss:\(%ebx\)
+ 7 000c 368C1D00 000000 mov %ds,%ss:0
+ 8 0013 368C1E mov %ds,%ss:\(%esi\)
+ 9 0016 368C1F mov %ds,%ss:\(%edi\)
+ 10 0019 368C5812 mov %ds,%ss:0x12\(%eax\)
+ 11 001d 368C5912 mov %ds,%ss:0x12\(%ecx\)
+ 12 0021 368C5A12 mov %ds,%ss:0x12\(%edx\)
+ 13 0025 368C5B12 mov %ds,%ss:0x12\(%ebx\)
+ 14 0029 8C5D12 mov %ds,%ss:0x12\(%ebp\)
+ 15 002c 368C5E12 mov %ds,%ss:0x12\(%esi\)
+ 16 0030 368C5F12 mov %ds,%ss:0x12\(%edi\)
+ 17 0034 368C9878 563412 mov %ds,%ss:0x12345678\(%eax\)
+ 18 003b 368C9978 563412 mov %ds,%ss:0x12345678\(%ecx\)
+ 19 0042 368C9A78 563412 mov %ds,%ss:0x12345678\(%edx\)
+ 20 0049 368C9B78 563412 mov %ds,%ss:0x12345678\(%ebx\)
+ 21 0050 8C9D7856 3412 mov %ds,%ss:0x12345678\(%ebp\)
+ 22 0056 368C9E78 563412 mov %ds,%ss:0x12345678\(%esi\)
+ 23 005d 368C9F78 563412 mov %ds,%ss:0x12345678\(%edi\)
+ 24 0064 8CD8 mov %ds,%eax
+ 25 0066 8CD9 mov %ds,%ecx
+ 26 0068 8CDA mov %ds,%edx
+ 27 006a 8CDB mov %ds,%ebx
+ 28 006c 8CDC mov %ds,%esp
+ 29 006e 8CDD mov %ds,%ebp
+ 30 0070 8CDE mov %ds,%esi
+ 31 0072 8CDF mov %ds,%edi
+ 32 0074 368C1C00 mov %ds,%ss:\(%eax,%eax,1\)
+ 33 0078 368C1C01 mov %ds,%ss:\(%ecx,%eax,1\)
+ 34 007c 368C1C02 mov %ds,%ss:\(%edx,%eax,1\)
+ 35 0080 368C1C03 mov %ds,%ss:\(%ebx,%eax,1\)
+ 36 0084 8C1C04 mov %ds,%ss:\(%esp,%eax,1\)
+ 37 0087 368C1C05 00000000 mov %ds,%ss:\(,%eax,1\)
+ 38 008f 368C1C06 mov %ds,%ss:\(%esi,%eax,1\)
+ 39 0093 368C1C07 mov %ds,%ss:\(%edi,%eax,1\)
+ 40 0097 368C1C08 mov %ds,%ss:\(%eax,%ecx,1\)
+ 41 009b 368C1C09 mov %ds,%ss:\(%ecx,%ecx,1\)
+ 42 009f 368C1C0A mov %ds,%ss:\(%edx,%ecx,1\)
+ 43 00a3 368C1C0B mov %ds,%ss:\(%ebx,%ecx,1\)
+ 44 00a7 8C1C0C mov %ds,%ss:\(%esp,%ecx,1\)
+ 45 00aa 368C1C0D 00000000 mov %ds,%ss:\(,%ecx,1\)
+ 46 00b2 368C1C0E mov %ds,%ss:\(%esi,%ecx,1\)
+ 47 00b6 368C1C0F mov %ds,%ss:\(%edi,%ecx,1\)
+ 48 00ba 368C1C10 mov %ds,%ss:\(%eax,%edx,1\)
+ 49 00be 368C1C11 mov %ds,%ss:\(%ecx,%edx,1\)
+ 50 00c2 368C1C12 mov %ds,%ss:\(%edx,%edx,1\)
+ 51 00c6 368C1C13 mov %ds,%ss:\(%ebx,%edx,1\)
+ 52 00ca 8C1C14 mov %ds,%ss:\(%esp,%edx,1\)
+ 53 00cd 368C1C15 00000000 mov %ds,%ss:\(,%edx,1\)
+ 54 00d5 368C1C16 mov %ds,%ss:\(%esi,%edx,1\)
+ 55 00d9 368C1C17 mov %ds,%ss:\(%edi,%edx,1\)
+ 56 00dd 368C1C18 mov %ds,%ss:\(%eax,%ebx,1\)
+ 57 00e1 368C1C19 mov %ds,%ss:\(%ecx,%ebx,1\)
+ 58 00e5 368C1C1A mov %ds,%ss:\(%edx,%ebx,1\)
+ 59 00e9 368C1C1B mov %ds,%ss:\(%ebx,%ebx,1\)
+ 60 00ed 8C1C1C mov %ds,%ss:\(%esp,%ebx,1\)
+ 61 00f0 368C1C1D 00000000 mov %ds,%ss:\(,%ebx,1\)
+ 62 00f8 368C1C1E mov %ds,%ss:\(%esi,%ebx,1\)
+ 63 00fc 368C1C1F mov %ds,%ss:\(%edi,%ebx,1\)
+ 64 0100 368C18 mov %ds,%ss:\(%eax,1\)
+ 65 0103 368C19 mov %ds,%ss:\(%ecx,1\)
+ 66 0106 368C1A mov %ds,%ss:\(%edx,1\)
+ 67 0109 368C1B mov %ds,%ss:\(%ebx,1\)
+ 68 010c 8C1C24 mov %ds,%ss:\(%esp,1\)
+ 69 010f 368C1D00 000000 mov %ds,%ss:\(,1\)
+ 70 0116 368C1E mov %ds,%ss:\(%esi,1\)
+ 71 0119 368C1F mov %ds,%ss:\(%edi,1\)
+ 72 011c 368C1C28 mov %ds,%ss:\(%eax,%ebp,1\)
+ 73 0120 368C1C29 mov %ds,%ss:\(%ecx,%ebp,1\)
+ 74 0124 368C1C2A mov %ds,%ss:\(%edx,%ebp,1\)
+ 75 0128 368C1C2B mov %ds,%ss:\(%ebx,%ebp,1\)
+ 76 012c 8C1C2C mov %ds,%ss:\(%esp,%ebp,1\)
+ 77 012f 368C1C2D 00000000 mov %ds,%ss:\(,%ebp,1\)
+ 78 0137 368C1C2E mov %ds,%ss:\(%esi,%ebp,1\)
+ 79 013b 368C1C2F mov %ds,%ss:\(%edi,%ebp,1\)
+ 80 013f 368C1C30 mov %ds,%ss:\(%eax,%esi,1\)
+ 81 0143 368C1C31 mov %ds,%ss:\(%ecx,%esi,1\)
+ 82 0147 368C1C32 mov %ds,%ss:\(%edx,%esi,1\)
+ 83 014b 368C1C33 mov %ds,%ss:\(%ebx,%esi,1\)
+ 84 014f 8C1C34 mov %ds,%ss:\(%esp,%esi,1\)
+ 85 0152 368C1C35 00000000 mov %ds,%ss:\(,%esi,1\)
+ 86 015a 368C1C36 mov %ds,%ss:\(%esi,%esi,1\)
+ 87 015e 368C1C37 mov %ds,%ss:\(%edi,%esi,1\)
+ 88 0162 368C1C38 mov %ds,%ss:\(%eax,%edi,1\)
+ 89 0166 368C1C39 mov %ds,%ss:\(%ecx,%edi,1\)
+ 90 016a 368C1C3A mov %ds,%ss:\(%edx,%edi,1\)
+ 91 016e 368C1C3B mov %ds,%ss:\(%ebx,%edi,1\)
+ 92 0172 8C1C3C mov %ds,%ss:\(%esp,%edi,1\)
+ 93 0175 368C1C3D 00000000 mov %ds,%ss:\(,%edi,1\)
+ 94 017d 368C1C3E mov %ds,%ss:\(%esi,%edi,1\)
+ 95 0181 368C1C3F mov %ds,%ss:\(%edi,%edi,1\)
+ 96 0185 368C1C40 mov %ds,%ss:\(%eax,%eax,2\)
+ 97 0189 368C1C41 mov %ds,%ss:\(%ecx,%eax,2\)
+ 98 018d 368C1C42 mov %ds,%ss:\(%edx,%eax,2\)
+ 99 0191 368C1C43 mov %ds,%ss:\(%ebx,%eax,2\)
+ 100 0195 8C1C44 mov %ds,%ss:\(%esp,%eax,2\)
+ 101 0198 368C1C45 00000000 mov %ds,%ss:\(,%eax,2\)
+ 102 01a0 368C1C46 mov %ds,%ss:\(%esi,%eax,2\)
+ 103 01a4 368C1C47 mov %ds,%ss:\(%edi,%eax,2\)
+ 104 01a8 368C1C48 mov %ds,%ss:\(%eax,%ecx,2\)
+ 105 01ac 368C1C49 mov %ds,%ss:\(%ecx,%ecx,2\)
+ 106 01b0 368C1C4A mov %ds,%ss:\(%edx,%ecx,2\)
+ 107 01b4 368C1C4B mov %ds,%ss:\(%ebx,%ecx,2\)
+ 108 01b8 8C1C4C mov %ds,%ss:\(%esp,%ecx,2\)
+ 109 01bb 368C1C4D 00000000 mov %ds,%ss:\(,%ecx,2\)
+ 110 01c3 368C1C4E mov %ds,%ss:\(%esi,%ecx,2\)
+ 111 01c7 368C1C4F mov %ds,%ss:\(%edi,%ecx,2\)
+ 112 01cb 368C1C50 mov %ds,%ss:\(%eax,%edx,2\)
+ 113 01cf 368C1C51 mov %ds,%ss:\(%ecx,%edx,2\)
+ 114 01d3 368C1C52 mov %ds,%ss:\(%edx,%edx,2\)
+ 115 01d7 368C1C53 mov %ds,%ss:\(%ebx,%edx,2\)
+ 116 01db 8C1C54 mov %ds,%ss:\(%esp,%edx,2\)
+ 117 01de 368C1C55 00000000 mov %ds,%ss:\(,%edx,2\)
+ 118 01e6 368C1C56 mov %ds,%ss:\(%esi,%edx,2\)
+ 119 01ea 368C1C57 mov %ds,%ss:\(%edi,%edx,2\)
+ 120 01ee 368C1C58 mov %ds,%ss:\(%eax,%ebx,2\)
+ 121 01f2 368C1C59 mov %ds,%ss:\(%ecx,%ebx,2\)
+ 122 01f6 368C1C5A mov %ds,%ss:\(%edx,%ebx,2\)
+ 123 01fa 368C1C5B mov %ds,%ss:\(%ebx,%ebx,2\)
+ 124 01fe 8C1C5C mov %ds,%ss:\(%esp,%ebx,2\)
+ 125 0201 368C1C5D 00000000 mov %ds,%ss:\(,%ebx,2\)
+ 126 0209 368C1C5E mov %ds,%ss:\(%esi,%ebx,2\)
+ 127 020d 368C1C5F mov %ds,%ss:\(%edi,%ebx,2\)
+ 128 0211 368C18 mov %ds,%ss:\(%eax,2\)
+.*Warning:.*
+ 129 0214 368C19 mov %ds,%ss:\(%ecx,2\)
+.*Warning:.*
+ 130 0217 368C1A mov %ds,%ss:\(%edx,2\)
+.*Warning:.*
+ 131 021a 368C1B mov %ds,%ss:\(%ebx,2\)
+.*Warning:.*
+ 132 021d 8C1C24 mov %ds,%ss:\(%esp,2\)
+.*Warning:.*
+ 133 0220 368C1D00 000000 mov %ds,%ss:\(,2\)
+.*Warning:.*
+ 134 0227 368C1E mov %ds,%ss:\(%esi,2\)
+.*Warning:.*
+ 135 022a 368C1F mov %ds,%ss:\(%edi,2\)
+.*Warning:.*
+ 136 022d 368C1C68 mov %ds,%ss:\(%eax,%ebp,2\)
+ 137 0231 368C1C69 mov %ds,%ss:\(%ecx,%ebp,2\)
+ 138 0235 368C1C6A mov %ds,%ss:\(%edx,%ebp,2\)
+ 139 0239 368C1C6B mov %ds,%ss:\(%ebx,%ebp,2\)
+ 140 023d 8C1C6C mov %ds,%ss:\(%esp,%ebp,2\)
+ 141 0240 368C1C6D 00000000 mov %ds,%ss:\(,%ebp,2\)
+ 142 0248 368C1C6E mov %ds,%ss:\(%esi,%ebp,2\)
+ 143 024c 368C1C6F mov %ds,%ss:\(%edi,%ebp,2\)
+ 144 0250 368C1C70 mov %ds,%ss:\(%eax,%esi,2\)
+ 145 0254 368C1C71 mov %ds,%ss:\(%ecx,%esi,2\)
+ 146 0258 368C1C72 mov %ds,%ss:\(%edx,%esi,2\)
+ 147 025c 368C1C73 mov %ds,%ss:\(%ebx,%esi,2\)
+ 148 0260 8C1C74 mov %ds,%ss:\(%esp,%esi,2\)
+ 149 0263 368C1C75 00000000 mov %ds,%ss:\(,%esi,2\)
+ 150 026b 368C1C76 mov %ds,%ss:\(%esi,%esi,2\)
+ 151 026f 368C1C77 mov %ds,%ss:\(%edi,%esi,2\)
+ 152 0273 368C1C78 mov %ds,%ss:\(%eax,%edi,2\)
+ 153 0277 368C1C79 mov %ds,%ss:\(%ecx,%edi,2\)
+ 154 027b 368C1C7A mov %ds,%ss:\(%edx,%edi,2\)
+ 155 027f 368C1C7B mov %ds,%ss:\(%ebx,%edi,2\)
+ 156 0283 8C1C7C mov %ds,%ss:\(%esp,%edi,2\)
+ 157 0286 368C1C7D 00000000 mov %ds,%ss:\(,%edi,2\)
+ 158 028e 368C1C7E mov %ds,%ss:\(%esi,%edi,2\)
+ 159 0292 368C1C7F mov %ds,%ss:\(%edi,%edi,2\)
+ 160 0296 368C1C80 mov %ds,%ss:\(%eax,%eax,4\)
+ 161 029a 368C1C81 mov %ds,%ss:\(%ecx,%eax,4\)
+ 162 029e 368C1C82 mov %ds,%ss:\(%edx,%eax,4\)
+ 163 02a2 368C1C83 mov %ds,%ss:\(%ebx,%eax,4\)
+ 164 02a6 8C1C84 mov %ds,%ss:\(%esp,%eax,4\)
+ 165 02a9 368C1C85 00000000 mov %ds,%ss:\(,%eax,4\)
+ 166 02b1 368C1C86 mov %ds,%ss:\(%esi,%eax,4\)
+ 167 02b5 368C1C87 mov %ds,%ss:\(%edi,%eax,4\)
+ 168 02b9 368C1C88 mov %ds,%ss:\(%eax,%ecx,4\)
+ 169 02bd 368C1C89 mov %ds,%ss:\(%ecx,%ecx,4\)
+ 170 02c1 368C1C8A mov %ds,%ss:\(%edx,%ecx,4\)
+ 171 02c5 368C1C8B mov %ds,%ss:\(%ebx,%ecx,4\)
+ 172 02c9 8C1C8C mov %ds,%ss:\(%esp,%ecx,4\)
+ 173 02cc 368C1C8D 00000000 mov %ds,%ss:\(,%ecx,4\)
+ 174 02d4 368C1C8E mov %ds,%ss:\(%esi,%ecx,4\)
+ 175 02d8 368C1C8F mov %ds,%ss:\(%edi,%ecx,4\)
+ 176 02dc 368C1C90 mov %ds,%ss:\(%eax,%edx,4\)
+ 177 02e0 368C1C91 mov %ds,%ss:\(%ecx,%edx,4\)
+ 178 02e4 368C1C92 mov %ds,%ss:\(%edx,%edx,4\)
+ 179 02e8 368C1C93 mov %ds,%ss:\(%ebx,%edx,4\)
+ 180 02ec 8C1C94 mov %ds,%ss:\(%esp,%edx,4\)
+ 181 02ef 368C1C95 00000000 mov %ds,%ss:\(,%edx,4\)
+ 182 02f7 368C1C96 mov %ds,%ss:\(%esi,%edx,4\)
+ 183 02fb 368C1C97 mov %ds,%ss:\(%edi,%edx,4\)
+ 184 02ff 368C1C98 mov %ds,%ss:\(%eax,%ebx,4\)
+ 185 0303 368C1C99 mov %ds,%ss:\(%ecx,%ebx,4\)
+ 186 0307 368C1C9A mov %ds,%ss:\(%edx,%ebx,4\)
+ 187 030b 368C1C9B mov %ds,%ss:\(%ebx,%ebx,4\)
+ 188 030f 8C1C9C mov %ds,%ss:\(%esp,%ebx,4\)
+ 189 0312 368C1C9D 00000000 mov %ds,%ss:\(,%ebx,4\)
+ 190 031a 368C1C9E mov %ds,%ss:\(%esi,%ebx,4\)
+ 191 031e 368C1C9F mov %ds,%ss:\(%edi,%ebx,4\)
+ 192 0322 368C18 mov %ds,%ss:\(%eax,4\)
+.*Warning:.*
+ 193 0325 368C19 mov %ds,%ss:\(%ecx,4\)
+.*Warning:.*
+ 194 0328 368C1A mov %ds,%ss:\(%edx,4\)
+.*Warning:.*
+ 195 032b 368C1B mov %ds,%ss:\(%ebx,4\)
+.*Warning:.*
+ 196 032e 8C1C24 mov %ds,%ss:\(%esp,4\)
+.*Warning:.*
+ 197 0331 368C1D00 000000 mov %ds,%ss:\(,4\)
+.*Warning:.*
+ 198 0338 368C1E mov %ds,%ss:\(%esi,4\)
+.*Warning:.*
+ 199 033b 368C1F mov %ds,%ss:\(%edi,4\)
+.*Warning:.*
+ 200 033e 368C1CA8 mov %ds,%ss:\(%eax,%ebp,4\)
+ 201 0342 368C1CA9 mov %ds,%ss:\(%ecx,%ebp,4\)
+ 202 0346 368C1CAA mov %ds,%ss:\(%edx,%ebp,4\)
+ 203 034a 368C1CAB mov %ds,%ss:\(%ebx,%ebp,4\)
+ 204 034e 8C1CAC mov %ds,%ss:\(%esp,%ebp,4\)
+ 205 0351 368C1CAD 00000000 mov %ds,%ss:\(,%ebp,4\)
+ 206 0359 368C1CAE mov %ds,%ss:\(%esi,%ebp,4\)
+ 207 035d 368C1CAF mov %ds,%ss:\(%edi,%ebp,4\)
+ 208 0361 368C1CB0 mov %ds,%ss:\(%eax,%esi,4\)
+ 209 0365 368C1CB1 mov %ds,%ss:\(%ecx,%esi,4\)
+ 210 0369 368C1CB2 mov %ds,%ss:\(%edx,%esi,4\)
+ 211 036d 368C1CB3 mov %ds,%ss:\(%ebx,%esi,4\)
+ 212 0371 8C1CB4 mov %ds,%ss:\(%esp,%esi,4\)
+ 213 0374 368C1CB5 00000000 mov %ds,%ss:\(,%esi,4\)
+ 214 037c 368C1CB6 mov %ds,%ss:\(%esi,%esi,4\)
+ 215 0380 368C1CB7 mov %ds,%ss:\(%edi,%esi,4\)
+ 216 0384 368C1CB8 mov %ds,%ss:\(%eax,%edi,4\)
+ 217 0388 368C1CB9 mov %ds,%ss:\(%ecx,%edi,4\)
+ 218 038c 368C1CBA mov %ds,%ss:\(%edx,%edi,4\)
+ 219 0390 368C1CBB mov %ds,%ss:\(%ebx,%edi,4\)
+ 220 0394 8C1CBC mov %ds,%ss:\(%esp,%edi,4\)
+ 221 0397 368C1CBD 00000000 mov %ds,%ss:\(,%edi,4\)
+ 222 039f 368C1CBE mov %ds,%ss:\(%esi,%edi,4\)
+ 223 03a3 368C1CBF mov %ds,%ss:\(%edi,%edi,4\)
+ 224 03a7 368C1CC0 mov %ds,%ss:\(%eax,%eax,8\)
+ 225 03ab 368C1CC1 mov %ds,%ss:\(%ecx,%eax,8\)
+ 226 03af 368C1CC2 mov %ds,%ss:\(%edx,%eax,8\)
+ 227 03b3 368C1CC3 mov %ds,%ss:\(%ebx,%eax,8\)
+ 228 03b7 8C1CC4 mov %ds,%ss:\(%esp,%eax,8\)
+ 229 03ba 368C1CC5 00000000 mov %ds,%ss:\(,%eax,8\)
+ 230 03c2 368C1CC6 mov %ds,%ss:\(%esi,%eax,8\)
+ 231 03c6 368C1CC7 mov %ds,%ss:\(%edi,%eax,8\)
+ 232 03ca 368C1CC8 mov %ds,%ss:\(%eax,%ecx,8\)
+ 233 03ce 368C1CC9 mov %ds,%ss:\(%ecx,%ecx,8\)
+ 234 03d2 368C1CCA mov %ds,%ss:\(%edx,%ecx,8\)
+ 235 03d6 368C1CCB mov %ds,%ss:\(%ebx,%ecx,8\)
+ 236 03da 8C1CCC mov %ds,%ss:\(%esp,%ecx,8\)
+ 237 03dd 368C1CCD 00000000 mov %ds,%ss:\(,%ecx,8\)
+ 238 03e5 368C1CCE mov %ds,%ss:\(%esi,%ecx,8\)
+ 239 03e9 368C1CCF mov %ds,%ss:\(%edi,%ecx,8\)
+ 240 03ed 368C1CD0 mov %ds,%ss:\(%eax,%edx,8\)
+ 241 03f1 368C1CD1 mov %ds,%ss:\(%ecx,%edx,8\)
+ 242 03f5 368C1CD2 mov %ds,%ss:\(%edx,%edx,8\)
+ 243 03f9 368C1CD3 mov %ds,%ss:\(%ebx,%edx,8\)
+ 244 03fd 8C1CD4 mov %ds,%ss:\(%esp,%edx,8\)
+ 245 0400 368C1CD5 00000000 mov %ds,%ss:\(,%edx,8\)
+ 246 0408 368C1CD6 mov %ds,%ss:\(%esi,%edx,8\)
+ 247 040c 368C1CD7 mov %ds,%ss:\(%edi,%edx,8\)
+ 248 0410 368C1CD8 mov %ds,%ss:\(%eax,%ebx,8\)
+ 249 0414 368C1CD9 mov %ds,%ss:\(%ecx,%ebx,8\)
+ 250 0418 368C1CDA mov %ds,%ss:\(%edx,%ebx,8\)
+ 251 041c 368C1CDB mov %ds,%ss:\(%ebx,%ebx,8\)
+ 252 0420 8C1CDC mov %ds,%ss:\(%esp,%ebx,8\)
+ 253 0423 368C1CDD 00000000 mov %ds,%ss:\(,%ebx,8\)
+ 254 042b 368C1CDE mov %ds,%ss:\(%esi,%ebx,8\)
+ 255 042f 368C1CDF mov %ds,%ss:\(%edi,%ebx,8\)
+ 256 0433 368C18 mov %ds,%ss:\(%eax,8\)
+.*Warning:.*
+ 257 0436 368C19 mov %ds,%ss:\(%ecx,8\)
+.*Warning:.*
+ 258 0439 368C1A mov %ds,%ss:\(%edx,8\)
+.*Warning:.*
+ 259 043c 368C1B mov %ds,%ss:\(%ebx,8\)
+.*Warning:.*
+ 260 043f 8C1C24 mov %ds,%ss:\(%esp,8\)
+.*Warning:.*
+ 261 0442 368C1D00 000000 mov %ds,%ss:\(,8\)
+.*Warning:.*
+ 262 0449 368C1E mov %ds,%ss:\(%esi,8\)
+.*Warning:.*
+ 263 044c 368C1F mov %ds,%ss:\(%edi,8\)
+.*Warning:.*
+ 264 044f 368C1CE8 mov %ds,%ss:\(%eax,%ebp,8\)
+ 265 0453 368C1CE9 mov %ds,%ss:\(%ecx,%ebp,8\)
+ 266 0457 368C1CEA mov %ds,%ss:\(%edx,%ebp,8\)
+ 267 045b 368C1CEB mov %ds,%ss:\(%ebx,%ebp,8\)
+ 268 045f 8C1CEC mov %ds,%ss:\(%esp,%ebp,8\)
+ 269 0462 368C1CED 00000000 mov %ds,%ss:\(,%ebp,8\)
+ 270 046a 368C1CEE mov %ds,%ss:\(%esi,%ebp,8\)
+ 271 046e 368C1CEF mov %ds,%ss:\(%edi,%ebp,8\)
+ 272 0472 368C1CF0 mov %ds,%ss:\(%eax,%esi,8\)
+ 273 0476 368C1CF1 mov %ds,%ss:\(%ecx,%esi,8\)
+ 274 047a 368C1CF2 mov %ds,%ss:\(%edx,%esi,8\)
+ 275 047e 368C1CF3 mov %ds,%ss:\(%ebx,%esi,8\)
+ 276 0482 8C1CF4 mov %ds,%ss:\(%esp,%esi,8\)
+ 277 0485 368C1CF5 00000000 mov %ds,%ss:\(,%esi,8\)
+ 278 048d 368C1CF6 mov %ds,%ss:\(%esi,%esi,8\)
+ 279 0491 368C1CF7 mov %ds,%ss:\(%edi,%esi,8\)
+ 280 0495 368C1CF8 mov %ds,%ss:\(%eax,%edi,8\)
+ 281 0499 368C1CFA mov %ds,%ss:\(%edx,%edi,8\)
+ 282 049d 368C1CF9 mov %ds,%ss:\(%ecx,%edi,8\)
+ 283 04a1 368C1CFB mov %ds,%ss:\(%ebx,%edi,8\)
+ 284 04a5 8C1CFC mov %ds,%ss:\(%esp,%edi,8\)
+ 285 04a8 368C1CFD 00000000 mov %ds,%ss:\(,%edi,8\)
+ 286 04b0 368C1CFE mov %ds,%ss:\(%esi,%edi,8\)
+ 287 04b4 368C1CFF mov %ds,%ss:\(%edi,%edi,8\)
+ 288 04b8 368C5C00 12 mov %ds,%ss:0x12\(%eax,%eax,1\)
+ 289 04bd 368C5C01 12 mov %ds,%ss:0x12\(%ecx,%eax,1\)
+ 290 04c2 368C5C02 12 mov %ds,%ss:0x12\(%edx,%eax,1\)
+ 291 04c7 368C5C03 12 mov %ds,%ss:0x12\(%ebx,%eax,1\)
+ 292 04cc 8C5C0412 mov %ds,%ss:0x12\(%esp,%eax,1\)
+ 293 04d0 8C5C0512 mov %ds,%ss:0x12\(%ebp,%eax,1\)
+ 294 04d4 368C5C06 12 mov %ds,%ss:0x12\(%esi,%eax,1\)
+ 295 04d9 368C5C07 12 mov %ds,%ss:0x12\(%edi,%eax,1\)
+ 296 04de 368C5C08 12 mov %ds,%ss:0x12\(%eax,%ecx,1\)
+ 297 04e3 368C5C09 12 mov %ds,%ss:0x12\(%ecx,%ecx,1\)
+ 298 04e8 368C5C0A 12 mov %ds,%ss:0x12\(%edx,%ecx,1\)
+ 299 04ed 368C5C0B 12 mov %ds,%ss:0x12\(%ebx,%ecx,1\)
+ 300 04f2 8C5C0C12 mov %ds,%ss:0x12\(%esp,%ecx,1\)
+ 301 04f6 8C5C0D12 mov %ds,%ss:0x12\(%ebp,%ecx,1\)
+ 302 04fa 368C5C0E 12 mov %ds,%ss:0x12\(%esi,%ecx,1\)
+ 303 04ff 368C5C0F 12 mov %ds,%ss:0x12\(%edi,%ecx,1\)
+ 304 0504 368C5C10 12 mov %ds,%ss:0x12\(%eax,%edx,1\)
+ 305 0509 368C5C11 12 mov %ds,%ss:0x12\(%ecx,%edx,1\)
+ 306 050e 368C5C12 12 mov %ds,%ss:0x12\(%edx,%edx,1\)
+ 307 0513 368C5C13 12 mov %ds,%ss:0x12\(%ebx,%edx,1\)
+ 308 0518 8C5C1412 mov %ds,%ss:0x12\(%esp,%edx,1\)
+ 309 051c 8C5C1512 mov %ds,%ss:0x12\(%ebp,%edx,1\)
+ 310 0520 368C5C16 12 mov %ds,%ss:0x12\(%esi,%edx,1\)
+ 311 0525 368C5C17 12 mov %ds,%ss:0x12\(%edi,%edx,1\)
+ 312 052a 368C5C18 12 mov %ds,%ss:0x12\(%eax,%ebx,1\)
+ 313 052f 368C5C19 12 mov %ds,%ss:0x12\(%ecx,%ebx,1\)
+ 314 0534 368C5C1A 12 mov %ds,%ss:0x12\(%edx,%ebx,1\)
+ 315 0539 368C5C1B 12 mov %ds,%ss:0x12\(%ebx,%ebx,1\)
+ 316 053e 8C5C1C12 mov %ds,%ss:0x12\(%esp,%ebx,1\)
+ 317 0542 8C5C1D12 mov %ds,%ss:0x12\(%ebp,%ebx,1\)
+ 318 0546 368C5C1E 12 mov %ds,%ss:0x12\(%esi,%ebx,1\)
+ 319 054b 368C5C1F 12 mov %ds,%ss:0x12\(%edi,%ebx,1\)
+ 320 0550 368C5812 mov %ds,%ss:0x12\(%eax,1\)
+ 321 0554 368C5912 mov %ds,%ss:0x12\(%ecx,1\)
+ 322 0558 368C5A12 mov %ds,%ss:0x12\(%edx,1\)
+ 323 055c 368C5B12 mov %ds,%ss:0x12\(%ebx,1\)
+ 324 0560 8C5C2412 mov %ds,%ss:0x12\(%esp,1\)
+ 325 0564 8C5D12 mov %ds,%ss:0x12\(%ebp,1\)
+ 326 0567 368C5E12 mov %ds,%ss:0x12\(%esi,1\)
+ 327 056b 368C5F12 mov %ds,%ss:0x12\(%edi,1\)
+ 328 056f 368C5C28 12 mov %ds,%ss:0x12\(%eax,%ebp,1\)
+ 329 0574 368C5C29 12 mov %ds,%ss:0x12\(%ecx,%ebp,1\)
+ 330 0579 368C5C2A 12 mov %ds,%ss:0x12\(%edx,%ebp,1\)
+ 331 057e 368C5C2B 12 mov %ds,%ss:0x12\(%ebx,%ebp,1\)
+ 332 0583 8C5C2C12 mov %ds,%ss:0x12\(%esp,%ebp,1\)
+ 333 0587 8C5C2D12 mov %ds,%ss:0x12\(%ebp,%ebp,1\)
+ 334 058b 368C5C2E 12 mov %ds,%ss:0x12\(%esi,%ebp,1\)
+ 335 0590 368C5C2F 12 mov %ds,%ss:0x12\(%edi,%ebp,1\)
+ 336 0595 368C5C30 12 mov %ds,%ss:0x12\(%eax,%esi,1\)
+ 337 059a 368C5C31 12 mov %ds,%ss:0x12\(%ecx,%esi,1\)
+ 338 059f 368C5C32 12 mov %ds,%ss:0x12\(%edx,%esi,1\)
+ 339 05a4 368C5C33 12 mov %ds,%ss:0x12\(%ebx,%esi,1\)
+ 340 05a9 8C5C3412 mov %ds,%ss:0x12\(%esp,%esi,1\)
+ 341 05ad 8C5C3512 mov %ds,%ss:0x12\(%ebp,%esi,1\)
+ 342 05b1 368C5C36 12 mov %ds,%ss:0x12\(%esi,%esi,1\)
+ 343 05b6 368C5C37 12 mov %ds,%ss:0x12\(%edi,%esi,1\)
+ 344 05bb 368C5C38 12 mov %ds,%ss:0x12\(%eax,%edi,1\)
+ 345 05c0 368C5C39 12 mov %ds,%ss:0x12\(%ecx,%edi,1\)
+ 346 05c5 368C5C3A 12 mov %ds,%ss:0x12\(%edx,%edi,1\)
+ 347 05ca 368C5C3B 12 mov %ds,%ss:0x12\(%ebx,%edi,1\)
+ 348 05cf 8C5C3C12 mov %ds,%ss:0x12\(%esp,%edi,1\)
+ 349 05d3 8C5C3D12 mov %ds,%ss:0x12\(%ebp,%edi,1\)
+ 350 05d7 368C5C3E 12 mov %ds,%ss:0x12\(%esi,%edi,1\)
+ 351 05dc 368C5C3F 12 mov %ds,%ss:0x12\(%edi,%edi,1\)
+ 352 05e1 368C5C40 12 mov %ds,%ss:0x12\(%eax,%eax,2\)
+ 353 05e6 368C5C41 12 mov %ds,%ss:0x12\(%ecx,%eax,2\)
+ 354 05eb 368C5C42 12 mov %ds,%ss:0x12\(%edx,%eax,2\)
+ 355 05f0 368C5C43 12 mov %ds,%ss:0x12\(%ebx,%eax,2\)
+ 356 05f5 8C5C4412 mov %ds,%ss:0x12\(%esp,%eax,2\)
+ 357 05f9 8C5C4512 mov %ds,%ss:0x12\(%ebp,%eax,2\)
+ 358 05fd 368C5C46 12 mov %ds,%ss:0x12\(%esi,%eax,2\)
+ 359 0602 368C5C47 12 mov %ds,%ss:0x12\(%edi,%eax,2\)
+ 360 0607 368C5C48 12 mov %ds,%ss:0x12\(%eax,%ecx,2\)
+ 361 060c 368C5C49 12 mov %ds,%ss:0x12\(%ecx,%ecx,2\)
+ 362 0611 368C5C4A 12 mov %ds,%ss:0x12\(%edx,%ecx,2\)
+ 363 0616 368C5C4B 12 mov %ds,%ss:0x12\(%ebx,%ecx,2\)
+ 364 061b 8C5C4C12 mov %ds,%ss:0x12\(%esp,%ecx,2\)
+ 365 061f 8C5C4D12 mov %ds,%ss:0x12\(%ebp,%ecx,2\)
+ 366 0623 368C5C4E 12 mov %ds,%ss:0x12\(%esi,%ecx,2\)
+ 367 0628 368C5C4F 12 mov %ds,%ss:0x12\(%edi,%ecx,2\)
+ 368 062d 368C5C50 12 mov %ds,%ss:0x12\(%eax,%edx,2\)
+ 369 0632 368C5C51 12 mov %ds,%ss:0x12\(%ecx,%edx,2\)
+ 370 0637 368C5C52 12 mov %ds,%ss:0x12\(%edx,%edx,2\)
+ 371 063c 368C5C53 12 mov %ds,%ss:0x12\(%ebx,%edx,2\)
+ 372 0641 8C5C5412 mov %ds,%ss:0x12\(%esp,%edx,2\)
+ 373 0645 8C5C5512 mov %ds,%ss:0x12\(%ebp,%edx,2\)
+ 374 0649 368C5C56 12 mov %ds,%ss:0x12\(%esi,%edx,2\)
+ 375 064e 368C5C57 12 mov %ds,%ss:0x12\(%edi,%edx,2\)
+ 376 0653 368C5C58 12 mov %ds,%ss:0x12\(%eax,%ebx,2\)
+ 377 0658 368C5C59 12 mov %ds,%ss:0x12\(%ecx,%ebx,2\)
+ 378 065d 368C5C5A 12 mov %ds,%ss:0x12\(%edx,%ebx,2\)
+ 379 0662 368C5C5B 12 mov %ds,%ss:0x12\(%ebx,%ebx,2\)
+ 380 0667 8C5C5C12 mov %ds,%ss:0x12\(%esp,%ebx,2\)
+ 381 066b 8C5C5D12 mov %ds,%ss:0x12\(%ebp,%ebx,2\)
+ 382 066f 368C5C5E 12 mov %ds,%ss:0x12\(%esi,%ebx,2\)
+ 383 0674 368C5C5F 12 mov %ds,%ss:0x12\(%edi,%ebx,2\)
+ 384 0679 368C5812 mov %ds,%ss:0x12\(%eax,2\)
+.*Warning:.*
+ 385 067d 368C5912 mov %ds,%ss:0x12\(%ecx,2\)
+.*Warning:.*
+ 386 0681 368C5A12 mov %ds,%ss:0x12\(%edx,2\)
+.*Warning:.*
+ 387 0685 368C5B12 mov %ds,%ss:0x12\(%ebx,2\)
+.*Warning:.*
+ 388 0689 8C5C2412 mov %ds,%ss:0x12\(%esp,2\)
+.*Warning:.*
+ 389 068d 8C5D12 mov %ds,%ss:0x12\(%ebp,2\)
+.*Warning:.*
+ 390 0690 368C5E12 mov %ds,%ss:0x12\(%esi,2\)
+.*Warning:.*
+ 391 0694 368C5F12 mov %ds,%ss:0x12\(%edi,2\)
+.*Warning:.*
+ 392 0698 368C5C68 12 mov %ds,%ss:0x12\(%eax,%ebp,2\)
+ 393 069d 368C5C69 12 mov %ds,%ss:0x12\(%ecx,%ebp,2\)
+ 394 06a2 368C5C6A 12 mov %ds,%ss:0x12\(%edx,%ebp,2\)
+ 395 06a7 368C5C6B 12 mov %ds,%ss:0x12\(%ebx,%ebp,2\)
+ 396 06ac 8C5C6C12 mov %ds,%ss:0x12\(%esp,%ebp,2\)
+ 397 06b0 8C5C6D12 mov %ds,%ss:0x12\(%ebp,%ebp,2\)
+ 398 06b4 368C5C6E 12 mov %ds,%ss:0x12\(%esi,%ebp,2\)
+ 399 06b9 368C5C6F 12 mov %ds,%ss:0x12\(%edi,%ebp,2\)
+ 400 06be 368C5C70 12 mov %ds,%ss:0x12\(%eax,%esi,2\)
+ 401 06c3 368C5C71 12 mov %ds,%ss:0x12\(%ecx,%esi,2\)
+ 402 06c8 368C5C72 12 mov %ds,%ss:0x12\(%edx,%esi,2\)
+ 403 06cd 368C5C73 12 mov %ds,%ss:0x12\(%ebx,%esi,2\)
+ 404 06d2 8C5C7412 mov %ds,%ss:0x12\(%esp,%esi,2\)
+ 405 06d6 8C5C7512 mov %ds,%ss:0x12\(%ebp,%esi,2\)
+ 406 06da 368C5C76 12 mov %ds,%ss:0x12\(%esi,%esi,2\)
+ 407 06df 368C5C77 12 mov %ds,%ss:0x12\(%edi,%esi,2\)
+ 408 06e4 368C5C78 12 mov %ds,%ss:0x12\(%eax,%edi,2\)
+ 409 06e9 368C5C79 12 mov %ds,%ss:0x12\(%ecx,%edi,2\)
+ 410 06ee 368C5C7A 12 mov %ds,%ss:0x12\(%edx,%edi,2\)
+ 411 06f3 368C5C7B 12 mov %ds,%ss:0x12\(%ebx,%edi,2\)
+ 412 06f8 8C5C7C12 mov %ds,%ss:0x12\(%esp,%edi,2\)
+ 413 06fc 8C5C7D12 mov %ds,%ss:0x12\(%ebp,%edi,2\)
+ 414 0700 368C5C7E 12 mov %ds,%ss:0x12\(%esi,%edi,2\)
+ 415 0705 368C5C7F 12 mov %ds,%ss:0x12\(%edi,%edi,2\)
+ 416 070a 368C5C80 12 mov %ds,%ss:0x12\(%eax,%eax,4\)
+ 417 070f 368C5C81 12 mov %ds,%ss:0x12\(%ecx,%eax,4\)
+ 418 0714 368C5C82 12 mov %ds,%ss:0x12\(%edx,%eax,4\)
+ 419 0719 368C5C83 12 mov %ds,%ss:0x12\(%ebx,%eax,4\)
+ 420 071e 8C5C8412 mov %ds,%ss:0x12\(%esp,%eax,4\)
+ 421 0722 8C5C8512 mov %ds,%ss:0x12\(%ebp,%eax,4\)
+ 422 0726 368C5C86 12 mov %ds,%ss:0x12\(%esi,%eax,4\)
+ 423 072b 368C5C87 12 mov %ds,%ss:0x12\(%edi,%eax,4\)
+ 424 0730 368C5C88 12 mov %ds,%ss:0x12\(%eax,%ecx,4\)
+ 425 0735 368C5C89 12 mov %ds,%ss:0x12\(%ecx,%ecx,4\)
+ 426 073a 368C5C8A 12 mov %ds,%ss:0x12\(%edx,%ecx,4\)
+ 427 073f 368C5C8B 12 mov %ds,%ss:0x12\(%ebx,%ecx,4\)
+ 428 0744 8C5C8C12 mov %ds,%ss:0x12\(%esp,%ecx,4\)
+ 429 0748 8C5C8D12 mov %ds,%ss:0x12\(%ebp,%ecx,4\)
+ 430 074c 368C5C8E 12 mov %ds,%ss:0x12\(%esi,%ecx,4\)
+ 431 0751 368C5C8F 12 mov %ds,%ss:0x12\(%edi,%ecx,4\)
+ 432 0756 368C5C90 12 mov %ds,%ss:0x12\(%eax,%edx,4\)
+ 433 075b 368C5C91 12 mov %ds,%ss:0x12\(%ecx,%edx,4\)
+ 434 0760 368C5C92 12 mov %ds,%ss:0x12\(%edx,%edx,4\)
+ 435 0765 368C5C93 12 mov %ds,%ss:0x12\(%ebx,%edx,4\)
+ 436 076a 8C5C9412 mov %ds,%ss:0x12\(%esp,%edx,4\)
+ 437 076e 8C5C9512 mov %ds,%ss:0x12\(%ebp,%edx,4\)
+ 438 0772 368C5C96 12 mov %ds,%ss:0x12\(%esi,%edx,4\)
+ 439 0777 368C5C97 12 mov %ds,%ss:0x12\(%edi,%edx,4\)
+ 440 077c 368C5C98 12 mov %ds,%ss:0x12\(%eax,%ebx,4\)
+ 441 0781 368C5C99 12 mov %ds,%ss:0x12\(%ecx,%ebx,4\)
+ 442 0786 368C5C9A 12 mov %ds,%ss:0x12\(%edx,%ebx,4\)
+ 443 078b 368C5C9B 12 mov %ds,%ss:0x12\(%ebx,%ebx,4\)
+ 444 0790 8C5C9C12 mov %ds,%ss:0x12\(%esp,%ebx,4\)
+ 445 0794 8C5C9D12 mov %ds,%ss:0x12\(%ebp,%ebx,4\)
+ 446 0798 368C5C9E 12 mov %ds,%ss:0x12\(%esi,%ebx,4\)
+ 447 079d 368C5C9F 12 mov %ds,%ss:0x12\(%edi,%ebx,4\)
+ 448 07a2 368C5812 mov %ds,%ss:0x12\(%eax,4\)
+.*Warning:.*
+ 449 07a6 368C5912 mov %ds,%ss:0x12\(%ecx,4\)
+.*Warning:.*
+ 450 07aa 368C5A12 mov %ds,%ss:0x12\(%edx,4\)
+.*Warning:.*
+ 451 07ae 368C5B12 mov %ds,%ss:0x12\(%ebx,4\)
+.*Warning:.*
+ 452 07b2 8C5C2412 mov %ds,%ss:0x12\(%esp,4\)
+.*Warning:.*
+ 453 07b6 8C5D12 mov %ds,%ss:0x12\(%ebp,4\)
+.*Warning:.*
+ 454 07b9 368C5E12 mov %ds,%ss:0x12\(%esi,4\)
+.*Warning:.*
+ 455 07bd 368C5F12 mov %ds,%ss:0x12\(%edi,4\)
+.*Warning:.*
+ 456 07c1 368C5CA8 12 mov %ds,%ss:0x12\(%eax,%ebp,4\)
+ 457 07c6 368C5CA9 12 mov %ds,%ss:0x12\(%ecx,%ebp,4\)
+ 458 07cb 368C5CAA 12 mov %ds,%ss:0x12\(%edx,%ebp,4\)
+ 459 07d0 368C5CAB 12 mov %ds,%ss:0x12\(%ebx,%ebp,4\)
+ 460 07d5 8C5CAC12 mov %ds,%ss:0x12\(%esp,%ebp,4\)
+ 461 07d9 8C5CAD12 mov %ds,%ss:0x12\(%ebp,%ebp,4\)
+ 462 07dd 368C5CAE 12 mov %ds,%ss:0x12\(%esi,%ebp,4\)
+ 463 07e2 368C5CAF 12 mov %ds,%ss:0x12\(%edi,%ebp,4\)
+ 464 07e7 368C5CB0 12 mov %ds,%ss:0x12\(%eax,%esi,4\)
+ 465 07ec 368C5CB1 12 mov %ds,%ss:0x12\(%ecx,%esi,4\)
+ 466 07f1 368C5CB2 12 mov %ds,%ss:0x12\(%edx,%esi,4\)
+ 467 07f6 368C5CB3 12 mov %ds,%ss:0x12\(%ebx,%esi,4\)
+ 468 07fb 8C5CB412 mov %ds,%ss:0x12\(%esp,%esi,4\)
+ 469 07ff 8C5CB512 mov %ds,%ss:0x12\(%ebp,%esi,4\)
+ 470 0803 368C5CB6 12 mov %ds,%ss:0x12\(%esi,%esi,4\)
+ 471 0808 368C5CB7 12 mov %ds,%ss:0x12\(%edi,%esi,4\)
+ 472 080d 368C5CB8 12 mov %ds,%ss:0x12\(%eax,%edi,4\)
+ 473 0812 368C5CB9 12 mov %ds,%ss:0x12\(%ecx,%edi,4\)
+ 474 0817 368C5CBA 12 mov %ds,%ss:0x12\(%edx,%edi,4\)
+ 475 081c 368C5CBB 12 mov %ds,%ss:0x12\(%ebx,%edi,4\)
+ 476 0821 8C5CBC12 mov %ds,%ss:0x12\(%esp,%edi,4\)
+ 477 0825 8C5CBD12 mov %ds,%ss:0x12\(%ebp,%edi,4\)
+ 478 0829 368C5CBE 12 mov %ds,%ss:0x12\(%esi,%edi,4\)
+ 479 082e 368C5CBF 12 mov %ds,%ss:0x12\(%edi,%edi,4\)
+ 480 0833 368C5CC0 12 mov %ds,%ss:0x12\(%eax,%eax,8\)
+ 481 0838 368C5CC1 12 mov %ds,%ss:0x12\(%ecx,%eax,8\)
+ 482 083d 368C5CC2 12 mov %ds,%ss:0x12\(%edx,%eax,8\)
+ 483 0842 368C5CC3 12 mov %ds,%ss:0x12\(%ebx,%eax,8\)
+ 484 0847 8C5CC412 mov %ds,%ss:0x12\(%esp,%eax,8\)
+ 485 084b 8C5CC512 mov %ds,%ss:0x12\(%ebp,%eax,8\)
+ 486 084f 368C5CC6 12 mov %ds,%ss:0x12\(%esi,%eax,8\)
+ 487 0854 368C5CC7 12 mov %ds,%ss:0x12\(%edi,%eax,8\)
+ 488 0859 368C5CC8 12 mov %ds,%ss:0x12\(%eax,%ecx,8\)
+ 489 085e 368C5CC9 12 mov %ds,%ss:0x12\(%ecx,%ecx,8\)
+ 490 0863 368C5CCA 12 mov %ds,%ss:0x12\(%edx,%ecx,8\)
+ 491 0868 368C5CCB 12 mov %ds,%ss:0x12\(%ebx,%ecx,8\)
+ 492 086d 8C5CCC12 mov %ds,%ss:0x12\(%esp,%ecx,8\)
+ 493 0871 8C5CCD12 mov %ds,%ss:0x12\(%ebp,%ecx,8\)
+ 494 0875 368C5CCE 12 mov %ds,%ss:0x12\(%esi,%ecx,8\)
+ 495 087a 368C5CCF 12 mov %ds,%ss:0x12\(%edi,%ecx,8\)
+ 496 087f 368C5CD0 12 mov %ds,%ss:0x12\(%eax,%edx,8\)
+ 497 0884 368C5CD1 12 mov %ds,%ss:0x12\(%ecx,%edx,8\)
+ 498 0889 368C5CD2 12 mov %ds,%ss:0x12\(%edx,%edx,8\)
+ 499 088e 368C5CD3 12 mov %ds,%ss:0x12\(%ebx,%edx,8\)
+ 500 0893 8C5CD412 mov %ds,%ss:0x12\(%esp,%edx,8\)
+ 501 0897 8C5CD512 mov %ds,%ss:0x12\(%ebp,%edx,8\)
+ 502 089b 368C5CD6 12 mov %ds,%ss:0x12\(%esi,%edx,8\)
+ 503 08a0 368C5CD7 12 mov %ds,%ss:0x12\(%edi,%edx,8\)
+ 504 08a5 368C5CD8 12 mov %ds,%ss:0x12\(%eax,%ebx,8\)
+ 505 08aa 368C5CD9 12 mov %ds,%ss:0x12\(%ecx,%ebx,8\)
+ 506 08af 368C5CDA 12 mov %ds,%ss:0x12\(%edx,%ebx,8\)
+ 507 08b4 368C5CDB 12 mov %ds,%ss:0x12\(%ebx,%ebx,8\)
+ 508 08b9 8C5CDC12 mov %ds,%ss:0x12\(%esp,%ebx,8\)
+ 509 08bd 8C5CDD12 mov %ds,%ss:0x12\(%ebp,%ebx,8\)
+ 510 08c1 368C5CDE 12 mov %ds,%ss:0x12\(%esi,%ebx,8\)
+ 511 08c6 368C5CDF 12 mov %ds,%ss:0x12\(%edi,%ebx,8\)
+ 512 08cb 368C5812 mov %ds,%ss:0x12\(%eax,8\)
+.*Warning:.*
+ 513 08cf 368C5912 mov %ds,%ss:0x12\(%ecx,8\)
+.*Warning:.*
+ 514 08d3 368C5A12 mov %ds,%ss:0x12\(%edx,8\)
+.*Warning:.*
+ 515 08d7 368C5B12 mov %ds,%ss:0x12\(%ebx,8\)
+.*Warning:.*
+ 516 08db 8C5C2412 mov %ds,%ss:0x12\(%esp,8\)
+.*Warning:.*
+ 517 08df 8C5D12 mov %ds,%ss:0x12\(%ebp,8\)
+.*Warning:.*
+ 518 08e2 368C5E12 mov %ds,%ss:0x12\(%esi,8\)
+.*Warning:.*
+ 519 08e6 368C5F12 mov %ds,%ss:0x12\(%edi,8\)
+.*Warning:.*
+ 520 08ea 368C5CE8 12 mov %ds,%ss:0x12\(%eax,%ebp,8\)
+ 521 08ef 368C5CE9 12 mov %ds,%ss:0x12\(%ecx,%ebp,8\)
+ 522 08f4 368C5CEA 12 mov %ds,%ss:0x12\(%edx,%ebp,8\)
+ 523 08f9 368C5CEB 12 mov %ds,%ss:0x12\(%ebx,%ebp,8\)
+ 524 08fe 8C5CEC12 mov %ds,%ss:0x12\(%esp,%ebp,8\)
+ 525 0902 8C5CED12 mov %ds,%ss:0x12\(%ebp,%ebp,8\)
+ 526 0906 368C5CEE 12 mov %ds,%ss:0x12\(%esi,%ebp,8\)
+ 527 090b 368C5CEF 12 mov %ds,%ss:0x12\(%edi,%ebp,8\)
+ 528 0910 368C5CF0 12 mov %ds,%ss:0x12\(%eax,%esi,8\)
+ 529 0915 368C5CF1 12 mov %ds,%ss:0x12\(%ecx,%esi,8\)
+ 530 091a 368C5CF2 12 mov %ds,%ss:0x12\(%edx,%esi,8\)
+ 531 091f 368C5CF3 12 mov %ds,%ss:0x12\(%ebx,%esi,8\)
+ 532 0924 8C5CF412 mov %ds,%ss:0x12\(%esp,%esi,8\)
+ 533 0928 8C5CF512 mov %ds,%ss:0x12\(%ebp,%esi,8\)
+ 534 092c 368C5CF6 12 mov %ds,%ss:0x12\(%esi,%esi,8\)
+ 535 0931 368C5CF7 12 mov %ds,%ss:0x12\(%edi,%esi,8\)
+ 536 0936 368C5CF8 12 mov %ds,%ss:0x12\(%eax,%edi,8\)
+ 537 093b 368C5CFA 12 mov %ds,%ss:0x12\(%edx,%edi,8\)
+ 538 0940 368C5CF9 12 mov %ds,%ss:0x12\(%ecx,%edi,8\)
+ 539 0945 368C5CFB 12 mov %ds,%ss:0x12\(%ebx,%edi,8\)
+ 540 094a 8C5CFC12 mov %ds,%ss:0x12\(%esp,%edi,8\)
+ 541 094e 8C5CFD12 mov %ds,%ss:0x12\(%ebp,%edi,8\)
+ 542 0952 368C5CFE 12 mov %ds,%ss:0x12\(%esi,%edi,8\)
+ 543 0957 368C5CFF 12 mov %ds,%ss:0x12\(%edi,%edi,8\)
+ 544 095c 368C9C00 78563412 mov %ds,%ss:0x12345678\(%eax,%eax,1\)
+ 545 0964 368C9C01 78563412 mov %ds,%ss:0x12345678\(%ecx,%eax,1\)
+ 546 096c 368C9C02 78563412 mov %ds,%ss:0x12345678\(%edx,%eax,1\)
+ 547 0974 368C9C03 78563412 mov %ds,%ss:0x12345678\(%ebx,%eax,1\)
+ 548 097c 8C9C0478 563412 mov %ds,%ss:0x12345678\(%esp,%eax,1\)
+ 549 0983 8C9C0578 563412 mov %ds,%ss:0x12345678\(%ebp,%eax,1\)
+ 550 098a 368C9C06 78563412 mov %ds,%ss:0x12345678\(%esi,%eax,1\)
+ 551 0992 368C9C07 78563412 mov %ds,%ss:0x12345678\(%edi,%eax,1\)
+ 552 099a 368C9C08 78563412 mov %ds,%ss:0x12345678\(%eax,%ecx,1\)
+ 553 09a2 368C9C09 78563412 mov %ds,%ss:0x12345678\(%ecx,%ecx,1\)
+ 554 09aa 368C9C0A 78563412 mov %ds,%ss:0x12345678\(%edx,%ecx,1\)
+ 555 09b2 368C9C0B 78563412 mov %ds,%ss:0x12345678\(%ebx,%ecx,1\)
+ 556 09ba 8C9C0C78 563412 mov %ds,%ss:0x12345678\(%esp,%ecx,1\)
+ 557 09c1 8C9C0D78 563412 mov %ds,%ss:0x12345678\(%ebp,%ecx,1\)
+ 558 09c8 368C9C0E 78563412 mov %ds,%ss:0x12345678\(%esi,%ecx,1\)
+ 559 09d0 368C9C0F 78563412 mov %ds,%ss:0x12345678\(%edi,%ecx,1\)
+ 560 09d8 368C9C10 78563412 mov %ds,%ss:0x12345678\(%eax,%edx,1\)
+ 561 09e0 368C9C11 78563412 mov %ds,%ss:0x12345678\(%ecx,%edx,1\)
+ 562 09e8 368C9C12 78563412 mov %ds,%ss:0x12345678\(%edx,%edx,1\)
+ 563 09f0 368C9C13 78563412 mov %ds,%ss:0x12345678\(%ebx,%edx,1\)
+ 564 09f8 8C9C1478 563412 mov %ds,%ss:0x12345678\(%esp,%edx,1\)
+ 565 09ff 8C9C1578 563412 mov %ds,%ss:0x12345678\(%ebp,%edx,1\)
+ 566 0a06 368C9C16 78563412 mov %ds,%ss:0x12345678\(%esi,%edx,1\)
+ 567 0a0e 368C9C17 78563412 mov %ds,%ss:0x12345678\(%edi,%edx,1\)
+ 568 0a16 368C9C18 78563412 mov %ds,%ss:0x12345678\(%eax,%ebx,1\)
+ 569 0a1e 368C9C19 78563412 mov %ds,%ss:0x12345678\(%ecx,%ebx,1\)
+ 570 0a26 368C9C1A 78563412 mov %ds,%ss:0x12345678\(%edx,%ebx,1\)
+ 571 0a2e 368C9C1B 78563412 mov %ds,%ss:0x12345678\(%ebx,%ebx,1\)
+ 572 0a36 8C9C1C78 563412 mov %ds,%ss:0x12345678\(%esp,%ebx,1\)
+ 573 0a3d 8C9C1D78 563412 mov %ds,%ss:0x12345678\(%ebp,%ebx,1\)
+ 574 0a44 368C9C1E 78563412 mov %ds,%ss:0x12345678\(%esi,%ebx,1\)
+ 575 0a4c 368C9C1F 78563412 mov %ds,%ss:0x12345678\(%edi,%ebx,1\)
+ 576 0a54 368C9878 563412 mov %ds,%ss:0x12345678\(%eax,1\)
+ 577 0a5b 368C9978 563412 mov %ds,%ss:0x12345678\(%ecx,1\)
+ 578 0a62 368C9A78 563412 mov %ds,%ss:0x12345678\(%edx,1\)
+ 579 0a69 368C9B78 563412 mov %ds,%ss:0x12345678\(%ebx,1\)
+ 580 0a70 8C9C2478 563412 mov %ds,%ss:0x12345678\(%esp,1\)
+ 581 0a77 8C9D7856 3412 mov %ds,%ss:0x12345678\(%ebp,1\)
+ 582 0a7d 368C9E78 563412 mov %ds,%ss:0x12345678\(%esi,1\)
+ 583 0a84 368C9F78 563412 mov %ds,%ss:0x12345678\(%edi,1\)
+ 584 0a8b 368C9C28 78563412 mov %ds,%ss:0x12345678\(%eax,%ebp,1\)
+ 585 0a93 368C9C29 78563412 mov %ds,%ss:0x12345678\(%ecx,%ebp,1\)
+ 586 0a9b 368C9C2A 78563412 mov %ds,%ss:0x12345678\(%edx,%ebp,1\)
+ 587 0aa3 368C9C2B 78563412 mov %ds,%ss:0x12345678\(%ebx,%ebp,1\)
+ 588 0aab 8C9C2C78 563412 mov %ds,%ss:0x12345678\(%esp,%ebp,1\)
+ 589 0ab2 8C9C2D78 563412 mov %ds,%ss:0x12345678\(%ebp,%ebp,1\)
+ 590 0ab9 368C9C2E 78563412 mov %ds,%ss:0x12345678\(%esi,%ebp,1\)
+ 591 0ac1 368C9C2F 78563412 mov %ds,%ss:0x12345678\(%edi,%ebp,1\)
+ 592 0ac9 368C9C30 78563412 mov %ds,%ss:0x12345678\(%eax,%esi,1\)
+ 593 0ad1 368C9C31 78563412 mov %ds,%ss:0x12345678\(%ecx,%esi,1\)
+ 594 0ad9 368C9C32 78563412 mov %ds,%ss:0x12345678\(%edx,%esi,1\)
+ 595 0ae1 368C9C33 78563412 mov %ds,%ss:0x12345678\(%ebx,%esi,1\)
+ 596 0ae9 8C9C3478 563412 mov %ds,%ss:0x12345678\(%esp,%esi,1\)
+ 597 0af0 8C9C3578 563412 mov %ds,%ss:0x12345678\(%ebp,%esi,1\)
+ 598 0af7 368C9C36 78563412 mov %ds,%ss:0x12345678\(%esi,%esi,1\)
+ 599 0aff 368C9C37 78563412 mov %ds,%ss:0x12345678\(%edi,%esi,1\)
+ 600 0b07 368C9C38 78563412 mov %ds,%ss:0x12345678\(%eax,%edi,1\)
+ 601 0b0f 368C9C39 78563412 mov %ds,%ss:0x12345678\(%ecx,%edi,1\)
+ 602 0b17 368C9C3A 78563412 mov %ds,%ss:0x12345678\(%edx,%edi,1\)
+ 603 0b1f 368C9C3B 78563412 mov %ds,%ss:0x12345678\(%ebx,%edi,1\)
+ 604 0b27 8C9C3C78 563412 mov %ds,%ss:0x12345678\(%esp,%edi,1\)
+ 605 0b2e 8C9C3D78 563412 mov %ds,%ss:0x12345678\(%ebp,%edi,1\)
+ 606 0b35 368C9C3E 78563412 mov %ds,%ss:0x12345678\(%esi,%edi,1\)
+ 607 0b3d 368C9C3F 78563412 mov %ds,%ss:0x12345678\(%edi,%edi,1\)
+ 608 0b45 368C9C40 78563412 mov %ds,%ss:0x12345678\(%eax,%eax,2\)
+ 609 0b4d 368C9C41 78563412 mov %ds,%ss:0x12345678\(%ecx,%eax,2\)
+ 610 0b55 368C9C42 78563412 mov %ds,%ss:0x12345678\(%edx,%eax,2\)
+ 611 0b5d 368C9C43 78563412 mov %ds,%ss:0x12345678\(%ebx,%eax,2\)
+ 612 0b65 8C9C4478 563412 mov %ds,%ss:0x12345678\(%esp,%eax,2\)
+ 613 0b6c 8C9C4578 563412 mov %ds,%ss:0x12345678\(%ebp,%eax,2\)
+ 614 0b73 368C9C46 78563412 mov %ds,%ss:0x12345678\(%esi,%eax,2\)
+ 615 0b7b 368C9C47 78563412 mov %ds,%ss:0x12345678\(%edi,%eax,2\)
+ 616 0b83 368C9C48 78563412 mov %ds,%ss:0x12345678\(%eax,%ecx,2\)
+ 617 0b8b 368C9C49 78563412 mov %ds,%ss:0x12345678\(%ecx,%ecx,2\)
+ 618 0b93 368C9C4A 78563412 mov %ds,%ss:0x12345678\(%edx,%ecx,2\)
+ 619 0b9b 368C9C4B 78563412 mov %ds,%ss:0x12345678\(%ebx,%ecx,2\)
+ 620 0ba3 8C9C4C78 563412 mov %ds,%ss:0x12345678\(%esp,%ecx,2\)
+ 621 0baa 8C9C4D78 563412 mov %ds,%ss:0x12345678\(%ebp,%ecx,2\)
+ 622 0bb1 368C9C4E 78563412 mov %ds,%ss:0x12345678\(%esi,%ecx,2\)
+ 623 0bb9 368C9C4F 78563412 mov %ds,%ss:0x12345678\(%edi,%ecx,2\)
+ 624 0bc1 368C9C50 78563412 mov %ds,%ss:0x12345678\(%eax,%edx,2\)
+ 625 0bc9 368C9C51 78563412 mov %ds,%ss:0x12345678\(%ecx,%edx,2\)
+ 626 0bd1 368C9C52 78563412 mov %ds,%ss:0x12345678\(%edx,%edx,2\)
+ 627 0bd9 368C9C53 78563412 mov %ds,%ss:0x12345678\(%ebx,%edx,2\)
+ 628 0be1 8C9C5478 563412 mov %ds,%ss:0x12345678\(%esp,%edx,2\)
+ 629 0be8 8C9C5578 563412 mov %ds,%ss:0x12345678\(%ebp,%edx,2\)
+ 630 0bef 368C9C56 78563412 mov %ds,%ss:0x12345678\(%esi,%edx,2\)
+ 631 0bf7 368C9C57 78563412 mov %ds,%ss:0x12345678\(%edi,%edx,2\)
+ 632 0bff 368C9C58 78563412 mov %ds,%ss:0x12345678\(%eax,%ebx,2\)
+ 633 0c07 368C9C59 78563412 mov %ds,%ss:0x12345678\(%ecx,%ebx,2\)
+ 634 0c0f 368C9C5A 78563412 mov %ds,%ss:0x12345678\(%edx,%ebx,2\)
+ 635 0c17 368C9C5B 78563412 mov %ds,%ss:0x12345678\(%ebx,%ebx,2\)
+ 636 0c1f 8C9C5C78 563412 mov %ds,%ss:0x12345678\(%esp,%ebx,2\)
+ 637 0c26 8C9C5D78 563412 mov %ds,%ss:0x12345678\(%ebp,%ebx,2\)
+ 638 0c2d 368C9C5E 78563412 mov %ds,%ss:0x12345678\(%esi,%ebx,2\)
+ 639 0c35 368C9C5F 78563412 mov %ds,%ss:0x12345678\(%edi,%ebx,2\)
+ 640 0c3d 368C9878 563412 mov %ds,%ss:0x12345678\(%eax,2\)
+.*Warning:.*
+ 641 0c44 368C9978 563412 mov %ds,%ss:0x12345678\(%ecx,2\)
+.*Warning:.*
+ 642 0c4b 368C9A78 563412 mov %ds,%ss:0x12345678\(%edx,2\)
+.*Warning:.*
+ 643 0c52 368C9B78 563412 mov %ds,%ss:0x12345678\(%ebx,2\)
+.*Warning:.*
+ 644 0c59 8C9C2478 563412 mov %ds,%ss:0x12345678\(%esp,2\)
+.*Warning:.*
+ 645 0c60 8C9D7856 3412 mov %ds,%ss:0x12345678\(%ebp,2\)
+.*Warning:.*
+ 646 0c66 368C9E78 563412 mov %ds,%ss:0x12345678\(%esi,2\)
+.*Warning:.*
+ 647 0c6d 368C9F78 563412 mov %ds,%ss:0x12345678\(%edi,2\)
+.*Warning:.*
+ 648 0c74 368C9C68 78563412 mov %ds,%ss:0x12345678\(%eax,%ebp,2\)
+ 649 0c7c 368C9C69 78563412 mov %ds,%ss:0x12345678\(%ecx,%ebp,2\)
+ 650 0c84 368C9C6A 78563412 mov %ds,%ss:0x12345678\(%edx,%ebp,2\)
+ 651 0c8c 368C9C6B 78563412 mov %ds,%ss:0x12345678\(%ebx,%ebp,2\)
+ 652 0c94 8C9C6C78 563412 mov %ds,%ss:0x12345678\(%esp,%ebp,2\)
+ 653 0c9b 8C9C6D78 563412 mov %ds,%ss:0x12345678\(%ebp,%ebp,2\)
+ 654 0ca2 368C9C6E 78563412 mov %ds,%ss:0x12345678\(%esi,%ebp,2\)
+ 655 0caa 368C9C6F 78563412 mov %ds,%ss:0x12345678\(%edi,%ebp,2\)
+ 656 0cb2 368C9C70 78563412 mov %ds,%ss:0x12345678\(%eax,%esi,2\)
+ 657 0cba 368C9C71 78563412 mov %ds,%ss:0x12345678\(%ecx,%esi,2\)
+ 658 0cc2 368C9C72 78563412 mov %ds,%ss:0x12345678\(%edx,%esi,2\)
+ 659 0cca 368C9C73 78563412 mov %ds,%ss:0x12345678\(%ebx,%esi,2\)
+ 660 0cd2 8C9C7478 563412 mov %ds,%ss:0x12345678\(%esp,%esi,2\)
+ 661 0cd9 8C9C7578 563412 mov %ds,%ss:0x12345678\(%ebp,%esi,2\)
+ 662 0ce0 368C9C76 78563412 mov %ds,%ss:0x12345678\(%esi,%esi,2\)
+ 663 0ce8 368C9C77 78563412 mov %ds,%ss:0x12345678\(%edi,%esi,2\)
+ 664 0cf0 368C9C78 78563412 mov %ds,%ss:0x12345678\(%eax,%edi,2\)
+ 665 0cf8 368C9C79 78563412 mov %ds,%ss:0x12345678\(%ecx,%edi,2\)
+ 666 0d00 368C9C7A 78563412 mov %ds,%ss:0x12345678\(%edx,%edi,2\)
+ 667 0d08 368C9C7B 78563412 mov %ds,%ss:0x12345678\(%ebx,%edi,2\)
+ 668 0d10 8C9C7C78 563412 mov %ds,%ss:0x12345678\(%esp,%edi,2\)
+ 669 0d17 8C9C7D78 563412 mov %ds,%ss:0x12345678\(%ebp,%edi,2\)
+ 670 0d1e 368C9C7E 78563412 mov %ds,%ss:0x12345678\(%esi,%edi,2\)
+ 671 0d26 368C9C7F 78563412 mov %ds,%ss:0x12345678\(%edi,%edi,2\)
+ 672 0d2e 368C9C80 78563412 mov %ds,%ss:0x12345678\(%eax,%eax,4\)
+ 673 0d36 368C9C81 78563412 mov %ds,%ss:0x12345678\(%ecx,%eax,4\)
+ 674 0d3e 368C9C82 78563412 mov %ds,%ss:0x12345678\(%edx,%eax,4\)
+ 675 0d46 368C9C83 78563412 mov %ds,%ss:0x12345678\(%ebx,%eax,4\)
+ 676 0d4e 8C9C8478 563412 mov %ds,%ss:0x12345678\(%esp,%eax,4\)
+ 677 0d55 8C9C8578 563412 mov %ds,%ss:0x12345678\(%ebp,%eax,4\)
+ 678 0d5c 368C9C86 78563412 mov %ds,%ss:0x12345678\(%esi,%eax,4\)
+ 679 0d64 368C9C87 78563412 mov %ds,%ss:0x12345678\(%edi,%eax,4\)
+ 680 0d6c 368C9C88 78563412 mov %ds,%ss:0x12345678\(%eax,%ecx,4\)
+ 681 0d74 368C9C89 78563412 mov %ds,%ss:0x12345678\(%ecx,%ecx,4\)
+ 682 0d7c 368C9C8A 78563412 mov %ds,%ss:0x12345678\(%edx,%ecx,4\)
+ 683 0d84 368C9C8B 78563412 mov %ds,%ss:0x12345678\(%ebx,%ecx,4\)
+ 684 0d8c 8C9C8C78 563412 mov %ds,%ss:0x12345678\(%esp,%ecx,4\)
+ 685 0d93 8C9C8D78 563412 mov %ds,%ss:0x12345678\(%ebp,%ecx,4\)
+ 686 0d9a 368C9C8E 78563412 mov %ds,%ss:0x12345678\(%esi,%ecx,4\)
+ 687 0da2 368C9C8F 78563412 mov %ds,%ss:0x12345678\(%edi,%ecx,4\)
+ 688 0daa 368C9C90 78563412 mov %ds,%ss:0x12345678\(%eax,%edx,4\)
+ 689 0db2 368C9C91 78563412 mov %ds,%ss:0x12345678\(%ecx,%edx,4\)
+ 690 0dba 368C9C92 78563412 mov %ds,%ss:0x12345678\(%edx,%edx,4\)
+ 691 0dc2 368C9C93 78563412 mov %ds,%ss:0x12345678\(%ebx,%edx,4\)
+ 692 0dca 8C9C9478 563412 mov %ds,%ss:0x12345678\(%esp,%edx,4\)
+ 693 0dd1 8C9C9578 563412 mov %ds,%ss:0x12345678\(%ebp,%edx,4\)
+ 694 0dd8 368C9C96 78563412 mov %ds,%ss:0x12345678\(%esi,%edx,4\)
+ 695 0de0 368C9C97 78563412 mov %ds,%ss:0x12345678\(%edi,%edx,4\)
+ 696 0de8 368C9C98 78563412 mov %ds,%ss:0x12345678\(%eax,%ebx,4\)
+ 697 0df0 368C9C99 78563412 mov %ds,%ss:0x12345678\(%ecx,%ebx,4\)
+ 698 0df8 368C9C9A 78563412 mov %ds,%ss:0x12345678\(%edx,%ebx,4\)
+ 699 0e00 368C9C9B 78563412 mov %ds,%ss:0x12345678\(%ebx,%ebx,4\)
+ 700 0e08 8C9C9C78 563412 mov %ds,%ss:0x12345678\(%esp,%ebx,4\)
+ 701 0e0f 8C9C9D78 563412 mov %ds,%ss:0x12345678\(%ebp,%ebx,4\)
+ 702 0e16 368C9C9E 78563412 mov %ds,%ss:0x12345678\(%esi,%ebx,4\)
+ 703 0e1e 368C9C9F 78563412 mov %ds,%ss:0x12345678\(%edi,%ebx,4\)
+ 704 0e26 368C9878 563412 mov %ds,%ss:0x12345678\(%eax,4\)
+.*Warning:.*
+ 705 0e2d 368C9978 563412 mov %ds,%ss:0x12345678\(%ecx,4\)
+.*Warning:.*
+ 706 0e34 368C9A78 563412 mov %ds,%ss:0x12345678\(%edx,4\)
+.*Warning:.*
+ 707 0e3b 368C9B78 563412 mov %ds,%ss:0x12345678\(%ebx,4\)
+.*Warning:.*
+ 708 0e42 8C9C2478 563412 mov %ds,%ss:0x12345678\(%esp,4\)
+.*Warning:.*
+ 709 0e49 8C9D7856 3412 mov %ds,%ss:0x12345678\(%ebp,4\)
+.*Warning:.*
+ 710 0e4f 368C9E78 563412 mov %ds,%ss:0x12345678\(%esi,4\)
+.*Warning:.*
+ 711 0e56 368C9F78 563412 mov %ds,%ss:0x12345678\(%edi,4\)
+.*Warning:.*
+ 712 0e5d 368C9CA8 78563412 mov %ds,%ss:0x12345678\(%eax,%ebp,4\)
+ 713 0e65 368C9CA9 78563412 mov %ds,%ss:0x12345678\(%ecx,%ebp,4\)
+ 714 0e6d 368C9CAA 78563412 mov %ds,%ss:0x12345678\(%edx,%ebp,4\)
+ 715 0e75 368C9CAB 78563412 mov %ds,%ss:0x12345678\(%ebx,%ebp,4\)
+ 716 0e7d 8C9CAC78 563412 mov %ds,%ss:0x12345678\(%esp,%ebp,4\)
+ 717 0e84 8C9CAD78 563412 mov %ds,%ss:0x12345678\(%ebp,%ebp,4\)
+ 718 0e8b 368C9CAE 78563412 mov %ds,%ss:0x12345678\(%esi,%ebp,4\)
+ 719 0e93 368C9CAF 78563412 mov %ds,%ss:0x12345678\(%edi,%ebp,4\)
+ 720 0e9b 368C9CB0 78563412 mov %ds,%ss:0x12345678\(%eax,%esi,4\)
+ 721 0ea3 368C9CB1 78563412 mov %ds,%ss:0x12345678\(%ecx,%esi,4\)
+ 722 0eab 368C9CB2 78563412 mov %ds,%ss:0x12345678\(%edx,%esi,4\)
+ 723 0eb3 368C9CB3 78563412 mov %ds,%ss:0x12345678\(%ebx,%esi,4\)
+ 724 0ebb 8C9CB478 563412 mov %ds,%ss:0x12345678\(%esp,%esi,4\)
+ 725 0ec2 8C9CB578 563412 mov %ds,%ss:0x12345678\(%ebp,%esi,4\)
+ 726 0ec9 368C9CB6 78563412 mov %ds,%ss:0x12345678\(%esi,%esi,4\)
+ 727 0ed1 368C9CB7 78563412 mov %ds,%ss:0x12345678\(%edi,%esi,4\)
+ 728 0ed9 368C9CB8 78563412 mov %ds,%ss:0x12345678\(%eax,%edi,4\)
+ 729 0ee1 368C9CB9 78563412 mov %ds,%ss:0x12345678\(%ecx,%edi,4\)
+ 730 0ee9 368C9CBA 78563412 mov %ds,%ss:0x12345678\(%edx,%edi,4\)
+ 731 0ef1 368C9CBB 78563412 mov %ds,%ss:0x12345678\(%ebx,%edi,4\)
+ 732 0ef9 8C9CBC78 563412 mov %ds,%ss:0x12345678\(%esp,%edi,4\)
+ 733 0f00 8C9CBD78 563412 mov %ds,%ss:0x12345678\(%ebp,%edi,4\)
+ 734 0f07 368C9CBE 78563412 mov %ds,%ss:0x12345678\(%esi,%edi,4\)
+ 735 0f0f 368C9CBF 78563412 mov %ds,%ss:0x12345678\(%edi,%edi,4\)
+ 736 0f17 368C9CC0 78563412 mov %ds,%ss:0x12345678\(%eax,%eax,8\)
+ 737 0f1f 368C9CC1 78563412 mov %ds,%ss:0x12345678\(%ecx,%eax,8\)
+ 738 0f27 368C9CC2 78563412 mov %ds,%ss:0x12345678\(%edx,%eax,8\)
+ 739 0f2f 368C9CC3 78563412 mov %ds,%ss:0x12345678\(%ebx,%eax,8\)
+ 740 0f37 8C9CC478 563412 mov %ds,%ss:0x12345678\(%esp,%eax,8\)
+ 741 0f3e 8C9CC578 563412 mov %ds,%ss:0x12345678\(%ebp,%eax,8\)
+ 742 0f45 368C9CC6 78563412 mov %ds,%ss:0x12345678\(%esi,%eax,8\)
+ 743 0f4d 368C9CC7 78563412 mov %ds,%ss:0x12345678\(%edi,%eax,8\)
+ 744 0f55 368C9CC8 78563412 mov %ds,%ss:0x12345678\(%eax,%ecx,8\)
+ 745 0f5d 368C9CC9 78563412 mov %ds,%ss:0x12345678\(%ecx,%ecx,8\)
+ 746 0f65 368C9CCA 78563412 mov %ds,%ss:0x12345678\(%edx,%ecx,8\)
+ 747 0f6d 368C9CCB 78563412 mov %ds,%ss:0x12345678\(%ebx,%ecx,8\)
+ 748 0f75 8C9CCC78 563412 mov %ds,%ss:0x12345678\(%esp,%ecx,8\)
+ 749 0f7c 8C9CCD78 563412 mov %ds,%ss:0x12345678\(%ebp,%ecx,8\)
+ 750 0f83 368C9CCE 78563412 mov %ds,%ss:0x12345678\(%esi,%ecx,8\)
+ 751 0f8b 368C9CCF 78563412 mov %ds,%ss:0x12345678\(%edi,%ecx,8\)
+ 752 0f93 368C9CD0 78563412 mov %ds,%ss:0x12345678\(%eax,%edx,8\)
+ 753 0f9b 368C9CD1 78563412 mov %ds,%ss:0x12345678\(%ecx,%edx,8\)
+ 754 0fa3 368C9CD2 78563412 mov %ds,%ss:0x12345678\(%edx,%edx,8\)
+ 755 0fab 368C9CD3 78563412 mov %ds,%ss:0x12345678\(%ebx,%edx,8\)
+ 756 0fb3 8C9CD478 563412 mov %ds,%ss:0x12345678\(%esp,%edx,8\)
+ 757 0fba 8C9CD578 563412 mov %ds,%ss:0x12345678\(%ebp,%edx,8\)
+ 758 0fc1 368C9CD6 78563412 mov %ds,%ss:0x12345678\(%esi,%edx,8\)
+ 759 0fc9 368C9CD7 78563412 mov %ds,%ss:0x12345678\(%edi,%edx,8\)
+ 760 0fd1 368C9CD8 78563412 mov %ds,%ss:0x12345678\(%eax,%ebx,8\)
+ 761 0fd9 368C9CD9 78563412 mov %ds,%ss:0x12345678\(%ecx,%ebx,8\)
+ 762 0fe1 368C9CDA 78563412 mov %ds,%ss:0x12345678\(%edx,%ebx,8\)
+ 763 0fe9 368C9CDB 78563412 mov %ds,%ss:0x12345678\(%ebx,%ebx,8\)
+ 764 0ff1 8C9CDC78 563412 mov %ds,%ss:0x12345678\(%esp,%ebx,8\)
+ 765 0ff8 8C9CDD78 563412 mov %ds,%ss:0x12345678\(%ebp,%ebx,8\)
+ 766 0fff 368C9CDE 78563412 mov %ds,%ss:0x12345678\(%esi,%ebx,8\)
+ 767 1007 368C9CDF 78563412 mov %ds,%ss:0x12345678\(%edi,%ebx,8\)
+ 768 100f 368C9878 563412 mov %ds,%ss:0x12345678\(%eax,8\)
+.*Warning:.*
+ 769 1016 368C9978 563412 mov %ds,%ss:0x12345678\(%ecx,8\)
+.*Warning:.*
+ 770 101d 368C9A78 563412 mov %ds,%ss:0x12345678\(%edx,8\)
+.*Warning:.*
+ 771 1024 368C9B78 563412 mov %ds,%ss:0x12345678\(%ebx,8\)
+.*Warning:.*
+ 772 102b 8C9C2478 563412 mov %ds,%ss:0x12345678\(%esp,8\)
+.*Warning:.*
+ 773 1032 8C9D7856 3412 mov %ds,%ss:0x12345678\(%ebp,8\)
+.*Warning:.*
+ 774 1038 368C9E78 563412 mov %ds,%ss:0x12345678\(%esi,8\)
+.*Warning:.*
+ 775 103f 368C9F78 563412 mov %ds,%ss:0x12345678\(%edi,8\)
+.*Warning:.*
+ 776 1046 368C9CE8 78563412 mov %ds,%ss:0x12345678\(%eax,%ebp,8\)
+ 777 104e 368C9CE9 78563412 mov %ds,%ss:0x12345678\(%ecx,%ebp,8\)
+ 778 1056 368C9CEA 78563412 mov %ds,%ss:0x12345678\(%edx,%ebp,8\)
+ 779 105e 368C9CEB 78563412 mov %ds,%ss:0x12345678\(%ebx,%ebp,8\)
+ 780 1066 8C9CEC78 563412 mov %ds,%ss:0x12345678\(%esp,%ebp,8\)
+ 781 106d 8C9CED78 563412 mov %ds,%ss:0x12345678\(%ebp,%ebp,8\)
+ 782 1074 368C9CEE 78563412 mov %ds,%ss:0x12345678\(%esi,%ebp,8\)
+ 783 107c 368C9CEF 78563412 mov %ds,%ss:0x12345678\(%edi,%ebp,8\)
+ 784 1084 368C9CF0 78563412 mov %ds,%ss:0x12345678\(%eax,%esi,8\)
+ 785 108c 368C9CF1 78563412 mov %ds,%ss:0x12345678\(%ecx,%esi,8\)
+ 786 1094 368C9CF2 78563412 mov %ds,%ss:0x12345678\(%edx,%esi,8\)
+ 787 109c 368C9CF3 78563412 mov %ds,%ss:0x12345678\(%ebx,%esi,8\)
+ 788 10a4 8C9CF478 563412 mov %ds,%ss:0x12345678\(%esp,%esi,8\)
+ 789 10ab 8C9CF578 563412 mov %ds,%ss:0x12345678\(%ebp,%esi,8\)
+ 790 10b2 368C9CF6 78563412 mov %ds,%ss:0x12345678\(%esi,%esi,8\)
+ 791 10ba 368C9CF7 78563412 mov %ds,%ss:0x12345678\(%edi,%esi,8\)
+ 792 10c2 368C9CF8 78563412 mov %ds,%ss:0x12345678\(%eax,%edi,8\)
+ 793 10ca 368C9CFA 78563412 mov %ds,%ss:0x12345678\(%edx,%edi,8\)
+ 794 10d2 368C9CF9 78563412 mov %ds,%ss:0x12345678\(%ecx,%edi,8\)
+ 795 10da 368C9CFB 78563412 mov %ds,%ss:0x12345678\(%ebx,%edi,8\)
+ 796 10e2 8C9CFC78 563412 mov %ds,%ss:0x12345678\(%esp,%edi,8\)
+ 797 10e9 8C9CFD78 563412 mov %ds,%ss:0x12345678\(%ebp,%edi,8\)
+ 798 10f0 368C9CFE 78563412 mov %ds,%ss:0x12345678\(%esi,%edi,8\)
+ 799 10f8 368C9CFF 78563412 mov %ds,%ss:0x12345678\(%edi,%edi,8\)
+ 800 1100 8C5C0500 mov %ds,%ss:\(%ebp,%eax,1\)
+ 801 1104 8C5C0D00 mov %ds,%ss:\(%ebp,%ecx,1\)
+ 802 1108 8C5C1500 mov %ds,%ss:\(%ebp,%edx,1\)
+ 803 110c 8C5C1D00 mov %ds,%ss:\(%ebp,%ebx,1\)
+ 804 1110 8C5D00 mov %ds,%ss:\(%ebp,1\)
+ 805 1113 8C5C2D00 mov %ds,%ss:\(%ebp,%ebp,1\)
+ 806 1117 8C5C3500 mov %ds,%ss:\(%ebp,%esi,1\)
+ 807 111b 8C5C3D00 mov %ds,%ss:\(%ebp,%edi,1\)
+ 808 111f 8C5C4500 mov %ds,%ss:\(%ebp,%eax,2\)
+ 809 1123 8C5C4D00 mov %ds,%ss:\(%ebp,%ecx,2\)
+ 810 1127 8C5C5500 mov %ds,%ss:\(%ebp,%edx,2\)
+ 811 112b 8C5C5D00 mov %ds,%ss:\(%ebp,%ebx,2\)
+ 812 112f 8C5D00 mov %ds,%ss:\(%ebp,2\)
+.*Warning:.*
+ 813 1132 8C5C6D00 mov %ds,%ss:\(%ebp,%ebp,2\)
+ 814 1136 8C5C7500 mov %ds,%ss:\(%ebp,%esi,2\)
+ 815 113a 8C5C7D00 mov %ds,%ss:\(%ebp,%edi,2\)
+ 816 113e 8C5C8500 mov %ds,%ss:\(%ebp,%eax,4\)
+ 817 1142 8C5C8D00 mov %ds,%ss:\(%ebp,%ecx,4\)
+ 818 1146 8C5C9500 mov %ds,%ss:\(%ebp,%edx,4\)
+ 819 114a 8C5C9D00 mov %ds,%ss:\(%ebp,%ebx,4\)
+ 820 114e 8C5D00 mov %ds,%ss:\(%ebp,4\)
+.*Warning:.*
+ 821 1151 8C5CAD00 mov %ds,%ss:\(%ebp,%ebp,4\)
+ 822 1155 8C5CB500 mov %ds,%ss:\(%ebp,%esi,4\)
+ 823 1159 8C5CBD00 mov %ds,%ss:\(%ebp,%edi,4\)
+ 824 115d 8C5CC500 mov %ds,%ss:\(%ebp,%eax,8\)
+ 825 1161 8C5CCD00 mov %ds,%ss:\(%ebp,%ecx,8\)
+ 826 1165 8C5CD500 mov %ds,%ss:\(%ebp,%edx,8\)
+ 827 1169 8C5CDD00 mov %ds,%ss:\(%ebp,%ebx,8\)
+ 828 116d 8C5D00 mov %ds,%ss:\(%ebp,8\)
+.*Warning:.*
+ 829 1170 8C5CED00 mov %ds,%ss:\(%ebp,%ebp,8\)
+ 830 1174 8C5CF500 mov %ds,%ss:\(%ebp,%esi,8\)
+ 831 1178 8C5CFD00 mov %ds,%ss:\(%ebp,%edi,8\)
+ 832 117c 368C1D12 000000 mov %ds,%ss:0x12\(,1\)
+ 833 1183 368C1D12 000000 mov %ds,%ss:0x12\(,2\)
+.*Warning:.*
+ 834 118a 368C1D12 000000 mov %ds,%ss:0x12\(,4\)
+.*Warning:.*
+ 835 1191 368C1D12 000000 mov %ds,%ss:0x12\(,8\)
+.*Warning:.*
+ 836 1198 8C18 mov %ds,%ds:\(%eax\)
+ 837 119a 8C19 mov %ds,%ds:\(%ecx\)
+ 838 119c 8C1A mov %ds,%ds:\(%edx\)
+ 839 119e 8C1B mov %ds,%ds:\(%ebx\)
+ 840 11a0 8C1D0000 0000 mov %ds,%ds:0
+ 841 11a6 8C1E mov %ds,%ds:\(%esi\)
+ 842 11a8 8C1F mov %ds,%ds:\(%edi\)
+ 843 11aa 8C5812 mov %ds,%ds:0x12\(%eax\)
+ 844 11ad 8C5912 mov %ds,%ds:0x12\(%ecx\)
+ 845 11b0 8C5A12 mov %ds,%ds:0x12\(%edx\)
+ 846 11b3 8C5B12 mov %ds,%ds:0x12\(%ebx\)
+ 847 11b6 3E8C5D12 mov %ds,%ds:0x12\(%ebp\)
+ 848 11ba 8C5E12 mov %ds,%ds:0x12\(%esi\)
+ 849 11bd 8C5F12 mov %ds,%ds:0x12\(%edi\)
+ 850 11c0 8C987856 3412 mov %ds,%ds:0x12345678\(%eax\)
+ 851 11c6 8C997856 3412 mov %ds,%ds:0x12345678\(%ecx\)
+ 852 11cc 8C9A7856 3412 mov %ds,%ds:0x12345678\(%edx\)
+ 853 11d2 8C9B7856 3412 mov %ds,%ds:0x12345678\(%ebx\)
+ 854 11d8 3E8C9D78 563412 mov %ds,%ds:0x12345678\(%ebp\)
+ 855 11df 8C9E7856 3412 mov %ds,%ds:0x12345678\(%esi\)
+ 856 11e5 8C9F7856 3412 mov %ds,%ds:0x12345678\(%edi\)
+ 857 11eb 8CD8 mov %ds,%eax
+ 858 11ed 8CD9 mov %ds,%ecx
+ 859 11ef 8CDA mov %ds,%edx
+ 860 11f1 8CDB mov %ds,%ebx
+ 861 11f3 8CDC mov %ds,%esp
+ 862 11f5 8CDD mov %ds,%ebp
+ 863 11f7 8CDE mov %ds,%esi
+ 864 11f9 8CDF mov %ds,%edi
+ 865 11fb 8C1C00 mov %ds,%ds:\(%eax,%eax,1\)
+ 866 11fe 8C1C01 mov %ds,%ds:\(%ecx,%eax,1\)
+ 867 1201 8C1C02 mov %ds,%ds:\(%edx,%eax,1\)
+ 868 1204 8C1C03 mov %ds,%ds:\(%ebx,%eax,1\)
+ 869 1207 3E8C1C04 mov %ds,%ds:\(%esp,%eax,1\)
+ 870 120b 8C1C0500 000000 mov %ds,%ds:\(,%eax,1\)
+ 871 1212 8C1C06 mov %ds,%ds:\(%esi,%eax,1\)
+ 872 1215 8C1C07 mov %ds,%ds:\(%edi,%eax,1\)
+ 873 1218 8C1C08 mov %ds,%ds:\(%eax,%ecx,1\)
+ 874 121b 8C1C09 mov %ds,%ds:\(%ecx,%ecx,1\)
+ 875 121e 8C1C0A mov %ds,%ds:\(%edx,%ecx,1\)
+ 876 1221 8C1C0B mov %ds,%ds:\(%ebx,%ecx,1\)
+ 877 1224 3E8C1C0C mov %ds,%ds:\(%esp,%ecx,1\)
+ 878 1228 8C1C0D00 000000 mov %ds,%ds:\(,%ecx,1\)
+ 879 122f 8C1C0E mov %ds,%ds:\(%esi,%ecx,1\)
+ 880 1232 8C1C0F mov %ds,%ds:\(%edi,%ecx,1\)
+ 881 1235 8C1C10 mov %ds,%ds:\(%eax,%edx,1\)
+ 882 1238 8C1C11 mov %ds,%ds:\(%ecx,%edx,1\)
+ 883 123b 8C1C12 mov %ds,%ds:\(%edx,%edx,1\)
+ 884 123e 8C1C13 mov %ds,%ds:\(%ebx,%edx,1\)
+ 885 1241 3E8C1C14 mov %ds,%ds:\(%esp,%edx,1\)
+ 886 1245 8C1C1500 000000 mov %ds,%ds:\(,%edx,1\)
+ 887 124c 8C1C16 mov %ds,%ds:\(%esi,%edx,1\)
+ 888 124f 8C1C17 mov %ds,%ds:\(%edi,%edx,1\)
+ 889 1252 8C1C18 mov %ds,%ds:\(%eax,%ebx,1\)
+ 890 1255 8C1C19 mov %ds,%ds:\(%ecx,%ebx,1\)
+ 891 1258 8C1C1A mov %ds,%ds:\(%edx,%ebx,1\)
+ 892 125b 8C1C1B mov %ds,%ds:\(%ebx,%ebx,1\)
+ 893 125e 3E8C1C1C mov %ds,%ds:\(%esp,%ebx,1\)
+ 894 1262 8C1C1D00 000000 mov %ds,%ds:\(,%ebx,1\)
+ 895 1269 8C1C1E mov %ds,%ds:\(%esi,%ebx,1\)
+ 896 126c 8C1C1F mov %ds,%ds:\(%edi,%ebx,1\)
+ 897 126f 8C18 mov %ds,%ds:\(%eax,1\)
+ 898 1271 8C19 mov %ds,%ds:\(%ecx,1\)
+ 899 1273 8C1A mov %ds,%ds:\(%edx,1\)
+ 900 1275 8C1B mov %ds,%ds:\(%ebx,1\)
+ 901 1277 3E8C1C24 mov %ds,%ds:\(%esp,1\)
+ 902 127b 8C1D0000 0000 mov %ds,%ds:\(,1\)
+ 903 1281 8C1E mov %ds,%ds:\(%esi,1\)
+ 904 1283 8C1F mov %ds,%ds:\(%edi,1\)
+ 905 1285 8C1C28 mov %ds,%ds:\(%eax,%ebp,1\)
+ 906 1288 8C1C29 mov %ds,%ds:\(%ecx,%ebp,1\)
+ 907 128b 8C1C2A mov %ds,%ds:\(%edx,%ebp,1\)
+ 908 128e 8C1C2B mov %ds,%ds:\(%ebx,%ebp,1\)
+ 909 1291 3E8C1C2C mov %ds,%ds:\(%esp,%ebp,1\)
+ 910 1295 8C1C2D00 000000 mov %ds,%ds:\(,%ebp,1\)
+ 911 129c 8C1C2E mov %ds,%ds:\(%esi,%ebp,1\)
+ 912 129f 8C1C2F mov %ds,%ds:\(%edi,%ebp,1\)
+ 913 12a2 8C1C30 mov %ds,%ds:\(%eax,%esi,1\)
+ 914 12a5 8C1C31 mov %ds,%ds:\(%ecx,%esi,1\)
+ 915 12a8 8C1C32 mov %ds,%ds:\(%edx,%esi,1\)
+ 916 12ab 8C1C33 mov %ds,%ds:\(%ebx,%esi,1\)
+ 917 12ae 3E8C1C34 mov %ds,%ds:\(%esp,%esi,1\)
+ 918 12b2 8C1C3500 000000 mov %ds,%ds:\(,%esi,1\)
+ 919 12b9 8C1C36 mov %ds,%ds:\(%esi,%esi,1\)
+ 920 12bc 8C1C37 mov %ds,%ds:\(%edi,%esi,1\)
+ 921 12bf 8C1C38 mov %ds,%ds:\(%eax,%edi,1\)
+ 922 12c2 8C1C39 mov %ds,%ds:\(%ecx,%edi,1\)
+ 923 12c5 8C1C3A mov %ds,%ds:\(%edx,%edi,1\)
+ 924 12c8 8C1C3B mov %ds,%ds:\(%ebx,%edi,1\)
+ 925 12cb 3E8C1C3C mov %ds,%ds:\(%esp,%edi,1\)
+ 926 12cf 8C1C3D00 000000 mov %ds,%ds:\(,%edi,1\)
+ 927 12d6 8C1C3E mov %ds,%ds:\(%esi,%edi,1\)
+ 928 12d9 8C1C3F mov %ds,%ds:\(%edi,%edi,1\)
+ 929 12dc 8C1C40 mov %ds,%ds:\(%eax,%eax,2\)
+ 930 12df 8C1C41 mov %ds,%ds:\(%ecx,%eax,2\)
+ 931 12e2 8C1C42 mov %ds,%ds:\(%edx,%eax,2\)
+ 932 12e5 8C1C43 mov %ds,%ds:\(%ebx,%eax,2\)
+ 933 12e8 3E8C1C44 mov %ds,%ds:\(%esp,%eax,2\)
+ 934 12ec 8C1C4500 000000 mov %ds,%ds:\(,%eax,2\)
+ 935 12f3 8C1C46 mov %ds,%ds:\(%esi,%eax,2\)
+ 936 12f6 8C1C47 mov %ds,%ds:\(%edi,%eax,2\)
+ 937 12f9 8C1C48 mov %ds,%ds:\(%eax,%ecx,2\)
+ 938 12fc 8C1C49 mov %ds,%ds:\(%ecx,%ecx,2\)
+ 939 12ff 8C1C4A mov %ds,%ds:\(%edx,%ecx,2\)
+ 940 1302 8C1C4B mov %ds,%ds:\(%ebx,%ecx,2\)
+ 941 1305 3E8C1C4C mov %ds,%ds:\(%esp,%ecx,2\)
+ 942 1309 8C1C4D00 000000 mov %ds,%ds:\(,%ecx,2\)
+ 943 1310 8C1C4E mov %ds,%ds:\(%esi,%ecx,2\)
+ 944 1313 8C1C4F mov %ds,%ds:\(%edi,%ecx,2\)
+ 945 1316 8C1C50 mov %ds,%ds:\(%eax,%edx,2\)
+ 946 1319 8C1C51 mov %ds,%ds:\(%ecx,%edx,2\)
+ 947 131c 8C1C52 mov %ds,%ds:\(%edx,%edx,2\)
+ 948 131f 8C1C53 mov %ds,%ds:\(%ebx,%edx,2\)
+ 949 1322 3E8C1C54 mov %ds,%ds:\(%esp,%edx,2\)
+ 950 1326 8C1C5500 000000 mov %ds,%ds:\(,%edx,2\)
+ 951 132d 8C1C56 mov %ds,%ds:\(%esi,%edx,2\)
+ 952 1330 8C1C57 mov %ds,%ds:\(%edi,%edx,2\)
+ 953 1333 8C1C58 mov %ds,%ds:\(%eax,%ebx,2\)
+ 954 1336 8C1C59 mov %ds,%ds:\(%ecx,%ebx,2\)
+ 955 1339 8C1C5A mov %ds,%ds:\(%edx,%ebx,2\)
+ 956 133c 8C1C5B mov %ds,%ds:\(%ebx,%ebx,2\)
+ 957 133f 3E8C1C5C mov %ds,%ds:\(%esp,%ebx,2\)
+ 958 1343 8C1C5D00 000000 mov %ds,%ds:\(,%ebx,2\)
+ 959 134a 8C1C5E mov %ds,%ds:\(%esi,%ebx,2\)
+ 960 134d 8C1C5F mov %ds,%ds:\(%edi,%ebx,2\)
+ 961 1350 8C18 mov %ds,%ds:\(%eax,2\)
+.*Warning:.*
+ 962 1352 8C19 mov %ds,%ds:\(%ecx,2\)
+.*Warning:.*
+ 963 1354 8C1A mov %ds,%ds:\(%edx,2\)
+.*Warning:.*
+ 964 1356 8C1B mov %ds,%ds:\(%ebx,2\)
+.*Warning:.*
+ 965 1358 3E8C1C24 mov %ds,%ds:\(%esp,2\)
+.*Warning:.*
+ 966 135c 8C1D0000 0000 mov %ds,%ds:\(,2\)
+.*Warning:.*
+ 967 1362 8C1E mov %ds,%ds:\(%esi,2\)
+.*Warning:.*
+ 968 1364 8C1F mov %ds,%ds:\(%edi,2\)
+.*Warning:.*
+ 969 1366 8C1C68 mov %ds,%ds:\(%eax,%ebp,2\)
+ 970 1369 8C1C69 mov %ds,%ds:\(%ecx,%ebp,2\)
+ 971 136c 8C1C6A mov %ds,%ds:\(%edx,%ebp,2\)
+ 972 136f 8C1C6B mov %ds,%ds:\(%ebx,%ebp,2\)
+ 973 1372 3E8C1C6C mov %ds,%ds:\(%esp,%ebp,2\)
+ 974 1376 8C1C6D00 000000 mov %ds,%ds:\(,%ebp,2\)
+ 975 137d 8C1C6E mov %ds,%ds:\(%esi,%ebp,2\)
+ 976 1380 8C1C6F mov %ds,%ds:\(%edi,%ebp,2\)
+ 977 1383 8C1C70 mov %ds,%ds:\(%eax,%esi,2\)
+ 978 1386 8C1C71 mov %ds,%ds:\(%ecx,%esi,2\)
+ 979 1389 8C1C72 mov %ds,%ds:\(%edx,%esi,2\)
+ 980 138c 8C1C73 mov %ds,%ds:\(%ebx,%esi,2\)
+ 981 138f 3E8C1C74 mov %ds,%ds:\(%esp,%esi,2\)
+ 982 1393 8C1C7500 000000 mov %ds,%ds:\(,%esi,2\)
+ 983 139a 8C1C76 mov %ds,%ds:\(%esi,%esi,2\)
+ 984 139d 8C1C77 mov %ds,%ds:\(%edi,%esi,2\)
+ 985 13a0 8C1C78 mov %ds,%ds:\(%eax,%edi,2\)
+ 986 13a3 8C1C79 mov %ds,%ds:\(%ecx,%edi,2\)
+ 987 13a6 8C1C7A mov %ds,%ds:\(%edx,%edi,2\)
+ 988 13a9 8C1C7B mov %ds,%ds:\(%ebx,%edi,2\)
+ 989 13ac 3E8C1C7C mov %ds,%ds:\(%esp,%edi,2\)
+ 990 13b0 8C1C7D00 000000 mov %ds,%ds:\(,%edi,2\)
+ 991 13b7 8C1C7E mov %ds,%ds:\(%esi,%edi,2\)
+ 992 13ba 8C1C7F mov %ds,%ds:\(%edi,%edi,2\)
+ 993 13bd 8C1C80 mov %ds,%ds:\(%eax,%eax,4\)
+ 994 13c0 8C1C81 mov %ds,%ds:\(%ecx,%eax,4\)
+ 995 13c3 8C1C82 mov %ds,%ds:\(%edx,%eax,4\)
+ 996 13c6 8C1C83 mov %ds,%ds:\(%ebx,%eax,4\)
+ 997 13c9 3E8C1C84 mov %ds,%ds:\(%esp,%eax,4\)
+ 998 13cd 8C1C8500 000000 mov %ds,%ds:\(,%eax,4\)
+ 999 13d4 8C1C86 mov %ds,%ds:\(%esi,%eax,4\)
+ 1000 13d7 8C1C87 mov %ds,%ds:\(%edi,%eax,4\)
+ 1001 13da 8C1C88 mov %ds,%ds:\(%eax,%ecx,4\)
+ 1002 13dd 8C1C89 mov %ds,%ds:\(%ecx,%ecx,4\)
+ 1003 13e0 8C1C8A mov %ds,%ds:\(%edx,%ecx,4\)
+ 1004 13e3 8C1C8B mov %ds,%ds:\(%ebx,%ecx,4\)
+ 1005 13e6 3E8C1C8C mov %ds,%ds:\(%esp,%ecx,4\)
+ 1006 13ea 8C1C8D00 000000 mov %ds,%ds:\(,%ecx,4\)
+ 1007 13f1 8C1C8E mov %ds,%ds:\(%esi,%ecx,4\)
+ 1008 13f4 8C1C8F mov %ds,%ds:\(%edi,%ecx,4\)
+ 1009 13f7 8C1C90 mov %ds,%ds:\(%eax,%edx,4\)
+ 1010 13fa 8C1C91 mov %ds,%ds:\(%ecx,%edx,4\)
+ 1011 13fd 8C1C92 mov %ds,%ds:\(%edx,%edx,4\)
+ 1012 1400 8C1C93 mov %ds,%ds:\(%ebx,%edx,4\)
+ 1013 1403 3E8C1C94 mov %ds,%ds:\(%esp,%edx,4\)
+ 1014 1407 8C1C9500 000000 mov %ds,%ds:\(,%edx,4\)
+ 1015 140e 8C1C96 mov %ds,%ds:\(%esi,%edx,4\)
+ 1016 1411 8C1C97 mov %ds,%ds:\(%edi,%edx,4\)
+ 1017 1414 8C1C98 mov %ds,%ds:\(%eax,%ebx,4\)
+ 1018 1417 8C1C99 mov %ds,%ds:\(%ecx,%ebx,4\)
+ 1019 141a 8C1C9A mov %ds,%ds:\(%edx,%ebx,4\)
+ 1020 141d 8C1C9B mov %ds,%ds:\(%ebx,%ebx,4\)
+ 1021 1420 3E8C1C9C mov %ds,%ds:\(%esp,%ebx,4\)
+ 1022 1424 8C1C9D00 000000 mov %ds,%ds:\(,%ebx,4\)
+ 1023 142b 8C1C9E mov %ds,%ds:\(%esi,%ebx,4\)
+ 1024 142e 8C1C9F mov %ds,%ds:\(%edi,%ebx,4\)
+ 1025 1431 8C18 mov %ds,%ds:\(%eax,4\)
+.*Warning:.*
+ 1026 1433 8C19 mov %ds,%ds:\(%ecx,4\)
+.*Warning:.*
+ 1027 1435 8C1A mov %ds,%ds:\(%edx,4\)
+.*Warning:.*
+ 1028 1437 8C1B mov %ds,%ds:\(%ebx,4\)
+.*Warning:.*
+ 1029 1439 3E8C1C24 mov %ds,%ds:\(%esp,4\)
+.*Warning:.*
+ 1030 143d 8C1D0000 0000 mov %ds,%ds:\(,4\)
+.*Warning:.*
+ 1031 1443 8C1E mov %ds,%ds:\(%esi,4\)
+.*Warning:.*
+ 1032 1445 8C1F mov %ds,%ds:\(%edi,4\)
+.*Warning:.*
+ 1033 1447 8C1CA8 mov %ds,%ds:\(%eax,%ebp,4\)
+ 1034 144a 8C1CA9 mov %ds,%ds:\(%ecx,%ebp,4\)
+ 1035 144d 8C1CAA mov %ds,%ds:\(%edx,%ebp,4\)
+ 1036 1450 8C1CAB mov %ds,%ds:\(%ebx,%ebp,4\)
+ 1037 1453 3E8C1CAC mov %ds,%ds:\(%esp,%ebp,4\)
+ 1038 1457 8C1CAD00 000000 mov %ds,%ds:\(,%ebp,4\)
+ 1039 145e 8C1CAE mov %ds,%ds:\(%esi,%ebp,4\)
+ 1040 1461 8C1CAF mov %ds,%ds:\(%edi,%ebp,4\)
+ 1041 1464 8C1CB0 mov %ds,%ds:\(%eax,%esi,4\)
+ 1042 1467 8C1CB1 mov %ds,%ds:\(%ecx,%esi,4\)
+ 1043 146a 8C1CB2 mov %ds,%ds:\(%edx,%esi,4\)
+ 1044 146d 8C1CB3 mov %ds,%ds:\(%ebx,%esi,4\)
+ 1045 1470 3E8C1CB4 mov %ds,%ds:\(%esp,%esi,4\)
+ 1046 1474 8C1CB500 000000 mov %ds,%ds:\(,%esi,4\)
+ 1047 147b 8C1CB6 mov %ds,%ds:\(%esi,%esi,4\)
+ 1048 147e 8C1CB7 mov %ds,%ds:\(%edi,%esi,4\)
+ 1049 1481 8C1CB8 mov %ds,%ds:\(%eax,%edi,4\)
+ 1050 1484 8C1CB9 mov %ds,%ds:\(%ecx,%edi,4\)
+ 1051 1487 8C1CBA mov %ds,%ds:\(%edx,%edi,4\)
+ 1052 148a 8C1CBB mov %ds,%ds:\(%ebx,%edi,4\)
+ 1053 148d 3E8C1CBC mov %ds,%ds:\(%esp,%edi,4\)
+ 1054 1491 8C1CBD00 000000 mov %ds,%ds:\(,%edi,4\)
+ 1055 1498 8C1CBE mov %ds,%ds:\(%esi,%edi,4\)
+ 1056 149b 8C1CBF mov %ds,%ds:\(%edi,%edi,4\)
+ 1057 149e 8C1CC0 mov %ds,%ds:\(%eax,%eax,8\)
+ 1058 14a1 8C1CC1 mov %ds,%ds:\(%ecx,%eax,8\)
+ 1059 14a4 8C1CC2 mov %ds,%ds:\(%edx,%eax,8\)
+ 1060 14a7 8C1CC3 mov %ds,%ds:\(%ebx,%eax,8\)
+ 1061 14aa 3E8C1CC4 mov %ds,%ds:\(%esp,%eax,8\)
+ 1062 14ae 8C1CC500 000000 mov %ds,%ds:\(,%eax,8\)
+ 1063 14b5 8C1CC6 mov %ds,%ds:\(%esi,%eax,8\)
+ 1064 14b8 8C1CC7 mov %ds,%ds:\(%edi,%eax,8\)
+ 1065 14bb 8C1CC8 mov %ds,%ds:\(%eax,%ecx,8\)
+ 1066 14be 8C1CC9 mov %ds,%ds:\(%ecx,%ecx,8\)
+ 1067 14c1 8C1CCA mov %ds,%ds:\(%edx,%ecx,8\)
+ 1068 14c4 8C1CCB mov %ds,%ds:\(%ebx,%ecx,8\)
+ 1069 14c7 3E8C1CCC mov %ds,%ds:\(%esp,%ecx,8\)
+ 1070 14cb 8C1CCD00 000000 mov %ds,%ds:\(,%ecx,8\)
+ 1071 14d2 8C1CCE mov %ds,%ds:\(%esi,%ecx,8\)
+ 1072 14d5 8C1CCF mov %ds,%ds:\(%edi,%ecx,8\)
+ 1073 14d8 8C1CD0 mov %ds,%ds:\(%eax,%edx,8\)
+ 1074 14db 8C1CD1 mov %ds,%ds:\(%ecx,%edx,8\)
+ 1075 14de 8C1CD2 mov %ds,%ds:\(%edx,%edx,8\)
+ 1076 14e1 8C1CD3 mov %ds,%ds:\(%ebx,%edx,8\)
+ 1077 14e4 3E8C1CD4 mov %ds,%ds:\(%esp,%edx,8\)
+ 1078 14e8 8C1CD500 000000 mov %ds,%ds:\(,%edx,8\)
+ 1079 14ef 8C1CD6 mov %ds,%ds:\(%esi,%edx,8\)
+ 1080 14f2 8C1CD7 mov %ds,%ds:\(%edi,%edx,8\)
+ 1081 14f5 8C1CD8 mov %ds,%ds:\(%eax,%ebx,8\)
+ 1082 14f8 8C1CD9 mov %ds,%ds:\(%ecx,%ebx,8\)
+ 1083 14fb 8C1CDA mov %ds,%ds:\(%edx,%ebx,8\)
+ 1084 14fe 8C1CDB mov %ds,%ds:\(%ebx,%ebx,8\)
+ 1085 1501 3E8C1CDC mov %ds,%ds:\(%esp,%ebx,8\)
+ 1086 1505 8C1CDD00 000000 mov %ds,%ds:\(,%ebx,8\)
+ 1087 150c 8C1CDE mov %ds,%ds:\(%esi,%ebx,8\)
+ 1088 150f 8C1CDF mov %ds,%ds:\(%edi,%ebx,8\)
+ 1089 1512 8C18 mov %ds,%ds:\(%eax,8\)
+.*Warning:.*
+ 1090 1514 8C19 mov %ds,%ds:\(%ecx,8\)
+.*Warning:.*
+ 1091 1516 8C1A mov %ds,%ds:\(%edx,8\)
+.*Warning:.*
+ 1092 1518 8C1B mov %ds,%ds:\(%ebx,8\)
+.*Warning:.*
+ 1093 151a 3E8C1C24 mov %ds,%ds:\(%esp,8\)
+.*Warning:.*
+ 1094 151e 8C1D0000 0000 mov %ds,%ds:\(,8\)
+.*Warning:.*
+ 1095 1524 8C1E mov %ds,%ds:\(%esi,8\)
+.*Warning:.*
+ 1096 1526 8C1F mov %ds,%ds:\(%edi,8\)
+.*Warning:.*
+ 1097 1528 8C1CE8 mov %ds,%ds:\(%eax,%ebp,8\)
+ 1098 152b 8C1CE9 mov %ds,%ds:\(%ecx,%ebp,8\)
+ 1099 152e 8C1CEA mov %ds,%ds:\(%edx,%ebp,8\)
+ 1100 1531 8C1CEB mov %ds,%ds:\(%ebx,%ebp,8\)
+ 1101 1534 3E8C1CEC mov %ds,%ds:\(%esp,%ebp,8\)
+ 1102 1538 8C1CED00 000000 mov %ds,%ds:\(,%ebp,8\)
+ 1103 153f 8C1CEE mov %ds,%ds:\(%esi,%ebp,8\)
+ 1104 1542 8C1CEF mov %ds,%ds:\(%edi,%ebp,8\)
+ 1105 1545 8C1CF0 mov %ds,%ds:\(%eax,%esi,8\)
+ 1106 1548 8C1CF1 mov %ds,%ds:\(%ecx,%esi,8\)
+ 1107 154b 8C1CF2 mov %ds,%ds:\(%edx,%esi,8\)
+ 1108 154e 8C1CF3 mov %ds,%ds:\(%ebx,%esi,8\)
+ 1109 1551 3E8C1CF4 mov %ds,%ds:\(%esp,%esi,8\)
+ 1110 1555 8C1CF500 000000 mov %ds,%ds:\(,%esi,8\)
+ 1111 155c 8C1CF6 mov %ds,%ds:\(%esi,%esi,8\)
+ 1112 155f 8C1CF7 mov %ds,%ds:\(%edi,%esi,8\)
+ 1113 1562 8C1CF8 mov %ds,%ds:\(%eax,%edi,8\)
+ 1114 1565 8C1CFA mov %ds,%ds:\(%edx,%edi,8\)
+ 1115 1568 8C1CF9 mov %ds,%ds:\(%ecx,%edi,8\)
+ 1116 156b 8C1CFB mov %ds,%ds:\(%ebx,%edi,8\)
+ 1117 156e 3E8C1CFC mov %ds,%ds:\(%esp,%edi,8\)
+ 1118 1572 8C1CFD00 000000 mov %ds,%ds:\(,%edi,8\)
+ 1119 1579 8C1CFE mov %ds,%ds:\(%esi,%edi,8\)
+ 1120 157c 8C1CFF mov %ds,%ds:\(%edi,%edi,8\)
+ 1121 157f 8C5C0012 mov %ds,%ds:0x12\(%eax,%eax,1\)
+ 1122 1583 8C5C0112 mov %ds,%ds:0x12\(%ecx,%eax,1\)
+ 1123 1587 8C5C0212 mov %ds,%ds:0x12\(%edx,%eax,1\)
+ 1124 158b 8C5C0312 mov %ds,%ds:0x12\(%ebx,%eax,1\)
+ 1125 158f 3E8C5C04 12 mov %ds,%ds:0x12\(%esp,%eax,1\)
+ 1126 1594 3E8C5C05 12 mov %ds,%ds:0x12\(%ebp,%eax,1\)
+ 1127 1599 8C5C0612 mov %ds,%ds:0x12\(%esi,%eax,1\)
+ 1128 159d 8C5C0712 mov %ds,%ds:0x12\(%edi,%eax,1\)
+ 1129 15a1 8C5C0812 mov %ds,%ds:0x12\(%eax,%ecx,1\)
+ 1130 15a5 8C5C0912 mov %ds,%ds:0x12\(%ecx,%ecx,1\)
+ 1131 15a9 8C5C0A12 mov %ds,%ds:0x12\(%edx,%ecx,1\)
+ 1132 15ad 8C5C0B12 mov %ds,%ds:0x12\(%ebx,%ecx,1\)
+ 1133 15b1 3E8C5C0C 12 mov %ds,%ds:0x12\(%esp,%ecx,1\)
+ 1134 15b6 3E8C5C0D 12 mov %ds,%ds:0x12\(%ebp,%ecx,1\)
+ 1135 15bb 8C5C0E12 mov %ds,%ds:0x12\(%esi,%ecx,1\)
+ 1136 15bf 8C5C0F12 mov %ds,%ds:0x12\(%edi,%ecx,1\)
+ 1137 15c3 8C5C1012 mov %ds,%ds:0x12\(%eax,%edx,1\)
+ 1138 15c7 8C5C1112 mov %ds,%ds:0x12\(%ecx,%edx,1\)
+ 1139 15cb 8C5C1212 mov %ds,%ds:0x12\(%edx,%edx,1\)
+ 1140 15cf 8C5C1312 mov %ds,%ds:0x12\(%ebx,%edx,1\)
+ 1141 15d3 3E8C5C14 12 mov %ds,%ds:0x12\(%esp,%edx,1\)
+ 1142 15d8 3E8C5C15 12 mov %ds,%ds:0x12\(%ebp,%edx,1\)
+ 1143 15dd 8C5C1612 mov %ds,%ds:0x12\(%esi,%edx,1\)
+ 1144 15e1 8C5C1712 mov %ds,%ds:0x12\(%edi,%edx,1\)
+ 1145 15e5 8C5C1812 mov %ds,%ds:0x12\(%eax,%ebx,1\)
+ 1146 15e9 8C5C1912 mov %ds,%ds:0x12\(%ecx,%ebx,1\)
+ 1147 15ed 8C5C1A12 mov %ds,%ds:0x12\(%edx,%ebx,1\)
+ 1148 15f1 8C5C1B12 mov %ds,%ds:0x12\(%ebx,%ebx,1\)
+ 1149 15f5 3E8C5C1C 12 mov %ds,%ds:0x12\(%esp,%ebx,1\)
+ 1150 15fa 3E8C5C1D 12 mov %ds,%ds:0x12\(%ebp,%ebx,1\)
+ 1151 15ff 8C5C1E12 mov %ds,%ds:0x12\(%esi,%ebx,1\)
+ 1152 1603 8C5C1F12 mov %ds,%ds:0x12\(%edi,%ebx,1\)
+ 1153 1607 8C5812 mov %ds,%ds:0x12\(%eax,1\)
+ 1154 160a 8C5912 mov %ds,%ds:0x12\(%ecx,1\)
+ 1155 160d 8C5A12 mov %ds,%ds:0x12\(%edx,1\)
+ 1156 1610 8C5B12 mov %ds,%ds:0x12\(%ebx,1\)
+ 1157 1613 3E8C5C24 12 mov %ds,%ds:0x12\(%esp,1\)
+ 1158 1618 3E8C5D12 mov %ds,%ds:0x12\(%ebp,1\)
+ 1159 161c 8C5E12 mov %ds,%ds:0x12\(%esi,1\)
+ 1160 161f 8C5F12 mov %ds,%ds:0x12\(%edi,1\)
+ 1161 1622 8C5C2812 mov %ds,%ds:0x12\(%eax,%ebp,1\)
+ 1162 1626 8C5C2912 mov %ds,%ds:0x12\(%ecx,%ebp,1\)
+ 1163 162a 8C5C2A12 mov %ds,%ds:0x12\(%edx,%ebp,1\)
+ 1164 162e 8C5C2B12 mov %ds,%ds:0x12\(%ebx,%ebp,1\)
+ 1165 1632 3E8C5C2C 12 mov %ds,%ds:0x12\(%esp,%ebp,1\)
+ 1166 1637 3E8C5C2D 12 mov %ds,%ds:0x12\(%ebp,%ebp,1\)
+ 1167 163c 8C5C2E12 mov %ds,%ds:0x12\(%esi,%ebp,1\)
+ 1168 1640 8C5C2F12 mov %ds,%ds:0x12\(%edi,%ebp,1\)
+ 1169 1644 8C5C3012 mov %ds,%ds:0x12\(%eax,%esi,1\)
+ 1170 1648 8C5C3112 mov %ds,%ds:0x12\(%ecx,%esi,1\)
+ 1171 164c 8C5C3212 mov %ds,%ds:0x12\(%edx,%esi,1\)
+ 1172 1650 8C5C3312 mov %ds,%ds:0x12\(%ebx,%esi,1\)
+ 1173 1654 3E8C5C34 12 mov %ds,%ds:0x12\(%esp,%esi,1\)
+ 1174 1659 3E8C5C35 12 mov %ds,%ds:0x12\(%ebp,%esi,1\)
+ 1175 165e 8C5C3612 mov %ds,%ds:0x12\(%esi,%esi,1\)
+ 1176 1662 8C5C3712 mov %ds,%ds:0x12\(%edi,%esi,1\)
+ 1177 1666 8C5C3812 mov %ds,%ds:0x12\(%eax,%edi,1\)
+ 1178 166a 8C5C3912 mov %ds,%ds:0x12\(%ecx,%edi,1\)
+ 1179 166e 8C5C3A12 mov %ds,%ds:0x12\(%edx,%edi,1\)
+ 1180 1672 8C5C3B12 mov %ds,%ds:0x12\(%ebx,%edi,1\)
+ 1181 1676 3E8C5C3C 12 mov %ds,%ds:0x12\(%esp,%edi,1\)
+ 1182 167b 3E8C5C3D 12 mov %ds,%ds:0x12\(%ebp,%edi,1\)
+ 1183 1680 8C5C3E12 mov %ds,%ds:0x12\(%esi,%edi,1\)
+ 1184 1684 8C5C3F12 mov %ds,%ds:0x12\(%edi,%edi,1\)
+ 1185 1688 8C5C4012 mov %ds,%ds:0x12\(%eax,%eax,2\)
+ 1186 168c 8C5C4112 mov %ds,%ds:0x12\(%ecx,%eax,2\)
+ 1187 1690 8C5C4212 mov %ds,%ds:0x12\(%edx,%eax,2\)
+ 1188 1694 8C5C4312 mov %ds,%ds:0x12\(%ebx,%eax,2\)
+ 1189 1698 3E8C5C44 12 mov %ds,%ds:0x12\(%esp,%eax,2\)
+ 1190 169d 3E8C5C45 12 mov %ds,%ds:0x12\(%ebp,%eax,2\)
+ 1191 16a2 8C5C4612 mov %ds,%ds:0x12\(%esi,%eax,2\)
+ 1192 16a6 8C5C4712 mov %ds,%ds:0x12\(%edi,%eax,2\)
+ 1193 16aa 8C5C4812 mov %ds,%ds:0x12\(%eax,%ecx,2\)
+ 1194 16ae 8C5C4912 mov %ds,%ds:0x12\(%ecx,%ecx,2\)
+ 1195 16b2 8C5C4A12 mov %ds,%ds:0x12\(%edx,%ecx,2\)
+ 1196 16b6 8C5C4B12 mov %ds,%ds:0x12\(%ebx,%ecx,2\)
+ 1197 16ba 3E8C5C4C 12 mov %ds,%ds:0x12\(%esp,%ecx,2\)
+ 1198 16bf 3E8C5C4D 12 mov %ds,%ds:0x12\(%ebp,%ecx,2\)
+ 1199 16c4 8C5C4E12 mov %ds,%ds:0x12\(%esi,%ecx,2\)
+ 1200 16c8 8C5C4F12 mov %ds,%ds:0x12\(%edi,%ecx,2\)
+ 1201 16cc 8C5C5012 mov %ds,%ds:0x12\(%eax,%edx,2\)
+ 1202 16d0 8C5C5112 mov %ds,%ds:0x12\(%ecx,%edx,2\)
+ 1203 16d4 8C5C5212 mov %ds,%ds:0x12\(%edx,%edx,2\)
+ 1204 16d8 8C5C5312 mov %ds,%ds:0x12\(%ebx,%edx,2\)
+ 1205 16dc 3E8C5C54 12 mov %ds,%ds:0x12\(%esp,%edx,2\)
+ 1206 16e1 3E8C5C55 12 mov %ds,%ds:0x12\(%ebp,%edx,2\)
+ 1207 16e6 8C5C5612 mov %ds,%ds:0x12\(%esi,%edx,2\)
+ 1208 16ea 8C5C5712 mov %ds,%ds:0x12\(%edi,%edx,2\)
+ 1209 16ee 8C5C5812 mov %ds,%ds:0x12\(%eax,%ebx,2\)
+ 1210 16f2 8C5C5912 mov %ds,%ds:0x12\(%ecx,%ebx,2\)
+ 1211 16f6 8C5C5A12 mov %ds,%ds:0x12\(%edx,%ebx,2\)
+ 1212 16fa 8C5C5B12 mov %ds,%ds:0x12\(%ebx,%ebx,2\)
+ 1213 16fe 3E8C5C5C 12 mov %ds,%ds:0x12\(%esp,%ebx,2\)
+ 1214 1703 3E8C5C5D 12 mov %ds,%ds:0x12\(%ebp,%ebx,2\)
+ 1215 1708 8C5C5E12 mov %ds,%ds:0x12\(%esi,%ebx,2\)
+ 1216 170c 8C5C5F12 mov %ds,%ds:0x12\(%edi,%ebx,2\)
+ 1217 1710 8C5812 mov %ds,%ds:0x12\(%eax,2\)
+.*Warning:.*
+ 1218 1713 8C5912 mov %ds,%ds:0x12\(%ecx,2\)
+.*Warning:.*
+ 1219 1716 8C5A12 mov %ds,%ds:0x12\(%edx,2\)
+.*Warning:.*
+ 1220 1719 8C5B12 mov %ds,%ds:0x12\(%ebx,2\)
+.*Warning:.*
+ 1221 171c 3E8C5C24 12 mov %ds,%ds:0x12\(%esp,2\)
+.*Warning:.*
+ 1222 1721 3E8C5D12 mov %ds,%ds:0x12\(%ebp,2\)
+.*Warning:.*
+ 1223 1725 8C5E12 mov %ds,%ds:0x12\(%esi,2\)
+.*Warning:.*
+ 1224 1728 8C5F12 mov %ds,%ds:0x12\(%edi,2\)
+.*Warning:.*
+ 1225 172b 8C5C6812 mov %ds,%ds:0x12\(%eax,%ebp,2\)
+ 1226 172f 8C5C6912 mov %ds,%ds:0x12\(%ecx,%ebp,2\)
+ 1227 1733 8C5C6A12 mov %ds,%ds:0x12\(%edx,%ebp,2\)
+ 1228 1737 8C5C6B12 mov %ds,%ds:0x12\(%ebx,%ebp,2\)
+ 1229 173b 3E8C5C6C 12 mov %ds,%ds:0x12\(%esp,%ebp,2\)
+ 1230 1740 3E8C5C6D 12 mov %ds,%ds:0x12\(%ebp,%ebp,2\)
+ 1231 1745 8C5C6E12 mov %ds,%ds:0x12\(%esi,%ebp,2\)
+ 1232 1749 8C5C6F12 mov %ds,%ds:0x12\(%edi,%ebp,2\)
+ 1233 174d 8C5C7012 mov %ds,%ds:0x12\(%eax,%esi,2\)
+ 1234 1751 8C5C7112 mov %ds,%ds:0x12\(%ecx,%esi,2\)
+ 1235 1755 8C5C7212 mov %ds,%ds:0x12\(%edx,%esi,2\)
+ 1236 1759 8C5C7312 mov %ds,%ds:0x12\(%ebx,%esi,2\)
+ 1237 175d 3E8C5C74 12 mov %ds,%ds:0x12\(%esp,%esi,2\)
+ 1238 1762 3E8C5C75 12 mov %ds,%ds:0x12\(%ebp,%esi,2\)
+ 1239 1767 8C5C7612 mov %ds,%ds:0x12\(%esi,%esi,2\)
+ 1240 176b 8C5C7712 mov %ds,%ds:0x12\(%edi,%esi,2\)
+ 1241 176f 8C5C7812 mov %ds,%ds:0x12\(%eax,%edi,2\)
+ 1242 1773 8C5C7912 mov %ds,%ds:0x12\(%ecx,%edi,2\)
+ 1243 1777 8C5C7A12 mov %ds,%ds:0x12\(%edx,%edi,2\)
+ 1244 177b 8C5C7B12 mov %ds,%ds:0x12\(%ebx,%edi,2\)
+ 1245 177f 3E8C5C7C 12 mov %ds,%ds:0x12\(%esp,%edi,2\)
+ 1246 1784 3E8C5C7D 12 mov %ds,%ds:0x12\(%ebp,%edi,2\)
+ 1247 1789 8C5C7E12 mov %ds,%ds:0x12\(%esi,%edi,2\)
+ 1248 178d 8C5C7F12 mov %ds,%ds:0x12\(%edi,%edi,2\)
+ 1249 1791 8C5C8012 mov %ds,%ds:0x12\(%eax,%eax,4\)
+ 1250 1795 8C5C8112 mov %ds,%ds:0x12\(%ecx,%eax,4\)
+ 1251 1799 8C5C8212 mov %ds,%ds:0x12\(%edx,%eax,4\)
+ 1252 179d 8C5C8312 mov %ds,%ds:0x12\(%ebx,%eax,4\)
+ 1253 17a1 3E8C5C84 12 mov %ds,%ds:0x12\(%esp,%eax,4\)
+ 1254 17a6 3E8C5C85 12 mov %ds,%ds:0x12\(%ebp,%eax,4\)
+ 1255 17ab 8C5C8612 mov %ds,%ds:0x12\(%esi,%eax,4\)
+ 1256 17af 8C5C8712 mov %ds,%ds:0x12\(%edi,%eax,4\)
+ 1257 17b3 8C5C8812 mov %ds,%ds:0x12\(%eax,%ecx,4\)
+ 1258 17b7 8C5C8912 mov %ds,%ds:0x12\(%ecx,%ecx,4\)
+ 1259 17bb 8C5C8A12 mov %ds,%ds:0x12\(%edx,%ecx,4\)
+ 1260 17bf 8C5C8B12 mov %ds,%ds:0x12\(%ebx,%ecx,4\)
+ 1261 17c3 3E8C5C8C 12 mov %ds,%ds:0x12\(%esp,%ecx,4\)
+ 1262 17c8 3E8C5C8D 12 mov %ds,%ds:0x12\(%ebp,%ecx,4\)
+ 1263 17cd 8C5C8E12 mov %ds,%ds:0x12\(%esi,%ecx,4\)
+ 1264 17d1 8C5C8F12 mov %ds,%ds:0x12\(%edi,%ecx,4\)
+ 1265 17d5 8C5C9012 mov %ds,%ds:0x12\(%eax,%edx,4\)
+ 1266 17d9 8C5C9112 mov %ds,%ds:0x12\(%ecx,%edx,4\)
+ 1267 17dd 8C5C9212 mov %ds,%ds:0x12\(%edx,%edx,4\)
+ 1268 17e1 8C5C9312 mov %ds,%ds:0x12\(%ebx,%edx,4\)
+ 1269 17e5 3E8C5C94 12 mov %ds,%ds:0x12\(%esp,%edx,4\)
+ 1270 17ea 3E8C5C95 12 mov %ds,%ds:0x12\(%ebp,%edx,4\)
+ 1271 17ef 8C5C9612 mov %ds,%ds:0x12\(%esi,%edx,4\)
+ 1272 17f3 8C5C9712 mov %ds,%ds:0x12\(%edi,%edx,4\)
+ 1273 17f7 8C5C9812 mov %ds,%ds:0x12\(%eax,%ebx,4\)
+ 1274 17fb 8C5C9912 mov %ds,%ds:0x12\(%ecx,%ebx,4\)
+ 1275 17ff 8C5C9A12 mov %ds,%ds:0x12\(%edx,%ebx,4\)
+ 1276 1803 8C5C9B12 mov %ds,%ds:0x12\(%ebx,%ebx,4\)
+ 1277 1807 3E8C5C9C 12 mov %ds,%ds:0x12\(%esp,%ebx,4\)
+ 1278 180c 3E8C5C9D 12 mov %ds,%ds:0x12\(%ebp,%ebx,4\)
+ 1279 1811 8C5C9E12 mov %ds,%ds:0x12\(%esi,%ebx,4\)
+ 1280 1815 8C5C9F12 mov %ds,%ds:0x12\(%edi,%ebx,4\)
+ 1281 1819 8C5812 mov %ds,%ds:0x12\(%eax,4\)
+.*Warning:.*
+ 1282 181c 8C5912 mov %ds,%ds:0x12\(%ecx,4\)
+.*Warning:.*
+ 1283 181f 8C5A12 mov %ds,%ds:0x12\(%edx,4\)
+.*Warning:.*
+ 1284 1822 8C5B12 mov %ds,%ds:0x12\(%ebx,4\)
+.*Warning:.*
+ 1285 1825 3E8C5C24 12 mov %ds,%ds:0x12\(%esp,4\)
+.*Warning:.*
+ 1286 182a 3E8C5D12 mov %ds,%ds:0x12\(%ebp,4\)
+.*Warning:.*
+ 1287 182e 8C5E12 mov %ds,%ds:0x12\(%esi,4\)
+.*Warning:.*
+ 1288 1831 8C5F12 mov %ds,%ds:0x12\(%edi,4\)
+.*Warning:.*
+ 1289 1834 8C5CA812 mov %ds,%ds:0x12\(%eax,%ebp,4\)
+ 1290 1838 8C5CA912 mov %ds,%ds:0x12\(%ecx,%ebp,4\)
+ 1291 183c 8C5CAA12 mov %ds,%ds:0x12\(%edx,%ebp,4\)
+ 1292 1840 8C5CAB12 mov %ds,%ds:0x12\(%ebx,%ebp,4\)
+ 1293 1844 3E8C5CAC 12 mov %ds,%ds:0x12\(%esp,%ebp,4\)
+ 1294 1849 3E8C5CAD 12 mov %ds,%ds:0x12\(%ebp,%ebp,4\)
+ 1295 184e 8C5CAE12 mov %ds,%ds:0x12\(%esi,%ebp,4\)
+ 1296 1852 8C5CAF12 mov %ds,%ds:0x12\(%edi,%ebp,4\)
+ 1297 1856 8C5CB012 mov %ds,%ds:0x12\(%eax,%esi,4\)
+ 1298 185a 8C5CB112 mov %ds,%ds:0x12\(%ecx,%esi,4\)
+ 1299 185e 8C5CB212 mov %ds,%ds:0x12\(%edx,%esi,4\)
+ 1300 1862 8C5CB312 mov %ds,%ds:0x12\(%ebx,%esi,4\)
+ 1301 1866 3E8C5CB4 12 mov %ds,%ds:0x12\(%esp,%esi,4\)
+ 1302 186b 3E8C5CB5 12 mov %ds,%ds:0x12\(%ebp,%esi,4\)
+ 1303 1870 8C5CB612 mov %ds,%ds:0x12\(%esi,%esi,4\)
+ 1304 1874 8C5CB712 mov %ds,%ds:0x12\(%edi,%esi,4\)
+ 1305 1878 8C5CB812 mov %ds,%ds:0x12\(%eax,%edi,4\)
+ 1306 187c 8C5CB912 mov %ds,%ds:0x12\(%ecx,%edi,4\)
+ 1307 1880 8C5CBA12 mov %ds,%ds:0x12\(%edx,%edi,4\)
+ 1308 1884 8C5CBB12 mov %ds,%ds:0x12\(%ebx,%edi,4\)
+ 1309 1888 3E8C5CBC 12 mov %ds,%ds:0x12\(%esp,%edi,4\)
+ 1310 188d 3E8C5CBD 12 mov %ds,%ds:0x12\(%ebp,%edi,4\)
+ 1311 1892 8C5CBE12 mov %ds,%ds:0x12\(%esi,%edi,4\)
+ 1312 1896 8C5CBF12 mov %ds,%ds:0x12\(%edi,%edi,4\)
+ 1313 189a 8C5CC012 mov %ds,%ds:0x12\(%eax,%eax,8\)
+ 1314 189e 8C5CC112 mov %ds,%ds:0x12\(%ecx,%eax,8\)
+ 1315 18a2 8C5CC212 mov %ds,%ds:0x12\(%edx,%eax,8\)
+ 1316 18a6 8C5CC312 mov %ds,%ds:0x12\(%ebx,%eax,8\)
+ 1317 18aa 3E8C5CC4 12 mov %ds,%ds:0x12\(%esp,%eax,8\)
+ 1318 18af 3E8C5CC5 12 mov %ds,%ds:0x12\(%ebp,%eax,8\)
+ 1319 18b4 8C5CC612 mov %ds,%ds:0x12\(%esi,%eax,8\)
+ 1320 18b8 8C5CC712 mov %ds,%ds:0x12\(%edi,%eax,8\)
+ 1321 18bc 8C5CC812 mov %ds,%ds:0x12\(%eax,%ecx,8\)
+ 1322 18c0 8C5CC912 mov %ds,%ds:0x12\(%ecx,%ecx,8\)
+ 1323 18c4 8C5CCA12 mov %ds,%ds:0x12\(%edx,%ecx,8\)
+ 1324 18c8 8C5CCB12 mov %ds,%ds:0x12\(%ebx,%ecx,8\)
+ 1325 18cc 3E8C5CCC 12 mov %ds,%ds:0x12\(%esp,%ecx,8\)
+ 1326 18d1 3E8C5CCD 12 mov %ds,%ds:0x12\(%ebp,%ecx,8\)
+ 1327 18d6 8C5CCE12 mov %ds,%ds:0x12\(%esi,%ecx,8\)
+ 1328 18da 8C5CCF12 mov %ds,%ds:0x12\(%edi,%ecx,8\)
+ 1329 18de 8C5CD012 mov %ds,%ds:0x12\(%eax,%edx,8\)
+ 1330 18e2 8C5CD112 mov %ds,%ds:0x12\(%ecx,%edx,8\)
+ 1331 18e6 8C5CD212 mov %ds,%ds:0x12\(%edx,%edx,8\)
+ 1332 18ea 8C5CD312 mov %ds,%ds:0x12\(%ebx,%edx,8\)
+ 1333 18ee 3E8C5CD4 12 mov %ds,%ds:0x12\(%esp,%edx,8\)
+ 1334 18f3 3E8C5CD5 12 mov %ds,%ds:0x12\(%ebp,%edx,8\)
+ 1335 18f8 8C5CD612 mov %ds,%ds:0x12\(%esi,%edx,8\)
+ 1336 18fc 8C5CD712 mov %ds,%ds:0x12\(%edi,%edx,8\)
+ 1337 1900 8C5CD812 mov %ds,%ds:0x12\(%eax,%ebx,8\)
+ 1338 1904 8C5CD912 mov %ds,%ds:0x12\(%ecx,%ebx,8\)
+ 1339 1908 8C5CDA12 mov %ds,%ds:0x12\(%edx,%ebx,8\)
+ 1340 190c 8C5CDB12 mov %ds,%ds:0x12\(%ebx,%ebx,8\)
+ 1341 1910 3E8C5CDC 12 mov %ds,%ds:0x12\(%esp,%ebx,8\)
+ 1342 1915 3E8C5CDD 12 mov %ds,%ds:0x12\(%ebp,%ebx,8\)
+ 1343 191a 8C5CDE12 mov %ds,%ds:0x12\(%esi,%ebx,8\)
+ 1344 191e 8C5CDF12 mov %ds,%ds:0x12\(%edi,%ebx,8\)
+ 1345 1922 8C5812 mov %ds,%ds:0x12\(%eax,8\)
+.*Warning:.*
+ 1346 1925 8C5912 mov %ds,%ds:0x12\(%ecx,8\)
+.*Warning:.*
+ 1347 1928 8C5A12 mov %ds,%ds:0x12\(%edx,8\)
+.*Warning:.*
+ 1348 192b 8C5B12 mov %ds,%ds:0x12\(%ebx,8\)
+.*Warning:.*
+ 1349 192e 3E8C5C24 12 mov %ds,%ds:0x12\(%esp,8\)
+.*Warning:.*
+ 1350 1933 3E8C5D12 mov %ds,%ds:0x12\(%ebp,8\)
+.*Warning:.*
+ 1351 1937 8C5E12 mov %ds,%ds:0x12\(%esi,8\)
+.*Warning:.*
+ 1352 193a 8C5F12 mov %ds,%ds:0x12\(%edi,8\)
+.*Warning:.*
+ 1353 193d 8C5CE812 mov %ds,%ds:0x12\(%eax,%ebp,8\)
+ 1354 1941 8C5CE912 mov %ds,%ds:0x12\(%ecx,%ebp,8\)
+ 1355 1945 8C5CEA12 mov %ds,%ds:0x12\(%edx,%ebp,8\)
+ 1356 1949 8C5CEB12 mov %ds,%ds:0x12\(%ebx,%ebp,8\)
+ 1357 194d 3E8C5CEC 12 mov %ds,%ds:0x12\(%esp,%ebp,8\)
+ 1358 1952 3E8C5CED 12 mov %ds,%ds:0x12\(%ebp,%ebp,8\)
+ 1359 1957 8C5CEE12 mov %ds,%ds:0x12\(%esi,%ebp,8\)
+ 1360 195b 8C5CEF12 mov %ds,%ds:0x12\(%edi,%ebp,8\)
+ 1361 195f 8C5CF012 mov %ds,%ds:0x12\(%eax,%esi,8\)
+ 1362 1963 8C5CF112 mov %ds,%ds:0x12\(%ecx,%esi,8\)
+ 1363 1967 8C5CF212 mov %ds,%ds:0x12\(%edx,%esi,8\)
+ 1364 196b 8C5CF312 mov %ds,%ds:0x12\(%ebx,%esi,8\)
+ 1365 196f 3E8C5CF4 12 mov %ds,%ds:0x12\(%esp,%esi,8\)
+ 1366 1974 3E8C5CF5 12 mov %ds,%ds:0x12\(%ebp,%esi,8\)
+ 1367 1979 8C5CF612 mov %ds,%ds:0x12\(%esi,%esi,8\)
+ 1368 197d 8C5CF712 mov %ds,%ds:0x12\(%edi,%esi,8\)
+ 1369 1981 8C5CF812 mov %ds,%ds:0x12\(%eax,%edi,8\)
+ 1370 1985 8C5CFA12 mov %ds,%ds:0x12\(%edx,%edi,8\)
+ 1371 1989 8C5CF912 mov %ds,%ds:0x12\(%ecx,%edi,8\)
+ 1372 198d 8C5CFB12 mov %ds,%ds:0x12\(%ebx,%edi,8\)
+ 1373 1991 3E8C5CFC 12 mov %ds,%ds:0x12\(%esp,%edi,8\)
+ 1374 1996 3E8C5CFD 12 mov %ds,%ds:0x12\(%ebp,%edi,8\)
+ 1375 199b 8C5CFE12 mov %ds,%ds:0x12\(%esi,%edi,8\)
+ 1376 199f 8C5CFF12 mov %ds,%ds:0x12\(%edi,%edi,8\)
+ 1377 19a3 8C9C0078 563412 mov %ds,%ds:0x12345678\(%eax,%eax,1\)
+ 1378 19aa 8C9C0178 563412 mov %ds,%ds:0x12345678\(%ecx,%eax,1\)
+ 1379 19b1 8C9C0278 563412 mov %ds,%ds:0x12345678\(%edx,%eax,1\)
+ 1380 19b8 8C9C0378 563412 mov %ds,%ds:0x12345678\(%ebx,%eax,1\)
+ 1381 19bf 3E8C9C04 78563412 mov %ds,%ds:0x12345678\(%esp,%eax,1\)
+ 1382 19c7 3E8C9C05 78563412 mov %ds,%ds:0x12345678\(%ebp,%eax,1\)
+ 1383 19cf 8C9C0678 563412 mov %ds,%ds:0x12345678\(%esi,%eax,1\)
+ 1384 19d6 8C9C0778 563412 mov %ds,%ds:0x12345678\(%edi,%eax,1\)
+ 1385 19dd 8C9C0878 563412 mov %ds,%ds:0x12345678\(%eax,%ecx,1\)
+ 1386 19e4 8C9C0978 563412 mov %ds,%ds:0x12345678\(%ecx,%ecx,1\)
+ 1387 19eb 8C9C0A78 563412 mov %ds,%ds:0x12345678\(%edx,%ecx,1\)
+ 1388 19f2 8C9C0B78 563412 mov %ds,%ds:0x12345678\(%ebx,%ecx,1\)
+ 1389 19f9 3E8C9C0C 78563412 mov %ds,%ds:0x12345678\(%esp,%ecx,1\)
+ 1390 1a01 3E8C9C0D 78563412 mov %ds,%ds:0x12345678\(%ebp,%ecx,1\)
+ 1391 1a09 8C9C0E78 563412 mov %ds,%ds:0x12345678\(%esi,%ecx,1\)
+ 1392 1a10 8C9C0F78 563412 mov %ds,%ds:0x12345678\(%edi,%ecx,1\)
+ 1393 1a17 8C9C1078 563412 mov %ds,%ds:0x12345678\(%eax,%edx,1\)
+ 1394 1a1e 8C9C1178 563412 mov %ds,%ds:0x12345678\(%ecx,%edx,1\)
+ 1395 1a25 8C9C1278 563412 mov %ds,%ds:0x12345678\(%edx,%edx,1\)
+ 1396 1a2c 8C9C1378 563412 mov %ds,%ds:0x12345678\(%ebx,%edx,1\)
+ 1397 1a33 3E8C9C14 78563412 mov %ds,%ds:0x12345678\(%esp,%edx,1\)
+ 1398 1a3b 3E8C9C15 78563412 mov %ds,%ds:0x12345678\(%ebp,%edx,1\)
+ 1399 1a43 8C9C1678 563412 mov %ds,%ds:0x12345678\(%esi,%edx,1\)
+ 1400 1a4a 8C9C1778 563412 mov %ds,%ds:0x12345678\(%edi,%edx,1\)
+ 1401 1a51 8C9C1878 563412 mov %ds,%ds:0x12345678\(%eax,%ebx,1\)
+ 1402 1a58 8C9C1978 563412 mov %ds,%ds:0x12345678\(%ecx,%ebx,1\)
+ 1403 1a5f 8C9C1A78 563412 mov %ds,%ds:0x12345678\(%edx,%ebx,1\)
+ 1404 1a66 8C9C1B78 563412 mov %ds,%ds:0x12345678\(%ebx,%ebx,1\)
+ 1405 1a6d 3E8C9C1C 78563412 mov %ds,%ds:0x12345678\(%esp,%ebx,1\)
+ 1406 1a75 3E8C9C1D 78563412 mov %ds,%ds:0x12345678\(%ebp,%ebx,1\)
+ 1407 1a7d 8C9C1E78 563412 mov %ds,%ds:0x12345678\(%esi,%ebx,1\)
+ 1408 1a84 8C9C1F78 563412 mov %ds,%ds:0x12345678\(%edi,%ebx,1\)
+ 1409 1a8b 8C987856 3412 mov %ds,%ds:0x12345678\(%eax,1\)
+ 1410 1a91 8C997856 3412 mov %ds,%ds:0x12345678\(%ecx,1\)
+ 1411 1a97 8C9A7856 3412 mov %ds,%ds:0x12345678\(%edx,1\)
+ 1412 1a9d 8C9B7856 3412 mov %ds,%ds:0x12345678\(%ebx,1\)
+ 1413 1aa3 3E8C9C24 78563412 mov %ds,%ds:0x12345678\(%esp,1\)
+ 1414 1aab 3E8C9D78 563412 mov %ds,%ds:0x12345678\(%ebp,1\)
+ 1415 1ab2 8C9E7856 3412 mov %ds,%ds:0x12345678\(%esi,1\)
+ 1416 1ab8 8C9F7856 3412 mov %ds,%ds:0x12345678\(%edi,1\)
+ 1417 1abe 8C9C2878 563412 mov %ds,%ds:0x12345678\(%eax,%ebp,1\)
+ 1418 1ac5 8C9C2978 563412 mov %ds,%ds:0x12345678\(%ecx,%ebp,1\)
+ 1419 1acc 8C9C2A78 563412 mov %ds,%ds:0x12345678\(%edx,%ebp,1\)
+ 1420 1ad3 8C9C2B78 563412 mov %ds,%ds:0x12345678\(%ebx,%ebp,1\)
+ 1421 1ada 3E8C9C2C 78563412 mov %ds,%ds:0x12345678\(%esp,%ebp,1\)
+ 1422 1ae2 3E8C9C2D 78563412 mov %ds,%ds:0x12345678\(%ebp,%ebp,1\)
+ 1423 1aea 8C9C2E78 563412 mov %ds,%ds:0x12345678\(%esi,%ebp,1\)
+ 1424 1af1 8C9C2F78 563412 mov %ds,%ds:0x12345678\(%edi,%ebp,1\)
+ 1425 1af8 8C9C3078 563412 mov %ds,%ds:0x12345678\(%eax,%esi,1\)
+ 1426 1aff 8C9C3178 563412 mov %ds,%ds:0x12345678\(%ecx,%esi,1\)
+ 1427 1b06 8C9C3278 563412 mov %ds,%ds:0x12345678\(%edx,%esi,1\)
+ 1428 1b0d 8C9C3378 563412 mov %ds,%ds:0x12345678\(%ebx,%esi,1\)
+ 1429 1b14 3E8C9C34 78563412 mov %ds,%ds:0x12345678\(%esp,%esi,1\)
+ 1430 1b1c 3E8C9C35 78563412 mov %ds,%ds:0x12345678\(%ebp,%esi,1\)
+ 1431 1b24 8C9C3678 563412 mov %ds,%ds:0x12345678\(%esi,%esi,1\)
+ 1432 1b2b 8C9C3778 563412 mov %ds,%ds:0x12345678\(%edi,%esi,1\)
+ 1433 1b32 8C9C3878 563412 mov %ds,%ds:0x12345678\(%eax,%edi,1\)
+ 1434 1b39 8C9C3978 563412 mov %ds,%ds:0x12345678\(%ecx,%edi,1\)
+ 1435 1b40 8C9C3A78 563412 mov %ds,%ds:0x12345678\(%edx,%edi,1\)
+ 1436 1b47 8C9C3B78 563412 mov %ds,%ds:0x12345678\(%ebx,%edi,1\)
+ 1437 1b4e 3E8C9C3C 78563412 mov %ds,%ds:0x12345678\(%esp,%edi,1\)
+ 1438 1b56 3E8C9C3D 78563412 mov %ds,%ds:0x12345678\(%ebp,%edi,1\)
+ 1439 1b5e 8C9C3E78 563412 mov %ds,%ds:0x12345678\(%esi,%edi,1\)
+ 1440 1b65 8C9C3F78 563412 mov %ds,%ds:0x12345678\(%edi,%edi,1\)
+ 1441 1b6c 8C9C4078 563412 mov %ds,%ds:0x12345678\(%eax,%eax,2\)
+ 1442 1b73 8C9C4178 563412 mov %ds,%ds:0x12345678\(%ecx,%eax,2\)
+ 1443 1b7a 8C9C4278 563412 mov %ds,%ds:0x12345678\(%edx,%eax,2\)
+ 1444 1b81 8C9C4378 563412 mov %ds,%ds:0x12345678\(%ebx,%eax,2\)
+ 1445 1b88 3E8C9C44 78563412 mov %ds,%ds:0x12345678\(%esp,%eax,2\)
+ 1446 1b90 3E8C9C45 78563412 mov %ds,%ds:0x12345678\(%ebp,%eax,2\)
+ 1447 1b98 8C9C4678 563412 mov %ds,%ds:0x12345678\(%esi,%eax,2\)
+ 1448 1b9f 8C9C4778 563412 mov %ds,%ds:0x12345678\(%edi,%eax,2\)
+ 1449 1ba6 8C9C4878 563412 mov %ds,%ds:0x12345678\(%eax,%ecx,2\)
+ 1450 1bad 8C9C4978 563412 mov %ds,%ds:0x12345678\(%ecx,%ecx,2\)
+ 1451 1bb4 8C9C4A78 563412 mov %ds,%ds:0x12345678\(%edx,%ecx,2\)
+ 1452 1bbb 8C9C4B78 563412 mov %ds,%ds:0x12345678\(%ebx,%ecx,2\)
+ 1453 1bc2 3E8C9C4C 78563412 mov %ds,%ds:0x12345678\(%esp,%ecx,2\)
+ 1454 1bca 3E8C9C4D 78563412 mov %ds,%ds:0x12345678\(%ebp,%ecx,2\)
+ 1455 1bd2 8C9C4E78 563412 mov %ds,%ds:0x12345678\(%esi,%ecx,2\)
+ 1456 1bd9 8C9C4F78 563412 mov %ds,%ds:0x12345678\(%edi,%ecx,2\)
+ 1457 1be0 8C9C5078 563412 mov %ds,%ds:0x12345678\(%eax,%edx,2\)
+ 1458 1be7 8C9C5178 563412 mov %ds,%ds:0x12345678\(%ecx,%edx,2\)
+ 1459 1bee 8C9C5278 563412 mov %ds,%ds:0x12345678\(%edx,%edx,2\)
+ 1460 1bf5 8C9C5378 563412 mov %ds,%ds:0x12345678\(%ebx,%edx,2\)
+ 1461 1bfc 3E8C9C54 78563412 mov %ds,%ds:0x12345678\(%esp,%edx,2\)
+ 1462 1c04 3E8C9C55 78563412 mov %ds,%ds:0x12345678\(%ebp,%edx,2\)
+ 1463 1c0c 8C9C5678 563412 mov %ds,%ds:0x12345678\(%esi,%edx,2\)
+ 1464 1c13 8C9C5778 563412 mov %ds,%ds:0x12345678\(%edi,%edx,2\)
+ 1465 1c1a 8C9C5878 563412 mov %ds,%ds:0x12345678\(%eax,%ebx,2\)
+ 1466 1c21 8C9C5978 563412 mov %ds,%ds:0x12345678\(%ecx,%ebx,2\)
+ 1467 1c28 8C9C5A78 563412 mov %ds,%ds:0x12345678\(%edx,%ebx,2\)
+ 1468 1c2f 8C9C5B78 563412 mov %ds,%ds:0x12345678\(%ebx,%ebx,2\)
+ 1469 1c36 3E8C9C5C 78563412 mov %ds,%ds:0x12345678\(%esp,%ebx,2\)
+ 1470 1c3e 3E8C9C5D 78563412 mov %ds,%ds:0x12345678\(%ebp,%ebx,2\)
+ 1471 1c46 8C9C5E78 563412 mov %ds,%ds:0x12345678\(%esi,%ebx,2\)
+ 1472 1c4d 8C9C5F78 563412 mov %ds,%ds:0x12345678\(%edi,%ebx,2\)
+ 1473 1c54 8C987856 3412 mov %ds,%ds:0x12345678\(%eax,2\)
+.*Warning:.*
+ 1474 1c5a 8C997856 3412 mov %ds,%ds:0x12345678\(%ecx,2\)
+.*Warning:.*
+ 1475 1c60 8C9A7856 3412 mov %ds,%ds:0x12345678\(%edx,2\)
+.*Warning:.*
+ 1476 1c66 8C9B7856 3412 mov %ds,%ds:0x12345678\(%ebx,2\)
+.*Warning:.*
+ 1477 1c6c 3E8C9C24 78563412 mov %ds,%ds:0x12345678\(%esp,2\)
+.*Warning:.*
+ 1478 1c74 3E8C9D78 563412 mov %ds,%ds:0x12345678\(%ebp,2\)
+.*Warning:.*
+ 1479 1c7b 8C9E7856 3412 mov %ds,%ds:0x12345678\(%esi,2\)
+.*Warning:.*
+ 1480 1c81 8C9F7856 3412 mov %ds,%ds:0x12345678\(%edi,2\)
+.*Warning:.*
+ 1481 1c87 8C9C6878 563412 mov %ds,%ds:0x12345678\(%eax,%ebp,2\)
+ 1482 1c8e 8C9C6978 563412 mov %ds,%ds:0x12345678\(%ecx,%ebp,2\)
+ 1483 1c95 8C9C6A78 563412 mov %ds,%ds:0x12345678\(%edx,%ebp,2\)
+ 1484 1c9c 8C9C6B78 563412 mov %ds,%ds:0x12345678\(%ebx,%ebp,2\)
+ 1485 1ca3 3E8C9C6C 78563412 mov %ds,%ds:0x12345678\(%esp,%ebp,2\)
+ 1486 1cab 3E8C9C6D 78563412 mov %ds,%ds:0x12345678\(%ebp,%ebp,2\)
+ 1487 1cb3 8C9C6E78 563412 mov %ds,%ds:0x12345678\(%esi,%ebp,2\)
+ 1488 1cba 8C9C6F78 563412 mov %ds,%ds:0x12345678\(%edi,%ebp,2\)
+ 1489 1cc1 8C9C7078 563412 mov %ds,%ds:0x12345678\(%eax,%esi,2\)
+ 1490 1cc8 8C9C7178 563412 mov %ds,%ds:0x12345678\(%ecx,%esi,2\)
+ 1491 1ccf 8C9C7278 563412 mov %ds,%ds:0x12345678\(%edx,%esi,2\)
+ 1492 1cd6 8C9C7378 563412 mov %ds,%ds:0x12345678\(%ebx,%esi,2\)
+ 1493 1cdd 3E8C9C74 78563412 mov %ds,%ds:0x12345678\(%esp,%esi,2\)
+ 1494 1ce5 3E8C9C75 78563412 mov %ds,%ds:0x12345678\(%ebp,%esi,2\)
+ 1495 1ced 8C9C7678 563412 mov %ds,%ds:0x12345678\(%esi,%esi,2\)
+ 1496 1cf4 8C9C7778 563412 mov %ds,%ds:0x12345678\(%edi,%esi,2\)
+ 1497 1cfb 8C9C7878 563412 mov %ds,%ds:0x12345678\(%eax,%edi,2\)
+ 1498 1d02 8C9C7978 563412 mov %ds,%ds:0x12345678\(%ecx,%edi,2\)
+ 1499 1d09 8C9C7A78 563412 mov %ds,%ds:0x12345678\(%edx,%edi,2\)
+ 1500 1d10 8C9C7B78 563412 mov %ds,%ds:0x12345678\(%ebx,%edi,2\)
+ 1501 1d17 3E8C9C7C 78563412 mov %ds,%ds:0x12345678\(%esp,%edi,2\)
+ 1502 1d1f 3E8C9C7D 78563412 mov %ds,%ds:0x12345678\(%ebp,%edi,2\)
+ 1503 1d27 8C9C7E78 563412 mov %ds,%ds:0x12345678\(%esi,%edi,2\)
+ 1504 1d2e 8C9C7F78 563412 mov %ds,%ds:0x12345678\(%edi,%edi,2\)
+ 1505 1d35 8C9C8078 563412 mov %ds,%ds:0x12345678\(%eax,%eax,4\)
+ 1506 1d3c 8C9C8178 563412 mov %ds,%ds:0x12345678\(%ecx,%eax,4\)
+ 1507 1d43 8C9C8278 563412 mov %ds,%ds:0x12345678\(%edx,%eax,4\)
+ 1508 1d4a 8C9C8378 563412 mov %ds,%ds:0x12345678\(%ebx,%eax,4\)
+ 1509 1d51 3E8C9C84 78563412 mov %ds,%ds:0x12345678\(%esp,%eax,4\)
+ 1510 1d59 3E8C9C85 78563412 mov %ds,%ds:0x12345678\(%ebp,%eax,4\)
+ 1511 1d61 8C9C8678 563412 mov %ds,%ds:0x12345678\(%esi,%eax,4\)
+ 1512 1d68 8C9C8778 563412 mov %ds,%ds:0x12345678\(%edi,%eax,4\)
+ 1513 1d6f 8C9C8878 563412 mov %ds,%ds:0x12345678\(%eax,%ecx,4\)
+ 1514 1d76 8C9C8978 563412 mov %ds,%ds:0x12345678\(%ecx,%ecx,4\)
+ 1515 1d7d 8C9C8A78 563412 mov %ds,%ds:0x12345678\(%edx,%ecx,4\)
+ 1516 1d84 8C9C8B78 563412 mov %ds,%ds:0x12345678\(%ebx,%ecx,4\)
+ 1517 1d8b 3E8C9C8C 78563412 mov %ds,%ds:0x12345678\(%esp,%ecx,4\)
+ 1518 1d93 3E8C9C8D 78563412 mov %ds,%ds:0x12345678\(%ebp,%ecx,4\)
+ 1519 1d9b 8C9C8E78 563412 mov %ds,%ds:0x12345678\(%esi,%ecx,4\)
+ 1520 1da2 8C9C8F78 563412 mov %ds,%ds:0x12345678\(%edi,%ecx,4\)
+ 1521 1da9 8C9C9078 563412 mov %ds,%ds:0x12345678\(%eax,%edx,4\)
+ 1522 1db0 8C9C9178 563412 mov %ds,%ds:0x12345678\(%ecx,%edx,4\)
+ 1523 1db7 8C9C9278 563412 mov %ds,%ds:0x12345678\(%edx,%edx,4\)
+ 1524 1dbe 8C9C9378 563412 mov %ds,%ds:0x12345678\(%ebx,%edx,4\)
+ 1525 1dc5 3E8C9C94 78563412 mov %ds,%ds:0x12345678\(%esp,%edx,4\)
+ 1526 1dcd 3E8C9C95 78563412 mov %ds,%ds:0x12345678\(%ebp,%edx,4\)
+ 1527 1dd5 8C9C9678 563412 mov %ds,%ds:0x12345678\(%esi,%edx,4\)
+ 1528 1ddc 8C9C9778 563412 mov %ds,%ds:0x12345678\(%edi,%edx,4\)
+ 1529 1de3 8C9C9878 563412 mov %ds,%ds:0x12345678\(%eax,%ebx,4\)
+ 1530 1dea 8C9C9978 563412 mov %ds,%ds:0x12345678\(%ecx,%ebx,4\)
+ 1531 1df1 8C9C9A78 563412 mov %ds,%ds:0x12345678\(%edx,%ebx,4\)
+ 1532 1df8 8C9C9B78 563412 mov %ds,%ds:0x12345678\(%ebx,%ebx,4\)
+ 1533 1dff 3E8C9C9C 78563412 mov %ds,%ds:0x12345678\(%esp,%ebx,4\)
+ 1534 1e07 3E8C9C9D 78563412 mov %ds,%ds:0x12345678\(%ebp,%ebx,4\)
+ 1535 1e0f 8C9C9E78 563412 mov %ds,%ds:0x12345678\(%esi,%ebx,4\)
+ 1536 1e16 8C9C9F78 563412 mov %ds,%ds:0x12345678\(%edi,%ebx,4\)
+ 1537 1e1d 8C987856 3412 mov %ds,%ds:0x12345678\(%eax,4\)
+.*Warning:.*
+ 1538 1e23 8C997856 3412 mov %ds,%ds:0x12345678\(%ecx,4\)
+.*Warning:.*
+ 1539 1e29 8C9A7856 3412 mov %ds,%ds:0x12345678\(%edx,4\)
+.*Warning:.*
+ 1540 1e2f 8C9B7856 3412 mov %ds,%ds:0x12345678\(%ebx,4\)
+.*Warning:.*
+ 1541 1e35 3E8C9C24 78563412 mov %ds,%ds:0x12345678\(%esp,4\)
+.*Warning:.*
+ 1542 1e3d 3E8C9D78 563412 mov %ds,%ds:0x12345678\(%ebp,4\)
+.*Warning:.*
+ 1543 1e44 8C9E7856 3412 mov %ds,%ds:0x12345678\(%esi,4\)
+.*Warning:.*
+ 1544 1e4a 8C9F7856 3412 mov %ds,%ds:0x12345678\(%edi,4\)
+.*Warning:.*
+ 1545 1e50 8C9CA878 563412 mov %ds,%ds:0x12345678\(%eax,%ebp,4\)
+ 1546 1e57 8C9CA978 563412 mov %ds,%ds:0x12345678\(%ecx,%ebp,4\)
+ 1547 1e5e 8C9CAA78 563412 mov %ds,%ds:0x12345678\(%edx,%ebp,4\)
+ 1548 1e65 8C9CAB78 563412 mov %ds,%ds:0x12345678\(%ebx,%ebp,4\)
+ 1549 1e6c 3E8C9CAC 78563412 mov %ds,%ds:0x12345678\(%esp,%ebp,4\)
+ 1550 1e74 3E8C9CAD 78563412 mov %ds,%ds:0x12345678\(%ebp,%ebp,4\)
+ 1551 1e7c 8C9CAE78 563412 mov %ds,%ds:0x12345678\(%esi,%ebp,4\)
+ 1552 1e83 8C9CAF78 563412 mov %ds,%ds:0x12345678\(%edi,%ebp,4\)
+ 1553 1e8a 8C9CB078 563412 mov %ds,%ds:0x12345678\(%eax,%esi,4\)
+ 1554 1e91 8C9CB178 563412 mov %ds,%ds:0x12345678\(%ecx,%esi,4\)
+ 1555 1e98 8C9CB278 563412 mov %ds,%ds:0x12345678\(%edx,%esi,4\)
+ 1556 1e9f 8C9CB378 563412 mov %ds,%ds:0x12345678\(%ebx,%esi,4\)
+ 1557 1ea6 3E8C9CB4 78563412 mov %ds,%ds:0x12345678\(%esp,%esi,4\)
+ 1558 1eae 3E8C9CB5 78563412 mov %ds,%ds:0x12345678\(%ebp,%esi,4\)
+ 1559 1eb6 8C9CB678 563412 mov %ds,%ds:0x12345678\(%esi,%esi,4\)
+ 1560 1ebd 8C9CB778 563412 mov %ds,%ds:0x12345678\(%edi,%esi,4\)
+ 1561 1ec4 8C9CB878 563412 mov %ds,%ds:0x12345678\(%eax,%edi,4\)
+ 1562 1ecb 8C9CB978 563412 mov %ds,%ds:0x12345678\(%ecx,%edi,4\)
+ 1563 1ed2 8C9CBA78 563412 mov %ds,%ds:0x12345678\(%edx,%edi,4\)
+ 1564 1ed9 8C9CBB78 563412 mov %ds,%ds:0x12345678\(%ebx,%edi,4\)
+ 1565 1ee0 3E8C9CBC 78563412 mov %ds,%ds:0x12345678\(%esp,%edi,4\)
+ 1566 1ee8 3E8C9CBD 78563412 mov %ds,%ds:0x12345678\(%ebp,%edi,4\)
+ 1567 1ef0 8C9CBE78 563412 mov %ds,%ds:0x12345678\(%esi,%edi,4\)
+ 1568 1ef7 8C9CBF78 563412 mov %ds,%ds:0x12345678\(%edi,%edi,4\)
+ 1569 1efe 8C9CC078 563412 mov %ds,%ds:0x12345678\(%eax,%eax,8\)
+ 1570 1f05 8C9CC178 563412 mov %ds,%ds:0x12345678\(%ecx,%eax,8\)
+ 1571 1f0c 8C9CC278 563412 mov %ds,%ds:0x12345678\(%edx,%eax,8\)
+ 1572 1f13 8C9CC378 563412 mov %ds,%ds:0x12345678\(%ebx,%eax,8\)
+ 1573 1f1a 3E8C9CC4 78563412 mov %ds,%ds:0x12345678\(%esp,%eax,8\)
+ 1574 1f22 3E8C9CC5 78563412 mov %ds,%ds:0x12345678\(%ebp,%eax,8\)
+ 1575 1f2a 8C9CC678 563412 mov %ds,%ds:0x12345678\(%esi,%eax,8\)
+ 1576 1f31 8C9CC778 563412 mov %ds,%ds:0x12345678\(%edi,%eax,8\)
+ 1577 1f38 8C9CC878 563412 mov %ds,%ds:0x12345678\(%eax,%ecx,8\)
+ 1578 1f3f 8C9CC978 563412 mov %ds,%ds:0x12345678\(%ecx,%ecx,8\)
+ 1579 1f46 8C9CCA78 563412 mov %ds,%ds:0x12345678\(%edx,%ecx,8\)
+ 1580 1f4d 8C9CCB78 563412 mov %ds,%ds:0x12345678\(%ebx,%ecx,8\)
+ 1581 1f54 3E8C9CCC 78563412 mov %ds,%ds:0x12345678\(%esp,%ecx,8\)
+ 1582 1f5c 3E8C9CCD 78563412 mov %ds,%ds:0x12345678\(%ebp,%ecx,8\)
+ 1583 1f64 8C9CCE78 563412 mov %ds,%ds:0x12345678\(%esi,%ecx,8\)
+ 1584 1f6b 8C9CCF78 563412 mov %ds,%ds:0x12345678\(%edi,%ecx,8\)
+ 1585 1f72 8C9CD078 563412 mov %ds,%ds:0x12345678\(%eax,%edx,8\)
+ 1586 1f79 8C9CD178 563412 mov %ds,%ds:0x12345678\(%ecx,%edx,8\)
+ 1587 1f80 8C9CD278 563412 mov %ds,%ds:0x12345678\(%edx,%edx,8\)
+ 1588 1f87 8C9CD378 563412 mov %ds,%ds:0x12345678\(%ebx,%edx,8\)
+ 1589 1f8e 3E8C9CD4 78563412 mov %ds,%ds:0x12345678\(%esp,%edx,8\)
+ 1590 1f96 3E8C9CD5 78563412 mov %ds,%ds:0x12345678\(%ebp,%edx,8\)
+ 1591 1f9e 8C9CD678 563412 mov %ds,%ds:0x12345678\(%esi,%edx,8\)
+ 1592 1fa5 8C9CD778 563412 mov %ds,%ds:0x12345678\(%edi,%edx,8\)
+ 1593 1fac 8C9CD878 563412 mov %ds,%ds:0x12345678\(%eax,%ebx,8\)
+ 1594 1fb3 8C9CD978 563412 mov %ds,%ds:0x12345678\(%ecx,%ebx,8\)
+ 1595 1fba 8C9CDA78 563412 mov %ds,%ds:0x12345678\(%edx,%ebx,8\)
+ 1596 1fc1 8C9CDB78 563412 mov %ds,%ds:0x12345678\(%ebx,%ebx,8\)
+ 1597 1fc8 3E8C9CDC 78563412 mov %ds,%ds:0x12345678\(%esp,%ebx,8\)
+ 1598 1fd0 3E8C9CDD 78563412 mov %ds,%ds:0x12345678\(%ebp,%ebx,8\)
+ 1599 1fd8 8C9CDE78 563412 mov %ds,%ds:0x12345678\(%esi,%ebx,8\)
+ 1600 1fdf 8C9CDF78 563412 mov %ds,%ds:0x12345678\(%edi,%ebx,8\)
+ 1601 1fe6 8C987856 3412 mov %ds,%ds:0x12345678\(%eax,8\)
+.*Warning:.*
+ 1602 1fec 8C997856 3412 mov %ds,%ds:0x12345678\(%ecx,8\)
+.*Warning:.*
+ 1603 1ff2 8C9A7856 3412 mov %ds,%ds:0x12345678\(%edx,8\)
+.*Warning:.*
+ 1604 1ff8 8C9B7856 3412 mov %ds,%ds:0x12345678\(%ebx,8\)
+.*Warning:.*
+ 1605 1ffe 3E8C9C24 78563412 mov %ds,%ds:0x12345678\(%esp,8\)
+.*Warning:.*
+ 1606 2006 3E8C9D78 563412 mov %ds,%ds:0x12345678\(%ebp,8\)
+.*Warning:.*
+ 1607 200d 8C9E7856 3412 mov %ds,%ds:0x12345678\(%esi,8\)
+.*Warning:.*
+ 1608 2013 8C9F7856 3412 mov %ds,%ds:0x12345678\(%edi,8\)
+.*Warning:.*
+ 1609 2019 8C9CE878 563412 mov %ds,%ds:0x12345678\(%eax,%ebp,8\)
+ 1610 2020 8C9CE978 563412 mov %ds,%ds:0x12345678\(%ecx,%ebp,8\)
+ 1611 2027 8C9CEA78 563412 mov %ds,%ds:0x12345678\(%edx,%ebp,8\)
+ 1612 202e 8C9CEB78 563412 mov %ds,%ds:0x12345678\(%ebx,%ebp,8\)
+ 1613 2035 3E8C9CEC 78563412 mov %ds,%ds:0x12345678\(%esp,%ebp,8\)
+ 1614 203d 3E8C9CED 78563412 mov %ds,%ds:0x12345678\(%ebp,%ebp,8\)
+ 1615 2045 8C9CEE78 563412 mov %ds,%ds:0x12345678\(%esi,%ebp,8\)
+ 1616 204c 8C9CEF78 563412 mov %ds,%ds:0x12345678\(%edi,%ebp,8\)
+ 1617 2053 8C9CF078 563412 mov %ds,%ds:0x12345678\(%eax,%esi,8\)
+ 1618 205a 8C9CF178 563412 mov %ds,%ds:0x12345678\(%ecx,%esi,8\)
+ 1619 2061 8C9CF278 563412 mov %ds,%ds:0x12345678\(%edx,%esi,8\)
+ 1620 2068 8C9CF378 563412 mov %ds,%ds:0x12345678\(%ebx,%esi,8\)
+ 1621 206f 3E8C9CF4 78563412 mov %ds,%ds:0x12345678\(%esp,%esi,8\)
+ 1622 2077 3E8C9CF5 78563412 mov %ds,%ds:0x12345678\(%ebp,%esi,8\)
+ 1623 207f 8C9CF678 563412 mov %ds,%ds:0x12345678\(%esi,%esi,8\)
+ 1624 2086 8C9CF778 563412 mov %ds,%ds:0x12345678\(%edi,%esi,8\)
+ 1625 208d 8C9CF878 563412 mov %ds,%ds:0x12345678\(%eax,%edi,8\)
+ 1626 2094 8C9CFA78 563412 mov %ds,%ds:0x12345678\(%edx,%edi,8\)
+ 1627 209b 8C9CF978 563412 mov %ds,%ds:0x12345678\(%ecx,%edi,8\)
+ 1628 20a2 8C9CFB78 563412 mov %ds,%ds:0x12345678\(%ebx,%edi,8\)
+ 1629 20a9 3E8C9CFC 78563412 mov %ds,%ds:0x12345678\(%esp,%edi,8\)
+ 1630 20b1 3E8C9CFD 78563412 mov %ds,%ds:0x12345678\(%ebp,%edi,8\)
+ 1631 20b9 8C9CFE78 563412 mov %ds,%ds:0x12345678\(%esi,%edi,8\)
+ 1632 20c0 8C9CFF78 563412 mov %ds,%ds:0x12345678\(%edi,%edi,8\)
+ 1633 20c7 3E8C5C05 00 mov %ds,%ds:\(%ebp,%eax,1\)
+ 1634 20cc 3E8C5C0D 00 mov %ds,%ds:\(%ebp,%ecx,1\)
+ 1635 20d1 3E8C5C15 00 mov %ds,%ds:\(%ebp,%edx,1\)
+ 1636 20d6 3E8C5C1D 00 mov %ds,%ds:\(%ebp,%ebx,1\)
+ 1637 20db 3E8C5D00 mov %ds,%ds:\(%ebp,1\)
+ 1638 20df 3E8C5C2D 00 mov %ds,%ds:\(%ebp,%ebp,1\)
+ 1639 20e4 3E8C5C35 00 mov %ds,%ds:\(%ebp,%esi,1\)
+ 1640 20e9 3E8C5C3D 00 mov %ds,%ds:\(%ebp,%edi,1\)
+ 1641 20ee 3E8C5C45 00 mov %ds,%ds:\(%ebp,%eax,2\)
+ 1642 20f3 3E8C5C4D 00 mov %ds,%ds:\(%ebp,%ecx,2\)
+ 1643 20f8 3E8C5C55 00 mov %ds,%ds:\(%ebp,%edx,2\)
+ 1644 20fd 3E8C5C5D 00 mov %ds,%ds:\(%ebp,%ebx,2\)
+ 1645 2102 3E8C5D00 mov %ds,%ds:\(%ebp,2\)
+.*Warning:.*
+ 1646 2106 3E8C5C6D 00 mov %ds,%ds:\(%ebp,%ebp,2\)
+ 1647 210b 3E8C5C75 00 mov %ds,%ds:\(%ebp,%esi,2\)
+ 1648 2110 3E8C5C7D 00 mov %ds,%ds:\(%ebp,%edi,2\)
+ 1649 2115 3E8C5C85 00 mov %ds,%ds:\(%ebp,%eax,4\)
+ 1650 211a 3E8C5C8D 00 mov %ds,%ds:\(%ebp,%ecx,4\)
+ 1651 211f 3E8C5C95 00 mov %ds,%ds:\(%ebp,%edx,4\)
+ 1652 2124 3E8C5C9D 00 mov %ds,%ds:\(%ebp,%ebx,4\)
+ 1653 2129 3E8C5D00 mov %ds,%ds:\(%ebp,4\)
+.*Warning:.*
+ 1654 212d 3E8C5CAD 00 mov %ds,%ds:\(%ebp,%ebp,4\)
+ 1655 2132 3E8C5CB5 00 mov %ds,%ds:\(%ebp,%esi,4\)
+ 1656 2137 3E8C5CBD 00 mov %ds,%ds:\(%ebp,%edi,4\)
+ 1657 213c 3E8C5CC5 00 mov %ds,%ds:\(%ebp,%eax,8\)
+ 1658 2141 3E8C5CCD 00 mov %ds,%ds:\(%ebp,%ecx,8\)
+ 1659 2146 3E8C5CD5 00 mov %ds,%ds:\(%ebp,%edx,8\)
+ 1660 214b 3E8C5CDD 00 mov %ds,%ds:\(%ebp,%ebx,8\)
+ 1661 2150 3E8C5D00 mov %ds,%ds:\(%ebp,8\)
+.*Warning:.*
+ 1662 2154 3E8C5CED 00 mov %ds,%ds:\(%ebp,%ebp,8\)
+ 1663 2159 3E8C5CF5 00 mov %ds,%ds:\(%ebp,%esi,8\)
+ 1664 215e 3E8C5CFD 00 mov %ds,%ds:\(%ebp,%edi,8\)
+ 1665 2163 8C1D1200 0000 mov %ds,%ds:0x12\(,1\)
+ 1666 2169 8C1D1200 0000 mov %ds,%ds:0x12\(,2\)
+.*Warning:.*
+ 1667 216f 8C1D1200 0000 mov %ds,%ds:0x12\(,4\)
+.*Warning:.*
+ 1668 2175 8C1D1200 0000 mov %ds,%ds:0x12\(,8\)
+.*Warning:.*
+ 1669 [ ]*
+ 1670 [ ]* # Force a good alignment.
+ 1671 217b 00 [ ]* .byte 0
diff --git a/gas/testsuite/gas/i386/modrm.s b/gas/testsuite/gas/i386/modrm.s
new file mode 100644
index 0000000000..a6fc689aa6
--- /dev/null
+++ b/gas/testsuite/gas/i386/modrm.s
@@ -0,0 +1,1671 @@
+.psize 0
+.text
+ mov %ds,%ss:(%eax)
+ mov %ds,%ss:(%ecx)
+ mov %ds,%ss:(%edx)
+ mov %ds,%ss:(%ebx)
+ mov %ds,%ss:0
+ mov %ds,%ss:(%esi)
+ mov %ds,%ss:(%edi)
+ mov %ds,%ss:0x12(%eax)
+ mov %ds,%ss:0x12(%ecx)
+ mov %ds,%ss:0x12(%edx)
+ mov %ds,%ss:0x12(%ebx)
+ mov %ds,%ss:0x12(%ebp)
+ mov %ds,%ss:0x12(%esi)
+ mov %ds,%ss:0x12(%edi)
+ mov %ds,%ss:0x12345678(%eax)
+ mov %ds,%ss:0x12345678(%ecx)
+ mov %ds,%ss:0x12345678(%edx)
+ mov %ds,%ss:0x12345678(%ebx)
+ mov %ds,%ss:0x12345678(%ebp)
+ mov %ds,%ss:0x12345678(%esi)
+ mov %ds,%ss:0x12345678(%edi)
+ mov %ds,%eax
+ mov %ds,%ecx
+ mov %ds,%edx
+ mov %ds,%ebx
+ mov %ds,%esp
+ mov %ds,%ebp
+ mov %ds,%esi
+ mov %ds,%edi
+ mov %ds,%ss:(%eax,%eax,1)
+ mov %ds,%ss:(%ecx,%eax,1)
+ mov %ds,%ss:(%edx,%eax,1)
+ mov %ds,%ss:(%ebx,%eax,1)
+ mov %ds,%ss:(%esp,%eax,1)
+ mov %ds,%ss:(,%eax,1)
+ mov %ds,%ss:(%esi,%eax,1)
+ mov %ds,%ss:(%edi,%eax,1)
+ mov %ds,%ss:(%eax,%ecx,1)
+ mov %ds,%ss:(%ecx,%ecx,1)
+ mov %ds,%ss:(%edx,%ecx,1)
+ mov %ds,%ss:(%ebx,%ecx,1)
+ mov %ds,%ss:(%esp,%ecx,1)
+ mov %ds,%ss:(,%ecx,1)
+ mov %ds,%ss:(%esi,%ecx,1)
+ mov %ds,%ss:(%edi,%ecx,1)
+ mov %ds,%ss:(%eax,%edx,1)
+ mov %ds,%ss:(%ecx,%edx,1)
+ mov %ds,%ss:(%edx,%edx,1)
+ mov %ds,%ss:(%ebx,%edx,1)
+ mov %ds,%ss:(%esp,%edx,1)
+ mov %ds,%ss:(,%edx,1)
+ mov %ds,%ss:(%esi,%edx,1)
+ mov %ds,%ss:(%edi,%edx,1)
+ mov %ds,%ss:(%eax,%ebx,1)
+ mov %ds,%ss:(%ecx,%ebx,1)
+ mov %ds,%ss:(%edx,%ebx,1)
+ mov %ds,%ss:(%ebx,%ebx,1)
+ mov %ds,%ss:(%esp,%ebx,1)
+ mov %ds,%ss:(,%ebx,1)
+ mov %ds,%ss:(%esi,%ebx,1)
+ mov %ds,%ss:(%edi,%ebx,1)
+ mov %ds,%ss:(%eax,1)
+ mov %ds,%ss:(%ecx,1)
+ mov %ds,%ss:(%edx,1)
+ mov %ds,%ss:(%ebx,1)
+ mov %ds,%ss:(%esp,1)
+ mov %ds,%ss:(,1)
+ mov %ds,%ss:(%esi,1)
+ mov %ds,%ss:(%edi,1)
+ mov %ds,%ss:(%eax,%ebp,1)
+ mov %ds,%ss:(%ecx,%ebp,1)
+ mov %ds,%ss:(%edx,%ebp,1)
+ mov %ds,%ss:(%ebx,%ebp,1)
+ mov %ds,%ss:(%esp,%ebp,1)
+ mov %ds,%ss:(,%ebp,1)
+ mov %ds,%ss:(%esi,%ebp,1)
+ mov %ds,%ss:(%edi,%ebp,1)
+ mov %ds,%ss:(%eax,%esi,1)
+ mov %ds,%ss:(%ecx,%esi,1)
+ mov %ds,%ss:(%edx,%esi,1)
+ mov %ds,%ss:(%ebx,%esi,1)
+ mov %ds,%ss:(%esp,%esi,1)
+ mov %ds,%ss:(,%esi,1)
+ mov %ds,%ss:(%esi,%esi,1)
+ mov %ds,%ss:(%edi,%esi,1)
+ mov %ds,%ss:(%eax,%edi,1)
+ mov %ds,%ss:(%ecx,%edi,1)
+ mov %ds,%ss:(%edx,%edi,1)
+ mov %ds,%ss:(%ebx,%edi,1)
+ mov %ds,%ss:(%esp,%edi,1)
+ mov %ds,%ss:(,%edi,1)
+ mov %ds,%ss:(%esi,%edi,1)
+ mov %ds,%ss:(%edi,%edi,1)
+ mov %ds,%ss:(%eax,%eax,2)
+ mov %ds,%ss:(%ecx,%eax,2)
+ mov %ds,%ss:(%edx,%eax,2)
+ mov %ds,%ss:(%ebx,%eax,2)
+ mov %ds,%ss:(%esp,%eax,2)
+ mov %ds,%ss:(,%eax,2)
+ mov %ds,%ss:(%esi,%eax,2)
+ mov %ds,%ss:(%edi,%eax,2)
+ mov %ds,%ss:(%eax,%ecx,2)
+ mov %ds,%ss:(%ecx,%ecx,2)
+ mov %ds,%ss:(%edx,%ecx,2)
+ mov %ds,%ss:(%ebx,%ecx,2)
+ mov %ds,%ss:(%esp,%ecx,2)
+ mov %ds,%ss:(,%ecx,2)
+ mov %ds,%ss:(%esi,%ecx,2)
+ mov %ds,%ss:(%edi,%ecx,2)
+ mov %ds,%ss:(%eax,%edx,2)
+ mov %ds,%ss:(%ecx,%edx,2)
+ mov %ds,%ss:(%edx,%edx,2)
+ mov %ds,%ss:(%ebx,%edx,2)
+ mov %ds,%ss:(%esp,%edx,2)
+ mov %ds,%ss:(,%edx,2)
+ mov %ds,%ss:(%esi,%edx,2)
+ mov %ds,%ss:(%edi,%edx,2)
+ mov %ds,%ss:(%eax,%ebx,2)
+ mov %ds,%ss:(%ecx,%ebx,2)
+ mov %ds,%ss:(%edx,%ebx,2)
+ mov %ds,%ss:(%ebx,%ebx,2)
+ mov %ds,%ss:(%esp,%ebx,2)
+ mov %ds,%ss:(,%ebx,2)
+ mov %ds,%ss:(%esi,%ebx,2)
+ mov %ds,%ss:(%edi,%ebx,2)
+ mov %ds,%ss:(%eax,2)
+ mov %ds,%ss:(%ecx,2)
+ mov %ds,%ss:(%edx,2)
+ mov %ds,%ss:(%ebx,2)
+ mov %ds,%ss:(%esp,2)
+ mov %ds,%ss:(,2)
+ mov %ds,%ss:(%esi,2)
+ mov %ds,%ss:(%edi,2)
+ mov %ds,%ss:(%eax,%ebp,2)
+ mov %ds,%ss:(%ecx,%ebp,2)
+ mov %ds,%ss:(%edx,%ebp,2)
+ mov %ds,%ss:(%ebx,%ebp,2)
+ mov %ds,%ss:(%esp,%ebp,2)
+ mov %ds,%ss:(,%ebp,2)
+ mov %ds,%ss:(%esi,%ebp,2)
+ mov %ds,%ss:(%edi,%ebp,2)
+ mov %ds,%ss:(%eax,%esi,2)
+ mov %ds,%ss:(%ecx,%esi,2)
+ mov %ds,%ss:(%edx,%esi,2)
+ mov %ds,%ss:(%ebx,%esi,2)
+ mov %ds,%ss:(%esp,%esi,2)
+ mov %ds,%ss:(,%esi,2)
+ mov %ds,%ss:(%esi,%esi,2)
+ mov %ds,%ss:(%edi,%esi,2)
+ mov %ds,%ss:(%eax,%edi,2)
+ mov %ds,%ss:(%ecx,%edi,2)
+ mov %ds,%ss:(%edx,%edi,2)
+ mov %ds,%ss:(%ebx,%edi,2)
+ mov %ds,%ss:(%esp,%edi,2)
+ mov %ds,%ss:(,%edi,2)
+ mov %ds,%ss:(%esi,%edi,2)
+ mov %ds,%ss:(%edi,%edi,2)
+ mov %ds,%ss:(%eax,%eax,4)
+ mov %ds,%ss:(%ecx,%eax,4)
+ mov %ds,%ss:(%edx,%eax,4)
+ mov %ds,%ss:(%ebx,%eax,4)
+ mov %ds,%ss:(%esp,%eax,4)
+ mov %ds,%ss:(,%eax,4)
+ mov %ds,%ss:(%esi,%eax,4)
+ mov %ds,%ss:(%edi,%eax,4)
+ mov %ds,%ss:(%eax,%ecx,4)
+ mov %ds,%ss:(%ecx,%ecx,4)
+ mov %ds,%ss:(%edx,%ecx,4)
+ mov %ds,%ss:(%ebx,%ecx,4)
+ mov %ds,%ss:(%esp,%ecx,4)
+ mov %ds,%ss:(,%ecx,4)
+ mov %ds,%ss:(%esi,%ecx,4)
+ mov %ds,%ss:(%edi,%ecx,4)
+ mov %ds,%ss:(%eax,%edx,4)
+ mov %ds,%ss:(%ecx,%edx,4)
+ mov %ds,%ss:(%edx,%edx,4)
+ mov %ds,%ss:(%ebx,%edx,4)
+ mov %ds,%ss:(%esp,%edx,4)
+ mov %ds,%ss:(,%edx,4)
+ mov %ds,%ss:(%esi,%edx,4)
+ mov %ds,%ss:(%edi,%edx,4)
+ mov %ds,%ss:(%eax,%ebx,4)
+ mov %ds,%ss:(%ecx,%ebx,4)
+ mov %ds,%ss:(%edx,%ebx,4)
+ mov %ds,%ss:(%ebx,%ebx,4)
+ mov %ds,%ss:(%esp,%ebx,4)
+ mov %ds,%ss:(,%ebx,4)
+ mov %ds,%ss:(%esi,%ebx,4)
+ mov %ds,%ss:(%edi,%ebx,4)
+ mov %ds,%ss:(%eax,4)
+ mov %ds,%ss:(%ecx,4)
+ mov %ds,%ss:(%edx,4)
+ mov %ds,%ss:(%ebx,4)
+ mov %ds,%ss:(%esp,4)
+ mov %ds,%ss:(,4)
+ mov %ds,%ss:(%esi,4)
+ mov %ds,%ss:(%edi,4)
+ mov %ds,%ss:(%eax,%ebp,4)
+ mov %ds,%ss:(%ecx,%ebp,4)
+ mov %ds,%ss:(%edx,%ebp,4)
+ mov %ds,%ss:(%ebx,%ebp,4)
+ mov %ds,%ss:(%esp,%ebp,4)
+ mov %ds,%ss:(,%ebp,4)
+ mov %ds,%ss:(%esi,%ebp,4)
+ mov %ds,%ss:(%edi,%ebp,4)
+ mov %ds,%ss:(%eax,%esi,4)
+ mov %ds,%ss:(%ecx,%esi,4)
+ mov %ds,%ss:(%edx,%esi,4)
+ mov %ds,%ss:(%ebx,%esi,4)
+ mov %ds,%ss:(%esp,%esi,4)
+ mov %ds,%ss:(,%esi,4)
+ mov %ds,%ss:(%esi,%esi,4)
+ mov %ds,%ss:(%edi,%esi,4)
+ mov %ds,%ss:(%eax,%edi,4)
+ mov %ds,%ss:(%ecx,%edi,4)
+ mov %ds,%ss:(%edx,%edi,4)
+ mov %ds,%ss:(%ebx,%edi,4)
+ mov %ds,%ss:(%esp,%edi,4)
+ mov %ds,%ss:(,%edi,4)
+ mov %ds,%ss:(%esi,%edi,4)
+ mov %ds,%ss:(%edi,%edi,4)
+ mov %ds,%ss:(%eax,%eax,8)
+ mov %ds,%ss:(%ecx,%eax,8)
+ mov %ds,%ss:(%edx,%eax,8)
+ mov %ds,%ss:(%ebx,%eax,8)
+ mov %ds,%ss:(%esp,%eax,8)
+ mov %ds,%ss:(,%eax,8)
+ mov %ds,%ss:(%esi,%eax,8)
+ mov %ds,%ss:(%edi,%eax,8)
+ mov %ds,%ss:(%eax,%ecx,8)
+ mov %ds,%ss:(%ecx,%ecx,8)
+ mov %ds,%ss:(%edx,%ecx,8)
+ mov %ds,%ss:(%ebx,%ecx,8)
+ mov %ds,%ss:(%esp,%ecx,8)
+ mov %ds,%ss:(,%ecx,8)
+ mov %ds,%ss:(%esi,%ecx,8)
+ mov %ds,%ss:(%edi,%ecx,8)
+ mov %ds,%ss:(%eax,%edx,8)
+ mov %ds,%ss:(%ecx,%edx,8)
+ mov %ds,%ss:(%edx,%edx,8)
+ mov %ds,%ss:(%ebx,%edx,8)
+ mov %ds,%ss:(%esp,%edx,8)
+ mov %ds,%ss:(,%edx,8)
+ mov %ds,%ss:(%esi,%edx,8)
+ mov %ds,%ss:(%edi,%edx,8)
+ mov %ds,%ss:(%eax,%ebx,8)
+ mov %ds,%ss:(%ecx,%ebx,8)
+ mov %ds,%ss:(%edx,%ebx,8)
+ mov %ds,%ss:(%ebx,%ebx,8)
+ mov %ds,%ss:(%esp,%ebx,8)
+ mov %ds,%ss:(,%ebx,8)
+ mov %ds,%ss:(%esi,%ebx,8)
+ mov %ds,%ss:(%edi,%ebx,8)
+ mov %ds,%ss:(%eax,8)
+ mov %ds,%ss:(%ecx,8)
+ mov %ds,%ss:(%edx,8)
+ mov %ds,%ss:(%ebx,8)
+ mov %ds,%ss:(%esp,8)
+ mov %ds,%ss:(,8)
+ mov %ds,%ss:(%esi,8)
+ mov %ds,%ss:(%edi,8)
+ mov %ds,%ss:(%eax,%ebp,8)
+ mov %ds,%ss:(%ecx,%ebp,8)
+ mov %ds,%ss:(%edx,%ebp,8)
+ mov %ds,%ss:(%ebx,%ebp,8)
+ mov %ds,%ss:(%esp,%ebp,8)
+ mov %ds,%ss:(,%ebp,8)
+ mov %ds,%ss:(%esi,%ebp,8)
+ mov %ds,%ss:(%edi,%ebp,8)
+ mov %ds,%ss:(%eax,%esi,8)
+ mov %ds,%ss:(%ecx,%esi,8)
+ mov %ds,%ss:(%edx,%esi,8)
+ mov %ds,%ss:(%ebx,%esi,8)
+ mov %ds,%ss:(%esp,%esi,8)
+ mov %ds,%ss:(,%esi,8)
+ mov %ds,%ss:(%esi,%esi,8)
+ mov %ds,%ss:(%edi,%esi,8)
+ mov %ds,%ss:(%eax,%edi,8)
+ mov %ds,%ss:(%edx,%edi,8)
+ mov %ds,%ss:(%ecx,%edi,8)
+ mov %ds,%ss:(%ebx,%edi,8)
+ mov %ds,%ss:(%esp,%edi,8)
+ mov %ds,%ss:(,%edi,8)
+ mov %ds,%ss:(%esi,%edi,8)
+ mov %ds,%ss:(%edi,%edi,8)
+ mov %ds,%ss:0x12(%eax,%eax,1)
+ mov %ds,%ss:0x12(%ecx,%eax,1)
+ mov %ds,%ss:0x12(%edx,%eax,1)
+ mov %ds,%ss:0x12(%ebx,%eax,1)
+ mov %ds,%ss:0x12(%esp,%eax,1)
+ mov %ds,%ss:0x12(%ebp,%eax,1)
+ mov %ds,%ss:0x12(%esi,%eax,1)
+ mov %ds,%ss:0x12(%edi,%eax,1)
+ mov %ds,%ss:0x12(%eax,%ecx,1)
+ mov %ds,%ss:0x12(%ecx,%ecx,1)
+ mov %ds,%ss:0x12(%edx,%ecx,1)
+ mov %ds,%ss:0x12(%ebx,%ecx,1)
+ mov %ds,%ss:0x12(%esp,%ecx,1)
+ mov %ds,%ss:0x12(%ebp,%ecx,1)
+ mov %ds,%ss:0x12(%esi,%ecx,1)
+ mov %ds,%ss:0x12(%edi,%ecx,1)
+ mov %ds,%ss:0x12(%eax,%edx,1)
+ mov %ds,%ss:0x12(%ecx,%edx,1)
+ mov %ds,%ss:0x12(%edx,%edx,1)
+ mov %ds,%ss:0x12(%ebx,%edx,1)
+ mov %ds,%ss:0x12(%esp,%edx,1)
+ mov %ds,%ss:0x12(%ebp,%edx,1)
+ mov %ds,%ss:0x12(%esi,%edx,1)
+ mov %ds,%ss:0x12(%edi,%edx,1)
+ mov %ds,%ss:0x12(%eax,%ebx,1)
+ mov %ds,%ss:0x12(%ecx,%ebx,1)
+ mov %ds,%ss:0x12(%edx,%ebx,1)
+ mov %ds,%ss:0x12(%ebx,%ebx,1)
+ mov %ds,%ss:0x12(%esp,%ebx,1)
+ mov %ds,%ss:0x12(%ebp,%ebx,1)
+ mov %ds,%ss:0x12(%esi,%ebx,1)
+ mov %ds,%ss:0x12(%edi,%ebx,1)
+ mov %ds,%ss:0x12(%eax,1)
+ mov %ds,%ss:0x12(%ecx,1)
+ mov %ds,%ss:0x12(%edx,1)
+ mov %ds,%ss:0x12(%ebx,1)
+ mov %ds,%ss:0x12(%esp,1)
+ mov %ds,%ss:0x12(%ebp,1)
+ mov %ds,%ss:0x12(%esi,1)
+ mov %ds,%ss:0x12(%edi,1)
+ mov %ds,%ss:0x12(%eax,%ebp,1)
+ mov %ds,%ss:0x12(%ecx,%ebp,1)
+ mov %ds,%ss:0x12(%edx,%ebp,1)
+ mov %ds,%ss:0x12(%ebx,%ebp,1)
+ mov %ds,%ss:0x12(%esp,%ebp,1)
+ mov %ds,%ss:0x12(%ebp,%ebp,1)
+ mov %ds,%ss:0x12(%esi,%ebp,1)
+ mov %ds,%ss:0x12(%edi,%ebp,1)
+ mov %ds,%ss:0x12(%eax,%esi,1)
+ mov %ds,%ss:0x12(%ecx,%esi,1)
+ mov %ds,%ss:0x12(%edx,%esi,1)
+ mov %ds,%ss:0x12(%ebx,%esi,1)
+ mov %ds,%ss:0x12(%esp,%esi,1)
+ mov %ds,%ss:0x12(%ebp,%esi,1)
+ mov %ds,%ss:0x12(%esi,%esi,1)
+ mov %ds,%ss:0x12(%edi,%esi,1)
+ mov %ds,%ss:0x12(%eax,%edi,1)
+ mov %ds,%ss:0x12(%ecx,%edi,1)
+ mov %ds,%ss:0x12(%edx,%edi,1)
+ mov %ds,%ss:0x12(%ebx,%edi,1)
+ mov %ds,%ss:0x12(%esp,%edi,1)
+ mov %ds,%ss:0x12(%ebp,%edi,1)
+ mov %ds,%ss:0x12(%esi,%edi,1)
+ mov %ds,%ss:0x12(%edi,%edi,1)
+ mov %ds,%ss:0x12(%eax,%eax,2)
+ mov %ds,%ss:0x12(%ecx,%eax,2)
+ mov %ds,%ss:0x12(%edx,%eax,2)
+ mov %ds,%ss:0x12(%ebx,%eax,2)
+ mov %ds,%ss:0x12(%esp,%eax,2)
+ mov %ds,%ss:0x12(%ebp,%eax,2)
+ mov %ds,%ss:0x12(%esi,%eax,2)
+ mov %ds,%ss:0x12(%edi,%eax,2)
+ mov %ds,%ss:0x12(%eax,%ecx,2)
+ mov %ds,%ss:0x12(%ecx,%ecx,2)
+ mov %ds,%ss:0x12(%edx,%ecx,2)
+ mov %ds,%ss:0x12(%ebx,%ecx,2)
+ mov %ds,%ss:0x12(%esp,%ecx,2)
+ mov %ds,%ss:0x12(%ebp,%ecx,2)
+ mov %ds,%ss:0x12(%esi,%ecx,2)
+ mov %ds,%ss:0x12(%edi,%ecx,2)
+ mov %ds,%ss:0x12(%eax,%edx,2)
+ mov %ds,%ss:0x12(%ecx,%edx,2)
+ mov %ds,%ss:0x12(%edx,%edx,2)
+ mov %ds,%ss:0x12(%ebx,%edx,2)
+ mov %ds,%ss:0x12(%esp,%edx,2)
+ mov %ds,%ss:0x12(%ebp,%edx,2)
+ mov %ds,%ss:0x12(%esi,%edx,2)
+ mov %ds,%ss:0x12(%edi,%edx,2)
+ mov %ds,%ss:0x12(%eax,%ebx,2)
+ mov %ds,%ss:0x12(%ecx,%ebx,2)
+ mov %ds,%ss:0x12(%edx,%ebx,2)
+ mov %ds,%ss:0x12(%ebx,%ebx,2)
+ mov %ds,%ss:0x12(%esp,%ebx,2)
+ mov %ds,%ss:0x12(%ebp,%ebx,2)
+ mov %ds,%ss:0x12(%esi,%ebx,2)
+ mov %ds,%ss:0x12(%edi,%ebx,2)
+ mov %ds,%ss:0x12(%eax,2)
+ mov %ds,%ss:0x12(%ecx,2)
+ mov %ds,%ss:0x12(%edx,2)
+ mov %ds,%ss:0x12(%ebx,2)
+ mov %ds,%ss:0x12(%esp,2)
+ mov %ds,%ss:0x12(%ebp,2)
+ mov %ds,%ss:0x12(%esi,2)
+ mov %ds,%ss:0x12(%edi,2)
+ mov %ds,%ss:0x12(%eax,%ebp,2)
+ mov %ds,%ss:0x12(%ecx,%ebp,2)
+ mov %ds,%ss:0x12(%edx,%ebp,2)
+ mov %ds,%ss:0x12(%ebx,%ebp,2)
+ mov %ds,%ss:0x12(%esp,%ebp,2)
+ mov %ds,%ss:0x12(%ebp,%ebp,2)
+ mov %ds,%ss:0x12(%esi,%ebp,2)
+ mov %ds,%ss:0x12(%edi,%ebp,2)
+ mov %ds,%ss:0x12(%eax,%esi,2)
+ mov %ds,%ss:0x12(%ecx,%esi,2)
+ mov %ds,%ss:0x12(%edx,%esi,2)
+ mov %ds,%ss:0x12(%ebx,%esi,2)
+ mov %ds,%ss:0x12(%esp,%esi,2)
+ mov %ds,%ss:0x12(%ebp,%esi,2)
+ mov %ds,%ss:0x12(%esi,%esi,2)
+ mov %ds,%ss:0x12(%edi,%esi,2)
+ mov %ds,%ss:0x12(%eax,%edi,2)
+ mov %ds,%ss:0x12(%ecx,%edi,2)
+ mov %ds,%ss:0x12(%edx,%edi,2)
+ mov %ds,%ss:0x12(%ebx,%edi,2)
+ mov %ds,%ss:0x12(%esp,%edi,2)
+ mov %ds,%ss:0x12(%ebp,%edi,2)
+ mov %ds,%ss:0x12(%esi,%edi,2)
+ mov %ds,%ss:0x12(%edi,%edi,2)
+ mov %ds,%ss:0x12(%eax,%eax,4)
+ mov %ds,%ss:0x12(%ecx,%eax,4)
+ mov %ds,%ss:0x12(%edx,%eax,4)
+ mov %ds,%ss:0x12(%ebx,%eax,4)
+ mov %ds,%ss:0x12(%esp,%eax,4)
+ mov %ds,%ss:0x12(%ebp,%eax,4)
+ mov %ds,%ss:0x12(%esi,%eax,4)
+ mov %ds,%ss:0x12(%edi,%eax,4)
+ mov %ds,%ss:0x12(%eax,%ecx,4)
+ mov %ds,%ss:0x12(%ecx,%ecx,4)
+ mov %ds,%ss:0x12(%edx,%ecx,4)
+ mov %ds,%ss:0x12(%ebx,%ecx,4)
+ mov %ds,%ss:0x12(%esp,%ecx,4)
+ mov %ds,%ss:0x12(%ebp,%ecx,4)
+ mov %ds,%ss:0x12(%esi,%ecx,4)
+ mov %ds,%ss:0x12(%edi,%ecx,4)
+ mov %ds,%ss:0x12(%eax,%edx,4)
+ mov %ds,%ss:0x12(%ecx,%edx,4)
+ mov %ds,%ss:0x12(%edx,%edx,4)
+ mov %ds,%ss:0x12(%ebx,%edx,4)
+ mov %ds,%ss:0x12(%esp,%edx,4)
+ mov %ds,%ss:0x12(%ebp,%edx,4)
+ mov %ds,%ss:0x12(%esi,%edx,4)
+ mov %ds,%ss:0x12(%edi,%edx,4)
+ mov %ds,%ss:0x12(%eax,%ebx,4)
+ mov %ds,%ss:0x12(%ecx,%ebx,4)
+ mov %ds,%ss:0x12(%edx,%ebx,4)
+ mov %ds,%ss:0x12(%ebx,%ebx,4)
+ mov %ds,%ss:0x12(%esp,%ebx,4)
+ mov %ds,%ss:0x12(%ebp,%ebx,4)
+ mov %ds,%ss:0x12(%esi,%ebx,4)
+ mov %ds,%ss:0x12(%edi,%ebx,4)
+ mov %ds,%ss:0x12(%eax,4)
+ mov %ds,%ss:0x12(%ecx,4)
+ mov %ds,%ss:0x12(%edx,4)
+ mov %ds,%ss:0x12(%ebx,4)
+ mov %ds,%ss:0x12(%esp,4)
+ mov %ds,%ss:0x12(%ebp,4)
+ mov %ds,%ss:0x12(%esi,4)
+ mov %ds,%ss:0x12(%edi,4)
+ mov %ds,%ss:0x12(%eax,%ebp,4)
+ mov %ds,%ss:0x12(%ecx,%ebp,4)
+ mov %ds,%ss:0x12(%edx,%ebp,4)
+ mov %ds,%ss:0x12(%ebx,%ebp,4)
+ mov %ds,%ss:0x12(%esp,%ebp,4)
+ mov %ds,%ss:0x12(%ebp,%ebp,4)
+ mov %ds,%ss:0x12(%esi,%ebp,4)
+ mov %ds,%ss:0x12(%edi,%ebp,4)
+ mov %ds,%ss:0x12(%eax,%esi,4)
+ mov %ds,%ss:0x12(%ecx,%esi,4)
+ mov %ds,%ss:0x12(%edx,%esi,4)
+ mov %ds,%ss:0x12(%ebx,%esi,4)
+ mov %ds,%ss:0x12(%esp,%esi,4)
+ mov %ds,%ss:0x12(%ebp,%esi,4)
+ mov %ds,%ss:0x12(%esi,%esi,4)
+ mov %ds,%ss:0x12(%edi,%esi,4)
+ mov %ds,%ss:0x12(%eax,%edi,4)
+ mov %ds,%ss:0x12(%ecx,%edi,4)
+ mov %ds,%ss:0x12(%edx,%edi,4)
+ mov %ds,%ss:0x12(%ebx,%edi,4)
+ mov %ds,%ss:0x12(%esp,%edi,4)
+ mov %ds,%ss:0x12(%ebp,%edi,4)
+ mov %ds,%ss:0x12(%esi,%edi,4)
+ mov %ds,%ss:0x12(%edi,%edi,4)
+ mov %ds,%ss:0x12(%eax,%eax,8)
+ mov %ds,%ss:0x12(%ecx,%eax,8)
+ mov %ds,%ss:0x12(%edx,%eax,8)
+ mov %ds,%ss:0x12(%ebx,%eax,8)
+ mov %ds,%ss:0x12(%esp,%eax,8)
+ mov %ds,%ss:0x12(%ebp,%eax,8)
+ mov %ds,%ss:0x12(%esi,%eax,8)
+ mov %ds,%ss:0x12(%edi,%eax,8)
+ mov %ds,%ss:0x12(%eax,%ecx,8)
+ mov %ds,%ss:0x12(%ecx,%ecx,8)
+ mov %ds,%ss:0x12(%edx,%ecx,8)
+ mov %ds,%ss:0x12(%ebx,%ecx,8)
+ mov %ds,%ss:0x12(%esp,%ecx,8)
+ mov %ds,%ss:0x12(%ebp,%ecx,8)
+ mov %ds,%ss:0x12(%esi,%ecx,8)
+ mov %ds,%ss:0x12(%edi,%ecx,8)
+ mov %ds,%ss:0x12(%eax,%edx,8)
+ mov %ds,%ss:0x12(%ecx,%edx,8)
+ mov %ds,%ss:0x12(%edx,%edx,8)
+ mov %ds,%ss:0x12(%ebx,%edx,8)
+ mov %ds,%ss:0x12(%esp,%edx,8)
+ mov %ds,%ss:0x12(%ebp,%edx,8)
+ mov %ds,%ss:0x12(%esi,%edx,8)
+ mov %ds,%ss:0x12(%edi,%edx,8)
+ mov %ds,%ss:0x12(%eax,%ebx,8)
+ mov %ds,%ss:0x12(%ecx,%ebx,8)
+ mov %ds,%ss:0x12(%edx,%ebx,8)
+ mov %ds,%ss:0x12(%ebx,%ebx,8)
+ mov %ds,%ss:0x12(%esp,%ebx,8)
+ mov %ds,%ss:0x12(%ebp,%ebx,8)
+ mov %ds,%ss:0x12(%esi,%ebx,8)
+ mov %ds,%ss:0x12(%edi,%ebx,8)
+ mov %ds,%ss:0x12(%eax,8)
+ mov %ds,%ss:0x12(%ecx,8)
+ mov %ds,%ss:0x12(%edx,8)
+ mov %ds,%ss:0x12(%ebx,8)
+ mov %ds,%ss:0x12(%esp,8)
+ mov %ds,%ss:0x12(%ebp,8)
+ mov %ds,%ss:0x12(%esi,8)
+ mov %ds,%ss:0x12(%edi,8)
+ mov %ds,%ss:0x12(%eax,%ebp,8)
+ mov %ds,%ss:0x12(%ecx,%ebp,8)
+ mov %ds,%ss:0x12(%edx,%ebp,8)
+ mov %ds,%ss:0x12(%ebx,%ebp,8)
+ mov %ds,%ss:0x12(%esp,%ebp,8)
+ mov %ds,%ss:0x12(%ebp,%ebp,8)
+ mov %ds,%ss:0x12(%esi,%ebp,8)
+ mov %ds,%ss:0x12(%edi,%ebp,8)
+ mov %ds,%ss:0x12(%eax,%esi,8)
+ mov %ds,%ss:0x12(%ecx,%esi,8)
+ mov %ds,%ss:0x12(%edx,%esi,8)
+ mov %ds,%ss:0x12(%ebx,%esi,8)
+ mov %ds,%ss:0x12(%esp,%esi,8)
+ mov %ds,%ss:0x12(%ebp,%esi,8)
+ mov %ds,%ss:0x12(%esi,%esi,8)
+ mov %ds,%ss:0x12(%edi,%esi,8)
+ mov %ds,%ss:0x12(%eax,%edi,8)
+ mov %ds,%ss:0x12(%edx,%edi,8)
+ mov %ds,%ss:0x12(%ecx,%edi,8)
+ mov %ds,%ss:0x12(%ebx,%edi,8)
+ mov %ds,%ss:0x12(%esp,%edi,8)
+ mov %ds,%ss:0x12(%ebp,%edi,8)
+ mov %ds,%ss:0x12(%esi,%edi,8)
+ mov %ds,%ss:0x12(%edi,%edi,8)
+ mov %ds,%ss:0x12345678(%eax,%eax,1)
+ mov %ds,%ss:0x12345678(%ecx,%eax,1)
+ mov %ds,%ss:0x12345678(%edx,%eax,1)
+ mov %ds,%ss:0x12345678(%ebx,%eax,1)
+ mov %ds,%ss:0x12345678(%esp,%eax,1)
+ mov %ds,%ss:0x12345678(%ebp,%eax,1)
+ mov %ds,%ss:0x12345678(%esi,%eax,1)
+ mov %ds,%ss:0x12345678(%edi,%eax,1)
+ mov %ds,%ss:0x12345678(%eax,%ecx,1)
+ mov %ds,%ss:0x12345678(%ecx,%ecx,1)
+ mov %ds,%ss:0x12345678(%edx,%ecx,1)
+ mov %ds,%ss:0x12345678(%ebx,%ecx,1)
+ mov %ds,%ss:0x12345678(%esp,%ecx,1)
+ mov %ds,%ss:0x12345678(%ebp,%ecx,1)
+ mov %ds,%ss:0x12345678(%esi,%ecx,1)
+ mov %ds,%ss:0x12345678(%edi,%ecx,1)
+ mov %ds,%ss:0x12345678(%eax,%edx,1)
+ mov %ds,%ss:0x12345678(%ecx,%edx,1)
+ mov %ds,%ss:0x12345678(%edx,%edx,1)
+ mov %ds,%ss:0x12345678(%ebx,%edx,1)
+ mov %ds,%ss:0x12345678(%esp,%edx,1)
+ mov %ds,%ss:0x12345678(%ebp,%edx,1)
+ mov %ds,%ss:0x12345678(%esi,%edx,1)
+ mov %ds,%ss:0x12345678(%edi,%edx,1)
+ mov %ds,%ss:0x12345678(%eax,%ebx,1)
+ mov %ds,%ss:0x12345678(%ecx,%ebx,1)
+ mov %ds,%ss:0x12345678(%edx,%ebx,1)
+ mov %ds,%ss:0x12345678(%ebx,%ebx,1)
+ mov %ds,%ss:0x12345678(%esp,%ebx,1)
+ mov %ds,%ss:0x12345678(%ebp,%ebx,1)
+ mov %ds,%ss:0x12345678(%esi,%ebx,1)
+ mov %ds,%ss:0x12345678(%edi,%ebx,1)
+ mov %ds,%ss:0x12345678(%eax,1)
+ mov %ds,%ss:0x12345678(%ecx,1)
+ mov %ds,%ss:0x12345678(%edx,1)
+ mov %ds,%ss:0x12345678(%ebx,1)
+ mov %ds,%ss:0x12345678(%esp,1)
+ mov %ds,%ss:0x12345678(%ebp,1)
+ mov %ds,%ss:0x12345678(%esi,1)
+ mov %ds,%ss:0x12345678(%edi,1)
+ mov %ds,%ss:0x12345678(%eax,%ebp,1)
+ mov %ds,%ss:0x12345678(%ecx,%ebp,1)
+ mov %ds,%ss:0x12345678(%edx,%ebp,1)
+ mov %ds,%ss:0x12345678(%ebx,%ebp,1)
+ mov %ds,%ss:0x12345678(%esp,%ebp,1)
+ mov %ds,%ss:0x12345678(%ebp,%ebp,1)
+ mov %ds,%ss:0x12345678(%esi,%ebp,1)
+ mov %ds,%ss:0x12345678(%edi,%ebp,1)
+ mov %ds,%ss:0x12345678(%eax,%esi,1)
+ mov %ds,%ss:0x12345678(%ecx,%esi,1)
+ mov %ds,%ss:0x12345678(%edx,%esi,1)
+ mov %ds,%ss:0x12345678(%ebx,%esi,1)
+ mov %ds,%ss:0x12345678(%esp,%esi,1)
+ mov %ds,%ss:0x12345678(%ebp,%esi,1)
+ mov %ds,%ss:0x12345678(%esi,%esi,1)
+ mov %ds,%ss:0x12345678(%edi,%esi,1)
+ mov %ds,%ss:0x12345678(%eax,%edi,1)
+ mov %ds,%ss:0x12345678(%ecx,%edi,1)
+ mov %ds,%ss:0x12345678(%edx,%edi,1)
+ mov %ds,%ss:0x12345678(%ebx,%edi,1)
+ mov %ds,%ss:0x12345678(%esp,%edi,1)
+ mov %ds,%ss:0x12345678(%ebp,%edi,1)
+ mov %ds,%ss:0x12345678(%esi,%edi,1)
+ mov %ds,%ss:0x12345678(%edi,%edi,1)
+ mov %ds,%ss:0x12345678(%eax,%eax,2)
+ mov %ds,%ss:0x12345678(%ecx,%eax,2)
+ mov %ds,%ss:0x12345678(%edx,%eax,2)
+ mov %ds,%ss:0x12345678(%ebx,%eax,2)
+ mov %ds,%ss:0x12345678(%esp,%eax,2)
+ mov %ds,%ss:0x12345678(%ebp,%eax,2)
+ mov %ds,%ss:0x12345678(%esi,%eax,2)
+ mov %ds,%ss:0x12345678(%edi,%eax,2)
+ mov %ds,%ss:0x12345678(%eax,%ecx,2)
+ mov %ds,%ss:0x12345678(%ecx,%ecx,2)
+ mov %ds,%ss:0x12345678(%edx,%ecx,2)
+ mov %ds,%ss:0x12345678(%ebx,%ecx,2)
+ mov %ds,%ss:0x12345678(%esp,%ecx,2)
+ mov %ds,%ss:0x12345678(%ebp,%ecx,2)
+ mov %ds,%ss:0x12345678(%esi,%ecx,2)
+ mov %ds,%ss:0x12345678(%edi,%ecx,2)
+ mov %ds,%ss:0x12345678(%eax,%edx,2)
+ mov %ds,%ss:0x12345678(%ecx,%edx,2)
+ mov %ds,%ss:0x12345678(%edx,%edx,2)
+ mov %ds,%ss:0x12345678(%ebx,%edx,2)
+ mov %ds,%ss:0x12345678(%esp,%edx,2)
+ mov %ds,%ss:0x12345678(%ebp,%edx,2)
+ mov %ds,%ss:0x12345678(%esi,%edx,2)
+ mov %ds,%ss:0x12345678(%edi,%edx,2)
+ mov %ds,%ss:0x12345678(%eax,%ebx,2)
+ mov %ds,%ss:0x12345678(%ecx,%ebx,2)
+ mov %ds,%ss:0x12345678(%edx,%ebx,2)
+ mov %ds,%ss:0x12345678(%ebx,%ebx,2)
+ mov %ds,%ss:0x12345678(%esp,%ebx,2)
+ mov %ds,%ss:0x12345678(%ebp,%ebx,2)
+ mov %ds,%ss:0x12345678(%esi,%ebx,2)
+ mov %ds,%ss:0x12345678(%edi,%ebx,2)
+ mov %ds,%ss:0x12345678(%eax,2)
+ mov %ds,%ss:0x12345678(%ecx,2)
+ mov %ds,%ss:0x12345678(%edx,2)
+ mov %ds,%ss:0x12345678(%ebx,2)
+ mov %ds,%ss:0x12345678(%esp,2)
+ mov %ds,%ss:0x12345678(%ebp,2)
+ mov %ds,%ss:0x12345678(%esi,2)
+ mov %ds,%ss:0x12345678(%edi,2)
+ mov %ds,%ss:0x12345678(%eax,%ebp,2)
+ mov %ds,%ss:0x12345678(%ecx,%ebp,2)
+ mov %ds,%ss:0x12345678(%edx,%ebp,2)
+ mov %ds,%ss:0x12345678(%ebx,%ebp,2)
+ mov %ds,%ss:0x12345678(%esp,%ebp,2)
+ mov %ds,%ss:0x12345678(%ebp,%ebp,2)
+ mov %ds,%ss:0x12345678(%esi,%ebp,2)
+ mov %ds,%ss:0x12345678(%edi,%ebp,2)
+ mov %ds,%ss:0x12345678(%eax,%esi,2)
+ mov %ds,%ss:0x12345678(%ecx,%esi,2)
+ mov %ds,%ss:0x12345678(%edx,%esi,2)
+ mov %ds,%ss:0x12345678(%ebx,%esi,2)
+ mov %ds,%ss:0x12345678(%esp,%esi,2)
+ mov %ds,%ss:0x12345678(%ebp,%esi,2)
+ mov %ds,%ss:0x12345678(%esi,%esi,2)
+ mov %ds,%ss:0x12345678(%edi,%esi,2)
+ mov %ds,%ss:0x12345678(%eax,%edi,2)
+ mov %ds,%ss:0x12345678(%ecx,%edi,2)
+ mov %ds,%ss:0x12345678(%edx,%edi,2)
+ mov %ds,%ss:0x12345678(%ebx,%edi,2)
+ mov %ds,%ss:0x12345678(%esp,%edi,2)
+ mov %ds,%ss:0x12345678(%ebp,%edi,2)
+ mov %ds,%ss:0x12345678(%esi,%edi,2)
+ mov %ds,%ss:0x12345678(%edi,%edi,2)
+ mov %ds,%ss:0x12345678(%eax,%eax,4)
+ mov %ds,%ss:0x12345678(%ecx,%eax,4)
+ mov %ds,%ss:0x12345678(%edx,%eax,4)
+ mov %ds,%ss:0x12345678(%ebx,%eax,4)
+ mov %ds,%ss:0x12345678(%esp,%eax,4)
+ mov %ds,%ss:0x12345678(%ebp,%eax,4)
+ mov %ds,%ss:0x12345678(%esi,%eax,4)
+ mov %ds,%ss:0x12345678(%edi,%eax,4)
+ mov %ds,%ss:0x12345678(%eax,%ecx,4)
+ mov %ds,%ss:0x12345678(%ecx,%ecx,4)
+ mov %ds,%ss:0x12345678(%edx,%ecx,4)
+ mov %ds,%ss:0x12345678(%ebx,%ecx,4)
+ mov %ds,%ss:0x12345678(%esp,%ecx,4)
+ mov %ds,%ss:0x12345678(%ebp,%ecx,4)
+ mov %ds,%ss:0x12345678(%esi,%ecx,4)
+ mov %ds,%ss:0x12345678(%edi,%ecx,4)
+ mov %ds,%ss:0x12345678(%eax,%edx,4)
+ mov %ds,%ss:0x12345678(%ecx,%edx,4)
+ mov %ds,%ss:0x12345678(%edx,%edx,4)
+ mov %ds,%ss:0x12345678(%ebx,%edx,4)
+ mov %ds,%ss:0x12345678(%esp,%edx,4)
+ mov %ds,%ss:0x12345678(%ebp,%edx,4)
+ mov %ds,%ss:0x12345678(%esi,%edx,4)
+ mov %ds,%ss:0x12345678(%edi,%edx,4)
+ mov %ds,%ss:0x12345678(%eax,%ebx,4)
+ mov %ds,%ss:0x12345678(%ecx,%ebx,4)
+ mov %ds,%ss:0x12345678(%edx,%ebx,4)
+ mov %ds,%ss:0x12345678(%ebx,%ebx,4)
+ mov %ds,%ss:0x12345678(%esp,%ebx,4)
+ mov %ds,%ss:0x12345678(%ebp,%ebx,4)
+ mov %ds,%ss:0x12345678(%esi,%ebx,4)
+ mov %ds,%ss:0x12345678(%edi,%ebx,4)
+ mov %ds,%ss:0x12345678(%eax,4)
+ mov %ds,%ss:0x12345678(%ecx,4)
+ mov %ds,%ss:0x12345678(%edx,4)
+ mov %ds,%ss:0x12345678(%ebx,4)
+ mov %ds,%ss:0x12345678(%esp,4)
+ mov %ds,%ss:0x12345678(%ebp,4)
+ mov %ds,%ss:0x12345678(%esi,4)
+ mov %ds,%ss:0x12345678(%edi,4)
+ mov %ds,%ss:0x12345678(%eax,%ebp,4)
+ mov %ds,%ss:0x12345678(%ecx,%ebp,4)
+ mov %ds,%ss:0x12345678(%edx,%ebp,4)
+ mov %ds,%ss:0x12345678(%ebx,%ebp,4)
+ mov %ds,%ss:0x12345678(%esp,%ebp,4)
+ mov %ds,%ss:0x12345678(%ebp,%ebp,4)
+ mov %ds,%ss:0x12345678(%esi,%ebp,4)
+ mov %ds,%ss:0x12345678(%edi,%ebp,4)
+ mov %ds,%ss:0x12345678(%eax,%esi,4)
+ mov %ds,%ss:0x12345678(%ecx,%esi,4)
+ mov %ds,%ss:0x12345678(%edx,%esi,4)
+ mov %ds,%ss:0x12345678(%ebx,%esi,4)
+ mov %ds,%ss:0x12345678(%esp,%esi,4)
+ mov %ds,%ss:0x12345678(%ebp,%esi,4)
+ mov %ds,%ss:0x12345678(%esi,%esi,4)
+ mov %ds,%ss:0x12345678(%edi,%esi,4)
+ mov %ds,%ss:0x12345678(%eax,%edi,4)
+ mov %ds,%ss:0x12345678(%ecx,%edi,4)
+ mov %ds,%ss:0x12345678(%edx,%edi,4)
+ mov %ds,%ss:0x12345678(%ebx,%edi,4)
+ mov %ds,%ss:0x12345678(%esp,%edi,4)
+ mov %ds,%ss:0x12345678(%ebp,%edi,4)
+ mov %ds,%ss:0x12345678(%esi,%edi,4)
+ mov %ds,%ss:0x12345678(%edi,%edi,4)
+ mov %ds,%ss:0x12345678(%eax,%eax,8)
+ mov %ds,%ss:0x12345678(%ecx,%eax,8)
+ mov %ds,%ss:0x12345678(%edx,%eax,8)
+ mov %ds,%ss:0x12345678(%ebx,%eax,8)
+ mov %ds,%ss:0x12345678(%esp,%eax,8)
+ mov %ds,%ss:0x12345678(%ebp,%eax,8)
+ mov %ds,%ss:0x12345678(%esi,%eax,8)
+ mov %ds,%ss:0x12345678(%edi,%eax,8)
+ mov %ds,%ss:0x12345678(%eax,%ecx,8)
+ mov %ds,%ss:0x12345678(%ecx,%ecx,8)
+ mov %ds,%ss:0x12345678(%edx,%ecx,8)
+ mov %ds,%ss:0x12345678(%ebx,%ecx,8)
+ mov %ds,%ss:0x12345678(%esp,%ecx,8)
+ mov %ds,%ss:0x12345678(%ebp,%ecx,8)
+ mov %ds,%ss:0x12345678(%esi,%ecx,8)
+ mov %ds,%ss:0x12345678(%edi,%ecx,8)
+ mov %ds,%ss:0x12345678(%eax,%edx,8)
+ mov %ds,%ss:0x12345678(%ecx,%edx,8)
+ mov %ds,%ss:0x12345678(%edx,%edx,8)
+ mov %ds,%ss:0x12345678(%ebx,%edx,8)
+ mov %ds,%ss:0x12345678(%esp,%edx,8)
+ mov %ds,%ss:0x12345678(%ebp,%edx,8)
+ mov %ds,%ss:0x12345678(%esi,%edx,8)
+ mov %ds,%ss:0x12345678(%edi,%edx,8)
+ mov %ds,%ss:0x12345678(%eax,%ebx,8)
+ mov %ds,%ss:0x12345678(%ecx,%ebx,8)
+ mov %ds,%ss:0x12345678(%edx,%ebx,8)
+ mov %ds,%ss:0x12345678(%ebx,%ebx,8)
+ mov %ds,%ss:0x12345678(%esp,%ebx,8)
+ mov %ds,%ss:0x12345678(%ebp,%ebx,8)
+ mov %ds,%ss:0x12345678(%esi,%ebx,8)
+ mov %ds,%ss:0x12345678(%edi,%ebx,8)
+ mov %ds,%ss:0x12345678(%eax,8)
+ mov %ds,%ss:0x12345678(%ecx,8)
+ mov %ds,%ss:0x12345678(%edx,8)
+ mov %ds,%ss:0x12345678(%ebx,8)
+ mov %ds,%ss:0x12345678(%esp,8)
+ mov %ds,%ss:0x12345678(%ebp,8)
+ mov %ds,%ss:0x12345678(%esi,8)
+ mov %ds,%ss:0x12345678(%edi,8)
+ mov %ds,%ss:0x12345678(%eax,%ebp,8)
+ mov %ds,%ss:0x12345678(%ecx,%ebp,8)
+ mov %ds,%ss:0x12345678(%edx,%ebp,8)
+ mov %ds,%ss:0x12345678(%ebx,%ebp,8)
+ mov %ds,%ss:0x12345678(%esp,%ebp,8)
+ mov %ds,%ss:0x12345678(%ebp,%ebp,8)
+ mov %ds,%ss:0x12345678(%esi,%ebp,8)
+ mov %ds,%ss:0x12345678(%edi,%ebp,8)
+ mov %ds,%ss:0x12345678(%eax,%esi,8)
+ mov %ds,%ss:0x12345678(%ecx,%esi,8)
+ mov %ds,%ss:0x12345678(%edx,%esi,8)
+ mov %ds,%ss:0x12345678(%ebx,%esi,8)
+ mov %ds,%ss:0x12345678(%esp,%esi,8)
+ mov %ds,%ss:0x12345678(%ebp,%esi,8)
+ mov %ds,%ss:0x12345678(%esi,%esi,8)
+ mov %ds,%ss:0x12345678(%edi,%esi,8)
+ mov %ds,%ss:0x12345678(%eax,%edi,8)
+ mov %ds,%ss:0x12345678(%edx,%edi,8)
+ mov %ds,%ss:0x12345678(%ecx,%edi,8)
+ mov %ds,%ss:0x12345678(%ebx,%edi,8)
+ mov %ds,%ss:0x12345678(%esp,%edi,8)
+ mov %ds,%ss:0x12345678(%ebp,%edi,8)
+ mov %ds,%ss:0x12345678(%esi,%edi,8)
+ mov %ds,%ss:0x12345678(%edi,%edi,8)
+ mov %ds,%ss:(%ebp,%eax,1)
+ mov %ds,%ss:(%ebp,%ecx,1)
+ mov %ds,%ss:(%ebp,%edx,1)
+ mov %ds,%ss:(%ebp,%ebx,1)
+ mov %ds,%ss:(%ebp,1)
+ mov %ds,%ss:(%ebp,%ebp,1)
+ mov %ds,%ss:(%ebp,%esi,1)
+ mov %ds,%ss:(%ebp,%edi,1)
+ mov %ds,%ss:(%ebp,%eax,2)
+ mov %ds,%ss:(%ebp,%ecx,2)
+ mov %ds,%ss:(%ebp,%edx,2)
+ mov %ds,%ss:(%ebp,%ebx,2)
+ mov %ds,%ss:(%ebp,2)
+ mov %ds,%ss:(%ebp,%ebp,2)
+ mov %ds,%ss:(%ebp,%esi,2)
+ mov %ds,%ss:(%ebp,%edi,2)
+ mov %ds,%ss:(%ebp,%eax,4)
+ mov %ds,%ss:(%ebp,%ecx,4)
+ mov %ds,%ss:(%ebp,%edx,4)
+ mov %ds,%ss:(%ebp,%ebx,4)
+ mov %ds,%ss:(%ebp,4)
+ mov %ds,%ss:(%ebp,%ebp,4)
+ mov %ds,%ss:(%ebp,%esi,4)
+ mov %ds,%ss:(%ebp,%edi,4)
+ mov %ds,%ss:(%ebp,%eax,8)
+ mov %ds,%ss:(%ebp,%ecx,8)
+ mov %ds,%ss:(%ebp,%edx,8)
+ mov %ds,%ss:(%ebp,%ebx,8)
+ mov %ds,%ss:(%ebp,8)
+ mov %ds,%ss:(%ebp,%ebp,8)
+ mov %ds,%ss:(%ebp,%esi,8)
+ mov %ds,%ss:(%ebp,%edi,8)
+ mov %ds,%ss:0x12(,1)
+ mov %ds,%ss:0x12(,2)
+ mov %ds,%ss:0x12(,4)
+ mov %ds,%ss:0x12(,8)
+ mov %ds,%ds:(%eax)
+ mov %ds,%ds:(%ecx)
+ mov %ds,%ds:(%edx)
+ mov %ds,%ds:(%ebx)
+ mov %ds,%ds:0
+ mov %ds,%ds:(%esi)
+ mov %ds,%ds:(%edi)
+ mov %ds,%ds:0x12(%eax)
+ mov %ds,%ds:0x12(%ecx)
+ mov %ds,%ds:0x12(%edx)
+ mov %ds,%ds:0x12(%ebx)
+ mov %ds,%ds:0x12(%ebp)
+ mov %ds,%ds:0x12(%esi)
+ mov %ds,%ds:0x12(%edi)
+ mov %ds,%ds:0x12345678(%eax)
+ mov %ds,%ds:0x12345678(%ecx)
+ mov %ds,%ds:0x12345678(%edx)
+ mov %ds,%ds:0x12345678(%ebx)
+ mov %ds,%ds:0x12345678(%ebp)
+ mov %ds,%ds:0x12345678(%esi)
+ mov %ds,%ds:0x12345678(%edi)
+ mov %ds,%eax
+ mov %ds,%ecx
+ mov %ds,%edx
+ mov %ds,%ebx
+ mov %ds,%esp
+ mov %ds,%ebp
+ mov %ds,%esi
+ mov %ds,%edi
+ mov %ds,%ds:(%eax,%eax,1)
+ mov %ds,%ds:(%ecx,%eax,1)
+ mov %ds,%ds:(%edx,%eax,1)
+ mov %ds,%ds:(%ebx,%eax,1)
+ mov %ds,%ds:(%esp,%eax,1)
+ mov %ds,%ds:(,%eax,1)
+ mov %ds,%ds:(%esi,%eax,1)
+ mov %ds,%ds:(%edi,%eax,1)
+ mov %ds,%ds:(%eax,%ecx,1)
+ mov %ds,%ds:(%ecx,%ecx,1)
+ mov %ds,%ds:(%edx,%ecx,1)
+ mov %ds,%ds:(%ebx,%ecx,1)
+ mov %ds,%ds:(%esp,%ecx,1)
+ mov %ds,%ds:(,%ecx,1)
+ mov %ds,%ds:(%esi,%ecx,1)
+ mov %ds,%ds:(%edi,%ecx,1)
+ mov %ds,%ds:(%eax,%edx,1)
+ mov %ds,%ds:(%ecx,%edx,1)
+ mov %ds,%ds:(%edx,%edx,1)
+ mov %ds,%ds:(%ebx,%edx,1)
+ mov %ds,%ds:(%esp,%edx,1)
+ mov %ds,%ds:(,%edx,1)
+ mov %ds,%ds:(%esi,%edx,1)
+ mov %ds,%ds:(%edi,%edx,1)
+ mov %ds,%ds:(%eax,%ebx,1)
+ mov %ds,%ds:(%ecx,%ebx,1)
+ mov %ds,%ds:(%edx,%ebx,1)
+ mov %ds,%ds:(%ebx,%ebx,1)
+ mov %ds,%ds:(%esp,%ebx,1)
+ mov %ds,%ds:(,%ebx,1)
+ mov %ds,%ds:(%esi,%ebx,1)
+ mov %ds,%ds:(%edi,%ebx,1)
+ mov %ds,%ds:(%eax,1)
+ mov %ds,%ds:(%ecx,1)
+ mov %ds,%ds:(%edx,1)
+ mov %ds,%ds:(%ebx,1)
+ mov %ds,%ds:(%esp,1)
+ mov %ds,%ds:(,1)
+ mov %ds,%ds:(%esi,1)
+ mov %ds,%ds:(%edi,1)
+ mov %ds,%ds:(%eax,%ebp,1)
+ mov %ds,%ds:(%ecx,%ebp,1)
+ mov %ds,%ds:(%edx,%ebp,1)
+ mov %ds,%ds:(%ebx,%ebp,1)
+ mov %ds,%ds:(%esp,%ebp,1)
+ mov %ds,%ds:(,%ebp,1)
+ mov %ds,%ds:(%esi,%ebp,1)
+ mov %ds,%ds:(%edi,%ebp,1)
+ mov %ds,%ds:(%eax,%esi,1)
+ mov %ds,%ds:(%ecx,%esi,1)
+ mov %ds,%ds:(%edx,%esi,1)
+ mov %ds,%ds:(%ebx,%esi,1)
+ mov %ds,%ds:(%esp,%esi,1)
+ mov %ds,%ds:(,%esi,1)
+ mov %ds,%ds:(%esi,%esi,1)
+ mov %ds,%ds:(%edi,%esi,1)
+ mov %ds,%ds:(%eax,%edi,1)
+ mov %ds,%ds:(%ecx,%edi,1)
+ mov %ds,%ds:(%edx,%edi,1)
+ mov %ds,%ds:(%ebx,%edi,1)
+ mov %ds,%ds:(%esp,%edi,1)
+ mov %ds,%ds:(,%edi,1)
+ mov %ds,%ds:(%esi,%edi,1)
+ mov %ds,%ds:(%edi,%edi,1)
+ mov %ds,%ds:(%eax,%eax,2)
+ mov %ds,%ds:(%ecx,%eax,2)
+ mov %ds,%ds:(%edx,%eax,2)
+ mov %ds,%ds:(%ebx,%eax,2)
+ mov %ds,%ds:(%esp,%eax,2)
+ mov %ds,%ds:(,%eax,2)
+ mov %ds,%ds:(%esi,%eax,2)
+ mov %ds,%ds:(%edi,%eax,2)
+ mov %ds,%ds:(%eax,%ecx,2)
+ mov %ds,%ds:(%ecx,%ecx,2)
+ mov %ds,%ds:(%edx,%ecx,2)
+ mov %ds,%ds:(%ebx,%ecx,2)
+ mov %ds,%ds:(%esp,%ecx,2)
+ mov %ds,%ds:(,%ecx,2)
+ mov %ds,%ds:(%esi,%ecx,2)
+ mov %ds,%ds:(%edi,%ecx,2)
+ mov %ds,%ds:(%eax,%edx,2)
+ mov %ds,%ds:(%ecx,%edx,2)
+ mov %ds,%ds:(%edx,%edx,2)
+ mov %ds,%ds:(%ebx,%edx,2)
+ mov %ds,%ds:(%esp,%edx,2)
+ mov %ds,%ds:(,%edx,2)
+ mov %ds,%ds:(%esi,%edx,2)
+ mov %ds,%ds:(%edi,%edx,2)
+ mov %ds,%ds:(%eax,%ebx,2)
+ mov %ds,%ds:(%ecx,%ebx,2)
+ mov %ds,%ds:(%edx,%ebx,2)
+ mov %ds,%ds:(%ebx,%ebx,2)
+ mov %ds,%ds:(%esp,%ebx,2)
+ mov %ds,%ds:(,%ebx,2)
+ mov %ds,%ds:(%esi,%ebx,2)
+ mov %ds,%ds:(%edi,%ebx,2)
+ mov %ds,%ds:(%eax,2)
+ mov %ds,%ds:(%ecx,2)
+ mov %ds,%ds:(%edx,2)
+ mov %ds,%ds:(%ebx,2)
+ mov %ds,%ds:(%esp,2)
+ mov %ds,%ds:(,2)
+ mov %ds,%ds:(%esi,2)
+ mov %ds,%ds:(%edi,2)
+ mov %ds,%ds:(%eax,%ebp,2)
+ mov %ds,%ds:(%ecx,%ebp,2)
+ mov %ds,%ds:(%edx,%ebp,2)
+ mov %ds,%ds:(%ebx,%ebp,2)
+ mov %ds,%ds:(%esp,%ebp,2)
+ mov %ds,%ds:(,%ebp,2)
+ mov %ds,%ds:(%esi,%ebp,2)
+ mov %ds,%ds:(%edi,%ebp,2)
+ mov %ds,%ds:(%eax,%esi,2)
+ mov %ds,%ds:(%ecx,%esi,2)
+ mov %ds,%ds:(%edx,%esi,2)
+ mov %ds,%ds:(%ebx,%esi,2)
+ mov %ds,%ds:(%esp,%esi,2)
+ mov %ds,%ds:(,%esi,2)
+ mov %ds,%ds:(%esi,%esi,2)
+ mov %ds,%ds:(%edi,%esi,2)
+ mov %ds,%ds:(%eax,%edi,2)
+ mov %ds,%ds:(%ecx,%edi,2)
+ mov %ds,%ds:(%edx,%edi,2)
+ mov %ds,%ds:(%ebx,%edi,2)
+ mov %ds,%ds:(%esp,%edi,2)
+ mov %ds,%ds:(,%edi,2)
+ mov %ds,%ds:(%esi,%edi,2)
+ mov %ds,%ds:(%edi,%edi,2)
+ mov %ds,%ds:(%eax,%eax,4)
+ mov %ds,%ds:(%ecx,%eax,4)
+ mov %ds,%ds:(%edx,%eax,4)
+ mov %ds,%ds:(%ebx,%eax,4)
+ mov %ds,%ds:(%esp,%eax,4)
+ mov %ds,%ds:(,%eax,4)
+ mov %ds,%ds:(%esi,%eax,4)
+ mov %ds,%ds:(%edi,%eax,4)
+ mov %ds,%ds:(%eax,%ecx,4)
+ mov %ds,%ds:(%ecx,%ecx,4)
+ mov %ds,%ds:(%edx,%ecx,4)
+ mov %ds,%ds:(%ebx,%ecx,4)
+ mov %ds,%ds:(%esp,%ecx,4)
+ mov %ds,%ds:(,%ecx,4)
+ mov %ds,%ds:(%esi,%ecx,4)
+ mov %ds,%ds:(%edi,%ecx,4)
+ mov %ds,%ds:(%eax,%edx,4)
+ mov %ds,%ds:(%ecx,%edx,4)
+ mov %ds,%ds:(%edx,%edx,4)
+ mov %ds,%ds:(%ebx,%edx,4)
+ mov %ds,%ds:(%esp,%edx,4)
+ mov %ds,%ds:(,%edx,4)
+ mov %ds,%ds:(%esi,%edx,4)
+ mov %ds,%ds:(%edi,%edx,4)
+ mov %ds,%ds:(%eax,%ebx,4)
+ mov %ds,%ds:(%ecx,%ebx,4)
+ mov %ds,%ds:(%edx,%ebx,4)
+ mov %ds,%ds:(%ebx,%ebx,4)
+ mov %ds,%ds:(%esp,%ebx,4)
+ mov %ds,%ds:(,%ebx,4)
+ mov %ds,%ds:(%esi,%ebx,4)
+ mov %ds,%ds:(%edi,%ebx,4)
+ mov %ds,%ds:(%eax,4)
+ mov %ds,%ds:(%ecx,4)
+ mov %ds,%ds:(%edx,4)
+ mov %ds,%ds:(%ebx,4)
+ mov %ds,%ds:(%esp,4)
+ mov %ds,%ds:(,4)
+ mov %ds,%ds:(%esi,4)
+ mov %ds,%ds:(%edi,4)
+ mov %ds,%ds:(%eax,%ebp,4)
+ mov %ds,%ds:(%ecx,%ebp,4)
+ mov %ds,%ds:(%edx,%ebp,4)
+ mov %ds,%ds:(%ebx,%ebp,4)
+ mov %ds,%ds:(%esp,%ebp,4)
+ mov %ds,%ds:(,%ebp,4)
+ mov %ds,%ds:(%esi,%ebp,4)
+ mov %ds,%ds:(%edi,%ebp,4)
+ mov %ds,%ds:(%eax,%esi,4)
+ mov %ds,%ds:(%ecx,%esi,4)
+ mov %ds,%ds:(%edx,%esi,4)
+ mov %ds,%ds:(%ebx,%esi,4)
+ mov %ds,%ds:(%esp,%esi,4)
+ mov %ds,%ds:(,%esi,4)
+ mov %ds,%ds:(%esi,%esi,4)
+ mov %ds,%ds:(%edi,%esi,4)
+ mov %ds,%ds:(%eax,%edi,4)
+ mov %ds,%ds:(%ecx,%edi,4)
+ mov %ds,%ds:(%edx,%edi,4)
+ mov %ds,%ds:(%ebx,%edi,4)
+ mov %ds,%ds:(%esp,%edi,4)
+ mov %ds,%ds:(,%edi,4)
+ mov %ds,%ds:(%esi,%edi,4)
+ mov %ds,%ds:(%edi,%edi,4)
+ mov %ds,%ds:(%eax,%eax,8)
+ mov %ds,%ds:(%ecx,%eax,8)
+ mov %ds,%ds:(%edx,%eax,8)
+ mov %ds,%ds:(%ebx,%eax,8)
+ mov %ds,%ds:(%esp,%eax,8)
+ mov %ds,%ds:(,%eax,8)
+ mov %ds,%ds:(%esi,%eax,8)
+ mov %ds,%ds:(%edi,%eax,8)
+ mov %ds,%ds:(%eax,%ecx,8)
+ mov %ds,%ds:(%ecx,%ecx,8)
+ mov %ds,%ds:(%edx,%ecx,8)
+ mov %ds,%ds:(%ebx,%ecx,8)
+ mov %ds,%ds:(%esp,%ecx,8)
+ mov %ds,%ds:(,%ecx,8)
+ mov %ds,%ds:(%esi,%ecx,8)
+ mov %ds,%ds:(%edi,%ecx,8)
+ mov %ds,%ds:(%eax,%edx,8)
+ mov %ds,%ds:(%ecx,%edx,8)
+ mov %ds,%ds:(%edx,%edx,8)
+ mov %ds,%ds:(%ebx,%edx,8)
+ mov %ds,%ds:(%esp,%edx,8)
+ mov %ds,%ds:(,%edx,8)
+ mov %ds,%ds:(%esi,%edx,8)
+ mov %ds,%ds:(%edi,%edx,8)
+ mov %ds,%ds:(%eax,%ebx,8)
+ mov %ds,%ds:(%ecx,%ebx,8)
+ mov %ds,%ds:(%edx,%ebx,8)
+ mov %ds,%ds:(%ebx,%ebx,8)
+ mov %ds,%ds:(%esp,%ebx,8)
+ mov %ds,%ds:(,%ebx,8)
+ mov %ds,%ds:(%esi,%ebx,8)
+ mov %ds,%ds:(%edi,%ebx,8)
+ mov %ds,%ds:(%eax,8)
+ mov %ds,%ds:(%ecx,8)
+ mov %ds,%ds:(%edx,8)
+ mov %ds,%ds:(%ebx,8)
+ mov %ds,%ds:(%esp,8)
+ mov %ds,%ds:(,8)
+ mov %ds,%ds:(%esi,8)
+ mov %ds,%ds:(%edi,8)
+ mov %ds,%ds:(%eax,%ebp,8)
+ mov %ds,%ds:(%ecx,%ebp,8)
+ mov %ds,%ds:(%edx,%ebp,8)
+ mov %ds,%ds:(%ebx,%ebp,8)
+ mov %ds,%ds:(%esp,%ebp,8)
+ mov %ds,%ds:(,%ebp,8)
+ mov %ds,%ds:(%esi,%ebp,8)
+ mov %ds,%ds:(%edi,%ebp,8)
+ mov %ds,%ds:(%eax,%esi,8)
+ mov %ds,%ds:(%ecx,%esi,8)
+ mov %ds,%ds:(%edx,%esi,8)
+ mov %ds,%ds:(%ebx,%esi,8)
+ mov %ds,%ds:(%esp,%esi,8)
+ mov %ds,%ds:(,%esi,8)
+ mov %ds,%ds:(%esi,%esi,8)
+ mov %ds,%ds:(%edi,%esi,8)
+ mov %ds,%ds:(%eax,%edi,8)
+ mov %ds,%ds:(%edx,%edi,8)
+ mov %ds,%ds:(%ecx,%edi,8)
+ mov %ds,%ds:(%ebx,%edi,8)
+ mov %ds,%ds:(%esp,%edi,8)
+ mov %ds,%ds:(,%edi,8)
+ mov %ds,%ds:(%esi,%edi,8)
+ mov %ds,%ds:(%edi,%edi,8)
+ mov %ds,%ds:0x12(%eax,%eax,1)
+ mov %ds,%ds:0x12(%ecx,%eax,1)
+ mov %ds,%ds:0x12(%edx,%eax,1)
+ mov %ds,%ds:0x12(%ebx,%eax,1)
+ mov %ds,%ds:0x12(%esp,%eax,1)
+ mov %ds,%ds:0x12(%ebp,%eax,1)
+ mov %ds,%ds:0x12(%esi,%eax,1)
+ mov %ds,%ds:0x12(%edi,%eax,1)
+ mov %ds,%ds:0x12(%eax,%ecx,1)
+ mov %ds,%ds:0x12(%ecx,%ecx,1)
+ mov %ds,%ds:0x12(%edx,%ecx,1)
+ mov %ds,%ds:0x12(%ebx,%ecx,1)
+ mov %ds,%ds:0x12(%esp,%ecx,1)
+ mov %ds,%ds:0x12(%ebp,%ecx,1)
+ mov %ds,%ds:0x12(%esi,%ecx,1)
+ mov %ds,%ds:0x12(%edi,%ecx,1)
+ mov %ds,%ds:0x12(%eax,%edx,1)
+ mov %ds,%ds:0x12(%ecx,%edx,1)
+ mov %ds,%ds:0x12(%edx,%edx,1)
+ mov %ds,%ds:0x12(%ebx,%edx,1)
+ mov %ds,%ds:0x12(%esp,%edx,1)
+ mov %ds,%ds:0x12(%ebp,%edx,1)
+ mov %ds,%ds:0x12(%esi,%edx,1)
+ mov %ds,%ds:0x12(%edi,%edx,1)
+ mov %ds,%ds:0x12(%eax,%ebx,1)
+ mov %ds,%ds:0x12(%ecx,%ebx,1)
+ mov %ds,%ds:0x12(%edx,%ebx,1)
+ mov %ds,%ds:0x12(%ebx,%ebx,1)
+ mov %ds,%ds:0x12(%esp,%ebx,1)
+ mov %ds,%ds:0x12(%ebp,%ebx,1)
+ mov %ds,%ds:0x12(%esi,%ebx,1)
+ mov %ds,%ds:0x12(%edi,%ebx,1)
+ mov %ds,%ds:0x12(%eax,1)
+ mov %ds,%ds:0x12(%ecx,1)
+ mov %ds,%ds:0x12(%edx,1)
+ mov %ds,%ds:0x12(%ebx,1)
+ mov %ds,%ds:0x12(%esp,1)
+ mov %ds,%ds:0x12(%ebp,1)
+ mov %ds,%ds:0x12(%esi,1)
+ mov %ds,%ds:0x12(%edi,1)
+ mov %ds,%ds:0x12(%eax,%ebp,1)
+ mov %ds,%ds:0x12(%ecx,%ebp,1)
+ mov %ds,%ds:0x12(%edx,%ebp,1)
+ mov %ds,%ds:0x12(%ebx,%ebp,1)
+ mov %ds,%ds:0x12(%esp,%ebp,1)
+ mov %ds,%ds:0x12(%ebp,%ebp,1)
+ mov %ds,%ds:0x12(%esi,%ebp,1)
+ mov %ds,%ds:0x12(%edi,%ebp,1)
+ mov %ds,%ds:0x12(%eax,%esi,1)
+ mov %ds,%ds:0x12(%ecx,%esi,1)
+ mov %ds,%ds:0x12(%edx,%esi,1)
+ mov %ds,%ds:0x12(%ebx,%esi,1)
+ mov %ds,%ds:0x12(%esp,%esi,1)
+ mov %ds,%ds:0x12(%ebp,%esi,1)
+ mov %ds,%ds:0x12(%esi,%esi,1)
+ mov %ds,%ds:0x12(%edi,%esi,1)
+ mov %ds,%ds:0x12(%eax,%edi,1)
+ mov %ds,%ds:0x12(%ecx,%edi,1)
+ mov %ds,%ds:0x12(%edx,%edi,1)
+ mov %ds,%ds:0x12(%ebx,%edi,1)
+ mov %ds,%ds:0x12(%esp,%edi,1)
+ mov %ds,%ds:0x12(%ebp,%edi,1)
+ mov %ds,%ds:0x12(%esi,%edi,1)
+ mov %ds,%ds:0x12(%edi,%edi,1)
+ mov %ds,%ds:0x12(%eax,%eax,2)
+ mov %ds,%ds:0x12(%ecx,%eax,2)
+ mov %ds,%ds:0x12(%edx,%eax,2)
+ mov %ds,%ds:0x12(%ebx,%eax,2)
+ mov %ds,%ds:0x12(%esp,%eax,2)
+ mov %ds,%ds:0x12(%ebp,%eax,2)
+ mov %ds,%ds:0x12(%esi,%eax,2)
+ mov %ds,%ds:0x12(%edi,%eax,2)
+ mov %ds,%ds:0x12(%eax,%ecx,2)
+ mov %ds,%ds:0x12(%ecx,%ecx,2)
+ mov %ds,%ds:0x12(%edx,%ecx,2)
+ mov %ds,%ds:0x12(%ebx,%ecx,2)
+ mov %ds,%ds:0x12(%esp,%ecx,2)
+ mov %ds,%ds:0x12(%ebp,%ecx,2)
+ mov %ds,%ds:0x12(%esi,%ecx,2)
+ mov %ds,%ds:0x12(%edi,%ecx,2)
+ mov %ds,%ds:0x12(%eax,%edx,2)
+ mov %ds,%ds:0x12(%ecx,%edx,2)
+ mov %ds,%ds:0x12(%edx,%edx,2)
+ mov %ds,%ds:0x12(%ebx,%edx,2)
+ mov %ds,%ds:0x12(%esp,%edx,2)
+ mov %ds,%ds:0x12(%ebp,%edx,2)
+ mov %ds,%ds:0x12(%esi,%edx,2)
+ mov %ds,%ds:0x12(%edi,%edx,2)
+ mov %ds,%ds:0x12(%eax,%ebx,2)
+ mov %ds,%ds:0x12(%ecx,%ebx,2)
+ mov %ds,%ds:0x12(%edx,%ebx,2)
+ mov %ds,%ds:0x12(%ebx,%ebx,2)
+ mov %ds,%ds:0x12(%esp,%ebx,2)
+ mov %ds,%ds:0x12(%ebp,%ebx,2)
+ mov %ds,%ds:0x12(%esi,%ebx,2)
+ mov %ds,%ds:0x12(%edi,%ebx,2)
+ mov %ds,%ds:0x12(%eax,2)
+ mov %ds,%ds:0x12(%ecx,2)
+ mov %ds,%ds:0x12(%edx,2)
+ mov %ds,%ds:0x12(%ebx,2)
+ mov %ds,%ds:0x12(%esp,2)
+ mov %ds,%ds:0x12(%ebp,2)
+ mov %ds,%ds:0x12(%esi,2)
+ mov %ds,%ds:0x12(%edi,2)
+ mov %ds,%ds:0x12(%eax,%ebp,2)
+ mov %ds,%ds:0x12(%ecx,%ebp,2)
+ mov %ds,%ds:0x12(%edx,%ebp,2)
+ mov %ds,%ds:0x12(%ebx,%ebp,2)
+ mov %ds,%ds:0x12(%esp,%ebp,2)
+ mov %ds,%ds:0x12(%ebp,%ebp,2)
+ mov %ds,%ds:0x12(%esi,%ebp,2)
+ mov %ds,%ds:0x12(%edi,%ebp,2)
+ mov %ds,%ds:0x12(%eax,%esi,2)
+ mov %ds,%ds:0x12(%ecx,%esi,2)
+ mov %ds,%ds:0x12(%edx,%esi,2)
+ mov %ds,%ds:0x12(%ebx,%esi,2)
+ mov %ds,%ds:0x12(%esp,%esi,2)
+ mov %ds,%ds:0x12(%ebp,%esi,2)
+ mov %ds,%ds:0x12(%esi,%esi,2)
+ mov %ds,%ds:0x12(%edi,%esi,2)
+ mov %ds,%ds:0x12(%eax,%edi,2)
+ mov %ds,%ds:0x12(%ecx,%edi,2)
+ mov %ds,%ds:0x12(%edx,%edi,2)
+ mov %ds,%ds:0x12(%ebx,%edi,2)
+ mov %ds,%ds:0x12(%esp,%edi,2)
+ mov %ds,%ds:0x12(%ebp,%edi,2)
+ mov %ds,%ds:0x12(%esi,%edi,2)
+ mov %ds,%ds:0x12(%edi,%edi,2)
+ mov %ds,%ds:0x12(%eax,%eax,4)
+ mov %ds,%ds:0x12(%ecx,%eax,4)
+ mov %ds,%ds:0x12(%edx,%eax,4)
+ mov %ds,%ds:0x12(%ebx,%eax,4)
+ mov %ds,%ds:0x12(%esp,%eax,4)
+ mov %ds,%ds:0x12(%ebp,%eax,4)
+ mov %ds,%ds:0x12(%esi,%eax,4)
+ mov %ds,%ds:0x12(%edi,%eax,4)
+ mov %ds,%ds:0x12(%eax,%ecx,4)
+ mov %ds,%ds:0x12(%ecx,%ecx,4)
+ mov %ds,%ds:0x12(%edx,%ecx,4)
+ mov %ds,%ds:0x12(%ebx,%ecx,4)
+ mov %ds,%ds:0x12(%esp,%ecx,4)
+ mov %ds,%ds:0x12(%ebp,%ecx,4)
+ mov %ds,%ds:0x12(%esi,%ecx,4)
+ mov %ds,%ds:0x12(%edi,%ecx,4)
+ mov %ds,%ds:0x12(%eax,%edx,4)
+ mov %ds,%ds:0x12(%ecx,%edx,4)
+ mov %ds,%ds:0x12(%edx,%edx,4)
+ mov %ds,%ds:0x12(%ebx,%edx,4)
+ mov %ds,%ds:0x12(%esp,%edx,4)
+ mov %ds,%ds:0x12(%ebp,%edx,4)
+ mov %ds,%ds:0x12(%esi,%edx,4)
+ mov %ds,%ds:0x12(%edi,%edx,4)
+ mov %ds,%ds:0x12(%eax,%ebx,4)
+ mov %ds,%ds:0x12(%ecx,%ebx,4)
+ mov %ds,%ds:0x12(%edx,%ebx,4)
+ mov %ds,%ds:0x12(%ebx,%ebx,4)
+ mov %ds,%ds:0x12(%esp,%ebx,4)
+ mov %ds,%ds:0x12(%ebp,%ebx,4)
+ mov %ds,%ds:0x12(%esi,%ebx,4)
+ mov %ds,%ds:0x12(%edi,%ebx,4)
+ mov %ds,%ds:0x12(%eax,4)
+ mov %ds,%ds:0x12(%ecx,4)
+ mov %ds,%ds:0x12(%edx,4)
+ mov %ds,%ds:0x12(%ebx,4)
+ mov %ds,%ds:0x12(%esp,4)
+ mov %ds,%ds:0x12(%ebp,4)
+ mov %ds,%ds:0x12(%esi,4)
+ mov %ds,%ds:0x12(%edi,4)
+ mov %ds,%ds:0x12(%eax,%ebp,4)
+ mov %ds,%ds:0x12(%ecx,%ebp,4)
+ mov %ds,%ds:0x12(%edx,%ebp,4)
+ mov %ds,%ds:0x12(%ebx,%ebp,4)
+ mov %ds,%ds:0x12(%esp,%ebp,4)
+ mov %ds,%ds:0x12(%ebp,%ebp,4)
+ mov %ds,%ds:0x12(%esi,%ebp,4)
+ mov %ds,%ds:0x12(%edi,%ebp,4)
+ mov %ds,%ds:0x12(%eax,%esi,4)
+ mov %ds,%ds:0x12(%ecx,%esi,4)
+ mov %ds,%ds:0x12(%edx,%esi,4)
+ mov %ds,%ds:0x12(%ebx,%esi,4)
+ mov %ds,%ds:0x12(%esp,%esi,4)
+ mov %ds,%ds:0x12(%ebp,%esi,4)
+ mov %ds,%ds:0x12(%esi,%esi,4)
+ mov %ds,%ds:0x12(%edi,%esi,4)
+ mov %ds,%ds:0x12(%eax,%edi,4)
+ mov %ds,%ds:0x12(%ecx,%edi,4)
+ mov %ds,%ds:0x12(%edx,%edi,4)
+ mov %ds,%ds:0x12(%ebx,%edi,4)
+ mov %ds,%ds:0x12(%esp,%edi,4)
+ mov %ds,%ds:0x12(%ebp,%edi,4)
+ mov %ds,%ds:0x12(%esi,%edi,4)
+ mov %ds,%ds:0x12(%edi,%edi,4)
+ mov %ds,%ds:0x12(%eax,%eax,8)
+ mov %ds,%ds:0x12(%ecx,%eax,8)
+ mov %ds,%ds:0x12(%edx,%eax,8)
+ mov %ds,%ds:0x12(%ebx,%eax,8)
+ mov %ds,%ds:0x12(%esp,%eax,8)
+ mov %ds,%ds:0x12(%ebp,%eax,8)
+ mov %ds,%ds:0x12(%esi,%eax,8)
+ mov %ds,%ds:0x12(%edi,%eax,8)
+ mov %ds,%ds:0x12(%eax,%ecx,8)
+ mov %ds,%ds:0x12(%ecx,%ecx,8)
+ mov %ds,%ds:0x12(%edx,%ecx,8)
+ mov %ds,%ds:0x12(%ebx,%ecx,8)
+ mov %ds,%ds:0x12(%esp,%ecx,8)
+ mov %ds,%ds:0x12(%ebp,%ecx,8)
+ mov %ds,%ds:0x12(%esi,%ecx,8)
+ mov %ds,%ds:0x12(%edi,%ecx,8)
+ mov %ds,%ds:0x12(%eax,%edx,8)
+ mov %ds,%ds:0x12(%ecx,%edx,8)
+ mov %ds,%ds:0x12(%edx,%edx,8)
+ mov %ds,%ds:0x12(%ebx,%edx,8)
+ mov %ds,%ds:0x12(%esp,%edx,8)
+ mov %ds,%ds:0x12(%ebp,%edx,8)
+ mov %ds,%ds:0x12(%esi,%edx,8)
+ mov %ds,%ds:0x12(%edi,%edx,8)
+ mov %ds,%ds:0x12(%eax,%ebx,8)
+ mov %ds,%ds:0x12(%ecx,%ebx,8)
+ mov %ds,%ds:0x12(%edx,%ebx,8)
+ mov %ds,%ds:0x12(%ebx,%ebx,8)
+ mov %ds,%ds:0x12(%esp,%ebx,8)
+ mov %ds,%ds:0x12(%ebp,%ebx,8)
+ mov %ds,%ds:0x12(%esi,%ebx,8)
+ mov %ds,%ds:0x12(%edi,%ebx,8)
+ mov %ds,%ds:0x12(%eax,8)
+ mov %ds,%ds:0x12(%ecx,8)
+ mov %ds,%ds:0x12(%edx,8)
+ mov %ds,%ds:0x12(%ebx,8)
+ mov %ds,%ds:0x12(%esp,8)
+ mov %ds,%ds:0x12(%ebp,8)
+ mov %ds,%ds:0x12(%esi,8)
+ mov %ds,%ds:0x12(%edi,8)
+ mov %ds,%ds:0x12(%eax,%ebp,8)
+ mov %ds,%ds:0x12(%ecx,%ebp,8)
+ mov %ds,%ds:0x12(%edx,%ebp,8)
+ mov %ds,%ds:0x12(%ebx,%ebp,8)
+ mov %ds,%ds:0x12(%esp,%ebp,8)
+ mov %ds,%ds:0x12(%ebp,%ebp,8)
+ mov %ds,%ds:0x12(%esi,%ebp,8)
+ mov %ds,%ds:0x12(%edi,%ebp,8)
+ mov %ds,%ds:0x12(%eax,%esi,8)
+ mov %ds,%ds:0x12(%ecx,%esi,8)
+ mov %ds,%ds:0x12(%edx,%esi,8)
+ mov %ds,%ds:0x12(%ebx,%esi,8)
+ mov %ds,%ds:0x12(%esp,%esi,8)
+ mov %ds,%ds:0x12(%ebp,%esi,8)
+ mov %ds,%ds:0x12(%esi,%esi,8)
+ mov %ds,%ds:0x12(%edi,%esi,8)
+ mov %ds,%ds:0x12(%eax,%edi,8)
+ mov %ds,%ds:0x12(%edx,%edi,8)
+ mov %ds,%ds:0x12(%ecx,%edi,8)
+ mov %ds,%ds:0x12(%ebx,%edi,8)
+ mov %ds,%ds:0x12(%esp,%edi,8)
+ mov %ds,%ds:0x12(%ebp,%edi,8)
+ mov %ds,%ds:0x12(%esi,%edi,8)
+ mov %ds,%ds:0x12(%edi,%edi,8)
+ mov %ds,%ds:0x12345678(%eax,%eax,1)
+ mov %ds,%ds:0x12345678(%ecx,%eax,1)
+ mov %ds,%ds:0x12345678(%edx,%eax,1)
+ mov %ds,%ds:0x12345678(%ebx,%eax,1)
+ mov %ds,%ds:0x12345678(%esp,%eax,1)
+ mov %ds,%ds:0x12345678(%ebp,%eax,1)
+ mov %ds,%ds:0x12345678(%esi,%eax,1)
+ mov %ds,%ds:0x12345678(%edi,%eax,1)
+ mov %ds,%ds:0x12345678(%eax,%ecx,1)
+ mov %ds,%ds:0x12345678(%ecx,%ecx,1)
+ mov %ds,%ds:0x12345678(%edx,%ecx,1)
+ mov %ds,%ds:0x12345678(%ebx,%ecx,1)
+ mov %ds,%ds:0x12345678(%esp,%ecx,1)
+ mov %ds,%ds:0x12345678(%ebp,%ecx,1)
+ mov %ds,%ds:0x12345678(%esi,%ecx,1)
+ mov %ds,%ds:0x12345678(%edi,%ecx,1)
+ mov %ds,%ds:0x12345678(%eax,%edx,1)
+ mov %ds,%ds:0x12345678(%ecx,%edx,1)
+ mov %ds,%ds:0x12345678(%edx,%edx,1)
+ mov %ds,%ds:0x12345678(%ebx,%edx,1)
+ mov %ds,%ds:0x12345678(%esp,%edx,1)
+ mov %ds,%ds:0x12345678(%ebp,%edx,1)
+ mov %ds,%ds:0x12345678(%esi,%edx,1)
+ mov %ds,%ds:0x12345678(%edi,%edx,1)
+ mov %ds,%ds:0x12345678(%eax,%ebx,1)
+ mov %ds,%ds:0x12345678(%ecx,%ebx,1)
+ mov %ds,%ds:0x12345678(%edx,%ebx,1)
+ mov %ds,%ds:0x12345678(%ebx,%ebx,1)
+ mov %ds,%ds:0x12345678(%esp,%ebx,1)
+ mov %ds,%ds:0x12345678(%ebp,%ebx,1)
+ mov %ds,%ds:0x12345678(%esi,%ebx,1)
+ mov %ds,%ds:0x12345678(%edi,%ebx,1)
+ mov %ds,%ds:0x12345678(%eax,1)
+ mov %ds,%ds:0x12345678(%ecx,1)
+ mov %ds,%ds:0x12345678(%edx,1)
+ mov %ds,%ds:0x12345678(%ebx,1)
+ mov %ds,%ds:0x12345678(%esp,1)
+ mov %ds,%ds:0x12345678(%ebp,1)
+ mov %ds,%ds:0x12345678(%esi,1)
+ mov %ds,%ds:0x12345678(%edi,1)
+ mov %ds,%ds:0x12345678(%eax,%ebp,1)
+ mov %ds,%ds:0x12345678(%ecx,%ebp,1)
+ mov %ds,%ds:0x12345678(%edx,%ebp,1)
+ mov %ds,%ds:0x12345678(%ebx,%ebp,1)
+ mov %ds,%ds:0x12345678(%esp,%ebp,1)
+ mov %ds,%ds:0x12345678(%ebp,%ebp,1)
+ mov %ds,%ds:0x12345678(%esi,%ebp,1)
+ mov %ds,%ds:0x12345678(%edi,%ebp,1)
+ mov %ds,%ds:0x12345678(%eax,%esi,1)
+ mov %ds,%ds:0x12345678(%ecx,%esi,1)
+ mov %ds,%ds:0x12345678(%edx,%esi,1)
+ mov %ds,%ds:0x12345678(%ebx,%esi,1)
+ mov %ds,%ds:0x12345678(%esp,%esi,1)
+ mov %ds,%ds:0x12345678(%ebp,%esi,1)
+ mov %ds,%ds:0x12345678(%esi,%esi,1)
+ mov %ds,%ds:0x12345678(%edi,%esi,1)
+ mov %ds,%ds:0x12345678(%eax,%edi,1)
+ mov %ds,%ds:0x12345678(%ecx,%edi,1)
+ mov %ds,%ds:0x12345678(%edx,%edi,1)
+ mov %ds,%ds:0x12345678(%ebx,%edi,1)
+ mov %ds,%ds:0x12345678(%esp,%edi,1)
+ mov %ds,%ds:0x12345678(%ebp,%edi,1)
+ mov %ds,%ds:0x12345678(%esi,%edi,1)
+ mov %ds,%ds:0x12345678(%edi,%edi,1)
+ mov %ds,%ds:0x12345678(%eax,%eax,2)
+ mov %ds,%ds:0x12345678(%ecx,%eax,2)
+ mov %ds,%ds:0x12345678(%edx,%eax,2)
+ mov %ds,%ds:0x12345678(%ebx,%eax,2)
+ mov %ds,%ds:0x12345678(%esp,%eax,2)
+ mov %ds,%ds:0x12345678(%ebp,%eax,2)
+ mov %ds,%ds:0x12345678(%esi,%eax,2)
+ mov %ds,%ds:0x12345678(%edi,%eax,2)
+ mov %ds,%ds:0x12345678(%eax,%ecx,2)
+ mov %ds,%ds:0x12345678(%ecx,%ecx,2)
+ mov %ds,%ds:0x12345678(%edx,%ecx,2)
+ mov %ds,%ds:0x12345678(%ebx,%ecx,2)
+ mov %ds,%ds:0x12345678(%esp,%ecx,2)
+ mov %ds,%ds:0x12345678(%ebp,%ecx,2)
+ mov %ds,%ds:0x12345678(%esi,%ecx,2)
+ mov %ds,%ds:0x12345678(%edi,%ecx,2)
+ mov %ds,%ds:0x12345678(%eax,%edx,2)
+ mov %ds,%ds:0x12345678(%ecx,%edx,2)
+ mov %ds,%ds:0x12345678(%edx,%edx,2)
+ mov %ds,%ds:0x12345678(%ebx,%edx,2)
+ mov %ds,%ds:0x12345678(%esp,%edx,2)
+ mov %ds,%ds:0x12345678(%ebp,%edx,2)
+ mov %ds,%ds:0x12345678(%esi,%edx,2)
+ mov %ds,%ds:0x12345678(%edi,%edx,2)
+ mov %ds,%ds:0x12345678(%eax,%ebx,2)
+ mov %ds,%ds:0x12345678(%ecx,%ebx,2)
+ mov %ds,%ds:0x12345678(%edx,%ebx,2)
+ mov %ds,%ds:0x12345678(%ebx,%ebx,2)
+ mov %ds,%ds:0x12345678(%esp,%ebx,2)
+ mov %ds,%ds:0x12345678(%ebp,%ebx,2)
+ mov %ds,%ds:0x12345678(%esi,%ebx,2)
+ mov %ds,%ds:0x12345678(%edi,%ebx,2)
+ mov %ds,%ds:0x12345678(%eax,2)
+ mov %ds,%ds:0x12345678(%ecx,2)
+ mov %ds,%ds:0x12345678(%edx,2)
+ mov %ds,%ds:0x12345678(%ebx,2)
+ mov %ds,%ds:0x12345678(%esp,2)
+ mov %ds,%ds:0x12345678(%ebp,2)
+ mov %ds,%ds:0x12345678(%esi,2)
+ mov %ds,%ds:0x12345678(%edi,2)
+ mov %ds,%ds:0x12345678(%eax,%ebp,2)
+ mov %ds,%ds:0x12345678(%ecx,%ebp,2)
+ mov %ds,%ds:0x12345678(%edx,%ebp,2)
+ mov %ds,%ds:0x12345678(%ebx,%ebp,2)
+ mov %ds,%ds:0x12345678(%esp,%ebp,2)
+ mov %ds,%ds:0x12345678(%ebp,%ebp,2)
+ mov %ds,%ds:0x12345678(%esi,%ebp,2)
+ mov %ds,%ds:0x12345678(%edi,%ebp,2)
+ mov %ds,%ds:0x12345678(%eax,%esi,2)
+ mov %ds,%ds:0x12345678(%ecx,%esi,2)
+ mov %ds,%ds:0x12345678(%edx,%esi,2)
+ mov %ds,%ds:0x12345678(%ebx,%esi,2)
+ mov %ds,%ds:0x12345678(%esp,%esi,2)
+ mov %ds,%ds:0x12345678(%ebp,%esi,2)
+ mov %ds,%ds:0x12345678(%esi,%esi,2)
+ mov %ds,%ds:0x12345678(%edi,%esi,2)
+ mov %ds,%ds:0x12345678(%eax,%edi,2)
+ mov %ds,%ds:0x12345678(%ecx,%edi,2)
+ mov %ds,%ds:0x12345678(%edx,%edi,2)
+ mov %ds,%ds:0x12345678(%ebx,%edi,2)
+ mov %ds,%ds:0x12345678(%esp,%edi,2)
+ mov %ds,%ds:0x12345678(%ebp,%edi,2)
+ mov %ds,%ds:0x12345678(%esi,%edi,2)
+ mov %ds,%ds:0x12345678(%edi,%edi,2)
+ mov %ds,%ds:0x12345678(%eax,%eax,4)
+ mov %ds,%ds:0x12345678(%ecx,%eax,4)
+ mov %ds,%ds:0x12345678(%edx,%eax,4)
+ mov %ds,%ds:0x12345678(%ebx,%eax,4)
+ mov %ds,%ds:0x12345678(%esp,%eax,4)
+ mov %ds,%ds:0x12345678(%ebp,%eax,4)
+ mov %ds,%ds:0x12345678(%esi,%eax,4)
+ mov %ds,%ds:0x12345678(%edi,%eax,4)
+ mov %ds,%ds:0x12345678(%eax,%ecx,4)
+ mov %ds,%ds:0x12345678(%ecx,%ecx,4)
+ mov %ds,%ds:0x12345678(%edx,%ecx,4)
+ mov %ds,%ds:0x12345678(%ebx,%ecx,4)
+ mov %ds,%ds:0x12345678(%esp,%ecx,4)
+ mov %ds,%ds:0x12345678(%ebp,%ecx,4)
+ mov %ds,%ds:0x12345678(%esi,%ecx,4)
+ mov %ds,%ds:0x12345678(%edi,%ecx,4)
+ mov %ds,%ds:0x12345678(%eax,%edx,4)
+ mov %ds,%ds:0x12345678(%ecx,%edx,4)
+ mov %ds,%ds:0x12345678(%edx,%edx,4)
+ mov %ds,%ds:0x12345678(%ebx,%edx,4)
+ mov %ds,%ds:0x12345678(%esp,%edx,4)
+ mov %ds,%ds:0x12345678(%ebp,%edx,4)
+ mov %ds,%ds:0x12345678(%esi,%edx,4)
+ mov %ds,%ds:0x12345678(%edi,%edx,4)
+ mov %ds,%ds:0x12345678(%eax,%ebx,4)
+ mov %ds,%ds:0x12345678(%ecx,%ebx,4)
+ mov %ds,%ds:0x12345678(%edx,%ebx,4)
+ mov %ds,%ds:0x12345678(%ebx,%ebx,4)
+ mov %ds,%ds:0x12345678(%esp,%ebx,4)
+ mov %ds,%ds:0x12345678(%ebp,%ebx,4)
+ mov %ds,%ds:0x12345678(%esi,%ebx,4)
+ mov %ds,%ds:0x12345678(%edi,%ebx,4)
+ mov %ds,%ds:0x12345678(%eax,4)
+ mov %ds,%ds:0x12345678(%ecx,4)
+ mov %ds,%ds:0x12345678(%edx,4)
+ mov %ds,%ds:0x12345678(%ebx,4)
+ mov %ds,%ds:0x12345678(%esp,4)
+ mov %ds,%ds:0x12345678(%ebp,4)
+ mov %ds,%ds:0x12345678(%esi,4)
+ mov %ds,%ds:0x12345678(%edi,4)
+ mov %ds,%ds:0x12345678(%eax,%ebp,4)
+ mov %ds,%ds:0x12345678(%ecx,%ebp,4)
+ mov %ds,%ds:0x12345678(%edx,%ebp,4)
+ mov %ds,%ds:0x12345678(%ebx,%ebp,4)
+ mov %ds,%ds:0x12345678(%esp,%ebp,4)
+ mov %ds,%ds:0x12345678(%ebp,%ebp,4)
+ mov %ds,%ds:0x12345678(%esi,%ebp,4)
+ mov %ds,%ds:0x12345678(%edi,%ebp,4)
+ mov %ds,%ds:0x12345678(%eax,%esi,4)
+ mov %ds,%ds:0x12345678(%ecx,%esi,4)
+ mov %ds,%ds:0x12345678(%edx,%esi,4)
+ mov %ds,%ds:0x12345678(%ebx,%esi,4)
+ mov %ds,%ds:0x12345678(%esp,%esi,4)
+ mov %ds,%ds:0x12345678(%ebp,%esi,4)
+ mov %ds,%ds:0x12345678(%esi,%esi,4)
+ mov %ds,%ds:0x12345678(%edi,%esi,4)
+ mov %ds,%ds:0x12345678(%eax,%edi,4)
+ mov %ds,%ds:0x12345678(%ecx,%edi,4)
+ mov %ds,%ds:0x12345678(%edx,%edi,4)
+ mov %ds,%ds:0x12345678(%ebx,%edi,4)
+ mov %ds,%ds:0x12345678(%esp,%edi,4)
+ mov %ds,%ds:0x12345678(%ebp,%edi,4)
+ mov %ds,%ds:0x12345678(%esi,%edi,4)
+ mov %ds,%ds:0x12345678(%edi,%edi,4)
+ mov %ds,%ds:0x12345678(%eax,%eax,8)
+ mov %ds,%ds:0x12345678(%ecx,%eax,8)
+ mov %ds,%ds:0x12345678(%edx,%eax,8)
+ mov %ds,%ds:0x12345678(%ebx,%eax,8)
+ mov %ds,%ds:0x12345678(%esp,%eax,8)
+ mov %ds,%ds:0x12345678(%ebp,%eax,8)
+ mov %ds,%ds:0x12345678(%esi,%eax,8)
+ mov %ds,%ds:0x12345678(%edi,%eax,8)
+ mov %ds,%ds:0x12345678(%eax,%ecx,8)
+ mov %ds,%ds:0x12345678(%ecx,%ecx,8)
+ mov %ds,%ds:0x12345678(%edx,%ecx,8)
+ mov %ds,%ds:0x12345678(%ebx,%ecx,8)
+ mov %ds,%ds:0x12345678(%esp,%ecx,8)
+ mov %ds,%ds:0x12345678(%ebp,%ecx,8)
+ mov %ds,%ds:0x12345678(%esi,%ecx,8)
+ mov %ds,%ds:0x12345678(%edi,%ecx,8)
+ mov %ds,%ds:0x12345678(%eax,%edx,8)
+ mov %ds,%ds:0x12345678(%ecx,%edx,8)
+ mov %ds,%ds:0x12345678(%edx,%edx,8)
+ mov %ds,%ds:0x12345678(%ebx,%edx,8)
+ mov %ds,%ds:0x12345678(%esp,%edx,8)
+ mov %ds,%ds:0x12345678(%ebp,%edx,8)
+ mov %ds,%ds:0x12345678(%esi,%edx,8)
+ mov %ds,%ds:0x12345678(%edi,%edx,8)
+ mov %ds,%ds:0x12345678(%eax,%ebx,8)
+ mov %ds,%ds:0x12345678(%ecx,%ebx,8)
+ mov %ds,%ds:0x12345678(%edx,%ebx,8)
+ mov %ds,%ds:0x12345678(%ebx,%ebx,8)
+ mov %ds,%ds:0x12345678(%esp,%ebx,8)
+ mov %ds,%ds:0x12345678(%ebp,%ebx,8)
+ mov %ds,%ds:0x12345678(%esi,%ebx,8)
+ mov %ds,%ds:0x12345678(%edi,%ebx,8)
+ mov %ds,%ds:0x12345678(%eax,8)
+ mov %ds,%ds:0x12345678(%ecx,8)
+ mov %ds,%ds:0x12345678(%edx,8)
+ mov %ds,%ds:0x12345678(%ebx,8)
+ mov %ds,%ds:0x12345678(%esp,8)
+ mov %ds,%ds:0x12345678(%ebp,8)
+ mov %ds,%ds:0x12345678(%esi,8)
+ mov %ds,%ds:0x12345678(%edi,8)
+ mov %ds,%ds:0x12345678(%eax,%ebp,8)
+ mov %ds,%ds:0x12345678(%ecx,%ebp,8)
+ mov %ds,%ds:0x12345678(%edx,%ebp,8)
+ mov %ds,%ds:0x12345678(%ebx,%ebp,8)
+ mov %ds,%ds:0x12345678(%esp,%ebp,8)
+ mov %ds,%ds:0x12345678(%ebp,%ebp,8)
+ mov %ds,%ds:0x12345678(%esi,%ebp,8)
+ mov %ds,%ds:0x12345678(%edi,%ebp,8)
+ mov %ds,%ds:0x12345678(%eax,%esi,8)
+ mov %ds,%ds:0x12345678(%ecx,%esi,8)
+ mov %ds,%ds:0x12345678(%edx,%esi,8)
+ mov %ds,%ds:0x12345678(%ebx,%esi,8)
+ mov %ds,%ds:0x12345678(%esp,%esi,8)
+ mov %ds,%ds:0x12345678(%ebp,%esi,8)
+ mov %ds,%ds:0x12345678(%esi,%esi,8)
+ mov %ds,%ds:0x12345678(%edi,%esi,8)
+ mov %ds,%ds:0x12345678(%eax,%edi,8)
+ mov %ds,%ds:0x12345678(%edx,%edi,8)
+ mov %ds,%ds:0x12345678(%ecx,%edi,8)
+ mov %ds,%ds:0x12345678(%ebx,%edi,8)
+ mov %ds,%ds:0x12345678(%esp,%edi,8)
+ mov %ds,%ds:0x12345678(%ebp,%edi,8)
+ mov %ds,%ds:0x12345678(%esi,%edi,8)
+ mov %ds,%ds:0x12345678(%edi,%edi,8)
+ mov %ds,%ds:(%ebp,%eax,1)
+ mov %ds,%ds:(%ebp,%ecx,1)
+ mov %ds,%ds:(%ebp,%edx,1)
+ mov %ds,%ds:(%ebp,%ebx,1)
+ mov %ds,%ds:(%ebp,1)
+ mov %ds,%ds:(%ebp,%ebp,1)
+ mov %ds,%ds:(%ebp,%esi,1)
+ mov %ds,%ds:(%ebp,%edi,1)
+ mov %ds,%ds:(%ebp,%eax,2)
+ mov %ds,%ds:(%ebp,%ecx,2)
+ mov %ds,%ds:(%ebp,%edx,2)
+ mov %ds,%ds:(%ebp,%ebx,2)
+ mov %ds,%ds:(%ebp,2)
+ mov %ds,%ds:(%ebp,%ebp,2)
+ mov %ds,%ds:(%ebp,%esi,2)
+ mov %ds,%ds:(%ebp,%edi,2)
+ mov %ds,%ds:(%ebp,%eax,4)
+ mov %ds,%ds:(%ebp,%ecx,4)
+ mov %ds,%ds:(%ebp,%edx,4)
+ mov %ds,%ds:(%ebp,%ebx,4)
+ mov %ds,%ds:(%ebp,4)
+ mov %ds,%ds:(%ebp,%ebp,4)
+ mov %ds,%ds:(%ebp,%esi,4)
+ mov %ds,%ds:(%ebp,%edi,4)
+ mov %ds,%ds:(%ebp,%eax,8)
+ mov %ds,%ds:(%ebp,%ecx,8)
+ mov %ds,%ds:(%ebp,%edx,8)
+ mov %ds,%ds:(%ebp,%ebx,8)
+ mov %ds,%ds:(%ebp,8)
+ mov %ds,%ds:(%ebp,%ebp,8)
+ mov %ds,%ds:(%ebp,%esi,8)
+ mov %ds,%ds:(%ebp,%edi,8)
+ mov %ds,%ds:0x12(,1)
+ mov %ds,%ds:0x12(,2)
+ mov %ds,%ds:0x12(,4)
+ mov %ds,%ds:0x12(,8)
+
+ # Force a good alignment.
+ .byte 0
diff --git a/gas/testsuite/gas/i386/opcode.d b/gas/testsuite/gas/i386/opcode.d
new file mode 100644
index 0000000000..fc3c158a16
--- /dev/null
+++ b/gas/testsuite/gas/i386/opcode.d
@@ -0,0 +1,574 @@
+#as: -J
+#objdump: -dw
+#name: i386 opcode
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+000 <foo>:
+ 0: 00 90 90 90 90 90 [ ]*add %dl,0x90909090\(%eax\)
+ 6: 01 90 90 90 90 90 [ ]*add %edx,0x90909090\(%eax\)
+ c: 02 90 90 90 90 90 [ ]*add 0x90909090\(%eax\),%dl
+ 12: 03 90 90 90 90 90 [ ]*add 0x90909090\(%eax\),%edx
+ 18: 04 90 [ ]*add \$0x90,%al
+ 1a: 05 90 90 90 90 [ ]*add \$0x90909090,%eax
+ 1f: 06 [ ]*push %es
+ 20: 07 [ ]*pop %es
+ 21: 08 90 90 90 90 90 [ ]*or %dl,0x90909090\(%eax\)
+ 27: 09 90 90 90 90 90 [ ]*or %edx,0x90909090\(%eax\)
+ 2d: 0a 90 90 90 90 90 [ ]*or 0x90909090\(%eax\),%dl
+ 33: 0b 90 90 90 90 90 [ ]*or 0x90909090\(%eax\),%edx
+ 39: 0c 90 [ ]*or \$0x90,%al
+ 3b: 0d 90 90 90 90 [ ]*or \$0x90909090,%eax
+ 40: 0e [ ]*push %cs
+ 41: 10 90 90 90 90 90 [ ]*adc %dl,0x90909090\(%eax\)
+ 47: 11 90 90 90 90 90 [ ]*adc %edx,0x90909090\(%eax\)
+ 4d: 12 90 90 90 90 90 [ ]*adc 0x90909090\(%eax\),%dl
+ 53: 13 90 90 90 90 90 [ ]*adc 0x90909090\(%eax\),%edx
+ 59: 14 90 [ ]*adc \$0x90,%al
+ 5b: 15 90 90 90 90 [ ]*adc \$0x90909090,%eax
+ 60: 16 [ ]*push %ss
+ 61: 17 [ ]*pop %ss
+ 62: 18 90 90 90 90 90 [ ]*sbb %dl,0x90909090\(%eax\)
+ 68: 19 90 90 90 90 90 [ ]*sbb %edx,0x90909090\(%eax\)
+ 6e: 1a 90 90 90 90 90 [ ]*sbb 0x90909090\(%eax\),%dl
+ 74: 1b 90 90 90 90 90 [ ]*sbb 0x90909090\(%eax\),%edx
+ 7a: 1c 90 [ ]*sbb \$0x90,%al
+ 7c: 1d 90 90 90 90 [ ]*sbb \$0x90909090,%eax
+ 81: 1e [ ]*push %ds
+ 82: 1f [ ]*pop %ds
+ 83: 20 90 90 90 90 90 [ ]*and %dl,0x90909090\(%eax\)
+ 89: 21 90 90 90 90 90 [ ]*and %edx,0x90909090\(%eax\)
+ 8f: 22 90 90 90 90 90 [ ]*and 0x90909090\(%eax\),%dl
+ 95: 23 90 90 90 90 90 [ ]*and 0x90909090\(%eax\),%edx
+ 9b: 24 90 [ ]*and \$0x90,%al
+ 9d: 25 90 90 90 90 [ ]*and \$0x90909090,%eax
+ a2: 27 [ ]*daa
+ a3: 28 90 90 90 90 90 [ ]*sub %dl,0x90909090\(%eax\)
+ a9: 29 90 90 90 90 90 [ ]*sub %edx,0x90909090\(%eax\)
+ af: 2a 90 90 90 90 90 [ ]*sub 0x90909090\(%eax\),%dl
+ b5: 2b 90 90 90 90 90 [ ]*sub 0x90909090\(%eax\),%edx
+ bb: 2c 90 [ ]*sub \$0x90,%al
+ bd: 2d 90 90 90 90 [ ]*sub \$0x90909090,%eax
+ c2: 2f [ ]*das
+ c3: 30 90 90 90 90 90 [ ]*xor %dl,0x90909090\(%eax\)
+ c9: 31 90 90 90 90 90 [ ]*xor %edx,0x90909090\(%eax\)
+ cf: 32 90 90 90 90 90 [ ]*xor 0x90909090\(%eax\),%dl
+ d5: 33 90 90 90 90 90 [ ]*xor 0x90909090\(%eax\),%edx
+ db: 34 90 [ ]*xor \$0x90,%al
+ dd: 35 90 90 90 90 [ ]*xor \$0x90909090,%eax
+ e2: 37 [ ]*aaa
+ e3: 38 90 90 90 90 90 [ ]*cmp %dl,0x90909090\(%eax\)
+ e9: 39 90 90 90 90 90 [ ]*cmp %edx,0x90909090\(%eax\)
+ ef: 3a 90 90 90 90 90 [ ]*cmp 0x90909090\(%eax\),%dl
+ f5: 3b 90 90 90 90 90 [ ]*cmp 0x90909090\(%eax\),%edx
+ fb: 3c 90 [ ]*cmp \$0x90,%al
+ fd: 3d 90 90 90 90 [ ]*cmp \$0x90909090,%eax
+ 102: 3f [ ]*aas
+ 103: 40 [ ]*inc %eax
+ 104: 41 [ ]*inc %ecx
+ 105: 42 [ ]*inc %edx
+ 106: 43 [ ]*inc %ebx
+ 107: 44 [ ]*inc %esp
+ 108: 45 [ ]*inc %ebp
+ 109: 46 [ ]*inc %esi
+ 10a: 47 [ ]*inc %edi
+ 10b: 48 [ ]*dec %eax
+ 10c: 49 [ ]*dec %ecx
+ 10d: 4a [ ]*dec %edx
+ 10e: 4b [ ]*dec %ebx
+ 10f: 4c [ ]*dec %esp
+ 110: 4d [ ]*dec %ebp
+ 111: 4e [ ]*dec %esi
+ 112: 4f [ ]*dec %edi
+ 113: 50 [ ]*push %eax
+ 114: 51 [ ]*push %ecx
+ 115: 52 [ ]*push %edx
+ 116: 53 [ ]*push %ebx
+ 117: 54 [ ]*push %esp
+ 118: 55 [ ]*push %ebp
+ 119: 56 [ ]*push %esi
+ 11a: 57 [ ]*push %edi
+ 11b: 58 [ ]*pop %eax
+ 11c: 59 [ ]*pop %ecx
+ 11d: 5a [ ]*pop %edx
+ 11e: 5b [ ]*pop %ebx
+ 11f: 5c [ ]*pop %esp
+ 120: 5d [ ]*pop %ebp
+ 121: 5e [ ]*pop %esi
+ 122: 5f [ ]*pop %edi
+ 123: 60 [ ]*pusha
+ 124: 61 [ ]*popa
+ 125: 62 90 90 90 90 90 [ ]*bound %edx,0x90909090\(%eax\)
+ 12b: 63 90 90 90 90 90 [ ]*arpl %dx,0x90909090\(%eax\)
+ 131: 68 90 90 90 90 [ ]*push \$0x90909090
+ 136: 69 90 90 90 90 90 90 90 90 90 [ ]*imul \$0x90909090,0x90909090\(%eax\),%edx
+ 140: 6a 90 [ ]*push \$0xffffff90
+ 142: 6b 90 90 90 90 90 90 [ ]*imul \$0xffffff90,0x90909090\(%eax\),%edx
+ 149: 6c [ ]*insb \(%dx\),%es:\(%edi\)
+ 14a: 6d [ ]*insl \(%dx\),%es:\(%edi\)
+ 14b: 6e [ ]*outsb %ds:\(%esi\),\(%dx\)
+ 14c: 6f [ ]*outsl %ds:\(%esi\),\(%dx\)
+ 14d: 70 90 [ ]*jo (0x)?df.*
+ 14f: 71 90 [ ]*jno (0x)?e1.*
+ 151: 72 90 [ ]*jb (0x)?e3.*
+ 153: 73 90 [ ]*jae (0x)?e5.*
+ 155: 74 90 [ ]*je (0x)?e7.*
+ 157: 75 90 [ ]*jne (0x)?e9.*
+ 159: 76 90 [ ]*jbe (0x)?eb.*
+ 15b: 77 90 [ ]*ja (0x)?ed.*
+ 15d: 78 90 [ ]*js (0x)?ef.*
+ 15f: 79 90 [ ]*jns (0x)?f1.*
+ 161: 7a 90 [ ]*jp (0x)?f3.*
+ 163: 7b 90 [ ]*jnp (0x)?f5.*
+ 165: 7c 90 [ ]*jl (0x)?f7.*
+ 167: 7d 90 [ ]*jge (0x)?f9.*
+ 169: 7e 90 [ ]*jle (0x)?fb.*
+ 16b: 7f 90 [ ]*jg (0x)?fd.*
+ 16d: 80 90 90 90 90 90 90 [ ]*adcb \$0x90,0x90909090\(%eax\)
+ 174: 81 90 90 90 90 90 90 90 90 90 [ ]*adcl \$0x90909090,0x90909090\(%eax\)
+ 17e: 83 90 90 90 90 90 90 [ ]*adcl \$0xffffff90,0x90909090\(%eax\)
+ 185: 84 90 90 90 90 90 [ ]*test %dl,0x90909090\(%eax\)
+ 18b: 85 90 90 90 90 90 [ ]*test %edx,0x90909090\(%eax\)
+ 191: 86 90 90 90 90 90 [ ]*xchg %dl,0x90909090\(%eax\)
+ 197: 87 90 90 90 90 90 [ ]*xchg %edx,0x90909090\(%eax\)
+ 19d: 88 90 90 90 90 90 [ ]*mov %dl,0x90909090\(%eax\)
+ 1a3: 89 90 90 90 90 90 [ ]*mov %edx,0x90909090\(%eax\)
+ 1a9: 8a 90 90 90 90 90 [ ]*mov 0x90909090\(%eax\),%dl
+ 1af: 8b 90 90 90 90 90 [ ]*mov 0x90909090\(%eax\),%edx
+ 1b5: 8c 90 90 90 90 90 [ ]*movl %ss,0x90909090\(%eax\)
+ 1bb: 8d 90 90 90 90 90 [ ]*lea 0x90909090\(%eax\),%edx
+ 1c1: 8e 90 90 90 90 90 [ ]*movl 0x90909090\(%eax\),%ss
+ 1c7: 8f 80 90 90 90 90 [ ]*popl 0x90909090\(%eax\)
+ 1cd: 90 [ ]*nop
+ 1ce: 91 [ ]*xchg %eax,%ecx
+ 1cf: 92 [ ]*xchg %eax,%edx
+ 1d0: 93 [ ]*xchg %eax,%ebx
+ 1d1: 94 [ ]*xchg %eax,%esp
+ 1d2: 95 [ ]*xchg %eax,%ebp
+ 1d3: 96 [ ]*xchg %eax,%esi
+ 1d4: 97 [ ]*xchg %eax,%edi
+ 1d5: 98 [ ]*cwtl
+ 1d6: 99 [ ]*cltd
+ 1d7: 9a 90 90 90 90 90 90 [ ]*lcall \$0x9090,\$0x90909090
+ 1de: 9b [ ]*fwait
+ 1df: 9c [ ]*pushf
+ 1e0: 9d [ ]*popf
+ 1e1: 9e [ ]*sahf
+ 1e2: 9f [ ]*lahf
+ 1e3: a0 90 90 90 90 [ ]*mov 0x90909090,%al
+ 1e8: a1 90 90 90 90 [ ]*mov 0x90909090,%eax
+ 1ed: a2 90 90 90 90 [ ]*mov %al,0x90909090
+ 1f2: a3 90 90 90 90 [ ]*mov %eax,0x90909090
+ 1f7: a4 [ ]*movsb %ds:\(%esi\),%es:\(%edi\)
+ 1f8: a5 [ ]*movsl %ds:\(%esi\),%es:\(%edi\)
+ 1f9: a6 [ ]*cmpsb %es:\(%edi\),%ds:\(%esi\)
+ 1fa: a7 [ ]*cmpsl %es:\(%edi\),%ds:\(%esi\)
+ 1fb: a8 90 [ ]*test \$0x90,%al
+ 1fd: a9 90 90 90 90 [ ]*test \$0x90909090,%eax
+ 202: aa [ ]*stos %al,%es:\(%edi\)
+ 203: ab [ ]*stos %eax,%es:\(%edi\)
+ 204: ac [ ]*lods %ds:\(%esi\),%al
+ 205: ad [ ]*lods %ds:\(%esi\),%eax
+ 206: ae [ ]*scas %es:\(%edi\),%al
+ 207: af [ ]*scas %es:\(%edi\),%eax
+ 208: b0 90 [ ]*mov \$0x90,%al
+ 20a: b1 90 [ ]*mov \$0x90,%cl
+ 20c: b2 90 [ ]*mov \$0x90,%dl
+ 20e: b3 90 [ ]*mov \$0x90,%bl
+ 210: b4 90 [ ]*mov \$0x90,%ah
+ 212: b5 90 [ ]*mov \$0x90,%ch
+ 214: b6 90 [ ]*mov \$0x90,%dh
+ 216: b7 90 [ ]*mov \$0x90,%bh
+ 218: b8 90 90 90 90 [ ]*mov \$0x90909090,%eax
+ 21d: b9 90 90 90 90 [ ]*mov \$0x90909090,%ecx
+ 222: ba 90 90 90 90 [ ]*mov \$0x90909090,%edx
+ 227: bb 90 90 90 90 [ ]*mov \$0x90909090,%ebx
+ 22c: bc 90 90 90 90 [ ]*mov \$0x90909090,%esp
+ 231: bd 90 90 90 90 [ ]*mov \$0x90909090,%ebp
+ 236: be 90 90 90 90 [ ]*mov \$0x90909090,%esi
+ 23b: bf 90 90 90 90 [ ]*mov \$0x90909090,%edi
+ 240: c0 90 90 90 90 90 90 [ ]*rclb \$0x90,0x90909090\(%eax\)
+ 247: c1 90 90 90 90 90 90 [ ]*rcll \$0x90,0x90909090\(%eax\)
+ 24e: c2 90 90 [ ]*ret \$0x9090
+ 251: c3 [ ]*ret
+ 252: c4 90 90 90 90 90 [ ]*les 0x90909090\(%eax\),%edx
+ 258: c5 90 90 90 90 90 [ ]*lds 0x90909090\(%eax\),%edx
+ 25e: c6 80 90 90 90 90 90 [ ]*movb \$0x90,0x90909090\(%eax\)
+ 265: c7 80 90 90 90 90 90 90 90 90 [ ]*movl \$0x90909090,0x90909090\(%eax\)
+ 26f: c8 90 90 90 [ ]*enter \$0x9090,\$0x90
+ 273: c9 [ ]*leave
+ 274: ca 90 90 [ ]*lret \$0x9090
+ 277: cb [ ]*lret
+ 278: cc [ ]*int3
+ 279: cd 90 [ ]*int \$0x90
+ 27b: ce [ ]*into
+ 27c: cf [ ]*iret
+ 27d: d0 90 90 90 90 90 [ ]*rclb 0x90909090\(%eax\)
+ 283: d1 90 90 90 90 90 [ ]*rcll 0x90909090\(%eax\)
+ 289: d2 90 90 90 90 90 [ ]*rclb %cl,0x90909090\(%eax\)
+ 28f: d3 90 90 90 90 90 [ ]*rcll %cl,0x90909090\(%eax\)
+ 295: d4 90 [ ]*aam \$0xffffff90
+ 297: d5 90 [ ]*aad \$0xffffff90
+ 299: d7 [ ]*xlat %ds:\(%ebx\)
+ 29a: d8 90 90 90 90 90 [ ]*fcoms 0x90909090\(%eax\)
+ 2a0: d9 90 90 90 90 90 [ ]*fsts 0x90909090\(%eax\)
+ 2a6: da 90 90 90 90 90 [ ]*ficoml 0x90909090\(%eax\)
+ 2ac: db 90 90 90 90 90 [ ]*fistl 0x90909090\(%eax\)
+ 2b2: dc 90 90 90 90 90 [ ]*fcoml 0x90909090\(%eax\)
+ 2b8: dd 90 90 90 90 90 [ ]*fstl 0x90909090\(%eax\)
+ 2be: de 90 90 90 90 90 [ ]*ficom 0x90909090\(%eax\)
+ 2c4: df 90 90 90 90 90 [ ]*fist 0x90909090\(%eax\)
+ 2ca: e0 90 [ ]*loopne (0x)?25c.*
+ 2cc: e1 90 [ ]*loope (0x)?25e.*
+ 2ce: e2 90 [ ]*loop (0x)?260.*
+ 2d0: e3 90 [ ]*jecxz (0x)?262.*
+ 2d2: e4 90 [ ]*in \$0x90,%al
+ 2d4: e5 90 [ ]*in \$0x90,%eax
+ 2d6: e6 90 [ ]*out %al,\$0x90
+ 2d8: e7 90 [ ]*out %eax,\$0x90
+ 2da: e8 90 90 90 90 [ ]*call (0x)?9090936f.*
+ 2df: e9 90 90 90 90 [ ]*jmp (0x)?90909374.*
+ 2e4: ea 90 90 90 90 90 90 [ ]*ljmp \$0x9090,\$0x90909090
+ 2eb: eb 90 [ ]*jmp (0x)?27d.*
+ 2ed: ec [ ]*in \(%dx\),%al
+ 2ee: ed [ ]*in \(%dx\),%eax
+ 2ef: ee [ ]*out %al,\(%dx\)
+ 2f0: ef [ ]*out %eax,\(%dx\)
+ 2f1: f4 [ ]*hlt
+ 2f2: f5 [ ]*cmc
+ 2f3: f6 90 90 90 90 90 [ ]*notb 0x90909090\(%eax\)
+ 2f9: f7 90 90 90 90 90 [ ]*notl 0x90909090\(%eax\)
+ 2ff: f8 [ ]*clc
+ 300: f9 [ ]*stc
+ 301: fa [ ]*cli
+ 302: fb [ ]*sti
+ 303: fc [ ]*cld
+ 304: fd [ ]*std
+ 305: ff 90 90 90 90 90 [ ]*call \*0x90909090\(%eax\)
+ 30b: 0f 00 90 90 90 90 90 [ ]*lldt 0x90909090\(%eax\)
+ 312: 0f 01 90 90 90 90 90 [ ]*lgdt 0x90909090\(%eax\)
+ 319: 0f 02 90 90 90 90 90 [ ]*lar 0x90909090\(%eax\),%edx
+ 320: 0f 03 90 90 90 90 90 [ ]*lsl 0x90909090\(%eax\),%edx
+ 327: 0f 06 [ ]*clts
+ 329: 0f 08 [ ]*invd
+ 32b: 0f 09 [ ]*wbinvd
+ 32d: 0f 0b [ ]*ud2a
+ 32f: 0f 20 d0 [ ]*mov %cr2,%eax
+ 332: 0f 21 d0 [ ]*mov %db2,%eax
+ 335: 0f 22 d0 [ ]*mov %eax,%cr2
+ 338: 0f 23 d0 [ ]*mov %eax,%db2
+ 33b: 0f 24 d0 [ ]*mov %tr2,%eax
+ 33e: 0f 26 d0 [ ]*mov %eax,%tr2
+ 341: 0f 30 [ ]*wrmsr
+ 343: 0f 31 [ ]*rdtsc
+ 345: 0f 32 [ ]*rdmsr
+ 347: 0f 33 [ ]*rdpmc
+ 349: 0f 40 90 90 90 90 90 [ ]*cmovo 0x90909090\(%eax\),%edx
+ 350: 0f 41 90 90 90 90 90 [ ]*cmovno 0x90909090\(%eax\),%edx
+ 357: 0f 42 90 90 90 90 90 [ ]*cmovb 0x90909090\(%eax\),%edx
+ 35e: 0f 43 90 90 90 90 90 [ ]*cmovae 0x90909090\(%eax\),%edx
+ 365: 0f 44 90 90 90 90 90 [ ]*cmove 0x90909090\(%eax\),%edx
+ 36c: 0f 45 90 90 90 90 90 [ ]*cmovne 0x90909090\(%eax\),%edx
+ 373: 0f 46 90 90 90 90 90 [ ]*cmovbe 0x90909090\(%eax\),%edx
+ 37a: 0f 47 90 90 90 90 90 [ ]*cmova 0x90909090\(%eax\),%edx
+ 381: 0f 48 90 90 90 90 90 [ ]*cmovs 0x90909090\(%eax\),%edx
+ 388: 0f 49 90 90 90 90 90 [ ]*cmovns 0x90909090\(%eax\),%edx
+ 38f: 0f 4a 90 90 90 90 90 [ ]*cmovp 0x90909090\(%eax\),%edx
+ 396: 0f 4b 90 90 90 90 90 [ ]*cmovnp 0x90909090\(%eax\),%edx
+ 39d: 0f 4c 90 90 90 90 90 [ ]*cmovl 0x90909090\(%eax\),%edx
+ 3a4: 0f 4d 90 90 90 90 90 [ ]*cmovge 0x90909090\(%eax\),%edx
+ 3ab: 0f 4e 90 90 90 90 90 [ ]*cmovle 0x90909090\(%eax\),%edx
+ 3b2: 0f 4f 90 90 90 90 90 [ ]*cmovg 0x90909090\(%eax\),%edx
+ 3b9: 0f 60 90 90 90 90 90 [ ]*punpcklbw 0x90909090\(%eax\),%mm2
+ 3c0: 0f 61 90 90 90 90 90 [ ]*punpcklwd 0x90909090\(%eax\),%mm2
+ 3c7: 0f 62 90 90 90 90 90 [ ]*punpckldq 0x90909090\(%eax\),%mm2
+ 3ce: 0f 63 90 90 90 90 90 [ ]*packsswb 0x90909090\(%eax\),%mm2
+ 3d5: 0f 64 90 90 90 90 90 [ ]*pcmpgtb 0x90909090\(%eax\),%mm2
+ 3dc: 0f 65 90 90 90 90 90 [ ]*pcmpgtw 0x90909090\(%eax\),%mm2
+ 3e3: 0f 66 90 90 90 90 90 [ ]*pcmpgtd 0x90909090\(%eax\),%mm2
+ 3ea: 0f 67 90 90 90 90 90 [ ]*packuswb 0x90909090\(%eax\),%mm2
+ 3f1: 0f 68 90 90 90 90 90 [ ]*punpckhbw 0x90909090\(%eax\),%mm2
+ 3f8: 0f 69 90 90 90 90 90 [ ]*punpckhwd 0x90909090\(%eax\),%mm2
+ 3ff: 0f 6a 90 90 90 90 90 [ ]*punpckhdq 0x90909090\(%eax\),%mm2
+ 406: 0f 6b 90 90 90 90 90 [ ]*packssdw 0x90909090\(%eax\),%mm2
+ 40d: 0f 6e 90 90 90 90 90 [ ]*movd 0x90909090\(%eax\),%mm2
+ 414: 0f 6f 90 90 90 90 90 [ ]*movq 0x90909090\(%eax\),%mm2
+ 41b: 0f 71 d0 90 [ ]*psrlw \$0x90,%mm0
+ 41f: 0f 72 d0 90 [ ]*psrld \$0x90,%mm0
+ 423: 0f 73 d0 90 [ ]*psrlq \$0x90,%mm0
+ 427: 0f 74 90 90 90 90 90 [ ]*pcmpeqb 0x90909090\(%eax\),%mm2
+ 42e: 0f 75 90 90 90 90 90 [ ]*pcmpeqw 0x90909090\(%eax\),%mm2
+ 435: 0f 76 90 90 90 90 90 [ ]*pcmpeqd 0x90909090\(%eax\),%mm2
+ 43c: 0f 77 [ ]*emms
+ 43e: 0f 7e 90 90 90 90 90 [ ]*movd %mm2,0x90909090\(%eax\)
+ 445: 0f 7f 90 90 90 90 90 [ ]*movq %mm2,0x90909090\(%eax\)
+ 44c: 0f 80 90 90 90 90 [ ]*jo (0x)?909094e2.*
+ 452: 0f 81 90 90 90 90 [ ]*jno (0x)?909094e8.*
+ 458: 0f 82 90 90 90 90 [ ]*jb (0x)?909094ee.*
+ 45e: 0f 83 90 90 90 90 [ ]*jae (0x)?909094f4.*
+ 464: 0f 84 90 90 90 90 [ ]*je (0x)?909094fa.*
+ 46a: 0f 85 90 90 90 90 [ ]*jne (0x)?90909500.*
+ 470: 0f 86 90 90 90 90 [ ]*jbe (0x)?90909506.*
+ 476: 0f 87 90 90 90 90 [ ]*ja (0x)?9090950c.*
+ 47c: 0f 88 90 90 90 90 [ ]*js (0x)?90909512.*
+ 482: 0f 89 90 90 90 90 [ ]*jns (0x)?90909518.*
+ 488: 0f 8a 90 90 90 90 [ ]*jp (0x)?9090951e.*
+ 48e: 0f 8b 90 90 90 90 [ ]*jnp (0x)?90909524.*
+ 494: 0f 8c 90 90 90 90 [ ]*jl (0x)?9090952a.*
+ 49a: 0f 8d 90 90 90 90 [ ]*jge (0x)?90909530.*
+ 4a0: 0f 8e 90 90 90 90 [ ]*jle (0x)?90909536.*
+ 4a6: 0f 8f 90 90 90 90 [ ]*jg (0x)?9090953c.*
+ 4ac: 0f 90 80 90 90 90 90 [ ]*seto 0x90909090\(%eax\)
+ 4b3: 0f 91 80 90 90 90 90 [ ]*setno 0x90909090\(%eax\)
+ 4ba: 0f 92 80 90 90 90 90 [ ]*setb 0x90909090\(%eax\)
+ 4c1: 0f 93 80 90 90 90 90 [ ]*setae 0x90909090\(%eax\)
+ 4c8: 0f 94 80 90 90 90 90 [ ]*sete 0x90909090\(%eax\)
+ 4cf: 0f 95 80 90 90 90 90 [ ]*setne 0x90909090\(%eax\)
+ 4d6: 0f 96 80 90 90 90 90 [ ]*setbe 0x90909090\(%eax\)
+ 4dd: 0f 97 80 90 90 90 90 [ ]*seta 0x90909090\(%eax\)
+ 4e4: 0f 98 80 90 90 90 90 [ ]*sets 0x90909090\(%eax\)
+ 4eb: 0f 99 80 90 90 90 90 [ ]*setns 0x90909090\(%eax\)
+ 4f2: 0f 9a 80 90 90 90 90 [ ]*setp 0x90909090\(%eax\)
+ 4f9: 0f 9b 80 90 90 90 90 [ ]*setnp 0x90909090\(%eax\)
+ 500: 0f 9c 80 90 90 90 90 [ ]*setl 0x90909090\(%eax\)
+ 507: 0f 9d 80 90 90 90 90 [ ]*setge 0x90909090\(%eax\)
+ 50e: 0f 9e 80 90 90 90 90 [ ]*setle 0x90909090\(%eax\)
+ 515: 0f 9f 80 90 90 90 90 [ ]*setg 0x90909090\(%eax\)
+ 51c: 0f a0 [ ]*push %fs
+ 51e: 0f a1 [ ]*pop %fs
+ 520: 0f a2 [ ]*cpuid
+ 522: 0f a3 90 90 90 90 90 [ ]*bt %edx,0x90909090\(%eax\)
+ 529: 0f a4 90 90 90 90 90 90 [ ]*shld \$0x90,%edx,0x90909090\(%eax\)
+ 531: 0f a5 90 90 90 90 90 [ ]*shld %cl,%edx,0x90909090\(%eax\)
+ 538: 0f a8 [ ]*push %gs
+ 53a: 0f a9 [ ]*pop %gs
+ 53c: 0f aa [ ]*rsm
+ 53e: 0f ab 90 90 90 90 90 [ ]*bts %edx,0x90909090\(%eax\)
+ 545: 0f ac 90 90 90 90 90 90 [ ]*shrd \$0x90,%edx,0x90909090\(%eax\)
+ 54d: 0f ad 90 90 90 90 90 [ ]*shrd %cl,%edx,0x90909090\(%eax\)
+ 554: 0f af 90 90 90 90 90 [ ]*imul 0x90909090\(%eax\),%edx
+ 55b: 0f b0 90 90 90 90 90 [ ]*cmpxchg %dl,0x90909090\(%eax\)
+ 562: 0f b1 90 90 90 90 90 [ ]*cmpxchg %edx,0x90909090\(%eax\)
+ 569: 0f b2 90 90 90 90 90 [ ]*lss 0x90909090\(%eax\),%edx
+ 570: 0f b3 90 90 90 90 90 [ ]*btr %edx,0x90909090\(%eax\)
+ 577: 0f b4 90 90 90 90 90 [ ]*lfs 0x90909090\(%eax\),%edx
+ 57e: 0f b5 90 90 90 90 90 [ ]*lgs 0x90909090\(%eax\),%edx
+ 585: 0f b6 90 90 90 90 90 [ ]*movzbl 0x90909090\(%eax\),%edx
+ 58c: 0f b7 90 90 90 90 90 [ ]*movzwl 0x90909090\(%eax\),%edx
+ 593: 0f b9 [ ]*ud2b
+ 595: 0f bb 90 90 90 90 90 [ ]*btc %edx,0x90909090\(%eax\)
+ 59c: 0f bc 90 90 90 90 90 [ ]*bsf 0x90909090\(%eax\),%edx
+ 5a3: 0f bd 90 90 90 90 90 [ ]*bsr 0x90909090\(%eax\),%edx
+ 5aa: 0f be 90 90 90 90 90 [ ]*movsbl 0x90909090\(%eax\),%edx
+ 5b1: 0f bf 90 90 90 90 90 [ ]*movswl 0x90909090\(%eax\),%edx
+ 5b8: 0f c0 90 90 90 90 90 [ ]*xadd %dl,0x90909090\(%eax\)
+ 5bf: 0f c1 90 90 90 90 90 [ ]*xadd %edx,0x90909090\(%eax\)
+ 5c6: 0f c8 [ ]*bswap %eax
+ 5c8: 0f c9 [ ]*bswap %ecx
+ 5ca: 0f ca [ ]*bswap %edx
+ 5cc: 0f cb [ ]*bswap %ebx
+ 5ce: 0f cc [ ]*bswap %esp
+ 5d0: 0f cd [ ]*bswap %ebp
+ 5d2: 0f ce [ ]*bswap %esi
+ 5d4: 0f cf [ ]*bswap %edi
+ 5d6: 0f d1 90 90 90 90 90 [ ]*psrlw 0x90909090\(%eax\),%mm2
+ 5dd: 0f d2 90 90 90 90 90 [ ]*psrld 0x90909090\(%eax\),%mm2
+ 5e4: 0f d3 90 90 90 90 90 [ ]*psrlq 0x90909090\(%eax\),%mm2
+ 5eb: 0f d5 90 90 90 90 90 [ ]*pmullw 0x90909090\(%eax\),%mm2
+ 5f2: 0f d8 90 90 90 90 90 [ ]*psubusb 0x90909090\(%eax\),%mm2
+ 5f9: 0f d9 90 90 90 90 90 [ ]*psubusw 0x90909090\(%eax\),%mm2
+ 600: 0f db 90 90 90 90 90 [ ]*pand 0x90909090\(%eax\),%mm2
+ 607: 0f dc 90 90 90 90 90 [ ]*paddusb 0x90909090\(%eax\),%mm2
+ 60e: 0f dd 90 90 90 90 90 [ ]*paddusw 0x90909090\(%eax\),%mm2
+ 615: 0f df 90 90 90 90 90 [ ]*pandn 0x90909090\(%eax\),%mm2
+ 61c: 0f e1 90 90 90 90 90 [ ]*psraw 0x90909090\(%eax\),%mm2
+ 623: 0f e2 90 90 90 90 90 [ ]*psrad 0x90909090\(%eax\),%mm2
+ 62a: 0f e5 90 90 90 90 90 [ ]*pmulhw 0x90909090\(%eax\),%mm2
+ 631: 0f e8 90 90 90 90 90 [ ]*psubsb 0x90909090\(%eax\),%mm2
+ 638: 0f e9 90 90 90 90 90 [ ]*psubsw 0x90909090\(%eax\),%mm2
+ 63f: 0f eb 90 90 90 90 90 [ ]*por 0x90909090\(%eax\),%mm2
+ 646: 0f ec 90 90 90 90 90 [ ]*paddsb 0x90909090\(%eax\),%mm2
+ 64d: 0f ed 90 90 90 90 90 [ ]*paddsw 0x90909090\(%eax\),%mm2
+ 654: 0f ef 90 90 90 90 90 [ ]*pxor 0x90909090\(%eax\),%mm2
+ 65b: 0f f1 90 90 90 90 90 [ ]*psllw 0x90909090\(%eax\),%mm2
+ 662: 0f f2 90 90 90 90 90 [ ]*pslld 0x90909090\(%eax\),%mm2
+ 669: 0f f3 90 90 90 90 90 [ ]*psllq 0x90909090\(%eax\),%mm2
+ 670: 0f f5 90 90 90 90 90 [ ]*pmaddwd 0x90909090\(%eax\),%mm2
+ 677: 0f f8 90 90 90 90 90 [ ]*psubb 0x90909090\(%eax\),%mm2
+ 67e: 0f f9 90 90 90 90 90 [ ]*psubw 0x90909090\(%eax\),%mm2
+ 685: 0f fa 90 90 90 90 90 [ ]*psubd 0x90909090\(%eax\),%mm2
+ 68c: 0f fc 90 90 90 90 90 [ ]*paddb 0x90909090\(%eax\),%mm2
+ 693: 0f fd 90 90 90 90 90 [ ]*paddw 0x90909090\(%eax\),%mm2
+ 69a: 0f fe 90 90 90 90 90 [ ]*paddd 0x90909090\(%eax\),%mm2
+ 6a1: 66 01 90 90 90 90 90 [ ]*add %dx,0x90909090\(%eax\)
+ 6a8: 66 03 90 90 90 90 90 [ ]*add 0x90909090\(%eax\),%dx
+ 6af: 66 05 90 90 [ ]*add \$0x9090,%ax
+ 6b3: 66 06 [ ]*pushw %es
+ 6b5: 66 07 [ ]*popw %es
+ 6b7: 66 09 90 90 90 90 90 [ ]*or %dx,0x90909090\(%eax\)
+ 6be: 66 0b 90 90 90 90 90 [ ]*or 0x90909090\(%eax\),%dx
+ 6c5: 66 0d 90 90 [ ]*or \$0x9090,%ax
+ 6c9: 66 0e [ ]*pushw %cs
+ 6cb: 66 11 90 90 90 90 90 [ ]*adc %dx,0x90909090\(%eax\)
+ 6d2: 66 13 90 90 90 90 90 [ ]*adc 0x90909090\(%eax\),%dx
+ 6d9: 66 15 90 90 [ ]*adc \$0x9090,%ax
+ 6dd: 66 16 [ ]*pushw %ss
+ 6df: 66 17 [ ]*popw %ss
+ 6e1: 66 19 90 90 90 90 90 [ ]*sbb %dx,0x90909090\(%eax\)
+ 6e8: 66 1b 90 90 90 90 90 [ ]*sbb 0x90909090\(%eax\),%dx
+ 6ef: 66 1d 90 90 [ ]*sbb \$0x9090,%ax
+ 6f3: 66 1e [ ]*pushw %ds
+ 6f5: 66 1f [ ]*popw %ds
+ 6f7: 66 21 90 90 90 90 90 [ ]*and %dx,0x90909090\(%eax\)
+ 6fe: 66 23 90 90 90 90 90 [ ]*and 0x90909090\(%eax\),%dx
+ 705: 66 25 90 90 [ ]*and \$0x9090,%ax
+ 709: 66 29 90 90 90 90 90 [ ]*sub %dx,0x90909090\(%eax\)
+ 710: 66 2b 90 90 90 90 90 [ ]*sub 0x90909090\(%eax\),%dx
+ 717: 66 2d 90 90 [ ]*sub \$0x9090,%ax
+ 71b: 66 31 90 90 90 90 90 [ ]*xor %dx,0x90909090\(%eax\)
+ 722: 66 33 90 90 90 90 90 [ ]*xor 0x90909090\(%eax\),%dx
+ 729: 66 35 90 90 [ ]*xor \$0x9090,%ax
+ 72d: 66 39 90 90 90 90 90 [ ]*cmp %dx,0x90909090\(%eax\)
+ 734: 66 3b 90 90 90 90 90 [ ]*cmp 0x90909090\(%eax\),%dx
+ 73b: 66 3d 90 90 [ ]*cmp \$0x9090,%ax
+ 73f: 66 40 [ ]*inc %ax
+ 741: 66 41 [ ]*inc %cx
+ 743: 66 42 [ ]*inc %dx
+ 745: 66 43 [ ]*inc %bx
+ 747: 66 44 [ ]*inc %sp
+ 749: 66 45 [ ]*inc %bp
+ 74b: 66 46 [ ]*inc %si
+ 74d: 66 47 [ ]*inc %di
+ 74f: 66 48 [ ]*dec %ax
+ 751: 66 49 [ ]*dec %cx
+ 753: 66 4a [ ]*dec %dx
+ 755: 66 4b [ ]*dec %bx
+ 757: 66 4c [ ]*dec %sp
+ 759: 66 4d [ ]*dec %bp
+ 75b: 66 4e [ ]*dec %si
+ 75d: 66 4f [ ]*dec %di
+ 75f: 66 50 [ ]*push %ax
+ 761: 66 51 [ ]*push %cx
+ 763: 66 52 [ ]*push %dx
+ 765: 66 53 [ ]*push %bx
+ 767: 66 54 [ ]*push %sp
+ 769: 66 55 [ ]*push %bp
+ 76b: 66 56 [ ]*push %si
+ 76d: 66 57 [ ]*push %di
+ 76f: 66 58 [ ]*pop %ax
+ 771: 66 59 [ ]*pop %cx
+ 773: 66 5a [ ]*pop %dx
+ 775: 66 5b [ ]*pop %bx
+ 777: 66 5c [ ]*pop %sp
+ 779: 66 5d [ ]*pop %bp
+ 77b: 66 5e [ ]*pop %si
+ 77d: 66 5f [ ]*pop %di
+ 77f: 66 60 [ ]*pushaw
+ 781: 66 61 [ ]*popaw
+ 783: 66 62 90 90 90 90 90 [ ]*bound %dx,0x90909090\(%eax\)
+ 78a: 66 68 90 90 [ ]*pushw \$0x9090
+ 78e: 66 69 90 90 90 90 90 90 90 [ ]*imul \$0x9090,0x90909090\(%eax\),%dx
+ 797: 66 6a 90 [ ]*pushw \$0xffffff90
+ 79a: 66 6b 90 90 90 90 90 90 [ ]*imul \$0xffffff90,0x90909090\(%eax\),%dx
+ 7a2: 66 6d [ ]*insw \(%dx\),%es:\(%edi\)
+ 7a4: 66 6f [ ]*outsw %ds:\(%esi\),\(%dx\)
+ 7a6: 66 81 90 90 90 90 90 90 90 [ ]*adcw \$0x9090,0x90909090\(%eax\)
+ 7af: 66 83 90 90 90 90 90 90 [ ]*adcw \$0xffffff90,0x90909090\(%eax\)
+ 7b7: 66 85 90 90 90 90 90 [ ]*test %dx,0x90909090\(%eax\)
+ 7be: 66 87 90 90 90 90 90 [ ]*xchg %dx,0x90909090\(%eax\)
+ 7c5: 66 89 90 90 90 90 90 [ ]*mov %dx,0x90909090\(%eax\)
+ 7cc: 66 8b 90 90 90 90 90 [ ]*mov 0x90909090\(%eax\),%dx
+ 7d3: 66 8c 90 90 90 90 90 [ ]*movw %ss,0x90909090\(%eax\)
+ 7da: 66 8d 90 90 90 90 90 [ ]*lea 0x90909090\(%eax\),%dx
+ 7e1: 66 8f 80 90 90 90 90 [ ]*popw 0x90909090\(%eax\)
+ 7e8: 66 91 [ ]*xchg %ax,%cx
+ 7ea: 66 92 [ ]*xchg %ax,%dx
+ 7ec: 66 93 [ ]*xchg %ax,%bx
+ 7ee: 66 94 [ ]*xchg %ax,%sp
+ 7f0: 66 95 [ ]*xchg %ax,%bp
+ 7f2: 66 96 [ ]*xchg %ax,%si
+ 7f4: 66 97 [ ]*xchg %ax,%di
+ 7f6: 66 98 [ ]*cbtw
+ 7f8: 66 99 [ ]*cwtd
+ 7fa: 66 9a 90 90 90 90 [ ]*lcallw \$0x9090,\$0x9090
+ 800: 66 9c [ ]*pushfw
+ 802: 66 9d [ ]*popfw
+ 804: 66 a1 90 90 90 90 [ ]*mov 0x90909090,%ax
+ 80a: 66 a3 90 90 90 90 [ ]*mov %ax,0x90909090
+ 810: 66 a5 [ ]*movsw %ds:\(%esi\),%es:\(%edi\)
+ 812: 66 a7 [ ]*cmpsw %es:\(%edi\),%ds:\(%esi\)
+ 814: 66 a9 90 90 [ ]*test \$0x9090,%ax
+ 818: 66 ab [ ]*stos %ax,%es:\(%edi\)
+ 81a: 66 ad [ ]*lods %ds:\(%esi\),%ax
+ 81c: 66 af [ ]*scas %es:\(%edi\),%ax
+ 81e: 66 b8 90 90 [ ]*mov \$0x9090,%ax
+ 822: 66 b9 90 90 [ ]*mov \$0x9090,%cx
+ 826: 66 ba 90 90 [ ]*mov \$0x9090,%dx
+ 82a: 66 bb 90 90 [ ]*mov \$0x9090,%bx
+ 82e: 66 bc 90 90 [ ]*mov \$0x9090,%sp
+ 832: 66 bd 90 90 [ ]*mov \$0x9090,%bp
+ 836: 66 be 90 90 [ ]*mov \$0x9090,%si
+ 83a: 66 bf 90 90 [ ]*mov \$0x9090,%di
+ 83e: 66 c1 90 90 90 90 90 90 [ ]*rclw \$0x90,0x90909090\(%eax\)
+ 846: 66 c2 90 90 [ ]*retw \$0x9090
+ 84a: 66 c3 [ ]*retw
+ 84c: 66 c4 90 90 90 90 90 [ ]*les 0x90909090\(%eax\),%dx
+ 853: 66 c5 90 90 90 90 90 [ ]*lds 0x90909090\(%eax\),%dx
+ 85a: 66 c7 80 90 90 90 90 90 90 [ ]*movw \$0x9090,0x90909090\(%eax\)
+ 863: 66 c8 90 90 90 [ ]*enterw \$0x9090,\$0x90
+ 868: 66 c9 [ ]*leavew
+ 86a: 66 ca 90 90 [ ]*lretw \$0x9090
+ 86e: 66 cb [ ]*lretw
+ 870: 66 cf [ ]*iretw
+ 872: 66 d1 90 90 90 90 90 [ ]*rclw 0x90909090\(%eax\)
+ 879: 66 d3 90 90 90 90 90 [ ]*rclw %cl,0x90909090\(%eax\)
+ 880: 66 e5 90 [ ]*in \$0x90,%ax
+ 883: 66 e7 90 [ ]*out %ax,\$0x90
+ 886: 66 e8 8f 90 [ ]*callw (0x)?ffff9919.*
+ 88a: 66 ea 90 90 90 90 [ ]*ljmpw \$0x9090,\$0x9090
+ 890: 66 ed [ ]*in \(%dx\),%ax
+ 892: 66 ef [ ]*out %ax,\(%dx\)
+ 894: 66 f7 90 90 90 90 90 [ ]*notw 0x90909090\(%eax\)
+ 89b: 66 ff 90 90 90 90 90 [ ]*callw \*0x90909090\(%eax\)
+ 8a2: 66 0f 02 90 90 90 90 90 [ ]*lar 0x90909090\(%eax\),%dx
+ 8aa: 66 0f 03 90 90 90 90 90 [ ]*lsl 0x90909090\(%eax\),%dx
+ 8b2: 66 0f 40 90 90 90 90 90 [ ]*cmovo 0x90909090\(%eax\),%dx
+ 8ba: 66 0f 41 90 90 90 90 90 [ ]*cmovno 0x90909090\(%eax\),%dx
+ 8c2: 66 0f 42 90 90 90 90 90 [ ]*cmovb 0x90909090\(%eax\),%dx
+ 8ca: 66 0f 43 90 90 90 90 90 [ ]*cmovae 0x90909090\(%eax\),%dx
+ 8d2: 66 0f 44 90 90 90 90 90 [ ]*cmove 0x90909090\(%eax\),%dx
+ 8da: 66 0f 45 90 90 90 90 90 [ ]*cmovne 0x90909090\(%eax\),%dx
+ 8e2: 66 0f 46 90 90 90 90 90 [ ]*cmovbe 0x90909090\(%eax\),%dx
+ 8ea: 66 0f 47 90 90 90 90 90 [ ]*cmova 0x90909090\(%eax\),%dx
+ 8f2: 66 0f 48 90 90 90 90 90 [ ]*cmovs 0x90909090\(%eax\),%dx
+ 8fa: 66 0f 49 90 90 90 90 90 [ ]*cmovns 0x90909090\(%eax\),%dx
+ 902: 66 0f 4a 90 90 90 90 90 [ ]*cmovp 0x90909090\(%eax\),%dx
+ 90a: 66 0f 4b 90 90 90 90 90 [ ]*cmovnp 0x90909090\(%eax\),%dx
+ 912: 66 0f 4c 90 90 90 90 90 [ ]*cmovl 0x90909090\(%eax\),%dx
+ 91a: 66 0f 4d 90 90 90 90 90 [ ]*cmovge 0x90909090\(%eax\),%dx
+ 922: 66 0f 4e 90 90 90 90 90 [ ]*cmovle 0x90909090\(%eax\),%dx
+ 92a: 66 0f 4f 90 90 90 90 90 [ ]*cmovg 0x90909090\(%eax\),%dx
+ 932: 66 0f a0 [ ]*pushw %fs
+ 935: 66 0f a1 [ ]*popw %fs
+ 938: 66 0f a3 90 90 90 90 90 [ ]*bt %dx,0x90909090\(%eax\)
+ 940: 66 0f a4 90 90 90 90 90 90 [ ]*shld \$0x90,%dx,0x90909090\(%eax\)
+ 949: 66 0f a5 90 90 90 90 90 [ ]*shld %cl,%dx,0x90909090\(%eax\)
+ 951: 66 0f a8 [ ]*pushw %gs
+ 954: 66 0f a9 [ ]*popw %gs
+ 957: 66 0f ab 90 90 90 90 90 [ ]*bts %dx,0x90909090\(%eax\)
+ 95f: 66 0f ac 90 90 90 90 90 90 [ ]*shrd \$0x90,%dx,0x90909090\(%eax\)
+ 968: 66 0f ad 90 90 90 90 90 [ ]*shrd %cl,%dx,0x90909090\(%eax\)
+ 970: 66 0f af 90 90 90 90 90 [ ]*imul 0x90909090\(%eax\),%dx
+ 978: 66 0f b1 90 90 90 90 90 [ ]*cmpxchg %dx,0x90909090\(%eax\)
+ 980: 66 0f b2 90 90 90 90 90 [ ]*lss 0x90909090\(%eax\),%dx
+ 988: 66 0f b3 90 90 90 90 90 [ ]*btr %dx,0x90909090\(%eax\)
+ 990: 66 0f b4 90 90 90 90 90 [ ]*lfs 0x90909090\(%eax\),%dx
+ 998: 66 0f b5 90 90 90 90 90 [ ]*lgs 0x90909090\(%eax\),%dx
+ 9a0: 66 0f b6 90 90 90 90 90 [ ]*movzbw 0x90909090\(%eax\),%dx
+ 9a8: 66 0f bb 90 90 90 90 90 [ ]*btc %dx,0x90909090\(%eax\)
+ 9b0: 66 0f bc 90 90 90 90 90 [ ]*bsf 0x90909090\(%eax\),%dx
+ 9b8: 66 0f bd 90 90 90 90 90 [ ]*bsr 0x90909090\(%eax\),%dx
+ 9c0: 66 0f be 90 90 90 90 90 [ ]*movsbw 0x90909090\(%eax\),%dx
+ 9c8: 66 0f c1 90 90 90 90 90 [ ]*xadd %dx,0x90909090\(%eax\)
diff --git a/gas/testsuite/gas/i386/opcode.s b/gas/testsuite/gas/i386/opcode.s
new file mode 100644
index 0000000000..39c5967b26
--- /dev/null
+++ b/gas/testsuite/gas/i386/opcode.s
@@ -0,0 +1,567 @@
+.text
+foo:
+ add %dl,0x90909090(%eax)
+ add %edx,0x90909090(%eax)
+ add 0x90909090(%eax),%dl
+ add 0x90909090(%eax),%edx
+ add $0x90,%al
+ add $0x90909090,%eax
+ push %es
+ pop %es
+ or %dl,0x90909090(%eax)
+ or %edx,0x90909090(%eax)
+ or 0x90909090(%eax),%dl
+ or 0x90909090(%eax),%edx
+ or $0x90,%al
+ or $0x90909090,%eax
+ push %cs
+ adc %dl,0x90909090(%eax)
+ adc %edx,0x90909090(%eax)
+ adc 0x90909090(%eax),%dl
+ adc 0x90909090(%eax),%edx
+ adc $0x90,%al
+ adc $0x90909090,%eax
+ push %ss
+ pop %ss
+ sbb %dl,0x90909090(%eax)
+ sbb %edx,0x90909090(%eax)
+ sbb 0x90909090(%eax),%dl
+ sbb 0x90909090(%eax),%edx
+ sbb $0x90,%al
+ sbb $0x90909090,%eax
+ push %ds
+ pop %ds
+ and %dl,0x90909090(%eax)
+ and %edx,0x90909090(%eax)
+ and 0x90909090(%eax),%dl
+ and 0x90909090(%eax),%edx
+ and $0x90,%al
+ and $0x90909090,%eax
+ daa
+ sub %dl,0x90909090(%eax)
+ sub %edx,0x90909090(%eax)
+ sub 0x90909090(%eax),%dl
+ sub 0x90909090(%eax),%edx
+ sub $0x90,%al
+ sub $0x90909090,%eax
+ das
+ xor %dl,0x90909090(%eax)
+ xor %edx,0x90909090(%eax)
+ xor 0x90909090(%eax),%dl
+ xor 0x90909090(%eax),%edx
+ xor $0x90,%al
+ xor $0x90909090,%eax
+ aaa
+ cmp %dl,0x90909090(%eax)
+ cmp %edx,0x90909090(%eax)
+ cmp 0x90909090(%eax),%dl
+ cmp 0x90909090(%eax),%edx
+ cmp $0x90,%al
+ cmp $0x90909090,%eax
+ aas
+ inc %eax
+ inc %ecx
+ inc %edx
+ inc %ebx
+ inc %esp
+ inc %ebp
+ inc %esi
+ inc %edi
+ dec %eax
+ dec %ecx
+ dec %edx
+ dec %ebx
+ dec %esp
+ dec %ebp
+ dec %esi
+ dec %edi
+ push %eax
+ push %ecx
+ push %edx
+ push %ebx
+ push %esp
+ push %ebp
+ push %esi
+ push %edi
+ pop %eax
+ pop %ecx
+ pop %edx
+ pop %ebx
+ pop %esp
+ pop %ebp
+ pop %esi
+ pop %edi
+ pusha
+ popa
+ bound %edx,0x90909090(%eax)
+ arpl %dx,0x90909090(%eax)
+ push $0x90909090
+ imul $0x90909090,0x90909090(%eax),%edx
+ push $0xffffff90
+ imul $0xffffff90,0x90909090(%eax),%edx
+ insb (%dx),%es:(%edi)
+ insl (%dx),%es:(%edi)
+ outsb %ds:(%esi),(%dx)
+ outsl %ds:(%esi),(%dx)
+ jo .+2-0x70
+ jno .+2-0x70
+ jb .+2-0x70
+ jae .+2-0x70
+ je .+2-0x70
+ jne .+2-0x70
+ jbe .+2-0x70
+ ja .+2-0x70
+ js .+2-0x70
+ jns .+2-0x70
+ jp .+2-0x70
+ jnp .+2-0x70
+ jl .+2-0x70
+ jge .+2-0x70
+ jle .+2-0x70
+ jg .+2-0x70
+ adcb $0x90,0x90909090(%eax)
+ adcl $0x90909090,0x90909090(%eax)
+ adcl $0xffffff90,0x90909090(%eax)
+ test %dl,0x90909090(%eax)
+ test %edx,0x90909090(%eax)
+ xchg %dl,0x90909090(%eax)
+ xchg %edx,0x90909090(%eax)
+ mov %dl,0x90909090(%eax)
+ mov %edx,0x90909090(%eax)
+ mov 0x90909090(%eax),%dl
+ mov 0x90909090(%eax),%edx
+ movl %ss,0x90909090(%eax)
+ lea 0x90909090(%eax),%edx
+ movl 0x90909090(%eax),%ss
+ popl 0x90909090(%eax)
+ xchg %eax,%eax
+ xchg %eax,%ecx
+ xchg %eax,%edx
+ xchg %eax,%ebx
+ xchg %eax,%esp
+ xchg %eax,%ebp
+ xchg %eax,%esi
+ xchg %eax,%edi
+ cwtl
+ cltd
+ lcall $0x9090,$0x90909090
+ fwait
+ pushf
+ popf
+ sahf
+ lahf
+ mov 0x90909090,%al
+ mov 0x90909090,%eax
+ mov %al,0x90909090
+ mov %eax,0x90909090
+ movsb %ds:(%esi),%es:(%edi)
+ movsl %ds:(%esi),%es:(%edi)
+ cmpsb %es:(%edi),%ds:(%esi)
+ cmpsl %es:(%edi),%ds:(%esi)
+ test $0x90,%al
+ test $0x90909090,%eax
+ stos %al,%es:(%edi)
+ stos %eax,%es:(%edi)
+ lods %ds:(%esi),%al
+ lods %ds:(%esi),%eax
+ scas %es:(%edi),%al
+ scas %es:(%edi),%eax
+ mov $0x90,%al
+ mov $0x90,%cl
+ mov $0x90,%dl
+ mov $0x90,%bl
+ mov $0x90,%ah
+ mov $0x90,%ch
+ mov $0x90,%dh
+ mov $0x90,%bh
+ mov $0x90909090,%eax
+ mov $0x90909090,%ecx
+ mov $0x90909090,%edx
+ mov $0x90909090,%ebx
+ mov $0x90909090,%esp
+ mov $0x90909090,%ebp
+ mov $0x90909090,%esi
+ mov $0x90909090,%edi
+ rclb $0x90,0x90909090(%eax)
+ rcll $0x90,0x90909090(%eax)
+ ret $0x9090
+ ret
+ les 0x90909090(%eax),%edx
+ lds 0x90909090(%eax),%edx
+ movb $0x90,0x90909090(%eax)
+ movl $0x90909090,0x90909090(%eax)
+ enter $0x9090,$0x90
+ leave
+ lret $0x9090
+ lret
+ int3
+ int $0x90
+ into
+ iret
+ rclb 0x90909090(%eax)
+ rcll 0x90909090(%eax)
+ rclb %cl,0x90909090(%eax)
+ rcll %cl,0x90909090(%eax)
+ aam $0xffffff90
+ aad $0xffffff90
+ xlat %ds:(%ebx)
+ fcoms 0x90909090(%eax)
+ fsts 0x90909090(%eax)
+ ficoml 0x90909090(%eax)
+ fistl 0x90909090(%eax)
+ fcoml 0x90909090(%eax)
+ fstl 0x90909090(%eax)
+ ficom 0x90909090(%eax)
+ fist 0x90909090(%eax)
+ loopne .+2-0x70
+ loope .+2-0x70
+ loop .+2-0x70
+ jecxz .+2-0x70
+ in $0x90,%al
+ in $0x90,%eax
+ out %al,$0x90
+ out %eax,$0x90
+ call .+5+0x90909090
+ jmp .+5+0x90909090
+ ljmp $0x9090,$0x90909090
+ jmp .+2-0x70
+ in (%dx),%al
+ in (%dx),%eax
+ out %al,(%dx)
+ out %eax,(%dx)
+ hlt
+ cmc
+ notb 0x90909090(%eax)
+ notl 0x90909090(%eax)
+ clc
+ stc
+ cli
+ sti
+ cld
+ std
+ call *0x90909090(%eax)
+ lldt 0x90909090(%eax)
+ lgdt 0x90909090(%eax)
+ lar 0x90909090(%eax),%edx
+ lsl 0x90909090(%eax),%edx
+ clts
+ invd
+ wbinvd
+ ud2a
+ mov %cr2,%eax
+ mov %db2,%eax
+ mov %eax,%cr2
+ mov %eax,%db2
+ mov %tr2,%eax
+ mov %eax,%tr2
+ wrmsr
+ rdtsc
+ rdmsr
+ rdpmc
+ cmovo 0x90909090(%eax),%edx
+ cmovno 0x90909090(%eax),%edx
+ cmovb 0x90909090(%eax),%edx
+ cmovae 0x90909090(%eax),%edx
+ cmove 0x90909090(%eax),%edx
+ cmovne 0x90909090(%eax),%edx
+ cmovbe 0x90909090(%eax),%edx
+ cmova 0x90909090(%eax),%edx
+ cmovs 0x90909090(%eax),%edx
+ cmovns 0x90909090(%eax),%edx
+ cmovp 0x90909090(%eax),%edx
+ cmovnp 0x90909090(%eax),%edx
+ cmovl 0x90909090(%eax),%edx
+ cmovge 0x90909090(%eax),%edx
+ cmovle 0x90909090(%eax),%edx
+ cmovg 0x90909090(%eax),%edx
+ punpcklbw 0x90909090(%eax),%mm2
+ punpcklwd 0x90909090(%eax),%mm2
+ punpckldq 0x90909090(%eax),%mm2
+ packsswb 0x90909090(%eax),%mm2
+ pcmpgtb 0x90909090(%eax),%mm2
+ pcmpgtw 0x90909090(%eax),%mm2
+ pcmpgtd 0x90909090(%eax),%mm2
+ packuswb 0x90909090(%eax),%mm2
+ punpckhbw 0x90909090(%eax),%mm2
+ punpckhwd 0x90909090(%eax),%mm2
+ punpckhdq 0x90909090(%eax),%mm2
+ packssdw 0x90909090(%eax),%mm2
+ movd 0x90909090(%eax),%mm2
+ movq 0x90909090(%eax),%mm2
+ psrlw $0x90,%mm0
+ psrld $0x90,%mm0
+ psrlq $0x90,%mm0
+ pcmpeqb 0x90909090(%eax),%mm2
+ pcmpeqw 0x90909090(%eax),%mm2
+ pcmpeqd 0x90909090(%eax),%mm2
+ emms
+ movd %mm2,0x90909090(%eax)
+ movq %mm2,0x90909090(%eax)
+ jo .+6+0x90909090
+ jno .+6+0x90909090
+ jb .+6+0x90909090
+ jae .+6+0x90909090
+ je .+6+0x90909090
+ jne .+6+0x90909090
+ jbe .+6+0x90909090
+ ja .+6+0x90909090
+ js .+6+0x90909090
+ jns .+6+0x90909090
+ jp .+6+0x90909090
+ jnp .+6+0x90909090
+ jl .+6+0x90909090
+ jge .+6+0x90909090
+ jle .+6+0x90909090
+ jg .+6+0x90909090
+ seto 0x90909090(%eax)
+ setno 0x90909090(%eax)
+ setb 0x90909090(%eax)
+ setae 0x90909090(%eax)
+ sete 0x90909090(%eax)
+ setne 0x90909090(%eax)
+ setbe 0x90909090(%eax)
+ seta 0x90909090(%eax)
+ sets 0x90909090(%eax)
+ setns 0x90909090(%eax)
+ setp 0x90909090(%eax)
+ setnp 0x90909090(%eax)
+ setl 0x90909090(%eax)
+ setge 0x90909090(%eax)
+ setle 0x90909090(%eax)
+ setg 0x90909090(%eax)
+ push %fs
+ pop %fs
+ cpuid
+ bt %edx,0x90909090(%eax)
+ shld $0x90,%edx,0x90909090(%eax)
+ shld %cl,%edx,0x90909090(%eax)
+ push %gs
+ pop %gs
+ rsm
+ bts %edx,0x90909090(%eax)
+ shrd $0x90,%edx,0x90909090(%eax)
+ shrd %cl,%edx,0x90909090(%eax)
+ imul 0x90909090(%eax),%edx
+ cmpxchg %dl,0x90909090(%eax)
+ cmpxchg %edx,0x90909090(%eax)
+ lss 0x90909090(%eax),%edx
+ btr %edx,0x90909090(%eax)
+ lfs 0x90909090(%eax),%edx
+ lgs 0x90909090(%eax),%edx
+ movzbl 0x90909090(%eax),%edx
+ movzwl 0x90909090(%eax),%edx
+ ud2b
+ btc %edx,0x90909090(%eax)
+ bsf 0x90909090(%eax),%edx
+ bsr 0x90909090(%eax),%edx
+ movsbl 0x90909090(%eax),%edx
+ movswl 0x90909090(%eax),%edx
+ xadd %dl,0x90909090(%eax)
+ xadd %edx,0x90909090(%eax)
+ bswap %eax
+ bswap %ecx
+ bswap %edx
+ bswap %ebx
+ bswap %esp
+ bswap %ebp
+ bswap %esi
+ bswap %edi
+ psrlw 0x90909090(%eax),%mm2
+ psrld 0x90909090(%eax),%mm2
+ psrlq 0x90909090(%eax),%mm2
+ pmullw 0x90909090(%eax),%mm2
+ psubusb 0x90909090(%eax),%mm2
+ psubusw 0x90909090(%eax),%mm2
+ pand 0x90909090(%eax),%mm2
+ paddusb 0x90909090(%eax),%mm2
+ paddusw 0x90909090(%eax),%mm2
+ pandn 0x90909090(%eax),%mm2
+ psraw 0x90909090(%eax),%mm2
+ psrad 0x90909090(%eax),%mm2
+ pmulhw 0x90909090(%eax),%mm2
+ psubsb 0x90909090(%eax),%mm2
+ psubsw 0x90909090(%eax),%mm2
+ por 0x90909090(%eax),%mm2
+ paddsb 0x90909090(%eax),%mm2
+ paddsw 0x90909090(%eax),%mm2
+ pxor 0x90909090(%eax),%mm2
+ psllw 0x90909090(%eax),%mm2
+ pslld 0x90909090(%eax),%mm2
+ psllq 0x90909090(%eax),%mm2
+ pmaddwd 0x90909090(%eax),%mm2
+ psubb 0x90909090(%eax),%mm2
+ psubw 0x90909090(%eax),%mm2
+ psubd 0x90909090(%eax),%mm2
+ paddb 0x90909090(%eax),%mm2
+ paddw 0x90909090(%eax),%mm2
+ paddd 0x90909090(%eax),%mm2
+ add %dx,0x90909090(%eax)
+ add 0x90909090(%eax),%dx
+ add $0x9090,%ax
+ pushw %es
+ popw %es
+ or %dx,0x90909090(%eax)
+ or 0x90909090(%eax),%dx
+ or $0x9090,%ax
+ pushw %cs
+ adc %dx,0x90909090(%eax)
+ adc 0x90909090(%eax),%dx
+ adc $0x9090,%ax
+ pushw %ss
+ popw %ss
+ sbb %dx,0x90909090(%eax)
+ sbb 0x90909090(%eax),%dx
+ sbb $0x9090,%ax
+ pushw %ds
+ popw %ds
+ and %dx,0x90909090(%eax)
+ and 0x90909090(%eax),%dx
+ and $0x9090,%ax
+ sub %dx,0x90909090(%eax)
+ sub 0x90909090(%eax),%dx
+ sub $0x9090,%ax
+ xor %dx,0x90909090(%eax)
+ xor 0x90909090(%eax),%dx
+ xor $0x9090,%ax
+ cmp %dx,0x90909090(%eax)
+ cmp 0x90909090(%eax),%dx
+ cmp $0x9090,%ax
+ inc %ax
+ inc %cx
+ inc %dx
+ inc %bx
+ inc %sp
+ inc %bp
+ inc %si
+ inc %di
+ dec %ax
+ dec %cx
+ dec %dx
+ dec %bx
+ dec %sp
+ dec %bp
+ dec %si
+ dec %di
+ push %ax
+ push %cx
+ push %dx
+ push %bx
+ push %sp
+ push %bp
+ push %si
+ push %di
+ pop %ax
+ pop %cx
+ pop %dx
+ pop %bx
+ pop %sp
+ pop %bp
+ pop %si
+ pop %di
+ pushaw
+ popaw
+ bound %dx,0x90909090(%eax)
+ pushw $0x9090
+ imul $0x9090,0x90909090(%eax),%dx
+ pushw $0xffffff90
+ imul $0xffffff90,0x90909090(%eax),%dx
+ insw (%dx),%es:(%edi)
+ outsw %ds:(%esi),(%dx)
+ adcw $0x9090,0x90909090(%eax)
+ adcw $0xffffff90,0x90909090(%eax)
+ test %dx,0x90909090(%eax)
+ xchg %dx,0x90909090(%eax)
+ mov %dx,0x90909090(%eax)
+ mov 0x90909090(%eax),%dx
+ movw %ss,0x90909090(%eax)
+ lea 0x90909090(%eax),%dx
+ popw 0x90909090(%eax)
+ xchg %ax,%cx
+ xchg %ax,%dx
+ xchg %ax,%bx
+ xchg %ax,%sp
+ xchg %ax,%bp
+ xchg %ax,%si
+ xchg %ax,%di
+ cbtw
+ cwtd
+ lcallw $0x9090,$0x9090
+ pushfw
+ popfw
+ mov 0x90909090,%ax
+ mov %ax,0x90909090
+ movsw %ds:(%esi),%es:(%edi)
+ cmpsw %es:(%edi),%ds:(%esi)
+ test $0x9090,%ax
+ stos %ax,%es:(%edi)
+ lods %ds:(%esi),%ax
+ scas %es:(%edi),%ax
+ mov $0x9090,%ax
+ mov $0x9090,%cx
+ mov $0x9090,%dx
+ mov $0x9090,%bx
+ mov $0x9090,%sp
+ mov $0x9090,%bp
+ mov $0x9090,%si
+ mov $0x9090,%di
+ rclw $0x90,0x90909090(%eax)
+ retw $0x9090
+ retw
+ les 0x90909090(%eax),%dx
+ lds 0x90909090(%eax),%dx
+ movw $0x9090,0x90909090(%eax)
+ enterw $0x9090,$0x90
+ leavew
+ lretw $0x9090
+ lretw
+ iretw
+ rclw 0x90909090(%eax)
+ rclw %cl,0x90909090(%eax)
+ in $0x90,%ax
+ out %ax,$0x90
+ callw .+3+0x9090
+ ljmpw $0x9090,$0x9090
+ in (%dx),%ax
+ out %ax,(%dx)
+ notw 0x90909090(%eax)
+ callw *0x90909090(%eax)
+ lar 0x90909090(%eax),%dx
+ lsl 0x90909090(%eax),%dx
+ cmovo 0x90909090(%eax),%dx
+ cmovno 0x90909090(%eax),%dx
+ cmovb 0x90909090(%eax),%dx
+ cmovae 0x90909090(%eax),%dx
+ cmove 0x90909090(%eax),%dx
+ cmovne 0x90909090(%eax),%dx
+ cmovbe 0x90909090(%eax),%dx
+ cmova 0x90909090(%eax),%dx
+ cmovs 0x90909090(%eax),%dx
+ cmovns 0x90909090(%eax),%dx
+ cmovp 0x90909090(%eax),%dx
+ cmovnp 0x90909090(%eax),%dx
+ cmovl 0x90909090(%eax),%dx
+ cmovge 0x90909090(%eax),%dx
+ cmovle 0x90909090(%eax),%dx
+ cmovg 0x90909090(%eax),%dx
+ pushw %fs
+ popw %fs
+ bt %dx,0x90909090(%eax)
+ shld $0x90,%dx,0x90909090(%eax)
+ shld %cl,%dx,0x90909090(%eax)
+ pushw %gs
+ popw %gs
+ bts %dx,0x90909090(%eax)
+ shrd $0x90,%dx,0x90909090(%eax)
+ shrd %cl,%dx,0x90909090(%eax)
+ imul 0x90909090(%eax),%dx
+ cmpxchg %dx,0x90909090(%eax)
+ lss 0x90909090(%eax),%dx
+ btr %dx,0x90909090(%eax)
+ lfs 0x90909090(%eax),%dx
+ lgs 0x90909090(%eax),%dx
+ movzbw 0x90909090(%eax),%dx
+ btc %dx,0x90909090(%eax)
+ bsf 0x90909090(%eax),%dx
+ bsr 0x90909090(%eax),%dx
+ movsbw 0x90909090(%eax),%dx
+ xadd %dx,0x90909090(%eax)
diff --git a/gas/testsuite/gas/i386/prefix.d b/gas/testsuite/gas/i386/prefix.d
new file mode 100644
index 0000000000..054b658a3c
--- /dev/null
+++ b/gas/testsuite/gas/i386/prefix.d
@@ -0,0 +1,15 @@
+#objdump: -dw
+#name: i386 prefix
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+000 <foo>:
+ 0: 9b 67 26 d9 3c [ ]*addr16 fstcw %es:\(%si\)
+ 5: 9b df e0 [ ]*fstsw %ax
+ 8: 9b df e0 [ ]*fstsw %ax
+ b: 9b df e0 [ ]*fstsw %ax
+ e: 9b 67 df e0 [ ]*addr16 fstsw %ax
+ 12: f3 67 66 36 a7 [ ]*repz addr16 cmpsw %es:\(%di\),%ss:\(%si\)
+ ...
diff --git a/gas/testsuite/gas/i386/prefix.s b/gas/testsuite/gas/i386/prefix.s
new file mode 100644
index 0000000000..043d31068a
--- /dev/null
+++ b/gas/testsuite/gas/i386/prefix.s
@@ -0,0 +1,11 @@
+.text
+foo:
+ addr16 fstcw %es:(%si)
+ fstsw
+ fstsw %ax
+ fstsw %eax
+ addr16 fstsw %ax
+ addr16 rep cmpsw %es:(%di),%ss:(%si)
+
+ # Get a good alignment.
+ .byte 0
diff --git a/gas/testsuite/gas/i386/reloc.d b/gas/testsuite/gas/i386/reloc.d
new file mode 100644
index 0000000000..c7903dd8d2
--- /dev/null
+++ b/gas/testsuite/gas/i386/reloc.d
@@ -0,0 +1,15 @@
+#objdump: -drw
+#name: i386 reloc
+
+.*: +file format .*i386.*
+
+Disassembly of section .text:
+
+00000000 <foo>:
+ 0: b3 00 [ ]*mov \$0x0,%bl 1: R_386_8 .text
+ 2: 68 00 00 00 00 [ ]*push \$0x0 3: R_386_32 .text
+ 7: 05 00 00 00 00 [ ]*add \$0x0,%eax 8: R_386_32 .text
+ c: 81 c3 00 00 00 00 [ ]*add \$0x0,%ebx e: R_386_32 .text
+ 12: 69 d2 00 00 00 00 [ ]*imul \$0x0,%edx,%edx 14: R_386_32 .text
+ 18: 9a 00 00 00 00 00 00 [ ]*lcall \$0x0,\$0x0 19: R_386_32 .text
+ 1f: 66 68 00 00 [ ]*pushw \$0x0 21: R_386_16 .text
diff --git a/gas/testsuite/gas/i386/reloc.s b/gas/testsuite/gas/i386/reloc.s
new file mode 100644
index 0000000000..13ee930db7
--- /dev/null
+++ b/gas/testsuite/gas/i386/reloc.s
@@ -0,0 +1,8 @@
+.text
+foo: mov $foo, %bl
+ push $foo
+ add $foo, %eax
+ add $foo, %ebx
+ imul $foo, %edx
+ lcall $0, $foo
+ pushw $foo
diff --git a/gas/testsuite/gas/i386/white.l b/gas/testsuite/gas/i386/white.l
new file mode 100644
index 0000000000..1ce6161fc9
--- /dev/null
+++ b/gas/testsuite/gas/i386/white.l
@@ -0,0 +1,21 @@
+GAS LISTING .*
+
+
+ 1 # test handling of whitespace, and upper-case
+ 2 .TeXt
+ 3 0000 36 ss
+ 4 0001 8803 mov % al , \( % ebx \)
+ 5 0003 C705D711 00007B00 0000 mOvl \$ 123 , 4567
+ 6 000d 678A787B ADDr16 mov 123 \( % bx , % si , 1 \) , % bh
+ 7 0011 FFE0 jmp \* % eax
+ 8 0013 6626FF23 foo: jmpw % es : \* \( % ebx \)
+ 9
+ 10 0017 A0500000 00 mov \( 0x8 \* 0Xa \) , % al
+ 11 001c B020 mov \$ \( 8 \* 4 \) , % al
+ 12 001e B713 mov \$ foo , % bH
+ 13 0020 B713 movb \$ foo , % BH
+ 14
+ 15 .CODE16
+ 16 0022 66B81300 0000 Mov \$ foo , %eAx
+ 17 .Code32
+ 18 0028 66B81300 mov \$ foo , %ax
diff --git a/gas/testsuite/gas/i386/white.s b/gas/testsuite/gas/i386/white.s
new file mode 100644
index 0000000000..3bf50705ff
--- /dev/null
+++ b/gas/testsuite/gas/i386/white.s
@@ -0,0 +1,18 @@
+# test handling of whitespace, and upper-case
+.TeXt
+ ss
+ mov % al , ( % ebx )
+ mOvl $ 123 , 4567
+ ADDr16 mov 123 ( % bx , % si , 1 ) , % bh
+ jmp * % eax
+foo: jmpw % es : * ( % ebx )
+
+ mov ( 0x8 * 0Xa ) , % al
+ mov $ ( 8 * 4 ) , % al
+ mov $ foo , % bH
+ movb $ foo , % BH
+
+.CODE16
+ Mov $ foo , %eAx
+.Code32
+ mov $ foo , %ax
diff --git a/gas/testsuite/gas/ieee-fp/x930509a.exp b/gas/testsuite/gas/ieee-fp/x930509a.exp
new file mode 100644
index 0000000000..d788d2c9e4
--- /dev/null
+++ b/gas/testsuite/gas/ieee-fp/x930509a.exp
@@ -0,0 +1,25 @@
+# Reported 93/05/09 by Jim Wilson: IEEE single-precision FLT_MIN value gets
+# assembled incorrectly. (Off by one ulp.)
+
+proc dotest {} {
+ set testname "IEEE FLT_MIN, single-precision"
+ set x 0
+ gas_start "x930509a.s" "-al"
+ while 1 {
+ expect {
+ -re " 00008000\[ \]+.single" { pass $testname; set x 1 }
+ -re " 00800000\[ \]+.single" { pass $testname; set x 1 }
+ -re " 0080 0000\[ \]+.single" { pass $testname; set x 1 }
+ -re " ........ +.single" { fail $testname; set x 1 }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+ gas_finish
+ if !$x then { fail "$testname (listing didn't match)" }
+}
+
+if ![istarget vax*-*-*] then {
+ dotest
+}
diff --git a/gas/testsuite/gas/ieee-fp/x930509a.s b/gas/testsuite/gas/ieee-fp/x930509a.s
new file mode 100644
index 0000000000..261b3383ac
--- /dev/null
+++ b/gas/testsuite/gas/ieee-fp/x930509a.s
@@ -0,0 +1,5 @@
+ .global _flt_min
+ .data
+ .align 4
+_flt_min:
+ .single 0r1.17549435e-38
diff --git a/gas/testsuite/gas/m32r/allinsn.d b/gas/testsuite/gas/m32r/allinsn.d
new file mode 100644
index 0000000000..55965e6605
--- /dev/null
+++ b/gas/testsuite/gas/m32r/allinsn.d
@@ -0,0 +1,374 @@
+#as:
+#objdump: -dr
+#name: allinsn
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+0000 <add>:
+ 0: 0d ad f0 00 add fp,fp \|\| nop
+
+0+0004 <add3>:
+ 4: 8d ad 00 00 add3 fp,fp,[#]*0
+
+0+0008 <and>:
+ 8: 0d cd f0 00 and fp,fp \|\| nop
+
+0+000c <and3>:
+ c: 8d cd 00 00 and3 fp,fp,[#]*0x0
+
+0+0010 <or>:
+ 10: 0d ed f0 00 or fp,fp \|\| nop
+
+0+0014 <or3>:
+ 14: 8d ed 00 00 or3 fp,fp,[#]*0x0
+
+0+0018 <xor>:
+ 18: 0d dd f0 00 xor fp,fp \|\| nop
+
+0+001c <xor3>:
+ 1c: 8d dd 00 00 xor3 fp,fp,[#]*0x0
+
+0+0020 <addi>:
+ 20: 4d 00 f0 00 addi fp,[#]*0 \|\| nop
+
+0+0024 <addv>:
+ 24: 0d 8d f0 00 addv fp,fp \|\| nop
+
+0+0028 <addv3>:
+ 28: 8d 8d 00 00 addv3 fp,fp,[#]*0
+
+0+002c <addx>:
+ 2c: 0d 9d f0 00 addx fp,fp \|\| nop
+
+0+0030 <bc8>:
+ 30: 7c f4 f0 00 bc 0 <add> \|\| nop
+
+0+0034 <bc8_s>:
+ 34: 7c f3 f0 00 bc 0 <add> \|\| nop
+
+0+0038 <bc24>:
+ 38: 7c f2 f0 00 bc 0 <add> \|\| nop
+
+0+003c <bc24_l>:
+ 3c: fc ff ff f1 bc 0 <add>
+
+0+0040 <beq>:
+ 40: bd 0d ff f0 beq fp,fp,0 <add>
+
+0+0044 <beqz>:
+ 44: b0 8d ff ef beqz fp,0 <add>
+
+0+0048 <bgez>:
+ 48: b0 bd ff ee bgez fp,0 <add>
+
+0+004c <bgtz>:
+ 4c: b0 dd ff ed bgtz fp,0 <add>
+
+0+0050 <blez>:
+ 50: b0 cd ff ec blez fp,0 <add>
+
+0+0054 <bltz>:
+ 54: b0 ad ff eb bltz fp,0 <add>
+
+0+0058 <bnez>:
+ 58: b0 9d ff ea bnez fp,0 <add>
+
+0+005c <bl8>:
+ 5c: 7e e9 f0 00 bl 0 <add> \|\| nop
+
+0+0060 <bl8_s>:
+ 60: 7e e8 f0 00 bl 0 <add> \|\| nop
+
+0+0064 <bl24>:
+ 64: 7e e7 f0 00 bl 0 <add> \|\| nop
+
+0+0068 <bl24_l>:
+ 68: fe ff ff e6 bl 0 <add>
+
+0+006c <bnc8>:
+ 6c: 7d e5 f0 00 bnc 0 <add> \|\| nop
+
+0+0070 <bnc8_s>:
+ 70: 7d e4 f0 00 bnc 0 <add> \|\| nop
+
+0+0074 <bnc24>:
+ 74: 7d e3 f0 00 bnc 0 <add> \|\| nop
+
+0+0078 <bnc24_l>:
+ 78: fd ff ff e2 bnc 0 <add>
+
+0+007c <bne>:
+ 7c: bd 1d ff e1 bne fp,fp,0 <add>
+
+0+0080 <bra8>:
+ 80: 7f e0 f0 00 bra 0 <add> \|\| nop
+
+0+0084 <bra8_s>:
+ 84: 7f df f0 00 bra 0 <add> \|\| nop
+
+0+0088 <bra24>:
+ 88: 7f de f0 00 bra 0 <add> \|\| nop
+
+0+008c <bra24_l>:
+ 8c: ff ff ff dd bra 0 <add>
+
+0+0090 <cmp>:
+ 90: 0d 4d f0 00 cmp fp,fp \|\| nop
+
+0+0094 <cmpi>:
+ 94: 80 4d 00 00 cmpi fp,[#]*0
+
+0+0098 <cmpu>:
+ 98: 0d 5d f0 00 cmpu fp,fp \|\| nop
+
+0+009c <cmpui>:
+ 9c: 80 5d 00 00 cmpui fp,[#]*0
+
+0+00a0 <div>:
+ a0: 9d 0d 00 00 div fp,fp
+
+0+00a4 <divu>:
+ a4: 9d 1d 00 00 divu fp,fp
+
+0+00a8 <rem>:
+ a8: 9d 2d 00 00 rem fp,fp
+
+0+00ac <remu>:
+ ac: 9d 3d 00 00 remu fp,fp
+
+0+00b0 <jl>:
+ b0: 1e cd f0 00 jl fp \|\| nop
+
+0+00b4 <jmp>:
+ b4: 1f cd f0 00 jmp fp \|\| nop
+
+0+00b8 <ld>:
+ b8: 2d cd f0 00 ld fp,@fp \|\| nop
+
+0+00bc <ld_2>:
+ bc: 2d cd f0 00 ld fp,@fp \|\| nop
+
+0+00c0 <ld_d>:
+ c0: ad cd 00 00 ld fp,@\(0,fp\)
+
+0+00c4 <ld_d2>:
+ c4: ad cd 00 00 ld fp,@\(0,fp\)
+
+0+00c8 <ldb>:
+ c8: 2d 8d f0 00 ldb fp,@fp \|\| nop
+
+0+00cc <ldb_2>:
+ cc: 2d 8d f0 00 ldb fp,@fp \|\| nop
+
+0+00d0 <ldb_d>:
+ d0: ad 8d 00 00 ldb fp,@\(0,fp\)
+
+0+00d4 <ldb_d2>:
+ d4: ad 8d 00 00 ldb fp,@\(0,fp\)
+
+0+00d8 <ldh>:
+ d8: 2d ad f0 00 ldh fp,@fp \|\| nop
+
+0+00dc <ldh_2>:
+ dc: 2d ad f0 00 ldh fp,@fp \|\| nop
+
+0+00e0 <ldh_d>:
+ e0: ad ad 00 00 ldh fp,@\(0,fp\)
+
+0+00e4 <ldh_d2>:
+ e4: ad ad 00 00 ldh fp,@\(0,fp\)
+
+0+00e8 <ldub>:
+ e8: 2d 9d f0 00 ldub fp,@fp \|\| nop
+
+0+00ec <ldub_2>:
+ ec: 2d 9d f0 00 ldub fp,@fp \|\| nop
+
+0+00f0 <ldub_d>:
+ f0: ad 9d 00 00 ldub fp,@\(0,fp\)
+
+0+00f4 <ldub_d2>:
+ f4: ad 9d 00 00 ldub fp,@\(0,fp\)
+
+0+00f8 <lduh>:
+ f8: 2d bd f0 00 lduh fp,@fp \|\| nop
+
+0+00fc <lduh_2>:
+ fc: 2d bd f0 00 lduh fp,@fp \|\| nop
+
+0+0100 <lduh_d>:
+ 100: ad bd 00 00 lduh fp,@\(0,fp\)
+
+0+0104 <lduh_d2>:
+ 104: ad bd 00 00 lduh fp,@\(0,fp\)
+
+0+0108 <ld_plus>:
+ 108: 2d ed f0 00 ld fp,@fp\+ \|\| nop
+
+0+010c <ld24>:
+ 10c: ed 00 00 00 ld24 fp,[#]*0 <add>
+ 10c: R_M32R_24 .data
+
+0+0110 <ldi8>:
+ 110: 6d 00 f0 00 ldi fp,[#]*0 \|\| nop
+
+0+0114 <ldi16>:
+ 114: 9d f0 01 00 ldi fp,[#]*256
+
+0+0118 <lock>:
+ 118: 2d dd f0 00 lock fp,@fp \|\| nop
+
+0+011c <machi>:
+ 11c: 3d 4d f0 00 machi fp,fp \|\| nop
+
+0+0120 <maclo>:
+ 120: 3d 5d f0 00 maclo fp,fp \|\| nop
+
+0+0124 <macwhi>:
+ 124: 3d 6d f0 00 macwhi fp,fp \|\| nop
+
+0+0128 <macwlo>:
+ 128: 3d 7d f0 00 macwlo fp,fp \|\| nop
+
+0+012c <mul>:
+ 12c: 1d 6d f0 00 mul fp,fp \|\| nop
+
+0+0130 <mulhi>:
+ 130: 3d 0d f0 00 mulhi fp,fp \|\| nop
+
+0+0134 <mullo>:
+ 134: 3d 1d f0 00 mullo fp,fp \|\| nop
+
+0+0138 <mulwhi>:
+ 138: 3d 2d f0 00 mulwhi fp,fp \|\| nop
+
+0+013c <mulwlo>:
+ 13c: 3d 3d f0 00 mulwlo fp,fp \|\| nop
+
+0+0140 <mv>:
+ 140: 1d 8d f0 00 mv fp,fp \|\| nop
+
+0+0144 <mvfachi>:
+ 144: 5d f0 f0 00 mvfachi fp \|\| nop
+
+0+0148 <mvfaclo>:
+ 148: 5d f1 f0 00 mvfaclo fp \|\| nop
+
+0+014c <mvfacmi>:
+ 14c: 5d f2 f0 00 mvfacmi fp \|\| nop
+
+0+0150 <mvfc>:
+ 150: 1d 90 f0 00 mvfc fp,psw \|\| nop
+
+0+0154 <mvtachi>:
+ 154: 5d 70 f0 00 mvtachi fp \|\| nop
+
+0+0158 <mvtaclo>:
+ 158: 5d 71 f0 00 mvtaclo fp \|\| nop
+
+0+015c <mvtc>:
+ 15c: 10 ad f0 00 mvtc fp,psw \|\| nop
+
+0+0160 <neg>:
+ 160: 0d 3d f0 00 neg fp,fp \|\| nop
+
+0+0164 <nop>:
+ 164: 70 00 f0 00 nop \|\| nop
+
+0+0168 <not>:
+ 168: 0d bd f0 00 not fp,fp \|\| nop
+
+0+016c <rac>:
+ 16c: dd c0 00 00 seth fp,[#]*0x0
+
+0+0170 <sll>:
+ 170: 1d 4d f0 00 sll fp,fp \|\| nop
+
+0+0174 <sll3>:
+ 174: 9d cd 00 00 sll3 fp,fp,[#]*0
+
+0+0178 <slli>:
+ 178: 5d 40 f0 00 slli fp,[#]*0x0 \|\| nop
+
+0+017c <sra>:
+ 17c: 1d 2d f0 00 sra fp,fp \|\| nop
+
+0+0180 <sra3>:
+ 180: 9d ad 00 00 sra3 fp,fp,[#]*0
+
+0+0184 <srai>:
+ 184: 5d 20 f0 00 srai fp,[#]*0x0 \|\| nop
+
+0+0188 <srl>:
+ 188: 1d 0d f0 00 srl fp,fp \|\| nop
+
+0+018c <srl3>:
+ 18c: 9d 8d 00 00 srl3 fp,fp,[#]*0
+
+0+0190 <srli>:
+ 190: 5d 00 f0 00 srli fp,[#]*0x0 \|\| nop
+
+0+0194 <st>:
+ 194: 2d 4d f0 00 st fp,@fp \|\| nop
+
+0+0198 <st_2>:
+ 198: 2d 4d f0 00 st fp,@fp \|\| nop
+
+0+019c <st_d>:
+ 19c: ad 4d 00 00 st fp,@\(0,fp\)
+
+0+01a0 <st_d2>:
+ 1a0: ad 4d 00 00 st fp,@\(0,fp\)
+
+0+01a4 <stb>:
+ 1a4: 2d 0d f0 00 stb fp,@fp \|\| nop
+
+0+01a8 <stb_2>:
+ 1a8: 2d 0d f0 00 stb fp,@fp \|\| nop
+
+0+01ac <stb_d>:
+ 1ac: ad 0d 00 00 stb fp,@\(0,fp\)
+
+0+01b0 <stb_d2>:
+ 1b0: ad 0d 00 00 stb fp,@\(0,fp\)
+
+0+01b4 <sth>:
+ 1b4: 2d 2d f0 00 sth fp,@fp \|\| nop
+
+0+01b8 <sth_2>:
+ 1b8: 2d 2d f0 00 sth fp,@fp \|\| nop
+
+0+01bc <sth_d>:
+ 1bc: ad 2d 00 00 sth fp,@\(0,fp\)
+
+0+01c0 <sth_d2>:
+ 1c0: ad 2d 00 00 sth fp,@\(0,fp\)
+
+0+01c4 <st_plus>:
+ 1c4: 2d 6d f0 00 st fp,@\+fp \|\| nop
+
+0+01c8 <st_minus>:
+ 1c8: 2d 7d f0 00 st fp,@-fp \|\| nop
+
+0+01cc <sub>:
+ 1cc: 0d 2d f0 00 sub fp,fp \|\| nop
+
+0+01d0 <subv>:
+ 1d0: 0d 0d f0 00 subv fp,fp \|\| nop
+
+0+01d4 <subx>:
+ 1d4: 0d 1d f0 00 subx fp,fp \|\| nop
+
+0+01d8 <trap>:
+ 1d8: 10 f0 f0 00 trap [#]*0x0 \|\| nop
+
+0+01dc <unlock>:
+ 1dc: 2d 5d f0 00 unlock fp,@fp \|\| nop
+
+0+01e0 <push>:
+ 1e0: 2d 7f f0 00 push fp \|\| nop
+
+0+01e4 <pop>:
+ 1e4: 2d ef f0 00 pop fp \|\| nop
diff --git a/gas/testsuite/gas/m32r/allinsn.exp b/gas/testsuite/gas/m32r/allinsn.exp
new file mode 100644
index 0000000000..c5ddd0eb3f
--- /dev/null
+++ b/gas/testsuite/gas/m32r/allinsn.exp
@@ -0,0 +1,5 @@
+# M32R assembler testsuite.
+
+if [istarget m32r*-*-*] {
+ run_dump_test "allinsn"
+}
diff --git a/gas/testsuite/gas/m32r/allinsn.s b/gas/testsuite/gas/m32r/allinsn.s
new file mode 100644
index 0000000000..86b456961a
--- /dev/null
+++ b/gas/testsuite/gas/m32r/allinsn.s
@@ -0,0 +1,501 @@
+ .data
+foodata: .word 42
+ .text
+footext:
+ .text
+ .global add
+add:
+ add fp,fp
+ .text
+ .global add3
+add3:
+ add3 fp,fp,#0
+ .text
+ .global and
+and:
+ and fp,fp
+ .text
+ .global and3
+and3:
+ and3 fp,fp,#0
+ .text
+ .global or
+or:
+ or fp,fp
+ .text
+ .global or3
+or3:
+ or3 fp,fp,#0
+ .text
+ .global xor
+xor:
+ xor fp,fp
+ .text
+ .global xor3
+xor3:
+ xor3 fp,fp,#0
+ .text
+ .global addi
+addi:
+ addi fp,#0
+ .text
+ .global addv
+addv:
+ addv fp,fp
+ .text
+ .global addv3
+addv3:
+ addv3 fp,fp,#0
+ .text
+ .global addx
+addx:
+ addx fp,fp
+ .text
+ .global bc8
+bc8:
+ bc footext
+ .text
+ .global bc8_s
+bc8_s:
+ bc.s footext
+ .text
+ .global bc24
+bc24:
+ bc footext
+ .text
+ .global bc24_l
+bc24_l:
+ bc.l footext
+ .text
+ .global beq
+beq:
+ beq fp,fp,footext
+ .text
+ .global beqz
+beqz:
+ beqz fp,footext
+ .text
+ .global bgez
+bgez:
+ bgez fp,footext
+ .text
+ .global bgtz
+bgtz:
+ bgtz fp,footext
+ .text
+ .global blez
+blez:
+ blez fp,footext
+ .text
+ .global bltz
+bltz:
+ bltz fp,footext
+ .text
+ .global bnez
+bnez:
+ bnez fp,footext
+ .text
+ .global bl8
+bl8:
+ bl footext
+ .text
+ .global bl8_s
+bl8_s:
+ bl.s footext
+ .text
+ .global bl24
+bl24:
+ bl footext
+ .text
+ .global bl24_l
+bl24_l:
+ bl.l footext
+ .text
+ .global bnc8
+bnc8:
+ bnc footext
+ .text
+ .global bnc8_s
+bnc8_s:
+ bnc.s footext
+ .text
+ .global bnc24
+bnc24:
+ bnc footext
+ .text
+ .global bnc24_l
+bnc24_l:
+ bnc.l footext
+ .text
+ .global bne
+bne:
+ bne fp,fp,footext
+ .text
+ .global bra8
+bra8:
+ bra footext
+ .text
+ .global bra8_s
+bra8_s:
+ bra.s footext
+ .text
+ .global bra24
+bra24:
+ bra footext
+ .text
+ .global bra24_l
+bra24_l:
+ bra.l footext
+ .text
+ .global cmp
+cmp:
+ cmp fp,fp
+ .text
+ .global cmpi
+cmpi:
+ cmpi fp,#0
+ .text
+ .global cmpu
+cmpu:
+ cmpu fp,fp
+ .text
+ .global cmpui
+cmpui:
+ cmpui fp,#0
+ .text
+ .global div
+div:
+ div fp,fp
+ .text
+ .global divu
+divu:
+ divu fp,fp
+ .text
+ .global rem
+rem:
+ rem fp,fp
+ .text
+ .global remu
+remu:
+ remu fp,fp
+ .text
+ .global jl
+jl:
+ jl fp
+ .text
+ .global jmp
+jmp:
+ jmp fp
+ .text
+ .global ld
+ld:
+ ld fp,@fp
+ .text
+ .global ld_2
+ld_2:
+ ld fp,@(fp)
+ .text
+ .global ld_d
+ld_d:
+ ld fp,@(0,fp)
+ .text
+ .global ld_d2
+ld_d2:
+ ld fp,@(fp,0)
+ .text
+ .global ldb
+ldb:
+ ldb fp,@fp
+ .text
+ .global ldb_2
+ldb_2:
+ ldb fp,@(fp)
+ .text
+ .global ldb_d
+ldb_d:
+ ldb fp,@(0,fp)
+ .text
+ .global ldb_d2
+ldb_d2:
+ ldb fp,@(fp,0)
+ .text
+ .global ldh
+ldh:
+ ldh fp,@fp
+ .text
+ .global ldh_2
+ldh_2:
+ ldh fp,@(fp)
+ .text
+ .global ldh_d
+ldh_d:
+ ldh fp,@(0,fp)
+ .text
+ .global ldh_d2
+ldh_d2:
+ ldh fp,@(fp,0)
+ .text
+ .global ldub
+ldub:
+ ldub fp,@fp
+ .text
+ .global ldub_2
+ldub_2:
+ ldub fp,@(fp)
+ .text
+ .global ldub_d
+ldub_d:
+ ldub fp,@(0,fp)
+ .text
+ .global ldub_d2
+ldub_d2:
+ ldub fp,@(fp,0)
+ .text
+ .global lduh
+lduh:
+ lduh fp,@fp
+ .text
+ .global lduh_2
+lduh_2:
+ lduh fp,@(fp)
+ .text
+ .global lduh_d
+lduh_d:
+ lduh fp,@(0,fp)
+ .text
+ .global lduh_d2
+lduh_d2:
+ lduh fp,@(fp,0)
+ .text
+ .global ld_plus
+ld_plus:
+ ld fp,@fp+
+ .text
+ .global ld24
+ld24:
+ ld24 fp,foodata
+ .text
+ .global ldi8
+ldi8:
+ ldi fp,0
+ .text
+ .global ldi16
+ldi16:
+ ldi fp,256
+ .text
+ .global lock
+lock:
+ lock fp,@fp
+ .text
+ .global machi
+machi:
+ machi fp,fp
+ .text
+ .global maclo
+maclo:
+ maclo fp,fp
+ .text
+ .global macwhi
+macwhi:
+ macwhi fp,fp
+ .text
+ .global macwlo
+macwlo:
+ macwlo fp,fp
+ .text
+ .global mul
+mul:
+ mul fp,fp
+ .text
+ .global mulhi
+mulhi:
+ mulhi fp,fp
+ .text
+ .global mullo
+mullo:
+ mullo fp,fp
+ .text
+ .global mulwhi
+mulwhi:
+ mulwhi fp,fp
+ .text
+ .global mulwlo
+mulwlo:
+ mulwlo fp,fp
+ .text
+ .global mv
+mv:
+ mv fp,fp
+ .text
+ .global mvfachi
+mvfachi:
+ mvfachi fp
+ .text
+ .global mvfaclo
+mvfaclo:
+ mvfaclo fp
+ .text
+ .global mvfacmi
+mvfacmi:
+ mvfacmi fp
+ .text
+ .global mvfc
+mvfc:
+ mvfc fp,psw
+ .text
+ .global mvtachi
+mvtachi:
+ mvtachi fp
+ .text
+ .global mvtaclo
+mvtaclo:
+ mvtaclo fp
+ .text
+ .global mvtc
+mvtc:
+ mvtc fp,psw
+ .text
+ .global neg
+neg:
+ neg fp,fp
+ .text
+ .global nop
+nop:
+ nop
+ .text
+ .global not
+not:
+ not fp,fp
+ .text
+ .global rac
+rac:
+ .text
+ .global rach
+rach:
+ .text
+ .global rte
+rte:
+ .text
+ .global seth
+seth:
+ seth fp,0
+ .text
+ .global sll
+sll:
+ sll fp,fp
+ .text
+ .global sll3
+sll3:
+ sll3 fp,fp,0
+ .text
+ .global slli
+slli:
+ slli fp,0
+ .text
+ .global sra
+sra:
+ sra fp,fp
+ .text
+ .global sra3
+sra3:
+ sra3 fp,fp,0
+ .text
+ .global srai
+srai:
+ srai fp,0
+ .text
+ .global srl
+srl:
+ srl fp,fp
+ .text
+ .global srl3
+srl3:
+ srl3 fp,fp,0
+ .text
+ .global srli
+srli:
+ srli fp,0
+ .text
+ .global st
+st:
+ st fp,@fp
+ .text
+ .global st_2
+st_2:
+ st fp,@(fp)
+ .text
+ .global st_d
+st_d:
+ st fp,@(0,fp)
+ .text
+ .global st_d2
+st_d2:
+ st fp,@(fp,0)
+ .text
+ .global stb
+stb:
+ stb fp,@fp
+ .text
+ .global stb_2
+stb_2:
+ stb fp,@(fp)
+ .text
+ .global stb_d
+stb_d:
+ stb fp,@(0,fp)
+ .text
+ .global stb_d2
+stb_d2:
+ stb fp,@(fp,0)
+ .text
+ .global sth
+sth:
+ sth fp,@fp
+ .text
+ .global sth_2
+sth_2:
+ sth fp,@(fp)
+ .text
+ .global sth_d
+sth_d:
+ sth fp,@(0,fp)
+ .text
+ .global sth_d2
+sth_d2:
+ sth fp,@(fp,0)
+ .text
+ .global st_plus
+st_plus:
+ st fp,@+fp
+ .text
+ .global st_minus
+st_minus:
+ st fp,@-fp
+ .text
+ .global sub
+sub:
+ sub fp,fp
+ .text
+ .global subv
+subv:
+ subv fp,fp
+ .text
+ .global subx
+subx:
+ subx fp,fp
+ .text
+ .global trap
+trap:
+ trap 0
+ .text
+ .global unlock
+unlock:
+ unlock fp,@fp
+ .text
+ .global push
+push:
+ push fp
+ .text
+ .global pop
+pop:
+ pop fp
diff --git a/gas/testsuite/gas/m32r/fslot.d b/gas/testsuite/gas/m32r/fslot.d
new file mode 100644
index 0000000000..a9cf02bd7d
--- /dev/null
+++ b/gas/testsuite/gas/m32r/fslot.d
@@ -0,0 +1,31 @@
+#as:
+#objdump: -dr
+#name: fslot
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+0 <bl>:
+ *0: 7e 00 f0 00 bl 0 <bl> \|\| nop
+ *4: 60 08 f0 00 ldi r0,[#]*8 \|\| nop
+
+0+8 <bl_s>:
+ *8: 7e 00 f0 00 bl 8 <bl_s> \|\| nop
+ *c: 60 08 f0 00 ldi r0,[#]*8 \|\| nop
+
+0+10 <bra>:
+ *10: 7f 00 f0 00 bra 10 <bra> \|\| nop
+ *14: 60 08 f0 00 ldi r0,[#]*8 \|\| nop
+
+0+18 <bra_s>:
+ *18: 7f 00 f0 00 bra 18 <bra_s> \|\| nop
+ *1c: 60 08 f0 00 ldi r0,[#]*8 \|\| nop
+
+0+20 <jl>:
+ *20: 1e c0 f0 00 jl r0 \|\| nop
+ *24: 60 08 f0 00 ldi r0,[#]*8 \|\| nop
+
+0+28 <trap>:
+ *28: 10 f4 f0 00 trap [#]*0x4 \|\| nop
+ *2c: 60 08 f0 00 ldi r0,[#]*8 \|\| nop
diff --git a/gas/testsuite/gas/m32r/fslot.s b/gas/testsuite/gas/m32r/fslot.s
new file mode 100644
index 0000000000..586b664d9e
--- /dev/null
+++ b/gas/testsuite/gas/m32r/fslot.s
@@ -0,0 +1,27 @@
+# Test the FILL-SLOT attribute.
+# The FILL-SLOT attribute ensures the next insn begins on a 32 byte boundary.
+# This is needed for example with bl because the subroutine will return
+# to a 32 bit boundary.
+
+ .text
+bl:
+ bl bl
+ ldi r0,#8
+bl_s:
+ bl.s bl_s
+ ldi r0,#8
+
+bra:
+ bra bra
+ ldi r0,#8
+bra_s:
+ bra.s bra_s
+ ldi r0,#8
+
+jl:
+ jl r0
+ ldi r0,#8
+
+trap:
+ trap #4
+ ldi r0,#8
diff --git a/gas/testsuite/gas/m32r/high-1.d b/gas/testsuite/gas/m32r/high-1.d
new file mode 100644
index 0000000000..b5ccb8c55b
--- /dev/null
+++ b/gas/testsuite/gas/m32r/high-1.d
@@ -0,0 +1,19 @@
+#as:
+#objdump: -dr
+#name: high-1
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0* <foo>:
+ *0: d4 c0 00 01 seth r4,[#]*0x1
+[ ]*0: R_M32R_HI16_ULO .text
+ *4: 84 e4 00 00 or3 r4,r4,[#]*0x0
+[ ]*4: R_M32R_LO16 .text
+ *8: d4 c0 12 34 seth r4,[#]*0x1234
+ *c: 84 e4 87 65 or3 r4,r4,[#]*0x8765
+ *10: d4 c0 12 35 seth r4,[#]*0x1235
+ *14: 84 e4 87 65 or3 r4,r4,[#]*0x8765
+ *18: d4 c0 87 65 seth r4,[#]*0x8765
+ *1c: 84 e4 43 21 or3 r4,r4,[#]*0x4321
diff --git a/gas/testsuite/gas/m32r/high-1.s b/gas/testsuite/gas/m32r/high-1.s
new file mode 100644
index 0000000000..8a5d1d10ab
--- /dev/null
+++ b/gas/testsuite/gas/m32r/high-1.s
@@ -0,0 +1,14 @@
+; Test high/shigh handling.
+
+foo:
+ seth r4,#high(foo+0x10000)
+ or3 r4,r4,#low(foo+0x10000)
+
+ seth r4,#high(0x12348765)
+ or3 r4,r4,#low(0x12348765)
+
+ seth r4,#shigh(0x12348765)
+ or3 r4,r4,#low(0x12348765)
+
+ seth r4,#shigh(0x87654321)
+ or3 r4,r4,#low(0x87654321)
diff --git a/gas/testsuite/gas/m32r/m32r.exp b/gas/testsuite/gas/m32r/m32r.exp
new file mode 100644
index 0000000000..28c23642fa
--- /dev/null
+++ b/gas/testsuite/gas/m32r/m32r.exp
@@ -0,0 +1,8 @@
+# M32R testcases
+
+if [istarget m32r*-*-*] {
+ run_dump_test "high-1"
+ run_dump_test "relax-1"
+ run_dump_test "uppercase"
+ run_dump_test "fslot"
+}
diff --git a/gas/testsuite/gas/m32r/outofrange.s b/gas/testsuite/gas/m32r/outofrange.s
new file mode 100644
index 0000000000..570d311bdc
--- /dev/null
+++ b/gas/testsuite/gas/m32r/outofrange.s
@@ -0,0 +1,145 @@
+; Test error messages where branches are out of range.
+
+; { dg-do assemble { target m32r-*-* } }
+
+ .text
+ .global foo
+foo:
+ bl.s label
+ ; { dg-error "out of range" "out of range bl.s" { target *-*-* } { 8 } }
+ bnc.s label
+ ; { dg-error "out of range" "out of range bnc.s" { target *-*-* } { 10 } }
+ bra.s label
+ ; { dg-error "out of range" "out of range bra.s" { target *-*-* } { 12 } }
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+ ld24 r0,#0
+label:
+ jmp r14
diff --git a/gas/testsuite/gas/m32r/relax-1.d b/gas/testsuite/gas/m32r/relax-1.d
new file mode 100644
index 0000000000..2a4fcb8005
--- /dev/null
+++ b/gas/testsuite/gas/m32r/relax-1.d
@@ -0,0 +1,18 @@
+#as:
+#objdump: -dr
+#name: relax-1
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0* <DoesNotWork>:
+ *0: 70 00 70 00 * nop -> nop
+
+0*4 <Work>:
+ *4: 70 00 70 00 * nop -> nop
+Disassembly of section .branch:
+
+0* <branch>:
+ *0: ff 00 00 01 bra 4 <Work>
+[ ]*0: R_M32R_26_PCREL .text
diff --git a/gas/testsuite/gas/m32r/relax-1.s b/gas/testsuite/gas/m32r/relax-1.s
new file mode 100644
index 0000000000..d4e12c0fd3
--- /dev/null
+++ b/gas/testsuite/gas/m32r/relax-1.s
@@ -0,0 +1,17 @@
+; Test relaxation into non-zero offset to different segment.
+
+ .section .branch, "ax",@progbits
+ .balign 4
+branch:
+ bra Work
+
+
+ .section .text
+ .balign 4
+DoesNotWork:
+ nop
+ nop
+
+Work:
+ nop
+ nop
diff --git a/gas/testsuite/gas/m32r/uppercase.d b/gas/testsuite/gas/m32r/uppercase.d
new file mode 100644
index 0000000000..12b1345988
--- /dev/null
+++ b/gas/testsuite/gas/m32r/uppercase.d
@@ -0,0 +1,26 @@
+#as:
+#objdump: -dr
+#name: uppercase
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+0000 <foo>:
+ 0: 10 81 10 91 * mv r0,r1 -> mvfc r0,cbr
+
+0+0004 <high>:
+ 4: d0 c0 00 00 seth r0,#0x0
+[ ]*4: R_M32R_HI16_ULO [.]text
+
+0+0008 <shigh>:
+ 8: d0 c0 00 00 seth r0,#0x0
+[ ]*8: R_M32R_HI16_SLO [.]text
+
+0+000c <low>:
+ c: 80 e0 00 0c or3 r0,r0,#0xc
+[ ]*c: R_M32R_LO16 [.]text
+
+0+0010 <sda>:
+ 10: 80 a0 00 00 add3 r0,r0,#0
+[ ]*10: R_M32R_SDA16 sdavar
diff --git a/gas/testsuite/gas/m32r/uppercase.s b/gas/testsuite/gas/m32r/uppercase.s
new file mode 100644
index 0000000000..bdaeafd9f1
--- /dev/null
+++ b/gas/testsuite/gas/m32r/uppercase.s
@@ -0,0 +1,14 @@
+ .text
+ .global foo
+foo:
+ mv R0,R1
+ mvfc R0,CBR
+
+high:
+ seth r0,#HIGH(high)
+shigh:
+ seth r0,#SHIGH(shigh)
+low:
+ or3 r0,r0,#LOW(low)
+sda:
+ add3 r0,r0,#SDA(sdavar)
diff --git a/gas/testsuite/gas/m68k-coff/gas.exp b/gas/testsuite/gas/m68k-coff/gas.exp
new file mode 100644
index 0000000000..ab7eefa3a5
--- /dev/null
+++ b/gas/testsuite/gas/m68k-coff/gas.exp
@@ -0,0 +1,15 @@
+#
+# Some m68k-coff tests
+#
+if [istarget m68*-*-coff] then {
+ gas_test "p2430.s" "" $stdoptlist "local branch not in text section"
+
+ gas_test "p2430a.s" "" $stdoptlist "local branch not in text section"
+
+ gas_test "t1.s" "" $stdoptlist "multiple .file directives"
+
+ gas_test "p2389.s" "" $stdoptlist "bss fill"
+
+ setup_xfail m68*-*-coff
+ gas_test_error "p2389a.s" "" "detect bss fill with non-zero data"
+}
diff --git a/gas/testsuite/gas/m68k-coff/p2389.s b/gas/testsuite/gas/m68k-coff/p2389.s
new file mode 100644
index 0000000000..3fa93e9b47
--- /dev/null
+++ b/gas/testsuite/gas/m68k-coff/p2389.s
@@ -0,0 +1,19 @@
+# I reached a point where the file looks
+# clean and complies with gas syntax, but it core dumps gas. Here's a
+# little gdb info:
+#
+# Program terminated with signal 11, Segmentation fault.
+# #0 0x6323c in memcpy ()
+# (gdb) bt
+# #0 0x6323c in memcpy ()
+# #1 0xf2b0 in fill_section (abfd=0xeaee8, filehdr=0x8a7f4,
+# file_cursor=0xf7fff654) at obj-format.c:534
+# #2 0x112a8 in write_object_file () at obj-format.c:1786
+# #3 0x13ef8 in main (argc=5, argv=0xf7fff7bc) at ../../p3/gas/as.c:310
+# (gdb)
+#
+# gas did manage to create the .o file at this point.
+
+ .bss
+
+_ASIC_INT_TBL: .space 32,0 | keep interrupt routines here
diff --git a/gas/testsuite/gas/m68k-coff/p2389a.s b/gas/testsuite/gas/m68k-coff/p2389a.s
new file mode 100644
index 0000000000..76b27657ad
--- /dev/null
+++ b/gas/testsuite/gas/m68k-coff/p2389a.s
@@ -0,0 +1,3 @@
+ .bss
+
+_ASIC_INT_TBL: .space 32,1 | keep interrupt routines here
diff --git a/gas/testsuite/gas/m68k-coff/p2430.s b/gas/testsuite/gas/m68k-coff/p2430.s
new file mode 100644
index 0000000000..49723d9df3
--- /dev/null
+++ b/gas/testsuite/gas/m68k-coff/p2430.s
@@ -0,0 +1,6 @@
+# This differs from p2430a.s (the customer's actual source file) only
+# in whitespace and comments. Strangely, this file gave no problems...
+
+ .sect foo
+tag:
+ bra tag
diff --git a/gas/testsuite/gas/m68k-coff/p2430a.s b/gas/testsuite/gas/m68k-coff/p2430a.s
new file mode 100644
index 0000000000..601fb117d9
--- /dev/null
+++ b/gas/testsuite/gas/m68k-coff/p2430a.s
@@ -0,0 +1,4 @@
+ .sect foo
+
+tag:
+ bra tag
diff --git a/gas/testsuite/gas/m68k-coff/t1.s b/gas/testsuite/gas/m68k-coff/t1.s
new file mode 100644
index 0000000000..cc015f2a0d
--- /dev/null
+++ b/gas/testsuite/gas/m68k-coff/t1.s
@@ -0,0 +1,36 @@
+# 1 "libgcc1.S"
+# 42 "libxyz1.S"
+# 259 "libgcc1.S"
+ .text
+ .proc
+|#PROC# 04
+ .globl __mulsi3
+ __mulsi3 :
+|#PROLOGUE# 0
+ link %a6 ,#0
+ addl #-LF14, %sp
+ moveml #LS14, %sp @
+|#PROLOGUE# 1
+ movew %a6 @(0x8), %d0
+ muluw %a6 @(0xe), %d0
+ movew %a6 @(0xa), %d1
+ muluw %a6 @(0xc), %d1
+ addw %d1 , %d0
+ lsll #8, %d0
+ lsll #8, %d0
+ movew %a6 @(0xa), %d1
+ muluw %a6 @(0xe), %d1
+ addl %d1 , %d0
+ jra LE14
+LE14:
+|#PROLOGUE# 2
+ moveml %sp @, #LS14
+ unlk %a6
+|#PROLOGUE# 3
+ rts
+ LF14 = 4
+ LS14 = 0x0002
+ LFF14 = 0
+# 354 "libgcc1.S"
+ LSS14 = 0x0
+ LV14 = 0
diff --git a/gas/testsuite/gas/m68k/all.exp b/gas/testsuite/gas/m68k/all.exp
new file mode 100644
index 0000000000..88ab2a05c0
--- /dev/null
+++ b/gas/testsuite/gas/m68k/all.exp
@@ -0,0 +1,39 @@
+#
+# Some generic m68k tests
+#
+if [istarget m68*-*-*] then {
+ gas_test "t2.s" "" "" "cross-section branch"
+ if [istarget m68*-motorola-sysv] then {
+ run_dump_test t2
+ }
+
+ gas_test "pic1.s" "" "" "PIC generation"
+
+ gas_test "disperr.s" "-m68020" "" "Incorrect Displacement too long error"
+
+ gas_test_error "p2410.s" "" "out-of-range 'bras'"
+
+ run_dump_test pcrel
+ run_dump_test operands
+ run_dump_test cas
+ run_dump_test bitfield
+ run_dump_test link
+ run_dump_test fmoveml
+
+ set testname "68000 operands"
+ gas_run "operands.s" "-m68000" "2>err.out"
+ if ![string match "child process exited abnormally" $comp_output] then {
+ send_log "$comp_output\n"
+ verbose "$comp_output" 3
+ fail $testname
+ } else {
+ if [regexp_diff "err.out" "$srcdir/$subdir/op68000.d"] then {
+ fail $testname
+ } else {
+ pass $testname
+ }
+ }
+}
+if [info exists errorInfo] then {
+ unset errorInfo
+ }
diff --git a/gas/testsuite/gas/m68k/bitfield.d b/gas/testsuite/gas/m68k/bitfield.d
new file mode 100644
index 0000000000..5fb1bdd9d8
--- /dev/null
+++ b/gas/testsuite/gas/m68k/bitfield.d
@@ -0,0 +1,28 @@
+#objdump: -d --prefix-addresses
+#name: bitfield
+
+# Test handling of bitfield instruction operands.
+
+.*: +file format .*
+
+Disassembly of section .text:
+0+000 <foo> bfexts %a0@,1,2,%d0
+0+004 <foo\+(0x|)4> bfexts %a0@,1,6,%d0
+0+008 <foo\+(0x|)8> bfexts %a0@,3,2,%d0
+0+00c <foo\+(0x|)c> bfexts %a0@,3,6,%d0
+0+010 <foo\+(0x|)10> bfexts %a0@,1,2,%d0
+0+014 <foo\+(0x|)14> bfexts %a0@,1,6,%d0
+0+018 <foo\+(0x|)18> bfexts %a0@,3,2,%d0
+0+01c <foo\+(0x|)1c> bfexts %a0@,3,6,%d0
+0+020 <foo\+(0x|)20> bfset %a0@,1,2
+0+024 <foo\+(0x|)24> bfset %a0@,1,6
+0+028 <foo\+(0x|)28> bfset %a0@,3,2
+0+02c <foo\+(0x|)2c> bfset %a0@,3,6
+0+030 <foo\+(0x|)30> bfset %a0@,1,2
+0+034 <foo\+(0x|)34> bfset %a0@,1,6
+0+038 <foo\+(0x|)38> bfset %a0@,3,2
+0+03c <foo\+(0x|)3c> bfset %a0@,3,6
+0+040 <foo\+(0x|)40> bfexts %a0@,%d1,%d2,%d0
+0+044 <foo\+(0x|)44> bfexts %a0@,%d1,%d2,%d0
+0+048 <foo\+(0x|)48> bfset %a0@,%d1,%d2
+0+04c <foo\+(0x|)4c> bfset %a0@,%d1,%d2
diff --git a/gas/testsuite/gas/m68k/bitfield.s b/gas/testsuite/gas/m68k/bitfield.s
new file mode 100644
index 0000000000..4d2f758255
--- /dev/null
+++ b/gas/testsuite/gas/m68k/bitfield.s
@@ -0,0 +1,24 @@
+# Test handling of bitfield instruction operands.
+ .text
+ .globl foo
+foo:
+ bfexts (%a0){&1:&2},%d0
+ bfexts (%a0){&1:&(2+4)},%d0
+ bfexts (%a0){&(1+2):&2},%d0
+ bfexts (%a0){&(1+2):&(2+4)},%d0
+ bfexts %a0@,&1,&2,%d0
+ bfexts %a0@,&1,&(2+4),%d0
+ bfexts %a0@,&1+2,&2,%d0
+ bfexts %a0@,&(1+2),&(2+4),%d0
+ bfset (%a0){&1:&2}
+ bfset (%a0){&1:&(2+4)}
+ bfset (%a0){&(1+2):&2}
+ bfset (%a0){&(1+2):&(2+4)}
+ bfset %a0@,&1,&2
+ bfset %a0@,&1,&(2+4)
+ bfset %a0@,&1+2,&2
+ bfset %a0@,&(1+2),&(2+4)
+ bfexts (%a0){%d1:%d2},%d0
+ bfexts %a0@,%d1,%d2,%d0
+ bfset (%a0){%d1:%d2}
+ bfset %a0@,%d1,%d2
diff --git a/gas/testsuite/gas/m68k/cas.d b/gas/testsuite/gas/m68k/cas.d
new file mode 100644
index 0000000000..6309733d14
--- /dev/null
+++ b/gas/testsuite/gas/m68k/cas.d
@@ -0,0 +1,20 @@
+#objdump: -d --prefix-addresses
+#name: cas
+
+# Test parsing of the operands of the cas instruction
+
+.*: +file format .*
+
+Disassembly of section .text:
+0+000 <foo> casw %d0,%d1,%a0@
+0+004 <foo\+(0x|)4> casw %d0,%d1,%a0@
+0+008 <foo\+(0x|)8> cas2w %d0,%d2,%d3,%d4,%a0@,%a1@
+0+00e <foo\+(0x|)e> cas2w %d0,%d2,%d3,%d4,@\(%d0\),@\(%d1\)
+0+014 <foo\+(0x|)14> cas2w %d0,%d2,%d3,%d4,%a0@,%a1@
+0+01a <foo\+(0x|)1a> cas2w %d0,%d2,%d3,%d4,%a0@,%a1@
+0+020 <foo\+(0x|)20> cas2w %d0,%d2,%d3,%d4,@\(%d0\),@\(%d1\)
+0+026 <foo\+(0x|)26> cas2w %d0,%d2,%d3,%d4,%a0@,%a1@
+0+02c <foo\+(0x|)2c> cas2w %d0,%d2,%d3,%d4,@\(%d0\),@\(%d1\)
+0+032 <foo\+(0x|)32> cas2w %d0,%d2,%d3,%d4,%a0@,%a1@
+0+038 <foo\+(0x|)38> cas2w %d0,%d2,%d3,%d4,%a0@,%a1@
+0+03e <foo\+(0x|)3e> cas2w %d0,%d2,%d3,%d4,@\(%d0\),@\(%d1\)
diff --git a/gas/testsuite/gas/m68k/cas.s b/gas/testsuite/gas/m68k/cas.s
new file mode 100644
index 0000000000..f64e7f54c3
--- /dev/null
+++ b/gas/testsuite/gas/m68k/cas.s
@@ -0,0 +1,16 @@
+# Test parsing of the operands of the cas instruction
+ .text
+ .globl foo
+foo:
+ cas %d0,%d1,(%a0)
+ cas %d0,%d1,%a0@
+ cas2 %d0:%d2,%d3:%d4,(%a0):(%a1)
+ cas2 %d0:%d2,%d3:%d4,(%d0):(%d1)
+ cas2 %d0:%d2,%d3:%d4,%a0@:%a1@
+ cas2 %d0:%d2,%d3:%d4,@(%a0):@(%a1)
+ cas2 %d0:%d2,%d3:%d4,@(%d0):@(%d1)
+ cas2 %d0,%d2,%d3,%d4,(%a0),(%a1)
+ cas2 %d0,%d2,%d3,%d4,(%d0),(%d1)
+ cas2 %d0,%d2,%d3,%d4,%a0@,%a1@
+ cas2 %d0,%d2,%d3,%d4,@(%a0),@(%a1)
+ cas2 %d0,%d2,%d3,%d4,@(%d0),@(%d1)
diff --git a/gas/testsuite/gas/m68k/disperr.s b/gas/testsuite/gas/m68k/disperr.s
new file mode 100644
index 0000000000..fcd3b7b2ee
--- /dev/null
+++ b/gas/testsuite/gas/m68k/disperr.s
@@ -0,0 +1,16 @@
+#NO_APP
+gcc2_compiled.:
+___gnu_compiled_c:
+.text
+ .even
+.globl _foo
+_foo:
+ link %a6,#-12
+ fmovex %a6@(-12),%fp0
+ fmovex %fp0,%sp@-
+ jbsr _bar
+ addqw #8,%sp
+ addqw #4,%sp
+L1:
+ unlk %a6
+ rts
diff --git a/gas/testsuite/gas/m68k/fmoveml.d b/gas/testsuite/gas/m68k/fmoveml.d
new file mode 100644
index 0000000000..e4e2793afd
--- /dev/null
+++ b/gas/testsuite/gas/m68k/fmoveml.d
@@ -0,0 +1,60 @@
+#objdump: -d --prefix-addresses
+#name: fmoveml
+
+# Test handling of fmoveml and fmovemx instructions.
+
+.*: +file format .*
+
+Disassembly of section .text:
+0+000 <foo> fmovel %fpcr,%a0@
+0+004 <foo\+(0x|)4> fmovel %fpsr,%a0@
+0+008 <foo\+(0x|)8> fmovel %fpiar,%a0@
+0+00c <foo\+(0x|)c> fmoveml %fpsr/%fpcr,%a0@
+0+010 <foo\+(0x|)10> fmoveml %fpiar/%fpcr,%a0@
+0+014 <foo\+(0x|)14> fmoveml %fpiar/%fpsr,%a0@
+0+018 <foo\+(0x|)18> fmoveml %fpiar/%fpsr/%fpcr,%a0@
+0+01c <foo\+(0x|)1c> fmovel %fpcr,%d0
+0+020 <foo\+(0x|)20> fmovel %fpsr,%d0
+0+024 <foo\+(0x|)24> fmovel %fpiar,%d0
+0+028 <foo\+(0x|)28> fmovel %fpiar,%a0
+0+02c <foo\+(0x|)2c> fmovel %a0@,%fpcr
+0+030 <foo\+(0x|)30> fmovel %a0@,%fpsr
+0+034 <foo\+(0x|)34> fmovel %a0@,%fpiar
+0+038 <foo\+(0x|)38> fmoveml %a0@,%fpsr/%fpcr
+0+03c <foo\+(0x|)3c> fmoveml %a0@,%fpiar/%fpcr
+0+040 <foo\+(0x|)40> fmoveml %a0@,%fpiar/%fpsr
+0+044 <foo\+(0x|)44> fmoveml %a0@,%fpiar/%fpsr/%fpcr
+0+048 <foo\+(0x|)48> fmovel %d0,%fpcr
+0+04c <foo\+(0x|)4c> fmovel %d0,%fpsr
+0+050 <foo\+(0x|)50> fmovel %d0,%fpiar
+0+054 <foo\+(0x|)54> fmovel %a0,%fpiar
+0+058 <foo\+(0x|)58> fmovel #1,%fpcr
+0+060 <foo\+(0x|)60> fmovel #1,%fpsr
+0+068 <foo\+(0x|)68> fmovel #1,%fpiar
+0+070 <foo\+(0x|)70> fmoveml #1,%fpsr/%fpcr
+0+078 <foo\+(0x|)78> fmoveml #1,%fpiar/%fpcr
+0+080 <foo\+(0x|)80> fmoveml #1,%fpiar/%fpsr
+0+088 <foo\+(0x|)88> fmoveml #1,%fpiar/%fpsr/%fpcr
+0+090 <foo\+(0x|)90> fmovemx %fp1,%a0@
+0+094 <foo\+(0x|)94> fmovemx %fp4,%a0@
+0+098 <foo\+(0x|)98> fmovemx %fp7,%a0@
+0+09c <foo\+(0x|)9c> fmovemx %fp1/%fp3,%a0@
+0+0a0 <foo\+(0x|)a0> fmovemx %fp1-%fp4,%a0@
+0+0a4 <foo\+(0x|)a4> fmovemx %fp0/%fp7,%a0@
+0+0a8 <foo\+(0x|)a8> fmovemx %fp0-%fp7,%a0@
+0+0ac <foo\+(0x|)ac> fmovemx %a0@,%fp0
+0+0b0 <foo\+(0x|)b0> fmovemx %a0@,%fp1
+0+0b4 <foo\+(0x|)b4> fmovemx %a0@,%fp7
+0+0b8 <foo\+(0x|)b8> fmovemx %a0@,%fp0/%fp3
+0+0bc <foo\+(0x|)bc> fmovemx %a0@,%fp0/%fp4
+0+0c0 <foo\+(0x|)c0> fmovemx %a0@,%fp2-%fp4
+0+0c4 <foo\+(0x|)c4> fmovemx %a0@,%fp1-%fp7
+0+0c8 <foo\+(0x|)c8> fmovemx %fp0,%a0@-
+0+0cc <foo\+(0x|)cc> fmovemx %fp0-%fp7,%a0@-
+0+0d0 <foo\+(0x|)d0> fmovemx %fp0/%fp4,%a0@-
+0+0d4 <foo\+(0x|)d4> fmovemx %a0@\+,%fp7
+0+0d8 <foo\+(0x|)d8> fmovemx %a0@\+,%fp0-%fp7
+0+0dc <foo\+(0x|)dc> fmovemx %a0@\+,%fp3/%fp7
+0+0e0 <foo\+(0x|)e0> fmovemx %d0,%a0@-
+0+0e4 <foo\+(0x|)e4> fmovemx %a0@\+,%d0
+0+0e8 <foo\+(0x|)e8> fmovemx %fp1/%fp5,%a0@-
diff --git a/gas/testsuite/gas/m68k/fmoveml.s b/gas/testsuite/gas/m68k/fmoveml.s
new file mode 100644
index 0000000000..e74224bafc
--- /dev/null
+++ b/gas/testsuite/gas/m68k/fmoveml.s
@@ -0,0 +1,58 @@
+# Test handling of the fmoveml and fmovemx instructions.
+ .text
+ .globl foo
+foo:
+ fmoveml %fpcr,%a0@
+ fmoveml %fpsr,%a0@
+ fmoveml %fpiar,%a0@
+ fmoveml %fpcr/%fpsr,%a0@
+ fmoveml %fpcr/%fpiar,%a0@
+ fmoveml %fpsr/%fpiar,%a0@
+ fmoveml %fpcr/%fpsr/%fpiar,%a0@
+ fmoveml %fpcr,%d0
+ fmoveml %fpsr,%d0
+ fmoveml %fpiar,%d0
+ fmoveml %fpiar,%a0
+ fmoveml %a0@,%fpcr
+ fmoveml %a0@,%fpsr
+ fmoveml %a0@,%fpiar
+ fmoveml %a0@,%fpsr/%fpcr
+ fmoveml %a0@,%fpiar/%fpcr
+ fmoveml %a0@,%fpiar/%fpsr
+ fmoveml %a0@,%fpsr/%fpiar/%fpcr
+ fmoveml %d0,%fpcr
+ fmoveml %d0,%fpsr
+ fmoveml %d0,%fpiar
+ fmoveml %a0,%fpiar
+ fmoveml &1,%fpcr
+ fmoveml &1,%fpsr
+ fmoveml &1,%fpiar
+ fmoveml &1,%fpcr/%fpsr
+ fmoveml &1,%fpcr/%fpiar
+ fmoveml &1,%fpsr/%fpiar
+ fmoveml &1,%fpiar/%fpsr/%fpcr
+
+ fmovemx %fp1,%a0@
+ fmovemx %fp4,%a0@
+ fmovemx %fp7,%a0@
+ fmovemx %fp1/%fp3,%a0@
+ fmovemx %fp1-%fp4,%a0@
+ fmovemx %fp0/%fp7,%a0@
+ fmovemx %fp0-%fp7,%a0@
+ fmovemx %a0@,%fp0
+ fmovemx %a0@,%fp1
+ fmovemx %a0@,%fp7
+ fmovemx %a0@,%fp0/%fp3
+ fmovemx %a0@,%fp0/%fp4
+ fmovemx %a0@,%fp2-%fp4
+ fmovemx %a0@,%fp1-%fp7
+ fmovemx &1,%a0@-
+ fmovemx &0xff,%a0@-
+ fmovemx &0x11,%a0@-
+ fmovemx %a0@+,&1
+ fmovemx %a0@+,&0xff
+ fmovemx %a0@+,&0x11
+ fmovemx %d0,%a0@-
+ fmovemx %a0@+,%d0
+ fmovemx &sym,%a0@-
+ sym = 0x22
diff --git a/gas/testsuite/gas/m68k/link.d b/gas/testsuite/gas/m68k/link.d
new file mode 100644
index 0000000000..005263fdbf
--- /dev/null
+++ b/gas/testsuite/gas/m68k/link.d
@@ -0,0 +1,17 @@
+#objdump: -d --prefix-addresses
+#name: link
+
+# Test handling of link instruction.
+
+.*: +file format .*
+
+Disassembly of section .text:
+0+000 <foo> linkw %fp,#0
+0+004 <foo\+(0x|)4> linkw %fp,#-4
+0+008 <foo\+(0x|)8> linkw %fp,#-32767
+0+00c <foo\+(0x|)c> linkw %fp,#-32768
+0+010 <foo\+(0x|)10> linkl %fp,#-32769
+0+016 <foo\+(0x|)16> linkw %fp,#32767
+0+01a <foo\+(0x|)1a> linkl %fp,#32768
+0+020 <foo\+(0x|)20> linkl %fp,#32769
+0+026 <foo\+(0x|)26> nop
diff --git a/gas/testsuite/gas/m68k/link.s b/gas/testsuite/gas/m68k/link.s
new file mode 100644
index 0000000000..1a321dd322
--- /dev/null
+++ b/gas/testsuite/gas/m68k/link.s
@@ -0,0 +1,13 @@
+# Test handling of link instruction.
+ .text
+ .globl foo
+foo:
+ link %a6,&0
+ link %a6,&-4
+ link %a6,&-0x7fff
+ link %a6,&-0x8000
+ link %a6,&-0x8001
+ link %a6,&0x7fff
+ link %a6,&0x8000
+ link %a6,&0x8001
+ nop
diff --git a/gas/testsuite/gas/m68k/op68000.d b/gas/testsuite/gas/m68k/op68000.d
new file mode 100644
index 0000000000..568d5a3a6c
--- /dev/null
+++ b/gas/testsuite/gas/m68k/op68000.d
@@ -0,0 +1,195 @@
+# This should match the stderr output of gas -m68000 on operands.s.
+# We don't bother to match the exact error message, but instead just
+# look for the statements which should fail.
+
+.*operands.s: Assembler messages:
+.*statement `tstl %a0' ignored
+.*statement `tstl %a0@\(8,%d0:w:2\)' ignored
+.*statement `tstl %a0@\(8,%d0:w:4\)' ignored
+.*statement `tstl %a0@\(8,%d0:w:8\)' ignored
+.*statement `tstl %a0@\(8,%d0:l:2\)' ignored
+.*statement `tstl %a0@\(8,%d0:l:4\)' ignored
+.*statement `tstl %a0@\(8,%d0:l:8\)' ignored
+.*statement `tstl %a0@\(%d0:w:2\)' ignored
+.*statement `tstl \(8,%a0,%d0\*2\)' ignored
+.*statement `tstl \(8,%a0,%d0\*4\)' ignored
+.*statement `tstl \(8,%a0,%d0\*8\)' ignored
+.*statement `tstl \(8,%a0,%d0.w\*2\)' ignored
+.*statement `tstl \(8,%a0,%d0.w\*4\)' ignored
+.*statement `tstl \(8,%a0,%d0.w\*8\)' ignored
+.*statement `tstl \(8,%a0,%d0.l\*2\)' ignored
+.*statement `tstl \(8,%a0,%d0.l\*4\)' ignored
+.*statement `tstl \(8,%a0,%d0.l\*8\)' ignored
+.*statement `tstl \(8,%a1.w\*2,%a0\)' ignored
+.*statement `tstl 8\(%a0,%d0.w\*2\)' ignored
+.*statement `tstl 8\(%d0.w\*2,%a0\)' ignored
+.*statement `tstl 8\(%a1.w\*2,%a0\)' ignored
+.*statement `tstl \(%a0,%d0.w\*2\)' ignored
+.*statement `tstl \(%d0.w\*2,%a0\)' ignored
+.*statement `tstl %a0@\(1000,%d0:w:2\)' ignored
+.*statement `tstl @\(1000,%d0:w:2\)' ignored
+.*statement `tstl @\(%d0:w:2\)' ignored
+.*statement `tstl @\(1000\)' ignored
+.*statement `tstl %a0@\(100000\)' ignored
+.*statement `tstl \(1000,%a0,%d0.w\*2\)' ignored
+.*statement `tstl \(1000,%d0,%a0\)' ignored
+.*statement `tstl \(1000,%a1.w\*2,%a0\)' ignored
+.*statement `tstl 1000\(%a0,%d0.w\*2\)' ignored
+.*statement `tstl 1000\(%d0,%a0\)' ignored
+.*statement `tstl \(1000,%d0.w\*2\)' ignored
+.*statement `tstl 1000\(%d0.w\*2\)' ignored
+.*statement `tstl \(%d0.w\*2\)' ignored
+.*statement `tstl \(100000,%a0\)' ignored
+.*statement `tstl 100000\(%a0\)' ignored
+.*statement `tstl %za1@\(1000,%d0:w:2\)' ignored
+.*statement `tstl %za1@\(100000\)' ignored
+.*statement `tstl \(1000,%za1,%d0.w\*2\)' ignored
+.*statement `tstl \(1000,%d0,%za1\)' ignored
+.*statement `tstl \(1000,%a1.w\*2,%za1\)' ignored
+.*statement `tstl 1000\(%za1,%d0.w\*2\)' ignored
+.*statement `tstl 1000\(%d0,%za1\)' ignored
+.*statement `tstl \(100000,%za1\)' ignored
+.*statement `tstl 100000\(%za1\)' ignored
+.*statement `tstl %a0@\(1000,%zd1:w:2\)' ignored
+.*statement `tstl @\(1000,%zd1:w:2\)' ignored
+.*statement `tstl @\(%zd1:w:2\)' ignored
+.*statement `tstl \(1000,%a0,%zd1.w\*2\)' ignored
+.*statement `tstl \(1000,%zd1,%a0\)' ignored
+.*statement `tstl \(1000,%za1.w\*2,%a0\)' ignored
+.*statement `tstl 1000\(%a0,%zd1.w\*2\)' ignored
+.*statement `tstl 1000\(%zd1,%a0\)' ignored
+.*statement `tstl \(1000,%zd1.w\*2\)' ignored
+.*statement `tstl 1000\(%zd1.w\*2\)' ignored
+.*statement `tstl \(%zd1.w\*2\)' ignored
+.*statement `tstl %a0@\(1000\)@\(2000,%d0:w:2\)' ignored
+.*statement `tstl %a0@\(1000\)@\(%d0:w:2\)' ignored
+.*statement `tstl %a0@\(1000\)@\(2000\)' ignored
+.*statement `tstl @\(1000\)@\(2000,%d0:w:2\)' ignored
+.*statement `tstl @\(1000\)@\(%d0:w:2\)' ignored
+.*statement `tstl @\(1000\)@\(2000\)' ignored
+.*statement `tstl %a0@\(0\)@\(2000,%d0:w:2\)' ignored
+.*statement `tstl %a0@\(0\)@\(%d0:w:2\)' ignored
+.*statement `tstl %a0@\(0\)@\(2000\)' ignored
+.*statement `tstl @\(0\)@\(2000,%d0:w:2\)' ignored
+.*statement `tstl @\(0\)@\(%d0:w:2\)' ignored
+.*statement `tstl @\(0\)@\(2000\)' ignored
+.*statement `tstl \(\[1000,%a0\],%d0:w:2,2000\)' ignored
+.*statement `tstl \(\[1000,%a0\],%d0:w:2\)' ignored
+.*statement `tstl \(\[1000,%a0\],2000\)' ignored
+.*statement `tstl \(\[1000\],%d0:w:2,2000\)' ignored
+.*statement `tstl \(\[1000\],%d0:w:2\)' ignored
+.*statement `tstl \(\[1000\],2000\)' ignored
+.*statement `tstl \(\[%a0\],%d0:w:2,2000\)' ignored
+.*statement `tstl \(\[%a0\],%d0:w:2\)' ignored
+.*statement `tstl \(\[%a0\],2000\)' ignored
+.*statement `tstl \(\[0\],%d0:w:2,2000\)' ignored
+.*statement `tstl \(\[0\],%d0:w:2\)' ignored
+.*statement `tstl \(\[0\],2000\)' ignored
+.*statement `tstl %a0@\(1000,%d0:w:2\)@\(2000\)' ignored
+.*statement `tstl %a0@\(1000,%d0:w:2\)@\(0\)' ignored
+.*statement `tstl @\(1000,%d0:w:2\)@\(2000\)' ignored
+.*statement `tstl @\(1000,%d0:w:2\)@\(0\)' ignored
+.*statement `tstl %a0@\(%d0:w:2\)@\(2000\)' ignored
+.*statement `tstl %a0@\(%d0:w:2\)@\(0\)' ignored
+.*statement `tstl @\(%d0:w:2\)@\(2000\)' ignored
+.*statement `tstl @\(%d0:w:2\)@\(0\)' ignored
+.*statement `tstl \(\[1000,%a0,%d0:w:2\],2000\)' ignored
+.*statement `tstl \(\[1000,%d0:w:2,%a0\],2000\)' ignored
+.*statement `tstl \(\[1000,%d0,%a0\],2000\)' ignored
+.*statement `tstl \(\[1000,%a1,%a0\],2000\)' ignored
+.*statement `tstl \(\[1000,%a1:w:2,%a0\],2000\)' ignored
+.*statement `tstl \(\[1000,%a0,%d0:w:2\]\)' ignored
+.*statement `tstl \(\[1000,%d0,%a0\]\)' ignored
+.*statement `tstl \(\[1000,%d0:w:2\],2000\)' ignored
+.*statement `tstl \(\[1000,%d0:w:2\]\)' ignored
+.*statement `tstl \(\[%a0,%d0:w:2\],2000\)' ignored
+.*statement `tstl \(\[%d0,%a0\],2000\)' ignored
+.*statement `tstl \(\[%a0,%d0:w:2\]\)' ignored
+.*statement `tstl \(\[%d0,%a0\]\)' ignored
+.*statement `tstl \(\[%d0:w:2\],2000\)' ignored
+.*statement `tstl \(\[%d0:w:2\]\)' ignored
+.*statement `pea %pc@\(8,%d0:w:2\)' ignored
+.*statement `pea %pc@\(%d0:w:2\)' ignored
+.*statement `pea \(8,%pc,%d0.w\*2\)' ignored
+.*statement `pea 8\(%pc,%d0.w\*2\)' ignored
+.*statement `pea \(%pc,%d0.w\*2\)' ignored
+.*statement `pea %pc@\(1000,%d0:w:2\)' ignored
+.*statement `pea %pc@\(100000\)' ignored
+.*statement `pea \(1000,%pc,%d0.w\*2\)' ignored
+.*statement `pea \(1000,%d0,%pc\)' ignored
+.*statement `pea \(1000,%a1.w\*2,%pc\)' ignored
+.*statement `pea \(1000,%a1,%pc\)' ignored
+.*statement `pea 1000\(%pc,%d0.w\*2\)' ignored
+.*statement `pea 1000\(%d0,%pc\)' ignored
+.*statement `pea 1000\(%a1,%pc\)' ignored
+.*statement `pea \(100000,%pc\)' ignored
+.*statement `pea 100000\(%pc\)' ignored
+.*statement `pea %zpc@\(1000,%d0:w:2\)' ignored
+.*statement `pea %zpc@\(100000\)' ignored
+.*statement `pea \(1000,%zpc,%d0.w\*2\)' ignored
+.*statement `pea \(1000,%d0,%zpc\)' ignored
+.*statement `pea \(1000,%a1.w\*2,%zpc\)' ignored
+.*statement `pea \(1000,%a1,%zpc\)' ignored
+.*statement `pea 1000\(%zpc,%d0.w\*2\)' ignored
+.*statement `pea 1000\(%d0,%zpc\)' ignored
+.*statement `pea 1000\(%a1,%zpc\)' ignored
+.*statement `pea \(100000,%zpc\)' ignored
+.*statement `pea 100000\(%zpc\)' ignored
+.*statement `pea %pc@\(1000\)@\(2000,%d0:w:2\)' ignored
+.*statement `pea %pc@\(1000\)@\(%d0:w:2\)' ignored
+.*statement `pea %pc@\(1000\)@\(2000\)' ignored
+.*statement `pea %pc@\(0\)@\(2000,%d0:w:2\)' ignored
+.*statement `pea %pc@\(0\)@\(%d0:w:2\)' ignored
+.*statement `pea %pc@\(0\)@\(2000\)' ignored
+.*statement `pea \(\[1000,%pc\],%d0:w:2,2000\)' ignored
+.*statement `pea \(\[1000,%pc\],%d0:w:2\)' ignored
+.*statement `pea \(\[1000,%pc\],2000\)' ignored
+.*statement `pea \(\[%pc\],%d0:w:2,2000\)' ignored
+.*statement `pea \(\[%pc\],%d0:w:2\)' ignored
+.*statement `pea \(\[%pc\],2000\)' ignored
+.*statement `pea %zpc@\(1000\)@\(2000,%d0:w:2\)' ignored
+.*statement `pea %zpc@\(1000\)@\(%d0:w:2\)' ignored
+.*statement `pea %zpc@\(1000\)@\(2000\)' ignored
+.*statement `pea %zpc@\(0\)@\(2000,%d0:w:2\)' ignored
+.*statement `pea %zpc@\(0\)@\(%d0:w:2\)' ignored
+.*statement `pea %zpc@\(0\)@\(2000\)' ignored
+.*statement `pea \(\[1000,%zpc\],%d0:w:2,2000\)' ignored
+.*statement `pea \(\[1000,%zpc\],%d0:w:2\)' ignored
+.*statement `pea \(\[1000,%zpc\],2000\)' ignored
+.*statement `pea \(\[%zpc\],%d0:w:2,2000\)' ignored
+.*statement `pea \(\[%zpc\],%d0:w:2\)' ignored
+.*statement `pea \(\[%zpc\],2000\)' ignored
+.*statement `pea %pc@\(1000,%d0:w:2\)@\(2000\)' ignored
+.*statement `pea %pc@\(1000,%d0:w:2\)@\(0\)' ignored
+.*statement `pea %pc@\(%d0:w:2\)@\(2000\)' ignored
+.*statement `pea %pc@\(%d0:w:2\)@\(0\)' ignored
+.*statement `pea \(\[1000,%pc,%d0:w:2\],2000\)' ignored
+.*statement `pea \(\[1000,%d0:w:2,%pc\],2000\)' ignored
+.*statement `pea \(\[1000,%d0,%pc\],2000\)' ignored
+.*statement `pea \(\[1000,%a1,%pc\],2000\)' ignored
+.*statement `pea \(\[1000,%pc,%a1\],2000\)' ignored
+.*statement `pea \(\[1000,%a1:w:2,%pc\],2000\)' ignored
+.*statement `pea \(\[1000,%pc,%d0:w:2\]\)' ignored
+.*statement `pea \(\[1000,%d0,%pc\]\)' ignored
+.*statement `pea \(\[1000,%a1,%pc\]\)' ignored
+.*statement `pea \(\[%pc,%d0:w:2\],2000\)' ignored
+.*statement `pea \(\[%pc,%a0\],2000\)' ignored
+.*statement `pea \(\[%pc,%d0:w:2\]\)' ignored
+.*statement `pea \(\[%d0,%pc\]\)' ignored
+.*statement `pea %zpc@\(1000,%d0:w:2\)@\(2000\)' ignored
+.*statement `pea %zpc@\(1000,%d0:w:2\)@\(0\)' ignored
+.*statement `pea %zpc@\(%d0:w:2\)@\(2000\)' ignored
+.*statement `pea %zpc@\(%d0:w:2\)@\(0\)' ignored
+.*statement `pea \(\[1000,%zpc,%d0:w:2\],2000\)' ignored
+.*statement `pea \(\[1000,%d0:w:2,%zpc\],2000\)' ignored
+.*statement `pea \(\[1000,%d0,%zpc\],2000\)' ignored
+.*statement `pea \(\[1000,%a1,%zpc\],2000\)' ignored
+.*statement `pea \(\[1000,%zpc,%a1\],2000\)' ignored
+.*statement `pea \(\[1000,%a1:w:2,%zpc\],2000\)' ignored
+.*statement `pea \(\[1000,%zpc,%d0:w:2\]\)' ignored
+.*statement `pea \(\[1000,%d0,%zpc\]\)' ignored
+.*statement `pea \(\[1000,%a1,%zpc\]\)' ignored
+.*statement `pea \(\[%zpc,%d0:w:2\],2000\)' ignored
+.*statement `pea \(\[%zpc,%a0\],2000\)' ignored
+.*statement `pea \(\[%zpc,%d0:w:2\]\)' ignored
+.*statement `pea \(\[%d0,%zpc\]\)' ignored
diff --git a/gas/testsuite/gas/m68k/operands.d b/gas/testsuite/gas/m68k/operands.d
new file mode 100644
index 0000000000..5b383c3f97
--- /dev/null
+++ b/gas/testsuite/gas/m68k/operands.d
@@ -0,0 +1,242 @@
+#objdump: -d --prefix-addresses
+#name: operands
+
+# Test handling of MIT and Motorola syntax operands
+# If you change this file, see also op68000.d.
+
+.*: +file format .*
+
+Disassembly of section .text:
+0+000 <foo> tstl %d0
+0+002 <foo\+(0x|)2> tstl %a0
+0+004 <foo\+(0x|)4> tstl %a0@
+0+006 <foo\+(0x|)6> tstl %a0@
+0+008 <foo\+(0x|)8> tstl %a0@\+
+0+00a <foo\+(0x|)a> tstl %a0@\+
+0+00c <foo\+(0x|)c> tstl %a0@-
+0+00e <foo\+(0x|)e> tstl %a0@-
+0+010 <foo\+(0x|)10> tstl %a0@\(8\)
+0+014 <foo\+(0x|)14> tstl %a0@\(8\)
+0+018 <foo\+(0x|)18> tstl %a0@\(8\)
+0+01c <foo\+(0x|)1c> tstl %a0@\(0+008,%d0:l\)
+0+020 <foo\+(0x|)20> tstl %a0@\(0+008,%d0:w\)
+0+024 <foo\+(0x|)24> tstl %a0@\(0+008,%d0:w\)
+0+028 <foo\+(0x|)28> tstl %a0@\(0+008,%d0:w:2\)
+0+02c <foo\+(0x|)2c> tstl %a0@\(0+008,%d0:w:4\)
+0+030 <foo\+(0x|)30> tstl %a0@\(0+008,%d0:w:8\)
+0+034 <foo\+(0x|)34> tstl %a0@\(0+008,%d0:l\)
+0+038 <foo\+(0x|)38> tstl %a0@\(0+008,%d0:l\)
+0+03c <foo\+(0x|)3c> tstl %a0@\(0+008,%d0:l:2\)
+0+040 <foo\+(0x|)40> tstl %a0@\(0+008,%d0:l:4\)
+0+044 <foo\+(0x|)44> tstl %a0@\(0+008,%d0:l:8\)
+0+048 <foo\+(0x|)48> tstl %a0@\(0+000,%d0:w:2\)
+0+04c <foo\+(0x|)4c> tstl %a0@\(0+008,%d0:l\)
+0+050 <foo\+(0x|)50> tstl %a0@\(0+008,%d0:l\)
+0+054 <foo\+(0x|)54> tstl %a0@\(0+008,%d0:l:2\)
+0+058 <foo\+(0x|)58> tstl %a0@\(0+008,%d0:l:4\)
+0+05c <foo\+(0x|)5c> tstl %a0@\(0+008,%d0:l:8\)
+0+060 <foo\+(0x|)60> tstl %a0@\(0+008,%d0:w\)
+0+064 <foo\+(0x|)64> tstl %a0@\(0+008,%d0:w\)
+0+068 <foo\+(0x|)68> tstl %a0@\(0+008,%d0:w:2\)
+0+06c <foo\+(0x|)6c> tstl %a0@\(0+008,%d0:w:4\)
+0+070 <foo\+(0x|)70> tstl %a0@\(0+008,%d0:w:8\)
+0+074 <foo\+(0x|)74> tstl %a0@\(0+008,%d0:l\)
+0+078 <foo\+(0x|)78> tstl %a0@\(0+008,%d0:l\)
+0+07c <foo\+(0x|)7c> tstl %a0@\(0+008,%d0:l:2\)
+0+080 <foo\+(0x|)80> tstl %a0@\(0+008,%d0:l:4\)
+0+084 <foo\+(0x|)84> tstl %a0@\(0+008,%d0:l:8\)
+0+088 <foo\+(0x|)88> tstl %a0@\(0+008,%d0:l\)
+0+08c <foo\+(0x|)8c> tstl %a0@\(0+008,%a1:w:2\)
+0+090 <foo\+(0x|)90> tstl %a1@\(0+008,%a0:l\)
+0+094 <foo\+(0x|)94> tstl %a0@\(0+008,%d0:w:2\)
+0+098 <foo\+(0x|)98> tstl %a0@\(0+008,%d0:w:2\)
+0+09c <foo\+(0x|)9c> tstl %a0@\(0+008,%a1:w:2\)
+0+0a0 <foo\+(0x|)a0> tstl %a0@\(0+000,%d0:w:2\)
+0+0a4 <foo\+(0x|)a4> tstl %a0@\(0+000,%d0:w:2\)
+0+0a8 <foo\+(0x|)a8> tstl %a0@\(0+3e8,%d0:w:2\)
+0+0ae <foo\+(0x|)ae> tstl @\(0+3e8,%d0:w:2\)
+0+0b4 <foo\+(0x|)b4> tstl @\(0+000,%d0:w:2\)
+0+0b8 <foo\+(0x|)b8> tstl @\(0+3e8\)
+0+0be <foo\+(0x|)be> tstl %a0@\(0+186a0\)
+0+0c6 <foo\+(0x|)c6> tstl %a0@\(0+3e8,%d0:w:2\)
+0+0cc <foo\+(0x|)cc> tstl %a0@\(0+3e8,%d0:l\)
+0+0d2 <foo\+(0x|)d2> tstl %a0@\(0+3e8,%a1:w:2\)
+0+0d8 <foo\+(0x|)d8> tstl %a0@\(0+3e8,%d0:w:2\)
+0+0de <foo\+(0x|)de> tstl %a0@\(0+3e8,%d0:l\)
+0+0e4 <foo\+(0x|)e4> tstl @\(0+3e8,%d0:w:2\)
+0+0ea <foo\+(0x|)ea> tstl @\(0+3e8,%d0:w:2\)
+0+0f0 <foo\+(0x|)f0> tstl @\(0+000,%d0:w:2\)
+0+0f4 <foo\+(0x|)f4> tstl %a0@\(0+186a0\)
+0+0fc <foo\+(0x|)fc> tstl %a0@\(0+186a0\)
+0+104 <foo\+(0x|)104> tstl @\(0+3e8,%d0:w:2\)
+0+10a <foo\+(0x|)10a> tstl @\(0+186a0\)
+0+112 <foo\+(0x|)112> tstl @\(0+3e8,%d0:w:2\)
+0+118 <foo\+(0x|)118> tstl @\(0+3e8,%d0:l\)
+0+11e <foo\+(0x|)11e> tstl @\(0+3e8,%a1:w:2\)
+0+124 <foo\+(0x|)124> tstl @\(0+3e8,%d0:w:2\)
+0+12a <foo\+(0x|)12a> tstl @\(0+3e8,%d0:l\)
+0+130 <foo\+(0x|)130> tstl @\(0+186a0\)
+0+138 <foo\+(0x|)138> tstl @\(0+186a0\)
+0+140 <foo\+(0x|)140> tstl %a0@\(0+3e8\)
+0+146 <foo\+(0x|)146> tstl @\(0+3e8\)
+0+14c <foo\+(0x|)14c> tstl @\(0+000\)
+0+150 <foo\+(0x|)150> tstl %a0@\(0+3e8\)
+0+156 <foo\+(0x|)156> tstl %a0@\(0+3e8\)
+0+15c <foo\+(0x|)15c> tstl %a0@\(0+3e8\)
+0+162 <foo\+(0x|)162> tstl %a0@\(0+3e8\)
+0+168 <foo\+(0x|)168> tstl %a0@\(0+3e8\)
+0+16e <foo\+(0x|)16e> tstl @\(0+3e8\)
+0+174 <foo\+(0x|)174> tstl @\(0+3e8\)
+0+17a <foo\+(0x|)17a> tstl @\(0+000\)
+0+17e <foo\+(0x|)17e> tstl %a0@\(0+3e8\)@\(0+7d0,%d0:w:2\)
+0+186 <foo\+(0x|)186> tstl %a0@\(0+3e8\)@\(0+000,%d0:w:2\)
+0+18c <foo\+(0x|)18c> tstl %a0@\(0+3e8\)@\(0+7d0\)
+0+194 <foo\+(0x|)194> tstl @\(0+3e8\)@\(0+7d0,%d0:w:2\)
+0+19c <foo\+(0x|)19c> tstl @\(0+3e8\)@\(0+000,%d0:w:2\)
+0+1a2 <foo\+(0x|)1a2> tstl @\(0+3e8\)@\(0+7d0\)
+0+1aa <foo\+(0x|)1aa> tstl %a0@\(0+000\)@\(0+7d0,%d0:w:2\)
+0+1b0 <foo\+(0x|)1b0> tstl %a0@\(0+000\)@\(0+000,%d0:w:2\)
+0+1b4 <foo\+(0x|)1b4> tstl %a0@\(0+000\)@\(0+7d0\)
+0+1ba <foo\+(0x|)1ba> tstl @\(0+000\)@\(0+7d0,%d0:w:2\)
+0+1c0 <foo\+(0x|)1c0> tstl @\(0+000\)@\(0+000,%d0:w:2\)
+0+1c4 <foo\+(0x|)1c4> tstl @\(0+000\)@\(0+7d0\)
+0+1ca <foo\+(0x|)1ca> tstl %a0@\(0+3e8\)@\(0+7d0,%d0:w:2\)
+0+1d2 <foo\+(0x|)1d2> tstl %a0@\(0+3e8\)@\(0+000,%d0:w:2\)
+0+1d8 <foo\+(0x|)1d8> tstl %a0@\(0+3e8\)@\(0+7d0\)
+0+1e0 <foo\+(0x|)1e0> tstl @\(0+3e8\)@\(0+7d0,%d0:w:2\)
+0+1e8 <foo\+(0x|)1e8> tstl @\(0+3e8\)@\(0+000,%d0:w:2\)
+0+1ee <foo\+(0x|)1ee> tstl @\(0+3e8\)@\(0+7d0\)
+0+1f6 <foo\+(0x|)1f6> tstl %a0@\(0+000\)@\(0+7d0,%d0:w:2\)
+0+1fc <foo\+(0x|)1fc> tstl %a0@\(0+000\)@\(0+000,%d0:w:2\)
+0+200 <foo\+(0x|)200> tstl %a0@\(0+000\)@\(0+7d0\)
+0+206 <foo\+(0x|)206> tstl @\(0+000\)@\(0+7d0,%d0:w:2\)
+0+20c <foo\+(0x|)20c> tstl @\(0+000\)@\(0+000,%d0:w:2\)
+0+210 <foo\+(0x|)210> tstl @\(0+000\)@\(0+7d0\)
+0+216 <foo\+(0x|)216> tstl %a0@\(0+3e8,%d0:w:2\)@\(0+7d0\)
+0+21e <foo\+(0x|)21e> tstl %a0@\(0+3e8,%d0:w:2\)@\(0+000\)
+0+224 <foo\+(0x|)224> tstl @\(0+3e8,%d0:w:2\)@\(0+7d0\)
+0+22c <foo\+(0x|)22c> tstl @\(0+3e8,%d0:w:2\)@\(0+000\)
+0+232 <foo\+(0x|)232> tstl %a0@\(0+000,%d0:w:2\)@\(0+7d0\)
+0+238 <foo\+(0x|)238> tstl %a0@\(0+000,%d0:w:2\)@\(0+000\)
+0+23c <foo\+(0x|)23c> tstl @\(0+000,%d0:w:2\)@\(0+7d0\)
+0+242 <foo\+(0x|)242> tstl @\(0+000,%d0:w:2\)@\(0+000\)
+0+246 <foo\+(0x|)246> tstl %a0@\(0+3e8,%d0:w:2\)@\(0+7d0\)
+0+24e <foo\+(0x|)24e> tstl %a0@\(0+3e8,%d0:w:2\)@\(0+7d0\)
+0+256 <foo\+(0x|)256> tstl %a0@\(0+3e8,%d0:l\)@\(0+7d0\)
+0+25e <foo\+(0x|)25e> tstl %a1@\(0+3e8,%a0:l\)@\(0+7d0\)
+0+266 <foo\+(0x|)266> tstl %a0@\(0+3e8,%a1:w:2\)@\(0+7d0\)
+0+26e <foo\+(0x|)26e> tstl %a0@\(0+3e8,%d0:w:2\)@\(0+000\)
+0+274 <foo\+(0x|)274> tstl %a0@\(0+3e8,%d0:l\)@\(0+000\)
+0+27a <foo\+(0x|)27a> tstl @\(0+3e8,%d0:w:2\)@\(0+7d0\)
+0+282 <foo\+(0x|)282> tstl @\(0+3e8,%d0:w:2\)@\(0+000\)
+0+288 <foo\+(0x|)288> tstl %a0@\(0+000,%d0:w:2\)@\(0+7d0\)
+0+28e <foo\+(0x|)28e> tstl %a0@\(0+000,%d0:l\)@\(0+7d0\)
+0+294 <foo\+(0x|)294> tstl %a0@\(0+000,%d0:w:2\)@\(0+000\)
+0+298 <foo\+(0x|)298> tstl %a0@\(0+000,%d0:l\)@\(0+000\)
+0+29c <foo\+(0x|)29c> tstl @\(0+000,%d0:w:2\)@\(0+7d0\)
+0+2a2 <foo\+(0x|)2a2> tstl @\(0+000,%d0:w:2\)@\(0+000\)
+0+2a6 <foo\+(0x|)2a6> pea %pc@\(0+2b0 <foo\+(0x|)2b0>\)
+0+2aa <foo\+(0x|)2aa> pea %pc@\(0+2b4 <foo\+(0x|)2b4>\)
+0+2ae <foo\+(0x|)2ae> pea %pc@\(0+2b8 <foo\+(0x|)2b8>\)
+0+2b2 <foo\+(0x|)2b2> pea %pc@\(0+000 <foo>\)
+0+2b6 <foo\+(0x|)2b6> pea %pc@\(0+2c0 <foo\+(0x|)2c0>,%d0:w:2\)
+0+2ba <foo\+(0x|)2ba> pea %pc@\(0+2bc <foo\+(0x|)2bc>,%d0:w:2\)
+0+2be <foo\+(0x|)2be> pea %pc@\(0+2c8 <foo\+(0x|)2c8>,%d0:w:2\)
+0+2c2 <foo\+(0x|)2c2> pea %pc@\(0+2cc <foo\+(0x|)2cc>,%d0:l\)
+0+2c6 <foo\+(0x|)2c6> pea %pc@\(0+2d0 <foo\+(0x|)2d0>,%a0:l\)
+0+2ca <foo\+(0x|)2ca> pea %pc@\(0+2d4 <foo\+(0x|)2d4>,%d0:w:2\)
+0+2ce <foo\+(0x|)2ce> pea %pc@\(0+2d8 <foo\+(0x|)2d8>,%d0:l\)
+0+2d2 <foo\+(0x|)2d2> pea %pc@\(0+2dc <foo\+(0x|)2dc>,%a0:l\)
+0+2d6 <foo\+(0x|)2d6> pea %pc@\(0+2d8 <foo\+(0x|)2d8>,%d0:w:2\)
+0+2da <foo\+(0x|)2da> pea %pc@\(0+2dc <foo\+(0x|)2dc>,%d0:l\)
+0+2de <foo\+(0x|)2de> pea %pc@\(0+2e0 <foo\+(0x|)2e0>,%a0:l\)
+0+2e2 <foo\+(0x|)2e2> pea %pc@\(0+6cc <.*>,%d0:w:2\)
+0+2e8 <foo\+(0x|)2e8> pea %pc@\(0+1898a <.*>\)
+0+2f0 <foo\+(0x|)2f0> pea %pc@\(0+6da <.*>,%d0:w:2\)
+0+2f6 <foo\+(0x|)2f6> pea %pc@\(0+6e0 <.*>,%d0:l\)
+0+2fc <foo\+(0x|)2fc> pea %pc@\(0+6e6 <.*>,%a1:w:2\)
+0+302 <foo\+(0x|)302> pea %pc@\(0+6ec <.*>,%a1:l\)
+0+308 <foo\+(0x|)308> pea %pc@\(0+6f2 <.*>,%d0:w:2\)
+0+30e <foo\+(0x|)30e> pea %pc@\(0+6f8 <.*>,%d0:l\)
+0+314 <foo\+(0x|)314> pea %pc@\(0+6fe <.*>,%a1:l\)
+0+31a <foo\+(0x|)31a> pea %pc@\(0+189bc <.*>\)
+0+322 <foo\+(0x|)322> pea %pc@\(0+189c4 <.*>\)
+0+32a <foo\+(0x|)32a> pea %zpc@\(0+3e8,%d0:w:2\)
+0+330 <foo\+(0x|)330> pea %zpc@\(0+186a0\)
+0+338 <foo\+(0x|)338> pea %zpc@\(0+3e8,%d0:w:2\)
+0+33e <foo\+(0x|)33e> pea %zpc@\(0+3e8,%d0:l\)
+0+344 <foo\+(0x|)344> pea %zpc@\(0+3e8,%a1:w:2\)
+0+34a <foo\+(0x|)34a> pea %zpc@\(0+3e8,%a1:l\)
+0+350 <foo\+(0x|)350> pea %zpc@\(0+3e8,%d0:w:2\)
+0+356 <foo\+(0x|)356> pea %zpc@\(0+3e8,%d0:l\)
+0+35c <foo\+(0x|)35c> pea %zpc@\(0+3e8,%a1:l\)
+0+362 <foo\+(0x|)362> pea %zpc@\(0+186a0\)
+0+36a <foo\+(0x|)36a> pea %zpc@\(0+186a0\)
+0+372 <foo\+(0x|)372> pea %pc@\(0+75c <.*>\)@\(0+7d0,%d0:w:2\)
+0+37a <foo\+(0x|)37a> pea %pc@\(0+764 <.*>\)@\(0+000,%d0:w:2\)
+0+380 <foo\+(0x|)380> pea %pc@\(0+76a <.*>\)@\(0+7d0\)
+0+388 <foo\+(0x|)388> pea %pc@\(0+38a <foo\+(0x|)38a>\)@\(0+7d0,%d0:w:2\)
+0+38e <foo\+(0x|)38e> pea %pc@\(0+390 <foo\+(0x|)390>\)@\(0+000,%d0:w:2\)
+0+392 <foo\+(0x|)392> pea %pc@\(0+394 <foo\+(0x|)394>\)@\(0+7d0\)
+0+398 <foo\+(0x|)398> pea %pc@\(0+782 <.*>\)@\(0+7d0,%d0:w:2\)
+0+3a0 <foo\+(0x|)3a0> pea %pc@\(0+78a <.*>\)@\(0+000,%d0:w:2\)
+0+3a6 <foo\+(0x|)3a6> pea %pc@\(0+790 <.*>\)@\(0+7d0\)
+0+3ae <foo\+(0x|)3ae> pea %pc@\(0+3b0 <foo\+(0x|)3b0>\)@\(0+7d0,%d0:w:2\)
+0+3b4 <foo\+(0x|)3b4> pea %pc@\(0+3b6 <foo\+(0x|)3b6>\)@\(0+000,%d0:w:2\)
+0+3b8 <foo\+(0x|)3b8> pea %pc@\(0+3ba <foo\+(0x|)3ba>\)@\(0+7d0\)
+0+3be <foo\+(0x|)3be> pea %zpc@\(0+3e8\)@\(0+7d0,%d0:w:2\)
+0+3c6 <foo\+(0x|)3c6> pea %zpc@\(0+3e8\)@\(0+000,%d0:w:2\)
+0+3cc <foo\+(0x|)3cc> pea %zpc@\(0+3e8\)@\(0+7d0\)
+0+3d4 <foo\+(0x|)3d4> pea %zpc@\(0+000\)@\(0+7d0,%d0:w:2\)
+0+3da <foo\+(0x|)3da> pea %zpc@\(0+000\)@\(0+000,%d0:w:2\)
+0+3de <foo\+(0x|)3de> pea %zpc@\(0+000\)@\(0+7d0\)
+0+3e4 <foo\+(0x|)3e4> pea %zpc@\(0+3e8\)@\(0+7d0,%d0:w:2\)
+0+3ec <foo\+(0x|)3ec> pea %zpc@\(0+3e8\)@\(0+000,%d0:w:2\)
+0+3f2 <foo\+(0x|)3f2> pea %zpc@\(0+3e8\)@\(0+7d0\)
+0+3fa <foo\+(0x|)3fa> pea %zpc@\(0+000\)@\(0+7d0,%d0:w:2\)
+0+400 <foo\+(0x|)400> pea %zpc@\(0+000\)@\(0+000,%d0:w:2\)
+0+404 <foo\+(0x|)404> pea %zpc@\(0+000\)@\(0+7d0\)
+0+40a <foo\+(0x|)40a> pea %pc@\(0+7f4 <.*>,%d0:w:2\)@\(0+7d0\)
+0+412 <foo\+(0x|)412> pea %pc@\(0+7fc <.*>,%d0:w:2\)@\(0+000\)
+0+418 <foo\+(0x|)418> pea %pc@\(0+41a <foo\+(0x|)41a>,%d0:w:2\)@\(0+7d0\)
+0+41e <foo\+(0x|)41e> pea %pc@\(0+420 <foo\+(0x|)420>,%d0:w:2\)@\(0+000\)
+0+422 <foo\+(0x|)422> pea %pc@\(0+80c <.*>,%d0:w:2\)@\(0+7d0\)
+0+42a <foo\+(0x|)42a> pea %pc@\(0+814 <.*>,%d0:w:2\)@\(0+7d0\)
+0+432 <foo\+(0x|)432> pea %pc@\(0+81c <.*>,%d0:l\)@\(0+7d0\)
+0+43a <foo\+(0x|)43a> pea %pc@\(0+824 <.*>,%a1:l\)@\(0+7d0\)
+0+442 <foo\+(0x|)442> pea %pc@\(0+82c <.*>,%a1:l\)@\(0+7d0\)
+0+44a <foo\+(0x|)44a> pea %pc@\(0+834 <.*>,%a1:w:2\)@\(0+7d0\)
+0+452 <foo\+(0x|)452> pea %pc@\(0+83c <.*>,%d0:w:2\)@\(0+000\)
+0+458 <foo\+(0x|)458> pea %pc@\(0+842 <.*>,%d0:l\)@\(0+000\)
+0+45e <foo\+(0x|)45e> pea %pc@\(0+848 <.*>,%a1:l\)@\(0+000\)
+0+464 <foo\+(0x|)464> pea %pc@\(0+466 <foo\+(0x|)466>,%d0:w:2\)@\(0+7d0\)
+0+46a <foo\+(0x|)46a> pea %pc@\(0+46c <foo\+(0x|)46c>,%a0:l\)@\(0+7d0\)
+0+470 <foo\+(0x|)470> pea %pc@\(0+472 <foo\+(0x|)472>,%d0:w:2\)@\(0+000\)
+0+474 <foo\+(0x|)474> pea %pc@\(0+476 <foo\+(0x|)476>,%d0:l\)@\(0+000\)
+0+478 <foo\+(0x|)478> pea %zpc@\(0+3e8,%d0:w:2\)@\(0+7d0\)
+0+480 <foo\+(0x|)480> pea %zpc@\(0+3e8,%d0:w:2\)@\(0+000\)
+0+486 <foo\+(0x|)486> pea %zpc@\(0+000,%d0:w:2\)@\(0+7d0\)
+0+48c <foo\+(0x|)48c> pea %zpc@\(0+000,%d0:w:2\)@\(0+000\)
+0+490 <foo\+(0x|)490> pea %zpc@\(0+3e8,%d0:w:2\)@\(0+7d0\)
+0+498 <foo\+(0x|)498> pea %zpc@\(0+3e8,%d0:w:2\)@\(0+7d0\)
+0+4a0 <foo\+(0x|)4a0> pea %zpc@\(0+3e8,%d0:l\)@\(0+7d0\)
+0+4a8 <foo\+(0x|)4a8> pea %zpc@\(0+3e8,%a1:l\)@\(0+7d0\)
+0+4b0 <foo\+(0x|)4b0> pea %zpc@\(0+3e8,%a1:l\)@\(0+7d0\)
+0+4b8 <foo\+(0x|)4b8> pea %zpc@\(0+3e8,%a1:w:2\)@\(0+7d0\)
+0+4c0 <foo\+(0x|)4c0> pea %zpc@\(0+3e8,%d0:w:2\)@\(0+000\)
+0+4c6 <foo\+(0x|)4c6> pea %zpc@\(0+3e8,%d0:l\)@\(0+000\)
+0+4cc <foo\+(0x|)4cc> pea %zpc@\(0+3e8,%a1:l\)@\(0+000\)
+0+4d2 <foo\+(0x|)4d2> pea %zpc@\(0+000,%d0:w:2\)@\(0+7d0\)
+0+4d8 <foo\+(0x|)4d8> pea %zpc@\(0+000,%a0:l\)@\(0+7d0\)
+0+4de <foo\+(0x|)4de> pea %zpc@\(0+000,%d0:w:2\)@\(0+000\)
+0+4e2 <foo\+(0x|)4e2> pea %zpc@\(0+000,%d0:l\)@\(0+000\)
+0+4e6 <foo\+(0x|)4e6> tstl 0+004 <foo\+(0x|)4>
+0+4ea <foo\+(0x|)4ea> tstl 0+004 <foo\+(0x|)4>
+0+4ee <foo\+(0x|)4ee> tstl 0+004 <foo\+(0x|)4>
+0+4f2 <foo\+(0x|)4f2> tstl 0+186a0 <.*>
+0+4f8 <foo\+(0x|)4f8> tstl 0+008 <foo\+(0x|)8>
+0+4fe <foo\+(0x|)4fe> tstl 0+008 <foo\+(0x|)8>
+0+504 <foo\+(0x|)504> addib #1,%d0
+0+508 <foo\+(0x|)508> addiw #1,%d0
+0+50c <foo\+(0x|)50c> addil #1,%d0
+0+512 <foo\+(0x|)512> addqb #1,%d0
diff --git a/gas/testsuite/gas/m68k/operands.s b/gas/testsuite/gas/m68k/operands.s
new file mode 100644
index 0000000000..b09f56fee1
--- /dev/null
+++ b/gas/testsuite/gas/m68k/operands.s
@@ -0,0 +1,272 @@
+# Test handling of MIT and Motorola syntax operands
+# If you change this file, see also op68000.d.
+ .text
+foo:
+ | Data register direct
+ tstl %d0
+
+ | Address register direct
+ tstl %a0
+
+ | Address register indirect
+ tstl %a0@
+ tstl (%a0)
+
+ | Address register indirect with postincrement
+ tstl %a0@+
+ tstl (%a0)+
+
+ | Address register indirect with predecrement
+ tstl %a0@-
+ tstl -(%a0)
+
+ | Address register indirect with displacement
+ tstl %a0@(8)
+ tstl (8,%a0)
+ tstl 8(%a0)
+
+ | Address register indirect with index (8-bit displacement)
+ tstl %a0@(8,%d0)
+ tstl %a0@(8,%d0:w)
+ tstl %a0@(8,%d0:w:1)
+ tstl %a0@(8,%d0:w:2)
+ tstl %a0@(8,%d0:w:4)
+ tstl %a0@(8,%d0:w:8)
+ tstl %a0@(8,%d0:l)
+ tstl %a0@(8,%d0:l:1)
+ tstl %a0@(8,%d0:l:2)
+ tstl %a0@(8,%d0:l:4)
+ tstl %a0@(8,%d0:l:8)
+ tstl %a0@(%d0:w:2)
+ tstl (8,%a0,%d0)
+ tstl (8,%a0,%d0*1)
+ tstl (8,%a0,%d0*2)
+ tstl (8,%a0,%d0*4)
+ tstl (8,%a0,%d0*8)
+ tstl (8,%a0,%d0.w)
+ tstl (8,%a0,%d0.w*1)
+ tstl (8,%a0,%d0.w*2)
+ tstl (8,%a0,%d0.w*4)
+ tstl (8,%a0,%d0.w*8)
+ tstl (8,%a0,%d0.l)
+ tstl (8,%a0,%d0.l*1)
+ tstl (8,%a0,%d0.l*2)
+ tstl (8,%a0,%d0.l*4)
+ tstl (8,%a0,%d0.l*8)
+ tstl (8,%d0,%a0)
+ tstl (8,%a1.w*2,%a0)
+ tstl (8,%a1,%a0)
+ tstl 8(%a0,%d0.w*2)
+ tstl 8(%d0.w*2,%a0)
+ tstl 8(%a1.w*2,%a0)
+ tstl (%a0,%d0.w*2)
+ tstl (%d0.w*2,%a0)
+
+ | Address register indirect with index (base displacement)
+ tstl %a0@(1000,%d0:w:2)
+ tstl @(1000,%d0:w:2)
+ tstl @(%d0:w:2)
+ tstl @(1000)
+ tstl %a0@(100000)
+ tstl (1000,%a0,%d0.w*2)
+ tstl (1000,%d0,%a0)
+ tstl (1000,%a1.w*2,%a0)
+ tstl 1000(%a0,%d0.w*2)
+ tstl 1000(%d0,%a0)
+ tstl (1000,%d0.w*2)
+ tstl 1000(%d0.w*2)
+ tstl (%d0.w*2)
+ tstl (100000,%a0)
+ tstl 100000(%a0)
+ tstl %za1@(1000,%d0:w:2)
+ tstl %za1@(100000)
+ tstl (1000,%za1,%d0.w*2)
+ tstl (1000,%d0,%za1)
+ tstl (1000,%a1.w*2,%za1)
+ tstl 1000(%za1,%d0.w*2)
+ tstl 1000(%d0,%za1)
+ tstl (100000,%za1)
+ tstl 100000(%za1)
+ tstl %a0@(1000,%zd1:w:2)
+ tstl @(1000,%zd1:w:2)
+ tstl @(%zd1:w:2)
+ tstl (1000,%a0,%zd1.w*2)
+ tstl (1000,%zd1,%a0)
+ tstl (1000,%za1.w*2,%a0)
+ tstl 1000(%a0,%zd1.w*2)
+ tstl 1000(%zd1,%a0)
+ tstl (1000,%zd1.w*2)
+ tstl 1000(%zd1.w*2)
+ tstl (%zd1.w*2)
+
+ | Memory indirect postindexed
+ tstl %a0@(1000)@(2000,%d0:w:2)
+ tstl %a0@(1000)@(%d0:w:2)
+ tstl %a0@(1000)@(2000)
+ tstl @(1000)@(2000,%d0:w:2)
+ tstl @(1000)@(%d0:w:2)
+ tstl @(1000)@(2000)
+ tstl %a0@(0)@(2000,%d0:w:2)
+ tstl %a0@(0)@(%d0:w:2)
+ tstl %a0@(0)@(2000)
+ tstl @(0)@(2000,%d0:w:2)
+ tstl @(0)@(%d0:w:2)
+ tstl @(0)@(2000)
+ tstl ([1000,%a0],%d0:w:2,2000)
+ tstl ([1000,%a0],%d0:w:2)
+ tstl ([1000,%a0],2000)
+ tstl ([1000],%d0:w:2,2000)
+ tstl ([1000],%d0:w:2)
+ tstl ([1000],2000)
+ tstl ([%a0],%d0:w:2,2000)
+ tstl ([%a0],%d0:w:2)
+ tstl ([%a0],2000)
+ tstl ([0],%d0:w:2,2000)
+ tstl ([0],%d0:w:2)
+ tstl ([0],2000)
+
+ | Memory indirect preindexed
+ tstl %a0@(1000,%d0:w:2)@(2000)
+ tstl %a0@(1000,%d0:w:2)@(0)
+ tstl @(1000,%d0:w:2)@(2000)
+ tstl @(1000,%d0:w:2)@(0)
+ tstl %a0@(%d0:w:2)@(2000)
+ tstl %a0@(%d0:w:2)@(0)
+ tstl @(%d0:w:2)@(2000)
+ tstl @(%d0:w:2)@(0)
+ tstl ([1000,%a0,%d0:w:2],2000)
+ tstl ([1000,%d0:w:2,%a0],2000)
+ tstl ([1000,%d0,%a0],2000)
+ tstl ([1000,%a1,%a0],2000)
+ tstl ([1000,%a1:w:2,%a0],2000)
+ tstl ([1000,%a0,%d0:w:2])
+ tstl ([1000,%d0,%a0])
+ tstl ([1000,%d0:w:2],2000)
+ tstl ([1000,%d0:w:2])
+ tstl ([%a0,%d0:w:2],2000)
+ tstl ([%d0,%a0],2000)
+ tstl ([%a0,%d0:w:2])
+ tstl ([%d0,%a0])
+ tstl ([%d0:w:2],2000)
+ tstl ([%d0:w:2])
+
+ | Program counter indirect with displacement
+ pea %pc@(8)
+ pea (8,%pc)
+ pea 8(%pc)
+ pea foo
+
+ | Program counter indirect with index (8-bit displacement)
+ pea %pc@(8,%d0:w:2)
+ pea %pc@(%d0:w:2)
+ pea (8,%pc,%d0.w*2)
+ pea (8,%d0,%pc)
+ pea (8,%a0,%pc)
+ pea 8(%pc,%d0.w*2)
+ pea 8(%d0,%pc)
+ pea 8(%a0,%pc)
+ pea (%pc,%d0.w*2)
+ pea (%d0,%pc)
+ pea (%a0,%pc)
+
+ | Program counter indirect with index (base displacement)
+ pea %pc@(1000,%d0:w:2)
+ pea %pc@(100000)
+ pea (1000,%pc,%d0.w*2)
+ pea (1000,%d0,%pc)
+ pea (1000,%a1.w*2,%pc)
+ pea (1000,%a1,%pc)
+ pea 1000(%pc,%d0.w*2)
+ pea 1000(%d0,%pc)
+ pea 1000(%a1,%pc)
+ pea (100000,%pc)
+ pea 100000(%pc)
+ pea %zpc@(1000,%d0:w:2)
+ pea %zpc@(100000)
+ pea (1000,%zpc,%d0.w*2)
+ pea (1000,%d0,%zpc)
+ pea (1000,%a1.w*2,%zpc)
+ pea (1000,%a1,%zpc)
+ pea 1000(%zpc,%d0.w*2)
+ pea 1000(%d0,%zpc)
+ pea 1000(%a1,%zpc)
+ pea (100000,%zpc)
+ pea 100000(%zpc)
+
+ | Program counter memory indirect postindexed
+ pea %pc@(1000)@(2000,%d0:w:2)
+ pea %pc@(1000)@(%d0:w:2)
+ pea %pc@(1000)@(2000)
+ pea %pc@(0)@(2000,%d0:w:2)
+ pea %pc@(0)@(%d0:w:2)
+ pea %pc@(0)@(2000)
+ pea ([1000,%pc],%d0:w:2,2000)
+ pea ([1000,%pc],%d0:w:2)
+ pea ([1000,%pc],2000)
+ pea ([%pc],%d0:w:2,2000)
+ pea ([%pc],%d0:w:2)
+ pea ([%pc],2000)
+ pea %zpc@(1000)@(2000,%d0:w:2)
+ pea %zpc@(1000)@(%d0:w:2)
+ pea %zpc@(1000)@(2000)
+ pea %zpc@(0)@(2000,%d0:w:2)
+ pea %zpc@(0)@(%d0:w:2)
+ pea %zpc@(0)@(2000)
+ pea ([1000,%zpc],%d0:w:2,2000)
+ pea ([1000,%zpc],%d0:w:2)
+ pea ([1000,%zpc],2000)
+ pea ([%zpc],%d0:w:2,2000)
+ pea ([%zpc],%d0:w:2)
+ pea ([%zpc],2000)
+
+ | Program counter memory indirect preindexed
+ pea %pc@(1000,%d0:w:2)@(2000)
+ pea %pc@(1000,%d0:w:2)@(0)
+ pea %pc@(%d0:w:2)@(2000)
+ pea %pc@(%d0:w:2)@(0)
+ pea ([1000,%pc,%d0:w:2],2000)
+ pea ([1000,%d0:w:2,%pc],2000)
+ pea ([1000,%d0,%pc],2000)
+ pea ([1000,%a1,%pc],2000)
+ pea ([1000,%pc,%a1],2000)
+ pea ([1000,%a1:w:2,%pc],2000)
+ pea ([1000,%pc,%d0:w:2])
+ pea ([1000,%d0,%pc])
+ pea ([1000,%a1,%pc])
+ pea ([%pc,%d0:w:2],2000)
+ pea ([%pc,%a0],2000)
+ pea ([%pc,%d0:w:2])
+ pea ([%d0,%pc])
+ pea %zpc@(1000,%d0:w:2)@(2000)
+ pea %zpc@(1000,%d0:w:2)@(0)
+ pea %zpc@(%d0:w:2)@(2000)
+ pea %zpc@(%d0:w:2)@(0)
+ pea ([1000,%zpc,%d0:w:2],2000)
+ pea ([1000,%d0:w:2,%zpc],2000)
+ pea ([1000,%d0,%zpc],2000)
+ pea ([1000,%a1,%zpc],2000)
+ pea ([1000,%zpc,%a1],2000)
+ pea ([1000,%a1:w:2,%zpc],2000)
+ pea ([1000,%zpc,%d0:w:2])
+ pea ([1000,%d0,%zpc])
+ pea ([1000,%a1,%zpc])
+ pea ([%zpc,%d0:w:2],2000)
+ pea ([%zpc,%a0],2000)
+ pea ([%zpc,%d0:w:2])
+ pea ([%d0,%zpc])
+
+ | Absolute short
+ tstl 4
+ tstl 4.w
+ tstl (4).w
+
+ | Absolute long
+ tstl 100000
+ tstl 8.l
+ tstl (8).l
+
+ | Immediate
+ addib &1,%d0
+ addiw &1,%d0
+ addil &1,%d0
+ addqb &1,%d0
diff --git a/gas/testsuite/gas/m68k/p2410.s b/gas/testsuite/gas/m68k/p2410.s
new file mode 100644
index 0000000000..4f0337a980
--- /dev/null
+++ b/gas/testsuite/gas/m68k/p2410.s
@@ -0,0 +1,15 @@
+.text
+start: nop
+ nop
+ nop
+ bras label1
+ bras label2
+.globl label1
+label1: nop
+ .space 0xa0
+ nop
+ nop
+.globl label2
+label2: bras label1
+ bras label2
+ nop
diff --git a/gas/testsuite/gas/m68k/p2663.s b/gas/testsuite/gas/m68k/p2663.s
new file mode 100644
index 0000000000..9f3650fb8a
--- /dev/null
+++ b/gas/testsuite/gas/m68k/p2663.s
@@ -0,0 +1,16 @@
+|
+| This code generates an incorrect pc relative offset
+|
+bug: movel #4,%d7
+ jsr table(%pc,%d7.w) | wrong
+ jsr %pc@(table-.-2:b,%d7:w) | correct but cryptic
+ nop
+ nop
+table:
+ bra junk
+ bra junk
+ bra junk
+
+junk:
+ nop
+ rts
diff --git a/gas/testsuite/gas/m68k/pcrel.d b/gas/testsuite/gas/m68k/pcrel.d
new file mode 100644
index 0000000000..b49835822b
--- /dev/null
+++ b/gas/testsuite/gas/m68k/pcrel.d
@@ -0,0 +1,88 @@
+#name: pcrel
+#objdump: -drs -j .text --prefix-addresses
+
+.*: file format .*
+
+Contents of section .text:
+ 0000 4e714e71 4cfa0300 fffa4cfa 0300fff4 NqNqL.....L.....
+ 0010 4cfb0300 08ee41fa ffea41fa ffe641fa L.....A...A...A.
+ 0020 ff6241fb 08de41fb 08da41fb 08d641fb .bA...A...A...A.
+ 0030 0920ffd2 41fb0920 ffcc41fb 0930ffff . ..A.. ..A..0..
+ 0040 ffc641fb 0930ffff ffbe4e71 61ff0000 ..A..0....Nqa...
+ 0050 00586100 0052614e 614c4e71 41f90000 .Xa..RaNaLNqA...
+ 0060 00(a6|00)41fa 004241fa 00be41fb 083a41fb ..A..BA...A..:A.
+ 0070 083641fb 083241fb 0920002e 41fb0920 .6A..2A.. ..A..
+ 0080 002841fb 09300000 002241fb 09300000 .\(A..0..."A..0..
+ 0090 001a41fb 09300000 001241fb 0920000a ..A..0....A.. ..
+ 00a0 41fb0804 4e714e71 4e7141fb 088041fb A...NqNqNqA...A.
+ 00b0 0920ff7f 41fb0920 800041fb 0930ffff . ..A.. ..A..0..
+ 00c0 7fff4e71 41fb087f 41fb0920 008041fb ..NqA...A.. ..A.
+ 00d0 09207fff 41fb0930 00008000 4e7141fa . ..A..0....NqA.
+ 00e0 800041fb 0170ffff 7fff4e71 41fa7fff ..A..p....NqA...
+ 00f0 41fb0170 00008000 4e7141fb 0170(ffff|0000) A..p....NqA..p..
+ 0100 (ff04|0000)41fb 0930(ffff|0000) (fefc|0000)4e71 41f90000 ..A..0....NqA...
+ 0110 0000............................... ................
+Disassembly of section \.text:
+0+0000 <.*> nop
+0+0002 <lbl_b> nop
+0+0004 <lbl_b\+(0x|)2> moveml %pc@\(0+0002 <lbl_b>\),%a0-%a1
+0+000a <lbl_b\+(0x|)8> moveml %pc@\(0+0002 <lbl_b>\),%a0-%a1
+0+0010 <lbl_b\+(0x|)e> moveml %pc@\(0+02 <lbl_b>,%d0:l\),%a0-%a1
+0+0016 <lbl_b\+(0x|)14> lea %pc@\(0+0002 <lbl_b>\),%a0
+0+001a <lbl_b\+(0x|)18> lea %pc@\(0+0002 <lbl_b>\),%a0
+0+001e <lbl_b\+(0x|)1c> lea %pc@\(f+ff82 <.*>\),%a0
+0+0022 <lbl_b\+(0x|)20> lea %pc@\(0+02 <lbl_b>,%d0:l\),%a0
+0+0026 <lbl_b\+(0x|)24> lea %pc@\(0+02 <lbl_b>,%d0:l\),%a0
+0+002a <lbl_b\+(0x|)28> lea %pc@\(0+02 <lbl_b>,%d0:l\),%a0
+0+002e <lbl_b\+(0x|)2c> lea %pc@\(0+02 <lbl_b>,%d0:l\),%a0
+0+0034 <lbl_b\+(0x|)32> lea %pc@\(0+02 <lbl_b>,%d0:l\),%a0
+0+003a <lbl_b\+(0x|)38> lea %pc@\(0+02 <lbl_b>,%d0:l\),%a0
+0+0042 <lbl_b\+(0x|)40> lea %pc@\(0+02 <lbl_b>,%d0:l\),%a0
+0+004a <lbl_b\+(0x|)48> nop
+0+004c <lbl_b\+(0x|)4a> bsrl 0+00a6 <lbl_a>
+0+0052 <lbl_b\+(0x|)50> bsrw 0+00a6 <lbl_a>
+0+0056 <lbl_b\+(0x|)54> bsrs 0+00a6 <lbl_a>
+0+0058 <lbl_b\+(0x|)56> bsrs 0+00a6 <lbl_a>
+0+005a <lbl_b\+(0x|)58> nop
+0+005c <lbl_b\+(0x|)5a> lea (0+00a6 <lbl_a>|0+0 <.*>),%a0
+ 5e: (32 \.text|R_68K_32 \.text\+0xa6)
+0+0062 <lbl_b\+(0x|)60> lea %pc@\(0+00a6 <lbl_a>\),%a0
+0+0066 <lbl_b\+(0x|)64> lea %pc@\(0+0126 <.*>\),%a0
+0+006a <lbl_b\+(0x|)68> lea %pc@\(0+a6 <lbl_a>,%d0:l\),%a0
+0+006e <lbl_b\+(0x|)6c> lea %pc@\(0+a6 <lbl_a>,%d0:l\),%a0
+0+0072 <lbl_b\+(0x|)70> lea %pc@\(0+a6 <lbl_a>,%d0:l\),%a0
+0+0076 <lbl_b\+(0x|)74> lea %pc@\(0+a6 <lbl_a>,%d0:l\),%a0
+0+007c <lbl_b\+(0x|)7a> lea %pc@\(0+a6 <lbl_a>,%d0:l\),%a0
+0+0082 <lbl_b\+(0x|)80> lea %pc@\(0+a6 <lbl_a>,%d0:l\),%a0
+0+008a <lbl_b\+(0x|)88> lea %pc@\(0+a6 <lbl_a>,%d0:l\),%a0
+0+0092 <lbl_b\+(0x|)90> lea %pc@\(0+a6 <lbl_a>,%d0:l\),%a0
+0+009a <lbl_b\+(0x|)98> lea %pc@\(0+a6 <lbl_a>,%d0:l\),%a0
+0+00a0 <lbl_b\+(0x|)9e> lea %pc@\(0+a6 <lbl_a>,%d0:l\),%a0
+0+00a4 <lbl_b\+(0x|)a2> nop
+0+00a6 <lbl_a> nop
+0+00a8 <lbl_a\+(0x|)2> nop
+0+00aa <lbl_a\+(0x|)4> lea %pc@\(0+2c <lbl_b\+(0x|)2a>,%d0:l\),%a0
+0+00ae <lbl_a\+(0x|)8> lea %pc@\(0+2f <lbl_b\+(0x|)2d>,%d0:l\),%a0
+0+00b4 <lbl_a\+(0x|)e> lea %pc@\(f+80b6 <.*>,%d0:l\),%a0
+0+00ba <lbl_a\+(0x|)14> lea %pc@\(f+80bb <.*>,%d0:l\),%a0
+0+00c2 <lbl_a\+(0x|)1c> nop
+0+00c4 <lbl_a\+(0x|)1e> lea %pc@\(0+145 <.*>,%d0:l\),%a0
+0+00c8 <lbl_a\+(0x|)22> lea %pc@\(0+14a <.*>,%d0:l\),%a0
+0+00ce <lbl_a\+(0x|)28> lea %pc@\(0+80cf <.*>,%d0:l\),%a0
+0+00d4 <lbl_a\+(0x|)2e> lea %pc@\(0+80d6 <.*>,%d0:l\),%a0
+0+00dc <lbl_a\+(0x|)36> nop
+0+00de <lbl_a\+(0x|)38> lea %pc@\(f+80e0 <.*>\),%a0
+0+00e2 <lbl_a\+(0x|)3c> lea %pc@\(f+80e3 <.*>\),%a0
+0+00ea <lbl_a\+(0x|)44> nop
+0+00ec <lbl_a\+(0x|)46> lea %pc@\(0+80ed <.*>\),%a0
+0+00f0 <lbl_a\+(0x|)4a> lea %pc@\(0+80f2 <.*>\),%a0
+0+00f8 <lbl_a\+(0x|)52> nop
+0+00fa <lbl_a\+(0x|)54> lea %pc@\((0+0 <.*>|0+0fc <lbl_a\+(0x|)56>)\),%a0
+ fe: (DISP32 undef|R_68K_PC32 undef\+0x2)
+0+0102 <lbl_a\+(0x|)5c> lea %pc@\((0+0 <.*>|0+0104 <lbl_a\+(0x|)5e>),%d0:l\),%a0
+ 106: (DISP32 undef|R_68K_PC32 undef\+0x2)
+0+010a <lbl_a\+(0x|)64> nop
+0+010c <lbl_a\+(0x|)66> lea 0+0 <.*>,%a0
+ 10e: (R_68K_)?32 undef
+0+0112 <lbl_a\+(0x|)6c> nop
+0+0114 <lbl_a\+(0x|)6e> orib #0,%d0
diff --git a/gas/testsuite/gas/m68k/pcrel.s b/gas/testsuite/gas/m68k/pcrel.s
new file mode 100644
index 0000000000..9c5c22b90f
--- /dev/null
+++ b/gas/testsuite/gas/m68k/pcrel.s
@@ -0,0 +1,59 @@
+ nop
+lbl_b: nop
+ moveml lbl_b,%a0-%a1
+ moveml %pc@(lbl_b),%a0-%a1
+ moveml %pc@(lbl_b,%d0),%a0-%a1
+ lea lbl_b,%a0
+ lea %pc@(lbl_b),%a0
+ lea %pc@(lbl_b-128),%a0
+ lea %pc@(lbl_b,%d0),%a0
+ lea %pc@(lbl_b:b,%d0),%a0
+ lea %pc@(lbl_b-.-2:b,%d0),%a0
+ lea %pc@(lbl_b:w,%d0),%a0
+ lea %pc@(lbl_b-.-2:w,%d0),%a0
+ lea %pc@(lbl_b:l,%d0),%a0
+ lea %pc@(lbl_b-.-2:l,%d0),%a0
+ nop
+ bsrl lbl_a
+ bsr lbl_a
+ bsrs lbl_a
+ jbsr lbl_a
+ nop
+ lea lbl_a,%a0
+ lea %pc@(lbl_a),%a0
+ lea %pc@(lbl_a+128),%a0
+ lea %pc@(lbl_a,%d0),%a0
+ lea %pc@(lbl_a:b,%d0),%a0
+ lea %pc@(lbl_a-.-2:b,%d0),%a0
+ lea %pc@(lbl_a:w,%d0),%a0
+ lea %pc@(lbl_a-.-2:w,%d0),%a0
+ lea %pc@(lbl_a:l,%d0),%a0
+ lea %pc@(lbl_a-.-2:l,%d0),%a0
+ lea %pc@(18:l,%d0),%a0
+ lea %pc@(10:w,%d0),%a0
+ lea %pc@(4:b,%d0),%a0
+ nop
+lbl_a: nop
+ nop
+ lea %pc@(.-126,%d0),%a0
+ lea %pc@(.-127,%d0),%a0
+ lea %pc@(.-32766,%d0),%a0
+ lea %pc@(.-32767,%d0),%a0
+ nop
+ lea %pc@(.+129,%d0),%a0
+ lea %pc@(.+130,%d0),%a0
+ lea %pc@(.+32769,%d0),%a0
+ lea %pc@(.+32770,%d0),%a0
+ nop
+ lea %pc@(.-32766),%a0
+ lea %pc@(.-32767),%a0
+ nop
+ lea %pc@(.+32769),%a0
+ lea %pc@(.+32770),%a0
+ nop
+ lea %pc@(undef),%a0
+ lea %pc@(undef,%d0),%a0
+ nop
+ lea undef,%a0
+ nop
+ .long 0
diff --git a/gas/testsuite/gas/m68k/pic1.s b/gas/testsuite/gas/m68k/pic1.s
new file mode 100644
index 0000000000..85787744ae
--- /dev/null
+++ b/gas/testsuite/gas/m68k/pic1.s
@@ -0,0 +1,5 @@
+ .text
+ .globl _foo
+_foo:
+ leal %pc@(_i), %a0
+ leal %pc@(_i-.), %a1
diff --git a/gas/testsuite/gas/m68k/t2.d b/gas/testsuite/gas/m68k/t2.d
new file mode 100644
index 0000000000..65109c8bb5
--- /dev/null
+++ b/gas/testsuite/gas/m68k/t2.d
@@ -0,0 +1,8 @@
+#PROG: nm
+#name: presence of section symbols
+
+00000012 b .bss
+0000000e d .data
+00000000 t .text
+0000000e d loop1
+00000000 t loop2
diff --git a/gas/testsuite/gas/m68k/t2.s b/gas/testsuite/gas/m68k/t2.s
new file mode 100644
index 0000000000..7b71e86ff9
--- /dev/null
+++ b/gas/testsuite/gas/m68k/t2.s
@@ -0,0 +1,6 @@
+ .text
+loop2:
+ move.l %d1,%a0@+
+ dbf %d0,loop1
+ .data
+loop1: bra loop2
diff --git a/gas/testsuite/gas/m88k/init.d b/gas/testsuite/gas/m88k/init.d
new file mode 100644
index 0000000000..b2d9259409
--- /dev/null
+++ b/gas/testsuite/gas/m88k/init.d
@@ -0,0 +1,11 @@
+#objdump: -d --prefix-addresses
+#name: padding of .init section
+
+.*: +file format .*
+
+Disassembly of section .text:
+Disassembly of section .init:
+00000000 <.init> subu r31,r31,0x10
+00000004 <.init\+0x4> st r13,r31,0x20
+00000008 <.init\+0x8> or r0,r0,r0
+0000000c <.init\+0xc> or r0,r0,r0
diff --git a/gas/testsuite/gas/m88k/init.s b/gas/testsuite/gas/m88k/init.s
new file mode 100644
index 0000000000..29681cb1e2
--- /dev/null
+++ b/gas/testsuite/gas/m88k/init.s
@@ -0,0 +1,5 @@
+; Test proper padding of the .init section
+ section .init,"x"
+ align 4
+ subu r31,r31,16
+ st r13,r31,32
diff --git a/gas/testsuite/gas/m88k/m88k.exp b/gas/testsuite/gas/m88k/m88k.exp
new file mode 100644
index 0000000000..6907c11506
--- /dev/null
+++ b/gas/testsuite/gas/m88k/m88k.exp
@@ -0,0 +1,10 @@
+#
+# Tests for m88k svr3 targets
+#
+if { [istarget m88*-*-sysv3] || [istarget m88*-*-coff* ] } then {
+ set testname "Proper padding of .init section"
+ run_dump_test init
+}
+if [info exists errorInfo] then {
+ unset errorInfo
+}
diff --git a/gas/testsuite/gas/macros/err.s b/gas/testsuite/gas/macros/err.s
new file mode 100644
index 0000000000..cc976311f5
--- /dev/null
+++ b/gas/testsuite/gas/macros/err.s
@@ -0,0 +1,5 @@
+ .macro m
+ m
+ .endm
+
+ m
diff --git a/gas/testsuite/gas/macros/irp.d b/gas/testsuite/gas/macros/irp.d
new file mode 100644
index 0000000000..6733622981
--- /dev/null
+++ b/gas/testsuite/gas/macros/irp.d
@@ -0,0 +1,13 @@
+#objdump: -r
+#name: macro irp
+
+.*: +file format .*
+
+RELOCATION RECORDS FOR .*
+OFFSET[ ]+TYPE[ ]+VALUE.*
+0+00[ ]+[a-zA-Z0-9_]+[ ]+r1
+0+04[ ]+[a-zA-Z0-9_]+[ ]+r2
+0+08[ ]+[a-zA-Z0-9_]+[ ]+r3
+0+0c[ ]+[a-zA-Z0-9_]+[ ]+s1
+0+10[ ]+[a-zA-Z0-9_]+[ ]+s2
+0+14[ ]+[a-zA-Z0-9_]+[ ]+s3
diff --git a/gas/testsuite/gas/macros/irp.s b/gas/testsuite/gas/macros/irp.s
new file mode 100644
index 0000000000..2f9a621445
--- /dev/null
+++ b/gas/testsuite/gas/macros/irp.s
@@ -0,0 +1,8 @@
+ .irp param,1,2,3
+ .long r\param
+ .endr
+
+ .irpc param,123
+ .long s\param
+ .endr
+
diff --git a/gas/testsuite/gas/macros/macros.exp b/gas/testsuite/gas/macros/macros.exp
new file mode 100644
index 0000000000..a51e485986
--- /dev/null
+++ b/gas/testsuite/gas/macros/macros.exp
@@ -0,0 +1,22 @@
+# Run some tests of gas macros.
+
+if ![istarget hppa*-*-*] {
+ run_dump_test test1
+}
+
+run_dump_test test2
+
+run_dump_test test3
+
+run_dump_test irp
+
+run_dump_test rept
+
+gas_test_error "err.s" "" "macro infinite recursion"
+
+case $target_triplet in {
+ { hppa*-*-* } { }
+ default {
+ run_dump_test semi
+ }
+}
diff --git a/gas/testsuite/gas/macros/rept.d b/gas/testsuite/gas/macros/rept.d
new file mode 100644
index 0000000000..efb5d996da
--- /dev/null
+++ b/gas/testsuite/gas/macros/rept.d
@@ -0,0 +1,10 @@
+#objdump: -r
+#name: macro rept
+
+.*: +file format .*
+
+RELOCATION RECORDS FOR .*
+OFFSET[ ]+TYPE[ ]+VALUE.*
+0+00[ ]+[a-zA-Z0-9_]+[ ]+r1
+0+04[ ]+[a-zA-Z0-9_]+[ ]+r1
+0+08[ ]+[a-zA-Z0-9_]+[ ]+r1
diff --git a/gas/testsuite/gas/macros/rept.s b/gas/testsuite/gas/macros/rept.s
new file mode 100644
index 0000000000..243cf67b8f
--- /dev/null
+++ b/gas/testsuite/gas/macros/rept.s
@@ -0,0 +1,3 @@
+ .rept 3
+ .long r1
+ .endr
diff --git a/gas/testsuite/gas/macros/semi.d b/gas/testsuite/gas/macros/semi.d
new file mode 100644
index 0000000000..ae89e73859
--- /dev/null
+++ b/gas/testsuite/gas/macros/semi.d
@@ -0,0 +1,8 @@
+#objdump: -s -j .text
+#name: semi
+
+.*: .*
+
+Contents of section .text:
+ 0000 3b203b20 3a203a20 00000000 00000000 ; ; : : ........
+ 0010 00000000 00000000 00000000 00000000 ................
diff --git a/gas/testsuite/gas/macros/semi.s b/gas/testsuite/gas/macros/semi.s
new file mode 100644
index 0000000000..d6e0963a16
--- /dev/null
+++ b/gas/testsuite/gas/macros/semi.s
@@ -0,0 +1,14 @@
+ .macro semicolon
+ .ascii "; "
+ .endm
+
+ .macro colon
+ .ascii ": "
+ .endm
+
+ semicolon
+ .ascii "; "
+ colon
+ .ascii ": "
+
+ .p2align 5,0
diff --git a/gas/testsuite/gas/macros/test1.d b/gas/testsuite/gas/macros/test1.d
new file mode 100644
index 0000000000..d84b3fb53b
--- /dev/null
+++ b/gas/testsuite/gas/macros/test1.d
@@ -0,0 +1,5 @@
+#nm: --extern-only
+#name: macro test 1
+
+0+01 A s1
+0+02 A s2
diff --git a/gas/testsuite/gas/macros/test1.s b/gas/testsuite/gas/macros/test1.s
new file mode 100644
index 0000000000..988b7cde0d
--- /dev/null
+++ b/gas/testsuite/gas/macros/test1.s
@@ -0,0 +1,7 @@
+ .macro m arg1 arg2
+ .globl \arg1
+ \arg1 = \arg2
+ .endm
+
+ m s1,1
+ m s2,2
diff --git a/gas/testsuite/gas/macros/test2.d b/gas/testsuite/gas/macros/test2.d
new file mode 100644
index 0000000000..741d734959
--- /dev/null
+++ b/gas/testsuite/gas/macros/test2.d
@@ -0,0 +1,10 @@
+#objdump: -r
+#name: macro test 2
+
+.*: +file format .*
+
+RELOCATION RECORDS FOR .*
+OFFSET[ ]+TYPE[ ]+VALUE.*
+0+00[ ]+[a-zA-Z0-9_]+[ ]+r1
+0+04[ ]+[a-zA-Z0-9_]+[ ]+r2
+0+08[ ]+[a-zA-Z0-9_]+[ ]+r3
diff --git a/gas/testsuite/gas/macros/test2.s b/gas/testsuite/gas/macros/test2.s
new file mode 100644
index 0000000000..838ce94032
--- /dev/null
+++ b/gas/testsuite/gas/macros/test2.s
@@ -0,0 +1,9 @@
+ .macro m arg1 arg2 arg3
+ .long \arg1
+ .ifc ,\arg2\arg3
+ .ELSE
+ m \arg2,\arg3
+ .endif
+ .endm
+
+ m r1,r2,r3
diff --git a/gas/testsuite/gas/macros/test3.d b/gas/testsuite/gas/macros/test3.d
new file mode 100644
index 0000000000..2580f76422
--- /dev/null
+++ b/gas/testsuite/gas/macros/test3.d
@@ -0,0 +1,8 @@
+#objdump: -r
+#name: macro test 3
+
+.*: +file format .*
+
+RELOCATION RECORDS FOR .*
+OFFSET[ ]+TYPE[ ]+VALUE.*
+0+00[ ]+[a-zA-Z0-9_]+[ ]+r1
diff --git a/gas/testsuite/gas/macros/test3.s b/gas/testsuite/gas/macros/test3.s
new file mode 100644
index 0000000000..c6410aec16
--- /dev/null
+++ b/gas/testsuite/gas/macros/test3.s
@@ -0,0 +1,7 @@
+ .macro m arg1 arg2
+ \arg1
+ .exitm
+ \arg2
+ .endm
+
+ m ".long r1",.garbage
diff --git a/gas/testsuite/gas/mcore/allinsn.d b/gas/testsuite/gas/mcore/allinsn.d
new file mode 100644
index 0000000000..913d8f51fe
--- /dev/null
+++ b/gas/testsuite/gas/mcore/allinsn.d
@@ -0,0 +1,400 @@
+#as:
+#objdump: -dr
+#name: allinsn
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+000 <abs>:
+ 0: 01 e0 abs r0
+
+0+002 <addc>:
+ 2: 06 21 addc r1, r2
+
+0+004 <addi>:
+ 4: 20 03 addi r3, 1
+
+0+006 <addu>:
+ 6: 1c 54 addu r4, r5
+
+0+008 <and>:
+ 8: 16 76 and r6, r7
+
+0+00a <andi>:
+ a: 2e 28 andi r8, 2
+
+0+00c <andn>:
+ c: 1f a9 andn r9, r10
+
+0+00e <asr>:
+ e: 1a cb asr r11, r12
+
+0+010 <asrc>:
+ 10: 3a 0d asrc r13
+
+0+012 <asri>:
+ 12: 3b fe asri r14, 31
+
+0+014 <bclri>:
+ 14: 30 0f bclri r15, 0
+
+0+016 <bf>:
+ 16: ef f4 bf 0x0
+
+0+018 <bgeni>:
+ 18: 32 70 bgeni r0, 7
+
+0+01a <BGENI>:
+ 1a: 32 80 bgeni r0, 8
+
+0+01c <BGENi>:
+ 1c: 33 f0 bgeni r0, 31
+
+0+01e <bgenr>:
+ 1e: 13 21 bgenr r1, r2
+
+0+020 <bkpt>:
+ ...
+
+0+022 <bmaski>:
+ 22: 2c 83 bmaski r3, 8
+
+0+024 <BMASKI>:
+ 24: 2d f3 bmaski r3, 31
+
+0+026 <br>:
+ 26: f7 ff br 0x26
+
+0+028 <brev>:
+ 28: 00 f4 brev r4
+
+0+02a <bseti>:
+ 2a: 35 e5 bseti r5, 30
+
+0+02c <bsr>:
+ 2c: ff e9 bsr 0x0
+
+0+02e <bt>:
+ 2e: e7 e8 bt 0x0
+
+0+030 <btsti>:
+ 30: 37 b6 btsti r6, 27
+
+0+032 <clrc>:
+ 32: 0f 00 cmpne r0, r0
+
+0+034 <clrf>:
+ 34: 01 d7 clrf r7
+
+0+036 <clrt>:
+ 36: 01 c8 clrt r8
+
+0+038 <cmphs>:
+ 38: 0c a9 cmphs r9, r10
+
+0+03a <cmplt>:
+ 3a: 0d cb cmplt r11, r12
+
+0+03c <cmplei>:
+ 3c: 22 eb cmplti r11, 15
+
+0+03e <cmplti>:
+ 3e: 23 fd cmplti r13, 32
+
+0+040 <cmpne>:
+ 40: 0f fe cmpne r14, r15
+
+0+042 <cmpnei>:
+ 42: 2a 00 cmpnei r0, 0
+
+0+044 <decf>:
+ 44: 00 91 decf r1
+
+0+046 <decgt>:
+ 46: 01 a2 decgt r2
+
+0+048 <declt>:
+ 48: 01 83 declt r3
+
+0+04a <decne>:
+ 4a: 01 b4 decne r4
+
+0+04c <dect>:
+ 4c: 00 85 dect r5
+
+0+04e <divs>:
+ 4e: 32 16 divs r6, r1
+
+0+050 <divu>:
+ 50: 2c 18 divu r8, r1
+
+0+052 <doze>:
+ 52: 00 06 doze
+
+0+054 <ff1>:
+ 54: 00 ea ff1 r10
+
+0+056 <incf>:
+ 56: 00 bb incf r11
+
+0+058 <inct>:
+ 58: 00 ac inct r12
+
+0+05a <ixh>:
+ 5a: 1d ed ixh r13, r14
+
+0+05c <ixw>:
+ 5c: 15 0f ixw r15, r0
+
+0+05e <jbf>:
+ 5e: ef d0 bf 0x0
+
+0+060 <jbr>:
+ 60: f0 0e br 0x7e
+
+0+062 <jbsr>:
+ 62: 7f 0a jsri 0x.*
+
+0+064 <jbt>:
+ 64: e0 0c bt 0x7e
+
+0+066 <jmp>:
+ 66: 00 c1 jmp r1
+
+0+068 <jmpi>:
+ 68: 70 09 jmpi 0x.*
+
+0+06a <jsr>:
+ 6a: 00 d2 jsr r2
+
+0+06c <jsri>:
+ 6c: 7f 08 jsri 0x.*
+
+0+06e <ld.b>:
+ 6e: a3 04 ldb r3, \(r4, 0\)
+
+0+070 <ld.h>:
+ 70: c5 16 ldh r5, \(r6, 2\)
+
+0+072 <ld.w>:
+ 72: 87 18 ld r7, \(r8, 4\)
+
+0+074 <ldb>:
+ 74: a9 fa ldb r9, \(r10, 15\)
+
+0+076 <ldh>:
+ 76: cb fc ldh r11, \(r12, 30\)
+
+0+078 <ld>:
+ 78: 8d 5e ld r13, \(r14, 20\)
+
+0+07a <ldw>:
+ 7a: 8d fe ld r13, \(r14, 60\)
+
+0+07c <ldm>:
+ 7c: 00 62 ldm r2-r15, \(r0\)
+
+0+07e <fooloop>:
+ 7e: 00 41 ldq r4-r7, \(r1\)
+
+0+080 <loopt>:
+ 80: 04 8e loopt r8, 0x64
+
+0+082 <LRW>:
+ 82: 79 03 lrw r9, 0x.*
+
+0+084 <lrw>:
+ 84: 79 04 lrw r9, 0x4321
+
+0+086 <foolit>:
+ 86: 12 34 mov r4, r3
+
+0+088 <lsl>:
+ 88: 1b ba lsl r10, r11
+
+0+08a <lslc>:
+ 8a: 3c 0c lslc r12
+
+0+08c <.XP0001>:
+ ...
+ 8c: ADDR32 .text
+ 90: ADDR32 .text.*
+ 94: 00 00 bkpt
+ 96: 43 21 .word 0x4321
+
+0+098 <lsli>:
+ 98: 3d fd lsli r13, 31
+
+0+09a <lsr>:
+ 9a: 0b fe lsr r14, r15
+
+0+09c <lsrc>:
+ 9c: 3e 00 lsrc r0
+
+0+09e <lsri>:
+ 9e: 3e 11 lsri r1, 1
+
+0+0a0 <mclri>:
+ a0: 30 64 bclri r4, 6
+
+0+0a2 <mfcr>:
+ a2: 10 02 mfcr r2, psr
+
+0+0a4 <mov>:
+ a4: 12 43 mov r3, r4
+
+0+0a6 <movf>:
+ a6: 0a 65 movf r5, r6
+
+0+0a8 <movi>:
+ a8: 67 f7 movi r7, 127
+
+0+0aa <movt>:
+ aa: 02 98 movt r8, r9
+
+0+0ac <mtcr>:
+ ac: 18 0a mtcr r10, psr
+
+0+0ae <mult>:
+ ae: 03 cb mult r11, r12
+
+0+0b0 <mvc>:
+ b0: 00 2d mvc r13
+
+0+0b2 <mvcv>:
+ b2: 00 3e mvcv r14
+
+0+0b4 <neg>:
+ b4: 28 02 rsubi r2, 0
+
+0+0b6 <not>:
+ b6: 01 ff not r15
+
+0+0b8 <or>:
+ b8: 1e 10 or r0, r1
+
+0+0ba <rfi>:
+ ba: 00 03 rfi
+
+0+0bc <rolc>:
+ bc: 06 66 addc r6, r6
+
+0+0be <rori>:
+ be: 39 a9 rotli r9, 26
+
+0+0c0 <rotlc>:
+ c0: 06 66 addc r6, r6
+
+0+0c2 <rotli>:
+ c2: 38 a2 rotli r2, 10
+
+0+0c4 <rotri>:
+ c4: 39 a9 rotli r9, 26
+
+0+0c6 <rsub>:
+ c6: 14 43 rsub r3, r4
+
+0+0c8 <rsubi>:
+ c8: 28 05 rsubi r5, 0
+
+0+0ca <rte>:
+ ca: 00 02 rte
+
+0+0cc <rts>:
+ cc: 00 cf jmp r15
+
+0+0ce <setc>:
+ ce: 0c 00 cmphs r0, r0
+
+0+0d0 <sextb>:
+ d0: 01 56 sextb r6
+
+0+0d2 <sexth>:
+ d2: 01 77 sexth r7
+
+0+0d4 <st.b>:
+ d4: b8 09 stb r8, \(r9, 0\)
+
+0+0d6 <st.h>:
+ d6: da 1b sth r10, \(r11, 2\)
+
+0+0d8 <st.w>:
+ d8: 9c 1d st r12, \(r13, 4\)
+
+0+0da <stb>:
+ da: be ff stb r14, \(r15, 15\)
+
+0+0dc <sth>:
+ dc: d0 f1 sth r0, \(r1, 30\)
+
+0+0de <stw>:
+ de: 92 f3 st r2, \(r3, 60\)
+
+0+0e0 <st>:
+ e0: 94 05 st r4, \(r5, 0\)
+
+0+0e2 <stm>:
+ e2: 00 7e stm r14-r15, \(r0\)
+
+0+0e4 <stop>:
+ e4: 00 04 stop
+
+0+0e6 <stq>:
+ e6: 00 51 stq r4-r7, \(r1\)
+
+0+0e8 <subc>:
+ e8: 07 d7 subc r7, r13
+
+0+0ea <subi>:
+ ea: 25 fe subi r14, 32
+
+0+0ec <subu>:
+ ec: 05 39 subu r9, r3
+
+0+0ee <sync>:
+ ee: 00 01 sync
+
+0+0f0 <tstlt>:
+ f0: 37 f5 btsti r5, 31
+
+0+0f2 <tstne>:
+ f2: 2a 07 cmpnei r7, 0
+
+0+0f4 <trap>:
+ f4: 00 0a trap 2
+
+0+0f6 <tst>:
+ f6: 0e ee tst r14, r14
+
+0+0f8 <tstnbz>:
+ f8: 01 92 tstnbz r2
+
+0+0fa <wait>:
+ fa: 00 05 wait
+
+0+0fc <xor>:
+ fc: 17 0f xor r15, r0
+
+0+0fe <xsr>:
+ fe: 38 0b xsr r11
+
+0+0100 <xtrb0>:
+ 100: 01 31 xtrb0 r1, r1
+
+0+0102 <xtrb1>:
+ 102: 01 22 xtrb1 r1, r2
+
+0+0104 <xtrb2>:
+ 104: 01 10 xtrb2 r1, r0
+
+0+0106 <xtrb3>:
+ 106: 01 0d xtrb3 r1, r13
+
+0+0108 <zextb>:
+ 108: 01 48 zextb r8
+
+0+010a <zexth>:
+ 10a: 01 64 zexth r4
+ 10c: 0f 00 cmpne r0, r0
+ 10e: 0f 00 cmpne r0, r0
diff --git a/gas/testsuite/gas/mcore/allinsn.exp b/gas/testsuite/gas/mcore/allinsn.exp
new file mode 100644
index 0000000000..9f57863ab3
--- /dev/null
+++ b/gas/testsuite/gas/mcore/allinsn.exp
@@ -0,0 +1,5 @@
+# M*Core assembler testsuite.
+
+if [istarget mcore-*-*] {
+ run_dump_test "allinsn"
+}
diff --git a/gas/testsuite/gas/mcore/allinsn.s b/gas/testsuite/gas/mcore/allinsn.s
new file mode 100644
index 0000000000..84068404e7
--- /dev/null
+++ b/gas/testsuite/gas/mcore/allinsn.s
@@ -0,0 +1,146 @@
+ .data
+foodata: .word 42
+ .text
+footext:
+
+.macro test insn text=""
+ .export \insn
+\insn:
+ \insn \text
+.endm
+
+ test abs r0
+ test addc "r1,r2" // A double forward slash starts a line comment
+ test addi "r3, 1" # So does a hash
+ test addu "r4, r5" // White space between operands should be ignored
+ test and "r6,r7" ; test andi "r8,#2" // A semicolon seperates statements
+ test andn "r9, r10"
+ test asr "r11, R12" // Uppercase R is allowed as a register prefix
+ test asrc "r13"
+ test asri "r14,#0x1f"
+ test bclri "r15,0"
+ test bf footext
+ test bgeni "sp, 7" // r0 can also be refered to as 'sp'
+ test BGENI "r0, 8" // Officially upper case or mixed case
+ test BGENi "r0, 31" // mnemonics should not be allowed, but we relax this...
+ test bgenr "r1, r2"
+ test bkpt
+ test bmaski "r3,#8"
+ test BMASKI "r3,0x1f"
+ test br . // Dot means the current address
+ test brev r4
+ test bseti "r5,30"
+ test bsr footext
+ test bt footext
+ test btsti "r6, 27"
+ test clrc
+ test clrf r7
+ test clrt r8
+ test cmphs "r9,r10"
+ test cmplt "r11,r12"
+ test cmplei "r11, 14"
+ test cmplti "r13,32"
+ test cmpne "r14, r15"
+ test cmpnei "r0,0"
+ test decf r1
+ test decgt r2
+ test declt r3
+ test decne r4
+ test dect r5
+ test divs "r6,r1"
+ test divu "r8, r1"
+ test doze
+ test ff1 r10
+ test incf r11
+ test inct r12
+ test ixh "r13,r14"
+ test ixw "r15,r0"
+ test jbf footext
+ test jbr fooloop
+ test jbsr footext
+ test jbt fooloop
+ test jmp r1
+ test jmpi footext
+ test jsr r2
+ test jsri footext
+ test ld.b "r3,(r4,0)"
+ test ld.h "r5 , ( r6, #2)"
+ test ld.w "r7, (r8, 0x4)"
+ test ldb "r9,(r10,#0xf)"
+ test ldh "r11, (r12, 30)"
+ test ld "r13, (r14, 20)"
+ test ldw "r13, (r14, 60)"
+ test ldm "r2-r15,(r0)"
+ .export fooloop
+fooloop:
+ test ldq "r4-r7,(r1)"
+ test loopt "r8, fooloop"
+ test LRW "r9, [foolit]"
+ test lrw "r9, 0x4321" // PC rel indirect
+ .global foolit
+foolit:
+ .word 0x1234
+ test lsl "r10,r11"
+ test lslc r12
+ .literals // Dump literals table
+ test lsli "r13,31"
+ test lsr "r14,r15"
+ test lsrc r0
+ test lsri "r1,1"
+ test mclri "r4, 64"
+ test mfcr "r2, cr0"
+ test mov "r3,r4"
+ test movf "r5, r6"
+ test movi "r7, 127"
+ test movt "r8, r9"
+ test mtcr "r10, psr"
+ test mult "r11, r12"
+ test mvc r13
+ test mvcv r14
+ test neg r2
+ test not r15
+ test or "r0,r1"
+ test rfi
+ test rolc "r6, 1"
+ test rori "r9, 6"
+ test rotlc "r6, 1"
+ test rotli "r2, #10"
+ test rotri "r9, 6"
+ test rsub "r3, r4"
+ test rsubi "r5, 0x0"
+ test rte
+ test rts
+ test setc
+ test sextb r6
+ test sexth r7
+ test st.b "r8, (r9, 0)"
+ test st.h "r10, (r11, 2)"
+ test st.w "r12, (r13, 4)"
+ test stb "r14, (r15, 15)"
+ test sth "r0, (r1, 30)"
+ test stw "r2, (r3, 0x3c)"
+ test st "r4, (r5, 0)"
+ test stm "r14 - r15 , (r0)"
+ test stop
+ test stq "r4 - r7 , (r1)"
+ test subc "r7, r13"
+ test subi "r14, 32"
+ test subu "r9, r3"
+ test sync
+ test tstlt r5
+ test tstne r7
+ test trap 2
+ test tst "r14, r14"
+ test tstnbz r2
+ test wait
+ test xor "r15,r0"
+ test xsr r11
+ test xtrb0 "r1, r1"
+ test xtrb1 "r1, r2"
+ test xtrb2 "r1, r0"
+ test xtrb3 "r1, r13"
+ test zextb r8
+ test zexth r4
+ clrc // These two instructions pad the object file
+ clrc // out to a 16 byte boundary.
+ \ No newline at end of file
diff --git a/gas/testsuite/gas/mips/abs.d b/gas/testsuite/gas/mips/abs.d
new file mode 100644
index 0000000000..c86d5c2b0f
--- /dev/null
+++ b/gas/testsuite/gas/mips/abs.d
@@ -0,0 +1,15 @@
+#objdump: -dr --prefix-addresses -mmips:4000
+#name: MIPS abs
+
+# Test the abs macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> bgez \$a0,0+000c <foo\+(0x|)c>
+0+0004 <[^>]*> nop
+0+0008 <[^>]*> neg \$a0,\$a0
+0+000c <[^>]*> bgez \$a1,0+0018 <foo\+(0x|)18>
+0+0010 <[^>]*> move \$a0,\$a1
+0+0014 <[^>]*> neg \$a0,\$a1
+ ...
diff --git a/gas/testsuite/gas/mips/abs.s b/gas/testsuite/gas/mips/abs.s
new file mode 100644
index 0000000000..1f2172bcb0
--- /dev/null
+++ b/gas/testsuite/gas/mips/abs.s
@@ -0,0 +1,5 @@
+# Source file used to test the abs macro.
+foo:
+ abs $4
+ abs $4,$5
+ .space 8
diff --git a/gas/testsuite/gas/mips/add.d b/gas/testsuite/gas/mips/add.d
new file mode 100644
index 0000000000..8c21d1dda3
--- /dev/null
+++ b/gas/testsuite/gas/mips/add.d
@@ -0,0 +1,20 @@
+#objdump: -dr --prefix-addresses -mmips:4000
+#name: MIPS add
+
+# Test the add macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> addi \$a0,\$a0,0
+0+0004 <[^>]*> addi \$a0,\$a0,1
+0+0008 <[^>]*> li \$at,0x8000
+0+000c <[^>]*> add \$a0,\$a0,\$at
+0+0010 <[^>]*> addi \$a0,\$a0,-32768
+0+0014 <[^>]*> lui \$at,0x1
+0+0018 <[^>]*> add \$a0,\$a0,\$at
+0+001c <[^>]*> lui \$at,0x1
+0+0020 <[^>]*> ori \$at,\$at,0xa5a5
+0+0024 <[^>]*> add \$a0,\$a0,\$at
+0+0028 <[^>]*> addiu \$a0,\$a0,1
+0+002c <[^>]*> nop
diff --git a/gas/testsuite/gas/mips/add.s b/gas/testsuite/gas/mips/add.s
new file mode 100644
index 0000000000..44e964bdd2
--- /dev/null
+++ b/gas/testsuite/gas/mips/add.s
@@ -0,0 +1,16 @@
+# Source file used to test the add macro.
+
+foo:
+ add $4,$4,0
+ add $4,$4,1
+ add $4,$4,0x8000
+ add $4,$4,-0x8000
+ add $4,$4,0x10000
+ add $4,$4,0x1a5a5
+
+# addu is handled the same way add is; just confirm that it isn't
+# totally broken.
+ addu $4,$4,1
+
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+ nop
diff --git a/gas/testsuite/gas/mips/and.d b/gas/testsuite/gas/mips/and.d
new file mode 100644
index 0000000000..8d617147ca
--- /dev/null
+++ b/gas/testsuite/gas/mips/and.d
@@ -0,0 +1,34 @@
+#objdump: -dr --prefix-addresses -mmips:4000
+#name: MIPS and
+
+# Test the and macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> andi \$a0,\$a0,0x0
+0+0004 <[^>]*> andi \$a0,\$a0,0x1
+0+0008 <[^>]*> andi \$a0,\$a0,0x8000
+0+000c <[^>]*> li \$at,-32768
+0+0010 <[^>]*> and \$a0,\$a0,\$at
+0+0014 <[^>]*> lui \$at,0x1
+0+0018 <[^>]*> and \$a0,\$a0,\$at
+0+001c <[^>]*> lui \$at,0x1
+0+0020 <[^>]*> ori \$at,\$at,0xa5a5
+0+0024 <[^>]*> and \$a0,\$a0,\$at
+0+0028 <[^>]*> ori \$a0,\$a1,0x0
+0+002c <[^>]*> nor \$a0,\$a0,\$zero
+0+0030 <[^>]*> ori \$a0,\$a1,0x1
+0+0034 <[^>]*> nor \$a0,\$a0,\$zero
+0+0038 <[^>]*> ori \$a0,\$a1,0x8000
+0+003c <[^>]*> nor \$a0,\$a0,\$zero
+0+0040 <[^>]*> li \$at,-32768
+0+0044 <[^>]*> nor \$a0,\$a1,\$at
+0+0048 <[^>]*> lui \$at,0x1
+0+004c <[^>]*> nor \$a0,\$a1,\$at
+0+0050 <[^>]*> lui \$at,0x1
+0+0054 <[^>]*> ori \$at,\$at,0xa5a5
+0+0058 <[^>]*> nor \$a0,\$a1,\$at
+0+005c <[^>]*> ori \$a0,\$a1,0x0
+0+0060 <[^>]*> xori \$a0,\$a1,0x0
+ ...
diff --git a/gas/testsuite/gas/mips/and.s b/gas/testsuite/gas/mips/and.s
new file mode 100644
index 0000000000..4dfc57e1f4
--- /dev/null
+++ b/gas/testsuite/gas/mips/and.s
@@ -0,0 +1,28 @@
+# Source file used to test the and macro.
+
+foo:
+ and $4,$4,0
+ and $4,$4,1
+ and $4,$4,0x8000
+ and $4,$4,-0x8000
+ and $4,$4,0x10000
+ and $4,$4,0x1a5a5
+
+# nor, or, and xor are handled by the same code. There is a special
+# case for nor, so we test all variants.
+
+ nor $4,$5,0
+ nor $4,$5,1
+ nor $4,$5,0x8000
+ nor $4,$5,-0x8000
+ nor $4,$5,0x10000
+ nor $4,$5,0x1a5a5
+
+ or $4,$5,0
+
+ xor $4,$5,0
+
+ # Round to a 16 byte boundary, for ease in testing multiple targets.
+ nop
+ nop
+ nop
diff --git a/gas/testsuite/gas/mips/beq.d b/gas/testsuite/gas/mips/beq.d
new file mode 100644
index 0000000000..a1329342f2
--- /dev/null
+++ b/gas/testsuite/gas/mips/beq.d
@@ -0,0 +1,40 @@
+#objdump: -dr --prefix-addresses -mmips:4000
+#name: MIPS beq
+
+# Test the beq macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> beq \$a0,\$a1,0+0000 <text_label>
+0+0004 <[^>]*> nop
+0+0008 <[^>]*> beqz \$a0,0+0000 <text_label>
+0+000c <[^>]*> nop
+0+0010 <[^>]*> li \$at,1
+0+0014 <[^>]*> beq \$a0,\$at,0+0000 <text_label>
+0+0018 <[^>]*> nop
+0+001c <[^>]*> li \$at,0x8000
+0+0020 <[^>]*> beq \$a0,\$at,0+0000 <text_label>
+0+0024 <[^>]*> nop
+0+0028 <[^>]*> li \$at,-32768
+0+002c <[^>]*> beq \$a0,\$at,0+0000 <text_label>
+0+0030 <[^>]*> nop
+0+0034 <[^>]*> lui \$at,0x1
+0+0038 <[^>]*> beq \$a0,\$at,0+0000 <text_label>
+0+003c <[^>]*> nop
+0+0040 <[^>]*> lui \$at,0x1
+0+0044 <[^>]*> ori \$at,\$at,0xa5a5
+0+0048 <[^>]*> beq \$a0,\$at,0+0000 <text_label>
+0+004c <[^>]*> nop
+0+0050 <[^>]*> bnez \$a0,0+0000 <text_label>
+0+0054 <[^>]*> nop
+0+0058 <[^>]*> beqzl \$a0,0+0000 <text_label>
+0+005c <[^>]*> nop
+0+0060 <[^>]*> bnezl \$a0,0+0000 <text_label>
+ ...
+0+20068 <[^>]*> j 0+0000 <text_label>
+[ ]*20068: (MIPS_JMP|JMPADDR|R_MIPS_26) .text
+0+2006c <[^>]*> nop
+0+20070 <[^>]*> jal 0+0000 <text_label>
+[ ]*20070: (MIPS_JMP|JMPADDR|R_MIPS_26) .text
+ ...
diff --git a/gas/testsuite/gas/mips/beq.s b/gas/testsuite/gas/mips/beq.s
new file mode 100644
index 0000000000..9922eecb27
--- /dev/null
+++ b/gas/testsuite/gas/mips/beq.s
@@ -0,0 +1,28 @@
+# Source file used to test the beq macro.
+ .globl text_label .text
+text_label:
+ beq $4,$5,text_label
+ beq $4,0,text_label
+ beq $4,1,text_label
+ beq $4,0x8000,text_label
+ beq $4,-0x8000,text_label
+ beq $4,0x10000,text_label
+ beq $4,0x1a5a5,text_label
+
+# bne is handled by the same code as beq. Just sanity check.
+ bne $4,0,text_label
+
+# Sanity check beql and bnel
+ .set mips2
+ beql $4,0,text_label
+ bnel $4,0,text_label
+
+# Test that branches which overflow are converted to jumps.
+ .space 0x20000
+ b text_label
+ bal text_label
+
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+ nop
+ nop
+ nop
diff --git a/gas/testsuite/gas/mips/bge.d b/gas/testsuite/gas/mips/bge.d
new file mode 100644
index 0000000000..ee3e27ce8e
--- /dev/null
+++ b/gas/testsuite/gas/mips/bge.d
@@ -0,0 +1,53 @@
+#objdump: -dr --prefix-addresses -mmips:4000
+#name: MIPS bge
+
+# Test the bge macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> slt \$at,\$a0,\$a1
+0+0004 <[^>]*> beqz \$at,0+0000 <text_label>
+0+0008 <[^>]*> nop
+0+000c <[^>]*> bgez \$a0,0+0000 <text_label>
+0+0010 <[^>]*> nop
+0+0014 <[^>]*> blez \$a1,0+0000 <text_label>
+0+0018 <[^>]*> nop
+0+001c <[^>]*> bgez \$a0,0+0000 <text_label>
+0+0020 <[^>]*> nop
+0+0024 <[^>]*> bgtz \$a0,0+0000 <text_label>
+0+0028 <[^>]*> nop
+0+002c <[^>]*> slti \$at,\$a0,2
+0+0030 <[^>]*> beqz \$at,0+0000 <text_label>
+0+0034 <[^>]*> nop
+0+0038 <[^>]*> li \$at,0x8000
+0+003c <[^>]*> slt \$at,\$a0,\$at
+0+0040 <[^>]*> beqz \$at,0+0000 <text_label>
+0+0044 <[^>]*> nop
+0+0048 <[^>]*> slti \$at,\$a0,-32768
+0+004c <[^>]*> beqz \$at,0+0000 <text_label>
+0+0050 <[^>]*> nop
+0+0054 <[^>]*> lui \$at,0x1
+0+0058 <[^>]*> slt \$at,\$a0,\$at
+0+005c <[^>]*> beqz \$at,0+0000 <text_label>
+0+0060 <[^>]*> nop
+0+0064 <[^>]*> lui \$at,0x1
+0+0068 <[^>]*> ori \$at,\$at,0xa5a5
+0+006c <[^>]*> slt \$at,\$a0,\$at
+0+0070 <[^>]*> beqz \$at,0+0000 <text_label>
+0+0074 <[^>]*> nop
+0+0078 <[^>]*> slt \$at,\$a1,\$a0
+0+007c <[^>]*> bnez \$at,0+0000 <text_label>
+0+0080 <[^>]*> nop
+0+0084 <[^>]*> bgtz \$a0,0+0000 <text_label>
+0+0088 <[^>]*> nop
+0+008c <[^>]*> bltz \$a1,0+0000 <text_label>
+0+0090 <[^>]*> nop
+0+0094 <[^>]*> bgtz \$a0,0+0000 <text_label>
+0+0098 <[^>]*> nop
+0+009c <[^>]*> slt \$at,\$a0,\$a1
+0+00a0 <[^>]*> beqzl \$at,0+0000 <text_label>
+0+00a4 <[^>]*> nop
+0+00a8 <[^>]*> slt \$at,\$a1,\$a0
+0+00ac <[^>]*> bnezl \$at,0+0000 <text_label>
+ ...
diff --git a/gas/testsuite/gas/mips/bge.s b/gas/testsuite/gas/mips/bge.s
new file mode 100644
index 0000000000..405fd82b2b
--- /dev/null
+++ b/gas/testsuite/gas/mips/bge.s
@@ -0,0 +1,31 @@
+# Source file used to test the bge macro.
+
+text_label:
+ bge $4,$5,text_label
+ bge $4,$0,text_label
+ bge $0,$5,text_label
+ bge $4,0,text_label
+ bge $4,1,text_label
+ bge $4,2,text_label
+ bge $4,0x8000,text_label
+ bge $4,-0x8000,text_label
+ bge $4,0x10000,text_label
+ bge $4,0x1a5a5,text_label
+
+# bgt is handled like bge, except when both arguments are registers.
+# Just sanity check it otherwise.
+ bgt $4,$5,text_label
+ bgt $4,$0,text_label
+ bgt $0,$5,text_label
+ bgt $4,0,text_label
+
+# Sanity test bgel and bgtl
+ .set mips2
+ bgel $4,$5,text_label
+ bgtl $4,$5,text_label
+
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+ nop
+ nop
+ nop
+ nop
diff --git a/gas/testsuite/gas/mips/bgeu.d b/gas/testsuite/gas/mips/bgeu.d
new file mode 100644
index 0000000000..93a6040114
--- /dev/null
+++ b/gas/testsuite/gas/mips/bgeu.d
@@ -0,0 +1,47 @@
+#objdump: -dr --prefix-addresses -mmips:4000
+#name: MIPS bgeu
+
+# Test the bgeu macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> sltu \$at,\$a0,\$a1
+0+0004 <[^>]*> beqz \$at,0+0000 <text_label>
+0+0008 <[^>]*> nop
+0+000c <[^>]*> beq \$zero,\$a1,0+0000 <text_label>
+0+0010 <[^>]*> nop
+0+0014 <[^>]*> bnez \$a0,0+0000 <text_label>
+0+0018 <[^>]*> nop
+0+001c <[^>]*> sltiu \$at,\$a0,2
+0+0020 <[^>]*> beqz \$at,0+0000 <text_label>
+0+0024 <[^>]*> nop
+0+0028 <[^>]*> li \$at,0x8000
+0+002c <[^>]*> sltu \$at,\$a0,\$at
+0+0030 <[^>]*> beqz \$at,0+0000 <text_label>
+0+0034 <[^>]*> nop
+0+0038 <[^>]*> sltiu \$at,\$a0,-32768
+0+003c <[^>]*> beqz \$at,0+0000 <text_label>
+0+0040 <[^>]*> nop
+0+0044 <[^>]*> lui \$at,0x1
+0+0048 <[^>]*> sltu \$at,\$a0,\$at
+0+004c <[^>]*> beqz \$at,0+0000 <text_label>
+0+0050 <[^>]*> nop
+0+0054 <[^>]*> lui \$at,0x1
+0+0058 <[^>]*> ori \$at,\$at,0xa5a5
+0+005c <[^>]*> sltu \$at,\$a0,\$at
+0+0060 <[^>]*> beqz \$at,0+0000 <text_label>
+0+0064 <[^>]*> nop
+0+0068 <[^>]*> sltu \$at,\$a1,\$a0
+0+006c <[^>]*> bnez \$at,0+0000 <text_label>
+0+0070 <[^>]*> nop
+0+0074 <[^>]*> bnez \$a0,0+0000 <text_label>
+0+0078 <[^>]*> nop
+0+007c <[^>]*> bnez \$a0,0+0000 <text_label>
+0+0080 <[^>]*> nop
+0+0084 <[^>]*> sltu \$at,\$a0,\$a1
+0+0088 <[^>]*> beqzl \$at,0+0000 <text_label>
+0+008c <[^>]*> nop
+0+0090 <[^>]*> sltu \$at,\$a1,\$a0
+0+0094 <[^>]*> bnezl \$at,0+0000 <text_label>
+ ...
diff --git a/gas/testsuite/gas/mips/bgeu.s b/gas/testsuite/gas/mips/bgeu.s
new file mode 100644
index 0000000000..1c37f96939
--- /dev/null
+++ b/gas/testsuite/gas/mips/bgeu.s
@@ -0,0 +1,27 @@
+# Source file used to test the bgeu macro.
+
+text_label:
+ bgeu $4,$5,text_label
+ bgeu $0,$5,text_label
+ # A second argument of 0 or $0 is always true
+ bgeu $4,1,text_label
+ bgeu $4,2,text_label
+ bgeu $4,0x8000,text_label
+ bgeu $4,-0x8000,text_label
+ bgeu $4,0x10000,text_label
+ bgeu $4,0x1a5a5,text_label
+
+# bgtu is handled like bgeu, except when both arguments are registers.
+# Just sanity check it otherwise.
+ bgtu $4,$5,text_label
+ bgtu $4,$0,text_label
+ bgtu $4,0,text_label
+
+# Sanity test bgeul and bgtul
+ .set mips2
+ bgeul $4,$5,text_label
+ bgtul $4,$5,text_label
+
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+ nop
+ nop
diff --git a/gas/testsuite/gas/mips/blt.d b/gas/testsuite/gas/mips/blt.d
new file mode 100644
index 0000000000..fc10e23a5a
--- /dev/null
+++ b/gas/testsuite/gas/mips/blt.d
@@ -0,0 +1,53 @@
+#objdump: -dr --prefix-addresses -mmips:4000
+#name: MIPS blt
+
+# Test the blt macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> slt \$at,\$a0,\$a1
+0+0004 <[^>]*> bnez \$at,0+0000 <text_label>
+0+0008 <[^>]*> nop
+0+000c <[^>]*> bltz \$a0,0+0000 <text_label>
+0+0010 <[^>]*> nop
+0+0014 <[^>]*> bgtz \$a1,0+0000 <text_label>
+0+0018 <[^>]*> nop
+0+001c <[^>]*> bltz \$a0,0+0000 <text_label>
+0+0020 <[^>]*> nop
+0+0024 <[^>]*> blez \$a0,0+0000 <text_label>
+0+0028 <[^>]*> nop
+0+002c <[^>]*> slti \$at,\$a0,2
+0+0030 <[^>]*> bnez \$at,0+0000 <text_label>
+0+0034 <[^>]*> nop
+0+0038 <[^>]*> li \$at,0x8000
+0+003c <[^>]*> slt \$at,\$a0,\$at
+0+0040 <[^>]*> bnez \$at,0+0000 <text_label>
+0+0044 <[^>]*> nop
+0+0048 <[^>]*> slti \$at,\$a0,-32768
+0+004c <[^>]*> bnez \$at,0+0000 <text_label>
+0+0050 <[^>]*> nop
+0+0054 <[^>]*> lui \$at,0x1
+0+0058 <[^>]*> slt \$at,\$a0,\$at
+0+005c <[^>]*> bnez \$at,0+0000 <text_label>
+0+0060 <[^>]*> nop
+0+0064 <[^>]*> lui \$at,0x1
+0+0068 <[^>]*> ori \$at,\$at,0xa5a5
+0+006c <[^>]*> slt \$at,\$a0,\$at
+0+0070 <[^>]*> bnez \$at,0+0000 <text_label>
+0+0074 <[^>]*> nop
+0+0078 <[^>]*> slt \$at,\$a1,\$a0
+0+007c <[^>]*> beqz \$at,0+0000 <text_label>
+0+0080 <[^>]*> nop
+0+0084 <[^>]*> blez \$a0,0+0000 <text_label>
+0+0088 <[^>]*> nop
+0+008c <[^>]*> bgez \$a1,0+0000 <text_label>
+0+0090 <[^>]*> nop
+0+0094 <[^>]*> blez \$a0,0+0000 <text_label>
+0+0098 <[^>]*> nop
+0+009c <[^>]*> slt \$at,\$a0,\$a1
+0+00a0 <[^>]*> bnezl \$at,0+0000 <text_label>
+0+00a4 <[^>]*> nop
+0+00a8 <[^>]*> slt \$at,\$a1,\$a0
+0+00ac <[^>]*> beqzl \$at,0+0000 <text_label>
+ ...
diff --git a/gas/testsuite/gas/mips/blt.s b/gas/testsuite/gas/mips/blt.s
new file mode 100644
index 0000000000..000305696d
--- /dev/null
+++ b/gas/testsuite/gas/mips/blt.s
@@ -0,0 +1,31 @@
+# Source file used to test the blt macro.
+
+text_label:
+ blt $4,$5,text_label
+ blt $4,$0,text_label
+ blt $0,$5,text_label
+ blt $4,0,text_label
+ blt $4,1,text_label
+ blt $4,2,text_label
+ blt $4,0x8000,text_label
+ blt $4,-0x8000,text_label
+ blt $4,0x10000,text_label
+ blt $4,0x1a5a5,text_label
+
+# ble is handled like blt, except when both arguments are registers.
+# Just sanity check it otherwise.
+ ble $4,$5,text_label
+ ble $4,$0,text_label
+ ble $0,$5,text_label
+ ble $4,0,text_label
+
+# Sanity test bltl and blel
+ .set mips2
+ bltl $4,$5,text_label
+ blel $4,$5,text_label
+
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+ nop
+ nop
+ nop
+ nop
diff --git a/gas/testsuite/gas/mips/bltu.d b/gas/testsuite/gas/mips/bltu.d
new file mode 100644
index 0000000000..9c261c638c
--- /dev/null
+++ b/gas/testsuite/gas/mips/bltu.d
@@ -0,0 +1,47 @@
+#objdump: -dr --prefix-addresses -mmips:4000
+#name: MIPS bltu
+
+# Test the bltu macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> sltu \$at,\$a0,\$a1
+0+0004 <[^>]*> bnez \$at,0+0000 <text_label>
+0+0008 <[^>]*> nop
+0+000c <[^>]*> bne \$zero,\$a1,0+0000 <text_label>
+0+0010 <[^>]*> nop
+0+0014 <[^>]*> beqz \$a0,0+0000 <text_label>
+0+0018 <[^>]*> nop
+0+001c <[^>]*> sltiu \$at,\$a0,2
+0+0020 <[^>]*> bnez \$at,0+0000 <text_label>
+0+0024 <[^>]*> nop
+0+0028 <[^>]*> li \$at,0x8000
+0+002c <[^>]*> sltu \$at,\$a0,\$at
+0+0030 <[^>]*> bnez \$at,0+0000 <text_label>
+0+0034 <[^>]*> nop
+0+0038 <[^>]*> sltiu \$at,\$a0,-32768
+0+003c <[^>]*> bnez \$at,0+0000 <text_label>
+0+0040 <[^>]*> nop
+0+0044 <[^>]*> lui \$at,0x1
+0+0048 <[^>]*> sltu \$at,\$a0,\$at
+0+004c <[^>]*> bnez \$at,0+0000 <text_label>
+0+0050 <[^>]*> nop
+0+0054 <[^>]*> lui \$at,0x1
+0+0058 <[^>]*> ori \$at,\$at,0xa5a5
+0+005c <[^>]*> sltu \$at,\$a0,\$at
+0+0060 <[^>]*> bnez \$at,0+0000 <text_label>
+0+0064 <[^>]*> nop
+0+0068 <[^>]*> sltu \$at,\$a1,\$a0
+0+006c <[^>]*> beqz \$at,0+0000 <text_label>
+0+0070 <[^>]*> nop
+0+0074 <[^>]*> beqz \$a0,0+0000 <text_label>
+0+0078 <[^>]*> nop
+0+007c <[^>]*> beqz \$a0,0+0000 <text_label>
+0+0080 <[^>]*> nop
+0+0084 <[^>]*> sltu \$at,\$a0,\$a1
+0+0088 <[^>]*> bnezl \$at,0+0000 <text_label>
+0+008c <[^>]*> nop
+0+0090 <[^>]*> sltu \$at,\$a1,\$a0
+0+0094 <[^>]*> beqzl \$at,0+0000 <text_label>
+ ...
diff --git a/gas/testsuite/gas/mips/bltu.s b/gas/testsuite/gas/mips/bltu.s
new file mode 100644
index 0000000000..44b1ae629e
--- /dev/null
+++ b/gas/testsuite/gas/mips/bltu.s
@@ -0,0 +1,27 @@
+# Source file used to test the bltu macro.
+
+text_label:
+ bltu $4,$5,text_label
+ bltu $0,$5,text_label
+ # A second argument of 0 or $0 is always false
+ bltu $4,1,text_label
+ bltu $4,2,text_label
+ bltu $4,0x8000,text_label
+ bltu $4,-0x8000,text_label
+ bltu $4,0x10000,text_label
+ bltu $4,0x1a5a5,text_label
+
+# bleu is handled like bltu, except when both arguments are registers.
+# Just sanity check it otherwise.
+ bleu $4,$5,text_label
+ bleu $4,$0,text_label
+ bleu $4,0,text_label
+
+# Sanity test bltul and bleul
+ .set mips2
+ bltul $4,$5,text_label
+ bleul $4,$5,text_label
+
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+ nop
+ nop
diff --git a/gas/testsuite/gas/mips/break20.d b/gas/testsuite/gas/mips/break20.d
new file mode 100644
index 0000000000..4498a4cd87
--- /dev/null
+++ b/gas/testsuite/gas/mips/break20.d
@@ -0,0 +1,18 @@
+#as: -mcpu=r3900
+#objdump: -dr --prefix-addresses -mmips:3900
+#name: MIPS 20-bit break
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> break
+0+0004 <[^>]*> break
+0+0008 <[^>]*> break 0x14
+0+000c <[^>]*> break 0x14,0x28
+0+0010 <[^>]*> break 0x3ff,0x3ff
+0+0014 <[^>]*> sdbbp
+0+0018 <[^>]*> sdbbp
+0+001c <[^>]*> sdbbp 0x14
+0+0020 <[^>]*> sdbbp 0x14,0x28
+0+0024 <[^>]*> sdbbp 0x3ff,0x3ff
+ ... \ No newline at end of file
diff --git a/gas/testsuite/gas/mips/break20.s b/gas/testsuite/gas/mips/break20.s
new file mode 100644
index 0000000000..ee35b0ec1b
--- /dev/null
+++ b/gas/testsuite/gas/mips/break20.s
@@ -0,0 +1,17 @@
+# Source file used to test the 20-bit break instructions
+foo:
+ break
+ break 0
+ break 20
+ break 20,40
+ break 1023,1023
+
+ sdbbp
+ sdbbp 0
+ sdbbp 20
+ sdbbp 20,40
+ sdbbp 1023,1023
+
+# force some padding, to make objdump consistently report that there's some
+# here...
+ .space 8
diff --git a/gas/testsuite/gas/mips/delay.d b/gas/testsuite/gas/mips/delay.d
new file mode 100644
index 0000000000..93dc0ec16b
--- /dev/null
+++ b/gas/testsuite/gas/mips/delay.d
@@ -0,0 +1,20 @@
+#objdump: -dr --prefix-addresses -mmips:4000
+#name: MIPS delay
+#as: -mips3 -mcpu=r4000
+
+#
+# Gas should produce nop's after mtc1 and related
+# insn's if the target fpr is used in the
+# immediatly following insn. See also nodelay.d.
+#
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> mtc1 \$zero,\$f0
+0+0004 <[^>]*> nop
+0+0008 <[^>]*> cvt.d.w \$f0,\$f0
+0+000c <[^>]*> mtc1 \$zero,\$f1
+0+0010 <[^>]*> nop
+0+0014 <[^>]*> cvt.d.w \$f1,\$f1
+ ...
diff --git a/gas/testsuite/gas/mips/delay.s b/gas/testsuite/gas/mips/delay.s
new file mode 100644
index 0000000000..5ee2f00aab
--- /dev/null
+++ b/gas/testsuite/gas/mips/delay.s
@@ -0,0 +1,8 @@
+# Source file used to test the abs macro.
+foo:
+ mtc1 $0,$f0
+ cvt.d.w $f0,$f0
+ mtc1 $0,$f1
+ cvt.d.w $f1,$f1
+ .space 8
+
diff --git a/gas/testsuite/gas/mips/div-ilocks.d b/gas/testsuite/gas/mips/div-ilocks.d
new file mode 100644
index 0000000000..75856d3302
--- /dev/null
+++ b/gas/testsuite/gas/mips/div-ilocks.d
@@ -0,0 +1,110 @@
+#objdump: -dr --prefix-addresses -mmips:4000
+#name: MIPS div
+#source: div.s
+
+# Test the div macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> div \$zero,\$a0,\$a1
+0+0004 <[^>]*> bnez \$a1,0+0010 <foo\+0x10>
+0+0008 <[^>]*> div \$zero,\$a0,\$a1
+0+000c <[^>]*> break (0x0,0x7|0x7)
+0+0010 <[^>]*> li \$at,-1
+0+0014 <[^>]*> bne \$a1,\$at,0+0028 <foo\+0x28>
+0+0018 <[^>]*> lui \$at,0x8000
+0+001c <[^>]*> bne \$a0,\$at,0+0028 <foo\+0x28>
+0+0020 <[^>]*> nop
+0+0024 <[^>]*> break (0x0,0x6|0x6)
+0+0028 <[^>]*> mflo \$a0
+0+002c <[^>]*> bnez \$a2,0+0038 <foo\+0x38>
+0+0030 <[^>]*> div \$zero,\$a1,\$a2
+0+0034 <[^>]*> break (0x0,0x7|0x7)
+0+0038 <[^>]*> li \$at,-1
+0+003c <[^>]*> bne \$a2,\$at,0+0050 <foo\+0x50>
+0+0040 <[^>]*> lui \$at,0x8000
+0+0044 <[^>]*> bne \$a1,\$at,0+0050 <foo\+0x50>
+0+0048 <[^>]*> nop
+0+004c <[^>]*> break (0x0,0x6|0x6)
+0+0050 <[^>]*> mflo \$a0
+0+0054 <[^>]*> move \$a0,\$a0
+0+0058 <[^>]*> move \$a0,\$a1
+0+005c <[^>]*> neg \$a0,\$a0
+0+0060 <[^>]*> neg \$a0,\$a1
+0+0064 <[^>]*> li \$at,2
+0+0068 <[^>]*> div \$zero,\$a0,\$at
+0+006c <[^>]*> mflo \$a0
+0+0070 <[^>]*> li \$at,2
+0+0074 <[^>]*> div \$zero,\$a1,\$at
+0+0078 <[^>]*> mflo \$a0
+0+007c <[^>]*> li \$at,0x8000
+0+0080 <[^>]*> div \$zero,\$a0,\$at
+0+0084 <[^>]*> mflo \$a0
+0+0088 <[^>]*> li \$at,0x8000
+0+008c <[^>]*> div \$zero,\$a1,\$at
+0+0090 <[^>]*> mflo \$a0
+0+0094 <[^>]*> li \$at,-32768
+0+0098 <[^>]*> div \$zero,\$a0,\$at
+0+009c <[^>]*> mflo \$a0
+0+00a0 <[^>]*> li \$at,-32768
+0+00a4 <[^>]*> div \$zero,\$a1,\$at
+0+00a8 <[^>]*> mflo \$a0
+0+00ac <[^>]*> lui \$at,0x1
+0+00b0 <[^>]*> div \$zero,\$a0,\$at
+0+00b4 <[^>]*> mflo \$a0
+0+00b8 <[^>]*> lui \$at,0x1
+0+00bc <[^>]*> div \$zero,\$a1,\$at
+0+00c0 <[^>]*> mflo \$a0
+0+00c4 <[^>]*> lui \$at,0x1
+0+00c8 <[^>]*> ori \$at,\$at,0xa5a5
+0+00cc <[^>]*> div \$zero,\$a0,\$at
+0+00d0 <[^>]*> mflo \$a0
+0+00d4 <[^>]*> lui \$at,0x1
+0+00d8 <[^>]*> ori \$at,\$at,0xa5a5
+0+00dc <[^>]*> div \$zero,\$a1,\$at
+0+00e0 <[^>]*> mflo \$a0
+0+00e4 <[^>]*> divu \$zero,\$a0,\$a1
+0+00e8 <[^>]*> bnez \$a1,0+0f4 <foo\+0xf4>
+0+00ec <[^>]*> divu \$zero,\$a0,\$a1
+0+00f0 <[^>]*> break (0x0,0x7|0x7)
+0+00f4 <[^>]*> mflo \$a0
+0+00f8 <[^>]*> bnez \$a2,0+0104 <foo\+0x104>
+0+00fc <[^>]*> divu \$zero,\$a1,\$a2
+0+0100 <[^>]*> break (0x0,0x7|0x7)
+0+0104 <[^>]*> mflo \$a0
+0+0108 <[^>]*> move \$a0,\$a0
+0+010c <[^>]*> bnez \$a2,0+0118 <foo\+0x118>
+0+0110 <[^>]*> div \$zero,\$a1,\$a2
+0+0114 <[^>]*> break (0x0,0x7|0x7)
+0+0118 <[^>]*> li \$at,-1
+0+011c <[^>]*> bne \$a2,\$at,0+0130 <foo\+0x130>
+0+0120 <[^>]*> lui \$at,0x8000
+0+0124 <[^>]*> bne \$a1,\$at,0+0130 <foo\+0x130>
+0+0128 <[^>]*> nop
+0+012c <[^>]*> break (0x0,0x6|0x6)
+0+0130 <[^>]*> mfhi \$a0
+0+0134 <[^>]*> li \$at,2
+0+0138 <[^>]*> divu \$zero,\$a1,\$at
+0+013c <[^>]*> mfhi \$a0
+0+0140 <[^>]*> bnez \$a2,0+014c <foo\+0x14c>
+0+0144 <[^>]*> ddiv \$zero,\$a1,\$a2
+0+0148 <[^>]*> break (0x0,0x7|0x7)
+0+014c <[^>]*> daddiu \$at,\$zero,-1
+0+0150 <[^>]*> bne \$a2,\$at,0+0168 <foo\+0x168>
+0+0154 <[^>]*> daddiu \$at,\$zero,1
+0+0158 <[^>]*> dsll32 \$at,\$at,0x1f
+0+015c <[^>]*> bne \$a1,\$at,0+0168 <foo\+0x168>
+0+0160 <[^>]*> nop
+0+0164 <[^>]*> break (0x0,0x6|0x6)
+0+0168 <[^>]*> mflo \$a0
+0+016c <[^>]*> li \$at,2
+0+0170 <[^>]*> ddivu \$zero,\$a1,\$at
+0+0174 <[^>]*> mflo \$a0
+0+0178 <[^>]*> li \$at,0x8000
+0+017c <[^>]*> ddiv \$zero,\$a1,\$at
+0+0180 <[^>]*> mfhi \$a0
+0+0184 <[^>]*> li \$at,-32768
+0+0188 <[^>]*> ddivu \$zero,\$a1,\$at
+0+018c <[^>]*> mfhi \$a0
+ ...
diff --git a/gas/testsuite/gas/mips/div.d b/gas/testsuite/gas/mips/div.d
new file mode 100644
index 0000000000..fec5bb2c59
--- /dev/null
+++ b/gas/testsuite/gas/mips/div.d
@@ -0,0 +1,125 @@
+#objdump: -dr --prefix-addresses -mmips:4000
+#as: -mcpu=r4000
+#name: MIPS div
+
+# Test the div macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> div \$zero,\$a0,\$a1
+0+0004 <[^>]*> bnez \$a1,0+0010 <foo\+0x10>
+0+0008 <[^>]*> div \$zero,\$a0,\$a1
+0+000c <[^>]*> break (0x0,0x7|0x7)
+0+0010 <[^>]*> li \$at,-1
+0+0014 <[^>]*> bne \$a1,\$at,0+0028 <foo\+0x28>
+0+0018 <[^>]*> lui \$at,0x8000
+0+001c <[^>]*> bne \$a0,\$at,0+0028 <foo\+0x28>
+0+0020 <[^>]*> nop
+0+0024 <[^>]*> break (0x0,0x6|0x6)
+0+0028 <[^>]*> mflo \$a0
+0+002c <[^>]*> nop
+0+0030 <[^>]*> bnez \$a2,0+003c <foo\+0x3c>
+0+0034 <[^>]*> div \$zero,\$a1,\$a2
+0+0038 <[^>]*> break (0x0,0x7|0x7)
+0+003c <[^>]*> li \$at,-1
+0+0040 <[^>]*> bne \$a2,\$at,0+0054 <foo\+0x54>
+0+0044 <[^>]*> lui \$at,0x8000
+0+0048 <[^>]*> bne \$a1,\$at,0+0054 <foo\+0x54>
+0+004c <[^>]*> nop
+0+0050 <[^>]*> break (0x0,0x6|0x6)
+0+0054 <[^>]*> mflo \$a0
+0+0058 <[^>]*> move \$a0,\$a0
+0+005c <[^>]*> move \$a0,\$a1
+0+0060 <[^>]*> neg \$a0,\$a0
+0+0064 <[^>]*> neg \$a0,\$a1
+0+0068 <[^>]*> li \$at,2
+0+006c <[^>]*> div \$zero,\$a0,\$at
+0+0070 <[^>]*> mflo \$a0
+0+0074 <[^>]*> li \$at,2
+0+0078 <[^>]*> nop
+0+007c <[^>]*> div \$zero,\$a1,\$at
+0+0080 <[^>]*> mflo \$a0
+0+0084 <[^>]*> li \$at,0x8000
+0+0088 <[^>]*> nop
+0+008c <[^>]*> div \$zero,\$a0,\$at
+0+0090 <[^>]*> mflo \$a0
+0+0094 <[^>]*> li \$at,0x8000
+0+0098 <[^>]*> nop
+0+009c <[^>]*> div \$zero,\$a1,\$at
+0+00a0 <[^>]*> mflo \$a0
+0+00a4 <[^>]*> li \$at,-32768
+0+00a8 <[^>]*> nop
+0+00ac <[^>]*> div \$zero,\$a0,\$at
+0+00b0 <[^>]*> mflo \$a0
+0+00b4 <[^>]*> li \$at,-32768
+0+00b8 <[^>]*> nop
+0+00bc <[^>]*> div \$zero,\$a1,\$at
+0+00c0 <[^>]*> mflo \$a0
+0+00c4 <[^>]*> lui \$at,0x1
+0+00c8 <[^>]*> nop
+0+00cc <[^>]*> div \$zero,\$a0,\$at
+0+00d0 <[^>]*> mflo \$a0
+0+00d4 <[^>]*> lui \$at,0x1
+0+00d8 <[^>]*> nop
+0+00dc <[^>]*> div \$zero,\$a1,\$at
+0+00e0 <[^>]*> mflo \$a0
+0+00e4 <[^>]*> lui \$at,0x1
+0+00e8 <[^>]*> ori \$at,\$at,0xa5a5
+0+00ec <[^>]*> div \$zero,\$a0,\$at
+0+00f0 <[^>]*> mflo \$a0
+0+00f4 <[^>]*> lui \$at,0x1
+0+00f8 <[^>]*> ori \$at,\$at,0xa5a5
+0+00fc <[^>]*> div \$zero,\$a1,\$at
+0+0100 <[^>]*> mflo \$a0
+ ...
+0+010c <[^>]*> divu \$zero,\$a0,\$a1
+0+0110 <[^>]*> bnez \$a1,0+011c <foo\+0x11c>
+0+0114 <[^>]*> divu \$zero,\$a0,\$a1
+0+0118 <[^>]*> break (0x0,0x7|0x7)
+0+011c <[^>]*> mflo \$a0
+0+0120 <[^>]*> nop
+0+0124 <[^>]*> bnez \$a2,0+0130 <foo\+0x130>
+0+0128 <[^>]*> divu \$zero,\$a1,\$a2
+0+012c <[^>]*> break (0x0,0x7|0x7)
+0+0130 <[^>]*> mflo \$a0
+0+0134 <[^>]*> move \$a0,\$a0
+0+0138 <[^>]*> bnez \$a2,0+0144 <foo\+0x144>
+0+013c <[^>]*> div \$zero,\$a1,\$a2
+0+0140 <[^>]*> break (0x0,0x7|0x7)
+0+0144 <[^>]*> li \$at,-1
+0+0148 <[^>]*> bne \$a2,\$at,0+015c <foo\+0x15c>
+0+014c <[^>]*> lui \$at,0x8000
+0+0150 <[^>]*> bne \$a1,\$at,0+015c <foo\+0x15c>
+0+0154 <[^>]*> nop
+0+0158 <[^>]*> break (0x0,0x6|0x6)
+0+015c <[^>]*> mfhi \$a0
+0+0160 <[^>]*> li \$at,2
+0+0164 <[^>]*> nop
+0+0168 <[^>]*> divu \$zero,\$a1,\$at
+0+016c <[^>]*> mfhi \$a0
+0+0170 <[^>]*> nop
+0+0174 <[^>]*> bnez \$a2,0+0180 <foo\+0x180>
+0+0178 <[^>]*> ddiv \$zero,\$a1,\$a2
+0+017c <[^>]*> break (0x0,0x7|0x7)
+0+0180 <[^>]*> daddiu \$at,\$zero,-1
+0+0184 <[^>]*> bne \$a2,\$at,0+019c <foo\+0x19c>
+0+0188 <[^>]*> daddiu \$at,\$zero,1
+0+018c <[^>]*> dsll32 \$at,\$at,0x1f
+0+0190 <[^>]*> bne \$a1,\$at,0+019c <foo\+0x19c>
+0+0194 <[^>]*> nop
+0+0198 <[^>]*> break (0x0,0x6|0x6)
+0+019c <[^>]*> mflo \$a0
+0+01a0 <[^>]*> li \$at,2
+0+01a4 <[^>]*> nop
+0+01a8 <[^>]*> ddivu \$zero,\$a1,\$at
+0+01ac <[^>]*> mflo \$a0
+0+01b0 <[^>]*> li \$at,0x8000
+0+01b4 <[^>]*> nop
+0+01b8 <[^>]*> ddiv \$zero,\$a1,\$at
+0+01bc <[^>]*> mfhi \$a0
+0+01c0 <[^>]*> li \$at,-32768
+0+01c4 <[^>]*> nop
+0+01c8 <[^>]*> ddivu \$zero,\$a1,\$at
+0+01cc <[^>]*> mfhi \$a0
+ ...
diff --git a/gas/testsuite/gas/mips/div.s b/gas/testsuite/gas/mips/div.s
new file mode 100644
index 0000000000..6d9990672d
--- /dev/null
+++ b/gas/testsuite/gas/mips/div.s
@@ -0,0 +1,41 @@
+# Source file used to test the div macro.
+foo:
+ div $0,$4,$5
+ div $4,$5
+ div $4,$5,$6
+ div $4,1
+ div $4,$5,1
+ div $4,-1
+ div $4,$5,-1
+ div $4,2
+ div $4,$5,2
+ div $4,0x8000
+ div $4,$5,0x8000
+ div $4,-0x8000
+ div $4,$5,-0x8000
+ div $4,0x10000
+ div $4,$5,0x10000
+ div $4,0x1a5a5
+ div $4,$5,0x1a5a5
+
+# divu is like div, except when both arguments are registers.
+# Just sanity check it otherwise.
+ divu $0,$4,$5
+ divu $4,$5
+ divu $4,$5,$6
+ divu $4,1
+
+# rem is like div, remu is like divu
+ rem $4,$5,$6
+ remu $4,$5,2
+
+# Sanity check the 64 bit versions.
+ .set mips3
+ ddiv $4,$5,$6
+ ddivu $4,$5,2
+ drem $4,$5,0x8000
+ dremu $4,$5,-0x8000
+
+# force some padding, to make objdump consistently report that there's some
+# here...
+ .space 8
diff --git a/gas/testsuite/gas/mips/dli.d b/gas/testsuite/gas/mips/dli.d
new file mode 100644
index 0000000000..72b445e2b1
--- /dev/null
+++ b/gas/testsuite/gas/mips/dli.d
@@ -0,0 +1,115 @@
+#objdump: -dr --prefix-addresses -mmips:4000
+#name: MIPS dli
+#as: -mips3
+
+# Test the dli macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> li \$a0,0
+0+0004 <[^>]*> li \$a0,1
+0+0008 <[^>]*> li \$a0,-1
+0+000c <[^>]*> li \$a0,0x8000
+0+0010 <[^>]*> li \$a0,-32768
+0+0014 <[^>]*> lui \$a0,0x1
+0+0018 <[^>]*> lui \$a0,0x1
+0+001c <[^>]*> ori \$a0,\$a0,0xa5a5
+0+0020 <[^>]*> li \$a0,0x8000
+0+0024 <[^>]*> dsll \$a0,\$a0,0x10
+0+0028 <[^>]*> ori \$a0,\$a0,0x1234
+0+002c <[^>]*> lui \$a0,0xffff
+0+0030 <[^>]*> dsrl32 \$a0,\$a0,0x0
+0+0034 <[^>]*> lui \$a0,0xffff
+0+0038 <[^>]*> dsrl32 \$a0,\$a0,0x0
+0+003c <[^>]*> li \$a0,-1
+0+0040 <[^>]*> li \$a0,-1
+0+0044 <[^>]*> dsrl \$a0,\$a0,0xc
+0+0048 <[^>]*> lui \$a0,0x8000
+0+004c <[^>]*> ori \$a0,\$a0,0x1234
+0+0050 <[^>]*> li \$a0,-32768
+0+0054 <[^>]*> dsll \$a0,\$a0,0x10
+0+0058 <[^>]*> ori \$a0,\$a0,0x1234
+0+005c <[^>]*> dsll \$a0,\$a0,0x10
+0+0060 <[^>]*> ori \$a0,\$a0,0x5678
+0+0064 <[^>]*> lui \$a0,0x8000
+0+0068 <[^>]*> ori \$a0,\$a0,0x1234
+0+006c <[^>]*> dsll \$a0,\$a0,0x10
+0+0070 <[^>]*> ori \$a0,\$a0,0x5678
+0+0074 <[^>]*> dsll \$a0,\$a0,0x10
+0+0078 <[^>]*> li \$a0,-30875
+0+007c <[^>]*> lui \$a0,0xffff
+0+0080 <[^>]*> ori \$a0,\$a0,0x4321
+0+0084 <[^>]*> li \$a0,-16
+0+0088 <[^>]*> li \$a0,-256
+0+008c <[^>]*> li \$a0,-4096
+0+0090 <[^>]*> lui \$a0,0xffff
+0+0094 <[^>]*> lui \$a0,0xfff0
+0+0098 <[^>]*> lui \$a0,0xff00
+0+009c <[^>]*> lui \$a0,0xf000
+0+00a0 <[^>]*> li \$a0,-1
+0+00a4 <[^>]*> dsll32 \$a0,\$a0,0x0
+0+00a8 <[^>]*> li \$a0,-16
+0+00ac <[^>]*> dsll32 \$a0,\$a0,0x0
+0+00b0 <[^>]*> li \$a0,-256
+0+00b4 <[^>]*> dsll32 \$a0,\$a0,0x0
+0+00b8 <[^>]*> li \$a0,-4096
+0+00bc <[^>]*> dsll32 \$a0,\$a0,0x0
+0+00c0 <[^>]*> li \$a0,0xffff
+0+00c4 <[^>]*> dsll32 \$a0,\$a0,0x10
+0+00c8 <[^>]*> li \$a0,0xfff0
+0+00cc <[^>]*> dsll32 \$a0,\$a0,0x10
+0+00d0 <[^>]*> li \$a0,0xff00
+0+00d4 <[^>]*> dsll32 \$a0,\$a0,0x10
+0+00d8 <[^>]*> li \$a0,0xf000
+0+00dc <[^>]*> dsll32 \$a0,\$a0,0x10
+0+00e0 <[^>]*> li \$a0,-1
+0+00e4 <[^>]*> dsrl \$a0,\$a0,0x4
+0+00e8 <[^>]*> li \$a0,-1
+0+00ec <[^>]*> dsrl \$a0,\$a0,0x8
+0+00f0 <[^>]*> li \$a0,-1
+0+00f4 <[^>]*> dsrl \$a0,\$a0,0xc
+0+00f8 <[^>]*> li \$a0,-1
+0+00fc <[^>]*> dsrl \$a0,\$a0,0x10
+0+0100 <[^>]*> li \$a0,-1
+0+0104 <[^>]*> dsrl \$a0,\$a0,0x14
+0+0108 <[^>]*> li \$a0,-1
+0+010c <[^>]*> dsrl \$a0,\$a0,0x18
+0+0110 <[^>]*> li \$a0,-1
+0+0114 <[^>]*> dsrl \$a0,\$a0,0x1c
+0+0118 <[^>]*> lui \$a0,0xffff
+0+011c <[^>]*> dsrl32 \$a0,\$a0,0x0
+0+0120 <[^>]*> lui \$a0,0xfff
+0+0124 <[^>]*> ori \$a0,\$a0,0xffff
+0+0128 <[^>]*> lui \$a0,0xff
+0+012c <[^>]*> ori \$a0,\$a0,0xffff
+0+0130 <[^>]*> lui \$a0,0xf
+0+0134 <[^>]*> ori \$a0,\$a0,0xffff
+0+0138 <[^>]*> li \$a0,0xffff
+0+013c <[^>]*> li \$a0,4095
+0+0140 <[^>]*> li \$a0,255
+0+0144 <[^>]*> li \$a0,15
+0+0148 <[^>]*> lui \$a0,0x3
+0+014c <[^>]*> ori \$a0,\$a0,0xfffc
+0+0150 <[^>]*> li \$a0,0xffff
+0+0154 <[^>]*> dsll \$a0,\$a0,0x1e
+0+0158 <[^>]*> li \$a0,0xffff
+0+015c <[^>]*> dsll32 \$a0,\$a0,0x2
+0+0160 <[^>]*> li \$a0,0xffff
+0+0164 <[^>]*> dsll32 \$a0,\$a0,0x6
+0+0168 <[^>]*> li \$a0,-1
+0+016c <[^>]*> dsll32 \$a0,\$a0,0x0
+0+0170 <[^>]*> dsrl \$a0,\$a0,0xa
+0+0174 <[^>]*> li \$a0,-1
+0+0178 <[^>]*> dsll \$a0,\$a0,0x1c
+0+017c <[^>]*> dsrl \$a0,\$a0,0xa
+0+0180 <[^>]*> li \$a0,-1
+0+0184 <[^>]*> dsll \$a0,\$a0,0x18
+0+0188 <[^>]*> dsrl \$a0,\$a0,0xa
+0+018c <[^>]*> lui \$a0,0x3f
+0+0190 <[^>]*> ori \$a0,\$a0,0xfc03
+0+0194 <[^>]*> dsll \$a0,\$a0,0x10
+0+0198 <[^>]*> ori \$a0,\$a0,0xffff
+0+019c <[^>]*> dsll \$a0,\$a0,0x10
+0+01a0 <[^>]*> ori \$a0,\$a0,0xc000
+ ...
diff --git a/gas/testsuite/gas/mips/dli.s b/gas/testsuite/gas/mips/dli.s
new file mode 100644
index 0000000000..6579528f17
--- /dev/null
+++ b/gas/testsuite/gas/mips/dli.s
@@ -0,0 +1,67 @@
+# Source file used to test the dli macro.
+
+foo:
+ dli $4,0
+ dli $4,1
+ dli $4,-1
+ dli $4,0x8000
+ dli $4,-0x8000
+ dli $4,0x10000
+ dli $4,0x1a5a5
+ dli $4,0x80001234
+ dli $4,0xffffffff
+ dli $4,0x00000000ffffffff
+ dli $4,0xffffffffffffffff
+ dli $4,0x000fffffffffffff
+ dli $4,0xffffffff80001234
+ dli $4,0xffff800012345678
+ dli $4,0x8000123456780000
+ dli $4,0xffffffffffff8765
+ dli $4,0xffffffffffff4321
+
+ dli $4,0xfffffffffffffff0
+ dli $4,0xffffffffffffff00
+ dli $4,0xfffffffffffff000
+ dli $4,0xffffffffffff0000
+ dli $4,0xfffffffffff00000
+ dli $4,0xffffffffff000000
+ dli $4,0xfffffffff0000000
+ dli $4,0xffffffff00000000
+ dli $4,0xfffffff000000000
+ dli $4,0xffffff0000000000
+ dli $4,0xfffff00000000000
+ dli $4,0xffff000000000000
+ dli $4,0xfff0000000000000
+ dli $4,0xff00000000000000
+ dli $4,0xf000000000000000
+
+ dli $4,0x0fffffffffffffff
+ dli $4,0x00ffffffffffffff
+ dli $4,0x000fffffffffffff
+ dli $4,0x0000ffffffffffff
+ dli $4,0x00000fffffffffff
+ dli $4,0x000000ffffffffff
+ dli $4,0x0000000fffffffff
+ dli $4,0x00000000ffffffff
+ dli $4,0x000000000fffffff
+ dli $4,0x0000000000ffffff
+ dli $4,0x00000000000fffff
+ dli $4,0x000000000000ffff
+ dli $4,0x0000000000000fff
+ dli $4,0x00000000000000ff
+ dli $4,0x000000000000000f
+
+ dli $4,0x000000000003fffc
+ dli $4,0x00003fffc0000000
+ dli $4,0x0003fffc00000000
+ dli $4,0x003fffc000000000
+ dli $4,0x003fffffffc00000
+ dli $4,0x003ffffffffc0000
+ dli $4,0x003fffffffffc000
+
+ dli $4,0x003ffc03ffffc000
+
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+ nop
+ nop
+ nop
diff --git a/gas/testsuite/gas/mips/elf_e_flags.c b/gas/testsuite/gas/mips/elf_e_flags.c
new file mode 100644
index 0000000000..17fb1110c8
--- /dev/null
+++ b/gas/testsuite/gas/mips/elf_e_flags.c
@@ -0,0 +1,24 @@
+/* This file isn't directly used by the test suite; it uses
+ elf_e_flags.s. However, I figured it would be nice to provide the
+ source code from which the .s file was generated.
+
+ It was compiled as follows:
+
+ mips64-elf-gcc -m4650 -S -O elf_e_flags.c
+
+ We use the -m4650 flag to get the 4650-specific 'mul' instruction
+ in there; the test suite wants to be sure that GAS's -m4650 flag
+ will indeed cause it to generate the 4650 mul instruction, and not
+ expand it as a macro. */
+
+int
+foo (int a, int b)
+{
+ return (a * b) + 1;
+}
+
+int
+main ()
+{
+ return 0;
+}
diff --git a/gas/testsuite/gas/mips/elf_e_flags.s b/gas/testsuite/gas/mips/elf_e_flags.s
new file mode 100644
index 0000000000..5fc32eafd1
--- /dev/null
+++ b/gas/testsuite/gas/mips/elf_e_flags.s
@@ -0,0 +1,43 @@
+ .file 1 "elf_e_flags.c"
+gcc2_compiled.:
+__gnu_compiled_c:
+ .text
+ .align 2
+ .globl foo
+ .text
+ .ent foo
+foo:
+ .frame $sp,0,$31 # vars= 0, regs= 0/0, args= 0, extra= 0
+ .mask 0x00000000,0
+ .fmask 0x00000000,0
+ mul $2,$4,$5
+ .set noreorder
+ .set nomacro
+ j $31
+ addu $2,$2,1
+ .set macro
+ .set reorder
+
+ .end foo
+ .align 2
+ .globl main
+ .text
+ .ent main
+main:
+ .frame $sp,40,$31 # vars= 0, regs= 1/0, args= 32, extra= 0
+ .mask 0x80000000,-8
+ .fmask 0x00000000,0
+ subu $sp,$sp,40
+ sd $31,32($sp)
+ jal __gccmain
+ move $2,$0
+ ld $31,32($sp)
+ #nop
+ .set noreorder
+ .set nomacro
+ j $31
+ addu $sp,$sp,40
+ .set macro
+ .set reorder
+
+ .end main
diff --git a/gas/testsuite/gas/mips/elf_e_flags1.d b/gas/testsuite/gas/mips/elf_e_flags1.d
new file mode 100644
index 0000000000..6faa7c1032
--- /dev/null
+++ b/gas/testsuite/gas/mips/elf_e_flags1.d
@@ -0,0 +1,26 @@
+# name: ELF e_flags: nothing special
+# source: elf_e_flags.s
+# objdump: -fd
+
+.*:.*file format.*mips.*
+architecture: mips:4000, flags 0x00000011:
+HAS_RELOC, HAS_SYMS
+start address 0x0000000000000000
+
+Disassembly of section .text:
+
+0000000000000000 <foo>:
+ 0: 00850019 multu \$a0,\$a1
+ 4: 00001012 mflo \$v0
+ 8: 03e00008 jr \$ra
+ c: 24420001 addiu \$v0,\$v0,1
+
+0000000000000010 <main>:
+ 10: 27bdffd8 addiu \$sp,\$sp,-40
+ 14: ffbf0020 sd \$ra,32\(\$sp\)
+ 18: 0c000000 jal 0 <foo>
+ 1c: 00000000 nop
+ 20: 0000102d move \$v0,\$zero
+ 24: dfbf0020 ld \$ra,32\(\$sp\)
+ 28: 03e00008 jr \$ra
+ 2c: 27bd0028 addiu \$sp,\$sp,40
diff --git a/gas/testsuite/gas/mips/elf_e_flags2.d b/gas/testsuite/gas/mips/elf_e_flags2.d
new file mode 100644
index 0000000000..50661c2f96
--- /dev/null
+++ b/gas/testsuite/gas/mips/elf_e_flags2.d
@@ -0,0 +1,26 @@
+# name: ELF e_flags: -m4650
+# source: elf_e_flags.s
+# as: -m4650
+# objdump: -fd
+
+.*:.*file format.*mips.*
+architecture: mips:4650, flags 0x00000011:
+HAS_RELOC, HAS_SYMS
+start address 0x0000000000000000
+
+Disassembly of section .text:
+
+0000000000000000 <foo>:
+ 0: 70851002 mul \$v0,\$a0,\$a1
+ 4: 03e00008 jr \$ra
+ 8: 24420001 addiu \$v0,\$v0,1
+
+000000000000000c <main>:
+ c: 27bdffd8 addiu \$sp,\$sp,-40
+ 10: ffbf0020 sd \$ra,32\(\$sp\)
+ 14: 0c000000 jal 0 <foo>
+ 18: 00000000 nop
+ 1c: 0000102d move \$v0,\$zero
+ 20: dfbf0020 ld \$ra,32\(\$sp\)
+ 24: 03e00008 jr \$ra
+ 28: 27bd0028 addiu \$sp,\$sp,40
diff --git a/gas/testsuite/gas/mips/elf_e_flags3.d b/gas/testsuite/gas/mips/elf_e_flags3.d
new file mode 100644
index 0000000000..aacc49e40d
--- /dev/null
+++ b/gas/testsuite/gas/mips/elf_e_flags3.d
@@ -0,0 +1,26 @@
+# name: ELF e_flags: -mcpu=4650
+# source: elf_e_flags.s
+# as: -mcpu=4650
+# objdump: -fd
+
+.*:.*file format.*mips.*
+architecture: mips:4650, flags 0x00000011:
+HAS_RELOC, HAS_SYMS
+start address 0x0000000000000000
+
+Disassembly of section .text:
+
+0000000000000000 <foo>:
+ 0: 70851002 mul \$v0,\$a0,\$a1
+ 4: 03e00008 jr \$ra
+ 8: 24420001 addiu \$v0,\$v0,1
+
+000000000000000c <main>:
+ c: 27bdffd8 addiu \$sp,\$sp,-40
+ 10: ffbf0020 sd \$ra,32\(\$sp\)
+ 14: 0c000000 jal 0 <foo>
+ 18: 00000000 nop
+ 1c: 0000102d move \$v0,\$zero
+ 20: dfbf0020 ld \$ra,32\(\$sp\)
+ 24: 03e00008 jr \$ra
+ 28: 27bd0028 addiu \$sp,\$sp,40
diff --git a/gas/testsuite/gas/mips/elf_e_flags4.d b/gas/testsuite/gas/mips/elf_e_flags4.d
new file mode 100644
index 0000000000..5eb70508a2
--- /dev/null
+++ b/gas/testsuite/gas/mips/elf_e_flags4.d
@@ -0,0 +1,26 @@
+# name: ELF e_flags: -m4650 -mcpu=4650
+# source: elf_e_flags.s
+# as: -m4650 -mcpu=4650
+# objdump: -fd
+
+.*:.*file format.*mips.*
+architecture: mips:4650, flags 0x00000011:
+HAS_RELOC, HAS_SYMS
+start address 0x0000000000000000
+
+Disassembly of section .text:
+
+0000000000000000 <foo>:
+ 0: 70851002 mul \$v0,\$a0,\$a1
+ 4: 03e00008 jr \$ra
+ 8: 24420001 addiu \$v0,\$v0,1
+
+000000000000000c <main>:
+ c: 27bdffd8 addiu \$sp,\$sp,-40
+ 10: ffbf0020 sd \$ra,32\(\$sp\)
+ 14: 0c000000 jal 0 <foo>
+ 18: 00000000 nop
+ 1c: 0000102d move \$v0,\$zero
+ 20: dfbf0020 ld \$ra,32\(\$sp\)
+ 24: 03e00008 jr \$ra
+ 28: 27bd0028 addiu \$sp,\$sp,40
diff --git a/gas/testsuite/gas/mips/itbl b/gas/testsuite/gas/mips/itbl
new file mode 100644
index 0000000000..30f8a79f60
--- /dev/null
+++ b/gas/testsuite/gas/mips/itbl
@@ -0,0 +1,19 @@
+
+ ; Test case for assembler option "itbl".
+ ; Run as "as --itbl itbl itbl.s"
+ ; or with stand-alone test case "itbl-test itbl itbl.s".
+ ; Here, the processors represent mips coprocessors.
+
+ p1 dreg d1 1 ; data register "d1" for COP1 has value 1
+ p1 creg c3 3 ; ctrl register "c3" for COP1 has value 3
+ p3 insn fie 0x1e:24-20 ; function "fill" for COP3 has value 31
+ p3 dreg d3 3 ; data register "d3" for COP3 has value 3
+ p3 creg c2 22 ; control register "c2" for COP3 has value 22
+ p3 insn fee 0x1e:24-20,dreg:17-13,creg:12-8,immed:7-0
+
+ p3 dreg d3 3 ; data register "d3" for COP3 has value 3
+ p3 creg c2 22 ; control register "c2" for COP3 has value 22
+ p3 insn fum 0x01e00001 dreg:17-13 creg:12-8
+ p3 insn foh 0xf:24-21 dreg:20-16 immed:15-0
+
+ p3 insn pig 0x1:24-21*[0x100|0x2], dreg:20-16, immed:15-0*0x10000
diff --git a/gas/testsuite/gas/mips/itbl.s b/gas/testsuite/gas/mips/itbl.s
new file mode 100644
index 0000000000..085545be1c
--- /dev/null
+++ b/gas/testsuite/gas/mips/itbl.s
@@ -0,0 +1,18 @@
+
+ ; Test case for assembler option "itbl".
+ ; Run as "as --itbl itbl itbl.s"
+ ; or with stand-alone test case "itbl-test itbl itbl.s".
+
+ ; Call mips coprocessor "cofun"s as defined in "itbl".
+
+ fee $d3,$c2,0x1 ; 0x4ff07601
+ fie ; 0x4ff00000
+ foh $2,0x100
+ fum $d3,$c2 ; 0x4ff07601
+ pig $2,0x100
+
+ ; Call a mips coprocessor instruction with register "d1"
+ ; defined in "itbl".
+
+ LWC1 $d1,0x100($2)
+
diff --git a/gas/testsuite/gas/mips/jal-empic.d b/gas/testsuite/gas/mips/jal-empic.d
new file mode 100644
index 0000000000..c46ccfacc7
--- /dev/null
+++ b/gas/testsuite/gas/mips/jal-empic.d
@@ -0,0 +1,26 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS jal-empic
+#as: -mips1 -membedded-pic
+#source: jal.s
+
+# Test the jal macro with -membedded-pic.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> jalr \$t9
+0+0004 <[^>]*> nop
+0+0008 <[^>]*> jalr \$a0,\$t9
+0+000c <[^>]*> nop
+0+0010 <[^>]*> bal 0+0000 <text_label>
+[ ]*10: PCREL16 .text
+0+0014 <[^>]*> nop
+0+0018 <[^>]*> bal 0+0018 <text_label\+(0x|)18>
+[ ]*18: PCREL16 external_text_label
+0+001c <[^>]*> nop
+0+0020 <[^>]*> b 0+0000 <text_label>
+[ ]*20: PCREL16 .text
+0+0024 <[^>]*> nop
+0+0028 <[^>]*> b 0+0028 <text_label\+(0x|)28>
+[ ]*28: PCREL16 external_text_label
+0+002c <[^>]*> nop
diff --git a/gas/testsuite/gas/mips/jal-svr4pic.d b/gas/testsuite/gas/mips/jal-svr4pic.d
new file mode 100644
index 0000000000..b15be76248
--- /dev/null
+++ b/gas/testsuite/gas/mips/jal-svr4pic.d
@@ -0,0 +1,39 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS R3000 jal-svr4pic
+#as: -mips1 -KPIC -mcpu=r3000
+
+# Test the jal macro with -KPIC.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> lui \$gp,0x0
+[ ]*0: R_MIPS_HI16 _gp_disp
+0+0004 <[^>]*> addiu \$gp,\$gp,0
+[ ]*4: R_MIPS_LO16 _gp_disp
+0+0008 <[^>]*> addu \$gp,\$gp,\$t9
+0+000c <[^>]*> sw \$gp,0\(\$sp\)
+0+0010 <[^>]*> jalr \$t9
+0+0014 <[^>]*> nop
+0+0018 <[^>]*> lw \$gp,0\(\$sp\)
+0+001c <[^>]*> jalr \$a0,\$t9
+0+0020 <[^>]*> nop
+0+0024 <[^>]*> lw \$gp,0\(\$sp\)
+0+0028 <[^>]*> nop
+0+002c <[^>]*> lw \$t9,0\(\$gp\)
+[ ]*2c: R_MIPS_GOT16 .text
+0+0030 <[^>]*> nop
+0+0034 <[^>]*> addiu \$t9,\$t9,0
+[ ]*34: R_MIPS_LO16 .text
+0+0038 <[^>]*> jalr \$t9
+0+003c <[^>]*> nop
+0+0040 <[^>]*> lw \$gp,0\(\$sp\)
+0+0044 <[^>]*> nop
+0+0048 <[^>]*> lw \$t9,0\(\$gp\)
+[ ]*48: R_MIPS_CALL16 external_text_label
+0+004c <[^>]*> nop
+0+0050 <[^>]*> jalr \$t9
+0+0054 <[^>]*> nop
+0+0058 <[^>]*> lw \$gp,0\(\$sp\)
+0+005c <[^>]*> b 0+0000 <text_label>
+ ...
diff --git a/gas/testsuite/gas/mips/jal-svr4pic.s b/gas/testsuite/gas/mips/jal-svr4pic.s
new file mode 100644
index 0000000000..9d89dfa50f
--- /dev/null
+++ b/gas/testsuite/gas/mips/jal-svr4pic.s
@@ -0,0 +1,20 @@
+# Source file used to test the jal macro with -KPIC code.
+
+text_label:
+ .set noreorder
+ .cpload $25
+ .set reorder
+ .cprestore 0
+ jal $25
+ jal $4,$25
+ jal text_label
+ jal external_text_label
+
+# Test j as well
+ j text_label
+
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+ nop
+ nop
+ nop
+ nop
diff --git a/gas/testsuite/gas/mips/jal-xgot.d b/gas/testsuite/gas/mips/jal-xgot.d
new file mode 100644
index 0000000000..a26dca38b2
--- /dev/null
+++ b/gas/testsuite/gas/mips/jal-xgot.d
@@ -0,0 +1,42 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS R3000 jal-xgot
+#as: -mips1 -KPIC -xgot -mcpu=r3000
+#source: jal-svr4pic.s
+
+# Test the jal macro with -KPIC -xgot.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> lui \$gp,0x0
+[ ]*0: R_MIPS_HI16 _gp_disp
+0+0004 <[^>]*> addiu \$gp,\$gp,0
+[ ]*4: R_MIPS_LO16 _gp_disp
+0+0008 <[^>]*> addu \$gp,\$gp,\$t9
+0+000c <[^>]*> sw \$gp,0\(\$sp\)
+0+0010 <[^>]*> jalr \$t9
+0+0014 <[^>]*> nop
+0+0018 <[^>]*> lw \$gp,0\(\$sp\)
+0+001c <[^>]*> jalr \$a0,\$t9
+0+0020 <[^>]*> nop
+0+0024 <[^>]*> lw \$gp,0\(\$sp\)
+0+0028 <[^>]*> nop
+0+002c <[^>]*> lw \$t9,0\(\$gp\)
+[ ]*2c: R_MIPS_GOT16 .text
+0+0030 <[^>]*> nop
+0+0034 <[^>]*> addiu \$t9,\$t9,0
+[ ]*34: R_MIPS_LO16 .text
+0+0038 <[^>]*> jalr \$t9
+0+003c <[^>]*> nop
+0+0040 <[^>]*> lw \$gp,0\(\$sp\)
+0+0044 <[^>]*> lui \$t9,0x0
+[ ]*44: R_MIPS_CALL_HI16 external_text_label
+0+0048 <[^>]*> addu \$t9,\$t9,\$gp
+0+004c <[^>]*> lw \$t9,0\(\$t9\)
+[ ]*4c: R_MIPS_CALL_LO16 external_text_label
+0+0050 <[^>]*> nop
+0+0054 <[^>]*> jalr \$t9
+0+0058 <[^>]*> nop
+0+005c <[^>]*> lw \$gp,0\(\$sp\)
+0+0060 <[^>]*> b 0+0000 <text_label>
+ ...
diff --git a/gas/testsuite/gas/mips/jal.d b/gas/testsuite/gas/mips/jal.d
new file mode 100644
index 0000000000..b7b586f212
--- /dev/null
+++ b/gas/testsuite/gas/mips/jal.d
@@ -0,0 +1,24 @@
+#objdump: -dr --prefix-addresses -mmips:4000
+#name: MIPS jal
+
+# Test the jal macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> jalr \$t9
+0+0004 <[^>]*> nop
+0+0008 <[^>]*> jalr \$a0,\$t9
+0+000c <[^>]*> nop
+0+0010 <[^>]*> jal 0+ <text_label>
+[ ]*10: (MIPS_JMP|MIPS_JMP|JMPADDR|R_MIPS_26) .text
+0+0014 <[^>]*> nop
+0+0018 <[^>]*> jal 0+ <text_label>
+[ ]*18: (MIPS_JMP|JMPADDR|R_MIPS_26) external_text_label
+0+001c <[^>]*> nop
+0+0020 <[^>]*> j 0+ <text_label>
+[ ]*20: (MIPS_JMP|JMPADDR|R_MIPS_26) .text
+0+0024 <[^>]*> nop
+0+0028 <[^>]*> j 0+ <text_label>
+[ ]*28: (MIPS_JMP|JMPADDR|R_MIPS_26) external_text_label
+0+002c <[^>]*> nop
diff --git a/gas/testsuite/gas/mips/jal.s b/gas/testsuite/gas/mips/jal.s
new file mode 100644
index 0000000000..379be9502a
--- /dev/null
+++ b/gas/testsuite/gas/mips/jal.s
@@ -0,0 +1,11 @@
+# Source file used to test the jal macro.
+ .globl text_label .text
+text_label:
+ jal $25
+ jal $4,$25
+ jal text_label
+ jal external_text_label
+
+# Test j as well
+ j text_label
+ j external_text_label
diff --git a/gas/testsuite/gas/mips/la-empic.d b/gas/testsuite/gas/mips/la-empic.d
new file mode 100644
index 0000000000..af29570d0b
--- /dev/null
+++ b/gas/testsuite/gas/mips/la-empic.d
@@ -0,0 +1,105 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS la-empic
+#as: -mips1 -membedded-pic
+
+# Test the la macro with -membedded-pic.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> li \$a0,0
+0+0004 <[^>]*> li \$a0,1
+0+0008 <[^>]*> li \$a0,0x8000
+0+000c <[^>]*> li \$a0,-32768
+0+0010 <[^>]*> lui \$a0,0x1
+0+0014 <[^>]*> lui \$a0,0x1
+0+0018 <[^>]*> ori \$a0,\$a0,0xa5a5
+0+001c <[^>]*> li \$a0,0
+0+0020 <[^>]*> addu \$a0,\$a0,\$a1
+0+0024 <[^>]*> li \$a0,1
+0+0028 <[^>]*> addu \$a0,\$a0,\$a1
+0+002c <[^>]*> li \$a0,0x8000
+0+0030 <[^>]*> addu \$a0,\$a0,\$a1
+0+0034 <[^>]*> li \$a0,-32768
+0+0038 <[^>]*> addu \$a0,\$a0,\$a1
+0+003c <[^>]*> lui \$a0,0x1
+0+0040 <[^>]*> addu \$a0,\$a0,\$a1
+0+0044 <[^>]*> lui \$a0,0x1
+0+0048 <[^>]*> ori \$a0,\$a0,0xa5a5
+0+004c <[^>]*> addu \$a0,\$a0,\$a1
+0+0050 <[^>]*> addiu \$a0,\$gp,-16384
+[ ]*50: [A-Z0-9_]*GPREL[A-Z0-9_]* .sdata.*
+0+0054 <[^>]*> addiu \$a0,\$gp,0
+[ ]*54: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_data_label
+0+0058 <[^>]*> addiu \$a0,\$gp,0
+[ ]*58: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+005c <[^>]*> addiu \$a0,\$gp,0
+[ ]*5c: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_common
+0+0060 <[^>]*> addiu \$a0,\$gp,0
+[ ]*60: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+0064 <[^>]*> addiu \$a0,\$gp,-16384
+[ ]*64: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0068 <[^>]*> addiu \$a0,\$gp,-15384
+[ ]*68: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+006c <[^>]*> addiu \$a0,\$gp,-16383
+[ ]*6c: [A-Z0-9_]*GPREL[A-Z0-9_]* .sdata.*
+0+0070 <[^>]*> addiu \$a0,\$gp,1
+[ ]*70: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_data_label
+0+0074 <[^>]*> addiu \$a0,\$gp,1
+[ ]*74: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+0078 <[^>]*> addiu \$a0,\$gp,1
+[ ]*78: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_common
+0+007c <[^>]*> addiu \$a0,\$gp,1
+[ ]*7c: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+0080 <[^>]*> addiu \$a0,\$gp,-16383
+[ ]*80: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0084 <[^>]*> addiu \$a0,\$gp,-15383
+[ ]*84: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0088 <[^>]*> addiu \$a0,\$gp,-16384
+[ ]*88: [A-Z0-9_]*GPREL[A-Z0-9_]* .sdata.*
+0+008c <[^>]*> addu \$a0,\$a0,\$a1
+0+0090 <[^>]*> addiu \$a0,\$gp,0
+[ ]*90: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_data_label
+0+0094 <[^>]*> addu \$a0,\$a0,\$a1
+0+0098 <[^>]*> addiu \$a0,\$gp,0
+[ ]*98: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+009c <[^>]*> addu \$a0,\$a0,\$a1
+0+00a0 <[^>]*> addiu \$a0,\$gp,0
+[ ]*a0: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_common
+0+00a4 <[^>]*> addu \$a0,\$a0,\$a1
+0+00a8 <[^>]*> addiu \$a0,\$gp,0
+[ ]*a8: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+00ac <[^>]*> addu \$a0,\$a0,\$a1
+0+00b0 <[^>]*> addiu \$a0,\$gp,-16384
+[ ]*b0: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00b4 <[^>]*> addu \$a0,\$a0,\$a1
+0+00b8 <[^>]*> addiu \$a0,\$gp,-15384
+[ ]*b8: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00bc <[^>]*> addu \$a0,\$a0,\$a1
+0+00c0 <[^>]*> addiu \$a0,\$gp,-16383
+[ ]*c0: [A-Z0-9_]*GPREL[A-Z0-9_]* .sdata.*
+0+00c4 <[^>]*> addu \$a0,\$a0,\$a1
+0+00c8 <[^>]*> addiu \$a0,\$gp,1
+[ ]*c8: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_data_label
+0+00cc <[^>]*> addu \$a0,\$a0,\$a1
+0+00d0 <[^>]*> addiu \$a0,\$gp,1
+[ ]*d0: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00d4 <[^>]*> addu \$a0,\$a0,\$a1
+0+00d8 <[^>]*> addiu \$a0,\$gp,1
+[ ]*d8: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_common
+0+00dc <[^>]*> addu \$a0,\$a0,\$a1
+0+00e0 <[^>]*> addiu \$a0,\$gp,1
+[ ]*e0: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+00e4 <[^>]*> addu \$a0,\$a0,\$a1
+0+00e8 <[^>]*> addiu \$a0,\$gp,-16383
+[ ]*e8: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00ec <[^>]*> addu \$a0,\$a0,\$a1
+0+00f0 <[^>]*> addiu \$a0,\$gp,-15383
+[ ]*f0: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00f4 <[^>]*> addu \$a0,\$a0,\$a1
+0+00f8 <[^>]*> lui \$a0,0x0
+[ ]*f8: RELHI external_text_label
+0+00fc <[^>]*> addiu \$a0,\$a0,252
+[ ]*fc: RELLO external_text_label
+0+0100 <[^>]*> li \$a0,248
+ ...
diff --git a/gas/testsuite/gas/mips/la-empic.s b/gas/testsuite/gas/mips/la-empic.s
new file mode 100644
index 0000000000..c6df5e3b58
--- /dev/null
+++ b/gas/testsuite/gas/mips/la-empic.s
@@ -0,0 +1,57 @@
+# Source file used to test the la macro with -membedded-pic
+
+ .data
+data_label:
+ .extern big_external_data_label,1000
+ .extern small_external_data_label,1
+ .comm big_external_common,1000
+ .comm small_external_common,1
+ .lcomm big_local_common,1000
+ .lcomm small_local_common,1
+
+ .text
+text_label:
+ la $4,0
+ la $4,1
+ la $4,0x8000
+ la $4,-0x8000
+ la $4,0x10000
+ la $4,0x1a5a5
+ la $4,0($5)
+ la $4,1($5)
+ la $4,0x8000($5)
+ la $4,-0x8000($5)
+ la $4,0x10000($5)
+ la $4,0x1a5a5($5)
+ la $4,data_label
+ la $4,big_external_data_label
+ la $4,small_external_data_label
+ la $4,big_external_common
+ la $4,small_external_common
+ la $4,big_local_common
+ la $4,small_local_common
+ la $4,data_label+1
+ la $4,big_external_data_label+1
+ la $4,small_external_data_label+1
+ la $4,big_external_common+1
+ la $4,small_external_common+1
+ la $4,big_local_common+1
+ la $4,small_local_common+1
+ la $4,data_label($5)
+ la $4,big_external_data_label($5)
+ la $4,small_external_data_label($5)
+ la $4,big_external_common($5)
+ la $4,small_external_common($5)
+ la $4,big_local_common($5)
+ la $4,small_local_common($5)
+ la $4,data_label+1($5)
+ la $4,big_external_data_label+1($5)
+ la $4,small_external_data_label+1($5)
+ la $4,big_external_common+1($5)
+ la $4,small_external_common+1($5)
+ la $4,big_local_common+1($5)
+ la $4,small_local_common+1($5)
+
+second_text_label:
+ la $4,external_text_label - text_label
+ la $4,second_text_label - text_label
diff --git a/gas/testsuite/gas/mips/la-svr4pic.d b/gas/testsuite/gas/mips/la-svr4pic.d
new file mode 100644
index 0000000000..4e8a3d54f4
--- /dev/null
+++ b/gas/testsuite/gas/mips/la-svr4pic.d
@@ -0,0 +1,474 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS la-svr4pic
+#as: -mips1 -KPIC --defsym KPIC=1
+#source: la.s
+
+# Test the la macro with -KPIC.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> li \$a0,0
+0+0004 <[^>]*> li \$a0,1
+0+0008 <[^>]*> li \$a0,0x8000
+0+000c <[^>]*> li \$a0,-32768
+0+0010 <[^>]*> lui \$a0,0x1
+0+0014 <[^>]*> lui \$a0,0x1
+0+0018 <[^>]*> ori \$a0,\$a0,0xa5a5
+0+001c <[^>]*> li \$a0,0
+0+0020 <[^>]*> addu \$a0,\$a0,\$a1
+0+0024 <[^>]*> li \$a0,1
+0+0028 <[^>]*> addu \$a0,\$a0,\$a1
+0+002c <[^>]*> li \$a0,0x8000
+0+0030 <[^>]*> addu \$a0,\$a0,\$a1
+0+0034 <[^>]*> li \$a0,-32768
+0+0038 <[^>]*> addu \$a0,\$a0,\$a1
+0+003c <[^>]*> lui \$a0,0x1
+0+0040 <[^>]*> addu \$a0,\$a0,\$a1
+0+0044 <[^>]*> lui \$a0,0x1
+0+0048 <[^>]*> ori \$a0,\$a0,0xa5a5
+0+004c <[^>]*> addu \$a0,\$a0,\$a1
+0+0050 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*50: R_MIPS_GOT16 .data
+0+0054 <[^>]*> nop
+0+0058 <[^>]*> addiu \$a0,\$a0,0
+[ ]*58: R_MIPS_LO16 .data
+0+005c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*5c: R_MIPS_GOT16 big_external_data_label
+0+0060 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*60: R_MIPS_GOT16 small_external_data_label
+0+0064 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*64: R_MIPS_GOT16 big_external_common
+0+0068 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*68: R_MIPS_GOT16 small_external_common
+0+006c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*6c: R_MIPS_GOT16 .bss
+0+0070 <[^>]*> nop
+0+0074 <[^>]*> addiu \$a0,\$a0,0
+[ ]*74: R_MIPS_LO16 .bss
+0+0078 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*78: R_MIPS_GOT16 .bss
+0+007c <[^>]*> nop
+0+0080 <[^>]*> addiu \$a0,\$a0,1000
+[ ]*80: R_MIPS_LO16 .bss
+0+0084 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*84: R_MIPS_GOT16 .data
+0+0088 <[^>]*> nop
+0+008c <[^>]*> addiu \$a0,\$a0,1
+[ ]*8c: R_MIPS_LO16 .data
+0+0090 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*90: R_MIPS_GOT16 big_external_data_label
+0+0094 <[^>]*> nop
+0+0098 <[^>]*> addiu \$a0,\$a0,1
+0+009c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*9c: R_MIPS_GOT16 small_external_data_label
+0+00a0 <[^>]*> nop
+0+00a4 <[^>]*> addiu \$a0,\$a0,1
+0+00a8 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*a8: R_MIPS_GOT16 big_external_common
+0+00ac <[^>]*> nop
+0+00b0 <[^>]*> addiu \$a0,\$a0,1
+0+00b4 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*b4: R_MIPS_GOT16 small_external_common
+0+00b8 <[^>]*> nop
+0+00bc <[^>]*> addiu \$a0,\$a0,1
+0+00c0 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*c0: R_MIPS_GOT16 .bss
+0+00c4 <[^>]*> nop
+0+00c8 <[^>]*> addiu \$a0,\$a0,1
+[ ]*c8: R_MIPS_LO16 .bss
+0+00cc <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*cc: R_MIPS_GOT16 .bss
+0+00d0 <[^>]*> nop
+0+00d4 <[^>]*> addiu \$a0,\$a0,1001
+[ ]*d4: R_MIPS_LO16 .bss
+0+00d8 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*d8: R_MIPS_GOT16 .data
+0+00dc <[^>]*> lui \$at,0x1
+0+00e0 <[^>]*> addiu \$at,\$at,-32768
+[ ]*e0: R_MIPS_LO16 .data
+0+00e4 <[^>]*> addu \$a0,\$a0,\$at
+0+00e8 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*e8: R_MIPS_GOT16 big_external_data_label
+0+00ec <[^>]*> lui \$at,0x1
+0+00f0 <[^>]*> addiu \$at,\$at,-32768
+0+00f4 <[^>]*> addu \$a0,\$a0,\$at
+0+00f8 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*f8: R_MIPS_GOT16 small_external_data_label
+0+00fc <[^>]*> lui \$at,0x1
+0+0100 <[^>]*> addiu \$at,\$at,-32768
+0+0104 <[^>]*> addu \$a0,\$a0,\$at
+0+0108 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*108: R_MIPS_GOT16 big_external_common
+0+010c <[^>]*> lui \$at,0x1
+0+0110 <[^>]*> addiu \$at,\$at,-32768
+0+0114 <[^>]*> addu \$a0,\$a0,\$at
+0+0118 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*118: R_MIPS_GOT16 small_external_common
+0+011c <[^>]*> lui \$at,0x1
+0+0120 <[^>]*> addiu \$at,\$at,-32768
+0+0124 <[^>]*> addu \$a0,\$a0,\$at
+0+0128 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*128: R_MIPS_GOT16 .bss
+0+012c <[^>]*> lui \$at,0x1
+0+0130 <[^>]*> addiu \$at,\$at,-32768
+[ ]*130: R_MIPS_LO16 .bss
+0+0134 <[^>]*> addu \$a0,\$a0,\$at
+0+0138 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*138: R_MIPS_GOT16 .bss
+0+013c <[^>]*> lui \$at,0x1
+0+0140 <[^>]*> addiu \$at,\$at,-31768
+[ ]*140: R_MIPS_LO16 .bss
+0+0144 <[^>]*> addu \$a0,\$a0,\$at
+0+0148 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*148: R_MIPS_GOT16 .data
+0+014c <[^>]*> nop
+0+0150 <[^>]*> addiu \$a0,\$a0,-32768
+[ ]*150: R_MIPS_LO16 .data
+0+0154 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*154: R_MIPS_GOT16 big_external_data_label
+0+0158 <[^>]*> nop
+0+015c <[^>]*> addiu \$a0,\$a0,-32768
+0+0160 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*160: R_MIPS_GOT16 small_external_data_label
+0+0164 <[^>]*> nop
+0+0168 <[^>]*> addiu \$a0,\$a0,-32768
+0+016c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*16c: R_MIPS_GOT16 big_external_common
+0+0170 <[^>]*> nop
+0+0174 <[^>]*> addiu \$a0,\$a0,-32768
+0+0178 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*178: R_MIPS_GOT16 small_external_common
+0+017c <[^>]*> nop
+0+0180 <[^>]*> addiu \$a0,\$a0,-32768
+0+0184 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*184: R_MIPS_GOT16 .bss
+0+0188 <[^>]*> nop
+0+018c <[^>]*> addiu \$a0,\$a0,-32768
+[ ]*18c: R_MIPS_LO16 .bss
+0+0190 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*190: R_MIPS_GOT16 .bss
+0+0194 <[^>]*> nop
+0+0198 <[^>]*> addiu \$a0,\$a0,-31768
+[ ]*198: R_MIPS_LO16 .bss
+0+019c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*19c: R_MIPS_GOT16 .data
+0+01a0 <[^>]*> lui \$at,0x1
+0+01a4 <[^>]*> addiu \$at,\$at,0
+[ ]*1a4: R_MIPS_LO16 .data
+0+01a8 <[^>]*> addu \$a0,\$a0,\$at
+0+01ac <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*1ac: R_MIPS_GOT16 big_external_data_label
+0+01b0 <[^>]*> lui \$at,0x1
+0+01b4 <[^>]*> addiu \$at,\$at,0
+0+01b8 <[^>]*> addu \$a0,\$a0,\$at
+0+01bc <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*1bc: R_MIPS_GOT16 small_external_data_label
+0+01c0 <[^>]*> lui \$at,0x1
+0+01c4 <[^>]*> addiu \$at,\$at,0
+0+01c8 <[^>]*> addu \$a0,\$a0,\$at
+0+01cc <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*1cc: R_MIPS_GOT16 big_external_common
+0+01d0 <[^>]*> lui \$at,0x1
+0+01d4 <[^>]*> addiu \$at,\$at,0
+0+01d8 <[^>]*> addu \$a0,\$a0,\$at
+0+01dc <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*1dc: R_MIPS_GOT16 small_external_common
+0+01e0 <[^>]*> lui \$at,0x1
+0+01e4 <[^>]*> addiu \$at,\$at,0
+0+01e8 <[^>]*> addu \$a0,\$a0,\$at
+0+01ec <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*1ec: R_MIPS_GOT16 .bss
+0+01f0 <[^>]*> lui \$at,0x1
+0+01f4 <[^>]*> addiu \$at,\$at,0
+[ ]*1f4: R_MIPS_LO16 .bss
+0+01f8 <[^>]*> addu \$a0,\$a0,\$at
+0+01fc <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*1fc: R_MIPS_GOT16 .bss
+0+0200 <[^>]*> lui \$at,0x1
+0+0204 <[^>]*> addiu \$at,\$at,1000
+[ ]*204: R_MIPS_LO16 .bss
+0+0208 <[^>]*> addu \$a0,\$a0,\$at
+0+020c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*20c: R_MIPS_GOT16 .data
+0+0210 <[^>]*> lui \$at,0x2
+0+0214 <[^>]*> addiu \$at,\$at,-23131
+[ ]*214: R_MIPS_LO16 .data
+0+0218 <[^>]*> addu \$a0,\$a0,\$at
+0+021c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*21c: R_MIPS_GOT16 big_external_data_label
+0+0220 <[^>]*> lui \$at,0x2
+0+0224 <[^>]*> addiu \$at,\$at,-23131
+0+0228 <[^>]*> addu \$a0,\$a0,\$at
+0+022c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*22c: R_MIPS_GOT16 small_external_data_label
+0+0230 <[^>]*> lui \$at,0x2
+0+0234 <[^>]*> addiu \$at,\$at,-23131
+0+0238 <[^>]*> addu \$a0,\$a0,\$at
+0+023c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*23c: R_MIPS_GOT16 big_external_common
+0+0240 <[^>]*> lui \$at,0x2
+0+0244 <[^>]*> addiu \$at,\$at,-23131
+0+0248 <[^>]*> addu \$a0,\$a0,\$at
+0+024c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*24c: R_MIPS_GOT16 small_external_common
+0+0250 <[^>]*> lui \$at,0x2
+0+0254 <[^>]*> addiu \$at,\$at,-23131
+0+0258 <[^>]*> addu \$a0,\$a0,\$at
+0+025c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*25c: R_MIPS_GOT16 .bss
+0+0260 <[^>]*> lui \$at,0x2
+0+0264 <[^>]*> addiu \$at,\$at,-23131
+[ ]*264: R_MIPS_LO16 .bss
+0+0268 <[^>]*> addu \$a0,\$a0,\$at
+0+026c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*26c: R_MIPS_GOT16 .bss
+0+0270 <[^>]*> lui \$at,0x2
+0+0274 <[^>]*> addiu \$at,\$at,-22131
+[ ]*274: R_MIPS_LO16 .bss
+0+0278 <[^>]*> addu \$a0,\$a0,\$at
+0+027c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*27c: R_MIPS_GOT16 .data
+0+0280 <[^>]*> nop
+0+0284 <[^>]*> addiu \$a0,\$a0,0
+[ ]*284: R_MIPS_LO16 .data
+0+0288 <[^>]*> addu \$a0,\$a0,\$a1
+0+028c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*28c: R_MIPS_GOT16 big_external_data_label
+0+0290 <[^>]*> nop
+0+0294 <[^>]*> addu \$a0,\$a0,\$a1
+0+0298 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*298: R_MIPS_GOT16 small_external_data_label
+0+029c <[^>]*> nop
+0+02a0 <[^>]*> addu \$a0,\$a0,\$a1
+0+02a4 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*2a4: R_MIPS_GOT16 big_external_common
+0+02a8 <[^>]*> nop
+0+02ac <[^>]*> addu \$a0,\$a0,\$a1
+0+02b0 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*2b0: R_MIPS_GOT16 small_external_common
+0+02b4 <[^>]*> nop
+0+02b8 <[^>]*> addu \$a0,\$a0,\$a1
+0+02bc <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*2bc: R_MIPS_GOT16 .bss
+0+02c0 <[^>]*> nop
+0+02c4 <[^>]*> addiu \$a0,\$a0,0
+[ ]*2c4: R_MIPS_LO16 .bss
+0+02c8 <[^>]*> addu \$a0,\$a0,\$a1
+0+02cc <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*2cc: R_MIPS_GOT16 .bss
+0+02d0 <[^>]*> nop
+0+02d4 <[^>]*> addiu \$a0,\$a0,1000
+[ ]*2d4: R_MIPS_LO16 .bss
+0+02d8 <[^>]*> addu \$a0,\$a0,\$a1
+0+02dc <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*2dc: R_MIPS_GOT16 .data
+0+02e0 <[^>]*> nop
+0+02e4 <[^>]*> addiu \$a0,\$a0,1
+[ ]*2e4: R_MIPS_LO16 .data
+0+02e8 <[^>]*> addu \$a0,\$a0,\$a1
+0+02ec <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*2ec: R_MIPS_GOT16 big_external_data_label
+0+02f0 <[^>]*> nop
+0+02f4 <[^>]*> addiu \$a0,\$a0,1
+0+02f8 <[^>]*> addu \$a0,\$a0,\$a1
+0+02fc <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*2fc: R_MIPS_GOT16 small_external_data_label
+0+0300 <[^>]*> nop
+0+0304 <[^>]*> addiu \$a0,\$a0,1
+0+0308 <[^>]*> addu \$a0,\$a0,\$a1
+0+030c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*30c: R_MIPS_GOT16 big_external_common
+0+0310 <[^>]*> nop
+0+0314 <[^>]*> addiu \$a0,\$a0,1
+0+0318 <[^>]*> addu \$a0,\$a0,\$a1
+0+031c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*31c: R_MIPS_GOT16 small_external_common
+0+0320 <[^>]*> nop
+0+0324 <[^>]*> addiu \$a0,\$a0,1
+0+0328 <[^>]*> addu \$a0,\$a0,\$a1
+0+032c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*32c: R_MIPS_GOT16 .bss
+0+0330 <[^>]*> nop
+0+0334 <[^>]*> addiu \$a0,\$a0,1
+[ ]*334: R_MIPS_LO16 .bss
+0+0338 <[^>]*> addu \$a0,\$a0,\$a1
+0+033c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*33c: R_MIPS_GOT16 .bss
+0+0340 <[^>]*> nop
+0+0344 <[^>]*> addiu \$a0,\$a0,1001
+[ ]*344: R_MIPS_LO16 .bss
+0+0348 <[^>]*> addu \$a0,\$a0,\$a1
+0+034c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*34c: R_MIPS_GOT16 .data
+0+0350 <[^>]*> lui \$at,0x1
+0+0354 <[^>]*> addiu \$at,\$at,-32768
+[ ]*354: R_MIPS_LO16 .data
+0+0358 <[^>]*> addu \$a0,\$a0,\$at
+0+035c <[^>]*> addu \$a0,\$a0,\$a1
+0+0360 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*360: R_MIPS_GOT16 big_external_data_label
+0+0364 <[^>]*> lui \$at,0x1
+0+0368 <[^>]*> addiu \$at,\$at,-32768
+0+036c <[^>]*> addu \$a0,\$a0,\$at
+0+0370 <[^>]*> addu \$a0,\$a0,\$a1
+0+0374 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*374: R_MIPS_GOT16 small_external_data_label
+0+0378 <[^>]*> lui \$at,0x1
+0+037c <[^>]*> addiu \$at,\$at,-32768
+0+0380 <[^>]*> addu \$a0,\$a0,\$at
+0+0384 <[^>]*> addu \$a0,\$a0,\$a1
+0+0388 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*388: R_MIPS_GOT16 big_external_common
+0+038c <[^>]*> lui \$at,0x1
+0+0390 <[^>]*> addiu \$at,\$at,-32768
+0+0394 <[^>]*> addu \$a0,\$a0,\$at
+0+0398 <[^>]*> addu \$a0,\$a0,\$a1
+0+039c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*39c: R_MIPS_GOT16 small_external_common
+0+03a0 <[^>]*> lui \$at,0x1
+0+03a4 <[^>]*> addiu \$at,\$at,-32768
+0+03a8 <[^>]*> addu \$a0,\$a0,\$at
+0+03ac <[^>]*> addu \$a0,\$a0,\$a1
+0+03b0 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*3b0: R_MIPS_GOT16 .bss
+0+03b4 <[^>]*> lui \$at,0x1
+0+03b8 <[^>]*> addiu \$at,\$at,-32768
+[ ]*3b8: R_MIPS_LO16 .bss
+0+03bc <[^>]*> addu \$a0,\$a0,\$at
+0+03c0 <[^>]*> addu \$a0,\$a0,\$a1
+0+03c4 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*3c4: R_MIPS_GOT16 .bss
+0+03c8 <[^>]*> lui \$at,0x1
+0+03cc <[^>]*> addiu \$at,\$at,-31768
+[ ]*3cc: R_MIPS_LO16 .bss
+0+03d0 <[^>]*> addu \$a0,\$a0,\$at
+0+03d4 <[^>]*> addu \$a0,\$a0,\$a1
+0+03d8 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*3d8: R_MIPS_GOT16 .data
+0+03dc <[^>]*> nop
+0+03e0 <[^>]*> addiu \$a0,\$a0,-32768
+[ ]*3e0: R_MIPS_LO16 .data
+0+03e4 <[^>]*> addu \$a0,\$a0,\$a1
+0+03e8 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*3e8: R_MIPS_GOT16 big_external_data_label
+0+03ec <[^>]*> nop
+0+03f0 <[^>]*> addiu \$a0,\$a0,-32768
+0+03f4 <[^>]*> addu \$a0,\$a0,\$a1
+0+03f8 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*3f8: R_MIPS_GOT16 small_external_data_label
+0+03fc <[^>]*> nop
+0+0400 <[^>]*> addiu \$a0,\$a0,-32768
+0+0404 <[^>]*> addu \$a0,\$a0,\$a1
+0+0408 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*408: R_MIPS_GOT16 big_external_common
+0+040c <[^>]*> nop
+0+0410 <[^>]*> addiu \$a0,\$a0,-32768
+0+0414 <[^>]*> addu \$a0,\$a0,\$a1
+0+0418 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*418: R_MIPS_GOT16 small_external_common
+0+041c <[^>]*> nop
+0+0420 <[^>]*> addiu \$a0,\$a0,-32768
+0+0424 <[^>]*> addu \$a0,\$a0,\$a1
+0+0428 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*428: R_MIPS_GOT16 .bss
+0+042c <[^>]*> nop
+0+0430 <[^>]*> addiu \$a0,\$a0,-32768
+[ ]*430: R_MIPS_LO16 .bss
+0+0434 <[^>]*> addu \$a0,\$a0,\$a1
+0+0438 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*438: R_MIPS_GOT16 .bss
+0+043c <[^>]*> nop
+0+0440 <[^>]*> addiu \$a0,\$a0,-31768
+[ ]*440: R_MIPS_LO16 .bss
+0+0444 <[^>]*> addu \$a0,\$a0,\$a1
+0+0448 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*448: R_MIPS_GOT16 .data
+0+044c <[^>]*> lui \$at,0x1
+0+0450 <[^>]*> addiu \$at,\$at,0
+[ ]*450: R_MIPS_LO16 .data
+0+0454 <[^>]*> addu \$a0,\$a0,\$at
+0+0458 <[^>]*> addu \$a0,\$a0,\$a1
+0+045c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*45c: R_MIPS_GOT16 big_external_data_label
+0+0460 <[^>]*> lui \$at,0x1
+0+0464 <[^>]*> addiu \$at,\$at,0
+0+0468 <[^>]*> addu \$a0,\$a0,\$at
+0+046c <[^>]*> addu \$a0,\$a0,\$a1
+0+0470 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*470: R_MIPS_GOT16 small_external_data_label
+0+0474 <[^>]*> lui \$at,0x1
+0+0478 <[^>]*> addiu \$at,\$at,0
+0+047c <[^>]*> addu \$a0,\$a0,\$at
+0+0480 <[^>]*> addu \$a0,\$a0,\$a1
+0+0484 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*484: R_MIPS_GOT16 big_external_common
+0+0488 <[^>]*> lui \$at,0x1
+0+048c <[^>]*> addiu \$at,\$at,0
+0+0490 <[^>]*> addu \$a0,\$a0,\$at
+0+0494 <[^>]*> addu \$a0,\$a0,\$a1
+0+0498 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*498: R_MIPS_GOT16 small_external_common
+0+049c <[^>]*> lui \$at,0x1
+0+04a0 <[^>]*> addiu \$at,\$at,0
+0+04a4 <[^>]*> addu \$a0,\$a0,\$at
+0+04a8 <[^>]*> addu \$a0,\$a0,\$a1
+0+04ac <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*4ac: R_MIPS_GOT16 .bss
+0+04b0 <[^>]*> lui \$at,0x1
+0+04b4 <[^>]*> addiu \$at,\$at,0
+[ ]*4b4: R_MIPS_LO16 .bss
+0+04b8 <[^>]*> addu \$a0,\$a0,\$at
+0+04bc <[^>]*> addu \$a0,\$a0,\$a1
+0+04c0 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*4c0: R_MIPS_GOT16 .bss
+0+04c4 <[^>]*> lui \$at,0x1
+0+04c8 <[^>]*> addiu \$at,\$at,1000
+[ ]*4c8: R_MIPS_LO16 .bss
+0+04cc <[^>]*> addu \$a0,\$a0,\$at
+0+04d0 <[^>]*> addu \$a0,\$a0,\$a1
+0+04d4 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*4d4: R_MIPS_GOT16 .data
+0+04d8 <[^>]*> lui \$at,0x2
+0+04dc <[^>]*> addiu \$at,\$at,-23131
+[ ]*4dc: R_MIPS_LO16 .data
+0+04e0 <[^>]*> addu \$a0,\$a0,\$at
+0+04e4 <[^>]*> addu \$a0,\$a0,\$a1
+0+04e8 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*4e8: R_MIPS_GOT16 big_external_data_label
+0+04ec <[^>]*> lui \$at,0x2
+0+04f0 <[^>]*> addiu \$at,\$at,-23131
+0+04f4 <[^>]*> addu \$a0,\$a0,\$at
+0+04f8 <[^>]*> addu \$a0,\$a0,\$a1
+0+04fc <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*4fc: R_MIPS_GOT16 small_external_data_label
+0+0500 <[^>]*> lui \$at,0x2
+0+0504 <[^>]*> addiu \$at,\$at,-23131
+0+0508 <[^>]*> addu \$a0,\$a0,\$at
+0+050c <[^>]*> addu \$a0,\$a0,\$a1
+0+0510 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*510: R_MIPS_GOT16 big_external_common
+0+0514 <[^>]*> lui \$at,0x2
+0+0518 <[^>]*> addiu \$at,\$at,-23131
+0+051c <[^>]*> addu \$a0,\$a0,\$at
+0+0520 <[^>]*> addu \$a0,\$a0,\$a1
+0+0524 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*524: R_MIPS_GOT16 small_external_common
+0+0528 <[^>]*> lui \$at,0x2
+0+052c <[^>]*> addiu \$at,\$at,-23131
+0+0530 <[^>]*> addu \$a0,\$a0,\$at
+0+0534 <[^>]*> addu \$a0,\$a0,\$a1
+0+0538 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*538: R_MIPS_GOT16 .bss
+0+053c <[^>]*> lui \$at,0x2
+0+0540 <[^>]*> addiu \$at,\$at,-23131
+[ ]*540: R_MIPS_LO16 .bss
+0+0544 <[^>]*> addu \$a0,\$a0,\$at
+0+0548 <[^>]*> addu \$a0,\$a0,\$a1
+0+054c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*54c: R_MIPS_GOT16 .bss
+0+0550 <[^>]*> lui \$at,0x2
+0+0554 <[^>]*> addiu \$at,\$at,-22131
+[ ]*554: R_MIPS_LO16 .bss
+0+0558 <[^>]*> addu \$a0,\$a0,\$at
+0+055c <[^>]*> addu \$a0,\$a0,\$a1
diff --git a/gas/testsuite/gas/mips/la-xgot.d b/gas/testsuite/gas/mips/la-xgot.d
new file mode 100644
index 0000000000..6e5cd26028
--- /dev/null
+++ b/gas/testsuite/gas/mips/la-xgot.d
@@ -0,0 +1,618 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS la-xgot
+#as: -mips1 -KPIC -xgot --defsym KPIC=1
+#source: la.s
+
+# Test the la macro with -KPIC -xgot.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> li \$a0,0
+0+0004 <[^>]*> li \$a0,1
+0+0008 <[^>]*> li \$a0,0x8000
+0+000c <[^>]*> li \$a0,-32768
+0+0010 <[^>]*> lui \$a0,0x1
+0+0014 <[^>]*> lui \$a0,0x1
+0+0018 <[^>]*> ori \$a0,\$a0,0xa5a5
+0+001c <[^>]*> li \$a0,0
+0+0020 <[^>]*> addu \$a0,\$a0,\$a1
+0+0024 <[^>]*> li \$a0,1
+0+0028 <[^>]*> addu \$a0,\$a0,\$a1
+0+002c <[^>]*> li \$a0,0x8000
+0+0030 <[^>]*> addu \$a0,\$a0,\$a1
+0+0034 <[^>]*> li \$a0,-32768
+0+0038 <[^>]*> addu \$a0,\$a0,\$a1
+0+003c <[^>]*> lui \$a0,0x1
+0+0040 <[^>]*> addu \$a0,\$a0,\$a1
+0+0044 <[^>]*> lui \$a0,0x1
+0+0048 <[^>]*> ori \$a0,\$a0,0xa5a5
+0+004c <[^>]*> addu \$a0,\$a0,\$a1
+0+0050 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*50: R_MIPS_GOT16 .data
+0+0054 <[^>]*> nop
+0+0058 <[^>]*> addiu \$a0,\$a0,0
+[ ]*58: R_MIPS_LO16 .data
+0+005c <[^>]*> lui \$a0,0x0
+[ ]*5c: R_MIPS_GOT_HI16 big_external_data_label
+0+0060 <[^>]*> addu \$a0,\$a0,\$gp
+0+0064 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*64: R_MIPS_GOT_LO16 big_external_data_label
+0+0068 <[^>]*> lui \$a0,0x0
+[ ]*68: R_MIPS_GOT_HI16 small_external_data_label
+0+006c <[^>]*> addu \$a0,\$a0,\$gp
+0+0070 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*70: R_MIPS_GOT_LO16 small_external_data_label
+0+0074 <[^>]*> lui \$a0,0x0
+[ ]*74: R_MIPS_GOT_HI16 big_external_common
+0+0078 <[^>]*> addu \$a0,\$a0,\$gp
+0+007c <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*7c: R_MIPS_GOT_LO16 big_external_common
+0+0080 <[^>]*> lui \$a0,0x0
+[ ]*80: R_MIPS_GOT_HI16 small_external_common
+0+0084 <[^>]*> addu \$a0,\$a0,\$gp
+0+0088 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*88: R_MIPS_GOT_LO16 small_external_common
+0+008c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*8c: R_MIPS_GOT16 .bss
+0+0090 <[^>]*> nop
+0+0094 <[^>]*> addiu \$a0,\$a0,0
+[ ]*94: R_MIPS_LO16 .bss
+0+0098 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*98: R_MIPS_GOT16 .bss
+0+009c <[^>]*> nop
+0+00a0 <[^>]*> addiu \$a0,\$a0,1000
+[ ]*a0: R_MIPS_LO16 .bss
+0+00a4 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*a4: R_MIPS_GOT16 .data
+0+00a8 <[^>]*> nop
+0+00ac <[^>]*> addiu \$a0,\$a0,1
+[ ]*ac: R_MIPS_LO16 .data
+0+00b0 <[^>]*> lui \$a0,0x0
+[ ]*b0: R_MIPS_GOT_HI16 big_external_data_label
+0+00b4 <[^>]*> addu \$a0,\$a0,\$gp
+0+00b8 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*b8: R_MIPS_GOT_LO16 big_external_data_label
+0+00bc <[^>]*> nop
+0+00c0 <[^>]*> addiu \$a0,\$a0,1
+0+00c4 <[^>]*> lui \$a0,0x0
+[ ]*c4: R_MIPS_GOT_HI16 small_external_data_label
+0+00c8 <[^>]*> addu \$a0,\$a0,\$gp
+0+00cc <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*cc: R_MIPS_GOT_LO16 small_external_data_label
+0+00d0 <[^>]*> nop
+0+00d4 <[^>]*> addiu \$a0,\$a0,1
+0+00d8 <[^>]*> lui \$a0,0x0
+[ ]*d8: R_MIPS_GOT_HI16 big_external_common
+0+00dc <[^>]*> addu \$a0,\$a0,\$gp
+0+00e0 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*e0: R_MIPS_GOT_LO16 big_external_common
+0+00e4 <[^>]*> nop
+0+00e8 <[^>]*> addiu \$a0,\$a0,1
+0+00ec <[^>]*> lui \$a0,0x0
+[ ]*ec: R_MIPS_GOT_HI16 small_external_common
+0+00f0 <[^>]*> addu \$a0,\$a0,\$gp
+0+00f4 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*f4: R_MIPS_GOT_LO16 small_external_common
+0+00f8 <[^>]*> nop
+0+00fc <[^>]*> addiu \$a0,\$a0,1
+0+0100 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*100: R_MIPS_GOT16 .bss
+0+0104 <[^>]*> nop
+0+0108 <[^>]*> addiu \$a0,\$a0,1
+[ ]*108: R_MIPS_LO16 .bss
+0+010c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*10c: R_MIPS_GOT16 .bss
+0+0110 <[^>]*> nop
+0+0114 <[^>]*> addiu \$a0,\$a0,1001
+[ ]*114: R_MIPS_LO16 .bss
+0+0118 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*118: R_MIPS_GOT16 .data
+0+011c <[^>]*> lui \$at,0x1
+0+0120 <[^>]*> addiu \$at,\$at,-32768
+[ ]*120: R_MIPS_LO16 .data
+0+0124 <[^>]*> addu \$a0,\$a0,\$at
+0+0128 <[^>]*> lui \$a0,0x0
+[ ]*128: R_MIPS_GOT_HI16 big_external_data_label
+0+012c <[^>]*> addu \$a0,\$a0,\$gp
+0+0130 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*130: R_MIPS_GOT_LO16 big_external_data_label
+0+0134 <[^>]*> lui \$at,0x1
+0+0138 <[^>]*> addiu \$at,\$at,-32768
+0+013c <[^>]*> addu \$a0,\$a0,\$at
+0+0140 <[^>]*> lui \$a0,0x0
+[ ]*140: R_MIPS_GOT_HI16 small_external_data_label
+0+0144 <[^>]*> addu \$a0,\$a0,\$gp
+0+0148 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*148: R_MIPS_GOT_LO16 small_external_data_label
+0+014c <[^>]*> lui \$at,0x1
+0+0150 <[^>]*> addiu \$at,\$at,-32768
+0+0154 <[^>]*> addu \$a0,\$a0,\$at
+0+0158 <[^>]*> lui \$a0,0x0
+[ ]*158: R_MIPS_GOT_HI16 big_external_common
+0+015c <[^>]*> addu \$a0,\$a0,\$gp
+0+0160 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*160: R_MIPS_GOT_LO16 big_external_common
+0+0164 <[^>]*> lui \$at,0x1
+0+0168 <[^>]*> addiu \$at,\$at,-32768
+0+016c <[^>]*> addu \$a0,\$a0,\$at
+0+0170 <[^>]*> lui \$a0,0x0
+[ ]*170: R_MIPS_GOT_HI16 small_external_common
+0+0174 <[^>]*> addu \$a0,\$a0,\$gp
+0+0178 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*178: R_MIPS_GOT_LO16 small_external_common
+0+017c <[^>]*> lui \$at,0x1
+0+0180 <[^>]*> addiu \$at,\$at,-32768
+0+0184 <[^>]*> addu \$a0,\$a0,\$at
+0+0188 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*188: R_MIPS_GOT16 .bss
+0+018c <[^>]*> lui \$at,0x1
+0+0190 <[^>]*> addiu \$at,\$at,-32768
+[ ]*190: R_MIPS_LO16 .bss
+0+0194 <[^>]*> addu \$a0,\$a0,\$at
+0+0198 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*198: R_MIPS_GOT16 .bss
+0+019c <[^>]*> lui \$at,0x1
+0+01a0 <[^>]*> addiu \$at,\$at,-31768
+[ ]*1a0: R_MIPS_LO16 .bss
+0+01a4 <[^>]*> addu \$a0,\$a0,\$at
+0+01a8 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*1a8: R_MIPS_GOT16 .data
+0+01ac <[^>]*> nop
+0+01b0 <[^>]*> addiu \$a0,\$a0,-32768
+[ ]*1b0: R_MIPS_LO16 .data
+0+01b4 <[^>]*> lui \$a0,0x0
+[ ]*1b4: R_MIPS_GOT_HI16 big_external_data_label
+0+01b8 <[^>]*> addu \$a0,\$a0,\$gp
+0+01bc <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*1bc: R_MIPS_GOT_LO16 big_external_data_label
+0+01c0 <[^>]*> nop
+0+01c4 <[^>]*> addiu \$a0,\$a0,-32768
+0+01c8 <[^>]*> lui \$a0,0x0
+[ ]*1c8: R_MIPS_GOT_HI16 small_external_data_label
+0+01cc <[^>]*> addu \$a0,\$a0,\$gp
+0+01d0 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*1d0: R_MIPS_GOT_LO16 small_external_data_label
+0+01d4 <[^>]*> nop
+0+01d8 <[^>]*> addiu \$a0,\$a0,-32768
+0+01dc <[^>]*> lui \$a0,0x0
+[ ]*1dc: R_MIPS_GOT_HI16 big_external_common
+0+01e0 <[^>]*> addu \$a0,\$a0,\$gp
+0+01e4 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*1e4: R_MIPS_GOT_LO16 big_external_common
+0+01e8 <[^>]*> nop
+0+01ec <[^>]*> addiu \$a0,\$a0,-32768
+0+01f0 <[^>]*> lui \$a0,0x0
+[ ]*1f0: R_MIPS_GOT_HI16 small_external_common
+0+01f4 <[^>]*> addu \$a0,\$a0,\$gp
+0+01f8 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*1f8: R_MIPS_GOT_LO16 small_external_common
+0+01fc <[^>]*> nop
+0+0200 <[^>]*> addiu \$a0,\$a0,-32768
+0+0204 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*204: R_MIPS_GOT16 .bss
+0+0208 <[^>]*> nop
+0+020c <[^>]*> addiu \$a0,\$a0,-32768
+[ ]*20c: R_MIPS_LO16 .bss
+0+0210 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*210: R_MIPS_GOT16 .bss
+0+0214 <[^>]*> nop
+0+0218 <[^>]*> addiu \$a0,\$a0,-31768
+[ ]*218: R_MIPS_LO16 .bss
+0+021c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*21c: R_MIPS_GOT16 .data
+0+0220 <[^>]*> lui \$at,0x1
+0+0224 <[^>]*> addiu \$at,\$at,0
+[ ]*224: R_MIPS_LO16 .data
+0+0228 <[^>]*> addu \$a0,\$a0,\$at
+0+022c <[^>]*> lui \$a0,0x0
+[ ]*22c: R_MIPS_GOT_HI16 big_external_data_label
+0+0230 <[^>]*> addu \$a0,\$a0,\$gp
+0+0234 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*234: R_MIPS_GOT_LO16 big_external_data_label
+0+0238 <[^>]*> lui \$at,0x1
+0+023c <[^>]*> addiu \$at,\$at,0
+0+0240 <[^>]*> addu \$a0,\$a0,\$at
+0+0244 <[^>]*> lui \$a0,0x0
+[ ]*244: R_MIPS_GOT_HI16 small_external_data_label
+0+0248 <[^>]*> addu \$a0,\$a0,\$gp
+0+024c <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*24c: R_MIPS_GOT_LO16 small_external_data_label
+0+0250 <[^>]*> lui \$at,0x1
+0+0254 <[^>]*> addiu \$at,\$at,0
+0+0258 <[^>]*> addu \$a0,\$a0,\$at
+0+025c <[^>]*> lui \$a0,0x0
+[ ]*25c: R_MIPS_GOT_HI16 big_external_common
+0+0260 <[^>]*> addu \$a0,\$a0,\$gp
+0+0264 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*264: R_MIPS_GOT_LO16 big_external_common
+0+0268 <[^>]*> lui \$at,0x1
+0+026c <[^>]*> addiu \$at,\$at,0
+0+0270 <[^>]*> addu \$a0,\$a0,\$at
+0+0274 <[^>]*> lui \$a0,0x0
+[ ]*274: R_MIPS_GOT_HI16 small_external_common
+0+0278 <[^>]*> addu \$a0,\$a0,\$gp
+0+027c <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*27c: R_MIPS_GOT_LO16 small_external_common
+0+0280 <[^>]*> lui \$at,0x1
+0+0284 <[^>]*> addiu \$at,\$at,0
+0+0288 <[^>]*> addu \$a0,\$a0,\$at
+0+028c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*28c: R_MIPS_GOT16 .bss
+0+0290 <[^>]*> lui \$at,0x1
+0+0294 <[^>]*> addiu \$at,\$at,0
+[ ]*294: R_MIPS_LO16 .bss
+0+0298 <[^>]*> addu \$a0,\$a0,\$at
+0+029c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*29c: R_MIPS_GOT16 .bss
+0+02a0 <[^>]*> lui \$at,0x1
+0+02a4 <[^>]*> addiu \$at,\$at,1000
+[ ]*2a4: R_MIPS_LO16 .bss
+0+02a8 <[^>]*> addu \$a0,\$a0,\$at
+0+02ac <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*2ac: R_MIPS_GOT16 .data
+0+02b0 <[^>]*> lui \$at,0x2
+0+02b4 <[^>]*> addiu \$at,\$at,-23131
+[ ]*2b4: R_MIPS_LO16 .data
+0+02b8 <[^>]*> addu \$a0,\$a0,\$at
+0+02bc <[^>]*> lui \$a0,0x0
+[ ]*2bc: R_MIPS_GOT_HI16 big_external_data_label
+0+02c0 <[^>]*> addu \$a0,\$a0,\$gp
+0+02c4 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*2c4: R_MIPS_GOT_LO16 big_external_data_label
+0+02c8 <[^>]*> lui \$at,0x2
+0+02cc <[^>]*> addiu \$at,\$at,-23131
+0+02d0 <[^>]*> addu \$a0,\$a0,\$at
+0+02d4 <[^>]*> lui \$a0,0x0
+[ ]*2d4: R_MIPS_GOT_HI16 small_external_data_label
+0+02d8 <[^>]*> addu \$a0,\$a0,\$gp
+0+02dc <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*2dc: R_MIPS_GOT_LO16 small_external_data_label
+0+02e0 <[^>]*> lui \$at,0x2
+0+02e4 <[^>]*> addiu \$at,\$at,-23131
+0+02e8 <[^>]*> addu \$a0,\$a0,\$at
+0+02ec <[^>]*> lui \$a0,0x0
+[ ]*2ec: R_MIPS_GOT_HI16 big_external_common
+0+02f0 <[^>]*> addu \$a0,\$a0,\$gp
+0+02f4 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*2f4: R_MIPS_GOT_LO16 big_external_common
+0+02f8 <[^>]*> lui \$at,0x2
+0+02fc <[^>]*> addiu \$at,\$at,-23131
+0+0300 <[^>]*> addu \$a0,\$a0,\$at
+0+0304 <[^>]*> lui \$a0,0x0
+[ ]*304: R_MIPS_GOT_HI16 small_external_common
+0+0308 <[^>]*> addu \$a0,\$a0,\$gp
+0+030c <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*30c: R_MIPS_GOT_LO16 small_external_common
+0+0310 <[^>]*> lui \$at,0x2
+0+0314 <[^>]*> addiu \$at,\$at,-23131
+0+0318 <[^>]*> addu \$a0,\$a0,\$at
+0+031c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*31c: R_MIPS_GOT16 .bss
+0+0320 <[^>]*> lui \$at,0x2
+0+0324 <[^>]*> addiu \$at,\$at,-23131
+[ ]*324: R_MIPS_LO16 .bss
+0+0328 <[^>]*> addu \$a0,\$a0,\$at
+0+032c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*32c: R_MIPS_GOT16 .bss
+0+0330 <[^>]*> lui \$at,0x2
+0+0334 <[^>]*> addiu \$at,\$at,-22131
+[ ]*334: R_MIPS_LO16 .bss
+0+0338 <[^>]*> addu \$a0,\$a0,\$at
+0+033c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*33c: R_MIPS_GOT16 .data
+0+0340 <[^>]*> nop
+0+0344 <[^>]*> addiu \$a0,\$a0,0
+[ ]*344: R_MIPS_LO16 .data
+0+0348 <[^>]*> addu \$a0,\$a0,\$a1
+0+034c <[^>]*> lui \$a0,0x0
+[ ]*34c: R_MIPS_GOT_HI16 big_external_data_label
+0+0350 <[^>]*> addu \$a0,\$a0,\$gp
+0+0354 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*354: R_MIPS_GOT_LO16 big_external_data_label
+0+0358 <[^>]*> nop
+0+035c <[^>]*> addu \$a0,\$a0,\$a1
+0+0360 <[^>]*> lui \$a0,0x0
+[ ]*360: R_MIPS_GOT_HI16 small_external_data_label
+0+0364 <[^>]*> addu \$a0,\$a0,\$gp
+0+0368 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*368: R_MIPS_GOT_LO16 small_external_data_label
+0+036c <[^>]*> nop
+0+0370 <[^>]*> addu \$a0,\$a0,\$a1
+0+0374 <[^>]*> lui \$a0,0x0
+[ ]*374: R_MIPS_GOT_HI16 big_external_common
+0+0378 <[^>]*> addu \$a0,\$a0,\$gp
+0+037c <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*37c: R_MIPS_GOT_LO16 big_external_common
+0+0380 <[^>]*> nop
+0+0384 <[^>]*> addu \$a0,\$a0,\$a1
+0+0388 <[^>]*> lui \$a0,0x0
+[ ]*388: R_MIPS_GOT_HI16 small_external_common
+0+038c <[^>]*> addu \$a0,\$a0,\$gp
+0+0390 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*390: R_MIPS_GOT_LO16 small_external_common
+0+0394 <[^>]*> nop
+0+0398 <[^>]*> addu \$a0,\$a0,\$a1
+0+039c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*39c: R_MIPS_GOT16 .bss
+0+03a0 <[^>]*> nop
+0+03a4 <[^>]*> addiu \$a0,\$a0,0
+[ ]*3a4: R_MIPS_LO16 .bss
+0+03a8 <[^>]*> addu \$a0,\$a0,\$a1
+0+03ac <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*3ac: R_MIPS_GOT16 .bss
+0+03b0 <[^>]*> nop
+0+03b4 <[^>]*> addiu \$a0,\$a0,1000
+[ ]*3b4: R_MIPS_LO16 .bss
+0+03b8 <[^>]*> addu \$a0,\$a0,\$a1
+0+03bc <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*3bc: R_MIPS_GOT16 .data
+0+03c0 <[^>]*> nop
+0+03c4 <[^>]*> addiu \$a0,\$a0,1
+[ ]*3c4: R_MIPS_LO16 .data
+0+03c8 <[^>]*> addu \$a0,\$a0,\$a1
+0+03cc <[^>]*> lui \$a0,0x0
+[ ]*3cc: R_MIPS_GOT_HI16 big_external_data_label
+0+03d0 <[^>]*> addu \$a0,\$a0,\$gp
+0+03d4 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*3d4: R_MIPS_GOT_LO16 big_external_data_label
+0+03d8 <[^>]*> nop
+0+03dc <[^>]*> addiu \$a0,\$a0,1
+0+03e0 <[^>]*> addu \$a0,\$a0,\$a1
+0+03e4 <[^>]*> lui \$a0,0x0
+[ ]*3e4: R_MIPS_GOT_HI16 small_external_data_label
+0+03e8 <[^>]*> addu \$a0,\$a0,\$gp
+0+03ec <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*3ec: R_MIPS_GOT_LO16 small_external_data_label
+0+03f0 <[^>]*> nop
+0+03f4 <[^>]*> addiu \$a0,\$a0,1
+0+03f8 <[^>]*> addu \$a0,\$a0,\$a1
+0+03fc <[^>]*> lui \$a0,0x0
+[ ]*3fc: R_MIPS_GOT_HI16 big_external_common
+0+0400 <[^>]*> addu \$a0,\$a0,\$gp
+0+0404 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*404: R_MIPS_GOT_LO16 big_external_common
+0+0408 <[^>]*> nop
+0+040c <[^>]*> addiu \$a0,\$a0,1
+0+0410 <[^>]*> addu \$a0,\$a0,\$a1
+0+0414 <[^>]*> lui \$a0,0x0
+[ ]*414: R_MIPS_GOT_HI16 small_external_common
+0+0418 <[^>]*> addu \$a0,\$a0,\$gp
+0+041c <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*41c: R_MIPS_GOT_LO16 small_external_common
+0+0420 <[^>]*> nop
+0+0424 <[^>]*> addiu \$a0,\$a0,1
+0+0428 <[^>]*> addu \$a0,\$a0,\$a1
+0+042c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*42c: R_MIPS_GOT16 .bss
+0+0430 <[^>]*> nop
+0+0434 <[^>]*> addiu \$a0,\$a0,1
+[ ]*434: R_MIPS_LO16 .bss
+0+0438 <[^>]*> addu \$a0,\$a0,\$a1
+0+043c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*43c: R_MIPS_GOT16 .bss
+0+0440 <[^>]*> nop
+0+0444 <[^>]*> addiu \$a0,\$a0,1001
+[ ]*444: R_MIPS_LO16 .bss
+0+0448 <[^>]*> addu \$a0,\$a0,\$a1
+0+044c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*44c: R_MIPS_GOT16 .data
+0+0450 <[^>]*> lui \$at,0x1
+0+0454 <[^>]*> addiu \$at,\$at,-32768
+[ ]*454: R_MIPS_LO16 .data
+0+0458 <[^>]*> addu \$a0,\$a0,\$at
+0+045c <[^>]*> addu \$a0,\$a0,\$a1
+0+0460 <[^>]*> lui \$a0,0x0
+[ ]*460: R_MIPS_GOT_HI16 big_external_data_label
+0+0464 <[^>]*> addu \$a0,\$a0,\$gp
+0+0468 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*468: R_MIPS_GOT_LO16 big_external_data_label
+0+046c <[^>]*> lui \$at,0x1
+0+0470 <[^>]*> addiu \$at,\$at,-32768
+0+0474 <[^>]*> addu \$a0,\$a0,\$at
+0+0478 <[^>]*> addu \$a0,\$a0,\$a1
+0+047c <[^>]*> lui \$a0,0x0
+[ ]*47c: R_MIPS_GOT_HI16 small_external_data_label
+0+0480 <[^>]*> addu \$a0,\$a0,\$gp
+0+0484 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*484: R_MIPS_GOT_LO16 small_external_data_label
+0+0488 <[^>]*> lui \$at,0x1
+0+048c <[^>]*> addiu \$at,\$at,-32768
+0+0490 <[^>]*> addu \$a0,\$a0,\$at
+0+0494 <[^>]*> addu \$a0,\$a0,\$a1
+0+0498 <[^>]*> lui \$a0,0x0
+[ ]*498: R_MIPS_GOT_HI16 big_external_common
+0+049c <[^>]*> addu \$a0,\$a0,\$gp
+0+04a0 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*4a0: R_MIPS_GOT_LO16 big_external_common
+0+04a4 <[^>]*> lui \$at,0x1
+0+04a8 <[^>]*> addiu \$at,\$at,-32768
+0+04ac <[^>]*> addu \$a0,\$a0,\$at
+0+04b0 <[^>]*> addu \$a0,\$a0,\$a1
+0+04b4 <[^>]*> lui \$a0,0x0
+[ ]*4b4: R_MIPS_GOT_HI16 small_external_common
+0+04b8 <[^>]*> addu \$a0,\$a0,\$gp
+0+04bc <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*4bc: R_MIPS_GOT_LO16 small_external_common
+0+04c0 <[^>]*> lui \$at,0x1
+0+04c4 <[^>]*> addiu \$at,\$at,-32768
+0+04c8 <[^>]*> addu \$a0,\$a0,\$at
+0+04cc <[^>]*> addu \$a0,\$a0,\$a1
+0+04d0 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*4d0: R_MIPS_GOT16 .bss
+0+04d4 <[^>]*> lui \$at,0x1
+0+04d8 <[^>]*> addiu \$at,\$at,-32768
+[ ]*4d8: R_MIPS_LO16 .bss
+0+04dc <[^>]*> addu \$a0,\$a0,\$at
+0+04e0 <[^>]*> addu \$a0,\$a0,\$a1
+0+04e4 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*4e4: R_MIPS_GOT16 .bss
+0+04e8 <[^>]*> lui \$at,0x1
+0+04ec <[^>]*> addiu \$at,\$at,-31768
+[ ]*4ec: R_MIPS_LO16 .bss
+0+04f0 <[^>]*> addu \$a0,\$a0,\$at
+0+04f4 <[^>]*> addu \$a0,\$a0,\$a1
+0+04f8 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*4f8: R_MIPS_GOT16 .data
+0+04fc <[^>]*> nop
+0+0500 <[^>]*> addiu \$a0,\$a0,-32768
+[ ]*500: R_MIPS_LO16 .data
+0+0504 <[^>]*> addu \$a0,\$a0,\$a1
+0+0508 <[^>]*> lui \$a0,0x0
+[ ]*508: R_MIPS_GOT_HI16 big_external_data_label
+0+050c <[^>]*> addu \$a0,\$a0,\$gp
+0+0510 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*510: R_MIPS_GOT_LO16 big_external_data_label
+0+0514 <[^>]*> nop
+0+0518 <[^>]*> addiu \$a0,\$a0,-32768
+0+051c <[^>]*> addu \$a0,\$a0,\$a1
+0+0520 <[^>]*> lui \$a0,0x0
+[ ]*520: R_MIPS_GOT_HI16 small_external_data_label
+0+0524 <[^>]*> addu \$a0,\$a0,\$gp
+0+0528 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*528: R_MIPS_GOT_LO16 small_external_data_label
+0+052c <[^>]*> nop
+0+0530 <[^>]*> addiu \$a0,\$a0,-32768
+0+0534 <[^>]*> addu \$a0,\$a0,\$a1
+0+0538 <[^>]*> lui \$a0,0x0
+[ ]*538: R_MIPS_GOT_HI16 big_external_common
+0+053c <[^>]*> addu \$a0,\$a0,\$gp
+0+0540 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*540: R_MIPS_GOT_LO16 big_external_common
+0+0544 <[^>]*> nop
+0+0548 <[^>]*> addiu \$a0,\$a0,-32768
+0+054c <[^>]*> addu \$a0,\$a0,\$a1
+0+0550 <[^>]*> lui \$a0,0x0
+[ ]*550: R_MIPS_GOT_HI16 small_external_common
+0+0554 <[^>]*> addu \$a0,\$a0,\$gp
+0+0558 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*558: R_MIPS_GOT_LO16 small_external_common
+0+055c <[^>]*> nop
+0+0560 <[^>]*> addiu \$a0,\$a0,-32768
+0+0564 <[^>]*> addu \$a0,\$a0,\$a1
+0+0568 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*568: R_MIPS_GOT16 .bss
+0+056c <[^>]*> nop
+0+0570 <[^>]*> addiu \$a0,\$a0,-32768
+[ ]*570: R_MIPS_LO16 .bss
+0+0574 <[^>]*> addu \$a0,\$a0,\$a1
+0+0578 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*578: R_MIPS_GOT16 .bss
+0+057c <[^>]*> nop
+0+0580 <[^>]*> addiu \$a0,\$a0,-31768
+[ ]*580: R_MIPS_LO16 .bss
+0+0584 <[^>]*> addu \$a0,\$a0,\$a1
+0+0588 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*588: R_MIPS_GOT16 .data
+0+058c <[^>]*> lui \$at,0x1
+0+0590 <[^>]*> addiu \$at,\$at,0
+[ ]*590: R_MIPS_LO16 .data
+0+0594 <[^>]*> addu \$a0,\$a0,\$at
+0+0598 <[^>]*> addu \$a0,\$a0,\$a1
+0+059c <[^>]*> lui \$a0,0x0
+[ ]*59c: R_MIPS_GOT_HI16 big_external_data_label
+0+05a0 <[^>]*> addu \$a0,\$a0,\$gp
+0+05a4 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*5a4: R_MIPS_GOT_LO16 big_external_data_label
+0+05a8 <[^>]*> lui \$at,0x1
+0+05ac <[^>]*> addiu \$at,\$at,0
+0+05b0 <[^>]*> addu \$a0,\$a0,\$at
+0+05b4 <[^>]*> addu \$a0,\$a0,\$a1
+0+05b8 <[^>]*> lui \$a0,0x0
+[ ]*5b8: R_MIPS_GOT_HI16 small_external_data_label
+0+05bc <[^>]*> addu \$a0,\$a0,\$gp
+0+05c0 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*5c0: R_MIPS_GOT_LO16 small_external_data_label
+0+05c4 <[^>]*> lui \$at,0x1
+0+05c8 <[^>]*> addiu \$at,\$at,0
+0+05cc <[^>]*> addu \$a0,\$a0,\$at
+0+05d0 <[^>]*> addu \$a0,\$a0,\$a1
+0+05d4 <[^>]*> lui \$a0,0x0
+[ ]*5d4: R_MIPS_GOT_HI16 big_external_common
+0+05d8 <[^>]*> addu \$a0,\$a0,\$gp
+0+05dc <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*5dc: R_MIPS_GOT_LO16 big_external_common
+0+05e0 <[^>]*> lui \$at,0x1
+0+05e4 <[^>]*> addiu \$at,\$at,0
+0+05e8 <[^>]*> addu \$a0,\$a0,\$at
+0+05ec <[^>]*> addu \$a0,\$a0,\$a1
+0+05f0 <[^>]*> lui \$a0,0x0
+[ ]*5f0: R_MIPS_GOT_HI16 small_external_common
+0+05f4 <[^>]*> addu \$a0,\$a0,\$gp
+0+05f8 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*5f8: R_MIPS_GOT_LO16 small_external_common
+0+05fc <[^>]*> lui \$at,0x1
+0+0600 <[^>]*> addiu \$at,\$at,0
+0+0604 <[^>]*> addu \$a0,\$a0,\$at
+0+0608 <[^>]*> addu \$a0,\$a0,\$a1
+0+060c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*60c: R_MIPS_GOT16 .bss
+0+0610 <[^>]*> lui \$at,0x1
+0+0614 <[^>]*> addiu \$at,\$at,0
+[ ]*614: R_MIPS_LO16 .bss
+0+0618 <[^>]*> addu \$a0,\$a0,\$at
+0+061c <[^>]*> addu \$a0,\$a0,\$a1
+0+0620 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*620: R_MIPS_GOT16 .bss
+0+0624 <[^>]*> lui \$at,0x1
+0+0628 <[^>]*> addiu \$at,\$at,1000
+[ ]*628: R_MIPS_LO16 .bss
+0+062c <[^>]*> addu \$a0,\$a0,\$at
+0+0630 <[^>]*> addu \$a0,\$a0,\$a1
+0+0634 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*634: R_MIPS_GOT16 .data
+0+0638 <[^>]*> lui \$at,0x2
+0+063c <[^>]*> addiu \$at,\$at,-23131
+[ ]*63c: R_MIPS_LO16 .data
+0+0640 <[^>]*> addu \$a0,\$a0,\$at
+0+0644 <[^>]*> addu \$a0,\$a0,\$a1
+0+0648 <[^>]*> lui \$a0,0x0
+[ ]*648: R_MIPS_GOT_HI16 big_external_data_label
+0+064c <[^>]*> addu \$a0,\$a0,\$gp
+0+0650 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*650: R_MIPS_GOT_LO16 big_external_data_label
+0+0654 <[^>]*> lui \$at,0x2
+0+0658 <[^>]*> addiu \$at,\$at,-23131
+0+065c <[^>]*> addu \$a0,\$a0,\$at
+0+0660 <[^>]*> addu \$a0,\$a0,\$a1
+0+0664 <[^>]*> lui \$a0,0x0
+[ ]*664: R_MIPS_GOT_HI16 small_external_data_label
+0+0668 <[^>]*> addu \$a0,\$a0,\$gp
+0+066c <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*66c: R_MIPS_GOT_LO16 small_external_data_label
+0+0670 <[^>]*> lui \$at,0x2
+0+0674 <[^>]*> addiu \$at,\$at,-23131
+0+0678 <[^>]*> addu \$a0,\$a0,\$at
+0+067c <[^>]*> addu \$a0,\$a0,\$a1
+0+0680 <[^>]*> lui \$a0,0x0
+[ ]*680: R_MIPS_GOT_HI16 big_external_common
+0+0684 <[^>]*> addu \$a0,\$a0,\$gp
+0+0688 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*688: R_MIPS_GOT_LO16 big_external_common
+0+068c <[^>]*> lui \$at,0x2
+0+0690 <[^>]*> addiu \$at,\$at,-23131
+0+0694 <[^>]*> addu \$a0,\$a0,\$at
+0+0698 <[^>]*> addu \$a0,\$a0,\$a1
+0+069c <[^>]*> lui \$a0,0x0
+[ ]*69c: R_MIPS_GOT_HI16 small_external_common
+0+06a0 <[^>]*> addu \$a0,\$a0,\$gp
+0+06a4 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*6a4: R_MIPS_GOT_LO16 small_external_common
+0+06a8 <[^>]*> lui \$at,0x2
+0+06ac <[^>]*> addiu \$at,\$at,-23131
+0+06b0 <[^>]*> addu \$a0,\$a0,\$at
+0+06b4 <[^>]*> addu \$a0,\$a0,\$a1
+0+06b8 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*6b8: R_MIPS_GOT16 .bss
+0+06bc <[^>]*> lui \$at,0x2
+0+06c0 <[^>]*> addiu \$at,\$at,-23131
+[ ]*6c0: R_MIPS_LO16 .bss
+0+06c4 <[^>]*> addu \$a0,\$a0,\$at
+0+06c8 <[^>]*> addu \$a0,\$a0,\$a1
+0+06cc <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*6cc: R_MIPS_GOT16 .bss
+0+06d0 <[^>]*> lui \$at,0x2
+0+06d4 <[^>]*> addiu \$at,\$at,-22131
+[ ]*6d4: R_MIPS_LO16 .bss
+0+06d8 <[^>]*> addu \$a0,\$a0,\$at
+0+06dc <[^>]*> addu \$a0,\$a0,\$a1
diff --git a/gas/testsuite/gas/mips/la.d b/gas/testsuite/gas/mips/la.d
new file mode 100644
index 0000000000..25eaa1e905
--- /dev/null
+++ b/gas/testsuite/gas/mips/la.d
@@ -0,0 +1,384 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS la
+#as: -mips1
+
+# Test the la macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> li \$a0,0
+0+0004 <[^>]*> li \$a0,1
+0+0008 <[^>]*> li \$a0,0x8000
+0+000c <[^>]*> li \$a0,-32768
+0+0010 <[^>]*> lui \$a0,0x1
+0+0014 <[^>]*> lui \$a0,0x1
+0+0018 <[^>]*> ori \$a0,\$a0,0xa5a5
+0+001c <[^>]*> li \$a0,0
+0+0020 <[^>]*> addu \$a0,\$a0,\$a1
+0+0024 <[^>]*> li \$a0,1
+0+0028 <[^>]*> addu \$a0,\$a0,\$a1
+0+002c <[^>]*> li \$a0,0x8000
+0+0030 <[^>]*> addu \$a0,\$a0,\$a1
+0+0034 <[^>]*> li \$a0,-32768
+0+0038 <[^>]*> addu \$a0,\$a0,\$a1
+0+003c <[^>]*> lui \$a0,0x1
+0+0040 <[^>]*> addu \$a0,\$a0,\$a1
+0+0044 <[^>]*> lui \$a0,0x1
+0+0048 <[^>]*> ori \$a0,\$a0,0xa5a5
+0+004c <[^>]*> addu \$a0,\$a0,\$a1
+0+0050 <[^>]*> lui \$a0,0x0
+[ ]*50: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0054 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*54: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0058 <[^>]*> lui \$a0,0x0
+[ ]*58: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+005c <[^>]*> addiu \$a0,\$a0,0
+[ ]*5c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0060 <[^>]*> addiu \$a0,\$gp,0
+[ ]*60: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+0064 <[^>]*> lui \$a0,0x0
+[ ]*64: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0068 <[^>]*> addiu \$a0,\$a0,0
+[ ]*68: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+006c <[^>]*> addiu \$a0,\$gp,0
+[ ]*6c: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+0070 <[^>]*> lui \$a0,0x0
+[ ]*70: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0074 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*74: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0078 <[^>]*> addiu \$a0,\$gp,[-0-9]+
+[ ]*78: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+007c <[^>]*> lui \$a0,0x0
+[ ]*7c: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0080 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*80: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0084 <[^>]*> lui \$a0,0x0
+[ ]*84: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0088 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*88: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+008c <[^>]*> addiu \$a0,\$gp,[-0-9]+
+[ ]*8c: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+0090 <[^>]*> lui \$a0,0x0
+[ ]*90: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0094 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*94: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0098 <[^>]*> addiu \$a0,\$gp,[-0-9]+
+[ ]*98: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+009c <[^>]*> lui \$a0,0x0
+[ ]*9c: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+00a0 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*a0: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+00a4 <[^>]*> addiu \$a0,\$gp,[-0-9]+
+[ ]*a4: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00a8 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*a8: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+00ac <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*ac: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+00b0 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*b0: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+00b4 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*b4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+00b8 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*b8: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+00bc <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*bc: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+00c0 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*c0: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+00c4 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*c4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+00c8 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*c8: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+00cc <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*cc: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+00d0 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*d0: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+00d4 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*d4: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+00d8 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*d8: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+00dc <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*dc: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+00e0 <[^>]*> lui \$a0,0x0
+[ ]*e0: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+00e4 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*e4: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+00e8 <[^>]*> lui \$a0,0x0
+[ ]*e8: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+00ec <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*ec: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+00f0 <[^>]*> lui \$a0,0x0
+[ ]*f0: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+00f4 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*f4: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+00f8 <[^>]*> lui \$a0,0x0
+[ ]*f8: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+00fc <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*fc: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0100 <[^>]*> lui \$a0,0x0
+[ ]*100: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0104 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*104: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0108 <[^>]*> lui \$a0,0x0
+[ ]*108: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+010c <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*10c: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0110 <[^>]*> lui \$a0,0x0
+[ ]*110: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0114 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*114: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0118 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*118: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+011c <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*11c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0120 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*120: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0124 <[^>]*> addiu \$a0,\$a0,0
+[ ]*124: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0128 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*128: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+012c <[^>]*> addiu \$a0,\$a0,0
+[ ]*12c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0130 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*130: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0134 <[^>]*> addiu \$a0,\$a0,0
+[ ]*134: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0138 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*138: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+013c <[^>]*> addiu \$a0,\$a0,0
+[ ]*13c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0140 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*140: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0144 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*144: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0148 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*148: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+014c <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*14c: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0150 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*150: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0154 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*154: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0158 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*158: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+015c <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*15c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0160 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*160: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0164 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*164: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0168 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*168: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+016c <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*16c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0170 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*170: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0174 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*174: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0178 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*178: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+017c <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*17c: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0180 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*180: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0184 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*184: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0188 <[^>]*> lui \$a0,0x0
+[ ]*188: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+018c <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*18c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0190 <[^>]*> addu \$a0,\$a0,\$a1
+0+0194 <[^>]*> lui \$a0,0x0
+[ ]*194: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0198 <[^>]*> addiu \$a0,\$a0,0
+[ ]*198: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+019c <[^>]*> addu \$a0,\$a0,\$a1
+0+01a0 <[^>]*> addiu \$a0,\$gp,0
+[ ]*1a0: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+01a4 <[^>]*> addu \$a0,\$a0,\$a1
+0+01a8 <[^>]*> lui \$a0,0x0
+[ ]*1a8: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+01ac <[^>]*> addiu \$a0,\$a0,0
+[ ]*1ac: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+01b0 <[^>]*> addu \$a0,\$a0,\$a1
+0+01b4 <[^>]*> addiu \$a0,\$gp,0
+[ ]*1b4: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+01b8 <[^>]*> addu \$a0,\$a0,\$a1
+0+01bc <[^>]*> lui \$a0,0x0
+[ ]*1bc: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+01c0 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*1c0: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+01c4 <[^>]*> addu \$a0,\$a0,\$a1
+0+01c8 <[^>]*> addiu \$a0,\$gp,[-0-9]+
+[ ]*1c8: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+01cc <[^>]*> addu \$a0,\$a0,\$a1
+0+01d0 <[^>]*> lui \$a0,0x0
+[ ]*1d0: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+01d4 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*1d4: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+01d8 <[^>]*> addu \$a0,\$a0,\$a1
+0+01dc <[^>]*> lui \$a0,0x0
+[ ]*1dc: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+01e0 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*1e0: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+01e4 <[^>]*> addu \$a0,\$a0,\$a1
+0+01e8 <[^>]*> addiu \$a0,\$gp,[-0-9]+
+[ ]*1e8: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+01ec <[^>]*> addu \$a0,\$a0,\$a1
+0+01f0 <[^>]*> lui \$a0,0x0
+[ ]*1f0: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+01f4 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*1f4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+01f8 <[^>]*> addu \$a0,\$a0,\$a1
+0+01fc <[^>]*> addiu \$a0,\$gp,[-0-9]+
+[ ]*1fc: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+0200 <[^>]*> addu \$a0,\$a0,\$a1
+0+0204 <[^>]*> lui \$a0,0x0
+[ ]*204: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0208 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*208: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+020c <[^>]*> addu \$a0,\$a0,\$a1
+0+0210 <[^>]*> addiu \$a0,\$gp,[-0-9]+
+[ ]*210: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0214 <[^>]*> addu \$a0,\$a0,\$a1
+0+0218 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*218: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+021c <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*21c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0220 <[^>]*> addu \$a0,\$a0,\$a1
+0+0224 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*224: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0228 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*228: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+022c <[^>]*> addu \$a0,\$a0,\$a1
+0+0230 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*230: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0234 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*234: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0238 <[^>]*> addu \$a0,\$a0,\$a1
+0+023c <[^>]*> lui \$a0,[-0-9x]+
+[ ]*23c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0240 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*240: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0244 <[^>]*> addu \$a0,\$a0,\$a1
+0+0248 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*248: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+024c <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*24c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0250 <[^>]*> addu \$a0,\$a0,\$a1
+0+0254 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*254: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0258 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*258: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+025c <[^>]*> addu \$a0,\$a0,\$a1
+0+0260 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*260: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0264 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*264: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0268 <[^>]*> addu \$a0,\$a0,\$a1
+0+026c <[^>]*> lui \$a0,0x0
+[ ]*26c: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0270 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*270: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0274 <[^>]*> addu \$a0,\$a0,\$a1
+0+0278 <[^>]*> lui \$a0,0x0
+[ ]*278: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+027c <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*27c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0280 <[^>]*> addu \$a0,\$a0,\$a1
+0+0284 <[^>]*> lui \$a0,0x0
+[ ]*284: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0288 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*288: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+028c <[^>]*> addu \$a0,\$a0,\$a1
+0+0290 <[^>]*> lui \$a0,0x0
+[ ]*290: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0294 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*294: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0298 <[^>]*> addu \$a0,\$a0,\$a1
+0+029c <[^>]*> lui \$a0,0x0
+[ ]*29c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+02a0 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*2a0: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+02a4 <[^>]*> addu \$a0,\$a0,\$a1
+0+02a8 <[^>]*> lui \$a0,0x0
+[ ]*2a8: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+02ac <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*2ac: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+02b0 <[^>]*> addu \$a0,\$a0,\$a1
+0+02b4 <[^>]*> lui \$a0,0x0
+[ ]*2b4: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+02b8 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*2b8: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+02bc <[^>]*> addu \$a0,\$a0,\$a1
+0+02c0 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*2c0: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+02c4 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*2c4: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+02c8 <[^>]*> addu \$a0,\$a0,\$a1
+0+02cc <[^>]*> lui \$a0,[-0-9x]+
+[ ]*2cc: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+02d0 <[^>]*> addiu \$a0,\$a0,0
+[ ]*2d0: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+02d4 <[^>]*> addu \$a0,\$a0,\$a1
+0+02d8 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*2d8: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+02dc <[^>]*> addiu \$a0,\$a0,0
+[ ]*2dc: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+02e0 <[^>]*> addu \$a0,\$a0,\$a1
+0+02e4 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*2e4: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+02e8 <[^>]*> addiu \$a0,\$a0,0
+[ ]*2e8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+02ec <[^>]*> addu \$a0,\$a0,\$a1
+0+02f0 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*2f0: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+02f4 <[^>]*> addiu \$a0,\$a0,0
+[ ]*2f4: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+02f8 <[^>]*> addu \$a0,\$a0,\$a1
+0+02fc <[^>]*> lui \$a0,[-0-9x]+
+[ ]*2fc: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0300 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*300: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0304 <[^>]*> addu \$a0,\$a0,\$a1
+0+0308 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*308: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+030c <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*30c: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0310 <[^>]*> addu \$a0,\$a0,\$a1
+0+0314 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*314: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0318 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*318: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+031c <[^>]*> addu \$a0,\$a0,\$a1
+0+0320 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*320: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0324 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*324: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0328 <[^>]*> addu \$a0,\$a0,\$a1
+0+032c <[^>]*> lui \$a0,[-0-9x]+
+[ ]*32c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0330 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*330: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0334 <[^>]*> addu \$a0,\$a0,\$a1
+0+0338 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*338: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+033c <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*33c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0340 <[^>]*> addu \$a0,\$a0,\$a1
+0+0344 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*344: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0348 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*348: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+034c <[^>]*> addu \$a0,\$a0,\$a1
+0+0350 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*350: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0354 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*354: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0358 <[^>]*> addu \$a0,\$a0,\$a1
+0+035c <[^>]*> lui \$a0,[-0-9x]+
+[ ]*35c: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0360 <[^>]*> addiu \$a0,\$a0,[-0-9]+
+[ ]*360: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0364 <[^>]*> addu \$a0,\$a0,\$a1
+ ...
diff --git a/gas/testsuite/gas/mips/la.s b/gas/testsuite/gas/mips/la.s
new file mode 100644
index 0000000000..078c811684
--- /dev/null
+++ b/gas/testsuite/gas/mips/la.s
@@ -0,0 +1,114 @@
+# Source file used to test the la macro.
+
+ .data
+data_label:
+ .extern big_external_data_label,1000
+ .extern small_external_data_label,1
+ .comm big_external_common,1000
+ .comm small_external_common,1
+ .lcomm big_local_common,1000
+ .lcomm small_local_common,1
+
+ .text
+ la $4,0
+ la $4,1
+ la $4,0x8000
+ la $4,-0x8000
+ la $4,0x10000
+ la $4,0x1a5a5
+ la $4,0($5)
+ la $4,1($5)
+ la $4,0x8000($5)
+ la $4,-0x8000($5)
+ la $4,0x10000($5)
+ la $4,0x1a5a5($5)
+ la $4,data_label
+ la $4,big_external_data_label
+ la $4,small_external_data_label
+ la $4,big_external_common
+ la $4,small_external_common
+ la $4,big_local_common
+ la $4,small_local_common
+ la $4,data_label+1
+ la $4,big_external_data_label+1
+ la $4,small_external_data_label+1
+ la $4,big_external_common+1
+ la $4,small_external_common+1
+ la $4,big_local_common+1
+ la $4,small_local_common+1
+ la $4,data_label+0x8000
+ la $4,big_external_data_label+0x8000
+ la $4,small_external_data_label+0x8000
+ la $4,big_external_common+0x8000
+ la $4,small_external_common+0x8000
+ la $4,big_local_common+0x8000
+ la $4,small_local_common+0x8000
+ la $4,data_label-0x8000
+ la $4,big_external_data_label-0x8000
+ la $4,small_external_data_label-0x8000
+ la $4,big_external_common-0x8000
+ la $4,small_external_common-0x8000
+ la $4,big_local_common-0x8000
+ la $4,small_local_common-0x8000
+ la $4,data_label+0x10000
+ la $4,big_external_data_label+0x10000
+ la $4,small_external_data_label+0x10000
+ la $4,big_external_common+0x10000
+ la $4,small_external_common+0x10000
+ la $4,big_local_common+0x10000
+ la $4,small_local_common+0x10000
+ la $4,data_label+0x1a5a5
+ la $4,big_external_data_label+0x1a5a5
+ la $4,small_external_data_label+0x1a5a5
+ la $4,big_external_common+0x1a5a5
+ la $4,small_external_common+0x1a5a5
+ la $4,big_local_common+0x1a5a5
+ la $4,small_local_common+0x1a5a5
+ la $4,data_label($5)
+ la $4,big_external_data_label($5)
+ la $4,small_external_data_label($5)
+ la $4,big_external_common($5)
+ la $4,small_external_common($5)
+ la $4,big_local_common($5)
+ la $4,small_local_common($5)
+ la $4,data_label+1($5)
+ la $4,big_external_data_label+1($5)
+ la $4,small_external_data_label+1($5)
+ la $4,big_external_common+1($5)
+ la $4,small_external_common+1($5)
+ la $4,big_local_common+1($5)
+ la $4,small_local_common+1($5)
+ la $4,data_label+0x8000($5)
+ la $4,big_external_data_label+0x8000($5)
+ la $4,small_external_data_label+0x8000($5)
+ la $4,big_external_common+0x8000($5)
+ la $4,small_external_common+0x8000($5)
+ la $4,big_local_common+0x8000($5)
+ la $4,small_local_common+0x8000($5)
+ la $4,data_label-0x8000($5)
+ la $4,big_external_data_label-0x8000($5)
+ la $4,small_external_data_label-0x8000($5)
+ la $4,big_external_common-0x8000($5)
+ la $4,small_external_common-0x8000($5)
+ la $4,big_local_common-0x8000($5)
+ la $4,small_local_common-0x8000($5)
+ la $4,data_label+0x10000($5)
+ la $4,big_external_data_label+0x10000($5)
+ la $4,small_external_data_label+0x10000($5)
+ la $4,big_external_common+0x10000($5)
+ la $4,small_external_common+0x10000($5)
+ la $4,big_local_common+0x10000($5)
+ la $4,small_local_common+0x10000($5)
+ la $4,data_label+0x1a5a5($5)
+ la $4,big_external_data_label+0x1a5a5($5)
+ la $4,small_external_data_label+0x1a5a5($5)
+ la $4,big_external_common+0x1a5a5($5)
+ la $4,small_external_common+0x1a5a5($5)
+ la $4,big_local_common+0x1a5a5($5)
+ la $4,small_local_common+0x1a5a5($5)
+
+ .ifndef KPIC
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+ nop
+ nop
+ .endif
diff --git a/gas/testsuite/gas/mips/lb-empic.d b/gas/testsuite/gas/mips/lb-empic.d
new file mode 100644
index 0000000000..9724a32bc6
--- /dev/null
+++ b/gas/testsuite/gas/mips/lb-empic.d
@@ -0,0 +1,102 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS lb-empic
+#as: -mips1 -membedded-pic
+#source: lb-pic.s
+
+# Test the lb macro with -membedded-pic.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> lb \$a0,0\(\$zero\)
+0+0004 <[^>]*> lb \$a0,1\(\$zero\)
+0+0008 <[^>]*> lui \$a0,0x1
+0+000c <[^>]*> lb \$a0,-32768\(\$a0\)
+0+0010 <[^>]*> lb \$a0,-32768\(\$zero\)
+0+0014 <[^>]*> lui \$a0,0x1
+0+0018 <[^>]*> lb \$a0,0\(\$a0\)
+0+001c <[^>]*> lui \$a0,0x2
+0+0020 <[^>]*> lb \$a0,-23131\(\$a0\)
+0+0024 <[^>]*> lb \$a0,0\(\$a1\)
+0+0028 <[^>]*> lb \$a0,1\(\$a1\)
+0+002c <[^>]*> lui \$a0,0x1
+0+0030 <[^>]*> addu \$a0,\$a0,\$a1
+0+0034 <[^>]*> lb \$a0,-32768\(\$a0\)
+0+0038 <[^>]*> lb \$a0,-32768\(\$a1\)
+0+003c <[^>]*> lui \$a0,0x1
+0+0040 <[^>]*> addu \$a0,\$a0,\$a1
+0+0044 <[^>]*> lb \$a0,0\(\$a0\)
+0+0048 <[^>]*> lui \$a0,0x2
+0+004c <[^>]*> addu \$a0,\$a0,\$a1
+0+0050 <[^>]*> lb \$a0,-23131\(\$a0\)
+0+0054 <[^>]*> lb \$a0,-16384\(\$gp\)
+[ ]*54: [A-Z0-9_]*GPREL[A-Z0-9_]* .sdata.*
+0+0058 <[^>]*> lb \$a0,0\(\$gp\)
+[ ]*58: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_data_label
+0+005c <[^>]*> lb \$a0,0\(\$gp\)
+[ ]*5c: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+0060 <[^>]*> lb \$a0,0\(\$gp\)
+[ ]*60: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_common
+0+0064 <[^>]*> lb \$a0,0\(\$gp\)
+[ ]*64: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+0068 <[^>]*> lb \$a0,-16384\(\$gp\)
+[ ]*68: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+006c <[^>]*> lb \$a0,-15384\(\$gp\)
+[ ]*6c: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0070 <[^>]*> lb \$a0,-16383\(\$gp\)
+[ ]*70: [A-Z0-9_]*GPREL[A-Z0-9_]* .sdata.*
+0+0074 <[^>]*> lb \$a0,1\(\$gp\)
+[ ]*74: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_data_label
+0+0078 <[^>]*> lb \$a0,1\(\$gp\)
+[ ]*78: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+007c <[^>]*> lb \$a0,1\(\$gp\)
+[ ]*7c: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_common
+0+0080 <[^>]*> lb \$a0,1\(\$gp\)
+[ ]*80: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+0084 <[^>]*> lb \$a0,-16383\(\$gp\)
+[ ]*84: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0088 <[^>]*> lb \$a0,-15383\(\$gp\)
+[ ]*88: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+008c <[^>]*> addu \$a0,\$a1,\$gp
+0+0090 <[^>]*> lb \$a0,-16384\(\$a0\)
+[ ]*90: [A-Z0-9_]*GPREL[A-Z0-9_]* .sdata.*
+0+0094 <[^>]*> addu \$a0,\$a1,\$gp
+0+0098 <[^>]*> lb \$a0,0\(\$a0\)
+[ ]*98: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_data_label
+0+009c <[^>]*> addu \$a0,\$a1,\$gp
+0+00a0 <[^>]*> lb \$a0,0\(\$a0\)
+[ ]*a0: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00a4 <[^>]*> addu \$a0,\$a1,\$gp
+0+00a8 <[^>]*> lb \$a0,0\(\$a0\)
+[ ]*a8: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_common
+0+00ac <[^>]*> addu \$a0,\$a1,\$gp
+0+00b0 <[^>]*> lb \$a0,0\(\$a0\)
+[ ]*b0: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+00b4 <[^>]*> addu \$a0,\$a1,\$gp
+0+00b8 <[^>]*> lb \$a0,-16384\(\$a0\)
+[ ]*b8: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00bc <[^>]*> addu \$a0,\$a1,\$gp
+0+00c0 <[^>]*> lb \$a0,-15384\(\$a0\)
+[ ]*c0: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00c4 <[^>]*> addu \$a0,\$a1,\$gp
+0+00c8 <[^>]*> lb \$a0,-16383\(\$a0\)
+[ ]*c8: [A-Z0-9_]*GPREL[A-Z0-9_]* .sdata.*
+0+00cc <[^>]*> addu \$a0,\$a1,\$gp
+0+00d0 <[^>]*> lb \$a0,1\(\$a0\)
+[ ]*d0: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_data_label
+0+00d4 <[^>]*> addu \$a0,\$a1,\$gp
+0+00d8 <[^>]*> lb \$a0,1\(\$a0\)
+[ ]*d8: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00dc <[^>]*> addu \$a0,\$a1,\$gp
+0+00e0 <[^>]*> lb \$a0,1\(\$a0\)
+[ ]*e0: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_common
+0+00e4 <[^>]*> addu \$a0,\$a1,\$gp
+0+00e8 <[^>]*> lb \$a0,1\(\$a0\)
+[ ]*e8: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+00ec <[^>]*> addu \$a0,\$a1,\$gp
+0+00f0 <[^>]*> lb \$a0,-16383\(\$a0\)
+[ ]*f0: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00f4 <[^>]*> addu \$a0,\$a1,\$gp
+0+00f8 <[^>]*> lb \$a0,-15383\(\$a0\)
+[ ]*f8: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00fc <[^>]*> nop
diff --git a/gas/testsuite/gas/mips/lb-pic.s b/gas/testsuite/gas/mips/lb-pic.s
new file mode 100644
index 0000000000..f2cfdf9b93
--- /dev/null
+++ b/gas/testsuite/gas/mips/lb-pic.s
@@ -0,0 +1,55 @@
+# Source file used to test the lb macro with PIC code.
+
+ .data
+data_label:
+ .extern big_external_data_label,1000
+ .extern small_external_data_label,1
+ .comm big_external_common,1000
+ .comm small_external_common,1
+ .lcomm big_local_common,1000
+ .lcomm small_local_common,1
+
+ .text
+ lb $4,0
+ lb $4,1
+ lb $4,0x8000
+ lb $4,-0x8000
+ lb $4,0x10000
+ lb $4,0x1a5a5
+ lb $4,0($5)
+ lb $4,1($5)
+ lb $4,0x8000($5)
+ lb $4,-0x8000($5)
+ lb $4,0x10000($5)
+ lb $4,0x1a5a5($5)
+ lb $4,data_label
+ lb $4,big_external_data_label
+ lb $4,small_external_data_label
+ lb $4,big_external_common
+ lb $4,small_external_common
+ lb $4,big_local_common
+ lb $4,small_local_common
+ lb $4,data_label+1
+ lb $4,big_external_data_label+1
+ lb $4,small_external_data_label+1
+ lb $4,big_external_common+1
+ lb $4,small_external_common+1
+ lb $4,big_local_common+1
+ lb $4,small_local_common+1
+ lb $4,data_label($5)
+ lb $4,big_external_data_label($5)
+ lb $4,small_external_data_label($5)
+ lb $4,big_external_common($5)
+ lb $4,small_external_common($5)
+ lb $4,big_local_common($5)
+ lb $4,small_local_common($5)
+ lb $4,data_label+1($5)
+ lb $4,big_external_data_label+1($5)
+ lb $4,small_external_data_label+1($5)
+ lb $4,big_external_common+1($5)
+ lb $4,small_external_common+1($5)
+ lb $4,big_local_common+1($5)
+ lb $4,small_local_common+1($5)
+
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+ nop
diff --git a/gas/testsuite/gas/mips/lb-svr4pic.d b/gas/testsuite/gas/mips/lb-svr4pic.d
new file mode 100644
index 0000000000..7d884d60ca
--- /dev/null
+++ b/gas/testsuite/gas/mips/lb-svr4pic.d
@@ -0,0 +1,182 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS lb-svr4pic
+#as: -mips1 -KPIC
+#source: lb-pic.s
+
+# Test the lb macro with -KPIC.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> lb \$a0,0\(\$zero\)
+0+0004 <[^>]*> lb \$a0,1\(\$zero\)
+0+0008 <[^>]*> lui \$a0,0x1
+0+000c <[^>]*> lb \$a0,-32768\(\$a0\)
+0+0010 <[^>]*> lb \$a0,-32768\(\$zero\)
+0+0014 <[^>]*> lui \$a0,0x1
+0+0018 <[^>]*> lb \$a0,0\(\$a0\)
+0+001c <[^>]*> lui \$a0,0x2
+0+0020 <[^>]*> lb \$a0,-23131\(\$a0\)
+0+0024 <[^>]*> lb \$a0,0\(\$a1\)
+0+0028 <[^>]*> lb \$a0,1\(\$a1\)
+0+002c <[^>]*> lui \$a0,0x1
+0+0030 <[^>]*> addu \$a0,\$a0,\$a1
+0+0034 <[^>]*> lb \$a0,-32768\(\$a0\)
+0+0038 <[^>]*> lb \$a0,-32768\(\$a1\)
+0+003c <[^>]*> lui \$a0,0x1
+0+0040 <[^>]*> addu \$a0,\$a0,\$a1
+0+0044 <[^>]*> lb \$a0,0\(\$a0\)
+0+0048 <[^>]*> lui \$a0,0x2
+0+004c <[^>]*> addu \$a0,\$a0,\$a1
+0+0050 <[^>]*> lb \$a0,-23131\(\$a0\)
+0+0054 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*54: R_MIPS_GOT16 .data
+0+0058 <[^>]*> nop
+0+005c <[^>]*> addiu \$a0,\$a0,0
+[ ]*5c: R_MIPS_LO16 .data
+0+0060 <[^>]*> lb \$a0,0\(\$a0\)
+0+0064 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*64: R_MIPS_GOT16 big_external_data_label
+0+0068 <[^>]*> nop
+0+006c <[^>]*> lb \$a0,0\(\$a0\)
+0+0070 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*70: R_MIPS_GOT16 small_external_data_label
+0+0074 <[^>]*> nop
+0+0078 <[^>]*> lb \$a0,0\(\$a0\)
+0+007c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*7c: R_MIPS_GOT16 big_external_common
+0+0080 <[^>]*> nop
+0+0084 <[^>]*> lb \$a0,0\(\$a0\)
+0+0088 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*88: R_MIPS_GOT16 small_external_common
+0+008c <[^>]*> nop
+0+0090 <[^>]*> lb \$a0,0\(\$a0\)
+0+0094 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*94: R_MIPS_GOT16 .bss
+0+0098 <[^>]*> nop
+0+009c <[^>]*> addiu \$a0,\$a0,0
+[ ]*9c: R_MIPS_LO16 .bss
+0+00a0 <[^>]*> lb \$a0,0\(\$a0\)
+0+00a4 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*a4: R_MIPS_GOT16 .bss
+0+00a8 <[^>]*> nop
+0+00ac <[^>]*> addiu \$a0,\$a0,1000
+[ ]*ac: R_MIPS_LO16 .bss
+0+00b0 <[^>]*> lb \$a0,0\(\$a0\)
+0+00b4 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*b4: R_MIPS_GOT16 .data
+0+00b8 <[^>]*> nop
+0+00bc <[^>]*> addiu \$a0,\$a0,0
+[ ]*bc: R_MIPS_LO16 .data
+0+00c0 <[^>]*> lb \$a0,1\(\$a0\)
+0+00c4 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*c4: R_MIPS_GOT16 big_external_data_label
+0+00c8 <[^>]*> nop
+0+00cc <[^>]*> lb \$a0,1\(\$a0\)
+0+00d0 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*d0: R_MIPS_GOT16 small_external_data_label
+0+00d4 <[^>]*> nop
+0+00d8 <[^>]*> lb \$a0,1\(\$a0\)
+0+00dc <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*dc: R_MIPS_GOT16 big_external_common
+0+00e0 <[^>]*> nop
+0+00e4 <[^>]*> lb \$a0,1\(\$a0\)
+0+00e8 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*e8: R_MIPS_GOT16 small_external_common
+0+00ec <[^>]*> nop
+0+00f0 <[^>]*> lb \$a0,1\(\$a0\)
+0+00f4 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*f4: R_MIPS_GOT16 .bss
+0+00f8 <[^>]*> nop
+0+00fc <[^>]*> addiu \$a0,\$a0,0
+[ ]*fc: R_MIPS_LO16 .bss
+0+0100 <[^>]*> lb \$a0,1\(\$a0\)
+0+0104 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*104: R_MIPS_GOT16 .bss
+0+0108 <[^>]*> nop
+0+010c <[^>]*> addiu \$a0,\$a0,1000
+[ ]*10c: R_MIPS_LO16 .bss
+0+0110 <[^>]*> lb \$a0,1\(\$a0\)
+0+0114 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*114: R_MIPS_GOT16 .data
+0+0118 <[^>]*> nop
+0+011c <[^>]*> addiu \$a0,\$a0,0
+[ ]*11c: R_MIPS_LO16 .data
+0+0120 <[^>]*> addu \$a0,\$a0,\$a1
+0+0124 <[^>]*> lb \$a0,0\(\$a0\)
+0+0128 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*128: R_MIPS_GOT16 big_external_data_label
+0+012c <[^>]*> nop
+0+0130 <[^>]*> addu \$a0,\$a0,\$a1
+0+0134 <[^>]*> lb \$a0,0\(\$a0\)
+0+0138 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*138: R_MIPS_GOT16 small_external_data_label
+0+013c <[^>]*> nop
+0+0140 <[^>]*> addu \$a0,\$a0,\$a1
+0+0144 <[^>]*> lb \$a0,0\(\$a0\)
+0+0148 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*148: R_MIPS_GOT16 big_external_common
+0+014c <[^>]*> nop
+0+0150 <[^>]*> addu \$a0,\$a0,\$a1
+0+0154 <[^>]*> lb \$a0,0\(\$a0\)
+0+0158 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*158: R_MIPS_GOT16 small_external_common
+0+015c <[^>]*> nop
+0+0160 <[^>]*> addu \$a0,\$a0,\$a1
+0+0164 <[^>]*> lb \$a0,0\(\$a0\)
+0+0168 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*168: R_MIPS_GOT16 .bss
+0+016c <[^>]*> nop
+0+0170 <[^>]*> addiu \$a0,\$a0,0
+[ ]*170: R_MIPS_LO16 .bss
+0+0174 <[^>]*> addu \$a0,\$a0,\$a1
+0+0178 <[^>]*> lb \$a0,0\(\$a0\)
+0+017c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*17c: R_MIPS_GOT16 .bss
+0+0180 <[^>]*> nop
+0+0184 <[^>]*> addiu \$a0,\$a0,1000
+[ ]*184: R_MIPS_LO16 .bss
+0+0188 <[^>]*> addu \$a0,\$a0,\$a1
+0+018c <[^>]*> lb \$a0,0\(\$a0\)
+0+0190 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*190: R_MIPS_GOT16 .data
+0+0194 <[^>]*> nop
+0+0198 <[^>]*> addiu \$a0,\$a0,0
+[ ]*198: R_MIPS_LO16 .data
+0+019c <[^>]*> addu \$a0,\$a0,\$a1
+0+01a0 <[^>]*> lb \$a0,1\(\$a0\)
+0+01a4 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*1a4: R_MIPS_GOT16 big_external_data_label
+0+01a8 <[^>]*> nop
+0+01ac <[^>]*> addu \$a0,\$a0,\$a1
+0+01b0 <[^>]*> lb \$a0,1\(\$a0\)
+0+01b4 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*1b4: R_MIPS_GOT16 small_external_data_label
+0+01b8 <[^>]*> nop
+0+01bc <[^>]*> addu \$a0,\$a0,\$a1
+0+01c0 <[^>]*> lb \$a0,1\(\$a0\)
+0+01c4 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*1c4: R_MIPS_GOT16 big_external_common
+0+01c8 <[^>]*> nop
+0+01cc <[^>]*> addu \$a0,\$a0,\$a1
+0+01d0 <[^>]*> lb \$a0,1\(\$a0\)
+0+01d4 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*1d4: R_MIPS_GOT16 small_external_common
+0+01d8 <[^>]*> nop
+0+01dc <[^>]*> addu \$a0,\$a0,\$a1
+0+01e0 <[^>]*> lb \$a0,1\(\$a0\)
+0+01e4 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*1e4: R_MIPS_GOT16 .bss
+0+01e8 <[^>]*> nop
+0+01ec <[^>]*> addiu \$a0,\$a0,0
+[ ]*1ec: R_MIPS_LO16 .bss
+0+01f0 <[^>]*> addu \$a0,\$a0,\$a1
+0+01f4 <[^>]*> lb \$a0,1\(\$a0\)
+0+01f8 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*1f8: R_MIPS_GOT16 .bss
+0+01fc <[^>]*> nop
+0+0200 <[^>]*> addiu \$a0,\$a0,1000
+[ ]*200: R_MIPS_LO16 .bss
+0+0204 <[^>]*> addu \$a0,\$a0,\$a1
+0+0208 <[^>]*> lb \$a0,1\(\$a0\)
+0+020c <[^>]*> nop
diff --git a/gas/testsuite/gas/mips/lb-xgot-ilocks.d b/gas/testsuite/gas/mips/lb-xgot-ilocks.d
new file mode 100644
index 0000000000..c08bd24c97
--- /dev/null
+++ b/gas/testsuite/gas/mips/lb-xgot-ilocks.d
@@ -0,0 +1,214 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS lb-xgot-ilocks
+#as: -mips1 -KPIC -xgot -mcpu=r3900
+#source: lb-pic.s
+
+# Test the lb macro with -KPIC -xgot.
+
+.*: +file format .*
+
+Disassembly of section \.text:
+0+0000 <.*> lb \$a0,0\(\$zero\)
+0+0004 <.*> lb \$a0,1\(\$zero\)
+0+0008 <.*> lui \$a0,0x1
+0+000c <.*> lb \$a0,-32768\(\$a0\)
+0+0010 <.*> lb \$a0,-32768\(\$zero\)
+0+0014 <.*> lui \$a0,0x1
+0+0018 <.*> lb \$a0,0\(\$a0\)
+0+001c <.*> lui \$a0,0x2
+0+0020 <.*> lb \$a0,-23131\(\$a0\)
+0+0024 <.*> lb \$a0,0\(\$a1\)
+0+0028 <.*> lb \$a0,1\(\$a1\)
+0+002c <.*> lui \$a0,0x1
+0+0030 <.*> addu \$a0,\$a0,\$a1
+0+0034 <.*> lb \$a0,-32768\(\$a0\)
+0+0038 <.*> lb \$a0,-32768\(\$a1\)
+0+003c <.*> lui \$a0,0x1
+0+0040 <.*> addu \$a0,\$a0,\$a1
+0+0044 <.*> lb \$a0,0\(\$a0\)
+0+0048 <.*> lui \$a0,0x2
+0+004c <.*> addu \$a0,\$a0,\$a1
+0+0050 <.*> lb \$a0,-23131\(\$a0\)
+0+0054 <.*> lw \$a0,0\(\$gp\)
+ 54: R_MIPS_GOT16 \.data
+0+0058 <.*> nop
+0+005c <.*> addiu \$a0,\$a0,0
+ 5c: R_MIPS_LO16 \.data
+0+0060 <.*> lb \$a0,0\(\$a0\)
+0+0064 <.*> lui \$a0,0x0
+ 64: R_MIPS_GOT_HI16 big_external_data_label
+0+0068 <.*> addu \$a0,\$a0,\$gp
+0+006c <.*> lw \$a0,0\(\$a0\)
+ 6c: R_MIPS_GOT_LO16 big_external_data_label
+0+0070 <.*> lb \$a0,0\(\$a0\)
+0+0074 <.*> lui \$a0,0x0
+ 74: R_MIPS_GOT_HI16 small_external_data_label
+0+0078 <.*> addu \$a0,\$a0,\$gp
+0+007c <.*> lw \$a0,0\(\$a0\)
+ 7c: R_MIPS_GOT_LO16 small_external_data_label
+0+0080 <.*> lb \$a0,0\(\$a0\)
+0+0084 <.*> lui \$a0,0x0
+ 84: R_MIPS_GOT_HI16 big_external_common
+0+0088 <.*> addu \$a0,\$a0,\$gp
+0+008c <.*> lw \$a0,0\(\$a0\)
+ 8c: R_MIPS_GOT_LO16 big_external_common
+0+0090 <.*> lb \$a0,0\(\$a0\)
+0+0094 <.*> lui \$a0,0x0
+ 94: R_MIPS_GOT_HI16 small_external_common
+0+0098 <.*> addu \$a0,\$a0,\$gp
+0+009c <.*> lw \$a0,0\(\$a0\)
+ 9c: R_MIPS_GOT_LO16 small_external_common
+0+00a0 <.*> lb \$a0,0\(\$a0\)
+0+00a4 <.*> lw \$a0,0\(\$gp\)
+ a4: R_MIPS_GOT16 \.bss
+0+00a8 <.*> nop
+0+00ac <.*> addiu \$a0,\$a0,0
+ ac: R_MIPS_LO16 \.bss
+0+00b0 <.*> lb \$a0,0\(\$a0\)
+0+00b4 <.*> lw \$a0,0\(\$gp\)
+ b4: R_MIPS_GOT16 \.bss
+0+00b8 <.*> nop
+0+00bc <.*> addiu \$a0,\$a0,1000
+ bc: R_MIPS_LO16 \.bss
+0+00c0 <.*> lb \$a0,0\(\$a0\)
+0+00c4 <.*> lw \$a0,0\(\$gp\)
+ c4: R_MIPS_GOT16 \.data
+0+00c8 <.*> nop
+0+00cc <.*> addiu \$a0,\$a0,0
+ cc: R_MIPS_LO16 \.data
+0+00d0 <.*> lb \$a0,1\(\$a0\)
+0+00d4 <.*> lui \$a0,0x0
+ d4: R_MIPS_GOT_HI16 big_external_data_label
+0+00d8 <.*> addu \$a0,\$a0,\$gp
+0+00dc <.*> lw \$a0,0\(\$a0\)
+ dc: R_MIPS_GOT_LO16 big_external_data_label
+0+00e0 <.*> lb \$a0,1\(\$a0\)
+0+00e4 <.*> lui \$a0,0x0
+ e4: R_MIPS_GOT_HI16 small_external_data_label
+0+00e8 <.*> addu \$a0,\$a0,\$gp
+0+00ec <.*> lw \$a0,0\(\$a0\)
+ ec: R_MIPS_GOT_LO16 small_external_data_label
+0+00f0 <.*> lb \$a0,1\(\$a0\)
+0+00f4 <.*> lui \$a0,0x0
+ f4: R_MIPS_GOT_HI16 big_external_common
+0+00f8 <.*> addu \$a0,\$a0,\$gp
+0+00fc <.*> lw \$a0,0\(\$a0\)
+ fc: R_MIPS_GOT_LO16 big_external_common
+0+0100 <.*> lb \$a0,1\(\$a0\)
+0+0104 <.*> lui \$a0,0x0
+ 104: R_MIPS_GOT_HI16 small_external_common
+0+0108 <.*> addu \$a0,\$a0,\$gp
+0+010c <.*> lw \$a0,0\(\$a0\)
+ 10c: R_MIPS_GOT_LO16 small_external_common
+0+0110 <.*> lb \$a0,1\(\$a0\)
+0+0114 <.*> lw \$a0,0\(\$gp\)
+ 114: R_MIPS_GOT16 \.bss
+0+0118 <.*> nop
+0+011c <.*> addiu \$a0,\$a0,0
+ 11c: R_MIPS_LO16 \.bss
+0+0120 <.*> lb \$a0,1\(\$a0\)
+0+0124 <.*> lw \$a0,0\(\$gp\)
+ 124: R_MIPS_GOT16 \.bss
+0+0128 <.*> nop
+0+012c <.*> addiu \$a0,\$a0,1000
+ 12c: R_MIPS_LO16 \.bss
+0+0130 <.*> lb \$a0,1\(\$a0\)
+0+0134 <.*> lw \$a0,0\(\$gp\)
+ 134: R_MIPS_GOT16 \.data
+0+0138 <.*> nop
+0+013c <.*> addiu \$a0,\$a0,0
+ 13c: R_MIPS_LO16 \.data
+0+0140 <.*> addu \$a0,\$a0,\$a1
+0+0144 <.*> lb \$a0,0\(\$a0\)
+0+0148 <.*> lui \$a0,0x0
+ 148: R_MIPS_GOT_HI16 big_external_data_label
+0+014c <.*> addu \$a0,\$a0,\$gp
+0+0150 <.*> lw \$a0,0\(\$a0\)
+ 150: R_MIPS_GOT_LO16 big_external_data_label
+0+0154 <.*> addu \$a0,\$a0,\$a1
+0+0158 <.*> lb \$a0,0\(\$a0\)
+0+015c <.*> lui \$a0,0x0
+ 15c: R_MIPS_GOT_HI16 small_external_data_label
+0+0160 <.*> addu \$a0,\$a0,\$gp
+0+0164 <.*> lw \$a0,0\(\$a0\)
+ 164: R_MIPS_GOT_LO16 small_external_data_label
+0+0168 <.*> addu \$a0,\$a0,\$a1
+0+016c <.*> lb \$a0,0\(\$a0\)
+0+0170 <.*> lui \$a0,0x0
+ 170: R_MIPS_GOT_HI16 big_external_common
+0+0174 <.*> addu \$a0,\$a0,\$gp
+0+0178 <.*> lw \$a0,0\(\$a0\)
+ 178: R_MIPS_GOT_LO16 big_external_common
+0+017c <.*> addu \$a0,\$a0,\$a1
+0+0180 <.*> lb \$a0,0\(\$a0\)
+0+0184 <.*> lui \$a0,0x0
+ 184: R_MIPS_GOT_HI16 small_external_common
+0+0188 <.*> addu \$a0,\$a0,\$gp
+0+018c <.*> lw \$a0,0\(\$a0\)
+ 18c: R_MIPS_GOT_LO16 small_external_common
+0+0190 <.*> addu \$a0,\$a0,\$a1
+0+0194 <.*> lb \$a0,0\(\$a0\)
+0+0198 <.*> lw \$a0,0\(\$gp\)
+ 198: R_MIPS_GOT16 \.bss
+0+019c <.*> nop
+0+01a0 <.*> addiu \$a0,\$a0,0
+ 1a0: R_MIPS_LO16 \.bss
+0+01a4 <.*> addu \$a0,\$a0,\$a1
+0+01a8 <.*> lb \$a0,0\(\$a0\)
+0+01ac <.*> lw \$a0,0\(\$gp\)
+ 1ac: R_MIPS_GOT16 \.bss
+0+01b0 <.*> nop
+0+01b4 <.*> addiu \$a0,\$a0,1000
+ 1b4: R_MIPS_LO16 \.bss
+0+01b8 <.*> addu \$a0,\$a0,\$a1
+0+01bc <.*> lb \$a0,0\(\$a0\)
+0+01c0 <.*> lw \$a0,0\(\$gp\)
+ 1c0: R_MIPS_GOT16 \.data
+0+01c4 <.*> nop
+0+01c8 <.*> addiu \$a0,\$a0,0
+ 1c8: R_MIPS_LO16 \.data
+0+01cc <.*> addu \$a0,\$a0,\$a1
+0+01d0 <.*> lb \$a0,1\(\$a0\)
+0+01d4 <.*> lui \$a0,0x0
+ 1d4: R_MIPS_GOT_HI16 big_external_data_label
+0+01d8 <.*> addu \$a0,\$a0,\$gp
+0+01dc <.*> lw \$a0,0\(\$a0\)
+ 1dc: R_MIPS_GOT_LO16 big_external_data_label
+0+01e0 <.*> addu \$a0,\$a0,\$a1
+0+01e4 <.*> lb \$a0,1\(\$a0\)
+0+01e8 <.*> lui \$a0,0x0
+ 1e8: R_MIPS_GOT_HI16 small_external_data_label
+0+01ec <.*> addu \$a0,\$a0,\$gp
+0+01f0 <.*> lw \$a0,0\(\$a0\)
+ 1f0: R_MIPS_GOT_LO16 small_external_data_label
+0+01f4 <.*> addu \$a0,\$a0,\$a1
+0+01f8 <.*> lb \$a0,1\(\$a0\)
+0+01fc <.*> lui \$a0,0x0
+ 1fc: R_MIPS_GOT_HI16 big_external_common
+0+0200 <.*> addu \$a0,\$a0,\$gp
+0+0204 <.*> lw \$a0,0\(\$a0\)
+ 204: R_MIPS_GOT_LO16 big_external_common
+0+0208 <.*> addu \$a0,\$a0,\$a1
+0+020c <.*> lb \$a0,1\(\$a0\)
+0+0210 <.*> lui \$a0,0x0
+ 210: R_MIPS_GOT_HI16 small_external_common
+0+0214 <.*> addu \$a0,\$a0,\$gp
+0+0218 <.*> lw \$a0,0\(\$a0\)
+ 218: R_MIPS_GOT_LO16 small_external_common
+0+021c <.*> addu \$a0,\$a0,\$a1
+0+0220 <.*> lb \$a0,1\(\$a0\)
+0+0224 <.*> lw \$a0,0\(\$gp\)
+ 224: R_MIPS_GOT16 \.bss
+0+0228 <.*> nop
+0+022c <.*> addiu \$a0,\$a0,0
+ 22c: R_MIPS_LO16 \.bss
+0+0230 <.*> addu \$a0,\$a0,\$a1
+0+0234 <.*> lb \$a0,1\(\$a0\)
+0+0238 <.*> lw \$a0,0\(\$gp\)
+ 238: R_MIPS_GOT16 \.bss
+0+023c <.*> nop
+0+0240 <.*> addiu \$a0,\$a0,1000
+ 240: R_MIPS_LO16 \.bss
+0+0244 <.*> addu \$a0,\$a0,\$a1
+0+0248 <.*> lb \$a0,1\(\$a0\)
+0+024c <.*> nop
diff --git a/gas/testsuite/gas/mips/lb-xgot.d b/gas/testsuite/gas/mips/lb-xgot.d
new file mode 100644
index 0000000000..b18c67e597
--- /dev/null
+++ b/gas/testsuite/gas/mips/lb-xgot.d
@@ -0,0 +1,242 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS lb-xgot
+#as: -mips1 -KPIC -xgot -mcpu=r3000
+#source: lb-pic.s
+
+# Test the lb macro with -KPIC -xgot.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> lb \$a0,0\(\$zero\)
+0+0004 <[^>]*> lb \$a0,1\(\$zero\)
+0+0008 <[^>]*> lui \$a0,0x1
+0+000c <[^>]*> lb \$a0,-32768\(\$a0\)
+0+0010 <[^>]*> lb \$a0,-32768\(\$zero\)
+0+0014 <[^>]*> lui \$a0,0x1
+0+0018 <[^>]*> lb \$a0,0\(\$a0\)
+0+001c <[^>]*> lui \$a0,0x2
+0+0020 <[^>]*> lb \$a0,-23131\(\$a0\)
+0+0024 <[^>]*> lb \$a0,0\(\$a1\)
+0+0028 <[^>]*> lb \$a0,1\(\$a1\)
+0+002c <[^>]*> lui \$a0,0x1
+0+0030 <[^>]*> addu \$a0,\$a0,\$a1
+0+0034 <[^>]*> lb \$a0,-32768\(\$a0\)
+0+0038 <[^>]*> lb \$a0,-32768\(\$a1\)
+0+003c <[^>]*> lui \$a0,0x1
+0+0040 <[^>]*> addu \$a0,\$a0,\$a1
+0+0044 <[^>]*> lb \$a0,0\(\$a0\)
+0+0048 <[^>]*> lui \$a0,0x2
+0+004c <[^>]*> addu \$a0,\$a0,\$a1
+0+0050 <[^>]*> lb \$a0,-23131\(\$a0\)
+0+0054 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*54: R_MIPS_GOT16 .data
+0+0058 <[^>]*> nop
+0+005c <[^>]*> addiu \$a0,\$a0,0
+[ ]*5c: R_MIPS_LO16 .data
+0+0060 <[^>]*> nop
+0+0064 <[^>]*> lb \$a0,0\(\$a0\)
+0+0068 <[^>]*> lui \$a0,0x0
+[ ]*68: R_MIPS_GOT_HI16 big_external_data_label
+0+006c <[^>]*> addu \$a0,\$a0,\$gp
+0+0070 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*70: R_MIPS_GOT_LO16 big_external_data_label
+0+0074 <[^>]*> nop
+0+0078 <[^>]*> lb \$a0,0\(\$a0\)
+0+007c <[^>]*> lui \$a0,0x0
+[ ]*7c: R_MIPS_GOT_HI16 small_external_data_label
+0+0080 <[^>]*> addu \$a0,\$a0,\$gp
+0+0084 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*84: R_MIPS_GOT_LO16 small_external_data_label
+0+0088 <[^>]*> nop
+0+008c <[^>]*> lb \$a0,0\(\$a0\)
+0+0090 <[^>]*> lui \$a0,0x0
+[ ]*90: R_MIPS_GOT_HI16 big_external_common
+0+0094 <[^>]*> addu \$a0,\$a0,\$gp
+0+0098 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*98: R_MIPS_GOT_LO16 big_external_common
+0+009c <[^>]*> nop
+0+00a0 <[^>]*> lb \$a0,0\(\$a0\)
+0+00a4 <[^>]*> lui \$a0,0x0
+[ ]*a4: R_MIPS_GOT_HI16 small_external_common
+0+00a8 <[^>]*> addu \$a0,\$a0,\$gp
+0+00ac <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*ac: R_MIPS_GOT_LO16 small_external_common
+0+00b0 <[^>]*> nop
+0+00b4 <[^>]*> lb \$a0,0\(\$a0\)
+0+00b8 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*b8: R_MIPS_GOT16 .bss
+0+00bc <[^>]*> nop
+0+00c0 <[^>]*> addiu \$a0,\$a0,0
+[ ]*c0: R_MIPS_LO16 .bss
+0+00c4 <[^>]*> nop
+0+00c8 <[^>]*> lb \$a0,0\(\$a0\)
+0+00cc <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*cc: R_MIPS_GOT16 .bss
+0+00d0 <[^>]*> nop
+0+00d4 <[^>]*> addiu \$a0,\$a0,1000
+[ ]*d4: R_MIPS_LO16 .bss
+0+00d8 <[^>]*> nop
+0+00dc <[^>]*> lb \$a0,0\(\$a0\)
+0+00e0 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*e0: R_MIPS_GOT16 .data
+0+00e4 <[^>]*> nop
+0+00e8 <[^>]*> addiu \$a0,\$a0,0
+[ ]*e8: R_MIPS_LO16 .data
+0+00ec <[^>]*> nop
+0+00f0 <[^>]*> lb \$a0,1\(\$a0\)
+0+00f4 <[^>]*> lui \$a0,0x0
+[ ]*f4: R_MIPS_GOT_HI16 big_external_data_label
+0+00f8 <[^>]*> addu \$a0,\$a0,\$gp
+0+00fc <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*fc: R_MIPS_GOT_LO16 big_external_data_label
+0+0100 <[^>]*> nop
+0+0104 <[^>]*> lb \$a0,1\(\$a0\)
+0+0108 <[^>]*> lui \$a0,0x0
+[ ]*108: R_MIPS_GOT_HI16 small_external_data_label
+0+010c <[^>]*> addu \$a0,\$a0,\$gp
+0+0110 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*110: R_MIPS_GOT_LO16 small_external_data_label
+0+0114 <[^>]*> nop
+0+0118 <[^>]*> lb \$a0,1\(\$a0\)
+0+011c <[^>]*> lui \$a0,0x0
+[ ]*11c: R_MIPS_GOT_HI16 big_external_common
+0+0120 <[^>]*> addu \$a0,\$a0,\$gp
+0+0124 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*124: R_MIPS_GOT_LO16 big_external_common
+0+0128 <[^>]*> nop
+0+012c <[^>]*> lb \$a0,1\(\$a0\)
+0+0130 <[^>]*> lui \$a0,0x0
+[ ]*130: R_MIPS_GOT_HI16 small_external_common
+0+0134 <[^>]*> addu \$a0,\$a0,\$gp
+0+0138 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*138: R_MIPS_GOT_LO16 small_external_common
+0+013c <[^>]*> nop
+0+0140 <[^>]*> lb \$a0,1\(\$a0\)
+0+0144 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*144: R_MIPS_GOT16 .bss
+0+0148 <[^>]*> nop
+0+014c <[^>]*> addiu \$a0,\$a0,0
+[ ]*14c: R_MIPS_LO16 .bss
+0+0150 <[^>]*> nop
+0+0154 <[^>]*> lb \$a0,1\(\$a0\)
+0+0158 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*158: R_MIPS_GOT16 .bss
+0+015c <[^>]*> nop
+0+0160 <[^>]*> addiu \$a0,\$a0,1000
+[ ]*160: R_MIPS_LO16 .bss
+0+0164 <[^>]*> nop
+0+0168 <[^>]*> lb \$a0,1\(\$a0\)
+0+016c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*16c: R_MIPS_GOT16 .data
+0+0170 <[^>]*> nop
+0+0174 <[^>]*> addiu \$a0,\$a0,0
+[ ]*174: R_MIPS_LO16 .data
+0+0178 <[^>]*> nop
+0+017c <[^>]*> addu \$a0,\$a0,\$a1
+0+0180 <[^>]*> lb \$a0,0\(\$a0\)
+0+0184 <[^>]*> lui \$a0,0x0
+[ ]*184: R_MIPS_GOT_HI16 big_external_data_label
+0+0188 <[^>]*> addu \$a0,\$a0,\$gp
+0+018c <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*18c: R_MIPS_GOT_LO16 big_external_data_label
+0+0190 <[^>]*> nop
+0+0194 <[^>]*> addu \$a0,\$a0,\$a1
+0+0198 <[^>]*> lb \$a0,0\(\$a0\)
+0+019c <[^>]*> lui \$a0,0x0
+[ ]*19c: R_MIPS_GOT_HI16 small_external_data_label
+0+01a0 <[^>]*> addu \$a0,\$a0,\$gp
+0+01a4 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*1a4: R_MIPS_GOT_LO16 small_external_data_label
+0+01a8 <[^>]*> nop
+0+01ac <[^>]*> addu \$a0,\$a0,\$a1
+0+01b0 <[^>]*> lb \$a0,0\(\$a0\)
+0+01b4 <[^>]*> lui \$a0,0x0
+[ ]*1b4: R_MIPS_GOT_HI16 big_external_common
+0+01b8 <[^>]*> addu \$a0,\$a0,\$gp
+0+01bc <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*1bc: R_MIPS_GOT_LO16 big_external_common
+0+01c0 <[^>]*> nop
+0+01c4 <[^>]*> addu \$a0,\$a0,\$a1
+0+01c8 <[^>]*> lb \$a0,0\(\$a0\)
+0+01cc <[^>]*> lui \$a0,0x0
+[ ]*1cc: R_MIPS_GOT_HI16 small_external_common
+0+01d0 <[^>]*> addu \$a0,\$a0,\$gp
+0+01d4 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*1d4: R_MIPS_GOT_LO16 small_external_common
+0+01d8 <[^>]*> nop
+0+01dc <[^>]*> addu \$a0,\$a0,\$a1
+0+01e0 <[^>]*> lb \$a0,0\(\$a0\)
+0+01e4 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*1e4: R_MIPS_GOT16 .bss
+0+01e8 <[^>]*> nop
+0+01ec <[^>]*> addiu \$a0,\$a0,0
+[ ]*1ec: R_MIPS_LO16 .bss
+0+01f0 <[^>]*> nop
+0+01f4 <[^>]*> addu \$a0,\$a0,\$a1
+0+01f8 <[^>]*> lb \$a0,0\(\$a0\)
+0+01fc <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*1fc: R_MIPS_GOT16 .bss
+0+0200 <[^>]*> nop
+0+0204 <[^>]*> addiu \$a0,\$a0,1000
+[ ]*204: R_MIPS_LO16 .bss
+0+0208 <[^>]*> nop
+0+020c <[^>]*> addu \$a0,\$a0,\$a1
+0+0210 <[^>]*> lb \$a0,0\(\$a0\)
+0+0214 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*214: R_MIPS_GOT16 .data
+0+0218 <[^>]*> nop
+0+021c <[^>]*> addiu \$a0,\$a0,0
+[ ]*21c: R_MIPS_LO16 .data
+0+0220 <[^>]*> nop
+0+0224 <[^>]*> addu \$a0,\$a0,\$a1
+0+0228 <[^>]*> lb \$a0,1\(\$a0\)
+0+022c <[^>]*> lui \$a0,0x0
+[ ]*22c: R_MIPS_GOT_HI16 big_external_data_label
+0+0230 <[^>]*> addu \$a0,\$a0,\$gp
+0+0234 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*234: R_MIPS_GOT_LO16 big_external_data_label
+0+0238 <[^>]*> nop
+0+023c <[^>]*> addu \$a0,\$a0,\$a1
+0+0240 <[^>]*> lb \$a0,1\(\$a0\)
+0+0244 <[^>]*> lui \$a0,0x0
+[ ]*244: R_MIPS_GOT_HI16 small_external_data_label
+0+0248 <[^>]*> addu \$a0,\$a0,\$gp
+0+024c <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*24c: R_MIPS_GOT_LO16 small_external_data_label
+0+0250 <[^>]*> nop
+0+0254 <[^>]*> addu \$a0,\$a0,\$a1
+0+0258 <[^>]*> lb \$a0,1\(\$a0\)
+0+025c <[^>]*> lui \$a0,0x0
+[ ]*25c: R_MIPS_GOT_HI16 big_external_common
+0+0260 <[^>]*> addu \$a0,\$a0,\$gp
+0+0264 <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*264: R_MIPS_GOT_LO16 big_external_common
+0+0268 <[^>]*> nop
+0+026c <[^>]*> addu \$a0,\$a0,\$a1
+0+0270 <[^>]*> lb \$a0,1\(\$a0\)
+0+0274 <[^>]*> lui \$a0,0x0
+[ ]*274: R_MIPS_GOT_HI16 small_external_common
+0+0278 <[^>]*> addu \$a0,\$a0,\$gp
+0+027c <[^>]*> lw \$a0,0\(\$a0\)
+[ ]*27c: R_MIPS_GOT_LO16 small_external_common
+0+0280 <[^>]*> nop
+0+0284 <[^>]*> addu \$a0,\$a0,\$a1
+0+0288 <[^>]*> lb \$a0,1\(\$a0\)
+0+028c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*28c: R_MIPS_GOT16 .bss
+0+0290 <[^>]*> nop
+0+0294 <[^>]*> addiu \$a0,\$a0,0
+[ ]*294: R_MIPS_LO16 .bss
+0+0298 <[^>]*> nop
+0+029c <[^>]*> addu \$a0,\$a0,\$a1
+0+02a0 <[^>]*> lb \$a0,1\(\$a0\)
+0+02a4 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*2a4: R_MIPS_GOT16 .bss
+0+02a8 <[^>]*> nop
+0+02ac <[^>]*> addiu \$a0,\$a0,1000
+[ ]*2ac: R_MIPS_LO16 .bss
+0+02b0 <[^>]*> nop
+0+02b4 <[^>]*> addu \$a0,\$a0,\$a1
+0+02b8 <[^>]*> lb \$a0,1\(\$a0\)
+0+02bc <[^>]*> nop
diff --git a/gas/testsuite/gas/mips/lb.d b/gas/testsuite/gas/mips/lb.d
new file mode 100644
index 0000000000..e45c4c4ca6
--- /dev/null
+++ b/gas/testsuite/gas/mips/lb.d
@@ -0,0 +1,395 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS lb
+#as: -mips1
+
+# Test the lb macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> lb \$a0,0\(\$zero\)
+0+0004 <[^>]*> lb \$a0,1\(\$zero\)
+0+0008 <[^>]*> lui \$a0,0x1
+0+000c <[^>]*> lb \$a0,-32768\(\$a0\)
+0+0010 <[^>]*> lb \$a0,-32768\(\$zero\)
+0+0014 <[^>]*> lui \$a0,0x1
+0+0018 <[^>]*> lb \$a0,0\(\$a0\)
+0+001c <[^>]*> lui \$a0,0x2
+0+0020 <[^>]*> lb \$a0,-23131\(\$a0\)
+0+0024 <[^>]*> lb \$a0,0\(\$a1\)
+0+0028 <[^>]*> lb \$a0,1\(\$a1\)
+0+002c <[^>]*> lui \$a0,0x1
+0+0030 <[^>]*> addu \$a0,\$a0,\$a1
+0+0034 <[^>]*> lb \$a0,-32768\(\$a0\)
+0+0038 <[^>]*> lb \$a0,-32768\(\$a1\)
+0+003c <[^>]*> lui \$a0,0x1
+0+0040 <[^>]*> addu \$a0,\$a0,\$a1
+0+0044 <[^>]*> lb \$a0,0\(\$a0\)
+0+0048 <[^>]*> lui \$a0,0x2
+0+004c <[^>]*> addu \$a0,\$a0,\$a1
+0+0050 <[^>]*> lb \$a0,-23131\(\$a0\)
+0+0054 <[^>]*> lui \$a0,0x0
+[ ]*54: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0058 <[^>]*> lb \$a0,[0-9]+\(\$a0\)
+[ ]*58: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+005c <[^>]*> lui \$a0,0x0
+[ ]*5c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0060 <[^>]*> lb \$a0,0\(\$a0\)
+[ ]*60: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0064 <[^>]*> lb \$a0,0\(\$gp\)
+[ ]*64: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+0068 <[^>]*> lui \$a0,0x0
+[ ]*68: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+006c <[^>]*> lb \$a0,0\(\$a0\)
+[ ]*6c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0070 <[^>]*> lb \$a0,0\(\$gp\)
+[ ]*70: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+0074 <[^>]*> lui \$a0,0x0
+[ ]*74: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0078 <[^>]*> lb \$a0,[0-9]+\(\$a0\)
+[ ]*78: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+007c <[^>]*> lb \$a0,-16384\(\$gp\)
+[ ]*7c: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0080 <[^>]*> lui \$a0,0x0
+[ ]*80: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0084 <[^>]*> lb \$a0,[0-9]+\(\$a0\)
+[ ]*84: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0088 <[^>]*> lui \$a0,0x0
+[ ]*88: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+008c <[^>]*> lb \$a0,1\(\$a0\)
+[ ]*8c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0090 <[^>]*> lb \$a0,1\(\$gp\)
+[ ]*90: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+0094 <[^>]*> lui \$a0,0x0
+[ ]*94: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0098 <[^>]*> lb \$a0,1\(\$a0\)
+[ ]*98: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+009c <[^>]*> lb \$a0,1\(\$gp\)
+[ ]*9c: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+00a0 <[^>]*> lui \$a0,0x0
+[ ]*a0: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+00a4 <[^>]*> lb \$a0,[0-9]+\(\$a0\)
+[ ]*a4: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+00a8 <[^>]*> lb \$a0,[-0-9]+\(\$gp\)
+[ ]*a8: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00ac <[^>]*> lui \$a0,[-0-9x]+
+[ ]*ac: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+00b0 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*b0: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+00b4 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*b4: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+00b8 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*b8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+00bc <[^>]*> lui \$a0,[-0-9x]+
+[ ]*bc: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+00c0 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*c0: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+00c4 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*c4: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+00c8 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*c8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+00cc <[^>]*> lui \$a0,[-0-9x]+
+[ ]*cc: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+00d0 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*d0: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+00d4 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*d4: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+00d8 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*d8: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+00dc <[^>]*> lui \$a0,[-0-9x]+
+[ ]*dc: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+00e0 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*e0: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+00e4 <[^>]*> lui \$a0,0x0
+[ ]*e4: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+00e8 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*e8: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+00ec <[^>]*> lui \$a0,0x0
+[ ]*ec: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+00f0 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*f0: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+00f4 <[^>]*> lui \$a0,0x0
+[ ]*f4: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+00f8 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*f8: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+00fc <[^>]*> lui \$a0,0x0
+[ ]*fc: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0100 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*100: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0104 <[^>]*> lui \$a0,0x0
+[ ]*104: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0108 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*108: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+010c <[^>]*> lui \$a0,0x0
+[ ]*10c: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0110 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*110: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0114 <[^>]*> lui \$a0,0x0
+[ ]*114: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0118 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*118: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+011c <[^>]*> lui \$a0,[-0-9x]+
+[ ]*11c: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0120 <[^>]*> lb \$a0,[0-9]+\(\$a0\)
+[ ]*120: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0124 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*124: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0128 <[^>]*> lb \$a0,0\(\$a0\)
+[ ]*128: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+012c <[^>]*> lui \$a0,[-0-9x]+
+[ ]*12c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0130 <[^>]*> lb \$a0,0\(\$a0\)
+[ ]*130: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0134 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*134: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0138 <[^>]*> lb \$a0,0\(\$a0\)
+[ ]*138: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+013c <[^>]*> lui \$a0,[-0-9x]+
+[ ]*13c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0140 <[^>]*> lb \$a0,0\(\$a0\)
+[ ]*140: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0144 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*144: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0148 <[^>]*> lb \$a0,[0-9]+\(\$a0\)
+[ ]*148: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+014c <[^>]*> lui \$a0,[-0-9x]+
+[ ]*14c: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0150 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*150: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0154 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*154: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0158 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*158: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+015c <[^>]*> lui \$a0,[-0-9x]+
+[ ]*15c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0160 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*160: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0164 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*164: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0168 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*168: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+016c <[^>]*> lui \$a0,[-0-9x]+
+[ ]*16c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0170 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*170: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0174 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*174: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0178 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*178: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+017c <[^>]*> lui \$a0,[-0-9x]+
+[ ]*17c: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0180 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*180: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0184 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*184: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0188 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*188: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+018c <[^>]*> lui \$a0,0x0
+[ ]*18c: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0190 <[^>]*> addu \$a0,\$a0,\$a1
+0+0194 <[^>]*> lb \$a0,[0-9]+\(\$a0\)
+[ ]*194: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0198 <[^>]*> lui \$a0,0x0
+[ ]*198: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+019c <[^>]*> addu \$a0,\$a0,\$a1
+0+01a0 <[^>]*> lb \$a0,0\(\$a0\)
+[ ]*1a0: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+01a4 <[^>]*> addu \$a0,\$a1,\$gp
+0+01a8 <[^>]*> lb \$a0,0\(\$a0\)
+[ ]*1a8: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+01ac <[^>]*> lui \$a0,0x0
+[ ]*1ac: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+01b0 <[^>]*> addu \$a0,\$a0,\$a1
+0+01b4 <[^>]*> lb \$a0,0\(\$a0\)
+[ ]*1b4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+01b8 <[^>]*> addu \$a0,\$a1,\$gp
+0+01bc <[^>]*> lb \$a0,0\(\$a0\)
+[ ]*1bc: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+01c0 <[^>]*> lui \$a0,0x0
+[ ]*1c0: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+01c4 <[^>]*> addu \$a0,\$a0,\$a1
+0+01c8 <[^>]*> lb \$a0,[0-9]+\(\$a0\)
+[ ]*1c8: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+01cc <[^>]*> addu \$a0,\$a1,\$gp
+0+01d0 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*1d0: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+01d4 <[^>]*> lui \$a0,0x0
+[ ]*1d4: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+01d8 <[^>]*> addu \$a0,\$a0,\$a1
+0+01dc <[^>]*> lb \$a0,[0-9]+\(\$a0\)
+[ ]*1dc: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+01e0 <[^>]*> lui \$a0,0x0
+[ ]*1e0: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+01e4 <[^>]*> addu \$a0,\$a0,\$a1
+0+01e8 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*1e8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+01ec <[^>]*> addu \$a0,\$a1,\$gp
+0+01f0 <[^>]*> lb \$a0,1\(\$a0\)
+[ ]*1f0: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+01f4 <[^>]*> lui \$a0,0x0
+[ ]*1f4: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+01f8 <[^>]*> addu \$a0,\$a0,\$a1
+0+01fc <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*1fc: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0200 <[^>]*> addu \$a0,\$a1,\$gp
+0+0204 <[^>]*> lb \$a0,1\(\$a0\)
+[ ]*204: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+0208 <[^>]*> lui \$a0,0x0
+[ ]*208: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+020c <[^>]*> addu \$a0,\$a0,\$a1
+0+0210 <[^>]*> lb \$a0,[0-9]+\(\$a0\)
+[ ]*210: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0214 <[^>]*> addu \$a0,\$a1,\$gp
+0+0218 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*218: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+021c <[^>]*> lui \$a0,[-0-9x]+
+[ ]*21c: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0220 <[^>]*> addu \$a0,\$a0,\$a1
+0+0224 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*224: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0228 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*228: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+022c <[^>]*> addu \$a0,\$a0,\$a1
+0+0230 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*230: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0234 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*234: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0238 <[^>]*> addu \$a0,\$a0,\$a1
+0+023c <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*23c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0240 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*240: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0244 <[^>]*> addu \$a0,\$a0,\$a1
+0+0248 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*248: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+024c <[^>]*> lui \$a0,[-0-9x]+
+[ ]*24c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0250 <[^>]*> addu \$a0,\$a0,\$a1
+0+0254 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*254: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0258 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*258: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+025c <[^>]*> addu \$a0,\$a0,\$a1
+0+0260 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*260: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0264 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*264: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0268 <[^>]*> addu \$a0,\$a0,\$a1
+0+026c <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*26c: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0270 <[^>]*> lui \$a0,0x0
+[ ]*270: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0274 <[^>]*> addu \$a0,\$a0,\$a1
+0+0278 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*278: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+027c <[^>]*> lui \$a0,0x0
+[ ]*27c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0280 <[^>]*> addu \$a0,\$a0,\$a1
+0+0284 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*284: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0288 <[^>]*> lui \$a0,0x0
+[ ]*288: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+028c <[^>]*> addu \$a0,\$a0,\$a1
+0+0290 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*290: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0294 <[^>]*> lui \$a0,0x0
+[ ]*294: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0298 <[^>]*> addu \$a0,\$a0,\$a1
+0+029c <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*29c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+02a0 <[^>]*> lui \$a0,0x0
+[ ]*2a0: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+02a4 <[^>]*> addu \$a0,\$a0,\$a1
+0+02a8 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*2a8: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+02ac <[^>]*> lui \$a0,0x0
+[ ]*2ac: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+02b0 <[^>]*> addu \$a0,\$a0,\$a1
+0+02b4 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*2b4: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+02b8 <[^>]*> lui \$a0,0x0
+[ ]*2b8: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+02bc <[^>]*> addu \$a0,\$a0,\$a1
+0+02c0 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*2c0: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+02c4 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*2c4: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+02c8 <[^>]*> addu \$a0,\$a0,\$a1
+0+02cc <[^>]*> lb \$a0,[0-9]+\(\$a0\)
+[ ]*2cc: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+02d0 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*2d0: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+02d4 <[^>]*> addu \$a0,\$a0,\$a1
+0+02d8 <[^>]*> lb \$a0,0\(\$a0\)
+[ ]*2d8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+02dc <[^>]*> lui \$a0,[-0-9x]+
+[ ]*2dc: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+02e0 <[^>]*> addu \$a0,\$a0,\$a1
+0+02e4 <[^>]*> lb \$a0,0\(\$a0\)
+[ ]*2e4: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+02e8 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*2e8: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+02ec <[^>]*> addu \$a0,\$a0,\$a1
+0+02f0 <[^>]*> lb \$a0,0\(\$a0\)
+[ ]*2f0: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+02f4 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*2f4: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+02f8 <[^>]*> addu \$a0,\$a0,\$a1
+0+02fc <[^>]*> lb \$a0,0\(\$a0\)
+[ ]*2fc: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0300 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*300: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0304 <[^>]*> addu \$a0,\$a0,\$a1
+0+0308 <[^>]*> lb \$a0,[0-9]+\(\$a0\)
+[ ]*308: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+030c <[^>]*> lui \$a0,[-0-9x]+
+[ ]*30c: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0310 <[^>]*> addu \$a0,\$a0,\$a1
+0+0314 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*314: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0318 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*318: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+031c <[^>]*> addu \$a0,\$a0,\$a1
+0+0320 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*320: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0324 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*324: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0328 <[^>]*> addu \$a0,\$a0,\$a1
+0+032c <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*32c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0330 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*330: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0334 <[^>]*> addu \$a0,\$a0,\$a1
+0+0338 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*338: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+033c <[^>]*> lui \$a0,[-0-9x]+
+[ ]*33c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0340 <[^>]*> addu \$a0,\$a0,\$a1
+0+0344 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*344: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0348 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*348: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+034c <[^>]*> addu \$a0,\$a0,\$a1
+0+0350 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*350: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0354 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*354: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0358 <[^>]*> addu \$a0,\$a0,\$a1
+0+035c <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*35c: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0360 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*360: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0364 <[^>]*> addu \$a0,\$a0,\$a1
+0+0368 <[^>]*> lb \$a0,[-0-9]+\(\$a0\)
+[ ]*368: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+036c <[^>]*> lbu \$a0,0\(\$zero\)
+0+0370 <[^>]*> lh \$a0,0\(\$zero\)
+0+0374 <[^>]*> lhu \$a0,0\(\$zero\)
+0+0378 <[^>]*> lw \$a0,0\(\$zero\)
+0+037c <[^>]*> lwl \$a0,0\(\$zero\)
+0+0380 <[^>]*> lwr \$a0,0\(\$zero\)
+0+0384 <[^>]*> lwc0 \$4,0\(\$zero\)
+0+0388 <[^>]*> lwc1 \$f4,0\(\$zero\)
+0+038c <[^>]*> lwc2 \$4,0\(\$zero\)
+0+0390 <[^>]*> lwc3 \$4,0\(\$zero\)
+ ...
diff --git a/gas/testsuite/gas/mips/lb.s b/gas/testsuite/gas/mips/lb.s
new file mode 100644
index 0000000000..303ccaf6e7
--- /dev/null
+++ b/gas/testsuite/gas/mips/lb.s
@@ -0,0 +1,125 @@
+# Source file used to test the lb macro.
+
+ .data
+data_label:
+ .extern big_external_data_label,1000
+ .extern small_external_data_label,1
+ .comm big_external_common,1000
+ .comm small_external_common,1
+ .lcomm big_local_common,1000
+ .lcomm small_local_common,1
+
+ .text
+ lb $4,0
+ lb $4,1
+ lb $4,0x8000
+ lb $4,-0x8000
+ lb $4,0x10000
+ lb $4,0x1a5a5
+ lb $4,0($5)
+ lb $4,1($5)
+ lb $4,0x8000($5)
+ lb $4,-0x8000($5)
+ lb $4,0x10000($5)
+ lb $4,0x1a5a5($5)
+ lb $4,data_label
+ lb $4,big_external_data_label
+ lb $4,small_external_data_label
+ lb $4,big_external_common
+ lb $4,small_external_common
+ lb $4,big_local_common
+ lb $4,small_local_common
+ lb $4,data_label+1
+ lb $4,big_external_data_label+1
+ lb $4,small_external_data_label+1
+ lb $4,big_external_common+1
+ lb $4,small_external_common+1
+ lb $4,big_local_common+1
+ lb $4,small_local_common+1
+ lb $4,data_label+0x8000
+ lb $4,big_external_data_label+0x8000
+ lb $4,small_external_data_label+0x8000
+ lb $4,big_external_common+0x8000
+ lb $4,small_external_common+0x8000
+ lb $4,big_local_common+0x8000
+ lb $4,small_local_common+0x8000
+ lb $4,data_label-0x8000
+ lb $4,big_external_data_label-0x8000
+ lb $4,small_external_data_label-0x8000
+ lb $4,big_external_common-0x8000
+ lb $4,small_external_common-0x8000
+ lb $4,big_local_common-0x8000
+ lb $4,small_local_common-0x8000
+ lb $4,data_label+0x10000
+ lb $4,big_external_data_label+0x10000
+ lb $4,small_external_data_label+0x10000
+ lb $4,big_external_common+0x10000
+ lb $4,small_external_common+0x10000
+ lb $4,big_local_common+0x10000
+ lb $4,small_local_common+0x10000
+ lb $4,data_label+0x1a5a5
+ lb $4,big_external_data_label+0x1a5a5
+ lb $4,small_external_data_label+0x1a5a5
+ lb $4,big_external_common+0x1a5a5
+ lb $4,small_external_common+0x1a5a5
+ lb $4,big_local_common+0x1a5a5
+ lb $4,small_local_common+0x1a5a5
+ lb $4,data_label($5)
+ lb $4,big_external_data_label($5)
+ lb $4,small_external_data_label($5)
+ lb $4,big_external_common($5)
+ lb $4,small_external_common($5)
+ lb $4,big_local_common($5)
+ lb $4,small_local_common($5)
+ lb $4,data_label+1($5)
+ lb $4,big_external_data_label+1($5)
+ lb $4,small_external_data_label+1($5)
+ lb $4,big_external_common+1($5)
+ lb $4,small_external_common+1($5)
+ lb $4,big_local_common+1($5)
+ lb $4,small_local_common+1($5)
+ lb $4,data_label+0x8000($5)
+ lb $4,big_external_data_label+0x8000($5)
+ lb $4,small_external_data_label+0x8000($5)
+ lb $4,big_external_common+0x8000($5)
+ lb $4,small_external_common+0x8000($5)
+ lb $4,big_local_common+0x8000($5)
+ lb $4,small_local_common+0x8000($5)
+ lb $4,data_label-0x8000($5)
+ lb $4,big_external_data_label-0x8000($5)
+ lb $4,small_external_data_label-0x8000($5)
+ lb $4,big_external_common-0x8000($5)
+ lb $4,small_external_common-0x8000($5)
+ lb $4,big_local_common-0x8000($5)
+ lb $4,small_local_common-0x8000($5)
+ lb $4,data_label+0x10000($5)
+ lb $4,big_external_data_label+0x10000($5)
+ lb $4,small_external_data_label+0x10000($5)
+ lb $4,big_external_common+0x10000($5)
+ lb $4,small_external_common+0x10000($5)
+ lb $4,big_local_common+0x10000($5)
+ lb $4,small_local_common+0x10000($5)
+ lb $4,data_label+0x1a5a5($5)
+ lb $4,big_external_data_label+0x1a5a5($5)
+ lb $4,small_external_data_label+0x1a5a5($5)
+ lb $4,big_external_common+0x1a5a5($5)
+ lb $4,small_external_common+0x1a5a5($5)
+ lb $4,big_local_common+0x1a5a5($5)
+ lb $4,small_local_common+0x1a5a5($5)
+
+# Several macros are handled like lb. Sanity check them.
+ lbu $4,0
+ lh $4,0
+ lhu $4,0
+ lw $4,0
+ lwl $4,0
+ lwr $4,0
+ lwc0 $4,0
+ lwc1 $4,0
+ lwc2 $4,0
+ lwc3 $4,0
+
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+ nop
+ nop
+ nop
diff --git a/gas/testsuite/gas/mips/ld-empic.d b/gas/testsuite/gas/mips/ld-empic.d
new file mode 100644
index 0000000000..fa961f69f1
--- /dev/null
+++ b/gas/testsuite/gas/mips/ld-empic.d
@@ -0,0 +1,186 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS ld-empic
+#as: -mips1 -membedded-pic --defsym EMPIC=1
+#source: ld-pic.s
+
+# Test the ld macro with -membedded-pic.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> lw \$a0,0\(\$zero\)
+0+0004 <[^>]*> lw \$a1,4\(\$zero\)
+0+0008 <[^>]*> lw \$a0,1\(\$zero\)
+0+000c <[^>]*> lw \$a1,5\(\$zero\)
+0+0010 <[^>]*> lui \$at,0x1
+0+0014 <[^>]*> lw \$a0,-32768\(\$at\)
+0+0018 <[^>]*> lw \$a1,-32764\(\$at\)
+0+001c <[^>]*> lw \$a0,-32768\(\$zero\)
+0+0020 <[^>]*> lw \$a1,-32764\(\$zero\)
+0+0024 <[^>]*> lui \$at,0x1
+0+0028 <[^>]*> lw \$a0,0\(\$at\)
+0+002c <[^>]*> lw \$a1,4\(\$at\)
+0+0030 <[^>]*> lui \$at,0x2
+0+0034 <[^>]*> lw \$a0,-23131\(\$at\)
+0+0038 <[^>]*> lw \$a1,-23127\(\$at\)
+0+003c <[^>]*> nop
+0+0040 <[^>]*> lw \$a0,0\(\$a1\)
+0+0044 <[^>]*> lw \$a1,4\(\$a1\)
+0+0048 <[^>]*> nop
+0+004c <[^>]*> lw \$a0,1\(\$a1\)
+0+0050 <[^>]*> lw \$a1,5\(\$a1\)
+0+0054 <[^>]*> lui \$at,0x1
+0+0058 <[^>]*> addu \$at,\$a1,\$at
+0+005c <[^>]*> lw \$a0,-32768\(\$at\)
+0+0060 <[^>]*> lw \$a1,-32764\(\$at\)
+0+0064 <[^>]*> nop
+0+0068 <[^>]*> lw \$a0,-32768\(\$a1\)
+0+006c <[^>]*> lw \$a1,-32764\(\$a1\)
+0+0070 <[^>]*> lui \$at,0x1
+0+0074 <[^>]*> addu \$at,\$a1,\$at
+0+0078 <[^>]*> lw \$a0,0\(\$at\)
+0+007c <[^>]*> lw \$a1,4\(\$at\)
+0+0080 <[^>]*> lui \$at,0x2
+0+0084 <[^>]*> addu \$at,\$a1,\$at
+0+0088 <[^>]*> lw \$a0,-23131\(\$at\)
+0+008c <[^>]*> lw \$a1,-23127\(\$at\)
+0+0090 <[^>]*> lw \$a0,-16384\(\$gp\)
+[ ]*90: [A-Z0-9_]*GPREL[A-Z0-9_]* .sdata.*
+0+0094 <[^>]*> lw \$a1,-16380\(\$gp\)
+[ ]*94: [A-Z0-9_]*GPREL[A-Z0-9_]* .sdata.*
+0+0098 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*98: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_data_label
+0+009c <[^>]*> lw \$a1,4\(\$gp\)
+[ ]*9c: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_data_label
+0+00a0 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*a0: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00a4 <[^>]*> lw \$a1,4\(\$gp\)
+[ ]*a4: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00a8 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*a8: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_common
+0+00ac <[^>]*> lw \$a1,4\(\$gp\)
+[ ]*ac: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_common
+0+00b0 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*b0: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+00b4 <[^>]*> lw \$a1,4\(\$gp\)
+[ ]*b4: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+00b8 <[^>]*> lw \$a0,-16384\(\$gp\)
+[ ]*b8: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00bc <[^>]*> lw \$a1,-16380\(\$gp\)
+[ ]*bc: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00c0 <[^>]*> lw \$a0,-15384\(\$gp\)
+[ ]*c0: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00c4 <[^>]*> lw \$a1,-15380\(\$gp\)
+[ ]*c4: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00c8 <[^>]*> lw \$a0,-16383\(\$gp\)
+[ ]*c8: [A-Z0-9_]*GPREL[A-Z0-9_]* .sdata.*
+0+00cc <[^>]*> lw \$a1,-16379\(\$gp\)
+[ ]*cc: [A-Z0-9_]*GPREL[A-Z0-9_]* .sdata.*
+0+00d0 <[^>]*> lw \$a0,1\(\$gp\)
+[ ]*d0: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_data_label
+0+00d4 <[^>]*> lw \$a1,5\(\$gp\)
+[ ]*d4: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_data_label
+0+00d8 <[^>]*> lw \$a0,1\(\$gp\)
+[ ]*d8: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00dc <[^>]*> lw \$a1,5\(\$gp\)
+[ ]*dc: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00e0 <[^>]*> lw \$a0,1\(\$gp\)
+[ ]*e0: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_common
+0+00e4 <[^>]*> lw \$a1,5\(\$gp\)
+[ ]*e4: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_common
+0+00e8 <[^>]*> lw \$a0,1\(\$gp\)
+[ ]*e8: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+00ec <[^>]*> lw \$a1,5\(\$gp\)
+[ ]*ec: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+00f0 <[^>]*> lw \$a0,-16383\(\$gp\)
+[ ]*f0: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00f4 <[^>]*> lw \$a1,-16379\(\$gp\)
+[ ]*f4: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00f8 <[^>]*> lw \$a0,-15383\(\$gp\)
+[ ]*f8: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00fc <[^>]*> lw \$a1,-15379\(\$gp\)
+[ ]*fc: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0100 <[^>]*> nop
+0+0104 <[^>]*> addu \$at,\$a1,\$gp
+0+0108 <[^>]*> lw \$a0,-16384\(\$at\)
+[ ]*108: [A-Z0-9_]*GPREL[A-Z0-9_]* .sdata.*
+0+010c <[^>]*> lw \$a1,-16380\(\$at\)
+[ ]*10c: [A-Z0-9_]*GPREL[A-Z0-9_]* .sdata.*
+0+0110 <[^>]*> nop
+0+0114 <[^>]*> addu \$at,\$a1,\$gp
+0+0118 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*118: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_data_label
+0+011c <[^>]*> lw \$a1,4\(\$at\)
+[ ]*11c: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_data_label
+0+0120 <[^>]*> nop
+0+0124 <[^>]*> addu \$at,\$a1,\$gp
+0+0128 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*128: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+012c <[^>]*> lw \$a1,4\(\$at\)
+[ ]*12c: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+0130 <[^>]*> nop
+0+0134 <[^>]*> addu \$at,\$a1,\$gp
+0+0138 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*138: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_common
+0+013c <[^>]*> lw \$a1,4\(\$at\)
+[ ]*13c: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_common
+0+0140 <[^>]*> nop
+0+0144 <[^>]*> addu \$at,\$a1,\$gp
+0+0148 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*148: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+014c <[^>]*> lw \$a1,4\(\$at\)
+[ ]*14c: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+0150 <[^>]*> nop
+0+0154 <[^>]*> addu \$at,\$a1,\$gp
+0+0158 <[^>]*> lw \$a0,-16384\(\$at\)
+[ ]*158: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+015c <[^>]*> lw \$a1,-16380\(\$at\)
+[ ]*15c: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0160 <[^>]*> nop
+0+0164 <[^>]*> addu \$at,\$a1,\$gp
+0+0168 <[^>]*> lw \$a0,-15384\(\$at\)
+[ ]*168: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+016c <[^>]*> lw \$a1,-15380\(\$at\)
+[ ]*16c: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0170 <[^>]*> nop
+0+0174 <[^>]*> addu \$at,\$a1,\$gp
+0+0178 <[^>]*> lw \$a0,-16383\(\$at\)
+[ ]*178: [A-Z0-9_]*GPREL[A-Z0-9_]* .sdata.*
+0+017c <[^>]*> lw \$a1,-16379\(\$at\)
+[ ]*17c: [A-Z0-9_]*GPREL[A-Z0-9_]* .sdata.*
+0+0180 <[^>]*> nop
+0+0184 <[^>]*> addu \$at,\$a1,\$gp
+0+0188 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*188: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_data_label
+0+018c <[^>]*> lw \$a1,5\(\$at\)
+[ ]*18c: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_data_label
+0+0190 <[^>]*> nop
+0+0194 <[^>]*> addu \$at,\$a1,\$gp
+0+0198 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*198: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+019c <[^>]*> lw \$a1,5\(\$at\)
+[ ]*19c: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+01a0 <[^>]*> nop
+0+01a4 <[^>]*> addu \$at,\$a1,\$gp
+0+01a8 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*1a8: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_common
+0+01ac <[^>]*> lw \$a1,5\(\$at\)
+[ ]*1ac: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_common
+0+01b0 <[^>]*> nop
+0+01b4 <[^>]*> addu \$at,\$a1,\$gp
+0+01b8 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*1b8: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+01bc <[^>]*> lw \$a1,5\(\$at\)
+[ ]*1bc: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+01c0 <[^>]*> nop
+0+01c4 <[^>]*> addu \$at,\$a1,\$gp
+0+01c8 <[^>]*> lw \$a0,-16383\(\$at\)
+[ ]*1c8: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+01cc <[^>]*> lw \$a1,-16379\(\$at\)
+[ ]*1cc: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+01d0 <[^>]*> nop
+0+01d4 <[^>]*> addu \$at,\$a1,\$gp
+0+01d8 <[^>]*> lw \$a0,-15383\(\$at\)
+[ ]*1d8: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+01dc <[^>]*> lw \$a1,-15379\(\$at\)
+[ ]*1dc: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
diff --git a/gas/testsuite/gas/mips/ld-ilocks-addr32.d b/gas/testsuite/gas/mips/ld-ilocks-addr32.d
new file mode 100644
index 0000000000..0846d614de
--- /dev/null
+++ b/gas/testsuite/gas/mips/ld-ilocks-addr32.d
@@ -0,0 +1,632 @@
+#objdump: -dr --prefix-addresses -mmips:4000
+#as: -mips3 -mcpu=r4000
+#name: MIPS ld-ilocks
+#source: ld.s
+
+# Test the ld macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <.text> lw \$a0,0\(\$zero\)
+0+0004 <[^>]*> lw \$a1,4\(\$zero\)
+0+0008 <[^>]*> lw \$a0,1\(\$zero\)
+0+000c <[^>]*> lw \$a1,5\(\$zero\)
+0+0010 <[^>]*> lui \$at,0x1
+0+0014 <[^>]*> lw \$a0,-32768\(\$at\)
+0+0018 <[^>]*> lw \$a1,-32764\(\$at\)
+0+001c <[^>]*> lw \$a0,-32768\(\$zero\)
+0+0020 <[^>]*> lw \$a1,-32764\(\$zero\)
+0+0024 <[^>]*> lui \$at,0x1
+0+0028 <[^>]*> lw \$a0,0\(\$at\)
+0+002c <[^>]*> lw \$a1,4\(\$at\)
+0+0030 <[^>]*> lui \$at,0x2
+0+0034 <[^>]*> lw \$a0,-23131\(\$at\)
+0+0038 <[^>]*> lw \$a1,-23127\(\$at\)
+0+003c <[^>]*> lw \$a0,0\(\$a1\)
+0+0040 <[^>]*> lw \$a1,4\(\$a1\)
+0+0044 <[^>]*> lw \$a0,1\(\$a1\)
+0+0048 <[^>]*> lw \$a1,5\(\$a1\)
+0+004c <[^>]*> lui \$at,0x1
+0+0050 <[^>]*> addu \$at,\$a1,\$at
+0+0054 <[^>]*> lw \$a0,-32768\(\$at\)
+0+0058 <[^>]*> lw \$a1,-32764\(\$at\)
+0+005c <[^>]*> lw \$a0,-32768\(\$a1\)
+0+0060 <[^>]*> lw \$a1,-32764\(\$a1\)
+0+0064 <[^>]*> lui \$at,0x1
+0+0068 <[^>]*> addu \$at,\$a1,\$at
+0+006c <[^>]*> lw \$a0,0\(\$at\)
+0+0070 <[^>]*> lw \$a1,4\(\$at\)
+0+0074 <[^>]*> lui \$at,0x2
+0+0078 <[^>]*> addu \$at,\$a1,\$at
+0+007c <[^>]*> lw \$a0,-23131\(\$at\)
+0+0080 <[^>]*> lw \$a1,-23127\(\$at\)
+0+0084 <[^>]*> lui \$at,0x0
+[ ]*84: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0088 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*88: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+008c <[^>]*> lw \$a1,4\(\$at\)
+[ ]*8c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0090 <[^>]*> lui \$at,0x0
+[ ]*90: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0094 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*94: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0098 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*98: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+009c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*9c: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00a0 <[^>]*> lw \$a1,4\(\$gp\)
+[ ]*a0: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00a4 <[^>]*> lui \$at,0x0
+[ ]*a4: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+00a8 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*a8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+00ac <[^>]*> lw \$a1,4\(\$at\)
+[ ]*ac: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+00b0 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*b0: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+00b4 <[^>]*> lw \$a1,4\(\$gp\)
+[ ]*b4: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+00b8 <[^>]*> lui \$at,0x0
+[ ]*b8: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+00bc <[^>]*> lw \$a0,0\(\$at\)
+[ ]*bc: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+00c0 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*c0: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+00c4 <[^>]*> lw \$a0,-16384\(\$gp\)
+[ ]*c4: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00c8 <[^>]*> lw \$a1,-16380\(\$gp\)
+[ ]*c8: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00cc <[^>]*> lui \$at,0x0
+[ ]*cc: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+00d0 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*d0: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+00d4 <[^>]*> lw \$a1,5\(\$at\)
+[ ]*d4: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+00d8 <[^>]*> lui \$at,0x0
+[ ]*d8: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+00dc <[^>]*> lw \$a0,1\(\$at\)
+[ ]*dc: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+00e0 <[^>]*> lw \$a1,5\(\$at\)
+[ ]*e0: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+00e4 <[^>]*> lw \$a0,1\(\$gp\)
+[ ]*e4: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00e8 <[^>]*> lw \$a1,5\(\$gp\)
+[ ]*e8: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00ec <[^>]*> lui \$at,0x0
+[ ]*ec: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+00f0 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*f0: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+00f4 <[^>]*> lw \$a1,5\(\$at\)
+[ ]*f4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+00f8 <[^>]*> lw \$a0,1\(\$gp\)
+[ ]*f8: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+00fc <[^>]*> lw \$a1,5\(\$gp\)
+[ ]*fc: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+0100 <[^>]*> lui \$at,0x0
+[ ]*100: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0104 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*104: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0108 <[^>]*> lw \$a1,5\(\$at\)
+[ ]*108: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+010c <[^>]*> lw \$a0,-16383\(\$gp\)
+[ ]*10c: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0110 <[^>]*> lw \$a1,-16379\(\$gp\)
+[ ]*110: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0114 <[^>]*> lui \$at,0x1
+[ ]*114: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0118 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*118: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+011c <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*11c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0120 <[^>]*> lui \$at,0x1
+[ ]*120: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0124 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*124: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0128 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*128: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+012c <[^>]*> lui \$at,0x1
+[ ]*12c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0130 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*130: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0134 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*134: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0138 <[^>]*> lui \$at,0x1
+[ ]*138: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+013c <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*13c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0140 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*140: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0144 <[^>]*> lui \$at,0x1
+[ ]*144: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0148 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*148: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+014c <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*14c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0150 <[^>]*> lui \$at,0x1
+[ ]*150: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0154 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*154: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0158 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*158: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+015c <[^>]*> lui \$at,0x1
+[ ]*15c: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0160 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*160: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0164 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*164: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0168 <[^>]*> lui \$at,0x0
+[ ]*168: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+016c <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*16c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0170 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*170: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0174 <[^>]*> lui \$at,0x0
+[ ]*174: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0178 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*178: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+017c <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*17c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0180 <[^>]*> lui \$at,0x0
+[ ]*180: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0184 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*184: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0188 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*188: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+018c <[^>]*> lui \$at,0x0
+[ ]*18c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0190 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*190: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0194 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*194: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0198 <[^>]*> lui \$at,0x0
+[ ]*198: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+019c <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*19c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+01a0 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*1a0: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+01a4 <[^>]*> lui \$at,0x0
+[ ]*1a4: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+01a8 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*1a8: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+01ac <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*1ac: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+01b0 <[^>]*> lui \$at,0x0
+[ ]*1b0: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+01b4 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*1b4: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+01b8 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*1b8: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+01bc <[^>]*> lui \$at,0x1
+[ ]*1bc: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+01c0 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*1c0: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+01c4 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*1c4: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+01c8 <[^>]*> lui \$at,0x1
+[ ]*1c8: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+01cc <[^>]*> lw \$a0,0\(\$at\)
+[ ]*1cc: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+01d0 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*1d0: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+01d4 <[^>]*> lui \$at,0x1
+[ ]*1d4: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+01d8 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*1d8: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+01dc <[^>]*> lw \$a1,4\(\$at\)
+[ ]*1dc: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+01e0 <[^>]*> lui \$at,0x1
+[ ]*1e0: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+01e4 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*1e4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+01e8 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*1e8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+01ec <[^>]*> lui \$at,0x1
+[ ]*1ec: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+01f0 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*1f0: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+01f4 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*1f4: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+01f8 <[^>]*> lui \$at,0x1
+[ ]*1f8: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+01fc <[^>]*> lw \$a0,0\(\$at\)
+[ ]*1fc: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0200 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*200: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0204 <[^>]*> lui \$at,0x1
+[ ]*204: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0208 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*208: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+020c <[^>]*> lw \$a1,4\(\$at\)
+[ ]*20c: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0210 <[^>]*> lui \$at,0x2
+[ ]*210: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0214 <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*214: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0218 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*218: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+021c <[^>]*> lui \$at,0x2
+[ ]*21c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0220 <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*220: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0224 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*224: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0228 <[^>]*> lui \$at,0x2
+[ ]*228: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+022c <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*22c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0230 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*230: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0234 <[^>]*> lui \$at,0x2
+[ ]*234: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0238 <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*238: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+023c <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*23c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0240 <[^>]*> lui \$at,0x2
+[ ]*240: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0244 <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*244: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0248 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*248: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+024c <[^>]*> lui \$at,0x2
+[ ]*24c: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0250 <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*250: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0254 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*254: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0258 <[^>]*> lui \$at,0x2
+[ ]*258: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+025c <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*25c: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0260 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*260: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0264 <[^>]*> lui \$at,0x0
+[ ]*264: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0268 <[^>]*> addu \$at,\$a1,\$at
+0+026c <[^>]*> lw \$a0,0\(\$at\)
+[ ]*26c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0270 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*270: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0274 <[^>]*> lui \$at,0x0
+[ ]*274: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0278 <[^>]*> addu \$at,\$a1,\$at
+0+027c <[^>]*> lw \$a0,0\(\$at\)
+[ ]*27c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0280 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*280: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0284 <[^>]*> addu \$at,\$a1,\$gp
+0+0288 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*288: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+028c <[^>]*> lw \$a1,4\(\$at\)
+[ ]*28c: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+0290 <[^>]*> lui \$at,0x0
+[ ]*290: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0294 <[^>]*> addu \$at,\$a1,\$at
+0+0298 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*298: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+029c <[^>]*> lw \$a1,4\(\$at\)
+[ ]*29c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+02a0 <[^>]*> addu \$at,\$a1,\$gp
+0+02a4 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*2a4: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+02a8 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*2a8: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+02ac <[^>]*> lui \$at,0x0
+[ ]*2ac: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+02b0 <[^>]*> addu \$at,\$a1,\$at
+0+02b4 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*2b4: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+02b8 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*2b8: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+02bc <[^>]*> addu \$at,\$a1,\$gp
+0+02c0 <[^>]*> lw \$a0,-16384\(\$at\)
+[ ]*2c0: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+02c4 <[^>]*> lw \$a1,-16380\(\$at\)
+[ ]*2c4: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+02c8 <[^>]*> lui \$at,0x0
+[ ]*2c8: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+02cc <[^>]*> addu \$at,\$a1,\$at
+0+02d0 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*2d0: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+02d4 <[^>]*> lw \$a1,5\(\$at\)
+[ ]*2d4: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+02d8 <[^>]*> lui \$at,0x0
+[ ]*2d8: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+02dc <[^>]*> addu \$at,\$a1,\$at
+0+02e0 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*2e0: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+02e4 <[^>]*> lw \$a1,5\(\$at\)
+[ ]*2e4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+02e8 <[^>]*> addu \$at,\$a1,\$gp
+0+02ec <[^>]*> lw \$a0,1\(\$at\)
+[ ]*2ec: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+02f0 <[^>]*> lw \$a1,5\(\$at\)
+[ ]*2f0: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+02f4 <[^>]*> lui \$at,0x0
+[ ]*2f4: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+02f8 <[^>]*> addu \$at,\$a1,\$at
+0+02fc <[^>]*> lw \$a0,1\(\$at\)
+[ ]*2fc: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0300 <[^>]*> lw \$a1,5\(\$at\)
+[ ]*300: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0304 <[^>]*> addu \$at,\$a1,\$gp
+0+0308 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*308: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+030c <[^>]*> lw \$a1,5\(\$at\)
+[ ]*30c: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+0310 <[^>]*> lui \$at,0x0
+[ ]*310: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0314 <[^>]*> addu \$at,\$a1,\$at
+0+0318 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*318: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+031c <[^>]*> lw \$a1,5\(\$at\)
+[ ]*31c: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0320 <[^>]*> addu \$at,\$a1,\$gp
+0+0324 <[^>]*> lw \$a0,-16383\(\$at\)
+[ ]*324: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0328 <[^>]*> lw \$a1,-16379\(\$at\)
+[ ]*328: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+032c <[^>]*> lui \$at,0x1
+[ ]*32c: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0330 <[^>]*> addu \$at,\$a1,\$at
+0+0334 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*334: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0338 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*338: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+033c <[^>]*> lui \$at,0x1
+[ ]*33c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0340 <[^>]*> addu \$at,\$a1,\$at
+0+0344 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*344: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0348 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*348: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+034c <[^>]*> lui \$at,0x1
+[ ]*34c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0350 <[^>]*> addu \$at,\$a1,\$at
+0+0354 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*354: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0358 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*358: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+035c <[^>]*> lui \$at,0x1
+[ ]*35c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0360 <[^>]*> addu \$at,\$a1,\$at
+0+0364 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*364: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0368 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*368: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+036c <[^>]*> lui \$at,0x1
+[ ]*36c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0370 <[^>]*> addu \$at,\$a1,\$at
+0+0374 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*374: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0378 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*378: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+037c <[^>]*> lui \$at,0x1
+[ ]*37c: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0380 <[^>]*> addu \$at,\$a1,\$at
+0+0384 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*384: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0388 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*388: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+038c <[^>]*> lui \$at,0x1
+[ ]*38c: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0390 <[^>]*> addu \$at,\$a1,\$at
+0+0394 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*394: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0398 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*398: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+039c <[^>]*> lui \$at,0x0
+[ ]*39c: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+03a0 <[^>]*> addu \$at,\$a1,\$at
+0+03a4 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*3a4: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+03a8 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*3a8: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+03ac <[^>]*> lui \$at,0x0
+[ ]*3ac: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+03b0 <[^>]*> addu \$at,\$a1,\$at
+0+03b4 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*3b4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+03b8 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*3b8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+03bc <[^>]*> lui \$at,0x0
+[ ]*3bc: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+03c0 <[^>]*> addu \$at,\$a1,\$at
+0+03c4 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*3c4: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+03c8 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*3c8: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+03cc <[^>]*> lui \$at,0x0
+[ ]*3cc: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+03d0 <[^>]*> addu \$at,\$a1,\$at
+0+03d4 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*3d4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+03d8 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*3d8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+03dc <[^>]*> lui \$at,0x0
+[ ]*3dc: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+03e0 <[^>]*> addu \$at,\$a1,\$at
+0+03e4 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*3e4: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+03e8 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*3e8: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+03ec <[^>]*> lui \$at,0x0
+[ ]*3ec: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+03f0 <[^>]*> addu \$at,\$a1,\$at
+0+03f4 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*3f4: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+03f8 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*3f8: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+03fc <[^>]*> lui \$at,0x0
+[ ]*3fc: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0400 <[^>]*> addu \$at,\$a1,\$at
+0+0404 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*404: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0408 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*408: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+040c <[^>]*> lui \$at,0x1
+[ ]*40c: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0410 <[^>]*> addu \$at,\$a1,\$at
+0+0414 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*414: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0418 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*418: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+041c <[^>]*> lui \$at,0x1
+[ ]*41c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0420 <[^>]*> addu \$at,\$a1,\$at
+0+0424 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*424: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0428 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*428: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+042c <[^>]*> lui \$at,0x1
+[ ]*42c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0430 <[^>]*> addu \$at,\$a1,\$at
+0+0434 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*434: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0438 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*438: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+043c <[^>]*> lui \$at,0x1
+[ ]*43c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0440 <[^>]*> addu \$at,\$a1,\$at
+0+0444 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*444: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0448 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*448: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+044c <[^>]*> lui \$at,0x1
+[ ]*44c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0450 <[^>]*> addu \$at,\$a1,\$at
+0+0454 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*454: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0458 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*458: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+045c <[^>]*> lui \$at,0x1
+[ ]*45c: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0460 <[^>]*> addu \$at,\$a1,\$at
+0+0464 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*464: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0468 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*468: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+046c <[^>]*> lui \$at,0x1
+[ ]*46c: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0470 <[^>]*> addu \$at,\$a1,\$at
+0+0474 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*474: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0478 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*478: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+047c <[^>]*> lui \$at,0x2
+[ ]*47c: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0480 <[^>]*> addu \$at,\$a1,\$at
+0+0484 <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*484: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0488 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*488: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+048c <[^>]*> lui \$at,0x2
+[ ]*48c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0490 <[^>]*> addu \$at,\$a1,\$at
+0+0494 <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*494: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0498 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*498: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+049c <[^>]*> lui \$at,0x2
+[ ]*49c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+04a0 <[^>]*> addu \$at,\$a1,\$at
+0+04a4 <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*4a4: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+04a8 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*4a8: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+04ac <[^>]*> lui \$at,0x2
+[ ]*4ac: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+04b0 <[^>]*> addu \$at,\$a1,\$at
+0+04b4 <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*4b4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+04b8 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*4b8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+04bc <[^>]*> lui \$at,0x2
+[ ]*4bc: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+04c0 <[^>]*> addu \$at,\$a1,\$at
+0+04c4 <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*4c4: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+04c8 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*4c8: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+04cc <[^>]*> lui \$at,0x2
+[ ]*4cc: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+04d0 <[^>]*> addu \$at,\$a1,\$at
+0+04d4 <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*4d4: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+04d8 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*4d8: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+04dc <[^>]*> lui \$at,0x2
+[ ]*4dc: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+04e0 <[^>]*> addu \$at,\$a1,\$at
+0+04e4 <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*4e4: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+04e8 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*4e8: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+04ec <[^>]*> lwc1 \$f5,0\(\$zero\)
+0+04f0 <[^>]*> lwc1 \$f4,4\(\$zero\)
+0+04f4 <[^>]*> lwc1 \$f5,1\(\$zero\)
+0+04f8 <[^>]*> lwc1 \$f4,5\(\$zero\)
+0+04fc <[^>]*> lui \$at,0x1
+0+0500 <[^>]*> lwc1 \$f5,-32768\(\$at\)
+0+0504 <[^>]*> lwc1 \$f4,-32764\(\$at\)
+0+0508 <[^>]*> lwc1 \$f5,-32768\(\$zero\)
+0+050c <[^>]*> lwc1 \$f4,-32764\(\$zero\)
+0+0510 <[^>]*> lwc1 \$f5,0\(\$a1\)
+0+0514 <[^>]*> lwc1 \$f4,4\(\$a1\)
+0+0518 <[^>]*> lwc1 \$f5,1\(\$a1\)
+0+051c <[^>]*> lwc1 \$f4,5\(\$a1\)
+0+0520 <[^>]*> lui \$at,0x1
+0+0524 <[^>]*> addu \$at,\$a1,\$at
+0+0528 <[^>]*> lwc1 \$f5,-32768\(\$at\)
+0+052c <[^>]*> lwc1 \$f4,-32764\(\$at\)
+0+0530 <[^>]*> lwc1 \$f5,-32768\(\$a1\)
+0+0534 <[^>]*> lwc1 \$f4,-32764\(\$a1\)
+0+0538 <[^>]*> lui \$at,0x2
+[ ]*538: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+053c <[^>]*> addu \$at,\$a1,\$at
+0+0540 <[^>]*> lwc1 \$f5,-23131\(\$at\)
+[ ]*540: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0544 <[^>]*> lwc1 \$f4,-23127\(\$at\)
+[ ]*544: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0548 <[^>]*> nop
+0+054c <[^>]*> swc1 \$f5,0\(\$zero\)
+0+0550 <[^>]*> swc1 \$f4,4\(\$zero\)
+0+0554 <[^>]*> swc1 \$f5,1\(\$zero\)
+0+0558 <[^>]*> swc1 \$f4,5\(\$zero\)
+0+055c <[^>]*> lui \$at,0x1
+0+0560 <[^>]*> swc1 \$f5,-32768\(\$at\)
+0+0564 <[^>]*> swc1 \$f4,-32764\(\$at\)
+0+0568 <[^>]*> swc1 \$f5,-32768\(\$zero\)
+0+056c <[^>]*> swc1 \$f4,-32764\(\$zero\)
+0+0570 <[^>]*> swc1 \$f5,0\(\$a1\)
+0+0574 <[^>]*> swc1 \$f4,4\(\$a1\)
+0+0578 <[^>]*> swc1 \$f5,1\(\$a1\)
+0+057c <[^>]*> swc1 \$f4,5\(\$a1\)
+0+0580 <[^>]*> lui \$at,0x1
+0+0584 <[^>]*> addu \$at,\$a1,\$at
+0+0588 <[^>]*> swc1 \$f5,-32768\(\$at\)
+0+058c <[^>]*> swc1 \$f4,-32764\(\$at\)
+0+0590 <[^>]*> swc1 \$f5,-32768\(\$a1\)
+0+0594 <[^>]*> swc1 \$f4,-32764\(\$a1\)
+0+0598 <[^>]*> lui \$at,0x2
+[ ]*598: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+059c <[^>]*> addu \$at,\$a1,\$at
+0+05a0 <[^>]*> swc1 \$f5,-23131\(\$at\)
+[ ]*5a0: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+05a4 <[^>]*> swc1 \$f4,-23127\(\$at\)
+[ ]*5a4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+05a8 <[^>]*> sw \$a0,0\(\$zero\)
+0+05ac <[^>]*> sw \$a1,4\(\$zero\)
+0+05b0 <[^>]*> lui \$a0,0x2
+[ ]*5b0: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+05b4 <[^>]*> addu \$a0,\$a0,\$a1
+0+05b8 <[^>]*> ld \$a0,-23131\(\$a0\)
+[ ]*5b8: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+05bc <[^>]*> lui \$at,0x2
+[ ]*5bc: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+05c0 <[^>]*> addu \$at,\$at,\$a1
+0+05c4 <[^>]*> sd \$a0,-23131\(\$at\)
+[ ]*5c4: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+05c8 <[^>]*> nop
+
diff --git a/gas/testsuite/gas/mips/ld-ilocks.d b/gas/testsuite/gas/mips/ld-ilocks.d
new file mode 100644
index 0000000000..eab2bdc795
--- /dev/null
+++ b/gas/testsuite/gas/mips/ld-ilocks.d
@@ -0,0 +1,631 @@
+#objdump: -dr --prefix-addresses
+#name: MIPS ld-ilocks
+#source: ld.s
+#as:
+# Test the ld macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <.text> lw \$a0,0\(\$zero\)
+0+0004 <[^>]*> lw \$a1,4\(\$zero\)
+0+0008 <[^>]*> lw \$a0,1\(\$zero\)
+0+000c <[^>]*> lw \$a1,5\(\$zero\)
+0+0010 <[^>]*> lui \$at,0x1
+0+0014 <[^>]*> lw \$a0,-32768\(\$at\)
+0+0018 <[^>]*> lw \$a1,-32764\(\$at\)
+0+001c <[^>]*> lw \$a0,-32768\(\$zero\)
+0+0020 <[^>]*> lw \$a1,-32764\(\$zero\)
+0+0024 <[^>]*> lui \$at,0x1
+0+0028 <[^>]*> lw \$a0,0\(\$at\)
+0+002c <[^>]*> lw \$a1,4\(\$at\)
+0+0030 <[^>]*> lui \$at,0x2
+0+0034 <[^>]*> lw \$a0,-23131\(\$at\)
+0+0038 <[^>]*> lw \$a1,-23127\(\$at\)
+0+003c <[^>]*> lw \$a0,0\(\$a1\)
+0+0040 <[^>]*> lw \$a1,4\(\$a1\)
+0+0044 <[^>]*> lw \$a0,1\(\$a1\)
+0+0048 <[^>]*> lw \$a1,5\(\$a1\)
+0+004c <[^>]*> lui \$at,0x1
+0+0050 <[^>]*> addu \$at,\$a1,\$at
+0+0054 <[^>]*> lw \$a0,-32768\(\$at\)
+0+0058 <[^>]*> lw \$a1,-32764\(\$at\)
+0+005c <[^>]*> lw \$a0,-32768\(\$a1\)
+0+0060 <[^>]*> lw \$a1,-32764\(\$a1\)
+0+0064 <[^>]*> lui \$at,0x1
+0+0068 <[^>]*> addu \$at,\$a1,\$at
+0+006c <[^>]*> lw \$a0,0\(\$at\)
+0+0070 <[^>]*> lw \$a1,4\(\$at\)
+0+0074 <[^>]*> lui \$at,0x2
+0+0078 <[^>]*> addu \$at,\$a1,\$at
+0+007c <[^>]*> lw \$a0,-23131\(\$at\)
+0+0080 <[^>]*> lw \$a1,-23127\(\$at\)
+0+0084 <[^>]*> lui \$at,0x0
+[ ]*84: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0088 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*88: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+008c <[^>]*> lw \$a1,4\(\$at\)
+[ ]*8c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0090 <[^>]*> lui \$at,0x0
+[ ]*90: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0094 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*94: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0098 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*98: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+009c <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*9c: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00a0 <[^>]*> lw \$a1,4\(\$gp\)
+[ ]*a0: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00a4 <[^>]*> lui \$at,0x0
+[ ]*a4: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+00a8 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*a8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+00ac <[^>]*> lw \$a1,4\(\$at\)
+[ ]*ac: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+00b0 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*b0: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+00b4 <[^>]*> lw \$a1,4\(\$gp\)
+[ ]*b4: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+00b8 <[^>]*> lui \$at,0x0
+[ ]*b8: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+00bc <[^>]*> lw \$a0,0\(\$at\)
+[ ]*bc: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+00c0 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*c0: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+00c4 <[^>]*> lw \$a0,-16384\(\$gp\)
+[ ]*c4: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00c8 <[^>]*> lw \$a1,-16380\(\$gp\)
+[ ]*c8: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00cc <[^>]*> lui \$at,0x0
+[ ]*cc: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+00d0 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*d0: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+00d4 <[^>]*> lw \$a1,5\(\$at\)
+[ ]*d4: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+00d8 <[^>]*> lui \$at,0x0
+[ ]*d8: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+00dc <[^>]*> lw \$a0,1\(\$at\)
+[ ]*dc: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+00e0 <[^>]*> lw \$a1,5\(\$at\)
+[ ]*e0: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+00e4 <[^>]*> lw \$a0,1\(\$gp\)
+[ ]*e4: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00e8 <[^>]*> lw \$a1,5\(\$gp\)
+[ ]*e8: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00ec <[^>]*> lui \$at,0x0
+[ ]*ec: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+00f0 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*f0: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+00f4 <[^>]*> lw \$a1,5\(\$at\)
+[ ]*f4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+00f8 <[^>]*> lw \$a0,1\(\$gp\)
+[ ]*f8: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+00fc <[^>]*> lw \$a1,5\(\$gp\)
+[ ]*fc: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+0100 <[^>]*> lui \$at,0x0
+[ ]*100: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0104 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*104: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0108 <[^>]*> lw \$a1,5\(\$at\)
+[ ]*108: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+010c <[^>]*> lw \$a0,-16383\(\$gp\)
+[ ]*10c: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0110 <[^>]*> lw \$a1,-16379\(\$gp\)
+[ ]*110: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0114 <[^>]*> lui \$at,0x1
+[ ]*114: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0118 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*118: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+011c <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*11c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0120 <[^>]*> lui \$at,0x1
+[ ]*120: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0124 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*124: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0128 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*128: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+012c <[^>]*> lui \$at,0x1
+[ ]*12c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0130 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*130: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0134 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*134: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0138 <[^>]*> lui \$at,0x1
+[ ]*138: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+013c <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*13c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0140 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*140: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0144 <[^>]*> lui \$at,0x1
+[ ]*144: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0148 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*148: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+014c <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*14c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0150 <[^>]*> lui \$at,0x1
+[ ]*150: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0154 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*154: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0158 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*158: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+015c <[^>]*> lui \$at,0x1
+[ ]*15c: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0160 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*160: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0164 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*164: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0168 <[^>]*> lui \$at,0x0
+[ ]*168: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+016c <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*16c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0170 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*170: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0174 <[^>]*> lui \$at,0x0
+[ ]*174: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0178 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*178: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+017c <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*17c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0180 <[^>]*> lui \$at,0x0
+[ ]*180: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0184 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*184: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0188 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*188: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+018c <[^>]*> lui \$at,0x0
+[ ]*18c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0190 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*190: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0194 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*194: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0198 <[^>]*> lui \$at,0x0
+[ ]*198: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+019c <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*19c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+01a0 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*1a0: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+01a4 <[^>]*> lui \$at,0x0
+[ ]*1a4: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+01a8 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*1a8: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+01ac <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*1ac: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+01b0 <[^>]*> lui \$at,0x0
+[ ]*1b0: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+01b4 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*1b4: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+01b8 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*1b8: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+01bc <[^>]*> lui \$at,0x1
+[ ]*1bc: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+01c0 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*1c0: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+01c4 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*1c4: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+01c8 <[^>]*> lui \$at,0x1
+[ ]*1c8: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+01cc <[^>]*> lw \$a0,0\(\$at\)
+[ ]*1cc: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+01d0 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*1d0: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+01d4 <[^>]*> lui \$at,0x1
+[ ]*1d4: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+01d8 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*1d8: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+01dc <[^>]*> lw \$a1,4\(\$at\)
+[ ]*1dc: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+01e0 <[^>]*> lui \$at,0x1
+[ ]*1e0: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+01e4 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*1e4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+01e8 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*1e8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+01ec <[^>]*> lui \$at,0x1
+[ ]*1ec: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+01f0 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*1f0: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+01f4 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*1f4: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+01f8 <[^>]*> lui \$at,0x1
+[ ]*1f8: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+01fc <[^>]*> lw \$a0,0\(\$at\)
+[ ]*1fc: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0200 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*200: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0204 <[^>]*> lui \$at,0x1
+[ ]*204: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0208 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*208: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+020c <[^>]*> lw \$a1,4\(\$at\)
+[ ]*20c: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0210 <[^>]*> lui \$at,0x2
+[ ]*210: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0214 <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*214: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0218 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*218: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+021c <[^>]*> lui \$at,0x2
+[ ]*21c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0220 <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*220: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0224 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*224: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0228 <[^>]*> lui \$at,0x2
+[ ]*228: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+022c <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*22c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0230 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*230: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0234 <[^>]*> lui \$at,0x2
+[ ]*234: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0238 <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*238: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+023c <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*23c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0240 <[^>]*> lui \$at,0x2
+[ ]*240: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0244 <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*244: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0248 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*248: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+024c <[^>]*> lui \$at,0x2
+[ ]*24c: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0250 <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*250: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0254 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*254: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0258 <[^>]*> lui \$at,0x2
+[ ]*258: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+025c <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*25c: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0260 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*260: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0264 <[^>]*> lui \$at,0x0
+[ ]*264: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0268 <[^>]*> addu \$at,\$a1,\$at
+0+026c <[^>]*> lw \$a0,0\(\$at\)
+[ ]*26c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0270 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*270: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0274 <[^>]*> lui \$at,0x0
+[ ]*274: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0278 <[^>]*> addu \$at,\$a1,\$at
+0+027c <[^>]*> lw \$a0,0\(\$at\)
+[ ]*27c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0280 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*280: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0284 <[^>]*> addu \$at,\$a1,\$gp
+0+0288 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*288: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+028c <[^>]*> lw \$a1,4\(\$at\)
+[ ]*28c: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+0290 <[^>]*> lui \$at,0x0
+[ ]*290: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0294 <[^>]*> addu \$at,\$a1,\$at
+0+0298 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*298: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+029c <[^>]*> lw \$a1,4\(\$at\)
+[ ]*29c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+02a0 <[^>]*> addu \$at,\$a1,\$gp
+0+02a4 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*2a4: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+02a8 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*2a8: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+02ac <[^>]*> lui \$at,0x0
+[ ]*2ac: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+02b0 <[^>]*> addu \$at,\$a1,\$at
+0+02b4 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*2b4: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+02b8 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*2b8: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+02bc <[^>]*> addu \$at,\$a1,\$gp
+0+02c0 <[^>]*> lw \$a0,-16384\(\$at\)
+[ ]*2c0: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+02c4 <[^>]*> lw \$a1,-16380\(\$at\)
+[ ]*2c4: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+02c8 <[^>]*> lui \$at,0x0
+[ ]*2c8: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+02cc <[^>]*> addu \$at,\$a1,\$at
+0+02d0 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*2d0: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+02d4 <[^>]*> lw \$a1,5\(\$at\)
+[ ]*2d4: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+02d8 <[^>]*> lui \$at,0x0
+[ ]*2d8: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+02dc <[^>]*> addu \$at,\$a1,\$at
+0+02e0 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*2e0: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+02e4 <[^>]*> lw \$a1,5\(\$at\)
+[ ]*2e4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+02e8 <[^>]*> addu \$at,\$a1,\$gp
+0+02ec <[^>]*> lw \$a0,1\(\$at\)
+[ ]*2ec: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+02f0 <[^>]*> lw \$a1,5\(\$at\)
+[ ]*2f0: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+02f4 <[^>]*> lui \$at,0x0
+[ ]*2f4: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+02f8 <[^>]*> addu \$at,\$a1,\$at
+0+02fc <[^>]*> lw \$a0,1\(\$at\)
+[ ]*2fc: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0300 <[^>]*> lw \$a1,5\(\$at\)
+[ ]*300: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0304 <[^>]*> addu \$at,\$a1,\$gp
+0+0308 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*308: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+030c <[^>]*> lw \$a1,5\(\$at\)
+[ ]*30c: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+0310 <[^>]*> lui \$at,0x0
+[ ]*310: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0314 <[^>]*> addu \$at,\$a1,\$at
+0+0318 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*318: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+031c <[^>]*> lw \$a1,5\(\$at\)
+[ ]*31c: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0320 <[^>]*> addu \$at,\$a1,\$gp
+0+0324 <[^>]*> lw \$a0,-16383\(\$at\)
+[ ]*324: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0328 <[^>]*> lw \$a1,-16379\(\$at\)
+[ ]*328: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+032c <[^>]*> lui \$at,0x1
+[ ]*32c: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0330 <[^>]*> addu \$at,\$a1,\$at
+0+0334 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*334: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0338 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*338: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+033c <[^>]*> lui \$at,0x1
+[ ]*33c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0340 <[^>]*> addu \$at,\$a1,\$at
+0+0344 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*344: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0348 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*348: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+034c <[^>]*> lui \$at,0x1
+[ ]*34c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0350 <[^>]*> addu \$at,\$a1,\$at
+0+0354 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*354: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0358 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*358: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+035c <[^>]*> lui \$at,0x1
+[ ]*35c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0360 <[^>]*> addu \$at,\$a1,\$at
+0+0364 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*364: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0368 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*368: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+036c <[^>]*> lui \$at,0x1
+[ ]*36c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0370 <[^>]*> addu \$at,\$a1,\$at
+0+0374 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*374: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0378 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*378: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+037c <[^>]*> lui \$at,0x1
+[ ]*37c: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0380 <[^>]*> addu \$at,\$a1,\$at
+0+0384 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*384: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0388 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*388: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+038c <[^>]*> lui \$at,0x1
+[ ]*38c: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0390 <[^>]*> addu \$at,\$a1,\$at
+0+0394 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*394: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0398 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*398: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+039c <[^>]*> lui \$at,0x0
+[ ]*39c: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+03a0 <[^>]*> addu \$at,\$a1,\$at
+0+03a4 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*3a4: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+03a8 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*3a8: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+03ac <[^>]*> lui \$at,0x0
+[ ]*3ac: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+03b0 <[^>]*> addu \$at,\$a1,\$at
+0+03b4 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*3b4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+03b8 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*3b8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+03bc <[^>]*> lui \$at,0x0
+[ ]*3bc: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+03c0 <[^>]*> addu \$at,\$a1,\$at
+0+03c4 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*3c4: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+03c8 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*3c8: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+03cc <[^>]*> lui \$at,0x0
+[ ]*3cc: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+03d0 <[^>]*> addu \$at,\$a1,\$at
+0+03d4 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*3d4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+03d8 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*3d8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+03dc <[^>]*> lui \$at,0x0
+[ ]*3dc: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+03e0 <[^>]*> addu \$at,\$a1,\$at
+0+03e4 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*3e4: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+03e8 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*3e8: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+03ec <[^>]*> lui \$at,0x0
+[ ]*3ec: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+03f0 <[^>]*> addu \$at,\$a1,\$at
+0+03f4 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*3f4: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+03f8 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*3f8: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+03fc <[^>]*> lui \$at,0x0
+[ ]*3fc: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0400 <[^>]*> addu \$at,\$a1,\$at
+0+0404 <[^>]*> lw \$a0,-32768\(\$at\)
+[ ]*404: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0408 <[^>]*> lw \$a1,-32764\(\$at\)
+[ ]*408: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+040c <[^>]*> lui \$at,0x1
+[ ]*40c: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0410 <[^>]*> addu \$at,\$a1,\$at
+0+0414 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*414: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0418 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*418: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+041c <[^>]*> lui \$at,0x1
+[ ]*41c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0420 <[^>]*> addu \$at,\$a1,\$at
+0+0424 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*424: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0428 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*428: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+042c <[^>]*> lui \$at,0x1
+[ ]*42c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0430 <[^>]*> addu \$at,\$a1,\$at
+0+0434 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*434: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0438 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*438: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+043c <[^>]*> lui \$at,0x1
+[ ]*43c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0440 <[^>]*> addu \$at,\$a1,\$at
+0+0444 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*444: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0448 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*448: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+044c <[^>]*> lui \$at,0x1
+[ ]*44c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0450 <[^>]*> addu \$at,\$a1,\$at
+0+0454 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*454: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0458 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*458: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+045c <[^>]*> lui \$at,0x1
+[ ]*45c: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0460 <[^>]*> addu \$at,\$a1,\$at
+0+0464 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*464: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0468 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*468: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+046c <[^>]*> lui \$at,0x1
+[ ]*46c: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0470 <[^>]*> addu \$at,\$a1,\$at
+0+0474 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*474: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0478 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*478: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+047c <[^>]*> lui \$at,0x2
+[ ]*47c: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0480 <[^>]*> addu \$at,\$a1,\$at
+0+0484 <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*484: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0488 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*488: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+048c <[^>]*> lui \$at,0x2
+[ ]*48c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0490 <[^>]*> addu \$at,\$a1,\$at
+0+0494 <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*494: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0498 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*498: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+049c <[^>]*> lui \$at,0x2
+[ ]*49c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+04a0 <[^>]*> addu \$at,\$a1,\$at
+0+04a4 <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*4a4: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+04a8 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*4a8: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+04ac <[^>]*> lui \$at,0x2
+[ ]*4ac: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+04b0 <[^>]*> addu \$at,\$a1,\$at
+0+04b4 <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*4b4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+04b8 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*4b8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+04bc <[^>]*> lui \$at,0x2
+[ ]*4bc: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+04c0 <[^>]*> addu \$at,\$a1,\$at
+0+04c4 <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*4c4: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+04c8 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*4c8: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+04cc <[^>]*> lui \$at,0x2
+[ ]*4cc: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+04d0 <[^>]*> addu \$at,\$a1,\$at
+0+04d4 <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*4d4: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+04d8 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*4d8: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+04dc <[^>]*> lui \$at,0x2
+[ ]*4dc: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+04e0 <[^>]*> addu \$at,\$a1,\$at
+0+04e4 <[^>]*> lw \$a0,-23131\(\$at\)
+[ ]*4e4: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+04e8 <[^>]*> lw \$a1,-23127\(\$at\)
+[ ]*4e8: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+04ec <[^>]*> lwc1 \$f[45],0\(\$zero\)
+0+04f0 <[^>]*> lwc1 \$f[45],4\(\$zero\)
+0+04f4 <[^>]*> lwc1 \$f[45],1\(\$zero\)
+0+04f8 <[^>]*> lwc1 \$f[45],5\(\$zero\)
+0+04fc <[^>]*> lui \$at,0x1
+0+0500 <[^>]*> lwc1 \$f[45],-32768\(\$at\)
+0+0504 <[^>]*> lwc1 \$f[45],-32764\(\$at\)
+0+0508 <[^>]*> lwc1 \$f[45],-32768\(\$zero\)
+0+050c <[^>]*> lwc1 \$f[45],-32764\(\$zero\)
+0+0510 <[^>]*> lwc1 \$f[45],0\(\$a1\)
+0+0514 <[^>]*> lwc1 \$f[45],4\(\$a1\)
+0+0518 <[^>]*> lwc1 \$f[45],1\(\$a1\)
+0+051c <[^>]*> lwc1 \$f[45],5\(\$a1\)
+0+0520 <[^>]*> lui \$at,0x1
+0+0524 <[^>]*> addu \$at,\$a1,\$at
+0+0528 <[^>]*> lwc1 \$f[45],-32768\(\$at\)
+0+052c <[^>]*> lwc1 \$f[45],-32764\(\$at\)
+0+0530 <[^>]*> lwc1 \$f[45],-32768\(\$a1\)
+0+0534 <[^>]*> lwc1 \$f[45],-32764\(\$a1\)
+0+0538 <[^>]*> lui \$at,0x2
+[ ]*538: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+053c <[^>]*> addu \$at,\$a1,\$at
+0+0540 <[^>]*> lwc1 \$f[45],-23131\(\$at\)
+[ ]*540: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0544 <[^>]*> lwc1 \$f[45],-23127\(\$at\)
+[ ]*544: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0548 <[^>]*> nop
+0+054c <[^>]*> swc1 \$f[45],0\(\$zero\)
+0+0550 <[^>]*> swc1 \$f[45],4\(\$zero\)
+0+0554 <[^>]*> swc1 \$f[45],1\(\$zero\)
+0+0558 <[^>]*> swc1 \$f[45],5\(\$zero\)
+0+055c <[^>]*> lui \$at,0x1
+0+0560 <[^>]*> swc1 \$f[45],-32768\(\$at\)
+0+0564 <[^>]*> swc1 \$f[45],-32764\(\$at\)
+0+0568 <[^>]*> swc1 \$f[45],-32768\(\$zero\)
+0+056c <[^>]*> swc1 \$f[45],-32764\(\$zero\)
+0+0570 <[^>]*> swc1 \$f[45],0\(\$a1\)
+0+0574 <[^>]*> swc1 \$f[45],4\(\$a1\)
+0+0578 <[^>]*> swc1 \$f[45],1\(\$a1\)
+0+057c <[^>]*> swc1 \$f[45],5\(\$a1\)
+0+0580 <[^>]*> lui \$at,0x1
+0+0584 <[^>]*> addu \$at,\$a1,\$at
+0+0588 <[^>]*> swc1 \$f[45],-32768\(\$at\)
+0+058c <[^>]*> swc1 \$f[45],-32764\(\$at\)
+0+0590 <[^>]*> swc1 \$f[45],-32768\(\$a1\)
+0+0594 <[^>]*> swc1 \$f[45],-32764\(\$a1\)
+0+0598 <[^>]*> lui \$at,0x2
+[ ]*598: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+059c <[^>]*> addu \$at,\$a1,\$at
+0+05a0 <[^>]*> swc1 \$f[45],-23131\(\$at\)
+[ ]*5a0: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+05a4 <[^>]*> swc1 \$f[45],-23127\(\$at\)
+[ ]*5a4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+05a8 <[^>]*> sw \$a0,0\(\$zero\)
+0+05ac <[^>]*> sw \$a1,4\(\$zero\)
+0+05b0 <[^>]*> lui \$a0,0x2
+[ ]*5b0: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+05b4 <[^>]*> (d|)addu \$a0,\$a0,\$a1
+0+05b8 <[^>]*> ld \$a0,-23131\(\$a0\)
+[ ]*5b8: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+05bc <[^>]*> lui \$at,0x2
+[ ]*5bc: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+05c0 <[^>]*> (d|)addu \$at,\$at,\$a1
+0+05c4 <[^>]*> sd \$a0,-23131\(\$at\)
+[ ]*5c4: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+05c8 <[^>]*> nop
+
diff --git a/gas/testsuite/gas/mips/ld-pic.s b/gas/testsuite/gas/mips/ld-pic.s
new file mode 100644
index 0000000000..ccf52dfcb4
--- /dev/null
+++ b/gas/testsuite/gas/mips/ld-pic.s
@@ -0,0 +1,60 @@
+# Source file used to test the ld macro with PIC code.
+
+ .set mips1
+
+ .data
+data_label:
+ .extern big_external_data_label,1000
+ .extern small_external_data_label,1
+ .comm big_external_common,1000
+ .comm small_external_common,1
+ .lcomm big_local_common,1000
+ .lcomm small_local_common,1
+
+ .text
+ ld $4,0
+ ld $4,1
+ ld $4,0x8000
+ ld $4,-0x8000
+ ld $4,0x10000
+ ld $4,0x1a5a5
+ ld $4,0($5)
+ ld $4,1($5)
+ ld $4,0x8000($5)
+ ld $4,-0x8000($5)
+ ld $4,0x10000($5)
+ ld $4,0x1a5a5($5)
+ ld $4,data_label
+ ld $4,big_external_data_label
+ ld $4,small_external_data_label
+ ld $4,big_external_common
+ ld $4,small_external_common
+ ld $4,big_local_common
+ ld $4,small_local_common
+ ld $4,data_label+1
+ ld $4,big_external_data_label+1
+ ld $4,small_external_data_label+1
+ ld $4,big_external_common+1
+ ld $4,small_external_common+1
+ ld $4,big_local_common+1
+ ld $4,small_local_common+1
+ ld $4,data_label($5)
+ ld $4,big_external_data_label($5)
+ ld $4,small_external_data_label($5)
+ ld $4,big_external_common($5)
+ ld $4,small_external_common($5)
+ ld $4,big_local_common($5)
+ ld $4,small_local_common($5)
+ ld $4,data_label+1($5)
+ ld $4,big_external_data_label+1($5)
+ ld $4,small_external_data_label+1($5)
+ ld $4,big_external_common+1($5)
+ ld $4,small_external_common+1($5)
+ ld $4,big_local_common+1($5)
+ ld $4,small_local_common+1($5)
+
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+ .ifndef EMPIC
+ nop
+ nop
+ .endif
diff --git a/gas/testsuite/gas/mips/ld-svr4pic.d b/gas/testsuite/gas/mips/ld-svr4pic.d
new file mode 100644
index 0000000000..2043d798f2
--- /dev/null
+++ b/gas/testsuite/gas/mips/ld-svr4pic.d
@@ -0,0 +1,225 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS ld-svr4pic
+#as: -mips1 -mcpu=r3000 -KPIC
+#source: ld-pic.s
+
+# Test the ld macro with -KPIC.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> lw \$a0,0\(\$zero\)
+0+0004 <[^>]*> lw \$a1,4\(\$zero\)
+0+0008 <[^>]*> lw \$a0,1\(\$zero\)
+0+000c <[^>]*> lw \$a1,5\(\$zero\)
+0+0010 <[^>]*> lui \$at,0x1
+0+0014 <[^>]*> lw \$a0,-32768\(\$at\)
+0+0018 <[^>]*> lw \$a1,-32764\(\$at\)
+0+001c <[^>]*> lw \$a0,-32768\(\$zero\)
+0+0020 <[^>]*> lw \$a1,-32764\(\$zero\)
+0+0024 <[^>]*> lui \$at,0x1
+0+0028 <[^>]*> lw \$a0,0\(\$at\)
+0+002c <[^>]*> lw \$a1,4\(\$at\)
+0+0030 <[^>]*> lui \$at,0x2
+0+0034 <[^>]*> lw \$a0,-23131\(\$at\)
+0+0038 <[^>]*> lw \$a1,-23127\(\$at\)
+0+003c <[^>]*> nop
+0+0040 <[^>]*> lw \$a0,0\(\$a1\)
+0+0044 <[^>]*> lw \$a1,4\(\$a1\)
+0+0048 <[^>]*> nop
+0+004c <[^>]*> lw \$a0,1\(\$a1\)
+0+0050 <[^>]*> lw \$a1,5\(\$a1\)
+0+0054 <[^>]*> lui \$at,0x1
+0+0058 <[^>]*> addu \$at,\$a1,\$at
+0+005c <[^>]*> lw \$a0,-32768\(\$at\)
+0+0060 <[^>]*> lw \$a1,-32764\(\$at\)
+0+0064 <[^>]*> nop
+0+0068 <[^>]*> lw \$a0,-32768\(\$a1\)
+0+006c <[^>]*> lw \$a1,-32764\(\$a1\)
+0+0070 <[^>]*> lui \$at,0x1
+0+0074 <[^>]*> addu \$at,\$a1,\$at
+0+0078 <[^>]*> lw \$a0,0\(\$at\)
+0+007c <[^>]*> lw \$a1,4\(\$at\)
+0+0080 <[^>]*> lui \$at,0x2
+0+0084 <[^>]*> addu \$at,\$a1,\$at
+0+0088 <[^>]*> lw \$a0,-23131\(\$at\)
+0+008c <[^>]*> lw \$a1,-23127\(\$at\)
+0+0090 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*90: R_MIPS_GOT16 .data
+0+0094 <[^>]*> nop
+0+0098 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*98: R_MIPS_LO16 .data
+0+009c <[^>]*> lw \$a1,4\(\$at\)
+[ ]*9c: R_MIPS_LO16 .data
+0+00a0 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*a0: R_MIPS_GOT16 big_external_data_label
+0+00a4 <[^>]*> nop
+0+00a8 <[^>]*> lw \$a0,0\(\$at\)
+0+00ac <[^>]*> lw \$a1,4\(\$at\)
+0+00b0 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*b0: R_MIPS_GOT16 small_external_data_label
+0+00b4 <[^>]*> nop
+0+00b8 <[^>]*> lw \$a0,0\(\$at\)
+0+00bc <[^>]*> lw \$a1,4\(\$at\)
+0+00c0 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*c0: R_MIPS_GOT16 big_external_common
+0+00c4 <[^>]*> nop
+0+00c8 <[^>]*> lw \$a0,0\(\$at\)
+0+00cc <[^>]*> lw \$a1,4\(\$at\)
+0+00d0 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*d0: R_MIPS_GOT16 small_external_common
+0+00d4 <[^>]*> nop
+0+00d8 <[^>]*> lw \$a0,0\(\$at\)
+0+00dc <[^>]*> lw \$a1,4\(\$at\)
+0+00e0 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*e0: R_MIPS_GOT16 .bss
+0+00e4 <[^>]*> nop
+0+00e8 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*e8: R_MIPS_LO16 .bss
+0+00ec <[^>]*> lw \$a1,4\(\$at\)
+[ ]*ec: R_MIPS_LO16 .bss
+0+00f0 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*f0: R_MIPS_GOT16 .bss
+0+00f4 <[^>]*> nop
+0+00f8 <[^>]*> lw \$a0,1000\(\$at\)
+[ ]*f8: R_MIPS_LO16 .bss
+0+00fc <[^>]*> lw \$a1,1004\(\$at\)
+[ ]*fc: R_MIPS_LO16 .bss
+0+0100 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*100: R_MIPS_GOT16 .data
+0+0104 <[^>]*> nop
+0+0108 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*108: R_MIPS_LO16 .data
+0+010c <[^>]*> lw \$a1,5\(\$at\)
+[ ]*10c: R_MIPS_LO16 .data
+0+0110 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*110: R_MIPS_GOT16 big_external_data_label
+0+0114 <[^>]*> nop
+0+0118 <[^>]*> lw \$a0,1\(\$at\)
+0+011c <[^>]*> lw \$a1,5\(\$at\)
+0+0120 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*120: R_MIPS_GOT16 small_external_data_label
+0+0124 <[^>]*> nop
+0+0128 <[^>]*> lw \$a0,1\(\$at\)
+0+012c <[^>]*> lw \$a1,5\(\$at\)
+0+0130 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*130: R_MIPS_GOT16 big_external_common
+0+0134 <[^>]*> nop
+0+0138 <[^>]*> lw \$a0,1\(\$at\)
+0+013c <[^>]*> lw \$a1,5\(\$at\)
+0+0140 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*140: R_MIPS_GOT16 small_external_common
+0+0144 <[^>]*> nop
+0+0148 <[^>]*> lw \$a0,1\(\$at\)
+0+014c <[^>]*> lw \$a1,5\(\$at\)
+0+0150 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*150: R_MIPS_GOT16 .bss
+0+0154 <[^>]*> nop
+0+0158 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*158: R_MIPS_LO16 .bss
+0+015c <[^>]*> lw \$a1,5\(\$at\)
+[ ]*15c: R_MIPS_LO16 .bss
+0+0160 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*160: R_MIPS_GOT16 .bss
+0+0164 <[^>]*> nop
+0+0168 <[^>]*> lw \$a0,1001\(\$at\)
+[ ]*168: R_MIPS_LO16 .bss
+0+016c <[^>]*> lw \$a1,1005\(\$at\)
+[ ]*16c: R_MIPS_LO16 .bss
+0+0170 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*170: R_MIPS_GOT16 .data
+0+0174 <[^>]*> nop
+0+0178 <[^>]*> addu \$at,\$a1,\$at
+0+017c <[^>]*> lw \$a0,0\(\$at\)
+[ ]*17c: R_MIPS_LO16 .data
+0+0180 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*180: R_MIPS_LO16 .data
+0+0184 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*184: R_MIPS_GOT16 big_external_data_label
+0+0188 <[^>]*> nop
+0+018c <[^>]*> addu \$at,\$a1,\$at
+0+0190 <[^>]*> lw \$a0,0\(\$at\)
+0+0194 <[^>]*> lw \$a1,4\(\$at\)
+0+0198 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*198: R_MIPS_GOT16 small_external_data_label
+0+019c <[^>]*> nop
+0+01a0 <[^>]*> addu \$at,\$a1,\$at
+0+01a4 <[^>]*> lw \$a0,0\(\$at\)
+0+01a8 <[^>]*> lw \$a1,4\(\$at\)
+0+01ac <[^>]*> lw \$at,0\(\$gp\)
+[ ]*1ac: R_MIPS_GOT16 big_external_common
+0+01b0 <[^>]*> nop
+0+01b4 <[^>]*> addu \$at,\$a1,\$at
+0+01b8 <[^>]*> lw \$a0,0\(\$at\)
+0+01bc <[^>]*> lw \$a1,4\(\$at\)
+0+01c0 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*1c0: R_MIPS_GOT16 small_external_common
+0+01c4 <[^>]*> nop
+0+01c8 <[^>]*> addu \$at,\$a1,\$at
+0+01cc <[^>]*> lw \$a0,0\(\$at\)
+0+01d0 <[^>]*> lw \$a1,4\(\$at\)
+0+01d4 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*1d4: R_MIPS_GOT16 .bss
+0+01d8 <[^>]*> nop
+0+01dc <[^>]*> addu \$at,\$a1,\$at
+0+01e0 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*1e0: R_MIPS_LO16 .bss
+0+01e4 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*1e4: R_MIPS_LO16 .bss
+0+01e8 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*1e8: R_MIPS_GOT16 .bss
+0+01ec <[^>]*> nop
+0+01f0 <[^>]*> addu \$at,\$a1,\$at
+0+01f4 <[^>]*> lw \$a0,1000\(\$at\)
+[ ]*1f4: R_MIPS_LO16 .bss
+0+01f8 <[^>]*> lw \$a1,1004\(\$at\)
+[ ]*1f8: R_MIPS_LO16 .bss
+0+01fc <[^>]*> lw \$at,0\(\$gp\)
+[ ]*1fc: R_MIPS_GOT16 .data
+0+0200 <[^>]*> nop
+0+0204 <[^>]*> addu \$at,\$a1,\$at
+0+0208 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*208: R_MIPS_LO16 .data
+0+020c <[^>]*> lw \$a1,5\(\$at\)
+[ ]*20c: R_MIPS_LO16 .data
+0+0210 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*210: R_MIPS_GOT16 big_external_data_label
+0+0214 <[^>]*> nop
+0+0218 <[^>]*> addu \$at,\$a1,\$at
+0+021c <[^>]*> lw \$a0,1\(\$at\)
+0+0220 <[^>]*> lw \$a1,5\(\$at\)
+0+0224 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*224: R_MIPS_GOT16 small_external_data_label
+0+0228 <[^>]*> nop
+0+022c <[^>]*> addu \$at,\$a1,\$at
+0+0230 <[^>]*> lw \$a0,1\(\$at\)
+0+0234 <[^>]*> lw \$a1,5\(\$at\)
+0+0238 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*238: R_MIPS_GOT16 big_external_common
+0+023c <[^>]*> nop
+0+0240 <[^>]*> addu \$at,\$a1,\$at
+0+0244 <[^>]*> lw \$a0,1\(\$at\)
+0+0248 <[^>]*> lw \$a1,5\(\$at\)
+0+024c <[^>]*> lw \$at,0\(\$gp\)
+[ ]*24c: R_MIPS_GOT16 small_external_common
+0+0250 <[^>]*> nop
+0+0254 <[^>]*> addu \$at,\$a1,\$at
+0+0258 <[^>]*> lw \$a0,1\(\$at\)
+0+025c <[^>]*> lw \$a1,5\(\$at\)
+0+0260 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*260: R_MIPS_GOT16 .bss
+0+0264 <[^>]*> nop
+0+0268 <[^>]*> addu \$at,\$a1,\$at
+0+026c <[^>]*> lw \$a0,1\(\$at\)
+[ ]*26c: R_MIPS_LO16 .bss
+0+0270 <[^>]*> lw \$a1,5\(\$at\)
+[ ]*270: R_MIPS_LO16 .bss
+0+0274 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*274: R_MIPS_GOT16 .bss
+0+0278 <[^>]*> nop
+0+027c <[^>]*> addu \$at,\$a1,\$at
+0+0280 <[^>]*> lw \$a0,1001\(\$at\)
+[ ]*280: R_MIPS_LO16 .bss
+0+0284 <[^>]*> lw \$a1,1005\(\$at\)
+[ ]*284: R_MIPS_LO16 .bss
+ ...
diff --git a/gas/testsuite/gas/mips/ld-xgot.d b/gas/testsuite/gas/mips/ld-xgot.d
new file mode 100644
index 0000000000..40262cf244
--- /dev/null
+++ b/gas/testsuite/gas/mips/ld-xgot.d
@@ -0,0 +1,273 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS ld-xgot
+#as: -mips1 -mcpu=r3000 -KPIC -xgot
+#source: ld-pic.s
+
+# Test the ld macro with -KPIC -xgot.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> lw \$a0,0\(\$zero\)
+0+0004 <[^>]*> lw \$a1,4\(\$zero\)
+0+0008 <[^>]*> lw \$a0,1\(\$zero\)
+0+000c <[^>]*> lw \$a1,5\(\$zero\)
+0+0010 <[^>]*> lui \$at,0x1
+0+0014 <[^>]*> lw \$a0,-32768\(\$at\)
+0+0018 <[^>]*> lw \$a1,-32764\(\$at\)
+0+001c <[^>]*> lw \$a0,-32768\(\$zero\)
+0+0020 <[^>]*> lw \$a1,-32764\(\$zero\)
+0+0024 <[^>]*> lui \$at,0x1
+0+0028 <[^>]*> lw \$a0,0\(\$at\)
+0+002c <[^>]*> lw \$a1,4\(\$at\)
+0+0030 <[^>]*> lui \$at,0x2
+0+0034 <[^>]*> lw \$a0,-23131\(\$at\)
+0+0038 <[^>]*> lw \$a1,-23127\(\$at\)
+0+003c <[^>]*> nop
+0+0040 <[^>]*> lw \$a0,0\(\$a1\)
+0+0044 <[^>]*> lw \$a1,4\(\$a1\)
+0+0048 <[^>]*> nop
+0+004c <[^>]*> lw \$a0,1\(\$a1\)
+0+0050 <[^>]*> lw \$a1,5\(\$a1\)
+0+0054 <[^>]*> lui \$at,0x1
+0+0058 <[^>]*> addu \$at,\$a1,\$at
+0+005c <[^>]*> lw \$a0,-32768\(\$at\)
+0+0060 <[^>]*> lw \$a1,-32764\(\$at\)
+0+0064 <[^>]*> nop
+0+0068 <[^>]*> lw \$a0,-32768\(\$a1\)
+0+006c <[^>]*> lw \$a1,-32764\(\$a1\)
+0+0070 <[^>]*> lui \$at,0x1
+0+0074 <[^>]*> addu \$at,\$a1,\$at
+0+0078 <[^>]*> lw \$a0,0\(\$at\)
+0+007c <[^>]*> lw \$a1,4\(\$at\)
+0+0080 <[^>]*> lui \$at,0x2
+0+0084 <[^>]*> addu \$at,\$a1,\$at
+0+0088 <[^>]*> lw \$a0,-23131\(\$at\)
+0+008c <[^>]*> lw \$a1,-23127\(\$at\)
+0+0090 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*90: R_MIPS_GOT16 .data
+0+0094 <[^>]*> nop
+0+0098 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*98: R_MIPS_LO16 .data
+0+009c <[^>]*> lw \$a1,4\(\$at\)
+[ ]*9c: R_MIPS_LO16 .data
+0+00a0 <[^>]*> lui \$at,0x0
+[ ]*a0: R_MIPS_GOT_HI16 big_external_data_label
+0+00a4 <[^>]*> addu \$at,\$at,\$gp
+0+00a8 <[^>]*> lw \$at,0\(\$at\)
+[ ]*a8: R_MIPS_GOT_LO16 big_external_data_label
+0+00ac <[^>]*> nop
+0+00b0 <[^>]*> lw \$a0,0\(\$at\)
+0+00b4 <[^>]*> lw \$a1,4\(\$at\)
+0+00b8 <[^>]*> lui \$at,0x0
+[ ]*b8: R_MIPS_GOT_HI16 small_external_data_label
+0+00bc <[^>]*> addu \$at,\$at,\$gp
+0+00c0 <[^>]*> lw \$at,0\(\$at\)
+[ ]*c0: R_MIPS_GOT_LO16 small_external_data_label
+0+00c4 <[^>]*> nop
+0+00c8 <[^>]*> lw \$a0,0\(\$at\)
+0+00cc <[^>]*> lw \$a1,4\(\$at\)
+0+00d0 <[^>]*> lui \$at,0x0
+[ ]*d0: R_MIPS_GOT_HI16 big_external_common
+0+00d4 <[^>]*> addu \$at,\$at,\$gp
+0+00d8 <[^>]*> lw \$at,0\(\$at\)
+[ ]*d8: R_MIPS_GOT_LO16 big_external_common
+0+00dc <[^>]*> nop
+0+00e0 <[^>]*> lw \$a0,0\(\$at\)
+0+00e4 <[^>]*> lw \$a1,4\(\$at\)
+0+00e8 <[^>]*> lui \$at,0x0
+[ ]*e8: R_MIPS_GOT_HI16 small_external_common
+0+00ec <[^>]*> addu \$at,\$at,\$gp
+0+00f0 <[^>]*> lw \$at,0\(\$at\)
+[ ]*f0: R_MIPS_GOT_LO16 small_external_common
+0+00f4 <[^>]*> nop
+0+00f8 <[^>]*> lw \$a0,0\(\$at\)
+0+00fc <[^>]*> lw \$a1,4\(\$at\)
+0+0100 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*100: R_MIPS_GOT16 .bss
+0+0104 <[^>]*> nop
+0+0108 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*108: R_MIPS_LO16 .bss
+0+010c <[^>]*> lw \$a1,4\(\$at\)
+[ ]*10c: R_MIPS_LO16 .bss
+0+0110 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*110: R_MIPS_GOT16 .bss
+0+0114 <[^>]*> nop
+0+0118 <[^>]*> lw \$a0,1000\(\$at\)
+[ ]*118: R_MIPS_LO16 .bss
+0+011c <[^>]*> lw \$a1,1004\(\$at\)
+[ ]*11c: R_MIPS_LO16 .bss
+0+0120 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*120: R_MIPS_GOT16 .data
+0+0124 <[^>]*> nop
+0+0128 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*128: R_MIPS_LO16 .data
+0+012c <[^>]*> lw \$a1,5\(\$at\)
+[ ]*12c: R_MIPS_LO16 .data
+0+0130 <[^>]*> lui \$at,0x0
+[ ]*130: R_MIPS_GOT_HI16 big_external_data_label
+0+0134 <[^>]*> addu \$at,\$at,\$gp
+0+0138 <[^>]*> lw \$at,0\(\$at\)
+[ ]*138: R_MIPS_GOT_LO16 big_external_data_label
+0+013c <[^>]*> nop
+0+0140 <[^>]*> lw \$a0,1\(\$at\)
+0+0144 <[^>]*> lw \$a1,5\(\$at\)
+0+0148 <[^>]*> lui \$at,0x0
+[ ]*148: R_MIPS_GOT_HI16 small_external_data_label
+0+014c <[^>]*> addu \$at,\$at,\$gp
+0+0150 <[^>]*> lw \$at,0\(\$at\)
+[ ]*150: R_MIPS_GOT_LO16 small_external_data_label
+0+0154 <[^>]*> nop
+0+0158 <[^>]*> lw \$a0,1\(\$at\)
+0+015c <[^>]*> lw \$a1,5\(\$at\)
+0+0160 <[^>]*> lui \$at,0x0
+[ ]*160: R_MIPS_GOT_HI16 big_external_common
+0+0164 <[^>]*> addu \$at,\$at,\$gp
+0+0168 <[^>]*> lw \$at,0\(\$at\)
+[ ]*168: R_MIPS_GOT_LO16 big_external_common
+0+016c <[^>]*> nop
+0+0170 <[^>]*> lw \$a0,1\(\$at\)
+0+0174 <[^>]*> lw \$a1,5\(\$at\)
+0+0178 <[^>]*> lui \$at,0x0
+[ ]*178: R_MIPS_GOT_HI16 small_external_common
+0+017c <[^>]*> addu \$at,\$at,\$gp
+0+0180 <[^>]*> lw \$at,0\(\$at\)
+[ ]*180: R_MIPS_GOT_LO16 small_external_common
+0+0184 <[^>]*> nop
+0+0188 <[^>]*> lw \$a0,1\(\$at\)
+0+018c <[^>]*> lw \$a1,5\(\$at\)
+0+0190 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*190: R_MIPS_GOT16 .bss
+0+0194 <[^>]*> nop
+0+0198 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*198: R_MIPS_LO16 .bss
+0+019c <[^>]*> lw \$a1,5\(\$at\)
+[ ]*19c: R_MIPS_LO16 .bss
+0+01a0 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*1a0: R_MIPS_GOT16 .bss
+0+01a4 <[^>]*> nop
+0+01a8 <[^>]*> lw \$a0,1001\(\$at\)
+[ ]*1a8: R_MIPS_LO16 .bss
+0+01ac <[^>]*> lw \$a1,1005\(\$at\)
+[ ]*1ac: R_MIPS_LO16 .bss
+0+01b0 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*1b0: R_MIPS_GOT16 .data
+0+01b4 <[^>]*> nop
+0+01b8 <[^>]*> addu \$at,\$a1,\$at
+0+01bc <[^>]*> lw \$a0,0\(\$at\)
+[ ]*1bc: R_MIPS_LO16 .data
+0+01c0 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*1c0: R_MIPS_LO16 .data
+0+01c4 <[^>]*> lui \$at,0x0
+[ ]*1c4: R_MIPS_GOT_HI16 big_external_data_label
+0+01c8 <[^>]*> addu \$at,\$at,\$gp
+0+01cc <[^>]*> lw \$at,0\(\$at\)
+[ ]*1cc: R_MIPS_GOT_LO16 big_external_data_label
+0+01d0 <[^>]*> nop
+0+01d4 <[^>]*> addu \$at,\$a1,\$at
+0+01d8 <[^>]*> lw \$a0,0\(\$at\)
+0+01dc <[^>]*> lw \$a1,4\(\$at\)
+0+01e0 <[^>]*> lui \$at,0x0
+[ ]*1e0: R_MIPS_GOT_HI16 small_external_data_label
+0+01e4 <[^>]*> addu \$at,\$at,\$gp
+0+01e8 <[^>]*> lw \$at,0\(\$at\)
+[ ]*1e8: R_MIPS_GOT_LO16 small_external_data_label
+0+01ec <[^>]*> nop
+0+01f0 <[^>]*> addu \$at,\$a1,\$at
+0+01f4 <[^>]*> lw \$a0,0\(\$at\)
+0+01f8 <[^>]*> lw \$a1,4\(\$at\)
+0+01fc <[^>]*> lui \$at,0x0
+[ ]*1fc: R_MIPS_GOT_HI16 big_external_common
+0+0200 <[^>]*> addu \$at,\$at,\$gp
+0+0204 <[^>]*> lw \$at,0\(\$at\)
+[ ]*204: R_MIPS_GOT_LO16 big_external_common
+0+0208 <[^>]*> nop
+0+020c <[^>]*> addu \$at,\$a1,\$at
+0+0210 <[^>]*> lw \$a0,0\(\$at\)
+0+0214 <[^>]*> lw \$a1,4\(\$at\)
+0+0218 <[^>]*> lui \$at,0x0
+[ ]*218: R_MIPS_GOT_HI16 small_external_common
+0+021c <[^>]*> addu \$at,\$at,\$gp
+0+0220 <[^>]*> lw \$at,0\(\$at\)
+[ ]*220: R_MIPS_GOT_LO16 small_external_common
+0+0224 <[^>]*> nop
+0+0228 <[^>]*> addu \$at,\$a1,\$at
+0+022c <[^>]*> lw \$a0,0\(\$at\)
+0+0230 <[^>]*> lw \$a1,4\(\$at\)
+0+0234 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*234: R_MIPS_GOT16 .bss
+0+0238 <[^>]*> nop
+0+023c <[^>]*> addu \$at,\$a1,\$at
+0+0240 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*240: R_MIPS_LO16 .bss
+0+0244 <[^>]*> lw \$a1,4\(\$at\)
+[ ]*244: R_MIPS_LO16 .bss
+0+0248 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*248: R_MIPS_GOT16 .bss
+0+024c <[^>]*> nop
+0+0250 <[^>]*> addu \$at,\$a1,\$at
+0+0254 <[^>]*> lw \$a0,1000\(\$at\)
+[ ]*254: R_MIPS_LO16 .bss
+0+0258 <[^>]*> lw \$a1,1004\(\$at\)
+[ ]*258: R_MIPS_LO16 .bss
+0+025c <[^>]*> lw \$at,0\(\$gp\)
+[ ]*25c: R_MIPS_GOT16 .data
+0+0260 <[^>]*> nop
+0+0264 <[^>]*> addu \$at,\$a1,\$at
+0+0268 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*268: R_MIPS_LO16 .data
+0+026c <[^>]*> lw \$a1,5\(\$at\)
+[ ]*26c: R_MIPS_LO16 .data
+0+0270 <[^>]*> lui \$at,0x0
+[ ]*270: R_MIPS_GOT_HI16 big_external_data_label
+0+0274 <[^>]*> addu \$at,\$at,\$gp
+0+0278 <[^>]*> lw \$at,0\(\$at\)
+[ ]*278: R_MIPS_GOT_LO16 big_external_data_label
+0+027c <[^>]*> nop
+0+0280 <[^>]*> addu \$at,\$a1,\$at
+0+0284 <[^>]*> lw \$a0,1\(\$at\)
+0+0288 <[^>]*> lw \$a1,5\(\$at\)
+0+028c <[^>]*> lui \$at,0x0
+[ ]*28c: R_MIPS_GOT_HI16 small_external_data_label
+0+0290 <[^>]*> addu \$at,\$at,\$gp
+0+0294 <[^>]*> lw \$at,0\(\$at\)
+[ ]*294: R_MIPS_GOT_LO16 small_external_data_label
+0+0298 <[^>]*> nop
+0+029c <[^>]*> addu \$at,\$a1,\$at
+0+02a0 <[^>]*> lw \$a0,1\(\$at\)
+0+02a4 <[^>]*> lw \$a1,5\(\$at\)
+0+02a8 <[^>]*> lui \$at,0x0
+[ ]*2a8: R_MIPS_GOT_HI16 big_external_common
+0+02ac <[^>]*> addu \$at,\$at,\$gp
+0+02b0 <[^>]*> lw \$at,0\(\$at\)
+[ ]*2b0: R_MIPS_GOT_LO16 big_external_common
+0+02b4 <[^>]*> nop
+0+02b8 <[^>]*> addu \$at,\$a1,\$at
+0+02bc <[^>]*> lw \$a0,1\(\$at\)
+0+02c0 <[^>]*> lw \$a1,5\(\$at\)
+0+02c4 <[^>]*> lui \$at,0x0
+[ ]*2c4: R_MIPS_GOT_HI16 small_external_common
+0+02c8 <[^>]*> addu \$at,\$at,\$gp
+0+02cc <[^>]*> lw \$at,0\(\$at\)
+[ ]*2cc: R_MIPS_GOT_LO16 small_external_common
+0+02d0 <[^>]*> nop
+0+02d4 <[^>]*> addu \$at,\$a1,\$at
+0+02d8 <[^>]*> lw \$a0,1\(\$at\)
+0+02dc <[^>]*> lw \$a1,5\(\$at\)
+0+02e0 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*2e0: R_MIPS_GOT16 .bss
+0+02e4 <[^>]*> nop
+0+02e8 <[^>]*> addu \$at,\$a1,\$at
+0+02ec <[^>]*> lw \$a0,1\(\$at\)
+[ ]*2ec: R_MIPS_LO16 .bss
+0+02f0 <[^>]*> lw \$a1,5\(\$at\)
+[ ]*2f0: R_MIPS_LO16 .bss
+0+02f4 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*2f4: R_MIPS_GOT16 .bss
+0+02f8 <[^>]*> nop
+0+02fc <[^>]*> addu \$at,\$a1,\$at
+0+0300 <[^>]*> lw \$a0,1001\(\$at\)
+[ ]*300: R_MIPS_LO16 .bss
+0+0304 <[^>]*> lw \$a1,1005\(\$at\)
+[ ]*304: R_MIPS_LO16 .bss
+ ...
diff --git a/gas/testsuite/gas/mips/ld.d b/gas/testsuite/gas/mips/ld.d
new file mode 100644
index 0000000000..5489cf16e3
--- /dev/null
+++ b/gas/testsuite/gas/mips/ld.d
@@ -0,0 +1,639 @@
+#objdump: -dr --prefix-addresses -mmips:4000
+#as: -mcpu=r4000
+#name: MIPS ld
+
+# Test the ld macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> lw \$a0,0\(\$zero\)
+0+0004 <[^>]*> lw \$a1,4\(\$zero\)
+0+0008 <[^>]*> lw \$a0,1\(\$zero\)
+0+000c <[^>]*> lw \$a1,5\(\$zero\)
+0+0010 <[^>]*> lui \$at,0x1
+0+0014 <[^>]*> lw \$a0,-32768\(\$at\)
+0+0018 <[^>]*> lw \$a1,-32764\(\$at\)
+0+001c <[^>]*> lw \$a0,-32768\(\$zero\)
+0+0020 <[^>]*> lw \$a1,-32764\(\$zero\)
+0+0024 <[^>]*> lui \$at,0x1
+0+0028 <[^>]*> lw \$a0,0\(\$at\)
+0+002c <[^>]*> lw \$a1,4\(\$at\)
+0+0030 <[^>]*> lui \$at,0x2
+0+0034 <[^>]*> lw \$a0,-23131\(\$at\)
+0+0038 <[^>]*> lw \$a1,-23127\(\$at\)
+0+003c <[^>]*> nop
+0+0040 <[^>]*> lw \$a0,0\(\$a1\)
+0+0044 <[^>]*> lw \$a1,4\(\$a1\)
+0+0048 <[^>]*> nop
+0+004c <[^>]*> lw \$a0,1\(\$a1\)
+0+0050 <[^>]*> lw \$a1,5\(\$a1\)
+0+0054 <[^>]*> lui \$at,0x1
+0+0058 <[^>]*> addu \$at,\$a1,\$at
+0+005c <[^>]*> lw \$a0,-32768\(\$at\)
+0+0060 <[^>]*> lw \$a1,-32764\(\$at\)
+0+0064 <[^>]*> nop
+0+0068 <[^>]*> lw \$a0,-32768\(\$a1\)
+0+006c <[^>]*> lw \$a1,-32764\(\$a1\)
+0+0070 <[^>]*> lui \$at,0x1
+0+0074 <[^>]*> addu \$at,\$a1,\$at
+0+0078 <[^>]*> lw \$a0,0\(\$at\)
+0+007c <[^>]*> lw \$a1,4\(\$at\)
+0+0080 <[^>]*> lui \$at,0x2
+0+0084 <[^>]*> addu \$at,\$a1,\$at
+0+0088 <[^>]*> lw \$a0,-23131\(\$at\)
+0+008c <[^>]*> lw \$a1,-23127\(\$at\)
+0+0090 <[^>]*> lui \$at,0x0
+[ ]*90: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0094 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*94: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0098 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*98: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+009c <[^>]*> lui \$at,0x0
+[ ]*9c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+00a0 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*a0: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+00a4 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*a4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+00a8 <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*a8: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00ac <[^>]*> lw \$a1,[-0-9]+\(\$gp\)
+[ ]*ac: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00b0 <[^>]*> lui \$at,0x0
+[ ]*b0: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+00b4 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*b4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+00b8 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*b8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+00bc <[^>]*> lw \$a0,0\(\$gp\)
+[ ]*bc: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+00c0 <[^>]*> lw \$a1,[-0-9]+\(\$gp\)
+[ ]*c0: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+00c4 <[^>]*> lui \$at,0x0
+[ ]*c4: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+00c8 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*c8: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+00cc <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*cc: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+00d0 <[^>]*> lw \$a0,[-0-9]+\(\$gp\)
+[ ]*d0: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00d4 <[^>]*> lw \$a1,[-0-9]+\(\$gp\)
+[ ]*d4: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00d8 <[^>]*> lui \$at,0x0
+[ ]*d8: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+00dc <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*dc: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+00e0 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*e0: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+00e4 <[^>]*> lui \$at,0x0
+[ ]*e4: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+00e8 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*e8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+00ec <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*ec: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+00f0 <[^>]*> lw \$a0,1\(\$gp\)
+[ ]*f0: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00f4 <[^>]*> lw \$a1,5\(\$gp\)
+[ ]*f4: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00f8 <[^>]*> lui \$at,0x0
+[ ]*f8: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+00fc <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*fc: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0100 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*100: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0104 <[^>]*> lw \$a0,1\(\$gp\)
+[ ]*104: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+0108 <[^>]*> lw \$a1,5\(\$gp\)
+[ ]*108: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+010c <[^>]*> lui \$at,0x0
+[ ]*10c: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0110 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*110: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0114 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*114: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0118 <[^>]*> lw \$a0,[-0-9]+\(\$gp\)
+[ ]*118: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+011c <[^>]*> lw \$a1,[-0-9]+\(\$gp\)
+[ ]*11c: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0120 <[^>]*> lui \$at,[-0-9x]+
+[ ]*120: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0124 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*124: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0128 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*128: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+012c <[^>]*> lui \$at,[-0-9x]+
+[ ]*12c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0130 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*130: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0134 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*134: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0138 <[^>]*> lui \$at,[-0-9x]+
+[ ]*138: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+013c <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*13c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0140 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*140: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0144 <[^>]*> lui \$at,[-0-9x]+
+[ ]*144: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0148 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*148: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+014c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*14c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0150 <[^>]*> lui \$at,[-0-9x]+
+[ ]*150: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0154 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*154: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0158 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*158: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+015c <[^>]*> lui \$at,[-0-9x]+
+[ ]*15c: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0160 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*160: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0164 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*164: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0168 <[^>]*> lui \$at,[-0-9x]+
+[ ]*168: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+016c <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*16c: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0170 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*170: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0174 <[^>]*> lui \$at,0x0
+[ ]*174: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0178 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*178: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+017c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*17c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0180 <[^>]*> lui \$at,0x0
+[ ]*180: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0184 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*184: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0188 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*188: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+018c <[^>]*> lui \$at,0x0
+[ ]*18c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0190 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*190: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0194 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*194: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0198 <[^>]*> lui \$at,0x0
+[ ]*198: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+019c <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*19c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+01a0 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*1a0: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+01a4 <[^>]*> lui \$at,0x0
+[ ]*1a4: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+01a8 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*1a8: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+01ac <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*1ac: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+01b0 <[^>]*> lui \$at,0x0
+[ ]*1b0: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+01b4 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*1b4: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+01b8 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*1b8: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+01bc <[^>]*> lui \$at,0x0
+[ ]*1bc: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+01c0 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*1c0: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+01c4 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*1c4: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+01c8 <[^>]*> lui \$at,[-0-9x]+
+[ ]*1c8: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+01cc <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*1cc: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+01d0 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*1d0: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+01d4 <[^>]*> lui \$at,[-0-9x]+
+[ ]*1d4: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+01d8 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*1d8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+01dc <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*1dc: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+01e0 <[^>]*> lui \$at,[-0-9x]+
+[ ]*1e0: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+01e4 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*1e4: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+01e8 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*1e8: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+01ec <[^>]*> lui \$at,[-0-9x]+
+[ ]*1ec: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+01f0 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*1f0: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+01f4 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*1f4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+01f8 <[^>]*> lui \$at,[-0-9x]+
+[ ]*1f8: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+01fc <[^>]*> lw \$a0,0\(\$at\)
+[ ]*1fc: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0200 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*200: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0204 <[^>]*> lui \$at,[-0-9x]+
+[ ]*204: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0208 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*208: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+020c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*20c: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0210 <[^>]*> lui \$at,[-0-9x]+
+[ ]*210: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0214 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*214: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0218 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*218: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+021c <[^>]*> lui \$at,[-0-9x]+
+[ ]*21c: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0220 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*220: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0224 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*224: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0228 <[^>]*> lui \$at,[-0-9x]+
+[ ]*228: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+022c <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*22c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0230 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*230: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0234 <[^>]*> lui \$at,[-0-9x]+
+[ ]*234: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0238 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*238: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+023c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*23c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0240 <[^>]*> lui \$at,[-0-9x]+
+[ ]*240: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0244 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*244: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0248 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*248: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+024c <[^>]*> lui \$at,[-0-9x]+
+[ ]*24c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0250 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*250: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0254 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*254: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0258 <[^>]*> lui \$at,[-0-9x]+
+[ ]*258: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+025c <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*25c: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0260 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*260: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0264 <[^>]*> lui \$at,[-0-9x]+
+[ ]*264: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0268 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*268: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+026c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*26c: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0270 <[^>]*> lui \$at,0x0
+[ ]*270: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0274 <[^>]*> addu \$at,\$a1,\$at
+0+0278 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*278: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+027c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*27c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0280 <[^>]*> lui \$at,0x0
+[ ]*280: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0284 <[^>]*> addu \$at,\$a1,\$at
+0+0288 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*288: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+028c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*28c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0290 <[^>]*> nop
+0+0294 <[^>]*> addu \$at,\$a1,\$gp
+0+0298 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*298: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+029c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*29c: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+02a0 <[^>]*> lui \$at,0x0
+[ ]*2a0: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+02a4 <[^>]*> addu \$at,\$a1,\$at
+0+02a8 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*2a8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+02ac <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*2ac: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+02b0 <[^>]*> nop
+0+02b4 <[^>]*> addu \$at,\$a1,\$gp
+0+02b8 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*2b8: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+02bc <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*2bc: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+02c0 <[^>]*> lui \$at,0x0
+[ ]*2c0: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+02c4 <[^>]*> addu \$at,\$a1,\$at
+0+02c8 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*2c8: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+02cc <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*2cc: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+02d0 <[^>]*> nop
+0+02d4 <[^>]*> addu \$at,\$a1,\$gp
+0+02d8 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*2d8: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+02dc <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*2dc: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+02e0 <[^>]*> lui \$at,0x0
+[ ]*2e0: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+02e4 <[^>]*> addu \$at,\$a1,\$at
+0+02e8 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*2e8: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+02ec <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*2ec: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+02f0 <[^>]*> lui \$at,0x0
+[ ]*2f0: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+02f4 <[^>]*> addu \$at,\$a1,\$at
+0+02f8 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*2f8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+02fc <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*2fc: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0300 <[^>]*> nop
+0+0304 <[^>]*> addu \$at,\$a1,\$gp
+0+0308 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*308: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+030c <[^>]*> lw \$a1,5\(\$at\)
+[ ]*30c: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+0310 <[^>]*> lui \$at,0x0
+[ ]*310: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0314 <[^>]*> addu \$at,\$a1,\$at
+0+0318 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*318: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+031c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*31c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0320 <[^>]*> nop
+0+0324 <[^>]*> addu \$at,\$a1,\$gp
+0+0328 <[^>]*> lw \$a0,1\(\$at\)
+[ ]*328: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+032c <[^>]*> lw \$a1,5\(\$at\)
+[ ]*32c: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+0330 <[^>]*> lui \$at,0x0
+[ ]*330: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0334 <[^>]*> addu \$at,\$a1,\$at
+0+0338 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*338: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+033c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*33c: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0340 <[^>]*> nop
+0+0344 <[^>]*> addu \$at,\$a1,\$gp
+0+0348 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*348: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+034c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*34c: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0350 <[^>]*> lui \$at,[-0-9x]+
+[ ]*350: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0354 <[^>]*> addu \$at,\$a1,\$at
+0+0358 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*358: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+035c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*35c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0360 <[^>]*> lui \$at,[-0-9x]+
+[ ]*360: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0364 <[^>]*> addu \$at,\$a1,\$at
+0+0368 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*368: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+036c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*36c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0370 <[^>]*> lui \$at,[-0-9x]+
+[ ]*370: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0374 <[^>]*> addu \$at,\$a1,\$at
+0+0378 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*378: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+037c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*37c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0380 <[^>]*> lui \$at,[-0-9x]+
+[ ]*380: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0384 <[^>]*> addu \$at,\$a1,\$at
+0+0388 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*388: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+038c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*38c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0390 <[^>]*> lui \$at,[-0-9x]+
+[ ]*390: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0394 <[^>]*> addu \$at,\$a1,\$at
+0+0398 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*398: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+039c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*39c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+03a0 <[^>]*> lui \$at,[-0-9x]+
+[ ]*3a0: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+03a4 <[^>]*> addu \$at,\$a1,\$at
+0+03a8 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*3a8: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+03ac <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*3ac: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+03b0 <[^>]*> lui \$at,[-0-9x]+
+[ ]*3b0: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+03b4 <[^>]*> addu \$at,\$a1,\$at
+0+03b8 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*3b8: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+03bc <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*3bc: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+03c0 <[^>]*> lui \$at,0x0
+[ ]*3c0: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+03c4 <[^>]*> addu \$at,\$a1,\$at
+0+03c8 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*3c8: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+03cc <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*3cc: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+03d0 <[^>]*> lui \$at,0x0
+[ ]*3d0: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+03d4 <[^>]*> addu \$at,\$a1,\$at
+0+03d8 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*3d8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+03dc <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*3dc: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+03e0 <[^>]*> lui \$at,0x0
+[ ]*3e0: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+03e4 <[^>]*> addu \$at,\$a1,\$at
+0+03e8 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*3e8: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+03ec <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*3ec: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+03f0 <[^>]*> lui \$at,0x0
+[ ]*3f0: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+03f4 <[^>]*> addu \$at,\$a1,\$at
+0+03f8 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*3f8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+03fc <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*3fc: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0400 <[^>]*> lui \$at,0x0
+[ ]*400: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0404 <[^>]*> addu \$at,\$a1,\$at
+0+0408 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*408: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+040c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*40c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0410 <[^>]*> lui \$at,0x0
+[ ]*410: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0414 <[^>]*> addu \$at,\$a1,\$at
+0+0418 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*418: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+041c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*41c: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0420 <[^>]*> lui \$at,0x0
+[ ]*420: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0424 <[^>]*> addu \$at,\$a1,\$at
+0+0428 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*428: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+042c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*42c: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0430 <[^>]*> lui \$at,[-0-9x]+
+[ ]*430: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0434 <[^>]*> addu \$at,\$a1,\$at
+0+0438 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*438: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+043c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*43c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0440 <[^>]*> lui \$at,[-0-9x]+
+[ ]*440: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0444 <[^>]*> addu \$at,\$a1,\$at
+0+0448 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*448: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+044c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*44c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0450 <[^>]*> lui \$at,[-0-9x]+
+[ ]*450: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0454 <[^>]*> addu \$at,\$a1,\$at
+0+0458 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*458: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+045c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*45c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0460 <[^>]*> lui \$at,[-0-9x]+
+[ ]*460: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0464 <[^>]*> addu \$at,\$a1,\$at
+0+0468 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*468: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+046c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*46c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0470 <[^>]*> lui \$at,[-0-9x]+
+[ ]*470: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0474 <[^>]*> addu \$at,\$a1,\$at
+0+0478 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*478: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+047c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*47c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0480 <[^>]*> lui \$at,[-0-9x]+
+[ ]*480: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0484 <[^>]*> addu \$at,\$a1,\$at
+0+0488 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*488: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+048c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*48c: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0490 <[^>]*> lui \$at,[-0-9x]+
+[ ]*490: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0494 <[^>]*> addu \$at,\$a1,\$at
+0+0498 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*498: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+049c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*49c: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+04a0 <[^>]*> lui \$at,[-0-9x]+
+[ ]*4a0: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+04a4 <[^>]*> addu \$at,\$a1,\$at
+0+04a8 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*4a8: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+04ac <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*4ac: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+04b0 <[^>]*> lui \$at,[-0-9x]+
+[ ]*4b0: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+04b4 <[^>]*> addu \$at,\$a1,\$at
+0+04b8 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*4b8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+04bc <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*4bc: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+04c0 <[^>]*> lui \$at,[-0-9x]+
+[ ]*4c0: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+04c4 <[^>]*> addu \$at,\$a1,\$at
+0+04c8 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*4c8: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+04cc <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*4cc: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+04d0 <[^>]*> lui \$at,[-0-9x]+
+[ ]*4d0: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+04d4 <[^>]*> addu \$at,\$a1,\$at
+0+04d8 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*4d8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+04dc <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*4dc: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+04e0 <[^>]*> lui \$at,[-0-9x]+
+[ ]*4e0: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+04e4 <[^>]*> addu \$at,\$a1,\$at
+0+04e8 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*4e8: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+04ec <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*4ec: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+04f0 <[^>]*> lui \$at,[-0-9x]+
+[ ]*4f0: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+04f4 <[^>]*> addu \$at,\$a1,\$at
+0+04f8 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*4f8: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+04fc <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*4fc: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0500 <[^>]*> lui \$at,[-0-9x]+
+[ ]*500: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0504 <[^>]*> addu \$at,\$a1,\$at
+0+0508 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*508: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+050c <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*50c: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0510 <[^>]*> lwc1 \$f[45],0\(\$zero\)
+0+0514 <[^>]*> lwc1 \$f[45],4\(\$zero\)
+0+0518 <[^>]*> lwc1 \$f[45],1\(\$zero\)
+0+051c <[^>]*> lwc1 \$f[45],5\(\$zero\)
+0+0520 <[^>]*> lui \$at,0x1
+0+0524 <[^>]*> lwc1 \$f[45],-32768\(\$at\)
+0+0528 <[^>]*> lwc1 \$f[45],-32764\(\$at\)
+0+052c <[^>]*> lwc1 \$f[45],-32768\(\$zero\)
+0+0530 <[^>]*> lwc1 \$f[45],-32764\(\$zero\)
+0+0534 <[^>]*> lwc1 \$f[45],0\(\$a1\)
+0+0538 <[^>]*> lwc1 \$f[45],4\(\$a1\)
+0+053c <[^>]*> lwc1 \$f[45],1\(\$a1\)
+0+0540 <[^>]*> lwc1 \$f[45],5\(\$a1\)
+0+0544 <[^>]*> lui \$at,0x1
+0+0548 <[^>]*> addu \$at,\$a1,\$at
+0+054c <[^>]*> lwc1 \$f[45],-32768\(\$at\)
+0+0550 <[^>]*> lwc1 \$f[45],-32764\(\$at\)
+0+0554 <[^>]*> lwc1 \$f[45],-32768\(\$a1\)
+0+0558 <[^>]*> lwc1 \$f[45],-32764\(\$a1\)
+0+055c <[^>]*> lui \$at,[-0-9x]+
+[ ]*55c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0560 <[^>]*> addu \$at,\$a1,\$at
+0+0564 <[^>]*> lwc1 \$f[45],[-0-9]+\(\$at\)
+[ ]*564: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0568 <[^>]*> lwc1 \$f[45],[-0-9]+\(\$at\)
+[ ]*568: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+056c <[^>]*> nop
+0+0570 <[^>]*> swc1 \$f[45],0\(\$zero\)
+0+0574 <[^>]*> swc1 \$f[45],4\(\$zero\)
+0+0578 <[^>]*> swc1 \$f[45],1\(\$zero\)
+0+057c <[^>]*> swc1 \$f[45],5\(\$zero\)
+0+0580 <[^>]*> lui \$at,0x1
+0+0584 <[^>]*> swc1 \$f[45],-32768\(\$at\)
+0+0588 <[^>]*> swc1 \$f[45],-32764\(\$at\)
+0+058c <[^>]*> swc1 \$f[45],-32768\(\$zero\)
+0+0590 <[^>]*> swc1 \$f[45],-32764\(\$zero\)
+0+0594 <[^>]*> swc1 \$f[45],0\(\$a1\)
+0+0598 <[^>]*> swc1 \$f[45],4\(\$a1\)
+0+059c <[^>]*> swc1 \$f[45],1\(\$a1\)
+0+05a0 <[^>]*> swc1 \$f[45],5\(\$a1\)
+0+05a4 <[^>]*> lui \$at,0x1
+0+05a8 <[^>]*> addu \$at,\$a1,\$at
+0+05ac <[^>]*> swc1 \$f[45],-32768\(\$at\)
+0+05b0 <[^>]*> swc1 \$f[45],-32764\(\$at\)
+0+05b4 <[^>]*> swc1 \$f[45],-32768\(\$a1\)
+0+05b8 <[^>]*> swc1 \$f[45],-32764\(\$a1\)
+0+05bc <[^>]*> lui \$at,[-0-9x]+
+[ ]*5bc: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+05c0 <[^>]*> addu \$at,\$a1,\$at
+0+05c4 <[^>]*> swc1 \$f[45],[-0-9]+\(\$at\)
+[ ]*5c4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+05c8 <[^>]*> swc1 \$f[45],[-0-9]+\(\$at\)
+[ ]*5c8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+05cc <[^>]*> sw \$a0,0\(\$zero\)
+0+05d0 <[^>]*> sw \$a1,4\(\$zero\)
+0+05d4 <[^>]*> lui \$a0,[-0-9x]+
+[ ]*5d4: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+05d8 <[^>]*> daddu \$a0,\$a0,\$a1
+0+05dc <[^>]*> ld \$a0,[-0-9]+\(\$a0\)
+[ ]*5dc: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+05e0 <[^>]*> lui \$at,[-0-9x]+
+[ ]*5e0: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+05e4 <[^>]*> daddu \$at,\$at,\$a1
+0+05e8 <[^>]*> sd \$a0,[-0-9]+\(\$at\)
+[ ]*5e8: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+05ec <[^>]*> nop
diff --git a/gas/testsuite/gas/mips/ld.s b/gas/testsuite/gas/mips/ld.s
new file mode 100644
index 0000000000..05ee3c03fe
--- /dev/null
+++ b/gas/testsuite/gas/mips/ld.s
@@ -0,0 +1,144 @@
+# Source file used to test the ld macro.
+
+ .set mips1
+
+ .data
+data_label:
+ .extern big_external_data_label,1000
+ .extern small_external_data_label,1
+ .comm big_external_common,1000
+ .comm small_external_common,1
+ .lcomm big_local_common,1000
+ .lcomm small_local_common,1
+
+ .text
+ ld $4,0
+ ld $4,1
+ ld $4,0x8000
+ ld $4,-0x8000
+ ld $4,0x10000
+ ld $4,0x1a5a5
+ ld $4,0($5)
+ ld $4,1($5)
+ ld $4,0x8000($5)
+ ld $4,-0x8000($5)
+ ld $4,0x10000($5)
+ ld $4,0x1a5a5($5)
+ ld $4,data_label
+ ld $4,big_external_data_label
+ ld $4,small_external_data_label
+ ld $4,big_external_common
+ ld $4,small_external_common
+ ld $4,big_local_common
+ ld $4,small_local_common
+ ld $4,data_label+1
+ ld $4,big_external_data_label+1
+ ld $4,small_external_data_label+1
+ ld $4,big_external_common+1
+ ld $4,small_external_common+1
+ ld $4,big_local_common+1
+ ld $4,small_local_common+1
+ ld $4,data_label+0x8000
+ ld $4,big_external_data_label+0x8000
+ ld $4,small_external_data_label+0x8000
+ ld $4,big_external_common+0x8000
+ ld $4,small_external_common+0x8000
+ ld $4,big_local_common+0x8000
+ ld $4,small_local_common+0x8000
+ ld $4,data_label-0x8000
+ ld $4,big_external_data_label-0x8000
+ ld $4,small_external_data_label-0x8000
+ ld $4,big_external_common-0x8000
+ ld $4,small_external_common-0x8000
+ ld $4,big_local_common-0x8000
+ ld $4,small_local_common-0x8000
+ ld $4,data_label+0x10000
+ ld $4,big_external_data_label+0x10000
+ ld $4,small_external_data_label+0x10000
+ ld $4,big_external_common+0x10000
+ ld $4,small_external_common+0x10000
+ ld $4,big_local_common+0x10000
+ ld $4,small_local_common+0x10000
+ ld $4,data_label+0x1a5a5
+ ld $4,big_external_data_label+0x1a5a5
+ ld $4,small_external_data_label+0x1a5a5
+ ld $4,big_external_common+0x1a5a5
+ ld $4,small_external_common+0x1a5a5
+ ld $4,big_local_common+0x1a5a5
+ ld $4,small_local_common+0x1a5a5
+ ld $4,data_label($5)
+ ld $4,big_external_data_label($5)
+ ld $4,small_external_data_label($5)
+ ld $4,big_external_common($5)
+ ld $4,small_external_common($5)
+ ld $4,big_local_common($5)
+ ld $4,small_local_common($5)
+ ld $4,data_label+1($5)
+ ld $4,big_external_data_label+1($5)
+ ld $4,small_external_data_label+1($5)
+ ld $4,big_external_common+1($5)
+ ld $4,small_external_common+1($5)
+ ld $4,big_local_common+1($5)
+ ld $4,small_local_common+1($5)
+ ld $4,data_label+0x8000($5)
+ ld $4,big_external_data_label+0x8000($5)
+ ld $4,small_external_data_label+0x8000($5)
+ ld $4,big_external_common+0x8000($5)
+ ld $4,small_external_common+0x8000($5)
+ ld $4,big_local_common+0x8000($5)
+ ld $4,small_local_common+0x8000($5)
+ ld $4,data_label-0x8000($5)
+ ld $4,big_external_data_label-0x8000($5)
+ ld $4,small_external_data_label-0x8000($5)
+ ld $4,big_external_common-0x8000($5)
+ ld $4,small_external_common-0x8000($5)
+ ld $4,big_local_common-0x8000($5)
+ ld $4,small_local_common-0x8000($5)
+ ld $4,data_label+0x10000($5)
+ ld $4,big_external_data_label+0x10000($5)
+ ld $4,small_external_data_label+0x10000($5)
+ ld $4,big_external_common+0x10000($5)
+ ld $4,small_external_common+0x10000($5)
+ ld $4,big_local_common+0x10000($5)
+ ld $4,small_local_common+0x10000($5)
+ ld $4,data_label+0x1a5a5($5)
+ ld $4,big_external_data_label+0x1a5a5($5)
+ ld $4,small_external_data_label+0x1a5a5($5)
+ ld $4,big_external_common+0x1a5a5($5)
+ ld $4,small_external_common+0x1a5a5($5)
+ ld $4,big_local_common+0x1a5a5($5)
+ ld $4,small_local_common+0x1a5a5($5)
+
+# l.d and s.d are sort of like ld.
+ l.d $f4,0
+ l.d $f4,1
+ l.d $f4,0x8000
+ l.d $f4,-0x8000
+ l.d $f4,0($5)
+ l.d $f4,1($5)
+ l.d $f4,0x8000($5)
+ l.d $f4,-0x8000($5)
+ l.d $f4,small_external_common+0x1a5a5($5)
+ # Little endian will insert a nop here.
+ # We put it in explicitly so that big and little endian are similar.
+ nop
+ s.d $f4,0
+ s.d $f4,1
+ s.d $f4,0x8000
+ s.d $f4,-0x8000
+ s.d $f4,0($5)
+ s.d $f4,1($5)
+ s.d $f4,0x8000($5)
+ s.d $f4,-0x8000($5)
+ s.d $f4,big_external_common+0x1a5a5($5)
+
+# sd is handled like ld. Sanity check it.
+ sd $4,0
+
+# Sanity check the -mips3 versions
+ .set mips3
+ ld $4,big_local_common+0x1a5a5($5)
+ sd $4,small_local_common+0x1a5a5($5)
+
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+ nop
diff --git a/gas/testsuite/gas/mips/li.d b/gas/testsuite/gas/mips/li.d
new file mode 100644
index 0000000000..0fe2b21ea1
--- /dev/null
+++ b/gas/testsuite/gas/mips/li.d
@@ -0,0 +1,16 @@
+#objdump: -dr --prefix-addresses -mmips:4000
+#name: MIPS li
+
+# Test the li macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> li \$a0,0
+0+0004 <[^>]*> li \$a0,1
+0+0008 <[^>]*> li \$a0,0x8000
+0+000c <[^>]*> li \$a0,-32768
+0+0010 <[^>]*> lui \$a0,0x1
+0+0014 <[^>]*> lui \$a0,0x1
+0+0018 <[^>]*> ori \$a0,\$a0,0xa5a5
+0+001c <[^>]*> nop
diff --git a/gas/testsuite/gas/mips/li.s b/gas/testsuite/gas/mips/li.s
new file mode 100644
index 0000000000..9c3a6018ad
--- /dev/null
+++ b/gas/testsuite/gas/mips/li.s
@@ -0,0 +1,12 @@
+# Source file used to test the li macro.
+
+foo:
+ li $4,0
+ li $4,1
+ li $4,0x8000
+ li $4,-0x8000
+ li $4,0x10000
+ li $4,0x1a5a5
+
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+ nop
diff --git a/gas/testsuite/gas/mips/lif-empic.d b/gas/testsuite/gas/mips/lif-empic.d
new file mode 100644
index 0000000000..b80dca3778
--- /dev/null
+++ b/gas/testsuite/gas/mips/lif-empic.d
@@ -0,0 +1,24 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS lifloat-empic
+#as: -mips1 -membedded-pic --defsym EMPIC=1
+#source: lifloat.s
+
+# Test the li.d and li.s macros with -membedded-pic.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> addiu \$at,\$gp,-16384
+[ ]*0: [A-Z0-9_]*GPREL[A-Z0-9_]* .rdata.*
+0+0004 <[^>]*> lw \$a0,0\(\$at\)
+0+0008 <[^>]*> lw \$a1,4\(\$at\)
+0+000c <[^>]*> lwc1 \$f[45],-16368\(\$gp\)
+[ ]*c: [A-Z0-9_]*LITERAL[A-Z0-9_]* .lit8.*
+0+0010 <[^>]*> lwc1 \$f[45],-16364\(\$gp\)
+[ ]*10: [A-Z0-9_]*LITERAL[A-Z0-9_]* .lit8.*
+0+0014 <[^>]*> lui \$a0,0x3f8f
+0+0018 <[^>]*> ori \$a0,\$a0,0xcd36
+0+001c <[^>]*> lui \$at,0x3f8f
+0+0020 <[^>]*> ori \$at,\$at,0xcd36
+0+0024 <[^>]*> mtc1 \$at,\$f4
+ ...
diff --git a/gas/testsuite/gas/mips/lif-svr4pic.d b/gas/testsuite/gas/mips/lif-svr4pic.d
new file mode 100644
index 0000000000..db09a7fd54
--- /dev/null
+++ b/gas/testsuite/gas/mips/lif-svr4pic.d
@@ -0,0 +1,30 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS lifloat-svr4pic
+#as: -mips1 -mcpu=r3000 -KPIC -EB --defsym SVR4=1
+#source: lifloat.s
+
+# Test the li.d and li.s macros with -KPIC.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*0: R_MIPS_GOT16 .rodata
+0+0004 <[^>]*> nop
+0+0008 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*8: R_MIPS_LO16 .rodata
+0+000c <[^>]*> lw \$a1,4\(\$at\)
+[ ]*c: R_MIPS_LO16 .rodata
+0+0010 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*10: R_MIPS_GOT16 .rodata
+0+0014 <[^>]*> nop
+0+0018 <[^>]*> lwc1 \$f5,8\(\$at\)
+[ ]*18: R_MIPS_LO16 .rodata
+0+001c <[^>]*> lwc1 \$f4,12\(\$at\)
+[ ]*1c: R_MIPS_LO16 .rodata
+0+0020 <[^>]*> lui \$a0,0x3f8f
+0+0024 <[^>]*> ori \$a0,\$a0,0xcd36
+0+0028 <[^>]*> lui \$at,0x3f8f
+0+002c <[^>]*> ori \$at,\$at,0xcd36
+0+0030 <[^>]*> mtc1 \$at,\$f4
+ ...
diff --git a/gas/testsuite/gas/mips/lif-xgot.d b/gas/testsuite/gas/mips/lif-xgot.d
new file mode 100644
index 0000000000..7b86e2b2a3
--- /dev/null
+++ b/gas/testsuite/gas/mips/lif-xgot.d
@@ -0,0 +1,30 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS lifloat-xgot
+#as: -mips1 -mcpu=r3000 -KPIC -xgot -EB --defsym XGOT=1
+#source: lifloat.s
+
+# Test the li.d and li.s macros with -KPIC -xgot.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*0: R_MIPS_GOT16 .rodata
+0+0004 <[^>]*> nop
+0+0008 <[^>]*> lw \$a0,0\(\$at\)
+[ ]*8: R_MIPS_LO16 .rodata
+0+000c <[^>]*> lw \$a1,4\(\$at\)
+[ ]*c: R_MIPS_LO16 .rodata
+0+0010 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*10: R_MIPS_GOT16 .rodata
+0+0014 <[^>]*> nop
+0+0018 <[^>]*> lwc1 \$f5,8\(\$at\)
+[ ]*18: R_MIPS_LO16 .rodata
+0+001c <[^>]*> lwc1 \$f4,12\(\$at\)
+[ ]*1c: R_MIPS_LO16 .rodata
+0+0020 <[^>]*> lui \$a0,0x3f8f
+0+0024 <[^>]*> ori \$a0,\$a0,0xcd36
+0+0028 <[^>]*> lui \$at,0x3f8f
+0+002c <[^>]*> ori \$at,\$at,0xcd36
+0+0030 <[^>]*> mtc1 \$at,\$f4
+ ...
diff --git a/gas/testsuite/gas/mips/lifloat.d b/gas/testsuite/gas/mips/lifloat.d
new file mode 100644
index 0000000000..e71b5548d4
--- /dev/null
+++ b/gas/testsuite/gas/mips/lifloat.d
@@ -0,0 +1,23 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS lifloat
+#as: -mips1
+
+# Test the li.d and li.s macros.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> lui \$at,0x0
+[ ]*0: [A-Z0-9_]*HI[A-Z0-9_]* .ro?data.*
+0+0004 <[^>]*> lw \$a0,[-0-9]+\(\$at\)
+[ ]*4: [A-Z0-9_]*LO[A-Z0-9_]* .ro?data.*
+0+0008 <[^>]*> lw \$a1,[-0-9]+\(\$at\)
+[ ]*8: [A-Z0-9_]*LO[A-Z0-9_]* .ro?data.*
+0+000c <[^>]*> lwc1 \$f[45],[-0-9]+\(\$gp\)
+[ ]*c: [A-Z0-9_]*LITERAL[A-Z0-9_]* .lit8.*
+0+0010 <[^>]*> lwc1 \$f[45],[-0-9]+\(\$gp\)
+[ ]*10: [A-Z0-9_]*LITERAL[A-Z0-9_]* .lit8.*
+0+0014 <[^>]*> lui \$a0,0x3f8f
+0+0018 <[^>]*> ori \$a0,\$a0,0xcd36
+0+001c <[^>]*> lwc1 \$f4,[-0-9]+\(\$gp\)
+[ ]*1c: [A-Z0-9_]*LITERAL[A-Z0-9_]* .lit4.*
diff --git a/gas/testsuite/gas/mips/lifloat.s b/gas/testsuite/gas/mips/lifloat.s
new file mode 100644
index 0000000000..3977f0e7d4
--- /dev/null
+++ b/gas/testsuite/gas/mips/lifloat.s
@@ -0,0 +1,24 @@
+# Source file used to test the li.d and li.s macros.
+
+foo:
+ li.d $4,1.12345
+ li.d $f4,1.12345
+
+ li.s $4,1.12345
+ li.s $f4,1.12345
+
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+ .ifdef SVR4
+ nop
+ nop
+ nop
+ .endif
+ .ifdef XGOT
+ nop
+ nop
+ nop
+ .endif
+ .ifdef EMPIC
+ nop
+ nop
+ .endif
diff --git a/gas/testsuite/gas/mips/lineno.d b/gas/testsuite/gas/mips/lineno.d
new file mode 100644
index 0000000000..d2a40f7a44
--- /dev/null
+++ b/gas/testsuite/gas/mips/lineno.d
@@ -0,0 +1,97 @@
+#objdump: -d -l -mmips:4000
+#name: assembly line numbers
+#as: -g -mcpu=r4000
+
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+0+0000 <main-0x10>:
+.*[0-9a-f]+:.*deadbeef.*
+.*[0-9a-f]+:.*deadbeef.*
+.*[0-9a-f]+:.*deadbeef.*
+.*[0-9a-f]+:.*deadbeef.*
+
+0+0010 <main>:
+main\(\):
+.*lineno.s:16
+.*10:.*addiu.*
+.*lineno.s:17
+.*14:.*sd.*
+.*lineno.s:18
+.*18:.*sd.*
+.*lineno.s:19
+.*1c:.*move.*
+.*lineno.s:20
+.*20:.*jal.*
+.*24:.*nop
+.*lineno.s:21
+.*28:.*li.*
+.*lineno.s:22
+.*2c:.*sw.*
+.*lineno.s:23
+.*30:.*lw.*
+.*lineno.s:24
+.*34:.*move.*
+.*lineno.s:25
+.*38:.*sll.*
+.*lineno.s:26
+.*3c:.*addu.*
+.*lineno.s:27
+.*40:.*sw.*
+.*lineno.s:28
+.*44:.*lw.*
+.*lineno.s:29
+.*48:.*jal.*
+.*4c:.*nop
+.*lineno.s:30
+.*50:.*lw.*
+.*lineno.s:31
+.*54:.*move.*
+.*lineno.s:32
+.*58:.*b.*
+.*5c:.*nop
+
+0000000000000060 <\$L1>:
+.*lineno.s:34
+.*60:.*move.*
+.*lineno.s:35
+.*64:.*ld.*
+.*lineno.s:36
+.*68:.*ld.*
+.*lineno.s:37
+.*6c:.*addiu.*
+.*lineno.s:38
+.*70:.*jr.*
+.*74:.*nop
+
+0000000000000078 <g>:
+g\(\):
+.*lineno.s:47
+.*78:.*addiu.*
+.*lineno.s:48
+.*7c:.*sd.*
+.*lineno.s:49
+.*80:.*move.*
+.*lineno.s:50
+.*84:.*sw.*
+.*lineno.s:51
+.*88:.*lw.*
+.*lineno.s:52
+.*8c:.*addiu.*
+.*lineno.s:53
+.*90:.*move.*
+.*lineno.s:54
+.*94:.*b.*
+.*98:.*nop
+
+000000000000009c <\$L2>:
+.*lineno.s:56
+.*9c:.*move.*
+.*lineno.s:57
+.*a0:.*ld.*
+.*lineno.s:58
+.*a4:.*addiu.*
+.*lineno.s:59
+.*a8:.*jr.*
+.*ac:.*nop
diff --git a/gas/testsuite/gas/mips/lineno.s b/gas/testsuite/gas/mips/lineno.s
new file mode 100644
index 0000000000..531f331a4a
--- /dev/null
+++ b/gas/testsuite/gas/mips/lineno.s
@@ -0,0 +1,60 @@
+ .text
+
+# some data
+ .word 0xdeadbeef
+ .word 0xdeadbeef
+ .word 0xdeadbeef
+ .word 0xdeadbeef
+
+# some real code, compiled from a toy C program
+ .globl main
+ .ent main
+main:
+ .frame $fp,32,$31 # vars= 16, regs= 2/0, args= 0, extra= 0
+ .mask 0xc0000000,-8
+ .fmask 0x00000000,0
+ subu $sp,$sp,32
+ sd $31,24($sp)
+ sd $fp,16($sp)
+ move $fp,$sp
+ jal __main
+ li $2,2 # 0x2
+ sw $2,0($fp)
+ lw $2,0($fp)
+ move $3,$2
+ sll $4,$3,1
+ addu $2,$4,$2
+ sw $2,4($fp)
+ lw $4,4($fp)
+ jal g
+ lw $3,0($fp)
+ move $2,$3
+ b $L1
+$L1:
+ move $sp,$fp
+ ld $31,24($sp)
+ ld $fp,16($sp)
+ addu $sp,$sp,32
+ j $31
+ .end main
+ .align 2
+ .globl g
+ .ent g
+g:
+ .frame $fp,32,$31 # vars= 16, regs= 1/0, args= 0, extra= 0
+ .mask 0x40000000,-16
+ .fmask 0x00000000,0
+ subu $sp,$sp,32
+ sd $fp,16($sp)
+ move $fp,$sp
+ sw $4,0($fp)
+ lw $2,0($fp)
+ addu $3,$2,1
+ move $2,$3
+ b $L2
+$L2:
+ move $sp,$fp
+ ld $fp,16($sp)
+ addu $sp,$sp,32
+ j $31
+ .end g
diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.exp
new file mode 100644
index 0000000000..1b5269d963
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips.exp
@@ -0,0 +1,102 @@
+#
+# Some generic MIPS tests
+#
+if [istarget mips*-*-*] then {
+ set no_mips16 0
+ set svr4pic [expr [istarget *-*-elf*] || [istarget *-*-irix5*] || [istarget *-*-irix6* ] ]
+ set empic [expr [istarget *-*-ecoff*] || [istarget *-*-ultrix*] || [istarget *-*-irix\[1-4\]*] ]
+ set aout [expr [istarget *-*-bsd*] || [istarget *-*-netbsd*] || [istarget *-*-openbsd*]]
+ set ilocks [istarget mipstx39*-*-*]
+ set gpr_ilocks [expr [istarget mipstx39*-*-*]]
+ set addr32 [expr [istarget mipstx39*-*-*]]
+
+
+
+
+
+ run_dump_test "abs"
+ run_dump_test "add"
+ run_dump_test "and"
+ run_dump_test "break20"
+ run_dump_test "trap20"
+ run_dump_test "beq"
+ run_dump_test "bge"
+ run_dump_test "bgeu"
+ run_dump_test "blt"
+ run_dump_test "bltu"
+ if !$ilocks { run_dump_test "div" } else { run_dump_test "div-ilocks" }
+ run_dump_test "dli"
+ run_dump_test "jal"
+ if $svr4pic { run_dump_test "jal-svr4pic" }
+ if $svr4pic { run_dump_test "jal-xgot" }
+ if $empic { run_dump_test "jal-empic" }
+ if !$aout { run_dump_test "la" }
+ if $svr4pic { run_dump_test "la-svr4pic" }
+ if $svr4pic { run_dump_test "la-xgot" }
+ if $empic { run_dump_test "la-empic" }
+ if !$aout { run_dump_test "lb" }
+ if $svr4pic { run_dump_test "lb-svr4pic" }
+ if $svr4pic {
+ # Both versions specify the cpu, so we can run both regardless of
+ # the interlocking in the configured default cpu.
+ run_dump_test "lb-xgot"
+ run_dump_test "lb-xgot-ilocks"
+ }
+ if $empic { run_dump_test "lb-empic" }
+ if !$aout {
+ if !$gpr_ilocks {
+ run_dump_test "ld"
+ } else {
+ if !$addr32 {
+ run_dump_test "ld-ilocks"
+ } else {
+ run_dump_test "ld-ilocks-addr32"
+ }
+ }
+ }
+ if $svr4pic { run_dump_test "ld-svr4pic" }
+ if $svr4pic { run_dump_test "ld-xgot" }
+ if $empic { run_dump_test "ld-empic" }
+ run_dump_test "li"
+ if !$aout { run_dump_test "lifloat" }
+ if $svr4pic { run_dump_test "lif-svr4pic" }
+ if $svr4pic { run_dump_test "lif-xgot" }
+ if $empic { run_dump_test "lif-empic" }
+ run_dump_test "mips4"
+ if !$ilocks { run_dump_test "mul" } else { run_dump_test "mul-ilocks" }
+ run_dump_test "rol"
+ if !$aout { run_dump_test "sb" }
+ run_dump_test "trunc"
+ if !$aout { run_dump_test "ulh" }
+ if $svr4pic { run_dump_test "ulh-svr4pic" }
+ if $svr4pic { run_dump_test "ulh-xgot" }
+ if $empic { run_dump_test "ulh-empic" }
+ if !$aout {
+ run_dump_test "ulw"
+ run_dump_test "uld"
+ run_dump_test "ush"
+ run_dump_test "usw"
+ run_dump_test "usd"
+ }
+ # The mips16 test can only be run on ELF, because only ELF
+ # supports the necessary mips16 reloc.
+ if { $svr4pic && !$no_mips16 } { run_dump_test "mips16" }
+ run_dump_test "delay"
+ run_dump_test "nodelay"
+ run_dump_test "mips4010"
+ run_dump_test "mips4650"
+ run_dump_test "mips4100"
+ run_dump_test "lineno"
+ run_dump_test "sync"
+
+ # Make sure that -mcpu=FOO and -mFOO are equivalent. Assemble a file
+ # containing 4650-specific instructions with -m4650 and -mcpu=4650,
+ # and verify that they're the same. Specifically, we're checking
+ # that the EF_MIPS_MACH field is set, and that the 4650 'mul'
+ # instruction does get used. In previous versions of GAS,
+ # only -mcpu=4650 would set the EF_MIPS_MACH field; -m4650 wouldn't.
+ run_dump_test "elf_e_flags1"
+ run_dump_test "elf_e_flags2"
+ run_dump_test "elf_e_flags3"
+ run_dump_test "elf_e_flags4"
+}
diff --git a/gas/testsuite/gas/mips/mips16.d b/gas/testsuite/gas/mips/mips16.d
new file mode 100644
index 0000000000..e4c1a0ca62
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips16.d
@@ -0,0 +1,683 @@
+#objdump: -dr -mmips:4000
+#as: -mips3 -mcpu=r4000
+#name: mips16
+
+# Test the mips16 instruction set.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+
+0+000000 <data1>:
+ 0: 00000000 nop
+
+0+000004 <insns1>:
+ 4: 3b40 ld \$v0,0\(\$v1\)
+ 6: f000 3b41 ld \$v0,1\(\$v1\)
+ a: f000 3b42 ld \$v0,2\(\$v1\)
+ e: f000 3b43 ld \$v0,3\(\$v1\)
+ 12: f000 3b44 ld \$v0,4\(\$v1\)
+ 16: 3b41 ld \$v0,8\(\$v1\)
+ 18: 3b42 ld \$v0,16\(\$v1\)
+ 1a: 3b44 ld \$v0,32\(\$v1\)
+ 1c: 3b48 ld \$v0,64\(\$v1\)
+ 1e: 3b50 ld \$v0,128\(\$v1\)
+ 20: f100 3b40 ld \$v0,256\(\$v1\)
+ 24: f200 3b40 ld \$v0,512\(\$v1\)
+ 28: f400 3b40 ld \$v0,1024\(\$v1\)
+ 2c: f001 3b40 ld \$v0,2048\(\$v1\)
+ 30: f7ff 3b5f ld \$v0,-1\(\$v1\)
+ 34: f7ff 3b5e ld \$v0,-2\(\$v1\)
+ 38: f7ff 3b5d ld \$v0,-3\(\$v1\)
+ 3c: f7ff 3b5c ld \$v0,-4\(\$v1\)
+ 40: f7ff 3b58 ld \$v0,-8\(\$v1\)
+ 44: f7ff 3b50 ld \$v0,-16\(\$v1\)
+ 48: f7ff 3b40 ld \$v0,-32\(\$v1\)
+ 4c: f7df 3b40 ld \$v0,-64\(\$v1\)
+ 50: f79f 3b40 ld \$v0,-128\(\$v1\)
+ 54: f71f 3b40 ld \$v0,-256\(\$v1\)
+ 58: f61f 3b40 ld \$v0,-512\(\$v1\)
+ 5c: f41f 3b40 ld \$v0,-1024\(\$v1\)
+ 60: f01f 3b40 ld \$v0,-2048\(\$v1\)
+ 64: f7bf fc40 ld \$v0,0 <data1>
+ 68: f6a0 fc54 ld \$v0,71c <data2>
+ 6c: f001 fc40 ld \$v0,868 <bar>
+ 70: f0c1 fc40 ld \$v0,930 <quux>
+ 74: f840 ld \$v0,0\(\$sp\)
+ 76: f000 f841 ld \$v0,1\(\$sp\)
+ 7a: f000 f842 ld \$v0,2\(\$sp\)
+ 7e: f000 f843 ld \$v0,3\(\$sp\)
+ 82: f000 f844 ld \$v0,4\(\$sp\)
+ 86: f841 ld \$v0,8\(\$sp\)
+ 88: f842 ld \$v0,16\(\$sp\)
+ 8a: f844 ld \$v0,32\(\$sp\)
+ 8c: f848 ld \$v0,64\(\$sp\)
+ 8e: f850 ld \$v0,128\(\$sp\)
+ 90: f100 f840 ld \$v0,256\(\$sp\)
+ 94: f200 f840 ld \$v0,512\(\$sp\)
+ 98: f400 f840 ld \$v0,1024\(\$sp\)
+ 9c: f001 f840 ld \$v0,2048\(\$sp\)
+ a0: f7ff f85f ld \$v0,-1\(\$sp\)
+ a4: f7ff f85e ld \$v0,-2\(\$sp\)
+ a8: f7ff f85d ld \$v0,-3\(\$sp\)
+ ac: f7ff f85c ld \$v0,-4\(\$sp\)
+ b0: f7ff f858 ld \$v0,-8\(\$sp\)
+ b4: f7ff f850 ld \$v0,-16\(\$sp\)
+ b8: f7ff f840 ld \$v0,-32\(\$sp\)
+ bc: f7df f840 ld \$v0,-64\(\$sp\)
+ c0: f79f f840 ld \$v0,-128\(\$sp\)
+ c4: f71f f840 ld \$v0,-256\(\$sp\)
+ c8: f61f f840 ld \$v0,-512\(\$sp\)
+ cc: f41f f840 ld \$v0,-1024\(\$sp\)
+ d0: f01f f840 ld \$v0,-2048\(\$sp\)
+ d4: bb40 lwu \$v0,0\(\$v1\)
+ d6: f000 bb41 lwu \$v0,1\(\$v1\)
+ da: f000 bb42 lwu \$v0,2\(\$v1\)
+ de: f000 bb43 lwu \$v0,3\(\$v1\)
+ e2: bb41 lwu \$v0,4\(\$v1\)
+ e4: bb42 lwu \$v0,8\(\$v1\)
+ e6: bb44 lwu \$v0,16\(\$v1\)
+ e8: bb48 lwu \$v0,32\(\$v1\)
+ ea: bb50 lwu \$v0,64\(\$v1\)
+ ec: f080 bb40 lwu \$v0,128\(\$v1\)
+ f0: f100 bb40 lwu \$v0,256\(\$v1\)
+ f4: f200 bb40 lwu \$v0,512\(\$v1\)
+ f8: f400 bb40 lwu \$v0,1024\(\$v1\)
+ fc: f001 bb40 lwu \$v0,2048\(\$v1\)
+ 100: f7ff bb5f lwu \$v0,-1\(\$v1\)
+ 104: f7ff bb5e lwu \$v0,-2\(\$v1\)
+ 108: f7ff bb5d lwu \$v0,-3\(\$v1\)
+ 10c: f7ff bb5c lwu \$v0,-4\(\$v1\)
+ 110: f7ff bb58 lwu \$v0,-8\(\$v1\)
+ 114: f7ff bb50 lwu \$v0,-16\(\$v1\)
+ 118: f7ff bb40 lwu \$v0,-32\(\$v1\)
+ 11c: f7df bb40 lwu \$v0,-64\(\$v1\)
+ 120: f79f bb40 lwu \$v0,-128\(\$v1\)
+ 124: f71f bb40 lwu \$v0,-256\(\$v1\)
+ 128: f61f bb40 lwu \$v0,-512\(\$v1\)
+ 12c: f41f bb40 lwu \$v0,-1024\(\$v1\)
+ 130: f01f bb40 lwu \$v0,-2048\(\$v1\)
+ 134: 9b40 lw \$v0,0\(\$v1\)
+ 136: f000 9b41 lw \$v0,1\(\$v1\)
+ 13a: f000 9b42 lw \$v0,2\(\$v1\)
+ 13e: f000 9b43 lw \$v0,3\(\$v1\)
+ 142: 9b41 lw \$v0,4\(\$v1\)
+ 144: 9b42 lw \$v0,8\(\$v1\)
+ 146: 9b44 lw \$v0,16\(\$v1\)
+ 148: 9b48 lw \$v0,32\(\$v1\)
+ 14a: 9b50 lw \$v0,64\(\$v1\)
+ 14c: f080 9b40 lw \$v0,128\(\$v1\)
+ 150: f100 9b40 lw \$v0,256\(\$v1\)
+ 154: f200 9b40 lw \$v0,512\(\$v1\)
+ 158: f400 9b40 lw \$v0,1024\(\$v1\)
+ 15c: f001 9b40 lw \$v0,2048\(\$v1\)
+ 160: f7ff 9b5f lw \$v0,-1\(\$v1\)
+ 164: f7ff 9b5e lw \$v0,-2\(\$v1\)
+ 168: f7ff 9b5d lw \$v0,-3\(\$v1\)
+ 16c: f7ff 9b5c lw \$v0,-4\(\$v1\)
+ 170: f7ff 9b58 lw \$v0,-8\(\$v1\)
+ 174: f7ff 9b50 lw \$v0,-16\(\$v1\)
+ 178: f7ff 9b40 lw \$v0,-32\(\$v1\)
+ 17c: f7df 9b40 lw \$v0,-64\(\$v1\)
+ 180: f79f 9b40 lw \$v0,-128\(\$v1\)
+ 184: f71f 9b40 lw \$v0,-256\(\$v1\)
+ 188: f61f 9b40 lw \$v0,-512\(\$v1\)
+ 18c: f41f 9b40 lw \$v0,-1024\(\$v1\)
+ 190: f01f 9b40 lw \$v0,-2048\(\$v1\)
+ 194: f67f b20c lw \$v0,0 <data1>
+ 198: f580 b204 lw \$v0,71c <data2>
+ 19c: f6c0 b20c lw \$v0,868 <bar>
+ 1a0: f780 b210 lw \$v0,930 <quux>
+ 1a4: 9200 lw \$v0,0\(\$sp\)
+ 1a6: f000 9201 lw \$v0,1\(\$sp\)
+ 1aa: f000 9202 lw \$v0,2\(\$sp\)
+ 1ae: f000 9203 lw \$v0,3\(\$sp\)
+ 1b2: 9201 lw \$v0,4\(\$sp\)
+ 1b4: 9202 lw \$v0,8\(\$sp\)
+ 1b6: 9204 lw \$v0,16\(\$sp\)
+ 1b8: 9208 lw \$v0,32\(\$sp\)
+ 1ba: 9210 lw \$v0,64\(\$sp\)
+ 1bc: 9220 lw \$v0,128\(\$sp\)
+ 1be: 9240 lw \$v0,256\(\$sp\)
+ 1c0: 9280 lw \$v0,512\(\$sp\)
+ 1c2: f400 9200 lw \$v0,1024\(\$sp\)
+ 1c6: f001 9200 lw \$v0,2048\(\$sp\)
+ 1ca: f7ff 921f lw \$v0,-1\(\$sp\)
+ 1ce: f7ff 921e lw \$v0,-2\(\$sp\)
+ 1d2: f7ff 921d lw \$v0,-3\(\$sp\)
+ 1d6: f7ff 921c lw \$v0,-4\(\$sp\)
+ 1da: f7ff 9218 lw \$v0,-8\(\$sp\)
+ 1de: f7ff 9210 lw \$v0,-16\(\$sp\)
+ 1e2: f7ff 9200 lw \$v0,-32\(\$sp\)
+ 1e6: f7df 9200 lw \$v0,-64\(\$sp\)
+ 1ea: f79f 9200 lw \$v0,-128\(\$sp\)
+ 1ee: f71f 9200 lw \$v0,-256\(\$sp\)
+ 1f2: f61f 9200 lw \$v0,-512\(\$sp\)
+ 1f6: f41f 9200 lw \$v0,-1024\(\$sp\)
+ 1fa: f01f 9200 lw \$v0,-2048\(\$sp\)
+ 1fe: 8b40 lh \$v0,0\(\$v1\)
+ 200: f000 8b41 lh \$v0,1\(\$v1\)
+ 204: 8b41 lh \$v0,2\(\$v1\)
+ 206: f000 8b43 lh \$v0,3\(\$v1\)
+ 20a: 8b42 lh \$v0,4\(\$v1\)
+ 20c: 8b44 lh \$v0,8\(\$v1\)
+ 20e: 8b48 lh \$v0,16\(\$v1\)
+ 210: 8b50 lh \$v0,32\(\$v1\)
+ 212: f040 8b40 lh \$v0,64\(\$v1\)
+ 216: f080 8b40 lh \$v0,128\(\$v1\)
+ 21a: f100 8b40 lh \$v0,256\(\$v1\)
+ 21e: f200 8b40 lh \$v0,512\(\$v1\)
+ 222: f400 8b40 lh \$v0,1024\(\$v1\)
+ 226: f001 8b40 lh \$v0,2048\(\$v1\)
+ 22a: f7ff 8b5f lh \$v0,-1\(\$v1\)
+ 22e: f7ff 8b5e lh \$v0,-2\(\$v1\)
+ 232: f7ff 8b5d lh \$v0,-3\(\$v1\)
+ 236: f7ff 8b5c lh \$v0,-4\(\$v1\)
+ 23a: f7ff 8b58 lh \$v0,-8\(\$v1\)
+ 23e: f7ff 8b50 lh \$v0,-16\(\$v1\)
+ 242: f7ff 8b40 lh \$v0,-32\(\$v1\)
+ 246: f7df 8b40 lh \$v0,-64\(\$v1\)
+ 24a: f79f 8b40 lh \$v0,-128\(\$v1\)
+ 24e: f71f 8b40 lh \$v0,-256\(\$v1\)
+ 252: f61f 8b40 lh \$v0,-512\(\$v1\)
+ 256: f41f 8b40 lh \$v0,-1024\(\$v1\)
+ 25a: f01f 8b40 lh \$v0,-2048\(\$v1\)
+ 25e: ab40 lhu \$v0,0\(\$v1\)
+ 260: f000 ab41 lhu \$v0,1\(\$v1\)
+ 264: ab41 lhu \$v0,2\(\$v1\)
+ 266: f000 ab43 lhu \$v0,3\(\$v1\)
+ 26a: ab42 lhu \$v0,4\(\$v1\)
+ 26c: ab44 lhu \$v0,8\(\$v1\)
+ 26e: ab48 lhu \$v0,16\(\$v1\)
+ 270: ab50 lhu \$v0,32\(\$v1\)
+ 272: f040 ab40 lhu \$v0,64\(\$v1\)
+ 276: f080 ab40 lhu \$v0,128\(\$v1\)
+ 27a: f100 ab40 lhu \$v0,256\(\$v1\)
+ 27e: f200 ab40 lhu \$v0,512\(\$v1\)
+ 282: f400 ab40 lhu \$v0,1024\(\$v1\)
+ 286: f001 ab40 lhu \$v0,2048\(\$v1\)
+ 28a: f7ff ab5f lhu \$v0,-1\(\$v1\)
+ 28e: f7ff ab5e lhu \$v0,-2\(\$v1\)
+ 292: f7ff ab5d lhu \$v0,-3\(\$v1\)
+ 296: f7ff ab5c lhu \$v0,-4\(\$v1\)
+ 29a: f7ff ab58 lhu \$v0,-8\(\$v1\)
+ 29e: f7ff ab50 lhu \$v0,-16\(\$v1\)
+ 2a2: f7ff ab40 lhu \$v0,-32\(\$v1\)
+ 2a6: f7df ab40 lhu \$v0,-64\(\$v1\)
+ 2aa: f79f ab40 lhu \$v0,-128\(\$v1\)
+ 2ae: f71f ab40 lhu \$v0,-256\(\$v1\)
+ 2b2: f61f ab40 lhu \$v0,-512\(\$v1\)
+ 2b6: f41f ab40 lhu \$v0,-1024\(\$v1\)
+ 2ba: f01f ab40 lhu \$v0,-2048\(\$v1\)
+ 2be: 8340 lb \$v0,0\(\$v1\)
+ 2c0: 8341 lb \$v0,1\(\$v1\)
+ 2c2: 8342 lb \$v0,2\(\$v1\)
+ 2c4: 8343 lb \$v0,3\(\$v1\)
+ 2c6: 8344 lb \$v0,4\(\$v1\)
+ 2c8: 8348 lb \$v0,8\(\$v1\)
+ 2ca: 8350 lb \$v0,16\(\$v1\)
+ 2cc: f020 8340 lb \$v0,32\(\$v1\)
+ 2d0: f040 8340 lb \$v0,64\(\$v1\)
+ 2d4: f080 8340 lb \$v0,128\(\$v1\)
+ 2d8: f100 8340 lb \$v0,256\(\$v1\)
+ 2dc: f200 8340 lb \$v0,512\(\$v1\)
+ 2e0: f400 8340 lb \$v0,1024\(\$v1\)
+ 2e4: f001 8340 lb \$v0,2048\(\$v1\)
+ 2e8: f7ff 835f lb \$v0,-1\(\$v1\)
+ 2ec: f7ff 835e lb \$v0,-2\(\$v1\)
+ 2f0: f7ff 835d lb \$v0,-3\(\$v1\)
+ 2f4: f7ff 835c lb \$v0,-4\(\$v1\)
+ 2f8: f7ff 8358 lb \$v0,-8\(\$v1\)
+ 2fc: f7ff 8350 lb \$v0,-16\(\$v1\)
+ 300: f7ff 8340 lb \$v0,-32\(\$v1\)
+ 304: f7df 8340 lb \$v0,-64\(\$v1\)
+ 308: f79f 8340 lb \$v0,-128\(\$v1\)
+ 30c: f71f 8340 lb \$v0,-256\(\$v1\)
+ 310: f61f 8340 lb \$v0,-512\(\$v1\)
+ 314: f41f 8340 lb \$v0,-1024\(\$v1\)
+ 318: f01f 8340 lb \$v0,-2048\(\$v1\)
+ 31c: a340 lbu \$v0,0\(\$v1\)
+ 31e: a341 lbu \$v0,1\(\$v1\)
+ 320: a342 lbu \$v0,2\(\$v1\)
+ 322: a343 lbu \$v0,3\(\$v1\)
+ 324: a344 lbu \$v0,4\(\$v1\)
+ 326: a348 lbu \$v0,8\(\$v1\)
+ 328: a350 lbu \$v0,16\(\$v1\)
+ 32a: f020 a340 lbu \$v0,32\(\$v1\)
+ 32e: f040 a340 lbu \$v0,64\(\$v1\)
+ 332: f080 a340 lbu \$v0,128\(\$v1\)
+ 336: f100 a340 lbu \$v0,256\(\$v1\)
+ 33a: f200 a340 lbu \$v0,512\(\$v1\)
+ 33e: f400 a340 lbu \$v0,1024\(\$v1\)
+ 342: f001 a340 lbu \$v0,2048\(\$v1\)
+ 346: f7ff a35f lbu \$v0,-1\(\$v1\)
+ 34a: f7ff a35e lbu \$v0,-2\(\$v1\)
+ 34e: f7ff a35d lbu \$v0,-3\(\$v1\)
+ 352: f7ff a35c lbu \$v0,-4\(\$v1\)
+ 356: f7ff a358 lbu \$v0,-8\(\$v1\)
+ 35a: f7ff a350 lbu \$v0,-16\(\$v1\)
+ 35e: f7ff a340 lbu \$v0,-32\(\$v1\)
+ 362: f7df a340 lbu \$v0,-64\(\$v1\)
+ 366: f79f a340 lbu \$v0,-128\(\$v1\)
+ 36a: f71f a340 lbu \$v0,-256\(\$v1\)
+ 36e: f61f a340 lbu \$v0,-512\(\$v1\)
+ 372: f41f a340 lbu \$v0,-1024\(\$v1\)
+ 376: f01f a340 lbu \$v0,-2048\(\$v1\)
+ 37a: 7b40 sd \$v0,0\(\$v1\)
+ 37c: f000 7b41 sd \$v0,1\(\$v1\)
+ 380: f000 7b42 sd \$v0,2\(\$v1\)
+ 384: f000 7b43 sd \$v0,3\(\$v1\)
+ 388: f000 7b44 sd \$v0,4\(\$v1\)
+ 38c: 7b41 sd \$v0,8\(\$v1\)
+ 38e: 7b42 sd \$v0,16\(\$v1\)
+ 390: 7b44 sd \$v0,32\(\$v1\)
+ 392: 7b48 sd \$v0,64\(\$v1\)
+ 394: 7b50 sd \$v0,128\(\$v1\)
+ 396: f100 7b40 sd \$v0,256\(\$v1\)
+ 39a: f200 7b40 sd \$v0,512\(\$v1\)
+ 39e: f400 7b40 sd \$v0,1024\(\$v1\)
+ 3a2: f001 7b40 sd \$v0,2048\(\$v1\)
+ 3a6: f7ff 7b5f sd \$v0,-1\(\$v1\)
+ 3aa: f7ff 7b5e sd \$v0,-2\(\$v1\)
+ 3ae: f7ff 7b5d sd \$v0,-3\(\$v1\)
+ 3b2: f7ff 7b5c sd \$v0,-4\(\$v1\)
+ 3b6: f7ff 7b58 sd \$v0,-8\(\$v1\)
+ 3ba: f7ff 7b50 sd \$v0,-16\(\$v1\)
+ 3be: f7ff 7b40 sd \$v0,-32\(\$v1\)
+ 3c2: f7df 7b40 sd \$v0,-64\(\$v1\)
+ 3c6: f79f 7b40 sd \$v0,-128\(\$v1\)
+ 3ca: f71f 7b40 sd \$v0,-256\(\$v1\)
+ 3ce: f61f 7b40 sd \$v0,-512\(\$v1\)
+ 3d2: f41f 7b40 sd \$v0,-1024\(\$v1\)
+ 3d6: f01f 7b40 sd \$v0,-2048\(\$v1\)
+ 3da: f940 sd \$v0,0\(\$sp\)
+ 3dc: f000 f941 sd \$v0,1\(\$sp\)
+ 3e0: f000 f942 sd \$v0,2\(\$sp\)
+ 3e4: f000 f943 sd \$v0,3\(\$sp\)
+ 3e8: f000 f944 sd \$v0,4\(\$sp\)
+ 3ec: f941 sd \$v0,8\(\$sp\)
+ 3ee: f942 sd \$v0,16\(\$sp\)
+ 3f0: f944 sd \$v0,32\(\$sp\)
+ 3f2: f948 sd \$v0,64\(\$sp\)
+ 3f4: f950 sd \$v0,128\(\$sp\)
+ 3f6: f100 f940 sd \$v0,256\(\$sp\)
+ 3fa: f200 f940 sd \$v0,512\(\$sp\)
+ 3fe: f400 f940 sd \$v0,1024\(\$sp\)
+ 402: f001 f940 sd \$v0,2048\(\$sp\)
+ 406: f7ff f95f sd \$v0,-1\(\$sp\)
+ 40a: f7ff f95e sd \$v0,-2\(\$sp\)
+ 40e: f7ff f95d sd \$v0,-3\(\$sp\)
+ 412: f7ff f95c sd \$v0,-4\(\$sp\)
+ 416: f7ff f958 sd \$v0,-8\(\$sp\)
+ 41a: f7ff f950 sd \$v0,-16\(\$sp\)
+ 41e: f7ff f940 sd \$v0,-32\(\$sp\)
+ 422: f7df f940 sd \$v0,-64\(\$sp\)
+ 426: f79f f940 sd \$v0,-128\(\$sp\)
+ 42a: f71f f940 sd \$v0,-256\(\$sp\)
+ 42e: f61f f940 sd \$v0,-512\(\$sp\)
+ 432: f41f f940 sd \$v0,-1024\(\$sp\)
+ 436: f01f f940 sd \$v0,-2048\(\$sp\)
+ 43a: fa00 sd \$ra,0\(\$sp\)
+ 43c: f000 fa01 sd \$ra,1\(\$sp\)
+ 440: f000 fa02 sd \$ra,2\(\$sp\)
+ 444: f000 fa03 sd \$ra,3\(\$sp\)
+ 448: f000 fa04 sd \$ra,4\(\$sp\)
+ 44c: fa01 sd \$ra,8\(\$sp\)
+ 44e: fa02 sd \$ra,16\(\$sp\)
+ 450: fa04 sd \$ra,32\(\$sp\)
+ 452: fa08 sd \$ra,64\(\$sp\)
+ 454: fa10 sd \$ra,128\(\$sp\)
+ 456: fa20 sd \$ra,256\(\$sp\)
+ 458: fa40 sd \$ra,512\(\$sp\)
+ 45a: fa80 sd \$ra,1024\(\$sp\)
+ 45c: f001 fa00 sd \$ra,2048\(\$sp\)
+ 460: f7ff fa1f sd \$ra,-1\(\$sp\)
+ 464: f7ff fa1e sd \$ra,-2\(\$sp\)
+ 468: f7ff fa1d sd \$ra,-3\(\$sp\)
+ 46c: f7ff fa1c sd \$ra,-4\(\$sp\)
+ 470: f7ff fa18 sd \$ra,-8\(\$sp\)
+ 474: f7ff fa10 sd \$ra,-16\(\$sp\)
+ 478: f7ff fa00 sd \$ra,-32\(\$sp\)
+ 47c: f7df fa00 sd \$ra,-64\(\$sp\)
+ 480: f79f fa00 sd \$ra,-128\(\$sp\)
+ 484: f71f fa00 sd \$ra,-256\(\$sp\)
+ 488: f61f fa00 sd \$ra,-512\(\$sp\)
+ 48c: f41f fa00 sd \$ra,-1024\(\$sp\)
+ 490: f01f fa00 sd \$ra,-2048\(\$sp\)
+ 494: db40 sw \$v0,0\(\$v1\)
+ 496: f000 db41 sw \$v0,1\(\$v1\)
+ 49a: f000 db42 sw \$v0,2\(\$v1\)
+ 49e: f000 db43 sw \$v0,3\(\$v1\)
+ 4a2: db41 sw \$v0,4\(\$v1\)
+ 4a4: db42 sw \$v0,8\(\$v1\)
+ 4a6: db44 sw \$v0,16\(\$v1\)
+ 4a8: db48 sw \$v0,32\(\$v1\)
+ 4aa: db50 sw \$v0,64\(\$v1\)
+ 4ac: f080 db40 sw \$v0,128\(\$v1\)
+ 4b0: f100 db40 sw \$v0,256\(\$v1\)
+ 4b4: f200 db40 sw \$v0,512\(\$v1\)
+ 4b8: f400 db40 sw \$v0,1024\(\$v1\)
+ 4bc: f001 db40 sw \$v0,2048\(\$v1\)
+ 4c0: f7ff db5f sw \$v0,-1\(\$v1\)
+ 4c4: f7ff db5e sw \$v0,-2\(\$v1\)
+ 4c8: f7ff db5d sw \$v0,-3\(\$v1\)
+ 4cc: f7ff db5c sw \$v0,-4\(\$v1\)
+ 4d0: f7ff db58 sw \$v0,-8\(\$v1\)
+ 4d4: f7ff db50 sw \$v0,-16\(\$v1\)
+ 4d8: f7ff db40 sw \$v0,-32\(\$v1\)
+ 4dc: f7df db40 sw \$v0,-64\(\$v1\)
+ 4e0: f79f db40 sw \$v0,-128\(\$v1\)
+ 4e4: f71f db40 sw \$v0,-256\(\$v1\)
+ 4e8: f61f db40 sw \$v0,-512\(\$v1\)
+ 4ec: f41f db40 sw \$v0,-1024\(\$v1\)
+ 4f0: f01f db40 sw \$v0,-2048\(\$v1\)
+ 4f4: d200 sw \$v0,0\(\$sp\)
+ 4f6: f000 d201 sw \$v0,1\(\$sp\)
+ 4fa: f000 d202 sw \$v0,2\(\$sp\)
+ 4fe: f000 d203 sw \$v0,3\(\$sp\)
+ 502: d201 sw \$v0,4\(\$sp\)
+ 504: d202 sw \$v0,8\(\$sp\)
+ 506: d204 sw \$v0,16\(\$sp\)
+ 508: d208 sw \$v0,32\(\$sp\)
+ 50a: d210 sw \$v0,64\(\$sp\)
+ 50c: d220 sw \$v0,128\(\$sp\)
+ 50e: d240 sw \$v0,256\(\$sp\)
+ 510: d280 sw \$v0,512\(\$sp\)
+ 512: f400 d200 sw \$v0,1024\(\$sp\)
+ 516: f001 d200 sw \$v0,2048\(\$sp\)
+ 51a: f7ff d21f sw \$v0,-1\(\$sp\)
+ 51e: f7ff d21e sw \$v0,-2\(\$sp\)
+ 522: f7ff d21d sw \$v0,-3\(\$sp\)
+ 526: f7ff d21c sw \$v0,-4\(\$sp\)
+ 52a: f7ff d218 sw \$v0,-8\(\$sp\)
+ 52e: f7ff d210 sw \$v0,-16\(\$sp\)
+ 532: f7ff d200 sw \$v0,-32\(\$sp\)
+ 536: f7df d200 sw \$v0,-64\(\$sp\)
+ 53a: f79f d200 sw \$v0,-128\(\$sp\)
+ 53e: f71f d200 sw \$v0,-256\(\$sp\)
+ 542: f61f d200 sw \$v0,-512\(\$sp\)
+ 546: f41f d200 sw \$v0,-1024\(\$sp\)
+ 54a: f01f d200 sw \$v0,-2048\(\$sp\)
+ 54e: 6200 sw \$ra,0\(\$sp\)
+ 550: f000 6201 sw \$ra,1\(\$sp\)
+ 554: f000 6202 sw \$ra,2\(\$sp\)
+ 558: f000 6203 sw \$ra,3\(\$sp\)
+ 55c: 6201 sw \$ra,4\(\$sp\)
+ 55e: 6202 sw \$ra,8\(\$sp\)
+ 560: 6204 sw \$ra,16\(\$sp\)
+ 562: 6208 sw \$ra,32\(\$sp\)
+ 564: 6210 sw \$ra,64\(\$sp\)
+ 566: 6220 sw \$ra,128\(\$sp\)
+ 568: 6240 sw \$ra,256\(\$sp\)
+ 56a: 6280 sw \$ra,512\(\$sp\)
+ 56c: f400 6200 sw \$ra,1024\(\$sp\)
+ 570: f001 6200 sw \$ra,2048\(\$sp\)
+ 574: f7ff 621f sw \$ra,-1\(\$sp\)
+ 578: f7ff 621e sw \$ra,-2\(\$sp\)
+ 57c: f7ff 621d sw \$ra,-3\(\$sp\)
+ 580: f7ff 621c sw \$ra,-4\(\$sp\)
+ 584: f7ff 6218 sw \$ra,-8\(\$sp\)
+ 588: f7ff 6210 sw \$ra,-16\(\$sp\)
+ 58c: f7ff 6200 sw \$ra,-32\(\$sp\)
+ 590: f7df 6200 sw \$ra,-64\(\$sp\)
+ 594: f79f 6200 sw \$ra,-128\(\$sp\)
+ 598: f71f 6200 sw \$ra,-256\(\$sp\)
+ 59c: f61f 6200 sw \$ra,-512\(\$sp\)
+ 5a0: f41f 6200 sw \$ra,-1024\(\$sp\)
+ 5a4: f01f 6200 sw \$ra,-2048\(\$sp\)
+ 5a8: cb40 sh \$v0,0\(\$v1\)
+ 5aa: f000 cb41 sh \$v0,1\(\$v1\)
+ 5ae: cb41 sh \$v0,2\(\$v1\)
+ 5b0: f000 cb43 sh \$v0,3\(\$v1\)
+ 5b4: cb42 sh \$v0,4\(\$v1\)
+ 5b6: cb44 sh \$v0,8\(\$v1\)
+ 5b8: cb48 sh \$v0,16\(\$v1\)
+ 5ba: cb50 sh \$v0,32\(\$v1\)
+ 5bc: f040 cb40 sh \$v0,64\(\$v1\)
+ 5c0: f080 cb40 sh \$v0,128\(\$v1\)
+ 5c4: f100 cb40 sh \$v0,256\(\$v1\)
+ 5c8: f200 cb40 sh \$v0,512\(\$v1\)
+ 5cc: f400 cb40 sh \$v0,1024\(\$v1\)
+ 5d0: f001 cb40 sh \$v0,2048\(\$v1\)
+ 5d4: f7ff cb5f sh \$v0,-1\(\$v1\)
+ 5d8: f7ff cb5e sh \$v0,-2\(\$v1\)
+ 5dc: f7ff cb5d sh \$v0,-3\(\$v1\)
+ 5e0: f7ff cb5c sh \$v0,-4\(\$v1\)
+ 5e4: f7ff cb58 sh \$v0,-8\(\$v1\)
+ 5e8: f7ff cb50 sh \$v0,-16\(\$v1\)
+ 5ec: f7ff cb40 sh \$v0,-32\(\$v1\)
+ 5f0: f7df cb40 sh \$v0,-64\(\$v1\)
+ 5f4: f79f cb40 sh \$v0,-128\(\$v1\)
+ 5f8: f71f cb40 sh \$v0,-256\(\$v1\)
+ 5fc: f61f cb40 sh \$v0,-512\(\$v1\)
+ 600: f41f cb40 sh \$v0,-1024\(\$v1\)
+ 604: f01f cb40 sh \$v0,-2048\(\$v1\)
+ 608: c340 sb \$v0,0\(\$v1\)
+ 60a: c341 sb \$v0,1\(\$v1\)
+ 60c: c342 sb \$v0,2\(\$v1\)
+ 60e: c343 sb \$v0,3\(\$v1\)
+ 610: c344 sb \$v0,4\(\$v1\)
+ 612: c348 sb \$v0,8\(\$v1\)
+ 614: c350 sb \$v0,16\(\$v1\)
+ 616: f020 c340 sb \$v0,32\(\$v1\)
+ 61a: f040 c340 sb \$v0,64\(\$v1\)
+ 61e: f080 c340 sb \$v0,128\(\$v1\)
+ 622: f100 c340 sb \$v0,256\(\$v1\)
+ 626: f200 c340 sb \$v0,512\(\$v1\)
+ 62a: f400 c340 sb \$v0,1024\(\$v1\)
+ 62e: f001 c340 sb \$v0,2048\(\$v1\)
+ 632: f7ff c35f sb \$v0,-1\(\$v1\)
+ 636: f7ff c35e sb \$v0,-2\(\$v1\)
+ 63a: f7ff c35d sb \$v0,-3\(\$v1\)
+ 63e: f7ff c35c sb \$v0,-4\(\$v1\)
+ 642: f7ff c358 sb \$v0,-8\(\$v1\)
+ 646: f7ff c350 sb \$v0,-16\(\$v1\)
+ 64a: f7ff c340 sb \$v0,-32\(\$v1\)
+ 64e: f7df c340 sb \$v0,-64\(\$v1\)
+ 652: f79f c340 sb \$v0,-128\(\$v1\)
+ 656: f71f c340 sb \$v0,-256\(\$v1\)
+ 65a: f61f c340 sb \$v0,-512\(\$v1\)
+ 65e: f41f c340 sb \$v0,-1024\(\$v1\)
+ 662: f01f c340 sb \$v0,-2048\(\$v1\)
+ 666: 6a00 li \$v0,0
+ 668: 6a01 li \$v0,1
+ 66a: f100 6a00 li \$v0,256
+ 66e: 675e move \$v0,\$s8
+ 670: 6592 move \$s4,\$v0
+ 672: 4350 daddiu \$v0,\$v1,0
+ 674: 4351 daddiu \$v0,\$v1,1
+ 676: 435f daddiu \$v0,\$v1,-1
+ 678: f010 4350 daddiu \$v0,\$v1,16
+ 67c: f7ff 4350 daddiu \$v0,\$v1,-16
+ 680: e388 daddu \$v0,\$v1,\$a0
+ 682: fd40 daddiu \$v0,0
+ 684: fd41 daddiu \$v0,1
+ 686: fd5f daddiu \$v0,-1
+ 688: f020 fd40 daddiu \$v0,32
+ 68c: f7ff fd40 daddiu \$v0,-32
+ 690: f080 fd40 daddiu \$v0,128
+ 694: f79f fd40 daddiu \$v0,-128
+ 698: f17f fe48 dla \$v0,0 <data1>
+ 69c: f080 fe40 dla \$v0,71c <data2>
+ 6a0: f1c0 fe48 dla \$v0,868 <bar>
+ 6a4: f280 fe4c dla \$v0,930 <quux>
+ 6a8: fb00 daddiu \$sp,0
+ 6aa: f000 fb01 daddiu \$sp,1
+ 6ae: f7ff fb1f daddiu \$sp,-1
+ 6b2: fb20 daddiu \$sp,256
+ 6b4: fbe0 daddiu \$sp,-256
+ 6b6: ff40 daddiu \$v0,\$sp,0
+ 6b8: f000 ff41 daddiu \$v0,\$sp,1
+ 6bc: f7ff ff5f daddiu \$v0,\$sp,-1
+ 6c0: ff48 daddiu \$v0,\$sp,32
+ 6c2: f7ff ff40 daddiu \$v0,\$sp,-32
+ 6c6: f080 ff40 daddiu \$v0,\$sp,128
+ 6ca: f79f ff40 daddiu \$v0,\$sp,-128
+ 6ce: 4340 addiu \$v0,\$v1,0
+ 6d0: 4341 addiu \$v0,\$v1,1
+ 6d2: 434f addiu \$v0,\$v1,-1
+ 6d4: f010 4340 addiu \$v0,\$v1,16
+ 6d8: f7ff 4340 addiu \$v0,\$v1,-16
+ 6dc: e389 addu \$v0,\$v1,\$a0
+ 6de: 4a00 addiu \$v0,0
+ 6e0: 4a01 addiu \$v0,1
+ 6e2: 4aff addiu \$v0,-1
+ 6e4: 4a20 addiu \$v0,32
+ 6e6: 4ae0 addiu \$v0,-32
+ 6e8: f080 4a00 addiu \$v0,128
+ 6ec: 4a80 addiu \$v0,-128
+ 6ee: f11f 0a14 la \$v0,0 <data1>
+ 6f2: 0a0b la \$v0,71c <data2>
+ 6f4: 0a5d la \$v0,868 <bar>
+ 6f6: 0a8f la \$v0,930 <quux>
+ 6f8: 6300 addiu \$sp,0
+ 6fa: f000 6301 addiu \$sp,1
+ 6fe: f7ff 631f addiu \$sp,-1
+ 702: 6320 addiu \$sp,256
+ 704: 63e0 addiu \$sp,-256
+ 706: 0200 addiu \$v0,\$sp,0
+ 708: f000 0201 addiu \$v0,\$sp,1
+ 70c: f7ff 021f addiu \$v0,\$sp,-1
+ 710: 0208 addiu \$v0,\$sp,32
+ 712: f7ff 0200 addiu \$v0,\$sp,-32
+ 716: 0220 addiu \$v0,\$sp,128
+ 718: f79f 0200 addiu \$v0,\$sp,-128
+
+0+00071c <data2>:
+ 71c: 00000000 nop
+
+0+000720 <insns2>:
+ 720: e38a dsubu \$v0,\$v1,\$a0
+ 722: e38b subu \$v0,\$v1,\$a0
+ 724: ea6b neg \$v0,\$v1
+ 726: ea6c and \$v0,\$v1
+ 728: ea6d or \$v0,\$v1
+ 72a: ea6e xor \$v0,\$v1
+ 72c: ea6f not \$v0,\$v1
+ 72e: 5200 slti \$v0,0
+ 730: 5201 slti \$v0,1
+ 732: f7ff 521f slti \$v0,-1
+ 736: 52ff slti \$v0,255
+ 738: f100 5200 slti \$v0,256
+ 73c: ea62 slt \$v0,\$v1
+ 73e: 5a00 sltiu \$v0,0
+ 740: 5a01 sltiu \$v0,1
+ 742: f7ff 5a1f sltiu \$v0,-1
+ 746: 5aff sltiu \$v0,255
+ 748: f100 5a00 sltiu \$v0,256
+ 74c: ea63 sltu \$v0,\$v1
+ 74e: 7200 cmpi \$v0,0
+ 750: 7201 cmpi \$v0,1
+ 752: 72ff cmpi \$v0,255
+ 754: f100 7200 cmpi \$v0,256
+ 758: ea6a cmp \$v0,\$v1
+ 75a: f000 3261 dsll \$v0,\$v1,0
+ 75e: 3265 dsll \$v0,\$v1,1
+ 760: 3261 dsll \$v0,\$v1,8
+ 762: f240 3261 dsll \$v0,\$v1,9
+ 766: f7e0 3261 dsll \$v0,\$v1,63
+ 76a: eb54 dsllv \$v0,\$v1
+ 76c: f000 e848 dsrl \$v0,0
+ 770: e948 dsrl \$v0,1
+ 772: e848 dsrl \$v0,8
+ 774: f240 e848 dsrl \$v0,9
+ 778: f7e0 e848 dsrl \$v0,63
+ 77c: eb56 dsrlv \$v0,\$v1
+ 77e: f000 e853 dsra \$v0,0
+ 782: e953 dsra \$v0,1
+ 784: e853 dsra \$v0,8
+ 786: f240 e853 dsra \$v0,9
+ 78a: f7e0 e853 dsra \$v0,63
+ 78e: eb57 dsrav \$v0,\$v1
+ 790: ea12 mflo \$v0
+ 792: eb10 mfhi \$v1
+ 794: f000 3260 sll \$v0,\$v1,0
+ 798: 3264 sll \$v0,\$v1,1
+ 79a: 3260 sll \$v0,\$v1,8
+ 79c: f240 3260 sll \$v0,\$v1,9
+ 7a0: f7c0 3260 sll \$v0,\$v1,31
+ 7a4: eb44 sllv \$v0,\$v1
+ 7a6: f000 3262 srl \$v0,\$v1,0
+ 7aa: 3266 srl \$v0,\$v1,1
+ 7ac: 3262 srl \$v0,\$v1,8
+ 7ae: f240 3262 srl \$v0,\$v1,9
+ 7b2: f7c0 3262 srl \$v0,\$v1,31
+ 7b6: eb46 srlv \$v0,\$v1
+ 7b8: f000 3263 sra \$v0,\$v1,0
+ 7bc: 3267 sra \$v0,\$v1,1
+ 7be: 3263 sra \$v0,\$v1,8
+ 7c0: f240 3263 sra \$v0,\$v1,9
+ 7c4: f7c0 3263 sra \$v0,\$v1,31
+ 7c8: eb47 srav \$v0,\$v1
+ 7ca: ea7c dmult \$v0,\$v1
+ 7cc: ea7d dmultu \$v0,\$v1
+ 7ce: ea7e ddiv \$zero,\$v0,\$v1
+ 7d0: 2b01 bnez \$v1,7d4 <insns2\+(0x|)b4>
+ 7d2: e8e5 break 7
+ 7d4: ea12 mflo \$v0
+ 7d6: 6500 nop
+ 7d8: 6500 nop
+ 7da: ea7f ddivu \$zero,\$v0,\$v1
+ 7dc: 2b01 bnez \$v1,7e0 <insns2\+(0x|)c0>
+ 7de: e8e5 break 7
+ 7e0: ea12 mflo \$v0
+ 7e2: 6500 nop
+ 7e4: 6500 nop
+ 7e6: ea78 mult \$v0,\$v1
+ 7e8: ea79 multu \$v0,\$v1
+ 7ea: ea7a div \$zero,\$v0,\$v1
+ 7ec: 2b01 bnez \$v1,7f0 <insns2\+(0x|)d0>
+ 7ee: e8e5 break 7
+ 7f0: ea12 mflo \$v0
+ 7f2: 6500 nop
+ 7f4: 6500 nop
+ 7f6: ea7b divu \$zero,\$v0,\$v1
+ 7f8: 2b01 bnez \$v1,7fc <insns2\+(0x|)dc>
+ 7fa: e8e5 break 7
+ 7fc: ea12 mflo \$v0
+ 7fe: ea00 jr \$v0
+ 800: 6500 nop
+ 802: e820 jr \$ra
+ 804: 6500 nop
+ 806: ea40 jalr \$v0
+ 808: 6500 nop
+ 80a: f3ff 221b beqz \$v0,4 <insns1>
+ 80e: 2288 beqz \$v0,720 <insns2>
+ 810: 222b beqz \$v0,868 <bar>
+ 812: f080 220d beqz \$v0,930 <quux>
+ 816: f3ff 2a15 bnez \$v0,4 <insns1>
+ 81a: 2a82 bnez \$v0,720 <insns2>
+ 81c: 2a25 bnez \$v0,868 <bar>
+ 81e: f080 2a07 bnez \$v0,930 <quux>
+ 822: f3ff 600f bteqz 4 <insns1>
+ 826: f77f 601b bteqz 720 <insns2>
+ 82a: 601e bteqz 868 <bar>
+ 82c: f080 6000 bteqz 930 <quux>
+ 830: f3ff 6108 btnez 4 <insns1>
+ 834: f77f 6114 btnez 720 <insns2>
+ 838: 6117 btnez 868 <bar>
+ 83a: 617a btnez 930 <quux>
+ 83c: f3ff 1002 b 4 <insns1>
+ 840: 176f b 720 <insns2>
+ 842: 1012 b 868 <bar>
+ 844: 1075 b 930 <quux>
+ 846: e805 break 0
+ 848: e825 break 1
+ 84a: efe5 break 63
+ 84c: 1800 0000 jal 0 <data1>
+ 84c: R_MIPS16_26 extern
+ 850: 6500 nop
+ 852: e809 entry
+ 854: e909 entry \$a0
+ 856: eb49 entry \$a0-\$a2,\$s0
+ 858: e8a9 entry \$s0-\$s1,\$ra
+ 85a: e829 entry \$ra
+ 85c: ef09 exit
+ 85e: ef49 exit \$s0
+ 860: efa9 exit \$s0-\$s1,\$ra
+ 862: ef29 exit \$ra
+ 864: 0000 addiu \$s0,\$sp,0
+ ...
+
+0+000868 <bar>:
+ ...
diff --git a/gas/testsuite/gas/mips/mips16.s b/gas/testsuite/gas/mips/mips16.s
new file mode 100644
index 0000000000..6268fb1650
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips16.s
@@ -0,0 +1,258 @@
+# Test the mips16 instruction set.
+
+ .set mips16
+
+ .macro ldst op, reg, base
+ \op \reg,0(\base)
+ \op \reg,1(\base)
+ \op \reg,2(\base)
+ \op \reg,3(\base)
+ \op \reg,4(\base)
+ \op \reg,8(\base)
+ \op \reg,16(\base)
+ \op \reg,32(\base)
+ \op \reg,64(\base)
+ \op \reg,128(\base)
+ \op \reg,256(\base)
+ \op \reg,512(\base)
+ \op \reg,1024(\base)
+ \op \reg,2048(\base)
+ \op \reg,-1(\base)
+ \op \reg,-2(\base)
+ \op \reg,-3(\base)
+ \op \reg,-4(\base)
+ \op \reg,-8(\base)
+ \op \reg,-16(\base)
+ \op \reg,-32(\base)
+ \op \reg,-64(\base)
+ \op \reg,-128(\base)
+ \op \reg,-256(\base)
+ \op \reg,-512(\base)
+ \op \reg,-1024(\base)
+ \op \reg,-2048(\base)
+ .endm
+
+ .p2align 3
+data1:
+ .word 0
+insns1:
+ ldst ld, $2, $3
+ ld $2,data1
+ ld $2,data2
+ ld $2,bar
+ ld $2,quux
+ ldst ld, $2, $sp
+ ldst lwu, $2, $3
+ ldst lw, $2, $3
+ lw $2,data1
+ lw $2,data2
+ lw $2,bar
+ lw $2,quux
+ ldst lw, $2, $sp
+ ldst lh, $2, $3
+ ldst lhu, $2, $3
+ ldst lb, $2, $3
+ ldst lbu, $2, $3
+ ldst sd, $2, $3
+ ldst sd, $2, $sp
+ ldst sd, $31, $sp
+ ldst sw, $2, $3
+ ldst sw, $2, $sp
+ ldst sw, $31, $sp
+ ldst sh, $2, $3
+ ldst sb, $2, $3
+
+ li $2,0
+ li $2,1
+ li $2,256
+
+ move $2,$30
+ move $20,$2
+
+ daddu $2,$3,0
+ daddu $2,$3,1
+ daddu $2,$3,-1
+ daddu $2,$3,16
+ daddu $2,$3,-16
+ daddu $2,$3,$4
+ daddu $2,0
+ daddu $2,1
+ daddu $2,-1
+ daddu $2,32
+ daddu $2,-32
+ daddu $2,128
+ daddu $2,-128
+ dla $2,data1
+ dla $2,data2
+ dla $2,bar
+ dla $2,quux
+ daddu $sp,0
+ daddu $sp,1
+ daddu $sp,-1
+ daddu $sp,256
+ daddu $sp,-256
+ daddu $2,$sp,0
+ daddu $2,$sp,1
+ daddu $2,$sp,-1
+ daddu $2,$sp,32
+ daddu $2,$sp,-32
+ daddu $2,$sp,128
+ daddu $2,$sp,-128
+
+ addu $2,$3,0
+ addu $2,$3,1
+ addu $2,$3,-1
+ addu $2,$3,16
+ addu $2,$3,-16
+ addu $2,$3,$4
+ addu $2,0
+ addu $2,1
+ addu $2,-1
+ addu $2,32
+ addu $2,-32
+ addu $2,128
+ addu $2,-128
+ la $2,data1
+ la $2,data2
+ la $2,bar
+ la $2,quux
+ addu $sp,0
+ addu $sp,1
+ addu $sp,-1
+ addu $sp,256
+ addu $sp,-256
+ addu $2,$sp,0
+ addu $2,$sp,1
+ addu $2,$sp,-1
+ addu $2,$sp,32
+ addu $2,$sp,-32
+ addu $2,$sp,128
+ addu $2,$sp,-128
+
+data2:
+ .word 0
+insns2:
+ dsubu $2,$3,$4
+ subu $2,$3,$4
+ neg $2,$3
+
+ and $2,$3
+ or $2,$3
+ xor $2,$3
+ not $2,$3
+
+ slt $2,0
+ slt $2,1
+ slt $2,-1
+ slt $2,255
+ slt $2,256
+ slt $2,$3
+ sltu $2,0
+ sltu $2,1
+ sltu $2,-1
+ sltu $2,255
+ sltu $2,256
+ sltu $2,$3
+ cmp $2,0
+ cmp $2,1
+ cmp $2,255
+ cmp $2,256
+ cmp $2,$3
+
+ dsll $2,$3,0
+ dsll $2,$3,1
+ dsll $2,$3,8
+ dsll $2,$3,9
+ dsll $2,$3,63
+ dsll $2,$3
+ dsrl $2,0
+ dsrl $2,1
+ dsrl $2,8
+ dsrl $2,9
+ dsrl $2,63
+ dsrl $2,$3
+ dsra $2,0
+ dsra $2,1
+ dsra $2,8
+ dsra $2,9
+ dsra $2,63
+ dsra $2,$3
+
+ mflo $2
+ mfhi $3
+
+ sll $2,$3,0
+ sll $2,$3,1
+ sll $2,$3,8
+ sll $2,$3,9
+ sll $2,$3,31
+ sll $2,$3
+ srl $2,$3,0
+ srl $2,$3,1
+ srl $2,$3,8
+ srl $2,$3,9
+ srl $2,$3,31
+ srl $2,$3
+ sra $2,$3,0
+ sra $2,$3,1
+ sra $2,$3,8
+ sra $2,$3,9
+ sra $2,$3,31
+ sra $2,$3
+
+ dmult $2,$3
+ dmultu $2,$3
+ ddiv $2,$3
+ ddivu $2,$3
+
+ mult $2,$3
+ multu $2,$3
+ div $2,$3
+ divu $2,$3
+
+ jr $2
+ jr $31
+ jalr $31,$2
+
+ beqz $2,insns1
+ beqz $2,insns2
+ beqz $2,bar
+ beqz $2,quux
+ bnez $2,insns1
+ bnez $2,insns2
+ bnez $2,bar
+ bnez $2,quux
+ bteqz insns1
+ bteqz insns2
+ bteqz bar
+ bteqz quux
+ btnez insns1
+ btnez insns2
+ btnez bar
+ btnez quux
+ b insns1
+ b insns2
+ b bar
+ b quux
+
+ break 0
+ break 1
+ break 63
+
+ jal extern
+
+ entry
+ entry $4
+ entry $4-$6,$16
+ entry $16-$17,$31
+ entry $31
+ exit
+ exit $16
+ exit $16-$17,$31
+ exit $31
+
+ .p2align 3
+bar:
+
+ .skip 200
+quux:
diff --git a/gas/testsuite/gas/mips/mips4.d b/gas/testsuite/gas/mips/mips4.d
new file mode 100644
index 0000000000..956de93f3d
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips4.d
@@ -0,0 +1,51 @@
+#objdump: -dr --prefix-addresses -mmips:5000
+#name: MIPS mips4
+#as: -mips4 -mcpu=r5000
+
+# Test the mips4 macros.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> bc1f 00000000+ <text_label>
+0+0004 <[^>]*> nop
+0+0008 <[^>]*> bc1f \$fcc1,00000000+ <text_label>
+0+000c <[^>]*> nop
+0+0010 <[^>]*> bc1fl \$fcc1,00000000+ <text_label>
+0+0014 <[^>]*> nop
+0+0018 <[^>]*> bc1t \$fcc1,00000000+ <text_label>
+0+001c <[^>]*> nop
+0+0020 <[^>]*> bc1tl \$fcc2,00000000+ <text_label>
+0+0024 <[^>]*> nop
+0+0028 <[^>]*> c.f.d \$f4,\$f6
+0+002c <[^>]*> c.f.d \$fcc1,\$f4,\$f6
+0+0030 <[^>]*> ldxc1 \$f2,\$a0\(\$a1\)
+0+0034 <[^>]*> lwxc1 \$f2,\$a0\(\$a1\)
+0+0038 <[^>]*> madd.d \$f0,\$f2,\$f4,\$f6
+0+003c <[^>]*> madd.s \$f0,\$f2,\$f4,\$f6
+0+0040 <[^>]*> movf \$a0,\$a1,\$fcc4
+0+0044 <[^>]*> movf.d \$f4,\$f6,\$fcc0
+0+0048 <[^>]*> movf.s \$f4,\$f6,\$fcc0
+0+004c <[^>]*> movn \$a0,\$a2,\$a2
+0+0050 <[^>]*> movn.d \$f4,\$f5,\$a2
+0+0054 <[^>]*> movn.s \$f4,\$f5,\$a2
+0+0058 <[^>]*> movt \$a0,\$a1,\$fcc4
+0+005c <[^>]*> movt.d \$f4,\$f6,\$fcc0
+0+0060 <[^>]*> movt.s \$f4,\$f6,\$fcc0
+0+0064 <[^>]*> movz \$a0,\$a2,\$a2
+0+0068 <[^>]*> movz.d \$f4,\$f5,\$a2
+0+006c <[^>]*> movz.s \$f4,\$f5,\$a2
+0+0070 <[^>]*> msub.d \$f0,\$f2,\$f4,\$f6
+0+0074 <[^>]*> msub.s \$f0,\$f2,\$f4,\$f6
+0+0078 <[^>]*> nmadd.d \$f0,\$f2,\$f4,\$f6
+0+007c <[^>]*> nmadd.s \$f0,\$f2,\$f4,\$f6
+0+0080 <[^>]*> nmsub.d \$f0,\$f2,\$f4,\$f6
+0+0084 <[^>]*> nmsub.s \$f0,\$f2,\$f4,\$f6
+0+0088 <[^>]*> prefx 0x4,\$a0\(\$a1\)
+0+008c <[^>]*> recip.d \$f4,\$f6
+0+0090 <[^>]*> recip.s \$f4,\$f6
+0+0094 <[^>]*> rsqrt.d \$f4,\$f6
+0+0098 <[^>]*> rsqrt.s \$f4,\$f6
+0+009c <[^>]*> sdxc1 \$f4,\$a0\(\$a1\)
+0+00a0 <[^>]*> swxc1 \$f4,\$a0\(\$a1\)
+ ...
diff --git a/gas/testsuite/gas/mips/mips4.s b/gas/testsuite/gas/mips/mips4.s
new file mode 100644
index 0000000000..bf8b943303
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips4.s
@@ -0,0 +1,52 @@
+# Source file used to test -mips4 instructions.
+
+text_label:
+ bc1f text_label
+ bc1f $fcc1,text_label
+ bc1fl $fcc1,text_label
+ bc1t $fcc1,text_label
+ bc1tl $fcc2,text_label
+ c.f.d $f4,$f6
+ c.f.d $fcc1,$f4,$f6
+ ldxc1 $f2,$4($5)
+ lwxc1 $f2,$4($5)
+ madd.d $f0,$f2,$f4,$f6
+ madd.s $f0,$f2,$f4,$f6
+ movf $4,$5,$fcc4
+ movf.d $f4,$f6,$fcc0
+ movf.s $f4,$f6,$fcc0
+ movn $4,$6,$6
+ movn.d $f4,$f5,$6
+ movn.s $f4,$f5,$6
+ movt $4,$5,$fcc4
+ movt.d $f4,$f6,$fcc0
+ movt.s $f4,$f6,$fcc0
+ movz $4,$6,$6
+ movz.d $f4,$f5,$6
+ movz.s $f4,$f5,$6
+ msub.d $f0,$f2,$f4,$f6
+ msub.s $f0,$f2,$f4,$f6
+ nmadd.d $f0,$f2,$f4,$f6
+ nmadd.s $f0,$f2,$f4,$f6
+ nmsub.d $f0,$f2,$f4,$f6
+ nmsub.s $f0,$f2,$f4,$f6
+
+ # We don't test pref because currently the disassembler will
+ # disassemble it as lwc3. lwc3 is correct for mips1 to mips3,
+ # while pref is correct for mips4. Unfortunately, the
+ # disassembler does not know which architecture it is
+ # disassembling for.
+ # pref 4,0($4)
+
+ prefx 4,$4($5)
+ recip.d $f4,$f6
+ recip.s $f4,$f6
+ rsqrt.d $f4,$f6
+ rsqrt.s $f4,$f6
+ sdxc1 $f4,$4($5)
+ swxc1 $f4,$4($5)
+
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+ nop
+ nop
+ nop
diff --git a/gas/testsuite/gas/mips/mips4010.d b/gas/testsuite/gas/mips/mips4010.d
new file mode 100644
index 0000000000..77de196df8
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips4010.d
@@ -0,0 +1,23 @@
+#objdump: -dr --prefix-addresses -mmips:4010
+#name: MIPS 4010
+#as: -mcpu=4010
+
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+0+0000 <stuff> flushi
+0+0004 <stuff\+0x4> flushd
+0+0008 <stuff\+0x8> flushid
+0+000c <stuff\+0xc> madd \$a0,\$a1
+0+0010 <stuff\+0x10> maddu \$a1,\$a2
+0+0014 <stuff\+0x14> ffc \$a2,\$a3
+0+0018 <stuff\+0x18> ffs \$a3,\$t0
+0+001c <stuff\+0x1c> msub \$t0,\$t1
+0+0020 <stuff\+0x20> msubu \$t1,\$t2
+0+0024 <stuff\+0x24> selsl \$t2,\$t3,\$t4
+0+0028 <stuff\+0x28> selsr \$t3,\$t4,\$t5
+0+002c <stuff\+0x2c> waiti
+0+0030 <stuff\+0x30> wb 16\(\$t6\)
+0+0034 <stuff\+0x34> addciu \$t6,\$t7,16
+ ...
diff --git a/gas/testsuite/gas/mips/mips4010.s b/gas/testsuite/gas/mips/mips4010.s
new file mode 100644
index 0000000000..e8d6e25544
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips4010.s
@@ -0,0 +1,20 @@
+ .text
+
+stuff:
+ .ent stuff
+ flushi
+ flushd
+ flushid
+ madd $4,$5
+ maddu $5,$6
+ ffc $6,$7
+ ffs $7,$8
+ msub $8,$9
+ msubu $9,$10
+ selsl $10,$11,$12
+ selsr $11,$12,$13
+ waiti
+ wb 16($14)
+ addciu $14,$15,16
+ nop
+ nop
diff --git a/gas/testsuite/gas/mips/mips4100.d b/gas/testsuite/gas/mips/mips4100.d
new file mode 100644
index 0000000000..ef84f12058
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips4100.d
@@ -0,0 +1,15 @@
+#objdump: -dr --prefix-addresses -mmips:4100
+#name: MIPS 4100
+#as: -mcpu=4100
+
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+0+0000 <stuff> dmadd16 \$a0,\$a1
+ ...
+0+000c <stuff\+0xc> madd16 \$a1,\$a2
+0+0010 <stuff\+0x10> hibernate
+0+0014 <stuff\+0x14> standby
+0+0018 <stuff\+0x18> suspend
+0+001c <stuff\+0x1c> nop
diff --git a/gas/testsuite/gas/mips/mips4100.s b/gas/testsuite/gas/mips/mips4100.s
new file mode 100644
index 0000000000..ca20e0e978
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips4100.s
@@ -0,0 +1,10 @@
+ .text
+
+stuff:
+ .ent stuff
+ dmadd16 $4,$5
+ madd16 $5,$6
+ hibernate
+ standby
+ suspend
+ nop
diff --git a/gas/testsuite/gas/mips/mips4650.d b/gas/testsuite/gas/mips/mips4650.d
new file mode 100644
index 0000000000..5e642a6a83
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips4650.d
@@ -0,0 +1,14 @@
+#objdump: -dr --prefix-addresses -mmips:4650
+#name: MIPS 4650
+#as: -mcpu=4650
+
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+0+0000 <stuff> mad \$a0,\$a1
+ ...
+0+000c <stuff\+0xc> madu \$a1,\$a2
+ ...
+0+0018 <stuff\+0x18> mul \$a2,\$a3,\$t0
+0+001c <stuff\+0x1c> nop
diff --git a/gas/testsuite/gas/mips/mips4650.s b/gas/testsuite/gas/mips/mips4650.s
new file mode 100644
index 0000000000..52c22a16f3
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips4650.s
@@ -0,0 +1,8 @@
+ .text
+
+stuff:
+ .ent stuff
+ mad $4,$5
+ madu $5,$6
+ mul $6,$7,$8
+ nop
diff --git a/gas/testsuite/gas/mips/mul-ilocks.d b/gas/testsuite/gas/mips/mul-ilocks.d
new file mode 100644
index 0000000000..061ed2ee5b
--- /dev/null
+++ b/gas/testsuite/gas/mips/mul-ilocks.d
@@ -0,0 +1,81 @@
+#objdump: -dr --prefix-addresses
+#name: MIPS mul-ilocks
+#as:
+#source: mul.s
+
+# Test the mul macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> multu \$a0,\$a1
+0+0004 <[^>]*> mflo \$a0
+0+0008 <[^>]*> multu \$a1,\$a2
+0+000c <[^>]*> mflo \$a0
+0+0010 <[^>]*> li \$at,0
+0+0014 <[^>]*> mult \$a1,\$at
+0+0018 <[^>]*> mflo \$a0
+0+001c <[^>]*> li \$at,1
+0+0020 <[^>]*> mult \$a1,\$at
+0+0024 <[^>]*> mflo \$a0
+0+0028 <[^>]*> li \$at,0x8000
+0+002c <[^>]*> mult \$a1,\$at
+0+0030 <[^>]*> mflo \$a0
+0+0034 <[^>]*> li \$at,-32768
+0+0038 <[^>]*> mult \$a1,\$at
+0+003c <[^>]*> mflo \$a0
+0+0040 <[^>]*> lui \$at,0x1
+0+0044 <[^>]*> mult \$a1,\$at
+0+0048 <[^>]*> mflo \$a0
+0+004c <[^>]*> lui \$at,0x1
+0+0050 <[^>]*> ori \$at,\$at,0xa5a5
+0+0054 <[^>]*> mult \$a1,\$at
+0+0058 <[^>]*> mflo \$a0
+0+005c <[^>]*> mult \$a0,\$a1
+0+0060 <[^>]*> mflo \$a0
+0+0064 <[^>]*> sra \$a0,\$a0,0x1f
+0+0068 <[^>]*> mfhi \$at
+0+006c <[^>]*> beq \$a0,\$at,0+78 <foo\+(0x|)78>
+0+0070 <[^>]*> nop
+0+0074 <[^>]*> break (0x0,0x6|0x6)
+0+0078 <[^>]*> mflo \$a0
+0+007c <[^>]*> mult \$a1,\$a2
+0+0080 <[^>]*> mflo \$a0
+0+0084 <[^>]*> sra \$a0,\$a0,0x1f
+0+0088 <[^>]*> mfhi \$at
+0+008c <[^>]*> beq \$a0,\$at,0+98 <foo\+(0x|)98>
+0+0090 <[^>]*> nop
+0+0094 <[^>]*> break (0x0,0x6|0x6)
+0+0098 <[^>]*> mflo \$a0
+0+009c <[^>]*> multu \$a0,\$a1
+0+00a0 <[^>]*> mfhi \$at
+0+00a4 <[^>]*> mflo \$a0
+0+00a8 <[^>]*> beqz \$at,0+b4 <foo\+(0x|)b4>
+0+00ac <[^>]*> nop
+0+00b0 <[^>]*> break (0x0,0x6|0x6)
+0+00b4 <[^>]*> multu \$a1,\$a2
+0+00b8 <[^>]*> mfhi \$at
+0+00bc <[^>]*> mflo \$a0
+0+00c0 <[^>]*> beqz \$at,0+cc <foo\+(0x|)cc>
+0+00c4 <[^>]*> nop
+0+00c8 <[^>]*> break (0x0,0x6|0x6)
+0+00cc <[^>]*> dmultu \$a1,\$a2
+0+00d0 <[^>]*> mflo \$a0
+0+00d4 <[^>]*> li \$at,1
+0+00d8 <[^>]*> dmult \$a1,\$at
+0+00dc <[^>]*> mflo \$a0
+0+00e0 <[^>]*> dmult \$a1,\$a2
+0+00e4 <[^>]*> mflo \$a0
+0+00e8 <[^>]*> dsra32 \$a0,\$a0,0x1f
+0+00ec <[^>]*> mfhi \$at
+0+00f0 <[^>]*> beq \$a0,\$at,0+fc <foo\+(0x|)fc>
+0+00f4 <[^>]*> nop
+0+00f8 <[^>]*> break (0x0,0x6|0x6)
+0+00fc <[^>]*> mflo \$a0
+0+0100 <[^>]*> dmultu \$a1,\$a2
+0+0104 <[^>]*> mfhi \$at
+0+0108 <[^>]*> mflo \$a0
+0+010c <[^>]*> beqz \$at,0+118 <foo\+(0x|)118>
+0+0110 <[^>]*> nop
+0+0114 <[^>]*> break (0x0,0x6|0x6)
+ ...
diff --git a/gas/testsuite/gas/mips/mul.d b/gas/testsuite/gas/mips/mul.d
new file mode 100644
index 0000000000..92b6265242
--- /dev/null
+++ b/gas/testsuite/gas/mips/mul.d
@@ -0,0 +1,92 @@
+#objdump: -dr --prefix-addresses -mmips:4000
+#as: -mcpu=r4000
+#name: MIPS mul
+
+# Test the mul macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> multu \$a0,\$a1
+0+0004 <[^>]*> mflo \$a0
+ ...
+0+0010 <[^>]*> multu \$a1,\$a2
+0+0014 <[^>]*> mflo \$a0
+0+0018 <[^>]*> li \$at,0
+0+001c <[^>]*> nop
+0+0020 <[^>]*> mult \$a1,\$at
+0+0024 <[^>]*> mflo \$a0
+0+0028 <[^>]*> li \$at,1
+0+002c <[^>]*> nop
+0+0030 <[^>]*> mult \$a1,\$at
+0+0034 <[^>]*> mflo \$a0
+0+0038 <[^>]*> li \$at,0x8000
+0+003c <[^>]*> nop
+0+0040 <[^>]*> mult \$a1,\$at
+0+0044 <[^>]*> mflo \$a0
+0+0048 <[^>]*> li \$at,-32768
+0+004c <[^>]*> nop
+0+0050 <[^>]*> mult \$a1,\$at
+0+0054 <[^>]*> mflo \$a0
+0+0058 <[^>]*> lui \$at,0x1
+0+005c <[^>]*> nop
+0+0060 <[^>]*> mult \$a1,\$at
+0+0064 <[^>]*> mflo \$a0
+0+0068 <[^>]*> lui \$at,0x1
+0+006c <[^>]*> ori \$at,\$at,0xa5a5
+0+0070 <[^>]*> mult \$a1,\$at
+0+0074 <[^>]*> mflo \$a0
+ ...
+0+0080 <[^>]*> mult \$a0,\$a1
+0+0084 <[^>]*> mflo \$a0
+0+0088 <[^>]*> sra \$a0,\$a0,0x1f
+0+008c <[^>]*> mfhi \$at
+0+0090 <[^>]*> beq \$a0,\$at,0+9c <foo\+(0x|)9c>
+0+0094 <[^>]*> nop
+0+0098 <[^>]*> break (0x0,0x6|0x6)
+0+009c <[^>]*> mflo \$a0
+ ...
+0+00a8 <[^>]*> mult \$a1,\$a2
+0+00ac <[^>]*> mflo \$a0
+0+00b0 <[^>]*> sra \$a0,\$a0,0x1f
+0+00b4 <[^>]*> mfhi \$at
+0+00b8 <[^>]*> beq \$a0,\$at,0+c4 <foo\+(0x|)c4>
+0+00bc <[^>]*> nop
+0+00c0 <[^>]*> break (0x0,0x6|0x6)
+0+00c4 <[^>]*> mflo \$a0
+ ...
+0+00d0 <[^>]*> multu \$a0,\$a1
+0+00d4 <[^>]*> mfhi \$at
+0+00d8 <[^>]*> mflo \$a0
+0+00dc <[^>]*> beqz \$at,0+e8 <foo\+(0x|)e8>
+0+00e0 <[^>]*> nop
+0+00e4 <[^>]*> break (0x0,0x6|0x6)
+0+00e8 <[^>]*> multu \$a1,\$a2
+0+00ec <[^>]*> mfhi \$at
+0+00f0 <[^>]*> mflo \$a0
+0+00f4 <[^>]*> beqz \$at,0+100 <foo\+(0x|)100>
+0+00f8 <[^>]*> nop
+0+00fc <[^>]*> break (0x0,0x6|0x6)
+0+0100 <[^>]*> dmultu \$a1,\$a2
+0+0104 <[^>]*> mflo \$a0
+0+0108 <[^>]*> li \$at,1
+0+010c <[^>]*> nop
+0+0110 <[^>]*> dmult \$a1,\$at
+0+0114 <[^>]*> mflo \$a0
+ ...
+0+0120 <[^>]*> dmult \$a1,\$a2
+0+0124 <[^>]*> mflo \$a0
+0+0128 <[^>]*> dsra32 \$a0,\$a0,0x1f
+0+012c <[^>]*> mfhi \$at
+0+0130 <[^>]*> beq \$a0,\$at,0+13c <foo\+(0x|)13c>
+0+0134 <[^>]*> nop
+0+0138 <[^>]*> break (0x0,0x6|0x6)
+0+013c <[^>]*> mflo \$a0
+ ...
+0+0148 <[^>]*> dmultu \$a1,\$a2
+0+014c <[^>]*> mfhi \$at
+0+0150 <[^>]*> mflo \$a0
+0+0154 <[^>]*> beqz \$at,0+160 <foo\+(0x|)160>
+0+0158 <[^>]*> nop
+0+015c <[^>]*> break (0x0,0x6|0x6)
+ ...
diff --git a/gas/testsuite/gas/mips/mul.s b/gas/testsuite/gas/mips/mul.s
new file mode 100644
index 0000000000..b29e369f7b
--- /dev/null
+++ b/gas/testsuite/gas/mips/mul.s
@@ -0,0 +1,27 @@
+# Source file used to test the mul macro.
+
+foo:
+ mul $4,$5
+ mul $4,$5,$6
+ mul $4,$5,0
+ mul $4,$5,1
+ mul $4,$5,0x8000
+ mul $4,$5,-0x8000
+ mul $4,$5,0x10000
+ mul $4,$5,0x1a5a5
+
+# mulo and mulou are only supported for register arguments
+ mulo $4,$5
+ mulo $4,$5,$6
+
+ mulou $4,$5
+ mulou $4,$5,$6
+
+# Sanity check the 64 bit versions.
+ .set mips3
+ dmul $4,$5,$6
+ dmul $4,$5,1
+ dmulo $4,$5,$6
+ dmulou $4,$5,$6
+
+ .space 8
diff --git a/gas/testsuite/gas/mips/nodelay.d b/gas/testsuite/gas/mips/nodelay.d
new file mode 100644
index 0000000000..dc930799b8
--- /dev/null
+++ b/gas/testsuite/gas/mips/nodelay.d
@@ -0,0 +1,19 @@
+#objdump: -dr --prefix-addresses -mmips:5000
+#name: MIPS nodelay
+#as: -mips4 -mcpu=r8000
+#source: delay.s
+
+# For -mips4
+# Gas should *not* produce nop's after mtc1 and related
+# insn's if the target fpr is used in the immediatly
+# following insn. See also delay.d.
+#
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> mtc1 \$zero,\$f0
+0+0004 <[^>]*> cvt.d.w \$f0,\$f0
+0+0008 <[^>]*> mtc1 \$zero,\$f1
+0+000c <[^>]*> cvt.d.w \$f1,\$f1
+ ...
diff --git a/gas/testsuite/gas/mips/rol.d b/gas/testsuite/gas/mips/rol.d
new file mode 100644
index 0000000000..14ce1425d4
--- /dev/null
+++ b/gas/testsuite/gas/mips/rol.d
@@ -0,0 +1,37 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#as: -mcpu=r3000
+#name: MIPS R3000 rol
+
+# Test the rol and ror macros.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> negu \$at,\$a1
+0+0004 <[^>]*> srlv \$at,\$a0,\$at
+0+0008 <[^>]*> sllv \$a0,\$a0,\$a1
+0+000c <[^>]*> or \$a0,\$a0,\$at
+0+0010 <[^>]*> negu \$at,\$a2
+0+0014 <[^>]*> srlv \$at,\$a1,\$at
+0+0018 <[^>]*> sllv \$a0,\$a1,\$a2
+0+001c <[^>]*> or \$a0,\$a0,\$at
+0+0020 <[^>]*> sll \$at,\$a0,0x1
+0+0024 <[^>]*> srl \$a0,\$a0,0x1f
+0+0028 <[^>]*> or \$a0,\$a0,\$at
+0+002c <[^>]*> sll \$at,\$a1,0x1
+0+0030 <[^>]*> srl \$a0,\$a1,0x1f
+0+0034 <[^>]*> or \$a0,\$a0,\$at
+0+0038 <[^>]*> negu \$at,\$a1
+0+003c <[^>]*> sllv \$at,\$a0,\$at
+0+0040 <[^>]*> srlv \$a0,\$a0,\$a1
+0+0044 <[^>]*> or \$a0,\$a0,\$at
+0+0048 <[^>]*> negu \$at,\$a2
+0+004c <[^>]*> sllv \$at,\$a1,\$at
+0+0050 <[^>]*> srlv \$a0,\$a1,\$a2
+0+0054 <[^>]*> or \$a0,\$a0,\$at
+0+0058 <[^>]*> srl \$at,\$a0,0x1
+0+005c <[^>]*> sll \$a0,\$a0,0x1f
+0+0060 <[^>]*> or \$a0,\$a0,\$at
+0+0064 <[^>]*> srl \$at,\$a1,0x1
+0+0068 <[^>]*> sll \$a0,\$a1,0x1f
+0+006c <[^>]*> or \$a0,\$a0,\$at
diff --git a/gas/testsuite/gas/mips/rol.s b/gas/testsuite/gas/mips/rol.s
new file mode 100644
index 0000000000..259a957e80
--- /dev/null
+++ b/gas/testsuite/gas/mips/rol.s
@@ -0,0 +1,12 @@
+# Source file used to test the rol and ror macros.
+
+foo:
+ rol $4,$5
+ rol $4,$5,$6
+ rol $4,1
+ rol $4,$5,1
+
+ ror $4,$5
+ ror $4,$5,$6
+ ror $4,1
+ ror $4,$5,1
diff --git a/gas/testsuite/gas/mips/sb.d b/gas/testsuite/gas/mips/sb.d
new file mode 100644
index 0000000000..0ef4bc12c2
--- /dev/null
+++ b/gas/testsuite/gas/mips/sb.d
@@ -0,0 +1,396 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS sb
+#as: -mips1
+
+# Test the sb macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> sb \$a0,0\(\$zero\)
+0+0004 <[^>]*> sb \$a0,1\(\$zero\)
+0+0008 <[^>]*> lui \$at,0x1
+0+000c <[^>]*> sb \$a0,-32768\(\$at\)
+0+0010 <[^>]*> sb \$a0,-32768\(\$zero\)
+0+0014 <[^>]*> lui \$at,0x1
+0+0018 <[^>]*> sb \$a0,0\(\$at\)
+0+001c <[^>]*> lui \$at,0x2
+0+0020 <[^>]*> sb \$a0,-23131\(\$at\)
+0+0024 <[^>]*> sb \$a0,0\(\$a1\)
+0+0028 <[^>]*> sb \$a0,1\(\$a1\)
+0+002c <[^>]*> lui \$at,0x1
+0+0030 <[^>]*> addu \$at,\$at,\$a1
+0+0034 <[^>]*> sb \$a0,-32768\(\$at\)
+0+0038 <[^>]*> sb \$a0,-32768\(\$a1\)
+0+003c <[^>]*> lui \$at,0x1
+0+0040 <[^>]*> addu \$at,\$at,\$a1
+0+0044 <[^>]*> sb \$a0,0\(\$at\)
+0+0048 <[^>]*> lui \$at,0x2
+0+004c <[^>]*> addu \$at,\$at,\$a1
+0+0050 <[^>]*> sb \$a0,-23131\(\$at\)
+0+0054 <[^>]*> lui \$at,0x0
+[ ]*54: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0058 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*58: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+005c <[^>]*> lui \$at,0x0
+[ ]*5c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0060 <[^>]*> sb \$a0,0\(\$at\)
+[ ]*60: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0064 <[^>]*> sb \$a0,0\(\$gp\)
+[ ]*64: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+0068 <[^>]*> lui \$at,0x0
+[ ]*68: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+006c <[^>]*> sb \$a0,0\(\$at\)
+[ ]*6c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0070 <[^>]*> sb \$a0,0\(\$gp\)
+[ ]*70: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+0074 <[^>]*> lui \$at,0x0
+[ ]*74: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0078 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*78: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+007c <[^>]*> sb \$a0,[-0-9]+\(\$gp\)
+[ ]*7c: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0080 <[^>]*> lui \$at,0x0
+[ ]*80: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0084 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*84: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0088 <[^>]*> lui \$at,0x0
+[ ]*88: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+008c <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*8c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0090 <[^>]*> sb \$a0,1\(\$gp\)
+[ ]*90: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+0094 <[^>]*> lui \$at,0x0
+[ ]*94: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0098 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*98: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+009c <[^>]*> sb \$a0,1\(\$gp\)
+[ ]*9c: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+00a0 <[^>]*> lui \$at,0x0
+[ ]*a0: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+00a4 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*a4: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+00a8 <[^>]*> sb \$a0,[-0-9]+\(\$gp\)
+[ ]*a8: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00ac <[^>]*> lui \$at,[-0-9x]+
+[ ]*ac: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+00b0 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*b0: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+00b4 <[^>]*> lui \$at,[-0-9x]+
+[ ]*b4: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+00b8 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*b8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+00bc <[^>]*> lui \$at,[-0-9x]+
+[ ]*bc: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+00c0 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*c0: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+00c4 <[^>]*> lui \$at,[-0-9x]+
+[ ]*c4: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+00c8 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*c8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+00cc <[^>]*> lui \$at,[-0-9x]+
+[ ]*cc: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+00d0 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*d0: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+00d4 <[^>]*> lui \$at,[-0-9x]+
+[ ]*d4: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+00d8 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*d8: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+00dc <[^>]*> lui \$at,[-0-9x]+
+[ ]*dc: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+00e0 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*e0: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+00e4 <[^>]*> lui \$at,0x0
+[ ]*e4: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+00e8 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*e8: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+00ec <[^>]*> lui \$at,0x0
+[ ]*ec: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+00f0 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*f0: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+00f4 <[^>]*> lui \$at,0x0
+[ ]*f4: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+00f8 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*f8: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+00fc <[^>]*> lui \$at,0x0
+[ ]*fc: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0100 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*100: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0104 <[^>]*> lui \$at,0x0
+[ ]*104: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0108 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*108: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+010c <[^>]*> lui \$at,0x0
+[ ]*10c: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0110 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*110: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0114 <[^>]*> lui \$at,0x0
+[ ]*114: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0118 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*118: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+011c <[^>]*> lui \$at,[-0-9x]+
+[ ]*11c: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0120 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*120: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0124 <[^>]*> lui \$at,[-0-9x]+
+[ ]*124: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0128 <[^>]*> sb \$a0,0\(\$at\)
+[ ]*128: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+012c <[^>]*> lui \$at,[-0-9x]+
+[ ]*12c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0130 <[^>]*> sb \$a0,0\(\$at\)
+[ ]*130: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0134 <[^>]*> lui \$at,[-0-9x]+
+[ ]*134: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0138 <[^>]*> sb \$a0,0\(\$at\)
+[ ]*138: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+013c <[^>]*> lui \$at,[-0-9x]+
+[ ]*13c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0140 <[^>]*> sb \$a0,0\(\$at\)
+[ ]*140: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0144 <[^>]*> lui \$at,[-0-9x]+
+[ ]*144: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0148 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*148: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+014c <[^>]*> lui \$at,[-0-9x]+
+[ ]*14c: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0150 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*150: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0154 <[^>]*> lui \$at,[-0-9x]+
+[ ]*154: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0158 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*158: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+015c <[^>]*> lui \$at,[-0-9x]+
+[ ]*15c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0160 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*160: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0164 <[^>]*> lui \$at,[-0-9x]+
+[ ]*164: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0168 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*168: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+016c <[^>]*> lui \$at,[-0-9x]+
+[ ]*16c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0170 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*170: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0174 <[^>]*> lui \$at,[-0-9x]+
+[ ]*174: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0178 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*178: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+017c <[^>]*> lui \$at,[-0-9x]+
+[ ]*17c: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0180 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*180: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0184 <[^>]*> lui \$at,[-0-9x]+
+[ ]*184: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0188 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*188: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+018c <[^>]*> lui \$at,0x0
+[ ]*18c: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0190 <[^>]*> addu \$at,\$at,\$a1
+0+0194 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*194: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0198 <[^>]*> lui \$at,0x0
+[ ]*198: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+019c <[^>]*> addu \$at,\$at,\$a1
+0+01a0 <[^>]*> sb \$a0,0\(\$at\)
+[ ]*1a0: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+01a4 <[^>]*> addu \$at,\$a1,\$gp
+0+01a8 <[^>]*> sb \$a0,0\(\$at\)
+[ ]*1a8: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+01ac <[^>]*> lui \$at,0x0
+[ ]*1ac: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+01b0 <[^>]*> addu \$at,\$at,\$a1
+0+01b4 <[^>]*> sb \$a0,0\(\$at\)
+[ ]*1b4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+01b8 <[^>]*> addu \$at,\$a1,\$gp
+0+01bc <[^>]*> sb \$a0,0\(\$at\)
+[ ]*1bc: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+01c0 <[^>]*> lui \$at,0x0
+[ ]*1c0: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+01c4 <[^>]*> addu \$at,\$at,\$a1
+0+01c8 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*1c8: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+01cc <[^>]*> addu \$at,\$a1,\$gp
+0+01d0 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*1d0: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+01d4 <[^>]*> lui \$at,0x0
+[ ]*1d4: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+01d8 <[^>]*> addu \$at,\$at,\$a1
+0+01dc <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*1dc: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+01e0 <[^>]*> lui \$at,0x0
+[ ]*1e0: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+01e4 <[^>]*> addu \$at,\$at,\$a1
+0+01e8 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*1e8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+01ec <[^>]*> addu \$at,\$a1,\$gp
+0+01f0 <[^>]*> sb \$a0,1\(\$at\)
+[ ]*1f0: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+01f4 <[^>]*> lui \$at,0x0
+[ ]*1f4: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+01f8 <[^>]*> addu \$at,\$at,\$a1
+0+01fc <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*1fc: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0200 <[^>]*> addu \$at,\$a1,\$gp
+0+0204 <[^>]*> sb \$a0,1\(\$at\)
+[ ]*204: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+0208 <[^>]*> lui \$at,0x0
+[ ]*208: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+020c <[^>]*> addu \$at,\$at,\$a1
+0+0210 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*210: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0214 <[^>]*> addu \$at,\$a1,\$gp
+0+0218 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*218: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+021c <[^>]*> lui \$at,[-0-9x]+
+[ ]*21c: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0220 <[^>]*> addu \$at,\$at,\$a1
+0+0224 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*224: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0228 <[^>]*> lui \$at,[-0-9x]+
+[ ]*228: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+022c <[^>]*> addu \$at,\$at,\$a1
+0+0230 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*230: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0234 <[^>]*> lui \$at,[-0-9x]+
+[ ]*234: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0238 <[^>]*> addu \$at,\$at,\$a1
+0+023c <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*23c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0240 <[^>]*> lui \$at,[-0-9x]+
+[ ]*240: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0244 <[^>]*> addu \$at,\$at,\$a1
+0+0248 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*248: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+024c <[^>]*> lui \$at,[-0-9x]+
+[ ]*24c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0250 <[^>]*> addu \$at,\$at,\$a1
+0+0254 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*254: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0258 <[^>]*> lui \$at,[-0-9x]+
+[ ]*258: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+025c <[^>]*> addu \$at,\$at,\$a1
+0+0260 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*260: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0264 <[^>]*> lui \$at,[-0-9x]+
+[ ]*264: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0268 <[^>]*> addu \$at,\$at,\$a1
+0+026c <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*26c: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0270 <[^>]*> lui \$at,0x0
+[ ]*270: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0274 <[^>]*> addu \$at,\$at,\$a1
+0+0278 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*278: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+027c <[^>]*> lui \$at,0x0
+[ ]*27c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0280 <[^>]*> addu \$at,\$at,\$a1
+0+0284 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*284: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0288 <[^>]*> lui \$at,0x0
+[ ]*288: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+028c <[^>]*> addu \$at,\$at,\$a1
+0+0290 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*290: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0294 <[^>]*> lui \$at,0x0
+[ ]*294: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0298 <[^>]*> addu \$at,\$at,\$a1
+0+029c <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*29c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+02a0 <[^>]*> lui \$at,0x0
+[ ]*2a0: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+02a4 <[^>]*> addu \$at,\$at,\$a1
+0+02a8 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*2a8: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+02ac <[^>]*> lui \$at,0x0
+[ ]*2ac: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+02b0 <[^>]*> addu \$at,\$at,\$a1
+0+02b4 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*2b4: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+02b8 <[^>]*> lui \$at,0x0
+[ ]*2b8: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+02bc <[^>]*> addu \$at,\$at,\$a1
+0+02c0 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*2c0: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+02c4 <[^>]*> lui \$at,[-0-9x]+
+[ ]*2c4: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+02c8 <[^>]*> addu \$at,\$at,\$a1
+0+02cc <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*2cc: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+02d0 <[^>]*> lui \$at,[-0-9x]+
+[ ]*2d0: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+02d4 <[^>]*> addu \$at,\$at,\$a1
+0+02d8 <[^>]*> sb \$a0,0\(\$at\)
+[ ]*2d8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+02dc <[^>]*> lui \$at,[-0-9x]+
+[ ]*2dc: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+02e0 <[^>]*> addu \$at,\$at,\$a1
+0+02e4 <[^>]*> sb \$a0,0\(\$at\)
+[ ]*2e4: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+02e8 <[^>]*> lui \$at,[-0-9x]+
+[ ]*2e8: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+02ec <[^>]*> addu \$at,\$at,\$a1
+0+02f0 <[^>]*> sb \$a0,0\(\$at\)
+[ ]*2f0: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+02f4 <[^>]*> lui \$at,[-0-9x]+
+[ ]*2f4: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+02f8 <[^>]*> addu \$at,\$at,\$a1
+0+02fc <[^>]*> sb \$a0,0\(\$at\)
+[ ]*2fc: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0300 <[^>]*> lui \$at,[-0-9x]+
+[ ]*300: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0304 <[^>]*> addu \$at,\$at,\$a1
+0+0308 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*308: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+030c <[^>]*> lui \$at,[-0-9x]+
+[ ]*30c: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0310 <[^>]*> addu \$at,\$at,\$a1
+0+0314 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*314: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0318 <[^>]*> lui \$at,[-0-9x]+
+[ ]*318: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+031c <[^>]*> addu \$at,\$at,\$a1
+0+0320 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*320: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0324 <[^>]*> lui \$at,[-0-9x]+
+[ ]*324: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0328 <[^>]*> addu \$at,\$at,\$a1
+0+032c <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*32c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0330 <[^>]*> lui \$at,[-0-9x]+
+[ ]*330: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0334 <[^>]*> addu \$at,\$at,\$a1
+0+0338 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*338: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+033c <[^>]*> lui \$at,[-0-9x]+
+[ ]*33c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0340 <[^>]*> addu \$at,\$at,\$a1
+0+0344 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*344: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0348 <[^>]*> lui \$at,[-0-9x]+
+[ ]*348: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+034c <[^>]*> addu \$at,\$at,\$a1
+0+0350 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*350: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0354 <[^>]*> lui \$at,[-0-9x]+
+[ ]*354: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0358 <[^>]*> addu \$at,\$at,\$a1
+0+035c <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*35c: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0360 <[^>]*> lui \$at,[-0-9x]+
+[ ]*360: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0364 <[^>]*> addu \$at,\$at,\$a1
+0+0368 <[^>]*> sb \$a0,[-0-9]+\(\$at\)
+[ ]*368: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+036c <[^>]*> sw \$a0,0\(\$zero\)
+0+0370 <[^>]*> sw \$a1,4\(\$zero\)
+0+0374 <[^>]*> sh \$a0,0\(\$zero\)
+0+0378 <[^>]*> sw \$a0,0\(\$zero\)
+0+037c <[^>]*> swc0 \$4,0\(\$zero\)
+0+0380 <[^>]*> swc1 \$f4,0\(\$zero\)
+0+0384 <[^>]*> swc2 \$4,0\(\$zero\)
+0+0388 <[^>]*> swc3 \$4,0\(\$zero\)
+0+038c <[^>]*> swc1 \$f4,0\(\$zero\)
+0+0390 <[^>]*> swl \$a0,0\(\$zero\)
+0+0394 <[^>]*> swr \$a0,0\(\$zero\)
+ ...
diff --git a/gas/testsuite/gas/mips/sb.s b/gas/testsuite/gas/mips/sb.s
new file mode 100644
index 0000000000..d0c73542ab
--- /dev/null
+++ b/gas/testsuite/gas/mips/sb.s
@@ -0,0 +1,124 @@
+# Source file used to test the sb macro.
+
+ .data
+data_label:
+ .extern big_external_data_label,1000
+ .extern small_external_data_label,1
+ .comm big_external_common,1000
+ .comm small_external_common,1
+ .lcomm big_local_common,1000
+ .lcomm small_local_common,1
+
+ .text
+ sb $4,0
+ sb $4,1
+ sb $4,0x8000
+ sb $4,-0x8000
+ sb $4,0x10000
+ sb $4,0x1a5a5
+ sb $4,0($5)
+ sb $4,1($5)
+ sb $4,0x8000($5)
+ sb $4,-0x8000($5)
+ sb $4,0x10000($5)
+ sb $4,0x1a5a5($5)
+ sb $4,data_label
+ sb $4,big_external_data_label
+ sb $4,small_external_data_label
+ sb $4,big_external_common
+ sb $4,small_external_common
+ sb $4,big_local_common
+ sb $4,small_local_common
+ sb $4,data_label+1
+ sb $4,big_external_data_label+1
+ sb $4,small_external_data_label+1
+ sb $4,big_external_common+1
+ sb $4,small_external_common+1
+ sb $4,big_local_common+1
+ sb $4,small_local_common+1
+ sb $4,data_label+0x8000
+ sb $4,big_external_data_label+0x8000
+ sb $4,small_external_data_label+0x8000
+ sb $4,big_external_common+0x8000
+ sb $4,small_external_common+0x8000
+ sb $4,big_local_common+0x8000
+ sb $4,small_local_common+0x8000
+ sb $4,data_label-0x8000
+ sb $4,big_external_data_label-0x8000
+ sb $4,small_external_data_label-0x8000
+ sb $4,big_external_common-0x8000
+ sb $4,small_external_common-0x8000
+ sb $4,big_local_common-0x8000
+ sb $4,small_local_common-0x8000
+ sb $4,data_label+0x10000
+ sb $4,big_external_data_label+0x10000
+ sb $4,small_external_data_label+0x10000
+ sb $4,big_external_common+0x10000
+ sb $4,small_external_common+0x10000
+ sb $4,big_local_common+0x10000
+ sb $4,small_local_common+0x10000
+ sb $4,data_label+0x1a5a5
+ sb $4,big_external_data_label+0x1a5a5
+ sb $4,small_external_data_label+0x1a5a5
+ sb $4,big_external_common+0x1a5a5
+ sb $4,small_external_common+0x1a5a5
+ sb $4,big_local_common+0x1a5a5
+ sb $4,small_local_common+0x1a5a5
+ sb $4,data_label($5)
+ sb $4,big_external_data_label($5)
+ sb $4,small_external_data_label($5)
+ sb $4,big_external_common($5)
+ sb $4,small_external_common($5)
+ sb $4,big_local_common($5)
+ sb $4,small_local_common($5)
+ sb $4,data_label+1($5)
+ sb $4,big_external_data_label+1($5)
+ sb $4,small_external_data_label+1($5)
+ sb $4,big_external_common+1($5)
+ sb $4,small_external_common+1($5)
+ sb $4,big_local_common+1($5)
+ sb $4,small_local_common+1($5)
+ sb $4,data_label+0x8000($5)
+ sb $4,big_external_data_label+0x8000($5)
+ sb $4,small_external_data_label+0x8000($5)
+ sb $4,big_external_common+0x8000($5)
+ sb $4,small_external_common+0x8000($5)
+ sb $4,big_local_common+0x8000($5)
+ sb $4,small_local_common+0x8000($5)
+ sb $4,data_label-0x8000($5)
+ sb $4,big_external_data_label-0x8000($5)
+ sb $4,small_external_data_label-0x8000($5)
+ sb $4,big_external_common-0x8000($5)
+ sb $4,small_external_common-0x8000($5)
+ sb $4,big_local_common-0x8000($5)
+ sb $4,small_local_common-0x8000($5)
+ sb $4,data_label+0x10000($5)
+ sb $4,big_external_data_label+0x10000($5)
+ sb $4,small_external_data_label+0x10000($5)
+ sb $4,big_external_common+0x10000($5)
+ sb $4,small_external_common+0x10000($5)
+ sb $4,big_local_common+0x10000($5)
+ sb $4,small_local_common+0x10000($5)
+ sb $4,data_label+0x1a5a5($5)
+ sb $4,big_external_data_label+0x1a5a5($5)
+ sb $4,small_external_data_label+0x1a5a5($5)
+ sb $4,big_external_common+0x1a5a5($5)
+ sb $4,small_external_common+0x1a5a5($5)
+ sb $4,big_local_common+0x1a5a5($5)
+ sb $4,small_local_common+0x1a5a5($5)
+
+# Several macros are handled like sb. Sanity check them.
+ sd $4,0
+ sh $4,0
+ sw $4,0
+ swc0 $4,0
+ swc1 $4,0
+ swc2 $4,0
+ swc3 $4,0
+ s.s $f4,0
+ swl $4,0
+ swr $4,0
+
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+ nop
+ nop
diff --git a/gas/testsuite/gas/mips/sync.d b/gas/testsuite/gas/mips/sync.d
new file mode 100644
index 0000000000..9b50ea2f33
--- /dev/null
+++ b/gas/testsuite/gas/mips/sync.d
@@ -0,0 +1,10 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: sync instructions
+#as:
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+0+0000 <foo> 0000000f[ ]*sync
+0+0004 <foo\+0x4> 0000040f[ ]*sync.p
+0+0008 <foo\+0x8> 0000000f[ ]*sync
diff --git a/gas/testsuite/gas/mips/sync.s b/gas/testsuite/gas/mips/sync.s
new file mode 100644
index 0000000000..dec0ed3e16
--- /dev/null
+++ b/gas/testsuite/gas/mips/sync.s
@@ -0,0 +1,5 @@
+ .text
+foo:
+ sync
+ sync.p
+ sync.l
diff --git a/gas/testsuite/gas/mips/trap20.d b/gas/testsuite/gas/mips/trap20.d
new file mode 100644
index 0000000000..997adb0b94
--- /dev/null
+++ b/gas/testsuite/gas/mips/trap20.d
@@ -0,0 +1,20 @@
+#as: -mcpu=r4000
+#objdump: -dr --prefix-addresses -mmips:4000
+#name: MIPS 20-bit trap
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> teq \$zero,\$v1
+0+0004 <[^>]*> teq \$zero,\$v1,0x1
+0+0008 <[^>]*> tge \$zero,\$v1
+0+000c <[^>]*> tge \$zero,\$v1,0x3
+0+0010 <[^>]*> tgeu \$zero,\$v1
+0+0014 <[^>]*> tgeu \$zero,\$v1,0x7
+0+0018 <[^>]*> tlt \$zero,\$v1
+0+001c <[^>]*> tlt \$zero,\$v1,0x1f
+0+0020 <[^>]*> tltu \$zero,\$v1
+0+0024 <[^>]*> tltu \$zero,\$v1,0xff
+0+0028 <[^>]*> tne \$zero,\$v1
+0+002c <[^>]*> tne \$zero,\$v1,0x3ff
+ ...
diff --git a/gas/testsuite/gas/mips/trap20.s b/gas/testsuite/gas/mips/trap20.s
new file mode 100644
index 0000000000..a56d659569
--- /dev/null
+++ b/gas/testsuite/gas/mips/trap20.s
@@ -0,0 +1,18 @@
+# Source file used to test the 20-bit trap instructions
+foo:
+ teq $0,$3
+ teq $0,$3,1
+ tge $0,$3
+ tge $0,$3,3
+ tgeu $0,$3
+ tgeu $0,$3,7
+ tlt $0,$3
+ tlt $0,$3,31
+ tltu $0,$3
+ tltu $0,$3,255
+ tne $0,$3
+ tne $0,$3,1023
+
+# force some padding, to make objdump consistently report that there's some
+# here...
+ .space 8
diff --git a/gas/testsuite/gas/mips/trunc.d b/gas/testsuite/gas/mips/trunc.d
new file mode 100644
index 0000000000..3738ae15c2
--- /dev/null
+++ b/gas/testsuite/gas/mips/trunc.d
@@ -0,0 +1,29 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS trunc
+#as: -mips1 -mcpu=r3000
+
+# Test the trunc macros.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> cfc1 \$a0,\$31
+0+0004 <[^>]*> cfc1 \$a0,\$31
+0+0008 <[^>]*> nop
+0+000c <[^>]*> ori \$at,\$a0,0x3
+0+0010 <[^>]*> xori \$at,\$at,0x2
+0+0014 <[^>]*> ctc1 \$at,\$31
+0+0018 <[^>]*> nop
+0+001c <[^>]*> cvt.w.d \$f4,\$f6
+0+0020 <[^>]*> ctc1 \$a0,\$31
+0+0024 <[^>]*> nop
+0+0028 <[^>]*> cfc1 \$a0,\$31
+0+002c <[^>]*> cfc1 \$a0,\$31
+0+0030 <[^>]*> nop
+0+0034 <[^>]*> ori \$at,\$a0,0x3
+0+0038 <[^>]*> xori \$at,\$at,0x2
+0+003c <[^>]*> ctc1 \$at,\$31
+0+0040 <[^>]*> nop
+0+0044 <[^>]*> cvt.w.s \$f4,\$f6
+0+0048 <[^>]*> ctc1 \$a0,\$31
+0+004c <[^>]*> nop
diff --git a/gas/testsuite/gas/mips/trunc.s b/gas/testsuite/gas/mips/trunc.s
new file mode 100644
index 0000000000..e1e90f1e31
--- /dev/null
+++ b/gas/testsuite/gas/mips/trunc.s
@@ -0,0 +1,6 @@
+# Source file used to test the trunc macros.
+
+foo:
+ trunc.w.d $f4,$f6,$4
+
+ trunc.w.s $f4,$f6,$4
diff --git a/gas/testsuite/gas/mips/uld.d b/gas/testsuite/gas/mips/uld.d
new file mode 100644
index 0000000000..f92e29d565
--- /dev/null
+++ b/gas/testsuite/gas/mips/uld.d
@@ -0,0 +1,270 @@
+#objdump: -dr --prefix-addresses -mmips:4000
+#name: MIPS uld
+#as: -mips3 -mcpu=r4000
+
+# Test the uld macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> ldl \$a0,[07]\(\$zero\)
+0+0004 <[^>]*> ldr \$a0,[07]\(\$zero\)
+0+0008 <[^>]*> ldl \$a0,[18]\(\$zero\)
+0+000c <[^>]*> ldr \$a0,[18]\(\$zero\)
+0+0010 <[^>]*> li \$at,0x8000
+0+0014 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+0018 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+001c <[^>]*> ldl \$a0,-3276[18]\(\$zero\)
+0+0020 <[^>]*> ldr \$a0,-3276[18]\(\$zero\)
+0+0024 <[^>]*> lui \$at,0x1
+0+0028 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+002c <[^>]*> ldr \$a0,[07]\(\$at\)
+0+0030 <[^>]*> lui \$at,0x1
+0+0034 <[^>]*> ori \$at,\$at,0xa5a5
+0+0038 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+003c <[^>]*> ldr \$a0,[07]\(\$at\)
+0+0040 <[^>]*> ldl \$a0,[07]\(\$a1\)
+0+0044 <[^>]*> ldr \$a0,[07]\(\$a1\)
+0+0048 <[^>]*> ldl \$a0,[18]\(\$a1\)
+0+004c <[^>]*> ldr \$a0,[-0-9]+\(\$a1\)
+0+0050 <[^>]*> lui \$at,[-0-9x]+
+[ ]*50: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0054 <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*54: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0058 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+005c <[^>]*> ldr \$a0,[07]\(\$at\)
+0+0060 <[^>]*> lui \$at,0x0
+[ ]*60: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0064 <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*64: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0068 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+006c <[^>]*> ldr \$a0,[07]\(\$at\)
+0+0070 <[^>]*> daddiu \$at,\$gp,0
+[ ]*70: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+0074 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+0078 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+007c <[^>]*> lui \$at,0x0
+[ ]*7c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0080 <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*80: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0084 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+0088 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+008c <[^>]*> daddiu \$at,\$gp,0
+[ ]*8c: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+0090 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+0094 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+0098 <[^>]*> lui \$at,[-0-9x]+
+[ ]*98: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+009c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*9c: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+00a0 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+00a4 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+00a8 <[^>]*> daddiu \$at,\$gp,[-0-9]+
+[ ]*a8: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00ac <[^>]*> ldl \$a0,[07]\(\$at\)
+0+00b0 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+00b4 <[^>]*> lui \$at,0x0
+[ ]*b4: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+00b8 <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*b8: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+00bc <[^>]*> ldl \$a0,[07]\(\$at\)
+0+00c0 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+00c4 <[^>]*> lui \$at,0x0
+[ ]*c4: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+00c8 <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*c8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+00cc <[^>]*> ldl \$a0,[07]\(\$at\)
+0+00d0 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+00d4 <[^>]*> daddiu \$at,\$gp,1
+[ ]*d4: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00d8 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+00dc <[^>]*> ldr \$a0,[07]\(\$at\)
+0+00e0 <[^>]*> lui \$at,0x0
+[ ]*e0: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+00e4 <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*e4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+00e8 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+00ec <[^>]*> ldr \$a0,[07]\(\$at\)
+0+00f0 <[^>]*> daddiu \$at,\$gp,1
+[ ]*f0: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+00f4 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+00f8 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+00fc <[^>]*> lui \$at,0x0
+[ ]*fc: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0100 <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*100: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0104 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+0108 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+010c <[^>]*> daddiu \$at,\$gp,[-0-9]+
+[ ]*10c: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0110 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+0114 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+0118 <[^>]*> lui \$at,[-0-9x]+
+[ ]*118: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+011c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*11c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0120 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+0124 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+0128 <[^>]*> lui \$at,[-0-9x]+
+[ ]*128: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+012c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*12c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0130 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+0134 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+0138 <[^>]*> lui \$at,[-0-9x]+
+[ ]*138: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+013c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*13c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0140 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+0144 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+0148 <[^>]*> lui \$at,[-0-9x]+
+[ ]*148: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+014c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*14c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0150 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+0154 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+0158 <[^>]*> lui \$at,[-0-9x]+
+[ ]*158: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+015c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*15c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0160 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+0164 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+0168 <[^>]*> lui \$at,[-0-9x]+
+[ ]*168: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+016c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*16c: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0170 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+0174 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+0178 <[^>]*> lui \$at,[-0-9x]+
+[ ]*178: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+017c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*17c: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0180 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+0184 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+0188 <[^>]*> lui \$at,0x0
+[ ]*188: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+018c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*18c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0190 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+0194 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+0198 <[^>]*> lui \$at,0x0
+[ ]*198: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+019c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*19c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+01a0 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+01a4 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+01a8 <[^>]*> lui \$at,0x0
+[ ]*1a8: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+01ac <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*1ac: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+01b0 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+01b4 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+01b8 <[^>]*> lui \$at,0x0
+[ ]*1b8: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+01bc <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*1bc: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+01c0 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+01c4 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+01c8 <[^>]*> lui \$at,0x0
+[ ]*1c8: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+01cc <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*1cc: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+01d0 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+01d4 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+01d8 <[^>]*> lui \$at,0x0
+[ ]*1d8: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+01dc <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*1dc: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+01e0 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+01e4 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+01e8 <[^>]*> lui \$at,0x0
+[ ]*1e8: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+01ec <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*1ec: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+01f0 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+01f4 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+01f8 <[^>]*> lui \$at,[-0-9x]+
+[ ]*1f8: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+01fc <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*1fc: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0200 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+0204 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+0208 <[^>]*> lui \$at,[-0-9x]+
+[ ]*208: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+020c <[^>]*> daddiu \$at,\$at,0
+[ ]*20c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0210 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+0214 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+0218 <[^>]*> lui \$at,[-0-9x]+
+[ ]*218: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+021c <[^>]*> daddiu \$at,\$at,0
+[ ]*21c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0220 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+0224 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+0228 <[^>]*> lui \$at,[-0-9x]+
+[ ]*228: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+022c <[^>]*> daddiu \$at,\$at,0
+[ ]*22c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0230 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+0234 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+0238 <[^>]*> lui \$at,[-0-9x]+
+[ ]*238: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+023c <[^>]*> daddiu \$at,\$at,0
+[ ]*23c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0240 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+0244 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+0248 <[^>]*> lui \$at,[-0-9x]+
+[ ]*248: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+024c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*24c: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0250 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+0254 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+0258 <[^>]*> lui \$at,[-0-9x]+
+[ ]*258: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+025c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*25c: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0260 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+0264 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+0268 <[^>]*> lui \$at,[-0-9x]+
+[ ]*268: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+026c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*26c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0270 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+0274 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+0278 <[^>]*> lui \$at,[-0-9x]+
+[ ]*278: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+027c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*27c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0280 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+0284 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+0288 <[^>]*> lui \$at,[-0-9x]+
+[ ]*288: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+028c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*28c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0290 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+0294 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+0298 <[^>]*> lui \$at,[-0-9x]+
+[ ]*298: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+029c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*29c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+02a0 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+02a4 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+02a8 <[^>]*> lui \$at,[-0-9x]+
+[ ]*2a8: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+02ac <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*2ac: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+02b0 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+02b4 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+02b8 <[^>]*> lui \$at,[-0-9x]+
+[ ]*2b8: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+02bc <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*2bc: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+02c0 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+02c4 <[^>]*> ldr \$a0,[07]\(\$at\)
+0+02c8 <[^>]*> lui \$at,[-0-9x]+
+[ ]*2c8: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+02cc <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*2cc: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+02d0 <[^>]*> ldl \$a0,[07]\(\$at\)
+0+02d4 <[^>]*> ldr \$a0,[07]\(\$at\)
+ ...
diff --git a/gas/testsuite/gas/mips/uld.s b/gas/testsuite/gas/mips/uld.s
new file mode 100644
index 0000000000..9eaffbc329
--- /dev/null
+++ b/gas/testsuite/gas/mips/uld.s
@@ -0,0 +1,66 @@
+# Source file used to test the uld macro.
+
+ .data
+data_label:
+ .extern big_external_data_label,1000
+ .extern small_external_data_label,1
+ .comm big_external_common,1000
+ .comm small_external_common,1
+ .lcomm big_local_common,1000
+ .lcomm small_local_common,1
+
+ .text
+ uld $4,0
+ uld $4,1
+ uld $4,0x8000
+ uld $4,-0x8000
+ uld $4,0x10000
+ uld $4,0x1a5a5
+ uld $4,0($5)
+ uld $4,1($5)
+ uld $4,data_label
+ uld $4,big_external_data_label
+ uld $4,small_external_data_label
+ uld $4,big_external_common
+ uld $4,small_external_common
+ uld $4,big_local_common
+ uld $4,small_local_common
+ uld $4,data_label+1
+ uld $4,big_external_data_label+1
+ uld $4,small_external_data_label+1
+ uld $4,big_external_common+1
+ uld $4,small_external_common+1
+ uld $4,big_local_common+1
+ uld $4,small_local_common+1
+ uld $4,data_label+0x8000
+ uld $4,big_external_data_label+0x8000
+ uld $4,small_external_data_label+0x8000
+ uld $4,big_external_common+0x8000
+ uld $4,small_external_common+0x8000
+ uld $4,big_local_common+0x8000
+ uld $4,small_local_common+0x8000
+ uld $4,data_label-0x8000
+ uld $4,big_external_data_label-0x8000
+ uld $4,small_external_data_label-0x8000
+ uld $4,big_external_common-0x8000
+ uld $4,small_external_common-0x8000
+ uld $4,big_local_common-0x8000
+ uld $4,small_local_common-0x8000
+ uld $4,data_label+0x10000
+ uld $4,big_external_data_label+0x10000
+ uld $4,small_external_data_label+0x10000
+ uld $4,big_external_common+0x10000
+ uld $4,small_external_common+0x10000
+ uld $4,big_local_common+0x10000
+ uld $4,small_local_common+0x10000
+ uld $4,data_label+0x1a5a5
+ uld $4,big_external_data_label+0x1a5a5
+ uld $4,small_external_data_label+0x1a5a5
+ uld $4,big_external_common+0x1a5a5
+ uld $4,small_external_common+0x1a5a5
+ uld $4,big_local_common+0x1a5a5
+ uld $4,small_local_common+0x1a5a5
+
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+ nop
+ nop
diff --git a/gas/testsuite/gas/mips/ulh-empic.d b/gas/testsuite/gas/mips/ulh-empic.d
new file mode 100644
index 0000000000..945f06b624
--- /dev/null
+++ b/gas/testsuite/gas/mips/ulh-empic.d
@@ -0,0 +1,91 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS ulh-empic
+#as: -mips1 -membedded-pic
+#source: ulh-pic.s
+
+# Test the ulh macro with -membedded-pic.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> addiu \$at,\$gp,-16384
+[ ]*0: [A-Z0-9_]*GPREL[A-Z0-9_]* .sdata.*
+0+0004 <[^>]*> lb \$a0,[01]\(\$at\)
+0+0008 <[^>]*> lbu \$at,[01]\(\$at\)
+0+000c <[^>]*> sll \$a0,\$a0,0x8
+0+0010 <[^>]*> or \$a0,\$a0,\$at
+0+0014 <[^>]*> addiu \$at,\$gp,0
+[ ]*14: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_data_label
+0+0018 <[^>]*> lbu \$a0,[01]\(\$at\)
+0+001c <[^>]*> lbu \$at,[01]\(\$at\)
+0+0020 <[^>]*> sll \$a0,\$a0,0x8
+0+0024 <[^>]*> or \$a0,\$a0,\$at
+0+0028 <[^>]*> addiu \$at,\$gp,0
+[ ]*28: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+002c <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0030 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0034 <[^>]*> addiu \$at,\$gp,0
+[ ]*34: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_common
+0+0038 <[^>]*> sb \$a0,[01]\(\$at\)
+0+003c <[^>]*> srl \$a0,\$a0,0x8
+0+0040 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0044 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0048 <[^>]*> sll \$a0,\$a0,0x8
+0+004c <[^>]*> or \$a0,\$a0,\$at
+0+0050 <[^>]*> addiu \$at,\$gp,0
+[ ]*50: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+0054 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0058 <[^>]*> swr \$a0,[03]\(\$at\)
+0+005c <[^>]*> addiu \$at,\$gp,-16384
+[ ]*5c: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0060 <[^>]*> lb \$a0,[01]\(\$at\)
+0+0064 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0068 <[^>]*> sll \$a0,\$a0,0x8
+0+006c <[^>]*> or \$a0,\$a0,\$at
+0+0070 <[^>]*> addiu \$at,\$gp,-15384
+[ ]*70: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0074 <[^>]*> lbu \$a0,[01]\(\$at\)
+0+0078 <[^>]*> lbu \$at,[01]\(\$at\)
+0+007c <[^>]*> sll \$a0,\$a0,0x8
+0+0080 <[^>]*> or \$a0,\$a0,\$at
+0+0084 <[^>]*> addiu \$at,\$gp,-16383
+[ ]*84: [A-Z0-9_]*GPREL[A-Z0-9_]* .sdata.*
+0+0088 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+008c <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0090 <[^>]*> addiu \$at,\$gp,1
+[ ]*90: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_data_label
+0+0094 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0098 <[^>]*> srl \$a0,\$a0,0x8
+0+009c <[^>]*> sb \$a0,[01]\(\$at\)
+0+00a0 <[^>]*> lbu \$at,[01]\(\$at\)
+0+00a4 <[^>]*> sll \$a0,\$a0,0x8
+0+00a8 <[^>]*> or \$a0,\$a0,\$at
+0+00ac <[^>]*> addiu \$at,\$gp,1
+[ ]*ac: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00b0 <[^>]*> swl \$a0,[03]\(\$at\)
+0+00b4 <[^>]*> swr \$a0,[03]\(\$at\)
+0+00b8 <[^>]*> addiu \$at,\$gp,1
+[ ]*b8: [A-Z0-9_]*GPREL[A-Z0-9_]* big_external_common
+0+00bc <[^>]*> lb \$a0,[01]\(\$at\)
+0+00c0 <[^>]*> lbu \$at,[01]\(\$at\)
+0+00c4 <[^>]*> sll \$a0,\$a0,0x8
+0+00c8 <[^>]*> or \$a0,\$a0,\$at
+0+00cc <[^>]*> addiu \$at,\$gp,1
+[ ]*cc: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+00d0 <[^>]*> lbu \$a0,[01]\(\$at\)
+0+00d4 <[^>]*> lbu \$at,[01]\(\$at\)
+0+00d8 <[^>]*> sll \$a0,\$a0,0x8
+0+00dc <[^>]*> or \$a0,\$a0,\$at
+0+00e0 <[^>]*> addiu \$at,\$gp,-16383
+[ ]*e0: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00e4 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+00e8 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+00ec <[^>]*> addiu \$at,\$gp,-15383
+[ ]*ec: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00f0 <[^>]*> sb \$a0,[01]\(\$at\)
+0+00f4 <[^>]*> srl \$a0,\$a0,0x8
+0+00f8 <[^>]*> sb \$a0,[01]\(\$at\)
+0+00fc <[^>]*> lbu \$at,[01]\(\$at\)
+0+0100 <[^>]*> sll \$a0,\$a0,0x8
+0+0104 <[^>]*> or \$a0,\$a0,\$at
+ ...
diff --git a/gas/testsuite/gas/mips/ulh-pic.s b/gas/testsuite/gas/mips/ulh-pic.s
new file mode 100644
index 0000000000..633b29c48f
--- /dev/null
+++ b/gas/testsuite/gas/mips/ulh-pic.s
@@ -0,0 +1,36 @@
+# Test unaligned load and store macros with PIC code. We don't bother
+# to test most cases. The actual loads and stores are tested by the
+# non-PIC test case. We just want to check that the initial address
+# is loaded correctly.
+
+ .data
+data_label:
+ .extern big_external_data_label,1000
+ .extern small_external_data_label,1
+ .comm big_external_common,1000
+ .comm small_external_common,1
+ .lcomm big_local_common,1000
+ .lcomm small_local_common,1
+
+ .text
+ ulh $4,data_label
+ ulhu $4,big_external_data_label
+ ulw $4,small_external_data_label
+ ush $4,big_external_common
+ usw $4,small_external_common
+ ulh $4,big_local_common
+ ulhu $4,small_local_common
+ ulw $4,data_label+1
+ ush $4,big_external_data_label+1
+ usw $4,small_external_data_label+1
+ ulh $4,big_external_common+1
+ ulhu $4,small_external_common+1
+ ulw $4,big_local_common+1
+ ush $4,small_local_common+1
+
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+ nop
+ .ifndef XGOT
+ nop
+ nop
+ .endif
diff --git a/gas/testsuite/gas/mips/ulh-svr4pic.d b/gas/testsuite/gas/mips/ulh-svr4pic.d
new file mode 100644
index 0000000000..86e33bd6bc
--- /dev/null
+++ b/gas/testsuite/gas/mips/ulh-svr4pic.d
@@ -0,0 +1,124 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS ulh-svr4pic
+#as: -mips1 -KPIC -EB
+#source: ulh-pic.s
+
+# Test the unaligned load and store macros with -KPIC.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*0: R_MIPS_GOT16 .data
+0+0004 <[^>]*> nop
+0+0008 <[^>]*> addiu \$at,\$at,0
+[ ]*8: R_MIPS_LO16 .data
+0+000c <[^>]*> lb \$a0,0\(\$at\)
+0+0010 <[^>]*> lbu \$at,1\(\$at\)
+0+0014 <[^>]*> sll \$a0,\$a0,0x8
+0+0018 <[^>]*> or \$a0,\$a0,\$at
+0+001c <[^>]*> lw \$at,0\(\$gp\)
+[ ]*1c: R_MIPS_GOT16 big_external_data_label
+0+0020 <[^>]*> nop
+0+0024 <[^>]*> lbu \$a0,0\(\$at\)
+0+0028 <[^>]*> lbu \$at,1\(\$at\)
+0+002c <[^>]*> sll \$a0,\$a0,0x8
+0+0030 <[^>]*> or \$a0,\$a0,\$at
+0+0034 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*34: R_MIPS_GOT16 small_external_data_label
+0+0038 <[^>]*> nop
+0+003c <[^>]*> lwl \$a0,0\(\$at\)
+0+0040 <[^>]*> lwr \$a0,3\(\$at\)
+0+0044 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*44: R_MIPS_GOT16 big_external_common
+0+0048 <[^>]*> nop
+0+004c <[^>]*> sb \$a0,1\(\$at\)
+0+0050 <[^>]*> srl \$a0,\$a0,0x8
+0+0054 <[^>]*> sb \$a0,0\(\$at\)
+0+0058 <[^>]*> lbu \$at,1\(\$at\)
+0+005c <[^>]*> sll \$a0,\$a0,0x8
+0+0060 <[^>]*> or \$a0,\$a0,\$at
+0+0064 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*64: R_MIPS_GOT16 small_external_common
+0+0068 <[^>]*> nop
+0+006c <[^>]*> swl \$a0,0\(\$at\)
+0+0070 <[^>]*> swr \$a0,3\(\$at\)
+0+0074 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*74: R_MIPS_GOT16 .bss
+0+0078 <[^>]*> nop
+0+007c <[^>]*> addiu \$at,\$at,0
+[ ]*7c: R_MIPS_LO16 .bss
+0+0080 <[^>]*> lb \$a0,0\(\$at\)
+0+0084 <[^>]*> lbu \$at,1\(\$at\)
+0+0088 <[^>]*> sll \$a0,\$a0,0x8
+0+008c <[^>]*> or \$a0,\$a0,\$at
+0+0090 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*90: R_MIPS_GOT16 .bss
+0+0094 <[^>]*> nop
+0+0098 <[^>]*> addiu \$at,\$at,1000
+[ ]*98: R_MIPS_LO16 .bss
+0+009c <[^>]*> lbu \$a0,0\(\$at\)
+0+00a0 <[^>]*> lbu \$at,1\(\$at\)
+0+00a4 <[^>]*> sll \$a0,\$a0,0x8
+0+00a8 <[^>]*> or \$a0,\$a0,\$at
+0+00ac <[^>]*> lw \$at,0\(\$gp\)
+[ ]*ac: R_MIPS_GOT16 .data
+0+00b0 <[^>]*> nop
+0+00b4 <[^>]*> addiu \$at,\$at,0
+[ ]*b4: R_MIPS_LO16 .data
+0+00b8 <[^>]*> addiu \$at,\$at,1
+0+00bc <[^>]*> lwl \$a0,0\(\$at\)
+0+00c0 <[^>]*> lwr \$a0,3\(\$at\)
+0+00c4 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*c4: R_MIPS_GOT16 big_external_data_label
+0+00c8 <[^>]*> nop
+0+00cc <[^>]*> addiu \$at,\$at,1
+0+00d0 <[^>]*> sb \$a0,1\(\$at\)
+0+00d4 <[^>]*> srl \$a0,\$a0,0x8
+0+00d8 <[^>]*> sb \$a0,0\(\$at\)
+0+00dc <[^>]*> lbu \$at,1\(\$at\)
+0+00e0 <[^>]*> sll \$a0,\$a0,0x8
+0+00e4 <[^>]*> or \$a0,\$a0,\$at
+0+00e8 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*e8: R_MIPS_GOT16 small_external_data_label
+0+00ec <[^>]*> nop
+0+00f0 <[^>]*> addiu \$at,\$at,1
+0+00f4 <[^>]*> swl \$a0,0\(\$at\)
+0+00f8 <[^>]*> swr \$a0,3\(\$at\)
+0+00fc <[^>]*> lw \$at,0\(\$gp\)
+[ ]*fc: R_MIPS_GOT16 big_external_common
+0+0100 <[^>]*> nop
+0+0104 <[^>]*> addiu \$at,\$at,1
+0+0108 <[^>]*> lb \$a0,0\(\$at\)
+0+010c <[^>]*> lbu \$at,1\(\$at\)
+0+0110 <[^>]*> sll \$a0,\$a0,0x8
+0+0114 <[^>]*> or \$a0,\$a0,\$at
+0+0118 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*118: R_MIPS_GOT16 small_external_common
+0+011c <[^>]*> nop
+0+0120 <[^>]*> addiu \$at,\$at,1
+0+0124 <[^>]*> lbu \$a0,0\(\$at\)
+0+0128 <[^>]*> lbu \$at,1\(\$at\)
+0+012c <[^>]*> sll \$a0,\$a0,0x8
+0+0130 <[^>]*> or \$a0,\$a0,\$at
+0+0134 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*134: R_MIPS_GOT16 .bss
+0+0138 <[^>]*> nop
+0+013c <[^>]*> addiu \$at,\$at,0
+[ ]*13c: R_MIPS_LO16 .bss
+0+0140 <[^>]*> addiu \$at,\$at,1
+0+0144 <[^>]*> lwl \$a0,0\(\$at\)
+0+0148 <[^>]*> lwr \$a0,3\(\$at\)
+0+014c <[^>]*> lw \$at,0\(\$gp\)
+[ ]*14c: R_MIPS_GOT16 .bss
+0+0150 <[^>]*> nop
+0+0154 <[^>]*> addiu \$at,\$at,1000
+[ ]*154: R_MIPS_LO16 .bss
+0+0158 <[^>]*> addiu \$at,\$at,1
+0+015c <[^>]*> sb \$a0,1\(\$at\)
+0+0160 <[^>]*> srl \$a0,\$a0,0x8
+0+0164 <[^>]*> sb \$a0,0\(\$at\)
+0+0168 <[^>]*> lbu \$at,1\(\$at\)
+0+016c <[^>]*> sll \$a0,\$a0,0x8
+0+0170 <[^>]*> or \$a0,\$a0,\$at
+ ...
diff --git a/gas/testsuite/gas/mips/ulh-xgot.d b/gas/testsuite/gas/mips/ulh-xgot.d
new file mode 100644
index 0000000000..982f9ce5c7
--- /dev/null
+++ b/gas/testsuite/gas/mips/ulh-xgot.d
@@ -0,0 +1,154 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS ulh-xgot
+#as: -mips1 -mcpu=r3000 -KPIC -xgot -EB --defsym XGOT=1
+#source: ulh-pic.s
+
+# Test the unaligned load and store macros with -KPIC -xgot.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*0: R_MIPS_GOT16 .data
+0+0004 <[^>]*> nop
+0+0008 <[^>]*> addiu \$at,\$at,0
+[ ]*8: R_MIPS_LO16 .data
+0+000c <[^>]*> nop
+0+0010 <[^>]*> lb \$a0,0\(\$at\)
+0+0014 <[^>]*> lbu \$at,1\(\$at\)
+0+0018 <[^>]*> sll \$a0,\$a0,0x8
+0+001c <[^>]*> or \$a0,\$a0,\$at
+0+0020 <[^>]*> lui \$at,0x0
+[ ]*20: R_MIPS_GOT_HI16 big_external_data_label
+0+0024 <[^>]*> addu \$at,\$at,\$gp
+0+0028 <[^>]*> lw \$at,0\(\$at\)
+[ ]*28: R_MIPS_GOT_LO16 big_external_data_label
+0+002c <[^>]*> nop
+0+0030 <[^>]*> lbu \$a0,0\(\$at\)
+0+0034 <[^>]*> lbu \$at,1\(\$at\)
+0+0038 <[^>]*> sll \$a0,\$a0,0x8
+0+003c <[^>]*> or \$a0,\$a0,\$at
+0+0040 <[^>]*> lui \$at,0x0
+[ ]*40: R_MIPS_GOT_HI16 small_external_data_label
+0+0044 <[^>]*> addu \$at,\$at,\$gp
+0+0048 <[^>]*> lw \$at,0\(\$at\)
+[ ]*48: R_MIPS_GOT_LO16 small_external_data_label
+0+004c <[^>]*> nop
+0+0050 <[^>]*> lwl \$a0,0\(\$at\)
+0+0054 <[^>]*> lwr \$a0,3\(\$at\)
+0+0058 <[^>]*> lui \$at,0x0
+[ ]*58: R_MIPS_GOT_HI16 big_external_common
+0+005c <[^>]*> addu \$at,\$at,\$gp
+0+0060 <[^>]*> lw \$at,0\(\$at\)
+[ ]*60: R_MIPS_GOT_LO16 big_external_common
+0+0064 <[^>]*> nop
+0+0068 <[^>]*> sb \$a0,1\(\$at\)
+0+006c <[^>]*> srl \$a0,\$a0,0x8
+0+0070 <[^>]*> sb \$a0,0\(\$at\)
+0+0074 <[^>]*> lbu \$at,1\(\$at\)
+0+0078 <[^>]*> sll \$a0,\$a0,0x8
+0+007c <[^>]*> or \$a0,\$a0,\$at
+0+0080 <[^>]*> lui \$at,0x0
+[ ]*80: R_MIPS_GOT_HI16 small_external_common
+0+0084 <[^>]*> addu \$at,\$at,\$gp
+0+0088 <[^>]*> lw \$at,0\(\$at\)
+[ ]*88: R_MIPS_GOT_LO16 small_external_common
+0+008c <[^>]*> nop
+0+0090 <[^>]*> swl \$a0,0\(\$at\)
+0+0094 <[^>]*> swr \$a0,3\(\$at\)
+0+0098 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*98: R_MIPS_GOT16 .bss
+0+009c <[^>]*> nop
+0+00a0 <[^>]*> addiu \$at,\$at,0
+[ ]*a0: R_MIPS_LO16 .bss
+0+00a4 <[^>]*> nop
+0+00a8 <[^>]*> lb \$a0,0\(\$at\)
+0+00ac <[^>]*> lbu \$at,1\(\$at\)
+0+00b0 <[^>]*> sll \$a0,\$a0,0x8
+0+00b4 <[^>]*> or \$a0,\$a0,\$at
+0+00b8 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*b8: R_MIPS_GOT16 .bss
+0+00bc <[^>]*> nop
+0+00c0 <[^>]*> addiu \$at,\$at,1000
+[ ]*c0: R_MIPS_LO16 .bss
+0+00c4 <[^>]*> nop
+0+00c8 <[^>]*> lbu \$a0,0\(\$at\)
+0+00cc <[^>]*> lbu \$at,1\(\$at\)
+0+00d0 <[^>]*> sll \$a0,\$a0,0x8
+0+00d4 <[^>]*> or \$a0,\$a0,\$at
+0+00d8 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*d8: R_MIPS_GOT16 .data
+0+00dc <[^>]*> nop
+0+00e0 <[^>]*> addiu \$at,\$at,0
+[ ]*e0: R_MIPS_LO16 .data
+0+00e4 <[^>]*> nop
+0+00e8 <[^>]*> addiu \$at,\$at,1
+0+00ec <[^>]*> lwl \$a0,0\(\$at\)
+0+00f0 <[^>]*> lwr \$a0,3\(\$at\)
+0+00f4 <[^>]*> lui \$at,0x0
+[ ]*f4: R_MIPS_GOT_HI16 big_external_data_label
+0+00f8 <[^>]*> addu \$at,\$at,\$gp
+0+00fc <[^>]*> lw \$at,0\(\$at\)
+[ ]*fc: R_MIPS_GOT_LO16 big_external_data_label
+0+0100 <[^>]*> nop
+0+0104 <[^>]*> addiu \$at,\$at,1
+0+0108 <[^>]*> sb \$a0,1\(\$at\)
+0+010c <[^>]*> srl \$a0,\$a0,0x8
+0+0110 <[^>]*> sb \$a0,0\(\$at\)
+0+0114 <[^>]*> lbu \$at,1\(\$at\)
+0+0118 <[^>]*> sll \$a0,\$a0,0x8
+0+011c <[^>]*> or \$a0,\$a0,\$at
+0+0120 <[^>]*> lui \$at,0x0
+[ ]*120: R_MIPS_GOT_HI16 small_external_data_label
+0+0124 <[^>]*> addu \$at,\$at,\$gp
+0+0128 <[^>]*> lw \$at,0\(\$at\)
+[ ]*128: R_MIPS_GOT_LO16 small_external_data_label
+0+012c <[^>]*> nop
+0+0130 <[^>]*> addiu \$at,\$at,1
+0+0134 <[^>]*> swl \$a0,0\(\$at\)
+0+0138 <[^>]*> swr \$a0,3\(\$at\)
+0+013c <[^>]*> lui \$at,0x0
+[ ]*13c: R_MIPS_GOT_HI16 big_external_common
+0+0140 <[^>]*> addu \$at,\$at,\$gp
+0+0144 <[^>]*> lw \$at,0\(\$at\)
+[ ]*144: R_MIPS_GOT_LO16 big_external_common
+0+0148 <[^>]*> nop
+0+014c <[^>]*> addiu \$at,\$at,1
+0+0150 <[^>]*> lb \$a0,0\(\$at\)
+0+0154 <[^>]*> lbu \$at,1\(\$at\)
+0+0158 <[^>]*> sll \$a0,\$a0,0x8
+0+015c <[^>]*> or \$a0,\$a0,\$at
+0+0160 <[^>]*> lui \$at,0x0
+[ ]*160: R_MIPS_GOT_HI16 small_external_common
+0+0164 <[^>]*> addu \$at,\$at,\$gp
+0+0168 <[^>]*> lw \$at,0\(\$at\)
+[ ]*168: R_MIPS_GOT_LO16 small_external_common
+0+016c <[^>]*> nop
+0+0170 <[^>]*> addiu \$at,\$at,1
+0+0174 <[^>]*> lbu \$a0,0\(\$at\)
+0+0178 <[^>]*> lbu \$at,1\(\$at\)
+0+017c <[^>]*> sll \$a0,\$a0,0x8
+0+0180 <[^>]*> or \$a0,\$a0,\$at
+0+0184 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*184: R_MIPS_GOT16 .bss
+0+0188 <[^>]*> nop
+0+018c <[^>]*> addiu \$at,\$at,0
+[ ]*18c: R_MIPS_LO16 .bss
+0+0190 <[^>]*> nop
+0+0194 <[^>]*> addiu \$at,\$at,1
+0+0198 <[^>]*> lwl \$a0,0\(\$at\)
+0+019c <[^>]*> lwr \$a0,3\(\$at\)
+0+01a0 <[^>]*> lw \$at,0\(\$gp\)
+[ ]*1a0: R_MIPS_GOT16 .bss
+0+01a4 <[^>]*> nop
+0+01a8 <[^>]*> addiu \$at,\$at,1000
+[ ]*1a8: R_MIPS_LO16 .bss
+0+01ac <[^>]*> nop
+0+01b0 <[^>]*> addiu \$at,\$at,1
+0+01b4 <[^>]*> sb \$a0,1\(\$at\)
+0+01b8 <[^>]*> srl \$a0,\$a0,0x8
+0+01bc <[^>]*> sb \$a0,0\(\$at\)
+0+01c0 <[^>]*> lbu \$at,1\(\$at\)
+0+01c4 <[^>]*> sll \$a0,\$a0,0x8
+0+01c8 <[^>]*> or \$a0,\$a0,\$at
+0+01cc <[^>]*> nop
diff --git a/gas/testsuite/gas/mips/ulh.d b/gas/testsuite/gas/mips/ulh.d
new file mode 100644
index 0000000000..8d6d4b4502
--- /dev/null
+++ b/gas/testsuite/gas/mips/ulh.d
@@ -0,0 +1,374 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS ulh
+#as: -mips1
+
+# Test the ulh macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> lb \$a0,[01]\(\$zero\)
+0+0004 <[^>]*> lbu \$at,[01]\(\$zero\)
+0+0008 <[^>]*> sll \$a0,\$a0,0x8
+0+000c <[^>]*> or \$a0,\$a0,\$at
+0+0010 <[^>]*> lb \$a0,[12]\(\$zero\)
+0+0014 <[^>]*> lbu \$at,[12]\(\$zero\)
+0+0018 <[^>]*> sll \$a0,\$a0,0x8
+0+001c <[^>]*> or \$a0,\$a0,\$at
+0+0020 <[^>]*> li \$at,0x8000
+0+0024 <[^>]*> lb \$a0,[01]\(\$at\)
+0+0028 <[^>]*> lbu \$at,[01]\(\$at\)
+0+002c <[^>]*> sll \$a0,\$a0,0x8
+0+0030 <[^>]*> or \$a0,\$a0,\$at
+0+0034 <[^>]*> lb \$a0,-3276[78]\(\$zero\)
+0+0038 <[^>]*> lbu \$at,-3276[78]\(\$zero\)
+0+003c <[^>]*> sll \$a0,\$a0,0x8
+0+0040 <[^>]*> or \$a0,\$a0,\$at
+0+0044 <[^>]*> lui \$at,0x1
+0+0048 <[^>]*> lb \$a0,[01]\(\$at\)
+0+004c <[^>]*> lbu \$at,[01]\(\$at\)
+0+0050 <[^>]*> sll \$a0,\$a0,0x8
+0+0054 <[^>]*> or \$a0,\$a0,\$at
+0+0058 <[^>]*> lui \$at,0x1
+0+005c <[^>]*> ori \$at,\$at,0xa5a5
+0+0060 <[^>]*> lb \$a0,[01]\(\$at\)
+0+0064 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0068 <[^>]*> sll \$a0,\$a0,0x8
+0+006c <[^>]*> or \$a0,\$a0,\$at
+0+0070 <[^>]*> lb \$a0,[01]\(\$a1\)
+0+0074 <[^>]*> lbu \$at,[01]\(\$a1\)
+0+0078 <[^>]*> sll \$a0,\$a0,0x8
+0+007c <[^>]*> or \$a0,\$a0,\$at
+0+0080 <[^>]*> lb \$a0,[12]\(\$a1\)
+0+0084 <[^>]*> lbu \$at,[12]\(\$a1\)
+0+0088 <[^>]*> sll \$a0,\$a0,0x8
+0+008c <[^>]*> or \$a0,\$a0,\$at
+0+0090 <[^>]*> lui \$at,[-0-9x]+
+[ ]*90: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0094 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*94: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0098 <[^>]*> lb \$a0,[01]\(\$at\)
+0+009c <[^>]*> lbu \$at,[01]\(\$at\)
+0+00a0 <[^>]*> sll \$a0,\$a0,0x8
+0+00a4 <[^>]*> or \$a0,\$a0,\$at
+0+00a8 <[^>]*> lui \$at,0x0
+[ ]*a8: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+00ac <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*ac: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+00b0 <[^>]*> lb \$a0,[01]\(\$at\)
+0+00b4 <[^>]*> lbu \$at,[01]\(\$at\)
+0+00b8 <[^>]*> sll \$a0,\$a0,0x8
+0+00bc <[^>]*> or \$a0,\$a0,\$at
+0+00c0 <[^>]*> addiu \$at,\$gp,0
+[ ]*c0: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00c4 <[^>]*> lb \$a0,[01]\(\$at\)
+0+00c8 <[^>]*> lbu \$at,[01]\(\$at\)
+0+00cc <[^>]*> sll \$a0,\$a0,0x8
+0+00d0 <[^>]*> or \$a0,\$a0,\$at
+0+00d4 <[^>]*> lui \$at,0x0
+[ ]*d4: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+00d8 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*d8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+00dc <[^>]*> lb \$a0,[01]\(\$at\)
+0+00e0 <[^>]*> lbu \$at,[01]\(\$at\)
+0+00e4 <[^>]*> sll \$a0,\$a0,0x8
+0+00e8 <[^>]*> or \$a0,\$a0,\$at
+0+00ec <[^>]*> addiu \$at,\$gp,0
+[ ]*ec: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+00f0 <[^>]*> lb \$a0,[01]\(\$at\)
+0+00f4 <[^>]*> lbu \$at,[01]\(\$at\)
+0+00f8 <[^>]*> sll \$a0,\$a0,0x8
+0+00fc <[^>]*> or \$a0,\$a0,\$at
+0+0100 <[^>]*> lui \$at,[-0-9x]+
+[ ]*100: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0104 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*104: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0108 <[^>]*> lb \$a0,[01]\(\$at\)
+0+010c <[^>]*> lbu \$at,[01]\(\$at\)
+0+0110 <[^>]*> sll \$a0,\$a0,0x8
+0+0114 <[^>]*> or \$a0,\$a0,\$at
+0+0118 <[^>]*> addiu \$at,\$gp,[-0-9]+
+[ ]*118: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+011c <[^>]*> lb \$a0,[01]\(\$at\)
+0+0120 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0124 <[^>]*> sll \$a0,\$a0,0x8
+0+0128 <[^>]*> or \$a0,\$a0,\$at
+0+012c <[^>]*> lui \$at,0x0
+[ ]*12c: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0130 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*130: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0134 <[^>]*> lb \$a0,[01]\(\$at\)
+0+0138 <[^>]*> lbu \$at,[01]\(\$at\)
+0+013c <[^>]*> sll \$a0,\$a0,0x8
+0+0140 <[^>]*> or \$a0,\$a0,\$at
+0+0144 <[^>]*> lui \$at,0x0
+[ ]*144: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0148 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*148: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+014c <[^>]*> lb \$a0,[01]\(\$at\)
+0+0150 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0154 <[^>]*> sll \$a0,\$a0,0x8
+0+0158 <[^>]*> or \$a0,\$a0,\$at
+0+015c <[^>]*> addiu \$at,\$gp,1
+[ ]*15c: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+0160 <[^>]*> lb \$a0,[01]\(\$at\)
+0+0164 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0168 <[^>]*> sll \$a0,\$a0,0x8
+0+016c <[^>]*> or \$a0,\$a0,\$at
+0+0170 <[^>]*> lui \$at,0x0
+[ ]*170: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0174 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*174: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0178 <[^>]*> lb \$a0,[01]\(\$at\)
+0+017c <[^>]*> lbu \$at,[01]\(\$at\)
+0+0180 <[^>]*> sll \$a0,\$a0,0x8
+0+0184 <[^>]*> or \$a0,\$a0,\$at
+0+0188 <[^>]*> addiu \$at,\$gp,1
+[ ]*188: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+018c <[^>]*> lb \$a0,[01]\(\$at\)
+0+0190 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0194 <[^>]*> sll \$a0,\$a0,0x8
+0+0198 <[^>]*> or \$a0,\$a0,\$at
+0+019c <[^>]*> lui \$at,0x0
+[ ]*19c: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+01a0 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*1a0: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+01a4 <[^>]*> lb \$a0,[01]\(\$at\)
+0+01a8 <[^>]*> lbu \$at,[01]\(\$at\)
+0+01ac <[^>]*> sll \$a0,\$a0,0x8
+0+01b0 <[^>]*> or \$a0,\$a0,\$at
+0+01b4 <[^>]*> addiu \$at,\$gp,[-0-9]+
+[ ]*1b4: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+01b8 <[^>]*> lb \$a0,[01]\(\$at\)
+0+01bc <[^>]*> lbu \$at,[01]\(\$at\)
+0+01c0 <[^>]*> sll \$a0,\$a0,0x8
+0+01c4 <[^>]*> or \$a0,\$a0,\$at
+0+01c8 <[^>]*> lui \$at,[-0-9x]+
+[ ]*1c8: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+01cc <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*1cc: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+01d0 <[^>]*> lb \$a0,[01]\(\$at\)
+0+01d4 <[^>]*> lbu \$at,[01]\(\$at\)
+0+01d8 <[^>]*> sll \$a0,\$a0,0x8
+0+01dc <[^>]*> or \$a0,\$a0,\$at
+0+01e0 <[^>]*> lui \$at,[-0-9x]+
+[ ]*1e0: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+01e4 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*1e4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+01e8 <[^>]*> lb \$a0,[01]\(\$at\)
+0+01ec <[^>]*> lbu \$at,[01]\(\$at\)
+0+01f0 <[^>]*> sll \$a0,\$a0,0x8
+0+01f4 <[^>]*> or \$a0,\$a0,\$at
+0+01f8 <[^>]*> lui \$at,[-0-9x]+
+[ ]*1f8: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+01fc <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*1fc: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0200 <[^>]*> lb \$a0,[01]\(\$at\)
+0+0204 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0208 <[^>]*> sll \$a0,\$a0,0x8
+0+020c <[^>]*> or \$a0,\$a0,\$at
+0+0210 <[^>]*> lui \$at,[-0-9x]+
+[ ]*210: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0214 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*214: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0218 <[^>]*> lb \$a0,[01]\(\$at\)
+0+021c <[^>]*> lbu \$at,[01]\(\$at\)
+0+0220 <[^>]*> sll \$a0,\$a0,0x8
+0+0224 <[^>]*> or \$a0,\$a0,\$at
+0+0228 <[^>]*> lui \$at,[-0-9x]+
+[ ]*228: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+022c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*22c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0230 <[^>]*> lb \$a0,[01]\(\$at\)
+0+0234 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0238 <[^>]*> sll \$a0,\$a0,0x8
+0+023c <[^>]*> or \$a0,\$a0,\$at
+0+0240 <[^>]*> lui \$at,[-0-9x]+
+[ ]*240: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0244 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*244: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0248 <[^>]*> lb \$a0,[01]\(\$at\)
+0+024c <[^>]*> lbu \$at,[01]\(\$at\)
+0+0250 <[^>]*> sll \$a0,\$a0,0x8
+0+0254 <[^>]*> or \$a0,\$a0,\$at
+0+0258 <[^>]*> lui \$at,[-0-9x]+
+[ ]*258: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+025c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*25c: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0260 <[^>]*> lb \$a0,[01]\(\$at\)
+0+0264 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0268 <[^>]*> sll \$a0,\$a0,0x8
+0+026c <[^>]*> or \$a0,\$a0,\$at
+0+0270 <[^>]*> lui \$at,0x0
+[ ]*270: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0274 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*274: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0278 <[^>]*> lb \$a0,[01]\(\$at\)
+0+027c <[^>]*> lbu \$at,[01]\(\$at\)
+0+0280 <[^>]*> sll \$a0,\$a0,0x8
+0+0284 <[^>]*> or \$a0,\$a0,\$at
+0+0288 <[^>]*> lui \$at,0x0
+[ ]*288: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+028c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*28c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0290 <[^>]*> lb \$a0,[01]\(\$at\)
+0+0294 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0298 <[^>]*> sll \$a0,\$a0,0x8
+0+029c <[^>]*> or \$a0,\$a0,\$at
+0+02a0 <[^>]*> lui \$at,0x0
+[ ]*2a0: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+02a4 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*2a4: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+02a8 <[^>]*> lb \$a0,[01]\(\$at\)
+0+02ac <[^>]*> lbu \$at,[01]\(\$at\)
+0+02b0 <[^>]*> sll \$a0,\$a0,0x8
+0+02b4 <[^>]*> or \$a0,\$a0,\$at
+0+02b8 <[^>]*> lui \$at,0x0
+[ ]*2b8: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+02bc <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*2bc: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+02c0 <[^>]*> lb \$a0,[01]\(\$at\)
+0+02c4 <[^>]*> lbu \$at,[01]\(\$at\)
+0+02c8 <[^>]*> sll \$a0,\$a0,0x8
+0+02cc <[^>]*> or \$a0,\$a0,\$at
+0+02d0 <[^>]*> lui \$at,0x0
+[ ]*2d0: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+02d4 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*2d4: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+02d8 <[^>]*> lb \$a0,[01]\(\$at\)
+0+02dc <[^>]*> lbu \$at,[01]\(\$at\)
+0+02e0 <[^>]*> sll \$a0,\$a0,0x8
+0+02e4 <[^>]*> or \$a0,\$a0,\$at
+0+02e8 <[^>]*> lui \$at,0x0
+[ ]*2e8: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+02ec <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*2ec: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+02f0 <[^>]*> lb \$a0,[01]\(\$at\)
+0+02f4 <[^>]*> lbu \$at,[01]\(\$at\)
+0+02f8 <[^>]*> sll \$a0,\$a0,0x8
+0+02fc <[^>]*> or \$a0,\$a0,\$at
+0+0300 <[^>]*> lui \$at,0x0
+[ ]*300: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0304 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*304: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0308 <[^>]*> lb \$a0,[01]\(\$at\)
+0+030c <[^>]*> lbu \$at,[01]\(\$at\)
+0+0310 <[^>]*> sll \$a0,\$a0,0x8
+0+0314 <[^>]*> or \$a0,\$a0,\$at
+0+0318 <[^>]*> lui \$at,[-0-9x]+
+[ ]*318: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+031c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*31c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0320 <[^>]*> lb \$a0,[01]\(\$at\)
+0+0324 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0328 <[^>]*> sll \$a0,\$a0,0x8
+0+032c <[^>]*> or \$a0,\$a0,\$at
+0+0330 <[^>]*> lui \$at,[-0-9x]+
+[ ]*330: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0334 <[^>]*> addiu \$at,\$at,0
+[ ]*334: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0338 <[^>]*> lb \$a0,[01]\(\$at\)
+0+033c <[^>]*> lbu \$at,[01]\(\$at\)
+0+0340 <[^>]*> sll \$a0,\$a0,0x8
+0+0344 <[^>]*> or \$a0,\$a0,\$at
+0+0348 <[^>]*> lui \$at,[-0-9x]+
+[ ]*348: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+034c <[^>]*> addiu \$at,\$at,0
+[ ]*34c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0350 <[^>]*> lb \$a0,[01]\(\$at\)
+0+0354 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0358 <[^>]*> sll \$a0,\$a0,0x8
+0+035c <[^>]*> or \$a0,\$a0,\$at
+0+0360 <[^>]*> lui \$at,[-0-9x]+
+[ ]*360: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0364 <[^>]*> addiu \$at,\$at,0
+[ ]*364: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0368 <[^>]*> lb \$a0,[01]\(\$at\)
+0+036c <[^>]*> lbu \$at,[01]\(\$at\)
+0+0370 <[^>]*> sll \$a0,\$a0,0x8
+0+0374 <[^>]*> or \$a0,\$a0,\$at
+0+0378 <[^>]*> lui \$at,[-0-9x]+
+[ ]*378: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+037c <[^>]*> addiu \$at,\$at,0
+[ ]*37c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0380 <[^>]*> lb \$a0,[01]\(\$at\)
+0+0384 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0388 <[^>]*> sll \$a0,\$a0,0x8
+0+038c <[^>]*> or \$a0,\$a0,\$at
+0+0390 <[^>]*> lui \$at,[-0-9x]+
+[ ]*390: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0394 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*394: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0398 <[^>]*> lb \$a0,[01]\(\$at\)
+0+039c <[^>]*> lbu \$at,[01]\(\$at\)
+0+03a0 <[^>]*> sll \$a0,\$a0,0x8
+0+03a4 <[^>]*> or \$a0,\$a0,\$at
+0+03a8 <[^>]*> lui \$at,[-0-9x]+
+[ ]*3a8: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+03ac <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*3ac: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+03b0 <[^>]*> lb \$a0,[01]\(\$at\)
+0+03b4 <[^>]*> lbu \$at,[01]\(\$at\)
+0+03b8 <[^>]*> sll \$a0,\$a0,0x8
+0+03bc <[^>]*> or \$a0,\$a0,\$at
+0+03c0 <[^>]*> lui \$at,[-0-9x]+
+[ ]*3c0: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+03c4 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*3c4: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+03c8 <[^>]*> lb \$a0,[01]\(\$at\)
+0+03cc <[^>]*> lbu \$at,[01]\(\$at\)
+0+03d0 <[^>]*> sll \$a0,\$a0,0x8
+0+03d4 <[^>]*> or \$a0,\$a0,\$at
+0+03d8 <[^>]*> lui \$at,[-0-9x]+
+[ ]*3d8: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+03dc <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*3dc: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+03e0 <[^>]*> lb \$a0,[01]\(\$at\)
+0+03e4 <[^>]*> lbu \$at,[01]\(\$at\)
+0+03e8 <[^>]*> sll \$a0,\$a0,0x8
+0+03ec <[^>]*> or \$a0,\$a0,\$at
+0+03f0 <[^>]*> lui \$at,[-0-9x]+
+[ ]*3f0: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+03f4 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*3f4: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+03f8 <[^>]*> lb \$a0,[01]\(\$at\)
+0+03fc <[^>]*> lbu \$at,[01]\(\$at\)
+0+0400 <[^>]*> sll \$a0,\$a0,0x8
+0+0404 <[^>]*> or \$a0,\$a0,\$at
+0+0408 <[^>]*> lui \$at,[-0-9x]+
+[ ]*408: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+040c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*40c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0410 <[^>]*> lb \$a0,[01]\(\$at\)
+0+0414 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0418 <[^>]*> sll \$a0,\$a0,0x8
+0+041c <[^>]*> or \$a0,\$a0,\$at
+0+0420 <[^>]*> lui \$at,[-0-9x]+
+[ ]*420: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0424 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*424: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0428 <[^>]*> lb \$a0,[01]\(\$at\)
+0+042c <[^>]*> lbu \$at,[01]\(\$at\)
+0+0430 <[^>]*> sll \$a0,\$a0,0x8
+0+0434 <[^>]*> or \$a0,\$a0,\$at
+0+0438 <[^>]*> lui \$at,[-0-9x]+
+[ ]*438: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+043c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*43c: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0440 <[^>]*> lb \$a0,[01]\(\$at\)
+0+0444 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0448 <[^>]*> sll \$a0,\$a0,0x8
+0+044c <[^>]*> or \$a0,\$a0,\$at
+0+0450 <[^>]*> lui \$at,[-0-9x]+
+[ ]*450: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0454 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*454: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0458 <[^>]*> lb \$a0,[01]\(\$at\)
+0+045c <[^>]*> lbu \$at,[01]\(\$at\)
+0+0460 <[^>]*> sll \$a0,\$a0,0x8
+0+0464 <[^>]*> or \$a0,\$a0,\$at
+0+0468 <[^>]*> lbu \$a0,[01]\(\$zero\)
+0+046c <[^>]*> lbu \$at,[01]\(\$zero\)
+0+0470 <[^>]*> sll \$a0,\$a0,0x8
+0+0474 <[^>]*> or \$a0,\$a0,\$at
+ ...
diff --git a/gas/testsuite/gas/mips/ulh.s b/gas/testsuite/gas/mips/ulh.s
new file mode 100644
index 0000000000..26ecbb9473
--- /dev/null
+++ b/gas/testsuite/gas/mips/ulh.s
@@ -0,0 +1,69 @@
+# Source file used to test the ulh macro.
+
+ .data
+data_label:
+ .extern big_external_data_label,1000
+ .extern small_external_data_label,1
+ .comm big_external_common,1000
+ .comm small_external_common,1
+ .lcomm big_local_common,1000
+ .lcomm small_local_common,1
+
+ .text
+ ulh $4,0
+ ulh $4,1
+ ulh $4,0x8000
+ ulh $4,-0x8000
+ ulh $4,0x10000
+ ulh $4,0x1a5a5
+ ulh $4,0($5)
+ ulh $4,1($5)
+ ulh $4,data_label
+ ulh $4,big_external_data_label
+ ulh $4,small_external_data_label
+ ulh $4,big_external_common
+ ulh $4,small_external_common
+ ulh $4,big_local_common
+ ulh $4,small_local_common
+ ulh $4,data_label+1
+ ulh $4,big_external_data_label+1
+ ulh $4,small_external_data_label+1
+ ulh $4,big_external_common+1
+ ulh $4,small_external_common+1
+ ulh $4,big_local_common+1
+ ulh $4,small_local_common+1
+ ulh $4,data_label+0x8000
+ ulh $4,big_external_data_label+0x8000
+ ulh $4,small_external_data_label+0x8000
+ ulh $4,big_external_common+0x8000
+ ulh $4,small_external_common+0x8000
+ ulh $4,big_local_common+0x8000
+ ulh $4,small_local_common+0x8000
+ ulh $4,data_label-0x8000
+ ulh $4,big_external_data_label-0x8000
+ ulh $4,small_external_data_label-0x8000
+ ulh $4,big_external_common-0x8000
+ ulh $4,small_external_common-0x8000
+ ulh $4,big_local_common-0x8000
+ ulh $4,small_local_common-0x8000
+ ulh $4,data_label+0x10000
+ ulh $4,big_external_data_label+0x10000
+ ulh $4,small_external_data_label+0x10000
+ ulh $4,big_external_common+0x10000
+ ulh $4,small_external_common+0x10000
+ ulh $4,big_local_common+0x10000
+ ulh $4,small_local_common+0x10000
+ ulh $4,data_label+0x1a5a5
+ ulh $4,big_external_data_label+0x1a5a5
+ ulh $4,small_external_data_label+0x1a5a5
+ ulh $4,big_external_common+0x1a5a5
+ ulh $4,small_external_common+0x1a5a5
+ ulh $4,big_local_common+0x1a5a5
+ ulh $4,small_local_common+0x1a5a5
+
+# ulhu is handled like ulh. Sanity check it.
+ ulhu $4,0
+
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+ nop
+ nop
diff --git a/gas/testsuite/gas/mips/ulw.d b/gas/testsuite/gas/mips/ulw.d
new file mode 100644
index 0000000000..bfbdc94df0
--- /dev/null
+++ b/gas/testsuite/gas/mips/ulw.d
@@ -0,0 +1,270 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS ulw
+#as: -mips1
+
+# Test the ulw macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> lwl \$a0,[03]\(\$zero\)
+0+0004 <[^>]*> lwr \$a0,[03]\(\$zero\)
+0+0008 <[^>]*> lwl \$a0,[14]\(\$zero\)
+0+000c <[^>]*> lwr \$a0,[14]\(\$zero\)
+0+0010 <[^>]*> li \$at,0x8000
+0+0014 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0018 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+001c <[^>]*> lwl \$a0,-3276[58]\(\$zero\)
+0+0020 <[^>]*> lwr \$a0,-3276[58]\(\$zero\)
+0+0024 <[^>]*> lui \$at,0x1
+0+0028 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+002c <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0030 <[^>]*> lui \$at,0x1
+0+0034 <[^>]*> ori \$at,\$at,0xa5a5
+0+0038 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+003c <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0040 <[^>]*> lwl \$a0,[03]\(\$a1\)
+0+0044 <[^>]*> lwr \$a0,[03]\(\$a1\)
+0+0048 <[^>]*> lwl \$a0,[14]\(\$a1\)
+0+004c <[^>]*> lwr \$a0,[-0-9]+\(\$a1\)
+0+0050 <[^>]*> lui \$at,[-0-9x]+
+[ ]*50: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0054 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*54: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0058 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+005c <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0060 <[^>]*> lui \$at,0x0
+[ ]*60: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0064 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*64: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0068 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+006c <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0070 <[^>]*> addiu \$at,\$gp,0
+[ ]*70: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+0074 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0078 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+007c <[^>]*> lui \$at,0x0
+[ ]*7c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0080 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*80: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0084 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0088 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+008c <[^>]*> addiu \$at,\$gp,0
+[ ]*8c: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+0090 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0094 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0098 <[^>]*> lui \$at,[-0-9x]+
+[ ]*98: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+009c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*9c: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+00a0 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+00a4 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+00a8 <[^>]*> addiu \$at,\$gp,[-0-9]+
+[ ]*a8: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00ac <[^>]*> lwl \$a0,[03]\(\$at\)
+0+00b0 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+00b4 <[^>]*> lui \$at,0x0
+[ ]*b4: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+00b8 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*b8: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+00bc <[^>]*> lwl \$a0,[03]\(\$at\)
+0+00c0 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+00c4 <[^>]*> lui \$at,0x0
+[ ]*c4: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+00c8 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*c8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+00cc <[^>]*> lwl \$a0,[03]\(\$at\)
+0+00d0 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+00d4 <[^>]*> addiu \$at,\$gp,1
+[ ]*d4: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00d8 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+00dc <[^>]*> lwr \$a0,[03]\(\$at\)
+0+00e0 <[^>]*> lui \$at,0x0
+[ ]*e0: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+00e4 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*e4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+00e8 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+00ec <[^>]*> lwr \$a0,[03]\(\$at\)
+0+00f0 <[^>]*> addiu \$at,\$gp,1
+[ ]*f0: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+00f4 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+00f8 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+00fc <[^>]*> lui \$at,0x0
+[ ]*fc: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0100 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*100: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0104 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0108 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+010c <[^>]*> addiu \$at,\$gp,[-0-9]+
+[ ]*10c: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0110 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0114 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0118 <[^>]*> lui \$at,[-0-9x]+
+[ ]*118: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+011c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*11c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0120 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0124 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0128 <[^>]*> lui \$at,[-0-9x]+
+[ ]*128: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+012c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*12c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0130 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0134 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0138 <[^>]*> lui \$at,[-0-9x]+
+[ ]*138: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+013c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*13c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0140 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0144 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0148 <[^>]*> lui \$at,[-0-9x]+
+[ ]*148: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+014c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*14c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0150 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0154 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0158 <[^>]*> lui \$at,[-0-9x]+
+[ ]*158: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+015c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*15c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0160 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0164 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0168 <[^>]*> lui \$at,[-0-9x]+
+[ ]*168: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+016c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*16c: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0170 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0174 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0178 <[^>]*> lui \$at,[-0-9x]+
+[ ]*178: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+017c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*17c: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0180 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0184 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0188 <[^>]*> lui \$at,0x0
+[ ]*188: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+018c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*18c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0190 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0194 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0198 <[^>]*> lui \$at,0x0
+[ ]*198: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+019c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*19c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+01a0 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+01a4 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+01a8 <[^>]*> lui \$at,0x0
+[ ]*1a8: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+01ac <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*1ac: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+01b0 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+01b4 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+01b8 <[^>]*> lui \$at,0x0
+[ ]*1b8: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+01bc <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*1bc: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+01c0 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+01c4 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+01c8 <[^>]*> lui \$at,0x0
+[ ]*1c8: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+01cc <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*1cc: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+01d0 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+01d4 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+01d8 <[^>]*> lui \$at,0x0
+[ ]*1d8: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+01dc <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*1dc: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+01e0 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+01e4 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+01e8 <[^>]*> lui \$at,0x0
+[ ]*1e8: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+01ec <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*1ec: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+01f0 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+01f4 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+01f8 <[^>]*> lui \$at,[-0-9x]+
+[ ]*1f8: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+01fc <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*1fc: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0200 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0204 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0208 <[^>]*> lui \$at,[-0-9x]+
+[ ]*208: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+020c <[^>]*> addiu \$at,\$at,0
+[ ]*20c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0210 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0214 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0218 <[^>]*> lui \$at,[-0-9x]+
+[ ]*218: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+021c <[^>]*> addiu \$at,\$at,0
+[ ]*21c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0220 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0224 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0228 <[^>]*> lui \$at,[-0-9x]+
+[ ]*228: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+022c <[^>]*> addiu \$at,\$at,0
+[ ]*22c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0230 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0234 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0238 <[^>]*> lui \$at,[-0-9x]+
+[ ]*238: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+023c <[^>]*> addiu \$at,\$at,0
+[ ]*23c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0240 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0244 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0248 <[^>]*> lui \$at,[-0-9x]+
+[ ]*248: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+024c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*24c: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0250 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0254 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0258 <[^>]*> lui \$at,[-0-9x]+
+[ ]*258: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+025c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*25c: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0260 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0264 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0268 <[^>]*> lui \$at,[-0-9x]+
+[ ]*268: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+026c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*26c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0270 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0274 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0278 <[^>]*> lui \$at,[-0-9x]+
+[ ]*278: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+027c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*27c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0280 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0284 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0288 <[^>]*> lui \$at,[-0-9x]+
+[ ]*288: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+028c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*28c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0290 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+0294 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+0298 <[^>]*> lui \$at,[-0-9x]+
+[ ]*298: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+029c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*29c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+02a0 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+02a4 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+02a8 <[^>]*> lui \$at,[-0-9x]+
+[ ]*2a8: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+02ac <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*2ac: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+02b0 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+02b4 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+02b8 <[^>]*> lui \$at,[-0-9x]+
+[ ]*2b8: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+02bc <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*2bc: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+02c0 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+02c4 <[^>]*> lwr \$a0,[03]\(\$at\)
+0+02c8 <[^>]*> lui \$at,[-0-9x]+
+[ ]*2c8: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+02cc <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*2cc: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+02d0 <[^>]*> lwl \$a0,[03]\(\$at\)
+0+02d4 <[^>]*> lwr \$a0,[03]\(\$at\)
+ ...
diff --git a/gas/testsuite/gas/mips/ulw.s b/gas/testsuite/gas/mips/ulw.s
new file mode 100644
index 0000000000..3a36f1c0b5
--- /dev/null
+++ b/gas/testsuite/gas/mips/ulw.s
@@ -0,0 +1,66 @@
+# Source file used to test the ulw macro.
+
+ .data
+data_label:
+ .extern big_external_data_label,1000
+ .extern small_external_data_label,1
+ .comm big_external_common,1000
+ .comm small_external_common,1
+ .lcomm big_local_common,1000
+ .lcomm small_local_common,1
+
+ .text
+ ulw $4,0
+ ulw $4,1
+ ulw $4,0x8000
+ ulw $4,-0x8000
+ ulw $4,0x10000
+ ulw $4,0x1a5a5
+ ulw $4,0($5)
+ ulw $4,1($5)
+ ulw $4,data_label
+ ulw $4,big_external_data_label
+ ulw $4,small_external_data_label
+ ulw $4,big_external_common
+ ulw $4,small_external_common
+ ulw $4,big_local_common
+ ulw $4,small_local_common
+ ulw $4,data_label+1
+ ulw $4,big_external_data_label+1
+ ulw $4,small_external_data_label+1
+ ulw $4,big_external_common+1
+ ulw $4,small_external_common+1
+ ulw $4,big_local_common+1
+ ulw $4,small_local_common+1
+ ulw $4,data_label+0x8000
+ ulw $4,big_external_data_label+0x8000
+ ulw $4,small_external_data_label+0x8000
+ ulw $4,big_external_common+0x8000
+ ulw $4,small_external_common+0x8000
+ ulw $4,big_local_common+0x8000
+ ulw $4,small_local_common+0x8000
+ ulw $4,data_label-0x8000
+ ulw $4,big_external_data_label-0x8000
+ ulw $4,small_external_data_label-0x8000
+ ulw $4,big_external_common-0x8000
+ ulw $4,small_external_common-0x8000
+ ulw $4,big_local_common-0x8000
+ ulw $4,small_local_common-0x8000
+ ulw $4,data_label+0x10000
+ ulw $4,big_external_data_label+0x10000
+ ulw $4,small_external_data_label+0x10000
+ ulw $4,big_external_common+0x10000
+ ulw $4,small_external_common+0x10000
+ ulw $4,big_local_common+0x10000
+ ulw $4,small_local_common+0x10000
+ ulw $4,data_label+0x1a5a5
+ ulw $4,big_external_data_label+0x1a5a5
+ ulw $4,small_external_data_label+0x1a5a5
+ ulw $4,big_external_common+0x1a5a5
+ ulw $4,small_external_common+0x1a5a5
+ ulw $4,big_local_common+0x1a5a5
+ ulw $4,small_local_common+0x1a5a5
+
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+ nop
+ nop
diff --git a/gas/testsuite/gas/mips/usd.d b/gas/testsuite/gas/mips/usd.d
new file mode 100644
index 0000000000..63c0b73b63
--- /dev/null
+++ b/gas/testsuite/gas/mips/usd.d
@@ -0,0 +1,270 @@
+#objdump: -dr --prefix-addresses -mmips:4000
+#name: MIPS usd
+#as: -mips3 -mcpu=r4000
+
+# Test the usd macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> sdl \$a0,[07]\(\$zero\)
+0+0004 <[^>]*> sdr \$a0,[07]\(\$zero\)
+0+0008 <[^>]*> sdl \$a0,[18]\(\$zero\)
+0+000c <[^>]*> sdr \$a0,[18]\(\$zero\)
+0+0010 <[^>]*> li \$at,0x8000
+0+0014 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+0018 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+001c <[^>]*> sdl \$a0,-3276[18]\(\$zero\)
+0+0020 <[^>]*> sdr \$a0,-3276[18]\(\$zero\)
+0+0024 <[^>]*> lui \$at,0x1
+0+0028 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+002c <[^>]*> sdr \$a0,[07]\(\$at\)
+0+0030 <[^>]*> lui \$at,0x1
+0+0034 <[^>]*> ori \$at,\$at,0xa5a5
+0+0038 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+003c <[^>]*> sdr \$a0,[07]\(\$at\)
+0+0040 <[^>]*> sdl \$a0,[07]\(\$a1\)
+0+0044 <[^>]*> sdr \$a0,[07]\(\$a1\)
+0+0048 <[^>]*> sdl \$a0,[18]\(\$a1\)
+0+004c <[^>]*> sdr \$a0,[-0-9]+\(\$a1\)
+0+0050 <[^>]*> lui \$at,[-0-9x]+
+[ ]*50: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0054 <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*54: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0058 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+005c <[^>]*> sdr \$a0,[07]\(\$at\)
+0+0060 <[^>]*> lui \$at,[-0-9x]+
+[ ]*60: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0064 <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*64: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0068 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+006c <[^>]*> sdr \$a0,[07]\(\$at\)
+0+0070 <[^>]*> daddiu \$at,\$gp,0
+[ ]*70: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+0074 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+0078 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+007c <[^>]*> lui \$at,0x0
+[ ]*7c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0080 <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*80: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0084 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+0088 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+008c <[^>]*> daddiu \$at,\$gp,0
+[ ]*8c: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+0090 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+0094 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+0098 <[^>]*> lui \$at,[-0-9x]+
+[ ]*98: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+009c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*9c: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+00a0 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+00a4 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+00a8 <[^>]*> daddiu \$at,\$gp,[-0-9]+
+[ ]*a8: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00ac <[^>]*> sdl \$a0,[07]\(\$at\)
+0+00b0 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+00b4 <[^>]*> lui \$at,0x0
+[ ]*b4: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+00b8 <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*b8: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+00bc <[^>]*> sdl \$a0,[07]\(\$at\)
+0+00c0 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+00c4 <[^>]*> lui \$at,0x0
+[ ]*c4: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+00c8 <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*c8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+00cc <[^>]*> sdl \$a0,[07]\(\$at\)
+0+00d0 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+00d4 <[^>]*> daddiu \$at,\$gp,1
+[ ]*d4: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00d8 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+00dc <[^>]*> sdr \$a0,[07]\(\$at\)
+0+00e0 <[^>]*> lui \$at,0x0
+[ ]*e0: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+00e4 <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*e4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+00e8 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+00ec <[^>]*> sdr \$a0,[07]\(\$at\)
+0+00f0 <[^>]*> daddiu \$at,\$gp,1
+[ ]*f0: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+00f4 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+00f8 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+00fc <[^>]*> lui \$at,0x0
+[ ]*fc: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0100 <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*100: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0104 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+0108 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+010c <[^>]*> daddiu \$at,\$gp,[-0-9]+
+[ ]*10c: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0110 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+0114 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+0118 <[^>]*> lui \$at,[-0-9x]+
+[ ]*118: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+011c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*11c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0120 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+0124 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+0128 <[^>]*> lui \$at,[-0-9x]+
+[ ]*128: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+012c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*12c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0130 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+0134 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+0138 <[^>]*> lui \$at,[-0-9x]+
+[ ]*138: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+013c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*13c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0140 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+0144 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+0148 <[^>]*> lui \$at,[-0-9x]+
+[ ]*148: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+014c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*14c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0150 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+0154 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+0158 <[^>]*> lui \$at,[-0-9x]+
+[ ]*158: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+015c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*15c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0160 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+0164 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+0168 <[^>]*> lui \$at,[-0-9x]+
+[ ]*168: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+016c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*16c: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0170 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+0174 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+0178 <[^>]*> lui \$at,[-0-9x]+
+[ ]*178: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+017c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*17c: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0180 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+0184 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+0188 <[^>]*> lui \$at,0x0
+[ ]*188: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+018c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*18c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0190 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+0194 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+0198 <[^>]*> lui \$at,0x0
+[ ]*198: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+019c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*19c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+01a0 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+01a4 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+01a8 <[^>]*> lui \$at,0x0
+[ ]*1a8: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+01ac <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*1ac: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+01b0 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+01b4 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+01b8 <[^>]*> lui \$at,0x0
+[ ]*1b8: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+01bc <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*1bc: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+01c0 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+01c4 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+01c8 <[^>]*> lui \$at,0x0
+[ ]*1c8: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+01cc <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*1cc: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+01d0 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+01d4 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+01d8 <[^>]*> lui \$at,0x0
+[ ]*1d8: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+01dc <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*1dc: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+01e0 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+01e4 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+01e8 <[^>]*> lui \$at,0x0
+[ ]*1e8: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+01ec <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*1ec: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+01f0 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+01f4 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+01f8 <[^>]*> lui \$at,[-0-9x]+
+[ ]*1f8: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+01fc <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*1fc: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0200 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+0204 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+0208 <[^>]*> lui \$at,[-0-9x]+
+[ ]*208: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+020c <[^>]*> daddiu \$at,\$at,0
+[ ]*20c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0210 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+0214 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+0218 <[^>]*> lui \$at,[-0-9x]+
+[ ]*218: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+021c <[^>]*> daddiu \$at,\$at,0
+[ ]*21c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0220 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+0224 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+0228 <[^>]*> lui \$at,[-0-9x]+
+[ ]*228: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+022c <[^>]*> daddiu \$at,\$at,0
+[ ]*22c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0230 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+0234 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+0238 <[^>]*> lui \$at,[-0-9x]+
+[ ]*238: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+023c <[^>]*> daddiu \$at,\$at,0
+[ ]*23c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0240 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+0244 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+0248 <[^>]*> lui \$at,[-0-9x]+
+[ ]*248: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+024c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*24c: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0250 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+0254 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+0258 <[^>]*> lui \$at,[-0-9x]+
+[ ]*258: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+025c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*25c: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0260 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+0264 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+0268 <[^>]*> lui \$at,[-0-9x]+
+[ ]*268: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+026c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*26c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0270 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+0274 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+0278 <[^>]*> lui \$at,[-0-9x]+
+[ ]*278: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+027c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*27c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0280 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+0284 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+0288 <[^>]*> lui \$at,[-0-9x]+
+[ ]*288: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+028c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*28c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0290 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+0294 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+0298 <[^>]*> lui \$at,[-0-9x]+
+[ ]*298: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+029c <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*29c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+02a0 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+02a4 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+02a8 <[^>]*> lui \$at,[-0-9x]+
+[ ]*2a8: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+02ac <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*2ac: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+02b0 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+02b4 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+02b8 <[^>]*> lui \$at,[-0-9x]+
+[ ]*2b8: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+02bc <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*2bc: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+02c0 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+02c4 <[^>]*> sdr \$a0,[07]\(\$at\)
+0+02c8 <[^>]*> lui \$at,[-0-9x]+
+[ ]*2c8: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+02cc <[^>]*> daddiu \$at,\$at,[-0-9]+
+[ ]*2cc: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+02d0 <[^>]*> sdl \$a0,[07]\(\$at\)
+0+02d4 <[^>]*> sdr \$a0,[07]\(\$at\)
+ ...
diff --git a/gas/testsuite/gas/mips/usd.s b/gas/testsuite/gas/mips/usd.s
new file mode 100644
index 0000000000..fd367351b7
--- /dev/null
+++ b/gas/testsuite/gas/mips/usd.s
@@ -0,0 +1,66 @@
+# Source file used to test the usd macro.
+
+ .data
+data_label:
+ .extern big_external_data_label,1000
+ .extern small_external_data_label,1
+ .comm big_external_common,1000
+ .comm small_external_common,1
+ .lcomm big_local_common,1000
+ .lcomm small_local_common,1
+
+ .text
+ usd $4,0
+ usd $4,1
+ usd $4,0x8000
+ usd $4,-0x8000
+ usd $4,0x10000
+ usd $4,0x1a5a5
+ usd $4,0($5)
+ usd $4,1($5)
+ usd $4,data_label
+ usd $4,big_external_data_label
+ usd $4,small_external_data_label
+ usd $4,big_external_common
+ usd $4,small_external_common
+ usd $4,big_local_common
+ usd $4,small_local_common
+ usd $4,data_label+1
+ usd $4,big_external_data_label+1
+ usd $4,small_external_data_label+1
+ usd $4,big_external_common+1
+ usd $4,small_external_common+1
+ usd $4,big_local_common+1
+ usd $4,small_local_common+1
+ usd $4,data_label+0x8000
+ usd $4,big_external_data_label+0x8000
+ usd $4,small_external_data_label+0x8000
+ usd $4,big_external_common+0x8000
+ usd $4,small_external_common+0x8000
+ usd $4,big_local_common+0x8000
+ usd $4,small_local_common+0x8000
+ usd $4,data_label-0x8000
+ usd $4,big_external_data_label-0x8000
+ usd $4,small_external_data_label-0x8000
+ usd $4,big_external_common-0x8000
+ usd $4,small_external_common-0x8000
+ usd $4,big_local_common-0x8000
+ usd $4,small_local_common-0x8000
+ usd $4,data_label+0x10000
+ usd $4,big_external_data_label+0x10000
+ usd $4,small_external_data_label+0x10000
+ usd $4,big_external_common+0x10000
+ usd $4,small_external_common+0x10000
+ usd $4,big_local_common+0x10000
+ usd $4,small_local_common+0x10000
+ usd $4,data_label+0x1a5a5
+ usd $4,big_external_data_label+0x1a5a5
+ usd $4,small_external_data_label+0x1a5a5
+ usd $4,big_external_common+0x1a5a5
+ usd $4,small_external_common+0x1a5a5
+ usd $4,big_local_common+0x1a5a5
+ usd $4,small_local_common+0x1a5a5
+
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+ nop
+ nop
diff --git a/gas/testsuite/gas/mips/ush.d b/gas/testsuite/gas/mips/ush.d
new file mode 100644
index 0000000000..c2f0a12eb7
--- /dev/null
+++ b/gas/testsuite/gas/mips/ush.d
@@ -0,0 +1,455 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS ush
+#as: -mips1
+
+# Test the ush macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> sb \$a0,[01]\(\$zero\)
+0+0004 <[^>]*> srl \$at,\$a0,0x8
+0+0008 <[^>]*> sb \$at,[01]\(\$zero\)
+0+000c <[^>]*> sb \$a0,[12]\(\$zero\)
+0+0010 <[^>]*> srl \$at,\$a0,0x8
+0+0014 <[^>]*> sb \$at,[12]\(\$zero\)
+0+0018 <[^>]*> li \$at,0x8000
+0+001c <[^>]*> sb \$a0,[01]\(\$at\)
+0+0020 <[^>]*> srl \$a0,\$a0,0x8
+0+0024 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0028 <[^>]*> lbu \$at,[01]\(\$at\)
+0+002c <[^>]*> sll \$a0,\$a0,0x8
+0+0030 <[^>]*> or \$a0,\$a0,\$at
+0+0034 <[^>]*> sb \$a0,-3276[78]\(\$zero\)
+0+0038 <[^>]*> srl \$at,\$a0,0x8
+0+003c <[^>]*> sb \$at,-3276[78]\(\$zero\)
+0+0040 <[^>]*> lui \$at,0x1
+0+0044 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0048 <[^>]*> srl \$a0,\$a0,0x8
+0+004c <[^>]*> sb \$a0,[01]\(\$at\)
+0+0050 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0054 <[^>]*> sll \$a0,\$a0,0x8
+0+0058 <[^>]*> or \$a0,\$a0,\$at
+0+005c <[^>]*> lui \$at,0x1
+0+0060 <[^>]*> ori \$at,\$at,0xa5a5
+0+0064 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0068 <[^>]*> srl \$a0,\$a0,0x8
+0+006c <[^>]*> sb \$a0,[01]\(\$at\)
+0+0070 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0074 <[^>]*> sll \$a0,\$a0,0x8
+0+0078 <[^>]*> or \$a0,\$a0,\$at
+0+007c <[^>]*> sb \$a0,[01]\(\$a1\)
+0+0080 <[^>]*> srl \$at,\$a0,0x8
+0+0084 <[^>]*> sb \$at,[01]\(\$a1\)
+0+0088 <[^>]*> sb \$a0,[12]\(\$a1\)
+0+008c <[^>]*> srl \$at,\$a0,0x8
+0+0090 <[^>]*> sb \$at,[12]\(\$a1\)
+0+0094 <[^>]*> lui \$at,[-0-9x]+
+[ ]*94: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0098 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*98: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+009c <[^>]*> sb \$a0,[01]\(\$at\)
+0+00a0 <[^>]*> srl \$a0,\$a0,0x8
+0+00a4 <[^>]*> sb \$a0,[01]\(\$at\)
+0+00a8 <[^>]*> lbu \$at,[01]\(\$at\)
+0+00ac <[^>]*> sll \$a0,\$a0,0x8
+0+00b0 <[^>]*> or \$a0,\$a0,\$at
+0+00b4 <[^>]*> lui \$at,0x0
+[ ]*b4: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+00b8 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*b8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+00bc <[^>]*> sb \$a0,[01]\(\$at\)
+0+00c0 <[^>]*> srl \$a0,\$a0,0x8
+0+00c4 <[^>]*> sb \$a0,[01]\(\$at\)
+0+00c8 <[^>]*> lbu \$at,[01]\(\$at\)
+0+00cc <[^>]*> sll \$a0,\$a0,0x8
+0+00d0 <[^>]*> or \$a0,\$a0,\$at
+0+00d4 <[^>]*> addiu \$at,\$gp,0
+[ ]*d4: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00d8 <[^>]*> sb \$a0,[01]\(\$at\)
+0+00dc <[^>]*> srl \$a0,\$a0,0x8
+0+00e0 <[^>]*> sb \$a0,[01]\(\$at\)
+0+00e4 <[^>]*> lbu \$at,[01]\(\$at\)
+0+00e8 <[^>]*> sll \$a0,\$a0,0x8
+0+00ec <[^>]*> or \$a0,\$a0,\$at
+0+00f0 <[^>]*> lui \$at,[-0-9x]+
+[ ]*f0: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+00f4 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*f4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+00f8 <[^>]*> sb \$a0,[01]\(\$at\)
+0+00fc <[^>]*> srl \$a0,\$a0,0x8
+0+0100 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0104 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0108 <[^>]*> sll \$a0,\$a0,0x8
+0+010c <[^>]*> or \$a0,\$a0,\$at
+0+0110 <[^>]*> addiu \$at,\$gp,0
+[ ]*110: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+0114 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0118 <[^>]*> srl \$a0,\$a0,0x8
+0+011c <[^>]*> sb \$a0,[01]\(\$at\)
+0+0120 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0124 <[^>]*> sll \$a0,\$a0,0x8
+0+0128 <[^>]*> or \$a0,\$a0,\$at
+0+012c <[^>]*> lui \$at,[-0-9x]+
+[ ]*12c: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0130 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*130: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0134 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0138 <[^>]*> srl \$a0,\$a0,0x8
+0+013c <[^>]*> sb \$a0,[01]\(\$at\)
+0+0140 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0144 <[^>]*> sll \$a0,\$a0,0x8
+0+0148 <[^>]*> or \$a0,\$a0,\$at
+0+014c <[^>]*> addiu \$at,\$gp,[-0-9]+
+[ ]*14c: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0150 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0154 <[^>]*> srl \$a0,\$a0,0x8
+0+0158 <[^>]*> sb \$a0,[01]\(\$at\)
+0+015c <[^>]*> lbu \$at,[01]\(\$at\)
+0+0160 <[^>]*> sll \$a0,\$a0,0x8
+0+0164 <[^>]*> or \$a0,\$a0,\$at
+0+0168 <[^>]*> lui \$at,0x0
+[ ]*168: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+016c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*16c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0170 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0174 <[^>]*> srl \$a0,\$a0,0x8
+0+0178 <[^>]*> sb \$a0,[01]\(\$at\)
+0+017c <[^>]*> lbu \$at,[01]\(\$at\)
+0+0180 <[^>]*> sll \$a0,\$a0,0x8
+0+0184 <[^>]*> or \$a0,\$a0,\$at
+0+0188 <[^>]*> lui \$at,0x0
+[ ]*188: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+018c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*18c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0190 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0194 <[^>]*> srl \$a0,\$a0,0x8
+0+0198 <[^>]*> sb \$a0,[01]\(\$at\)
+0+019c <[^>]*> lbu \$at,[01]\(\$at\)
+0+01a0 <[^>]*> sll \$a0,\$a0,0x8
+0+01a4 <[^>]*> or \$a0,\$a0,\$at
+0+01a8 <[^>]*> addiu \$at,\$gp,1
+[ ]*1a8: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+01ac <[^>]*> sb \$a0,[01]\(\$at\)
+0+01b0 <[^>]*> srl \$a0,\$a0,0x8
+0+01b4 <[^>]*> sb \$a0,[01]\(\$at\)
+0+01b8 <[^>]*> lbu \$at,[01]\(\$at\)
+0+01bc <[^>]*> sll \$a0,\$a0,0x8
+0+01c0 <[^>]*> or \$a0,\$a0,\$at
+0+01c4 <[^>]*> lui \$at,0x0
+[ ]*1c4: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+01c8 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*1c8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+01cc <[^>]*> sb \$a0,[01]\(\$at\)
+0+01d0 <[^>]*> srl \$a0,\$a0,0x8
+0+01d4 <[^>]*> sb \$a0,[01]\(\$at\)
+0+01d8 <[^>]*> lbu \$at,[01]\(\$at\)
+0+01dc <[^>]*> sll \$a0,\$a0,0x8
+0+01e0 <[^>]*> or \$a0,\$a0,\$at
+0+01e4 <[^>]*> addiu \$at,\$gp,1
+[ ]*1e4: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+01e8 <[^>]*> sb \$a0,[01]\(\$at\)
+0+01ec <[^>]*> srl \$a0,\$a0,0x8
+0+01f0 <[^>]*> sb \$a0,[01]\(\$at\)
+0+01f4 <[^>]*> lbu \$at,[01]\(\$at\)
+0+01f8 <[^>]*> sll \$a0,\$a0,0x8
+0+01fc <[^>]*> or \$a0,\$a0,\$at
+0+0200 <[^>]*> lui \$at,0x0
+[ ]*200: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0204 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*204: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0208 <[^>]*> sb \$a0,[01]\(\$at\)
+0+020c <[^>]*> srl \$a0,\$a0,0x8
+0+0210 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0214 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0218 <[^>]*> sll \$a0,\$a0,0x8
+0+021c <[^>]*> or \$a0,\$a0,\$at
+0+0220 <[^>]*> addiu \$at,\$gp,[-0-9]+
+[ ]*220: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0224 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0228 <[^>]*> srl \$a0,\$a0,0x8
+0+022c <[^>]*> sb \$a0,[01]\(\$at\)
+0+0230 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0234 <[^>]*> sll \$a0,\$a0,0x8
+0+0238 <[^>]*> or \$a0,\$a0,\$at
+0+023c <[^>]*> lui \$at,[-0-9x]+
+[ ]*23c: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0240 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*240: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0244 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0248 <[^>]*> srl \$a0,\$a0,0x8
+0+024c <[^>]*> sb \$a0,[01]\(\$at\)
+0+0250 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0254 <[^>]*> sll \$a0,\$a0,0x8
+0+0258 <[^>]*> or \$a0,\$a0,\$at
+0+025c <[^>]*> lui \$at,[-0-9x]+
+[ ]*25c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0260 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*260: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0264 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0268 <[^>]*> srl \$a0,\$a0,0x8
+0+026c <[^>]*> sb \$a0,[01]\(\$at\)
+0+0270 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0274 <[^>]*> sll \$a0,\$a0,0x8
+0+0278 <[^>]*> or \$a0,\$a0,\$at
+0+027c <[^>]*> lui \$at,[-0-9x]+
+[ ]*27c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0280 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*280: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0284 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0288 <[^>]*> srl \$a0,\$a0,0x8
+0+028c <[^>]*> sb \$a0,[01]\(\$at\)
+0+0290 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0294 <[^>]*> sll \$a0,\$a0,0x8
+0+0298 <[^>]*> or \$a0,\$a0,\$at
+0+029c <[^>]*> lui \$at,[-0-9x]+
+[ ]*29c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+02a0 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*2a0: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+02a4 <[^>]*> sb \$a0,[01]\(\$at\)
+0+02a8 <[^>]*> srl \$a0,\$a0,0x8
+0+02ac <[^>]*> sb \$a0,[01]\(\$at\)
+0+02b0 <[^>]*> lbu \$at,[01]\(\$at\)
+0+02b4 <[^>]*> sll \$a0,\$a0,0x8
+0+02b8 <[^>]*> or \$a0,\$a0,\$at
+0+02bc <[^>]*> lui \$at,[-0-9x]+
+[ ]*2bc: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+02c0 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*2c0: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+02c4 <[^>]*> sb \$a0,[01]\(\$at\)
+0+02c8 <[^>]*> srl \$a0,\$a0,0x8
+0+02cc <[^>]*> sb \$a0,[01]\(\$at\)
+0+02d0 <[^>]*> lbu \$at,[01]\(\$at\)
+0+02d4 <[^>]*> sll \$a0,\$a0,0x8
+0+02d8 <[^>]*> or \$a0,\$a0,\$at
+0+02dc <[^>]*> lui \$at,[-0-9x]+
+[ ]*2dc: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+02e0 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*2e0: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+02e4 <[^>]*> sb \$a0,[01]\(\$at\)
+0+02e8 <[^>]*> srl \$a0,\$a0,0x8
+0+02ec <[^>]*> sb \$a0,[01]\(\$at\)
+0+02f0 <[^>]*> lbu \$at,[01]\(\$at\)
+0+02f4 <[^>]*> sll \$a0,\$a0,0x8
+0+02f8 <[^>]*> or \$a0,\$a0,\$at
+0+02fc <[^>]*> lui \$at,[-0-9x]+
+[ ]*2fc: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+0300 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*300: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0304 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0308 <[^>]*> srl \$a0,\$a0,0x8
+0+030c <[^>]*> sb \$a0,[01]\(\$at\)
+0+0310 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0314 <[^>]*> sll \$a0,\$a0,0x8
+0+0318 <[^>]*> or \$a0,\$a0,\$at
+0+031c <[^>]*> lui \$at,0x0
+[ ]*31c: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0320 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*320: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0324 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0328 <[^>]*> srl \$a0,\$a0,0x8
+0+032c <[^>]*> sb \$a0,[01]\(\$at\)
+0+0330 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0334 <[^>]*> sll \$a0,\$a0,0x8
+0+0338 <[^>]*> or \$a0,\$a0,\$at
+0+033c <[^>]*> lui \$at,0x0
+[ ]*33c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0340 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*340: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0344 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0348 <[^>]*> srl \$a0,\$a0,0x8
+0+034c <[^>]*> sb \$a0,[01]\(\$at\)
+0+0350 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0354 <[^>]*> sll \$a0,\$a0,0x8
+0+0358 <[^>]*> or \$a0,\$a0,\$at
+0+035c <[^>]*> lui \$at,0x0
+[ ]*35c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0360 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*360: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0364 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0368 <[^>]*> srl \$a0,\$a0,0x8
+0+036c <[^>]*> sb \$a0,[01]\(\$at\)
+0+0370 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0374 <[^>]*> sll \$a0,\$a0,0x8
+0+0378 <[^>]*> or \$a0,\$a0,\$at
+0+037c <[^>]*> lui \$at,0x0
+[ ]*37c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0380 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*380: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0384 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0388 <[^>]*> srl \$a0,\$a0,0x8
+0+038c <[^>]*> sb \$a0,[01]\(\$at\)
+0+0390 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0394 <[^>]*> sll \$a0,\$a0,0x8
+0+0398 <[^>]*> or \$a0,\$a0,\$at
+0+039c <[^>]*> lui \$at,0x0
+[ ]*39c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+03a0 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*3a0: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+03a4 <[^>]*> sb \$a0,[01]\(\$at\)
+0+03a8 <[^>]*> srl \$a0,\$a0,0x8
+0+03ac <[^>]*> sb \$a0,[01]\(\$at\)
+0+03b0 <[^>]*> lbu \$at,[01]\(\$at\)
+0+03b4 <[^>]*> sll \$a0,\$a0,0x8
+0+03b8 <[^>]*> or \$a0,\$a0,\$at
+0+03bc <[^>]*> lui \$at,0x0
+[ ]*3bc: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+03c0 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*3c0: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+03c4 <[^>]*> sb \$a0,[01]\(\$at\)
+0+03c8 <[^>]*> srl \$a0,\$a0,0x8
+0+03cc <[^>]*> sb \$a0,[01]\(\$at\)
+0+03d0 <[^>]*> lbu \$at,[01]\(\$at\)
+0+03d4 <[^>]*> sll \$a0,\$a0,0x8
+0+03d8 <[^>]*> or \$a0,\$a0,\$at
+0+03dc <[^>]*> lui \$at,0x0
+[ ]*3dc: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+03e0 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*3e0: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+03e4 <[^>]*> sb \$a0,[01]\(\$at\)
+0+03e8 <[^>]*> srl \$a0,\$a0,0x8
+0+03ec <[^>]*> sb \$a0,[01]\(\$at\)
+0+03f0 <[^>]*> lbu \$at,[01]\(\$at\)
+0+03f4 <[^>]*> sll \$a0,\$a0,0x8
+0+03f8 <[^>]*> or \$a0,\$a0,\$at
+0+03fc <[^>]*> lui \$at,[-0-9x]+
+[ ]*3fc: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0400 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*400: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0404 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0408 <[^>]*> srl \$a0,\$a0,0x8
+0+040c <[^>]*> sb \$a0,[01]\(\$at\)
+0+0410 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0414 <[^>]*> sll \$a0,\$a0,0x8
+0+0418 <[^>]*> or \$a0,\$a0,\$at
+0+041c <[^>]*> lui \$at,[-0-9x]+
+[ ]*41c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0420 <[^>]*> addiu \$at,\$at,0
+[ ]*420: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0424 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0428 <[^>]*> srl \$a0,\$a0,0x8
+0+042c <[^>]*> sb \$a0,[01]\(\$at\)
+0+0430 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0434 <[^>]*> sll \$a0,\$a0,0x8
+0+0438 <[^>]*> or \$a0,\$a0,\$at
+0+043c <[^>]*> lui \$at,[-0-9x]+
+[ ]*43c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0440 <[^>]*> addiu \$at,\$at,0
+[ ]*440: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0444 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0448 <[^>]*> srl \$a0,\$a0,0x8
+0+044c <[^>]*> sb \$a0,[01]\(\$at\)
+0+0450 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0454 <[^>]*> sll \$a0,\$a0,0x8
+0+0458 <[^>]*> or \$a0,\$a0,\$at
+0+045c <[^>]*> lui \$at,[-0-9x]+
+[ ]*45c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0460 <[^>]*> addiu \$at,\$at,0
+[ ]*460: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0464 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0468 <[^>]*> srl \$a0,\$a0,0x8
+0+046c <[^>]*> sb \$a0,[01]\(\$at\)
+0+0470 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0474 <[^>]*> sll \$a0,\$a0,0x8
+0+0478 <[^>]*> or \$a0,\$a0,\$at
+0+047c <[^>]*> lui \$at,[-0-9x]+
+[ ]*47c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0480 <[^>]*> addiu \$at,\$at,0
+[ ]*480: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0484 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0488 <[^>]*> srl \$a0,\$a0,0x8
+0+048c <[^>]*> sb \$a0,[01]\(\$at\)
+0+0490 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0494 <[^>]*> sll \$a0,\$a0,0x8
+0+0498 <[^>]*> or \$a0,\$a0,\$at
+0+049c <[^>]*> lui \$at,[-0-9x]+
+[ ]*49c: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+04a0 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*4a0: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+04a4 <[^>]*> sb \$a0,[01]\(\$at\)
+0+04a8 <[^>]*> srl \$a0,\$a0,0x8
+0+04ac <[^>]*> sb \$a0,[01]\(\$at\)
+0+04b0 <[^>]*> lbu \$at,[01]\(\$at\)
+0+04b4 <[^>]*> sll \$a0,\$a0,0x8
+0+04b8 <[^>]*> or \$a0,\$a0,\$at
+0+04bc <[^>]*> lui \$at,[-0-9x]+
+[ ]*4bc: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+04c0 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*4c0: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+04c4 <[^>]*> sb \$a0,[01]\(\$at\)
+0+04c8 <[^>]*> srl \$a0,\$a0,0x8
+0+04cc <[^>]*> sb \$a0,[01]\(\$at\)
+0+04d0 <[^>]*> lbu \$at,[01]\(\$at\)
+0+04d4 <[^>]*> sll \$a0,\$a0,0x8
+0+04d8 <[^>]*> or \$a0,\$a0,\$at
+0+04dc <[^>]*> lui \$at,[-0-9x]+
+[ ]*4dc: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+04e0 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*4e0: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+04e4 <[^>]*> sb \$a0,[01]\(\$at\)
+0+04e8 <[^>]*> srl \$a0,\$a0,0x8
+0+04ec <[^>]*> sb \$a0,[01]\(\$at\)
+0+04f0 <[^>]*> lbu \$at,[01]\(\$at\)
+0+04f4 <[^>]*> sll \$a0,\$a0,0x8
+0+04f8 <[^>]*> or \$a0,\$a0,\$at
+0+04fc <[^>]*> lui \$at,[-0-9x]+
+[ ]*4fc: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0500 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*500: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0504 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0508 <[^>]*> srl \$a0,\$a0,0x8
+0+050c <[^>]*> sb \$a0,[01]\(\$at\)
+0+0510 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0514 <[^>]*> sll \$a0,\$a0,0x8
+0+0518 <[^>]*> or \$a0,\$a0,\$at
+0+051c <[^>]*> lui \$at,[-0-9x]+
+[ ]*51c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+0520 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*520: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0524 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0528 <[^>]*> srl \$a0,\$a0,0x8
+0+052c <[^>]*> sb \$a0,[01]\(\$at\)
+0+0530 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0534 <[^>]*> sll \$a0,\$a0,0x8
+0+0538 <[^>]*> or \$a0,\$a0,\$at
+0+053c <[^>]*> lui \$at,[-0-9x]+
+[ ]*53c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0540 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*540: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0544 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0548 <[^>]*> srl \$a0,\$a0,0x8
+0+054c <[^>]*> sb \$a0,[01]\(\$at\)
+0+0550 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0554 <[^>]*> sll \$a0,\$a0,0x8
+0+0558 <[^>]*> or \$a0,\$a0,\$at
+0+055c <[^>]*> lui \$at,[-0-9x]+
+[ ]*55c: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+0560 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*560: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0564 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0568 <[^>]*> srl \$a0,\$a0,0x8
+0+056c <[^>]*> sb \$a0,[01]\(\$at\)
+0+0570 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0574 <[^>]*> sll \$a0,\$a0,0x8
+0+0578 <[^>]*> or \$a0,\$a0,\$at
+0+057c <[^>]*> lui \$at,[-0-9x]+
+[ ]*57c: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0580 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*580: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0584 <[^>]*> sb \$a0,[01]\(\$at\)
+0+0588 <[^>]*> srl \$a0,\$a0,0x8
+0+058c <[^>]*> sb \$a0,[01]\(\$at\)
+0+0590 <[^>]*> lbu \$at,[01]\(\$at\)
+0+0594 <[^>]*> sll \$a0,\$a0,0x8
+0+0598 <[^>]*> or \$a0,\$a0,\$at
+0+059c <[^>]*> lui \$at,[-0-9x]+
+[ ]*59c: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+05a0 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*5a0: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+05a4 <[^>]*> sb \$a0,[01]\(\$at\)
+0+05a8 <[^>]*> srl \$a0,\$a0,0x8
+0+05ac <[^>]*> sb \$a0,[01]\(\$at\)
+0+05b0 <[^>]*> lbu \$at,[01]\(\$at\)
+0+05b4 <[^>]*> sll \$a0,\$a0,0x8
+0+05b8 <[^>]*> or \$a0,\$a0,\$at
+0+05bc <[^>]*> nop
diff --git a/gas/testsuite/gas/mips/ush.s b/gas/testsuite/gas/mips/ush.s
new file mode 100644
index 0000000000..c155814338
--- /dev/null
+++ b/gas/testsuite/gas/mips/ush.s
@@ -0,0 +1,65 @@
+# Source file used to test the ush macro.
+
+ .data
+data_label:
+ .extern big_external_data_label,1000
+ .extern small_external_data_label,1
+ .comm big_external_common,1000
+ .comm small_external_common,1
+ .lcomm big_local_common,1000
+ .lcomm small_local_common,1
+
+ .text
+ ush $4,0
+ ush $4,1
+ ush $4,0x8000
+ ush $4,-0x8000
+ ush $4,0x10000
+ ush $4,0x1a5a5
+ ush $4,0($5)
+ ush $4,1($5)
+ ush $4,data_label
+ ush $4,big_external_data_label
+ ush $4,small_external_data_label
+ ush $4,big_external_common
+ ush $4,small_external_common
+ ush $4,big_local_common
+ ush $4,small_local_common
+ ush $4,data_label+1
+ ush $4,big_external_data_label+1
+ ush $4,small_external_data_label+1
+ ush $4,big_external_common+1
+ ush $4,small_external_common+1
+ ush $4,big_local_common+1
+ ush $4,small_local_common+1
+ ush $4,data_label+0x8000
+ ush $4,big_external_data_label+0x8000
+ ush $4,small_external_data_label+0x8000
+ ush $4,big_external_common+0x8000
+ ush $4,small_external_common+0x8000
+ ush $4,big_local_common+0x8000
+ ush $4,small_local_common+0x8000
+ ush $4,data_label-0x8000
+ ush $4,big_external_data_label-0x8000
+ ush $4,small_external_data_label-0x8000
+ ush $4,big_external_common-0x8000
+ ush $4,small_external_common-0x8000
+ ush $4,big_local_common-0x8000
+ ush $4,small_local_common-0x8000
+ ush $4,data_label+0x10000
+ ush $4,big_external_data_label+0x10000
+ ush $4,small_external_data_label+0x10000
+ ush $4,big_external_common+0x10000
+ ush $4,small_external_common+0x10000
+ ush $4,big_local_common+0x10000
+ ush $4,small_local_common+0x10000
+ ush $4,data_label+0x1a5a5
+ ush $4,big_external_data_label+0x1a5a5
+ ush $4,small_external_data_label+0x1a5a5
+ ush $4,big_external_common+0x1a5a5
+ ush $4,small_external_common+0x1a5a5
+ ush $4,big_local_common+0x1a5a5
+ ush $4,small_local_common+0x1a5a5
+
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+ nop
diff --git a/gas/testsuite/gas/mips/usw.d b/gas/testsuite/gas/mips/usw.d
new file mode 100644
index 0000000000..59d28cc22e
--- /dev/null
+++ b/gas/testsuite/gas/mips/usw.d
@@ -0,0 +1,270 @@
+#objdump: -dr --prefix-addresses -mmips:3000
+#name: MIPS usw
+#as: -mips1
+
+# Test the usw macro.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> swl \$a0,[03]\(\$zero\)
+0+0004 <[^>]*> swr \$a0,[03]\(\$zero\)
+0+0008 <[^>]*> swl \$a0,[14]\(\$zero\)
+0+000c <[^>]*> swr \$a0,[14]\(\$zero\)
+0+0010 <[^>]*> li \$at,0x8000
+0+0014 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0018 <[^>]*> swr \$a0,[03]\(\$at\)
+0+001c <[^>]*> swl \$a0,-3276[58]\(\$zero\)
+0+0020 <[^>]*> swr \$a0,-3276[58]\(\$zero\)
+0+0024 <[^>]*> lui \$at,0x1
+0+0028 <[^>]*> swl \$a0,[03]\(\$at\)
+0+002c <[^>]*> swr \$a0,[03]\(\$at\)
+0+0030 <[^>]*> lui \$at,0x1
+0+0034 <[^>]*> ori \$at,\$at,0xa5a5
+0+0038 <[^>]*> swl \$a0,[03]\(\$at\)
+0+003c <[^>]*> swr \$a0,[03]\(\$at\)
+0+0040 <[^>]*> swl \$a0,[03]\(\$a1\)
+0+0044 <[^>]*> swr \$a0,[03]\(\$a1\)
+0+0048 <[^>]*> swl \$a0,[14]\(\$a1\)
+0+004c <[^>]*> swr \$a0,[-0-9]+\(\$a1\)
+0+0050 <[^>]*> lui \$at,[-0-9x]+
+[ ]*50: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+0054 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*54: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0058 <[^>]*> swl \$a0,[03]\(\$at\)
+0+005c <[^>]*> swr \$a0,[03]\(\$at\)
+0+0060 <[^>]*> lui \$at,[-0-9x]+
+[ ]*60: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+0064 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*64: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0068 <[^>]*> swl \$a0,[03]\(\$at\)
+0+006c <[^>]*> swr \$a0,[03]\(\$at\)
+0+0070 <[^>]*> addiu \$at,\$gp,0
+[ ]*70: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+0074 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0078 <[^>]*> swr \$a0,[03]\(\$at\)
+0+007c <[^>]*> lui \$at,0x0
+[ ]*7c: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+0080 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*80: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0084 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0088 <[^>]*> swr \$a0,[03]\(\$at\)
+0+008c <[^>]*> addiu \$at,\$gp,0
+[ ]*8c: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+0090 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0094 <[^>]*> swr \$a0,[03]\(\$at\)
+0+0098 <[^>]*> lui \$at,[-0-9x]+
+[ ]*98: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+009c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*9c: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+00a0 <[^>]*> swl \$a0,[03]\(\$at\)
+0+00a4 <[^>]*> swr \$a0,[03]\(\$at\)
+0+00a8 <[^>]*> addiu \$at,\$gp,[-0-9]+
+[ ]*a8: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+00ac <[^>]*> swl \$a0,[03]\(\$at\)
+0+00b0 <[^>]*> swr \$a0,[03]\(\$at\)
+0+00b4 <[^>]*> lui \$at,0x0
+[ ]*b4: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+00b8 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*b8: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+00bc <[^>]*> swl \$a0,[03]\(\$at\)
+0+00c0 <[^>]*> swr \$a0,[03]\(\$at\)
+0+00c4 <[^>]*> lui \$at,0x0
+[ ]*c4: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+00c8 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*c8: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+00cc <[^>]*> swl \$a0,[03]\(\$at\)
+0+00d0 <[^>]*> swr \$a0,[03]\(\$at\)
+0+00d4 <[^>]*> addiu \$at,\$gp,1
+[ ]*d4: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_data_label
+0+00d8 <[^>]*> swl \$a0,[03]\(\$at\)
+0+00dc <[^>]*> swr \$a0,[03]\(\$at\)
+0+00e0 <[^>]*> lui \$at,0x0
+[ ]*e0: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+00e4 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*e4: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+00e8 <[^>]*> swl \$a0,[03]\(\$at\)
+0+00ec <[^>]*> swr \$a0,[03]\(\$at\)
+0+00f0 <[^>]*> addiu \$at,\$gp,1
+[ ]*f0: [A-Z0-9_]*GPREL[A-Z0-9_]* small_external_common
+0+00f4 <[^>]*> swl \$a0,[03]\(\$at\)
+0+00f8 <[^>]*> swr \$a0,[03]\(\$at\)
+0+00fc <[^>]*> lui \$at,0x0
+[ ]*fc: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+0100 <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*100: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0104 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0108 <[^>]*> swr \$a0,[03]\(\$at\)
+0+010c <[^>]*> addiu \$at,\$gp,[-0-9]+
+[ ]*10c: [A-Z0-9_]*GPREL[A-Z0-9_]* .sbss.*
+0+0110 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0114 <[^>]*> swr \$a0,[03]\(\$at\)
+0+0118 <[^>]*> lui \$at,[-0-9x]+
+[ ]*118: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+011c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*11c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0120 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0124 <[^>]*> swr \$a0,[03]\(\$at\)
+0+0128 <[^>]*> lui \$at,[-0-9x]+
+[ ]*128: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+012c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*12c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0130 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0134 <[^>]*> swr \$a0,[03]\(\$at\)
+0+0138 <[^>]*> lui \$at,[-0-9x]+
+[ ]*138: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+013c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*13c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0140 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0144 <[^>]*> swr \$a0,[03]\(\$at\)
+0+0148 <[^>]*> lui \$at,[-0-9x]+
+[ ]*148: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+014c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*14c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0150 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0154 <[^>]*> swr \$a0,[03]\(\$at\)
+0+0158 <[^>]*> lui \$at,[-0-9x]+
+[ ]*158: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+015c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*15c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0160 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0164 <[^>]*> swr \$a0,[03]\(\$at\)
+0+0168 <[^>]*> lui \$at,[-0-9x]+
+[ ]*168: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+016c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*16c: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0170 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0174 <[^>]*> swr \$a0,[03]\(\$at\)
+0+0178 <[^>]*> lui \$at,[-0-9x]+
+[ ]*178: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+017c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*17c: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0180 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0184 <[^>]*> swr \$a0,[03]\(\$at\)
+0+0188 <[^>]*> lui \$at,0x0
+[ ]*188: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+018c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*18c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0190 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0194 <[^>]*> swr \$a0,[03]\(\$at\)
+0+0198 <[^>]*> lui \$at,0x0
+[ ]*198: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+019c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*19c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+01a0 <[^>]*> swl \$a0,[03]\(\$at\)
+0+01a4 <[^>]*> swr \$a0,[03]\(\$at\)
+0+01a8 <[^>]*> lui \$at,0x0
+[ ]*1a8: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+01ac <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*1ac: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+01b0 <[^>]*> swl \$a0,[03]\(\$at\)
+0+01b4 <[^>]*> swr \$a0,[03]\(\$at\)
+0+01b8 <[^>]*> lui \$at,0x0
+[ ]*1b8: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+01bc <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*1bc: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+01c0 <[^>]*> swl \$a0,[03]\(\$at\)
+0+01c4 <[^>]*> swr \$a0,[03]\(\$at\)
+0+01c8 <[^>]*> lui \$at,0x0
+[ ]*1c8: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+01cc <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*1cc: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+01d0 <[^>]*> swl \$a0,[03]\(\$at\)
+0+01d4 <[^>]*> swr \$a0,[03]\(\$at\)
+0+01d8 <[^>]*> lui \$at,0x0
+[ ]*1d8: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+01dc <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*1dc: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+01e0 <[^>]*> swl \$a0,[03]\(\$at\)
+0+01e4 <[^>]*> swr \$a0,[03]\(\$at\)
+0+01e8 <[^>]*> lui \$at,0x0
+[ ]*1e8: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+01ec <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*1ec: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+01f0 <[^>]*> swl \$a0,[03]\(\$at\)
+0+01f4 <[^>]*> swr \$a0,[03]\(\$at\)
+0+01f8 <[^>]*> lui \$at,[-0-9x]+
+[ ]*1f8: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+01fc <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*1fc: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0200 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0204 <[^>]*> swr \$a0,[03]\(\$at\)
+0+0208 <[^>]*> lui \$at,[-0-9x]+
+[ ]*208: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+020c <[^>]*> addiu \$at,\$at,0
+[ ]*20c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0210 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0214 <[^>]*> swr \$a0,[03]\(\$at\)
+0+0218 <[^>]*> lui \$at,[-0-9x]+
+[ ]*218: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+021c <[^>]*> addiu \$at,\$at,0
+[ ]*21c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0220 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0224 <[^>]*> swr \$a0,[03]\(\$at\)
+0+0228 <[^>]*> lui \$at,[-0-9x]+
+[ ]*228: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+022c <[^>]*> addiu \$at,\$at,0
+[ ]*22c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+0230 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0234 <[^>]*> swr \$a0,[03]\(\$at\)
+0+0238 <[^>]*> lui \$at,[-0-9x]+
+[ ]*238: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+023c <[^>]*> addiu \$at,\$at,0
+[ ]*23c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+0240 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0244 <[^>]*> swr \$a0,[03]\(\$at\)
+0+0248 <[^>]*> lui \$at,[-0-9x]+
+[ ]*248: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+024c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*24c: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+0250 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0254 <[^>]*> swr \$a0,[03]\(\$at\)
+0+0258 <[^>]*> lui \$at,[-0-9x]+
+[ ]*258: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+025c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*25c: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+0260 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0264 <[^>]*> swr \$a0,[03]\(\$at\)
+0+0268 <[^>]*> lui \$at,[-0-9x]+
+[ ]*268: [A-Z0-9_]*HI[A-Z0-9_]* .data.*
+0+026c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*26c: [A-Z0-9_]*LO[A-Z0-9_]* .data.*
+0+0270 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0274 <[^>]*> swr \$a0,[03]\(\$at\)
+0+0278 <[^>]*> lui \$at,[-0-9x]+
+[ ]*278: [A-Z0-9_]*HI[A-Z0-9_]* big_external_data_label
+0+027c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*27c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_data_label
+0+0280 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0284 <[^>]*> swr \$a0,[03]\(\$at\)
+0+0288 <[^>]*> lui \$at,[-0-9x]+
+[ ]*288: [A-Z0-9_]*HI[A-Z0-9_]* small_external_data_label
+0+028c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*28c: [A-Z0-9_]*LO[A-Z0-9_]* small_external_data_label
+0+0290 <[^>]*> swl \$a0,[03]\(\$at\)
+0+0294 <[^>]*> swr \$a0,[03]\(\$at\)
+0+0298 <[^>]*> lui \$at,[-0-9x]+
+[ ]*298: [A-Z0-9_]*HI[A-Z0-9_]* big_external_common
+0+029c <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*29c: [A-Z0-9_]*LO[A-Z0-9_]* big_external_common
+0+02a0 <[^>]*> swl \$a0,[03]\(\$at\)
+0+02a4 <[^>]*> swr \$a0,[03]\(\$at\)
+0+02a8 <[^>]*> lui \$at,[-0-9x]+
+[ ]*2a8: [A-Z0-9_]*HI[A-Z0-9_]* small_external_common
+0+02ac <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*2ac: [A-Z0-9_]*LO[A-Z0-9_]* small_external_common
+0+02b0 <[^>]*> swl \$a0,[03]\(\$at\)
+0+02b4 <[^>]*> swr \$a0,[03]\(\$at\)
+0+02b8 <[^>]*> lui \$at,[-0-9x]+
+[ ]*2b8: [A-Z0-9_]*HI[A-Z0-9_]* .bss.*
+0+02bc <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*2bc: [A-Z0-9_]*LO[A-Z0-9_]* .bss.*
+0+02c0 <[^>]*> swl \$a0,[03]\(\$at\)
+0+02c4 <[^>]*> swr \$a0,[03]\(\$at\)
+0+02c8 <[^>]*> lui \$at,[-0-9x]+
+[ ]*2c8: [A-Z0-9_]*HI[A-Z0-9_]* .sbss.*
+0+02cc <[^>]*> addiu \$at,\$at,[-0-9]+
+[ ]*2cc: [A-Z0-9_]*LO[A-Z0-9_]* .sbss.*
+0+02d0 <[^>]*> swl \$a0,[03]\(\$at\)
+0+02d4 <[^>]*> swr \$a0,[03]\(\$at\)
+ ...
diff --git a/gas/testsuite/gas/mips/usw.s b/gas/testsuite/gas/mips/usw.s
new file mode 100644
index 0000000000..df1c60c285
--- /dev/null
+++ b/gas/testsuite/gas/mips/usw.s
@@ -0,0 +1,66 @@
+# Source file used to test the usw macro.
+
+ .data
+data_label:
+ .extern big_external_data_label,1000
+ .extern small_external_data_label,1
+ .comm big_external_common,1000
+ .comm small_external_common,1
+ .lcomm big_local_common,1000
+ .lcomm small_local_common,1
+
+ .text
+ usw $4,0
+ usw $4,1
+ usw $4,0x8000
+ usw $4,-0x8000
+ usw $4,0x10000
+ usw $4,0x1a5a5
+ usw $4,0($5)
+ usw $4,1($5)
+ usw $4,data_label
+ usw $4,big_external_data_label
+ usw $4,small_external_data_label
+ usw $4,big_external_common
+ usw $4,small_external_common
+ usw $4,big_local_common
+ usw $4,small_local_common
+ usw $4,data_label+1
+ usw $4,big_external_data_label+1
+ usw $4,small_external_data_label+1
+ usw $4,big_external_common+1
+ usw $4,small_external_common+1
+ usw $4,big_local_common+1
+ usw $4,small_local_common+1
+ usw $4,data_label+0x8000
+ usw $4,big_external_data_label+0x8000
+ usw $4,small_external_data_label+0x8000
+ usw $4,big_external_common+0x8000
+ usw $4,small_external_common+0x8000
+ usw $4,big_local_common+0x8000
+ usw $4,small_local_common+0x8000
+ usw $4,data_label-0x8000
+ usw $4,big_external_data_label-0x8000
+ usw $4,small_external_data_label-0x8000
+ usw $4,big_external_common-0x8000
+ usw $4,small_external_common-0x8000
+ usw $4,big_local_common-0x8000
+ usw $4,small_local_common-0x8000
+ usw $4,data_label+0x10000
+ usw $4,big_external_data_label+0x10000
+ usw $4,small_external_data_label+0x10000
+ usw $4,big_external_common+0x10000
+ usw $4,small_external_common+0x10000
+ usw $4,big_local_common+0x10000
+ usw $4,small_local_common+0x10000
+ usw $4,data_label+0x1a5a5
+ usw $4,big_external_data_label+0x1a5a5
+ usw $4,small_external_data_label+0x1a5a5
+ usw $4,big_external_common+0x1a5a5
+ usw $4,small_external_common+0x1a5a5
+ usw $4,big_local_common+0x1a5a5
+ usw $4,small_local_common+0x1a5a5
+
+# Round to a 16 byte boundary, for ease in testing multiple targets.
+ nop
+ nop
diff --git a/gas/testsuite/gas/mn10200/add.s b/gas/testsuite/gas/mn10200/add.s
new file mode 100644
index 0000000000..ed251bc55e
--- /dev/null
+++ b/gas/testsuite/gas/mn10200/add.s
@@ -0,0 +1,13 @@
+ .text
+ add d1,d2
+ add d2,a3
+ add a2,d1
+ add a3,a2
+ add 16,d1
+ add 256,d2
+ add 131071,d3
+ add 16,a1
+ add 256,a2
+ add 131071,a3
+ addc d1,d2
+ addnf 16,a2
diff --git a/gas/testsuite/gas/mn10200/basic.exp b/gas/testsuite/gas/mn10200/basic.exp
new file mode 100644
index 0000000000..3793eb17ed
--- /dev/null
+++ b/gas/testsuite/gas/mn10200/basic.exp
@@ -0,0 +1,836 @@
+# Copyright (C) 1996 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, 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 more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# DejaGnu@cygnus.com
+
+# Written by Cygnus Support.
+
+proc do_add {} {
+ set testname "add.s: Add operations"
+ set x 0
+
+ gas_start "add.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 96\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0001 F20B\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0003 F2C9\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0005 F24E\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0007 D510\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0009 F71A0001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000d F463FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +8 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0012 D110\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 F70A0001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 F467FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +11 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001d F286\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001f F50E10\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==14] then { pass $testname } else { fail $testname }
+}
+
+proc do_bcc {} {
+ set testname "bcc.s: Bcc tests"
+ set x 0
+
+ gas_start "bcc.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 E800\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 E900\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 E100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0006 E200\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 E300\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000a E000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c E500\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000e E600\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 E700\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0012 E400\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 F5FC00\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0017 F5FD00\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001a F5FE00\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001d F5FF00\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 EA00\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==15] then { pass $testname } else { fail $testname }
+}
+
+proc do_bccx {} {
+ set testname "bccx.s: Bccx tests"
+ set x 0
+
+ gas_start "bccx.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F5E800\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0003 F5E900\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0006 F5E100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0009 F5E200\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c F5E300\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000f F5E000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0012 F5E500\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0015 F5E600\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 F5E700\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001b F5E400\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001e F5EC00\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0021 F5ED00\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 F5EE00\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0027 F5EF00\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==14] then { pass $testname } else { fail $testname }
+}
+
+proc do_bit {} {
+ set testname "bit.s: bit tests"
+ set x 0
+
+ gas_start "bit.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F50540\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0003 F7060020\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0007 F029\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0009 F039\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +12 +FFFF40\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==4] then { pass $testname } else { fail $testname }
+}
+
+
+proc do_cmp {} {
+ set testname "cmp.s: cmp tests"
+ set x 0
+
+ gas_start "cmp.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F396\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 F22B\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 F2EF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0006 F26E\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 DB10\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000a F74A0001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000e F479FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +8 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0013 EE0001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0016 F47DFFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +10 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==11] then { pass $testname } else { fail $testname }
+}
+
+proc do_ext {} {
+ set testname "ext.s: ext tests"
+ set x 0
+
+ gas_start "ext.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F3C5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 B2\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0003 B7\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 BA\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0005 BD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==5] then { pass $testname } else { fail $testname }
+}
+
+proc do_extend {} {
+ set testname "extend.s: extended instruction tests"
+ set x 0
+
+ gas_start "extend.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F505\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 F6FA\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 F606\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0006 F90210\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0009 FB030100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000d FD030001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +7 +FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0013 F616\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0015 F91610\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 FB170100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c FD170001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +11 +FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0022 F64B\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 F65E\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0026 F676\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==15] then { pass $testname } else { fail $testname }
+}
+
+proc do_logical {} {
+ set testname "logical.s: logical tests"
+ set x 0
+
+ gas_start "logical.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F306\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 F5027F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0005 F703FF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0009 F710FF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000d F316\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000f F50A7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0012 F743FF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0016 F714FF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001a F326\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c F74FFF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 F3E7\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==11] then { pass $testname } else { fail $testname }
+}
+
+proc do_loop {} {
+ set testname "loop.s: loop tests"
+ set x 0
+
+ gas_start "loop.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 D8\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0001 D9\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 D1\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0003 D2\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 D3\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0005 D0\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0006 D5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0007 D6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 D7\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0009 D4\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000a DA\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000b DB\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==12] then { pass $testname } else { fail $testname }
+}
+
+proc do_mov1 {} {
+ set testname "mov1.s: mov1 tests"
+ set x 0
+
+ gas_start "mov1.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F236\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 F2F9\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0005 F279\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0007 F3F3\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0009 F3D8\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000b F3E1\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000d F3C8\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000f 29\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 6908\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0012 F7C90001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0016 F489FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +13 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==13] then { pass $testname } else { fail $testname }
+}
+
+proc do_mov2 {} {
+ set testname "mov2.s: mov2 tests"
+ set x 0
+
+ gas_start "mov2.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F156\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 C90080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0005 F4C1FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +4 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000a 7908\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c F7B90001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 F4F9FFFF \[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +7 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0015 F116\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0017 F7310080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001b F4D1FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +10 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==12] then { pass $testname } else { fail $testname }
+}
+
+proc do_mov3 {} {
+ set testname "mov3.s: mov3 tests"
+ set x 0
+
+ gas_start "mov3.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 09\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0001 4920\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0003 F7890001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0007 F409FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +5 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c F1E9\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000e C18000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0011 F441FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +8 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0016 5920\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 F7A90001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c F419FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +11 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==13] then { pass $testname } else { fail $testname }
+}
+
+proc do_mov4 {} {
+ set testname "mov4.s: mov4 tests"
+ set x 0
+
+ gas_start "mov4.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F1A9\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 F7218000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0006 F451FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +4 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000b 8508\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000d F90001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 F471FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +7 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0015 DD0001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 F475FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +9 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==11] then { pass $testname } else { fail $testname }
+}
+
+proc do_movx {} {
+ set testname "movx.s: movx tests"
+ set x 0
+
+ gas_start "movx.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F57908\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0003 F7790001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0007 F4B9FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +4 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c F55908\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000f F7690001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0013 F439FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +7 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==8] then { pass $testname } else { fail $testname }
+}
+
+proc do_movb {} {
+ set testname "movb.s: movb tests"
+ set x 0
+
+ gas_start "movb.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F52908\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0003 F7D90001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0007 F4A9FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +4 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c F06B\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000e F4C6FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +6 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0013 19\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 F51908\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0017 F7990001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001b F429FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +10 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 F0E9\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0022 C50001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0025 F445FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +13 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==16] then { pass $testname } else { fail $testname }
+}
+
+proc do_movbu {} {
+ set testname "movbu.s: movbu tests"
+ set x 0
+
+ gas_start "movbu.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 39\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0001 F53908\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 F7590001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 F499FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +5 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000d F096\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000f CD0080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0012 F4C9FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +8 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==9] then { pass $testname } else { fail $testname }
+}
+
+proc do_movhu {} {
+ set testname "movhu.s: movhu tests"
+ set x 0
+
+ gas_start "movhu.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F066\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 F86608\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0005 FA660100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0009 FC660001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +5 +FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000f F8BD08\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0012 FABD0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0016 FCBD0001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +8 +FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c F4A5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001e 398000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0021 FCAD0001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +11 +FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0027 F076\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0029 F87620\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c FA760100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 FC760001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +15 +FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0036 F89720\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0039 FA978000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003d FC970001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +18 +FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0043 F4DA\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0045 070080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 FC870001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +21 +FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==26] then { pass $testname } else { fail $testname }
+}
+
+proc do_movm {} {
+ set testname "movm.s: movm tests"
+ set x 0
+
+ gas_start "movm.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 CE30\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 CEF8\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 CF30\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0006 CFF8\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==4] then { pass $testname } else { fail $testname }
+}
+
+proc do_muldiv {} {
+ set testname "muldiv.s: muldiv tests"
+ set x 0
+
+ gas_start "muldiv.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F346\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 F35B\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 F36E\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==3] then { pass $testname } else { fail $testname }
+}
+
+proc do_other {} {
+ set testname "other.s: other tests"
+ set x 0
+
+ gas_start "other.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 FC0001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0003 F4E0FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +3 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 F008\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000a FD0001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000d F4E1FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +6 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0012 F009\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 FE\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0015 EB\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0016 F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==11] then { pass $testname } else { fail $testname }
+}
+
+proc do_shift {} {
+ set testname "shift.s: shift tests"
+ set x 0
+
+ gas_start "shift.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F33A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 F33F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 F335\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0006 F332\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==4] then { pass $testname } else { fail $testname }
+}
+
+proc do_sub {} {
+ set testname "sub.s: sub tests"
+ set x 0
+
+ gas_start "sub.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 A6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0001 F21B\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0003 F2DF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0005 F25E\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0007 F71EFF7F \[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000b F46AFFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +7 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 F70EFF7F \[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 F46EFFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +9 +01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0019 F296 \[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==11] then { pass $testname } else { fail $testname }
+}
+
+if [istarget mn10200*-*-*] then {
+ # Test the basic instruction parser.
+ do_add
+ do_bcc
+ do_bccx
+ do_bit
+ do_cmp
+ do_ext
+ do_logical
+ do_mov1
+ do_mov2
+ do_mov3
+ do_mov4
+ do_movb
+ do_movx
+ do_movbu
+ do_muldiv
+ do_other
+ do_shift
+ do_sub
+}
diff --git a/gas/testsuite/gas/mn10200/bcc.s b/gas/testsuite/gas/mn10200/bcc.s
new file mode 100644
index 0000000000..8292dce04f
--- /dev/null
+++ b/gas/testsuite/gas/mn10200/bcc.s
@@ -0,0 +1,17 @@
+ .text
+foo:
+ beq foo
+ bne foo
+ bgt foo
+ bge foo
+ ble foo
+ blt foo
+ bhi foo
+ bcc foo
+ bls foo
+ bcs foo
+ bvc foo
+ bvs foo
+ bnc foo
+ bns foo
+ bra foo
diff --git a/gas/testsuite/gas/mn10200/bccx.s b/gas/testsuite/gas/mn10200/bccx.s
new file mode 100644
index 0000000000..e4e7edf5e3
--- /dev/null
+++ b/gas/testsuite/gas/mn10200/bccx.s
@@ -0,0 +1,16 @@
+ .text
+foo:
+ beqx foo
+ bnex foo
+ bgtx foo
+ bgex foo
+ blex foo
+ bltx foo
+ bhix foo
+ bccx foo
+ blsx foo
+ bcsx foo
+ bvcx foo
+ bvsx foo
+ bncx foo
+ bnsx foo
diff --git a/gas/testsuite/gas/mn10200/bit.s b/gas/testsuite/gas/mn10200/bit.s
new file mode 100644
index 0000000000..5db60d495b
--- /dev/null
+++ b/gas/testsuite/gas/mn10200/bit.s
@@ -0,0 +1,5 @@
+ .text
+ btst 64,d1
+ btst 8192,d2
+ bset d1,(a2)
+ bclr d1,(a2)
diff --git a/gas/testsuite/gas/mn10200/cmp.s b/gas/testsuite/gas/mn10200/cmp.s
new file mode 100644
index 0000000000..133925b38c
--- /dev/null
+++ b/gas/testsuite/gas/mn10200/cmp.s
@@ -0,0 +1,10 @@
+ .text
+ cmp d1,d2
+ cmp d2,a3
+ cmp a3,d3
+ cmp a3,a2
+ cmp 16,d3
+ cmp 256,d2
+ cmp 131071,d1
+ cmp 256,a2
+ cmp 131071,a1
diff --git a/gas/testsuite/gas/mn10200/ext.s b/gas/testsuite/gas/mn10200/ext.s
new file mode 100644
index 0000000000..1be01bac89
--- /dev/null
+++ b/gas/testsuite/gas/mn10200/ext.s
@@ -0,0 +1,7 @@
+ .text
+ ext d1
+ extx d2
+ extxu d3
+ extxb d2
+ extxbu d1
+
diff --git a/gas/testsuite/gas/mn10200/logical.s b/gas/testsuite/gas/mn10200/logical.s
new file mode 100644
index 0000000000..0809d7f387
--- /dev/null
+++ b/gas/testsuite/gas/mn10200/logical.s
@@ -0,0 +1,12 @@
+ .text
+ and d1,d2
+ and 127,d2
+ and 32767,d3
+ and 32767,psw
+ or d1,d2
+ or 127,d2
+ or 32767,d3
+ or 32767,psw
+ xor d1,d2
+ xor 32767,d3
+ not d3
diff --git a/gas/testsuite/gas/mn10200/mov1.s b/gas/testsuite/gas/mn10200/mov1.s
new file mode 100644
index 0000000000..c828e32e59
--- /dev/null
+++ b/gas/testsuite/gas/mn10200/mov1.s
@@ -0,0 +1,13 @@
+ .text
+ mov d1,a2
+ mov a2,d1
+ mov d1,d2
+ mov a2,a1
+ mov psw,d3
+ mov d2,psw
+ mov mdr,d1
+ mov d2,mdr
+ mov (a2),d1
+ mov (8,a2),d1
+ mov (256,a2),d1
+ mov (131071,a2),d1
diff --git a/gas/testsuite/gas/mn10200/mov2.s b/gas/testsuite/gas/mn10200/mov2.s
new file mode 100644
index 0000000000..8df6e2544c
--- /dev/null
+++ b/gas/testsuite/gas/mn10200/mov2.s
@@ -0,0 +1,10 @@
+ .text
+ mov (d1,a1),d2
+ mov (32768),d1
+ mov (131071),d1
+ mov (8,a2),a1
+ mov (256,a2),a1
+ mov (131071,a2),a1
+ mov (d1,a1),a2
+ mov (32768),a1
+ mov (131071),a1
diff --git a/gas/testsuite/gas/mn10200/mov3.s b/gas/testsuite/gas/mn10200/mov3.s
new file mode 100644
index 0000000000..bd7490a35a
--- /dev/null
+++ b/gas/testsuite/gas/mn10200/mov3.s
@@ -0,0 +1,11 @@
+ .text
+ mov d1,(a2)
+ mov d1,(32,a2)
+ mov d1,(256,a2)
+ mov d1,(131071,a2)
+ mov d1,(d2,a2)
+ mov d1,(128)
+ mov d1,(131071)
+ mov a1,(32,a2)
+ mov a1,(256,a2)
+ mov a1,(131071,a2)
diff --git a/gas/testsuite/gas/mn10200/mov4.s b/gas/testsuite/gas/mn10200/mov4.s
new file mode 100644
index 0000000000..f1187e01fe
--- /dev/null
+++ b/gas/testsuite/gas/mn10200/mov4.s
@@ -0,0 +1,9 @@
+ .text
+ mov a1,(d2,a2)
+ mov a1,(128)
+ mov a1,(131071)
+ mov 8,d1
+ mov 256,d1
+ mov 131071,d1
+ mov 256,a1
+ mov 131071,a1
diff --git a/gas/testsuite/gas/mn10200/movb.s b/gas/testsuite/gas/mn10200/movb.s
new file mode 100644
index 0000000000..2556614754
--- /dev/null
+++ b/gas/testsuite/gas/mn10200/movb.s
@@ -0,0 +1,13 @@
+ .text
+ movb (8,a2),d1
+ movb (256,a2),d1
+ movb (131071,a2),d1
+ movb (d2,a2),d3
+ movb (131071),d2
+ movb d1,(a2)
+ movb d1,(8,a2)
+ movb d1,(256,a2)
+ movb d1,(131071,a2)
+ movb d1,(d2,a2)
+ movb d1,(256)
+ movb d1,(131071)
diff --git a/gas/testsuite/gas/mn10200/movbu.s b/gas/testsuite/gas/mn10200/movbu.s
new file mode 100644
index 0000000000..01d973a1b1
--- /dev/null
+++ b/gas/testsuite/gas/mn10200/movbu.s
@@ -0,0 +1,8 @@
+ .text
+ movbu (a2),d1
+ movbu (8,a2),d1
+ movbu (256,a2),d1
+ movbu (131071,a2),d1
+ movbu (d1,a1),d2
+ movbu (32768),d1
+ movbu (131071),d1
diff --git a/gas/testsuite/gas/mn10200/movx.s b/gas/testsuite/gas/mn10200/movx.s
new file mode 100644
index 0000000000..70e1d714f5
--- /dev/null
+++ b/gas/testsuite/gas/mn10200/movx.s
@@ -0,0 +1,7 @@
+ .text
+ movx (8,a2),d1
+ movx (256,a2),d1
+ movx (131071,a2),d1
+ movx d1,(8,a2)
+ movx d1,(256,a2)
+ movx d1,(131071,a2)
diff --git a/gas/testsuite/gas/mn10200/muldiv.s b/gas/testsuite/gas/mn10200/muldiv.s
new file mode 100644
index 0000000000..0f170265c8
--- /dev/null
+++ b/gas/testsuite/gas/mn10200/muldiv.s
@@ -0,0 +1,4 @@
+ .text
+ mul d1,d2
+ mulu d2,d3
+ divu d3,d2
diff --git a/gas/testsuite/gas/mn10200/other.s b/gas/testsuite/gas/mn10200/other.s
new file mode 100644
index 0000000000..ecf94bdfd6
--- /dev/null
+++ b/gas/testsuite/gas/mn10200/other.s
@@ -0,0 +1,10 @@
+ .text
+ jmp 256
+ jmp 131071
+ jmp (a2)
+ jsr 256
+ jsr 131071
+ jsr (a2)
+ rts
+ rti
+ nop
diff --git a/gas/testsuite/gas/mn10200/shift.s b/gas/testsuite/gas/mn10200/shift.s
new file mode 100644
index 0000000000..568e769f6f
--- /dev/null
+++ b/gas/testsuite/gas/mn10200/shift.s
@@ -0,0 +1,5 @@
+ .text
+ asr d2
+ lsr d3
+ ror d1
+ rol d2
diff --git a/gas/testsuite/gas/mn10200/sub.s b/gas/testsuite/gas/mn10200/sub.s
new file mode 100644
index 0000000000..25516548f5
--- /dev/null
+++ b/gas/testsuite/gas/mn10200/sub.s
@@ -0,0 +1,10 @@
+ .text
+ sub d1,d2
+ sub d2,a3
+ sub a3,d3
+ sub a3,a2
+ sub 32767,d2
+ sub 131071,d2
+ sub 32767,a2
+ sub 131071,a2
+ subc d1,d2
diff --git a/gas/testsuite/gas/mn10300/add.s b/gas/testsuite/gas/mn10300/add.s
new file mode 100644
index 0000000000..16f558f502
--- /dev/null
+++ b/gas/testsuite/gas/mn10300/add.s
@@ -0,0 +1,15 @@
+ .text
+ add d1,d2
+ add d2,a3
+ add a3,a2
+ add a2,d1
+ add 16,d1
+ add 256,d2
+ add 131071,d3
+ add 16,a1
+ add 256,a2
+ add 131071,a3
+ add 16,sp
+ add 256,sp
+ add 131071,sp
+ addc d1,d2
diff --git a/gas/testsuite/gas/mn10300/basic.exp b/gas/testsuite/gas/mn10300/basic.exp
new file mode 100644
index 0000000000..7c057b9a07
--- /dev/null
+++ b/gas/testsuite/gas/mn10300/basic.exp
@@ -0,0 +1,986 @@
+# Copyright (C) 1996 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, 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 more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# DejaGnu@cygnus.com
+
+# Written by Cygnus Support.
+
+proc do_add {} {
+ set testname "add.s: Add operations"
+ set x 0
+
+ gas_start "add.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 E6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0001 F16B\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0003 F17E\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0005 F159\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0007 2910\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0009 FAC20001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000d FCC3FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +8 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0013 2110\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0015 FAD20001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0019 FCD3FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +11 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001f F8FE10\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0022 FAFE0001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0026 FCFEFFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +14 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c F146\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==17] then { pass $testname } else { fail $testname }
+}
+
+proc do_bcc {} {
+ set testname "bcc.s: Bcc tests"
+ set x 0
+
+ gas_start "bcc.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 C800\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 C900\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 C100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0006 C200\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 C300\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000a C000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c C500\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000e C600\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 C700\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0012 C400\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 F8E800\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0017 F8E900\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001a F8EA00\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001d F8EB00\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 CA00\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==15] then { pass $testname } else { fail $testname }
+}
+
+proc do_bit {} {
+ set testname "bit.s: bit tests"
+ set x 0
+
+ gas_start "bit.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F8ED40\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0003 FAEE0020\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0007 FCEFFFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +4 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000d FAF90840\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0011 FE02FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +6 +010040\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 F086\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001a FAF10840\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001e FE00FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +9 +010040\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0025 F096\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0027 FAF50840\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002b FE01FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +12 +010040\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==15] then { pass $testname } else { fail $testname }
+}
+
+proc do_cmp {} {
+ set testname "cmp.s: cmp tests"
+ set x 0
+
+ gas_start "cmp.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 A6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0001 F1AB\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0003 F19F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0005 BE\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0006 AF10\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 FACA0001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c FCC9FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +8 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0012 BF10\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 FADA0001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 FCD9FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +11 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==12] then { pass $testname } else { fail $testname }
+}
+
+proc do_ext {} {
+ set testname "ext.s: ext tests"
+ set x 0
+
+ gas_start "ext.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F2D1\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 12\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0003 17\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 1A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0005 1D\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==5] then { pass $testname } else { fail $testname }
+}
+
+proc do_extend {} {
+ set testname "extend.s: extended instruction tests"
+ set x 0
+
+ gas_start "extend.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F505\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 F6FA\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 F606\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0006 F90210\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0009 FB030001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000d FD03FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +7 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0013 F616\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0015 F91610\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 FB170001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c FD17FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +11 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0022 F64B\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 F65E\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0026 F676\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==15] then { pass $testname } else { fail $testname }
+}
+
+proc do_logical {} {
+ set testname "logical.s: logical tests"
+ set x 0
+
+ gas_start "logical.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F206\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 F8E27F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0005 FAE3FF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0009 FCE3FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +5 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000f FAFCFF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0013 F216\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0015 F8E67F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 FAE7FF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c FCE7FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +10 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0022 FAFDFF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0026 F226\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 FAEBFF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c FCEBFFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +14 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0032 F233\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==17] then { pass $testname } else { fail $testname }
+}
+
+proc do_loop {} {
+ set testname "loop.s: loop tests"
+ set x 0
+
+ gas_start "loop.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 D8\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0001 D9\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 D1\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0003 D2\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 D3\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0005 D0\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0006 D5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0007 D6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 D7\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0009 D4\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000a DA\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000b DB\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==12] then { pass $testname } else { fail $testname }
+}
+
+proc do_mov1 {} {
+ set testname "mov1.s: mov1 tests"
+ set x 0
+
+ gas_start "mov1.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 86\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0001 F1E6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0003 F1D9\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0005 99\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0006 3E\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0007 F2F4\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0009 F2FB\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000b F2E1\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000d F2FA\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000f 76\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 F80608\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0013 FA060001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0017 FC06FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +14 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001d 5908\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001f FAB50001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0023 F2E7\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==17] then { pass $testname } else { fail $testname }
+}
+
+proc do_mov2 {} {
+ set testname "mov2.s: mov2 tests"
+ set x 0
+
+ gas_start "mov2.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 FCB5FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +2 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0006 F325\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 310080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000b FCA5FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +5 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0011 F006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0013 F82608\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0016 FA260001 \[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001a FC26FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +9 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 5D08\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0022 FAB10001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0026 FCB1FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +12 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c F3A5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002e FAA10080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0032 FCA1FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +15 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 F8F120\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==20] then { pass $testname } else { fail $testname }
+}
+
+proc do_mov3 {} {
+ set testname "mov3.s: mov3 tests"
+ set x 0
+
+ gas_start "mov3.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 66\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0001 F81620\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 FA160001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 FC16FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +5 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000e 4620\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 FA950080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 FC95FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +8 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001a F35A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c 058000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001f FC85FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +11 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0025 F016\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0027 F83620\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002a FA360001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002e FC36FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +15 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 4720\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==19] then { pass $testname } else { fail $testname }
+}
+
+proc do_mov4 {} {
+ set testname "mov4.s: mov4 tests"
+ set x 0
+
+ gas_start "mov4.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 FA940080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 FC94FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +3 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000a F3DA\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c FA848000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 FC84FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +6 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0016 F8F520\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0019 8508\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001b 2D0001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001e FCCDFFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +10 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 9508\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0026 250001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0029 FCDDFFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +13 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==16] then { pass $testname } else { fail $testname }
+}
+
+proc do_movbu {} {
+ set testname "movbu.s: movbu tests"
+ set x 0
+
+ gas_start "movbu.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F046\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 F84608\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0005 FA460001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0009 FC46FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +5 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000f F8B908\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0012 FAB90001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0016 FCB9FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +8 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c F425\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001e 350080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0021 FCA9FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +11 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0027 F056\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0029 F85620\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c FA560001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 FC56FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +15 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0036 F89620\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0039 FA960080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003d FC96FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +18 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0043 F45A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0045 068000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 FC86FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +21 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==26] then { pass $testname } else { fail $testname }
+}
+
+proc do_movhu {} {
+ set testname "movhu.s: movhu tests"
+ set x 0
+
+ gas_start "movhu.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F066\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 F86608\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0005 FA660001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0009 FC66FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +5 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000f F8BD08\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0012 FABD0001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0016 FCBDFFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +8 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c F4A5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001e 390080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0021 FCADFFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +11 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0027 F076\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0029 F87620\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c FA760001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 FC76FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +15 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0036 F89720\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0039 FA970080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003d FC97FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +18 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0043 F4DA\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0045 078000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 FC87FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +21 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==26] then { pass $testname } else { fail $testname }
+}
+
+proc do_movm {} {
+ set testname "movm.s: movm tests"
+ set x 0
+
+ gas_start "movm.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 CE30\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 CEF8\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 CF30\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0006 CFF8\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==4] then { pass $testname } else { fail $testname }
+}
+
+proc do_muldiv {} {
+ set testname "muldiv.s: muldiv tests"
+ set x 0
+
+ gas_start "muldiv.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F246\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 F25B\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 F26F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0006 F27E\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==4] then { pass $testname } else { fail $testname }
+}
+
+proc do_other {} {
+ set testname "other.s: other tests"
+ set x 0
+
+ gas_start "other.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 08\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0001 44\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 49\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0003 53\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 F0F6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0006 CC0001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0009 DCFFFF01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +8 +00\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000e CD000130\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +9 +09\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0013 DDFFFF01\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +10 +003020\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001a F0F2\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c FAFF0001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 FCFFFFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +13 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0026 DF3007\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0029 DE3005\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c F0FC\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002e F0FD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 F0FE\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0032 CB\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0033 F0FF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==23] then { pass $testname } else { fail $testname }
+}
+
+proc do_shift {} {
+ set testname "shift.s: shift tests"
+ set x 0
+
+ gas_start "shift.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F2B6\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 F8CA04\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0005 F2AB\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0007 F8C704\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000a F29E\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c F8C204\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000f 56\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 F285\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0012 F282\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==9] then { pass $testname } else { fail $testname }
+}
+
+proc do_sub {} {
+ set testname "sub.s: sub tests"
+ set x 0
+
+ gas_start "sub.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F106\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 F12B\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 F11F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0006 F13E\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 FCC6FFFF \[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +6 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000e FCD5FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +7 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 F186\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==9] then { pass $testname } else { fail $testname }
+}
+
+proc do_udf {} {
+ set testname "udf.s: udf tests part 1"
+ set x 0
+
+ gas_start "udf.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F601\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 F611\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 F621\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0006 F631\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 F641\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000a F651\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c F661\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000e F671\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 F681\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0012 F691\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 F6A1\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0016 F6B1\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 F6C1\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001a F6D1\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c F6E1\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001e F6F1\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 F501\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0022 F511\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 F521\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0026 F531\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 F541\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002a F551\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c F561\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002e F571\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 F581\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0032 F591\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 F5A1\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0036 F5B1\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 F5C1\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003a F5D1\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c F5E1\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003e F5F1\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 F9017F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0043 F9117F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0046 F9217F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0049 F9317F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004c F9417F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004f F9517F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0052 F9617F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0055 F9717F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0058 F9817F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 005b F9917F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 005e F9A17F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0061 F9B17F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0064 F9C17F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0067 F9D17F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 006a F9E17F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 006d F9F17F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0070 FB01FF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0074 FB11FF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0078 FB21FF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 007c FB31FF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0080 FB41FF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0084 FB51FF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0088 FB61FF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 008c FB71FF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0090 FB81FF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0094 FB91FF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0098 FBA1FF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 009c FBB1FF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a0 FBC1FF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a4 FBD1FF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00a8 FBE1FF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00ac FBF1FF7F\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b0 FD01FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +66 +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00b6 FD11FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +67 +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00bc FD21FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +68 +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c2 FD31FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +69 +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00c8 FD41FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +70 +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00ce FD51FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +71 +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00d4 FD61FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +72 +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00da FD71FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +73 +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e0 FD81FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +74 +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00e6 FD91FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +75 +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00ec FDA1FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +76 +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00f2 FDB1FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +77 +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00f8 FDC1FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +78 +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 00fe FDD1FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +79 +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0104 FDE1FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +80 +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 010a FDF1FFFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +81 +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0110 F90580\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0113 F91580\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0116 F92580\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0119 F93580\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 011c F94580\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 011f F95580\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0122 F96580\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0125 F97580\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0128 F98580\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 012b F99580\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 012e F9A580\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0131 F9B580\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0134 F9C580\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0137 F9D580\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 013a F9E580\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 013d F9F580\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0140 FB050080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0144 FB150080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0148 FB250080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 014c FB350080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0150 FB450080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0154 FB550080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0158 FB650080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 015c FB750080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0160 FB850080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0164 FB950080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0168 FBA50080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 016c FBB50080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0170 FBC50080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0174 FBD50080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0178 FBE50080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 017c FBF50080\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0180 FD050000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +114 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0186 FD150000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +115 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 018c FD250000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +116 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0192 FD350000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +117 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0198 FD450000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +118 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 019e FD550000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +119 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01a4 FD650000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +120 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01aa FD750000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +121 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01b0 FD850000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +122 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01b6 FD950000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +123 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01bc FDA50000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +124 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01c2 FDB50000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +125 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01c8 FDC50000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +126 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01ce FDD50000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +127 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01d4 FDE50000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +128 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 01da FDF50000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +129 +0100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==160] then { pass $testname } else { fail $testname }
+}
+
+
+if [istarget mn10300*-*-*] then {
+ # Test the basic instruction parser.
+ do_add
+ do_bcc
+ do_bit
+ do_cmp
+ do_ext
+ do_extend
+ do_logical
+ do_loop
+ do_mov1
+ do_mov2
+ do_mov3
+ do_mov4
+ do_movbu
+ do_movhu
+ do_movm
+ do_muldiv
+ do_other
+ do_shift
+ do_sub
+ do_udf
+}
diff --git a/gas/testsuite/gas/mn10300/bcc.s b/gas/testsuite/gas/mn10300/bcc.s
new file mode 100644
index 0000000000..8292dce04f
--- /dev/null
+++ b/gas/testsuite/gas/mn10300/bcc.s
@@ -0,0 +1,17 @@
+ .text
+foo:
+ beq foo
+ bne foo
+ bgt foo
+ bge foo
+ ble foo
+ blt foo
+ bhi foo
+ bcc foo
+ bls foo
+ bcs foo
+ bvc foo
+ bvs foo
+ bnc foo
+ bns foo
+ bra foo
diff --git a/gas/testsuite/gas/mn10300/bit.s b/gas/testsuite/gas/mn10300/bit.s
new file mode 100644
index 0000000000..f5c551952b
--- /dev/null
+++ b/gas/testsuite/gas/mn10300/bit.s
@@ -0,0 +1,12 @@
+ .text
+ btst 64,d1
+ btst 8192,d2
+ btst 131071,d3
+ btst 64,(8,a1)
+ btst 64,(131071)
+ bset d1,(a2)
+ bset 64,(8,a1)
+ bset 64,(131071)
+ bclr d1,(a2)
+ bclr 64,(8,a1)
+ bclr 64,(131071)
diff --git a/gas/testsuite/gas/mn10300/cmp.s b/gas/testsuite/gas/mn10300/cmp.s
new file mode 100644
index 0000000000..7f8a71d419
--- /dev/null
+++ b/gas/testsuite/gas/mn10300/cmp.s
@@ -0,0 +1,11 @@
+ .text
+ cmp d1,d2
+ cmp d2,a3
+ cmp a3,d3
+ cmp a3,a2
+ cmp 16,d3
+ cmp 256,d2
+ cmp 131071,d1
+ cmp 16,a3
+ cmp 256,a2
+ cmp 131071,a1
diff --git a/gas/testsuite/gas/mn10300/ext.s b/gas/testsuite/gas/mn10300/ext.s
new file mode 100644
index 0000000000..f0e2e79006
--- /dev/null
+++ b/gas/testsuite/gas/mn10300/ext.s
@@ -0,0 +1,7 @@
+ .text
+ ext d1
+ extb d2
+ extbu d3
+ exth d2
+ exthu d1
+
diff --git a/gas/testsuite/gas/mn10300/extend.s b/gas/testsuite/gas/mn10300/extend.s
new file mode 100644
index 0000000000..d6405b71fd
--- /dev/null
+++ b/gas/testsuite/gas/mn10300/extend.s
@@ -0,0 +1,15 @@
+ .text
+ putx d1
+ getx d2
+ mulq d1,d2
+ mulq 16,d2
+ mulq 256,d3
+ mulq 131071,d3
+ mulqu d1,d2
+ mulqu 16,d2
+ mulqu 256,d3
+ mulqu 131071,d3
+ sat16 d2,d3
+ sat24 d3,d2
+ bsch d1,d2
+
diff --git a/gas/testsuite/gas/mn10300/logical.s b/gas/testsuite/gas/mn10300/logical.s
new file mode 100644
index 0000000000..b0976db33d
--- /dev/null
+++ b/gas/testsuite/gas/mn10300/logical.s
@@ -0,0 +1,15 @@
+ .text
+ and d1,d2
+ and 127,d2
+ and 32767,d3
+ and 131071,d3
+ and 32767,psw
+ or d1,d2
+ or 127,d2
+ or 32767,d3
+ or 131071,d3
+ or 32767,psw
+ xor d1,d2
+ xor 32767,d3
+ xor 131071,d3
+ not d3
diff --git a/gas/testsuite/gas/mn10300/loop.s b/gas/testsuite/gas/mn10300/loop.s
new file mode 100644
index 0000000000..d9182070e4
--- /dev/null
+++ b/gas/testsuite/gas/mn10300/loop.s
@@ -0,0 +1,15 @@
+ .text
+foo:
+ leq
+ lne
+ lgt
+ lge
+ lle
+ llt
+ lhi
+ lcc
+ lls
+ lcs
+ lra
+ setlb
+
diff --git a/gas/testsuite/gas/mn10300/mov1.s b/gas/testsuite/gas/mn10300/mov1.s
new file mode 100644
index 0000000000..a44cc553b6
--- /dev/null
+++ b/gas/testsuite/gas/mn10300/mov1.s
@@ -0,0 +1,17 @@
+ .text
+ mov d1,d2
+ mov d1,a2
+ mov a2,d1
+ mov a2,a1
+ mov sp,a2
+ mov a1,sp
+ mov d2,psw
+ mov mdr,d1
+ mov d2,mdr
+ mov (a2),d1
+ mov (8,a2),d1
+ mov (256,a2),d1
+ mov (131071,a2),d1
+ mov (8,sp),d1
+ mov (256,sp),d1
+ mov psw,d3
diff --git a/gas/testsuite/gas/mn10300/mov2.s b/gas/testsuite/gas/mn10300/mov2.s
new file mode 100644
index 0000000000..50d1edc5a8
--- /dev/null
+++ b/gas/testsuite/gas/mn10300/mov2.s
@@ -0,0 +1,16 @@
+ .text
+ mov (131071,sp),d1
+ mov (d1,a1),d2
+ mov (32768),d1
+ mov (131071),d1
+ mov (a2),a1
+ mov (8,a2),a1
+ mov (256,a2),a1
+ mov (131071,a2),a1
+ mov (8,sp),a1
+ mov (256,sp),a1
+ mov (131071,sp),a1
+ mov (d1,a1),a2
+ mov (32768),a1
+ mov (131071),a1
+ mov (32,a1),sp
diff --git a/gas/testsuite/gas/mn10300/mov3.s b/gas/testsuite/gas/mn10300/mov3.s
new file mode 100644
index 0000000000..90ec0b98a9
--- /dev/null
+++ b/gas/testsuite/gas/mn10300/mov3.s
@@ -0,0 +1,16 @@
+ .text
+ mov d1,(a2)
+ mov d1,(32,a2)
+ mov d1,(256,a2)
+ mov d1,(131071,a2)
+ mov d1,(32,sp)
+ mov d1,(32768,sp)
+ mov d1,(131071,sp)
+ mov d1,(d2,a2)
+ mov d1,(128)
+ mov d1,(131071)
+ mov a1,(a2)
+ mov a1,(32,a2)
+ mov a1,(256,a2)
+ mov a1,(131071,a2)
+ mov a1,(32,sp)
diff --git a/gas/testsuite/gas/mn10300/mov4.s b/gas/testsuite/gas/mn10300/mov4.s
new file mode 100644
index 0000000000..99d69c12dc
--- /dev/null
+++ b/gas/testsuite/gas/mn10300/mov4.s
@@ -0,0 +1,13 @@
+ .text
+ mov a1,(32768,sp)
+ mov a1,(131071,sp)
+ mov a1,(d2,a2)
+ mov a1,(128)
+ mov a1,(131071)
+ mov sp,(32,a1)
+ mov 8,d1
+ mov 256,d1
+ mov 131071,d1
+ mov 8,a1
+ mov 256,a1
+ mov 131071,a1
diff --git a/gas/testsuite/gas/mn10300/movbu.s b/gas/testsuite/gas/mn10300/movbu.s
new file mode 100644
index 0000000000..8fdb7beef4
--- /dev/null
+++ b/gas/testsuite/gas/mn10300/movbu.s
@@ -0,0 +1,21 @@
+ .text
+ movbu (a2),d1
+ movbu (8,a2),d1
+ movbu (256,a2),d1
+ movbu (131071,a2),d1
+ movbu (8,sp),d1
+ movbu (256,sp),d1
+ movbu (131071,sp),d1
+ movbu (d1,a1),d2
+ movbu (32768),d1
+ movbu (131071),d1
+ movbu d1,(a2)
+ movbu d1,(32,a2)
+ movbu d1,(256,a2)
+ movbu d1,(131071,a2)
+ movbu d1,(32,sp)
+ movbu d1,(32768,sp)
+ movbu d1,(131071,sp)
+ movbu d1,(d2,a2)
+ movbu d1,(128)
+ movbu d1,(131071)
diff --git a/gas/testsuite/gas/mn10300/movhu.s b/gas/testsuite/gas/mn10300/movhu.s
new file mode 100644
index 0000000000..4637e80df7
--- /dev/null
+++ b/gas/testsuite/gas/mn10300/movhu.s
@@ -0,0 +1,21 @@
+ .text
+ movhu (a2),d1
+ movhu (8,a2),d1
+ movhu (256,a2),d1
+ movhu (131071,a2),d1
+ movhu (8,sp),d1
+ movhu (256,sp),d1
+ movhu (131071,sp),d1
+ movhu (d1,a1),d2
+ movhu (32768),d1
+ movhu (131071),d1
+ movhu d1,(a2)
+ movhu d1,(32,a2)
+ movhu d1,(256,a2)
+ movhu d1,(131071,a2)
+ movhu d1,(32,sp)
+ movhu d1,(32768,sp)
+ movhu d1,(131071,sp)
+ movhu d1,(d2,a2)
+ movhu d1,(128)
+ movhu d1,(131071)
diff --git a/gas/testsuite/gas/mn10300/movm.s b/gas/testsuite/gas/mn10300/movm.s
new file mode 100644
index 0000000000..ccfc6830ef
--- /dev/null
+++ b/gas/testsuite/gas/mn10300/movm.s
@@ -0,0 +1,5 @@
+ .text
+ movm (sp),[a2,a3]
+ movm (sp),[d2,d3,a2,a3,other]
+ movm [a2,a3],(sp)
+ movm [d2,d3,a2,a3,other],(sp)
diff --git a/gas/testsuite/gas/mn10300/muldiv.s b/gas/testsuite/gas/mn10300/muldiv.s
new file mode 100644
index 0000000000..3f11e5d166
--- /dev/null
+++ b/gas/testsuite/gas/mn10300/muldiv.s
@@ -0,0 +1,5 @@
+ .text
+ mul d1,d2
+ mulu d2,d3
+ div d3,d3
+ divu d3,d2
diff --git a/gas/testsuite/gas/mn10300/other.s b/gas/testsuite/gas/mn10300/other.s
new file mode 100644
index 0000000000..3eaf74a3f5
--- /dev/null
+++ b/gas/testsuite/gas/mn10300/other.s
@@ -0,0 +1,20 @@
+ .text
+ clr d2
+ inc d1
+ inc a2
+ inc4 a3
+ jmp (a2)
+ jmp 256
+ jmp 131071
+ call 256,[a2,a3],9
+ call 131071,[a2,a3],32
+ calls (a2)
+ calls 256
+ calls 131071
+ ret [a2,a3],7
+ retf [a2,a3],5
+ rets
+ rti
+ trap
+ nop
+ rtm
diff --git a/gas/testsuite/gas/mn10300/shift.s b/gas/testsuite/gas/mn10300/shift.s
new file mode 100644
index 0000000000..ec8c9cefb9
--- /dev/null
+++ b/gas/testsuite/gas/mn10300/shift.s
@@ -0,0 +1,10 @@
+ .text
+ asr d1,d2
+ asr 4,d2
+ lsr d2,d3
+ lsr 4,d3
+ asl d3,d2
+ asl 4,d2
+ asl2 d2
+ ror d1
+ rol d2
diff --git a/gas/testsuite/gas/mn10300/sub.s b/gas/testsuite/gas/mn10300/sub.s
new file mode 100644
index 0000000000..13dc663d84
--- /dev/null
+++ b/gas/testsuite/gas/mn10300/sub.s
@@ -0,0 +1,8 @@
+ .text
+ sub d1,d2
+ sub d2,a3
+ sub a3,d3
+ sub a3,a2
+ sub 131071,d2
+ sub 131071,a1
+ subc d1,d2
diff --git a/gas/testsuite/gas/mn10300/udf.s b/gas/testsuite/gas/mn10300/udf.s
new file mode 100644
index 0000000000..87cbd136f2
--- /dev/null
+++ b/gas/testsuite/gas/mn10300/udf.s
@@ -0,0 +1,129 @@
+ .text
+ udf00 d0,d1
+ udf01 d0,d1
+ udf02 d0,d1
+ udf03 d0,d1
+ udf04 d0,d1
+ udf05 d0,d1
+ udf06 d0,d1
+ udf07 d0,d1
+ udf08 d0,d1
+ udf09 d0,d1
+ udf10 d0,d1
+ udf11 d0,d1
+ udf12 d0,d1
+ udf13 d0,d1
+ udf14 d0,d1
+ udf15 d0,d1
+ udf20 d0,d1
+ udf21 d0,d1
+ udf22 d0,d1
+ udf23 d0,d1
+ udf24 d0,d1
+ udf25 d0,d1
+ udf26 d0,d1
+ udf27 d0,d1
+ udf28 d0,d1
+ udf29 d0,d1
+ udf30 d0,d1
+ udf31 d0,d1
+ udf32 d0,d1
+ udf33 d0,d1
+ udf34 d0,d1
+ udf35 d0,d1
+ udf00 127,d1
+ udf01 127,d1
+ udf02 127,d1
+ udf03 127,d1
+ udf04 127,d1
+ udf05 127,d1
+ udf06 127,d1
+ udf07 127,d1
+ udf08 127,d1
+ udf09 127,d1
+ udf10 127,d1
+ udf11 127,d1
+ udf12 127,d1
+ udf13 127,d1
+ udf14 127,d1
+ udf15 127,d1
+ udf00 32767,d1
+ udf01 32767,d1
+ udf02 32767,d1
+ udf03 32767,d1
+ udf04 32767,d1
+ udf05 32767,d1
+ udf06 32767,d1
+ udf07 32767,d1
+ udf08 32767,d1
+ udf09 32767,d1
+ udf10 32767,d1
+ udf11 32767,d1
+ udf12 32767,d1
+ udf13 32767,d1
+ udf14 32767,d1
+ udf15 32767,d1
+ udf00 65535,d1
+ udf01 65535,d1
+ udf02 65535,d1
+ udf03 65535,d1
+ udf04 65535,d1
+ udf05 65535,d1
+ udf06 65535,d1
+ udf07 65535,d1
+ udf08 65535,d1
+ udf09 65535,d1
+ udf10 65535,d1
+ udf11 65535,d1
+ udf12 65535,d1
+ udf13 65535,d1
+ udf14 65535,d1
+ udf15 65535,d1
+ udfu00 128,d1
+ udfu01 128,d1
+ udfu02 128,d1
+ udfu03 128,d1
+ udfu04 128,d1
+ udfu05 128,d1
+ udfu06 128,d1
+ udfu07 128,d1
+ udfu08 128,d1
+ udfu09 128,d1
+ udfu10 128,d1
+ udfu11 128,d1
+ udfu12 128,d1
+ udfu13 128,d1
+ udfu14 128,d1
+ udfu15 128,d1
+ udfu00 32768,d1
+ udfu01 32768,d1
+ udfu02 32768,d1
+ udfu03 32768,d1
+ udfu04 32768,d1
+ udfu05 32768,d1
+ udfu06 32768,d1
+ udfu07 32768,d1
+ udfu08 32768,d1
+ udfu09 32768,d1
+ udfu10 32768,d1
+ udfu11 32768,d1
+ udfu12 32768,d1
+ udfu13 32768,d1
+ udfu14 32768,d1
+ udfu15 32768,d1
+ udfu00 65536,d1
+ udfu01 65536,d1
+ udfu02 65536,d1
+ udfu03 65536,d1
+ udfu04 65536,d1
+ udfu05 65536,d1
+ udfu06 65536,d1
+ udfu07 65536,d1
+ udfu08 65536,d1
+ udfu09 65536,d1
+ udfu10 65536,d1
+ udfu11 65536,d1
+ udfu12 65536,d1
+ udfu13 65536,d1
+ udfu14 65536,d1
+ udfu15 65536,d1
diff --git a/gas/testsuite/gas/mri/char.d b/gas/testsuite/gas/mri/char.d
new file mode 100644
index 0000000000..025f4b5914
--- /dev/null
+++ b/gas/testsuite/gas/mri/char.d
@@ -0,0 +1,9 @@
+#objcopy: -O srec
+#name: MRI character constants
+#as: -M
+
+# Test MRI character constants
+
+S0.*
+S113....(61616263616263646500000061276200)|(61616263646362610000006500622761).*
+#pass
diff --git a/gas/testsuite/gas/mri/char.s b/gas/testsuite/gas/mri/char.s
new file mode 100644
index 0000000000..7b0a83a9d2
--- /dev/null
+++ b/gas/testsuite/gas/mri/char.s
@@ -0,0 +1,6 @@
+; Test MRI style character constants.
+
+ dc.b 'a'
+ dc.b 'abc'
+ dc.l 'abcde'
+ dc.l 'a''b'
diff --git a/gas/testsuite/gas/mri/comment.d b/gas/testsuite/gas/mri/comment.d
new file mode 100644
index 0000000000..30434dd2f8
--- /dev/null
+++ b/gas/testsuite/gas/mri/comment.d
@@ -0,0 +1,9 @@
+#nm: --extern-only
+#name: MRI comments
+#as: -M
+
+# Test MRI comments
+
+0+02 A RAM
+0+01 A ROM
+ * U label
diff --git a/gas/testsuite/gas/mri/comment.s b/gas/testsuite/gas/mri/comment.s
new file mode 100644
index 0000000000..857318fa65
--- /dev/null
+++ b/gas/testsuite/gas/mri/comment.s
@@ -0,0 +1,13 @@
+ xref label
+ xdef ROM,RAM
+ * this is a comment
+
+ dc.l label loop if we haven't reach end yet
+
+ROM EQU $00000001 * word wide
+RAM EQU $00000002 word wide
+ dc.l RAM
+ dc.l 0 ,really,a,comment
+; a comment
+ ; another comment
+ ; another comment
diff --git a/gas/testsuite/gas/mri/common.d b/gas/testsuite/gas/mri/common.d
new file mode 100644
index 0000000000..c1c1530c21
--- /dev/null
+++ b/gas/testsuite/gas/mri/common.d
@@ -0,0 +1,8 @@
+#nm: --extern-only
+#name: MRI common sections
+#as: -M
+
+# Test MRI common sections
+
+0+08 C 00com2
+0+08 C com1
diff --git a/gas/testsuite/gas/mri/common.s b/gas/testsuite/gas/mri/common.s
new file mode 100644
index 0000000000..d735c6b920
--- /dev/null
+++ b/gas/testsuite/gas/mri/common.s
@@ -0,0 +1,11 @@
+; Test MRI common sections
+ common com1
+ ds.l 1
+com2 common 00
+ ds.l 1
+incom ds.l 1
+ common com1
+ ds.l 1
+ data
+ dc.l com1
+ dc.l incom
diff --git a/gas/testsuite/gas/mri/constants.d b/gas/testsuite/gas/mri/constants.d
new file mode 100644
index 0000000000..7210022284
--- /dev/null
+++ b/gas/testsuite/gas/mri/constants.d
@@ -0,0 +1,20 @@
+#nm: --extern-only
+#name: MRI constants
+#as: -M
+
+# Test MRI style constants
+
+0*0 T foo
+0*a A s01
+0*a A s02
+0*a A s03
+0*a A s04
+0*a A s05
+0*a A s06
+0*a A s07
+0*a A s08
+0*a A s09
+0*61 A s10
+0*61 A s11
+0*61626364 A s12
+0*61276200 A s13
diff --git a/gas/testsuite/gas/mri/constants.s b/gas/testsuite/gas/mri/constants.s
new file mode 100644
index 0000000000..0034e6765e
--- /dev/null
+++ b/gas/testsuite/gas/mri/constants.s
@@ -0,0 +1,31 @@
+ xdef s01,s02,s03,s04,s05,s06,s07,s08,s09,s10,s11,s12,s13
+s01 equ %1010
+s02 equ 1010b
+s03 equ @12
+s04 equ 12o
+s05 equ 12q
+s06 equ 10
+s07 equ 10d
+s08 equ $a
+s09 equ 0ah
+s10 equ 'a'
+s11 equ A'a'
+s12 equ 'abcd'
+s13 equ 'a''b'
+
+ xdef foo
+foo
+ moveq.l #%1010,d0
+ moveq.l #1010b,d0
+ moveq.l #@12,d0
+ moveq.l #12o,d0
+ moveq.l #12q,d0
+ moveq.l #10,d0
+ moveq.l #10d,d0
+ moveq.l #$a,d0
+ moveq.l #0ah,d0
+ moveq.l #'a',d0
+ moveq.l #A'a',d0
+ nop
+
+ end
diff --git a/gas/testsuite/gas/mri/empty.s b/gas/testsuite/gas/mri/empty.s
new file mode 100644
index 0000000000..94c2cdd71d
--- /dev/null
+++ b/gas/testsuite/gas/mri/empty.s
@@ -0,0 +1,9 @@
+SBT MACRO ; empty macro
+ ENDM
+
+ SBT arg1
+ SBT arg2 - one tww
+ SBT arg3 - one two three
+ SBT arg4 - one two three four
+ SBT arg5 - one two three four five
+ SBT arg6 - one two (three)
diff --git a/gas/testsuite/gas/mri/equ.d b/gas/testsuite/gas/mri/equ.d
new file mode 100644
index 0000000000..e5f9a86776
--- /dev/null
+++ b/gas/testsuite/gas/mri/equ.d
@@ -0,0 +1,7 @@
+#nm: --extern-only
+#name: MRI EQU
+#as: -M
+
+# Test the MRI EQU directive
+
+0*4 A SYMBOL
diff --git a/gas/testsuite/gas/mri/equ.s b/gas/testsuite/gas/mri/equ.s
new file mode 100644
index 0000000000..a6512a10ca
--- /dev/null
+++ b/gas/testsuite/gas/mri/equ.s
@@ -0,0 +1,3 @@
+# Test the MRI EQU directive
+ XDEF SYMBOL
+SYMBOL EQU 4
diff --git a/gas/testsuite/gas/mri/expr.d b/gas/testsuite/gas/mri/expr.d
new file mode 100644
index 0000000000..71dee4eb21
--- /dev/null
+++ b/gas/testsuite/gas/mri/expr.d
@@ -0,0 +1,11 @@
+#nm: --extern-only
+#name: MRI expressions
+#as: -M
+
+# Test expressions in MRI mode
+
+00* A s1
+00*12 A s2
+00*6 A s3
+(00000000)?ff* A s4
+00* A s5
diff --git a/gas/testsuite/gas/mri/expr.s b/gas/testsuite/gas/mri/expr.s
new file mode 100644
index 0000000000..57677c18e1
--- /dev/null
+++ b/gas/testsuite/gas/mri/expr.s
@@ -0,0 +1,7 @@
+; Test expressions in MRI mode
+ xdef s1,s2,s3,s4,s5
+s1 equ 1>2
+s2 equ 3<<1*3
+s3 equ 5!!3
+s4 equ "0
+s5 equ (1>=2)!(1<>1)
diff --git a/gas/testsuite/gas/mri/float.d b/gas/testsuite/gas/mri/float.d
new file mode 100644
index 0000000000..dea627afa6
--- /dev/null
+++ b/gas/testsuite/gas/mri/float.d
@@ -0,0 +1,10 @@
+#objcopy: -O srec
+#name: MRI floating point constants
+#as: -M
+
+# Test MRI floating point constants
+
+S0.*
+S118....(123456789ABCDEF03F800000412000004120000042)|(F0DEBC9A785634120000803F000020410000204100).*
+S10.....(C80000)|(00C842).*
+#pass
diff --git a/gas/testsuite/gas/mri/float.s b/gas/testsuite/gas/mri/float.s
new file mode 100644
index 0000000000..637f9c6c91
--- /dev/null
+++ b/gas/testsuite/gas/mri/float.s
@@ -0,0 +1,7 @@
+; Test floating point constants in MRI mode.
+
+ dc.d :1234_5678_9abc_def0
+ dc.s 1.0
+ dc.s 1e1
+ dc.s 1_e_1
+ dc.s 1E2
diff --git a/gas/testsuite/gas/mri/for.d b/gas/testsuite/gas/mri/for.d
new file mode 100644
index 0000000000..e75fb95c7b
--- /dev/null
+++ b/gas/testsuite/gas/mri/for.d
@@ -0,0 +1,30 @@
+#objdump: -d --prefix-addresses
+#name: MRI structured for
+#as: -M
+
+# Test MRI structured for pseudo-op.
+
+.*: file format .*
+
+Disassembly of section .text:
+0+000 <foo> clrw %d1
+0+002 <foo\+(0x|)2> movew #1,%d0
+0+006 <foo\+(0x|)6> cmpiw #10,%d0
+0+00a <foo\+(0x|)a> blts 0+016 <foo\+(0x|)16>
+0+00c <foo\+(0x|)c> addw %d0,%d1
+0+00e <foo\+(0x|)e> bvcs 0+012 <foo\+(0x|)12>
+0+010 <foo\+(0x|)10> bras 0+016 <foo\+(0x|)16>
+0+012 <foo\+(0x|)12> addqw #2,%d0
+0+014 <foo\+(0x|)14> bras 0+006 <foo\+(0x|)6>
+0+016 <foo\+(0x|)16> clrw %d1
+0+018 <foo\+(0x|)18> movew #10,%d0
+0+01c <foo\+(0x|)1c> cmpiw #1,%d0
+0+020 <foo\+(0x|)20> bgts 0+030 <foo\+(0x|)30>
+0+022 <foo\+(0x|)22> cmpiw #100,%d1
+0+026 <foo\+(0x|)26> bgts 0+02a <foo\+(0x|)2a>
+0+028 <foo\+(0x|)28> bras 0+02c <foo\+(0x|)2c>
+0+02a <foo\+(0x|)2a> addw %d0,%d1
+0+02c <foo\+(0x|)2c> subqw #1,%d0
+0+02e <foo\+(0x|)2e> bras 0+01c <foo\+(0x|)1c>
+0+030 <foo\+(0x|)30> nop
+0+032 <foo\+(0x|)32> nop
diff --git a/gas/testsuite/gas/mri/for.s b/gas/testsuite/gas/mri/for.s
new file mode 100644
index 0000000000..7524725a4b
--- /dev/null
+++ b/gas/testsuite/gas/mri/for.s
@@ -0,0 +1,22 @@
+; Test MRI structured for pseudo-op.
+
+ xdef foo
+foo
+ clr d1
+ for d0 = #1 to #10 by #2 do
+ add d0,d1 arbitrary text 'in comment field
+ if <vs> then
+ break
+ endi
+ endf
+
+ clr d1
+ for d0 = #10 downto #1 do
+ if d1 <ge> #100 then
+ next
+ endi
+ add d0,d1
+ endf
+
+ nop
+ nop
diff --git a/gas/testsuite/gas/mri/if.d b/gas/testsuite/gas/mri/if.d
new file mode 100644
index 0000000000..832972cd40
--- /dev/null
+++ b/gas/testsuite/gas/mri/if.d
@@ -0,0 +1,25 @@
+#objdump: -d --prefix-addresses
+#name: MRI structured if
+#as: -M
+
+# Test MRI structured if pseudo-op.
+
+.*: file format .*
+
+Disassembly of section .text:
+0+000 <foo> cmpw %d1,%d0
+0+002 <foo\+(0x|)2> bles 0+014 <foo\+(0x|)14>
+0+004 <foo\+(0x|)4> cmpw %d2,%d0
+0+006 <foo\+(0x|)6> bles 0+014 <foo\+(0x|)14>
+0+008 <foo\+(0x|)8> cmpw %d1,%d2
+0+00a <foo\+(0x|)a> bles 0+010 <foo\+(0x|)10>
+0+00c <foo\+(0x|)c> movew %d1,%d3
+0+00e <foo\+(0x|)e> bras 0+012 <foo\+(0x|)12>
+0+010 <foo\+(0x|)10> movew %d2,%d3
+0+012 <foo\+(0x|)12> bras 0+01e <foo\+(0x|)1e>
+0+014 <foo\+(0x|)14> cmpw %d0,%d1
+0+016 <foo\+(0x|)16> bgts 0+01c <foo\+(0x|)1c>
+0+018 <foo\+(0x|)18> cmpw %d0,%d2
+0+01a <foo\+(0x|)1a> bles 0+01e <foo\+(0x|)1e>
+0+01c <foo\+(0x|)1c> movew %d0,%d3
+0+01e <foo\+(0x|)1e> nop
diff --git a/gas/testsuite/gas/mri/if.s b/gas/testsuite/gas/mri/if.s
new file mode 100644
index 0000000000..2646be8ab1
--- /dev/null
+++ b/gas/testsuite/gas/mri/if.s
@@ -0,0 +1,17 @@
+; Test MRI structured if pseudo-op.
+
+ xdef foo
+foo
+ if d1 <gt> d0 and d2 <gt> d0 then
+ if d1 <gt> d2 then
+ move d1,d3
+ else
+ move d2,d3
+ endi
+ else
+ if d0 <gt> d1 or d0 <gt> d2 then
+ move d0,d3
+ endi
+ endi
+
+ nop
diff --git a/gas/testsuite/gas/mri/immconst.d b/gas/testsuite/gas/mri/immconst.d
new file mode 100644
index 0000000000..ef2da10afd
--- /dev/null
+++ b/gas/testsuite/gas/mri/immconst.d
@@ -0,0 +1,22 @@
+#objdump: -d --prefix-addresses
+#name: MRI immediate constants
+#as: -M
+#source: constants.s
+
+# Test MRI immediate constants
+
+.*: file format .*
+
+Disassembly of section .text:
+0+000 <foo> moveq #10,%d0
+0+002 <foo\+(0x|)2> moveq #10,%d0
+0+004 <foo\+(0x|)4> moveq #10,%d0
+0+006 <foo\+(0x|)6> moveq #10,%d0
+0+008 <foo\+(0x|)8> moveq #10,%d0
+0+00a <foo\+(0x|)a> moveq #10,%d0
+0+00c <foo\+(0x|)c> moveq #10,%d0
+0+00e <foo\+(0x|)e> moveq #10,%d0
+0+010 <foo\+(0x|)10> moveq #10,%d0
+0+012 <foo\+(0x|)12> moveq #97,%d0
+0+014 <foo\+(0x|)14> moveq #97,%d0
+0+016 <foo\+(0x|)16> nop
diff --git a/gas/testsuite/gas/mri/label.d b/gas/testsuite/gas/mri/label.d
new file mode 100644
index 0000000000..9ce5858daf
--- /dev/null
+++ b/gas/testsuite/gas/mri/label.d
@@ -0,0 +1,8 @@
+#nm: --extern-only
+#name: MRI label
+#as: -M
+
+# Test using an MRI style label
+
+0000* T LABEL
+[ ]*U SYMBOL
diff --git a/gas/testsuite/gas/mri/label.s b/gas/testsuite/gas/mri/label.s
new file mode 100644
index 0000000000..b05ec2a4f4
--- /dev/null
+++ b/gas/testsuite/gas/mri/label.s
@@ -0,0 +1,5 @@
+; Test using an MRI style label
+* Also test MRI style comments
+! And another comment
+ XDEF LABEL
+LABEL DC.L SYMBOL ; And yet another comment
diff --git a/gas/testsuite/gas/mri/moveml.d b/gas/testsuite/gas/mri/moveml.d
new file mode 100644
index 0000000000..2c36fa8ee5
--- /dev/null
+++ b/gas/testsuite/gas/mri/moveml.d
@@ -0,0 +1,27 @@
+#objdump: -d
+#name: MRI moveml
+#as: -M
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+000 <.text>:
+ 0: 4cdf 07fc moveml %sp@\+,%d2-%a2
+ 4: 4cdf 07fc moveml %sp@\+,%d2-%a2
+ 8: 48f9 07fc 0000 moveml %d2-%a2,0 <.text>
+ e: 0000
+ 10: 48f9 07fc 0000 moveml %d2-%a2,0 <.text>
+ 16: 0000
+ 18: 4cf9 07fc 0000 moveml 0 <.text>,%d2-%a2
+ 1e: 0000
+ 20: 4cf9 07fc 0000 moveml 0 <.text>,%d2-%a2
+ 26: 0000
+ 28: 4cf9 07fc 0001 moveml 16000 <fdsa>,%d2-%a2
+ 2e: 6000
+ 30: 4cf9 07fc 0001 moveml 16000 <fdsa>,%d2-%a2
+ 36: 6000
+ 38: 48f9 07fc 0001 moveml %d2-%a2,16000 <fdsa>
+ 3e: 6000
+ 40: 48f9 07fc 0001 moveml %d2-%a2,16000 <fdsa>
+ 46: 6000
diff --git a/gas/testsuite/gas/mri/moveml.s b/gas/testsuite/gas/mri/moveml.s
new file mode 100644
index 0000000000..b8fc728ba8
--- /dev/null
+++ b/gas/testsuite/gas/mri/moveml.s
@@ -0,0 +1,17 @@
+asdf reg a0-a2/d2-d7
+fdsa equ $16000
+
+ movem.l (sp)+,a0-a2/d2-d7
+ movem.l (sp)+,asdf
+
+ movem.l a0-a2/d2-d7,symbol
+ movem.l asdf,symbol
+
+ movem.l symbol,a0-a2/d2-d7
+ movem.l symbol,asdf
+
+ movem.l fdsa,a0-a2/d2-d7
+ movem.l fdsa,asdf
+
+ movem.l a0-a2/d2-d7,fdsa
+ movem.l asdf,fdsa
diff --git a/gas/testsuite/gas/mri/mri.exp b/gas/testsuite/gas/mri/mri.exp
new file mode 100644
index 0000000000..f3fcded1e5
--- /dev/null
+++ b/gas/testsuite/gas/mri/mri.exp
@@ -0,0 +1,28 @@
+#
+# Test the m68k MRI compatibility mode.
+#
+# I originally thought that most of tests applied to any MRI
+# assembler, but it turns out that different MRI assemblers use
+# different syntaxes.
+#
+
+if ![istarget "m68*-*-*"] {
+ return
+}
+
+run_dump_test label
+run_dump_test equ
+run_dump_test constants
+run_dump_test immconst
+run_dump_test float
+run_dump_test char
+run_dump_test expr
+run_dump_test common
+run_dump_test comment
+gas_test "empty.s" "-M" "" "MRI empty macro"
+run_dump_test for
+run_dump_test if
+run_dump_test repeat
+run_dump_test while
+run_dump_test semi
+run_dump_test moveml
diff --git a/gas/testsuite/gas/mri/repeat.d b/gas/testsuite/gas/mri/repeat.d
new file mode 100644
index 0000000000..3cc5f63839
--- /dev/null
+++ b/gas/testsuite/gas/mri/repeat.d
@@ -0,0 +1,16 @@
+#objdump: -d --prefix-addresses
+#name: MRI structured repeat
+#as: -M
+
+# Test MRI structured repeat pseudo-op.
+
+.*: file format .*
+
+Disassembly of section .text:
+0+000 <foo> bccs 0+000 <foo>
+0+002 <foo\+(0x|)2> clrw %d1
+0+004 <foo\+(0x|)4> addqw #1,%d1
+0+006 <foo\+(0x|)6> cmpiw #10,%d1
+0+00a <foo\+(0x|)a> bgts 0+004 <foo\+(0x|)4>
+0+00c <foo\+(0x|)c> nop
+0+00e <foo\+(0x|)e> nop
diff --git a/gas/testsuite/gas/mri/repeat.s b/gas/testsuite/gas/mri/repeat.s
new file mode 100644
index 0000000000..0e4ea2b652
--- /dev/null
+++ b/gas/testsuite/gas/mri/repeat.s
@@ -0,0 +1,14 @@
+; Test MRI structured repeat pseudo-op.
+
+ xdef foo
+foo
+ repeat
+ until <cs>
+
+ clr d1
+ repeat
+ add #1,d1
+ until d1 <ge> #10
+
+ nop
+ nop
diff --git a/gas/testsuite/gas/mri/semi.d b/gas/testsuite/gas/mri/semi.d
new file mode 100644
index 0000000000..0decce1847
--- /dev/null
+++ b/gas/testsuite/gas/mri/semi.d
@@ -0,0 +1,9 @@
+#objdump: -s -j .text
+#name: MRI semi
+#as: -M
+
+.*: .*
+
+Contents of section .text:
+ 0000 3b203b20 3a203a20 00000000 00000000 ; ; : : ........
+ 0010 00000000 00000000 00000000 00000000 ................
diff --git a/gas/testsuite/gas/mri/semi.s b/gas/testsuite/gas/mri/semi.s
new file mode 100644
index 0000000000..5b30677c47
--- /dev/null
+++ b/gas/testsuite/gas/mri/semi.s
@@ -0,0 +1,14 @@
+semicolon macro
+ dc.b '; '
+ endm
+
+colon macro
+ dc.b ': '
+ endm
+
+ semicolon
+ dc.b '; '
+ colon
+ dc.b ': '
+
+ p2align 5
diff --git a/gas/testsuite/gas/mri/while.d b/gas/testsuite/gas/mri/while.d
new file mode 100644
index 0000000000..d8dd37a359
--- /dev/null
+++ b/gas/testsuite/gas/mri/while.d
@@ -0,0 +1,18 @@
+#objdump: -d --prefix-addresses
+#name: MRI structured while
+#as: -M
+
+# Test MRI structure while pseudo-op.
+
+.*: file format .*
+
+Disassembly of section .text:
+0+000 <foo> bccs 0+004 <foo\+(0x|)4>
+0+002 <foo\+(0x|)2> bras 0+000 <foo>
+0+004 <foo\+(0x|)4> clrw %d1
+0+006 <foo\+(0x|)6> cmpiw #10,%d1
+0+00a <foo\+(0x|)a> blts 0+010 <foo\+(0x|)10>
+0+00c <foo\+(0x|)c> addqw #1,%d1
+0+00e <foo\+(0x|)e> bras 0+006 <foo\+(0x|)6>
+0+010 <foo\+(0x|)10> nop
+0+012 <foo\+(0x|)12> nop
diff --git a/gas/testsuite/gas/mri/while.s b/gas/testsuite/gas/mri/while.s
new file mode 100644
index 0000000000..35cbdbbbc1
--- /dev/null
+++ b/gas/testsuite/gas/mri/while.s
@@ -0,0 +1,14 @@
+; Test MRI structured while pseudo-op.
+
+ xdef foo
+foo
+ while <cs> do
+ endw
+
+ clr d1
+ while d1 <le> #10 do
+ add #1,d1
+ endw
+
+ nop
+ nop
diff --git a/gas/testsuite/gas/ppc/astest.d b/gas/testsuite/gas/ppc/astest.d
new file mode 100644
index 0000000000..68aab554df
--- /dev/null
+++ b/gas/testsuite/gas/ppc/astest.d
@@ -0,0 +1,74 @@
+#objdump: -Dr
+#name: PowerPC test 1
+
+.*: +file format elf32-powerpc
+
+Disassembly of section \.text:
+
+0+0000000 <foo>:
+ 0: 60 00 00 00 nop
+ 4: 60 00 00 00 nop
+ 8: 60 00 00 00 nop
+
+0+000000c <a>:
+ c: 48 00 00 04 b 10 <apfour>
+
+0+0000010 <apfour>:
+ 10: 48 00 00 08 b 18 <apfour\+0x8>
+ 14: 48 00 00 00 b 14 <apfour\+0x4>
+ 14: R_PPC_REL24 x
+ 18: 48 00 00 04 b 1c <apfour\+0xc>
+ 18: R_PPC_REL24 \.data\+0x4
+ 1c: 48 00 00 00 b 1c <apfour\+0xc>
+ 1c: R_PPC_REL24 z
+ 20: 48 00 00 14 b 34 <apfour\+0x24>
+ 20: R_PPC_REL24 z\+0x14
+ 24: 48 00 00 04 b 28 <apfour\+0x18>
+ 28: 48 00 00 00 b 28 <apfour\+0x18>
+ 28: R_PPC_REL24 a
+ 2c: 4b ff ff e4 b 10 <apfour>
+ 30: 48 00 00 04 b 34 <apfour\+0x24>
+ 30: R_PPC_REL24 a\+0x4
+ 34: 4b ff ff e0 b 14 <apfour\+0x4>
+ 38: 48 00 00 00 b 38 <apfour\+0x28>
+ 38: R_PPC_LOCAL24PC a
+ 3c: 4b ff ff d4 b 10 <apfour>
+
+ 40: 00 00 00 40 \.long 0x40
+ 40: R_PPC_ADDR32 \.text\+0x40
+
+ 44: 00 00 00 4c \.long 0x4c
+ 44: R_PPC_ADDR32 \.text\+0x4c
+ 48: 00 00 00 00 \.long 0x0
+ 48: R_PPC_REL32 x
+ 4c: 00 00 00 04 \.long 0x4
+ 4c: R_PPC_REL32 x\+0x4
+ \.\.\.
+ 50: R_PPC_REL32 z
+ 54: R_PPC_REL32 y
+ 58: R_PPC_ADDR32 x
+ 5c: R_PPC_ADDR32 y
+ 60: R_PPC_ADDR32 z
+ 64: ff ff ff fc fnmsub f31,f31,f31,f31
+ 64: R_PPC_ADDR32 x\+0xf+ffffffc
+ 68: ff ff ff fc fnmsub f31,f31,f31,f31
+ 68: R_PPC_ADDR32 y\+0xf+ffffffc
+ 6c: ff ff ff fc fnmsub f31,f31,f31,f31
+ 6c: R_PPC_ADDR32 z\+0xf+ffffffc
+ 70: ff ff ff 9c \.long 0xffffff9c
+ 74: ff ff ff 9c \.long 0xffffff9c
+ \.\.\.
+ 78: R_PPC_ADDR32 a
+ 7c: R_PPC_ADDR32 b
+ 80: R_PPC_ADDR32 apfour
+ 84: ff ff ff fc fnmsub f31,f31,f31,f31
+ 88: 00 00 00 02 \.long 0x2
+ 88: R_PPC_ADDR32 apfour\+0x2
+ 8c: 00 00 00 00 \.long 0x0
+Disassembly of section \.data:
+
+0+0000000 <x>:
+ 0: 00 00 00 00 \.long 0x0
+
+0+0000004 <y>:
+ 4: 00 00 00 00 \.long 0x0
diff --git a/gas/testsuite/gas/ppc/astest.s b/gas/testsuite/gas/ppc/astest.s
new file mode 100644
index 0000000000..f1af216313
--- /dev/null
+++ b/gas/testsuite/gas/ppc/astest.s
@@ -0,0 +1,52 @@
+ .section ".data"
+ .globl x
+ .globl z
+x: .long 0
+z = . + 4
+four = z - x - 4
+y: .long 0
+
+ .section ".text"
+foo:
+ nop ; nop ; nop
+ .globl a
+a: b .+4
+b: b .+8
+ b x
+ b y
+ b z
+ b z+20
+ b .+four
+ b a
+ b b
+ b a+4
+ b b+4
+ b a@local
+ b b@local
+ .long .
+ .long .+8
+ .long x-.
+ .long x+4-.
+ .long z-.
+ .long y-.
+ .long x
+ .long y
+ .long z
+ .long x-four
+ .long y-four
+ .long z-four
+ .long a-.
+ .long b-.
+ .long a
+ .long b
+
+apfour = a + four
+ .long apfour
+ .long a-apfour
+ .long apfour+2
+ .long apfour-b
+
+ .type foo,@function
+ .type a,@function
+ .type b,@function
+ .type apfour,@function
diff --git a/gas/testsuite/gas/ppc/astest2.d b/gas/testsuite/gas/ppc/astest2.d
new file mode 100644
index 0000000000..740e3bfe19
--- /dev/null
+++ b/gas/testsuite/gas/ppc/astest2.d
@@ -0,0 +1,75 @@
+#objdump: -Dr
+#name: PowerPC test 2
+
+.*: +file format elf32-powerpc
+
+Disassembly of section .text:
+
+0+0000000 <foo>:
+ 0: 60 00 00 00 nop
+ 4: 60 00 00 00 nop
+ 8: 60 00 00 00 nop
+ c: 48 00 00 04 b 10 <foo\+0x10>
+ 10: 48 00 00 08 b 18 <foo\+0x18>
+ 14: 48 00 00 00 b 14 <foo\+0x14>
+ 14: R_PPC_REL24 x
+ 18: 48 00 00 04 b 1c <foo\+0x1c>
+ 18: R_PPC_REL24 .data\+0x4
+ 1c: 48 00 00 00 b 1c <foo\+0x1c>
+ 1c: R_PPC_REL24 z
+ 20: 48 00 00 14 b 34 <foo\+0x34>
+ 20: R_PPC_REL24 z\+0x14
+ 24: 48 00 00 04 b 28 <foo\+0x28>
+ 28: 48 00 00 00 b 28 <foo\+0x28>
+ 28: R_PPC_REL24 a
+ 2c: 48 00 00 50 b 7c <apfour>
+ 30: 48 00 00 04 b 34 <foo\+0x34>
+ 30: R_PPC_REL24 a\+0x4
+ 34: 48 00 00 4c b 80 <apfour\+0x4>
+ 38: 48 00 00 00 b 38 <foo\+0x38>
+ 38: R_PPC_LOCAL24PC a
+ 3c: 48 00 00 40 b 7c <apfour>
+
+ 40: 00 00 00 40 .long 0x40
+ 40: R_PPC_ADDR32 .text\+0x40
+
+ 44: 00 00 00 4c .long 0x4c
+ 44: R_PPC_ADDR32 .text\+0x4c
+ 48: 00 00 00 00 .long 0x0
+ 48: R_PPC_REL32 x
+ 4c: 00 00 00 04 .long 0x4
+ 4c: R_PPC_REL32 x\+0x4
+ ...
+ 50: R_PPC_REL32 z
+ 54: R_PPC_REL32 y
+ 58: R_PPC_ADDR32 x
+ 5c: R_PPC_ADDR32 y
+ 60: R_PPC_ADDR32 z
+ 64: ff ff ff fc fnmsub f31,f31,f31,f31
+ 64: R_PPC_ADDR32 x\+0xf+ffffffc
+ 68: ff ff ff fc fnmsub f31,f31,f31,f31
+ 68: R_PPC_ADDR32 y\+0xf+ffffffc
+ 6c: ff ff ff fc fnmsub f31,f31,f31,f31
+ 6c: R_PPC_ADDR32 z\+0xf+ffffffc
+ 70: 00 00 00 08 .long 0x8
+ 74: 00 00 00 08 .long 0x8
+
+0+0000078 <a>:
+ 78: 00 00 00 00 .long 0x0
+ 78: R_PPC_ADDR32 a
+
+0+000007c <apfour>:
+ ...
+ 7c: R_PPC_ADDR32 b
+ 80: R_PPC_ADDR32 apfour
+ 84: ff ff ff fc fnmsub f31,f31,f31,f31
+ 88: 00 00 00 02 .long 0x2
+ 88: R_PPC_ADDR32 apfour\+0x2
+ 8c: 00 00 00 00 .long 0x0
+Disassembly of section .data:
+
+0+0000000 <x>:
+ 0: 00 00 00 00 .long 0x0
+
+0+0000004 <y>:
+ 4: 00 00 00 00 .long 0x0
diff --git a/gas/testsuite/gas/ppc/astest2.s b/gas/testsuite/gas/ppc/astest2.s
new file mode 100644
index 0000000000..5af223378f
--- /dev/null
+++ b/gas/testsuite/gas/ppc/astest2.s
@@ -0,0 +1,52 @@
+four = 4
+ .section ".text"
+foo:
+ nop ; nop ; nop
+ .globl a
+ b .+4
+ b .+8
+ b x
+ b y
+ b z
+ b z+20
+ b .+four
+ b a
+ b b
+ b a+4
+ b b+4
+ b a@local
+ b b@local
+ .long .
+ .long .+8
+ .long x-.
+ .long x+4-.
+ .long z-.
+ .long y-.
+ .long x
+ .long y
+ .long z
+ .long x-four
+ .long y-four
+ .long z-four
+ .long a-.
+ .long b-.
+a: .long a
+b: .long b
+
+apfour = a + four
+ .long apfour
+ .long a-apfour
+ .long apfour+2
+ .long apfour-b
+
+ .section ".data"
+ .globl x
+ .globl z
+x: .long 0
+z = . + 4
+y: .long 0
+
+ .type foo,@function
+ .type a,@function
+ .type b,@function
+ .type apfour,@function
diff --git a/gas/testsuite/gas/ppc/ppc.exp b/gas/testsuite/gas/ppc/ppc.exp
new file mode 100644
index 0000000000..572fbc345b
--- /dev/null
+++ b/gas/testsuite/gas/ppc/ppc.exp
@@ -0,0 +1,21 @@
+#
+# Some PowerPC tests
+#
+
+# These tests are currently ELF specific, only because nobody has
+# converted them to look for XCOFF relocations.
+
+if { [istarget powerpc*-*-*bsd*] \
+ || [istarget powerpc*-*-elf*] \
+ || [istarget powerpc*-*-eabi*] \
+ || [istarget powerpc*-*-sysv4*] \
+ || [istarget powerpc*-*-linux*] \
+ || [istarget powerpc*-*-solaris*] \
+ || [istarget powerpc*-*-rtems*] } then {
+ run_dump_test "astest"
+ run_dump_test "astest2"
+}
+
+if { [istarget powerpc*-*-*] } then {
+ run_dump_test "simpshft"
+}
diff --git a/gas/testsuite/gas/ppc/simpshft.d b/gas/testsuite/gas/ppc/simpshft.d
new file mode 100644
index 0000000000..06893d5539
--- /dev/null
+++ b/gas/testsuite/gas/ppc/simpshft.d
@@ -0,0 +1,27 @@
+#objdump: -s -j .text
+#as: -mppc64
+#name: PowerPC test 3, simplified shifts
+
+.*
+
+Contents of section \.text:
+ 0000 78640fe0 7883f80e 78a545e4 78640020 xd..x...x.E.xd.
+ 0010 54640ffe 5083f800 54a5402e 5464043e Td..P...T.@.Td.>
+ 0020 78640004 786407e4 7864f806 7864ffe6 xd..xd..xd..xd..
+ 0030 7864f842 7864ffe2 7864000c 7864080c xd.Bxd..xd..xd..
+ 0040 78640fac 786407ec 78640000 78640800 xd..xd..xd..xd..
+ 0050 7864f802 78640000 7864f802 78640800 xd..xd..xd..xd..
+ 0060 78652010 786407e4 7864f806 78640000 xe .xd..xd..xd..
+ 0070 7864f842 78640fe0 78640000 78640040 xd.Bxd..xd..xd.@
+ 0080 786407e0 786407e4 786407a4 78640004 xd..xd..xd..xd..
+ 0090 78640008 78640048 786407e8 78640fa8 xd..xd.Hxd..xd..
+ 00a0 7864f80a 54640000 5464003e 5464f800 xd..Td..Td.>Td..
+ 00b0 5464f83e 5464f87e 5464fffe 50640000 Td.>Td.~Td..Pd..
+ 00c0 5064003e 50640ffe 5064f800 5064003e Pd.>Pd..Pd..Pd.>
+ 00d0 506407fe 5464003e 5464083e 5464f83e Pd..Td.>Td.>Td.>
+ 00e0 5464003e 5464f83e 5464083e 5c65203e Td.>Td.>Td.>\\e >
+ 00f0 5464003e 5464083c 5464f800 5464003e Td.>Td.<Td..Td.>
+ 0100 5464f87e 54640ffe 5464003e 5464007e Td.~Td..Td.>Td.~
+ 0110 546407fe 5464003e 5464003c 54640000 Td..Td.>Td.<Td..
+ 0120 5464003e 5464007e 546407fe 54640fbc Td.>Td.~Td..Td..
+ 0130 5464f800 00000000 Td......
diff --git a/gas/testsuite/gas/ppc/simpshft.s b/gas/testsuite/gas/ppc/simpshft.s
new file mode 100644
index 0000000000..39ff98d07b
--- /dev/null
+++ b/gas/testsuite/gas/ppc/simpshft.s
@@ -0,0 +1,110 @@
+# These are all the examples from section F.4 of
+# "PowerPC Microprocessor Family: The Programming Environments".
+# 64-bit examples
+ extrdi %r4,%r3,1,0
+ insrdi %r3,%r4,1,0
+ sldi %r5,%r5,8
+ clrldi %r4,%r3,32
+# 32-bit examples
+ extrwi %r4,%r3,1,0
+ insrwi %r3,%r4,1,0
+ slwi %r5,%r5,8
+ clrlwi %r4,%r3,16
+
+
+# These test the remaining corner cases for 64-bit operations.
+ extldi %r4,%r3,1,0
+ extldi %r4,%r3,64,0
+ extldi %r4,%r3,1,63
+ extldi %r4,%r3,64,63 # bit weird, that one.
+
+ extrdi %r4,%r3,63,0
+ extrdi %r4,%r3,1,62
+
+ insrdi %r4,%r3,64,0
+ insrdi %r4,%r3,63,0
+ insrdi %r4,%r3,1,62
+ insrdi %r4,%r3,1,63
+
+ rotldi %r4,%r3,0
+ rotldi %r4,%r3,1
+ rotldi %r4,%r3,63
+
+ rotrdi %r4,%r3,0
+ rotrdi %r4,%r3,1
+ rotrdi %r4,%r3,63
+
+ rotld %r5,%r3,%r4
+
+ sldi %r4,%r3,0
+ sldi %r4,%r3,63
+
+ srdi %r4,%r3,0
+ srdi %r4,%r3,1
+ srdi %r4,%r3,63
+
+ clrldi %r4,%r3,0
+ clrldi %r4,%r3,1
+ clrldi %r4,%r3,63
+
+ clrrdi %r4,%r3,0
+ clrrdi %r4,%r3,1
+ clrrdi %r4,%r3,63
+
+ clrlsldi %r4,%r3,0,0
+ clrlsldi %r4,%r3,1,0
+ clrlsldi %r4,%r3,63,0
+ clrlsldi %r4,%r3,63,1
+ clrlsldi %r4,%r3,63,63
+
+# These test the remaining corner cases for 32-bit operations.
+ extlwi %r4,%r3,1,0
+ extlwi %r4,%r3,32,0
+ extlwi %r4,%r3,1,31
+ extlwi %r4,%r3,32,31 # bit weird, that one.
+
+ extrwi %r4,%r3,31,0
+ extrwi %r4,%r3,1,30
+
+ inslwi %r4,%r3,1,0
+ inslwi %r4,%r3,32,0
+ inslwi %r4,%r3,1,31
+
+ insrwi %r4,%r3,1,0
+ insrwi %r4,%r3,32,0
+ insrwi %r4,%r3,1,31
+
+ rotlwi %r4,%r3,0
+ rotlwi %r4,%r3,1
+ rotlwi %r4,%r3,31
+
+ rotrwi %r4,%r3,0
+ rotrwi %r4,%r3,1
+ rotrwi %r4,%r3,31
+
+ rotlw %r5,%r3,%r4
+
+ slwi %r4,%r3,0
+ slwi %r4,%r3,1
+ slwi %r4,%r3,31
+
+ srwi %r4,%r3,0
+ srwi %r4,%r3,1
+ srwi %r4,%r3,31
+
+ clrlwi %r4,%r3,0
+ clrlwi %r4,%r3,1
+ clrlwi %r4,%r3,31
+
+ clrrwi %r4,%r3,0
+ clrrwi %r4,%r3,1
+ clrrwi %r4,%r3,31
+
+ clrlslwi %r4,%r3,0,0
+ clrlslwi %r4,%r3,1,0
+ clrlslwi %r4,%r3,31,0
+ clrlslwi %r4,%r3,31,1
+ clrlslwi %r4,%r3,31,31
+
+# Force alignment so that we pass the test on AIX
+ .p2align 3
diff --git a/gas/testsuite/gas/sh/basic.exp b/gas/testsuite/gas/sh/basic.exp
new file mode 100644
index 0000000000..30dbb0b2d0
--- /dev/null
+++ b/gas/testsuite/gas/sh/basic.exp
@@ -0,0 +1,86 @@
+# Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, 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 more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# DejaGnu@cygnus.com
+
+# Written by Cygnus Support.
+
+proc do_fp {} {
+ set testname "fp.s: floating point tests (sh3e)"
+ set x 0
+
+ gas_start "fp.s" "-al"
+
+ # Check the assembled instruction against a table built by the HP assembler
+ # Any differences should be checked by hand -- with the number of problems
+ # I've seen in the HP assembler I don't completely trust it.
+ #
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 F008\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 F00A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 F009\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0006 F00B\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 F006\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000a F007\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c F10C\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000e F08D\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 F09D\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0012 F100\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 F101\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0016 F102\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 F103\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001a F10E\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c F104\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001e F105\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 F04D\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0022 F05D\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 F06D\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0026 F02D\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 F03D\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002a F00D\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c F01D\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002e 435A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 4356\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0032 436A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 4366\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0036 035A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 4352\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003a 036A\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c 4362\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==31] then { pass $testname } else { fail $testname }
+}
+
+
+if [istarget sh*-*-*] then {
+ # Test the basic instruction parser.
+ do_fp
+}
diff --git a/gas/testsuite/gas/sh/fp.s b/gas/testsuite/gas/sh/fp.s
new file mode 100644
index 0000000000..352d86480b
--- /dev/null
+++ b/gas/testsuite/gas/sh/fp.s
@@ -0,0 +1,44 @@
+ .file "test.c"
+ .data
+
+! Hitachi SH cc1 (cygnus-2.7.1-950728) arguments: -O -fpeephole
+! -ffunction-cse -freg-struct-return -fdelayed-branch -fcommon -fgnu-linker
+
+gcc2_compiled.:
+___gnu_compiled_c:
+ .text
+ .align 2
+ .global _foo
+_foo:
+ fmov.s @r0,fr0
+ fmov.s fr0,@r0
+ fmov.s @r0+,fr0
+ fmov.s fr0,@-r0
+ fmov.s @(r0,r0),fr0
+ fmov.s fr0,@(r0,r0)
+ fmov fr0,fr1
+ fldi0 fr0
+ fldi1 fr0
+ fadd fr0,fr1
+ fsub fr0,fr1
+ fmul fr0,fr1
+ fdiv fr0,fr1
+ fmac fr0,fr0,fr1
+ fcmp/eq fr0,fr1
+ fcmp/gt fr0,fr1
+ fneg fr0
+ fabs fr0
+ fsqrt fr0
+ float fpul,fr0
+ ftrc fr0,fpul
+ fsts fpul,fr0
+ flds fr0,fpul
+ lds r3,fpul
+ lds.l @r3+,fpul
+ lds r3,fpscr
+ lds.l @r3+,fpscr
+ sts fpul,r3
+ sts.l fpul,@-r3
+ sts fpscr,r3
+ sts.l fpscr,@-r3
+
diff --git a/gas/testsuite/gas/sparc-solaris/addend.exp b/gas/testsuite/gas/sparc-solaris/addend.exp
new file mode 100644
index 0000000000..27838c7b14
--- /dev/null
+++ b/gas/testsuite/gas/sparc-solaris/addend.exp
@@ -0,0 +1,36 @@
+#
+# Solaris on SPARC tests
+#
+
+if [istarget sparc*-*-solaris2*] then {
+ set x1 0
+ set x2 0
+ set x3 0
+ set x4 0
+ set x5 0
+ set x6 0
+ set testname "addends (part 2)"
+ if [gas_test_old "addend.s" "" "addends (part 1)"] then {
+ objdump_start_no_subdir "a.out" "-r"
+ while 1 {
+ # These are what we get using the Solaris assembler.
+ expect {
+ -re "08 R_SPARC_WDISP22 +foo1\[+\]+0x0+04\[^\n\]*\n" { incr x1 }
+ -re "0c R_SPARC_WDISP22 +foo1\[+\]+0x0+04\[^\n\]*\n" { incr x2 }
+ -re "10 R_SPARC_WDISP22 +foo1\[^\n\]*\n" { incr x3 }
+ -re "14 R_SPARC_WDISP22 +foo1\[^\n\]*\n" { incr x4 }
+ -re "1c R_SPARC_32 +foo1\[^\n\]*\n" { incr x5 }
+ -re "20 R_SPARC_32 +foo1\[+\]+0x0+04\[^\n\]*\n" { incr x6 }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+ objdump_finish
+ if [all_ones $x1 $x2 $x3 $x4 $x5 $x6] then {
+ pass $testname
+ } else {
+ fail $testname
+ }
+ }
+}
diff --git a/gas/testsuite/gas/sparc-solaris/addend.s b/gas/testsuite/gas/sparc-solaris/addend.s
new file mode 100644
index 0000000000..18eb108a9b
--- /dev/null
+++ b/gas/testsuite/gas/sparc-solaris/addend.s
@@ -0,0 +1,11 @@
+ .global foo
+foo:
+ nop
+ nop
+ ba foo1+0x4
+ ba foo1+0x4
+ ba foo1
+ ba foo1
+ nop
+ .word foo1
+ .word foo1+4
diff --git a/gas/testsuite/gas/sparc-solaris/gas.exp b/gas/testsuite/gas/sparc-solaris/gas.exp
new file mode 100644
index 0000000000..63af6917e9
--- /dev/null
+++ b/gas/testsuite/gas/sparc-solaris/gas.exp
@@ -0,0 +1,10 @@
+#
+# Solaris-2 on SPARC tests
+#
+# The two compilers, cc and gcc, generate quite different debugging
+# records. Verify that we can accept both.
+#
+if [istarget sparc-*-solaris2*] then {
+ gas_test "sol-cc.s" "" $stdoptlist "SPARC Solaris cc -g"
+ gas_test "sol-gcc.s" "" $stdoptlist "SPARC Solaris gcc -g"
+}
diff --git a/gas/testsuite/gas/sparc-solaris/sol-cc.s b/gas/testsuite/gas/sparc-solaris/sol-cc.s
new file mode 100644
index 0000000000..8a250dabb9
--- /dev/null
+++ b/gas/testsuite/gas/sparc-solaris/sol-cc.s
@@ -0,0 +1,81 @@
+ .section ".text" ! [internal]
+ .proc 4
+ .global main
+ .align 4
+ .global main
+main:
+!#PROLOGUE# 0
+!#PROLOGUE# 1
+ save %sp,-96,%sp
+ sethi %hi(.L18),%o0
+ sethi %hi(msg),%o1
+ or %o1,%lo(msg),%o1 ! [internal]
+ call printf,2
+ or %o0,%lo(.L18),%o0 ! [internal]
+ ret
+ restore %g0,0,%o0
+ .type main,#function
+ .size main,(.-main)
+ .section ".data" ! [internal]
+ .align 4
+Ddata.data:
+ .section ".bss" ! [internal]
+Bbss.bss:
+ .section ".rodata" ! [internal]
+Drodata.rodata:
+ .file "hi-sol.c"
+ .global msg
+ .global msg
+msg:
+ .ascii "hello, world!\0"
+ .type msg,#object
+ .size msg,14
+ .section ".data1", #write, #alloc ! [internal]
+ .align 4
+.L18:
+ .ascii "%s\n\0"
+ .ident "acomp: (CDS) SPARCompilers 2.0.1 03 Sep 1992"
+ .section "text" ! [internal]
+ .stabs "/cygint/s1/users/raeburn/",100,0,0,0
+ .stabs "hi-sol.c",100,0,3,0
+ .stabs "",56,0,0,0
+ .stabs "",56,0,0,0
+ .stabs "Xt ; g ; O ; V=2.0",60,0,0,0x2bb773ba
+ .stabs "char:t(0,1)=bsc1;0;8;",128,0,0,0
+ .stabs "short:t(0,2)=bs2;0;16;",128,0,0,0
+ .stabs "int:t(0,3)=bs4;0;32;",128,0,0,0
+ .stabs "long:t(0,4)=bs4;0;32;",128,0,0,0
+ .stabs "long long:t(0,5)=bs8;0;64;",128,0,0,0
+ .stabs "signed char:t(0,6)=bsc1;0;8;",128,0,0,0
+ .stabs "signed short:t(0,7)=bs2;0;16;",128,0,0,0
+ .stabs "signed int:t(0,8)=bs4;0;32;",128,0,0,0
+ .stabs "signed long:t(0,9)=bs4;0;32;",128,0,0,0
+ .stabs "signed long long:t(0,10)=bs8;0;64;",128,0,0,0
+ .stabs "unsigned char:t(0,11)=buc1;0;8;",128,0,0,0
+ .stabs "unsigned short:t(0,12)=bu2;0;16;",128,0,0,0
+ .stabs "unsigned int:t(0,13)=bu4;0;32;",128,0,0,0
+ .stabs "unsigned long:t(0,14)=bu4;0;32;",128,0,0,0
+ .stabs "unsigned long long:t(0,15)=bu8;0;64;",128,0,0,0
+ .stabs "float:t(0,16)=R1;4;",128,0,0,0
+ .stabs "double:t(0,17)=R2;8;",128,0,0,0
+ .stabs "long double:t(0,18)=R6;16;",128,0,0,0
+ .stabs "void:t(0,19)=bs0;0;0",128,0,0,0
+ .stabs "msg:G(0,20)=ar(0,3);0;13;(0,1)",32,0,14,0
+ .stabs "main:F(0,3);(0,3);(0,21)=*(0,22)=*(0,1)",36,0,0,main
+ .stabs "main",42,0,0,0
+ .stabn 192,0,1,0
+ .stabn 68,0,4,0
+ .stabs "argc:p(0,3)",160,0,4,68
+ .stabs "argv:p(0,21)",160,0,4,72
+ .stabs "printf:P(0,3)",36,0,0,0
+ .stabn 224,0,1,0
+ .stabs "",98,0,0,0
+ .section "text" ! [internal]
+ .xstabs ".stab.index","/cygint/s1/users/raeburn/",100,0,0,0
+ .xstabs ".stab.index","hi-sol.c",100,0,3,0
+ .xstabs ".stab.index","",56,0,0,0
+ .xstabs ".stab.index","",56,0,0,0
+ .xstabs ".stab.index","Xt ; g ; O ; V=2.0",60,0,0,0x2bb773ba
+ .xstabs ".stab.index","msg",32,0,0,0
+ .xstabs ".stab.index","main",42,0,0,0
+ .xstabs ".stab.index","main",36,0,0,0
diff --git a/gas/testsuite/gas/sparc-solaris/sol-gcc.s b/gas/testsuite/gas/sparc-solaris/sol-gcc.s
new file mode 100644
index 0000000000..295fdcdd88
--- /dev/null
+++ b/gas/testsuite/gas/sparc-solaris/sol-gcc.s
@@ -0,0 +1,66 @@
+ .file "hi-sol.c"
+.stabs "/1h/devo/src/gas/testsuite/gas/",100,0,0,.LLtext0
+.stabs "hi-sol.c",100,0,0,.LLtext0
+.section ".text"
+.LLtext0:
+ .stabs "gcc2_compiled.", 0x3c, 0, 0, 0
+.stabs "int:t1=r1;-2147483648;2147483647;",128,0,0,0
+.stabs "char:t2=r2;0;127;",128,0,0,0
+.stabs "long int:t3=r1;-2147483648;2147483647;",128,0,0,0
+.stabs "unsigned int:t4=r1;0;-1;",128,0,0,0
+.stabs "long unsigned int:t5=r1;0;-1;",128,0,0,0
+.stabs "short int:t6=r1;-32768;32767;",128,0,0,0
+.stabs "long long int:t7=r1;0;-1;",128,0,0,0
+.stabs "short unsigned int:t8=r1;0;65535;",128,0,0,0
+.stabs "long long unsigned int:t9=r1;0;-1;",128,0,0,0
+.stabs "signed char:t10=r1;-128;127;",128,0,0,0
+.stabs "unsigned char:t11=r1;0;255;",128,0,0,0
+.stabs "float:t12=r1;4;0;",128,0,0,0
+.stabs "double:t13=r1;8;0;",128,0,0,0
+.stabs "long double:t14=r1;8;0;",128,0,0,0
+.stabs "void:t15=15",128,0,0,0
+.stabs "msg:G16=ar1;0;13;2",32,0,0,0
+ .global msg
+.section ".rodata"
+ .align 8
+ .type msg,#object
+ .size msg,14
+msg:
+ .asciz "hello, world!"
+ .align 8
+.LLC0:
+ .asciz "%s\n"
+.section ".text"
+ .align 4
+.stabs "main:F1",36,0,0,main
+.stabs "argc:P1",64,0,0,24
+.stabs "argv:P17=*18=*2",64,0,0,25
+ .global main
+ .type main,#function
+ .proc 04
+main:
+.stabn 68,0,4,.LM1-main
+.LM1:
+ !#PROLOGUE# 0
+ save %sp,-112,%sp
+ !#PROLOGUE# 1
+.stabn 68,0,5,.LM2-main
+.LM2:
+.LLBB2:
+ sethi %hi(.LLC0),%o0
+ or %o0,%lo(.LLC0),%o0
+ sethi %hi(msg),%o1
+ call printf,0
+ or %o1,%lo(msg),%o1
+.stabn 68,0,6,.LM3-main
+.LM3:
+.stabn 68,0,7,.LM4-main
+.LM4:
+.LLBE2:
+ ret
+ restore %g0,0,%o0
+.LLfe1:
+ .size main,.LLfe1-main
+.stabn 192,0,0,.LLBB2-main
+.stabn 224,0,0,.LLBE2-main
+ .ident "GCC: (GNU) cygnus-2.3.3"
diff --git a/gas/testsuite/gas/sparc/asi.d b/gas/testsuite/gas/sparc/asi.d
new file mode 100644
index 0000000000..835ea1a8b2
--- /dev/null
+++ b/gas/testsuite/gas/sparc/asi.d
@@ -0,0 +1,35 @@
+#as: -Av9
+#objdump: -dr
+#name: sparc64 asi
+
+.*: +file format .*sparc.*
+
+Disassembly of section .text:
+
+0+ <.text>:
+ 0: c4 80 40 00 lda \[ %g1 \] \(0\), %g2
+ 4: c4 80 5f e0 lda \[ %g1 \] \(255\), %g2
+ 8: c4 80 42 00 lda \[ %g1 \] #ASI_AIUP, %g2
+ c: c4 80 42 20 lda \[ %g1 \] #ASI_AIUS, %g2
+ 10: c4 80 43 00 lda \[ %g1 \] #ASI_AIUP_L, %g2
+ 14: c4 80 43 20 lda \[ %g1 \] #ASI_AIUS_L, %g2
+ 18: c4 80 50 00 lda \[ %g1 \] #ASI_P, %g2
+ 1c: c4 80 50 20 lda \[ %g1 \] #ASI_S, %g2
+ 20: c4 80 50 40 lda \[ %g1 \] #ASI_PNF, %g2
+ 24: c4 80 50 60 lda \[ %g1 \] #ASI_SNF, %g2
+ 28: c4 80 51 00 lda \[ %g1 \] #ASI_P_L, %g2
+ 2c: c4 80 51 20 lda \[ %g1 \] #ASI_S_L, %g2
+ 30: c4 80 51 40 lda \[ %g1 \] #ASI_PNF_L, %g2
+ 34: c4 80 51 60 lda \[ %g1 \] #ASI_SNF_L, %g2
+ 38: c4 80 42 00 lda \[ %g1 \] #ASI_AIUP, %g2
+ 3c: c4 80 42 20 lda \[ %g1 \] #ASI_AIUS, %g2
+ 40: c4 80 43 00 lda \[ %g1 \] #ASI_AIUP_L, %g2
+ 44: c4 80 43 20 lda \[ %g1 \] #ASI_AIUS_L, %g2
+ 48: c4 80 50 00 lda \[ %g1 \] #ASI_P, %g2
+ 4c: c4 80 50 20 lda \[ %g1 \] #ASI_S, %g2
+ 50: c4 80 50 40 lda \[ %g1 \] #ASI_PNF, %g2
+ 54: c4 80 50 60 lda \[ %g1 \] #ASI_SNF, %g2
+ 58: c4 80 51 00 lda \[ %g1 \] #ASI_P_L, %g2
+ 5c: c4 80 51 20 lda \[ %g1 \] #ASI_S_L, %g2
+ 60: c4 80 51 40 lda \[ %g1 \] #ASI_PNF_L, %g2
+ 64: c4 80 51 60 lda \[ %g1 \] #ASI_SNF_L, %g2
diff --git a/gas/testsuite/gas/sparc/asi.s b/gas/testsuite/gas/sparc/asi.s
new file mode 100644
index 0000000000..c56fe9c24d
--- /dev/null
+++ b/gas/testsuite/gas/sparc/asi.s
@@ -0,0 +1,28 @@
+# Test asi's.
+ .text
+ lduwa [%g1]0,%g2
+ lduwa [%g1]255,%g2
+ lduwa [%g1]#ASI_AIUP,%g2
+ lduwa [%g1]#ASI_AIUS,%g2
+ lduwa [%g1]#ASI_AIUP_L,%g2
+ lduwa [%g1]#ASI_AIUS_L,%g2
+ lduwa [%g1]#ASI_P,%g2
+ lduwa [%g1]#ASI_S,%g2
+ lduwa [%g1]#ASI_PNF,%g2
+ lduwa [%g1]#ASI_SNF,%g2
+ lduwa [%g1]#ASI_P_L,%g2
+ lduwa [%g1]#ASI_S_L,%g2
+ lduwa [%g1]#ASI_PNF_L,%g2
+ lduwa [%g1]#ASI_SNF_L,%g2
+ lduwa [%g1]#ASI_AS_IF_USER_PRIMARY,%g2
+ lduwa [%g1]#ASI_AS_IF_USER_SECONDARY,%g2
+ lduwa [%g1]#ASI_AS_IF_USER_PRIMARY_LITTLE,%g2
+ lduwa [%g1]#ASI_AS_IF_USER_SECONDARY_LITTLE,%g2
+ lduwa [%g1]#ASI_PRIMARY,%g2
+ lduwa [%g1]#ASI_SECONDARY,%g2
+ lduwa [%g1]#ASI_PRIMARY_NOFAULT,%g2
+ lduwa [%g1]#ASI_SECONDARY_NOFAULT,%g2
+ lduwa [%g1]#ASI_PRIMARY_LITTLE,%g2
+ lduwa [%g1]#ASI_SECONDARY_LITTLE,%g2
+ lduwa [%g1]#ASI_PRIMARY_NOFAULT_LITTLE,%g2
+ lduwa [%g1]#ASI_SECONDARY_NOFAULT_LITTLE,%g2
diff --git a/gas/testsuite/gas/sparc/membar.d b/gas/testsuite/gas/sparc/membar.d
new file mode 100644
index 0000000000..6ab6b2edb1
--- /dev/null
+++ b/gas/testsuite/gas/sparc/membar.d
@@ -0,0 +1,19 @@
+#as: -Av9
+#objdump: -dr
+#name: sparc64 membar
+
+.*: +file format .*sparc.*
+
+Disassembly of section .text:
+
+0+ <.text>:
+ 0: 81 43 e0 00 membar 0
+ 4: 81 43 e0 7f membar #Sync|#MemIssue|#Lookaside|#StoreStore|#LoadStore|#StoreLoad|#LoadLoad
+ 8: 81 43 e0 7f membar #Sync|#MemIssue|#Lookaside|#StoreStore|#LoadStore|#StoreLoad|#LoadLoad
+ c: 81 43 e0 40 membar #Sync
+ 10: 81 43 e0 20 membar #MemIssue
+ 14: 81 43 e0 10 membar #Lookaside
+ 18: 81 43 e0 08 membar #StoreStore
+ 1c: 81 43 e0 04 membar #LoadStore
+ 20: 81 43 e0 02 membar #StoreLoad
+ 24: 81 43 e0 01 membar #LoadLoad
diff --git a/gas/testsuite/gas/sparc/membar.s b/gas/testsuite/gas/sparc/membar.s
new file mode 100644
index 0000000000..d805e0720f
--- /dev/null
+++ b/gas/testsuite/gas/sparc/membar.s
@@ -0,0 +1,12 @@
+# Test membar args
+ .text
+ membar 0
+ membar 127
+ membar #Sync|#MemIssue|#Lookaside|#StoreStore|#LoadStore|#StoreLoad|#LoadLoad
+ membar #Sync
+ membar #MemIssue
+ membar #Lookaside
+ membar #StoreStore
+ membar #LoadStore
+ membar #StoreLoad
+ membar #LoadLoad
diff --git a/gas/testsuite/gas/sparc/mism-1.s b/gas/testsuite/gas/sparc/mism-1.s
new file mode 100644
index 0000000000..fac5e48270
--- /dev/null
+++ b/gas/testsuite/gas/sparc/mism-1.s
@@ -0,0 +1,22 @@
+! Test architecture mismatch warnings.
+! We don't test every possible mismatch, we just want to be reasonable sure
+! the mismatch checking code works.
+!
+! { dg-do assemble { target sparc*-*-* } }
+! { dg-options -Av6 }
+
+! sparclite
+
+ divscc %g1,%g2,%g3 ! { dg-error "mismatch|sparclite" "sparclite divscc mismatch" }
+
+ scan %g1,%g2,%g3 ! { dg-error "mismatch|sparclite" "sparclite scan mismatch" }
+
+! v9
+
+ movrz %g1,%g2,%g3 ! { dg-error "mismatch|v9" "v9 fp reg mismatch" }
+
+! v9a
+
+ shutdown ! { dg-error "mismatch|v9a" "v9a shutdown mismatch" }
+
+foo:
diff --git a/gas/testsuite/gas/sparc/mismatch.exp b/gas/testsuite/gas/sparc/mismatch.exp
new file mode 100644
index 0000000000..6f89de2a24
--- /dev/null
+++ b/gas/testsuite/gas/sparc/mismatch.exp
@@ -0,0 +1,20 @@
+# Test architecture mismatch errors.
+#
+# GAS issues two lines of error text for each mismatch:
+#
+# mm-lite.s:7: Error: Architecture mismatch on "divscc".
+# mm-lite.s:7: (Requires sparclite; requested architecture is v8.)
+#
+# The suggested regexp argument to dg-error is "mismatch|<arch>".
+
+if [istarget sparc*-*-*] {
+
+ load_lib gas-dg.exp
+
+ dg-init
+
+ dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/mism-*.s]] "" ""
+
+ dg-finish
+
+}
diff --git a/gas/testsuite/gas/sparc/prefetch.d b/gas/testsuite/gas/sparc/prefetch.d
new file mode 100644
index 0000000000..41803ed97d
--- /dev/null
+++ b/gas/testsuite/gas/sparc/prefetch.d
@@ -0,0 +1,19 @@
+#as: -Av9
+#objdump: -dr
+#name: sparc64 prefetch
+
+.*: +file format .*sparc.*
+
+Disassembly of section .text:
+
+0+ <.text>:
+ 0: c1 68 40 00 prefetch \[ %g1 \], #n_reads
+ 4: ff 68 40 00 prefetch \[ %g1 \], 31
+ 8: c1 68 40 00 prefetch \[ %g1 \], #n_reads
+ c: c3 68 40 00 prefetch \[ %g1 \], #one_read
+ 10: c5 68 40 00 prefetch \[ %g1 \], #n_writes
+ 14: c7 68 40 00 prefetch \[ %g1 \], #one_write
+ 18: c1 e8 42 00 prefetcha \[ %g1 \] #ASI_AIUP, #n_reads
+ 1c: ff e8 60 00 prefetcha \[ %g1 \] %asi, 31
+ 20: c1 e8 42 20 prefetcha \[ %g1 \] #ASI_AIUS, #n_reads
+ 24: c3 e8 60 00 prefetcha \[ %g1 \] %asi, #one_read
diff --git a/gas/testsuite/gas/sparc/prefetch.s b/gas/testsuite/gas/sparc/prefetch.s
new file mode 100644
index 0000000000..18c68bbbc0
--- /dev/null
+++ b/gas/testsuite/gas/sparc/prefetch.s
@@ -0,0 +1,11 @@
+ .text
+ prefetch [%g1],0
+ prefetch [%g1],31
+ prefetch [%g1],#n_reads
+ prefetch [%g1],#one_read
+ prefetch [%g1],#n_writes
+ prefetch [%g1],#one_write
+ prefetcha [%g1]#ASI_AIUP,0
+ prefetcha [%g1]%asi,31
+ prefetcha [%g1]#ASI_AIUS,#n_reads
+ prefetcha [%g1]%asi,#one_read
diff --git a/gas/testsuite/gas/sparc/rdpr.d b/gas/testsuite/gas/sparc/rdpr.d
new file mode 100644
index 0000000000..60a7b619a6
--- /dev/null
+++ b/gas/testsuite/gas/sparc/rdpr.d
@@ -0,0 +1,26 @@
+#as: -Av9
+#objdump: -dr
+#name: sparc64 rdpr
+
+.*: +file format .*sparc.*
+
+Disassembly of section .text:
+
+0+ <.text>:
+ 0: 83 50 00 00 rdpr %tpc, %g1
+ 4: 85 50 40 00 rdpr %tnpc, %g2
+ 8: 87 50 80 00 rdpr %tstate, %g3
+ c: 89 50 c0 00 rdpr %tt, %g4
+ 10: 8b 51 00 00 rdpr %tick, %g5
+ 14: 8d 51 40 00 rdpr %tba, %g6
+ 18: 8f 51 80 00 rdpr %pstate, %g7
+ 1c: 91 51 c0 00 rdpr %tl, %o0
+ 20: 93 52 00 00 rdpr %pil, %o1
+ 24: 95 52 40 00 rdpr %cwp, %o2
+ 28: 97 52 80 00 rdpr %cansave, %o3
+ 2c: 99 52 c0 00 rdpr %canrestore, %o4
+ 30: 9b 53 00 00 rdpr %cleanwin, %o5
+ 34: 9d 53 40 00 rdpr %otherwin, %sp
+ 38: 9f 53 80 00 rdpr %wstate, %o7
+ 3c: a1 53 c0 00 rdpr %fq, %l0
+ 40: a3 57 c0 00 rdpr %ver, %l1
diff --git a/gas/testsuite/gas/sparc/rdpr.s b/gas/testsuite/gas/sparc/rdpr.s
new file mode 100644
index 0000000000..f44619cea4
--- /dev/null
+++ b/gas/testsuite/gas/sparc/rdpr.s
@@ -0,0 +1,19 @@
+# Test rdpr
+ .text
+ rdpr %tpc,%g1
+ rdpr %tnpc,%g2
+ rdpr %tstate,%g3
+ rdpr %tt,%g4
+ rdpr %tick,%g5
+ rdpr %tba,%g6
+ rdpr %pstate,%g7
+ rdpr %tl,%o0
+ rdpr %pil,%o1
+ rdpr %cwp,%o2
+ rdpr %cansave,%o3
+ rdpr %canrestore,%o4
+ rdpr %cleanwin,%o5
+ rdpr %otherwin,%o6
+ rdpr %wstate,%o7
+ rdpr %fq,%l0
+ rdpr %ver,%l1
diff --git a/gas/testsuite/gas/sparc/reloc64.d b/gas/testsuite/gas/sparc/reloc64.d
new file mode 100644
index 0000000000..f4b825ad78
--- /dev/null
+++ b/gas/testsuite/gas/sparc/reloc64.d
@@ -0,0 +1,76 @@
+#as: -Av9
+#objdump: -dr
+#name: sparc64 reloc64
+
+.*: +file format .*sparc.*
+
+Disassembly of section .text:
+
+0+ <foo>:
+ 0: 03 04 8d 15 sethi %hi\(0x12345400\), %g1
+ 4: 82 10 62 78 or %g1, 0x278, %g1.*
+ 8: 01 00 00 00 nop
+ c: 03 00 00 00 sethi %hi\(0x0\), %g1
+ c: R_SPARC_HH22 .text
+ 10: 82 10 60 00 mov %g1, %g1 ! 0 <foo>
+ 10: R_SPARC_HM10 .text
+ 14: 01 00 00 00 nop
+ 18: 03 00 00 00 sethi %hi\(0x0\), %g1
+ 18: R_SPARC_HH22 .text\+0x1234567800000000
+ 1c: 82 10 60 00 mov %g1, %g1 ! 0 <foo>
+ 1c: R_SPARC_HM10 .text\+0x1234567800000000
+ 20: 01 00 00 00 nop
+ 24: 03 3f b7 2e sethi %hi\(0xfedcb800\), %g1
+ 28: 82 10 62 98 or %g1, 0x298, %g1.*
+ 2c: 05 1d 95 0c sethi %hi\(0x76543000\), %g2
+ 30: 84 10 62 10 or %g1, 0x210, %g2
+ 34: 01 00 00 00 nop
+ 38: 03 00 00 00 sethi %hi\(0x0\), %g1
+ 38: R_SPARC_HH22 .text
+ 3c: 82 10 60 00 mov %g1, %g1 ! 0 <foo>
+ 3c: R_SPARC_HM10 .text
+ 40: 05 00 00 00 sethi %hi\(0x0\), %g2
+ 40: R_SPARC_LM22 .text
+ 44: 84 10 60 00 mov %g1, %g2
+ 44: R_SPARC_LO10 .text
+ 48: 01 00 00 00 nop
+ 4c: 03 00 00 00 sethi %hi\(0x0\), %g1
+ 4c: R_SPARC_HH22 .text\+0xfedcba9876543210
+ 50: 82 10 60 00 mov %g1, %g1 ! 0 <foo>
+ 50: R_SPARC_HM10 .text\+0xfedcba9876543210
+ 54: 05 00 00 00 sethi %hi\(0x0\), %g2
+ 54: R_SPARC_LM22 .text\+0xfedcba9876543210
+ 58: 84 10 60 00 mov %g1, %g2
+ 58: R_SPARC_LO10 .text\+0xfedcba9876543210
+ 5c: 01 00 00 00 nop
+ 60: 03 2a 61 d9 sethi %hi\(0xa9876400\), %g1
+ 64: 82 10 61 43 or %g1, 0x143, %g1.*
+ 68: 82 10 62 10 or %g1, 0x210, %g1
+ 6c: 01 00 00 00 nop
+ 70: 03 00 00 00 sethi %hi\(0x0\), %g1
+ 70: R_SPARC_H44 .text
+ 74: 82 10 60 00 mov %g1, %g1 ! 0 <foo>
+ 74: R_SPARC_M44 .text
+ 78: 82 10 60 00 mov %g1, %g1
+ 78: R_SPARC_L44 .text
+ 7c: 01 00 00 00 nop
+ 80: 03 00 00 00 sethi %hi\(0x0\), %g1
+ 80: R_SPARC_H44 .text\+0xa9876543210
+ 84: 82 10 60 00 mov %g1, %g1 ! 0 <foo>
+ 84: R_SPARC_M44 .text\+0xa9876543210
+ 88: 82 10 60 00 mov %g1, %g1
+ 88: R_SPARC_L44 .text\+0xa9876543210
+ 8c: 01 00 00 00 nop
+ 90: 03 22 6a f3 sethi %hi\(0x89abcc00\), %g1
+ 94: 82 18 7e 10 xor %g1, -496, %g1
+ 98: 01 00 00 00 nop
+ 9c: 03 00 00 00 sethi %hi\(0x0\), %g1
+ 9c: R_SPARC_HIX22 .text
+ a0: 82 18 60 00 xor %g1, 0, %g1
+ a0: R_SPARC_LOX10 .text
+ a4: 01 00 00 00 nop
+ a8: 03 00 00 00 sethi %hi\(0x0\), %g1
+ a8: R_SPARC_HIX22 .text\+0xffffffff76543210
+ ac: 82 18 60 00 xor %g1, 0, %g1
+ ac: R_SPARC_LOX10 .text\+0xffffffff76543210
+ b0: 01 00 00 00 nop
diff --git a/gas/testsuite/gas/sparc/reloc64.s b/gas/testsuite/gas/sparc/reloc64.s
new file mode 100644
index 0000000000..9ead6afbf2
--- /dev/null
+++ b/gas/testsuite/gas/sparc/reloc64.s
@@ -0,0 +1,48 @@
+# sparc64 special relocs
+
+foo:
+ sethi %uhi(0x1234567800000000),%g1
+ or %g1,%ulo(0x1234567800000000),%g1
+ nop
+ sethi %uhi(foo),%g1
+ or %g1,%ulo(foo),%g1
+ nop
+ sethi %uhi(foo+0x1234567800000000),%g1
+ or %g1,%ulo(foo+0x1234567800000000),%g1
+ nop
+ sethi %hh(0xfedcba9876543210),%g1
+ or %g1,%hm(0xfedcba9876543210),%g1
+ sethi %lm(0xfedcba9876543210),%g2
+ or %g1,%lo(0xfedcba9876543210),%g2
+ nop
+ sethi %hh(foo),%g1
+ or %g1,%hm(foo),%g1
+ sethi %lm(foo),%g2
+ or %g1,%lo(foo),%g2
+ nop
+ sethi %hh(foo+0xfedcba9876543210),%g1
+ or %g1,%hm(foo+0xfedcba9876543210),%g1
+ sethi %lm(foo+0xfedcba9876543210),%g2
+ or %g1,%lo(foo+0xfedcba9876543210),%g2
+ nop
+ sethi %h44(0xa9876543210),%g1
+ or %g1,%m44(0xa9876543210),%g1
+ or %g1,%l44(0xa9876543210),%g1
+ nop
+ sethi %h44(foo),%g1
+ or %g1,%m44(foo),%g1
+ or %g1,%l44(foo),%g1
+ nop
+ sethi %h44(foo+0xa9876543210),%g1
+ or %g1,%m44(foo+0xa9876543210),%g1
+ or %g1,%l44(foo+0xa9876543210),%g1
+ nop
+ sethi %hix(0xffffffff76543210),%g1
+ xor %g1,%lox(0xffffffff76543210),%g1
+ nop
+ sethi %hix(foo),%g1
+ xor %g1,%lox(foo),%g1
+ nop
+ sethi %hix(foo+0xffffffff76543210),%g1
+ xor %g1,%lox(foo+0xffffffff76543210),%g1
+ nop
diff --git a/gas/testsuite/gas/sparc/set64.d b/gas/testsuite/gas/sparc/set64.d
new file mode 100644
index 0000000000..121becad74
--- /dev/null
+++ b/gas/testsuite/gas/sparc/set64.d
@@ -0,0 +1,88 @@
+#as: -Av9
+#objdump: -dr
+#name: sparc64 set64
+
+.*: +file format .*sparc.*
+
+Disassembly of section .text:
+
+0+ <foo>:
+ 0: 05 00 00 00 sethi %hi\(0x0\), %g2
+ 0: R_SPARC_HI22 .text
+ 4: 84 10 a0 00 mov %g2, %g2 ! 0 <foo>
+ 4: R_SPARC_LO10 .text
+ 8: 07 1d 95 0c sethi %hi\(0x76543000\), %g3
+ c: 86 10 e2 10 or %g3, 0x210, %g3 ! 76543210 <\*ABS\*\+(0x|)0x76543210>
+ 10: 88 10 20 00 clr %g4
+ 14: 0b 00 00 3f sethi %hi\(0xfc00\), %g5
+ 18: 8a 11 63 ff or %g5, 0x3ff, %g5 ! ffff <\*ABS\*\+(0x|)ffff>
+ 1c: 03 00 00 00 sethi %hi\(0x0\), %g1
+ 1c: R_SPARC_HH22 .text
+ 20: 82 10 60 00 mov %g1, %g1 ! 0 <foo>
+ 20: R_SPARC_HM10 .text
+ 24: 05 00 00 00 sethi %hi\(0x0\), %g2
+ 24: R_SPARC_HI22 .text
+ 28: 84 10 a0 00 mov %g2, %g2 ! 0 <foo>
+ 28: R_SPARC_LO10 .text
+ 2c: 83 28 70 20 sllx %g1, 0x20, %g1
+ 30: 84 10 80 01 or %g2, %g1, %g2
+ 34: 86 10 3f ff mov -1, %g3
+ 38: 86 10 20 00 clr %g3
+ 3c: 86 10 20 01 mov 1, %g3
+ 40: 86 10 2f ff mov 0xfff, %g3
+ 44: 07 00 00 04 sethi %hi\(0x1000\), %g3
+ 48: 86 10 30 00 mov -4096, %g3
+ 4c: 07 3f ff fb sethi %hi\(0xffffec00\), %g3
+ 50: 86 10 e3 ff or %g3, 0x3ff, %g3 ! ffffefff <\*ABS\*\+(0x|)ffffefff>
+ 54: 87 38 e0 00 sra %g3, 0, %g3
+ 58: 07 00 00 3f sethi %hi\(0xfc00\), %g3
+ 5c: 86 10 e3 ff or %g3, 0x3ff, %g3 ! ffff <\*ABS\*\+(0x|)ffff>
+ 60: 07 3f ff c0 sethi %hi\(0xffff0000\), %g3
+ 64: 87 38 e0 00 sra %g3, 0, %g3
+ 68: 09 1f ff ff sethi %hi\(0x7ffffc00\), %g4
+ 6c: 88 11 23 ff or %g4, 0x3ff, %g4 ! 7fffffff <\*ABS\*\+(0x|)7fffffff>
+ 70: 09 20 00 00 sethi %hi\(0x80000000\), %g4
+ 74: 09 20 00 00 sethi %hi\(0x80000000\), %g4
+ 78: 89 39 20 00 sra %g4, 0, %g4
+ 7c: 82 10 3f ff mov -1, %g1
+ 80: 09 1f ff ff sethi %hi\(0x7ffffc00\), %g4
+ 84: 88 11 23 ff or %g4, 0x3ff, %g4 ! 7fffffff <\*ABS\*\+(0x|)7fffffff>
+ 88: 83 28 70 20 sllx %g1, 0x20, %g1
+ 8c: 88 11 00 01 or %g4, %g1, %g4
+ 90: 09 3f ff ff sethi %hi\(0xfffffc00\), %g4
+ 94: 88 11 23 ff or %g4, 0x3ff, %g4 ! ffffffff <\*ABS\*\+(0x|)ffffffff>
+ 98: 88 10 20 01 mov 1, %g4
+ 9c: 89 29 30 20 sllx %g4, 0x20, %g4
+ a0: 03 1f ff ff sethi %hi\(0x7ffffc00\), %g1
+ a4: 82 10 63 ff or %g1, 0x3ff, %g1 ! 7fffffff <\*ABS\*\+(0x|)7fffffff>
+ a8: 0b 3f ff ff sethi %hi\(0xfffffc00\), %g5
+ ac: 8a 11 63 ff or %g5, 0x3ff, %g5 ! ffffffff <\*ABS\*\+(0x|)ffffffff>
+ b0: 83 28 70 20 sllx %g1, 0x20, %g1
+ b4: 8a 11 40 01 or %g5, %g1, %g5
+ b8: 0b 20 00 00 sethi %hi\(0x80000000\), %g5
+ bc: 8b 29 70 20 sllx %g5, 0x20, %g5
+ c0: 8a 10 3f ff mov -1, %g5
+ c4: 8b 29 70 20 sllx %g5, 0x20, %g5
+ c8: 0b 20 00 00 sethi %hi\(0x80000000\), %g5
+ cc: 8b 39 60 00 sra %g5, 0, %g5
+ d0: 03 3f ff c0 sethi %hi\(0xffff0000\), %g1
+ d4: 0b 3f ff c0 sethi %hi\(0xffff0000\), %g5
+ d8: 83 28 70 20 sllx %g1, 0x20, %g1
+ dc: 8a 11 40 01 or %g5, %g1, %g5
+ e0: 03 3f ff c0 sethi %hi\(0xffff0000\), %g1
+ e4: 8a 10 20 01 mov 1, %g5
+ e8: 83 28 70 20 sllx %g1, 0x20, %g1
+ ec: 8a 11 40 01 or %g5, %g1, %g5
+ f0: 82 10 20 01 mov 1, %g1
+ f4: 0b 3f ff c0 sethi %hi\(0xffff0000\), %g5
+ f8: 8a 11 60 01 or %g5, 1, %g5 ! ffff0001 <\*ABS\*\+(0x|)ffff0001>
+ fc: 83 28 70 20 sllx %g1, 0x20, %g1
+ 100: 8a 11 40 01 or %g5, %g1, %g5
+ 104: 82 10 20 01 mov 1, %g1
+ 108: 0b 3f ff c0 sethi %hi\(0xffff0000\), %g5
+ 10c: 83 28 70 20 sllx %g1, 0x20, %g1
+ 110: 8a 11 40 01 or %g5, %g1, %g5
+ 114: 82 10 20 01 mov 1, %g1
+ 118: 8a 10 20 01 mov 1, %g5
+ 11c: 83 28 70 20 sllx %g1, 0x20, %g1
+ 120: 8a 11 40 01 or %g5, %g1, %g5
diff --git a/gas/testsuite/gas/sparc/set64.s b/gas/testsuite/gas/sparc/set64.s
new file mode 100644
index 0000000000..92dc931748
--- /dev/null
+++ b/gas/testsuite/gas/sparc/set64.s
@@ -0,0 +1,43 @@
+# sparc64 set insn handling (includes set, setuw, setsw, setx)
+# FIXME: setuw,setsw not tested for yet.
+
+foo:
+ set foo,%g2
+ set 0x76543210,%g3
+ set 0,%g4
+ set 65535,%g5
+
+ setx foo,%g1,%g2
+
+ setx -1,%g1,%g3
+ setx 0,%g1,%g3
+ setx 1,%g1,%g3
+ setx 4095,%g1,%g3
+ setx 4096,%g1,%g3
+ setx -4096,%g1,%g3
+ setx -4097,%g1,%g3
+ setx 65535,%g1,%g3
+ setx -65536,%g1,%g3
+
+ setx 2147483647,%g1,%g4
+ setx 2147483648,%g1,%g4
+ setx -2147483648,%g1,%g4
+ setx -2147483649,%g1,%g4
+ setx 4294967295,%g1,%g4
+ setx 4294967296,%g1,%g4
+
+! GAS doesn't handle large base10 numbers yet.
+! setx 9223372036854775807,%g1,%g5
+! setx 9223372036854775808,%g1,%g5
+! setx -9223372036854775808,%g1,%g5
+! setx -9223372036854775809,%g1,%g5
+
+ setx 0x7fffffffffffffff,%g1,%g5
+ setx 0x8000000000000000,%g1,%g5 ! test only hh22 needed
+ setx 0xffffffff00000000,%g1,%g5 ! test only hm10 needed
+ setx 0xffffffff80000000,%g1,%g5 ! test sign-ext of lower 32
+ setx 0xffff0000ffff0000,%g1,%g5 ! test hh22,hi22
+ setx 0xffff000000000001,%g1,%g5 ! test hh22,lo10
+ setx 0x00000001ffff0001,%g1,%g5 ! test hm10,hi22,lo10
+ setx 0x00000001ffff0000,%g1,%g5 ! test hm10,hi22
+ setx 0x0000000100000001,%g1,%g5 ! test hm10,lo10
diff --git a/gas/testsuite/gas/sparc/sparc.exp b/gas/testsuite/gas/sparc/sparc.exp
new file mode 100644
index 0000000000..1a79358459
--- /dev/null
+++ b/gas/testsuite/gas/sparc/sparc.exp
@@ -0,0 +1,27 @@
+# Some generic SPARC and SPARC64 tests
+
+# FIXME: The tests here aren't really bullet proof. A mistake in the opcode
+# table can slip through since we use the same table for assembly and
+# disassembly. The way to fix this is to include a hex dump of the insns
+# and test that as well. Later.
+
+if [istarget sparc*-*-*] {
+ run_dump_test "synth"
+}
+
+
+if [istarget sparc64*-*-*] {
+ run_dump_test "asi"
+ run_dump_test "membar"
+ run_dump_test "prefetch"
+ run_dump_test "set64"
+ run_dump_test "synth64"
+ run_dump_test "rdpr"
+ run_dump_test "wrpr"
+ run_dump_test "reloc64"
+}
+
+if [istarget sparclet*-*-*] {
+ run_dump_test "splet"
+ run_dump_test "splet-2"
+}
diff --git a/gas/testsuite/gas/sparc/splet-2.d b/gas/testsuite/gas/sparc/splet-2.d
new file mode 100644
index 0000000000..d0555385c8
--- /dev/null
+++ b/gas/testsuite/gas/sparc/splet-2.d
@@ -0,0 +1,23 @@
+#as: -Asparclet
+#objdump: -dr
+#name: sparclet coprocessor registers
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+ <start>:
+ 0: 81 b0 40 c0 cwrcxt %g1, %ccsr
+ 4: 83 b0 40 c0 cwrcxt %g1, %ccfr
+ 8: 85 b0 40 c0 cwrcxt %g1, %cccrcr
+ c: 87 b0 40 c0 cwrcxt %g1, %ccpr
+ 10: 89 b0 40 c0 cwrcxt %g1, %ccsr2
+ 14: 8b b0 40 c0 cwrcxt %g1, %cccrr
+ 18: 8d b0 40 c0 cwrcxt %g1, %ccrstr
+ 1c: 83 b0 01 00 crdcxt %ccsr, %g1
+ 20: 83 b0 41 00 crdcxt %ccfr, %g1
+ 24: 83 b0 81 00 crdcxt %cccrcr, %g1
+ 28: 83 b0 c1 00 crdcxt %ccpr, %g1
+ 2c: 83 b1 01 00 crdcxt %ccsr2, %g1
+ 30: 83 b1 41 00 crdcxt %cccrr, %g1
+ 34: 83 b1 81 00 crdcxt %ccrstr, %g1
diff --git a/gas/testsuite/gas/sparc/splet-2.s b/gas/testsuite/gas/sparc/splet-2.s
new file mode 100644
index 0000000000..5d3449560a
--- /dev/null
+++ b/gas/testsuite/gas/sparc/splet-2.s
@@ -0,0 +1,21 @@
+! Test sparclet coprocessor registers.
+
+ .text
+ .global start
+start:
+
+ cwrcxt %g1,%ccsr
+ cwrcxt %g1,%ccfr
+ cwrcxt %g1,%cccrcr
+ cwrcxt %g1,%ccpr
+ cwrcxt %g1,%ccsr2
+ cwrcxt %g1,%cccrr
+ cwrcxt %g1,%ccrstr
+
+ crdcxt %ccsr,%g1
+ crdcxt %ccfr,%g1
+ crdcxt %cccrcr,%g1
+ crdcxt %ccpr,%g1
+ crdcxt %ccsr2,%g1
+ crdcxt %cccrr,%g1
+ crdcxt %ccrstr,%g1
diff --git a/gas/testsuite/gas/sparc/splet.d b/gas/testsuite/gas/sparc/splet.d
new file mode 100644
index 0000000000..9ac0a21818
--- /dev/null
+++ b/gas/testsuite/gas/sparc/splet.d
@@ -0,0 +1,195 @@
+#as: -Asparclet
+#objdump: -dr
+#name: sparclet extensions
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+ <start>:
+ 0: a1 40 00 00 rd %y, %l0
+ 4: a1 40 40 00 rd %asr1, %l0
+ 8: a1 43 c0 00 rd %asr15, %l0
+ c: a1 44 40 00 rd %asr17, %l0
+ 10: a1 44 80 00 rd %asr18, %l0
+ 14: a1 44 c0 00 rd %asr19, %l0
+ 18: a1 45 00 00 rd %asr20, %l0
+ 1c: a1 45 40 00 rd %asr21, %l0
+ 20: a1 45 80 00 rd %asr22, %l0
+ 24: 81 84 20 00 mov %l0, %y
+ 28: 83 84 20 00 mov %l0, %asr1
+ 2c: 9f 84 20 00 mov %l0, %asr15
+ 30: a3 84 20 00 mov %l0, %asr17
+ 34: a5 84 20 00 mov %l0, %asr18
+ 38: a7 84 20 00 mov %l0, %asr19
+ 3c: a9 84 20 00 mov %l0, %asr20
+ 40: ab 84 20 00 mov %l0, %asr21
+ 44: ad 84 20 00 mov %l0, %asr22
+
+0+48 <test_umul>:
+ 48: 86 50 40 02 umul %g1, %g2, %g3
+ 4c: 86 50 40 02 umul %g1, %g2, %g3
+
+0+50 <test_smul>:
+ 50: 86 58 40 02 smul %g1, %g2, %g3
+ 54: 86 58 40 02 smul %g1, %g2, %g3
+
+0+58 <test_stbar>:
+ 58: 81 43 c0 00 stbar
+ 5c: 81 43 c0 00 stbar
+ 60: 00 00 00 01 unimp 0x1
+ 64: 81 dc 40 00 flush %l1
+
+0+68 <test_scan>:
+ 68: a7 64 7f ff scan %l1, -1, %l3
+ 6c: a7 64 60 00 scan %l1, 0, %l3
+ 70: a7 64 40 11 scan %l1, %l1, %l3
+
+0+74 <test_shuffle>:
+ 74: a3 6c 20 01 shuffle %l0, 1, %l1
+ 78: a3 6c 20 02 shuffle %l0, 2, %l1
+ 7c: a3 6c 20 04 shuffle %l0, 4, %l1
+ 80: a3 6c 20 08 shuffle %l0, 8, %l1
+ 84: a3 6c 20 10 shuffle %l0, 0x10, %l1
+ 88: a3 6c 20 18 shuffle %l0, 0x18, %l1
+
+0+8c <test_umac>:
+ 8c: a1 f4 40 12 umac %l1, %l2, %l0
+ 90: a1 f4 60 02 umac %l1, 2, %l0
+ 94: a1 f4 60 02 umac %l1, 2, %l0
+
+0+98 <test_umacd>:
+ 98: a1 74 80 14 umacd %l2, %l4, %l0
+ 9c: a1 74 a0 03 umacd %l2, 3, %l0
+ a0: a1 74 a0 03 umacd %l2, 3, %l0
+
+0+a4 <test_smac>:
+ a4: a1 fc 40 12 smac %l1, %l2, %l0
+ a8: a1 fc 7f d6 smac %l1, -42, %l0
+ ac: a1 fc 7f d6 smac %l1, -42, %l0
+
+0+b0 <test_smacd>:
+ b0: a1 7c 80 14 smacd %l2, %l4, %l0
+ b4: a1 7c a0 7b smacd %l2, 0x7b, %l0
+ b8: a1 7c a0 7b smacd %l2, 0x7b, %l0
+
+0+bc <test_umuld>:
+ bc: 90 4a 80 0c umuld %o2, %o4, %o0
+ c0: 90 4a a2 34 umuld %o2, 0x234, %o0
+ c4: 90 4a a5 67 umuld %o2, 0x567, %o0
+
+0+c8 <test_smuld>:
+ c8: b0 6e 80 1c smuld %i2, %i4, %i0
+ cc: b0 6e b0 00 smuld %i2, -4096, %i0
+ d0: b0 6f 2f ff smuld %i4, 0xfff, %i0
+
+0+d4 <test_coprocessor>:
+ d4: 81 b4 00 11 cpush %l0, %l1
+ d8: 81 b4 20 01 cpush %l0, 1
+ dc: 81 b4 00 51 cpusha %l0, %l1
+ e0: 81 b4 20 41 cpusha %l0, 1
+ e4: a1 b0 00 80 cpull %l0
+ e8: a1 b0 01 00 crdcxt %ccsr, %l0
+ ec: a1 b0 41 00 crdcxt %ccfr, %l0
+ f0: a1 b0 c1 00 crdcxt %ccpr, %l0
+ f4: a1 b0 81 00 crdcxt %cccrcr, %l0
+ f8: 81 b4 00 c0 cwrcxt %l0, %ccsr
+ fc: 83 b4 00 c0 cwrcxt %l0, %ccfr
+ 100: 87 b4 00 c0 cwrcxt %l0, %ccpr
+ 104: 85 b4 00 c0 cwrcxt %l0, %cccrcr
+ 108: 01 c0 00 01 cbn 10c <test_coprocessor\+(0x|)38>
+ 108: WDISP22 stop\+0xfffffef8
+ 10c: 01 00 00 00 nop
+ 110: 21 c0 00 01 cbn,a 114 <test_coprocessor\+(0x|)40>
+ 110: WDISP22 stop\+0xfffffef0
+ 114: 01 00 00 00 nop
+ 118: 03 c0 00 01 cbe 11c <test_coprocessor\+(0x|)48>
+ 118: WDISP22 stop\+0xfffffee8
+ 11c: 01 00 00 00 nop
+ 120: 23 c0 00 01 cbe,a 124 <test_coprocessor\+(0x|)50>
+ 120: WDISP22 stop\+0xfffffee0
+ 124: 01 00 00 00 nop
+ 128: 05 c0 00 01 cbf 12c <test_coprocessor\+(0x|)58>
+ 128: WDISP22 stop\+0xfffffed8
+ 12c: 01 00 00 00 nop
+ 130: 25 c0 00 01 cbf,a 134 <test_coprocessor\+(0x|)60>
+ 130: WDISP22 stop\+0xfffffed0
+ 134: 01 00 00 00 nop
+ 138: 07 c0 00 01 cbef 13c <test_coprocessor\+(0x|)68>
+ 138: WDISP22 stop\+0xfffffec8
+ 13c: 01 00 00 00 nop
+ 140: 27 c0 00 01 cbef,a 144 <test_coprocessor\+(0x|)70>
+ 140: WDISP22 stop\+0xfffffec0
+ 144: 01 00 00 00 nop
+ 148: 09 c0 00 01 cbr 14c <test_coprocessor\+(0x|)78>
+ 148: WDISP22 stop\+0xfffffeb8
+ 14c: 01 00 00 00 nop
+ 150: 29 c0 00 01 cbr,a 154 <test_coprocessor\+(0x|)80>
+ 150: WDISP22 stop\+0xfffffeb0
+ 154: 01 00 00 00 nop
+ 158: 0b c0 00 01 cber 15c <test_coprocessor\+(0x|)88>
+ 158: WDISP22 stop\+0xfffffea8
+ 15c: 01 00 00 00 nop
+ 160: 2b c0 00 01 cber,a 164 <test_coprocessor\+(0x|)90>
+ 160: WDISP22 stop\+0xfffffea0
+ 164: 01 00 00 00 nop
+ 168: 0d c0 00 01 cbfr 16c <test_coprocessor\+(0x|)98>
+ 168: WDISP22 stop\+0xfffffe98
+ 16c: 01 00 00 00 nop
+ 170: 2d c0 00 01 cbfr,a 174 <test_coprocessor\+(0x|)a0>
+ 170: WDISP22 stop\+0xfffffe90
+ 174: 01 00 00 00 nop
+ 178: 0f c0 00 01 cbefr 17c <test_coprocessor\+(0x|)a8>
+ 178: WDISP22 stop\+0xfffffe88
+ 17c: 01 00 00 00 nop
+ 180: 2f c0 00 01 cbefr,a 184 <test_coprocessor\+(0x|)b0>
+ 180: WDISP22 stop\+0xfffffe80
+ 184: 01 00 00 00 nop
+ 188: 11 c0 00 01 cba 18c <test_coprocessor\+(0x|)b8>
+ 188: WDISP22 stop\+0xfffffe78
+ 18c: 01 00 00 00 nop
+ 190: 31 c0 00 01 cba,a 194 <test_coprocessor\+(0x|)c0>
+ 190: WDISP22 stop\+0xfffffe70
+ 194: 01 00 00 00 nop
+ 198: 13 c0 00 01 cbne 19c <test_coprocessor\+(0x|)c8>
+ 198: WDISP22 stop\+0xfffffe68
+ 19c: 01 00 00 00 nop
+ 1a0: 33 c0 00 01 cbne,a 1a4 <test_coprocessor\+(0x|)d0>
+ 1a0: WDISP22 stop\+0xfffffe60
+ 1a4: 01 00 00 00 nop
+ 1a8: 15 c0 00 01 cbnf 1ac <test_coprocessor\+(0x|)d8>
+ 1a8: WDISP22 stop\+0xfffffe58
+ 1ac: 01 00 00 00 nop
+ 1b0: 35 c0 00 01 cbnf,a 1b4 <test_coprocessor\+(0x|)e0>
+ 1b0: WDISP22 stop\+0xfffffe50
+ 1b4: 01 00 00 00 nop
+ 1b8: 17 c0 00 01 cbnef 1bc <test_coprocessor\+(0x|)e8>
+ 1b8: WDISP22 stop\+0xfffffe48
+ 1bc: 01 00 00 00 nop
+ 1c0: 37 c0 00 01 cbnef,a 1c4 <test_coprocessor\+(0x|)f0>
+ 1c0: WDISP22 stop\+0xfffffe40
+ 1c4: 01 00 00 00 nop
+ 1c8: 19 c0 00 01 cbnr 1cc <test_coprocessor\+(0x|)f8>
+ 1c8: WDISP22 stop\+0xfffffe38
+ 1cc: 01 00 00 00 nop
+ 1d0: 39 c0 00 01 cbnr,a 1d4 <test_coprocessor\+(0x|)100>
+ 1d0: WDISP22 stop\+0xfffffe30
+ 1d4: 01 00 00 00 nop
+ 1d8: 1b c0 00 01 cbner 1dc <test_coprocessor\+(0x|)108>
+ 1d8: WDISP22 stop\+0xfffffe28
+ 1dc: 01 00 00 00 nop
+ 1e0: 3b c0 00 01 cbner,a 1e4 <test_coprocessor\+(0x|)110>
+ 1e0: WDISP22 stop\+0xfffffe20
+ 1e4: 01 00 00 00 nop
+ 1e8: 1d c0 00 01 cbnfr 1ec <test_coprocessor\+(0x|)118>
+ 1e8: WDISP22 stop\+0xfffffe18
+ 1ec: 01 00 00 00 nop
+ 1f0: 3d c0 00 01 cbnfr,a 1f4 <test_coprocessor\+(0x|)120>
+ 1f0: WDISP22 stop\+0xfffffe10
+ 1f4: 01 00 00 00 nop
+ 1f8: 1f c0 00 01 cbnefr 1fc <test_coprocessor\+(0x|)128>
+ 1f8: WDISP22 stop\+0xfffffe08
+ 1fc: 01 00 00 00 nop
+ 200: 3f c0 00 01 cbnefr,a 204 <test_coprocessor\+(0x|)130>
+ 200: WDISP22 stop\+0xfffffe00
+ 204: 01 00 00 00 nop
diff --git a/gas/testsuite/gas/sparc/splet.s b/gas/testsuite/gas/sparc/splet.s
new file mode 100644
index 0000000000..0dfd5074bd
--- /dev/null
+++ b/gas/testsuite/gas/sparc/splet.s
@@ -0,0 +1,211 @@
+ .text
+ .global start
+
+! Starting point
+start:
+
+! test all ASRs
+
+ rd %asr0, %l0
+ rd %asr1, %l0
+ rd %asr15, %l0
+ rd %asr17, %l0
+ rd %asr18, %l0
+ rd %asr19, %l0 ! should stop the processor
+ rd %asr20, %l0
+ rd %asr21, %l0
+ rd %asr22, %l0
+
+ wr %l0, 0, %asr0
+ wr %l0, 0, %asr1
+ wr %l0, 0, %asr15
+ wr %l0, 0, %asr17
+ wr %l0, 0, %asr18
+ wr %l0, 0, %asr19
+ wr %l0, 0, %asr20
+ wr %l0, 0, %asr21
+ wr %l0, 0, %asr22
+
+! test UMUL with no overflow inside Y
+test_umul:
+ umul %g1, %g2, %g3
+
+! test UMUL with an overflow inside Y
+
+ umul %g1, %g2, %g3 ! %g3 must be equal to 0
+
+! test SMUL with negative result
+test_smul:
+ smul %g1, %g2, %g3
+
+! test SMUL with positive result
+
+ smul %g1, %g2, %g3
+
+! test STBAR: there are two possible syntaxes
+test_stbar:
+ stbar ! is a valid V8 syntax, at least a synthetic
+ ! instruction
+ rd %asr15, %g0 ! other solution
+
+! test UNIMP
+ unimp 1
+
+! test FLUSH
+ flush %l1 ! is the official V8 syntax
+
+! test SCAN: find first 0
+test_scan:
+ scan %l1, 0xffffffff, %l3
+
+! test scan: find first 1
+
+ scan %l1, 0, %l3
+
+! test scan: find first bit != bit-0
+
+ scan %l1, %l1, %l3
+
+! test SHUFFLE
+test_shuffle:
+ shuffle %l0, 0x1, %l1
+ shuffle %l0, 0x2, %l1
+ shuffle %l0, 0x4, %l1
+ shuffle %l0, 0x8, %l1
+ shuffle %l0, 0x10, %l1
+ shuffle %l0, 0x18, %l1
+
+! test UMAC
+test_umac:
+ umac %l1, %l2, %l0
+ umac %l1, 2, %l0
+ umac 2, %l1, %l0
+
+! test UMACD
+test_umacd:
+ umacd %l2, %l4, %l0
+ umacd %l2, 3, %l0
+ umacd 3, %l2, %l0
+
+! test SMAC
+test_smac:
+ smac %l1, %l2, %l0
+ smac %l1, -42, %l0
+ smac -42, %l1, %l0
+
+! test SMACD
+test_smacd:
+ smacd %l2, %l4, %l0
+ smacd %l2, 123, %l0
+ smacd 123, %l2, %l0
+
+! test UMULD
+test_umuld:
+ umuld %o2, %o4, %o0
+ umuld %o2, 0x234, %o0
+ umuld 0x567, %o2, %o0
+
+! test SMULD
+test_smuld:
+ smuld %i2, %i4, %i0
+ smuld %i2, -4096, %i0
+ smuld 4095, %i4, %i0
+
+! Coprocessor instructions
+test_coprocessor:
+! %ccsr is register # 0
+! %ccfr is register # 1
+! %ccpr is register # 3
+! %cccrcr is register # 2
+
+! test CPUSH: just syntax
+
+ cpush %l0, %l1
+ cpush %l0, 1
+ cpusha %l0, %l1
+ cpusha %l0, 1
+
+! test CPULL: just syntax
+
+ cpull %l0
+
+! test CPRDCXT: just syntax
+
+ crdcxt %ccsr, %l0
+ crdcxt %ccfr, %l0
+ crdcxt %ccpr, %l0
+ crdcxt %cccrcr, %l0
+
+! test CPWRCXT: just syntax
+
+ cwrcxt %l0, %ccsr
+ cwrcxt %l0, %ccfr
+ cwrcxt %l0, %ccpr
+ cwrcxt %l0, %cccrcr
+
+! test CBccc: just syntax
+
+ cbn stop
+ nop
+ cbn,a stop
+ nop
+ cbe stop
+ nop
+ cbe,a stop
+ nop
+ cbf stop
+ nop
+ cbf,a stop
+ nop
+ cbef stop
+ nop
+ cbef,a stop
+ nop
+ cbr stop
+ nop
+ cbr,a stop
+ nop
+ cber stop
+ nop
+ cber,a stop
+ nop
+ cbfr stop
+ nop
+ cbfr,a stop
+ nop
+ cbefr stop
+ nop
+ cbefr,a stop
+ nop
+ cba stop
+ nop
+ cba,a stop
+ nop
+ cbne stop
+ nop
+ cbne,a stop
+ nop
+ cbnf stop
+ nop
+ cbnf,a stop
+ nop
+ cbnef stop
+ nop
+ cbnef,a stop
+ nop
+ cbnr stop
+ nop
+ cbnr,a stop
+ nop
+ cbner stop
+ nop
+ cbner,a stop
+ nop
+ cbnfr stop
+ nop
+ cbnfr,a stop
+ nop
+ cbnefr stop
+ nop
+ cbnefr,a stop
+ nop
diff --git a/gas/testsuite/gas/sparc/synth.d b/gas/testsuite/gas/sparc/synth.d
new file mode 100644
index 0000000000..dd222c5bc3
--- /dev/null
+++ b/gas/testsuite/gas/sparc/synth.d
@@ -0,0 +1,11 @@
+#as: -Av7
+#objdump: -dr --prefix-addresses
+#name: sparc synth
+
+.*: +file format .*
+
+Disassembly of section .text:
+0+0000 <foo> xnor %g1, %g0, %g2
+0+0004 <foo\+(0x|)4> xnor %g1, %g0, %g1
+0+0008 <foo\+(0x|)8> neg %g1, %g2
+0+000c <foo\+(0x|)c> neg %g1
diff --git a/gas/testsuite/gas/sparc/synth.s b/gas/testsuite/gas/sparc/synth.s
new file mode 100644
index 0000000000..9e06628948
--- /dev/null
+++ b/gas/testsuite/gas/sparc/synth.s
@@ -0,0 +1,7 @@
+# common (v8 or v9) synthetic insns
+ .text
+foo:
+ not %g1,%g2
+ not %g1
+ neg %g1,%g2
+ neg %g1
diff --git a/gas/testsuite/gas/sparc/synth64.d b/gas/testsuite/gas/sparc/synth64.d
new file mode 100644
index 0000000000..a29dab7fcf
--- /dev/null
+++ b/gas/testsuite/gas/sparc/synth64.d
@@ -0,0 +1,19 @@
+#as: -Av9
+#objdump: -dr --prefix-addresses
+#name: sparc64 synth64
+
+.*: +file format .*sparc.*
+
+Disassembly of section .text:
+0+0000 <foo-(0x|)4> iprefetch 0+0004 <foo>
+0+0004 <foo> signx %g1, %g2
+0+0008 <foo\+(0x|)4> clruw %g1, %g2
+0+000c <foo\+(0x|)8> cas \[ %g1 \], %g2, %g3
+0+0010 <foo\+(0x|)c> casl \[ %g1 \], %g2, %g3
+0+0014 <foo\+(0x|)10> casx \[ %g1 \], %g2, %g3
+0+0018 <foo\+(0x|)14> casxl \[ %g1 \], %g2, %g3
+0+001c <foo\+(0x|)18> clrx \[ %g1 \+ %g2 \]
+0+0020 <foo\+(0x|)1c> clrx \[ %g1 \]
+0+0024 <foo\+(0x|)20> clrx \[ %g1 \+ 1 \]
+0+0028 <foo\+(0x|)24> clrx \[ %g1 \+ 0x2a \]
+0+002c <foo\+(0x|)28> clrx \[ 0x42 \]
diff --git a/gas/testsuite/gas/sparc/synth64.s b/gas/testsuite/gas/sparc/synth64.s
new file mode 100644
index 0000000000..659f3c270b
--- /dev/null
+++ b/gas/testsuite/gas/sparc/synth64.s
@@ -0,0 +1,16 @@
+# sparc64 synthetic insns
+ .text
+ iprefetch foo
+foo:
+ signx %g1,%g2
+ clruw %g1,%g2
+ cas [%g1],%g2,%g3
+ casl [%g1],%g2,%g3
+ casx [%g1],%g2,%g3
+ casxl [%g1],%g2,%g3
+
+ clrx [%g1+%g2]
+ clrx [%g1]
+ clrx [%g1+1]
+ clrx [42+%g1]
+ clrx [0x42]
diff --git a/gas/testsuite/gas/sparc/wrpr.d b/gas/testsuite/gas/sparc/wrpr.d
new file mode 100644
index 0000000000..e75dcb8065
--- /dev/null
+++ b/gas/testsuite/gas/sparc/wrpr.d
@@ -0,0 +1,24 @@
+#as: -Av9
+#objdump: -dr
+#name: sparc64 wrpr
+
+.*: +file format .*sparc.*
+
+Disassembly of section .text:
+
+0+ <.text>:
+ 0: 81 90 40 00 wrpr %g1, %tpc
+ 4: 83 90 80 00 wrpr %g2, %tnpc
+ 8: 85 90 c0 00 wrpr %g3, %tstate
+ c: 87 91 00 00 wrpr %g4, %tt
+ 10: 89 91 40 00 wrpr %g5, %tick
+ 14: 8b 91 80 00 wrpr %g6, %tba
+ 18: 8d 91 c0 00 wrpr %g7, %pstate
+ 1c: 8f 92 00 00 wrpr %o0, %tl
+ 20: 91 92 40 00 wrpr %o1, %pil
+ 24: 93 92 80 00 wrpr %o2, %cwp
+ 28: 95 92 c0 00 wrpr %o3, %cansave
+ 2c: 97 93 00 00 wrpr %o4, %canrestore
+ 30: 99 93 40 00 wrpr %o5, %cleanwin
+ 34: 9b 93 80 00 wrpr %sp, %otherwin
+ 38: 9d 93 c0 00 wrpr %o7, %wstate
diff --git a/gas/testsuite/gas/sparc/wrpr.s b/gas/testsuite/gas/sparc/wrpr.s
new file mode 100644
index 0000000000..67fd4504f4
--- /dev/null
+++ b/gas/testsuite/gas/sparc/wrpr.s
@@ -0,0 +1,17 @@
+# Test wrpr
+ .text
+ wrpr %g1,%tpc
+ wrpr %g2,%tnpc
+ wrpr %g3,%tstate
+ wrpr %g4,%tt
+ wrpr %g5,%tick
+ wrpr %g6,%tba
+ wrpr %g7,%pstate
+ wrpr %o0,%tl
+ wrpr %o1,%pil
+ wrpr %o2,%cwp
+ wrpr %o3,%cansave
+ wrpr %o4,%canrestore
+ wrpr %o5,%cleanwin
+ wrpr %o6,%otherwin
+ wrpr %o7,%wstate
diff --git a/gas/testsuite/gas/sun4/addend.d b/gas/testsuite/gas/sun4/addend.d
new file mode 100644
index 0000000000..50ff458ab3
--- /dev/null
+++ b/gas/testsuite/gas/sun4/addend.d
@@ -0,0 +1,13 @@
+#objdump: -r
+# name : addends
+.*: +file format a.out-sunos-big
+
+RELOCATION RECORDS FOR \[.text\]:
+OFFSET TYPE +VALUE
+0+08 WDISP22 +foo1\+0xf+fc
+0+0c WDISP22 +foo1\+0xf+f8
+0+10 WDISP22 +foo1\+0xf+f0
+0+14 WDISP22 +foo1\+0xf+ec
+0+1c 32 +foo1
+0+20 32 +foo1\+0x0+4
+#0+20 32 +foo1\+0x0+4
diff --git a/gas/testsuite/gas/sun4/addend.exp b/gas/testsuite/gas/sun4/addend.exp
new file mode 100644
index 0000000000..f27b46ef2b
--- /dev/null
+++ b/gas/testsuite/gas/sun4/addend.exp
@@ -0,0 +1,7 @@
+#
+# SunOS4 on SPARC tests
+#
+
+if [istarget sparc-*-sunos4*] then {
+ run_dump_test "addend"
+}
diff --git a/gas/testsuite/gas/sun4/addend.s b/gas/testsuite/gas/sun4/addend.s
new file mode 100644
index 0000000000..18eb108a9b
--- /dev/null
+++ b/gas/testsuite/gas/sun4/addend.s
@@ -0,0 +1,11 @@
+ .global foo
+foo:
+ nop
+ nop
+ ba foo1+0x4
+ ba foo1+0x4
+ ba foo1
+ ba foo1
+ nop
+ .word foo1
+ .word foo1+4
diff --git a/gas/testsuite/gas/template b/gas/testsuite/gas/template
new file mode 100644
index 0000000000..a24d79ed74
--- /dev/null
+++ b/gas/testsuite/gas/template
@@ -0,0 +1,96 @@
+#
+# This is sort of a prototype test case, which parses the listing output
+# from the assembler. Later, more prototypes should be added for cases
+# where objdump gets run over the .o file, and anything else like that...
+#
+# When you write a test case that uses the listing output, just copy this
+# file (trimming down the overly-verbose comments a little), and
+# adjust it to do what you need.
+#
+# Remember that any ".exp" file found in the tree will be processed by
+# dejagnu.
+
+#
+# FIRST SAMPLE TEST CASE
+#
+
+proc do_foo {} {
+# This string is used below when printing out a success or failure message.
+# If more than one test is run by a given .exp file, it'd be nice to include
+# the name of the input file.
+ set testname "foo.s: multi-register tweaking and frobnication"
+
+# I use this as a flag to record whether the test case passed. If this
+# flag is still clear when EOF is reached, this test fails. If there are
+# two or more patterns, and I need to see all of them, I'll create N variables
+# and check if the sum is N.
+ set x 0
+
+# Call gas_start with two arguments: The input file name (which it'll search
+# for in $srcdir/$subdir, that is, the source directory where the .exp file
+# is), and a (possibly empty) string of options to pass to the assembler.
+ gas_start "foo.s" "-al"
+
+# Now I just iterate over all the output lines, looking for what I want
+# to see. Since each pattern explicitly will not span line breaks, there's
+# also a pattern for lines that don't match anything else. (Is it safe to
+# use ".*" for patterns not crossing line breaks? I don't think "$" does the
+# right thing for that, in any case. I should check into whether the extra
+# pattern is even needed.
+
+# Apparently CRLF is received when using ptys for subprocesses; hence the
+# \r\n for matching line number 3.
+
+# Note that if you use "{ ... }" for the expect clause, you can't have
+# comments inside it.
+
+# This test case is kinda bogus in that seeing either a word of all zeros
+# at address zero or a C-style comment on line three that says "Looking for
+# C comments" (with very specific punctuation and whitespace) will cause
+# it to pass this test. Usually
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 00000000\[^\n\]*\n" { set x 1 }
+ -re "^ +3\[ \t\]+/. Looking for C comments. ./\r\n" { set x 1 }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+# This was intended to do any cleanup necessary. It kinda looks like it isn't
+# needed, but just in case, please keep it in for now.
+ gas_finish
+
+# Did we find what we were looking for? If not, flunk it.
+ if $x then { pass $testname } else { fail $testname }
+}
+
+# Now actually run the test. It can be conditionalized if the test is
+# not appropriate for all targets. The proc "istarget" checks a generalized
+# form of the target name, so that (e.g.) "m68332-unknown-aout" would match
+# here. So far, I think only the CPU name is actually ever altered.
+if [istarget m68k-*] then {
+ do_foo
+}
+
+
+
+
+#
+# SECOND SAMPLE TEST CASE
+#
+
+# This is a tiny bit like the C compiler torture tests, in that it'll run
+# the assembler with the power set of the list of options supplied.
+#
+# The first argument is the test file name; the second is arguments that
+# are always to be provided; the third is a space-separated list of options
+# which are optional (ending in ">" if output should be ignored, like "-a>");
+# the fourth is the name of the test. So far, only binary options are handled
+# this way; N-way options (like CPU type for m68k) aren't handled yet.
+#
+# The variable $stdoptlist usually has a reasonable set of optional options
+# for this target.
+
+# No, PIC isn't supported yet. This is only an example.
+gas_test "quux.s" "-K" $stdoptlist "use of quuxes in PIC mode"
diff --git a/gas/testsuite/gas/tic80/add.d b/gas/testsuite/gas/tic80/add.d
new file mode 100644
index 0000000000..3dec70729d
--- /dev/null
+++ b/gas/testsuite/gas/tic80/add.d
@@ -0,0 +1,22 @@
+#objdump: -d
+#name: TIc80 signed and unsigned add instructions
+
+.*: +file format .*tic80.*
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 0a 00 fb 62.*
+ 4: ff 3f ac 20.*
+ 8: 00 40 2c 21.*
+ c: 00 10 7b 31 00 40 00 00.*
+ 14: 00 10 fb 41 ff bf ff ff.*
+ 1c: 00 10 bb 5a ff ff ff 7f.*
+ 24: 00 10 3b 6b 00 00 00 80.*
+ 2c: 0a 20 fb 62.*
+ 30: ff bf ac 20.*
+ 34: 00 c0 2c 21.*
+ 38: 00 30 7b 31 00 40 00 00.*
+ 40: 00 30 fb 41 ff bf ff ff.*
+ 48: 00 30 bb 5a ff ff ff 7f.*
+ 50: 00 30 3b 6b 00 00 00 80.*
diff --git a/gas/testsuite/gas/tic80/add.lst b/gas/testsuite/gas/tic80/add.lst
new file mode 100644
index 0000000000..e12b3682aa
--- /dev/null
+++ b/gas/testsuite/gas/tic80/add.lst
@@ -0,0 +1,34 @@
+MVP MP Macro Assembler Version 1.13 Mon Feb 10 20:13:33 1997
+Copyright (c) 1993-1995 Texas Instruments Incorporated
+
+add.s PAGE 1
+
+ 1 ; Test signed and unsigned addition instruction.
+ 2 ; Test boundary conditions to ensure proper handling.
+ 3 ; Note that unsigned addition still uses signed immediates.
+ 4
+ 5 00000000 62FB000A add r10,r11,r12 ; Register form
+ 6 00000004 20AC3FFF add 16383,r2,r4 ; Maximum positive short signed immediate
+ 7 00000008 212C4000 add -16384,r4,r4 ; Minimum negative short signed immediate
+ 8 0000000C 317B1000 add 16384,r5,r6 ; Minimum positive long signed immediate
+ 00000010 00004000
+ 9 00000014 41FB1000 add -16385,r7,r8 ; Maximum negative short signed immediate
+ 00000018 FFFFBFFF
+ 10 0000001C 5ABB1000 add 2147483647,r10,r11 ; Maximum positive long signed immediate
+ 00000020 7FFFFFFF
+ 11 00000024 6B3B1000 add -2147483648,r12,r13 ; Minimum positive long signed immediate
+ 00000028 80000000
+ 12
+ 13 0000002C 62FB200A addu r10,r11,r12 ; Register form
+ 14 00000030 20ACBFFF addu 16383,r2,r4 ; Maximum positive short signed immediate
+ 15 00000034 212CC000 addu -16384,r4,r4 ; Minimum negative short signed immediate
+ 16 00000038 317B3000 addu 16384,r5,r6 ; Minimum positive long signed immediate
+ 0000003C 00004000
+ 17 00000040 41FB3000 addu -16385,r7,r8 ; Maximum negative short signed immediate
+ 00000044 FFFFBFFF
+ 18 00000048 5ABB3000 addu 2147483647,r10,r11 ; Maximum positive long signed immediate
+ 0000004C 7FFFFFFF
+ 19 00000050 6B3B3000 addu -2147483648,r12,r13 ; Minimum positive long signed immediate
+ 00000054 80000000
+
+ No Errors, No Warnings
diff --git a/gas/testsuite/gas/tic80/add.s b/gas/testsuite/gas/tic80/add.s
new file mode 100644
index 0000000000..6c229ed1fe
--- /dev/null
+++ b/gas/testsuite/gas/tic80/add.s
@@ -0,0 +1,19 @@
+; Test signed and unsigned addition instruction.
+; Test boundary conditions to ensure proper handling.
+; Note that unsigned addition still uses signed immediates.
+
+ add r10,r11,r12 ; Register form
+ add 16383,r2,r4 ; Maximum positive short signed immediate
+ add -16384,r4,r4 ; Minimum negative short signed immediate
+ add 16384,r5,r6 ; Minimum positive long signed immediate
+ add -16385,r7,r8 ; Maximum negative long signed immediate
+ add 2147483647,r10,r11 ; Maximum positive long signed immediate
+ add -2147483648,r12,r13 ; Minimum negative long signed immediate
+
+ addu r10,r11,r12 ; Register form
+ addu 16383,r2,r4 ; Maximum positive short signed immediate
+ addu -16384,r4,r4 ; Minimum negative short signed immediate
+ addu 16384,r5,r6 ; Minimum positive long signed immediate
+ addu -16385,r7,r8 ; Maximum negative long signed immediate
+ addu 2147483647,r10,r11 ; Maximum positive long signed immediate
+ addu -2147483648,r12,r13 ; Minimum negative long signed immediate
diff --git a/gas/testsuite/gas/tic80/align.d b/gas/testsuite/gas/tic80/align.d
new file mode 100644
index 0000000000..88f961046e
--- /dev/null
+++ b/gas/testsuite/gas/tic80/align.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name: TIc80 .align pseudo op
+
+.*: +file format .*tic80.*
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: ab 00 00 00.*
+ 4: cd 00 ef 00.*
+ 8: f1 00 00 00.*
+ c: ee 00 00 00.*
+ 10: ac 00 00 00.*
+ 14: 00 00 00 00.*
+ 18: ab 00 00 00.*
+ 1c: 00 00 00 00.*
+ 20: fe 00 00 00.*
+ \.\.\.
+ 30: de ad be ef.*
diff --git a/gas/testsuite/gas/tic80/align.lst b/gas/testsuite/gas/tic80/align.lst
new file mode 100644
index 0000000000..915415ad57
--- /dev/null
+++ b/gas/testsuite/gas/tic80/align.lst
@@ -0,0 +1,47 @@
+MVP MP Macro Assembler Version 1.13 Thu Feb 27 17:02:23 1997
+Copyright (c) 1993-1995 Texas Instruments Incorporated
+
+align.s PAGE 1
+
+ 1 ;; Test the .align directive.
+ 2
+ 3 00000000 .text
+ 4
+ 5 ;; This should generate 0xAB000000
+ 6 00000000 AB .byte 0xAB
+ 7 00000001 .align ; Should default to 4 byte alignment
+ 8
+ 9 ;; This should generate 0xCD00EF00
+ 10 00000004 CD .byte 0xCD
+ 11 .align 2 ; Should align to the next 2-byte boundary (pad with one null byt
+ 12 00000006 EF .byte 0xEF
+ 13 .align 1
+ 14
+ 15 ;; This should generate 0xF1000000
+ 16 00000007 .align 4 ; Should not affect alignment (already on 4)
+ 17 00000008 F1 .byte 0xF1
+ 18 00000009 .align 4 ; Should align to next 4 byte boundary
+ 19
+ 20 ;; This should generate 0xEE000000 since we are already on 4 byte alignment
+ 21 0000000C EE .byte 0xEE
+ 22 0000000D .align 8
+ 23
+ 24 ;; This should generate 0xAC000000 0x00000000
+ 25 00000010 AC .byte 0xAC
+ 26 00000011 .align 8
+ 27
+ 28 ;; This should generate 0xAB000000 0x00000000 since we are at 8 byte alignment
+ 29 00000018 AB .byte 0xAB
+ 30 00000019 .align 16
+ 31
+ 32 ;; This should generate 0xFE000000 0x00000000 0x00000000 0x00000000
+ 33 00000020 FE .byte 0xFE
+ 34 00000021 .align 16
+ 35
+ 36 ;; This just forces the disassembler to not print ... for trailing nulls
+ 37 00000030 DE .byte 0xDE, 0xAD, 0xBE, 0xEF
+ 00000031 AD
+ 00000032 BE
+ 00000033 EF
+
+ No Errors, No Warnings
diff --git a/gas/testsuite/gas/tic80/align.s b/gas/testsuite/gas/tic80/align.s
new file mode 100644
index 0000000000..02c1256f50
--- /dev/null
+++ b/gas/testsuite/gas/tic80/align.s
@@ -0,0 +1,37 @@
+;; Test the .align directive.
+
+ .text
+
+ ;; This should generate 0xAB000000
+ .byte 0xAB
+ .align ; Should default to 4 byte alignment
+
+ ;; This should generate 0xCD00EF00
+ .byte 0xCD
+ .align 2 ; Should align to the next 2-byte boundary (pad with one null byte)
+ .byte 0xEF
+ .align 1
+
+ ;; This should generate 0xF1000000
+ .align 4 ; Should not affect alignment (already on 4)
+ .byte 0xF1
+ .align 4 ; Should align to next 4 byte boundary
+
+ ;; This should generate 0xEE000000 since we are already on 4 byte alignment
+ .byte 0xEE
+ .align 8
+
+ ;; This should generate 0xAC000000 0x00000000
+ .byte 0xAC
+ .align 8
+
+ ;; This should generate 0xAB000000 0x00000000 since we are at 8 byte alignment
+ .byte 0xAB
+ .align 16
+
+ ;; This should generate 0xFE000000 0x00000000 0x00000000 0x00000000
+ .byte 0xFE
+ .align 16
+
+ ;; This just forces the disassembler to not print ... for trailing nulls
+ .byte 0xDE, 0xAD, 0xBE, 0xEF
diff --git a/gas/testsuite/gas/tic80/bitnum.d b/gas/testsuite/gas/tic80/bitnum.d
new file mode 100644
index 0000000000..fcaee8b086
--- /dev/null
+++ b/gas/testsuite/gas/tic80/bitnum.d
@@ -0,0 +1,82 @@
+#objdump: -d
+#name: TIc80 coverage of symbolic BITNUM values
+
+.*: +file format .*tic80.*
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 0a 40 39 fa.*
+ 4: 0a 40 39 f2.*
+ 8: 0a 40 39 ea.*
+ c: 0a 40 39 e2.*
+ 10: 0a 40 39 da.*
+ 14: 0a 40 39 d2.*
+ 18: 0a 40 39 ca.*
+ 1c: 0a 40 39 c2.*
+ 20: 0a 40 39 ba.*
+ 24: 0a 40 39 b2.*
+ 28: 0a 40 39 aa.*
+ 2c: 0a 40 39 a2.*
+ 30: 0a 40 39 9a.*
+ 34: 0a 40 39 92.*
+ 38: 0a 40 39 8a.*
+ 3c: 0a 40 39 82.*
+ 40: 0a 40 39 7a.*
+ 44: 0a 40 39 72.*
+ 48: 0a 40 39 6a.*
+ 4c: 0a 40 39 62.*
+ 50: 0a 40 39 5a.*
+ 54: 0a 40 39 52.*
+ 58: 0a 40 39 4a.*
+ 5c: 0a 40 39 42.*
+ 60: 0a 40 39 3a.*
+ 64: 0a 40 39 32.*
+ 68: 0a 40 39 2a.*
+ 6c: 0a 40 39 22.*
+ 70: 0a 40 39 1a.*
+ 74: 0a 40 39 12.*
+ 78: 0a 40 39 5a.*
+ 7c: 0a 40 39 52.*
+ 80: 0a 40 39 4a.*
+ 84: 0a 40 39 42.*
+ 88: 0a 40 39 3a.*
+ 8c: 0a 40 39 32.*
+ 90: 0a 40 39 2a.*
+ 94: 0a 40 39 22.*
+ 98: 0a 40 39 1a.*
+ 9c: 0a 40 39 12.*
+ a0: 0a 40 39 0a.*
+ a4: 0a 40 39 02.*
+ a8: 0a 40 39 fa.*
+ ac: 0a 40 39 f2.*
+ b0: 0a 40 39 ea.*
+ b4: 0a 40 39 e2.*
+ b8: 0a 40 39 da.*
+ bc: 0a 40 39 d2.*
+ c0: 0a 40 39 ca.*
+ c4: 0a 40 39 c2.*
+ c8: 0a 40 39 ba.*
+ cc: 0a 40 39 b2.*
+ d0: 0a 40 39 aa.*
+ d4: 0a 40 39 a2.*
+ d8: 0a 40 39 9a.*
+ dc: 0a 40 39 92.*
+ e0: 0a 40 39 8a.*
+ e4: 0a 40 39 82.*
+ e8: 0a 40 39 7a.*
+ ec: 0a 40 39 72.*
+ f0: 0a 40 39 6a.*
+ f4: 0a 40 39 62.*
+ f8: 0a 40 39 5a.*
+ fc: 0a 40 39 52.*
+ 100: 0a 40 39 4a.*
+ 104: 0a 40 39 42.*
+ 108: 0a 40 39 3a.*
+ 10c: 0a 40 39 32.*
+ 110: 0a 40 39 2a.*
+ 114: 0a 40 39 22.*
+ 118: 0a 40 39 1a.*
+ 11c: 0a 40 39 12.*
+ 120: 0a 40 39 0a.*
+ 124: 0a 40 39 02.*
diff --git a/gas/testsuite/gas/tic80/bitnum.lst b/gas/testsuite/gas/tic80/bitnum.lst
new file mode 100644
index 0000000000..acc268bb26
--- /dev/null
+++ b/gas/testsuite/gas/tic80/bitnum.lst
@@ -0,0 +1,97 @@
+MVP MP Macro Assembler Version 1.13 Sat Feb 22 21:37:15 1997
+Copyright (c) 1993-1995 Texas Instruments Incorporated
+
+bitnum.s PAGE 1
+
+ 1 ;; Test that all the predefined symbol names for the BITNUM field
+ 2 ;; are properly accepted and translated to numeric values. Also
+ 3 ;; verifies that they are disassembled correctly as symbolics, and
+ 4 ;; that the raw numeric values are handled correctly (stored as
+ 5 ;; the one's complement of the operand numeric value.
+ 6
+ 7 00000000 FA39400A bbo r10,r8,eq.b ; (~0 & 0x1F)
+ 8 00000004 F239400A bbo r10,r8,ne.b ; (~1 & 0x1F)
+ 9 00000008 EA39400A bbo r10,r8,gt.b ; (~2 & 0x1F)
+ 10 0000000C E239400A bbo r10,r8,le.b ; (~3 & 0x1F)
+ 11 00000010 DA39400A bbo r10,r8,lt.b ; (~4 & 0x1F)
+ 12 00000014 D239400A bbo r10,r8,ge.b ; (~5 & 0x1F)
+ 13 00000018 CA39400A bbo r10,r8,hi.b ; (~6 & 0x1F)
+ 14 0000001C C239400A bbo r10,r8,ls.b ; (~7 & 0x1F)
+ 15 00000020 BA39400A bbo r10,r8,lo.b ; (~8 & 0x1F)
+ 16 00000024 B239400A bbo r10,r8,hs.b ; (~9 & 0x1F)
+ 17
+ 18 00000028 AA39400A bbo r10,r8,eq.h ; (~10 & 0x1F)
+ 19 0000002C A239400A bbo r10,r8,ne.h ; (~11 & 0x1F)
+ 20 00000030 9A39400A bbo r10,r8,gt.h ; (~12 & 0x1F)
+ 21 00000034 9239400A bbo r10,r8,le.h ; (~13 & 0x1F)
+ 22 00000038 8A39400A bbo r10,r8,lt.h ; (~14 & 0x1F)
+ 23 0000003C 8239400A bbo r10,r8,ge.h ; (~15 & 0x1F)
+ 24 00000040 7A39400A bbo r10,r8,hi.h ; (~16 & 0x1F)
+ 25 00000044 7239400A bbo r10,r8,ls.h ; (~17 & 0x1F)
+ 26 00000048 6A39400A bbo r10,r8,lo.h ; (~18 & 0x1F)
+ 27 0000004C 6239400A bbo r10,r8,hs.h ; (~19 & 0x1F)
+ 28
+ 29 00000050 5A39400A bbo r10,r8,eq.w ; (~20 & 0x1F)
+ 30 00000054 5239400A bbo r10,r8,ne.w ; (~21 & 0x1F)
+ 31 00000058 4A39400A bbo r10,r8,gt.w ; (~22 & 0x1F)
+ 32 0000005C 4239400A bbo r10,r8,le.w ; (~23 & 0x1F)
+ 33 00000060 3A39400A bbo r10,r8,lt.w ; (~24 & 0x1F)
+ 34 00000064 3239400A bbo r10,r8,ge.w ; (~25 & 0x1F)
+ 35 00000068 2A39400A bbo r10,r8,hi.w ; (~26 & 0x1F)
+ 36 0000006C 2239400A bbo r10,r8,ls.w ; (~27 & 0x1F)
+ 37 00000070 1A39400A bbo r10,r8,lo.w ; (~28 & 0x1F)
+ 38 00000074 1239400A bbo r10,r8,hs.w ; (~29 & 0x1F)
+ 39
+ 40 00000078 5A39400A bbo r10,r8,eq.f ; (~20 & 0x1F)
+ 41 0000007C 5239400A bbo r10,r8,ne.f ; (~21 & 0x1F)
+ 42 00000080 4A39400A bbo r10,r8,gt.f ; (~22 & 0x1F)
+ 43 00000084 4239400A bbo r10,r8,le.f ; (~23 & 0x1F)
+ 44 00000088 3A39400A bbo r10,r8,lt.f ; (~24 & 0x1F)
+ 45 0000008C 3239400A bbo r10,r8,ge.f ; (~25 & 0x1F)
+ 46 00000090 2A39400A bbo r10,r8,ou.f ; (~26 & 0x1F)
+ 47 00000094 2239400A bbo r10,r8,in.f ; (~27 & 0x1F)
+ 48 00000098 1A39400A bbo r10,r8,ib.f ; (~28 & 0x1F)
+ 49 0000009C 1239400A bbo r10,r8,ob.f ; (~29 & 0x1F)
+ 50 000000A0 0A39400A bbo r10,r8,uo.f ; (~30 & 0x1F)
+ 51 000000A4 0239400A bbo r10,r8,or.f ; (~31 & 0x1F)
+ 52
+ 53 000000A8 FA39400A bbo r10,r8,0
+ 54 000000AC F239400A bbo r10,r8,1
+ 55 000000B0 EA39400A bbo r10,r8,2
+ MVP MP Macro Assembler Version 1.13 Sat Feb 22 21:37:15 1997
+Copyright (c) 1993-1995 Texas Instruments Incorporated
+
+bitnum.s PAGE 2
+
+ 56 000000B4 E239400A bbo r10,r8,3
+ 57 000000B8 DA39400A bbo r10,r8,4
+ 58 000000BC D239400A bbo r10,r8,5
+ 59 000000C0 CA39400A bbo r10,r8,6
+ 60 000000C4 C239400A bbo r10,r8,7
+ 61 000000C8 BA39400A bbo r10,r8,8
+ 62 000000CC B239400A bbo r10,r8,9
+ 63 000000D0 AA39400A bbo r10,r8,10
+ 64 000000D4 A239400A bbo r10,r8,11
+ 65 000000D8 9A39400A bbo r10,r8,12
+ 66 000000DC 9239400A bbo r10,r8,13
+ 67 000000E0 8A39400A bbo r10,r8,14
+ 68 000000E4 8239400A bbo r10,r8,15
+ 69 000000E8 7A39400A bbo r10,r8,16
+ 70 000000EC 7239400A bbo r10,r8,17
+ 71 000000F0 6A39400A bbo r10,r8,18
+ 72 000000F4 6239400A bbo r10,r8,19
+ 73 000000F8 5A39400A bbo r10,r8,20
+ 74 000000FC 5239400A bbo r10,r8,21
+ 75 00000100 4A39400A bbo r10,r8,22
+ 76 00000104 4239400A bbo r10,r8,23
+ 77 00000108 3A39400A bbo r10,r8,24
+ 78 0000010C 3239400A bbo r10,r8,25
+ 79 00000110 2A39400A bbo r10,r8,26
+ 80 00000114 2239400A bbo r10,r8,27
+ 81 00000118 1A39400A bbo r10,r8,28
+ 82 0000011C 1239400A bbo r10,r8,29
+ 83 00000120 0A39400A bbo r10,r8,30
+ 84 00000124 0239400A bbo r10,r8,31
+ 85
+
+ No Errors, No Warnings
diff --git a/gas/testsuite/gas/tic80/bitnum.s b/gas/testsuite/gas/tic80/bitnum.s
new file mode 100644
index 0000000000..2526e0644e
--- /dev/null
+++ b/gas/testsuite/gas/tic80/bitnum.s
@@ -0,0 +1,85 @@
+;; Test that all the predefined symbol names for the BITNUM field
+;; are properly accepted and translated to numeric values. Also
+;; verifies that they are disassembled correctly as symbolics, and
+;; that the raw numeric values are handled correctly (stored as
+;; the one's complement of the operand numeric value.
+
+ bbo r10,r8,eq.b ; (~0 & 0x1F)
+ bbo r10,r8,ne.b ; (~1 & 0x1F)
+ bbo r10,r8,gt.b ; (~2 & 0x1F)
+ bbo r10,r8,le.b ; (~3 & 0x1F)
+ bbo r10,r8,lt.b ; (~4 & 0x1F)
+ bbo r10,r8,ge.b ; (~5 & 0x1F)
+ bbo r10,r8,hi.b ; (~6 & 0x1F)
+ bbo r10,r8,ls.b ; (~7 & 0x1F)
+ bbo r10,r8,lo.b ; (~8 & 0x1F)
+ bbo r10,r8,hs.b ; (~9 & 0x1F)
+
+ bbo r10,r8,eq.h ; (~10 & 0x1F)
+ bbo r10,r8,ne.h ; (~11 & 0x1F)
+ bbo r10,r8,gt.h ; (~12 & 0x1F)
+ bbo r10,r8,le.h ; (~13 & 0x1F)
+ bbo r10,r8,lt.h ; (~14 & 0x1F)
+ bbo r10,r8,ge.h ; (~15 & 0x1F)
+ bbo r10,r8,hi.h ; (~16 & 0x1F)
+ bbo r10,r8,ls.h ; (~17 & 0x1F)
+ bbo r10,r8,lo.h ; (~18 & 0x1F)
+ bbo r10,r8,hs.h ; (~19 & 0x1F)
+
+ bbo r10,r8,eq.w ; (~20 & 0x1F)
+ bbo r10,r8,ne.w ; (~21 & 0x1F)
+ bbo r10,r8,gt.w ; (~22 & 0x1F)
+ bbo r10,r8,le.w ; (~23 & 0x1F)
+ bbo r10,r8,lt.w ; (~24 & 0x1F)
+ bbo r10,r8,ge.w ; (~25 & 0x1F)
+ bbo r10,r8,hi.w ; (~26 & 0x1F)
+ bbo r10,r8,ls.w ; (~27 & 0x1F)
+ bbo r10,r8,lo.w ; (~28 & 0x1F)
+ bbo r10,r8,hs.w ; (~29 & 0x1F)
+
+ bbo r10,r8,eq.f ; (~20 & 0x1F)
+ bbo r10,r8,ne.f ; (~21 & 0x1F)
+ bbo r10,r8,gt.f ; (~22 & 0x1F)
+ bbo r10,r8,le.f ; (~23 & 0x1F)
+ bbo r10,r8,lt.f ; (~24 & 0x1F)
+ bbo r10,r8,ge.f ; (~25 & 0x1F)
+ bbo r10,r8,ou.f ; (~26 & 0x1F)
+ bbo r10,r8,in.f ; (~27 & 0x1F)
+ bbo r10,r8,ib.f ; (~28 & 0x1F)
+ bbo r10,r8,ob.f ; (~29 & 0x1F)
+ bbo r10,r8,uo.f ; (~30 & 0x1F)
+ bbo r10,r8,or.f ; (~31 & 0x1F)
+
+ bbo r10,r8,0
+ bbo r10,r8,1
+ bbo r10,r8,2
+ bbo r10,r8,3
+ bbo r10,r8,4
+ bbo r10,r8,5
+ bbo r10,r8,6
+ bbo r10,r8,7
+ bbo r10,r8,8
+ bbo r10,r8,9
+ bbo r10,r8,10
+ bbo r10,r8,11
+ bbo r10,r8,12
+ bbo r10,r8,13
+ bbo r10,r8,14
+ bbo r10,r8,15
+ bbo r10,r8,16
+ bbo r10,r8,17
+ bbo r10,r8,18
+ bbo r10,r8,19
+ bbo r10,r8,20
+ bbo r10,r8,21
+ bbo r10,r8,22
+ bbo r10,r8,23
+ bbo r10,r8,24
+ bbo r10,r8,25
+ bbo r10,r8,26
+ bbo r10,r8,27
+ bbo r10,r8,28
+ bbo r10,r8,29
+ bbo r10,r8,30
+ bbo r10,r8,31
+
diff --git a/gas/testsuite/gas/tic80/ccode.d b/gas/testsuite/gas/tic80/ccode.d
new file mode 100644
index 0000000000..b5a38aa7d0
--- /dev/null
+++ b/gas/testsuite/gas/tic80/ccode.d
@@ -0,0 +1,32 @@
+#objdump: -d
+#name: TIc80 coverage of symbolic condition code values
+
+.*: +file format .*tic80.*
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 07 a0 79 01.*
+ 4: 07 a0 79 09.*
+ 8: 07 a0 79 11.*
+ c: 07 a0 79 19.*
+ 10: 07 a0 79 21.*
+ 14: 07 a0 79 29.*
+ 18: 07 a0 79 31.*
+ 1c: 07 a0 79 39.*
+ 20: 07 a0 79 41.*
+ 24: 07 a0 79 49.*
+ 28: 07 a0 79 51.*
+ 2c: 07 a0 79 59.*
+ 30: 07 a0 79 61.*
+ 34: 07 a0 79 69.*
+ 38: 07 a0 79 71.*
+ 3c: 07 a0 79 79.*
+ 40: 07 a0 79 81.*
+ 44: 07 a0 79 89.*
+ 48: 07 a0 79 91.*
+ 4c: 07 a0 79 99.*
+ 50: 07 a0 79 a1.*
+ 54: 07 a0 79 a9.*
+ 58: 07 a0 79 b1.*
+ 5c: 07 a0 79 b9.*
diff --git a/gas/testsuite/gas/tic80/ccode.lst b/gas/testsuite/gas/tic80/ccode.lst
new file mode 100644
index 0000000000..460351c6e9
--- /dev/null
+++ b/gas/testsuite/gas/tic80/ccode.lst
@@ -0,0 +1,37 @@
+MVP MP Macro Assembler Version 1.13 Mon Feb 10 17:00:49 1997
+Copyright (c) 1993-1995 Texas Instruments Incorporated
+
+ccode.s PAGE 1
+
+ 1 ;; Test that all the predefined symbol names for the condition
+ 2 ;; codes are properly accepted and translated to numeric values.
+ 3 ;; Also verifies that they are disassembled correctly as symbolics.
+ 4
+ 5 00000000 0179A007 bcnd.a r7,r5,nev.b ; 00000
+ 6 00000004 0979A007 bcnd.a r7,r5,gt0.b ; 00001
+ 7 00000008 1179A007 bcnd.a r7,r5,eq0.b ; 00010
+ 8 0000000C 1979A007 bcnd.a r7,r5,ge0.b ; 00011
+ 9 00000010 2179A007 bcnd.a r7,r5,lt0.b ; 00100
+ 10 00000014 2979A007 bcnd.a r7,r5,ne0.b ; 00101
+ 11 00000018 3179A007 bcnd.a r7,r5,le0.b ; 00110
+ 12 0000001C 3979A007 bcnd.a r7,r5,alw.b ; 00111
+ 13
+ 14 00000020 4179A007 bcnd.a r7,r5,nev.h ; 01000
+ 15 00000024 4979A007 bcnd.a r7,r5,gt0.h ; 01001
+ 16 00000028 5179A007 bcnd.a r7,r5,eq0.h ; 01010
+ 17 0000002C 5979A007 bcnd.a r7,r5,ge0.h ; 01011
+ 18 00000030 6179A007 bcnd.a r7,r5,lt0.h ; 01100
+ 19 00000034 6979A007 bcnd.a r7,r5,ne0.h ; 01101
+ 20 00000038 7179A007 bcnd.a r7,r5,le0.h ; 01110
+ 21 0000003C 7979A007 bcnd.a r7,r5,alw.h ; 01111
+ 22
+ 23 00000040 8179A007 bcnd.a r7,r5,nev.w ; 10000
+ 24 00000044 8979A007 bcnd.a r7,r5,gt0.w ; 10001
+ 25 00000048 9179A007 bcnd.a r7,r5,eq0.w ; 10010
+ 26 0000004C 9979A007 bcnd.a r7,r5,ge0.w ; 10011
+ 27 00000050 A179A007 bcnd.a r7,r5,lt0.w ; 10100
+ 28 00000054 A979A007 bcnd.a r7,r5,ne0.w ; 10101
+ 29 00000058 B179A007 bcnd.a r7,r5,le0.w ; 10110
+ 30 0000005C B979A007 bcnd.a r7,r5,alw.w ; 10111
+
+ No Errors, No Warnings
diff --git a/gas/testsuite/gas/tic80/ccode.s b/gas/testsuite/gas/tic80/ccode.s
new file mode 100644
index 0000000000..9e4aac1155
--- /dev/null
+++ b/gas/testsuite/gas/tic80/ccode.s
@@ -0,0 +1,30 @@
+;; Test that all the predefined symbol names for the condition
+;; codes are properly accepted and translated to numeric values.
+;; Also verifies that they are disassembled correctly as symbolics.
+
+ bcnd.a r7,r5,nev.b ; 00000
+ bcnd.a r7,r5,gt0.b ; 00001
+ bcnd.a r7,r5,eq0.b ; 00010
+ bcnd.a r7,r5,ge0.b ; 00011
+ bcnd.a r7,r5,lt0.b ; 00100
+ bcnd.a r7,r5,ne0.b ; 00101
+ bcnd.a r7,r5,le0.b ; 00110
+ bcnd.a r7,r5,alw.b ; 00111
+
+ bcnd.a r7,r5,nev.h ; 01000
+ bcnd.a r7,r5,gt0.h ; 01001
+ bcnd.a r7,r5,eq0.h ; 01010
+ bcnd.a r7,r5,ge0.h ; 01011
+ bcnd.a r7,r5,lt0.h ; 01100
+ bcnd.a r7,r5,ne0.h ; 01101
+ bcnd.a r7,r5,le0.h ; 01110
+ bcnd.a r7,r5,alw.h ; 01111
+
+ bcnd.a r7,r5,nev.w ; 10000
+ bcnd.a r7,r5,gt0.w ; 10001
+ bcnd.a r7,r5,eq0.w ; 10010
+ bcnd.a r7,r5,ge0.w ; 10011
+ bcnd.a r7,r5,lt0.w ; 10100
+ bcnd.a r7,r5,ne0.w ; 10101
+ bcnd.a r7,r5,le0.w ; 10110
+ bcnd.a r7,r5,alw.w ; 10111
diff --git a/gas/testsuite/gas/tic80/cregops.d b/gas/testsuite/gas/tic80/cregops.d
new file mode 100644
index 0000000000..44b61e98c1
--- /dev/null
+++ b/gas/testsuite/gas/tic80/cregops.d
@@ -0,0 +1,68 @@
+#objdump: -d
+#name: TIc80 control register operands
+
+.*: +file format .*tic80.*
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 34 00 02 10.*
+ 4: 39 00 02 10.*
+ 8: 3a 00 02 10.*
+ c: 02 00 02 10.*
+ 10: 00 05 02 10.*
+ 14: 00 04 02 10.*
+ 18: 01 04 02 10.*
+ 1c: 0a 04 02 10.*
+ 20: 0b 04 02 10.*
+ 24: 0c 04 02 10.*
+ 28: 0d 04 02 10.*
+ 2c: 0e 04 02 10.*
+ 30: 0f 04 02 10.*
+ 34: 02 04 02 10.*
+ 38: 03 04 02 10.*
+ 3c: 04 04 02 10.*
+ 40: 05 04 02 10.*
+ 44: 06 04 02 10.*
+ 48: 07 04 02 10.*
+ 4c: 08 04 02 10.*
+ 50: 09 04 02 10.*
+ 54: 33 00 02 10.*
+ 58: 01 00 02 10.*
+ 5c: 00 00 02 10.*
+ 60: 11 00 02 10.*
+ 64: 14 00 02 10.*
+ 68: 13 00 02 10.*
+ 6c: 10 00 02 10.*
+ 70: 12 00 02 10.*
+ 74: 08 00 02 10.*
+ 78: 06 00 02 10.*
+ 7c: 00 03 02 10.*
+ 80: 00 40 02 10.*
+ 84: 01 40 02 10.*
+ 88: 04 00 02 10.*
+ 8c: 00 02 02 10.*
+ 90: 01 02 02 10.*
+ 94: 0a 02 02 10.*
+ 98: 0b 02 02 10.*
+ 9c: 0c 02 02 10.*
+ a0: 0d 02 02 10.*
+ a4: 0e 02 02 10.*
+ a8: 0f 02 02 10.*
+ ac: 02 02 02 10.*
+ b0: 03 02 02 10.*
+ b4: 04 02 02 10.*
+ b8: 05 02 02 10.*
+ bc: 06 02 02 10.*
+ c0: 07 02 02 10.*
+ c4: 08 02 02 10.*
+ c8: 09 02 02 10.*
+ cc: 31 00 02 10.*
+ d0: 30 00 02 10.*
+ d4: 02 40 02 10.*
+ d8: 0d 00 02 10.*
+ dc: 0a 00 02 10.*
+ e0: 20 00 02 10.*
+ e4: 21 00 02 10.*
+ e8: 0e 00 02 10.*
+ ec: 0f 00 02 10.*
diff --git a/gas/testsuite/gas/tic80/cregops.lst b/gas/testsuite/gas/tic80/cregops.lst
new file mode 100644
index 0000000000..65ea57fe64
--- /dev/null
+++ b/gas/testsuite/gas/tic80/cregops.lst
@@ -0,0 +1,76 @@
+MVP MP Macro Assembler Version 1.13 Mon Feb 10 17:00:56 1997
+Copyright (c) 1993-1995 Texas Instruments Incorporated
+
+cregops.s PAGE 1
+
+ 1 ;; Test that all predefined symbol names for control registers
+ 2 ;; are properly accepted and translated to numeric values. Also
+ 3 ;; verifies that they are diassembled correctly as symbolics.
+ 4
+ 5 00000000 10020034 rdcr ANASTAT,r2
+ 6 00000004 10020039 rdcr BRK1,r2
+ 7 00000008 1002003A rdcr BRK2,r2
+ 8 0000000C 10020002 rdcr CONFIG,r2
+ 9 00000010 10020500 rdcr DLRU,r2
+ 10 00000014 10020400 rdcr DTAG0,r2
+ 11 00000018 10020401 rdcr DTAG1,r2
+ 12 0000001C 1002040A rdcr DTAG10,r2
+ 13 00000020 1002040B rdcr DTAG11,r2
+ 14 00000024 1002040C rdcr DTAG12,r2
+ 15 00000028 1002040D rdcr DTAG13,r2
+ 16 0000002C 1002040E rdcr DTAG14,r2
+ 17 00000030 1002040F rdcr DTAG15,r2
+ 18 00000034 10020402 rdcr DTAG2,r2
+ 19 00000038 10020403 rdcr DTAG3,r2
+ 20 0000003C 10020404 rdcr DTAG4,r2
+ 21 00000040 10020405 rdcr DTAG5,r2
+ 22 00000044 10020406 rdcr DTAG6,r2
+ 23 00000048 10020407 rdcr DTAG7,r2
+ 24 0000004C 10020408 rdcr DTAG8,r2
+ 25 00000050 10020409 rdcr DTAG9,r2
+ 26 00000054 10020033 rdcr ECOMCNTL,r2
+ 27 00000058 10020001 rdcr EIP,r2
+ 28 0000005C 10020000 rdcr EPC,r2
+ 29 00000060 10020011 rdcr FLTADR,r2
+ 30 00000064 10020014 rdcr FLTDTH,r2
+ 31 00000068 10020013 rdcr FLTDTL,r2
+ 32 0000006C 10020010 rdcr FLTOP,r2
+ 33 00000070 10020012 rdcr FLTTAG,r2
+ 34 00000074 10020008 rdcr FPST,r2
+ 35 00000078 10020006 rdcr IE,r2
+ 36 0000007C 10020300 rdcr ILRU,r2
+ 37 00000080 10024000 rdcr IN0P,r2
+ 38 00000084 10024001 rdcr IN1P,r2
+ 39 00000088 10020004 rdcr INTPEN,r2
+ 40 0000008C 10020200 rdcr ITAG0,r2
+ 41 00000090 10020201 rdcr ITAG1,r2
+ 42 00000094 1002020A rdcr ITAG10,r2
+ 43 00000098 1002020B rdcr ITAG11,r2
+ 44 0000009C 1002020C rdcr ITAG12,r2
+ 45 000000A0 1002020D rdcr ITAG13,r2
+ 46 000000A4 1002020E rdcr ITAG14,r2
+ 47 000000A8 1002020F rdcr ITAG15,r2
+ 48 000000AC 10020202 rdcr ITAG2,r2
+ 49 000000B0 10020203 rdcr ITAG3,r2
+ 50 000000B4 10020204 rdcr ITAG4,r2
+ 51 000000B8 10020205 rdcr ITAG5,r2
+ 52 000000BC 10020206 rdcr ITAG6,r2
+ 53 000000C0 10020207 rdcr ITAG7,r2
+ 54 000000C4 10020208 rdcr ITAG8,r2
+ 55 000000C8 10020209 rdcr ITAG9,r2
+ MVP MP Macro Assembler Version 1.13 Mon Feb 10 17:00:56 1997
+Copyright (c) 1993-1995 Texas Instruments Incorporated
+
+cregops.s PAGE 2
+
+ 56 000000CC 10020031 rdcr MIP,r2
+ 57 000000D0 10020030 rdcr MPC,r2
+ 58 000000D4 10024002 rdcr OUTP,r2
+ 59 000000D8 1002000D rdcr PKTREQ,r2
+ 60 000000DC 1002000A rdcr PPERROR,r2
+ 61 000000E0 10020020 rdcr SYSSTK,r2
+ 62 000000E4 10020021 rdcr SYSTMP,r2
+ 63 000000E8 1002000E rdcr TCOUNT,r2
+ 64 000000EC 1002000F rdcr TSCALE,r2
+
+ No Errors, No Warnings
diff --git a/gas/testsuite/gas/tic80/cregops.s b/gas/testsuite/gas/tic80/cregops.s
new file mode 100644
index 0000000000..8a0adcf565
--- /dev/null
+++ b/gas/testsuite/gas/tic80/cregops.s
@@ -0,0 +1,64 @@
+;; Test that all predefined symbol names for control registers
+;; are properly accepted and translated to numeric values. Also
+;; verifies that they are diassembled correctly as symbolics.
+
+ rdcr ANASTAT,r2
+ rdcr BRK1,r2
+ rdcr BRK2,r2
+ rdcr CONFIG,r2
+ rdcr DLRU,r2
+ rdcr DTAG0,r2
+ rdcr DTAG1,r2
+ rdcr DTAG10,r2
+ rdcr DTAG11,r2
+ rdcr DTAG12,r2
+ rdcr DTAG13,r2
+ rdcr DTAG14,r2
+ rdcr DTAG15,r2
+ rdcr DTAG2,r2
+ rdcr DTAG3,r2
+ rdcr DTAG4,r2
+ rdcr DTAG5,r2
+ rdcr DTAG6,r2
+ rdcr DTAG7,r2
+ rdcr DTAG8,r2
+ rdcr DTAG9,r2
+ rdcr ECOMCNTL,r2
+ rdcr EIP,r2
+ rdcr EPC,r2
+ rdcr FLTADR,r2
+ rdcr FLTDTH,r2
+ rdcr FLTDTL,r2
+ rdcr FLTOP,r2
+ rdcr FLTTAG,r2
+ rdcr FPST,r2
+ rdcr IE,r2
+ rdcr ILRU,r2
+ rdcr IN0P,r2
+ rdcr IN1P,r2
+ rdcr INTPEN,r2
+ rdcr ITAG0,r2
+ rdcr ITAG1,r2
+ rdcr ITAG10,r2
+ rdcr ITAG11,r2
+ rdcr ITAG12,r2
+ rdcr ITAG13,r2
+ rdcr ITAG14,r2
+ rdcr ITAG15,r2
+ rdcr ITAG2,r2
+ rdcr ITAG3,r2
+ rdcr ITAG4,r2
+ rdcr ITAG5,r2
+ rdcr ITAG6,r2
+ rdcr ITAG7,r2
+ rdcr ITAG8,r2
+ rdcr ITAG9,r2
+ rdcr MIP,r2
+ rdcr MPC,r2
+ rdcr OUTP,r2
+ rdcr PKTREQ,r2
+ rdcr PPERROR,r2
+ rdcr SYSSTK,r2
+ rdcr SYSTMP,r2
+ rdcr TCOUNT,r2
+ rdcr TSCALE,r2
diff --git a/gas/testsuite/gas/tic80/endmask.d b/gas/testsuite/gas/tic80/endmask.d
new file mode 100644
index 0000000000..5cd0847111
--- /dev/null
+++ b/gas/testsuite/gas/tic80/endmask.d
@@ -0,0 +1,41 @@
+#objdump: -d
+#name: TIc80 coverage of shift instruction ENDMASK field
+
+.*: +file format .*tic80.*
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 05 00 c7 49.*
+ 4: 25 00 c7 49.*
+ 8: 45 00 c7 49.*
+ c: 65 00 c7 49.*
+ 10: 85 00 c7 49.*
+ 14: a5 00 c7 49.*
+ 18: c5 00 c7 49.*
+ 1c: e5 00 c7 49.*
+ 20: 05 01 c7 49.*
+ 24: 25 01 c7 49.*
+ 28: 45 01 c7 49.*
+ 2c: 65 01 c7 49.*
+ 30: 85 01 c7 49.*
+ 34: a5 01 c7 49.*
+ 38: c5 01 c7 49.*
+ 3c: e5 01 c7 49.*
+ 40: 05 02 c7 49.*
+ 44: 25 02 c7 49.*
+ 48: 45 02 c7 49.*
+ 4c: 65 02 c7 49.*
+ 50: 85 02 c7 49.*
+ 54: a5 02 c7 49.*
+ 58: c5 02 c7 49.*
+ 5c: e5 02 c7 49.*
+ 60: 05 03 c7 49.*
+ 64: 25 03 c7 49.*
+ 68: 45 03 c7 49.*
+ 6c: 65 03 c7 49.*
+ 70: 85 03 c7 49.*
+ 74: a5 03 c7 49.*
+ 78: c5 03 c7 49.*
+ 7c: e5 03 c7 49.*
+ 80: 05 00 c7 49.*
diff --git a/gas/testsuite/gas/tic80/endmask.lst b/gas/testsuite/gas/tic80/endmask.lst
new file mode 100644
index 0000000000..9103b33dd7
--- /dev/null
+++ b/gas/testsuite/gas/tic80/endmask.lst
@@ -0,0 +1,45 @@
+MVP MP Macro Assembler Version 1.13 Mon Feb 10 17:00:29 1997
+Copyright (c) 1993-1995 Texas Instruments Incorporated
+
+endmask.s PAGE 1
+
+ 1 ;; Test all possible combinations of the endmask in bits 5-9.
+ 2 ;; The mask that is used is computed as 2**bits-1 where bits
+ 3 ;; are the bits 5-9 from the instruction. Note that 0 and 32
+ 4 ;; are treated identically, and disassembled as 0.
+ 5
+ 6 00000000 49C70005 sl.iz 5,0,r7,r9
+ 7 00000004 49C70025 sl.iz 5,1,r7,r9
+ 8 00000008 49C70045 sl.iz 5,2,r7,r9
+ 9 0000000C 49C70065 sl.iz 5,3,r7,r9
+ 10 00000010 49C70085 sl.iz 5,4,r7,r9
+ 11 00000014 49C700A5 sl.iz 5,5,r7,r9
+ 12 00000018 49C700C5 sl.iz 5,6,r7,r9
+ 13 0000001C 49C700E5 sl.iz 5,7,r7,r9
+ 14 00000020 49C70105 sl.iz 5,8,r7,r9
+ 15 00000024 49C70125 sl.iz 5,9,r7,r9
+ 16 00000028 49C70145 sl.iz 5,10,r7,r9
+ 17 0000002C 49C70165 sl.iz 5,11,r7,r9
+ 18 00000030 49C70185 sl.iz 5,12,r7,r9
+ 19 00000034 49C701A5 sl.iz 5,13,r7,r9
+ 20 00000038 49C701C5 sl.iz 5,14,r7,r9
+ 21 0000003C 49C701E5 sl.iz 5,15,r7,r9
+ 22 00000040 49C70205 sl.iz 5,16,r7,r9
+ 23 00000044 49C70225 sl.iz 5,17,r7,r9
+ 24 00000048 49C70245 sl.iz 5,18,r7,r9
+ 25 0000004C 49C70265 sl.iz 5,19,r7,r9
+ 26 00000050 49C70285 sl.iz 5,20,r7,r9
+ 27 00000054 49C702A5 sl.iz 5,21,r7,r9
+ 28 00000058 49C702C5 sl.iz 5,22,r7,r9
+ 29 0000005C 49C702E5 sl.iz 5,23,r7,r9
+ 30 00000060 49C70305 sl.iz 5,24,r7,r9
+ 31 00000064 49C70325 sl.iz 5,25,r7,r9
+ 32 00000068 49C70345 sl.iz 5,26,r7,r9
+ 33 0000006C 49C70365 sl.iz 5,27,r7,r9
+ 34 00000070 49C70385 sl.iz 5,28,r7,r9
+ 35 00000074 49C703A5 sl.iz 5,29,r7,r9
+ 36 00000078 49C703C5 sl.iz 5,30,r7,r9
+ 37 0000007C 49C703E5 sl.iz 5,31,r7,r9
+ 38 00000080 49C70005 sl.iz 5,32,r7,r9
+
+ No Errors, No Warnings
diff --git a/gas/testsuite/gas/tic80/endmask.s b/gas/testsuite/gas/tic80/endmask.s
new file mode 100644
index 0000000000..a36aedebaf
--- /dev/null
+++ b/gas/testsuite/gas/tic80/endmask.s
@@ -0,0 +1,38 @@
+;; Test all possible combinations of the endmask in bits 5-9.
+;; The mask that is used is computed as 2**bits-1 where bits
+;; are the bits 5-9 from the instruction. Note that 0 and 32
+;; are treated identically, and disassembled as 0.
+
+ sl.iz 5,0,r7,r9
+ sl.iz 5,1,r7,r9
+ sl.iz 5,2,r7,r9
+ sl.iz 5,3,r7,r9
+ sl.iz 5,4,r7,r9
+ sl.iz 5,5,r7,r9
+ sl.iz 5,6,r7,r9
+ sl.iz 5,7,r7,r9
+ sl.iz 5,8,r7,r9
+ sl.iz 5,9,r7,r9
+ sl.iz 5,10,r7,r9
+ sl.iz 5,11,r7,r9
+ sl.iz 5,12,r7,r9
+ sl.iz 5,13,r7,r9
+ sl.iz 5,14,r7,r9
+ sl.iz 5,15,r7,r9
+ sl.iz 5,16,r7,r9
+ sl.iz 5,17,r7,r9
+ sl.iz 5,18,r7,r9
+ sl.iz 5,19,r7,r9
+ sl.iz 5,20,r7,r9
+ sl.iz 5,21,r7,r9
+ sl.iz 5,22,r7,r9
+ sl.iz 5,23,r7,r9
+ sl.iz 5,24,r7,r9
+ sl.iz 5,25,r7,r9
+ sl.iz 5,26,r7,r9
+ sl.iz 5,27,r7,r9
+ sl.iz 5,28,r7,r9
+ sl.iz 5,29,r7,r9
+ sl.iz 5,30,r7,r9
+ sl.iz 5,31,r7,r9
+ sl.iz 5,32,r7,r9
diff --git a/gas/testsuite/gas/tic80/float.d b/gas/testsuite/gas/tic80/float.d
new file mode 100644
index 0000000000..87eb85ba7c
--- /dev/null
+++ b/gas/testsuite/gas/tic80/float.d
@@ -0,0 +1,40 @@
+#objdump: -d
+#name: TIc80 simple floating point operands
+
+.*: +file format .*tic80.*
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 80 12 be 51 16 68 a9 65.*
+ 8: 00 12 be 51 16 68 a9 e5.*
+ 10: 00 10 be 51 9a 6d 41 19.*
+ 18: 80 b0 3e 52 9a 6d 41 99.*
+ 20: 00 b0 3e 52 00 00 00 00.*
+ 28: 80 72 be 51 00 00 00 40.*
+ 30: 00 72 be 51 00 00 00 3f.*
+ 38: 00 70 be 51 00 00 80 45.*
+ 40: 80 52 be 51 00 00 80 c5.*
+ 48: 00 52 be 51 00 00 00 40.*
+ 50: 00 50 be 51 00 00 00 40.*
+ 58: 80 93 3e 40 00 00 00 40.*
+ 60: 80 95 3e 40 00 00 00 40.*
+ 68: 80 91 3e 40 00 00 00 40.*
+ 70: 80 97 3e 40 00 00 00 40.*
+ 78: 00 92 3e 40 00 00 00 40.*
+ 80: 00 94 3e 40 00 00 00 40.*
+ 88: 00 90 3e 40 00 00 00 40.*
+ 90: 00 96 3e 40 00 00 00 40.*
+ 98: 00 93 3e 40 00 00 00 40.*
+ a0: 00 95 3e 40 00 00 00 40.*
+ a8: 00 91 3e 40 00 00 00 40.*
+ b0: 00 97 3e 40 00 00 00 40.*
+ b8: 80 92 3e 40 00 00 00 40.*
+ c0: 80 94 3e 40 00 00 00 40.*
+ c8: 80 90 3e 40 00 00 00 40.*
+ d0: 80 96 3e 40 00 00 00 40.*
+ d8: 00 f2 3e 50 00 00 00 40.*
+ e0: 00 f0 3e 50 00 00 00 40.*
+ e8: 80 32 be 51 00 00 00 40.*
+ f0: 00 32 be 51 00 00 00 40.*
+ f8: 00 30 be 51 00 00 00 40.*
diff --git a/gas/testsuite/gas/tic80/float.lst b/gas/testsuite/gas/tic80/float.lst
new file mode 100644
index 0000000000..6134590ca6
--- /dev/null
+++ b/gas/testsuite/gas/tic80/float.lst
@@ -0,0 +1,76 @@
+MVP MP Macro Assembler Version 1.13 Wed Feb 26 22:09:09 1997
+Copyright (c) 1993-1995 Texas Instruments Incorporated
+
+float.s PAGE 1
+
+ 1 00000000 51BE1280 fadd.sdd 1.0E23,r6,r10 ; Immediate form
+ 00000004 65A96816
+ 2 00000008 51BE1200 fadd.ssd -1.0E23,r6,r10 ; Immediate form
+ 0000000C E5A96816
+ 3 00000010 51BE1000 fadd.sss 1.0E-23,r6,r10 ; Immediate form
+ 00000014 19416D9A
+ 4 00000018 523EB080 fcmp.sd -1.0E-23,r8,r10 ; Immediate form
+ 0000001C 99416D9A
+ 5 00000020 523EB000 fcmp.ss 0.0,r8,r10 ; Immediate form
+ 00000024 00000000
+ 6 00000028 51BE7280 fdiv.sdd 2.0,r6,r10 ; Immediate form
+ 0000002C 40000000
+ 7 00000030 51BE7200 fdiv.ssd 0.5,r6,r10 ; Immediate form
+ 00000034 3F000000
+ 8 00000038 51BE7000 fdiv.sss 4096.0,r6,r10 ; Immediate form
+ 0000003C 45800000
+ 9 00000040 51BE5280 fmpy.sdd -4096.0,r6,r10 ; Immediate form
+ 00000044 C5800000
+ 10 00000048 51BE5200 fmpy.ssd 2.0,r6,r10 ; Immediate form
+ 0000004C 40000000
+ 11 00000050 51BE5000 fmpy.sss 2.0,r6,r10 ; Immediate form
+ 00000054 40000000
+ 12 00000058 403E9380 frndm.sd 2.0,r8 ; Immediate form
+ 0000005C 40000000
+ 13 00000060 403E9580 frndm.si 2.0,r8 ; Immediate form
+ 00000064 40000000
+ 14 00000068 403E9180 frndm.ss 2.0,r8 ; Immediate form
+ 0000006C 40000000
+ 15 00000070 403E9780 frndm.su 2.0,r8 ; Immediate form
+ 00000074 40000000
+ 16 00000078 403E9200 frndn.sd 2.0,r8 ; Immediate form
+ 0000007C 40000000
+ 17 00000080 403E9400 frndn.si 2.0,r8 ; Immediate form
+ 00000084 40000000
+ 18 00000088 403E9000 frndn.ss 2.0,r8 ; Immediate form
+ 0000008C 40000000
+ 19 00000090 403E9600 frndn.su 2.0,r8 ; Immediate form
+ 00000094 40000000
+ 20 00000098 403E9300 frndp.sd 2.0,r8 ; Immediate form
+ 0000009C 40000000
+ 21 000000A0 403E9500 frndp.si 2.0,r8 ; Immediate form
+ 000000A4 40000000
+ 22 000000A8 403E9100 frndp.ss 2.0,r8 ; Immediate form
+ 000000AC 40000000
+ 23 000000B0 403E9700 frndp.su 2.0,r8 ; Immediate form
+ 000000B4 40000000
+ 24 000000B8 403E9280 frndz.sd 2.0,r8 ; Immediate form
+ 000000BC 40000000
+ 25 000000C0 403E9480 frndz.si 2.0,r8 ; Immediate form
+ 000000C4 40000000
+ 26 000000C8 403E9080 frndz.ss 2.0,r8 ; Immediate form
+ 000000CC 40000000
+ 27 000000D0 403E9680 frndz.su 2.0,r8 ; Immediate form
+ 000000D4 40000000
+ 28 000000D8 503EF200 fsqrt.sd 2.0,r10 ; Immediate form
+ MVP MP Macro Assembler Version 1.13 Wed Feb 26 22:09:09 1997
+Copyright (c) 1993-1995 Texas Instruments Incorporated
+
+float.s PAGE 2
+
+ 000000DC 40000000
+ 29 000000E0 503EF000 fsqrt.ss 2.0,r10 ; Immediate form
+ 000000E4 40000000
+ 30 000000E8 51BE3280 fsub.sdd 2.0,r6,r10 ; Immediate form
+ 000000EC 40000000
+ 31 000000F0 51BE3200 fsub.ssd 2.0,r6,r10 ; Immediate form
+ 000000F4 40000000
+ 32 000000F8 51BE3000 fsub.sss 2.0,r6,r10 ; Immediate form
+ 000000FC 40000000
+
+ No Errors, No Warnings
diff --git a/gas/testsuite/gas/tic80/float.s b/gas/testsuite/gas/tic80/float.s
new file mode 100644
index 0000000000..98a2b7ae83
--- /dev/null
+++ b/gas/testsuite/gas/tic80/float.s
@@ -0,0 +1,32 @@
+ fadd.sdd 0f1.0E23,r6,r10 ; Immediate form
+ fadd.ssd 0f-1.0E23,r6,r10 ; Immediate form
+ fadd.sss 0f1.0E-23,r6,r10 ; Immediate form
+ fcmp.sd 0f-1.0E-23,r8,r10 ; Immediate form
+ fcmp.ss 0f0.0,r8,r10 ; Immediate form
+ fdiv.sdd 0f2.0,r6,r10 ; Immediate form
+ fdiv.ssd 0f0.5,r6,r10 ; Immediate form
+ fdiv.sss 0f4096.0,r6,r10 ; Immediate form
+ fmpy.sdd 0f-4096.0,r6,r10 ; Immediate form
+ fmpy.ssd 0f2.0,r6,r10 ; Immediate form
+ fmpy.sss 0f2.0,r6,r10 ; Immediate form
+ frndm.sd 0f2.0,r8 ; Immediate form
+ frndm.si 0f2.0,r8 ; Immediate form
+ frndm.ss 0f2.0,r8 ; Immediate form
+ frndm.su 0f2.0,r8 ; Immediate form
+ frndn.sd 0f2.0,r8 ; Immediate form
+ frndn.si 0f2.0,r8 ; Immediate form
+ frndn.ss 0f2.0,r8 ; Immediate form
+ frndn.su 0f2.0,r8 ; Immediate form
+ frndp.sd 0f2.0,r8 ; Immediate form
+ frndp.si 0f2.0,r8 ; Immediate form
+ frndp.ss 0f2.0,r8 ; Immediate form
+ frndp.su 0f2.0,r8 ; Immediate form
+ frndz.sd 0f2.0,r8 ; Immediate form
+ frndz.si 0f2.0,r8 ; Immediate form
+ frndz.ss 0f2.0,r8 ; Immediate form
+ frndz.su 0f2.0,r8 ; Immediate form
+ fsqrt.sd 0f2.0,r10 ; Immediate form
+ fsqrt.ss 0f2.0,r10 ; Immediate form
+ fsub.sdd 0f2.0,r6,r10 ; Immediate form
+ fsub.ssd 0f2.0,r6,r10 ; Immediate form
+ fsub.sss 0f2.0,r6,r10 ; Immediate form
diff --git a/gas/testsuite/gas/tic80/regops.d b/gas/testsuite/gas/tic80/regops.d
new file mode 100644
index 0000000000..dd0fa85753
--- /dev/null
+++ b/gas/testsuite/gas/tic80/regops.d
@@ -0,0 +1,188 @@
+#objdump: -d
+#name: TIc80 register operands
+
+.*: +file format .*tic80.*
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 03 00 3b 29.*
+ 4: 03 20 3b 29.*
+ 8: 05 20 32 11.*
+ c: 05 20 32 11.*
+ 10: 0a 00 33 73.*
+ 14: 0a 80 32 73.*
+ 18: 0a 40 32 73.*
+ 1c: 0a 40 39 1a.*
+ 20: 0a 60 39 fa.*
+ 24: 0a 00 39 22.*
+ 28: 0a 20 39 2a.*
+ 2c: 04 80 b9 21.*
+ 30: 04 a0 b9 21.*
+ 34: 06 00 39 00.*
+ 38: 06 20 39 00.*
+ 3c: 0a 00 03 00.*
+ 40: 06 00 38 f8.*
+ 44: 06 20 38 f8.*
+ 48: 07 40 30 00.*
+ 4c: 03 00 3a 29.*
+ 50: 08 00 b7 02.*
+ 54: 08 00 b7 0a.*
+ 58: 04 04 b4 41.*
+ 5c: 04 24 b4 41.*
+ 60: 04 44 b4 41.*
+ 64: 04 64 b4 41.*
+ 68: 04 04 b5 41.*
+ 6c: 04 24 b5 41.*
+ 70: 04 04 b6 41.*
+ 74: 04 24 b6 41.*
+ 78: 04 44 b6 41.*
+ 7c: 04 64 b6 41.*
+ 80: 05 20 30 08.*
+ 84: e3 47 71 31.*
+ 88: c2 07 71 49.*
+ 8c: 02 00 3e 31.*
+ 90: 02 02 3e 31.*
+ 94: 82 02 3e 31.*
+ 98: 22 02 3e 31.*
+ 9c: a2 02 3e 31.*
+ a0: 04 a0 be 41.*
+ a4: 84 a0 be 41.*
+ a8: 24 a0 be 41.*
+ ac: a4 a0 be 41.*
+ b0: 02 60 3e 31.*
+ b4: 02 62 3e 31.*
+ b8: 82 62 3e 31.*
+ bc: 22 62 3e 31.*
+ c0: a2 62 3e 31.*
+ c4: 02 40 3e 31.*
+ c8: 02 42 3e 31.*
+ cc: 82 42 3e 31.*
+ d0: 22 42 3e 31.*
+ d4: a2 42 3e 31.*
+ d8: 42 45 3e 31.*
+ dc: e2 47 3e 31.*
+ e0: 84 81 3e 30.*
+ e4: 84 83 3e 30.*
+ e8: 84 85 3e 30.*
+ ec: 84 87 3e 30.*
+ f0: a2 81 3e 40.*
+ f4: a2 83 3e 40.*
+ f8: a2 85 3e 40.*
+ fc: a2 87 3e 40.*
+ 100: c4 81 3e 30.*
+ 104: c4 83 3e 30.*
+ 108: e2 81 3e 40.*
+ 10c: e2 83 3e 40.*
+ 110: 04 80 3e 30.*
+ 114: 04 82 3e 30.*
+ 118: 04 84 3e 30.*
+ 11c: 04 86 3e 30.*
+ 120: 22 80 3e 40.*
+ 124: 22 82 3e 40.*
+ 128: 22 84 3e 40.*
+ 12c: 22 86 3e 40.*
+ 130: 44 80 3e 30.*
+ 134: 44 82 3e 30.*
+ 138: 62 80 3e 40.*
+ 13c: 62 82 3e 40.*
+ 140: 04 81 3e 30.*
+ 144: 04 83 3e 30.*
+ 148: 04 85 3e 30.*
+ 14c: 04 87 3e 30.*
+ 150: 22 81 3e 40.*
+ 154: 22 83 3e 40.*
+ 158: 22 85 3e 40.*
+ 15c: 22 87 3e 40.*
+ 160: 44 81 3e 30.*
+ 164: 44 83 3e 30.*
+ 168: 62 81 3e 40.*
+ 16c: 62 83 3e 40.*
+ 170: 84 80 3e 30.*
+ 174: 84 82 3e 30.*
+ 178: 84 84 3e 30.*
+ 17c: 84 86 3e 30.*
+ 180: a2 80 3e 40.*
+ 184: a2 82 3e 40.*
+ 188: a2 84 3e 40.*
+ 18c: a2 86 3e 40.*
+ 190: c4 80 3e 30.*
+ 194: c4 82 3e 30.*
+ 198: e2 80 3e 40.*
+ 19c: e2 82 3e 40.*
+ 1a0: 06 e0 3e 40.*
+ 1a4: 06 e2 3e 40.*
+ 1a8: 26 e2 3e 40.*
+ 1ac: 02 20 3e 31.*
+ 1b0: 02 22 3e 31.*
+ 1b4: 82 22 3e 31.*
+ 1b8: 22 22 3e 31.*
+ 1bc: a2 22 3e 31.*
+ 1c0: e4 e3 31 52.*
+ 1c4: 04 80 b8 41.*
+ 1c8: 04 a0 b8 41.*
+ 1cc: 04 00 b4 41.*
+ 1d0: 04 20 b4 41.*
+ 1d4: 04 40 b4 41.*
+ 1d8: 04 60 b4 41.*
+ 1dc: 04 00 b5 41.*
+ 1e0: 04 20 b5 41.*
+ 1e4: 00 00 ff 41.*
+ 1e8: 01 e0 b2 18.*
+ 1ec: 01 e0 b2 18.*
+ 1f0: 01 c0 b3 18.*
+ 1f4: 01 a0 b3 18.*
+ 1f8: 01 60 b3 18.*
+ 1fc: 06 80 30 20.*
+ 200: 00 20 3f 29.*
+ 204: e2 03 31 52.*
+ 208: e8 07 b1 30.*
+ 20c: e4 c3 b1 30.*
+ 210: 84 01 71 31.*
+ 214: 84 21 71 31.*
+ 218: 84 41 71 31.*
+ 21c: 84 61 71 31.*
+ 220: 84 81 71 31.*
+ 224: 84 a1 71 31.*
+ 228: 84 c1 71 31.*
+ 22c: 84 e1 71 31.*
+ 230: 84 09 71 31.*
+ 234: 84 29 71 31.*
+ 238: 84 49 71 31.*
+ 23c: 84 69 71 31.*
+ 240: 84 89 71 31.*
+ 244: 84 a9 71 31.*
+ 248: 84 c9 71 31.*
+ 24c: 84 e9 71 31.*
+ 250: 84 05 71 31.*
+ 254: 84 25 71 31.*
+ 258: 84 45 71 31.*
+ 25c: 84 65 71 31.*
+ 260: 84 85 71 31.*
+ 264: 84 a5 71 31.*
+ 268: 84 c5 71 31.*
+ 26c: 84 e5 71 31.*
+ 270: 04 a4 b1 41.*
+ 274: 84 0d 71 31.*
+ 278: 84 2d 71 31.*
+ 27c: 84 4d 71 31.*
+ 280: 84 6d 71 31.*
+ 284: 84 8d 71 31.*
+ 288: 84 ad 71 31.*
+ 28c: 84 cd 71 31.*
+ 290: 84 ed 71 31.*
+ 294: 04 64 b1 41.*
+ 298: 04 00 b6 41.*
+ 29c: 04 20 b6 41.*
+ 2a0: 04 40 b6 41.*
+ 2a4: 04 60 b6 41.*
+ 2a8: 07 40 3b 4a.*
+ 2ac: 07 60 3b 4a.*
+ 2b0: 08 a0 b0 21.*
+ 2b4: 0a 20 30 00.*
+ 2b8: 02 00 3c 01.*
+ 2bc: 82 00 bc 01.*
+ 2c0: a2 00 bc 02.*
+ 2c4: 06 a0 70 01.*
+ 2c8: 05 20 b3 39.*
+ 2cc: 07 c0 32 4a.*
diff --git a/gas/testsuite/gas/tic80/regops.lst b/gas/testsuite/gas/tic80/regops.lst
new file mode 100644
index 0000000000..f889dd1a08
--- /dev/null
+++ b/gas/testsuite/gas/tic80/regops.lst
@@ -0,0 +1,264 @@
+MVP MP Macro Assembler Version 1.13 Mon Feb 10 17:00:24 1997
+Copyright (c) 1993-1995 Texas Instruments Incorporated
+
+regops.s PAGE 1
+
+ 1 ;; Simple register forms
+ 2 ;; Those instructions which also use an immediate just use a constant.
+ 3
+ 4 00000000 .text
+ 5
+ 6 00000000 293B0003 add r3,r4,r5
+ 7 00000004 293B2003 addu r3,r4,r5
+ 8 00000008 11322005 and r5,r4,r2
+ 9 0000000C 11322005 and.tt r5,r4,r2
+ 10 00000010 7333000A and.ff r10,r12,r14
+ 11 00000014 7332800A and.ft r10,r12,r14
+ 12 00000018 7332400A and.tf r10,r12,r14
+ 13 0000001C 1A39400A bbo r10,r8,lo.w
+ 14 00000020 FA39600A bbo.a r10,r8,eq.b
+ 15 00000024 2239000A bbz r10,r8,ls.w
+ 16 00000028 2A39200A bbz.a r10,r8,hi.w
+ 17 0000002C 21B98004 bcnd r4,r6,lt0.b
+ 18 00000030 21B9A004 bcnd.a r4,r6,lt0.b
+ 19 00000034 00390006 br r6
+ 20 00000038 00392006 br.a r6
+ 21 0000003C 0003000A brcr 10
+ 22 00000040 F8380006 bsr r6,r31
+ 23 00000044 F8382006 bsr.a r6,r31
+ 24 00000048 00304007 cmnd r7
+ 25 0000004C 293A0003 cmp r3,r4,r5
+ 26 00000050 02B70008 dcachec r8(r10)
+ 27 00000054 0AB70008 dcachef r8(r10)
+ 28 00000058 41B40404 dld.b r4(r6),r8
+ 29 0000005C 41B42404 dld.h r4(r6),r8
+ 30 00000060 41B44404 dld r4(r6),r8
+ 31 00000064 41B46404 dld.d r4(r6),r8
+ 32 00000068 41B50404 dld.ub r4(r6),r8
+ 33 0000006C 41B52404 dld.uh r4(r6),r8
+ 34 00000070 41B60404 dst.b r4(r6),r8
+ 35 00000074 41B62404 dst.h r4(r6),r8
+ 36 00000078 41B64404 dst r4(r6),r8
+ 37 0000007C 41B66404 dst.d r4(r6),r8
+ 38 00000080 08302005 etrap r5
+ 39 00000084 317147E3 exts r3,31,r5,r6
+ 40 00000088 497107C2 extu r2,30,r5,r9
+ 41 0000008C 313E0002 fadd.sss r2,r4,r6
+ 42 00000090 313E0202 fadd.ssd r2,r4,r6
+ 43 00000094 313E0282 fadd.sdd r2,r4,r6
+ 44 00000098 313E0222 fadd.dsd r2,r4,r6
+ 45 0000009C 313E02A2 fadd.ddd r2,r4,r6
+ 46 000000A0 41BEA004 fcmp.ss r4,r6,r8
+ 47 000000A4 41BEA084 fcmp.sd r4,r6,r8
+ 48 000000A8 41BEA024 fcmp.ds r4,r6,r8
+ 49 000000AC 41BEA0A4 fcmp.dd r4,r6,r8
+ 50 000000B0 313E6002 fdiv.sss r2,r4,r6
+ 51 000000B4 313E6202 fdiv.ssd r2,r4,r6
+ 52 000000B8 313E6282 fdiv.sdd r2,r4,r6
+ 53 000000BC 313E6222 fdiv.dsd r2,r4,r6
+ 54 000000C0 313E62A2 fdiv.ddd r2,r4,r6
+ 55 000000C4 313E4002 fmpy.sss r2,r4,r6
+ MVP MP Macro Assembler Version 1.13 Mon Feb 10 17:00:24 1997
+Copyright (c) 1993-1995 Texas Instruments Incorporated
+
+regops.s PAGE 2
+
+ 56 000000C8 313E4202 fmpy.ssd r2,r4,r6
+ 57 000000CC 313E4282 fmpy.sdd r2,r4,r6
+ 58 000000D0 313E4222 fmpy.dsd r2,r4,r6
+ 59 000000D4 313E42A2 fmpy.ddd r2,r4,r6
+ 60 000000D8 313E4542 fmpy.iii r2,r4,r6
+ 61 000000DC 313E47E2 fmpy.uuu r2,r4,r6
+ 62 000000E0 303E8184 frndm.ss r4,r6
+ 63 000000E4 303E8384 frndm.sd r4,r6
+ 64 000000E8 303E8584 frndm.si r4,r6
+ 65 000000EC 303E8784 frndm.su r4,r6
+ 66 000000F0 403E81A2 frndm.ds r2,r8
+ 67 000000F4 403E83A2 frndm.dd r2,r8
+ 68 000000F8 403E85A2 frndm.di r2,r8
+ 69 000000FC 403E87A2 frndm.du r2,r8
+ 70 00000100 303E81C4 frndm.is r4,r6
+ 71 00000104 303E83C4 frndm.id r4,r6
+ 72 00000108 403E81E2 frndm.us r2,r8
+ 73 0000010C 403E83E2 frndm.ud r2,r8
+ 74 00000110 303E8004 frndn.ss r4,r6
+ 75 00000114 303E8204 frndn.sd r4,r6
+ 76 00000118 303E8404 frndn.si r4,r6
+ 77 0000011C 303E8604 frndn.su r4,r6
+ 78 00000120 403E8022 frndn.ds r2,r8
+ 79 00000124 403E8222 frndn.dd r2,r8
+ 80 00000128 403E8422 frndn.di r2,r8
+ 81 0000012C 403E8622 frndn.du r2,r8
+ 82 00000130 303E8044 frndn.is r4,r6
+ 83 00000134 303E8244 frndn.id r4,r6
+ 84 00000138 403E8062 frndn.us r2,r8
+ 85 0000013C 403E8262 frndn.ud r2,r8
+ 86 00000140 303E8104 frndp.ss r4,r6
+ 87 00000144 303E8304 frndp.sd r4,r6
+ 88 00000148 303E8504 frndp.si r4,r6
+ 89 0000014C 303E8704 frndp.su r4,r6
+ 90 00000150 403E8122 frndp.ds r2,r8
+ 91 00000154 403E8322 frndp.dd r2,r8
+ 92 00000158 403E8522 frndp.di r2,r8
+ 93 0000015C 403E8722 frndp.du r2,r8
+ 94 00000160 303E8144 frndp.is r4,r6
+ 95 00000164 303E8344 frndp.id r4,r6
+ 96 00000168 403E8162 frndp.us r2,r8
+ 97 0000016C 403E8362 frndp.ud r2,r8
+ 98 00000170 303E8084 frndz.ss r4,r6
+ 99 00000174 303E8284 frndz.sd r4,r6
+ 100 00000178 303E8484 frndz.si r4,r6
+ 101 0000017C 303E8684 frndz.su r4,r6
+ 102 00000180 403E80A2 frndz.ds r2,r8
+ 103 00000184 403E82A2 frndz.dd r2,r8
+ 104 00000188 403E84A2 frndz.di r2,r8
+ 105 0000018C 403E86A2 frndz.du r2,r8
+ 106 00000190 303E80C4 frndz.is r4,r6
+ 107 00000194 303E82C4 frndz.id r4,r6
+ 108 00000198 403E80E2 frndz.us r2,r8
+ 109 0000019C 403E82E2 frndz.ud r2,r8
+ 110 000001A0 403EE006 fsqrt.ss r6,r8
+ MVP MP Macro Assembler Version 1.13 Mon Feb 10 17:00:24 1997
+Copyright (c) 1993-1995 Texas Instruments Incorporated
+
+regops.s PAGE 3
+
+ 111 000001A4 403EE206 fsqrt.sd r6,r8
+ 112 000001A8 403EE226 fsqrt.dd r6,r8
+ 113 000001AC 313E2002 fsub.sss r2,r4,r6
+ 114 000001B0 313E2202 fsub.ssd r2,r4,r6
+ 115 000001B4 313E2282 fsub.sdd r2,r4,r6
+ 116 000001B8 313E2222 fsub.dsd r2,r4,r6
+ 117 000001BC 313E22A2 fsub.ddd r2,r4,r6
+ 118 000001C0 5231E3E4 ins r4,31,r8,r10
+ 119 000001C4 41B88004 jsr r4(r6),r8
+ 120 000001C8 41B8A004 jsr.a r4(r6),r8
+ 121 000001CC 41B40004 ld.b r4(r6),r8
+ 122 000001D0 41B42004 ld.h r4(r6),r8
+ 123 000001D4 41B44004 ld r4(r6),r8
+ 124 000001D8 41B46004 ld.d r4(r6),r8
+ 125 000001DC 41B50004 ld.ub r4(r6),r8
+ 126 000001E0 41B52004 ld.uh r4(r6),r8
+ 127 000001E4 41FF0007 lmo r7,r8
+ 128 000001E8 18B2E001 or r1,r2,r3
+ 129 000001EC 18B2E001 or.tt r1,r2,r3
+ 130 000001F0 18B3C001 or.ff r1,r2,r3
+ 131 000001F4 18B3A001 or.ft r1,r2,r3
+ 132 000001F8 18B36001 or.tf r1,r2,r3
+ 133 000001FC 20308006 rdcr r6,r4
+ 134 00000200 293F2004 rmo r4,r5
+ 135 00000204 523103E2 rotl r2,31,r8,r10
+ 136 00000208 30B107E8 rotr r8,31,r2,r6
+ 137 0000020C 30B1C3E4 shl r4,31,r2,r6
+ 138 00000210 31710184 sl.dz r4,12,r5,r6
+ 139 00000214 31712184 sl.dm r4,12,r5,r6
+ 140 00000218 31714184 sl.ds r4,12,r5,r6
+ 141 0000021C 31716184 sl.ez r4,12,r5,r6
+ 142 00000220 31718184 sl.em r4,12,r5,r6
+ 143 00000224 3171A184 sl.es r4,12,r5,r6
+ 144 00000228 3171C184 sl.iz r4,12,r5,r6
+ 145 0000022C 3171E184 sl.im r4,12,r5,r6
+ 146 00000230 31710984 sli.dz r4,12,r5,r6
+ 147 00000234 31712984 sli.dm r4,12,r5,r6
+ 148 00000238 31714984 sli.ds r4,12,r5,r6
+ 149 0000023C 31716984 sli.ez r4,12,r5,r6
+ 150 00000240 31718984 sli.em r4,12,r5,r6
+ 151 00000244 3171A984 sli.es r4,12,r5,r6
+ 152 00000248 3171C984 sli.iz r4,12,r5,r6
+ 153 0000024C 3171E984 sli.im r4,12,r5,r6
+ 154 00000250 31710584 sr.dz r4,12,r5,r6
+ 155 00000254 31712584 sr.dm r4,12,r5,r6
+ 156 00000258 31714584 sr.ds r4,12,r5,r6
+ 157 0000025C 31716584 sr.ez r4,12,r5,r6
+ 158 00000260 31718584 sr.em r4,12,r5,r6
+ 159 00000264 3171A584 sr.es r4,12,r5,r6
+ 160 00000268 3171C584 sr.iz r4,12,r5,r6
+ 161 0000026C 3171E584 sr.im r4,12,r5,r6
+ 162 00000270 41B1A404 sra r4,32,r6,r8
+ 163 00000274 31710D84 sri.dz r4,12,r5,r6
+ 164 00000278 31712D84 sri.dm r4,12,r5,r6
+ 165 0000027C 31714D84 sri.ds r4,12,r5,r6
+ MVP MP Macro Assembler Version 1.13 Mon Feb 10 17:00:24 1997
+Copyright (c) 1993-1995 Texas Instruments Incorporated
+
+regops.s PAGE 4
+
+ 166 00000280 31716D84 sri.ez r4,12,r5,r6
+ 167 00000284 31718D84 sri.em r4,12,r5,r6
+ 168 00000288 3171AD84 sri.es r4,12,r5,r6
+ 169 0000028C 3171CD84 sri.iz r4,12,r5,r6
+ 170 00000290 3171ED84 sri.im r4,12,r5,r6
+ 171 00000294 41B16404 srl r4,32,r6,r8
+ 172 00000298 41B60004 st.b r4(r6),r8
+ 173 0000029C 41B62004 st.h r4(r6),r8
+ 174 000002A0 41B64004 st r4(r6),r8
+ 175 000002A4 41B66004 st.d r4(r6),r8
+ 176 000002A8 4A3B4007 sub r7,r8,r9
+ 177 000002AC 4A3B6007 subu r7,r8,r9
+ 178 000002B0 21B0A008 swcr r8,r6,r4
+ 179 000002B4 0030200A trap r10
+ 180 000002B8 013C0002 vadd.ss r2,r4,r4
+ 181 000002BC 01BC0082 vadd.sd r2,r6,r6
+ 182 000002C0 02BC00A2 vadd.dd r2,r10,r10
+ 183 ; vld0.s r6
+ 184 ; vld1.s r7
+ 185 ; vld0.d r6
+ 186 ; vld1.d r8
+ 187 ; vmac.sss r7,r9,0,a3
+ 188 ; vmac.sss r7,r9,0,r10
+ 189 ; vmac.sss r7,r9,a1,a3
+ 190 ; vmac.sss r7,r9,a3,r10
+ 191 ; vmac.ssd r7,r9,0,a0
+ 192 ; vmac.ssd r7,r9,0,r10
+ 193 ; vmac.ssd r7,r9,a1,a2
+ 194 ; vmac.ssd r7,r9,a3,r10
+ 195 ; vmpy.ss r1,r3,r3
+ 196 ; vmpy.sd r5,r6,r6
+ 197 ; vmpy.dd r2,r4,r4
+ 198 ; vmsc.sss r7,r9,0,a0
+ 199 ; vmsc.sss r7,r9,0,r10
+ 200 ; vmsc.sss r7,r9,a0,a1
+ 201 ; vmsc.sss r7,r9,a3,r10
+ 202 ; vmsc.ssd r7,r9,0,a0
+ 203 ; vmsc.ssd r7,r9,0,r10
+ 204 ; vmsc.ssd r7,r9,a0,a1
+ 205 ; vmsc.ssd r7,r9,a3,r10
+ 206 ; vmsub.ss r6,a2,a4
+ 207 ; vmsub.sd r6,a2,a4
+ 208 ; vmsub.ss r4,a4,r6
+ 209 ; vmsub.sd r4,a4,r6
+ 210 ; vrnd.si r4,r6
+ 211 ; vrnd.si r4,a0
+ 212 ; vrnd.su r4,r6
+ 213 ; vrnd.su r4,a0
+ 214 ; vrnd.ss r4,r6
+ 215 ; vrnd.ss r4,a0
+ 216 ; vrnd.sd r4,r6
+ 217 ; vrnd.sd r4,a0
+ 218 ; vrnd.di r4,r6
+ 219 ; vrnd.di r4,a0
+ 220 ; vrnd.du r4,r6
+ MVP MP Macro Assembler Version 1.13 Mon Feb 10 17:00:24 1997
+Copyright (c) 1993-1995 Texas Instruments Incorporated
+
+regops.s PAGE 5
+
+ 221 ; vrnd.du r4,a0
+ 222 ; vrnd.ds r4,r6
+ 223 ; vrnd.ds r4,a0
+ 224 ; vrnd.dd r4,r6
+ 225 ; vrnd.dd r4,a0
+ 226 ; vrnd.is r4,r6
+ 227 ; vrnd.id r4,r6
+ 228 ; vrnd.us r4,r6
+ 229 ; vrnd.ud r4,r6
+ 230 ; vst.s r6
+ 231 ; vst.d r6
+ 232 ; vsub.ss r2,r4,r6
+ 233 ; vsub.sd r2,r4,r6
+ 234 ; vsub.dd r2,r4,r6
+ 235 000002C4 0170A006 wrcr r6,r5
+ 236 000002C8 39B32005 xnor r5,r6,r7
+ 237 000002CC 4A32C007 xor r7,r8,r9
+
+ No Errors, No Warnings
diff --git a/gas/testsuite/gas/tic80/regops.s b/gas/testsuite/gas/tic80/regops.s
new file mode 100644
index 0000000000..f4f93523c3
--- /dev/null
+++ b/gas/testsuite/gas/tic80/regops.s
@@ -0,0 +1,237 @@
+;; Simple register forms
+;; Those instructions which also use an immediate just use a constant.
+
+ .text
+
+ add r3,r4,r5
+ addu r3,r4,r5
+ and r5,r4,r2
+ and.tt r5,r4,r2
+ and.ff r10,r12,r14
+ and.ft r10,r12,r14
+ and.tf r10,r12,r14
+ bbo r10,r8,lo.w
+ bbo.a r10,r8,eq.b
+ bbz r10,r8,ls.w
+ bbz.a r10,r8,hi.w
+ bcnd r4,r6,lt0.b
+ bcnd.a r4,r6,lt0.b
+ br r6
+ br.a r6
+ brcr 10
+ bsr r6,r31
+ bsr.a r6,r31
+ cmnd r7
+ cmp r3,r4,r5
+ dcachec r8(r10)
+ dcachef r8(r10)
+ dld.b r4(r6),r8
+ dld.h r4(r6),r8
+ dld r4(r6),r8
+ dld.d r4(r6),r8
+ dld.ub r4(r6),r8
+ dld.uh r4(r6),r8
+ dst.b r4(r6),r8
+ dst.h r4(r6),r8
+ dst r4(r6),r8
+ dst.d r4(r6),r8
+ etrap r5
+ exts r3,31,r5,r6
+ extu r2,30,r5,r9
+ fadd.sss r2,r4,r6
+ fadd.ssd r2,r4,r6
+ fadd.sdd r2,r4,r6
+ fadd.dsd r2,r4,r6
+ fadd.ddd r2,r4,r6
+ fcmp.ss r4,r6,r8
+ fcmp.sd r4,r6,r8
+ fcmp.ds r4,r6,r8
+ fcmp.dd r4,r6,r8
+ fdiv.sss r2,r4,r6
+ fdiv.ssd r2,r4,r6
+ fdiv.sdd r2,r4,r6
+ fdiv.dsd r2,r4,r6
+ fdiv.ddd r2,r4,r6
+ fmpy.sss r2,r4,r6
+ fmpy.ssd r2,r4,r6
+ fmpy.sdd r2,r4,r6
+ fmpy.dsd r2,r4,r6
+ fmpy.ddd r2,r4,r6
+ fmpy.iii r2,r4,r6
+ fmpy.uuu r2,r4,r6
+ frndm.ss r4,r6
+ frndm.sd r4,r6
+ frndm.si r4,r6
+ frndm.su r4,r6
+ frndm.ds r2,r8
+ frndm.dd r2,r8
+ frndm.di r2,r8
+ frndm.du r2,r8
+ frndm.is r4,r6
+ frndm.id r4,r6
+ frndm.us r2,r8
+ frndm.ud r2,r8
+ frndn.ss r4,r6
+ frndn.sd r4,r6
+ frndn.si r4,r6
+ frndn.su r4,r6
+ frndn.ds r2,r8
+ frndn.dd r2,r8
+ frndn.di r2,r8
+ frndn.du r2,r8
+ frndn.is r4,r6
+ frndn.id r4,r6
+ frndn.us r2,r8
+ frndn.ud r2,r8
+ frndp.ss r4,r6
+ frndp.sd r4,r6
+ frndp.si r4,r6
+ frndp.su r4,r6
+ frndp.ds r2,r8
+ frndp.dd r2,r8
+ frndp.di r2,r8
+ frndp.du r2,r8
+ frndp.is r4,r6
+ frndp.id r4,r6
+ frndp.us r2,r8
+ frndp.ud r2,r8
+ frndz.ss r4,r6
+ frndz.sd r4,r6
+ frndz.si r4,r6
+ frndz.su r4,r6
+ frndz.ds r2,r8
+ frndz.dd r2,r8
+ frndz.di r2,r8
+ frndz.du r2,r8
+ frndz.is r4,r6
+ frndz.id r4,r6
+ frndz.us r2,r8
+ frndz.ud r2,r8
+ fsqrt.ss r6,r8
+ fsqrt.sd r6,r8
+ fsqrt.dd r6,r8
+ fsub.sss r2,r4,r6
+ fsub.ssd r2,r4,r6
+ fsub.sdd r2,r4,r6
+ fsub.dsd r2,r4,r6
+ fsub.ddd r2,r4,r6
+ ins r4,31,r8,r10
+ jsr r4(r6),r8
+ jsr.a r4(r6),r8
+ ld.b r4(r6),r8
+ ld.h r4(r6),r8
+ ld r4(r6),r8
+ ld.d r4(r6),r8
+ ld.ub r4(r6),r8
+ ld.uh r4(r6),r8
+ lmo r7,r8
+ or r1,r2,r3
+ or.tt r1,r2,r3
+ or.ff r1,r2,r3
+ or.ft r1,r2,r3
+ or.tf r1,r2,r3
+ rdcr r6,r4
+ rmo r4,r5
+ rotl r2,31,r8,r10
+ rotr r8,31,r2,r6
+ shl r4,31,r2,r6
+ sl.dz r4,12,r5,r6
+ sl.dm r4,12,r5,r6
+ sl.ds r4,12,r5,r6
+ sl.ez r4,12,r5,r6
+ sl.em r4,12,r5,r6
+ sl.es r4,12,r5,r6
+ sl.iz r4,12,r5,r6
+ sl.im r4,12,r5,r6
+ sli.dz r4,12,r5,r6
+ sli.dm r4,12,r5,r6
+ sli.ds r4,12,r5,r6
+ sli.ez r4,12,r5,r6
+ sli.em r4,12,r5,r6
+ sli.es r4,12,r5,r6
+ sli.iz r4,12,r5,r6
+ sli.im r4,12,r5,r6
+ sr.dz r4,12,r5,r6
+ sr.dm r4,12,r5,r6
+ sr.ds r4,12,r5,r6
+ sr.ez r4,12,r5,r6
+ sr.em r4,12,r5,r6
+ sr.es r4,12,r5,r6
+ sr.iz r4,12,r5,r6
+ sr.im r4,12,r5,r6
+ sra r4,32,r6,r8
+ sri.dz r4,12,r5,r6
+ sri.dm r4,12,r5,r6
+ sri.ds r4,12,r5,r6
+ sri.ez r4,12,r5,r6
+ sri.em r4,12,r5,r6
+ sri.es r4,12,r5,r6
+ sri.iz r4,12,r5,r6
+ sri.im r4,12,r5,r6
+ srl r4,32,r6,r8
+ st.b r4(r6),r8
+ st.h r4(r6),r8
+ st r4(r6),r8
+ st.d r4(r6),r8
+ sub r7,r8,r9
+ subu r7,r8,r9
+ swcr r8,r6,r4
+ trap r10
+ vadd.ss r2,r4,r4
+ vadd.sd r2,r6,r6
+ vadd.dd r2,r10,r10
+; vld0.s r6
+; vld1.s r7
+; vld0.d r6
+; vld1.d r8
+; vmac.sss r7,r9,0,a3
+; vmac.sss r7,r9,0,r10
+; vmac.sss r7,r9,a1,a3
+; vmac.sss r7,r9,a3,r10
+; vmac.ssd r7,r9,0,a0
+; vmac.ssd r7,r9,0,r10
+; vmac.ssd r7,r9,a1,a2
+; vmac.ssd r7,r9,a3,r10
+; vmpy.ss r1,r3,r3
+; vmpy.sd r5,r6,r6
+; vmpy.dd r2,r4,r4
+; vmsc.sss r7,r9,0,a0
+; vmsc.sss r7,r9,0,r10
+; vmsc.sss r7,r9,a0,a1
+; vmsc.sss r7,r9,a3,r10
+; vmsc.ssd r7,r9,0,a0
+; vmsc.ssd r7,r9,0,r10
+; vmsc.ssd r7,r9,a0,a1
+; vmsc.ssd r7,r9,a3,r10
+; vmsub.ss r6,a2,a4
+; vmsub.sd r6,a2,a4
+; vmsub.ss r4,a4,r6
+; vmsub.sd r4,a4,r6
+; vrnd.si r4,r6
+; vrnd.si r4,a0
+; vrnd.su r4,r6
+; vrnd.su r4,a0
+; vrnd.ss r4,r6
+; vrnd.ss r4,a0
+; vrnd.sd r4,r6
+; vrnd.sd r4,a0
+; vrnd.di r4,r6
+; vrnd.di r4,a0
+; vrnd.du r4,r6
+; vrnd.du r4,a0
+; vrnd.ds r4,r6
+; vrnd.ds r4,a0
+; vrnd.dd r4,r6
+; vrnd.dd r4,a0
+; vrnd.is r4,r6
+; vrnd.id r4,r6
+; vrnd.us r4,r6
+; vrnd.ud r4,r6
+; vst.s r6
+; vst.d r6
+; vsub.ss r2,r4,r6
+; vsub.sd r2,r4,r6
+; vsub.dd r2,r4,r6
+ wrcr r6,r5
+ xnor r5,r6,r7
+ xor r7,r8,r9
diff --git a/gas/testsuite/gas/tic80/regops2.d b/gas/testsuite/gas/tic80/regops2.d
new file mode 100644
index 0000000000..0b7f4a16bf
--- /dev/null
+++ b/gas/testsuite/gas/tic80/regops2.d
@@ -0,0 +1,68 @@
+#objdump: -d
+#name: TIc80 register operands with :m modifier
+
+.*: +file format .*tic80.*
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 08 80 b7 02.*
+ 4: 04 00 9e 02.*
+ 8: fc 7f 9e 02.*
+ c: 00 90 b7 02 78 56 34 12.*
+ 14: 00 90 b7 02 ef be ad de.*
+ 1c: 08 80 b7 0a.*
+ 20: 04 00 9e 0a.*
+ 24: fc 7f 9e 0a.*
+ 28: 00 90 b7 0a 78 56 34 12.*
+ 30: 00 90 b7 0a ef be ad de.*
+ 38: 04 84 b4 41.*
+ 3c: 04 a4 b4 41.*
+ 40: 04 c4 b4 41.*
+ 44: 04 e4 b4 41.*
+ 48: 00 94 b4 41 00 00 00 e0.*
+ 50: 00 b4 b4 41 00 00 00 e0.*
+ 58: 00 d4 b4 41 00 00 00 e0.*
+ 60: 00 f4 b4 41 00 00 00 e0.*
+ 68: 04 84 b5 41.*
+ 6c: 04 a4 b5 41.*
+ 70: 00 94 b5 41 00 00 00 e0.*
+ 78: 00 b4 b5 41 00 00 00 e0.*
+ 80: 04 84 b6 41.*
+ 84: 04 a4 b6 41.*
+ 88: 04 c4 b6 41.*
+ 8c: 04 e4 b6 41.*
+ 90: 00 94 b6 41 00 00 00 e0.*
+ 98: 00 b4 b6 41 00 00 00 e0.*
+ a0: 00 d4 b6 41 00 00 00 e0.*
+ a8: 00 f4 b6 41 00 00 00 e0.*
+ b0: 04 80 b4 41.*
+ b4: 04 a0 b4 41.*
+ b8: 04 c0 b4 41.*
+ bc: 04 e0 b4 41.*
+ c0: f0 7f 92 41.*
+ c4: f0 ff 92 41.*
+ c8: f0 7f 93 41.*
+ cc: f0 ff 93 41.*
+ d0: 00 90 b4 41 00 00 00 e0.*
+ d8: 00 b0 b4 41 00 00 00 e0.*
+ e0: 00 d0 b4 41 00 00 00 e0.*
+ e8: 00 f0 b4 41 00 00 00 e0.*
+ f0: 04 80 b5 41.*
+ f4: 04 a0 b5 41.*
+ f8: f0 7f 96 41.*
+ fc: f0 ff 96 41.*
+ 100: 00 90 b5 41 00 00 00 e0.*
+ 108: 00 b0 b5 41 00 00 00 e0.*
+ 110: 04 80 b6 41.*
+ 114: 04 a0 b6 41.*
+ 118: 04 c0 b6 41.*
+ 11c: 04 e0 b6 41.*
+ 120: 00 7f 9a 41.*
+ 124: 00 ff 9a 41.*
+ 128: 00 7f 9b 41.*
+ 12c: 00 ff 9b 41.*
+ 130: 00 90 b6 41 00 00 00 e0.*
+ 138: 00 b0 b6 41 00 00 00 e0.*
+ 140: 00 d0 b6 41 00 00 00 e0.*
+ 148: 00 f0 b6 41 00 00 00 e0.*
diff --git a/gas/testsuite/gas/tic80/regops2.lst b/gas/testsuite/gas/tic80/regops2.lst
new file mode 100644
index 0000000000..651fb9716f
--- /dev/null
+++ b/gas/testsuite/gas/tic80/regops2.lst
@@ -0,0 +1,96 @@
+MVP MP Macro Assembler Version 1.13 Wed Feb 26 14:32:14 1997
+Copyright (c) 1993-1995 Texas Instruments Incorporated
+
+regops2.s PAGE 1
+
+ 1 00000000 02B78008 dcachec r8(r10:m) ; Register form (modified)
+ 2 00000004 029E0004 dcachec 4(r10:m) ; Short Immediate form (positive offset) (modified)
+ 3 00000008 029E7FFC dcachec -4(r10:m) ; Short Immediate form (negative offset) (modified)
+ 4 0000000C 02B79000 dcachec 0x12345678(r10:m) ; Long Immediate form (positive offset) (modified)
+ 00000010 12345678
+ 5 00000014 02B79000 dcachec 0xDEADBEEF(r10:m) ; Long Immediate form (negative offset) (modified)
+ 00000018 DEADBEEF
+ 6 0000001C 0AB78008 dcachef r8(r10:m) ; Register form (modified)
+ 7 00000020 0A9E0004 dcachef 4(r10:m) ; Short Immediate form (positive offset) (modified)
+ 8 00000024 0A9E7FFC dcachef -4(r10:m) ; Short Immediate form (negative offset) (modified)
+ 9 00000028 0AB79000 dcachef 0x12345678(r10:m) ; Long Immediate form (positive offset) (modified)
+ 0000002C 12345678
+ 10 00000030 0AB79000 dcachef 0xDEADBEEF(r10:m) ; Long Immediate form (negative offset) (modified)
+ 00000034 DEADBEEF
+ 11 00000038 41B48404 dld.b r4(r6:m),r8 ; Register form
+ 12 0000003C 41B4A404 dld.h r4(r6:m),r8 ; Register form
+ 13 00000040 41B4C404 dld r4(r6:m),r8 ; Register form
+ 14 00000044 41B4E404 dld.d r4(r6:m),r8 ; Register form
+ 15 00000048 41B49400 dld.b 0xE0000000(r6:m),r8 ; Long Immediate form
+ 0000004C E0000000
+ 16 00000050 41B4B400 dld.h 0xE0000000(r6:m),r8 ; Long Immediate form
+ 00000054 E0000000
+ 17 00000058 41B4D400 dld 0xE0000000(r6:m),r8 ; Long Immediate form
+ 0000005C E0000000
+ 18 00000060 41B4F400 dld.d 0xE0000000(r6:m),r8 ; Long Immediate form
+ 00000064 E0000000
+ 19 00000068 41B58404 dld.ub r4(r6:m),r8 ; Register form
+ 20 0000006C 41B5A404 dld.uh r4(r6:m),r8 ; Register form
+ 21 00000070 41B59400 dld.ub 0xE0000000(r6:m),r8 ; Long Immediate form
+ 00000074 E0000000
+ 22 00000078 41B5B400 dld.uh 0xE0000000(r6:m),r8 ; Long Immediate form
+ 0000007C E0000000
+ 23 00000080 41B68404 dst.b r4(r6:m),r8 ; Register form
+ 24 00000084 41B6A404 dst.h r4(r6:m),r8 ; Register form
+ 25 00000088 41B6C404 dst r4(r6:m),r8 ; Register form
+ 26 0000008C 41B6E404 dst.d r4(r6:m),r8 ; Register form
+ 27 00000090 41B69400 dst.b 0xE0000000(r6:m),r8 ; Long Immediate form
+ 00000094 E0000000
+ 28 00000098 41B6B400 dst.h 0xE0000000(r6:m),r8 ; Long Immediate form
+ 0000009C E0000000
+ 29 000000A0 41B6D400 dst 0xE0000000(r6:m),r8 ; Long Immediate form
+ 000000A4 E0000000
+ 30 000000A8 41B6F400 dst.d 0xE0000000(r6:m),r8 ; Long Immediate form
+ 000000AC E0000000
+ 31 000000B0 41B48004 ld.b r4(r6:m),r8 ; Register form
+ 32 000000B4 41B4A004 ld.h r4(r6:m),r8 ; Register form
+ 33 000000B8 41B4C004 ld r4(r6:m),r8 ; Register form
+ 34 000000BC 41B4E004 ld.d r4(r6:m),r8 ; Register form
+ 35 000000C0 41927FF0 ld.b -16(r6:m),r8 ; Short Immediate form
+ 36 000000C4 4192FFF0 ld.h -16(r6:m),r8 ; Short Immediate form
+ 37 000000C8 41937FF0 ld -16(r6:m),r8 ; Short Immediate form
+ 38 000000CC 4193FFF0 ld.d -16(r6:m),r8 ; Short Immediate form
+ 39 000000D0 41B49000 ld.b 0xE0000000(r6:m),r8 ; Long Immediate form
+ 000000D4 E0000000
+ 40 000000D8 41B4B000 ld.h 0xE0000000(r6:m),r8 ; Long Immediate form
+ MVP MP Macro Assembler Version 1.13 Wed Feb 26 14:32:14 1997
+Copyright (c) 1993-1995 Texas Instruments Incorporated
+
+regops2.s PAGE 2
+
+ 000000DC E0000000
+ 41 000000E0 41B4D000 ld 0xE0000000(r6:m),r8 ; Long Immediate form
+ 000000E4 E0000000
+ 42 000000E8 41B4F000 ld.d 0xE0000000(r6:m),r8 ; Long Immediate form
+ 000000EC E0000000
+ 43 000000F0 41B58004 ld.ub r4(r6:m),r8 ; Register form
+ 44 000000F4 41B5A004 ld.uh r4(r6:m),r8 ; Register form
+ 45 000000F8 41967FF0 ld.ub -16(r6:m),r8 ; Short Immediate form
+ 46 000000FC 4196FFF0 ld.uh -16(r6:m),r8 ; Short Immediate form
+ 47 00000100 41B59000 ld.ub 0xE0000000(r6:m),r8 ; Long Immediate form
+ 00000104 E0000000
+ 48 00000108 41B5B000 ld.uh 0xE0000000(r6:m),r8 ; Long Immediate form
+ 0000010C E0000000
+ 49 00000110 41B68004 st.b r4(r6:m),r8 ; Register form
+ 50 00000114 41B6A004 st.h r4(r6:m),r8 ; Register form
+ 51 00000118 41B6C004 st r4(r6:m),r8 ; Register form
+ 52 0000011C 41B6E004 st.d r4(r6:m),r8 ; Register form
+ 53 00000120 419A7F00 st.b -256(r6:m),r8 ; Short Immediate form
+ 54 00000124 419AFF00 st.h -256(r6:m),r8 ; Short Immediate form
+ 55 00000128 419B7F00 st -256(r6:m),r8 ; Short Immediate form
+ 56 0000012C 419BFF00 st.d -256(r6:m),r8 ; Short Immediate form
+ 57 00000130 41B69000 st.b 0xE0000000(r6:m),r8 ; Long Immediate form
+ 00000134 E0000000
+ 58 00000138 41B6B000 st.h 0xE0000000(r6:m),r8 ; Long Immediate form
+ 0000013C E0000000
+ 59 00000140 41B6D000 st 0xE0000000(r6:m),r8 ; Long Immediate form
+ 00000144 E0000000
+ 60 00000148 41B6F000 st.d 0xE0000000(r6:m),r8 ; Long Immediate form
+ 0000014C E0000000
+
+ No Errors, No Warnings
diff --git a/gas/testsuite/gas/tic80/regops2.s b/gas/testsuite/gas/tic80/regops2.s
new file mode 100644
index 0000000000..18755b3846
--- /dev/null
+++ b/gas/testsuite/gas/tic80/regops2.s
@@ -0,0 +1,60 @@
+ dcachec r8(r10:m) ; Register form (modified)
+ dcachec 4(r10:m) ; Short Immediate form (positive offset) (modified)
+ dcachec -4(r10:m) ; Short Immediate form (negative offset) (modified)
+ dcachec 0x12345678(r10:m) ; Long Immediate form (positive offset) (modified)
+ dcachec 0xDEADBEEF(r10:m) ; Long Immediate form (negative offset) (modified)
+ dcachef r8(r10:m) ; Register form (modified)
+ dcachef 4(r10:m) ; Short Immediate form (positive offset) (modified)
+ dcachef -4(r10:m) ; Short Immediate form (negative offset) (modified)
+ dcachef 0x12345678(r10:m) ; Long Immediate form (positive offset) (modified)
+ dcachef 0xDEADBEEF(r10:m) ; Long Immediate form (negative offset) (modified)
+ dld.b r4(r6:m),r8 ; Register form
+ dld.h r4(r6:m),r8 ; Register form
+ dld r4(r6:m),r8 ; Register form
+ dld.d r4(r6:m),r8 ; Register form
+ dld.b 0xE0000000(r6:m),r8 ; Long Immediate form
+ dld.h 0xE0000000(r6:m),r8 ; Long Immediate form
+ dld 0xE0000000(r6:m),r8 ; Long Immediate form
+ dld.d 0xE0000000(r6:m),r8 ; Long Immediate form
+ dld.ub r4(r6:m),r8 ; Register form
+ dld.uh r4(r6:m),r8 ; Register form
+ dld.ub 0xE0000000(r6:m),r8 ; Long Immediate form
+ dld.uh 0xE0000000(r6:m),r8 ; Long Immediate form
+ dst.b r4(r6:m),r8 ; Register form
+ dst.h r4(r6:m),r8 ; Register form
+ dst r4(r6:m),r8 ; Register form
+ dst.d r4(r6:m),r8 ; Register form
+ dst.b 0xE0000000(r6:m),r8 ; Long Immediate form
+ dst.h 0xE0000000(r6:m),r8 ; Long Immediate form
+ dst 0xE0000000(r6:m),r8 ; Long Immediate form
+ dst.d 0xE0000000(r6:m),r8 ; Long Immediate form
+ ld.b r4(r6:m),r8 ; Register form
+ ld.h r4(r6:m),r8 ; Register form
+ ld r4(r6:m),r8 ; Register form
+ ld.d r4(r6:m),r8 ; Register form
+ ld.b -16(r6:m),r8 ; Short Immediate form
+ ld.h -16(r6:m),r8 ; Short Immediate form
+ ld -16(r6:m),r8 ; Short Immediate form
+ ld.d -16(r6:m),r8 ; Short Immediate form
+ ld.b 0xE0000000(r6:m),r8 ; Long Immediate form
+ ld.h 0xE0000000(r6:m),r8 ; Long Immediate form
+ ld 0xE0000000(r6:m),r8 ; Long Immediate form
+ ld.d 0xE0000000(r6:m),r8 ; Long Immediate form
+ ld.ub r4(r6:m),r8 ; Register form
+ ld.uh r4(r6:m),r8 ; Register form
+ ld.ub -16(r6:m),r8 ; Short Immediate form
+ ld.uh -16(r6:m),r8 ; Short Immediate form
+ ld.ub 0xE0000000(r6:m),r8 ; Long Immediate form
+ ld.uh 0xE0000000(r6:m),r8 ; Long Immediate form
+ st.b r4(r6:m),r8 ; Register form
+ st.h r4(r6:m),r8 ; Register form
+ st r4(r6:m),r8 ; Register form
+ st.d r4(r6:m),r8 ; Register form
+ st.b -256(r6:m),r8 ; Short Immediate form
+ st.h -256(r6:m),r8 ; Short Immediate form
+ st -256(r6:m),r8 ; Short Immediate form
+ st.d -256(r6:m),r8 ; Short Immediate form
+ st.b 0xE0000000(r6:m),r8 ; Long Immediate form
+ st.h 0xE0000000(r6:m),r8 ; Long Immediate form
+ st 0xE0000000(r6:m),r8 ; Long Immediate form
+ st.d 0xE0000000(r6:m),r8 ; Long Immediate form
diff --git a/gas/testsuite/gas/tic80/regops3.d b/gas/testsuite/gas/tic80/regops3.d
new file mode 100644
index 0000000000..32a3012407
--- /dev/null
+++ b/gas/testsuite/gas/tic80/regops3.d
@@ -0,0 +1,28 @@
+#objdump: -d
+#name: TIc80 register operands with :s modifier
+
+.*: +file format .*tic80.*
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 04 0c b4 41.*
+ 4: 04 2c b4 41.*
+ 8: 04 4c b4 41.*
+ c: 04 6c b4 41.*
+ 10: 04 0c b5 41.*
+ 14: 04 2c b5 41.*
+ 18: 04 0c b6 41.*
+ 1c: 04 2c b6 41.*
+ 20: 04 4c b6 41.*
+ 24: 04 6c b6 41.*
+ 28: 04 08 b4 41.*
+ 2c: 04 28 b4 41.*
+ 30: 04 48 b4 41.*
+ 34: 04 68 b4 41.*
+ 38: 04 08 b5 41.*
+ 3c: 04 28 b5 41.*
+ 40: 04 08 b6 41.*
+ 44: 04 28 b6 41.*
+ 48: 04 48 b6 41.*
+ 4c: 04 68 b6 41.*
diff --git a/gas/testsuite/gas/tic80/regops3.lst b/gas/testsuite/gas/tic80/regops3.lst
new file mode 100644
index 0000000000..d65803f1a6
--- /dev/null
+++ b/gas/testsuite/gas/tic80/regops3.lst
@@ -0,0 +1,27 @@
+MVP MP Macro Assembler Version 1.13 Wed Feb 26 14:32:19 1997
+Copyright (c) 1993-1995 Texas Instruments Incorporated
+
+regops3.s PAGE 1
+
+ 1 00000000 41B40C04 dld.b r4:s(r6),r8 ; Register form
+ 2 00000004 41B42C04 dld.h r4:s(r6),r8 ; Register form
+ 3 00000008 41B44C04 dld r4:s(r6),r8 ; Register form
+ 4 0000000C 41B46C04 dld.d r4:s(r6),r8 ; Register form
+ 5 00000010 41B50C04 dld.ub r4:s(r6),r8 ; Register form
+ 6 00000014 41B52C04 dld.uh r4:s(r6),r8 ; Register form
+ 7 00000018 41B60C04 dst.b r4:s(r6),r8 ; Register form
+ 8 0000001C 41B62C04 dst.h r4:s(r6),r8 ; Register form
+ 9 00000020 41B64C04 dst r4:s(r6),r8 ; Register form
+ 10 00000024 41B66C04 dst.d r4:s(r6),r8 ; Register form
+ 11 00000028 41B40804 ld.b r4:s(r6),r8 ; Register form
+ 12 0000002C 41B42804 ld.h r4:s(r6),r8 ; Register form
+ 13 00000030 41B44804 ld r4:s(r6),r8 ; Register form
+ 14 00000034 41B46804 ld.d r4:s(r6),r8 ; Register form
+ 15 00000038 41B50804 ld.ub r4:s(r6),r8 ; Register form
+ 16 0000003C 41B52804 ld.uh r4:s(r6),r8 ; Register form
+ 17 00000040 41B60804 st.b r4:s(r6),r8 ; Register form
+ 18 00000044 41B62804 st.h r4:s(r6),r8 ; Register form
+ 19 00000048 41B64804 st r4:s(r6),r8 ; Register form
+ 20 0000004C 41B66804 st.d r4:s(r6),r8 ; Register form
+
+ No Errors, No Warnings
diff --git a/gas/testsuite/gas/tic80/regops3.s b/gas/testsuite/gas/tic80/regops3.s
new file mode 100644
index 0000000000..5ed87d5109
--- /dev/null
+++ b/gas/testsuite/gas/tic80/regops3.s
@@ -0,0 +1,20 @@
+ dld.b r4:s(r6),r8 ; Register form
+ dld.h r4:s(r6),r8 ; Register form
+ dld r4:s(r6),r8 ; Register form
+ dld.d r4:s(r6),r8 ; Register form
+ dld.ub r4:s(r6),r8 ; Register form
+ dld.uh r4:s(r6),r8 ; Register form
+ dst.b r4:s(r6),r8 ; Register form
+ dst.h r4:s(r6),r8 ; Register form
+ dst r4:s(r6),r8 ; Register form
+ dst.d r4:s(r6),r8 ; Register form
+ ld.b r4:s(r6),r8 ; Register form
+ ld.h r4:s(r6),r8 ; Register form
+ ld r4:s(r6),r8 ; Register form
+ ld.d r4:s(r6),r8 ; Register form
+ ld.ub r4:s(r6),r8 ; Register form
+ ld.uh r4:s(r6),r8 ; Register form
+ st.b r4:s(r6),r8 ; Register form
+ st.h r4:s(r6),r8 ; Register form
+ st r4:s(r6),r8 ; Register form
+ st.d r4:s(r6),r8 ; Register form
diff --git a/gas/testsuite/gas/tic80/regops4.d b/gas/testsuite/gas/tic80/regops4.d
new file mode 100644
index 0000000000..33607c9692
--- /dev/null
+++ b/gas/testsuite/gas/tic80/regops4.d
@@ -0,0 +1,28 @@
+#objdump: -d
+#name: TIc80 register operands with both :m and :s modifier
+
+.*: +file format .*tic80.*
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 04 8c b4 41.*
+ 4: 04 ac b4 41.*
+ 8: 04 cc b4 41.*
+ c: 04 ec b4 41.*
+ 10: 04 8c b5 41.*
+ 14: 04 ac b5 41.*
+ 18: 04 8c b6 41.*
+ 1c: 04 ac b6 41.*
+ 20: 04 cc b6 41.*
+ 24: 04 ec b6 41.*
+ 28: 04 88 b4 41.*
+ 2c: 04 a8 b4 41.*
+ 30: 04 c8 b4 41.*
+ 34: 04 e8 b4 41.*
+ 38: 04 88 b5 41.*
+ 3c: 04 a8 b5 41.*
+ 40: 04 88 b6 41.*
+ 44: 04 a8 b6 41.*
+ 48: 04 c8 b6 41.*
+ 4c: 04 e8 b6 41.*
diff --git a/gas/testsuite/gas/tic80/regops4.lst b/gas/testsuite/gas/tic80/regops4.lst
new file mode 100644
index 0000000000..3af3c9af49
--- /dev/null
+++ b/gas/testsuite/gas/tic80/regops4.lst
@@ -0,0 +1,27 @@
+MVP MP Macro Assembler Version 1.13 Wed Feb 26 14:32:25 1997
+Copyright (c) 1993-1995 Texas Instruments Incorporated
+
+regops4.s PAGE 1
+
+ 1 00000000 41B48C04 dld.b r4:s(r6:m),r8 ; Register form
+ 2 00000004 41B4AC04 dld.h r4:s(r6:m),r8 ; Register form
+ 3 00000008 41B4CC04 dld r4:s(r6:m),r8 ; Register form
+ 4 0000000C 41B4EC04 dld.d r4:s(r6:m),r8 ; Register form
+ 5 00000010 41B58C04 dld.ub r4:s(r6:m),r8 ; Register form
+ 6 00000014 41B5AC04 dld.uh r4:s(r6:m),r8 ; Register form
+ 7 00000018 41B68C04 dst.b r4:s(r6:m),r8 ; Register form
+ 8 0000001C 41B6AC04 dst.h r4:s(r6:m),r8 ; Register form
+ 9 00000020 41B6CC04 dst r4:s(r6:m),r8 ; Register form
+ 10 00000024 41B6EC04 dst.d r4:s(r6:m),r8 ; Register form
+ 11 00000028 41B48804 ld.b r4:s(r6:m),r8 ; Register form
+ 12 0000002C 41B4A804 ld.h r4:s(r6:m),r8 ; Register form
+ 13 00000030 41B4C804 ld r4:s(r6:m),r8 ; Register form
+ 14 00000034 41B4E804 ld.d r4:s(r6:m),r8 ; Register form
+ 15 00000038 41B58804 ld.ub r4:s(r6:m),r8 ; Register form
+ 16 0000003C 41B5A804 ld.uh r4:s(r6:m),r8 ; Register form
+ 17 00000040 41B68804 st.b r4:s(r6:m),r8 ; Register form
+ 18 00000044 41B6A804 st.h r4:s(r6:m),r8 ; Register form
+ 19 00000048 41B6C804 st r4:s(r6:m),r8 ; Register form
+ 20 0000004C 41B6E804 st.d r4:s(r6:m),r8 ; Register form
+
+ No Errors, No Warnings
diff --git a/gas/testsuite/gas/tic80/regops4.s b/gas/testsuite/gas/tic80/regops4.s
new file mode 100644
index 0000000000..5ba77e9138
--- /dev/null
+++ b/gas/testsuite/gas/tic80/regops4.s
@@ -0,0 +1,20 @@
+ dld.b r4:s(r6:m),r8 ; Register form
+ dld.h r4:s(r6:m),r8 ; Register form
+ dld r4:s(r6:m),r8 ; Register form
+ dld.d r4:s(r6:m),r8 ; Register form
+ dld.ub r4:s(r6:m),r8 ; Register form
+ dld.uh r4:s(r6:m),r8 ; Register form
+ dst.b r4:s(r6:m),r8 ; Register form
+ dst.h r4:s(r6:m),r8 ; Register form
+ dst r4:s(r6:m),r8 ; Register form
+ dst.d r4:s(r6:m),r8 ; Register form
+ ld.b r4:s(r6:m),r8 ; Register form
+ ld.h r4:s(r6:m),r8 ; Register form
+ ld r4:s(r6:m),r8 ; Register form
+ ld.d r4:s(r6:m),r8 ; Register form
+ ld.ub r4:s(r6:m),r8 ; Register form
+ ld.uh r4:s(r6:m),r8 ; Register form
+ st.b r4:s(r6:m),r8 ; Register form
+ st.h r4:s(r6:m),r8 ; Register form
+ st r4:s(r6:m),r8 ; Register form
+ st.d r4:s(r6:m),r8 ; Register form
diff --git a/gas/testsuite/gas/tic80/relocs1.c b/gas/testsuite/gas/tic80/relocs1.c
new file mode 100644
index 0000000000..6af04b1100
--- /dev/null
+++ b/gas/testsuite/gas/tic80/relocs1.c
@@ -0,0 +1,28 @@
+extern int xfunc (int y);
+
+static int sfunc (int y)
+{
+ xfunc (y);
+}
+
+int gfunc (int y)
+{
+ sfunc (y);
+}
+
+int branches (int y)
+{
+ int z;
+
+ for (z = y; z < y + 10; z++)
+ {
+ if (z & 0x1)
+ {
+ gfunc (z);
+ }
+ else
+ {
+ xfunc (z);
+ }
+ }
+}
diff --git a/gas/testsuite/gas/tic80/relocs1.d b/gas/testsuite/gas/tic80/relocs1.d
new file mode 100644
index 0000000000..14ca6c9b12
--- /dev/null
+++ b/gas/testsuite/gas/tic80/relocs1.d
@@ -0,0 +1,56 @@
+#objdump: -d
+#name: TIc80 simple relocs, global/local funcs & branches (code)
+
+.*: +file format .*tic80.*
+
+Disassembly of section .text:
+
+00000000 <_sfunc>:
+ 0: f0 ff 6c 08.*
+ 4: 0c 00 59 f8.*
+ 8: 00 00 59 10.*
+ c: 00 90 38 f8 00 00 00 00.*
+ 14: 00 00 51 10.*
+ 18: 0c 00 51 f8.*
+ 1c: 1f 80 38 00.*
+ 20: 10 80 6c 08.*
+
+00000024 <_gfunc>:
+ 24: f0 ff 6c 08.*
+ 28: 0c 00 59 f8.*
+ 2c: 00 00 59 10.*
+ 30: 00 90 38 f8 00 00 00 00.*
+ 38: 00 00 51 10.*
+ 3c: 0c 00 51 f8.*
+ 40: 1f 80 38 00.*
+ 44: 10 80 6c 08.*
+
+00000048 <_branches>:
+ 48: f0 ff 6c 08.*
+ 4c: 0c 00 59 f8.*
+ 50: 00 00 59 10.*
+ 54: 00 00 51 10.*
+ 58: 04 00 59 10.*
+ 5c: 00 00 51 10.*
+ 60: 04 00 51 18.*
+ 64: 0a 80 ac 10.*
+ 68: 03 00 ba 10.*
+ 6c: 12 80 a5 30.*
+ 70: 04 00 51 10.*
+ 74: 05 80 a4 f8.*
+ 78: 00 90 38 f8 24 00 00 00.*
+ 80: 04 00 51 10.*
+ 84: 04 80 24 00.*
+ 88: 00 90 38 f8 00 00 00 00.*
+ 90: 04 00 51 10.*
+ 94: 04 00 51 10.*
+ 98: 01 80 ac 10.*
+ 9c: 04 00 59 10.*
+ a0: 00 00 51 18.*
+ a4: 04 00 51 10.*
+ a8: 0a 80 ec 18.*
+ ac: 02 00 fa 10.*
+ b0: f0 ff a5 38.*
+ b4: 0c 00 51 f8.*
+ b8: 1f 80 38 00.*
+ bc: 10 80 6c 08.*
diff --git a/gas/testsuite/gas/tic80/relocs1.lst b/gas/testsuite/gas/tic80/relocs1.lst
new file mode 100644
index 0000000000..9faeb1aab4
--- /dev/null
+++ b/gas/testsuite/gas/tic80/relocs1.lst
@@ -0,0 +1,80 @@
+MVP MP Macro Assembler Version 1.13 Sat Feb 22 13:19:28 1997
+Copyright (c) 1993-1995 Texas Instruments Incorporated
+
+relocs1.s PAGE 1
+
+ 1 ;; This is the hand hacked output of the TI C compiler for a simple
+ 2 ;; test program that contains local/global functions, local/global
+ 3 ;; function calls, and an "if" and "for" statement.
+ 4
+ 5 .global _xfunc
+ 6
+ 7 00000000 _sfunc:
+ 8 00000000 086CFFF0 addu -16,r1,r1
+ 9 00000004 F859000C st 12(r1),r31
+ 10 00000008 10590000 st 0(r1),r2
+ 11 0000000C F8389000 jsr _xfunc(r0),r31
+ 00000010 00000000
+ 12 00000014 10510000 ld 0(r1),r2
+ 13 00000018 F851000C ld 12(r1),r31
+ 14 0000001C 0038801F jsr r31(r0),r0
+ 15 00000020 086C8010 addu 16,r1,r1
+ 16
+ 17 .global _gfunc
+ 18
+ 19 00000024 _gfunc:
+ 20 00000024 086CFFF0 addu -16,r1,r1
+ 21 00000028 F859000C st 12(r1),r31
+ 22 0000002C 10590000 st 0(r1),r2
+ 23 00000030 F8389000 jsr _sfunc(r0),r31
+ 00000034 00000000
+ 24 00000038 10510000 ld 0(r1),r2
+ 25 0000003C F851000C ld 12(r1),r31
+ 26 00000040 0038801F jsr r31(r0),r0
+ 27 00000044 086C8010 addu 16,r1,r1
+ 28
+ 29
+ 30 .global _branches
+ 31
+ 32 00000048 _branches:
+ 33 00000048 086CFFF0 addu -16,r1,r1
+ 34 0000004C F859000C st 12(r1),r31
+ 35 00000050 10590000 st 0(r1),r2
+ 36 00000054 10510000 ld 0(r1),r2
+ 37 00000058 10590004 st 4(r1),r2
+ 38 0000005C 10510000 ld 0(r1),r2
+ 39 00000060 18510004 ld 4(r1),r3
+ 40 00000064 10AC800A addu 10,r2,r2
+ 41 00000068 10BA0003 cmp r3,r2,r2
+ 42 0000006C 30A58012 bbo.a L12,r2,ge.w
+ 43 00000070 L8:
+ 44 00000070 10510004 ld 4(r1),r2
+ 45 00000074 F8A48005 bbz.a L10,r2,0
+ 46 00000078 F8389000 jsr _gfunc(r0),r31
+ 0000007C 00000024
+ 47 00000080 10510004 ld 4(r1),r2
+ 48 00000084 00248004 br.a L11
+ 49 00000088 L10:
+ 50 00000088 F8389000 jsr _xfunc(r0),r31
+ 0000008C 00000000
+ 51 00000090 10510004 ld 4(r1),r2
+ MVP MP Macro Assembler Version 1.13 Sat Feb 22 13:19:28 1997
+Copyright (c) 1993-1995 Texas Instruments Incorporated
+
+relocs1.s PAGE 2
+
+ 52 00000094 L11:
+ 53 00000094 10510004 ld 4(r1),r2
+ 54 00000098 10AC8001 addu 1,r2,r2
+ 55 0000009C 10590004 st 4(r1),r2
+ 56 000000A0 18510000 ld 0(r1),r3
+ 57 000000A4 10510004 ld 4(r1),r2
+ 58 000000A8 18EC800A addu 10,r3,r3
+ 59 000000AC 10FA0002 cmp r2,r3,r2
+ 60 000000B0 38A5FFF0 bbo.a L8,r2,lt.w
+ 61 000000B4 L12:
+ 62 000000B4 F851000C ld 12(r1),r31
+ 63 000000B8 0038801F jsr r31(r0),r0
+ 64 000000BC 086C8010 addu 16,r1,r1
+
+ No Errors, No Warnings
diff --git a/gas/testsuite/gas/tic80/relocs1.s b/gas/testsuite/gas/tic80/relocs1.s
new file mode 100644
index 0000000000..149e3956ed
--- /dev/null
+++ b/gas/testsuite/gas/tic80/relocs1.s
@@ -0,0 +1,66 @@
+;; This is the hand hacked output of the TI C compiler for a simple
+;; test program that contains local/global functions, local/global
+;; function calls, and an "if" and "for" statement.
+
+ .file "relocs1.s"
+
+ .global _xfunc
+
+_sfunc:
+ addu -16,r1,r1
+ st 12(r1),r31
+ st 0(r1),r2
+ jsr _xfunc(r0),r31
+ ld 0(r1),r2
+ ld 12(r1),r31
+ jsr r31(r0),r0
+ addu 16,r1,r1
+
+ .global _gfunc
+
+_gfunc:
+ addu -16,r1,r1
+ st 12(r1),r31
+ st 0(r1),r2
+ jsr _sfunc(r0),r31
+ ld 0(r1),r2
+ ld 12(r1),r31
+ jsr r31(r0),r0
+ addu 16,r1,r1
+
+
+ .global _branches
+
+_branches:
+ addu -16,r1,r1
+ st 12(r1),r31
+ st 0(r1),r2
+ ld 0(r1),r2
+ st 4(r1),r2
+ ld 0(r1),r2
+ ld 4(r1),r3
+ addu 10,r2,r2
+ cmp r3,r2,r2
+ bbo.a L12,r2,ge.w
+L8:
+ ld 4(r1),r2
+ bbz.a L10,r2,0
+ jsr _gfunc(r0),r31
+ ld 4(r1),r2
+ br.a L11
+L10:
+ jsr _xfunc(r0),r31
+ ld 4(r1),r2
+L11:
+ ld 4(r1),r2
+ addu 1,r2,r2
+ st 4(r1),r2
+ ld 0(r1),r3
+ ld 4(r1),r2
+ addu 10,r3,r3
+ cmp r2,r3,r2
+ bbo.a L8,r2,lt.w
+L12:
+ ld 12(r1),r31
+ jsr r31(r0),r0
+ addu 16,r1,r1
diff --git a/gas/testsuite/gas/tic80/relocs1b.d b/gas/testsuite/gas/tic80/relocs1b.d
new file mode 100644
index 0000000000..4eb31611d2
--- /dev/null
+++ b/gas/testsuite/gas/tic80/relocs1b.d
@@ -0,0 +1,12 @@
+#objdump: -r
+#source: relocs1.s
+#name: TIc80 simple relocs, global/local funcs & branches (relocs)
+
+.*: +file format .*tic80.*
+
+RELOCATION RECORDS FOR \[.text\]:
+OFFSET TYPE VALUE
+00000010 32 _xfunc
+00000034 32 .text
+0000007c 32 .text
+0000008c 32 _xfunc
diff --git a/gas/testsuite/gas/tic80/relocs2.c b/gas/testsuite/gas/tic80/relocs2.c
new file mode 100644
index 0000000000..3f1120c21b
--- /dev/null
+++ b/gas/testsuite/gas/tic80/relocs2.c
@@ -0,0 +1,41 @@
+extern char x_char;
+extern short x_short;
+static int x_int;
+extern long x_long;
+extern float x_float;
+extern double x_double;
+extern char *x_char_p;
+
+static char s_char;
+static short s_short;
+static int s_int;
+static long s_long;
+static float s_float;
+static double s_double;
+static char *s_char_p;
+
+char g_char;
+short g_short;
+int g_int;
+long g_long;
+float g_float;
+double g_double;
+char *g_char_p;
+
+main ()
+{
+ x_char = s_char;
+ g_char = x_char;
+ x_short = s_short;
+ g_short = x_short;
+ x_int = s_int;
+ g_int = x_int;
+ x_long = s_long;
+ g_long = x_long;
+ x_float = s_float;
+ g_float = x_float;
+ x_double = s_double;
+ g_double = x_double;
+ x_char_p = s_char_p;
+ g_char_p = x_char_p;
+}
diff --git a/gas/testsuite/gas/tic80/relocs2.d b/gas/testsuite/gas/tic80/relocs2.d
new file mode 100644
index 0000000000..cf3e87ded6
--- /dev/null
+++ b/gas/testsuite/gas/tic80/relocs2.d
@@ -0,0 +1,37 @@
+#objdump: -d
+#name: TIc80 simple relocs, static and global variables (code)
+
+.*: +file format .*tic80.*
+
+Disassembly of section .text:
+
+00000000 <_main>:
+ 0: 00 10 34 10 24 02 00 00.*
+ 8: 00 10 36 10 00 00 00 00.*
+ 10: 00 10 34 10 00 00 00 00.*
+ 18: 00 10 36 10 04 02 00 00.*
+ 20: 00 30 34 10 24 03 00 00.*
+ 28: 00 30 36 10 00 00 00 00.*
+ 30: 00 30 34 10 00 00 00 00.*
+ 38: 00 30 36 10 04 03 00 00.*
+ 40: 00 50 34 10 34 02 00 00.*
+ 48: 00 50 36 10 34 03 00 00.*
+ 50: 00 50 34 10 34 03 00 00.*
+ 58: 00 50 36 10 14 02 00 00.*
+ 60: 00 50 34 10 f4 01 00 00.*
+ 68: 00 50 36 10 00 00 00 00.*
+ 70: 00 50 34 10 00 00 00 00.*
+ 78: 00 50 36 10 f4 00 00 00.*
+ 80: 00 50 34 10 f4 02 00 00.*
+ 88: 00 50 36 10 00 00 00 00.*
+ 90: 00 50 34 10 00 00 00 00.*
+ 98: 00 50 36 10 14 03 00 00.*
+ a0: 00 70 34 10 e4 01 00 00.*
+ a8: 00 70 36 10 00 00 00 00.*
+ b0: 00 70 34 10 00 00 00 00.*
+ b8: 00 70 36 10 e4 02 00 00.*
+ c0: 00 50 34 10 44 03 00 00.*
+ c8: 00 50 36 10 00 00 00 00.*
+ d0: 00 50 34 10 00 00 00 00.*
+ d8: 00 50 36 10 e4 00 00 00.*
+ e0: 1f a0 38 00.*
diff --git a/gas/testsuite/gas/tic80/relocs2.lst b/gas/testsuite/gas/tic80/relocs2.lst
new file mode 100644
index 0000000000..0690a8ce84
--- /dev/null
+++ b/gas/testsuite/gas/tic80/relocs2.lst
@@ -0,0 +1,112 @@
+MVP MP Macro Assembler Version 1.13 Sun Feb 23 12:16:32 1997
+Copyright (c) 1993-1995 Texas Instruments Incorporated
+
+relocs2.s PAGE 1
+
+ 1 ;; This is the hand hacked output of the TI C compiler for a simple
+ 2 ;; test program that contains static, global, and extern data variables.
+ 3
+ 4 .file "relocs2.s"
+ 5 .global _x_char
+ 6 .global _x_short
+ 7 .global _x_long
+ 8 .global _x_float
+ 9 .global _x_double
+ 10 .global _x_char_p
+ 11 .global _g_char
+ 12 .global _g_short
+ 13 .global _g_int
+ 14 .global _g_long
+ 15 .global _g_float
+ 16 .global _g_double
+ 17 .global _g_char_p
+ 18 .global _main
+ 19
+ 20 00000000 _main:
+ 21 00000000 10341000 ld.b _s_char+0(r0),r2
+ 00000004 0000001C
+ 22 00000008 10361000 st.b _x_char+0(r0),r2
+ 0000000C 00000000
+ 23 00000010 10341000 ld.b _x_char+0(r0),r2
+ 00000014 00000000
+ 24 00000018 10361000 st.b _g_char+0(r0),r2
+ 0000001C 00000014
+ 25 00000020 10343000 ld.h _s_short+0(r0),r2
+ 00000024 0000003C
+ 26 00000028 10363000 st.h _x_short+0(r0),r2
+ 0000002C 00000000
+ 27 00000030 10343000 ld.h _x_short+0(r0),r2
+ 00000034 00000000
+ 28 00000038 10363000 st.h _g_short+0(r0),r2
+ 0000003C 00000034
+ 29 00000040 10345000 ld _s_int+0(r0),r2
+ 00000044 00000020
+ 30 00000048 10365000 st _x_int+0(r0),r2
+ 0000004C 00000040
+ 31 00000050 10345000 ld _x_int+0(r0),r2
+ 00000054 00000040
+ 32 00000058 10365000 st _g_int+0(r0),r2
+ 0000005C 00000018
+ 33 00000060 10345000 ld _s_long+0(r0),r2
+ 00000064 00000010
+ 34 00000068 10365000 st _x_long+0(r0),r2
+ 0000006C 00000000
+ 35 00000070 10345000 ld _x_long+0(r0),r2
+ 00000074 00000000
+ 36 00000078 10365000 st _g_long+0(r0),r2
+ 0000007C 00000004
+ 37 00000080 10345000 ld _s_float+0(r0),r2
+ 00000084 00000030
+ 38 00000088 10365000 st _x_float+0(r0),r2
+ MVP MP Macro Assembler Version 1.13 Sun Feb 23 12:16:32 1997
+Copyright (c) 1993-1995 Texas Instruments Incorporated
+
+relocs2.s PAGE 2
+
+ 0000008C 00000000
+ 39 00000090 10345000 ld _x_float+0(r0),r2
+ 00000094 00000000
+ 40 00000098 10365000 st _g_float+0(r0),r2
+ 0000009C 00000038
+ 41 000000A0 10347000 ld.d _s_double+0(r0),r2
+ 000000A4 00000008
+ 42 000000A8 10367000 st.d _x_double+0(r0),r2
+ 000000AC 00000000
+ 43 000000B0 10347000 ld.d _x_double+0(r0),r2
+ 000000B4 00000000
+ 44 000000B8 10367000 st.d _g_double+0(r0),r2
+ 000000BC 00000028
+ 45 000000C0 10345000 ld _s_char_p+0(r0),r2
+ 000000C4 00000044
+ 46 000000C8 10365000 st _x_char_p+0(r0),r2
+ 000000CC 00000000
+ 47 000000D0 10345000 ld _x_char_p+0(r0),r2
+ 000000D4 00000000
+ 48 000000D8 10365000 st _g_char_p+0(r0),r2
+ 000000DC 00000000
+ 49 000000E0 0038A01F jsr.a r31(r0),r0
+ 50
+ 51 .global _g_char_p
+ 52 00000000 .bss _g_char_p,4,4
+ 53 .global _g_long
+ 54 00000004 .bss _g_long,4,4
+ 55 00000008 .bss _s_double,8,8
+ 56 00000010 .bss _s_long,4,4
+ 57 .global _g_char
+ 58 00000014 .bss _g_char,1,4
+ 59 .global _g_int
+ 60 00000018 .bss _g_int,4,4
+ 61 0000001C .bss _s_char,1,4
+ 62 00000020 .bss _s_int,4,4
+ 63 .global _g_double
+ 64 00000028 .bss _g_double,8,8
+ 65 00000030 .bss _s_float,4,4
+ 66 .global _g_short
+ 67 00000034 .bss _g_short,2,4
+ 68 .global _g_float
+ 69 00000038 .bss _g_float,4,4
+ 70 0000003C .bss _s_short,2,4
+ 71 00000040 .bss _x_int,4,4
+ 72 00000044 .bss _s_char_p,4,4
+
+ No Errors, No Warnings
diff --git a/gas/testsuite/gas/tic80/relocs2.s b/gas/testsuite/gas/tic80/relocs2.s
new file mode 100644
index 0000000000..e4257df865
--- /dev/null
+++ b/gas/testsuite/gas/tic80/relocs2.s
@@ -0,0 +1,72 @@
+;; This is the hand hacked output of the TI C compiler for a simple
+;; test program that contains static, global, and extern data variables.
+
+ .file "relocs2.s"
+ .global _x_char
+ .global _x_short
+ .global _x_long
+ .global _x_float
+ .global _x_double
+ .global _x_char_p
+ .global _g_char
+ .global _g_short
+ .global _g_int
+ .global _g_long
+ .global _g_float
+ .global _g_double
+ .global _g_char_p
+ .global _main
+
+_main:
+ ld.b _s_char+0(r0),r2
+ st.b _x_char+0(r0),r2
+ ld.b _x_char+0(r0),r2
+ st.b _g_char+0(r0),r2
+ ld.h _s_short+0(r0),r2
+ st.h _x_short+0(r0),r2
+ ld.h _x_short+0(r0),r2
+ st.h _g_short+0(r0),r2
+ ld _s_int+0(r0),r2
+ st _x_int+0(r0),r2
+ ld _x_int+0(r0),r2
+ st _g_int+0(r0),r2
+ ld _s_long+0(r0),r2
+ st _x_long+0(r0),r2
+ ld _x_long+0(r0),r2
+ st _g_long+0(r0),r2
+ ld _s_float+0(r0),r2
+ st _x_float+0(r0),r2
+ ld _x_float+0(r0),r2
+ st _g_float+0(r0),r2
+ ld.d _s_double+0(r0),r2
+ st.d _x_double+0(r0),r2
+ ld.d _x_double+0(r0),r2
+ st.d _g_double+0(r0),r2
+ ld _s_char_p+0(r0),r2
+ st _x_char_p+0(r0),r2
+ ld _x_char_p+0(r0),r2
+ st _g_char_p+0(r0),r2
+ jsr.a r31(r0),r0
+
+ .global _g_char_p
+ .bss _g_char_p,4,4
+ .global _g_long
+ .bss _g_long,4,4
+ .bss _s_double,8,8
+ .bss _s_long,4,4
+ .global _g_char
+ .bss _g_char,1,4
+ .global _g_int
+ .bss _g_int,4,4
+ .bss _s_char,1,4
+ .bss _s_int,4,4
+ .global _g_double
+ .bss _g_double,8,8
+ .bss _s_float,4,4
+ .global _g_short
+ .bss _g_short,2,4
+ .global _g_float
+ .bss _g_float,4,4
+ .bss _s_short,2,4
+ .bss _x_int,4,4
+ .bss _s_char_p,4,4
diff --git a/gas/testsuite/gas/tic80/relocs2b.d b/gas/testsuite/gas/tic80/relocs2b.d
new file mode 100644
index 0000000000..604f99d90a
--- /dev/null
+++ b/gas/testsuite/gas/tic80/relocs2b.d
@@ -0,0 +1,38 @@
+#objdump: -r
+#source: relocs2.s
+#name: TIc80 simple relocs, static and global variables (relocs)
+
+.*: +file format .*tic80.*
+
+RELOCATION RECORDS FOR \[.text\]:
+OFFSET TYPE VALUE
+00000004 32 .bss\+0xffffff1c
+0000000c 32 _x_char
+00000014 32 _x_char
+0000001c 32 .bss\+0xffffff1c
+00000024 32 .bss\+0xffffff1c
+0000002c 32 _x_short
+00000034 32 _x_short
+0000003c 32 .bss\+0xffffff1c
+00000044 32 .bss\+0xffffff1c
+0000004c 32 .bss\+0xffffff1c
+00000054 32 .bss\+0xffffff1c
+0000005c 32 .bss\+0xffffff1c
+00000064 32 .bss\+0xffffff1c
+0000006c 32 _x_long
+00000074 32 _x_long
+0000007c 32 .bss\+0xffffff1c
+00000084 32 .bss\+0xffffff1c
+0000008c 32 _x_float
+00000094 32 _x_float
+0000009c 32 .bss\+0xffffff1c
+000000a4 32 .bss\+0xffffff1c
+000000ac 32 _x_double
+000000b4 32 _x_double
+000000bc 32 .bss\+0xffffff1c
+000000c4 32 .bss\+0xffffff1c
+000000cc 32 _x_char_p
+000000d4 32 _x_char_p
+000000dc 32 .bss\+0xffffff1c
+
+
diff --git a/gas/testsuite/gas/tic80/tic80.exp b/gas/testsuite/gas/tic80/tic80.exp
new file mode 100644
index 0000000000..49c4633996
--- /dev/null
+++ b/gas/testsuite/gas/tic80/tic80.exp
@@ -0,0 +1,21 @@
+#
+# TI TMS320C80 tests.
+#
+if [istarget tic80*-*-*] then {
+
+ run_dump_test "regops"
+ run_dump_test "regops2"
+ run_dump_test "regops3"
+ run_dump_test "regops4"
+ run_dump_test "cregops"
+ run_dump_test "float"
+ run_dump_test "endmask"
+ run_dump_test "bitnum"
+ run_dump_test "ccode"
+ run_dump_test "add"
+ run_dump_test "relocs1"
+ run_dump_test "relocs1b"
+ run_dump_test "relocs2"
+ run_dump_test "relocs2b"
+ run_dump_test "align"
+}
diff --git a/gas/testsuite/gas/v850/arith.s b/gas/testsuite/gas/v850/arith.s
new file mode 100644
index 0000000000..e72140fff1
--- /dev/null
+++ b/gas/testsuite/gas/v850/arith.s
@@ -0,0 +1,24 @@
+
+ .text
+ .global arith_opcodes
+arith_opcodes:
+ add r5,r6
+ add 5,r6
+ addi 7,r5,r6
+ divh r5,r6
+ mulh r5,r6
+ mulh 5,r6
+ mulhi 7,r5,r6
+ sar r5,r6
+ sar 31,r6
+ satadd r5,r6
+ satadd 5,r6
+ satsub r5,r6
+ satsubi 7,r5,r6
+ satsubr r5,r6
+ shl r5,r6
+ shl 31,r6
+ shr r5,r6
+ shr 31,r6
+ sub r5,r6
+ subr r5,r6
diff --git a/gas/testsuite/gas/v850/basic.exp b/gas/testsuite/gas/v850/basic.exp
new file mode 100644
index 0000000000..c06a631576
--- /dev/null
+++ b/gas/testsuite/gas/v850/basic.exp
@@ -0,0 +1,438 @@
+# Copyright (C) 1996 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, 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 more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Please email any bugs, comments, and/or additions to this file to:
+# DejaGnu@cygnus.com
+
+# Written by Cygnus Support.
+
+proc do_arith {} {
+ set testname "arith.s: Arithmetic operations"
+ set x 0
+
+ gas_start "arith.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ # -re "^ +\[0-9\]+ 0000 489A0000\[^\n\]*\n" { set x [expr $x+1] }
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 C531\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 4532\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 05360700\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 4530\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000a E530\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c E532\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000e E5360700\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0012 E537A000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0016 BF32\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 C530\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001a 2532\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c A530\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001e 65360700\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0022 8530\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 E537C000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 DF32\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002a E5378000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002e 9F32\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 A531\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0032 8531\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==20] then { pass $testname } else { fail $testname }
+}
+
+proc do_bit {} {
+ set testname "bit.s: bit operations"
+ set x 0
+
+ gas_start "bit.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 C6AF1000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 C66F1000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 C62F1000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c C6EF1000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==4] then { pass $testname } else { fail $testname }
+}
+
+proc do_branch {} {
+ set testname "branch.s: branch operations"
+ set x 0
+
+ gas_start "branch.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 8F05\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 FEFD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 E6FD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0006 D7FD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 CBFD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000a B9FD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c A1FD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000e 93FD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 82FD\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0012 FAF5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 E0F5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0016 D8F5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 C4F5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001a BCF5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c A1F5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001e 99F5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 82F5\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0022 FAED\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 E5ED\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0026 DDED\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==20] then { pass $testname } else { fail $testname }
+}
+
+proc do_compare {} {
+ set testname "compare.s: compare operations"
+ set x 0
+
+ gas_start "compare.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 E531\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 6532\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 E02F0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 E82F0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c E12F0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 E12F0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0014 E92F0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 E92F0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c E22F0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 EA2F0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0024 E32F0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0028 EB2F0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 002c E42F0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 E42F0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 EC2F0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0038 EC2F0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 003c E52F0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 ED2F0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 E62F0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0048 EE2F0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 004c E72F0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0050 EF2F0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0054 6531\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==23] then { pass $testname } else { fail $testname }
+}
+
+proc do_jumps {} {
+ set testname "jumps.s: jumps operations"
+ set x 0
+
+ gas_start "jumps.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 802F0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 6500\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0006 BF07FAFF\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==3] then { pass $testname } else { fail $testname }
+}
+
+proc do_logical {} {
+ set testname "logical.s: logical operations"
+ set x 0
+
+ gas_start "logical.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 4531\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 C5360700\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0006 2530\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 0531\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000a 85360700\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000e 2531\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 A5360700\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==7] then { pass $testname } else { fail $testname }
+}
+
+proc do_mem {} {
+ set testname "mem.s: memory operations"
+ set x 0
+
+ gas_start "mem.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 05370500\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 25370400\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 25370500\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 4033\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000e 4034\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0010 4035\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0012 462F0500\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0016 662F0400\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001a 662F0500\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001e C033\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0020 C034\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0022 4135\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==12] then { pass $testname } else { fail $testname }
+}
+
+proc do_misc {} {
+ set testname "misc.s: misc operations"
+ set x 0
+
+ gas_start "misc.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 E0076001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 E0876001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 E0072001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000e E0074001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0012 E0070001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0016 FF070001\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001a E72F2000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001e E53F4000\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==9] then { pass $testname } else { fail $testname }
+}
+
+proc do_move {} {
+ set testname "move.s: move operations"
+ set x 0
+
+ gas_start "move.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 0530\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0002 0532\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 25360700\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 45360700\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==4] then { pass $testname } else { fail $testname }
+}
+
+proc do_hilo {} {
+ set testname "hilo.s: hilo tests"
+ set x 0
+
+ gas_start "hilo.s" "-al"
+
+ # Instead of having a variable for each match string just increment the
+ # total number of matches seen. That's simpler when testing large numbers
+ # of instructions (as these tests to).
+ while 1 {
+ expect {
+ -re "^ +\[0-9\]+ 0000 200EEFBE\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0004 410EAEDE\[^\n\]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 410EADDE\[^\n\]*\n" { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==3] then { pass $testname } else { fail $testname }
+}
+
+
+proc do_simple_reloc_tests {} {
+ set testname "reloc.s: Test for proper relocations (part 2)"
+ set x 0
+
+ if [gas_test_old "reloc.s" "" "Test for proper relocation (part 1)"] then {
+ objdump_start_no_subdir "a.out" "-r"
+
+ while 1 {
+ expect {
+ -re "^00000002\[^\n\]*R_V850_LO16\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^00000006\[^\n\]*R_V850_HI16_S\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^0000000a\[^\n\]*R_V850_HI16\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^0000000e\[^\n\]*R_V850_ZDA_16_16_OFFSET\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^00000012\[^\n\]*R_V850_TDA_16_16_OFFSET\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "^00000016\[^\n\]*R_V850_SDA_16_16_OFFSET\[^\n\]*\n"
+ { set x [expr $x+1] }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ objdump_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x==6] then { pass $testname } else { fail $testname }
+}
+
+if [istarget v850*-*-*] then {
+ # Test the basic instruction parser.
+ do_arith
+ do_bit
+ do_branch
+ do_compare
+ do_jumps
+ do_logical
+ do_mem
+ do_misc
+ do_move
+
+ # Make sure we handle lo() hi() and hi0() correctly.
+ do_hilo
+
+ # Check for proper relocs on lo, hi, hi0, zdaoff, tdaoff and sdaoff
+ # expressions
+ do_simple_reloc_tests
+
+ gas_test "hilo2.s" "" "" "hi/lo regression test"
+ gas_test "fepsw.s" "" "" "eqsw regression test"
+
+ gas_test_error "range.s" "-mwarn-signed-overflow" "Check for range error on byte load/store"
+}
diff --git a/gas/testsuite/gas/v850/bit.s b/gas/testsuite/gas/v850/bit.s
new file mode 100644
index 0000000000..aa1ac05d0e
--- /dev/null
+++ b/gas/testsuite/gas/v850/bit.s
@@ -0,0 +1,8 @@
+
+ .text
+ .global bit
+bit:
+ clr1 5,16[r6]
+ not1 5,16[r6]
+ set1 5,16[r6]
+ tst1 5,16[r6]
diff --git a/gas/testsuite/gas/v850/branch.s b/gas/testsuite/gas/v850/branch.s
new file mode 100644
index 0000000000..a1c1b42804
--- /dev/null
+++ b/gas/testsuite/gas/v850/branch.s
@@ -0,0 +1,24 @@
+
+ .text
+ .global bcc
+bcc:
+ bgt bcc
+ bge bcc
+ blt bcc
+ ble bcc
+ bh bcc
+ bnl bcc
+ bl bcc
+ bnh bcc
+ be bcc
+ bne bcc
+ bv bcc
+ bnv bcc
+ bn bcc
+ bp bcc
+ bc bcc
+ bnc bcc
+ bz bcc
+ bnz bcc
+ br bcc
+ bsa bcc
diff --git a/gas/testsuite/gas/v850/compare.s b/gas/testsuite/gas/v850/compare.s
new file mode 100644
index 0000000000..d41c8a84de
--- /dev/null
+++ b/gas/testsuite/gas/v850/compare.s
@@ -0,0 +1,28 @@
+
+ .text
+ .global compare
+compare:
+ cmp r5,r6
+ cmp 5,r6
+ setf v,r5
+ setf nv,r5
+ setf c,r5
+ setf l,r5
+ setf nc,r5
+ setf nl,r5
+ setf z,r5
+ setf nz,r5
+ setf nh,r5
+ setf h,r5
+ setf s,r5
+ setf n,r5
+ setf ns,r5
+ setf p,r5
+ setf t,r5
+ setf sa,r5
+ setf lt,r5
+ setf ge,r5
+ setf le,r5
+ setf gt,r5
+ tst r5,r6
+
diff --git a/gas/testsuite/gas/v850/fepsw.s b/gas/testsuite/gas/v850/fepsw.s
new file mode 100644
index 0000000000..e20333cb2b
--- /dev/null
+++ b/gas/testsuite/gas/v850/fepsw.s
@@ -0,0 +1,2 @@
+ .text
+ ldsr r17,fepsw
diff --git a/gas/testsuite/gas/v850/hilo.s b/gas/testsuite/gas/v850/hilo.s
new file mode 100644
index 0000000000..5067e56de5
--- /dev/null
+++ b/gas/testsuite/gas/v850/hilo.s
@@ -0,0 +1,5 @@
+
+ .text
+ movea lo(0xdeadbeef),r0,r1
+ movhi hi(0xdeadbeef),r1,r1
+ movhi hi0(0xdeadbeef),r1,r1
diff --git a/gas/testsuite/gas/v850/hilo2.s b/gas/testsuite/gas/v850/hilo2.s
new file mode 100644
index 0000000000..661d59347b
--- /dev/null
+++ b/gas/testsuite/gas/v850/hilo2.s
@@ -0,0 +1,4 @@
+ .text
+ .org 0x10000
+ movea hi(blah),r0,r1
+blah:
diff --git a/gas/testsuite/gas/v850/jumps.s b/gas/testsuite/gas/v850/jumps.s
new file mode 100644
index 0000000000..173164b7fb
--- /dev/null
+++ b/gas/testsuite/gas/v850/jumps.s
@@ -0,0 +1,8 @@
+
+ .text
+ .global jumps
+jumps:
+ jarl jumps,r5
+ jmp [r5]
+ jr jumps
+
diff --git a/gas/testsuite/gas/v850/logical.s b/gas/testsuite/gas/v850/logical.s
new file mode 100644
index 0000000000..ab00b3bcb0
--- /dev/null
+++ b/gas/testsuite/gas/v850/logical.s
@@ -0,0 +1,11 @@
+
+ .text
+ .global logicals
+logicals:
+ and r5,r6
+ andi 7,r5,r6
+ not r5,r6
+ or r5,r6
+ ori 7,r5,r6
+ xor r5,r6
+ xori 7,r5,r6
diff --git a/gas/testsuite/gas/v850/mem.s b/gas/testsuite/gas/v850/mem.s
new file mode 100644
index 0000000000..9c69cea278
--- /dev/null
+++ b/gas/testsuite/gas/v850/mem.s
@@ -0,0 +1,16 @@
+
+ .text
+ .global memory
+memory:
+ ld.b 5[r5],r6
+ ld.h 4[r5],r6
+ ld.w 4[r5],r6
+ sld.b 64[ep],r6
+ sld.h 128[ep],r6
+ sld.w 128[ep],r6
+ st.b r5,5[r6]
+ st.h r5,4[r6]
+ st.w r5,4[r6]
+ sst.b r6,64[ep]
+ sst.h r6,128[ep]
+ sst.w r6,128[ep]
diff --git a/gas/testsuite/gas/v850/misc.s b/gas/testsuite/gas/v850/misc.s
new file mode 100644
index 0000000000..52c4e4bbe4
--- /dev/null
+++ b/gas/testsuite/gas/v850/misc.s
@@ -0,0 +1,13 @@
+
+ .text
+ .global misc
+misc:
+ di
+ ei
+ halt
+ nop
+ reti
+ trap 0
+ trap 31
+ ldsr r7,psw
+ stsr psw,r7
diff --git a/gas/testsuite/gas/v850/move.s b/gas/testsuite/gas/v850/move.s
new file mode 100644
index 0000000000..cba6fae970
--- /dev/null
+++ b/gas/testsuite/gas/v850/move.s
@@ -0,0 +1,8 @@
+
+ .text
+ .global move
+move:
+ mov r5,r6
+ mov 5,r6
+ movea 7,r5,r6
+ movhi 7,r5,r6
diff --git a/gas/testsuite/gas/v850/range.s b/gas/testsuite/gas/v850/range.s
new file mode 100644
index 0000000000..42accf4779
--- /dev/null
+++ b/gas/testsuite/gas/v850/range.s
@@ -0,0 +1,2 @@
+ .text
+ ld.b 0xff62[r0],r0
diff --git a/gas/testsuite/gas/v850/reloc.s b/gas/testsuite/gas/v850/reloc.s
new file mode 100644
index 0000000000..6738d26dd9
--- /dev/null
+++ b/gas/testsuite/gas/v850/reloc.s
@@ -0,0 +1,7 @@
+ .text
+ movea lo(foo),r0,r1
+ movhi hi(foo),r1,r1
+ movhi hi0(foo),r1,r1
+ movea zdaoff(_foo),r0,r1
+ movhi tdaoff(_foo),ep,r1
+ movhi sdaoff(_foo),gp,r1
diff --git a/gas/testsuite/gas/vax/quad.exp b/gas/testsuite/gas/vax/quad.exp
new file mode 100644
index 0000000000..34770c5b6c
--- /dev/null
+++ b/gas/testsuite/gas/vax/quad.exp
@@ -0,0 +1,23 @@
+proc do_quad {} {
+ set testname "quad.s: quadword immediate values"
+ set x1 0
+ set x2 0
+ set x3 0
+ gas_start "quad.s" "-al"
+ while 1 {
+ expect {
+ -re "^ +2\[ \t\]+0000+ 7D8F7856\[ \t\]+movq\[^\n\]*\n" { set x1 1 }
+ -re "^ +2\[ \t\]+3412DDCC\[^\n\]*\n" { set x2 1 }
+ -re "^ +2\[ \t\]+BBAA5001\[ \t\]*\r\n" { set x3 1 }
+ -re "\[^\n\]*\n" { }
+ timeout { perror "timeout\n"; break }
+ eof { break }
+ }
+ }
+ gas_finish
+ if [all_ones $x1 $x2 $x3] then { pass $testname } else { fail $testname }
+}
+
+if [istarget vax-*-*] then {
+ do_quad
+}
diff --git a/gas/testsuite/gas/vax/quad.s b/gas/testsuite/gas/vax/quad.s
new file mode 100644
index 0000000000..78ad4ad0fc
--- /dev/null
+++ b/gas/testsuite/gas/vax/quad.s
@@ -0,0 +1,2 @@
+ .text
+ movq $0xaabbccdd12345678,r0
diff --git a/gas/testsuite/gas/vtable/entry0.d b/gas/testsuite/gas/vtable/entry0.d
new file mode 100644
index 0000000000..ee0bb99027
--- /dev/null
+++ b/gas/testsuite/gas/vtable/entry0.d
@@ -0,0 +1,10 @@
+#objdump: -r
+#name: vtable entry0
+
+.*: +file format .*
+
+RELOCATION RECORDS FOR \[.text\]:
+OFFSET +TYPE +VALUE
+0+0000010 R_.*_GNU_VTENTRY vtbl_a
+
+
diff --git a/gas/testsuite/gas/vtable/entry0.s b/gas/testsuite/gas/vtable/entry0.s
new file mode 100644
index 0000000000..36f89e3894
--- /dev/null
+++ b/gas/testsuite/gas/vtable/entry0.s
@@ -0,0 +1,2 @@
+.text
+.vtable_entry vtbl_a, 16
diff --git a/gas/testsuite/gas/vtable/entry1.d b/gas/testsuite/gas/vtable/entry1.d
new file mode 100644
index 0000000000..7fa6e4b743
--- /dev/null
+++ b/gas/testsuite/gas/vtable/entry1.d
@@ -0,0 +1,10 @@
+#objdump: -r
+#name: vtable entry1
+
+.*: +file format .*
+
+RELOCATION RECORDS FOR \[.text\]:
+OFFSET +TYPE +VALUE
+0+0000000 R_.*_GNU_VTENTRY vtbl_a.*
+
+
diff --git a/gas/testsuite/gas/vtable/entry1.s b/gas/testsuite/gas/vtable/entry1.s
new file mode 100644
index 0000000000..36f89e3894
--- /dev/null
+++ b/gas/testsuite/gas/vtable/entry1.s
@@ -0,0 +1,2 @@
+.text
+.vtable_entry vtbl_a, 16
diff --git a/gas/testsuite/gas/vtable/inherit0.d b/gas/testsuite/gas/vtable/inherit0.d
new file mode 100644
index 0000000000..62795b1ac1
--- /dev/null
+++ b/gas/testsuite/gas/vtable/inherit0.d
@@ -0,0 +1,10 @@
+#objdump: -r
+#name: vtable inherit0
+
+.*: +file format .*
+
+RELOCATION RECORDS FOR \[.data\]:
+OFFSET +TYPE +VALUE
+0+0000000 R_.*_GNU_VTINHERIT \*ABS\*
+0+0000010 R_.*_GNU_VTINHERIT vtbl_a
+
diff --git a/gas/testsuite/gas/vtable/inherit0.s b/gas/testsuite/gas/vtable/inherit0.s
new file mode 100644
index 0000000000..d438df6954
--- /dev/null
+++ b/gas/testsuite/gas/vtable/inherit0.s
@@ -0,0 +1,13 @@
+.data
+
+.type vtbl_a,object
+vtbl_a:
+ .space 16
+.size vtbl_a,16
+.vtable_inherit vtbl_a, 0
+
+.type vtbl_b,object
+vtbl_b:
+ .space 16
+.size vtbl_b,16
+.vtable_inherit vtbl_b, vtbl_a
diff --git a/gas/testsuite/gas/vtable/inherit1.l b/gas/testsuite/gas/vtable/inherit1.l
new file mode 100644
index 0000000000..bdd6358345
--- /dev/null
+++ b/gas/testsuite/gas/vtable/inherit1.l
@@ -0,0 +1,6 @@
+.*: Assembler messages:
+.*:1: Error: expected `vtbl_a' to have already been set for .vtable_inherit
+.*GAS.*
+
+
+ +1.*vtable_inherit vtbl_a, 0
diff --git a/gas/testsuite/gas/vtable/inherit1.s b/gas/testsuite/gas/vtable/inherit1.s
new file mode 100644
index 0000000000..7dd1d2877b
--- /dev/null
+++ b/gas/testsuite/gas/vtable/inherit1.s
@@ -0,0 +1 @@
+.vtable_inherit vtbl_a, 0
diff --git a/gas/testsuite/gas/vtable/vtable.exp b/gas/testsuite/gas/vtable/vtable.exp
new file mode 100644
index 0000000000..5d14451524
--- /dev/null
+++ b/gas/testsuite/gas/vtable/vtable.exp
@@ -0,0 +1,39 @@
+#
+# vtable tests
+#
+proc run_list_test { name opts } {
+ global srcdir subdir
+ set testname "vtable $name"
+ set file $srcdir/$subdir/$name
+ gas_run ${name}.s $opts ">&dump.out"
+ if { [regexp_diff "dump.out" "${file}.l"] } then {
+ fail $testname
+ verbose "output is [file_contents "dump.out"]" 2
+ return
+ }
+ pass $testname
+}
+
+# Vtable bits are only supported by ELF targets.
+if {[istarget "*-*-elf*"] || [istarget "*-*-linux*"]} then {
+
+
+ # not supported by D30V
+ if {[istarget "d30v-*-*"]} {
+ return
+ }
+
+ run_dump_test "inherit0"
+ run_list_test "inherit1" "-al"
+
+ # The vtable entry results are different on Rel and Rela targets.
+ if {[istarget "i*86-*-*"] || [istarget "mips*-*-*"]} then {
+
+ run_dump_test "entry0"
+
+ } else {
+
+ run_dump_test "entry1"
+
+ }
+}
diff --git a/gas/testsuite/gasp/INC1.H b/gas/testsuite/gasp/INC1.H
new file mode 100644
index 0000000000..0d3732310f
--- /dev/null
+++ b/gas/testsuite/gasp/INC1.H
@@ -0,0 +1,3 @@
+FILE 1 FIRST LINE
+ .INCLUDE "INC2.H"
+FILE 1 LAST LINE
diff --git a/gas/testsuite/gasp/INC2.H b/gas/testsuite/gasp/INC2.H
new file mode 100644
index 0000000000..083c3dce2c
--- /dev/null
+++ b/gas/testsuite/gasp/INC2.H
@@ -0,0 +1,2 @@
+ FILE 2 FIRST LINE
+ FILE 2 LAST LINE
diff --git a/gas/testsuite/gasp/assign.asm b/gas/testsuite/gasp/assign.asm
new file mode 100644
index 0000000000..7f66718468
--- /dev/null
+++ b/gas/testsuite/gasp/assign.asm
@@ -0,0 +1,13 @@
+
+foo: .ASSIGNC "hello"
+BAR: .ASSIGNA 12+34
+
+ \&foo'foo
+ \&foo\&foo\&foo
+ \&foo \&foo \&foo
+ \&BAR\&bar\&BAR
+
+
+
+
+ .END
diff --git a/gas/testsuite/gasp/assign.err b/gas/testsuite/gasp/assign.err
new file mode 100644
index 0000000000..fe3733f7ea
--- /dev/null
+++ b/gas/testsuite/gasp/assign.err
@@ -0,0 +1 @@
+assign.asm:8 Can't find preprocessor variable bar.
diff --git a/gas/testsuite/gasp/assign.out b/gas/testsuite/gasp/assign.out
new file mode 100644
index 0000000000..85509ae614
--- /dev/null
+++ b/gas/testsuite/gasp/assign.out
@@ -0,0 +1,22 @@
+!
+
+!foo: .ASSIGNC "hello"
+!BAR: .ASSIGNA 12+34
+!
+
+! \&foo'foo
+ hellofoo
+! \&foo\&foo\&foo
+ hellohellohello
+! \&foo \&foo \&foo
+ hello hello hello
+! \&BAR\&bar\&BAR
+ 4646
+!
+
+!
+
+!
+
+!
+! .END
diff --git a/gas/testsuite/gasp/condass.asm b/gas/testsuite/gasp/condass.asm
new file mode 100644
index 0000000000..2bd9f0732f
--- /dev/null
+++ b/gas/testsuite/gasp/condass.asm
@@ -0,0 +1,129 @@
+ .AIF 1 EQ 1
+ OK
+ .AELSE
+ BAD
+ .AENDI
+ .AIF 1 EQ 2
+ BAD
+ .AELSE
+ OK
+ .AENDI
+ .AIF 1 EQ 2
+ BAD
+ .AELSE
+ OK
+ .AIF 1 EQ 2
+ BAD
+ .AELSE
+ OK
+ .AENDI
+ .AENDI
+ .AIF 1 LT 2
+ OK
+ .AENDI
+ .AIF 1 EQ 2
+ BAD
+ .AENDI
+ .AIF 1 NE 2
+ OK
+ .AENDI
+ .AIF 1 LE 2
+ OK
+ .AENDI
+ .AIF 1 GT 2
+ BAD
+ .AENDI
+ .AIF 3 GE 2
+ OK
+ .AENDI
+ .AIF 3 LT 2
+ BAD
+ .AENDI
+ .AIF 3 EQ 2
+ BAD
+ .AENDI
+ .AIF 3 NE 2
+ OK
+ .AENDI
+ .AIF 3 LE 2
+ BAD
+ .AENDI
+ .AIF 3 GT 2
+ OK
+ .AENDI
+ .AIF 3 GE 2
+ OK
+ .AENDI
+ .AIF "FOO" EQ "BAR"
+ BAD
+ .AENDI
+ .AIF "FOO" EQ "FOO"
+ OK
+ .AENDI
+ .AIF "FOO" NE "BAR"
+ OK
+ .AENDI
+ .AIF "FOO" EQ "FOO"
+ OK
+ .AENDI
+ .AIF 1 EQ 1
+ .AIF 1 EQ 1
+ OK
+ .AELSE
+ BAD
+ .AENDI
+ .AIF 1 EQ 0
+ BAD
+ .AELSE
+ OK
+ .AENDI
+ OK
+ .AELSE
+ BAD
+ .AENDI
+ .AIF 1 EQ 0
+ BAD
+ .AELSE
+ OK
+ .AENDI
+ .AIF 1 EQ 1
+ OK
+ .AELSE
+ BAD
+ .AENDI
+ .AIF 1 EQ 0
+ BAD
+ .AELSE
+ .AIF 1 EQ 1
+ OK
+ .AELSE
+ BAD
+ .AENDI
+ .AIF 1 EQ 0
+ BAD
+ .AELSE
+ OK
+ .AENDI
+ OK
+ .AENDI
+ .AIF 1 EQ 1
+ OK
+ .AIF 1 EQ 1
+ OK
+ .AELSE
+ BAD
+ .AENDI
+ .AIF 1 EQ 0
+ BAD
+ .AELSE
+ OK
+ .AENDI
+ .AELSE
+ BAD
+ .AENDI
+ .AIF 1 EQ 0
+ BAD
+ .AELSE
+ OK
+ .AENDI
+ .END
diff --git a/gas/testsuite/gasp/condass.err b/gas/testsuite/gasp/condass.err
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/gas/testsuite/gasp/condass.err
diff --git a/gas/testsuite/gasp/condass.out b/gas/testsuite/gasp/condass.out
new file mode 100644
index 0000000000..115cef5be8
--- /dev/null
+++ b/gas/testsuite/gasp/condass.out
@@ -0,0 +1,155 @@
+! .AIF 1 EQ 1
+! OK
+ OK
+! .AELSE
+! BAD
+! .AENDI
+! .AIF 1 EQ 2
+! BAD
+! .AELSE
+! OK
+ OK
+! .AENDI
+! .AIF 1 EQ 2
+! BAD
+! .AELSE
+! OK
+ OK
+! .AIF 1 EQ 2
+! BAD
+! .AELSE
+! OK
+ OK
+! .AENDI
+! .AENDI
+! .AIF 1 LT 2
+! OK
+ OK
+! .AENDI
+! .AIF 1 EQ 2
+! BAD
+! .AENDI
+! .AIF 1 NE 2
+! OK
+ OK
+! .AENDI
+! .AIF 1 LE 2
+! OK
+ OK
+! .AENDI
+! .AIF 1 GT 2
+! BAD
+! .AENDI
+! .AIF 3 GE 2
+! OK
+ OK
+! .AENDI
+! .AIF 3 LT 2
+! BAD
+! .AENDI
+! .AIF 3 EQ 2
+! BAD
+! .AENDI
+! .AIF 3 NE 2
+! OK
+ OK
+! .AENDI
+! .AIF 3 LE 2
+! BAD
+! .AENDI
+! .AIF 3 GT 2
+! OK
+ OK
+! .AENDI
+! .AIF 3 GE 2
+! OK
+ OK
+! .AENDI
+! .AIF "FOO" EQ "BAR"
+! BAD
+! .AENDI
+! .AIF "FOO" EQ "FOO"
+! OK
+ OK
+! .AENDI
+! .AIF "FOO" NE "BAR"
+! OK
+ OK
+! .AENDI
+! .AIF "FOO" EQ "FOO"
+! OK
+ OK
+! .AENDI
+! .AIF 1 EQ 1
+! .AIF 1 EQ 1
+! OK
+ OK
+! .AELSE
+! BAD
+! .AENDI
+! .AIF 1 EQ 0
+! BAD
+! .AELSE
+! OK
+ OK
+! .AENDI
+! OK
+ OK
+! .AELSE
+! BAD
+! .AENDI
+! .AIF 1 EQ 0
+! BAD
+! .AELSE
+! OK
+ OK
+! .AENDI
+! .AIF 1 EQ 1
+! OK
+ OK
+! .AELSE
+! BAD
+! .AENDI
+! .AIF 1 EQ 0
+! BAD
+! .AELSE
+! .AIF 1 EQ 1
+! OK
+ OK
+! .AELSE
+! BAD
+! .AENDI
+! .AIF 1 EQ 0
+! BAD
+! .AELSE
+! OK
+ OK
+! .AENDI
+! OK
+ OK
+! .AENDI
+! .AIF 1 EQ 1
+! OK
+ OK
+! .AIF 1 EQ 1
+! OK
+ OK
+! .AELSE
+! BAD
+! .AENDI
+! .AIF 1 EQ 0
+! BAD
+! .AELSE
+! OK
+ OK
+! .AENDI
+! .AELSE
+! BAD
+! .AENDI
+! .AIF 1 EQ 0
+! BAD
+! .AELSE
+! OK
+ OK
+! .AENDI
+! .END
diff --git a/gas/testsuite/gasp/crash.asm b/gas/testsuite/gasp/crash.asm
new file mode 100644
index 0000000000..a710cc548d
--- /dev/null
+++ b/gas/testsuite/gasp/crash.asm
@@ -0,0 +1,22 @@
+
+ Stuff to try and crash it
+
+foo: .MACRO
+ HI
+bar: .MACRO
+ THERE
+ bar
+ .ENDM
+
+
+ .ENDM
+ foo
+ foo
+ foo
+ foo
+ foo
+ bar
+
+
+
+
diff --git a/gas/testsuite/gasp/crash.err b/gas/testsuite/gasp/crash.err
new file mode 100644
index 0000000000..1008802107
--- /dev/null
+++ b/gas/testsuite/gasp/crash.err
@@ -0,0 +1 @@
+crash.asm:18 Unreasonable expansion (-u turns off check).
diff --git a/gas/testsuite/gasp/crash.out b/gas/testsuite/gasp/crash.out
new file mode 100644
index 0000000000..6b948a3d9d
--- /dev/null
+++ b/gas/testsuite/gasp/crash.out
@@ -0,0 +1,3059 @@
+!
+
+! Stuff to try and crash it
+ Stuff to try and crash it
+!
+
+!foo: .MACRO
+! HI
+!bar: .MACRO
+! THERE
+! bar
+! .ENDM
+!
+!
+! .ENDM
+! foo
+! HI
+ HI
+!bar: .MACRO
+! THERE
+! bar
+! .ENDM
+!
+
+!
+
+! foo
+! HI
+ HI
+!bar: .MACRO
+! THERE
+! bar
+! .ENDM
+!
+
+!
+
+! foo
+! HI
+ HI
+!bar: .MACRO
+! THERE
+! bar
+! .ENDM
+!
+
+!
+
+! foo
+! HI
+ HI
+!bar: .MACRO
+! THERE
+! bar
+! .ENDM
+!
+
+!
+
+! foo
+! HI
+ HI
+!bar: .MACRO
+! THERE
+! bar
+! .ENDM
+!
+
+!
+
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
+! THERE
+ THERE
+! bar
diff --git a/gas/testsuite/gasp/crash1.asm b/gas/testsuite/gasp/crash1.asm
new file mode 100644
index 0000000000..d2b6b3082e
--- /dev/null
+++ b/gas/testsuite/gasp/crash1.asm
@@ -0,0 +1,13 @@
+
+
+ .MACRO foo a b c=a
+ \a \b \c \d
+ .ENDM
+
+ foo 1 2
+ foo 1 2 3 4
+ foo 1
+ foo
+
+
+ .END
diff --git a/gas/testsuite/gasp/crash1.err b/gas/testsuite/gasp/crash1.err
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/gas/testsuite/gasp/crash1.err
diff --git a/gas/testsuite/gasp/crash1.out b/gas/testsuite/gasp/crash1.out
new file mode 100644
index 0000000000..725d078e3c
--- /dev/null
+++ b/gas/testsuite/gasp/crash1.out
@@ -0,0 +1,24 @@
+!
+
+!
+
+! .MACRO foo a b c=a
+! \a \b \c \d
+! .ENDM
+!
+
+! foo 1 2
+! 1 2 a \d
+ 1 2 a \d
+! foo 1 2 3 4
+! foo 1
+! 1 a \d
+ 1 a \d
+! foo
+! a \d
+ a \d
+!
+
+!
+
+! .END
diff --git a/gas/testsuite/gasp/crash2.asm b/gas/testsuite/gasp/crash2.asm
new file mode 100644
index 0000000000..288a003d9f
--- /dev/null
+++ b/gas/testsuite/gasp/crash2.asm
@@ -0,0 +1,41 @@
+
+foo: .ASSIGNA 1
+ \&foo+1
+ \&foo+1
+foo: .ASSIGNC "foo"
+ \&foo+1
+ \&foo+1
+
+foo: .ASSIGNA 1
+ \&foo+1
+ \&foo+1
+foo: .ASSIGNC "foo"
+ \&foo+1
+ \&foo+1
+
+foo: .ASSIGNA 1
+ \&foo+1
+ \&foo+1
+foo: .ASSIGNC "foo"
+ \&foo+1
+ \&foo+1
+
+foo: .ASSIGNA 1
+ \&foo+1
+ \&foo+1
+foo: .ASSIGNC "foo"
+ \&foo+1
+ \&foo+1
+
+foo: .ASSIGNA 1
+ \&foo+1
+ \&foo+1
+foo: .ASSIGNC "foo"
+ \&foo+1
+ \&foo+1
+ foo
+ foo foo
+ foo foo
+ foo
+ .END
+
diff --git a/gas/testsuite/gasp/crash2.err b/gas/testsuite/gasp/crash2.err
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/gas/testsuite/gasp/crash2.err
diff --git a/gas/testsuite/gasp/crash2.out b/gas/testsuite/gasp/crash2.out
new file mode 100644
index 0000000000..0d1a2f7e4a
--- /dev/null
+++ b/gas/testsuite/gasp/crash2.out
@@ -0,0 +1,69 @@
+!
+
+!foo: .ASSIGNA 1
+! \&foo+1
+ 1+1
+! \&foo+1
+ 1+1
+!foo: .ASSIGNC "foo"
+! \&foo+1
+ foo+1
+! \&foo+1
+ foo+1
+!
+
+!foo: .ASSIGNA 1
+! \&foo+1
+ 1+1
+! \&foo+1
+ 1+1
+!foo: .ASSIGNC "foo"
+! \&foo+1
+ foo+1
+! \&foo+1
+ foo+1
+!
+
+!foo: .ASSIGNA 1
+! \&foo+1
+ 1+1
+! \&foo+1
+ 1+1
+!foo: .ASSIGNC "foo"
+! \&foo+1
+ foo+1
+! \&foo+1
+ foo+1
+!
+
+!foo: .ASSIGNA 1
+! \&foo+1
+ 1+1
+! \&foo+1
+ 1+1
+!foo: .ASSIGNC "foo"
+! \&foo+1
+ foo+1
+! \&foo+1
+ foo+1
+!
+
+!foo: .ASSIGNA 1
+! \&foo+1
+ 1+1
+! \&foo+1
+ 1+1
+!foo: .ASSIGNC "foo"
+! \&foo+1
+ foo+1
+! \&foo+1
+ foo+1
+! foo
+ foo
+! foo foo
+ foo foo
+! foo foo
+ foo foo
+! foo
+ foo
+! .END
diff --git a/gas/testsuite/gasp/data.asm b/gas/testsuite/gasp/data.asm
new file mode 100644
index 0000000000..ba6b0a046f
--- /dev/null
+++ b/gas/testsuite/gasp/data.asm
@@ -0,0 +1,23 @@
+
+foo .DATA 1,2,3
+bar .DATA 1,2,3,4,5 ,6
+ .DATA.B 12345,12,2
+ .DATA.W 9,2,12,3,13+41,foo+9
+ .DATA.L 2~99
+
+
+
+ .DATAB 1,2,3
+ .DATAB 1,2,3
+
+
+
+
+ .DATAB 1,9+32
+
+ .DATAB.L 1,H'11111111
+ .DATAB.W 2,H'2222
+ .DATAB.B 3,H'333
+
+
+ .END
diff --git a/gas/testsuite/gasp/data.err b/gas/testsuite/gasp/data.err
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/gas/testsuite/gasp/data.err
diff --git a/gas/testsuite/gasp/data.out b/gas/testsuite/gasp/data.out
new file mode 100644
index 0000000000..e96e1e58ca
--- /dev/null
+++ b/gas/testsuite/gasp/data.out
@@ -0,0 +1,45 @@
+!
+
+!foo .DATA 1,2,3
+foo: .long 1,2,3
+!bar .DATA 1,2,3,4,5 ,6
+bar: .long 1,2,3,4,5,6
+! .DATA.B 12345,12,2
+ .byte 12345,12,2
+! .DATA.W 9,2,12,3,13+41,foo+9
+ .short 9,2,12,3,54,foo+9
+! .DATA.L 2~99
+ .long 97
+!
+
+!
+
+!
+
+! .DATAB 1,2,3
+ .fill 1,4,2
+! .DATAB 1,2,3
+ .fill 1,4,2
+!
+
+!
+
+!
+
+!
+
+! .DATAB 1,9+32
+ .fill 1,4,41
+!
+
+! .DATAB.L 1,H'11111111
+ .fill 1,4,286331153
+! .DATAB.W 2,H'2222
+ .fill 2,2,8738
+! .DATAB.B 3,H'333
+ .fill 3,1,819
+!
+
+!
+
+! .END
diff --git a/gas/testsuite/gasp/exp.asm b/gas/testsuite/gasp/exp.asm
new file mode 100644
index 0000000000..041608a818
--- /dev/null
+++ b/gas/testsuite/gasp/exp.asm
@@ -0,0 +1,80 @@
+
+; test all ops
+
+a1 .EQU 4+10
+a2 .EQU 4-10
+a3 .EQU 4&10
+a4 .EQU 4|2
+a5 .EQU 4~2
+a6 .EQU 4*10
+a7 .EQU 40/10
+a8 .EQU +7
+a9 .EQU -7
+a10 .EQU ~7
+
+
+ a1 a2 a3 a4 a5 a6 a7 a8 a9 a10
+
+; test the priorities
+
+b1 .EQU 1|2~3&4+5-8*7/2
+b2 .EQU (1|2~(3&(4+5-(8*(7/2)))))
+b3 .EQU 10*2/3*4
+b4 .EQU (((10*2)/3)*4)
+b5 .EQU 10+2-3+4
+b6 .EQU (((10+2)-3)+4)
+
+ b1 b2 b3 b4
+
+; test association
+
+c1 .EQU -~3
+c2 .EQU ~-3
+c3 .EQU -(~3)
+c4 .EQU ~(-3)
+
+ c1 c2 c3 c4
+
+; test rules for symbols
+
+ok1 .EQU FOO
+ok2 .EQU FOO+10
+ok3 .EQU 10+FOO
+ok4 .EQU FOO-10
+
+ ok1
+ ok2
+ ok3
+ ok4
+
+ok5 .EQU FOO+3+4+5+6
+ok6 .EQU FOO-BAR
+
+ ok5
+ ok6
+
+bad1 .EQU FOO+FOO
+bad2 .EQU FOO*2
+bad3 .EQU FOO/2
+bad4 .EQU FOO|2
+bad5 .EQU FOO&2
+bad6 .EQU FOO~2
+bad7 .EQU FOO*2
+
+; test spacing
+
+space1 .EQU 1 + 2 +3+FOO + 3
+space2
+
+; from the SH manual
+
+ .DATA.L 1+(2-(3+(4-5))),1
+
+ .DATA.L -H'fffffff1+H'000000f0*H'00000010|H'000000f0&H'0000ffff,H'00000fff
+
+ .DATA.L -~-~H'0000000f,H'00
+
+
+
+
+ .END
diff --git a/gas/testsuite/gasp/exp.err b/gas/testsuite/gasp/exp.err
new file mode 100644
index 0000000000..f41fd52804
--- /dev/null
+++ b/gas/testsuite/gasp/exp.err
@@ -0,0 +1,7 @@
+exp.asm:56 can't add two relocatable expressions
+exp.asm:57 the * operator cannot take non-absolute arguments.
+exp.asm:58 the / operator cannot take non-absolute arguments.
+exp.asm:59 the | operator cannot take non-absolute arguments.
+exp.asm:60 the & operator cannot take non-absolute arguments.
+exp.asm:61 the ~ operator cannot take non-absolute arguments.
+exp.asm:62 the * operator cannot take non-absolute arguments.
diff --git a/gas/testsuite/gasp/exp.out b/gas/testsuite/gasp/exp.out
new file mode 100644
index 0000000000..cecb9a881e
--- /dev/null
+++ b/gas/testsuite/gasp/exp.out
@@ -0,0 +1,124 @@
+!
+
+!; test all ops
+ ; test all ops
+!
+
+!a1 .EQU 4+10
+!a2 .EQU 4-10
+!a3 .EQU 4&10
+!a4 .EQU 4|2
+!a5 .EQU 4~2
+!a6 .EQU 4*10
+!a7 .EQU 40/10
+!a8 .EQU +7
+!a9 .EQU -7
+!a10 .EQU ~7
+!
+
+!
+
+! a1 a2 a3 a4 a5 a6 a7 a8 a9 a10
+ 14 -6 0 6 6 40 4 7 -7 -8
+!
+
+!; test the priorities
+ ; test the priorities
+!
+
+!b1 .EQU 1|2~3&4+5-8*7/2
+!b2 .EQU (1|2~(3&(4+5-(8*(7/2)))))
+!b3 .EQU 10*2/3*4
+!b4 .EQU (((10*2)/3)*4)
+!b5 .EQU 10+2-3+4
+!b6 .EQU (((10+2)-3)+4)
+!
+
+! b1 b2 b3 b4
+ 2 2 24 24
+!
+
+!; test association
+ ; test association
+!
+
+!c1 .EQU -~3
+!c2 .EQU ~-3
+!c3 .EQU -(~3)
+!c4 .EQU ~(-3)
+!
+
+! c1 c2 c3 c4
+ 4 2 4 2
+!
+
+!; test rules for symbols
+ ; test rules for symbols
+!
+
+!ok1 .EQU FOO
+!ok2 .EQU FOO+10
+!ok3 .EQU 10+FOO
+!ok4 .EQU FOO-10
+!
+
+! ok1
+ FOO
+! ok2
+ FOO+10
+! ok3
+ FOO+10
+! ok4
+ FOO+-10
+!
+
+!ok5 .EQU FOO+3+4+5+6
+!ok6 .EQU FOO-BAR
+!
+
+! ok5
+ FOO+18
+! ok6
+ FOO-FOO
+!
+
+!bad1 .EQU FOO+FOO
+!bad2 .EQU FOO*2
+!bad3 .EQU FOO/2
+!bad4 .EQU FOO|2
+!bad5 .EQU FOO&2
+!bad6 .EQU FOO~2
+!bad7 .EQU FOO*2
+!
+
+!; test spacing
+ ; test spacing
+!
+
+!space1 .EQU 1 + 2 +3+FOO + 3
+!space2
+space2:
+!
+
+!; from the SH manual
+ ; from the SH manual
+!
+
+! .DATA.L 1+(2-(3+(4-5))),1
+ .long 1,1
+!
+
+! .DATA.L -H'fffffff1+H'000000f0*H'00000010|H'000000f0&H'0000ffff,H'00000fff
+ .long 4095,4095
+!
+
+! .DATA.L -~-~H'0000000f,H'00
+ .long 17,0
+!
+
+!
+
+!
+!
+
+! .END
diff --git a/gas/testsuite/gasp/gasp.exp b/gas/testsuite/gasp/gasp.exp
new file mode 100644
index 0000000000..2a72a6d359
--- /dev/null
+++ b/gas/testsuite/gasp/gasp.exp
@@ -0,0 +1,40 @@
+# Test gasp.
+
+proc gasp_test { filename testname opt } {
+ global GASP
+ global srcdir
+ global host_triplet
+
+ send_log "$srcdir/lib/run $GASP -I$srcdir/gasp -s $opt $filename.asm -o gasp.out\n"
+ catch "exec $srcdir/lib/run $GASP -I$srcdir/gasp -s $opt $filename.asm -o gasp.out" errs
+ catch "exec diff gasp.out $filename.out" diffs
+ set diffs [prune_warnings $diffs]
+ if ![string match "" $diffs] {
+ send_log "$diffs\n"
+ verbose $diffs
+ fail $testname
+ return 0
+ } else {
+ pass $testname
+ }
+
+}
+
+foreach src [ lsort [ glob $srcdir/gasp/*.asm ] ] {
+ regsub -all ".asm" $src "" t
+ regsub "^.*/(\[^/\]*)$" $t "gasp \\1" testname
+ gasp_test $t $testname ""
+}
+
+foreach src [ lsort [ glob $srcdir/gasp/mri/*.asm ] ] {
+ regsub -all ".asm" $src "" t
+ regsub "^.*/(\[^/\]*)$" $t "gasp MRI \\1" testname
+ gasp_test $t $testname "-M"
+}
+
+# FIXME: this is here cause of a bug in DejaGnu 1.1.1. When it is no longer
+# in use, then this can be removed.
+if [info exists errorInfo] then {
+ unset errorInfo
+}
+
diff --git a/gas/testsuite/gasp/include.asm b/gas/testsuite/gasp/include.asm
new file mode 100644
index 0000000000..69ed1dd5e8
--- /dev/null
+++ b/gas/testsuite/gasp/include.asm
@@ -0,0 +1,4 @@
+ HI
+ .INCLUDE "INC1.H"
+ THERE
+ .END
diff --git a/gas/testsuite/gasp/include.err b/gas/testsuite/gasp/include.err
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/gas/testsuite/gasp/include.err
diff --git a/gas/testsuite/gasp/include.out b/gas/testsuite/gasp/include.out
new file mode 100644
index 0000000000..d77a0df74f
--- /dev/null
+++ b/gas/testsuite/gasp/include.out
@@ -0,0 +1,15 @@
+! HI
+ HI
+! .INCLUDE "INC1.H"
+!FILE 1 FIRST LINE
+FILE: 1 FIRST LINE
+! .INCLUDE "INC2.H"
+! FILE 2 FIRST LINE
+ FILE 2 FIRST LINE
+! FILE 2 LAST LINE
+ FILE 2 LAST LINE
+!FILE 1 LAST LINE
+FILE: 1 LAST LINE
+! THERE
+ THERE
+! .END
diff --git a/gas/testsuite/gasp/listing.asm b/gas/testsuite/gasp/listing.asm
new file mode 100644
index 0000000000..2f14cfc584
--- /dev/null
+++ b/gas/testsuite/gasp/listing.asm
@@ -0,0 +1,15 @@
+
+
+ .HEADING " ""QUOTE"" "
+ .PAGE
+ .PRINT LIST
+ foo
+ .PRINT NOLIST
+ foo
+
+
+ .FORM LIN=12
+ .FORM COL=90
+ .FORM LIN=123 COL=23
+
+ .END
diff --git a/gas/testsuite/gasp/listing.err b/gas/testsuite/gasp/listing.err
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/gas/testsuite/gasp/listing.err
diff --git a/gas/testsuite/gasp/listing.out b/gas/testsuite/gasp/listing.out
new file mode 100644
index 0000000000..585bda2728
--- /dev/null
+++ b/gas/testsuite/gasp/listing.out
@@ -0,0 +1,28 @@
+!
+
+!
+
+! .HEADING " ""QUOTE"" "
+ .title " "QUOTE" "
+! .PAGE
+ .eject
+! .PRINT LIST
+ .list
+! foo
+ foo
+! .PRINT NOLIST
+ .nolist
+! foo
+ foo
+!
+
+!
+
+! .FORM LIN=12
+ .psize 12,132
+! .FORM COL=90
+ .psize 60,90
+! .FORM LIN=123 COL=23
+ .psize 123,23
+!
+! .END
diff --git a/gas/testsuite/gasp/macro.asm b/gas/testsuite/gasp/macro.asm
new file mode 100644
index 0000000000..dfb16bff29
--- /dev/null
+++ b/gas/testsuite/gasp/macro.asm
@@ -0,0 +1,102 @@
+ .MACRO SUM FROM=0, TO=9
+ ; \FROM \TO
+ MOV R\FROM,R10
+COUNT .ASSIGNA \FROM+1
+ .AWHILE \&COUNT LE \TO
+ MOV R\&COUNT,R10
+COUNT .ASSIGNA \&COUNT+1
+ .AENDW
+ .ENDM
+
+ SUM 0,5
+ SUM TO=5
+ SUM FROM=2, TO=5
+
+
+; hi this is a comment
+ .MACRO BACK_SLASH_SET
+ \(MOV #"\",R0)
+ .ENDM
+ BACK_SLASH_SET
+ .MACRO COMM
+ bar ; this comment will get copied out
+ foo \; this one will get dropped
+ .ENDM
+ COMM
+ BACK_SLASH_SET
+ .MACRO PLUS2
+ ADD #1,R\&V1
+ .SDATA "\&V'1"
+ .ENDM
+V .ASSIGNC "R"
+V1 .ASSIGNA 1
+ PLUS2
+ .MACRO PLUS1 P,P1
+ ADD #1,\P1
+ .SDATA "\P'1"
+ .ENDM
+ PLUS1 R,R1
+
+ .MACRO SUM P1
+ MOV R0,R10
+ ADD R1,R10
+ ADD R2,R10
+ \P1
+ ADD R3,R10
+ .ENDM
+
+ SUM .EXITM
+
+ .MACRO foo bar=a default=b
+ \bar
+ \default
+ bar
+ default
+ .ENDM
+ foo default=dog bar=cat
+ foo X Y
+ foo
+ foo bar=cat default=dog
+
+
+ .MACRO foo bar
+ HI
+ HI \bar
+ HI
+ .ENDM
+
+ foo 1
+ foo 123
+ foo 1 2 3 4
+ foo
+
+
+ .MACRO PUSH Rn
+ MOV.L \Rn,@-r15
+ .ENDM
+ PUSH R0
+ PUSH R1
+
+
+ .MACRO RES_STR STR, Rn
+ MOV.L #str\@,\Rn
+ BRA end_str\@
+ NOP
+str\@ .SDATA "\STR"
+ .ALIGN 2
+end_str\@
+ .ENDM
+
+ RES_STR "ONE",R0
+ RES_STR "TWO",R1
+ RES_STR "THREE",R2
+
+
+
+ RES_STR STR=donkey Rn=R1
+ RES_STR donkey,R1
+ RES_STR donkey Rn=R1
+ .END
+
+
+
diff --git a/gas/testsuite/gasp/macro.err b/gas/testsuite/gasp/macro.err
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/gas/testsuite/gasp/macro.err
diff --git a/gas/testsuite/gasp/macro.out b/gas/testsuite/gasp/macro.out
new file mode 100644
index 0000000000..0740732c7c
--- /dev/null
+++ b/gas/testsuite/gasp/macro.out
@@ -0,0 +1,382 @@
+! .MACRO SUM FROM=0, TO=9
+! ; \FROM \TO
+! MOV R\FROM,R10
+!COUNT .ASSIGNA \FROM+1
+! .AWHILE \&COUNT LE \TO
+! MOV R\&COUNT,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AENDW
+! .ENDM
+!
+
+! SUM 0,5
+! ; 0 5
+ ; 0 5
+! MOV R0,R10
+ MOV R0,R10
+!COUNT .ASSIGNA 0+1
+! .AWHILE \&COUNT LE 5
+! MOV R\&COUNT,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AENDW
+! MOV R\&COUNT,R10
+ MOV R1,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AWHILE \&COUNT LE 5
+! MOV R\&COUNT,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AENDW
+! MOV R\&COUNT,R10
+ MOV R2,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AWHILE \&COUNT LE 5
+! MOV R\&COUNT,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AENDW
+! MOV R\&COUNT,R10
+ MOV R3,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AWHILE \&COUNT LE 5
+! MOV R\&COUNT,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AENDW
+! MOV R\&COUNT,R10
+ MOV R4,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AWHILE \&COUNT LE 5
+! MOV R\&COUNT,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AENDW
+! MOV R\&COUNT,R10
+ MOV R5,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AWHILE \&COUNT LE 5
+! MOV R\&COUNT,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AENDW
+! SUM TO=5
+! ; 0 5
+ ; 0 5
+! MOV R0,R10
+ MOV R0,R10
+!COUNT .ASSIGNA 0+1
+! .AWHILE \&COUNT LE 5
+! MOV R\&COUNT,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AENDW
+! MOV R\&COUNT,R10
+ MOV R1,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AWHILE \&COUNT LE 5
+! MOV R\&COUNT,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AENDW
+! MOV R\&COUNT,R10
+ MOV R2,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AWHILE \&COUNT LE 5
+! MOV R\&COUNT,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AENDW
+! MOV R\&COUNT,R10
+ MOV R3,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AWHILE \&COUNT LE 5
+! MOV R\&COUNT,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AENDW
+! MOV R\&COUNT,R10
+ MOV R4,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AWHILE \&COUNT LE 5
+! MOV R\&COUNT,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AENDW
+! MOV R\&COUNT,R10
+ MOV R5,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AWHILE \&COUNT LE 5
+! MOV R\&COUNT,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AENDW
+! SUM FROM=2, TO=5
+! ; 2 5
+ ; 2 5
+! MOV R2,R10
+ MOV R2,R10
+!COUNT .ASSIGNA 2+1
+! .AWHILE \&COUNT LE 5
+! MOV R\&COUNT,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AENDW
+! MOV R\&COUNT,R10
+ MOV R3,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AWHILE \&COUNT LE 5
+! MOV R\&COUNT,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AENDW
+! MOV R\&COUNT,R10
+ MOV R4,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AWHILE \&COUNT LE 5
+! MOV R\&COUNT,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AENDW
+! MOV R\&COUNT,R10
+ MOV R5,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AWHILE \&COUNT LE 5
+! MOV R\&COUNT,R10
+!COUNT .ASSIGNA \&COUNT+1
+! .AENDW
+!
+
+!
+
+!; hi this is a comment
+ ; hi this is a comment
+! .MACRO BACK_SLASH_SET
+! \(MOV #"\",R0)
+! .ENDM
+! BACK_SLASH_SET
+! MOV #"\",R0
+ MOV #"\",R0
+! .MACRO COMM
+! bar ; this comment will get copied out
+! foo \; this one will get dropped
+! .ENDM
+! COMM
+! bar ; this comment will get copied out
+ bar ; this comment will get copied out
+! foo \; this one will get dropped
+ foo \; this one will get dropped
+! BACK_SLASH_SET
+! MOV #"\",R0
+ MOV #"\",R0
+! .MACRO PLUS2
+! ADD #1,R\&V1
+! .SDATA "\&V'1"
+! .ENDM
+!V .ASSIGNC "R"
+!V1 .ASSIGNA 1
+! PLUS2
+! ADD #1,R\&V1
+ ADD #1,R1
+! .SDATA "\&V'1"
+ .byte 82,49
+! .MACRO PLUS1 P,P1
+! ADD #1,\P1
+! .SDATA "\P'1"
+! .ENDM
+! PLUS1 R,R1
+! ADD #1,R1
+ ADD #1,R1
+! .SDATA "R1"
+ .byte 82,49
+!
+
+! .MACRO SUM P1
+! MOV R0,R10
+! ADD R1,R10
+! ADD R2,R10
+! \P1
+! ADD R3,R10
+! .ENDM
+!
+
+! SUM .EXITM
+! MOV R0,R10
+ MOV R0,R10
+! ADD R1,R10
+ ADD R1,R10
+! ADD R2,R10
+ ADD R2,R10
+! .EXITM
+!
+
+! .MACRO foo bar=a default=b
+! \bar
+! \default
+! bar
+! default
+! .ENDM
+! foo default=dog bar=cat
+! cat
+ cat
+! dog
+ dog
+! bar
+ bar
+! default
+ default
+! foo X Y
+! X
+ X
+! Y
+ Y
+! bar
+ bar
+! default
+ default
+! foo
+! a
+ a
+! b
+ b
+! bar
+ bar
+! default
+ default
+! foo bar=cat default=dog
+! cat
+ cat
+! dog
+ dog
+! bar
+ bar
+! default
+ default
+!
+
+!
+
+! .MACRO foo bar
+! HI
+! HI \bar
+! HI
+! .ENDM
+!
+
+! foo 1
+! HI
+ HI
+! HI 1
+ HI 1
+! HI
+ HI
+! foo 123
+! HI
+ HI
+! HI 123
+ HI 123
+! HI
+ HI
+! foo 1 2 3 4
+! foo
+! HI
+ HI
+! HI
+ HI
+! HI
+ HI
+!
+
+!
+! .MACRO PUSH Rn
+! MOV.L \Rn,@-r15
+! .ENDM
+! PUSH R0
+! MOV.L R0,@-r15
+ MOV.L R0,@-r15
+! PUSH R1
+! MOV.L R1,@-r15
+ MOV.L R1,@-r15
+!
+
+!
+
+! .MACRO RES_STR STR, Rn
+! MOV.L #str\@,\Rn
+! BRA end_str\@
+! NOP
+!str\@ .SDATA "\STR"
+! .ALIGN 2
+!end_str\@
+! .ENDM
+!
+! RES_STR "ONE",R0
+! MOV.L #str00018,R0
+ MOV.L #str00018,R0
+! BRA end_str00018
+ BRA end_str00018
+! NOP
+ NOP
+!str00018 .SDATA "ONE"
+str00018: .byte 79,78,69
+! .ALIGN 2
+ .align 2
+!end_str00018
+end_str00018:
+! RES_STR "TWO",R1
+! MOV.L #str00019,R1
+ MOV.L #str00019,R1
+! BRA end_str00019
+ BRA end_str00019
+! NOP
+ NOP
+!str00019 .SDATA "TWO"
+str00019: .byte 84,87,79
+! .ALIGN 2
+ .align 2
+!end_str00019
+end_str00019:
+! RES_STR "THREE",R2
+! MOV.L #str00020,R2
+ MOV.L #str00020,R2
+! BRA end_str00020
+ BRA end_str00020
+! NOP
+ NOP
+!str00020 .SDATA "THREE"
+str00020: .byte 84,72,82,69,69
+! .ALIGN 2
+ .align 2
+!end_str00020
+end_str00020:
+!
+
+!
+
+!
+
+! RES_STR STR=donkey Rn=R1
+! MOV.L #str00021,R1
+ MOV.L #str00021,R1
+! BRA end_str00021
+ BRA end_str00021
+! NOP
+ NOP
+!str00021 .SDATA "donkey"
+str00021: .byte 100,111,110,107,101,121
+! .ALIGN 2
+ .align 2
+!end_str00021
+end_str00021:
+! RES_STR donkey,R1
+! MOV.L #str00022,R1
+ MOV.L #str00022,R1
+! BRA end_str00022
+ BRA end_str00022
+! NOP
+ NOP
+!str00022 .SDATA "donkey"
+str00022: .byte 100,111,110,107,101,121
+! .ALIGN 2
+ .align 2
+!end_str00022
+end_str00022:
+! RES_STR donkey Rn=R1
+! MOV.L #str00023,R1
+ MOV.L #str00023,R1
+! BRA end_str00023
+ BRA end_str00023
+! NOP
+ NOP
+!str00023 .SDATA "donkey"
+str00023: .byte 100,111,110,107,101,121
+! .ALIGN 2
+ .align 2
+!end_str00023
+end_str00023:
+! .END
diff --git a/gas/testsuite/gasp/mdouble.asm b/gas/testsuite/gasp/mdouble.asm
new file mode 100644
index 0000000000..dbb77b4d4a
--- /dev/null
+++ b/gas/testsuite/gasp/mdouble.asm
@@ -0,0 +1,47 @@
+
+ .MACRO HI
+ A
+ \! this is hidden
+ B
+ ! this is not
+ C
+ .ENDM
+ Hello
+ HI
+ Emily
+
+
+ H'0f
+ 200+H'0F
+
+XX .ASSIGNA Q'100
+! Definition:
+ .MACRO GET X=100,Y,Z
+ MOV #\X+H'0F,@B
+ \Y
+\Z JMP @MAIN
+L\@ ADD #1,@HL
+ MOV #0,@C \! Clear C
+ ADD #2,@C
+ ADD #\&XX, @C
+ .ENDM
+
+ NOP
+
+!Call:
+ GET 200,"ADD #1,@B", ENTRY
+ .END
+
+ ; Definition:
+
+
+ NOP
+
+ ;Call:
+ MOV #200+0F,@B
+ ADD #1,@B
+ENTRY: JMP @MAIN
+L00000: ADD #1,@HL
+ MOV #0,@C
+ ADD #2,@C
+ ADD #0, @C
diff --git a/gas/testsuite/gasp/mdouble.err b/gas/testsuite/gasp/mdouble.err
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/gas/testsuite/gasp/mdouble.err
diff --git a/gas/testsuite/gasp/mdouble.out b/gas/testsuite/gasp/mdouble.out
new file mode 100644
index 0000000000..9d9ad62d28
--- /dev/null
+++ b/gas/testsuite/gasp/mdouble.out
@@ -0,0 +1,68 @@
+!
+
+! .MACRO HI
+! A
+! \! this is hidden
+! B
+! ! this is not
+! C
+! .ENDM
+! Hello
+ Hello
+! HI
+! A
+ A
+!
+! B
+ B
+! ! this is not
+ ! this is not
+! C
+ C
+! Emily
+ Emily
+!
+!
+
+! H'0f
+ 15
+! 200+H'0F
+ 200+15
+!
+
+!XX .ASSIGNA Q'100
+!! Definition:
+ ! Definition:
+! .MACRO GET X=100,Y,Z
+! MOV #\X+H'0F,@B
+! \Y
+!\Z JMP @MAIN
+!L\@ ADD #1,@HL
+! MOV #0,@C \! Clear C
+! ADD #2,@C
+! ADD #\&XX, @C
+! .ENDM
+!
+
+! NOP
+ NOP
+!
+
+!!Call:
+ !Call:
+! GET 200,"ADD #1,@B", ENTRY
+! MOV #200+H'0F,@B
+ MOV #200+15,@B
+! ADD #1,@B
+ ADD #1,@B
+!ENTRY JMP @MAIN
+ENTRY: JMP @MAIN
+!L00001 ADD #1,@HL
+L00001: ADD #1,@HL
+! MOV #0,@C
+ MOV #0,@C
+! ADD #2,@C
+ ADD #2,@C
+! ADD #\&XX, @C
+ ADD #64, @C
+! .END
diff --git a/gas/testsuite/gasp/mri/embed.asm b/gas/testsuite/gasp/mri/embed.asm
new file mode 100644
index 0000000000..f1b8f78bf8
--- /dev/null
+++ b/gas/testsuite/gasp/mri/embed.asm
@@ -0,0 +1,5 @@
+embed macro label
+addr&&label dc.l label
+ endm
+
+ embed foo
diff --git a/gas/testsuite/gasp/mri/embed.out b/gas/testsuite/gasp/mri/embed.out
new file mode 100644
index 0000000000..92d925f4b0
--- /dev/null
+++ b/gas/testsuite/gasp/mri/embed.out
@@ -0,0 +1,9 @@
+;embed macro label
+;addr&&label dc.l label
+; endm
+;
+
+; embed foo
+;addrfoo dc.l foo
+addrfoo: dc.l foo
+; \ No newline at end of file
diff --git a/gas/testsuite/gasp/mri/exists.asm b/gas/testsuite/gasp/mri/exists.asm
new file mode 100644
index 0000000000..87220c624e
--- /dev/null
+++ b/gas/testsuite/gasp/mri/exists.asm
@@ -0,0 +1,10 @@
+exists macro arg1,arg2
+ ifne ==arg2
+ move arg1,arg2
+ elsec
+ push arg1
+ endc
+ endm
+
+ exists foo,bar
+ exists foo
diff --git a/gas/testsuite/gasp/mri/exists.out b/gas/testsuite/gasp/mri/exists.out
new file mode 100644
index 0000000000..e75337d511
--- /dev/null
+++ b/gas/testsuite/gasp/mri/exists.out
@@ -0,0 +1,24 @@
+;exists macro arg1,arg2
+; ifne ==arg2
+; move arg1,arg2
+; elsec
+; push arg1
+; endc
+; endm
+;
+
+; exists foo,bar
+; ifne -1
+; move foo,bar
+ move foo,bar
+; elsec
+; push foo
+; endc
+; exists foo
+; ifne 0
+; move foo,
+; elsec
+; push foo
+ push foo
+; endc
+; \ No newline at end of file
diff --git a/gas/testsuite/gasp/mri/irp.asm b/gas/testsuite/gasp/mri/irp.asm
new file mode 100644
index 0000000000..cda21d9ed3
--- /dev/null
+++ b/gas/testsuite/gasp/mri/irp.asm
@@ -0,0 +1,4 @@
+ irp param,arg1,arg2,arg3
+ dc.l param
+ endr
+ end quit
diff --git a/gas/testsuite/gasp/mri/irp.out b/gas/testsuite/gasp/mri/irp.out
new file mode 100644
index 0000000000..9105620406
--- /dev/null
+++ b/gas/testsuite/gasp/mri/irp.out
@@ -0,0 +1,8 @@
+; irp param,arg1,arg2,arg3
+; dc.l param
+; endr
+ dc.l arg1
+ dc.l arg2
+ dc.l arg3
+; end quit
+ end quit
diff --git a/gas/testsuite/gasp/mri/irpc.asm b/gas/testsuite/gasp/mri/irpc.asm
new file mode 100644
index 0000000000..a51d687891
--- /dev/null
+++ b/gas/testsuite/gasp/mri/irpc.asm
@@ -0,0 +1,3 @@
+ irpc dummy,1234
+ dc.l dummy
+ endr
diff --git a/gas/testsuite/gasp/mri/irpc.out b/gas/testsuite/gasp/mri/irpc.out
new file mode 100644
index 0000000000..59f8824fa6
--- /dev/null
+++ b/gas/testsuite/gasp/mri/irpc.out
@@ -0,0 +1,8 @@
+; irpc dummy,1234
+; dc.l dummy
+; endr
+ dc.l 1
+ dc.l 2
+ dc.l 3
+ dc.l 4
+; \ No newline at end of file
diff --git a/gas/testsuite/gasp/mri/macro.asm b/gas/testsuite/gasp/mri/macro.asm
new file mode 100644
index 0000000000..b711bd0b41
--- /dev/null
+++ b/gas/testsuite/gasp/mri/macro.asm
@@ -0,0 +1,8 @@
+get macro arg1,arg2,arg3
+ dc.l arg1
+ arg2
+arg3 dc.l \4
+ move.\0 d0,d1
+ endm
+
+ get.b 1,<dc.l 2>,label,four
diff --git a/gas/testsuite/gasp/mri/macro.out b/gas/testsuite/gasp/mri/macro.out
new file mode 100644
index 0000000000..86eeb944a2
--- /dev/null
+++ b/gas/testsuite/gasp/mri/macro.out
@@ -0,0 +1,18 @@
+;get macro arg1,arg2,arg3
+; dc.l arg1
+; arg2
+;arg3 dc.l \4
+; move.\0 d0,d1
+; endm
+;
+
+; get.b 1,<dc.l 2>,label,four
+; dc.l 1
+ dc.l 1
+; dc.l 2
+ dc.l 2
+;label dc.l four
+label: dc.l four
+; move.b d0,d1
+ move.b d0,d1
+; \ No newline at end of file
diff --git a/gas/testsuite/gasp/mri/narg.asm b/gas/testsuite/gasp/mri/narg.asm
new file mode 100644
index 0000000000..114c94032e
--- /dev/null
+++ b/gas/testsuite/gasp/mri/narg.asm
@@ -0,0 +1,9 @@
+loop macro arg1,arg2,arg3
+ dc.l NARG
+ ifne NARG
+ dc.l arg1
+ loop arg2,arg3
+ endc
+ endm
+
+ loop 1,2,3
diff --git a/gas/testsuite/gasp/mri/narg.out b/gas/testsuite/gasp/mri/narg.out
new file mode 100644
index 0000000000..723ebc1142
--- /dev/null
+++ b/gas/testsuite/gasp/mri/narg.out
@@ -0,0 +1,38 @@
+;loop macro arg1,arg2,arg3
+; dc.l NARG
+; ifne NARG
+; dc.l arg1
+; loop arg2,arg3
+; endc
+; endm
+;
+
+; loop 1,2,3
+; dc.l 3
+ dc.l 3
+; ifne 3
+; dc.l 1
+ dc.l 1
+; loop 2,3
+; dc.l 2
+ dc.l 2
+; ifne 2
+; dc.l 2
+ dc.l 2
+; loop 3,
+; dc.l 1
+ dc.l 1
+; ifne 1
+; dc.l 3
+ dc.l 3
+; loop ,
+; dc.l 0
+ dc.l 0
+; ifne 0
+; dc.l
+; loop ,
+; endc
+; endc
+; endc
+; endc
+; \ No newline at end of file
diff --git a/gas/testsuite/gasp/mri/rept.asm b/gas/testsuite/gasp/mri/rept.asm
new file mode 100644
index 0000000000..d563bb217a
--- /dev/null
+++ b/gas/testsuite/gasp/mri/rept.asm
@@ -0,0 +1,3 @@
+ rept 3
+ dc.l 1
+ endr
diff --git a/gas/testsuite/gasp/mri/rept.out b/gas/testsuite/gasp/mri/rept.out
new file mode 100644
index 0000000000..da4ed6be57
--- /dev/null
+++ b/gas/testsuite/gasp/mri/rept.out
@@ -0,0 +1,16 @@
+; rept 3
+; dc.l 1
+; endr
+; dc.l 1
+ dc.l 1
+; REPT 2
+; dc.l 1
+; ENDR
+; dc.l 1
+ dc.l 1
+; REPT 1
+; dc.l 1
+; ENDR
+; dc.l 1
+ dc.l 1
+; \ No newline at end of file
diff --git a/gas/testsuite/gasp/pl1.asm b/gas/testsuite/gasp/pl1.asm
new file mode 100644
index 0000000000..f38bfde93b
--- /dev/null
+++ b/gas/testsuite/gasp/pl1.asm
@@ -0,0 +1,20 @@
+
+ .ALTERNATE
+
+alloc MACRO val1,val2
+ DB val1
+ DB val2
+ ENDM
+
+ alloc "that's" 'show biz'
+ alloc 0,1
+ alloc 0 1
+ alloc 0 1
+ alloc ,1
+
+
+
+
+
+
+
diff --git a/gas/testsuite/gasp/pl1.err b/gas/testsuite/gasp/pl1.err
new file mode 100644
index 0000000000..a1e3318844
--- /dev/null
+++ b/gas/testsuite/gasp/pl1.err
@@ -0,0 +1 @@
+END missing from end of file.
diff --git a/gas/testsuite/gasp/pl1.out b/gas/testsuite/gasp/pl1.out
new file mode 100644
index 0000000000..8b80f12bb8
--- /dev/null
+++ b/gas/testsuite/gasp/pl1.out
@@ -0,0 +1,49 @@
+!
+! .ALTERNATE
+!
+
+!alloc MACRO val1,val2
+! DB val1
+! DB val2
+! ENDM
+!
+
+! alloc "that's" 'show biz'
+! DB "that's"
+ .byte 116,104,97,116,39,115
+! DB "show biz"
+ .byte 115,104,111,119,32,98,105,122
+! alloc 0,1
+! DB 0
+ .byte 0
+! DB 1
+ .byte 1
+! alloc 0 1
+! DB 0
+ .byte 0
+! DB 1
+ .byte 1
+! alloc 0 1
+! DB 0
+ .byte 0
+! DB 1
+ .byte 1
+! alloc ,1
+! DB
+ .byte
+! DB 1
+ .byte 1
+!
+
+!
+
+!
+!
+
+!
+
+!
+
+!
+
+! \ No newline at end of file
diff --git a/gas/testsuite/gasp/pl2.asm b/gas/testsuite/gasp/pl2.asm
new file mode 100644
index 0000000000..2971137185
--- /dev/null
+++ b/gas/testsuite/gasp/pl2.asm
@@ -0,0 +1,28 @@
+
+
+ .ALTERNATE
+
+ ! ok
+ !! also ok
+
+foo MACRO
+ ! you can see me
+ !! but not me
+ ! you can see me
+ !! but not me
+ but this "SHOULD !!BE OK"
+ ENDM
+
+ foo
+
+
+define MACRO val1,val2
+ DB val1 ! this comment will show up
+ DB val2 !! this on won't
+ ENDM
+
+ define 0,1
+
+
+ END
+
diff --git a/gas/testsuite/gasp/pl2.err b/gas/testsuite/gasp/pl2.err
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/gas/testsuite/gasp/pl2.err
diff --git a/gas/testsuite/gasp/pl2.out b/gas/testsuite/gasp/pl2.out
new file mode 100644
index 0000000000..cca6fa3668
--- /dev/null
+++ b/gas/testsuite/gasp/pl2.out
@@ -0,0 +1,51 @@
+!
+
+!
+
+! .ALTERNATE
+!
+
+! ! ok
+ ! ok
+! !! also ok
+ !! also ok
+!
+
+!foo MACRO
+! ! you can see me
+! !! but not me
+! ! you can see me
+! !! but not me
+! but this "SHOULD !!BE OK"
+! ENDM
+!
+
+! foo
+! ! you can see me
+ ! you can see me
+!
+! ! you can see me
+ ! you can see me
+!
+! but this "SHOULD !!BE OK"
+ but this "SHOULD !!BE OK"
+!
+
+!
+
+!define MACRO val1,val2
+! DB val1 ! this comment will show up
+! DB val2 !! this on won't
+! ENDM
+!
+
+! define 0,1
+! DB 0 ! this comment will show up
+ .byte 0! this comment will show up
+! DB 1
+ .byte 1
+!
+
+!
+
+! END
diff --git a/gas/testsuite/gasp/pl3.asm b/gas/testsuite/gasp/pl3.asm
new file mode 100644
index 0000000000..0131dcc157
--- /dev/null
+++ b/gas/testsuite/gasp/pl3.asm
@@ -0,0 +1,30 @@
+ .ALTERNATE
+
+foo MACRO string
+ LOCAL lab1, lab2
+lab1: DATA.L lab2
+lab2: SDATA string
+ ENDM
+
+ foo "An example"
+ foo "using LOCAL"
+
+! test of LOCAL directive
+
+chk_err MACRO limit
+ LOCAL skip !! frob
+ LOCAL zap,dog,barf
+barf: cmp ax,limit !! check value against
+ !! limit
+ jle skip !! skip call if OK
+skip: call error
+ foo dog
+ zap dog
+ nop
+ ENDM
+
+ chk_err 5
+ chk_err 10
+
+
+ END
diff --git a/gas/testsuite/gasp/pl3.err b/gas/testsuite/gasp/pl3.err
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/gas/testsuite/gasp/pl3.err
diff --git a/gas/testsuite/gasp/pl3.out b/gas/testsuite/gasp/pl3.out
new file mode 100644
index 0000000000..066194c7e2
--- /dev/null
+++ b/gas/testsuite/gasp/pl3.out
@@ -0,0 +1,86 @@
+! .ALTERNATE
+!
+
+!foo MACRO string
+! LOCAL lab1, lab2
+!lab1: DATA.L lab2
+!lab2: SDATA string
+! ENDM
+!
+
+! foo "An example"
+!
+!LL0001: DATA.L LL0002
+LL0001: .long LL0002
+!LL0002: SDATA "An example"
+LL0002: .byte 65,110,32,101,120,97,109,112,108,101
+! foo "using LOCAL"
+!
+!LL0003: DATA.L LL0004
+LL0003: .long LL0004
+!LL0004: SDATA "using LOCAL"
+LL0004: .byte 117,115,105,110,103,32,76,79,67,65,76
+!
+
+!! test of LOCAL directive
+ ! test of LOCAL directive
+!
+
+!chk_err MACRO limit
+! LOCAL skip !! frob
+! LOCAL zap,dog,barf
+!barf: cmp ax,limit !! check value against
+! !! limit
+! jle skip !! skip call if OK
+!skip: call error
+! foo dog
+! zap dog
+! nop
+! ENDM
+!
+
+! chk_err 5
+!
+!
+!LL0008: cmp ax,5
+LL0008: cmp ax,5
+!
+! jle LL0005
+ jle LL0005
+!LL0005: call error
+LL0005: call error
+! foo LL0007
+!
+!LL0009: DATA.L LL000a
+LL0009: .long LL000a
+!LL000a: SDATA LL0007
+LL000a: .byte 76,76,48,48,48,55
+! LL0006 LL0007
+ LL0006 LL0007
+! nop
+ nop
+! chk_err 10
+!
+!
+!LL000e: cmp ax,10
+LL000e: cmp ax,10
+!
+! jle LL000b
+ jle LL000b
+!LL000b: call error
+LL000b: call error
+! foo LL000d
+!
+!LL000f: DATA.L LL0010
+LL000f: .long LL0010
+!LL0010: SDATA LL000d
+LL0010: .byte 76,76,48,48,48,100
+! LL000c LL000d
+ LL000c LL000d
+! nop
+ nop
+!
+
+!
+
+! END
diff --git a/gas/testsuite/gasp/pl4.asm b/gas/testsuite/gasp/pl4.asm
new file mode 100644
index 0000000000..f1dd3e80cd
--- /dev/null
+++ b/gas/testsuite/gasp/pl4.asm
@@ -0,0 +1,10 @@
+ .ALTERNATE
+! test of macro substitution around &s
+
+
+foo MACRO a,b
+ x&a&b
+ ENDM
+
+ foo 3 2
+ END
diff --git a/gas/testsuite/gasp/pl4.err b/gas/testsuite/gasp/pl4.err
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/gas/testsuite/gasp/pl4.err
diff --git a/gas/testsuite/gasp/pl4.out b/gas/testsuite/gasp/pl4.out
new file mode 100644
index 0000000000..35d1391d18
--- /dev/null
+++ b/gas/testsuite/gasp/pl4.out
@@ -0,0 +1,16 @@
+! .ALTERNATE
+!! test of macro substitution around &s
+ ! test of macro substitution around &s
+!
+
+!
+
+!foo MACRO a,b
+! x&a&b
+! ENDM
+!
+
+! foo 3 2
+! x32
+ x32
+! END
diff --git a/gas/testsuite/gasp/pl5.asm b/gas/testsuite/gasp/pl5.asm
new file mode 100644
index 0000000000..16b999b1fd
--- /dev/null
+++ b/gas/testsuite/gasp/pl5.asm
@@ -0,0 +1,15 @@
+! test of literal text operator
+ .ALTERNATE
+foop MACRO str1,str2
+ SDATA "str1"
+ SDATA str2
+ ENDM
+
+
+
+ foop this< is a <string> with angle brackets>
+ foop this< is a string with spaces>
+ foop this < is a string with a !>>
+
+
+ END
diff --git a/gas/testsuite/gasp/pl5.err b/gas/testsuite/gasp/pl5.err
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/gas/testsuite/gasp/pl5.err
diff --git a/gas/testsuite/gasp/pl5.out b/gas/testsuite/gasp/pl5.out
new file mode 100644
index 0000000000..0aa488b5ec
--- /dev/null
+++ b/gas/testsuite/gasp/pl5.out
@@ -0,0 +1,32 @@
+!! test of literal text operator
+ ! test of literal text operator
+! .ALTERNATE
+!foop MACRO str1,str2
+! SDATA "str1"
+! SDATA str2
+! ENDM
+!
+
+!
+
+!
+! foop this< is a <string> with angle brackets>
+! SDATA "this"
+ .byte 116,104,105,115
+! SDATA " is a <string> with angle brackets"
+ .byte 32,105,115,32,97,32,60,115,116,114,105,110,103,62,32,119,105,116,104,32,97,110,103,108,101,32,98,114,97,99,107,101,116,115
+! foop this< is a string with spaces>
+! SDATA "this"
+ .byte 116,104,105,115
+! SDATA " is a string with spaces"
+ .byte 32,105,115,32,97,32,115,116,114,105,110,103,32,119,105,116,104,32,115,112,97,99,101,115
+! foop this < is a string with a !>>
+! SDATA "this"
+ .byte 116,104,105,115
+! SDATA " is a string with a >"
+ .byte 32,105,115,32,97,32,115,116,114,105,110,103,32,119,105,116,104,32,97,32,62
+!
+
+!
+
+! END
diff --git a/gas/testsuite/gasp/pl6.asm b/gas/testsuite/gasp/pl6.asm
new file mode 100644
index 0000000000..162d617588
--- /dev/null
+++ b/gas/testsuite/gasp/pl6.asm
@@ -0,0 +1,21 @@
+ .ALTERNATE
+! test of expression operator
+define MACRO val, string
+ SDATA val
+ SDATA string
+ ENDM
+ define "1","99%of100" ! notice % within string
+ define %1 + 2, "=3"
+
+
+ define % 1 + 2 %3+4
+
+ define %3*4-2 <=10>
+
+ define %3*4-2 5
+
+ define %1 + 2,<is equal to %1 + 2, right?>
+
+ ! has no effect
+
+ end
diff --git a/gas/testsuite/gasp/pl6.err b/gas/testsuite/gasp/pl6.err
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/gas/testsuite/gasp/pl6.err
diff --git a/gas/testsuite/gasp/pl6.out b/gas/testsuite/gasp/pl6.out
new file mode 100644
index 0000000000..dcd16cf831
--- /dev/null
+++ b/gas/testsuite/gasp/pl6.out
@@ -0,0 +1,54 @@
+! .ALTERNATE
+!! test of expression operator
+ ! test of expression operator
+!define MACRO val, string
+! SDATA val
+! SDATA string
+! ENDM
+! define "1","99%of100" ! notice % within string
+! SDATA "1"
+ .byte 49
+! SDATA "99%of100"
+ .byte 57,57,37,111,102,49,48,48
+! define %1 + 2, "=3"
+! SDATA 3
+ .byte 51
+! SDATA "=3"
+ .byte 61,51
+!
+
+!
+
+! define % 1 + 2 %3+4
+! SDATA 3
+ .byte 51
+! SDATA 7
+ .byte 55
+!
+
+! define %3*4-2 <=10>
+! SDATA 10
+ .byte 49,48
+! SDATA "=10"
+ .byte 61,49,48
+!
+
+! define %3*4-2 5
+! SDATA 10
+ .byte 49,48
+! SDATA 5
+ .byte 53
+!
+
+! define %1 + 2,<is equal to %1 + 2, right?>
+! SDATA 3
+ .byte 51
+! SDATA "is equal to %1 + 2, right?"
+ .byte 105,115,32,101,113,117,97,108,32,116,111,32,37,49,32,43,32,50,44,32,114,105,103,104,116,63
+!
+
+! ! has no effect
+ ! has no effect
+!
+
+! end
diff --git a/gas/testsuite/gasp/pl7.asm b/gas/testsuite/gasp/pl7.asm
new file mode 100644
index 0000000000..58a40afe10
--- /dev/null
+++ b/gas/testsuite/gasp/pl7.asm
@@ -0,0 +1,12 @@
+ .ALTERNATE
+! test of string operators
+define MACRO str1,str2
+ SDATA str1
+ SDATA "str2"
+ENDM
+ define one" way to get "spaces,0
+ define "lot's! of <special>,chars%", 0
+
+
+
+
diff --git a/gas/testsuite/gasp/pl7.err b/gas/testsuite/gasp/pl7.err
new file mode 100644
index 0000000000..a1e3318844
--- /dev/null
+++ b/gas/testsuite/gasp/pl7.err
@@ -0,0 +1 @@
+END missing from end of file.
diff --git a/gas/testsuite/gasp/pl7.out b/gas/testsuite/gasp/pl7.out
new file mode 100644
index 0000000000..1519b3430c
--- /dev/null
+++ b/gas/testsuite/gasp/pl7.out
@@ -0,0 +1,26 @@
+! .ALTERNATE
+!! test of string operators
+ ! test of string operators
+!define MACRO str1,str2
+! SDATA str1
+! SDATA "str2"
+!ENDM
+! define one" way to get "spaces,0
+! SDATA one" way to get "spaces
+ .byte 111,110,101,34,32,119,97,121,32,116,111,32,103,101,116,32,34,115,112,97,99,101,115
+! SDATA "0"
+ .byte 48
+! define "lot's! of <special>,chars%", 0
+! SDATA "lot's of <special>,chars%"
+ .byte 108,111,116,39,115,32,111,102,32,60,115,112,101,99,105,97,108,62,44,99,104,97,114,115,37
+! SDATA "0"
+ .byte 48
+!
+
+!
+
+!
+
+!
+
+! \ No newline at end of file
diff --git a/gas/testsuite/gasp/pl8.asm b/gas/testsuite/gasp/pl8.asm
new file mode 100644
index 0000000000..925b172397
--- /dev/null
+++ b/gas/testsuite/gasp/pl8.asm
@@ -0,0 +1,18 @@
+
+ .ALTERNATE
+ SDATA %1+2+3
+ SDATA "5"
+
+
+
+ MACRO foo
+ SDATA "HI" !! this will go
+ SDATA "THERE ! this will stay
+ ENDM
+
+ foo
+
+
+ SDATA <!<this is <a wacky> example!>!!>
+ SDATA "<this is <a wacky> example>!"
+ END
diff --git a/gas/testsuite/gasp/pl8.err b/gas/testsuite/gasp/pl8.err
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/gas/testsuite/gasp/pl8.err
diff --git a/gas/testsuite/gasp/pl8.out b/gas/testsuite/gasp/pl8.out
new file mode 100644
index 0000000000..3710412330
--- /dev/null
+++ b/gas/testsuite/gasp/pl8.out
@@ -0,0 +1,33 @@
+!
+
+! .ALTERNATE
+! SDATA %1+2+3
+ .byte 37,49,43,50,43,51,32
+! SDATA "5"
+ .byte 53
+!
+
+!
+
+!
+
+! MACRO foo
+! SDATA "HI" !! this will go
+! SDATA "THERE ! this will stay
+! ENDM
+!
+
+! foo
+! SDATA "HI"
+ .byte 72,73
+! SDATA "THERE ! this will stay
+ .byte 84,72,69,82,69,9,32,116,104,105,115,32,119,105,108,108,32,115,116,97,121
+!
+
+!
+
+! SDATA <!<this is <a wacky> example!>!!>
+ .byte 60,116,104,105,115,32,105,115,32,60,97,32,119,97,99,107,121,62,32,101,120,97,109,112,108,101,62,33
+! SDATA "<this is <a wacky> example>!"
+ .byte 60,116,104,105,115,32,105,115,32,60,97,32,119,97,99,107,121,62,32,101,120,97,109,112,108,101,62,34
+! END
diff --git a/gas/testsuite/gasp/pr7583.asm b/gas/testsuite/gasp/pr7583.asm
new file mode 100644
index 0000000000..c97caf546d
--- /dev/null
+++ b/gas/testsuite/gasp/pr7583.asm
@@ -0,0 +1,3 @@
+
+ .sdata "v1.0000"
+ .end
diff --git a/gas/testsuite/gasp/pr7583.err b/gas/testsuite/gasp/pr7583.err
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/gas/testsuite/gasp/pr7583.err
diff --git a/gas/testsuite/gasp/pr7583.out b/gas/testsuite/gasp/pr7583.out
new file mode 100644
index 0000000000..a5df1d7f58
--- /dev/null
+++ b/gas/testsuite/gasp/pr7583.out
@@ -0,0 +1,5 @@
+!
+
+! .sdata "v1.0000"
+ .byte 118,49,46,48,48,48,48
+! .end
diff --git a/gas/testsuite/gasp/reg.asm b/gas/testsuite/gasp/reg.asm
new file mode 100644
index 0000000000..eb463ed7e7
--- /dev/null
+++ b/gas/testsuite/gasp/reg.asm
@@ -0,0 +1,9 @@
+
+
+foo .REG (r1)
+ add foo,foo
+
+bar .reg (r2)
+ add bar,foo
+
+ .END
diff --git a/gas/testsuite/gasp/reg.err b/gas/testsuite/gasp/reg.err
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/gas/testsuite/gasp/reg.err
diff --git a/gas/testsuite/gasp/reg.out b/gas/testsuite/gasp/reg.out
new file mode 100644
index 0000000000..79268a36bd
--- /dev/null
+++ b/gas/testsuite/gasp/reg.out
@@ -0,0 +1,15 @@
+!
+
+!
+
+!foo .REG (r1)
+! add foo,foo
+ add r1,r1
+!
+
+!bar .reg (r2)
+! add bar,foo
+ add r2,r1
+!
+
+! .END
diff --git a/gas/testsuite/gasp/rep.asm b/gas/testsuite/gasp/rep.asm
new file mode 100644
index 0000000000..027ac47080
--- /dev/null
+++ b/gas/testsuite/gasp/rep.asm
@@ -0,0 +1,13 @@
+ .AREPEAT 5
+ FIVE
+ .AREPEAT 2
+ TWO
+ .AENDR
+ .AREPEAT 3
+ THREE
+ .AREPEAT 2
+ TWO
+ .AENDR
+ .AENDR
+ .AENDR
+ .END
diff --git a/gas/testsuite/gasp/rep.err b/gas/testsuite/gasp/rep.err
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/gas/testsuite/gasp/rep.err
diff --git a/gas/testsuite/gasp/rep.out b/gas/testsuite/gasp/rep.out
new file mode 100644
index 0000000000..510d0e1777
--- /dev/null
+++ b/gas/testsuite/gasp/rep.out
@@ -0,0 +1,391 @@
+! .AREPEAT 5
+! FIVE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AREPEAT 3
+! THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AENDR
+! .AENDR
+! FIVE
+ FIVE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 3
+! THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AENDR
+! THREE
+ THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 2
+! THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AENDR
+! THREE
+ THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AENDR
+! THREE
+ THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 4
+! FIVE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AREPEAT 3
+! THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AENDR
+! .AENDR
+! FIVE
+ FIVE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 3
+! THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AENDR
+! THREE
+ THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 2
+! THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AENDR
+! THREE
+ THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AENDR
+! THREE
+ THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 3
+! FIVE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AREPEAT 3
+! THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AENDR
+! .AENDR
+! FIVE
+ FIVE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 3
+! THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AENDR
+! THREE
+ THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 2
+! THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AENDR
+! THREE
+ THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AENDR
+! THREE
+ THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 2
+! FIVE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AREPEAT 3
+! THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AENDR
+! .AENDR
+! FIVE
+ FIVE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 3
+! THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AENDR
+! THREE
+ THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 2
+! THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AENDR
+! THREE
+ THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AENDR
+! THREE
+ THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! FIVE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AREPEAT 3
+! THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AENDR
+! .AENDR
+! FIVE
+ FIVE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 3
+! THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AENDR
+! THREE
+ THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 2
+! THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AENDR
+! THREE
+ THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! .AENDR
+! THREE
+ THREE
+! .AREPEAT 2
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .AREPEAT 1
+! TWO
+! .AENDR
+! TWO
+ TWO
+! .END
diff --git a/gas/testsuite/gasp/repeat.asm b/gas/testsuite/gasp/repeat.asm
new file mode 100644
index 0000000000..7a85da314a
--- /dev/null
+++ b/gas/testsuite/gasp/repeat.asm
@@ -0,0 +1,14 @@
+
+ .AREPEAT 10
+ TEN
+ .AREPEAT 2
+ TWENTY
+ .AENDR
+ .AENDR
+
+ .AREPEAT 3
+ ROTCL R2
+ DIV1 R0,R1
+ .AENDR
+
+ .END
diff --git a/gas/testsuite/gasp/repeat.err b/gas/testsuite/gasp/repeat.err
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/gas/testsuite/gasp/repeat.err
diff --git a/gas/testsuite/gasp/repeat.out b/gas/testsuite/gasp/repeat.out
new file mode 100644
index 0000000000..705d8d88e4
--- /dev/null
+++ b/gas/testsuite/gasp/repeat.out
@@ -0,0 +1,211 @@
+!
+
+! .AREPEAT 10
+! TEN
+! .AREPEAT 2
+! TWENTY
+! .AENDR
+! .AENDR
+! TEN
+ TEN
+! .AREPEAT 2
+! TWENTY
+! .AENDR
+! TWENTY
+ TWENTY
+! .AREPEAT 1
+! TWENTY
+! .AENDR
+! TWENTY
+ TWENTY
+! .AREPEAT 9
+! TEN
+! .AREPEAT 2
+! TWENTY
+! .AENDR
+! .AENDR
+! TEN
+ TEN
+! .AREPEAT 2
+! TWENTY
+! .AENDR
+! TWENTY
+ TWENTY
+! .AREPEAT 1
+! TWENTY
+! .AENDR
+! TWENTY
+ TWENTY
+! .AREPEAT 8
+! TEN
+! .AREPEAT 2
+! TWENTY
+! .AENDR
+! .AENDR
+! TEN
+ TEN
+! .AREPEAT 2
+! TWENTY
+! .AENDR
+! TWENTY
+ TWENTY
+! .AREPEAT 1
+! TWENTY
+! .AENDR
+! TWENTY
+ TWENTY
+! .AREPEAT 7
+! TEN
+! .AREPEAT 2
+! TWENTY
+! .AENDR
+! .AENDR
+! TEN
+ TEN
+! .AREPEAT 2
+! TWENTY
+! .AENDR
+! TWENTY
+ TWENTY
+! .AREPEAT 1
+! TWENTY
+! .AENDR
+! TWENTY
+ TWENTY
+! .AREPEAT 6
+! TEN
+! .AREPEAT 2
+! TWENTY
+! .AENDR
+! .AENDR
+! TEN
+ TEN
+! .AREPEAT 2
+! TWENTY
+! .AENDR
+! TWENTY
+ TWENTY
+! .AREPEAT 1
+! TWENTY
+! .AENDR
+! TWENTY
+ TWENTY
+! .AREPEAT 5
+! TEN
+! .AREPEAT 2
+! TWENTY
+! .AENDR
+! .AENDR
+! TEN
+ TEN
+! .AREPEAT 2
+! TWENTY
+! .AENDR
+! TWENTY
+ TWENTY
+! .AREPEAT 1
+! TWENTY
+! .AENDR
+! TWENTY
+ TWENTY
+! .AREPEAT 4
+! TEN
+! .AREPEAT 2
+! TWENTY
+! .AENDR
+! .AENDR
+! TEN
+ TEN
+! .AREPEAT 2
+! TWENTY
+! .AENDR
+! TWENTY
+ TWENTY
+! .AREPEAT 1
+! TWENTY
+! .AENDR
+! TWENTY
+ TWENTY
+! .AREPEAT 3
+! TEN
+! .AREPEAT 2
+! TWENTY
+! .AENDR
+! .AENDR
+! TEN
+ TEN
+! .AREPEAT 2
+! TWENTY
+! .AENDR
+! TWENTY
+ TWENTY
+! .AREPEAT 1
+! TWENTY
+! .AENDR
+! TWENTY
+ TWENTY
+! .AREPEAT 2
+! TEN
+! .AREPEAT 2
+! TWENTY
+! .AENDR
+! .AENDR
+! TEN
+ TEN
+! .AREPEAT 2
+! TWENTY
+! .AENDR
+! TWENTY
+ TWENTY
+! .AREPEAT 1
+! TWENTY
+! .AENDR
+! TWENTY
+ TWENTY
+! .AREPEAT 1
+! TEN
+! .AREPEAT 2
+! TWENTY
+! .AENDR
+! .AENDR
+! TEN
+ TEN
+! .AREPEAT 2
+! TWENTY
+! .AENDR
+! TWENTY
+ TWENTY
+! .AREPEAT 1
+! TWENTY
+! .AENDR
+! TWENTY
+ TWENTY
+!
+
+! .AREPEAT 3
+! ROTCL R2
+! DIV1 R0,R1
+! .AENDR
+! ROTCL R2
+ ROTCL R2
+! DIV1 R0,R1
+ DIV1 R0,R1
+! .AREPEAT 2
+! ROTCL R2
+! DIV1 R0,R1
+! .AENDR
+! ROTCL R2
+ ROTCL R2
+! DIV1 R0,R1
+ DIV1 R0,R1
+! .AREPEAT 1
+! ROTCL R2
+! DIV1 R0,R1
+! .AENDR
+! ROTCL R2
+ ROTCL R2
+! DIV1 R0,R1
+ DIV1 R0,R1
+!
+
+! .END
diff --git a/gas/testsuite/gasp/reperr.asm b/gas/testsuite/gasp/reperr.asm
new file mode 100644
index 0000000000..60882b2299
--- /dev/null
+++ b/gas/testsuite/gasp/reperr.asm
@@ -0,0 +1,2 @@
+
+ .REPEAT 10
diff --git a/gas/testsuite/gasp/reperr.err b/gas/testsuite/gasp/reperr.err
new file mode 100644
index 0000000000..a1e3318844
--- /dev/null
+++ b/gas/testsuite/gasp/reperr.err
@@ -0,0 +1 @@
+END missing from end of file.
diff --git a/gas/testsuite/gasp/reperr.out b/gas/testsuite/gasp/reperr.out
new file mode 100644
index 0000000000..2c9f8c6a91
--- /dev/null
+++ b/gas/testsuite/gasp/reperr.out
@@ -0,0 +1,5 @@
+!
+
+! .REPEAT 10
+ .REPEAT 10
+! \ No newline at end of file
diff --git a/gas/testsuite/gasp/reperr1.asm b/gas/testsuite/gasp/reperr1.asm
new file mode 100644
index 0000000000..2d987e48f4
--- /dev/null
+++ b/gas/testsuite/gasp/reperr1.asm
@@ -0,0 +1,3 @@
+
+ .AREPEAT 10
+ .END
diff --git a/gas/testsuite/gasp/reperr1.err b/gas/testsuite/gasp/reperr1.err
new file mode 100644
index 0000000000..536545be1d
--- /dev/null
+++ b/gas/testsuite/gasp/reperr1.err
@@ -0,0 +1 @@
+End of file whilst inside AREPEAT, started on line 3.
diff --git a/gas/testsuite/gasp/reperr1.out b/gas/testsuite/gasp/reperr1.out
new file mode 100644
index 0000000000..dd82880b36
--- /dev/null
+++ b/gas/testsuite/gasp/reperr1.out
@@ -0,0 +1,5 @@
+!
+
+! .AREPEAT 10
+! .END
+! \ No newline at end of file
diff --git a/gas/testsuite/gasp/reperr2.asm b/gas/testsuite/gasp/reperr2.asm
new file mode 100644
index 0000000000..de06a71217
--- /dev/null
+++ b/gas/testsuite/gasp/reperr2.asm
@@ -0,0 +1,6 @@
+
+ .AREPEAT 5
+ .AENDR
+ .AENDR
+ .END
+
diff --git a/gas/testsuite/gasp/reperr2.err b/gas/testsuite/gasp/reperr2.err
new file mode 100644
index 0000000000..840ccc5237
--- /dev/null
+++ b/gas/testsuite/gasp/reperr2.err
@@ -0,0 +1 @@
+reperr2.asm:4 AENDR without a AREPEAT.
diff --git a/gas/testsuite/gasp/reperr2.out b/gas/testsuite/gasp/reperr2.out
new file mode 100644
index 0000000000..df7a84d584
--- /dev/null
+++ b/gas/testsuite/gasp/reperr2.out
@@ -0,0 +1,14 @@
+!
+
+! .AREPEAT 5
+! .AENDR
+! .AREPEAT 4
+! .AENDR
+! .AREPEAT 3
+! .AENDR
+! .AREPEAT 2
+! .AENDR
+! .AREPEAT 1
+! .AENDR
+! .AENDR
+! .END
diff --git a/gas/testsuite/gasp/reperr3.asm b/gas/testsuite/gasp/reperr3.asm
new file mode 100644
index 0000000000..464bc79ba3
--- /dev/null
+++ b/gas/testsuite/gasp/reperr3.asm
@@ -0,0 +1,21 @@
+ .AREPEAT 4
+ .AREPEAT 4
+ .AREPEAT 4
+ .AREPEAT 4
+ stuff
+ .AENDR
+ which
+ .AENDR
+ will
+ .AENDR
+ get
+ .AENDR
+ repetaed
+ .AENDR
+
+ .AENDR
+ .AENDR
+ .AENDR
+ .AENDR
+ .AENDR
+ .END
diff --git a/gas/testsuite/gasp/reperr3.err b/gas/testsuite/gasp/reperr3.err
new file mode 100644
index 0000000000..1be0dceecf
--- /dev/null
+++ b/gas/testsuite/gasp/reperr3.err
@@ -0,0 +1,6 @@
+reperr3.asm:14 AENDR without a AREPEAT.
+reperr3.asm:16 AENDR without a AREPEAT.
+reperr3.asm:17 AENDR without a AREPEAT.
+reperr3.asm:18 AENDR without a AREPEAT.
+reperr3.asm:19 AENDR without a AREPEAT.
+reperr3.asm:20 AENDR without a AREPEAT.
diff --git a/gas/testsuite/gasp/reperr3.out b/gas/testsuite/gasp/reperr3.out
new file mode 100644
index 0000000000..9a3513b7ba
--- /dev/null
+++ b/gas/testsuite/gasp/reperr3.out
@@ -0,0 +1,2035 @@
+! .AREPEAT 4
+! .AREPEAT 4
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! will
+! .AENDR
+! get
+! .AENDR
+! .AREPEAT 4
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! will
+! .AENDR
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 3
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 2
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 1
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! will
+ will
+! .AREPEAT 3
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! will
+! .AENDR
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 3
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 2
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 1
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! will
+ will
+! .AREPEAT 2
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! will
+! .AENDR
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 3
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 2
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 1
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! will
+ will
+! .AREPEAT 1
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! will
+! .AENDR
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 3
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 2
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 1
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! will
+ will
+! get
+ get
+! .AREPEAT 3
+! .AREPEAT 4
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! will
+! .AENDR
+! get
+! .AENDR
+! .AREPEAT 4
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! will
+! .AENDR
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 3
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 2
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 1
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! will
+ will
+! .AREPEAT 3
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! will
+! .AENDR
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 3
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 2
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 1
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! will
+ will
+! .AREPEAT 2
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! will
+! .AENDR
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 3
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 2
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 1
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! will
+ will
+! .AREPEAT 1
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! will
+! .AENDR
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 3
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 2
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 1
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! will
+ will
+! get
+ get
+! .AREPEAT 2
+! .AREPEAT 4
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! will
+! .AENDR
+! get
+! .AENDR
+! .AREPEAT 4
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! will
+! .AENDR
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 3
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 2
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 1
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! will
+ will
+! .AREPEAT 3
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! will
+! .AENDR
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 3
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 2
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 1
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! will
+ will
+! .AREPEAT 2
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! will
+! .AENDR
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 3
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 2
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 1
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! will
+ will
+! .AREPEAT 1
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! will
+! .AENDR
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 3
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 2
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 1
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! will
+ will
+! get
+ get
+! .AREPEAT 1
+! .AREPEAT 4
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! will
+! .AENDR
+! get
+! .AENDR
+! .AREPEAT 4
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! will
+! .AENDR
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 3
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 2
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 1
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! will
+ will
+! .AREPEAT 3
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! will
+! .AENDR
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 3
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 2
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 1
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! will
+ will
+! .AREPEAT 2
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! will
+! .AENDR
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 3
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 2
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 1
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! will
+ will
+! .AREPEAT 1
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! will
+! .AENDR
+! .AREPEAT 4
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 3
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 2
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! .AREPEAT 1
+! .AREPEAT 4
+! stuff
+! .AENDR
+! which
+! .AENDR
+! .AREPEAT 4
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 3
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 2
+! stuff
+! .AENDR
+! stuff
+ stuff
+! .AREPEAT 1
+! stuff
+! .AENDR
+! stuff
+ stuff
+! which
+ which
+! will
+ will
+! get
+ get
+! repetaed
+ repetaed
+! .AENDR
+!
+
+! .AENDR
+! .AENDR
+! .AENDR
+! .AENDR
+! .AENDR
+! .END
diff --git a/gas/testsuite/gasp/sdata.asm b/gas/testsuite/gasp/sdata.asm
new file mode 100644
index 0000000000..d6bd23c245
--- /dev/null
+++ b/gas/testsuite/gasp/sdata.asm
@@ -0,0 +1,24 @@
+
+
+ .SDATA "HI","STEVE"
+ .SDATA "HI" , "STEVE" , <72>,<73>,<83><69><86><69>
+
+ .SDATA "H""I" , "STEVE" , <72>,<73>,<83><69><86><69>
+
+
+
+ .SDATA "SHOULD NOT FAIL" "HERE"
+ .SDATA "SHOULD FAIL" foo "HERE"
+
+ .SDATAB 8,"BOINK"
+
+ ; examples from book
+
+ .SDATAB 2,"AAAAA"
+ .SDATAB 2,"""BBB"""
+ .SDATAB 2,"AABB"<H'07>
+
+
+a1: .SDATAZ "HI"
+a2: .SDATAC "HI"
+a3: .SDATA "HI"
diff --git a/gas/testsuite/gasp/sdata.err b/gas/testsuite/gasp/sdata.err
new file mode 100644
index 0000000000..7544ccc957
--- /dev/null
+++ b/gas/testsuite/gasp/sdata.err
@@ -0,0 +1,3 @@
+sdata.asm:19 Character code in string must be absolute expression.
+sdata.asm:19 Missing > for character code.
+END missing from end of file.
diff --git a/gas/testsuite/gasp/sdata.out b/gas/testsuite/gasp/sdata.out
new file mode 100644
index 0000000000..e689d35e82
--- /dev/null
+++ b/gas/testsuite/gasp/sdata.out
@@ -0,0 +1,59 @@
+!
+
+!
+
+! .SDATA "HI","STEVE"
+ .byte 72,73,83,84,69,86,69
+! .SDATA "HI" , "STEVE" , <72>,<73>,<83><69><86><69>
+ .byte 72,73,83,84,69,86,69,72,73,83,69,86,69
+!
+
+! .SDATA "H""I" , "STEVE" , <72>,<73>,<83><69><86><69>
+ .byte 72,34,73,83,84,69,86,69,72,73,83,69,86,69
+!
+
+!
+
+!
+
+! .SDATA "SHOULD NOT FAIL" "HERE"
+ .byte 83,72,79,85,76,68,32,78,79,84,32,70,65,73,76,72,69,82,69
+! .SDATA "SHOULD FAIL" foo "HERE"
+ .byte 83,72,79,85,76,68,32,70,65,73,76,102,111,111,32,34,72,69,82,69,34,32
+!
+
+! .SDATAB 8,"BOINK"
+ .byte 66,79,73,78,75
+ .byte 66,79,73,78,75
+ .byte 66,79,73,78,75
+ .byte 66,79,73,78,75
+ .byte 66,79,73,78,75
+ .byte 66,79,73,78,75
+ .byte 66,79,73,78,75
+ .byte 66,79,73,78,75
+!
+
+! ; examples from book
+ ; examples from book
+!
+
+! .SDATAB 2,"AAAAA"
+ .byte 65,65,65,65,65
+ .byte 65,65,65,65,65
+! .SDATAB 2,"""BBB"""
+ .byte 34,66,66,66,34
+ .byte 34,66,66,66,34
+! .SDATAB 2,"AABB"<H'07>
+ .byte 65,65,66,66,0
+ .byte 65,65,66,66,0
+!
+
+!
+
+!a1: .SDATAZ "HI"
+a1: .byte 72,73,0
+!a2: .SDATAC "HI"
+a2: .byte 2,72,73
+!a3: .SDATA "HI"
+a3: .byte 72,73
+! \ No newline at end of file
diff --git a/gas/testsuite/gasp/sfunc.asm b/gas/testsuite/gasp/sfunc.asm
new file mode 100644
index 0000000000..b59949a9d1
--- /dev/null
+++ b/gas/testsuite/gasp/sfunc.asm
@@ -0,0 +1,26 @@
+
+ .MACRO RESERVE_STR P1=0 P2
+ .SDATA .SUBSTR("ABCDEFG",\P1,\P2)
+ .ENDM
+
+ RESERVE_STR 2,2
+ RESERVE_STR ,3
+
+
+ .MACRO FIND_STR P1
+ .DATA.W .INSTR("ABCDEFG","\P1", 0)
+ .ENDM
+
+ FIND_STR CDE
+ FIND_STR H
+
+ .MACRO RESERVE_LENGTH P1
+ .ALIGN 4
+ .SRES .LEN("\P1")
+ .ENDM
+
+ RESERVE_LENGTH ABCDEF
+ RESERVE_LENGTH ABC
+
+ .END
+
diff --git a/gas/testsuite/gasp/sfunc.err b/gas/testsuite/gasp/sfunc.err
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/gas/testsuite/gasp/sfunc.err
diff --git a/gas/testsuite/gasp/sfunc.out b/gas/testsuite/gasp/sfunc.out
new file mode 100644
index 0000000000..50f694ff99
--- /dev/null
+++ b/gas/testsuite/gasp/sfunc.out
@@ -0,0 +1,49 @@
+!
+
+! .MACRO RESERVE_STR P1=0 P2
+! .SDATA .SUBSTR("ABCDEFG",\P1,\P2)
+! .ENDM
+!
+
+! RESERVE_STR 2,2
+! .SDATA .SUBSTR("ABCDEFG",2,2)
+ .byte 67,68
+! RESERVE_STR ,3
+! .SDATA .SUBSTR("ABCDEFG",0,3)
+ .byte 65,66,67
+!
+
+!
+
+! .MACRO FIND_STR P1
+! .DATA.W .INSTR("ABCDEFG","\P1", 0)
+! .ENDM
+!
+
+! FIND_STR CDE
+! .DATA.W .INSTR("ABCDEFG","CDE", 0)
+ .short 2
+! FIND_STR H
+! .DATA.W .INSTR("ABCDEFG","H", 0)
+ .short -1
+!
+
+! .MACRO RESERVE_LENGTH P1
+! .ALIGN 4
+! .SRES .LEN("\P1")
+! .ENDM
+!
+
+! RESERVE_LENGTH ABCDEF
+! .ALIGN 4
+ .align 4
+! .SRES .LEN("ABCDEF")
+ .space 24
+! RESERVE_LENGTH ABC
+! .ALIGN 4
+ .align 4
+! .SRES .LEN("ABC")
+ .space 12
+!
+
+! .END
diff --git a/gas/testsuite/gasp/t1.asm b/gas/testsuite/gasp/t1.asm
new file mode 100644
index 0000000000..df54c6cdf2
--- /dev/null
+++ b/gas/testsuite/gasp/t1.asm
@@ -0,0 +1,3 @@
+
+ test for eof in middle of line
+ .END
diff --git a/gas/testsuite/gasp/t1.err b/gas/testsuite/gasp/t1.err
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/gas/testsuite/gasp/t1.err
diff --git a/gas/testsuite/gasp/t1.out b/gas/testsuite/gasp/t1.out
new file mode 100644
index 0000000000..39230e1680
--- /dev/null
+++ b/gas/testsuite/gasp/t1.out
@@ -0,0 +1,5 @@
+!
+
+! test for eof in middle of line
+ test for eof in middle of line
+! .END
diff --git a/gas/testsuite/gasp/t2.asm b/gas/testsuite/gasp/t2.asm
new file mode 100644
index 0000000000..38a351a775
--- /dev/null
+++ b/gas/testsuite/gasp/t2.asm
@@ -0,0 +1,8 @@
+
+
+ test
++ continued
++ lines
+
+
+ .END
diff --git a/gas/testsuite/gasp/t2.err b/gas/testsuite/gasp/t2.err
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/gas/testsuite/gasp/t2.err
diff --git a/gas/testsuite/gasp/t2.out b/gas/testsuite/gasp/t2.out
new file mode 100644
index 0000000000..0c44e8bc1d
--- /dev/null
+++ b/gas/testsuite/gasp/t2.out
@@ -0,0 +1,13 @@
+!
+
+!
+
+! test
+!+continued
+!+lines
+ testcontinuedlines
+!
+
+!
+
+! .END
diff --git a/gas/testsuite/gasp/t3.asm b/gas/testsuite/gasp/t3.asm
new file mode 100644
index 0000000000..27702db8c8
--- /dev/null
+++ b/gas/testsuite/gasp/t3.asm
@@ -0,0 +1,12 @@
+
+ test base convertions
+
+ B'1001000
+ Q'210
+ D'136
+ H'88
+
+ FOOB'1001000BAR
+ FOOQ'210BAR
+ FOOD'136BAR
+ FOOH'88BAR
diff --git a/gas/testsuite/gasp/t3.err b/gas/testsuite/gasp/t3.err
new file mode 100644
index 0000000000..a1e3318844
--- /dev/null
+++ b/gas/testsuite/gasp/t3.err
@@ -0,0 +1 @@
+END missing from end of file.
diff --git a/gas/testsuite/gasp/t3.out b/gas/testsuite/gasp/t3.out
new file mode 100644
index 0000000000..8ad150bfcd
--- /dev/null
+++ b/gas/testsuite/gasp/t3.out
@@ -0,0 +1,25 @@
+!
+
+! test base convertions
+ test base convertions
+!
+
+! B'1001000
+ 72
+! Q'210
+ 136
+! D'136
+ 136
+! H'88
+ 136
+!
+
+! FOOB'1001000BAR
+ FOOB'1001000BAR
+! FOOQ'210BAR
+ FOOQ'210BAR
+! FOOD'136BAR
+ FOOD'136BAR
+! FOOH'88BAR
+ FOOH'88BAR
+! \ No newline at end of file
diff --git a/gas/testsuite/gasp/while.asm b/gas/testsuite/gasp/while.asm
new file mode 100644
index 0000000000..09143ccd81
--- /dev/null
+++ b/gas/testsuite/gasp/while.asm
@@ -0,0 +1,18 @@
+ donkey
+bar .ASSIGNA 0
+ .AWHILE \&bar LT 5
+ HI BAR IS \&bar
+foo .ASSIGNA 0
+ .AWHILE \&foo LT 2
+ HI BEFORE
+ .AREPEAT 2
+ HI MEDIUM \&foo \&bar
+ .AENDR
+ HI AFTER
+foo .ASSIGNA \&foo + 1
+ .AENDW
+bar .ASSIGNA \&bar + 1
+ AND ITS NOW \&bar
+ .AENDW
+ .END
+
diff --git a/gas/testsuite/gasp/while.err b/gas/testsuite/gasp/while.err
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/gas/testsuite/gasp/while.err
diff --git a/gas/testsuite/gasp/while.out b/gas/testsuite/gasp/while.out
new file mode 100644
index 0000000000..128aeb1a6d
--- /dev/null
+++ b/gas/testsuite/gasp/while.out
@@ -0,0 +1,388 @@
+! donkey
+ donkey
+!bar .ASSIGNA 0
+! .AWHILE \&bar LT 5
+! HI BAR IS \&bar
+!foo .ASSIGNA 0
+! .AWHILE \&foo LT 2
+! HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AENDW
+!bar .ASSIGNA \&bar + 1
+! AND ITS NOW \&bar
+! .AENDW
+! HI BAR IS \&bar
+ HI BAR IS 0
+!foo .ASSIGNA 0
+! .AWHILE \&foo LT 2
+! HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AENDW
+! HI BEFORE
+ HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI MEDIUM \&foo \&bar
+ HI MEDIUM 0 0
+! .AREPEAT 1
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI MEDIUM \&foo \&bar
+ HI MEDIUM 0 0
+! HI AFTER
+ HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AWHILE \&foo LT 2
+! HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AENDW
+! HI BEFORE
+ HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI MEDIUM \&foo \&bar
+ HI MEDIUM 1 0
+! .AREPEAT 1
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI MEDIUM \&foo \&bar
+ HI MEDIUM 1 0
+! HI AFTER
+ HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AWHILE \&foo LT 2
+! HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AENDW
+!bar .ASSIGNA \&bar + 1
+! AND ITS NOW \&bar
+ AND ITS NOW 1
+! .AWHILE \&bar LT 5
+! HI BAR IS \&bar
+!foo .ASSIGNA 0
+! .AWHILE \&foo LT 2
+! HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AENDW
+!bar .ASSIGNA \&bar + 1
+! AND ITS NOW \&bar
+! .AENDW
+! HI BAR IS \&bar
+ HI BAR IS 1
+!foo .ASSIGNA 0
+! .AWHILE \&foo LT 2
+! HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AENDW
+! HI BEFORE
+ HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI MEDIUM \&foo \&bar
+ HI MEDIUM 0 1
+! .AREPEAT 1
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI MEDIUM \&foo \&bar
+ HI MEDIUM 0 1
+! HI AFTER
+ HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AWHILE \&foo LT 2
+! HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AENDW
+! HI BEFORE
+ HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI MEDIUM \&foo \&bar
+ HI MEDIUM 1 1
+! .AREPEAT 1
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI MEDIUM \&foo \&bar
+ HI MEDIUM 1 1
+! HI AFTER
+ HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AWHILE \&foo LT 2
+! HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AENDW
+!bar .ASSIGNA \&bar + 1
+! AND ITS NOW \&bar
+ AND ITS NOW 2
+! .AWHILE \&bar LT 5
+! HI BAR IS \&bar
+!foo .ASSIGNA 0
+! .AWHILE \&foo LT 2
+! HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AENDW
+!bar .ASSIGNA \&bar + 1
+! AND ITS NOW \&bar
+! .AENDW
+! HI BAR IS \&bar
+ HI BAR IS 2
+!foo .ASSIGNA 0
+! .AWHILE \&foo LT 2
+! HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AENDW
+! HI BEFORE
+ HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI MEDIUM \&foo \&bar
+ HI MEDIUM 0 2
+! .AREPEAT 1
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI MEDIUM \&foo \&bar
+ HI MEDIUM 0 2
+! HI AFTER
+ HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AWHILE \&foo LT 2
+! HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AENDW
+! HI BEFORE
+ HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI MEDIUM \&foo \&bar
+ HI MEDIUM 1 2
+! .AREPEAT 1
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI MEDIUM \&foo \&bar
+ HI MEDIUM 1 2
+! HI AFTER
+ HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AWHILE \&foo LT 2
+! HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AENDW
+!bar .ASSIGNA \&bar + 1
+! AND ITS NOW \&bar
+ AND ITS NOW 3
+! .AWHILE \&bar LT 5
+! HI BAR IS \&bar
+!foo .ASSIGNA 0
+! .AWHILE \&foo LT 2
+! HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AENDW
+!bar .ASSIGNA \&bar + 1
+! AND ITS NOW \&bar
+! .AENDW
+! HI BAR IS \&bar
+ HI BAR IS 3
+!foo .ASSIGNA 0
+! .AWHILE \&foo LT 2
+! HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AENDW
+! HI BEFORE
+ HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI MEDIUM \&foo \&bar
+ HI MEDIUM 0 3
+! .AREPEAT 1
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI MEDIUM \&foo \&bar
+ HI MEDIUM 0 3
+! HI AFTER
+ HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AWHILE \&foo LT 2
+! HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AENDW
+! HI BEFORE
+ HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI MEDIUM \&foo \&bar
+ HI MEDIUM 1 3
+! .AREPEAT 1
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI MEDIUM \&foo \&bar
+ HI MEDIUM 1 3
+! HI AFTER
+ HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AWHILE \&foo LT 2
+! HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AENDW
+!bar .ASSIGNA \&bar + 1
+! AND ITS NOW \&bar
+ AND ITS NOW 4
+! .AWHILE \&bar LT 5
+! HI BAR IS \&bar
+!foo .ASSIGNA 0
+! .AWHILE \&foo LT 2
+! HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AENDW
+!bar .ASSIGNA \&bar + 1
+! AND ITS NOW \&bar
+! .AENDW
+! HI BAR IS \&bar
+ HI BAR IS 4
+!foo .ASSIGNA 0
+! .AWHILE \&foo LT 2
+! HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AENDW
+! HI BEFORE
+ HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI MEDIUM \&foo \&bar
+ HI MEDIUM 0 4
+! .AREPEAT 1
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI MEDIUM \&foo \&bar
+ HI MEDIUM 0 4
+! HI AFTER
+ HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AWHILE \&foo LT 2
+! HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AENDW
+! HI BEFORE
+ HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI MEDIUM \&foo \&bar
+ HI MEDIUM 1 4
+! .AREPEAT 1
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI MEDIUM \&foo \&bar
+ HI MEDIUM 1 4
+! HI AFTER
+ HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AWHILE \&foo LT 2
+! HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AENDW
+!bar .ASSIGNA \&bar + 1
+! AND ITS NOW \&bar
+ AND ITS NOW 5
+! .AWHILE \&bar LT 5
+! HI BAR IS \&bar
+!foo .ASSIGNA 0
+! .AWHILE \&foo LT 2
+! HI BEFORE
+! .AREPEAT 2
+! HI MEDIUM \&foo \&bar
+! .AENDR
+! HI AFTER
+!foo .ASSIGNA \&foo + 1
+! .AENDW
+!bar .ASSIGNA \&bar + 1
+! AND ITS NOW \&bar
+! .AENDW
+! .END
diff --git a/gas/testsuite/lib/doboth b/gas/testsuite/lib/doboth
new file mode 100755
index 0000000000..bcb837cff2
--- /dev/null
+++ b/gas/testsuite/lib/doboth
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+x=$1 ; shift
+y=$1 ; shift
+
+rm tmp.0 > /dev/null 2>&1
+ln -s $x tmp.0
+$* tmp.0 > tmp.1
+
+rm tmp.0
+ln -s $y tmp.0
+$* tmp.0 > tmp.2
+
+rm tmp.0
+
+diff -c tmp.1 tmp.2
+exit
+
+#eof
diff --git a/gas/testsuite/lib/doobjcmp b/gas/testsuite/lib/doobjcmp
new file mode 100755
index 0000000000..35c32da0de
--- /dev/null
+++ b/gas/testsuite/lib/doobjcmp
@@ -0,0 +1,88 @@
+#!/bin/sh
+# compare two object files, in depth.
+
+x=$1
+y=$2
+BOTH="$1 $2"
+
+
+# if they cmp, we're fine.
+if (cmp $BOTH > /dev/null)
+then
+ exit 0
+fi
+
+# otherwise, we must look closer.
+if (doboth $BOTH size)
+then
+ echo Sizes ok.
+else
+ echo Sizes differ:
+ size $BOTH
+# exit 1
+fi
+
+if (doboth $BOTH objdump +header)
+then
+ echo Headers ok.
+else
+ echo Header differences.
+# exit 1
+fi
+
+if (doboth $BOTH objdump +text > /dev/null)
+then
+ echo Text ok.
+else
+ echo Text differences.
+# doboth $BOTH objdump +text
+# exit 1
+fi
+
+if (doboth $BOTH objdump +data > /dev/null)
+then
+ echo Data ok.
+else
+ echo Data differences.
+# doboth $BOTH objdump +data
+# exit 1
+fi
+
+if (doboth $BOTH objdump +symbols > /dev/null)
+then
+ echo Symbols ok.
+else
+ echo -n Symbol differences...
+
+ if (doboth $BOTH dounsortsymbols)
+ then
+ echo but symbols are simply ordered differently.
+# echo Now what to do about relocs'?'
+# exit 1
+ else
+ echo and symbols differ in content.
+ exit 1
+ fi
+fi
+
+# of course, if there were symbol diffs, then the reloc symbol indexes
+# will be off.
+
+if (doboth $BOTH objdump -r > /dev/null)
+then
+ echo Reloc ok.
+else
+ echo -n Reloc differences...
+
+ if (doboth $BOTH dounsortreloc)
+ then
+ echo but relocs are simply ordered differently.
+ else
+ echo and relocs differ in content.
+ exit 1
+ fi
+fi
+
+exit
+
+# eof
diff --git a/gas/testsuite/lib/dostriptest b/gas/testsuite/lib/dostriptest
new file mode 100755
index 0000000000..3a51701559
--- /dev/null
+++ b/gas/testsuite/lib/dostriptest
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+x=striptest.xx.$$
+y=striptest.yy.$$
+
+cp $1 $x
+strip $x
+cp $2 $y
+strip $y
+
+doobjcmp $x $y
+exit
+
+#eof
diff --git a/gas/testsuite/lib/dotest b/gas/testsuite/lib/dotest
new file mode 100755
index 0000000000..a768a22530
--- /dev/null
+++ b/gas/testsuite/lib/dotest
@@ -0,0 +1,43 @@
+#!/bin/sh
+# ad hoc debug tool
+
+x=$1
+y=$2
+
+xout=`basename $x`.xxx.$$
+yout=`basename $x`.yyy.$$
+
+mkdir $xout
+mkdir $yout
+
+for i in *.s
+do
+ echo Testing $i...
+ object=`basename $i .s`.o
+ $x $i -o $xout/$object
+ $y $i -o $yout/$object
+
+# if they cmp, we're ok. Otherwise we have to look closer.
+
+ if (cmp $xout/$object $yout/$object)
+ then
+ echo $i is ok.
+ else
+ if (doobjcmp $xout/$object $yout/$object)
+ then
+ echo Not the same but objcmp ok.
+ else
+ exit 1
+ fi
+ fi
+
+ echo
+done
+
+rm -rf $xout $yout
+
+exit 0
+
+# EOF
+
+
diff --git a/gas/testsuite/lib/dounsreloc b/gas/testsuite/lib/dounsreloc
new file mode 100755
index 0000000000..0d69533824
--- /dev/null
+++ b/gas/testsuite/lib/dounsreloc
@@ -0,0 +1,8 @@
+#!/bin/sh
+# objdump the reloc table, but strip off the headings and reloc
+# numbers and sort the result. Intended for use in comparing reloc
+# tables that may not be in the same order.
+
+objdump +reloc +omit-relocation-numbers +omit-symbol-numbers $1 \
+ | sort
+#eof
diff --git a/gas/testsuite/lib/dounssym b/gas/testsuite/lib/dounssym
new file mode 100755
index 0000000000..a44da62fb0
--- /dev/null
+++ b/gas/testsuite/lib/dounssym
@@ -0,0 +1,8 @@
+#!/bin/sh
+# objdump the symbol table, but strip off the headings and symbol
+# numbers and sort the result. Intended for use in comparing symbol
+# tables that may not be in the same order.
+
+objdump +symbols +omit-symbol-numbers $1 \
+ | sort
+#eof
diff --git a/gas/testsuite/lib/gas-defs.exp b/gas/testsuite/lib/gas-defs.exp
new file mode 100644
index 0000000000..757718ffa4
--- /dev/null
+++ b/gas/testsuite/lib/gas-defs.exp
@@ -0,0 +1,574 @@
+# Copyright (C) 1993, 1994, 1997 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, 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 more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# DejaGnu@cygnus.com
+
+# This file was written by Ken Raeburn (raeburn@cygnus.com).
+
+proc gas_version {} {
+ global AS
+ catch "exec $AS -version < /dev/null" tmp
+ # Should find a way to discard constant parts, keep whatever's
+ # left, so the version string could be almost anything at all...
+ regexp "\[^\n\]* (cygnus-|)(\[-0-9.a-zA-Z-\]+)\[\r\n\].*" $tmp version cyg number
+ if ![info exists number] then {
+ return "[which $AS] (no version number)\n"
+ }
+ clone_output "[which $AS] $number\n"
+ unset version
+}
+
+proc gas_run { prog as_opts redir } {
+ global AS
+ global ASFLAGS
+ global comp_output
+ global srcdir
+ global subdir
+ global host_triplet
+
+ verbose "Executing $srcdir/lib/run $AS $ASFLAGS $as_opts $srcdir/$subdir/$prog $redir"
+ catch "exec $srcdir/lib/run $AS $ASFLAGS $as_opts $srcdir/$subdir/$prog $redir" comp_output
+ set comp_output [prune_warnings $comp_output]
+ verbose "output was $comp_output"
+ return [list $comp_output ""];
+}
+
+proc all_ones { args } {
+ foreach x $args { if [expr $x!=1] { return 0 } }
+ return 1
+}
+
+proc gas_start { prog as_opts } {
+ global AS
+ global ASFLAGS
+ global srcdir
+ global subdir
+ global spawn_id
+
+ verbose "Starting $AS $ASFLAGS $as_opts $prog" 2
+ catch {
+ spawn -noecho -nottycopy $srcdir/lib/run $AS $ASFLAGS $as_opts $srcdir/$subdir/$prog
+ } foo
+ if ![regexp {^[0-9]+} $foo] then {
+ perror "Can't run $subdir/$prog: $foo"
+ }
+}
+
+proc gas_finish { } {
+ global spawn_id
+
+ catch "close"
+ catch "wait"
+}
+
+proc want_no_output { testname } {
+ global comp_output
+
+ if ![string match "" $comp_output] then {
+ send_log "$comp_output\n"
+ verbose "$comp_output" 3
+ }
+ if [string match "" $comp_output] then {
+ pass "$testname"
+ return 1
+ } else {
+ fail "$testname"
+ return 0
+ }
+}
+
+proc gas_test_old { file as_opts testname } {
+ gas_run $file $as_opts ""
+ return [want_no_output $testname]
+}
+
+proc gas_test { file as_opts var_opts testname } {
+ global comp_output
+
+ set i 0
+ foreach word $var_opts {
+ set ignore_stdout($i) [string match "*>" $word]
+ set opt($i) [string trim $word {>}]
+ incr i
+ }
+ set max [expr 1<<$i]
+ for {set i 0} {[expr $i<$max]} {incr i} {
+ set maybe_ignore_stdout ""
+ set extra_opts ""
+ for {set bit 0} {(1<<$bit)<$max} {incr bit} {
+ set num [expr 1<<$bit]
+ if [expr $i&$num] then {
+ set extra_opts "$extra_opts $opt($bit)"
+ if $ignore_stdout($bit) then {
+ set maybe_ignore_stdout ">/dev/null"
+ }
+ }
+ }
+ set extra_opts [string trim $extra_opts]
+ gas_run $file "$as_opts $extra_opts" $maybe_ignore_stdout
+
+ # Should I be able to use a conditional expression here?
+ if [string match "" $extra_opts] then {
+ want_no_output $testname
+ } else {
+ want_no_output "$testname ($extra_opts)"
+ }
+ }
+ if [info exists errorInfo] then {
+ unset errorInfo
+ }
+}
+
+proc gas_test_ignore_stdout { file as_opts testname } {
+ global comp_output
+
+ gas_run $file $as_opts ">/dev/null"
+ want_no_output $testname
+}
+
+proc gas_test_error { file as_opts testname } {
+ global comp_output
+
+ gas_run $file $as_opts ">/dev/null"
+ if ![string match "" $comp_output] then {
+ send_log "$comp_output\n"
+ verbose "$comp_output" 3
+ }
+ if [string match "" $comp_output] then {
+ fail "$testname"
+ } else {
+ pass "$testname"
+ }
+}
+
+proc gas_exit {} {}
+
+proc gas_init { args } {
+ global target_cpu
+ global target_cpu_family
+ global target_family
+ global target_vendor
+ global target_os
+ global stdoptlist
+
+ case "$target_cpu" in {
+ "m68???" { set target_cpu_family m68k }
+ "i[34]86" { set target_cpu_family i386 }
+ default { set target_cpu_family $target_cpu }
+ }
+
+ set target_family "$target_cpu_family-$target_vendor-$target_os"
+ set stdoptlist "-a>"
+
+ if ![istarget "*-*-*"] {
+ perror "Target name [istarget] is not a triple."
+ }
+ # Need to return an empty string.
+ return
+}
+
+
+# run_dump_test FILE
+#
+# Assemble a .s file, then run some utility on it and check the output.
+#
+# There should be an assembly language file named FILE.s in the test
+# suite directory, and a pattern file called FILE.d. `run_dump_test'
+# will assemble FILE.s, run some tool like `objdump', `objcopy', or
+# `nm' on the .o file to produce textual output, and then analyze that
+# with regexps. The FILE.d file specifies what program to run, and
+# what to expect in its output.
+#
+# The FILE.d file begins with zero or more option lines, which specify
+# flags to pass to the assembler, the program to run to dump the
+# assembler's output, and the options it wants. The option lines have
+# the syntax:
+#
+# # OPTION: VALUE
+#
+# OPTION is the name of some option, like "name" or "objdump", and
+# VALUE is OPTION's value. The valid options are described below.
+# Whitespace is ignored everywhere, except within VALUE. The option
+# list ends with the first line that doesn't match the above syntax
+# (hmm, not great for error detection).
+#
+# The interesting options are:
+#
+# name: TEST-NAME
+# The name of this test, passed to DejaGNU's `pass' and `fail'
+# commands. If omitted, this defaults to FILE, the root of the
+# .s and .d files' names.
+#
+# as: FLAGS
+# When assembling FILE.s, pass FLAGS to the assembler.
+#
+# PROG: PROGRAM-NAME
+# The name of the program to run to analyze the .o file produced
+# by the assembler. This can be omitted; run_dump_test will guess
+# which program to run by seeing which of the flags options below
+# is present.
+#
+# objdump: FLAGS
+# nm: FLAGS
+# objcopy: FLAGS
+# Use the specified program to analyze the .o file, and pass it
+# FLAGS, in addition to the .o file name.
+#
+# source: SOURCE
+# Assemble the file SOURCE.s. If omitted, this defaults to FILE.s.
+# This is useful if several .d files want to share a .s file.
+#
+# Each option may occur at most once.
+#
+# After the option lines come regexp lines. `run_dump_test' calls
+# `regexp_diff' to compare the output of the dumping tool against the
+# regexps in FILE.d. `regexp_diff' is defined later in this file; see
+# further comments there.
+
+proc run_dump_test { name } {
+ global subdir srcdir
+ global OBJDUMP NM AS OBJCOPY
+ global OBJDUMPFLAGS NMFLAGS ASFLAGS OBJCOPYFLAGS
+ global host_triplet
+
+ if [string match "*/*" $name] {
+ set file $name
+ set name [file tail $name]
+ } else {
+ set file "$srcdir/$subdir/$name"
+ }
+ set opt_array [slurp_options "${file}.d"]
+ if { $opt_array == -1 } {
+ unresolved $subdir/$name
+ return
+ }
+ set opts(as) {}
+ set opts(objdump) {}
+ set opts(nm) {}
+ set opts(objcopy) {}
+ set opts(name) {}
+ set opts(PROG) {}
+ set opts(source) {}
+
+ foreach i $opt_array {
+ set opt_name [lindex $i 0]
+ set opt_val [lindex $i 1]
+ if ![info exists opts($opt_name)] {
+ perror "unknown option $opt_name in file $file.d"
+ unresolved $subdir/$name
+ return
+ }
+ if [string length $opts($opt_name)] {
+ perror "option $opt_name multiply set in $file.d"
+ unresolved $subdir/$name
+ return
+ }
+ set opts($opt_name) $opt_val
+ }
+
+ if {$opts(PROG) != ""} {
+ switch -- $opts(PROG) {
+ objdump
+ { set program objdump }
+ nm
+ { set program nm }
+ objcopy
+ { set program objcopy }
+ default
+ { perror "unrecognized program option $opts(PROG) in $file.d"
+ unresolved $subdir/$name
+ return }
+ }
+ } else {
+ # Guess which program to run, by seeing which option was specified.
+ set program ""
+ foreach p {objdump objcopy nm} {
+ if {$opts($p) != ""} {
+ if {$program != ""} {
+ perror "ambiguous dump program in $file.d"
+ unresolved $subdir/$name
+ return
+ } else {
+ set program $p
+ }
+ }
+ }
+ if {$program == ""} {
+ perror "dump program unspecified in $file.d"
+ unresolved $subdir/$name
+ return
+ }
+ }
+
+ set progopts1 $opts($program)
+ eval set progopts \$[string toupper $program]FLAGS
+ eval set binary \$[string toupper $program]
+ if { $opts(name) == "" } {
+ set testname "$subdir/$name"
+ } else {
+ set testname $opts(name)
+ }
+
+ if { $opts(source) == "" } {
+ set sourcefile ${file}.s
+ } else {
+ set sourcefile $srcdir/$subdir/$opts(source)
+ }
+
+ send_log "$AS $ASFLAGS $opts(as) -o dump.o $sourcefile\n"
+ catch "exec $srcdir/lib/run $AS $ASFLAGS $opts(as) -o dump.o $sourcefile" comp_output
+ set comp_output [prune_warnings $comp_output]
+
+ if ![string match "" $comp_output] then {
+ send_log "$comp_output\n"
+ verbose "$comp_output" 3
+ fail $testname
+ return
+ }
+
+ if { [which $binary] == 0 } {
+ untested $testname
+ return
+ }
+
+ if { $progopts1 == "" } { set $progopts1 "-r" }
+ verbose "running $binary $progopts $progopts1" 3
+
+ # Objcopy, unlike the other two, won't send its output to stdout,
+ # so we have to run it specially.
+ if { $program == "objcopy" } {
+ send_log "$binary $progopts $progopts1 dump.o dump.out\n"
+ catch "exec $binary $progopts $progopts1 dump.o dump.out" comp_output
+ set comp_output [prune_warnings $comp_output]
+ if ![string match "" $comp_output] then {
+ send_log "$comp_output\n"
+ fail $testname
+ return
+ }
+ } else {
+ send_log "$binary $progopts $progopts1 dump.o > dump.out\n"
+ catch "exec $binary $progopts $progopts1 dump.o > dump.out" comp_output
+ set comp_output [prune_warnings $comp_output]
+ if ![string match "" $comp_output] then {
+ send_log "$comp_output\n"
+ fail $testname
+ return
+ }
+ }
+
+ verbose_eval {[file_contents "dump.out"]} 3
+ if { [regexp_diff "dump.out" "${file}.d"] } then {
+ fail $testname
+ verbose "output is [file_contents "dump.out"]" 2
+ return
+ }
+
+ pass $testname
+}
+
+proc slurp_options { file } {
+ if [catch { set f [open $file r] } x] {
+ #perror "couldn't open `$file': $x"
+ perror "$x"
+ return -1
+ }
+ set opt_array {}
+ # whitespace expression
+ set ws {[ ]*}
+ set nws {[^ ]*}
+ # whitespace is ignored anywhere except within the options list;
+ # option names are alphabetic only
+ set pat "^#${ws}(\[a-zA-Z\]*)$ws:${ws}(.*)$ws\$"
+ while { [gets $f line] != -1 } {
+ set line [string trim $line]
+ # Whitespace here is space-tab.
+ if [regexp $pat $line xxx opt_name opt_val] {
+ # match!
+ lappend opt_array [list $opt_name $opt_val]
+ } else {
+ break
+ }
+ }
+ close $f
+ return $opt_array
+}
+
+proc objdump { opts } {
+ global OBJDUMP
+ global comp_output
+ global host_triplet
+
+ catch "exec $OBJDUMP $opts" comp_output
+ set comp_output [prune_warnings $comp_output]
+ verbose "objdump output=$comp_output\n" 3
+}
+
+proc objdump_start_no_subdir { prog opts } {
+ global OBJDUMP
+ global srcdir
+ global spawn_id
+
+ verbose "Starting $OBJDUMP $opts $prog" 2
+ catch {
+ spawn -noecho -nottyinit $srcdir/lib/run $OBJDUMP $opts $prog
+ } foo
+ if ![regexp {^[0-9]+} $foo] then {
+ perror "Can't run $prog: $foo"
+ }
+}
+
+proc objdump_finish { } {
+ global spawn_id
+
+ catch "close"
+ catch "wait"
+}
+
+# Default timeout is 10 seconds, loses on a slow machine. But some
+# configurations of dejagnu may override it.
+if {$timeout<120} then { set timeout 120 }
+
+expect_after -i {
+ timeout { perror "timeout" }
+ "virtual memory exhausted" { perror "virtual memory exhausted" }
+ buffer_full { perror "buffer full" }
+ eof { perror "eof" }
+}
+
+# regexp_diff, based on simple_diff taken from ld test suite
+# compares two files line-by-line
+# file1 contains strings, file2 contains regexps and #-comments
+# blank lines are ignored in either file
+# returns non-zero if differences exist
+#
+proc regexp_diff { file_1 file_2 } {
+
+ set eof -1
+ set end_1 0
+ set end_2 0
+ set differences 0
+ set diff_pass 0
+
+ if [file exists $file_1] then {
+ set file_a [open $file_1 r]
+ } else {
+ warning "$file_1 doesn't exist"
+ return 1
+ }
+
+ if [file exists $file_2] then {
+ set file_b [open $file_2 r]
+ } else {
+ fail "$file_2 doesn't exist"
+ close $file_a
+ return 1
+ }
+
+ verbose " Regexp-diff'ing: $file_1 $file_2" 2
+
+ while { 1 } {
+ set line_a ""
+ set line_b ""
+ while { [string length $line_a] == 0 } {
+ if { [gets $file_a line_a] == $eof } {
+ set end_1 1
+ break
+ }
+ }
+ while { [string length $line_b] == 0 || [string match "#*" $line_b] } {
+ if [ string match "#pass" $line_b ] {
+ set end_2 1
+ set diff_pass 1
+ break
+ }
+ if { [gets $file_b line_b] == $eof } {
+ set end_2 1
+ break
+ }
+ }
+
+ if { $diff_pass } {
+ break
+ } elseif { $end_1 && $end_2 } {
+ break
+ } elseif { $end_1 } {
+ send_log "extra regexps in $file_2 starting with \"^$line_b$\"\nEOF from $file_1\n"
+ verbose "extra regexps in $file_2 starting with \"^$line_b$\"\nEOF from $file_1" 3
+ set differences 1
+ break
+ } elseif { $end_2 } {
+ send_log "extra lines in $file_1 starting with \"^$line_a$\"\nEOF from $file_2\n"
+ verbose "extra lines in $file_1 starting with \"^$line_a$\"\nEOF from $file_2\n" 3
+ set differences 1
+ break
+ } else {
+ verbose "regexp \"^$line_b$\"\nline \"$line_a\"" 3
+ if ![regexp "^$line_b$" "$line_a"] {
+ send_log "regexp_diff match failure\n"
+ send_log "regexp \"^$line_b$\"\nline \"$line_a\"\n"
+ set differences 1
+ break
+ }
+ }
+ }
+
+ if { $differences == 0 && !$diff_pass && [eof $file_a] != [eof $file_b] } {
+ send_log "$file_1 and $file_2 are different lengths\n"
+ verbose "$file_1 and $file_2 are different lengths" 3
+ set differences 1
+ }
+
+ close $file_a
+ close $file_b
+
+ return $differences
+}
+
+proc file_contents { filename } {
+ set file [open $filename r]
+ set contents [read $file]
+ close $file
+ return $contents
+}
+
+proc verbose_eval { expr { level 1 } } {
+ global verbose
+ if $verbose>$level then { eval verbose "$expr" $level }
+}
+
+# This definition is taken from an unreleased version of DejaGnu. Once
+# that version gets released, and has been out in the world for a few
+# months at least, it may be safe to delete this copy.
+if ![string length [info proc prune_warnings]] {
+ #
+ # prune_warnings -- delete various system verbosities from TEXT.
+ #
+ # An example is:
+ # ld.so: warning: /usr/lib/libc.so.1.8.1 has older revision than expected 9
+ #
+ # Sites with particular verbose os's may wish to override this in site.exp.
+ #
+ proc prune_warnings { text } {
+ # This is from sun4's. Do it for all machines for now.
+ # The "\\1" is to try to preserve a "\n" but only if necessary.
+ regsub -all "(^|\n)(ld.so: warning:\[^\n\]*\n?)+" $text "\\1" text
+
+ # It might be tempting to get carried away and delete blank lines, etc.
+ # Just delete *exactly* what we're ask to, and that's it.
+ return $text
+ }
+}
diff --git a/gas/testsuite/lib/gas-dg.exp b/gas/testsuite/lib/gas-dg.exp
new file mode 100644
index 0000000000..92f7f3136c
--- /dev/null
+++ b/gas/testsuite/lib/gas-dg.exp
@@ -0,0 +1,53 @@
+# Define gas callbacks for dg.exp.
+
+load_lib dg.exp
+
+# The use of this function is still in a bit of flux.
+# It should be theoretically possible to assemble, link, and run a file
+# but we currently don't support that. Assembler testcases aren't usually
+# that elaborate anyway. :-)
+
+proc gas-dg-test { prog do_what tool_flags } {
+ # FIXME: the gas testsuite doesn't define tmpdir. Use outdir?
+ set output_file "./a.out"
+
+ switch $do_what {
+ "preprocess" {
+ }
+ "assemble" {
+ }
+ "link" {
+ }
+ "run" {
+ # This is the only place where we care if an executable was
+ # created or not. If it was, dg.exp will try to run it.
+ catch "exec rm -f $output_file"
+ }
+ default {
+ perror "$do_what: not a valid dg-do keyword"
+ return ""
+ }
+ }
+
+ # gas_start prepends $srcdir/$subdir so we must remove it from PROG
+ # if present. First remove extraneous //'s.
+ global srcdir subdir
+ set dir "$srcdir/$subdir"
+ regsub -all "//" $dir "/" dir
+ regsub -all "//" $prog "/" prog
+ if [string match "$dir/*" $prog] {
+ regsub "$dir" $prog "" prog
+ }
+
+ # FIXME: This should be gas_start but it doesn't set comp_output.
+ return [gas_run $prog $tool_flags ""]
+}
+
+proc gas-dg-prune { system text } {
+ #send_user "Before:$text\n"
+ regsub -all "(^|\n)\[^\n\]*: Assembler messages:\[^\n\]*" $text "" text
+ regsub -all "(^|\n)\[^\n\]*: End of file not at end\[^\n\]*Newline inserted." $text "" text
+ #send_user "After:$text\n"
+
+ return $text
+}
diff --git a/gas/testsuite/lib/run b/gas/testsuite/lib/run
new file mode 100755
index 0000000000..d4150f8d4c
--- /dev/null
+++ b/gas/testsuite/lib/run
@@ -0,0 +1,2 @@
+#!/bin/sh
+eval exec $@
diff --git a/gas/vmsconf.sh b/gas/vmsconf.sh
new file mode 100644
index 0000000000..014538a154
--- /dev/null
+++ b/gas/vmsconf.sh
@@ -0,0 +1,128 @@
+#!/bin/sh
+
+cat << 'EOF'
+$!make-gas.com
+$! Set the def dir to proper place for use in batch. Works for interactive to.
+$flnm = f$enviroment("PROCEDURE") ! get current procedure name
+$set default 'f$parse(flnm,,,"DEVICE")''f$parse(flnm,,,"DIRECTORY")'
+$v = 'f$verify(0)'
+$!
+$! Command file to build a GNU assembler on VMS
+$!
+$! If you are using a version of GCC that supports global constants
+$! you should remove the define="const=" from the gcc lines.
+$!
+$! Caution: Versions 1.38.1 and earlier had a bug in the handling of
+$! some static constants. If you are using such a version of the
+$! assembler, and you wish to compile without the "const=" hack,
+$! you should first build this version *with* the "const="
+$! definition, and then use that assembler to rebuild it without the
+$! "const=" definition. Failure to do this will result in an assembler
+$! that will mung floating point constants.
+$!
+$! Note: The version of gas shipped on the GCC VMS tapes has been patched
+$! to fix the above mentioned bug.
+$!
+$ !The gcc-vms driver was modified to use `-1' quite some time ago,
+$ !so don't echo this text any more...
+$ !write sys$output "If this assembler is going to be used with GCC 1.n, you"
+$ !write sys$output "need to modify the driver to supply the -1 switch to gas."
+$ !write sys$output "This is required because of a small change in how global"
+$ !write sys$output "constant variables are handled. Failure to include this"
+$ !write sys$output "will result in linker warning messages about mismatched
+$ !write sys$output "psect attributes."
+$!
+$ gas_host="vms"
+$ arch_indx = 1 + ((f$getsyi("CPU").ge.128).and.1) ! vax==1, alpha==2
+$ arch = f$element(arch_indx,"|","|VAX|Alpha|")
+$ if arch.eqs."VAX"
+$ then
+$ cpu_type="vax"
+$ obj_format="vms"
+$ atof="vax"
+$ else
+$ cpu_type="alpha"
+$ obj_format="evax"
+$ atof="ieee"
+$ endif
+$ emulation="generic"
+$!
+$ COPY = "copy/noLog"
+$!
+$ C_DEFS :="""VMS"""
+$! C_DEFS :="""VMS""","""const="""
+$ C_INCLUDES = "/Include=([],[.config],[-.include],[-.include.aout])"
+$ C_FLAGS = "/noVerbose/Debug" + c_includes
+$!
+$!
+$ on error then goto bail
+$ if f$search("[-.libiberty]liberty.olb").eqs.""
+$ then @[-.libiberty]vmsbuild.com
+$ write sys$output "Now building gas."
+$ endif
+$ if "''p1'" .eqs. "LINK" then goto Link
+$!
+$! This helps gcc 1.nn find the aout/* files.
+$!
+$ aout_dev = f$parse(flnm,,,"DEVICE")
+$ tmp = aout_dev - ":"
+$if f$trnlnm(tmp).nes."" then aout_dev = f$trnlnm(tmp)
+$ aout_dir = aout_dev+f$parse(flnm,,,"DIRECTORY")' -
+ - "GAS]" + "INCLUDE.AOUT.]" - "]["
+$assign 'aout_dir' aout/tran=conc
+$ opcode_dir = aout_dev+f$parse(flnm,,,"DIRECTORY")' -
+ - "GAS]" + "INCLUDE.OPCODE.]" - "]["
+$assign 'opcode_dir' opcode/tran=conc
+$!
+$ set verify
+$!
+$ gcc 'c_flags'/Define=('C_DEFS')/Object=[]tc-'cpu_type'.obj [.config]tc-'cpu_type'.c
+$ gcc 'c_flags'/Define=('C_DEFS')/Object=[]obj-'obj_format'.obj [.config]obj-'obj_format'.c
+$ gcc 'c_flags'/Define=('C_DEFS')/Object=[]atof-'atof'.obj [.config]atof-'atof'.c
+EOF
+
+cfiles="`echo $* | sed -e 's/\.o/.c/g' -e 's!../\([^ /]*\)/\([^ /]*\.c\)![-.\1]\2!g'`"
+
+for cfile in $cfiles ; do
+ case $cfile in
+ "[-."*)
+ base=`echo $cfile | sed -e 's/\[.*\]//' -e 's/\.c$//'`
+ echo "\$ gcc 'c_flags'/Define=('C_DEFS')/Object=[]$base.obj $cfile"
+ ;;
+ *)
+ echo "\$ gcc 'c_flags'/Define=('C_DEFS') $cfile"
+ ;;
+ esac
+done
+
+cat << 'EOF'
+$link:
+$!'f$verify(0)'
+$ if f$trnlnm("IFILE$").nes."" then close/noLog ifile$
+$ create gcc-as.opt
+!
+! Linker options file for GNU assembler
+!
+$ open/Append ifile$ gcc-as.opt
+$ write ifile$ "tc-''cpu_type'.obj"
+$ write ifile$ "obj-''obj_format'.obj"
+$ write ifile$ "atof-''atof'.obj"
+$ COPY sys$input: ifile$:
+EOF
+
+for obj in $* ; do
+ # Change "foo.o" into "foo.obj".
+ echo ${obj}bj,- | sed 's!.*/!!g'
+done
+
+cat << 'EOF'
+[-.libiberty]liberty.olb/Lib
+gnu_cc:[000000]gcclib.olb/Lib,sys$library:vaxcrtl.olb/Lib
+! Tell linker exactly what psect attributes we want -- match VAXCRTL.
+psect_attr=ENVIRON,long,pic,ovr,rel,gbl,noshr,noexe,rd,wrt
+$ close ifile$
+$ set verify=(Proc,noImag)
+$ link/noMap/Exec=gcc-as.exe gcc-as.opt/Opt,version.opt/Opt
+$!
+$bail: exit $status + 0*f$verify(v) !'f$verify(0)'
+EOF
diff --git a/gas/write.c b/gas/write.c
new file mode 100644
index 0000000000..18e6e103f9
--- /dev/null
+++ b/gas/write.c
@@ -0,0 +1,2884 @@
+/* write.c - emit .o file
+ Copyright (C) 1986, 87, 90, 91, 92, 93, 94, 95, 96, 97, 1998
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* This thing should be set up to do byteordering correctly. But... */
+
+#include "as.h"
+#include "subsegs.h"
+#include "obstack.h"
+#include "output-file.h"
+
+/* This looks like a good idea. Let's try turning it on always, for now. */
+#undef BFD_FAST_SECTION_FILL
+#define BFD_FAST_SECTION_FILL
+
+/* The NOP_OPCODE is for the alignment fill value. Fill it with a nop
+ instruction so that the disassembler does not choke on it. */
+#ifndef NOP_OPCODE
+#define NOP_OPCODE 0x00
+#endif
+
+#ifndef TC_ADJUST_RELOC_COUNT
+#define TC_ADJUST_RELOC_COUNT(FIXP,COUNT)
+#endif
+
+#ifndef TC_FORCE_RELOCATION
+#define TC_FORCE_RELOCATION(FIXP) 0
+#endif
+
+#ifndef TC_FORCE_RELOCATION_SECTION
+#define TC_FORCE_RELOCATION_SECTION(FIXP,SEG) TC_FORCE_RELOCATION(FIXP)
+#endif
+
+#ifndef MD_PCREL_FROM_SECTION
+#define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from(FIXP)
+#endif
+
+#ifndef WORKING_DOT_WORD
+extern CONST int md_short_jump_size;
+extern CONST int md_long_jump_size;
+#endif
+
+int symbol_table_frozen;
+void print_fixup PARAMS ((fixS *));
+
+#ifdef BFD_ASSEMBLER
+static void renumber_sections PARAMS ((bfd *, asection *, PTR));
+
+/* We generally attach relocs to frag chains. However, after we have
+ chained these all together into a segment, any relocs we add after
+ that must be attached to a segment. This will include relocs added
+ in md_estimate_size_for_relax, for example. */
+static int frags_chained = 0;
+#endif
+
+#ifndef BFD_ASSEMBLER
+
+#ifndef MANY_SEGMENTS
+struct frag *text_frag_root;
+struct frag *data_frag_root;
+struct frag *bss_frag_root;
+
+struct frag *text_last_frag; /* Last frag in segment. */
+struct frag *data_last_frag; /* Last frag in segment. */
+static struct frag *bss_last_frag; /* Last frag in segment. */
+#endif
+
+#ifndef BFD
+static object_headers headers;
+#endif
+
+long string_byte_count;
+char *next_object_file_charP; /* Tracks object file bytes. */
+
+#ifndef OBJ_VMS
+int magic_number_for_object_file = DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE;
+#endif
+
+#endif /* BFD_ASSEMBLER */
+
+static int n_fixups;
+
+#ifdef BFD_ASSEMBLER
+static fixS *fix_new_internal PARAMS ((fragS *, int where, int size,
+ symbolS *add, symbolS *sub,
+ offsetT offset, int pcrel,
+ bfd_reloc_code_real_type r_type));
+#else
+static fixS *fix_new_internal PARAMS ((fragS *, int where, int size,
+ symbolS *add, symbolS *sub,
+ offsetT offset, int pcrel,
+ int r_type));
+#endif
+#if defined (BFD_ASSEMBLER) || (!defined (BFD) && !defined (OBJ_VMS))
+static long fixup_segment PARAMS ((fixS * fixP, segT this_segment_type));
+#endif
+static relax_addressT relax_align PARAMS ((relax_addressT addr, int align));
+#if defined (BFD_ASSEMBLER) || ! defined (BFD)
+static fragS *chain_frchains_together_1 PARAMS ((segT, struct frchain *));
+#endif
+#ifdef BFD_ASSEMBLER
+static void chain_frchains_together PARAMS ((bfd *, segT, PTR));
+static void cvt_frag_to_fill PARAMS ((segT, fragS *));
+static void relax_and_size_seg PARAMS ((bfd *, asection *, PTR));
+static void adjust_reloc_syms PARAMS ((bfd *, asection *, PTR));
+static void write_relocs PARAMS ((bfd *, asection *, PTR));
+static void write_contents PARAMS ((bfd *, asection *, PTR));
+static void set_symtab PARAMS ((void));
+#endif
+#if defined (BFD_ASSEMBLER) || (! defined (BFD) && ! defined (OBJ_AOUT))
+static void merge_data_into_text PARAMS ((void));
+#endif
+#if ! defined (BFD_ASSEMBLER) && ! defined (BFD)
+static void cvt_frag_to_fill PARAMS ((object_headers *, segT, fragS *));
+static void remove_subsegs PARAMS ((frchainS *, int, fragS **, fragS **));
+static void relax_and_size_all_segments PARAMS ((void));
+#endif
+
+/*
+ * fix_new()
+ *
+ * Create a fixS in obstack 'notes'.
+ */
+static fixS *
+fix_new_internal (frag, where, size, add_symbol, sub_symbol, offset, pcrel,
+ r_type)
+ fragS *frag; /* Which frag? */
+ int where; /* Where in that frag? */
+ int size; /* 1, 2, or 4 usually. */
+ symbolS *add_symbol; /* X_add_symbol. */
+ symbolS *sub_symbol; /* X_op_symbol. */
+ offsetT offset; /* X_add_number. */
+ int pcrel; /* TRUE if PC-relative relocation. */
+#ifdef BFD_ASSEMBLER
+ bfd_reloc_code_real_type r_type; /* Relocation type */
+#else
+ int r_type; /* Relocation type */
+#endif
+{
+ fixS *fixP;
+
+ n_fixups++;
+
+ fixP = (fixS *) obstack_alloc (&notes, sizeof (fixS));
+
+ fixP->fx_frag = frag;
+ fixP->fx_where = where;
+ fixP->fx_size = size;
+ /* We've made fx_size a narrow field; check that it's wide enough. */
+ if (fixP->fx_size != size)
+ {
+ as_bad (_("field fx_size too small to hold %d"), size);
+ abort ();
+ }
+ fixP->fx_addsy = add_symbol;
+ fixP->fx_subsy = sub_symbol;
+ fixP->fx_offset = offset;
+ fixP->fx_pcrel = pcrel;
+ fixP->fx_plt = 0;
+#if defined(NEED_FX_R_TYPE) || defined (BFD_ASSEMBLER)
+ fixP->fx_r_type = r_type;
+#endif
+ fixP->fx_im_disp = 0;
+ fixP->fx_pcrel_adjust = 0;
+ fixP->fx_bit_fixP = 0;
+ fixP->fx_addnumber = 0;
+ fixP->fx_tcbit = 0;
+ fixP->fx_done = 0;
+ fixP->fx_no_overflow = 0;
+ fixP->fx_signed = 0;
+
+#ifdef USING_CGEN
+ fixP->fx_cgen.insn = NULL;
+ fixP->fx_cgen.opinfo = 0;
+#endif
+
+#ifdef TC_FIX_TYPE
+ TC_INIT_FIX_DATA(fixP);
+#endif
+
+ as_where (&fixP->fx_file, &fixP->fx_line);
+
+ /* Usually, we want relocs sorted numerically, but while
+ comparing to older versions of gas that have relocs
+ reverse sorted, it is convenient to have this compile
+ time option. xoxorich. */
+
+ {
+
+#ifdef BFD_ASSEMBLER
+ fixS **seg_fix_rootP = (frags_chained
+ ? &seg_info (now_seg)->fix_root
+ : &frchain_now->fix_root);
+ fixS **seg_fix_tailP = (frags_chained
+ ? &seg_info (now_seg)->fix_tail
+ : &frchain_now->fix_tail);
+#endif
+
+#ifdef REVERSE_SORT_RELOCS
+
+ fixP->fx_next = *seg_fix_rootP;
+ *seg_fix_rootP = fixP;
+
+#else /* REVERSE_SORT_RELOCS */
+
+ fixP->fx_next = NULL;
+
+ if (*seg_fix_tailP)
+ (*seg_fix_tailP)->fx_next = fixP;
+ else
+ *seg_fix_rootP = fixP;
+ *seg_fix_tailP = fixP;
+
+#endif /* REVERSE_SORT_RELOCS */
+
+ }
+
+ return fixP;
+}
+
+/* Create a fixup relative to a symbol (plus a constant). */
+
+fixS *
+fix_new (frag, where, size, add_symbol, offset, pcrel, r_type)
+ fragS *frag; /* Which frag? */
+ int where; /* Where in that frag? */
+ int size; /* 1, 2, or 4 usually. */
+ symbolS *add_symbol; /* X_add_symbol. */
+ offsetT offset; /* X_add_number. */
+ int pcrel; /* TRUE if PC-relative relocation. */
+#ifdef BFD_ASSEMBLER
+ bfd_reloc_code_real_type r_type; /* Relocation type */
+#else
+ int r_type; /* Relocation type */
+#endif
+{
+ return fix_new_internal (frag, where, size, add_symbol,
+ (symbolS *) NULL, offset, pcrel, r_type);
+}
+
+/* Create a fixup for an expression. Currently we only support fixups
+ for difference expressions. That is itself more than most object
+ file formats support anyhow. */
+
+fixS *
+fix_new_exp (frag, where, size, exp, pcrel, r_type)
+ fragS *frag; /* Which frag? */
+ int where; /* Where in that frag? */
+ int size; /* 1, 2, or 4 usually. */
+ expressionS *exp; /* Expression. */
+ int pcrel; /* TRUE if PC-relative relocation. */
+#ifdef BFD_ASSEMBLER
+ bfd_reloc_code_real_type r_type; /* Relocation type */
+#else
+ int r_type; /* Relocation type */
+#endif
+{
+ symbolS *add = NULL;
+ symbolS *sub = NULL;
+ offsetT off = 0;
+
+ switch (exp->X_op)
+ {
+ case O_absent:
+ break;
+
+ case O_add:
+ /* This comes up when _GLOBAL_OFFSET_TABLE_+(.-L0) is read, if
+ the difference expression cannot immediately be reduced. */
+ {
+ symbolS *stmp = make_expr_symbol (exp);
+ exp->X_op = O_symbol;
+ exp->X_op_symbol = 0;
+ exp->X_add_symbol = stmp;
+ exp->X_add_number = 0;
+ return fix_new_exp (frag, where, size, exp, pcrel, r_type);
+ }
+
+ case O_symbol_rva:
+ add = exp->X_add_symbol;
+ off = exp->X_add_number;
+
+#if defined(BFD_ASSEMBLER)
+ r_type = BFD_RELOC_RVA;
+#else
+#if defined(TC_RVA_RELOC)
+ r_type = TC_RVA_RELOC;
+#else
+ as_fatal(_("rva not supported"));
+#endif
+#endif
+ break;
+
+ case O_uminus:
+ sub = exp->X_add_symbol;
+ off = exp->X_add_number;
+ break;
+
+ case O_subtract:
+ sub = exp->X_op_symbol;
+ /* Fall through. */
+ case O_symbol:
+ add = exp->X_add_symbol;
+ /* Fall through. */
+ case O_constant:
+ off = exp->X_add_number;
+ break;
+
+ default:
+ add = make_expr_symbol (exp);
+ break;
+ }
+
+ return fix_new_internal (frag, where, size, add, sub, off,
+ pcrel, r_type);
+}
+
+/* Append a string onto another string, bumping the pointer along. */
+void
+append (charPP, fromP, length)
+ char **charPP;
+ char *fromP;
+ unsigned long length;
+{
+ /* Don't trust memcpy() of 0 chars. */
+ if (length == 0)
+ return;
+
+ memcpy (*charPP, fromP, length);
+ *charPP += length;
+}
+
+#ifndef BFD_ASSEMBLER
+int section_alignment[SEG_MAXIMUM_ORDINAL];
+#endif
+
+/*
+ * This routine records the largest alignment seen for each segment.
+ * If the beginning of the segment is aligned on the worst-case
+ * boundary, all of the other alignments within it will work. At
+ * least one object format really uses this info.
+ */
+void
+record_alignment (seg, align)
+ /* Segment to which alignment pertains */
+ segT seg;
+ /* Alignment, as a power of 2 (e.g., 1 => 2-byte boundary, 2 => 4-byte
+ boundary, etc.) */
+ int align;
+{
+ if (seg == absolute_section)
+ return;
+#ifdef BFD_ASSEMBLER
+ if ((unsigned int) align > bfd_get_section_alignment (stdoutput, seg))
+ bfd_set_section_alignment (stdoutput, seg, align);
+#else
+ if (align > section_alignment[(int) seg])
+ section_alignment[(int) seg] = align;
+#endif
+}
+
+#ifdef BFD_ASSEMBLER
+
+/* Reset the section indices after removing the gas created sections. */
+
+static void
+renumber_sections (abfd, sec, countparg)
+ bfd *abfd;
+ asection *sec;
+ PTR countparg;
+{
+ int *countp = (int *) countparg;
+
+ sec->index = *countp;
+ ++*countp;
+}
+
+#endif /* defined (BFD_ASSEMBLER) */
+
+#if defined (BFD_ASSEMBLER) || ! defined (BFD)
+
+static fragS *
+chain_frchains_together_1 (section, frchp)
+ segT section;
+ struct frchain *frchp;
+{
+ fragS dummy, *prev_frag = &dummy;
+#ifdef BFD_ASSEMBLER
+ fixS fix_dummy, *prev_fix = &fix_dummy;
+#endif
+
+ for (; frchp && frchp->frch_seg == section; frchp = frchp->frch_next)
+ {
+ prev_frag->fr_next = frchp->frch_root;
+ prev_frag = frchp->frch_last;
+ assert (prev_frag->fr_type != 0);
+#ifdef BFD_ASSEMBLER
+ if (frchp->fix_root != (fixS *) NULL)
+ {
+ if (seg_info (section)->fix_root == (fixS *) NULL)
+ seg_info (section)->fix_root = frchp->fix_root;
+ prev_fix->fx_next = frchp->fix_root;
+ seg_info (section)->fix_tail = frchp->fix_tail;
+ prev_fix = frchp->fix_tail;
+ }
+#endif
+ }
+ assert (prev_frag->fr_type != 0);
+ prev_frag->fr_next = 0;
+ return prev_frag;
+}
+
+#endif
+
+#ifdef BFD_ASSEMBLER
+
+static void
+chain_frchains_together (abfd, section, xxx)
+ bfd *abfd; /* unused */
+ segT section;
+ PTR xxx; /* unused */
+{
+ segment_info_type *info;
+
+ /* BFD may have introduced its own sections without using
+ subseg_new, so it is possible that seg_info is NULL. */
+ info = seg_info (section);
+ if (info != (segment_info_type *) NULL)
+ info->frchainP->frch_last
+ = chain_frchains_together_1 (section, info->frchainP);
+
+ /* Now that we've chained the frags together, we must add new fixups
+ to the segment, not to the frag chain. */
+ frags_chained = 1;
+}
+
+#endif
+
+#if !defined (BFD) && !defined (BFD_ASSEMBLER)
+
+static void
+remove_subsegs (head, seg, root, last)
+ frchainS *head;
+ int seg;
+ fragS **root;
+ fragS **last;
+{
+ *root = head->frch_root;
+ *last = chain_frchains_together_1 (seg, head);
+}
+
+#endif /* BFD */
+
+#if defined (BFD_ASSEMBLER) || !defined (BFD)
+
+#ifdef BFD_ASSEMBLER
+static void
+cvt_frag_to_fill (sec, fragP)
+ segT sec;
+ fragS *fragP;
+#else
+static void
+cvt_frag_to_fill (headersP, sec, fragP)
+ object_headers *headersP;
+ segT sec;
+ fragS *fragP;
+#endif
+{
+ switch (fragP->fr_type)
+ {
+ case rs_align:
+ case rs_align_code:
+ case rs_org:
+ case rs_space:
+#ifdef HANDLE_ALIGN
+ HANDLE_ALIGN (fragP);
+#endif
+ know (fragP->fr_next != NULL);
+ fragP->fr_offset = (fragP->fr_next->fr_address
+ - fragP->fr_address
+ - fragP->fr_fix) / fragP->fr_var;
+ if (fragP->fr_offset < 0)
+ {
+ as_bad (_("attempt to .org/.space backwards? (%ld)"),
+ (long) fragP->fr_offset);
+ }
+ fragP->fr_type = rs_fill;
+ break;
+
+ case rs_fill:
+ break;
+
+ case rs_leb128:
+ {
+ valueT value = S_GET_VALUE (fragP->fr_symbol);
+ int size;
+
+ size = output_leb128 (fragP->fr_literal + fragP->fr_fix, value,
+ fragP->fr_subtype);
+
+ fragP->fr_fix += size;
+ fragP->fr_type = rs_fill;
+ fragP->fr_var = 0;
+ fragP->fr_offset = 0;
+ fragP->fr_symbol = NULL;
+ }
+ break;
+
+ case rs_cfa:
+ eh_frame_convert_frag (fragP);
+ break;
+
+ case rs_machine_dependent:
+#ifdef BFD_ASSEMBLER
+ md_convert_frag (stdoutput, sec, fragP);
+#else
+ md_convert_frag (headersP, sec, fragP);
+#endif
+
+ assert (fragP->fr_next == NULL
+ || ((offsetT) (fragP->fr_next->fr_address - fragP->fr_address)
+ == fragP->fr_fix));
+
+ /*
+ * After md_convert_frag, we make the frag into a ".space 0".
+ * Md_convert_frag() should set up any fixSs and constants
+ * required.
+ */
+ frag_wane (fragP);
+ break;
+
+#ifndef WORKING_DOT_WORD
+ case rs_broken_word:
+ {
+ struct broken_word *lie;
+
+ if (fragP->fr_subtype)
+ {
+ fragP->fr_fix += md_short_jump_size;
+ for (lie = (struct broken_word *) (fragP->fr_symbol);
+ lie && lie->dispfrag == fragP;
+ lie = lie->next_broken_word)
+ if (lie->added == 1)
+ fragP->fr_fix += md_long_jump_size;
+ }
+ frag_wane (fragP);
+ }
+ break;
+#endif
+
+ default:
+ BAD_CASE (fragP->fr_type);
+ break;
+ }
+}
+
+#endif /* defined (BFD_ASSEMBLER) || !defined (BFD) */
+
+#ifdef BFD_ASSEMBLER
+static void
+relax_and_size_seg (abfd, sec, xxx)
+ bfd *abfd;
+ asection *sec;
+ PTR xxx;
+{
+ flagword flags;
+ fragS *fragp;
+ segment_info_type *seginfo;
+ int x;
+ valueT size, newsize;
+
+ subseg_change (sec, 0);
+
+ flags = bfd_get_section_flags (abfd, sec);
+
+ seginfo = seg_info (sec);
+ if (seginfo && seginfo->frchainP)
+ {
+ relax_segment (seginfo->frchainP->frch_root, sec);
+ for (fragp = seginfo->frchainP->frch_root; fragp; fragp = fragp->fr_next)
+ cvt_frag_to_fill (sec, fragp);
+ for (fragp = seginfo->frchainP->frch_root;
+ fragp->fr_next;
+ fragp = fragp->fr_next)
+ /* walk to last elt */;
+ size = fragp->fr_address + fragp->fr_fix;
+ }
+ else
+ size = 0;
+
+ if (size > 0 && ! seginfo->bss)
+ flags |= SEC_HAS_CONTENTS;
+
+ /* @@ This is just an approximation. */
+ if (seginfo && seginfo->fix_root)
+ flags |= SEC_RELOC;
+ else
+ flags &= ~SEC_RELOC;
+ x = bfd_set_section_flags (abfd, sec, flags);
+ assert (x == true);
+
+ newsize = md_section_align (sec, size);
+ x = bfd_set_section_size (abfd, sec, newsize);
+ assert (x == true);
+
+ /* If the size had to be rounded up, add some padding in the last
+ non-empty frag. */
+ assert (newsize >= size);
+ if (size != newsize)
+ {
+ fragS *last = seginfo->frchainP->frch_last;
+ fragp = seginfo->frchainP->frch_root;
+ while (fragp->fr_next != last)
+ fragp = fragp->fr_next;
+ last->fr_address = size;
+ fragp->fr_offset += newsize - size;
+ }
+
+#ifdef tc_frob_section
+ tc_frob_section (sec);
+#endif
+#ifdef obj_frob_section
+ obj_frob_section (sec);
+#endif
+}
+
+#ifdef DEBUG2
+static void
+dump_section_relocs (abfd, sec, stream_)
+ bfd *abfd;
+ asection *sec;
+ char *stream_;
+{
+ FILE *stream = (FILE *) stream_;
+ segment_info_type *seginfo = seg_info (sec);
+ fixS *fixp = seginfo->fix_root;
+
+ if (!fixp)
+ return;
+
+ fprintf (stream, "sec %s relocs:\n", sec->name);
+ while (fixp)
+ {
+ symbolS *s = fixp->fx_addsy;
+ if (s)
+ {
+ fprintf (stream, " %08x: %s(%s", fixp, S_GET_NAME (s),
+ s->bsym->section->name);
+ if (s->bsym->flags & BSF_SECTION_SYM)
+ {
+ fprintf (stream, " section sym");
+ if (S_GET_VALUE (s))
+ fprintf (stream, "+%x", S_GET_VALUE (s));
+ }
+ else
+ fprintf (stream, "+%x", S_GET_VALUE (s));
+ fprintf (stream, ")+%x\n", fixp->fx_offset);
+ }
+ else
+ fprintf (stream, " %08x: type %d no sym\n", fixp, fixp->fx_r_type);
+ fixp = fixp->fx_next;
+ }
+}
+#else
+#define dump_section_relocs(ABFD,SEC,STREAM) ((void) 0)
+#endif
+
+#ifndef EMIT_SECTION_SYMBOLS
+#define EMIT_SECTION_SYMBOLS 1
+#endif
+
+static void
+adjust_reloc_syms (abfd, sec, xxx)
+ bfd *abfd;
+ asection *sec;
+ PTR xxx;
+{
+ segment_info_type *seginfo = seg_info (sec);
+ fixS *fixp;
+
+ if (seginfo == NULL)
+ return;
+
+ dump_section_relocs (abfd, sec, stderr);
+
+ for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
+ if (fixp->fx_done)
+ /* ignore it */;
+ else if (fixp->fx_addsy)
+ {
+ symbolS *sym;
+ asection *symsec;
+
+#ifdef DEBUG5
+ fprintf (stderr, "\n\nadjusting fixup:\n");
+ print_fixup (fixp);
+#endif
+
+ sym = fixp->fx_addsy;
+
+ /* All symbols should have already been resolved at this
+ point. It is possible to see unresolved expression
+ symbols, though, since they are not in the regular symbol
+ table. */
+ if (sym != NULL && ! sym->sy_resolved)
+ resolve_symbol_value (sym, 1);
+
+ if (fixp->fx_subsy != NULL && ! fixp->fx_subsy->sy_resolved)
+ resolve_symbol_value (fixp->fx_subsy, 1);
+
+ /* If this symbol is equated to an undefined symbol, convert
+ the fixup to being against that symbol. */
+ if (sym != NULL && sym->sy_value.X_op == O_symbol
+ && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
+ {
+ fixp->fx_offset += sym->sy_value.X_add_number;
+ sym = sym->sy_value.X_add_symbol;
+ fixp->fx_addsy = sym;
+ }
+
+ if (sym != NULL && sym->sy_mri_common)
+ {
+ /* These symbols are handled specially in fixup_segment. */
+ goto done;
+ }
+
+ symsec = S_GET_SEGMENT (sym);
+
+ if (symsec == NULL)
+ abort ();
+
+ if (bfd_is_abs_section (symsec))
+ {
+ /* The fixup_segment routine will not use this symbol in a
+ relocation unless TC_FORCE_RELOCATION returns 1. */
+ if (TC_FORCE_RELOCATION (fixp))
+ {
+ fixp->fx_addsy->sy_used_in_reloc = 1;
+#ifdef UNDEFINED_DIFFERENCE_OK
+ if (fixp->fx_subsy != NULL)
+ fixp->fx_subsy->sy_used_in_reloc = 1;
+#endif
+ }
+ goto done;
+ }
+
+ /* If it's one of these sections, assume the symbol is
+ definitely going to be output. The code in
+ md_estimate_size_before_relax in tc-mips.c uses this test
+ as well, so if you change this code you should look at that
+ code. */
+ if (bfd_is_und_section (symsec)
+ || bfd_is_com_section (symsec))
+ {
+ fixp->fx_addsy->sy_used_in_reloc = 1;
+#ifdef UNDEFINED_DIFFERENCE_OK
+ /* We have the difference of an undefined symbol and some
+ other symbol. Make sure to mark the other symbol as used
+ in a relocation so that it will always be output. */
+ if (fixp->fx_subsy)
+ fixp->fx_subsy->sy_used_in_reloc = 1;
+#endif
+ goto done;
+ }
+
+ /* Don't try to reduce relocs which refer to .linkonce
+ sections. It can lead to confusion when a debugging
+ section refers to a .linkonce section. I hope this will
+ always be correct. */
+ if (symsec != sec)
+ {
+ boolean linkonce;
+
+ linkonce = false;
+#ifdef BFD_ASSEMBLER
+ if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE)
+ != 0)
+ linkonce = true;
+#endif
+#ifdef OBJ_ELF
+ /* The GNU toolchain uses an extension for ELF: a section
+ beginning with the magic string .gnu.linkonce is a
+ linkonce section. */
+ if (strncmp (segment_name (symsec), ".gnu.linkonce",
+ sizeof ".gnu.linkonce" - 1) == 0)
+ linkonce = true;
+#endif
+
+ if (linkonce)
+ {
+ fixp->fx_addsy->sy_used_in_reloc = 1;
+#ifdef UNDEFINED_DIFFERENCE_OK
+ if (fixp->fx_subsy != NULL)
+ fixp->fx_subsy->sy_used_in_reloc = 1;
+#endif
+ goto done;
+ }
+ }
+
+ /* Since we're reducing to section symbols, don't attempt to reduce
+ anything that's already using one. */
+ if (sym->bsym->flags & BSF_SECTION_SYM)
+ {
+ fixp->fx_addsy->sy_used_in_reloc = 1;
+ goto done;
+ }
+
+#ifdef BFD_ASSEMBLER
+ /* We can never adjust a reloc against a weak symbol. If we
+ did, and the weak symbol was overridden by a real symbol
+ somewhere else, then our relocation would be pointing at
+ the wrong area of memory. */
+ if (S_IS_WEAK (sym))
+ {
+ fixp->fx_addsy->sy_used_in_reloc = 1;
+ goto done;
+ }
+#endif
+
+ /* Is there some other reason we can't adjust this one? (E.g.,
+ call/bal links in i960-bout symbols.) */
+#ifdef obj_fix_adjustable
+ if (! obj_fix_adjustable (fixp))
+ {
+ fixp->fx_addsy->sy_used_in_reloc = 1;
+ goto done;
+ }
+#endif
+
+ /* Is there some other (target cpu dependent) reason we can't adjust
+ this one? (E.g. relocations involving function addresses on
+ the PA. */
+#ifdef tc_fix_adjustable
+ if (! tc_fix_adjustable (fixp))
+ {
+ fixp->fx_addsy->sy_used_in_reloc = 1;
+ goto done;
+ }
+#endif
+
+ /* If the section symbol isn't going to be output, the relocs
+ at least should still work. If not, figure out what to do
+ when we run into that case.
+
+ We refetch the segment when calling section_symbol, rather
+ than using symsec, because S_GET_VALUE may wind up changing
+ the section when it calls resolve_symbol_value. */
+ fixp->fx_offset += S_GET_VALUE (sym);
+ fixp->fx_addsy = section_symbol (S_GET_SEGMENT (sym));
+ fixp->fx_addsy->sy_used_in_reloc = 1;
+
+ done:
+ ;
+ }
+#if 1/*def RELOC_REQUIRES_SYMBOL*/
+ else
+ {
+ /* There was no symbol required by this relocation. However,
+ BFD doesn't really handle relocations without symbols well.
+ (At least, the COFF support doesn't.) So for now we fake up
+ a local symbol in the absolute section. */
+
+ fixp->fx_addsy = section_symbol (absolute_section);
+/* fixp->fx_addsy->sy_used_in_reloc = 1; */
+ }
+#endif
+
+ dump_section_relocs (abfd, sec, stderr);
+}
+
+static void
+write_relocs (abfd, sec, xxx)
+ bfd *abfd;
+ asection *sec;
+ PTR xxx;
+{
+ segment_info_type *seginfo = seg_info (sec);
+ int i;
+ unsigned int n;
+ arelent **relocs;
+ fixS *fixp;
+ char *err;
+
+ /* If seginfo is NULL, we did not create this section; don't do
+ anything with it. */
+ if (seginfo == NULL)
+ return;
+
+ fixup_segment (seginfo->fix_root, sec);
+
+ n = 0;
+ for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
+ n++;
+
+#ifndef RELOC_EXPANSION_POSSIBLE
+ /* Set up reloc information as well. */
+ relocs = (arelent **) xmalloc (n * sizeof (arelent *));
+ memset ((char*)relocs, 0, n * sizeof (arelent*));
+
+ i = 0;
+ for (fixp = seginfo->fix_root; fixp != (fixS *) NULL; fixp = fixp->fx_next)
+ {
+ arelent *reloc;
+ bfd_reloc_status_type s;
+ symbolS *sym;
+
+ if (fixp->fx_done)
+ {
+ n--;
+ continue;
+ }
+
+ /* If this is an undefined symbol which was equated to another
+ symbol, then use generate the reloc against the latter symbol
+ rather than the former. */
+ sym = fixp->fx_addsy;
+ while (sym->sy_value.X_op == O_symbol
+ && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
+ {
+ symbolS *n;
+
+ /* We must avoid looping, as that can occur with a badly
+ written program. */
+ n = sym->sy_value.X_add_symbol;
+ if (n == sym)
+ break;
+ fixp->fx_offset += sym->sy_value.X_add_number;
+ sym = n;
+ }
+ fixp->fx_addsy = sym;
+
+ reloc = tc_gen_reloc (sec, fixp);
+ if (!reloc)
+ {
+ n--;
+ continue;
+ }
+
+#if 0
+ /* This test is triggered inappropriately for the SH. */
+ if (fixp->fx_where + fixp->fx_size
+ > fixp->fx_frag->fr_fix + fixp->fx_frag->fr_offset)
+ abort ();
+#endif
+
+ s = bfd_install_relocation (stdoutput, reloc,
+ fixp->fx_frag->fr_literal,
+ fixp->fx_frag->fr_address,
+ sec, &err);
+ switch (s)
+ {
+ case bfd_reloc_ok:
+ break;
+ case bfd_reloc_overflow:
+ as_bad_where (fixp->fx_file, fixp->fx_line, _("relocation overflow"));
+ break;
+ case bfd_reloc_outofrange:
+ as_bad_where (fixp->fx_file, fixp->fx_line, _("relocation out of range"));
+ break;
+ default:
+ as_fatal (_("%s:%u: bad return from bfd_install_relocation: %x"),
+ fixp->fx_file, fixp->fx_line, s);
+ }
+ relocs[i++] = reloc;
+ }
+#else
+ n = n * MAX_RELOC_EXPANSION;
+ /* Set up reloc information as well. */
+ relocs = (arelent **) xmalloc (n * sizeof (arelent *));
+
+ i = 0;
+ for (fixp = seginfo->fix_root; fixp != (fixS *) NULL; fixp = fixp->fx_next)
+ {
+ arelent **reloc;
+ char *data;
+ bfd_reloc_status_type s;
+ symbolS *sym;
+ int j;
+
+ if (fixp->fx_done)
+ {
+ n--;
+ continue;
+ }
+
+ /* If this is an undefined symbol which was equated to another
+ symbol, then use generate the reloc against the latter symbol
+ rather than the former. */
+ sym = fixp->fx_addsy;
+ while (sym->sy_value.X_op == O_symbol
+ && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
+ sym = sym->sy_value.X_add_symbol;
+ fixp->fx_addsy = sym;
+
+ reloc = tc_gen_reloc (sec, fixp);
+
+ for (j = 0; reloc[j]; j++)
+ {
+ relocs[i++] = reloc[j];
+ assert(i <= n);
+ }
+ data = fixp->fx_frag->fr_literal + fixp->fx_where;
+ if (fixp->fx_where + fixp->fx_size
+ > fixp->fx_frag->fr_fix + fixp->fx_frag->fr_offset)
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("internal error: fixup not contained within frag"));
+ for (j = 0; reloc[j]; j++)
+ {
+ s = bfd_install_relocation (stdoutput, reloc[j],
+ fixp->fx_frag->fr_literal,
+ fixp->fx_frag->fr_address,
+ sec, &err);
+ switch (s)
+ {
+ case bfd_reloc_ok:
+ break;
+ case bfd_reloc_overflow:
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("relocation overflow"));
+ break;
+ default:
+ as_fatal (_("%s:%u: bad return from bfd_install_relocation"),
+ fixp->fx_file, fixp->fx_line);
+ }
+ }
+ }
+ n = i;
+#endif
+
+#ifdef DEBUG4
+ {
+ int i, j, nsyms;
+ asymbol **sympp;
+ sympp = bfd_get_outsymbols (stdoutput);
+ nsyms = bfd_get_symcount (stdoutput);
+ for (i = 0; i < n; i++)
+ if (((*relocs[i]->sym_ptr_ptr)->flags & BSF_SECTION_SYM) == 0)
+ {
+ for (j = 0; j < nsyms; j++)
+ if (sympp[j] == *relocs[i]->sym_ptr_ptr)
+ break;
+ if (j == nsyms)
+ abort ();
+ }
+ }
+#endif
+
+ if (n)
+ bfd_set_reloc (stdoutput, sec, relocs, n);
+ else
+ bfd_set_section_flags (abfd, sec,
+ (bfd_get_section_flags (abfd, sec)
+ & (flagword) ~SEC_RELOC));
+
+#ifdef DEBUG3
+ {
+ int i;
+ arelent *r;
+ asymbol *s;
+ fprintf (stderr, "relocs for sec %s\n", sec->name);
+ for (i = 0; i < n; i++)
+ {
+ r = relocs[i];
+ s = *r->sym_ptr_ptr;
+ fprintf (stderr, " reloc %2d @%08x off %4x : sym %-10s addend %x\n",
+ i, r, r->address, s->name, r->addend);
+ }
+ }
+#endif
+}
+
+static void
+write_contents (abfd, sec, xxx)
+ bfd *abfd;
+ asection *sec;
+ PTR xxx;
+{
+ segment_info_type *seginfo = seg_info (sec);
+ unsigned long offset = 0;
+ fragS *f;
+
+ /* Write out the frags. */
+ if (seginfo == NULL
+ || ! (bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS))
+ return;
+
+ for (f = seginfo->frchainP->frch_root;
+ f;
+ f = f->fr_next)
+ {
+ int x;
+ unsigned long fill_size;
+ char *fill_literal;
+ long count;
+
+ assert (f->fr_type == rs_fill);
+ if (f->fr_fix)
+ {
+ x = bfd_set_section_contents (stdoutput, sec,
+ f->fr_literal, (file_ptr) offset,
+ (bfd_size_type) f->fr_fix);
+ if (x == false)
+ {
+ bfd_perror (stdoutput->filename);
+ as_perror (_("FATAL: Can't write %s"), stdoutput->filename);
+ exit (EXIT_FAILURE);
+ }
+ offset += f->fr_fix;
+ }
+ fill_literal = f->fr_literal + f->fr_fix;
+ fill_size = f->fr_var;
+ count = f->fr_offset;
+ assert (count >= 0);
+ if (fill_size && count)
+ {
+ char buf[256];
+ if (fill_size > sizeof(buf))
+ {
+ /* Do it the old way. Can this ever happen? */
+ while (count--)
+ {
+ x = bfd_set_section_contents (stdoutput, sec,
+ fill_literal,
+ (file_ptr) offset,
+ (bfd_size_type) fill_size);
+ if (x == false)
+ {
+ bfd_perror (stdoutput->filename);
+ as_perror (_("FATAL: Can't write %s"), stdoutput->filename);
+ exit (EXIT_FAILURE);
+ }
+ offset += fill_size;
+ }
+ }
+ else
+ {
+ /* Build a buffer full of fill objects and output it as
+ often as necessary. This saves on the overhead of
+ potentially lots of bfd_set_section_contents calls. */
+ int n_per_buf, i;
+ if (fill_size == 1)
+ {
+ n_per_buf = sizeof (buf);
+ memset (buf, *fill_literal, n_per_buf);
+ }
+ else
+ {
+ char *bufp;
+ n_per_buf = sizeof(buf)/fill_size;
+ for (i = n_per_buf, bufp = buf; i; i--, bufp += fill_size)
+ memcpy(bufp, fill_literal, fill_size);
+ }
+ for (; count > 0; count -= n_per_buf)
+ {
+ n_per_buf = n_per_buf > count ? count : n_per_buf;
+ x = bfd_set_section_contents (stdoutput, sec,
+ buf, (file_ptr) offset,
+ (bfd_size_type) n_per_buf * fill_size);
+ if (x != true)
+ as_fatal (_("Cannot write to output file."));
+ offset += n_per_buf * fill_size;
+ }
+ }
+ }
+ }
+}
+#endif
+
+#if defined(BFD_ASSEMBLER) || (!defined (BFD) && !defined(OBJ_AOUT))
+static void
+merge_data_into_text ()
+{
+#if defined(BFD_ASSEMBLER) || defined(MANY_SEGMENTS)
+ seg_info (text_section)->frchainP->frch_last->fr_next =
+ seg_info (data_section)->frchainP->frch_root;
+ seg_info (text_section)->frchainP->frch_last =
+ seg_info (data_section)->frchainP->frch_last;
+ seg_info (data_section)->frchainP = 0;
+#else
+ fixS *tmp;
+
+ text_last_frag->fr_next = data_frag_root;
+ text_last_frag = data_last_frag;
+ data_last_frag = NULL;
+ data_frag_root = NULL;
+ if (text_fix_root)
+ {
+ for (tmp = text_fix_root; tmp->fx_next; tmp = tmp->fx_next);;
+ tmp->fx_next = data_fix_root;
+ text_fix_tail = data_fix_tail;
+ }
+ else
+ text_fix_root = data_fix_root;
+ data_fix_root = NULL;
+#endif
+}
+#endif /* BFD_ASSEMBLER || (! BFD && ! OBJ_AOUT) */
+
+#if !defined (BFD_ASSEMBLER) && !defined (BFD)
+static void
+relax_and_size_all_segments ()
+{
+ fragS *fragP;
+
+ relax_segment (text_frag_root, SEG_TEXT);
+ relax_segment (data_frag_root, SEG_DATA);
+ relax_segment (bss_frag_root, SEG_BSS);
+ /*
+ * Now the addresses of frags are correct within the segment.
+ */
+
+ know (text_last_frag->fr_type == rs_fill && text_last_frag->fr_offset == 0);
+ H_SET_TEXT_SIZE (&headers, text_last_frag->fr_address);
+ text_last_frag->fr_address = H_GET_TEXT_SIZE (&headers);
+
+ /*
+ * Join the 2 segments into 1 huge segment.
+ * To do this, re-compute every rn_address in the SEG_DATA frags.
+ * Then join the data frags after the text frags.
+ *
+ * Determine a_data [length of data segment].
+ */
+ if (data_frag_root)
+ {
+ register relax_addressT slide;
+
+ know ((text_last_frag->fr_type == rs_fill) && (text_last_frag->fr_offset == 0));
+
+ H_SET_DATA_SIZE (&headers, data_last_frag->fr_address);
+ data_last_frag->fr_address = H_GET_DATA_SIZE (&headers);
+ slide = H_GET_TEXT_SIZE (&headers); /* & in file of the data segment. */
+#ifdef OBJ_BOUT
+#define RoundUp(N,S) (((N)+(S)-1)&-(S))
+ /* For b.out: If the data section has a strict alignment
+ requirement, its load address in the .o file will be
+ rounded up from the size of the text section. These
+ two values are *not* the same! Similarly for the bss
+ section.... */
+ slide = RoundUp (slide, 1 << section_alignment[SEG_DATA]);
+#endif
+
+ for (fragP = data_frag_root; fragP; fragP = fragP->fr_next)
+ {
+ fragP->fr_address += slide;
+ } /* for each data frag */
+
+ know (text_last_frag != 0);
+ text_last_frag->fr_next = data_frag_root;
+ }
+ else
+ {
+ H_SET_DATA_SIZE (&headers, 0);
+ }
+
+#ifdef OBJ_BOUT
+ /* See above comments on b.out data section address. */
+ {
+ long bss_vma;
+ if (data_last_frag == 0)
+ bss_vma = H_GET_TEXT_SIZE (&headers);
+ else
+ bss_vma = data_last_frag->fr_address;
+ bss_vma = RoundUp (bss_vma, 1 << section_alignment[SEG_BSS]);
+ bss_address_frag.fr_address = bss_vma;
+ }
+#else /* ! OBJ_BOUT */
+ bss_address_frag.fr_address = (H_GET_TEXT_SIZE (&headers) +
+ H_GET_DATA_SIZE (&headers));
+
+#endif /* ! OBJ_BOUT */
+
+ /* Slide all the frags */
+ if (bss_frag_root)
+ {
+ relax_addressT slide = bss_address_frag.fr_address;
+
+ for (fragP = bss_frag_root; fragP; fragP = fragP->fr_next)
+ {
+ fragP->fr_address += slide;
+ } /* for each bss frag */
+ }
+
+ if (bss_last_frag)
+ H_SET_BSS_SIZE (&headers,
+ bss_last_frag->fr_address - bss_frag_root->fr_address);
+ else
+ H_SET_BSS_SIZE (&headers, 0);
+}
+#endif /* ! BFD_ASSEMBLER && ! BFD */
+
+#if defined (BFD_ASSEMBLER) || !defined (BFD)
+
+#ifdef BFD_ASSEMBLER
+static void
+set_symtab ()
+{
+ int nsyms;
+ asymbol **asympp;
+ symbolS *symp;
+ boolean result;
+ extern PTR bfd_alloc PARAMS ((bfd *, size_t));
+
+ /* Count symbols. We can't rely on a count made by the loop in
+ write_object_file, because *_frob_file may add a new symbol or
+ two. */
+ nsyms = 0;
+ for (symp = symbol_rootP; symp; symp = symbol_next (symp))
+ nsyms++;
+
+ if (nsyms)
+ {
+ int i;
+
+ asympp = (asymbol **) bfd_alloc (stdoutput,
+ nsyms * sizeof (asymbol *));
+ symp = symbol_rootP;
+ for (i = 0; i < nsyms; i++, symp = symbol_next (symp))
+ {
+ asympp[i] = symp->bsym;
+ symp->written = 1;
+ }
+ }
+ else
+ asympp = 0;
+ result = bfd_set_symtab (stdoutput, asympp, nsyms);
+ assert (result == true);
+ symbol_table_frozen = 1;
+}
+#endif
+
+/* Finish the subsegments. After every sub-segment, we fake an
+ ".align ...". This conforms to BSD4.2 brane-damage. We then fake
+ ".fill 0" because that is the kind of frag that requires least
+ thought. ".align" frags like to have a following frag since that
+ makes calculating their intended length trivial. */
+
+#ifndef SUB_SEGMENT_ALIGN
+#ifdef BFD_ASSEMBLER
+#define SUB_SEGMENT_ALIGN(SEG) (0)
+#else
+#define SUB_SEGMENT_ALIGN(SEG) (2)
+#endif
+#endif
+
+void
+subsegs_finish ()
+{
+ struct frchain *frchainP;
+
+ for (frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next)
+ {
+ subseg_set (frchainP->frch_seg, frchainP->frch_subseg);
+
+ /* This now gets called even if we had errors. In that case,
+ any alignment is meaningless, and, moreover, will look weird
+ if we are generating a listing. */
+ frag_align (had_errors () ? 0 : SUB_SEGMENT_ALIGN (now_seg),
+ NOP_OPCODE, 0);
+
+ /* frag_align will have left a new frag.
+ Use this last frag for an empty ".fill".
+
+ For this segment ...
+ Create a last frag. Do not leave a "being filled in frag". */
+
+ frag_wane (frag_now);
+ frag_now->fr_fix = 0;
+ know (frag_now->fr_next == NULL);
+ }
+}
+
+/* Write the object file. */
+
+void
+write_object_file ()
+{
+#if ! defined (BFD_ASSEMBLER) || ! defined (WORKING_DOT_WORD)
+ fragS *fragP; /* Track along all frags. */
+#endif
+
+ /* Do we really want to write it? */
+ {
+ int n_warns, n_errs;
+ n_warns = had_warnings ();
+ n_errs = had_errors ();
+ /* The -Z flag indicates that an object file should be generated,
+ regardless of warnings and errors. */
+ if (flag_always_generate_output)
+ {
+ if (n_warns || n_errs)
+ as_warn (_("%d error%s, %d warning%s, generating bad object file.\n"),
+ n_errs, n_errs == 1 ? "" : "s",
+ n_warns, n_warns == 1 ? "" : "s");
+ }
+ else
+ {
+ if (n_errs)
+ as_fatal (_("%d error%s, %d warning%s, no object file generated.\n"),
+ n_errs, n_errs == 1 ? "" : "s",
+ n_warns, n_warns == 1 ? "" : "s");
+ }
+ }
+
+#ifdef OBJ_VMS
+ /* Under VMS we try to be compatible with VAX-11 "C". Thus, we call
+ a routine to check for the definition of the procedure "_main",
+ and if so -- fix it up so that it can be program entry point. */
+ vms_check_for_main ();
+#endif /* OBJ_VMS */
+
+ /* From now on, we don't care about sub-segments. Build one frag chain
+ for each segment. Linked thru fr_next. */
+
+#ifdef BFD_ASSEMBLER
+ /* Remove the sections created by gas for its own purposes. */
+ {
+ asection **seclist, *sec;
+ int i;
+
+ seclist = &stdoutput->sections;
+ while (seclist && *seclist)
+ {
+ sec = *seclist;
+ while (sec == reg_section || sec == expr_section)
+ {
+ sec = sec->next;
+ *seclist = sec;
+ stdoutput->section_count--;
+ if (!sec)
+ break;
+ }
+ if (*seclist)
+ seclist = &(*seclist)->next;
+ }
+ i = 0;
+ bfd_map_over_sections (stdoutput, renumber_sections, &i);
+ }
+
+ bfd_map_over_sections (stdoutput, chain_frchains_together, (char *) 0);
+#else
+ remove_subsegs (frchain_root, SEG_TEXT, &text_frag_root, &text_last_frag);
+ remove_subsegs (data0_frchainP, SEG_DATA, &data_frag_root, &data_last_frag);
+ remove_subsegs (bss0_frchainP, SEG_BSS, &bss_frag_root, &bss_last_frag);
+#endif
+
+ /* We have two segments. If user gave -R flag, then we must put the
+ data frags into the text segment. Do this before relaxing so
+ we know to take advantage of -R and make shorter addresses. */
+#if !defined (OBJ_AOUT) || defined (BFD_ASSEMBLER)
+ if (flag_readonly_data_in_text)
+ {
+ merge_data_into_text ();
+ }
+#endif
+
+#ifdef BFD_ASSEMBLER
+ bfd_map_over_sections (stdoutput, relax_and_size_seg, (char *) 0);
+#else
+ relax_and_size_all_segments ();
+#endif /* BFD_ASSEMBLER */
+
+#ifndef BFD_ASSEMBLER
+ /*
+ *
+ * Crawl the symbol chain.
+ *
+ * For each symbol whose value depends on a frag, take the address of
+ * that frag and subsume it into the value of the symbol.
+ * After this, there is just one way to lookup a symbol value.
+ * Values are left in their final state for object file emission.
+ * We adjust the values of 'L' local symbols, even if we do
+ * not intend to emit them to the object file, because their values
+ * are needed for fix-ups.
+ *
+ * Unless we saw a -L flag, remove all symbols that begin with 'L'
+ * from the symbol chain. (They are still pointed to by the fixes.)
+ *
+ * Count the remaining symbols.
+ * Assign a symbol number to each symbol.
+ * Count the number of string-table chars we will emit.
+ * Put this info into the headers as appropriate.
+ *
+ */
+ know (zero_address_frag.fr_address == 0);
+ string_byte_count = sizeof (string_byte_count);
+
+ obj_crawl_symbol_chain (&headers);
+
+ if (string_byte_count == sizeof (string_byte_count))
+ string_byte_count = 0;
+
+ H_SET_STRING_SIZE (&headers, string_byte_count);
+
+ /*
+ * Addresses of frags now reflect addresses we use in the object file.
+ * Symbol values are correct.
+ * Scan the frags, converting any ".org"s and ".align"s to ".fill"s.
+ * Also converting any machine-dependent frags using md_convert_frag();
+ */
+ subseg_change (SEG_TEXT, 0);
+
+ for (fragP = text_frag_root; fragP; fragP = fragP->fr_next)
+ {
+ /* At this point we have linked all the frags into a single
+ chain. However, cvt_frag_to_fill may call md_convert_frag
+ which may call fix_new. We need to ensure that fix_new adds
+ the fixup to the right section. */
+ if (fragP == data_frag_root)
+ subseg_change (SEG_DATA, 0);
+
+ cvt_frag_to_fill (&headers, SEG_TEXT, fragP);
+
+ /* Some assert macros don't work with # directives mixed in. */
+#ifndef NDEBUG
+ if (!(fragP->fr_next == NULL
+#ifdef OBJ_BOUT
+ || fragP->fr_next == data_frag_root
+#endif
+ || ((fragP->fr_next->fr_address - fragP->fr_address)
+ == (fragP->fr_fix + fragP->fr_offset * fragP->fr_var))))
+ abort ();
+#endif
+ }
+#endif /* ! BFD_ASSEMBLER */
+
+#ifndef WORKING_DOT_WORD
+ {
+ struct broken_word *lie;
+ struct broken_word **prevP;
+
+ prevP = &broken_words;
+ for (lie = broken_words; lie; lie = lie->next_broken_word)
+ if (!lie->added)
+ {
+ expressionS exp;
+
+ subseg_change (lie->seg, lie->subseg);
+ exp.X_op = O_subtract;
+ exp.X_add_symbol = lie->add;
+ exp.X_op_symbol = lie->sub;
+ exp.X_add_number = lie->addnum;
+#ifdef BFD_ASSEMBLER
+#ifdef TC_CONS_FIX_NEW
+ TC_CONS_FIX_NEW (lie->frag,
+ lie->word_goes_here - lie->frag->fr_literal,
+ 2, &exp);
+#else
+ fix_new_exp (lie->frag,
+ lie->word_goes_here - lie->frag->fr_literal,
+ 2, &exp, 0, BFD_RELOC_16);
+#endif
+#else
+#if defined(TC_SPARC) || defined(TC_A29K) || defined(NEED_FX_R_TYPE)
+ fix_new_exp (lie->frag,
+ lie->word_goes_here - lie->frag->fr_literal,
+ 2, &exp, 0, NO_RELOC);
+#else
+#ifdef TC_NS32K
+ fix_new_ns32k_exp (lie->frag,
+ lie->word_goes_here - lie->frag->fr_literal,
+ 2, &exp, 0, 0, 2, 0, 0);
+#else
+ fix_new_exp (lie->frag,
+ lie->word_goes_here - lie->frag->fr_literal,
+ 2, &exp, 0, 0);
+#endif /* TC_NS32K */
+#endif /* TC_SPARC|TC_A29K|NEED_FX_R_TYPE */
+#endif /* BFD_ASSEMBLER */
+ *prevP = lie->next_broken_word;
+ }
+ else
+ prevP = &(lie->next_broken_word);
+
+ for (lie = broken_words; lie;)
+ {
+ struct broken_word *untruth;
+ char *table_ptr;
+ addressT table_addr;
+ addressT from_addr, to_addr;
+ int n, m;
+
+ subseg_change (lie->seg, lie->subseg);
+ fragP = lie->dispfrag;
+
+ /* Find out how many broken_words go here. */
+ n = 0;
+ for (untruth = lie; untruth && untruth->dispfrag == fragP; untruth = untruth->next_broken_word)
+ if (untruth->added == 1)
+ n++;
+
+ table_ptr = lie->dispfrag->fr_opcode;
+ table_addr = lie->dispfrag->fr_address + (table_ptr - lie->dispfrag->fr_literal);
+ /* Create the jump around the long jumps. This is a short
+ jump from table_ptr+0 to table_ptr+n*long_jump_size. */
+ from_addr = table_addr;
+ to_addr = table_addr + md_short_jump_size + n * md_long_jump_size;
+ md_create_short_jump (table_ptr, from_addr, to_addr, lie->dispfrag, lie->add);
+ table_ptr += md_short_jump_size;
+ table_addr += md_short_jump_size;
+
+ for (m = 0; lie && lie->dispfrag == fragP; m++, lie = lie->next_broken_word)
+ {
+ if (lie->added == 2)
+ continue;
+ /* Patch the jump table */
+ /* This is the offset from ??? to table_ptr+0 */
+ to_addr = table_addr - S_GET_VALUE (lie->sub);
+#ifdef BFD_ASSEMBLER
+ to_addr -= lie->sub->sy_frag->fr_address;
+#endif
+ md_number_to_chars (lie->word_goes_here, to_addr, 2);
+ for (untruth = lie->next_broken_word; untruth && untruth->dispfrag == fragP; untruth = untruth->next_broken_word)
+ {
+ if (untruth->use_jump == lie)
+ md_number_to_chars (untruth->word_goes_here, to_addr, 2);
+ }
+
+ /* Install the long jump */
+ /* this is a long jump from table_ptr+0 to the final target */
+ from_addr = table_addr;
+ to_addr = S_GET_VALUE (lie->add) + lie->addnum;
+#ifdef BFD_ASSEMBLER
+ to_addr += lie->add->sy_frag->fr_address;
+#endif
+ md_create_long_jump (table_ptr, from_addr, to_addr, lie->dispfrag, lie->add);
+ table_ptr += md_long_jump_size;
+ table_addr += md_long_jump_size;
+ }
+ }
+ }
+#endif /* not WORKING_DOT_WORD */
+
+#ifndef BFD_ASSEMBLER
+#ifndef OBJ_VMS
+ { /* not vms */
+ char *the_object_file;
+ long object_file_size;
+ /*
+ * Scan every FixS performing fixups. We had to wait until now to do
+ * this because md_convert_frag() may have made some fixSs.
+ */
+ int trsize, drsize;
+
+ subseg_change (SEG_TEXT, 0);
+ trsize = md_reloc_size * fixup_segment (text_fix_root, SEG_TEXT);
+ subseg_change (SEG_DATA, 0);
+ drsize = md_reloc_size * fixup_segment (data_fix_root, SEG_DATA);
+ H_SET_RELOCATION_SIZE (&headers, trsize, drsize);
+
+ /* FIXME move this stuff into the pre-write-hook */
+ H_SET_MAGIC_NUMBER (&headers, magic_number_for_object_file);
+ H_SET_ENTRY_POINT (&headers, 0);
+
+ obj_pre_write_hook (&headers); /* extra coff stuff */
+
+ object_file_size = H_GET_FILE_SIZE (&headers);
+ next_object_file_charP = the_object_file = xmalloc (object_file_size);
+
+ output_file_create (out_file_name);
+
+ obj_header_append (&next_object_file_charP, &headers);
+
+ know ((next_object_file_charP - the_object_file) == H_GET_HEADER_SIZE (&headers));
+
+ /*
+ * Emit code.
+ */
+ for (fragP = text_frag_root; fragP; fragP = fragP->fr_next)
+ {
+ register long count;
+ register char *fill_literal;
+ register long fill_size;
+
+ PROGRESS (1);
+ know (fragP->fr_type == rs_fill);
+ append (&next_object_file_charP, fragP->fr_literal, (unsigned long) fragP->fr_fix);
+ fill_literal = fragP->fr_literal + fragP->fr_fix;
+ fill_size = fragP->fr_var;
+ know (fragP->fr_offset >= 0);
+
+ for (count = fragP->fr_offset; count; count--)
+ {
+ append (&next_object_file_charP, fill_literal, (unsigned long) fill_size);
+ } /* for each */
+
+ } /* for each code frag. */
+
+ know ((next_object_file_charP - the_object_file) == (H_GET_HEADER_SIZE (&headers) + H_GET_TEXT_SIZE (&headers) + H_GET_DATA_SIZE (&headers)));
+
+ /*
+ * Emit relocations.
+ */
+ obj_emit_relocations (&next_object_file_charP, text_fix_root, (relax_addressT) 0);
+ know ((next_object_file_charP - the_object_file) == (H_GET_HEADER_SIZE (&headers) + H_GET_TEXT_SIZE (&headers) + H_GET_DATA_SIZE (&headers) + H_GET_TEXT_RELOCATION_SIZE (&headers)));
+#ifdef TC_I960
+ /* Make addresses in data relocation directives relative to beginning of
+ * first data fragment, not end of last text fragment: alignment of the
+ * start of the data segment may place a gap between the segments.
+ */
+ obj_emit_relocations (&next_object_file_charP, data_fix_root, data0_frchainP->frch_root->fr_address);
+#else /* TC_I960 */
+ obj_emit_relocations (&next_object_file_charP, data_fix_root, text_last_frag->fr_address);
+#endif /* TC_I960 */
+
+ know ((next_object_file_charP - the_object_file) == (H_GET_HEADER_SIZE (&headers) + H_GET_TEXT_SIZE (&headers) + H_GET_DATA_SIZE (&headers) + H_GET_TEXT_RELOCATION_SIZE (&headers) + H_GET_DATA_RELOCATION_SIZE (&headers)));
+
+ /*
+ * Emit line number entries.
+ */
+ OBJ_EMIT_LINENO (&next_object_file_charP, lineno_rootP, the_object_file);
+ know ((next_object_file_charP - the_object_file) == (H_GET_HEADER_SIZE (&headers) + H_GET_TEXT_SIZE (&headers) + H_GET_DATA_SIZE (&headers) + H_GET_TEXT_RELOCATION_SIZE (&headers) + H_GET_DATA_RELOCATION_SIZE (&headers) + H_GET_LINENO_SIZE (&headers)));
+
+ /*
+ * Emit symbols.
+ */
+ obj_emit_symbols (&next_object_file_charP, symbol_rootP);
+ know ((next_object_file_charP - the_object_file) == (H_GET_HEADER_SIZE (&headers) + H_GET_TEXT_SIZE (&headers) + H_GET_DATA_SIZE (&headers) + H_GET_TEXT_RELOCATION_SIZE (&headers) + H_GET_DATA_RELOCATION_SIZE (&headers) + H_GET_LINENO_SIZE (&headers) + H_GET_SYMBOL_TABLE_SIZE (&headers)));
+
+ /*
+ * Emit strings.
+ */
+
+ if (string_byte_count > 0)
+ {
+ obj_emit_strings (&next_object_file_charP);
+ } /* only if we have a string table */
+
+#ifdef BFD_HEADERS
+ bfd_seek (stdoutput, 0, 0);
+ bfd_write (the_object_file, 1, object_file_size, stdoutput);
+#else
+
+ /* Write the data to the file */
+ output_file_append (the_object_file, object_file_size, out_file_name);
+ free (the_object_file);
+#endif
+ } /* non vms output */
+#else /* OBJ_VMS */
+ /*
+ * Now do the VMS-dependent part of writing the object file
+ */
+ vms_write_object_file (H_GET_TEXT_SIZE (&headers),
+ H_GET_DATA_SIZE (&headers),
+ H_GET_BSS_SIZE (&headers),
+ text_frag_root, data_frag_root);
+#endif /* OBJ_VMS */
+#else /* BFD_ASSEMBLER */
+
+ /* Resolve symbol values. This needs to be done before processing
+ the relocations. */
+ if (symbol_rootP)
+ {
+ symbolS *symp;
+
+ for (symp = symbol_rootP; symp; symp = symbol_next (symp))
+ if (!symp->sy_resolved)
+ resolve_symbol_value (symp, 1);
+ }
+
+ PROGRESS (1);
+
+#ifdef tc_frob_file_before_adjust
+ tc_frob_file_before_adjust ();
+#endif
+#ifdef obj_frob_file_before_adjust
+ obj_frob_file_before_adjust ();
+#endif
+
+ bfd_map_over_sections (stdoutput, adjust_reloc_syms, (char *)0);
+
+ /* Set up symbol table, and write it out. */
+ if (symbol_rootP)
+ {
+ symbolS *symp;
+
+ for (symp = symbol_rootP; symp; symp = symbol_next (symp))
+ {
+ int punt = 0;
+ const char *name;
+
+ if (symp->sy_mri_common)
+ {
+ if (S_IS_EXTERNAL (symp))
+ as_bad (_("%s: global symbols not supported in common sections"),
+ S_GET_NAME (symp));
+ symbol_remove (symp, &symbol_rootP, &symbol_lastP);
+ continue;
+ }
+
+ name = S_GET_NAME (symp);
+ if (name)
+ {
+ const char *name2 = decode_local_label_name ((char *)S_GET_NAME (symp));
+ /* They only differ if `name' is a fb or dollar local
+ label name. */
+ if (name2 != name && ! S_IS_DEFINED (symp))
+ as_bad (_("local label %s is not defined"), name2);
+ }
+
+ /* Do it again, because adjust_reloc_syms might introduce
+ more symbols. They'll probably only be section symbols,
+ but they'll still need to have the values computed. */
+ if (! symp->sy_resolved)
+ {
+ if (symp->sy_value.X_op == O_constant)
+ {
+ /* This is the normal case; skip the call. */
+ S_SET_VALUE (symp,
+ (S_GET_VALUE (symp)
+ + symp->sy_frag->fr_address));
+ symp->sy_resolved = 1;
+ }
+ else
+ resolve_symbol_value (symp, 1);
+ }
+
+ /* Skip symbols which were equated to undefined or common
+ symbols. */
+ if (symp->sy_value.X_op == O_symbol
+ && (! S_IS_DEFINED (symp) || S_IS_COMMON (symp)))
+ {
+ symbol_remove (symp, &symbol_rootP, &symbol_lastP);
+ continue;
+ }
+
+ /* So far, common symbols have been treated like undefined symbols.
+ Put them in the common section now. */
+ if (S_IS_DEFINED (symp) == 0
+ && S_GET_VALUE (symp) != 0)
+ S_SET_SEGMENT (symp, bfd_com_section_ptr);
+#if 0
+ printf ("symbol `%s'\n\t@%x: value=%d flags=%x seg=%s\n",
+ S_GET_NAME (symp), symp,
+ S_GET_VALUE (symp),
+ symp->bsym->flags,
+ segment_name (symp->bsym->section));
+#endif
+
+#ifdef obj_frob_symbol
+ obj_frob_symbol (symp, punt);
+#endif
+#ifdef tc_frob_symbol
+ if (! punt || symp->sy_used_in_reloc)
+ tc_frob_symbol (symp, punt);
+#endif
+
+ /* If we don't want to keep this symbol, splice it out of
+ the chain now. If EMIT_SECTION_SYMBOLS is 0, we never
+ want section symbols. Otherwise, we skip local symbols
+ and symbols that the frob_symbol macros told us to punt,
+ but we keep such symbols if they are used in relocs. */
+ if ((! EMIT_SECTION_SYMBOLS
+ && (symp->bsym->flags & BSF_SECTION_SYM) != 0)
+ /* Note that S_IS_EXTERN and S_IS_LOCAL are not always
+ opposites. Sometimes the former checks flags and the
+ latter examines the name... */
+ || (!S_IS_EXTERN (symp)
+ && (S_IS_LOCAL (symp) || punt)
+ && ! symp->sy_used_in_reloc))
+ {
+ symbol_remove (symp, &symbol_rootP, &symbol_lastP);
+ /* After symbol_remove, symbol_next(symp) still returns
+ the one that came after it in the chain. So we don't
+ need to do any extra cleanup work here. */
+
+ continue;
+ }
+
+ /* Make sure we really got a value for the symbol. */
+ if (! symp->sy_resolved)
+ {
+ as_bad (_("can't resolve value for symbol \"%s\""),
+ S_GET_NAME (symp));
+ symp->sy_resolved = 1;
+ }
+
+ /* Set the value into the BFD symbol. Up til now the value
+ has only been kept in the gas symbolS struct. */
+ symp->bsym->value = S_GET_VALUE (symp);
+ }
+ }
+
+ PROGRESS (1);
+
+ /* Now do any format-specific adjustments to the symbol table, such
+ as adding file symbols. */
+#ifdef tc_adjust_symtab
+ tc_adjust_symtab ();
+#endif
+#ifdef obj_adjust_symtab
+ obj_adjust_symtab ();
+#endif
+
+ /* Now that all the sizes are known, and contents correct, we can
+ start writing to the file. */
+ set_symtab ();
+
+ /* If *_frob_file changes the symbol value at this point, it is
+ responsible for moving the changed value into symp->bsym->value
+ as well. Hopefully all symbol value changing can be done in
+ *_frob_symbol. */
+#ifdef tc_frob_file
+ tc_frob_file ();
+#endif
+#ifdef obj_frob_file
+ obj_frob_file ();
+#endif
+
+ bfd_map_over_sections (stdoutput, write_relocs, (char *) 0);
+
+#ifdef tc_frob_file_after_relocs
+ tc_frob_file_after_relocs ();
+#endif
+#ifdef obj_frob_file_after_relocs
+ obj_frob_file_after_relocs ();
+#endif
+
+ bfd_map_over_sections (stdoutput, write_contents, (char *) 0);
+#endif /* BFD_ASSEMBLER */
+}
+#endif /* ! BFD */
+
+/*
+ * relax_segment()
+ *
+ * Now we have a segment, not a crowd of sub-segments, we can make fr_address
+ * values.
+ *
+ * Relax the frags.
+ *
+ * After this, all frags in this segment have addresses that are correct
+ * within the segment. Since segments live in different file addresses,
+ * these frag addresses may not be the same as final object-file addresses.
+ */
+
+#ifdef TC_GENERIC_RELAX_TABLE
+
+static int is_dnrange PARAMS ((fragS *, fragS *));
+
+/* Subroutines of relax_segment. */
+static int
+is_dnrange (f1, f2)
+ fragS *f1;
+ fragS *f2;
+{
+ for (; f1; f1 = f1->fr_next)
+ if (f1->fr_next == f2)
+ return 1;
+ return 0;
+}
+
+/* Relax a fragment by scanning TC_GENERIC_RELAX_TABLE. */
+
+long
+relax_frag (fragP, stretch)
+ fragS *fragP;
+ long stretch;
+{
+ const relax_typeS *this_type;
+ const relax_typeS *start_type;
+ relax_substateT next_state;
+ relax_substateT this_state;
+ long aim, target, growth;
+ symbolS *symbolP = fragP->fr_symbol;
+ long offset = fragP->fr_offset;
+ /* Recompute was_address by undoing "+= stretch" done by relax_segment. */
+ unsigned long was_address = fragP->fr_address - stretch;
+ unsigned long address = fragP->fr_address;
+ const relax_typeS *table = TC_GENERIC_RELAX_TABLE;
+
+ this_state = fragP->fr_subtype;
+ start_type = this_type = table + this_state;
+ target = offset;
+
+ if (symbolP)
+ {
+#ifndef DIFF_EXPR_OK
+#if !defined (MANY_SEGMENTS) && !defined (BFD_ASSEMBLER)
+ know ((S_GET_SEGMENT (symbolP) == SEG_ABSOLUTE)
+ || (S_GET_SEGMENT (symbolP) == SEG_DATA)
+ || (S_GET_SEGMENT (symbolP) == SEG_BSS)
+ || (S_GET_SEGMENT (symbolP) == SEG_TEXT));
+#endif
+ know (symbolP->sy_frag);
+#endif
+ know (!(S_GET_SEGMENT (symbolP) == absolute_section)
+ || symbolP->sy_frag == &zero_address_frag);
+ target +=
+ S_GET_VALUE (symbolP)
+ + symbolP->sy_frag->fr_address;
+
+ /* If frag has yet to be reached on this pass,
+ assume it will move by STRETCH just as we did.
+ If this is not so, it will be because some frag
+ between grows, and that will force another pass.
+
+ Beware zero-length frags.
+
+ There should be a faster way to do this. */
+
+ if (symbolP->sy_frag->fr_address >= was_address
+ && is_dnrange (fragP, symbolP->sy_frag))
+ {
+ target += stretch;
+ }
+ }
+
+ aim = target - address - fragP->fr_fix;
+#ifdef TC_PCREL_ADJUST
+ /* Currently only the ns32k family needs this */
+ aim += TC_PCREL_ADJUST(fragP);
+/*#else*/
+ /* This machine doesn't want to use pcrel_adjust.
+ In that case, pcrel_adjust should be zero. */
+/* assert (fragP->fr_targ.ns32k.pcrel_adjust == 0);*/
+#endif
+#ifdef md_prepare_relax_scan /* formerly called M68K_AIM_KLUDGE */
+ md_prepare_relax_scan (fragP, address, aim, this_state, this_type);
+#endif
+
+ if (aim < 0)
+ {
+ /* Look backwards. */
+ for (next_state = this_type->rlx_more; next_state;)
+ if (aim >= this_type->rlx_backward)
+ next_state = 0;
+ else
+ {
+ /* Grow to next state. */
+ this_state = next_state;
+ this_type = table + this_state;
+ next_state = this_type->rlx_more;
+ }
+ }
+ else
+ {
+ /* Look forwards. */
+ for (next_state = this_type->rlx_more; next_state;)
+ if (aim <= this_type->rlx_forward)
+ next_state = 0;
+ else
+ {
+ /* Grow to next state. */
+ this_state = next_state;
+ this_type = table + this_state;
+ next_state = this_type->rlx_more;
+ }
+ }
+
+ growth = this_type->rlx_length - start_type->rlx_length;
+ if (growth != 0)
+ fragP->fr_subtype = this_state;
+ return growth;
+}
+
+#endif /* defined (TC_GENERIC_RELAX_TABLE) */
+
+/* Relax_align. Advance location counter to next address that has 'alignment'
+ lowest order bits all 0s, return size of adjustment made. */
+static relax_addressT
+relax_align (address, alignment)
+ register relax_addressT address; /* Address now. */
+ register int alignment; /* Alignment (binary). */
+{
+ relax_addressT mask;
+ relax_addressT new_address;
+
+ mask = ~((~0) << alignment);
+ new_address = (address + mask) & (~mask);
+#ifdef LINKER_RELAXING_SHRINKS_ONLY
+ if (linkrelax)
+ /* We must provide lots of padding, so the linker can discard it
+ when needed. The linker will not add extra space, ever. */
+ new_address += (1 << alignment);
+#endif
+ return (new_address - address);
+}
+
+void
+relax_segment (segment_frag_root, segment)
+ struct frag *segment_frag_root;
+ segT segment;
+{
+ register struct frag *fragP;
+ register relax_addressT address;
+#if !defined (MANY_SEGMENTS) && !defined (BFD_ASSEMBLER)
+ know (segment == SEG_DATA || segment == SEG_TEXT || segment == SEG_BSS);
+#endif
+ /* In case md_estimate_size_before_relax() wants to make fixSs. */
+ subseg_change (segment, 0);
+
+ /* For each frag in segment: count and store (a 1st guess of)
+ fr_address. */
+ address = 0;
+ for (fragP = segment_frag_root; fragP; fragP = fragP->fr_next)
+ {
+ fragP->fr_address = address;
+ address += fragP->fr_fix;
+
+ switch (fragP->fr_type)
+ {
+ case rs_fill:
+ address += fragP->fr_offset * fragP->fr_var;
+ break;
+
+ case rs_align:
+ case rs_align_code:
+ {
+ addressT offset = relax_align (address, (int) fragP->fr_offset);
+
+ if (fragP->fr_subtype != 0 && offset > fragP->fr_subtype)
+ offset = 0;
+
+ if (offset % fragP->fr_var != 0)
+ {
+ as_bad (_("alignment padding (%lu bytes) not a multiple of %ld"),
+ (unsigned long) offset, (long) fragP->fr_var);
+ offset -= (offset % fragP->fr_var);
+ }
+
+ address += offset;
+ }
+ break;
+
+ case rs_org:
+ case rs_space:
+ /* Assume .org is nugatory. It will grow with 1st relax. */
+ break;
+
+ case rs_machine_dependent:
+ address += md_estimate_size_before_relax (fragP, segment);
+ break;
+
+#ifndef WORKING_DOT_WORD
+ /* Broken words don't concern us yet */
+ case rs_broken_word:
+ break;
+#endif
+
+ case rs_leb128:
+ /* Initial guess is always 1; doing otherwise can result in
+ stable solutions that are larger than the minimum. */
+ address += fragP->fr_offset = 1;
+ break;
+
+ case rs_cfa:
+ address += eh_frame_estimate_size_before_relax (fragP);
+ break;
+
+ default:
+ BAD_CASE (fragP->fr_type);
+ break;
+ } /* switch(fr_type) */
+ } /* for each frag in the segment */
+
+ /* Do relax(). */
+ {
+ long stretch; /* May be any size, 0 or negative. */
+ /* Cumulative number of addresses we have */
+ /* relaxed this pass. */
+ /* We may have relaxed more than one address. */
+ long stretched; /* Have we stretched on this pass? */
+ /* This is 'cuz stretch may be zero, when, in fact some piece of code
+ grew, and another shrank. If a branch instruction doesn't fit anymore,
+ we could be scrod. */
+
+ do
+ {
+ stretch = stretched = 0;
+ for (fragP = segment_frag_root; fragP; fragP = fragP->fr_next)
+ {
+ long growth = 0;
+ addressT was_address;
+ offsetT offset;
+ symbolS *symbolP;
+
+ was_address = fragP->fr_address;
+ address = fragP->fr_address += stretch;
+ symbolP = fragP->fr_symbol;
+ offset = fragP->fr_offset;
+
+ switch (fragP->fr_type)
+ {
+ case rs_fill: /* .fill never relaxes. */
+ growth = 0;
+ break;
+
+#ifndef WORKING_DOT_WORD
+ /* JF: This is RMS's idea. I do *NOT* want to be blamed
+ for it I do not want to write it. I do not want to have
+ anything to do with it. This is not the proper way to
+ implement this misfeature. */
+ case rs_broken_word:
+ {
+ struct broken_word *lie;
+ struct broken_word *untruth;
+
+ /* Yes this is ugly (storing the broken_word pointer
+ in the symbol slot). Still, this whole chunk of
+ code is ugly, and I don't feel like doing anything
+ about it. Think of it as stubbornness in action. */
+ growth = 0;
+ for (lie = (struct broken_word *) (fragP->fr_symbol);
+ lie && lie->dispfrag == fragP;
+ lie = lie->next_broken_word)
+ {
+
+ if (lie->added)
+ continue;
+
+ offset = (lie->add->sy_frag->fr_address
+ + S_GET_VALUE (lie->add)
+ + lie->addnum
+ - (lie->sub->sy_frag->fr_address
+ + S_GET_VALUE (lie->sub)));
+ if (offset <= -32768 || offset >= 32767)
+ {
+ if (flag_warn_displacement)
+ {
+ char buf[50];
+ sprint_value (buf, (addressT) lie->addnum);
+ as_warn (_(".word %s-%s+%s didn't fit"),
+ S_GET_NAME (lie->add),
+ S_GET_NAME (lie->sub),
+ buf);
+ }
+ lie->added = 1;
+ if (fragP->fr_subtype == 0)
+ {
+ fragP->fr_subtype++;
+ growth += md_short_jump_size;
+ }
+ for (untruth = lie->next_broken_word;
+ untruth && untruth->dispfrag == lie->dispfrag;
+ untruth = untruth->next_broken_word)
+ if ((untruth->add->sy_frag == lie->add->sy_frag)
+ && S_GET_VALUE (untruth->add) == S_GET_VALUE (lie->add))
+ {
+ untruth->added = 2;
+ untruth->use_jump = lie;
+ }
+ growth += md_long_jump_size;
+ }
+ }
+
+ break;
+ } /* case rs_broken_word */
+#endif
+ case rs_align:
+ case rs_align_code:
+ {
+ addressT oldoff, newoff;
+
+ oldoff = relax_align (was_address + fragP->fr_fix,
+ (int) offset);
+ newoff = relax_align (address + fragP->fr_fix,
+ (int) offset);
+
+ if (fragP->fr_subtype != 0)
+ {
+ if (oldoff > fragP->fr_subtype)
+ oldoff = 0;
+ if (newoff > fragP->fr_subtype)
+ newoff = 0;
+ }
+
+ growth = newoff - oldoff;
+ }
+ break;
+
+ case rs_org:
+ {
+ long target = offset;
+ long after;
+
+ if (symbolP)
+ {
+#if !defined (MANY_SEGMENTS) && !defined (BFD_ASSEMBLER)
+ know ((S_GET_SEGMENT (symbolP) == SEG_ABSOLUTE)
+ || (S_GET_SEGMENT (symbolP) == SEG_DATA)
+ || (S_GET_SEGMENT (symbolP) == SEG_TEXT)
+ || S_GET_SEGMENT (symbolP) == SEG_BSS);
+ know (symbolP->sy_frag);
+ know (!(S_GET_SEGMENT (symbolP) == SEG_ABSOLUTE)
+ || (symbolP->sy_frag == &zero_address_frag));
+#endif
+ target += S_GET_VALUE (symbolP)
+ + symbolP->sy_frag->fr_address;
+ } /* if we have a symbol */
+
+ know (fragP->fr_next);
+ after = fragP->fr_next->fr_address;
+ growth = target - after;
+ if (growth < 0)
+ {
+ /* Growth may be negative, but variable part of frag
+ cannot have fewer than 0 chars. That is, we can't
+ .org backwards. */
+ as_bad (_("attempt to .org backwards ignored"));
+ growth = 0;
+ }
+
+ growth -= stretch; /* This is an absolute growth factor */
+ break;
+ }
+
+ case rs_space:
+ if (symbolP)
+ {
+ growth = S_GET_VALUE (symbolP);
+ if (symbolP->sy_frag != &zero_address_frag
+ || S_IS_COMMON (symbolP)
+ || ! S_IS_DEFINED (symbolP))
+ as_bad_where (fragP->fr_file, fragP->fr_line,
+ _(".space specifies non-absolute value"));
+ fragP->fr_symbol = 0;
+ if (growth < 0)
+ {
+ as_warn (_(".space or .fill with negative value, ignored"));
+ growth = 0;
+ }
+ }
+ else
+ growth = 0;
+ break;
+
+ case rs_machine_dependent:
+#ifdef md_relax_frag
+ growth = md_relax_frag (fragP, stretch);
+#else
+#ifdef TC_GENERIC_RELAX_TABLE
+ /* The default way to relax a frag is to look through
+ TC_GENERIC_RELAX_TABLE. */
+ growth = relax_frag (fragP, stretch);
+#endif /* TC_GENERIC_RELAX_TABLE */
+#endif
+ break;
+
+ case rs_leb128:
+ {
+ valueT value;
+ int size;
+
+ value = resolve_symbol_value (fragP->fr_symbol, 0);
+ size = sizeof_leb128 (value, fragP->fr_subtype);
+ growth = size - fragP->fr_offset;
+ fragP->fr_offset = size;
+ }
+ break;
+
+ case rs_cfa:
+ growth = eh_frame_relax_frag (fragP);
+ break;
+
+ default:
+ BAD_CASE (fragP->fr_type);
+ break;
+ }
+ if (growth)
+ {
+ stretch += growth;
+ stretched++;
+ }
+ } /* For each frag in the segment. */
+ }
+ while (stretched); /* Until nothing further to relax. */
+ } /* do_relax */
+
+ /*
+ * We now have valid fr_address'es for each frag.
+ */
+
+ /*
+ * All fr_address's are correct, relative to their own segment.
+ * We have made all the fixS we will ever make.
+ */
+} /* relax_segment() */
+
+#if defined (BFD_ASSEMBLER) || (!defined (BFD) && !defined (OBJ_VMS))
+
+#ifndef TC_RELOC_RTSYM_LOC_FIXUP
+#define TC_RELOC_RTSYM_LOC_FIXUP(X) (1)
+#endif
+
+/* fixup_segment()
+
+ Go through all the fixS's in a segment and see which ones can be
+ handled now. (These consist of fixS where we have since discovered
+ the value of a symbol, or the address of the frag involved.)
+ For each one, call md_apply_fix to put the fix into the frag data.
+
+ Result is a count of how many relocation structs will be needed to
+ handle the remaining fixS's that we couldn't completely handle here.
+ These will be output later by emit_relocations(). */
+
+static long
+fixup_segment (fixP, this_segment_type)
+ register fixS *fixP;
+ segT this_segment_type; /* N_TYPE bits for segment. */
+{
+ long seg_reloc_count = 0;
+ symbolS *add_symbolP;
+ symbolS *sub_symbolP;
+ valueT add_number;
+ int size;
+ char *place;
+ long where;
+ int pcrel, plt;
+ fragS *fragP;
+ segT add_symbol_segment = absolute_section;
+
+ /* If the linker is doing the relaxing, we must not do any fixups.
+
+ Well, strictly speaking that's not true -- we could do any that are
+ PC-relative and don't cross regions that could change size. And for the
+ i960 (the only machine for which we've got a relaxing linker right now),
+ we might be able to turn callx/callj into bal anyways in cases where we
+ know the maximum displacement. */
+ if (linkrelax)
+ {
+ for (; fixP; fixP = fixP->fx_next)
+ seg_reloc_count++;
+ TC_ADJUST_RELOC_COUNT (fixP, seg_reloc_count);
+ return seg_reloc_count;
+ }
+
+ for (; fixP; fixP = fixP->fx_next)
+ {
+
+#ifdef DEBUG5
+ fprintf (stderr, "\nprocessing fixup:\n");
+ print_fixup (fixP);
+#endif
+
+
+ fragP = fixP->fx_frag;
+ know (fragP);
+ where = fixP->fx_where;
+ place = fragP->fr_literal + where;
+ size = fixP->fx_size;
+ add_symbolP = fixP->fx_addsy;
+#ifdef TC_VALIDATE_FIX
+ TC_VALIDATE_FIX (fixP, this_segment_type, skip);
+#endif
+ sub_symbolP = fixP->fx_subsy;
+ add_number = fixP->fx_offset;
+ pcrel = fixP->fx_pcrel;
+ plt = fixP->fx_plt;
+
+ if (add_symbolP != NULL
+ && add_symbolP->sy_mri_common)
+ {
+ know (add_symbolP->sy_value.X_op == O_symbol);
+ add_number += S_GET_VALUE (add_symbolP);
+ fixP->fx_offset = add_number;
+ add_symbolP = fixP->fx_addsy = add_symbolP->sy_value.X_add_symbol;
+ }
+
+ if (add_symbolP)
+ add_symbol_segment = S_GET_SEGMENT (add_symbolP);
+
+ if (sub_symbolP)
+ {
+ resolve_symbol_value (sub_symbolP, 1);
+ if (add_symbolP == NULL || add_symbol_segment == absolute_section)
+ {
+ if (add_symbolP != NULL)
+ {
+ add_number += S_GET_VALUE (add_symbolP);
+ add_symbolP = NULL;
+ fixP->fx_addsy = NULL;
+ }
+
+ /* It's just -sym */
+ if (S_GET_SEGMENT (sub_symbolP) == absolute_section)
+ {
+ add_number -= S_GET_VALUE (sub_symbolP);
+ fixP->fx_subsy = NULL;
+ }
+ else if (pcrel
+ && S_GET_SEGMENT (sub_symbolP) == this_segment_type)
+ {
+ /* Should try converting to a constant. */
+ goto bad_sub_reloc;
+ }
+ else
+ bad_sub_reloc:
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Negative of non-absolute symbol %s"),
+ S_GET_NAME (sub_symbolP));
+ }
+ else if (S_GET_SEGMENT (sub_symbolP) == add_symbol_segment
+ && SEG_NORMAL (add_symbol_segment))
+ {
+ /* Difference of 2 symbols from same segment.
+ Can't make difference of 2 undefineds: 'value' means
+ something different for N_UNDF. */
+#ifdef TC_I960
+ /* Makes no sense to use the difference of 2 arbitrary symbols
+ as the target of a call instruction. */
+ if (fixP->fx_tcbit)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("callj to difference of 2 symbols"));
+#endif /* TC_I960 */
+ add_number += S_GET_VALUE (add_symbolP) -
+ S_GET_VALUE (sub_symbolP);
+
+ add_symbolP = NULL;
+ pcrel = 0; /* No further pcrel processing. */
+
+ /* Let the target machine make the final determination
+ as to whether or not a relocation will be needed to
+ handle this fixup. */
+ if (!TC_FORCE_RELOCATION_SECTION (fixP, this_segment_type))
+ {
+ fixP->fx_pcrel = 0;
+ fixP->fx_addsy = NULL;
+ fixP->fx_subsy = NULL;
+ }
+ }
+ else
+ {
+ /* Different segments in subtraction. */
+ know (!(S_IS_EXTERNAL (sub_symbolP)
+ && (S_GET_SEGMENT (sub_symbolP) == absolute_section)));
+
+ if ((S_GET_SEGMENT (sub_symbolP) == absolute_section))
+ add_number -= S_GET_VALUE (sub_symbolP);
+
+#ifdef DIFF_EXPR_OK
+ else if (S_GET_SEGMENT (sub_symbolP) == this_segment_type
+#if 0 /* Do this even if it's already described as pc-relative. For example,
+ on the m68k, an operand of "pc@(foo-.-2)" should address "foo" in a
+ pc-relative mode. */
+ && pcrel
+#endif
+ )
+ {
+ /* Make it pc-relative. */
+ add_number += (MD_PCREL_FROM_SECTION (fixP, this_segment_type)
+ - S_GET_VALUE (sub_symbolP));
+ pcrel = 1;
+ fixP->fx_pcrel = 1;
+ sub_symbolP = 0;
+ fixP->fx_subsy = 0;
+ }
+#endif
+#ifdef UNDEFINED_DIFFERENCE_OK
+ /* The PA needs this for PIC code generation. We basically
+ don't want to do anything if we have the difference of two
+ symbols at this point. */
+ else if (1)
+ {
+ /* Leave it alone. */
+ }
+#endif
+#ifdef BFD_ASSEMBLER
+ else if (fixP->fx_r_type == BFD_RELOC_GPREL32
+ || fixP->fx_r_type == BFD_RELOC_GPREL16)
+ {
+ /* Leave it alone. */
+ }
+#endif
+ else
+ {
+ char buf[50];
+ sprint_value (buf, fragP->fr_address + where);
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Subtraction of two symbols in different sections \"%s\" {%s section} - \"%s\" {%s section} at file address %s."),
+ S_GET_NAME (add_symbolP),
+ segment_name (S_GET_SEGMENT (add_symbolP)),
+ S_GET_NAME (sub_symbolP),
+ segment_name (S_GET_SEGMENT (sub_symbolP)),
+ buf);
+ }
+ }
+ }
+
+ if (add_symbolP)
+ {
+ if (add_symbol_segment == this_segment_type && pcrel && !plt
+ && TC_RELOC_RTSYM_LOC_FIXUP (fixP))
+ {
+ /*
+ * This fixup was made when the symbol's segment was
+ * SEG_UNKNOWN, but it is now in the local segment.
+ * So we know how to do the address without relocation.
+ */
+#ifdef TC_I960
+ /* reloc_callj() may replace a 'call' with a 'calls' or a
+ 'bal', in which cases it modifies *fixP as appropriate.
+ In the case of a 'calls', no further work is required,
+ and *fixP has been set up to make the rest of the code
+ below a no-op. */
+ reloc_callj (fixP);
+#endif /* TC_I960 */
+
+ add_number += S_GET_VALUE (add_symbolP);
+ add_number -= MD_PCREL_FROM_SECTION (fixP, this_segment_type);
+ pcrel = 0; /* Lie. Don't want further pcrel processing. */
+
+ /* Let the target machine make the final determination
+ as to whether or not a relocation will be needed to
+ handle this fixup. */
+ if (!TC_FORCE_RELOCATION (fixP))
+ {
+ fixP->fx_pcrel = 0;
+ fixP->fx_addsy = NULL;
+ }
+ }
+ else
+ {
+ if (add_symbol_segment == absolute_section
+ && ! pcrel)
+ {
+#ifdef TC_I960
+ /* See comment about reloc_callj() above. */
+ reloc_callj (fixP);
+#endif /* TC_I960 */
+ add_number += S_GET_VALUE (add_symbolP);
+
+ /* Let the target machine make the final determination
+ as to whether or not a relocation will be needed to
+ handle this fixup. */
+
+ if (!TC_FORCE_RELOCATION (fixP))
+ {
+ fixP->fx_addsy = NULL;
+ add_symbolP = NULL;
+ }
+ }
+ else if (add_symbol_segment == undefined_section
+#ifdef BFD_ASSEMBLER
+ || bfd_is_com_section (add_symbol_segment)
+#endif
+ )
+ {
+#ifdef TC_I960
+ if ((int) fixP->fx_bit_fixP == 13)
+ {
+ /* This is a COBR instruction. They have only a
+ * 13-bit displacement and are only to be used
+ * for local branches: flag as error, don't generate
+ * relocation.
+ */
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("can't use COBR format with external label"));
+ fixP->fx_addsy = NULL;
+ fixP->fx_done = 1;
+ continue;
+ } /* COBR */
+#endif /* TC_I960 */
+
+#ifdef OBJ_COFF
+#ifdef TE_I386AIX
+ if (S_IS_COMMON (add_symbolP))
+ add_number += S_GET_VALUE (add_symbolP);
+#endif /* TE_I386AIX */
+#endif /* OBJ_COFF */
+ ++seg_reloc_count;
+ }
+ else
+ {
+ seg_reloc_count++;
+#if !(defined (TC_V850) && defined (OBJ_ELF))
+#if !(defined (TC_M68K) && defined (OBJ_ELF))
+#if !(defined (TC_ARM) && defined (OBJ_ELF))
+#if !defined (TC_I386) || !(defined (OBJ_ELF) || defined (OBJ_COFF)) || defined (TE_PE)
+ add_number += S_GET_VALUE (add_symbolP);
+#endif
+#endif
+#endif
+#endif
+ }
+ }
+ }
+
+ if (pcrel)
+ {
+ add_number -= MD_PCREL_FROM_SECTION (fixP, this_segment_type);
+ if (add_symbolP == 0)
+ {
+#ifndef BFD_ASSEMBLER
+ fixP->fx_addsy = &abs_symbol;
+#else
+ fixP->fx_addsy = section_symbol (absolute_section);
+#endif
+ fixP->fx_addsy->sy_used_in_reloc = 1;
+ ++seg_reloc_count;
+ }
+ }
+
+ if (!fixP->fx_bit_fixP && !fixP->fx_no_overflow && size > 0)
+ {
+ if ((size_t) size < sizeof (valueT))
+ {
+ valueT mask, hibit;
+
+ /* set all bits to one */
+ mask = 0;
+ mask--;
+ /* Technically, combining these produces an undefined result
+ if size is sizeof (valueT), though I think these two
+ half-way operations should both be defined. And the
+ compiler should be able to combine them if it's valid on
+ the host architecture. */
+ mask <<= size * 4;
+ mask <<= size * 4;
+ hibit = (valueT) 1 << (size * 8 - 1);
+ if (((add_number & mask) != 0
+ || (fixP->fx_signed
+ && (add_number & hibit) != 0))
+ && ((add_number & mask) != mask
+ || (add_number & hibit) == 0))
+ {
+ char buf[50], buf2[50];
+ sprint_value (buf, fragP->fr_address + where);
+ if (add_number > 1000)
+ sprint_value (buf2, add_number);
+ else
+ sprintf (buf2, "%ld", (long) add_number);
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Value of %s too large for field of %d bytes at %s"),
+ buf2, size, buf);
+ } /* generic error checking */
+ }
+#ifdef WARN_SIGNED_OVERFLOW_WORD
+ /* Warn if a .word value is too large when treated as a signed
+ number. We already know it is not too negative. This is to
+ catch over-large switches generated by gcc on the 68k. */
+ if (!flag_signed_overflow_ok
+ && size == 2
+ && add_number > 0x7fff)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Signed .word overflow; switch may be too large; %ld at 0x%lx"),
+ (long) add_number,
+ (unsigned long) (fragP->fr_address + where));
+#endif
+ } /* not a bit fix */
+
+ if (!fixP->fx_done)
+ {
+#ifdef MD_APPLY_FIX3
+ md_apply_fix3 (fixP, &add_number, this_segment_type);
+#else
+#ifdef BFD_ASSEMBLER
+ md_apply_fix (fixP, &add_number);
+#else
+ md_apply_fix (fixP, add_number);
+#endif
+#endif
+
+#ifndef TC_HANDLES_FX_DONE
+ /* If the tc-* files haven't been converted, assume it's handling
+ it the old way, where a null fx_addsy means that the fix has
+ been applied completely, and no further work is needed. */
+ if (fixP->fx_addsy == 0 && fixP->fx_pcrel == 0)
+ fixP->fx_done = 1;
+#endif
+ }
+#ifdef TC_VALIDATE_FIX
+ skip: ;
+#endif
+#ifdef DEBUG5
+ fprintf (stderr, "result:\n");
+ print_fixup (fixP);
+#endif
+ } /* For each fixS in this segment. */
+
+ TC_ADJUST_RELOC_COUNT (fixP, seg_reloc_count);
+ return seg_reloc_count;
+}
+
+#endif /* defined (BFD_ASSEMBLER) || (!defined (BFD) && !defined (OBJ_VMS)) */
+
+void
+number_to_chars_bigendian (buf, val, n)
+ char *buf;
+ valueT val;
+ int n;
+{
+ if ((size_t) n > sizeof (val) || n <= 0)
+ abort ();
+ while (n--)
+ {
+ buf[n] = val & 0xff;
+ val >>= 8;
+ }
+}
+
+void
+number_to_chars_littleendian (buf, val, n)
+ char *buf;
+ valueT val;
+ int n;
+{
+ if ((size_t) n > sizeof (val) || n <= 0)
+ abort ();
+ while (n--)
+ {
+ *buf++ = val & 0xff;
+ val >>= 8;
+ }
+}
+
+void
+write_print_statistics (file)
+ FILE *file;
+{
+ fprintf (stderr, "fixups: %d\n", n_fixups);
+}
+
+/* for debugging */
+extern int indent_level;
+
+void
+print_fixup (fixp)
+ fixS *fixp;
+{
+ indent_level = 1;
+ fprintf (stderr, "fix %lx %s:%d", (long) fixp, fixp->fx_file, fixp->fx_line);
+ if (fixp->fx_pcrel)
+ fprintf (stderr, " pcrel");
+ if (fixp->fx_pcrel_adjust)
+ fprintf (stderr, " pcrel_adjust=%d", fixp->fx_pcrel_adjust);
+ if (fixp->fx_im_disp)
+ {
+#ifdef TC_NS32K
+ fprintf (stderr, " im_disp=%d", fixp->fx_im_disp);
+#else
+ fprintf (stderr, " im_disp");
+#endif
+ }
+ if (fixp->fx_tcbit)
+ fprintf (stderr, " tcbit");
+ if (fixp->fx_done)
+ fprintf (stderr, " done");
+ fprintf (stderr, "\n size=%d frag=%lx where=%ld offset=%lx addnumber=%lx",
+ fixp->fx_size, (long) fixp->fx_frag, (long) fixp->fx_where,
+ (long) fixp->fx_offset, (long) fixp->fx_addnumber);
+#ifdef BFD_ASSEMBLER
+ fprintf (stderr, "\n %s (%d)", bfd_get_reloc_code_name (fixp->fx_r_type),
+ fixp->fx_r_type);
+#else
+#ifdef NEED_FX_R_TYPE
+ fprintf (stderr, " r_type=%d", fixp->fx_r_type);
+#endif
+#endif
+ if (fixp->fx_addsy)
+ {
+ fprintf (stderr, "\n +<");
+ print_symbol_value_1 (stderr, fixp->fx_addsy);
+ fprintf (stderr, ">");
+ }
+ if (fixp->fx_subsy)
+ {
+ fprintf (stderr, "\n -<");
+ print_symbol_value_1 (stderr, fixp->fx_subsy);
+ fprintf (stderr, ">");
+ }
+ fprintf (stderr, "\n");
+#ifdef TC_FIX_DATA_PRINT
+ TC_FIX_DATA_PRINT (stderr, fixp);
+#endif
+}
+
+/* end of write.c */
diff --git a/gas/write.h b/gas/write.h
new file mode 100644
index 0000000000..186d2ada1b
--- /dev/null
+++ b/gas/write.h
@@ -0,0 +1,208 @@
+/* write.h
+ Copyright (C) 1987, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS 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 more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#ifndef __write_h__
+#define __write_h__
+
+#ifndef TC_I960
+#ifdef hpux
+#define EXEC_MACHINE_TYPE HP9000S200_ID
+#endif
+#endif /* TC_I960 */
+
+#ifndef BFD_ASSEMBLER
+
+#ifndef LOCAL_LABEL
+#define LOCAL_LABEL(name) (name [0] == 'L' )
+#endif
+
+#define S_LOCAL_NAME(s) (LOCAL_LABEL (S_GET_NAME (s)))
+
+#endif /* ! BFD_ASSEMBLER */
+
+/* This is the name of a fake symbol which will never appear in the
+ assembler output. S_IS_LOCAL detects it because of the \001. */
+#define FAKE_LABEL_NAME "L0\001"
+
+#include "bit_fix.h"
+
+/*
+ * FixSs may be built up in any order.
+ */
+
+struct fix
+{
+ /* These small fields are grouped together for compactness of
+ this structure, and efficiency of access on some architectures. */
+
+ /* pc-relative offset adjust (only used by m68k) */
+ char fx_pcrel_adjust;
+
+ /* How many bytes are involved? */
+ unsigned char fx_size;
+
+ /* Is this a pc-relative relocation? */
+ unsigned fx_pcrel : 1;
+
+ /* Is this a relocation to a procedure linkage table entry? If so,
+ some of the reductions we try to apply are invalid. A better way
+ might be to represent PLT entries with different kinds of
+ symbols, and use normal relocations (with undefined symbols);
+ look into it for version 2.6. */
+ unsigned fx_plt : 1;
+
+ /* Is this value an immediate displacement? */
+ /* Only used on i960 and ns32k; merge it into TC_FIX_TYPE sometime. */
+ unsigned fx_im_disp : 2;
+
+ /* A bit for the CPU specific code.
+ This probably can be folded into tc_fix_data, below. */
+ unsigned fx_tcbit : 1;
+
+ /* Has this relocation already been applied? */
+ unsigned fx_done : 1;
+
+ /* Suppress overflow complaints on large addends. This is used
+ in the PowerPC ELF config to allow large addends on the
+ BFD_RELOC_{LO16,HI16,HI16_S} relocations.
+
+ @@ Can this be determined from BFD? */
+ unsigned fx_no_overflow : 1;
+
+ /* The value is signed when checking for overflow. */
+ unsigned fx_signed : 1;
+
+ /* Which frag does this fix apply to? */
+ fragS *fx_frag;
+
+ /* Where is the first byte to fix up? */
+ long fx_where;
+
+ /* NULL or Symbol whose value we add in. */
+ symbolS *fx_addsy;
+
+ /* NULL or Symbol whose value we subtract. */
+ symbolS *fx_subsy;
+
+ /* Absolute number we add in. */
+ valueT fx_offset;
+
+ /* Next fixS in linked list, or NULL. */
+ struct fix *fx_next;
+
+ /* If NULL, no bitfix's to do. */
+ /* Only i960-coff and ns32k use this, and i960-coff stores an
+ integer. This can probably be folded into tc_fix_data, below.
+ @@ Alpha also uses it, but only to disable certain relocation
+ processing. */
+ bit_fixS *fx_bit_fixP;
+
+#ifdef BFD_ASSEMBLER
+ bfd_reloc_code_real_type fx_r_type;
+#else
+#ifdef NEED_FX_R_TYPE
+ /* Hack for machines where the type of reloc can't be
+ worked out by looking at how big it is. */
+ int fx_r_type;
+#endif
+#endif
+
+ /* This field is sort of misnamed. It appears to be a sort of random
+ scratch field, for use by the back ends. The main gas code doesn't
+ do anything but initialize it to zero. The use of it does need to
+ be coordinated between the cpu and format files, though. E.g., some
+ coff targets pass the `addend' field from the cpu file via this
+ field. I don't know why the `fx_offset' field above can't be used
+ for that; investigate later and document. KR */
+ valueT fx_addnumber;
+
+ /* The location of the instruction which created the reloc, used
+ in error messages. */
+ char *fx_file;
+ unsigned fx_line;
+
+#ifdef USING_CGEN
+ struct {
+ /* CGEN_INSN entry for this instruction. */
+ const struct cgen_insn *insn;
+ /* Target specific data, usually reloc number. */
+ int opinfo;
+ } fx_cgen;
+#endif
+
+#ifdef TC_FIX_TYPE
+ /* Location where a backend can attach additional data
+ needed to perform fixups. */
+ TC_FIX_TYPE tc_fix_data;
+#endif
+};
+
+typedef struct fix fixS;
+
+#ifndef BFD_ASSEMBLER
+extern char *next_object_file_charP;
+
+#ifndef MANY_SEGMENTS
+COMMON fixS *text_fix_root, *text_fix_tail; /* Chains fixSs. */
+COMMON fixS *data_fix_root, *data_fix_tail; /* Chains fixSs. */
+COMMON fixS *bss_fix_root, *bss_fix_tail; /* Chains fixSs. */
+extern struct frag *text_last_frag; /* Last frag in segment. */
+extern struct frag *data_last_frag; /* Last frag in segment. */
+#endif
+COMMON fixS **seg_fix_rootP, **seg_fix_tailP; /* -> one of above. */
+#endif
+
+extern long string_byte_count;
+extern int section_alignment[];
+
+extern bit_fixS *bit_fix_new
+ PARAMS ((int size, int offset, long base_type, long base_adj, long min,
+ long max, long add));
+extern void append PARAMS ((char **charPP, char *fromP, unsigned long length));
+extern void record_alignment PARAMS ((segT seg, int align));
+extern void subsegs_finish PARAMS ((void));
+extern void write_object_file PARAMS ((void));
+extern long relax_frag PARAMS ((fragS *, long));
+extern void relax_segment
+ PARAMS ((struct frag * seg_frag_root, segT seg_type));
+
+extern void number_to_chars_littleendian PARAMS ((char *, valueT, int));
+extern void number_to_chars_bigendian PARAMS ((char *, valueT, int));
+
+#ifdef BFD_ASSEMBLER
+extern fixS *fix_new
+ PARAMS ((fragS * frag, int where, int size, symbolS * add_symbol,
+ offsetT offset, int pcrel, bfd_reloc_code_real_type r_type));
+extern fixS *fix_new_exp
+ PARAMS ((fragS * frag, int where, int size, expressionS *exp, int pcrel,
+ bfd_reloc_code_real_type r_type));
+#else
+extern fixS *fix_new
+ PARAMS ((fragS * frag, int where, int size, symbolS * add_symbol,
+ offsetT offset, int pcrel, int r_type));
+extern fixS *fix_new_exp
+ PARAMS ((fragS * frag, int where, int size, expressionS *exp, int pcrel,
+ int r_type));
+#endif
+
+extern void write_print_statistics PARAMS ((FILE *));
+
+#endif /* __write_h__ */
+/* end of write.h */